#!/usr/bin/perl
# 
# This scans the nodes and DR host for DRBD resources and their states. 
# 
# NOTE: The data stored here is not bound to a given host. As such, only hosted VMs are processed.
# 
# Examples;
# 
# Exit codes;
# 0 = Normal exit.
# 1 = Startup failure (not running as root, no DB, bad file read, etc)
# 2 = DRBD not found or configured.
# 
# TODO: 
# - Create a background script that is invoked when we see a resync is running that loops every few seconds 
#   and updates the progress in the database, exiting when the last resync is complete.
# - If the DRBD proxy file exists, see how long until it expires. May want to suppress alerts if no resources
#   use it.

use strict;
use warnings;
use Anvil::Tools;
use Data::Dumper;
use Text::Diff;

# Disable buffering
$| = 1;

# Prevent a discrepency between UID/GID and EUID/EGID from throwing an error.
$< = $>;
$( = $);

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->data->{'scan-drbd'}{alert_sort} = 2;
$anvil->data->{'scan-drbd'}{queries}    = [];

# Make sure we're running as 'root'
# $< == real UID, $> == effective UID
if (($< != 0) && ($> != 0))
{
	# Not root
	print $anvil->Words->string({key => "error_0005"})."\n";
	$anvil->nice_exit({exit_code => 1});
}

$anvil->data->{scancore}{'scan-drbd'}{disable}         = 0;
$anvil->data->{scancore}{'scan-drbd'}{'auto-undefine'} = 1;
$anvil->Storage->read_config();

# Read switches
$anvil->Get->switches({list => ["purge"], man => $THIS_FILE});

# Handle start-up tasks
my $problem = $anvil->ScanCore->agent_startup({agent => $THIS_FILE});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
if ($problem)
{
	$anvil->nice_exit({exit_code => 1});
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }});

if ($anvil->data->{switches}{purge})
{
	# This can be called when doing bulk-database purges.
	my $schema_file = $anvil->data->{path}{directories}{scan_agents}."/".$THIS_FILE."/".$THIS_FILE.".sql";
	$anvil->Database->purge_data({
		debug  => 2,
		tables => $anvil->Database->get_tables_from_schema({debug => 3, schema_file => $schema_file}),
	});
	$anvil->nice_exit({exit_code => 0});
}

if ($anvil->DRBD->gather_data({debug => 2}))
{
	# DRBD not found or configured.
	$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "scan_drbd_error_0001"});
	$anvil->nice_exit({exit_code => 2});
}

# Make sure that lvm.conf's filter of DRBD devices is in place.
$problem = $anvil->Storage->manage_lvm_conf({debug => 2});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});

# TODO: Remove these eventually.
update_res_files($anvil);
check_schema($anvil);

read_last_scan($anvil);

find_changes($anvil);

check_config($anvil);

fix_things($anvil);

update_dr_status($anvil);

# Shut down.
$anvil->ScanCore->agent_shutdown({agent => $THIS_FILE});


#############################################################################################################
# Functions                                                                                                 #
#############################################################################################################

# This records the DRBD resources that are connected or down, so that anvil-safe-start knows what to connecte
# on reboot.
sub update_dr_status
{
	my ($anvil) = @_;
	
	my $host_type = $anvil->Get->host_type();
	if ($host_type ne "dr")
	{
		# Nothing to do, return.
		return(0);
	}
	
	# Don't update until after anvil-safe-start has run.
	my $tmp_file = $anvil->data->{path}{data}{'anvil-safe-start.ran'};
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { tmp_file => $tmp_file }});
	if (-e $tmp_file)
	{
		my $uptime       = $anvil->Get->uptime();
		my $ass_last_ran = $anvil->Storage->read_file({file => $tmp_file}); # Don't snicker
		my $boot_time    = time - $uptime;
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			uptime       => $uptime, 
			ass_last_ran => $ass_last_ran,
			boot_time    => $boot_time,
		}});
		if ($boot_time > $ass_last_ran)
		{
			# Don't change anything yet.
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "scan_drbd_message_0038"});
			return(0);
		}
	}
	
	# Still alive? Update variables.
	my $host_uuid = $anvil->Get->host_uuid;
	foreach my $resource (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}})
	{
		my $variable_name  = "drbd::resource::dr::".$resource."::is_up";
		my $variable_value = $anvil->data->{new}{resource}{$resource}{up} ? 1 : 0;
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			's1:resource'       => $resource,
			's2:variable_name'  => $variable_name,
			's3:variable_value' => $variable_value, 
		}});
		
		my $variable_uuid = $anvil->Database->insert_or_update_variables({
			variable_name         => $variable_name, 
			variable_value        => $variable_value, 
			variable_default      => "0", 
			variable_description  => "striker_0003", 
			variable_section      => "dr", 
			variable_source_uuid  => $host_uuid, 
			variable_source_table => "hosts", 
		});
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }});
	}
	
	return(0);
}

# With the deprecation of device fancy names in DRBD resource file's device statements.
# See: https://github.com/LINBIT/drbd-utils/commit/1678d5fdedb4f38a66b743a27e4b33fedc9d6042
sub update_res_files
{
	my ($anvil) = @_;
	
	foreach my $resource (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}})
	{
		my $config_file = $anvil->data->{new}{resource}{$resource}{config_file};
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { config_file => $config_file }});
		
		my $valid_file      = 0;
		my $new_config_body = "";
		my $old_config_body = $anvil->Storage->read_file({file => $config_file});
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { old_config_body => $old_config_body }});
		foreach my $line (split/\n/, $old_config_body)
		{
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
			if ($line =~ /resource "$resource" \{/)
			{
				$valid_file = 1;
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { valid_file => $valid_file }});
			}
			if ($line =~ /device\s+(\/dev\/.*?)\s+minor\s+(\d+);/)
			{
				my $device =  $1;
				     $line =~ s/$device\s+//;
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
					's1:device' => $device,
					's2:line'   => $line,
				}});
			}
			$new_config_body .= $line."\n";
		}
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { new_config_body => $new_config_body }});
		
		my $difference = diff \$old_config_body, \$new_config_body, { STYLE => 'Unified' };
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { difference => $difference }});
		
		if (($difference) && ($valid_file))
		{
			# Update the config.
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0033", variables => {
				file => $config_file,
				diff => $difference, 
			}});
			
			$anvil->Storage->write_file({
				debug     => 3,
				body      => $new_config_body,
				file      => $config_file,
				backup    => 1,
				overwrite => 1,
				group     => "root",
				user      => "root",
				mode      => "0644",
			});
		}
	}
	
	return(0);
}

# This looks for issues that we can fix, and if any are found, we try to fix them.
sub fix_things
{
	my ($anvil) = @_;
	
	# If the cluster is up and both nodes are online, make sure all DRBD resources are connected.
	$anvil->Database->get_hosts();
	$anvil->DRBD->get_status();
	my $host_uuid       = $anvil->Get->host_uuid();
	my $host_type       = $anvil->Get->host_type();
	my $short_host_name = $anvil->Get->short_host_name();
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
		host_uuid       => $host_uuid,
		host_type       => $host_type,
		short_host_name => $short_host_name, 
	}});
	if ($host_type eq "node")
	{
		my $problem = $anvil->Cluster->parse_cib({debug => 3});
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			problem                     => $problem,
			"cib::parsed::local::ready" => $anvil->data->{cib}{parsed}{'local'}{ready},
			"cib::parsed::peer::ready"  => $anvil->data->{cib}{parsed}{peer}{ready},
		}});
		
		if ((not $problem) && ($anvil->data->{cib}{parsed}{peer}{ready}) && ($anvil->data->{cib}{parsed}{'local'}{ready}))
		{
			# Walk through all resources and make sure the peer and local disks are attached and 
			# the connection established.
			foreach my $resource (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}})
			{
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { resource => $resource }});
				
				# Check connection states.
				foreach my $local_name (sort {$a cmp $b} keys%{$anvil->data->{drbd}{status}})
				{
					$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { local_name => $local_name }});
					foreach my $peer (sort {$a cmp $b} keys %{$anvil->data->{drbd}{status}{$local_name}{resource}{$resource}{connection}})
					{
						my $connection_state = lc($anvil->data->{drbd}{status}{$local_name}{resource}{$resource}{connection}{$peer}{'connection-state'});
						my $peer_host_uuid   = $anvil->Get->host_uuid_from_name({host_name => $peer, debug => 3});
						my $peer_host_type   = exists $anvil->data->{hosts}{host_uuid}{$host_uuid} ? $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type} : "";
						$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
							's1:peer'             => $peer,
							's2:connection_state' => $connection_state, 
							's3:peer_host_uuid'   => $peer_host_uuid, 
							's4:peer_host_type'   => $peer_host_type, 
						}});
						
						if (($peer_host_type eq "node") && ($connection_state eq "standalone"))
						{
							# Are either of the nodes still 'allow-two-primary', 
							# set it to 'no' (no migration is happening anyway, 
							# if we're StandAlone), and try reconnecting.
							my $variables = {
								resource => $resource,
								peer     => $peer, 
							};
							$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_drbd_message_0037", variables => $variables});
							$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0037", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
							
							$anvil->DRBD->manage_resource({
								debug    => 2,
								resource => $resource,
								task     => "up",
							});
						}
					}
				}
				
				foreach my $volume (sort {$a <=> $b} keys %{$anvil->data->{new}{resource}{$resource}{volume}})
				{
					$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { volume => $volume }});
					foreach my $peer (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}})
					{
						my $peer_host_uuid = $anvil->Get->host_uuid_from_name({host_name => $peer});
						my $peer_host_type = exists $anvil->data->{hosts}{host_uuid}{$host_uuid} ? $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type} : "";
						$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
							's1:peer'           => $peer,
							's2:peer_host_uuid' => $peer_host_uuid, 
							's3:peer_host_type' => $peer_host_type, 
						}});
						
						if ($peer_host_type eq "node")
						{
							my $connection_state = $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{connection_state};
							my $local_role       = $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{local_role};
							my $peer_role        = $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{peer_role};
							my $local_disk_state = $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{local_disk_state};
							my $peer_disk_state  = $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{peer_disk_state}; 
							$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
								's1:connection_state' => $connection_state, 
								's2:local_role'       => $local_role, 
								's3:peer_role'        => $peer_role, 
								's4:local_disk_state' => $local_disk_state, 
								's5:peer_disk_state'  => $peer_disk_state, 
							}});
							
							# Find the peer's host_uuid and make sure we're 
							# talking to a node, not a DR host.
							if ($local_disk_state eq "down")
							{
								# Bring it up.
								my $variables = {
									resource => $resource,
									volume   => $volume, 
									peer     => $peer, 
								};
								$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_drbd_message_0036", variables => $variables});
								$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0036", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
								
								$anvil->DRBD->manage_resource({
									debug    => 2,
									resource => $resource,
									task     => "up",
								});
							}
						}
					}
				}
			}
		}
	}
	
	return(0);
}

