#!/usr/bin/perl
# 
# This prints JSON formated data reporting the status of DRBD resources and volumes.
# 

use strict;
use warnings;
use Anvil::Tools;
use Data::Dumper;
use JSON;

$| = 1;

my $THIS_FILE           =  ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory   =  ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
if (($running_directory =~ /^\./) && ($ENV{PWD}))
{
	$running_directory =~ s/^\./$ENV{PWD}/;
}

my $anvil = Anvil::Tools->new();

$anvil->Get->switches;

$anvil->Database->connect;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
if (not $anvil->data->{sys}{database}{connections})
{
	# No databases, exit.
	$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, priority => "err", key => "error_0003"});
	$anvil->nice_exit({exit_code => 1});
}

# Read in any CGI variables, if needed.
$anvil->Get->cgi();

$anvil->Database->get_hosts();
$anvil->Database->get_anvils();
$anvil->DRBD->gather_data();

print $anvil->Template->get({file => "shared.html", name => "json_headers", show_name => 0})."\n";

my $hash              = {};
my $anvil_uuid        = "";
my $active_resource   = "";
my $volume_array      = "";
my $connection_array  = "";
my $target_array      = "";
   $hash->{resources} = [];
if ($anvil->data->{cgi}{anvil_uuid}{value})
{
	$anvil_uuid = $anvil->data->{cgi}{anvil_uuid}{value};
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }});
}
elsif ($anvil->data->{switches}{'anvil-uuid'})
{
	$anvil_uuid = $anvil->data->{switches}{'anvil-uuid'};
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }});
}
if ((not $anvil_uuid) or (not exists $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}))
{
	$anvil->data->{anvil_status}{anvil_name} = "!!invalid!anvil_uuid!!";
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'anvil_status::anvil_name' => $anvil->data->{anvil_status}{anvil_name} }});
}
else
{
	my $node1_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid};
	my $node2_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
	my $dr1_uuid   = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid};
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
		node1_uuid => $node1_uuid,
		node2_uuid => $node2_uuid, 
		dr1_uuid   => $dr1_uuid, 
	}});
	
	$anvil->data->{raw}{newest_record}{$node1_uuid} = 0;
	$anvil->data->{raw}{newest_record}{$node2_uuid} = 0;
	my @hosts = ($node1_uuid, $node2_uuid);
	if ($dr1_uuid)
	{
		push @hosts, $dr1_uuid;
		$anvil->data->{raw}{newest_record}{$dr1_uuid} = 0;
	}
	
	foreach my $host_uuid (@hosts)
	{
		my $host_name       =  $anvil->Get->host_name_from_uuid({host_uuid => $host_uuid});
		my $short_host_name =  $host_name;
		   $short_host_name =~ s/\..*$//;
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			host_uuid       => $host_uuid,
			host_name       => $host_name, 
			short_host_name => $short_host_name 
		}});
		my $query = "
SELECT 
    scan_drbd_resource_uuid, 
    scan_drbd_resource_name, 
    scan_drbd_resource_up, 
    round(extract(epoch from modified_date)) 
FROM 
    scan_drbd_resources 
WHERE 
    scan_drbd_resource_host_uuid = ".$anvil->Database->quote($host_uuid)."