# In the early days, scan_drbd_peers -> scan_drbd_peer_tcp_port was type numeric. This wasn't compatible with
# drbd-proxy and had to be changed to type text to support csv port lists.
sub check_schema
{
	my ($anvil) = @_;
	
	my $query = "SELECT table_schema, data_type FROM information_schema.columns WHERE column_name = 'scan_drbd_peer_tcp_port';";
	$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 $schema = $row->[0]; 
		my $type   = $row->[1]; 
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			schema => $schema,
			type   => $type,
		}});
		
		if ($type ne "text")
		{
			my $query = "ALTER TABLE ".$schema.".scan_drbd_peers ALTER COLUMN scan_drbd_peer_tcp_port TYPE text;";
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { query => $query }});
			$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
		}
	}
	
	return(0);
}

# This looks at the global-common.conf file and updates it, if needed.
sub check_config
{
	my ($anvil) = @_;
	
	if (not exists $anvil->data->{sys}{privacy}{strong})
	{
		$anvil->data->{sys}{privacy}{strong} = 0;
	}
	
	my $updated = $anvil->DRBD->update_global_common({
		debug       => 2,
		usage_count => $anvil->data->{sys}{privacy}{strong} ? 0 : 1,
	});
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { updated => $updated }});
	if ($updated)
	{
		# Send a notice-level alert
		my $variables = {
			file => $anvil->data->{path}{configs}{'global-common.conf'},
			diff => $updated, 
		};
		$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_drbd_message_0034", variables => $variables});
		$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0034", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
	}
	
	return(0);
}

sub process_drbd
{
	my ($anvil) = @_;
	
	if ($anvil->data->{old}{scan_drbd_uuid})
	{
		# Existing, any changes?
		my $scan_drbd_uuid                 = $anvil->data->{old}{scan_drbd_uuid};
		my $new_scan_drbd_common_xml       = $anvil->data->{new}{scan_drbd}{scan_drbd_common_xml};
		my $old_scan_drbd_common_xml       = $anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_common_xml};
		my $scan_drbd_common_xml_diff      = diff \$old_scan_drbd_common_xml, \$new_scan_drbd_common_xml, { STYLE => 'Unified' };
		my $new_scan_drbd_flush_disk       = $anvil->data->{new}{scan_drbd}{scan_drbd_flush_disk};
		my $old_scan_drbd_flush_disk       = $anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_flush_disk};
		my $new_scan_drbd_flush_md         = $anvil->data->{new}{scan_drbd}{scan_drbd_flush_md};
		my $old_scan_drbd_flush_md         = $anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_flush_md};
		my $new_scan_drbd_timeout          = $anvil->data->{new}{scan_drbd}{scan_drbd_timeout};
		my $old_scan_drbd_timeout          = $anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_timeout};
		my $new_scan_drbd_total_sync_speed = $anvil->data->{new}{scan_drbd}{scan_drbd_total_sync_speed};
		my $old_scan_drbd_total_sync_speed = $anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_total_sync_speed};
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
			"s1:new_scan_drbd_common_xml" => $new_scan_drbd_common_xml, 
			"s2:old_scan_drbd_common_xml" => $old_scan_drbd_common_xml, 
		}});
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
			"s01:scan_drbd_uuid"                 => $scan_drbd_uuid, 
			"s02:scan_drbd_common_xml_diff"      => $scan_drbd_common_xml_diff, 
			"s03:new_scan_drbd_flush_disk"       => $new_scan_drbd_flush_disk, 
			"s04:old_scan_drbd_flush_disk"       => $old_scan_drbd_flush_disk, 
			"s05:new_scan_drbd_flush_md"         => $new_scan_drbd_flush_md, 
			"s06:old_scan_drbd_flush_md"         => $old_scan_drbd_flush_md, 
			"s07:new_scan_drbd_timeout"          => $new_scan_drbd_timeout, 
			"s08:old_scan_drbd_timeout"          => $old_scan_drbd_timeout, 
			"s09:new_scan_drbd_total_sync_speed" => $new_scan_drbd_total_sync_speed." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_total_sync_speed})."/s)", 
			"s10:old_scan_drbd_total_sync_speed" => $old_scan_drbd_total_sync_speed." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_drbd_total_sync_speed})."/s)", 
		}});
		
		my $update = 0;
		if ($new_scan_drbd_flush_disk ne $old_scan_drbd_flush_disk)
		{
			   $update    = 1;
			my $variables = {
				old_value => $new_scan_drbd_flush_disk ? "#!string!scan_drbd_unit_0001!#" : "#!string!scan_drbd_unit_0002!#", 
				new_value => $old_scan_drbd_flush_disk ? "#!string!scan_drbd_unit_0001!#" : "#!string!scan_drbd_unit_0002!#", 
			};
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_drbd_message_0002", variables => $variables});
			$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0002", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
		}
		if ($new_scan_drbd_flush_md ne $old_scan_drbd_flush_md)
		{
			   $update    = 1;
			my $variables = {
				old_value => $new_scan_drbd_flush_md ? "#!string!scan_drbd_unit_0001!#" : "#!string!scan_drbd_unit_0002!#", 
				new_value => $old_scan_drbd_flush_md ? "#!string!scan_drbd_unit_0001!#" : "#!string!scan_drbd_unit_0002!#", 
			};
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_drbd_message_0003", variables => $variables});
			$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0003", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
			
		}
		if ($new_scan_drbd_timeout ne $old_scan_drbd_timeout)
		{
			   $update    = 1;
			my $variables = {
				old_value => $new_scan_drbd_timeout, 
				new_value => $old_scan_drbd_timeout, 
			};
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_drbd_message_0004", variables => $variables});
			$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0004", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
			
		}
		if ($new_scan_drbd_total_sync_speed ne $old_scan_drbd_total_sync_speed)
		{
			# This changes _constantly_ during a resync, so it's info-level.
			   $update    = 1;
			my $variables = {
				old_value => $anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_total_sync_speed}), 
				new_value => $anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_drbd_total_sync_speed}), 
			};
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_drbd_message_0005", variables => $variables});
			$anvil->Alert->register({alert_level => "info", message => "scan_drbd_message_0005", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
			
		}
		if ($scan_drbd_common_xml_diff)
		{
			   $update    = 1;
			my $variables = {
				difference => $scan_drbd_common_xml_diff, 
				new_config => $new_scan_drbd_common_xml, 
			};
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_drbd_message_0006", variables => $variables});
			$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0006", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
		}
		
		if ($update)
		{
			# UPDATE!
			my $query = "
UPDATE 
    scan_drbd 
SET
    scan_drbd_common_xml       = ".$anvil->Database->quote($new_scan_drbd_common_xml).", 
    scan_drbd_flush_disk       = ".$anvil->Database->quote($new_scan_drbd_flush_disk).", 
    scan_drbd_flush_md         = ".$anvil->Database->quote($new_scan_drbd_flush_md).", 
    scan_drbd_timeout          = ".$anvil->Database->quote($new_scan_drbd_timeout).", 
    scan_drbd_total_sync_speed = ".$anvil->Database->quote($new_scan_drbd_total_sync_speed).", 
    modified_date              = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." 
WHERE 
    scan_drbd_uuid             = ".$anvil->Database->quote($scan_drbd_uuid)."
;
";
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
			$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
		}
	}
	else
	{
		# New, INSERT.
		my $scan_drbd_uuid                 = $anvil->Get->uuid();
		my $new_scan_drbd_common_xml       = $anvil->data->{new}{scan_drbd}{scan_drbd_common_xml};
		my $new_scan_drbd_flush_disk       = $anvil->data->{new}{scan_drbd}{scan_drbd_flush_disk};
		my $new_scan_drbd_flush_md         = $anvil->data->{new}{scan_drbd}{scan_drbd_flush_md};
		my $new_scan_drbd_timeout          = $anvil->data->{new}{scan_drbd}{scan_drbd_timeout};
		my $new_scan_drbd_total_sync_speed = $anvil->data->{new}{scan_drbd}{scan_drbd_total_sync_speed};
		my $say_scan_drbd_total_sync_speed = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new}{scan_drbd}{scan_drbd_total_sync_speed}})."/#!string!scan_drbd_unit_0003!#";
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
			"s1:scan_drbd_uuid"                 => $scan_drbd_uuid, 
			"s2:new_scan_drbd_flush_disk"       => $new_scan_drbd_flush_disk, 
			"s3:new_scan_drbd_flush_md"         => $new_scan_drbd_flush_md, 
			"s4:new_scan_drbd_timeout"          => $new_scan_drbd_timeout, 
			"s5:new_scan_drbd_total_sync_speed" => $new_scan_drbd_total_sync_speed, 
			"s6:say_scan_drbd_total_sync_speed" => $say_scan_drbd_total_sync_speed, 
			"s7:new_scan_drbd_common_xml"       => $new_scan_drbd_common_xml, 
		}});
		
		$anvil->data->{old}{scan_drbd_uuid} = $scan_drbd_uuid;
		
		my $variables = {
			new_scan_drbd_flush_disk       => $new_scan_drbd_flush_disk ? "#!string!scan_drbd_unit_0001!#" : "#!string!scan_drbd_unit_0002!#", 
			new_scan_drbd_flush_md         => $new_scan_drbd_flush_md   ? "#!string!scan_drbd_unit_0001!#" : "#!string!scan_drbd_unit_0002!#", 
			new_scan_drbd_timeout          => $new_scan_drbd_timeout, 
			say_scan_drbd_total_sync_speed => $say_scan_drbd_total_sync_speed, 
		};
		$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0001", variables => $variables});
		$anvil->Alert->register({alert_level => "warning", message => "scan_drbd_message_0001", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
		
		my $query = "
INSERT INTO 
    scan_drbd
(
    scan_drbd_uuid, 
    scan_drbd_host_uuid, 
    scan_drbd_common_xml, 
    scan_drbd_flush_disk, 
    scan_drbd_flush_md, 
    scan_drbd_timeout, 
    scan_drbd_total_sync_speed, 
    modified_date
) VALUES (
    ".$anvil->Database->quote($scan_drbd_uuid).", 
    ".$anvil->Database->quote($anvil->Get->host_uuid).", 
    ".$anvil->Database->quote($new_scan_drbd_common_xml).", 
    ".$anvil->Database->quote($new_scan_drbd_flush_disk).", 
    ".$anvil->Database->quote($new_scan_drbd_flush_md).", 
    ".$anvil->Database->quote($new_scan_drbd_timeout).", 
    ".$anvil->Database->quote($new_scan_drbd_total_sync_speed).", 
    ".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
);";
		# Now record the query in the array
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
		$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
	}
	
	return(0);
}

sub process_resource
{
	my ($anvil, $resource) = @_;
	
	my $scan_drbd_resource_uuid    = "";
	my $scan_drbd_resource_name    = $resource;
	my $new_scan_drbd_resource_up  = $anvil->data->{new}{resource}{$resource}{up};
	my $new_scan_drbd_resource_xml = $anvil->data->{new}{resource}{$resource}{xml};
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
		"s1:scan_drbd_resource_name"    => $scan_drbd_resource_name, 
		"s2:new_scan_drbd_resource_up"  => $new_scan_drbd_resource_up, 
		"s3:new_scan_drbd_resource_xml" => $new_scan_drbd_resource_xml, 
	}});
	
	if (exists $anvil->data->{old}{resource_to_uuid}{$scan_drbd_resource_name})
	{
		# If there was a UUID from the resource file, it's the one 
		   $scan_drbd_resource_uuid     = $anvil->data->{old}{resource_to_uuid}{$scan_drbd_resource_name}{uuid};
		my $old_scan_drbd_resource_name = $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_name};
		my $old_scan_drbd_resource_up   = $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_up};
		my $old_scan_drbd_resource_xml  = $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_xml};
		my $xml_difference              = diff \$old_scan_drbd_resource_xml, \$new_scan_drbd_resource_xml, { STYLE => 'Unified' };
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			"s1:old_scan_drbd_resource_name" => $old_scan_drbd_resource_name,
			"s2:old_scan_drbd_resource_up"   => $old_scan_drbd_resource_up,
			"s3:xml_difference"              => $xml_difference, 
			"s4:old_scan_drbd_resource_xml"  => $old_scan_drbd_resource_xml,
			"s5:new_scan_drbd_resource_xml"  => $new_scan_drbd_resource_xml, 
		}});
		
		if (not defined $old_scan_drbd_resource_xml)
		{
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_warning_0001"});
			$anvil->nice_exit({exit_code => 1});
		}
		
		my $update = 0;
		if ($scan_drbd_resource_name ne $old_scan_drbd_resource_name)
		{
			# Name has changed.
				$update    = 1;
			my $variables = {
				new_value => $scan_drbd_resource_name, 
				old_value => $old_scan_drbd_resource_name, 
			};
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0010", variables => $variables});
			$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0010", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
		}
		if ($new_scan_drbd_resource_up ne $old_scan_drbd_resource_up)
		{
			# Resoure state has changed.
				$update    = 1;
			my $variables = {
				resource_name => $scan_drbd_resource_name, 
				new_value     => $new_scan_drbd_resource_up ? "#!string!scan_drbd_unit_0004!#" : "#!string!scan_drbd_unit_0005!#", 
				old_value     => $old_scan_drbd_resource_up ? "#!string!scan_drbd_unit_0004!#" : "#!string!scan_drbd_unit_0005!#", 
			};
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0011", variables => $variables});
			$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0011", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
		}
		if ($old_scan_drbd_resource_xml eq "DELETED")
		{
			# Resource came back.
				$update    = 1;
			my $variables = {
				resource_name => $scan_drbd_resource_name, 
				new_config    => $new_scan_drbd_resource_xml, 
			};
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0012", variables => $variables});
			$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0012", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
		}
		elsif ($xml_difference)
		{
			# Resoure state has changed.
				$update    = 1;
			my $variables = {
				resource_name => $scan_drbd_resource_name, 
				differnce     => $xml_difference, 
				new_config    => $new_scan_drbd_resource_xml, 
			};
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0013", variables => $variables});
			$anvil->Alert->register({clear_alert => 1, alert_level => "warning", message => "scan_drbd_message_0013", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
		}
		if ($update)
		{
			my $query = "
UPDATE 
    scan_drbd_resources
SET 
    scan_drbd_resource_name = ".$anvil->Database->quote($scan_drbd_resource_name).", 
    scan_drbd_resource_up   = ".$anvil->Database->quote($new_scan_drbd_resource_up).", 
    scan_drbd_resource_xml  = ".$anvil->Database->quote($new_scan_drbd_resource_xml).", 
    modified_date           = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." 
WHERE 
    scan_drbd_resource_uuid = ".$anvil->Database->quote($scan_drbd_resource_uuid)."
;";
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
			push @{$anvil->data->{'scan-drbd'}{queries}}, $query;
		}
		
		# Mark that we've seen it.
		$anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{processed} = 1;
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			"old::scan_drbd_resource::scan_drbd_resource_uuid::${scan_drbd_resource_uuid}::processed" => $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{processed},
		}});
	}
	else
	{
		# New resource.
		### This was the old way
		#$scan_drbd_resource_uuid = $anvil->DRBD->resource_uuid({
		#	resource          => $scan_drbd_resource_name,
		#	resource_file     => $anvil->data->{new}{resource}{$scan_drbd_resource_name}{config_file},
		#	new_resource_uuid => $anvil->Get->uuid(), 
		#});
		$scan_drbd_resource_uuid = $anvil->Get->uuid();
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_drbd_resource_uuid => $scan_drbd_resource_uuid }});
		
		my $variables = {
			resource_name  => $scan_drbd_resource_name, 
			resource_state => $new_scan_drbd_resource_up ? "#!string!scan_drbd_unit_0004!#" : "#!string!scan_drbd_unit_0005!#", 
		};
		$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0007", variables => $variables});
		$anvil->Alert->register({alert_level => "warning", message => "scan_drbd_message_0007", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
		
		my $query = "
INSERT INTO 
    scan_drbd_resources 
(
    scan_drbd_resource_uuid, 
    scan_drbd_resource_host_uuid, 
    scan_drbd_resource_name, 
    scan_drbd_resource_up, 
    scan_drbd_resource_xml, 
    modified_date
) VALUES (
    ".$anvil->Database->quote($scan_drbd_resource_uuid).", 
    ".$anvil->Database->quote($anvil->Get->host_uuid).", 
    ".$anvil->Database->quote($scan_drbd_resource_name).", 
    ".$anvil->Database->quote($new_scan_drbd_resource_up).", 
    ".$anvil->Database->quote($new_scan_drbd_resource_xml).", 
    ".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
);";
		# Now record the query in the array
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
		$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
	}
	
	# Now process volumes
	process_volumes($anvil, $scan_drbd_resource_name, $scan_drbd_resource_uuid);
	
	process_peers($anvil, $resource, $scan_drbd_resource_uuid);
	
	return(0);
}