;";    
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
		my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
		my $count   = @{$results};
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			results => $results, 
			count   => $count, 
		}});
		foreach my $row (@{$results})
		{
			my $scan_drbd_resource_uuid = $row->[0];
			my $scan_drbd_resource_name = $row->[1];
			my $scan_drbd_resource_up   = $row->[2];
			my $modified_date           = $row->[3];
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
				scan_drbd_resource_uuid => $scan_drbd_resource_uuid, 
				scan_drbd_resource_name => $scan_drbd_resource_name, 
				scan_drbd_resource_up   => $scan_drbd_resource_up, 
				modified_date           => $modified_date, 
			}});
			
			if ($modified_date > $anvil->data->{raw}{newest_record}{$host_uuid})
			{
				$anvil->data->{raw}{newest_record}{$host_uuid} = $modified_date;
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
					"raw::newest_record::${host_uuid}" => $anvil->data->{raw}{newest_record}{$host_uuid}, 
				}});
			}
			
			my $volumes       = [];
			my $resource_hash = {
				resource_name      => $scan_drbd_resource_name,
				resource_host_uuid => $host_uuid,
				is_active          => $scan_drbd_resource_up, 
				timestamp          => $anvil->data->{raw}{newest_record}{$host_uuid}, 
				volumes            => $volumes, 
			};
			
			push @{$hash->{resources}}, $resource_hash;
			
			my $query = "
SELECT 
    scan_drbd_volume_uuid, 
    scan_drbd_volume_number, 
    scan_drbd_volume_device_path, 
    scan_drbd_volume_device_minor, 
    scan_drbd_volume_size, 
    round(extract(epoch from modified_date)) 
FROM 
    scan_drbd_volumes 
WHERE 
    scan_drbd_volume_scan_drbd_resource_uuid = ".$anvil->Database->quote($scan_drbd_resource_uuid)."
;";
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
			my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
			my $count   = @{$results};
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
				results => $results, 
				count   => $count, 
			}});
			foreach my $row (@{$results})
			{
				my $scan_drbd_volume_uuid         = $row->[0];
				my $scan_drbd_volume_number       = $row->[1];
				my $scan_drbd_volume_device_path  = $row->[2];
				my $scan_drbd_volume_device_minor = $row->[3];
				my $scan_drbd_volume_size         = $row->[4];
				my $modified_date                 = $row->[5];
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
					scan_drbd_volume_uuid         => $scan_drbd_volume_uuid, 
					scan_drbd_volume_number       => $scan_drbd_volume_number, 
					scan_drbd_volume_device_path  => $scan_drbd_volume_device_path, 
					scan_drbd_volume_device_minor => $scan_drbd_volume_device_minor, 
					scan_drbd_volume_size         => $scan_drbd_volume_size, 
					modified_date                 => $modified_date, 
				}});
			
				if ($modified_date > $anvil->data->{raw}{newest_record}{$host_uuid})
				{
					$anvil->data->{raw}{newest_record}{$host_uuid} = $modified_date;
					$resource_hash->{timestamp}                    = $modified_date;
					$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
						"raw::newest_record::${host_uuid}" => $anvil->data->{raw}{newest_record}{$host_uuid}, 
					}});
				}
				
				my $connections = [];
				push @{$volumes}, {
					number            => $scan_drbd_volume_number, 
					drbd_device_path  => $scan_drbd_volume_device_path, 
					drbd_device_minor => $scan_drbd_volume_device_minor, 
					size              => $scan_drbd_volume_size, 
					connections       => $connections, 
				};
				
				my $query = "
SELECT 
    scan_drbd_peer_host_name, 
    scan_drbd_peer_connection_state, 
    scan_drbd_peer_local_disk_state, 
    scan_drbd_peer_disk_state, 
    scan_drbd_peer_local_role, 
    scan_drbd_peer_role, 
    scan_drbd_peer_out_of_sync_size, 
    scan_drbd_peer_replication_speed, 
    scan_drbd_peer_estimated_time_to_sync, 
    scan_drbd_peer_ip_address, 
    scan_drbd_peer_tcp_port, 
    scan_drbd_peer_protocol, 
    scan_drbd_peer_fencing, 
    round(extract(epoch from modified_date)) 
FROM 
    scan_drbd_peers 
WHERE 
    scan_drbd_peer_scan_drbd_volume_uuid = ".$anvil->Database->quote($scan_drbd_volume_uuid)."