sub process_peers
{
	my ($anvil, $resource, $scan_drbd_resource_uuid) = @_;
	
	foreach my $volume_number (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$resource}{volume}})
	{
		foreach my $peer_host_name (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$resource}{volume}{$volume_number}{peer}})
		{
			### NOTE: Volume needs to be volume_uuid by this point
			### NOTE: So, if we're a node and the peer is Sync'ing from DR, we'll see the
			###       OOS drop and can calculate the % sync change, but we don't see the 
			###       ETA. Also, it appears to be random which peer a node decides to 
			###       sync from. So what we'll need to do when generating the JSON for 
			###       the UI is to see which peers are SyncSource and SyncTarget and pull
			###       the ETA from them.
			my $new_scan_drbd_peer_connection_state       = $anvil->data->{new}{resource}{$resource}{volume}{$volume_number}{peer}{$peer_host_name}{connection_state};
			my $new_scan_drbd_peer_local_disk_state       = $anvil->data->{new}{resource}{$resource}{volume}{$volume_number}{peer}{$peer_host_name}{local_disk_state};
			my $new_scan_drbd_peer_disk_state             = $anvil->data->{new}{resource}{$resource}{volume}{$volume_number}{peer}{$peer_host_name}{peer_disk_state};
			my $new_scan_drbd_peer_local_role             = $anvil->data->{new}{resource}{$resource}{volume}{$volume_number}{peer}{$peer_host_name}{local_role};
			my $new_scan_drbd_peer_role                   = $anvil->data->{new}{resource}{$resource}{volume}{$volume_number}{peer}{$peer_host_name}{peer_role};
			my $new_scan_drbd_peer_out_of_sync_size       = $anvil->data->{new}{resource}{$resource}{volume}{$volume_number}{peer}{$peer_host_name}{out_of_sync_size};
			my $new_scan_drbd_peer_replication_speed      = $anvil->data->{new}{resource}{$resource}{volume}{$volume_number}{peer}{$peer_host_name}{replication_speed};
			my $new_scan_drbd_peer_estimated_time_to_sync = $anvil->data->{new}{resource}{$resource}{volume}{$volume_number}{peer}{$peer_host_name}{estimated_time_to_sync};
			my $new_scan_drbd_peer_ip_address             = $anvil->data->{new}{resource}{$resource}{peer}{$peer_host_name}{peer_ip_address};
			my $new_scan_drbd_peer_tcp_port               = $anvil->data->{new}{resource}{$resource}{peer}{$peer_host_name}{tcp_port};
			my $new_scan_drbd_peer_protocol               = $anvil->data->{new}{resource}{$resource}{peer}{$peer_host_name}{protocol};
			my $new_scan_drbd_peer_fencing                = $anvil->data->{new}{resource}{$resource}{peer}{$peer_host_name}{fencing};
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
				"s1:volume_number"                              => $volume_number, 
				"s2:peer_host_name"                             => $peer_host_name, 
				"s3:new_scan_drbd_peer_connection_state"        => $new_scan_drbd_peer_connection_state, 
				"s4:new_scan_drbd_peer_local_disk_state"        => $new_scan_drbd_peer_local_disk_state, 
				"s5:new_scan_drbd_peer_disk_state"              => $new_scan_drbd_peer_disk_state, 
				"s6:new_scan_drbd_peer_local_role"              => $new_scan_drbd_peer_local_role, 
				"s7:new_scan_drbd_peer_role"                    => $new_scan_drbd_peer_role, 
				"s8:new_scan_drbd_peer_out_of_sync_size"        => $new_scan_drbd_peer_out_of_sync_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_peer_out_of_sync_size}).")", 
				"s9:new_scan_drbd_peer_replication_speed"       => $new_scan_drbd_peer_replication_speed." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_peer_replication_speed})."/s)", 
				"s10:new_scan_drbd_peer_estimated_time_to_sync" => $new_scan_drbd_peer_estimated_time_to_sync." (".$anvil->Convert->time({'time' => $new_scan_drbd_peer_estimated_time_to_sync, long => 1, translate => 1}).")", 
				"s11:new_scan_drbd_peer_ip_address"             => $new_scan_drbd_peer_ip_address, 
				"s12:new_scan_drbd_peer_tcp_port"               => $new_scan_drbd_peer_tcp_port, 
				"s13:new_scan_drbd_peer_protocol"               => $new_scan_drbd_peer_protocol,
				"s14:new_scan_drbd_peer_fencing"                => $new_scan_drbd_peer_fencing,
			}});
			
			# Is there a proxy config?
# 			my $new_scan_drbd_peer_inside_ip_address  = "";
# 			my $new_scan_drbd_peer_inside_tcp_port    = "";
# 			my $new_scan_drbd_peer_outside_ip_address = "";
# 			my $new_scan_drbd_peer_outside_tcp_port   = "";
# 			if (exists $anvil->data->{new}{resource}{$resource}{proxy}{$peer_host_name})
# 			{
# 				$new_scan_drbd_peer_inside_ip_address  = $anvil->data->{new}{resource}{$resource}{proxy}{$peer_host_name}{inside}{ip_address};
# 				$new_scan_drbd_peer_inside_tcp_port    = $anvil->data->{new}{resource}{$resource}{proxy}{$peer_host_name}{inside}{ip_port};
# 				$new_scan_drbd_peer_outside_ip_address = $anvil->data->{new}{resource}{$resource}{proxy}{$peer_host_name}{outside}{ip_address};
# 				$new_scan_drbd_peer_outside_tcp_port   = $anvil->data->{new}{resource}{$resource}{proxy}{$peer_host_name}{outside}{ip_port};
# 				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
# 					"s1:new_scan_drbd_peer_inside_ip_address"  => $new_scan_drbd_peer_inside_ip_address, 
# 					"s2:new_scan_drbd_peer_inside_tcp_port"    => $new_scan_drbd_peer_inside_tcp_port, 
# 					"s3:new_scan_drbd_peer_outside_ip_address" => $new_scan_drbd_peer_outside_ip_address, 
# 					"s4:new_scan_drbd_peer_outside_tcp_port"   => $new_scan_drbd_peer_outside_tcp_port, 
# 				}});
# 			}
			
			if (exists $anvil->data->{old}{resource_to_uuid}{$resource}{volume}{$volume_number}{peer}{$peer_host_name})
			{
				# Look for changes
				my $scan_drbd_peer_uuid                       = $anvil->data->{old}{resource_to_uuid}{$resource}{volume}{$volume_number}{peer}{$peer_host_name}{uuid};
				my $scan_drbd_peer_scan_drbd_volume_uuid      = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_scan_drbd_volume_uuid};
				my $old_scan_drbd_peer_connection_state       = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_connection_state};
				my $old_scan_drbd_peer_local_disk_state       = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_local_disk_state};
				my $old_scan_drbd_peer_disk_state             = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_disk_state};
				my $old_scan_drbd_peer_local_role             = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_local_role};
				my $old_scan_drbd_peer_role                   = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_role};
				my $old_scan_drbd_peer_out_of_sync_size       = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_out_of_sync_size};
				my $old_scan_drbd_peer_replication_speed      = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_replication_speed};
				my $old_scan_drbd_peer_estimated_time_to_sync = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_estimated_time_to_sync};
				my $old_scan_drbd_peer_ip_address             = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_ip_address};
				my $old_scan_drbd_peer_tcp_port               = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_tcp_port};
				my $old_scan_drbd_peer_protocol               = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_protocol};
				my $old_scan_drbd_peer_fencing                = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_fencing};
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
					"s1:scan_drbd_peer_uuid"                        => $scan_drbd_peer_uuid, 
					"s2:scan_drbd_peer_scan_drbd_volume_uuid"       => $scan_drbd_peer_scan_drbd_volume_uuid, 
					"s3:old_scan_drbd_peer_connection_state"        => $old_scan_drbd_peer_connection_state, 
					"s4:old_scan_drbd_peer_local_disk_state"        => $old_scan_drbd_peer_local_disk_state, 
					"s5:old_scan_drbd_peer_disk_state"              => $old_scan_drbd_peer_disk_state, 
					"s6:old_scan_drbd_peer_local_role"              => $old_scan_drbd_peer_local_role, 
					"s7:old_scan_drbd_peer_role"                    => $old_scan_drbd_peer_role, 
					"s8:old_scan_drbd_peer_out_of_sync_size"        => $old_scan_drbd_peer_out_of_sync_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_drbd_peer_out_of_sync_size}).")", 
					"s9:old_scan_drbd_peer_replication_speed"       => $old_scan_drbd_peer_replication_speed." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_drbd_peer_replication_speed})."/s)", 
					"s10:old_scan_drbd_peer_estimated_time_to_sync" => $old_scan_drbd_peer_estimated_time_to_sync." (".$anvil->Convert->time({'time' => $old_scan_drbd_peer_estimated_time_to_sync, long => 1, translate => 1}).")", 
					"s11:old_scan_drbd_peer_ip_address"             => $old_scan_drbd_peer_ip_address, 
					"s12:old_scan_drbd_peer_tcp_port"               => $old_scan_drbd_peer_tcp_port, 
					"s13:old_scan_drbd_peer_protocol"               => $old_scan_drbd_peer_protocol,
					"s14:old_scan_drbd_peer_fencing"                => $old_scan_drbd_peer_fencing,
				}});
				
				my $update = 0;
				if ($new_scan_drbd_peer_connection_state ne $old_scan_drbd_peer_connection_state)
				{
					   $update    = 1;
					my $variables = {
						resource_name                => $resource, 
						volume_number                => $volume_number, 
						peer_name                    => $peer_host_name, 
						new_connection_state         => "#!string!scan_drbd_state_".$new_scan_drbd_peer_connection_state."_name!#",
						new_connection_state_explain => "#!string!scan_drbd_state_".$new_scan_drbd_peer_connection_state."_explain!#",
						old_connection_state         => "#!string!scan_drbd_state_".$old_scan_drbd_peer_connection_state."_name!#",
						old_connection_state_explain => "#!string!scan_drbd_state_".$old_scan_drbd_peer_connection_state."_explain!#",
					};
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0021", variables => $variables});
					$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0021", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				if ($new_scan_drbd_peer_local_disk_state ne $old_scan_drbd_peer_local_disk_state)
				{
					   $update    = 1;
					my $variables = {
						resource_name                => $resource, 
						volume_number                => $volume_number, 
						peer_name                    => $peer_host_name, 
						new_local_disk_state         => "#!string!scan_drbd_state_".$new_scan_drbd_peer_local_disk_state."_name!#",
						new_local_disk_state_explain => "#!string!scan_drbd_state_".$new_scan_drbd_peer_local_disk_state."_explain!#",
						old_local_disk_state         => "#!string!scan_drbd_state_".$old_scan_drbd_peer_local_disk_state."_name!#",
						old_local_disk_state_explain => "#!string!scan_drbd_state_".$old_scan_drbd_peer_local_disk_state."_explain!#",
					};
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0022", variables => $variables});
					$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0022", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				if ($new_scan_drbd_peer_disk_state ne $old_scan_drbd_peer_disk_state)
				{
					   $update    = 1;
					my $variables = {
						resource_name          => $resource, 
						volume_number          => $volume_number, 
						peer_name              => $peer_host_name, 
						new_disk_state         => "#!string!scan_drbd_state_".$new_scan_drbd_peer_disk_state."_name!#",
						new_disk_state_explain => "#!string!scan_drbd_state_".$new_scan_drbd_peer_disk_state."_explain!#",
						old_disk_state         => "#!string!scan_drbd_state_".$old_scan_drbd_peer_disk_state."_name!#",
						old_disk_state_explain => "#!string!scan_drbd_state_".$old_scan_drbd_peer_disk_state."_explain!#",
					};
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0023", variables => $variables});
					$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0023", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				if ($new_scan_drbd_peer_local_role ne $old_scan_drbd_peer_local_role)
				{
					   $update    = 1;
					my $variables = {
						resource_name          => $resource, 
						volume_number          => $volume_number, 
						peer_name              => $peer_host_name, 
						new_local_role         => "#!string!scan_drbd_state_".$new_scan_drbd_peer_local_role."_name!#",
						new_local_role_explain => "#!string!scan_drbd_state_".$new_scan_drbd_peer_local_role."_explain!#",
						old_local_role         => "#!string!scan_drbd_state_".$old_scan_drbd_peer_local_role."_name!#",
						old_local_role_explain => "#!string!scan_drbd_state_".$old_scan_drbd_peer_local_role."_explain!#",
					};
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0024", variables => $variables});
					$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0024", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				if ($new_scan_drbd_peer_role ne $old_scan_drbd_peer_role)
				{
					   $update    = 1;
					my $variables = {
						resource_name    => $resource, 
						volume_number    => $volume_number, 
						peer_name        => $peer_host_name, 
						new_role         => "#!string!scan_drbd_state_".$new_scan_drbd_peer_role."_name!#",
						new_role_explain => "#!string!scan_drbd_state_".$new_scan_drbd_peer_role."_explain!#",
						old_role         => "#!string!scan_drbd_state_".$old_scan_drbd_peer_role."_name!#",
						old_role_explain => "#!string!scan_drbd_state_".$old_scan_drbd_peer_role."_explain!#",
					};
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0025", variables => $variables});
					$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0025", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				if ($new_scan_drbd_peer_out_of_sync_size ne $old_scan_drbd_peer_out_of_sync_size)
				{
					# This constantly changes during a resync
					   $update    = 1;
					my $variables = {
						resource_name        => $resource, 
						volume_number        => $volume_number, 
						peer_name            => $peer_host_name, 
						new_out_of_sync_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_peer_out_of_sync_size}),
						old_out_of_sync_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_drbd_peer_out_of_sync_size}),
					};
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0026", variables => $variables});
					$anvil->Alert->register({alert_level => "info", message => "scan_drbd_message_0026", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				if ($new_scan_drbd_peer_replication_speed ne $old_scan_drbd_peer_replication_speed)
				{
					# This constantly changes during a resync
					   $update    = 1;
					my $variables = {
						resource_name         => $resource, 
						volume_number         => $volume_number, 
						peer_name             => $peer_host_name, 
						new_replication_speed => $anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_peer_replication_speed}),
						old_replication_speed => $anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_drbd_peer_replication_speed}),
					};
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0027", variables => $variables});
					$anvil->Alert->register({alert_level => "info", message => "scan_drbd_message_0027", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				if ($new_scan_drbd_peer_estimated_time_to_sync ne $old_scan_drbd_peer_estimated_time_to_sync)
				{
					# This constantly changes during a resync
					   $update    = 1;
					my $variables = {
						resource_name              => $resource, 
						volume_number              => $volume_number, 
						peer_name                  => $peer_host_name, 
						new_estimated_time_to_sync => $anvil->Convert->time({'time' => $new_scan_drbd_peer_estimated_time_to_sync, long => 1, translate => 1}),
						old_estimated_time_to_sync => $anvil->Convert->time({'time' => $old_scan_drbd_peer_estimated_time_to_sync, long => 1, translate => 1}),
					};
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0028", variables => $variables});
					$anvil->Alert->register({alert_level => "info", message => "scan_drbd_message_0028", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				if (($new_scan_drbd_peer_ip_address ne $old_scan_drbd_peer_ip_address) or 
				    ($new_scan_drbd_peer_tcp_port   ne $old_scan_drbd_peer_tcp_port))
				{
					   $update    = 1;
					my $variables = {
						resource_name  => $resource, 
						volume_number  => $volume_number, 
						peer_name      => $peer_host_name, 
						new_ip_address => $new_scan_drbd_peer_ip_address,
						new_tcp_port   => $new_scan_drbd_peer_tcp_port,
						old_ip_address => $old_scan_drbd_peer_ip_address,
						old_tcp_port   => $old_scan_drbd_peer_tcp_port,
					};
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0029", variables => $variables});
					$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0029", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				if ($new_scan_drbd_peer_protocol ne $old_scan_drbd_peer_protocol)
				{
					   $update    = 1;
					my $variables = {
						resource_name => $resource, 
						volume_number => $volume_number, 
						peer_name     => $peer_host_name, 
						new_protocol  => $new_scan_drbd_peer_protocol,
						old_protocol  => $old_scan_drbd_peer_protocol,
					};
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0030", variables => $variables});
					$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0030", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				if ($new_scan_drbd_peer_fencing ne $old_scan_drbd_peer_fencing)
				{
					   $update    = 1;
					my $variables = {
						resource_name => $resource, 
						volume_number => $volume_number, 
						peer_name     => $peer_host_name, 
						new_fencing   => $new_scan_drbd_peer_fencing,
						old_fencing   => $old_scan_drbd_peer_fencing,
					};
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0031", variables => $variables});
					$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0031", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				
				if ($update)
				{
					my $query = "
UPDATE 
    scan_drbd_peers 
SET 
    scan_drbd_peer_host_name              = ".$anvil->Database->quote($peer_host_name).", 
    scan_drbd_peer_connection_state       = ".$anvil->Database->quote($new_scan_drbd_peer_connection_state).", 
    scan_drbd_peer_local_disk_state       = ".$anvil->Database->quote($new_scan_drbd_peer_local_disk_state).", 
    scan_drbd_peer_disk_state             = ".$anvil->Database->quote($new_scan_drbd_peer_disk_state).", 
    scan_drbd_peer_local_role             = ".$anvil->Database->quote($new_scan_drbd_peer_local_role).", 
    scan_drbd_peer_role                   = ".$anvil->Database->quote($new_scan_drbd_peer_role).", 
    scan_drbd_peer_out_of_sync_size       = ".$anvil->Database->quote($new_scan_drbd_peer_out_of_sync_size).", 
    scan_drbd_peer_replication_speed      = ".$anvil->Database->quote($new_scan_drbd_peer_replication_speed).", 
    scan_drbd_peer_estimated_time_to_sync = ".$anvil->Database->quote($new_scan_drbd_peer_estimated_time_to_sync).", 
    scan_drbd_peer_ip_address             = ".$anvil->Database->quote($new_scan_drbd_peer_ip_address).", 
    scan_drbd_peer_tcp_port               = ".$anvil->Database->quote($new_scan_drbd_peer_tcp_port).", 
    scan_drbd_peer_protocol               = ".$anvil->Database->quote($new_scan_drbd_peer_protocol).", 
    scan_drbd_peer_fencing                = ".$anvil->Database->quote($new_scan_drbd_peer_fencing).", 
    modified_date                         = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
WHERE
    scan_drbd_peer_uuid                   = ".$anvil->Database->quote($scan_drbd_peer_uuid)." 
;";
					$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
					push @{$anvil->data->{'scan-drbd'}{queries}}, $query;
				}
				
				$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{processed} = 1;
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
					"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::processed" => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{processed},
				}});
			}
			else
			{
				# New
				my $variables = {
					resource_name          => $resource, 
					volume_number          => $volume_number, 
					peer_name              => $peer_host_name, 
					connection_state       => $new_scan_drbd_peer_connection_state, 
					local_disk_state       => $new_scan_drbd_peer_local_disk_state, 
					disk_state             => $new_scan_drbd_peer_disk_state, 
					local_role             => $new_scan_drbd_peer_local_role, 
					peer_role              => $new_scan_drbd_peer_role, 
					out_of_sync_size       => $anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_peer_out_of_sync_size}), 
					replication_speed      => $anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_peer_replication_speed}), 
					estimated_time_to_sync => $anvil->Convert->time({'time' => $new_scan_drbd_peer_estimated_time_to_sync, long => 1, translate => 1}), 
					peer_ip_address        => $new_scan_drbd_peer_ip_address, 
					peer_tcp_port          => $new_scan_drbd_peer_tcp_port, 
					peer_protocol          => $new_scan_drbd_peer_protocol,
					peer_fencing           => $new_scan_drbd_peer_fencing,
				};
				$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0020", variables => $variables});
				$anvil->Alert->register({alert_level => "warning", message => "scan_drbd_message_0020", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				
				my $scan_drbd_peer_uuid                  = $anvil->Get->uuid();
				my $scan_drbd_peer_scan_drbd_volume_uuid = $anvil->data->{volume_uuid}{resource}{$resource}{volume}{$volume_number}{uuid};
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
					scan_drbd_peer_uuid                  => $scan_drbd_peer_uuid,
					scan_drbd_peer_scan_drbd_volume_uuid => $scan_drbd_peer_scan_drbd_volume_uuid, 
				}});
				
				if (not $scan_drbd_peer_scan_drbd_volume_uuid)
				{
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_warning_0002"});
					$anvil->nice_exit({exit_code => 1});
				}
				
				my $query = "
INSERT INTO 
    scan_drbd_peers 
(
    scan_drbd_peer_uuid, 
    scan_drbd_peer_host_uuid, 
    scan_drbd_peer_scan_drbd_volume_uuid, 
    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, 
    modified_date
) VALUES (
    ".$anvil->Database->quote($scan_drbd_peer_uuid).", 
    ".$anvil->Database->quote($anvil->Get->host_uuid).", 
    ".$anvil->Database->quote($scan_drbd_peer_scan_drbd_volume_uuid).", 
    ".$anvil->Database->quote($peer_host_name).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_connection_state).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_local_disk_state).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_disk_state).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_local_role).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_role).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_out_of_sync_size).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_replication_speed).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_estimated_time_to_sync).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_ip_address).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_tcp_port).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_protocol).", 
    ".$anvil->Database->quote($new_scan_drbd_peer_fencing).", 
    ".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
);";
				# Now record the query immediately
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
				$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
			}
		}
	}
	
	return(0);
}