;";
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
				my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
				my $count   = @{$results};
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
					results => $results, 
					count   => $count, 
				}});
				foreach my $row (@{$results})
				{
					my $scan_drbd_peer_host_name              = $row->[0];
					my $scan_drbd_peer_connection_state       = $row->[1];
					my $scan_drbd_peer_local_disk_state       = $row->[2];
					my $scan_drbd_peer_disk_state             = $row->[3];
					my $scan_drbd_peer_local_role             = $row->[4];
					my $scan_drbd_peer_role                   = $row->[5];
					my $scan_drbd_peer_out_of_sync_size       = $row->[6];
					my $scan_drbd_peer_replication_speed      = $row->[7];
					my $scan_drbd_peer_estimated_time_to_sync = $row->[8];
					my $scan_drbd_peer_ip_address             = $row->[9];
					my $scan_drbd_peer_tcp_port               = $row->[10];
					my $scan_drbd_peer_protocol               = $row->[11];
					my $scan_drbd_peer_fencing                = $row->[12];
					my $modified_date                         = $row->[13];
					$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
						scan_drbd_peer_host_name              => $scan_drbd_peer_host_name,
						scan_drbd_peer_connection_state       => $scan_drbd_peer_connection_state,
						scan_drbd_peer_local_disk_state       => $scan_drbd_peer_local_disk_state,
						scan_drbd_peer_disk_state             => $scan_drbd_peer_disk_state,
						scan_drbd_peer_local_role             => $scan_drbd_peer_local_role,
						scan_drbd_peer_role                   => $scan_drbd_peer_role,
						scan_drbd_peer_out_of_sync_size       => $scan_drbd_peer_out_of_sync_size,
						scan_drbd_peer_replication_speed      => $scan_drbd_peer_replication_speed,
						scan_drbd_peer_estimated_time_to_sync => $scan_drbd_peer_estimated_time_to_sync,
						scan_drbd_peer_ip_address             => $scan_drbd_peer_ip_address,
						scan_drbd_peer_tcp_port               => $scan_drbd_peer_tcp_port,
						scan_drbd_peer_protocol               => $scan_drbd_peer_protocol,
						scan_drbd_peer_fencing                => $scan_drbd_peer_fencing,
						modified_date                         => $modified_date,
					}});
					if ($modified_date > $anvil->data->{raw}{newest_record}{$host_uuid})
					{
						$anvil->data->{raw}{newest_record}{$host_uuid} = $modified_date;
						$resource_hash->{timestamp}                    = $modified_date;
						$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
							"raw::newest_record::${host_uuid}" => $anvil->data->{raw}{newest_record}{$host_uuid}, 
						}});
					}
					
					push @{$connections}, {
						protocol   => "async_".lc($scan_drbd_peer_protocol),
						connection => $scan_drbd_peer_connection_state,
						ip_address => $scan_drbd_peer_ip_address, 
						tcp_port   => $scan_drbd_peer_tcp_port, 
						fencing    => $scan_drbd_peer_fencing,
						targets    => [
							# Local
							{
								target_name      => $short_host_name, 
								target_host_uuid => $host_uuid,
								role             => $scan_drbd_peer_local_role,
								disk_states      => $scan_drbd_peer_local_disk_state,
							},
							# Peer
							{
								target_name      => $scan_drbd_peer_host_name, 
								target_host_uuid => $anvil->Get->host_uuid_from_name({host_name => $scan_drbd_peer_host_name}),
								role             => $scan_drbd_peer_role,
								disk_states      => $scan_drbd_peer_disk_state,
							},
						],
						resync => {
							rate             => $scan_drbd_peer_replication_speed, # Bytes / second
							percent_complete => (($scan_drbd_peer_out_of_sync_size / $scan_drbd_volume_size) * 100),
							oos_size         => $scan_drbd_peer_out_of_sync_size, 
							time_remain      => $scan_drbd_peer_estimated_time_to_sync, 
						},
					};
				}
			}
		}
	}
}

print JSON->new->utf8->encode($hash)."\n";