sub process_volumes
{
	my ($anvil, $scan_drbd_resource_name, $scan_drbd_resource_uuid) = @_;
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
		scan_drbd_resource_name => $scan_drbd_resource_name, 
		scan_drbd_resource_uuid => $scan_drbd_resource_uuid,
	}});
	
	foreach my $scan_drbd_volume_number (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$scan_drbd_resource_name}{volume}})
	{
		my $new_scan_drbd_volume_device_path  = $anvil->data->{new}{resource}{$scan_drbd_resource_name}{volume}{$scan_drbd_volume_number}{device_path};
		my $new_scan_drbd_volume_device_minor = $anvil->data->{new}{resource}{$scan_drbd_resource_name}{volume}{$scan_drbd_volume_number}{device_minor};
		my $new_scan_drbd_volume_size         = $anvil->data->{new}{resource}{$scan_drbd_resource_name}{volume}{$scan_drbd_volume_number}{size};
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
			"s1:scan_drbd_resource_name"           => $scan_drbd_resource_name, 
			"s2:scan_drbd_resource_uuid"           => $scan_drbd_resource_uuid, 
			"s3:scan_drbd_volume_number"           => $scan_drbd_volume_number, 
			"s4:new_scan_drbd_volume_device_path"  => $new_scan_drbd_volume_device_path, 
			"s5:new_scan_drbd_volume_device_minor" => $new_scan_drbd_volume_device_minor, 
			"s6:new_scan_drbd_volume_size"         => $new_scan_drbd_volume_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_volume_size}).")",
		}});
		
		if (exists $anvil->data->{volume_to_uuid}{$scan_drbd_resource_name}{volume_number}{$scan_drbd_volume_number})
		{
			# Existing volume, look for changes.
			my $scan_drbd_volume_uuid             = $anvil->data->{volume_to_uuid}{$scan_drbd_resource_name}{volume_number}{$scan_drbd_volume_number}{uuid};
			my $old_scan_drbd_volume_device_path  = $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_device_path};
			my $old_scan_drbd_volume_device_minor = $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_device_minor};
			my $old_scan_drbd_volume_size         = $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_size};
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
				"s1:scan_drbd_volume_uuid"             => $scan_drbd_volume_uuid, 
				"s2:old_scan_drbd_volume_device_path"  => $old_scan_drbd_volume_device_path, 
				"s3:old_scan_drbd_volume_device_minor" => $old_scan_drbd_volume_device_minor, 
				"s4:old_scan_drbd_volume_size"         => $old_scan_drbd_volume_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_drbd_volume_size}).")",
			}});
			
			# If the $new_scan_drbd_volume_size is '0', the device is down. Don't update it so we can 
			# recall the last known size.
			if ($new_scan_drbd_volume_size == 0)
			{
				$new_scan_drbd_volume_size = $old_scan_drbd_volume_size;
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
					new_scan_drbd_volume_size => $new_scan_drbd_volume_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_volume_size}).")",
				}});
			}
			
			my $update = 0;
			if ($new_scan_drbd_volume_device_path ne $old_scan_drbd_volume_device_path)
			{
				   $update    = 1;
				my $variables = {
					resource_name => $scan_drbd_resource_name, 
					volume_number => $scan_drbd_volume_number, 
					new_value     => $new_scan_drbd_volume_device_path, 
					old_value     => $old_scan_drbd_volume_device_path, 
				};
				if ($old_scan_drbd_volume_device_path eq "DELETED")
				{
					# Volume has returned.
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0016", variables => $variables});
					$anvil->Alert->register({alert_level => "warning", message => "scan_drbd_message_0016", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
				else
				{
					# Path has changed. Probably part of a server rename.
					$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0017", variables => $variables});
					$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0017", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
				}
			}
			if ($new_scan_drbd_volume_device_minor ne $old_scan_drbd_volume_device_minor)
			{
				# The minor-number changing is almost certainly a human-changed thing.
				   $update    = 1;
				my $variables = {
					resource_name => $scan_drbd_resource_name, 
					volume_number => $scan_drbd_volume_number, 
					new_value     => $new_scan_drbd_volume_device_minor, 
					old_value     => $old_scan_drbd_volume_device_minor, 
				};
				$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0018", variables => $variables});
				$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0018", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
			}
			if ($new_scan_drbd_volume_size ne $old_scan_drbd_volume_size)
			{
				# Looks like the volume was resized.
				   $update    = 1;
				my $variables = {
					resource_name => $scan_drbd_resource_name, 
					volume_number => $scan_drbd_volume_number, 
					new_value     => $anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_volume_size}), 
					old_value     => $anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_drbd_volume_size}), 
				};
				$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0019", variables => $variables});
				$anvil->Alert->register({alert_level => "notice", message => "scan_drbd_message_0019", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
			}
			
			if ($update)
			{
				my $query = "
UPDATE 
    scan_drbd_volumes
SET 
    scan_drbd_volume_device_path  = ".$anvil->Database->quote($new_scan_drbd_volume_device_path).", 
    scan_drbd_volume_device_minor = ".$anvil->Database->quote($new_scan_drbd_volume_device_minor).", 
    scan_drbd_volume_size         = ".$anvil->Database->quote($new_scan_drbd_volume_size).", 
    modified_date                 = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." 
WHERE 
    scan_drbd_volume_uuid         = ".$anvil->Database->quote($scan_drbd_volume_uuid)."
;";
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
				push @{$anvil->data->{'scan-drbd'}{queries}}, $query;
			}
			
			$anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{processed} = 1;
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
				"old::scan_drbd_volume::scan_drbd_volume_uuid::${scan_drbd_volume_uuid}::processed" => $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{processed},
			}});
		}
		else
		{
			# New volume, INSERT.
			my $variables = {
				resource_name => $scan_drbd_resource_name, 
				volume_number => $scan_drbd_volume_number, 
				device_path   => $new_scan_drbd_volume_device_path, 
				device_minor  => $new_scan_drbd_volume_device_minor, 
				volume_size   => $new_scan_drbd_volume_size, 
			};
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0014", variables => $variables});
			$anvil->Alert->register({alert_level => "warning", message => "scan_drbd_message_0014", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
			
			my $scan_drbd_volume_uuid = $anvil->Get->uuid();
			my $query                 = "
INSERT INTO 
    scan_drbd_volumes 
(
    scan_drbd_volume_uuid, 
    scan_drbd_volume_host_uuid, 
    scan_drbd_volume_scan_drbd_resource_uuid, 
    scan_drbd_volume_number, 
    scan_drbd_volume_device_path, 
    scan_drbd_volume_device_minor, 
    scan_drbd_volume_size, 
    modified_date
) VALUES (
    ".$anvil->Database->quote($scan_drbd_volume_uuid).", 
    ".$anvil->Database->quote($anvil->Get->host_uuid).", 
    ".$anvil->Database->quote($scan_drbd_resource_uuid).", 
    ".$anvil->Database->quote($scan_drbd_volume_number).", 
    ".$anvil->Database->quote($new_scan_drbd_volume_device_path).", 
    ".$anvil->Database->quote($new_scan_drbd_volume_device_minor).", 
    ".$anvil->Database->quote($new_scan_drbd_volume_size).", 
    ".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
);";
			# Now record the query in the array
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
			$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
			
			$anvil->data->{volume_uuid}{resource}{$scan_drbd_resource_name}{volume}{$scan_drbd_volume_number}{uuid} = $scan_drbd_volume_uuid;
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
				"volume_uuid::resource::${scan_drbd_resource_name}::volume::${scan_drbd_volume_number}::uuid" => $anvil->data->{volume_uuid}{resource}{$scan_drbd_resource_name}{volume}{$scan_drbd_volume_number}{uuid}, 
			}});
		}
	}
	
	return(0);
}

sub find_changes
{
	my ($anvil) = @_;
	
	#print Dumper $anvil->data->{new};
	my $new_scan_drbd_common_xml       = $anvil->data->{new}{scan_drbd}{scan_drbd_common_xml};
	my $new_scan_drbd_flush_disk       = $anvil->data->{new}{scan_drbd}{scan_drbd_flush_disk};
	my $new_scan_drbd_flush_md         = $anvil->data->{new}{scan_drbd}{scan_drbd_flush_md};
	my $new_scan_drbd_timeout          = $anvil->data->{new}{scan_drbd}{scan_drbd_timeout};
	my $new_scan_drbd_total_sync_speed = $anvil->data->{new}{scan_drbd}{scan_drbd_total_sync_speed};
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
		"s1:new_scan_drbd_flush_disk"       => $new_scan_drbd_flush_disk, 
		"s2:new_scan_drbd_flush_md"         => $new_scan_drbd_flush_md, 
		"s3:new_scan_drbd_timeout"          => $new_scan_drbd_timeout, 
		"s4:new_scan_drbd_total_sync_speed" => $new_scan_drbd_total_sync_speed." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_scan_drbd_total_sync_speed})."/s)", 
		"s5:new_scan_drbd_common_xml"       => $new_scan_drbd_common_xml, 
	}});
	
	process_drbd($anvil);
	
	foreach my $resource (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}})
	{
		process_resource($anvil, $resource);
	}

	# Check for resources that have vanished.
	foreach my $scan_drbd_resource_uuid (keys %{$anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}})
	{
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			"old::scan_drbd_volume::scan_drbd_resource::scan_drbd_resource_uuid::${scan_drbd_resource_uuid}::processed" => $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{processed},
		}});
		next if $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{processed};
		
		my $old_scan_drbd_resource_name = $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_name};
		my $old_scan_drbd_resource_up   = $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_up};
		my $old_scan_drbd_resource_xml  = $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_xml};
		next if $old_scan_drbd_resource_xml eq "DELETED";
		
		my $variables = {
			resource_name => $old_scan_drbd_resource_name, 
		};
		$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0009", variables => $variables});
		$anvil->Alert->register({alert_level => "warning", message => "scan_drbd_message_0009", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
		
		# If we're here, this is a freshly vanished resource.
		my $query = "
UPDATE 
    scan_drbd_resources
SET 
    scan_drbd_resource_xml  = 'DELETED', 
    modified_date           = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." 
WHERE 
    scan_drbd_resource_uuid = ".$anvil->Database->quote($scan_drbd_resource_uuid)."
;
;";
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
		push @{$anvil->data->{'scan-drbd'}{queries}}, $query;
	}
	
	# Now look for deleted volumes
	foreach my $scan_drbd_volume_uuid (keys %{$anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}})
	{
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			"old::scan_drbd_volume::scan_drbd_volume_uuid::${scan_drbd_volume_uuid}::processed" => $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{processed},
		}});
		next if $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{processed};
		
		my $scan_drbd_resource_uuid          = $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_scan_drbd_resource_uuid};
		my $scan_drbd_resource_name          = $anvil->data->{old}{uuid_to_resource}{$scan_drbd_resource_uuid}{name};
		my $old_scan_drbd_volume_device_path = $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_device_path};
		my $old_scan_drbd_volume_number      = $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_number};
		next if $old_scan_drbd_volume_device_path eq "DELETED";
		
		my $variables = {
			resource_name => $scan_drbd_resource_name, 
			volume_number => $old_scan_drbd_volume_number, 
		};
		$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0015", variables => $variables});
		$anvil->Alert->register({alert_level => "warning", message => "scan_drbd_message_0015", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
		
		# If we're here, this is a freshly vanished resource.
		my $query = "
UPDATE 
    scan_drbd_volumes
SET 
    scan_drbd_volume_device_path = 'DELETED', 
    modified_date                = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." 
WHERE 
    scan_drbd_volume_uuid        = ".$anvil->Database->quote($scan_drbd_volume_uuid)."
;";
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
		push @{$anvil->data->{'scan-drbd'}{queries}}, $query;
	}
	
	foreach my $scan_drbd_peer_uuid (keys %{$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}})
	{
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::processed" => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{processed},
		}});
		next if $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{processed};
		
		my $old_scan_drbd_peer_connection_state = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_connection_state};
		next if $old_scan_drbd_peer_connection_state eq "DELETED";
		
		my $scan_drbd_peer_name     = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_host_name};
		my $scan_drbd_volume_uuid   = $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_scan_drbd_volume_uuid};
		my $scan_drbd_volume_number = $anvil->data->{volume_to_uuid}{$scan_drbd_volume_uuid}{number};
		my $scan_drbd_resource_uuid = $anvil->data->{volume_to_uuid}{$scan_drbd_volume_uuid}{on_resource};
		my $scan_drbd_resource_name = $anvil->data->{old}{uuid_to_resource}{$scan_drbd_resource_uuid}{name};
		
		my $variables = {
			resource_name => $scan_drbd_resource_name, 
			volume_number => $scan_drbd_volume_number, 
			peer_name     => $scan_drbd_peer_name, 
		};
		$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0032", variables => $variables});
		$anvil->Alert->register({alert_level => "warning", message => "scan_drbd_message_0032", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-drbd'}{alert_sort}++});
		
		# If we're here, this is a freshly vanished resource.
		my $query = "
UPDATE 
    scan_drbd_peers
SET 
    scan_drbd_peer_connection_state = 'DELETED', 
    modified_date                   = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." 
WHERE 
    scan_drbd_peer_uuid             = ".$anvil->Database->quote($scan_drbd_peer_uuid)."
;";
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
		push @{$anvil->data->{'scan-drbd'}{queries}}, $query;
	}
	
	# Commit all pending queries.
	$anvil->Database->write({query => $anvil->data->{'scan-drbd'}{queries}, source => $THIS_FILE, line => __LINE__});

	
	return(0);
}

# This reads in the last scan's data.
sub read_last_scan
{
	my ($anvil) = @_;
	
	# This is used to determine if there's an entry in scan_drbd directly.
	$anvil->data->{old}{scan_drbd_uuid} = "";
	
	# This calls up the entry for this host. There will only be one.
	my $query = "
SELECT 
    scan_drbd_uuid, 
    scan_drbd_common_xml, 
    scan_drbd_flush_disk, 
    scan_drbd_flush_md, 
    scan_drbd_timeout, 
    scan_drbd_total_sync_speed 
FROM 
    scan_drbd 
WHERE 
    scan_drbd_host_uuid = ".$anvil->Database->quote($anvil->Get->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})
	{
		# We've got an entry in the 'scan_drbd' table, so now we'll look for data in the node and 
		# services tables.
		my $scan_drbd_uuid = $row->[0]; 
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_drbd_uuid => $scan_drbd_uuid }});
		
		# Store the old data now.
		$anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_common_xml}       = $row->[1];
		$anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_flush_disk}       = $row->[2];
		$anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_flush_md}         = $row->[3];
		$anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_timeout}          = $row->[4];
		$anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_total_sync_speed} = $row->[5];
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 
			"old::scan_drbd::scan_drbd_uuid::${scan_drbd_uuid}::scan_drbd_common_xml"       => $anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_common_xml},
			"old::scan_drbd::scan_drbd_uuid::${scan_drbd_uuid}::scan_drbd_flush_disk"       => $anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_flush_disk},
			"old::scan_drbd::scan_drbd_uuid::${scan_drbd_uuid}::scan_drbd_flush_md"         => $anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_flush_md},
			"old::scan_drbd::scan_drbd_uuid::${scan_drbd_uuid}::scan_drbd_timeout"          => $anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_timeout},
			"old::scan_drbd::scan_drbd_uuid::${scan_drbd_uuid}::scan_drbd_total_sync_speed" => $anvil->data->{old}{scan_drbd}{scan_drbd_uuid}{$scan_drbd_uuid}{scan_drbd_total_sync_speed},
		}});
		
		# Record the drbd_uuid in an easy to find place for later when looking for changes.
		$anvil->data->{old}{scan_drbd_uuid} = $scan_drbd_uuid;
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "old::scan_drbd_uuid" => $anvil->data->{old}{scan_drbd_uuid} }});
	}
	undef $count;
	undef $results;

	# Read in the RAM module data.
	$query = "
SELECT 
    scan_drbd_resource_uuid, 
    scan_drbd_resource_name, 
    scan_drbd_resource_up, 
    scan_drbd_resource_xml
FROM 
    scan_drbd_resources 
WHERE 
    scan_drbd_resource_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." 
;";
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
	
	$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
	$count   = @{$results};
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
		results => $results, 
		count   => $count, 
	}});
	foreach my $row (@{$results})
	{
		# We've got an entry in the 'scan_drbd_resources' table, so now we'll look for data in the node and 
		# services tables.
		my $scan_drbd_resource_uuid = $row->[0]; 
		my $scan_drbd_resource_name = $row->[1]; 
		$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,
		}});
		
		# Store the old data now.
		$anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{processed}               = 0;
		$anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_name} = $scan_drbd_resource_name;
		$anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_up}   = $row->[2];
		$anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_xml}  = $row->[3];
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			"old::scan_drbd_resource::scan_drbd_resource_uuid::${scan_drbd_resource_uuid}::scan_drbd_resource_name" => $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_name},
			"old::scan_drbd_resource::scan_drbd_resource_uuid::${scan_drbd_resource_uuid}::scan_drbd_resource_up"   => $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_up},
			"old::scan_drbd_resource::scan_drbd_resource_uuid::${scan_drbd_resource_uuid}::scan_drbd_resource_xml"  => $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$scan_drbd_resource_uuid}{scan_drbd_resource_xml},
		}});
		
		# Record the scan_drbd_resource_uuid in an easy to find place for later when looking for changes.
		$anvil->data->{old}{resource_to_uuid}{$scan_drbd_resource_name}{uuid} = $scan_drbd_resource_uuid;
		$anvil->data->{old}{uuid_to_resource}{$scan_drbd_resource_uuid}{name} = $scan_drbd_resource_name;
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			"old::resource_to_uuid::${scan_drbd_resource_name}::uuid" => $anvil->data->{old}{resource_to_uuid}{$scan_drbd_resource_name}{uuid}, 
			"old::uuid_to_resource::${scan_drbd_resource_uuid}::name" => $anvil->data->{old}{uuid_to_resource}{$scan_drbd_resource_uuid}{name}, 
		}});
	}
	undef $count;
	undef $results;
	
	# Read in the RAM module data.
	$query = "
SELECT 
    scan_drbd_volume_uuid, 
    scan_drbd_volume_scan_drbd_resource_uuid, 
    scan_drbd_volume_number, 
    scan_drbd_volume_device_path, 
    scan_drbd_volume_device_minor, 
    scan_drbd_volume_size
FROM 
    scan_drbd_volumes 
WHERE 
    scan_drbd_volume_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." 
;";
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
	
	$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
	$count   = @{$results};
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
		results => $results, 
		count   => $count, 
	}});
	foreach my $row (@{$results})
	{
		# We've got an entry in the 'scan_drbd_volumes' table, so now we'll look for data in the node and 
		# services tables.
		my $scan_drbd_volume_uuid                    = $row->[0]; 
		my $scan_drbd_volume_scan_drbd_resource_uuid = $row->[1]; 
		my $scan_drbd_volume_number                  = $row->[2];
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			scan_drbd_volume_uuid                    => $scan_drbd_volume_uuid,
			scan_drbd_volume_scan_drbd_resource_uuid => $scan_drbd_volume_scan_drbd_resource_uuid,
			scan_drbd_volume_number                  => $scan_drbd_volume_number, 
		}});
		
		# Store the old data now.
		$anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{processed}                                = 0;
		$anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_scan_drbd_resource_uuid} = $scan_drbd_volume_scan_drbd_resource_uuid;
		$anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_number}                  = $scan_drbd_volume_number;
		$anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_device_path}             = $row->[3];
		$anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_device_minor}            = $row->[4];
		$anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_size}                    = $row->[5];
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			"old::scan_drbd_volume::scan_drbd_volume_uuid::${scan_drbd_volume_uuid}::scan_drbd_volume_scan_drbd_resource_uuid" => $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_scan_drbd_resource_uuid},
			"old::scan_drbd_volume::scan_drbd_volume_uuid::${scan_drbd_volume_uuid}::scan_drbd_volume_number"                  => $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_number},
			"old::scan_drbd_volume::scan_drbd_volume_uuid::${scan_drbd_volume_uuid}::scan_drbd_volume_device_path"             => $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_device_path},
			"old::scan_drbd_volume::scan_drbd_volume_uuid::${scan_drbd_volume_uuid}::scan_drbd_volume_device_minor"            => $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_device_minor},
			"old::scan_drbd_volume::scan_drbd_volume_uuid::${scan_drbd_volume_uuid}::scan_drbd_volume_xml"                     => $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_size}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_volume_uuid}{scan_drbd_volume_size}}).")",
		}});
		
		# Record the scan_drbd_volume_uuid in an easy to find place for later when looking for changes.
		my $on_resource_name = $anvil->data->{old}{uuid_to_resource}{$scan_drbd_volume_scan_drbd_resource_uuid}{name};
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { on_resource_name => $on_resource_name }});

		$anvil->data->{volume_to_uuid}{$scan_drbd_volume_uuid}{number}                                   = $scan_drbd_volume_number;
		$anvil->data->{volume_to_uuid}{$scan_drbd_volume_uuid}{on_resource}                              = $scan_drbd_volume_scan_drbd_resource_uuid;
		$anvil->data->{volume_to_uuid}{$on_resource_name}{volume_number}{$scan_drbd_volume_number}{uuid} = $scan_drbd_volume_uuid;
		$anvil->data->{volume_uuid}{resource}{$on_resource_name}{volume}{$scan_drbd_volume_number}{uuid} = $scan_drbd_volume_uuid;
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			"volume_to_uuid::${scan_drbd_volume_uuid}::number"                                     => $anvil->data->{volume_to_uuid}{$scan_drbd_volume_uuid}{number}, 
			"volume_to_uuid::${scan_drbd_volume_uuid}::on_resource"                                => $anvil->data->{volume_to_uuid}{$scan_drbd_volume_uuid}{on_resource}, 
			"volume_to_uuid::${on_resource_name}::volume_number::${scan_drbd_volume_number}::uuid" => $anvil->data->{volume_to_uuid}{$on_resource_name}{volume_number}{$scan_drbd_volume_number}{uuid}, 
			"volume_uuid::resource::${on_resource_name}::volume::${scan_drbd_volume_number}::uuid" => $anvil->data->{volume_uuid}{resource}{$on_resource_name}{volume}{$scan_drbd_volume_number}{uuid},
		}});
	}
	undef $count;
	undef $results;
	
	# Read in the RAM module data.
	$query = "
SELECT 
    scan_drbd_peer_uuid, 
    scan_drbd_peer_scan_drbd_volume_uuid, 
    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 
FROM 
    scan_drbd_peers 
WHERE 
    scan_drbd_peer_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." 
;";
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
	
	$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
	$count   = @{$results};
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
		results => $results, 
		count   => $count, 
	}});
	foreach my $row (@{$results})
	{
		# We've got an entry in the 'scan_drbd_peers' table, so now we'll look for data in the node and 
		# services tables.
		my $scan_drbd_peer_uuid                  = $row->[0]; 
		my $scan_drbd_peer_scan_drbd_volume_uuid = $row->[1]; 
		my $scan_drbd_peer_host_name             = $row->[2];
		my $scan_drbd_peer_connection_state      = $row->[3];
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			scan_drbd_peer_uuid                  => $scan_drbd_peer_uuid,
			scan_drbd_peer_scan_drbd_volume_uuid => $scan_drbd_peer_scan_drbd_volume_uuid,
			scan_drbd_peer_host_name             => $scan_drbd_peer_host_name, 
			scan_drbd_peer_connection_state      => $scan_drbd_peer_connection_state, 
		}});
		
		# It's possible that a DELETED resource no longer has corresponding LVM data. If so, we'll 
		# purge this record.
		if (($scan_drbd_peer_connection_state eq "DELETED") && (not exists $anvil->data->{volume_to_uuid}{$scan_drbd_peer_scan_drbd_volume_uuid}))
		{
			# Purge it.
			my $resource_uuid = $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_peer_scan_drbd_volume_uuid}{scan_drbd_volume_scan_drbd_resource_uuid};
			my $volume_number = $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_peer_scan_drbd_volume_uuid}{scan_drbd_volume_number};
			my $resource_name = $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$resource_uuid}{scan_drbd_resource_name};
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
				resource_uuid => $resource_uuid, 
				volume_number => $volume_number, 
				resource_name => $resource_name, 
			}});
			$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0035", variables => {
				peer_name     => $scan_drbd_peer_host_name, 
				resource_name => $resource_name, 
				volume_number => $volume_number, 
			}});
			
			my $queries = [];
			push @{$queries}, "DELETE FROM history.scan_drbd_peers WHERE scan_drbd_peer_uuid = '".$scan_drbd_peer_uuid."';";
			push @{$queries}, "DELETE FROM scan_drbd_peers WHERE scan_drbd_peer_uuid = '".$scan_drbd_peer_uuid."';";
			foreach my $query (@{$queries})
			{
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
			}
			$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__});
			
			next;
		}
		
		# Store the old data now.
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{processed}                             = 0;
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_scan_drbd_volume_uuid}  = $scan_drbd_peer_scan_drbd_volume_uuid;
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_host_name}              = $scan_drbd_peer_host_name;
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_connection_state}       = $scan_drbd_peer_connection_state;
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_local_disk_state}       = $row->[4];
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_disk_state}             = $row->[5];
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_local_role}             = $row->[6];
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_role}                   = $row->[7];
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_out_of_sync_size}       = $row->[8];
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_replication_speed}      = $row->[9];
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_estimated_time_to_sync} = $row->[10];
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_ip_address}             = $row->[11];
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_tcp_port}               = $row->[12];
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_protocol}               = $row->[13];
		$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_fencing}                = $row->[14];
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_scan_drbd_volume_uuid"  => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_scan_drbd_volume_uuid},
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_host_name"              => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_host_name},
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_connection_state"       => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_connection_state},
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_local_disk_state"       => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_local_disk_state},
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_disk_state"             => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_disk_state},
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_local_role"             => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_local_role},
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_role"                   => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_role},
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_out_of_sync_size"       => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_out_of_sync_size}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_out_of_sync_size}}).")",
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_replication_speed"      => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_replication_speed}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_replication_speed}}).")",
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_estimated_time_to_sync" => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_estimated_time_to_sync}." (".$anvil->Convert->time({'time' => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_estimated_time_to_sync}, long => 1, translate => 1}).")",
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_ip_address"             => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_ip_address},
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_tcp_port"               => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_tcp_port},
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_protocol"               => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_protocol},
			"old::scan_drbd_peer::scan_drbd_peer_uuid::${scan_drbd_peer_uuid}::scan_drbd_peer_fencing"                => $anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_fencing},
		}});
		
		# Record the scan_drbd_peer_uuid in an easy to find place for later when looking for changes.
		my $volume_number    = $anvil->data->{volume_to_uuid}{$scan_drbd_peer_scan_drbd_volume_uuid}{number};
		my $on_resource_uuid = $anvil->data->{volume_to_uuid}{$scan_drbd_peer_scan_drbd_volume_uuid}{on_resource};
		my $on_resource_name = $anvil->data->{old}{uuid_to_resource}{$on_resource_uuid}{name};
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			volume_number    => $volume_number,
			on_resource_uuid => $on_resource_uuid, 
			on_resource_name => $on_resource_name, 
		}});
		
		$anvil->data->{old}{resource_to_uuid}{$on_resource_name}{volume}{$volume_number}{peer}{$scan_drbd_peer_host_name}{uuid} = $scan_drbd_peer_uuid;
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
			"old::resource_to_uuid::${on_resource_name}::volume::${volume_number}::peer::${scan_drbd_peer_host_name}::uuid" => $anvil->data->{old}{resource_to_uuid}{$on_resource_name}{volume}{$volume_number}{peer}{$scan_drbd_peer_host_name}{uuid}, 
		}});
	}
	
	return(0);
}
