diff --git a/Anvil/Tools/Cluster.pm b/Anvil/Tools/Cluster.pm
index 11a2c55e..3b9fe02a 100644
--- a/Anvil/Tools/Cluster.pm
+++ b/Anvil/Tools/Cluster.pm
@@ -299,8 +299,7 @@ sub assemble_storage_groups
SELECT
anvil_name,
anvil_node1_host_uuid,
- anvil_node2_host_uuid,
- anvil_dr1_host_uuid
+ anvil_node2_host_uuid
FROM
anvils
WHERE
@@ -321,15 +320,13 @@ WHERE
}
# Get the details.
- my $anvil_name = $results->[0]->[0];
- my $node1_host_uuid = $results->[0]->[1];
- my $node2_host_uuid = $results->[0]->[2];
- my $dr1_host_uuid = defined $results->[0]->[3] ? $results->[0]->[3] : "";
+ my $anvil_name = $results->[0]->[0];
+ my $node1_host_uuid = $results->[0]->[1];
+ my $node2_host_uuid = $results->[0]->[2];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
anvil_name => $anvil_name,
node1_host_uuid => $node1_host_uuid,
node2_host_uuid => $node2_host_uuid,
- dr1_host_uuid => $dr1_host_uuid,
}});
# Load known storage groups.
@@ -337,20 +334,9 @@ WHERE
# Look for ungrouped VGs and see if we can group them by matching identical sizes together.
my $hosts = [$node1_host_uuid, $node2_host_uuid];
- if ($dr1_host_uuid)
- {
- push @{$hosts}, $dr1_host_uuid;
- }
- else
- {
- # No DR.
- $anvil->data->{ungrouped_vg_count}{dr1} = 0;
- }
foreach my $host_uuid (@{$hosts})
{
- my $this_is = "node1";
- if ($host_uuid eq $node2_host_uuid) { $this_is = "node2"; }
- elsif ($host_uuid eq $dr1_host_uuid) { $this_is = "dr1"; }
+ my $this_is = $host_uuid eq $node2_host_uuid ? "node2" : "node1";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_is => $this_is }});
$anvil->data->{ungrouped_vg_count}{$this_is} = 0;
@@ -432,13 +418,13 @@ ORDER BY
my $reload_storage_groups = 0;
foreach my $scan_lvm_vg_size (sort {$a cmp $b} keys %{$anvil->data->{ungrouped_vgs}})
{
- # If there are two or three VGs, we can create a group.
+ # If there are two VGs, we can create a group.
my $count = keys %{$anvil->data->{ungrouped_vgs}{$scan_lvm_vg_size}{host_uuid}};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
scan_lvm_vg_size => $scan_lvm_vg_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_size}).")",
count => $count,
}});
- if (($count == 2) or ($count == 3))
+ if ($count == 2)
{
# Create the volume group ... group. First we need a group number
my $storage_group_uuid = $anvil->Database->insert_or_update_storage_groups({
@@ -447,11 +433,10 @@ ORDER BY
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { storage_group_uuid => $storage_group_uuid }});
+ # Now add the VGs as members.
foreach my $host_uuid (keys %{$anvil->data->{ungrouped_vgs}{$scan_lvm_vg_size}{host_uuid}})
{
- my $this_is = "node1";
- if ($host_uuid eq $node2_host_uuid) { $this_is = "node2"; }
- elsif ($host_uuid eq $dr1_host_uuid) { $this_is = "dr1"; }
+ my $this_is = $host_uuid eq $node2_host_uuid ? "node2" : "node1";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_is => $this_is }});
my $storage_group_member_vg_uuid = $anvil->data->{ungrouped_vgs}{$scan_lvm_vg_size}{host_uuid}{$host_uuid}{vg_internal_uuid};
@@ -482,27 +467,21 @@ ORDER BY
}
# If there's only one VG on each node that is ungrouped, group them even though they're not the same
- # size. If DR also has only 1 VG ungrouped, it'll be added, too.
+ # size.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"ungrouped_vg_count::node1" => $anvil->data->{ungrouped_vg_count}{node1},
"ungrouped_vg_count::node2" => $anvil->data->{ungrouped_vg_count}{node2},
- "ungrouped_vg_count::dr1" => $anvil->data->{ungrouped_vg_count}{dr1},
}});
if (($anvil->data->{ungrouped_vg_count}{node1} == 1) && ($anvil->data->{ungrouped_vg_count}{node2} == 1))
{
# We do!
- my $storage_group_uuid = $anvil->Database->create_storage_group({
- debug => $debug,
+ my $storage_group_uuid = $anvil->Database->insert_or_update_storage_groups({
+ debug => 2,
storage_group_anvil_uuid => $anvil_uuid,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { storage_group_uuid => $storage_group_uuid }});
- my $hosts = [$node1_host_uuid, $node2_host_uuid];
- if ($anvil->data->{ungrouped_vg_count}{dr1} == 1)
- {
- push @{$hosts}, $dr1_host_uuid;
- }
- foreach my $host_uuid (@{$hosts})
+ foreach my $host_uuid ($node1_host_uuid, $node2_host_uuid)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
@@ -539,13 +518,131 @@ ORDER BY
if ($reload_storage_groups)
{
$anvil->Database->get_storage_group_data({debug => $debug});
- my $storage_group_uuid = $anvil->Database->insert_or_update_storage_groups({
- debug => 2,
- storage_group_anvil_uuid => $anvil_uuid,
- });
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { storage_group_uuid => $storage_group_uuid }});
}
+ # Now loop through any attached DRs and add the VGs that are closest in sizes to the VGs we have in
+ # this Anvil! node.
+ $anvil->Database->get_dr_links({debug => 2});
+
+ # This was going to automatically add VGs from DR hosts to an Anvil's Storage Group, but given now
+ # that things can be linked in random ways, this doesn't seem to make sense anymore. So the code is
+ # (not complete but) preserved here in case we change out mind later.
+=cut
+ foreach my $dr_link_host_name (sort {$a cmp $b} keys %{$anvil->data->{dr_links}{by_anvil_uuid}{$anvil_uuid}{dr_link_host_name}})
+ {
+ my $dr_link_uuid = $anvil->data->{dr_links}{by_anvil_uuid}{$anvil_uuid}{dr_link_host_name}{$dr_link_host_name}{dr_link_uuid};
+ my $dr_link_host_uuid = $anvil->Database->get_host_uuid_from_string({debug => $debug, string => $dr_link_host_name});
+ my $dr_link_short_host_name = $anvil->data->{hosts}{host_uuid}{$dr_link_host_uuid}{short_host_name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ 's1:dr_link_host_name' => $dr_link_host_name,
+ 's2:dr_link_host_uuid' => $dr_link_host_uuid,
+ 's3:dr_link_short_host_name' => $dr_link_short_host_name,
+ 's4:dr_link_uuid' => $dr_link_uuid,
+ }});
+
+ # What VGs do these DR hosts have, and are they in any storage groups yet?
+ my $query = "
+SELECT
+ scan_lvm_vg_uuid,
+ scan_lvm_vg_name,
+ scan_lvm_vg_size,
+ scan_lvm_vg_internal_uuid
+FROM
+ scan_lvm_vgs
+WHERE
+ scan_lvm_vg_host_uuid = ".$anvil->Database->quote($dr_link_uuid)."
+AND
+ scan_lvm_vg_name != 'DELETED'
+ORDER BY
+ scan_lvm_vg_size ASC
+;";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, 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 => $debug, list => {
+ results => $results,
+ count => $count,
+ }});
+
+ foreach my $row (@{$results})
+ {
+ my $scan_lvm_vg_uuid = $row->[0];
+ my $scan_lvm_vg_name = $row->[1];
+ my $scan_lvm_vg_size = $row->[2];
+ my $scan_lvm_vg_internal_uuid = $row->[3];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ 's1:scan_lvm_vg_uuid' => $scan_lvm_vg_uuid,
+ 's2:scan_lvm_vg_name' => $scan_lvm_vg_name,
+ 's3:scan_lvm_vg_size' => $scan_lvm_vg_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_size}).")",
+ 's4:scan_lvm_vg_internal_uuid' => $scan_lvm_vg_internal_uuid,
+ }});
+
+ # Is this VG already in a storage group for this anvil! node?
+ my $vg_found = 0;
+ foreach my $storage_group_uuid (keys %{$anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}})
+ {
+ my $storage_group_name = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{group_name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ 's1:storage_group_uuid' => $storage_group_uuid,
+ 's2:storage_group_name' => $storage_group_name,
+ }});
+ foreach my $this_host_uuid (sort {$a cmp $b} keys %{$anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{short_host_name}})
+ {
+ next if $this_host_uuid eq $dr_link_host_uuid;
+ my $storage_group_member_note = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$$this_host_uuid}{storage_group_member_note};
+ my $storage_group_member_vg_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$this_host_uuid}{vg_internal_uuid};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ 's1:this_host_uuid' => $this_host_uuid,
+ 's2:storage_group_member_vg_uuid' => $storage_group_member_vg_uuid,
+ 's3:storage_group_member_note' => $storage_group_member_note,
+ }});
+ next if $storage_group_member_note eq "DELETED";
+ if ($storage_group_member_vg_uuid eq $scan_lvm_vg_internal_uuid)
+ {
+ $vg_found = 1;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { vg_found => $vg_found }});
+ }
+ }
+ }
+
+ if (not $vg_found)
+ {
+ # Find the smallest
+ my $query = "
+SELECT
+ scan_lvm_vg_uuid,
+ scan_lvm_vg_name,
+ scan_lvm_vg_size,
+ scan_lvm_vg_internal_uuid
+FROM
+ scan_lvm_vgs
+WHERE
+ scan_lvm_vg_host_uuid = ".$anvil->Database->quote($dr_link_uuid)."
+AND
+ scan_lvm_vg_name != 'DELETED'
+ORDER BY
+ scan_lvm_vg_size ASC
+;";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, 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 => $debug, list => {
+ results => $results,
+ count => $count,
+ }});
+
+ foreach my $row (@{$results})
+ {
+ my $scan_lvm_vg_uuid = $row->[0];
+ my $scan_lvm_vg_name = $row->[1];
+ my $scan_lvm_vg_size = $row->[2];
+ my $scan_lvm_vg_internal_uuid = $row->[3];
+ }
+ }
+ }
+ }
+=cut
+
return(0);
}
diff --git a/Anvil/Tools/DRBD.pm b/Anvil/Tools/DRBD.pm
index 457abf43..cb175545 100644
--- a/Anvil/Tools/DRBD.pm
+++ b/Anvil/Tools/DRBD.pm
@@ -24,6 +24,7 @@ my $THIS_FILE = "DRBD.pm";
# get_next_resource
# get_status
# manage_resource
+# parse_resource
# reload_defaults
# remove_backing_lv
# resource_uuid
@@ -1492,7 +1493,7 @@ LIMIT 1
my $value = $option_ref->{value};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
variable => $variable,
- value => $variable,
+ value => $value,
}});
if ($variable eq "auto-promote")
{
@@ -1581,10 +1582,14 @@ LIMIT 1
if (($anvil->data->{drbd}{config}{$host}{host}) && ($anvil->data->{drbd}{config}{$host}{host} eq $this_host))
{
+ $anvil->data->{drbd}{config}{$host}{by_res}{$by_res}{on} = $lv_path;
+ $anvil->data->{drbd}{config}{$host}{by_res}{$by_res}{resource} = $this_resource;
$anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_path}{on} = $lv_path;
$anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_path}{resource} = $this_resource;
$anvil->data->{drbd}{config}{$host}{lv_path}{$lv_path}{under} = $drbd_path;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "drbd::config::${host}::by_res::${by_res}::on" => $anvil->data->{drbd}{config}{$host}{by_res}{$by_res}{on},
+ "drbd::config::${host}::by_res::${by_res}::resource" => $anvil->data->{drbd}{config}{$host}{by_res}{$by_res}{resource},
"drbd::config::${host}::drbd_path::${drbd_path}::on" => $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_path}{on},
"drbd::config::${host}::drbd_path::${drbd_path}::resource" => $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_path}{resource},
"drbd::config::${host}::lv_path::${lv_path}::under" => $anvil->data->{drbd}{config}{$host}{lv_path}{$lv_path}{under},
@@ -2357,6 +2362,253 @@ sub manage_resource
return($return_code);
}
+
+=head2 parse_resource
+
+This takes the XML from a specific DRBD resource and parses it.
+
+Parameters;
+
+=head3 xml (required)
+
+This is the XML to parse, generally as stored in the C<< scan_drbd_resources >> -> C<< scan_drbd_resource_xml >>.
+
+=cut
+sub parse_resource
+{
+ my $self = shift;
+ my $parameter = shift;
+ my $anvil = $self->parent;
+ my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "DRBD->parse_resource()" }});
+
+ my $xml = defined $parameter->{xml} ? $parameter->{xml} : "";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ xml => $xml,
+ }});
+
+ if (not $xml)
+ {
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "DRBD->parse_resource()", parameter => "xml" }});
+ return("!!error!!");
+ }
+
+ local $@;
+ my $dom = eval { XML::LibXML->load_xml(string => $xml); };
+ if ($@)
+ {
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "error_0253", variables => {
+ xml => $xml,
+ error => $@,
+ }});
+ return(1);
+ }
+ else
+ {
+ # Successful parse!
+=cut
+
+
+
+ /dev/drbd_srv01-fs37_0
+ /dev/cs_vm-a01n01/srv01-fs37_0
+ internal
+
+
+ /dev/drbd_srv01-fs37_1
+ /dev/cs_vm-a01n01/srv01-fs37_1
+ internal
+
+ (null)
+
+
+
+ /dev/drbd_srv01-fs37_0
+ /dev/cs_vm-a01n02/srv01-fs37_0
+ internal
+
+
+ /dev/drbd_srv01-fs37_1
+ /dev/cs_vm-a01n02/srv01-fs37_1
+ internal
+
+ (null)
+
+
+
+ /dev/drbd_srv01-fs37_0
+ /dev/cs_vm-a01dr01/srv01-fs37_0
+ internal
+
+
+ /dev/drbd_srv01-fs37_1
+ /dev/cs_vm-a01dr01/srv01-fs37_1
+ internal
+
+ (null)
+
+
+ 10.101.10.1
+ 10.101.10.2
+
+
+
+
+ 10.201.10.1
+ 10.201.10.3
+
+
+
+
+ 10.201.10.2
+ 10.201.10.3
+
+
+
+
+=cut
+ foreach my $name ($dom->findnodes('/resource'))
+ {
+ my $resource = $name->{name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { resource => $resource }});
+
+ foreach my $host ($name->findnodes('./host'))
+ {
+ my $this_host_name = $host->{name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_host_name => $this_host_name }});
+
+ # Record the details under the hosts
+ foreach my $volume_vnr ($host->findnodes('./volume'))
+ {
+ my $volume = $volume_vnr->{vnr};
+ my $meta_disk = $volume_vnr->findvalue('./meta-disk');
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ 's1:volume' => $volume,
+ 's2:meta_disk' => $meta_disk,
+ }});
+
+ my $host_uuid = $anvil->Get->host_uuid_from_name({host_name => $this_host_name});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
+
+ $anvil->data->{new}{resource}{$resource}{host_name}{$this_host_name}{host_uuid} = $host_uuid;
+ $anvil->data->{new}{resource}{$resource}{host_uuid}{$host_uuid}{volume_number}{$volume}{device_path} = $volume_vnr->findvalue('./device');
+ $anvil->data->{new}{resource}{$resource}{host_uuid}{$host_uuid}{volume_number}{$volume}{backing_disk} = $volume_vnr->findvalue('./disk');
+ $anvil->data->{new}{resource}{$resource}{host_uuid}{$host_uuid}{volume_number}{$volume}{device_minor} = $volume_vnr->findvalue('./device/@minor');
+ $anvil->data->{new}{resource}{$resource}{host_uuid}{$host_uuid}{volume_number}{$volume}{meta_disk} = $meta_disk;
+ $anvil->data->{new}{resource}{$resource}{host_uuid}{$host_uuid}{volume_number}{$volume}{size} = 0;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "s1:new::resource::${resource}::host_name::${this_host_name}::host_uuid" => $anvil->data->{new}{resource}{$resource}{host_name}{$this_host_name}{host_uuid},
+ "s2:new::resource::${resource}::host_uuid::${host_uuid}::volume_number::${volume}::device_path" => $anvil->data->{new}{resource}{$resource}{host_uuid}{$host_uuid}{volume_number}{$volume}{device_path},
+ "s3:new::resource::${resource}::host_uuid::${host_uuid}::volume_number::${volume}::backing_disk" => $anvil->data->{new}{resource}{$resource}{host_uuid}{$host_uuid}{volume_number}{$volume}{backing_disk},
+ "s4:new::resource::${resource}::host_uuid::${host_uuid}::volume_number::${volume}::device_minor" => $anvil->data->{new}{resource}{$resource}{host_uuid}{$host_uuid}{volume_number}{$volume}{device_minor},
+ "s5:new::resource::${resource}::host_uuid::${host_uuid}::volume_number::${volume}::meta_disk" => $anvil->data->{new}{resource}{$resource}{host_uuid}{$host_uuid}{volume_number}{$volume}{meta_disk},
+ }});
+ }
+ }
+ foreach my $connection ($name->findnodes('./connection'))
+ {
+ my $host1_name = "";
+ my $host1_ip_address = "";
+ my $host1_tcp_port = "";
+ my $host2_name = "";
+ my $host2_ip_address = "";
+ my $host2_tcp_port = "";
+ my $peer = "";
+ foreach my $host ($connection->findnodes('./host'))
+ {
+ my $this_host_name = $host->{name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_host_name => $this_host_name }});
+ if (not $host1_name)
+ {
+ $host1_name = $this_host_name;
+ $host1_ip_address = $host->findvalue('./address');
+ $host1_tcp_port = $host->findvalue('./address/@port');
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ host1_name => $host1_name,
+ host1_ip_address => $host1_ip_address,
+ host1_tcp_port => $host1_tcp_port,
+ }});
+ }
+ else
+ {
+ $host2_name = $this_host_name;
+ $host2_ip_address = $host->findvalue('./address');
+ $host2_tcp_port = $host->findvalue('./address/@port');
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ host2_name => $host2_name,
+ host2_ip_address => $host2_ip_address,
+ host2_tcp_port => $host2_tcp_port,
+ }});
+
+ $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host1_ip_address} = $host1_ip_address;
+ $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host1_tcp_port} = $host1_tcp_port;
+ $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_ip_address} = $host2_ip_address;
+ $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_tcp_port} = $host2_tcp_port;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "s1:new::resource::${resource}::host1_to_host2::${host1_name}::${host2_name}::host1_ip_address" => $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host1_ip_address},
+ "s2:new::resource::${resource}::host1_to_host2::${host1_name}::${host2_name}::host1_tcp_port" => $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host1_tcp_port},
+ "s3:new::resource::${resource}::host1_to_host2::${host1_name}::${host2_name}::host2_ip_address" => $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_ip_address},
+ "s4:new::resource::${resource}::host1_to_host2::${host1_name}::${host2_name}::host2_tcp_port" => $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_tcp_port},
+ }});
+
+ foreach my $proxy ($host->findnodes('./proxy'))
+ {
+ my $host_name = $proxy->{hostname};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_name => $host_name }});
+
+ # This should always be the target, but lets be safe/careful
+ next if $host_name ne $host2_name;
+
+ $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_inside_ip_address} = $proxy->findvalue('./inside');
+ $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_inside_tcp_port} = $proxy->findvalue('./inside/@port');
+ $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_outside_ip_address} = $proxy->findvalue('./outside');
+ $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_outside_tcp_port} = $proxy->findvalue('./outside/@port');
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "s1:new::resource::${resource}::host1_to_host2::${host1_name}::${host2_name}::host2_inside_ip_address" => $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_inside_ip_address},
+ "s2:new::resource::${resource}::host1_to_host2::${host1_name}::${host2_name}::host2_inside_tcp_port" => $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_inside_tcp_port},
+ "s3:new::resource::${resource}::host1_to_host2::${host1_name}::${host2_name}::host2_outside_ip_address" => $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_outside_ip_address},
+ "s4:new::resource::${resource}::host1_to_host2::${host1_name}::${host2_name}::host2_outside_tcp_port" => $anvil->data->{new}{resource}{$resource}{host1_to_host2}{$host1_name}{$host2_name}{host2_outside_tcp_port},
+ }});
+
+ $anvil->data->{new}{resource}{$resource}{proxy}{$host_name}{inside}{ip_address} = $proxy->findvalue('./inside');
+ $anvil->data->{new}{resource}{$resource}{proxy}{$host_name}{inside}{tcp_port} = $proxy->findvalue('./inside/@port');
+ $anvil->data->{new}{resource}{$resource}{proxy}{$host_name}{outside}{ip_address} = $proxy->findvalue('./outside');
+ $anvil->data->{new}{resource}{$resource}{proxy}{$host_name}{outside}{tcp_port} = $proxy->findvalue('./outside/@port');
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "new::resource::${resource}::proxy::${host_name}::inside::ip_address" => $anvil->data->{new}{resource}{$resource}{proxy}{$host_name}{inside}{ip_address},
+ "new::resource::${resource}::proxy::${host_name}::inside::tcp_port" => $anvil->data->{new}{resource}{$resource}{proxy}{$host_name}{inside}{tcp_port},
+ "new::resource::${resource}::proxy::${host_name}::outside::ip_address" => $anvil->data->{new}{resource}{$resource}{proxy}{$host_name}{outside}{ip_address},
+ "new::resource::${resource}::proxy::${host_name}::outside::tcp_port" => $anvil->data->{new}{resource}{$resource}{proxy}{$host_name}{outside}{tcp_port},
+ }});
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return(0);
+}
+
+
=head2 reload_defaults
This switches DRBD back to running using the values in the config files. Specifically, it calls C<< drbdadm adjust all >>.
diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm
index a3fa059d..8d2cd92e 100644
--- a/Anvil/Tools/Database.pm
+++ b/Anvil/Tools/Database.pm
@@ -97,6 +97,7 @@ my $THIS_FILE = "Database.pm";
# refresh_timestamp
# resync_databases
# shutdown
+# track_files
# update_host_status
# write
# _add_to_local_config
@@ -386,7 +387,7 @@ sub backup_database
=head2 check_file_locations
-This method checks to see that there is a corresponding entry in C<< file_locations >> for all Anvil! systems and files in the database. Any that are found to be missing will be set to C<< file_location_active >> -> c<< true >>.
+This method checks to see that there is a corresponding entry in C<< file_locations >> for all hosts and files in the database. Any that are found to be missing will be set to C<< file_location_active >> -> c<< true >>.
This method takes no parameters.
@@ -400,32 +401,32 @@ sub check_file_locations
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->check_file_locations()" }});
# Get all the Anvil! systems we know of.
- $anvil->Database->get_anvils({debug => $debug});
- $anvil->Database->get_files({debug => $debug});
- $anvil->Database->get_file_locations({debug => $debug});
+ $anvil->Database->get_hosts({debug => $debug});
+ #$anvil->Database->get_files({debug => $debug});
+ #$anvil->Database->get_file_locations({debug => $debug});
- foreach my $anvil_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_name}})
+ foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{hosts}{host_name}})
{
- my $anvil_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_uuid};
+ my $host_uuid = $anvil->data->{hosts}{host_name}{$host_name}{host_uuid};
foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{files}{file_name}})
{
my $file_uuid = $anvil->data->{files}{file_name}{$file_name}{file_uuid};
# Does this file exist for this Anvil! system?
- if (not exists $anvil->data->{file_locations}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_location_uuid})
+ if (not exists $anvil->data->{file_locations}{host_uuid}{$host_uuid}{file_uuid}{$file_uuid}{file_location_uuid})
{
# Add this entry.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0613", variables => {
- anvil_name => $anvil_name,
- file_name => $file_name,
+ host_name => $host_name,
+ file_name => $file_name,
}});
my $file_location_uuid = $anvil->Database->insert_or_update_file_locations({
- debug => $debug,
- file_location_file_uuid => $file_uuid,
- file_location_anvil_uuid => $anvil_uuid,
- file_location_active => 1,
+ debug => $debug,
+ file_location_file_uuid => $file_uuid,
+ file_location_host_uuid => $host_uuid,
+ file_location_active => 1,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_location_uuid => $file_location_uuid }});
}
@@ -2710,7 +2711,6 @@ SELECT
anvil_password,
anvil_node1_host_uuid,
anvil_node2_host_uuid,
- anvil_dr1_host_uuid,
modified_date
FROM
anvils ";
@@ -2737,8 +2737,7 @@ WHERE
my $anvil_password = $row->[3];
my $anvil_node1_host_uuid = defined $row->[4] ? $row->[4] : "";
my $anvil_node2_host_uuid = defined $row->[5] ? $row->[5] : "";
- my $anvil_dr1_host_uuid = defined $row->[6] ? $row->[6] : "";
- my $modified_date = $row->[7];
+ my $modified_date = $row->[6];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
anvil_uuid => $anvil_uuid,
anvil_name => $anvil_name,
@@ -2746,7 +2745,6 @@ WHERE
anvil_password => $anvil->Log->is_secure($anvil_password),
anvil_node1_host_uuid => $anvil_node1_host_uuid,
anvil_node2_host_uuid => $anvil_node2_host_uuid,
- anvil_dr1_host_uuid => $anvil_dr1_host_uuid,
modified_date => $modified_date,
}});
@@ -2756,7 +2754,6 @@ WHERE
$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password} = $anvil_password;
$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid} = $anvil_node1_host_uuid;
$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid} = $anvil_node2_host_uuid;
- $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid} = $anvil_dr1_host_uuid;
$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{modified_date} = $modified_date;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"anvils::anvil_uuid::${anvil_uuid}::anvil_name" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name},
@@ -2764,7 +2761,6 @@ WHERE
"anvils::anvil_uuid::${anvil_uuid}::anvil_password" => $anvil->Log->is_secure($anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password}),
"anvils::anvil_uuid::${anvil_uuid}::anvil_node1_host_uuid" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid},
"anvils::anvil_uuid::${anvil_uuid}::anvil_node2_host_uuid" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid},
- "anvils::anvil_uuid::${anvil_uuid}::anvil_dr1_host_uuid" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid},
"anvils::anvil_uuid::${anvil_uuid}::modified_date" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{modified_date},
}});
@@ -2775,7 +2771,6 @@ WHERE
$anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_password} = $anvil_password;
$anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_node1_host_uuid} = $anvil_node1_host_uuid;
$anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_node2_host_uuid} = $anvil_node2_host_uuid;
- $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_dr1_host_uuid} = $anvil_dr1_host_uuid;
$anvil->data->{anvils}{anvil_name}{$anvil_name}{modified_date} = $modified_date;
$anvil->data->{anvils}{anvil_name}{$anvil_name}{query_time} = time;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
@@ -2784,7 +2779,6 @@ WHERE
"anvils::anvil_name::${anvil_name}::anvil_password" => $anvil->Log->is_secure($anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_password}),
"anvils::anvil_name::${anvil_name}::anvil_node1_host_uuid" => $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_node1_host_uuid},
"anvils::anvil_name::${anvil_name}::anvil_node2_host_uuid" => $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_node2_host_uuid},
- "anvils::anvil_name::${anvil_name}::anvil_dr1_host_uuid" => $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_dr1_host_uuid},
"anvils::anvil_name::${anvil_name}::modified_date" => $anvil->data->{anvils}{anvil_name}{$anvil_name}{modified_date},
"anvils::anvil_name::${anvil_name}::query_time" => $anvil->data->{anvils}{anvil_name}{$anvil_name}{query_time},
}});
@@ -2811,60 +2805,6 @@ WHERE
"anvils::host_uuid::${anvil_node2_host_uuid}::role" => $anvil->data->{anvils}{host_uuid}{$anvil_node2_host_uuid}{role},
}});
}
- ### TODO: Remove this once the switch over to 'dr_links' is done.
- if ($anvil_dr1_host_uuid)
- {
- $anvil->data->{anvils}{host_uuid}{$anvil_dr1_host_uuid}{anvil_name} = $anvil_name;
- $anvil->data->{anvils}{host_uuid}{$anvil_dr1_host_uuid}{anvil_uuid} = $anvil_uuid;
- $anvil->data->{anvils}{host_uuid}{$anvil_dr1_host_uuid}{role} = "dr1";
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
- "anvils::host_uuid::${anvil_dr1_host_uuid}::anvil_name" => $anvil->data->{anvils}{host_uuid}{$anvil_dr1_host_uuid}{anvil_name},
- "anvils::host_uuid::${anvil_dr1_host_uuid}::anvil_uuid" => $anvil->data->{anvils}{host_uuid}{$anvil_dr1_host_uuid}{anvil_uuid},
- "anvils::host_uuid::${anvil_dr1_host_uuid}::role" => $anvil->data->{anvils}{host_uuid}{$anvil_dr1_host_uuid}{role},
- }});
- }
-
- # Track the files on this Anvil!
- foreach my $file_location_uuid (keys %{$anvil->data->{file_locations}{file_location_uuid}})
- {
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
- "file_locations::file_location_uuid::${file_location_uuid}::file_location_anvil_uuid" => $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_anvil_uuid},
- "file_locations::file_location_uuid::${file_location_uuid}::file_location_active" => $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active},
- }});
- next if $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_anvil_uuid} ne $anvil_uuid;
- next if not $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active};
-
- my $file_uuid = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_file_uuid};
-
- next if not exists $anvil->data->{files}{file_uuid}{$file_uuid};
-
- my $file_name = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name};
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
- file_uuid => $file_uuid,
- file_name => $file_name,
- }});
-
- # If the file was deleted, this won't exist
- next if not exists $anvil->data->{files}{file_uuid}{$file_uuid};
- $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_name} = $file_name;
- $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_directory};
- $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_size};
- $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_md5sum};
- $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_type};
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
- "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_name" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_name},
- "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_directory" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory},
- "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_size" => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size}})." (".$anvil->Convert->add_commas({number => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size}}).")",
- "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_md5sum" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum},
- "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_type" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type},
- }});
-
- # Make it so that we can list the files by name.
- $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid} = $file_uuid;
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
- "anvils::anvil_uuid::${anvil_uuid}::file_name::${file_name}::file_uuid" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid},
- }});
- }
# Process DR hosts this Anvil! is allowed to use.
if (exists $anvil->data->{dr_links}{by_anvil_uuid}{$anvil_uuid})
@@ -3238,7 +3178,7 @@ WHERE
This loads the known install file_locations into the C<< anvil::data >> hash at:
* file_locations::file_location_uuid::::file_location_file_uuid
-* file_locations::file_location_uuid::::file_location_anvil_uuid
+* file_locations::file_location_uuid::::file_location_host_uuid
* file_locations::file_location_uuid::::file_location_active
* file_locations::file_location_uuid::::modified_date
@@ -3264,7 +3204,7 @@ sub get_file_locations
SELECT
file_location_uuid,
file_location_file_uuid,
- file_location_anvil_uuid,
+ file_location_host_uuid,
file_location_active,
modified_date
FROM
@@ -3279,35 +3219,47 @@ FROM
}});
foreach my $row (@{$results})
{
- my $file_location_uuid = $row->[0];
- my $file_location_file_uuid = $row->[1];
- my $file_location_anvil_uuid = $row->[2];
- my $file_location_active = $row->[3];
- my $modified_date = $row->[4];
+ my $file_location_uuid = $row->[0];
+ my $file_location_file_uuid = $row->[1];
+ my $file_location_host_uuid = $row->[2];
+ my $file_location_active = $row->[3];
+ my $modified_date = $row->[4];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
- file_location_uuid => $file_location_uuid,
- file_location_file_uuid => $file_location_file_uuid,
- file_location_anvil_uuid => $file_location_anvil_uuid,
- file_location_active => $file_location_active,
- modified_date => $modified_date,
+ file_location_uuid => $file_location_uuid,
+ file_location_file_uuid => $file_location_file_uuid,
+ file_location_host_uuid => $file_location_host_uuid,
+ file_location_active => $file_location_active,
+ modified_date => $modified_date,
}});
# Record the data in the hash, too.
- $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_file_uuid} = $file_location_file_uuid;
- $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_anvil_uuid} = $file_location_anvil_uuid;
- $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active} = $file_location_active;
- $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{modified_date} = $modified_date;
+ $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_file_uuid} = $file_location_file_uuid;
+ $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_host_uuid} = $file_location_host_uuid;
+ $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active} = $file_location_active;
+ $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{modified_date} = $modified_date;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
- "file_locations::file_location_uuid::${file_location_uuid}::file_location_file_uuid" => $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_file_uuid},
- "file_locations::file_location_uuid::${file_location_uuid}::file_location_anvil_uuid" => $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_anvil_uuid},
- "file_locations::file_location_uuid::${file_location_uuid}::file_location_active" => $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active},
- "file_locations::file_location_uuid::${file_location_uuid}::modified_date" => $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{modified_date},
+ "file_locations::file_location_uuid::${file_location_uuid}::file_location_file_uuid" => $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_file_uuid},
+ "file_locations::file_location_uuid::${file_location_uuid}::file_location_host_uuid" => $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_host_uuid},
+ "file_locations::file_location_uuid::${file_location_uuid}::file_location_active" => $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active},
+ "file_locations::file_location_uuid::${file_location_uuid}::modified_date" => $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{modified_date},
}});
+ ### TODO: Remove this when the WebUI is updated.
+ # If this host is a node in an Anvil!, set the old 'file_location_anvil_uuid' to maintain
+ # backwards compatibility.
+ if ((exists $anvil->data->{hosts}{host_uuid}{$file_location_host_uuid}) &&
+ ($anvil->data->{hosts}{host_uuid}{$file_location_host_uuid}{anvil_uuid}))
+ {
+ $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_anvil_uuid} = $anvil->data->{hosts}{host_uuid}{$file_location_host_uuid}{anvil_uuid};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "file_locations::file_location_uuid::${file_location_uuid}::file_location_anvil_uuid" => $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_anvil_uuid},
+ }});
+ }
+
# Make it easy to find files by anvil and file UUID.
- $anvil->data->{file_locations}{anvil_uuid}{$file_location_anvil_uuid}{file_uuid}{$file_location_file_uuid}{file_location_uuid} = $file_location_uuid;
+ $anvil->data->{file_locations}{host_uuid}{$file_location_host_uuid}{file_uuid}{$file_location_file_uuid}{file_location_uuid} = $file_location_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
- "file_locations::anvil_uuid::${file_location_anvil_uuid}::file_uuid::${file_location_file_uuid}::file_location_uuid" => $anvil->data->{file_locations}{anvil_uuid}{$file_location_anvil_uuid}{file_uuid}{$file_location_file_uuid}{file_location_uuid},
+ "file_locations::host_uuid::${file_location_host_uuid}::file_uuid::${file_location_file_uuid}::file_location_uuid" => $anvil->data->{file_locations}{host_uuid}{$file_location_host_uuid}{file_uuid}{$file_location_file_uuid}{file_location_uuid},
}});
}
@@ -5297,6 +5249,12 @@ sub get_storage_group_data
$scan_lvm_exists = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { scan_lvm_exists => $scan_lvm_exists }});
}
+
+ # Loads hosts, if it hasn't been before.
+ if (not exists $anvil->data->{hosts}{host_uuid})
+ {
+ $anvil->Database->get_hosts({debug => $debug});
+ }
$query = "
SELECT
@@ -7918,7 +7876,7 @@ INSERT INTO
This updates (or inserts) a record in the 'file_locations' table. The C<< file_location_uuid >> referencing the database row will be returned.
-This table is used to track which files on Striker dashboards need to be on given Anvil! members.
+This table is used to track which files on Striker dashboards need to be on given Anvil! members and DR hosts.
If there is an error, an empty string is returned.
@@ -7928,13 +7886,19 @@ Parameters;
If not passed, a check will be made to see if an existing entry is found for C<< file_location_file_uuid >>. If found, that entry will be updated. If not found, a new record will be inserted.
+=head3 file_location_anvil_uuid (required)
+
+This is the C<< anvils >> -> C<< anvil_uuid >> being referenced. This works by figuring out which hosts are a member of the Anvil! node, and which DR hosts are linked, and makes a recursive call to this method for each of their C<< hosts >> -> C<< host_uuid >>.
+
+B<< Note >>: When this is used, a comma-separated list of C<< host_uuid=file_location_uuid >> is returned.
+
=head3 file_location_file_uuid (required)
This is the C<< files >> -> C<< file_uuid >> being referenced.
-=head3 file_location_anvil_uuid (required)
+=head3 file_location_host_uuid (required)
-This is the C<< anvils >> -> C<< anvil_uuid >> being referenced.
+This is the C<< hosts >> -> C<< host_uuid >> being referenced.
=head3 file_location_active (required)
@@ -7955,16 +7919,18 @@ sub insert_or_update_file_locations
my $file = defined $parameter->{file} ? $parameter->{file} : "";
my $line = defined $parameter->{line} ? $parameter->{line} : "";
my $file_location_uuid = defined $parameter->{file_location_uuid} ? $parameter->{file_location_uuid} : "";
- my $file_location_file_uuid = defined $parameter->{file_location_file_uuid} ? $parameter->{file_location_file_uuid} : "";
my $file_location_anvil_uuid = defined $parameter->{file_location_anvil_uuid} ? $parameter->{file_location_anvil_uuid} : "";
+ my $file_location_file_uuid = defined $parameter->{file_location_file_uuid} ? $parameter->{file_location_file_uuid} : "";
+ my $file_location_host_uuid = defined $parameter->{file_location_host_uuid} ? $parameter->{file_location_host_uuid} : "";
my $file_location_active = defined $parameter->{file_location_active} ? $parameter->{file_location_active} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
uuid => $uuid,
file => $file,
line => $line,
file_location_uuid => $file_location_uuid,
- file_location_file_uuid => $file_location_file_uuid,
file_location_anvil_uuid => $file_location_anvil_uuid,
+ file_location_file_uuid => $file_location_file_uuid,
+ file_location_host_uuid => $file_location_host_uuid,
file_location_active => $file_location_active,
}});
@@ -7974,10 +7940,10 @@ sub insert_or_update_file_locations
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_file_locations()", parameter => "file_location_file_uuid" }});
return("");
}
- if (not $file_location_anvil_uuid)
+ if (not $file_location_host_uuid)
{
# Throw an error and exit.
- $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_file_locations()", parameter => "file_location_anvil_uuid" }});
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_file_locations()", parameter => "file_location_host_uuid" }});
return("");
}
if (($file_location_active ne "0") && ($file_location_active ne "1"))
@@ -7987,6 +7953,59 @@ sub insert_or_update_file_locations
return("");
}
+ # If we've got an Anvil! uuid, find out the hosts and DR links connected to the Anvil! are found and
+ # this method is recursively called for each host.
+ if ($file_location_anvil_uuid)
+ {
+ $anvil->Database->get_anvils({debug => $debug});
+ if (not exists $anvil->data->{anvils}{anvil_uuid}{$file_location_anvil_uuid})
+ {
+ # Bad Anvil! UUID.
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0169", variables => { anvil_uuid => $file_location_anvil_uuid }});
+ return("");
+ }
+ my $hosts = ();
+ push @{$hosts}, $anvil->data->{anvils}{anvil_uuid}{$file_location_anvil_uuid}{anvil_node1_host_uuid};
+ push @{$hosts}, $anvil->data->{anvils}{anvil_uuid}{$file_location_anvil_uuid}{anvil_node2_host_uuid};
+ if (exists $anvil->data->{dr_links}{by_anvil_uuid}{$file_location_anvil_uuid})
+ {
+ foreach my $dr_link_host_uuid (sort {$a cmp $b} keys %{$anvil->data->{dr_links}{by_anvil_uuid}{$file_location_anvil_uuid}{dr_link_host_uuid}})
+ {
+ my $dr_link_uuid = $anvil->data->{dr_links}{by_anvil_uuid}{$file_location_anvil_uuid}{dr_link_host_uuid}{$dr_link_host_uuid}{dr_link_uuid};
+ my $dr_link_note = $anvil->data->{dr_links}{dr_link_uuid}{$dr_link_uuid}{dr_link_note};
+ my $dr_link_short_host_name = $anvil->data->{hosts}{host_uuid}{$dr_link_host_uuid}{short_host_name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "s1:dr_link_host_uuid" => $dr_link_host_uuid,
+ "s2:dr_link_uuid" => $dr_link_uuid,
+ "s3:dr_link_note" => $dr_link_note,
+ "s4:dr_link_short_host_name" => $dr_link_short_host_name,
+ }});
+
+ next if $dr_link_note eq "DELETED";
+ push @{$hosts}, $dr_link_host_uuid;
+ }
+ }
+ my $file_location_uuids = "";
+ foreach my $host_uuid (@{$hosts})
+ {
+ my $file_location_uuid = $anvil->Database->insert_or_update_file_locations({
+ debug => $debug,
+ file_location_file_uuid => $file_location_file_uuid,
+ file_location_host_uuid => $host_uuid,
+ file_location_active => $file_location_active,
+ });
+ $file_location_uuids .= $host_uuid."=".$file_location_uuid.",";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ file_location_uuid => $file_location_uuid,
+ file_location_uuids => $file_location_uuids,
+ }});
+ }
+ $file_location_uuids =~ s/,$//;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_location_uuids => $file_location_uuids }});
+
+ return($file_location_uuids);
+ }
+
# If we don't have a UUID, see if we can find one for the given md5sum.
if (not $file_location_uuid)
{
@@ -7996,9 +8015,9 @@ SELECT
FROM
file_locations
WHERE
- file_location_file_uuid = ".$anvil->Database->quote($file_location_file_uuid)."
+ file_location_file_uuid = ".$anvil->Database->quote($file_location_file_uuid)."
AND
- file_location_anvil_uuid = ".$anvil->Database->quote($file_location_anvil_uuid)."
+ file_location_host_uuid = ".$anvil->Database->quote($file_location_host_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
@@ -8029,15 +8048,15 @@ INSERT INTO
(
file_location_uuid,
file_location_file_uuid,
- file_location_anvil_uuid,
+ file_location_host_uuid,
file_location_active,
modified_date
) VALUES (
".$anvil->Database->quote($file_location_uuid).",
".$anvil->Database->quote($file_location_file_uuid).",
- ".$anvil->Database->quote($file_location_anvil_uuid).",
+ ".$anvil->Database->quote($file_location_host_uuid).",
".$anvil->Database->quote($file_location_active).",
- ".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
+ ".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
);
";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
@@ -8049,8 +8068,8 @@ INSERT INTO
my $query = "
SELECT
file_location_file_uuid,
- file_location_anvil_uuid,
- file_location_active,
+ file_location_host_uuid,
+ file_location_active
FROM
file_locations
WHERE
@@ -8072,31 +8091,31 @@ WHERE
}
foreach my $row (@{$results})
{
- my $old_file_location_file_uuid = $row->[0];
- my $old_file_location_anvil_uuid = $row->[1];
- my $old_file_location_active = $row->[2];
+ my $old_file_location_file_uuid = $row->[0];
+ my $old_file_location_host_uuid = $row->[1];
+ my $old_file_location_active = $row->[2];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
- old_file_location_file_uuid => $old_file_location_file_uuid,
- old_file_location_anvil_uuid => $old_file_location_anvil_uuid,
- old_file_location_active => $old_file_location_active,
+ old_file_location_file_uuid => $old_file_location_file_uuid,
+ old_file_location_host_uuid => $old_file_location_host_uuid,
+ old_file_location_active => $old_file_location_active,
}});
# Anything change?
- if (($old_file_location_file_uuid ne $file_location_file_uuid) or
- ($old_file_location_anvil_uuid ne $file_location_anvil_uuid) or
- ($old_file_location_active ne $file_location_active))
+ if (($old_file_location_file_uuid ne $file_location_file_uuid) or
+ ($old_file_location_host_uuid ne $file_location_host_uuid) or
+ ($old_file_location_active ne $file_location_active))
{
# Something changed, save.
my $query = "
UPDATE
file_locations
SET
- file_location_file_uuid = ".$anvil->Database->quote($file_location_file_uuid).",
- file_location_anvil_uuid = ".$anvil->Database->quote($file_location_anvil_uuid).",
- file_location_active = ".$anvil->Database->quote($file_location_active).",
- modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
+ file_location_file_uuid = ".$anvil->Database->quote($file_location_file_uuid).",
+ file_location_host_uuid = ".$anvil->Database->quote($file_location_host_uuid).",
+ file_location_active = ".$anvil->Database->quote($file_location_active).",
+ modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
WHERE
- file_location_uuid = ".$anvil->Database->quote($file_location_uuid)."
+ file_location_uuid = ".$anvil->Database->quote($file_location_uuid)."
";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
$anvil->Database->write({uuid => $uuid, query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__});
@@ -13409,7 +13428,7 @@ AND
if (not $storage_group_member_uuid)
{
# INSERT
- my $storage_group_member_uuid = $anvil->Get->uuid();
+ $storage_group_member_uuid = $anvil->Get->uuid();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { storage_group_member_uuid => $storage_group_member_uuid }});
my $query = "
@@ -17501,6 +17520,237 @@ AND
}
+=head2 track_file
+
+This looks at all files in the database, and then for all Anvil! systems and linked DR hosts, ensures that there's a corresponding C<< file_locations >> entry.
+
+This method takes no parameters.
+
+=cut
+sub track_files
+{
+ my $self = shift;
+ my $parameter = shift;
+ my $anvil = $self->parent;
+ my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->track_files()" }});
+
+ my $anvils = keys %{$anvil->data->{anvils}{anvil_name}};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { anvils => $anvils }});
+ if (not $anvils)
+ {
+ $anvil->Database->get_anvils({debug => $debug});
+ }
+
+ my $files = keys %{$anvil->data->{files}{file_uuid}};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { files => $files }});
+ if (not $files)
+ {
+ $anvil->Database->get_files({debug => $debug});
+ }
+
+ my $file_locations = keys %{$anvil->data->{file_locations}{file_location_uuid}};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_locations => $file_locations }});
+ if (not $file_locations)
+ {
+ $anvil->Database->get_file_locations({debug => $debug});
+ }
+
+ my $dr_link_uuid = keys %{$anvil->data->{dr_links}{dr_link_uuid}};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { dr_link_uuid => $dr_link_uuid }});
+ if (not $dr_link_uuid)
+ {
+ $anvil->Database->get_dr_links({debug => $debug});
+ }
+
+ foreach my $anvil_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_name}})
+ {
+ my $anvil_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_uuid};
+ my $anvil_description = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_description};
+ my $anvil_node1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid};
+ my $anvil_node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ 's1:anvil_name' => $anvil_name,
+ 's2:anvil_uuid' => $anvil_uuid,
+ 's3:anvil_description' => $anvil_description,
+ 's4:anvil_node1_host_uuid' => $anvil_node1_host_uuid,
+ 's5:anvil_node2_host_uuid' => $anvil_node2_host_uuid,
+ }});
+
+ # Loop through all files and see if there's a corresponding file_location for each sub-node.
+ my $reload = 0;
+ foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{files}{file_name}})
+ {
+ my $file_uuid = $anvil->data->{files}{file_name}{$file_name}{file_uuid};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ 's1:file_name' => $file_name,
+ 's2:file_uuid' => $file_uuid,
+ }});
+
+ foreach my $host_uuid ($anvil_node1_host_uuid, $anvil_node2_host_uuid)
+ {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
+
+ if ((not exists $anvil->data->{file_locations}{host_uuid}{$host_uuid}{file_uuid}{$file_uuid}) or
+ ($anvil->data->{file_locations}{host_uuid}{$host_uuid}{file_uuid}{$file_uuid}{file_location_uuid}))
+ {
+ # Add it
+ $reload = 1;
+ my ($file_location_uuid) = $anvil->Database->insert_or_update_file_locations({
+ debug => $debug,
+ file_location_file_uuid => $file_uuid,
+ file_location_host_uuid => $host_uuid,
+ file_location_active => 1,
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ reload => $reload,
+ file_location_uuid => $file_location_uuid,
+ }});
+ }
+ }
+ }
+ if ($reload)
+ {
+ $anvil->Database->get_file_locations({debug => $debug});
+ }
+
+ # Track the files on this Anvil!
+ foreach my $file_location_uuid (keys %{$anvil->data->{file_locations}{file_location_uuid}})
+ {
+ my $file_uuid = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_file_uuid};
+ my $file_type = $anvil->data->{files}{file_uuid}{$file_uuid}{file_type};
+ my $file_name = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ file_location_uuid => $file_location_uuid,
+ file_uuid => $file_uuid,
+ file_type => $file_type,
+ file_name => $file_name,
+ }});
+ next if $file_type eq "DELETED";
+
+ ### TODO - Left off here, not adding DR links.
+ my $anvil_needs_file = 0;
+ foreach my $host_uuid ($anvil_node1_host_uuid, $anvil_node2_host_uuid)
+ {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
+
+ if ((exists $anvil->data->{file_locations}{host_uuid}{$host_uuid}{file_uuid}{$file_uuid}) &&
+ ($anvil->data->{file_locations}{host_uuid}{$host_uuid}{file_uuid}{$file_uuid}{file_location_uuid}))
+ {
+ my $file_location_uuid = $anvil->data->{file_locations}{host_uuid}{$host_uuid}{file_uuid}{$file_uuid}{file_location_uuid};
+ my $file_location_active = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ file_location_uuid => $file_location_uuid,
+ file_location_active => $file_location_active,
+ }});
+
+ if ($file_location_active)
+ {
+ $anvil_needs_file = 1;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { anvil_needs_file => $anvil_needs_file }});
+ }
+ }
+ }
+
+ # If either node wanted the file, both nodes and all linked DRs need it.
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { anvil_needs_file => $anvil_needs_file }});
+ if ($anvil_needs_file)
+ {
+ # Update the hosts
+ foreach my $host_uuid ($anvil_node1_host_uuid, $anvil_node2_host_uuid)
+ {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
+
+ my ($file_location_uuid) = $anvil->Database->insert_or_update_file_locations({
+ debug => $debug,
+ file_location_file_uuid => $file_uuid,
+ file_location_host_uuid => $host_uuid,
+ file_location_active => 1,
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_location_uuid => $file_location_uuid }});
+ }
+
+ # Make sure linked DR hosts have this file, also.
+ foreach my $host_uuid (keys %{$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{dr_host}})
+ {
+ my $file_location_uuid = $anvil->data->{file_locations}{host_uuid}{$host_uuid}{file_uuid}{$file_uuid}{file_location_uuid};
+ my $file_location_active = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active};
+
+ if (not $file_location_active)
+ {
+ my ($file_location_uuid) = $anvil->Database->insert_or_update_file_locations({
+ debug => $debug,
+ file_location_file_uuid => $file_uuid,
+ file_location_host_uuid => $host_uuid,
+ file_location_active => 1,
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_location_uuid => $file_location_uuid }});
+ }
+ }
+
+ # If the file was deleted, this won't exist
+ next if not exists $anvil->data->{files}{file_uuid}{$file_uuid};
+
+ # Record that this Anvil! node has this file.
+ $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_name} = $file_name;
+ $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_directory};
+ $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_size};
+ $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_md5sum};
+ $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_type};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_name" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_name},
+ "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_directory" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory},
+ "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_size" => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size}})." (".$anvil->Convert->add_commas({number => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size}}).")",
+ "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_md5sum" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum},
+ "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_type" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type},
+ }});
+
+ # Make it so that we can list the files by name.
+ $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid} = $file_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "anvils::anvil_uuid::${anvil_uuid}::file_name::${file_name}::file_uuid" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid},
+ }});
+
+ # Make sure linked DR hosts have this file, also.
+ foreach my $host_uuid (keys %{$anvil->data->{dr_links}{by_anvil_uuid}{$anvil_uuid}{dr_link_host_uuid}})
+ {
+ my $host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ host_name => $host_name,
+ host_uuid => $host_uuid,
+ }});
+
+ my $file_location_uuid = "";
+ my $file_location_active = 0;
+ if (exists $anvil->data->{file_locations}{host_uuid}{$host_uuid}{file_uuid}{$file_uuid})
+ {
+ $file_location_uuid = $anvil->data->{file_locations}{host_uuid}{$host_uuid}{file_uuid}{$file_uuid}{file_location_uuid};
+ $file_location_active = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active};
+ }
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ file_location_uuid => $file_location_uuid,
+ file_location_active => $file_location_active,
+ }});
+
+ if (not $file_location_active)
+ {
+ my ($file_location_uuid) = $anvil->Database->insert_or_update_file_locations({
+ debug => $debug,
+ file_location_file_uuid => $file_uuid,
+ file_location_host_uuid => $host_uuid,
+ file_location_active => 1,
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_location_uuid => $file_location_uuid }});
+ }
+ }
+ }
+ }
+ }
+
+ return(0);
+}
+
+
=head2 update_host_status
This is a variant on C<< insert_or_update_hosts >> designed only to update the power status of a host.
diff --git a/Anvil/Tools/Get.pm b/Anvil/Tools/Get.pm
index 4df0a8fe..2fddbbda 100644
--- a/Anvil/Tools/Get.pm
+++ b/Anvil/Tools/Get.pm
@@ -643,7 +643,7 @@ WHERE
# How many cores?
if ((not $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores}) or
- ($scan_hardware_cpu_cores < $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores}))
+ ($scan_hardware_cpu_cores < $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores}))
{
$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores} = $scan_hardware_cpu_cores;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
@@ -651,15 +651,25 @@ WHERE
}});
}
if ((not $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}) or
- ($scan_hardware_cpu_threads < $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}))
+ ($scan_hardware_cpu_threads < $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}))
{
$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads} = $scan_hardware_cpu_threads;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"anvil_resources::${anvil_uuid}::cpu::threads" => $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads},
}});
}
+
+ # If there are less threads than cores, set the cores to be equal to threads.
+ if ($anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads} < $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores})
+ {
+ $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads} = $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "anvil_resources::${anvil_uuid}::cpu::threads" => $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads},
+ }});
+ }
+
if ((not $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}) or
- ($scan_hardware_ram_total < $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{hardware}))
+ ($scan_hardware_ram_total < $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{hardware}))
{
$anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available} = $scan_hardware_ram_total;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
@@ -2114,9 +2124,9 @@ sub server_from_switch
server_string => $server_string,
}});
- if ((not $server_string) && ($anvil->data->{switches}{'anvil'}))
+ if ((not $server_string) && ($anvil->data->{switches}{'server'}))
{
- $server_string = $anvil->data->{switches}{'anvil'};
+ $server_string = $anvil->data->{switches}{'server'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { server_string => $server_string }});
}
if (not $server_string)
@@ -2125,10 +2135,16 @@ sub server_from_switch
return("!!error!!", "");
}
+ $anvil->Database->get_anvils({debug => $debug});
$anvil->Database->get_servers({debug => $debug});
$anvil->data->{switches}{server_name} = "" if not exists $anvil->data->{switches}{server_name};
$anvil->data->{switches}{server_uuid} = "" if not exists $anvil->data->{switches}{server_uuid};
- if (exists $anvil->data->{servers}{server_uuid}{$server_string}{server_name})
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ server_string => $server_string,
+ "switches::server_name" => $anvil->data->{switches}{server_name},
+ "switches::server_uuid" => $anvil->data->{switches}{server_uuid},
+ }});
+ if (exists $anvil->data->{servers}{server_uuid}{$server_string})
{
# Found it by UUID.
$anvil->data->{switches}{server_name} = $anvil->data->{anvils}{server_uuid}{$server_string}{server_name};
@@ -2138,14 +2154,33 @@ sub server_from_switch
"switches::server_uuid" => $anvil->data->{switches}{server_uuid},
}});
}
- elsif (exists $anvil->data->{anvils}{server_uuid}{$server_string})
+ else
{
- $anvil->data->{switches}{server_name} = $server_string;
- $anvil->data->{switches}{server_uuid} = $anvil->data->{anvils}{server_uuid}{$server_string}{server_uuid};
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
- "switches::server_name" => $anvil->data->{switches}{server_name},
- "switches::server_uuid" => $anvil->data->{switches}{server_uuid},
- }});
+ # If we have an anvil_uuid, see if the server exists there.
+ foreach my $this_anvil_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_name}})
+ {
+ my $this_anvil_uuid = $anvil->data->{anvils}{anvil_name}{$this_anvil_name}{anvil_uuid};
+ if (($anvil_uuid) && ($anvil_uuid ne $this_anvil_uuid))
+ {
+ next;
+ }
+ foreach my $this_server_name (sort {$a cmp $b} keys %{$anvil->data->{servers}{anvil_uuid}{$this_anvil_uuid}{server_name}})
+ {
+ my $this_server_uuid = $anvil->data->{servers}{anvil_uuid}{$this_anvil_uuid}{server_name}{$this_server_name}{server_uuid};
+ if (($server_string eq $this_server_name) or
+ ($server_string eq $this_server_uuid))
+ {
+ # Found it
+ $anvil->data->{switches}{server_name} = $this_server_name;
+ $anvil->data->{switches}{server_uuid} = $this_server_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "switches::server_name" => $anvil->data->{switches}{server_name},
+ "switches::server_uuid" => $anvil->data->{switches}{server_uuid},
+ }});
+ last;
+ }
+ }
+ }
}
return($anvil->data->{switches}{server_name}, $anvil->data->{switches}{server_uuid});
diff --git a/Anvil/Tools/Network.pm b/Anvil/Tools/Network.pm
index f6a1a792..b7126177 100644
--- a/Anvil/Tools/Network.pm
+++ b/Anvil/Tools/Network.pm
@@ -18,6 +18,7 @@ my $THIS_FILE = "Network.pm";
# check_network
# check_internet
# download
+# find_access
# find_matches
# find_target_ip
# get_company_from_mac
@@ -1186,6 +1187,169 @@ sub download
}
+=head2 find_access
+
+This takes a host's UUID or name, and finds networks that this host can reach it on. If the target is not found in the database, C<< !!error!! >> is returned. Otherwise, the number of matches found is returned.
+
+B<< Note >>: This requires that the target has recorded it's network in the database.
+
+It was written to be a saner version of C<< Network->find_matches() >>
+
+Matches will be stored as:
+
+* network_access::::local_ip_address =
+* network_access::::local_subnet_mask =
+* network_access::::local_interface =
+* network_access::::local_speed =
+* network_access::::target_ip_address =
+* network_access::::target_subnet_mask =
+* network_access::::target_interface =
+* network_access::::target_speed =
+
+Where C<< network_name >> will be C<< bcnX >>, C<< ifnX >>, etc.
+
+Paramters;
+
+=head3 target (required)
+
+This is the host we're looking for connection options with.
+
+=cut
+sub find_access
+{
+ my $self = shift;
+ my $parameter = shift;
+ my $anvil = $self->parent;
+ my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Network->find_access()" }});
+
+ my $target = defined $parameter->{target} ? $parameter->{target} : "";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ target => $target,
+ }});
+
+ if (not $target)
+ {
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Network->find_access()", parameter => "target" }});
+ return("!!error!!");
+ }
+
+ # Take the target and find the host_uuid and host_name.
+ my $target_host_uuid = $anvil->Database->get_host_uuid_from_string({debug => $debug, string => $target});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { target_host_uuid => $target_host_uuid }});
+
+ if (not $target_host_uuid)
+ {
+ # Bad target.
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0414", variables => { target => $target }});
+ return("!!error!!");
+ }
+
+ my $host_uuid = $anvil->Get->host_uuid;
+ my $short_host_name = $anvil->Get->short_host_name;
+ my $target_short_host_name = $anvil->data->{hosts}{host_uuid}{$target_host_uuid}{short_host_name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ host_uuid => $host_uuid,
+ short_host_name => $short_host_name,
+ target_short_host_name => $target_short_host_name,
+ }});
+
+ # Load our IPs
+ $anvil->Network->load_ips({
+ debug => $debug,
+ host => $short_host_name,
+ });
+ # Load our target's IPs.
+ $anvil->Network->load_ips({
+ debug => $debug,
+ host => $target_short_host_name,
+ host_uuid => $target_host_uuid,
+ });
+
+ # Loop through the first, and on each interface with an IP/subnet mask, look for a match in the second.
+ foreach my $local_interface (sort {$b cmp $a} keys %{$anvil->data->{network}{$short_host_name}{interface}})
+ {
+ my $local_ip = $anvil->data->{network}{$short_host_name}{interface}{$local_interface}{ip};
+ my $local_subnet_mask = $anvil->data->{network}{$short_host_name}{interface}{$local_interface}{subnet_mask};
+ my $local_speed = $anvil->data->{network}{$short_host_name}{interface}{$local_interface}{speed};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ local_interface => $local_interface,
+ local_ip => $local_ip,
+ local_subnet_mask => $local_subnet_mask,
+ local_speed => $local_speed,
+ }});
+
+ if (($local_ip) && ($local_subnet_mask))
+ {
+ # Look for a match.
+ my $local_network = $anvil->Network->get_network({
+ debug => $debug,
+ ip => $local_ip,
+ subnet_mask => $local_subnet_mask,
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { local_network => $local_network }});
+
+ foreach my $target_interface (sort {$b cmp $a} keys %{$anvil->data->{network}{$target_short_host_name}{interface}})
+ {
+ my $target_ip = $anvil->data->{network}{$target_short_host_name}{interface}{$target_interface}{ip};
+ my $target_subnet_mask = $anvil->data->{network}{$target_short_host_name}{interface}{$target_interface}{subnet_mask};
+ my $target_speed = $anvil->data->{network}{$target_short_host_name}{interface}{$target_interface}{speed};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ target_interface => $target_interface,
+ target_ip => $target_ip,
+ target_subnet_mask => $target_subnet_mask,
+ target_speed => $target_speed,
+ }});
+ if (($target_ip) && ($target_subnet_mask))
+ {
+ # Do we have a match?
+ my $target_network = $anvil->Network->get_network({
+ debug => $debug,
+ ip => $target_ip,
+ subnet_mask => $target_subnet_mask,
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ local_network => $local_network,
+ target_network => $target_network,
+ }});
+
+ if ($local_network eq $target_network)
+ {
+ # Match!
+ my $network_name = $target_interface;
+ $network_name =~ s/^(\w+\d+)_.*$/$1/;
+
+ $anvil->data->{network_access}{$network_name}{local_interface} = $local_interface;
+ $anvil->data->{network_access}{$network_name}{local_speed} = $local_speed;
+ $anvil->data->{network_access}{$network_name}{local_ip_address} = $local_ip;
+ $anvil->data->{network_access}{$network_name}{local_subnet_mask} = $local_subnet_mask;
+ $anvil->data->{network_access}{$network_name}{target_interface} = $target_interface;
+ $anvil->data->{network_access}{$network_name}{target_speed} = $target_speed;
+ $anvil->data->{network_access}{$network_name}{target_ip_address} = $target_ip;
+ $anvil->data->{network_access}{$network_name}{target_subnet_mask} = $target_subnet_mask;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "s1:network_access::${network_name}::local_interface" => $anvil->data->{network_access}{$network_name}{local_interface},
+ "s2:network_access::${network_name}::local_speed" => $anvil->data->{network_access}{$network_name}{local_speed},
+ "s3:network_access::${network_name}::local_ip_address" => $anvil->data->{network_access}{$network_name}{local_ip_address},
+ "s4:network_access::${network_name}::local_subnet_mask" => $anvil->data->{network_access}{$network_name}{local_subnet_mask},
+ "s5:network_access::${network_name}::target_interface" => $anvil->data->{network_access}{$network_name}{target_interface},
+ "s6:network_access::${network_name}::target_speed" => $anvil->data->{network_access}{$network_name}{target_speed},
+ "s7:network_access::${network_name}::target_ip_address" => $anvil->data->{network_access}{$network_name}{target_ip_address},
+ "s8:network_access::${network_name}::target_subnet_mask" => $anvil->data->{network_access}{$network_name}{target_subnet_mask},
+ }});
+ }
+ }
+ }
+ }
+ }
+
+ my $matches = keys %{$anvil->data->{network_access}};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { matches => $matches }});
+ return($matches);
+}
+
+
+
=head2 find_matches
This takes two hash keys from prior C<< Network->get_ips() >> or C<< ->load_ips() >> runs and finds which are on the same network.
@@ -2583,7 +2747,7 @@ AND
"network::${host}::interface::${bond_name}::down_delay" => $anvil->data->{network}{$host}{interface}{$bond_name}{down_delay},
"network::${host}::interface::${bond_name}::mac_address" => $anvil->data->{network}{$host}{interface}{$bond_name}{mac_address},
"network::${host}::interface::${bond_name}::operational" => $anvil->data->{network}{$host}{interface}{$bond_name}{operational},
- "network::${host}::interface::${bond_name}::bridge_uuid" => $anvil->data->{network}{$host}{interface}{$bond_name}{bridge},
+ "network::${host}::interface::${bond_name}::bridge_uuid" => $anvil->data->{network}{$host}{interface}{$bond_name}{bridge_uuid},
"network::${host}::interface::${bond_name}::type" => $anvil->data->{network}{$host}{interface}{$bond_name}{type},
}});
}
@@ -2763,7 +2927,7 @@ sub load_ips
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Network->load_ips()" }});
my $clear = defined $parameter->{clear} ? $parameter->{clear} : 1;
- my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : $anvil->Get->host_uuid;
+ my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : "";
my $host = defined $parameter->{host} ? $parameter->{host} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
clear => $clear,
@@ -2773,8 +2937,8 @@ sub load_ips
if (not $host_uuid)
{
- $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Network->load_ips()", parameter => "ip" }});
- return("");
+ $host_uuid = $anvil->Get->host_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
}
if (not $host)
@@ -2832,9 +2996,56 @@ AND
ip_address_on_uuid => $ip_address_on_uuid,
}});
- my $interface_name = "";
- my $interface_mac = "";
+ my $bridge_name = "";
+ my $bond_name = "";
+ my $interface_name = "";
+ my $interface_mac = "";
+ my $network_interface_uuid = "";
if ($ip_address_on_type eq "interface")
+ {
+ $network_interface_uuid = $ip_address_on_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { network_interface_uuid => $network_interface_uuid }});
+ }
+ else
+ {
+ my $query = "";
+ if ($ip_address_on_type eq "bridge")
+ {
+ # What's the bridge UUID?
+ $query = "SELECT bond_name, bond_active_interface FROM bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($ip_address_on_uuid).";";
+
+ # Get the bridge name, also.
+ if (1)
+ {
+ my $query = "SELECT bridge_name FROM bridges WHERE bridge_uuid = ".$anvil->Database->quote($ip_address_on_uuid).";";
+ $bridge_name = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { bridge_name => $bridge_name }});
+ }
+ }
+ else
+ {
+ $query = "SELECT bond_name, bond_active_interface FROM bonds WHERE bond_uuid = ".$anvil->Database->quote($ip_address_on_uuid).";";
+ }
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
+ my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
+ $bond_name = $results->[0]->[0];
+ my $active_interface = $results->[0]->[1];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ interface_name => $interface_name,
+ active_interface => $active_interface,
+ }});
+
+ if ($active_interface)
+ {
+ my $query = "SELECT network_interface_uuid FROM network_interfaces WHERE network_interface_host_uuid = ".$anvil->Database->quote($host_uuid)." AND network_interface_name = ".$anvil->Database->quote($active_interface).";";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
+
+ $network_interface_uuid = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { active_interface => $active_interface }});
+ }
+ }
+
+ if ($network_interface_uuid)
{
my $query = "
SELECT
@@ -2852,7 +3063,7 @@ SELECT
FROM
network_interfaces
WHERE
- network_interface_uuid = ".$anvil->Database->quote($ip_address_on_uuid)."
+ network_interface_uuid = ".$anvil->Database->quote($network_interface_uuid)."
AND
network_interface_operational != 'DELETED'
;";
@@ -2872,22 +3083,34 @@ AND
interface_mac => $interface_mac,
}});
- $anvil->data->{network}{$host}{interface}{$interface_name}{network_interface_uuid} = $results->[0]->[0];
- $anvil->data->{network}{$host}{interface}{$interface_name}{mac_address} = $interface_mac;
- $anvil->data->{network}{$host}{interface}{$interface_name}{ip} = $ip_address_address;
- $anvil->data->{network}{$host}{interface}{$interface_name}{subnet_mask} = $ip_address_subnet_mask;
- $anvil->data->{network}{$host}{interface}{$interface_name}{default_gateway} = $ip_address_default_gateway;
- $anvil->data->{network}{$host}{interface}{$interface_name}{gateway} = $ip_address_gateway;
- $anvil->data->{network}{$host}{interface}{$interface_name}{dns} = $ip_address_dns;
- $anvil->data->{network}{$host}{interface}{$interface_name}{type} = $ip_address_on_type;
- $anvil->data->{network}{$host}{interface}{$interface_name}{speed} = $results->[0]->[3];
- $anvil->data->{network}{$host}{interface}{$interface_name}{mtu} = $results->[0]->[4];
- $anvil->data->{network}{$host}{interface}{$interface_name}{link_state} = $results->[0]->[5];
- $anvil->data->{network}{$host}{interface}{$interface_name}{operational} = $results->[0]->[6];
- $anvil->data->{network}{$host}{interface}{$interface_name}{duplex} = $results->[0]->[7];
- $anvil->data->{network}{$host}{interface}{$interface_name}{medium} = $results->[0]->[8];
- $anvil->data->{network}{$host}{interface}{$interface_name}{bond_uuid} = $results->[0]->[9];
- $anvil->data->{network}{$host}{interface}{$interface_name}{bridge_uuid} = $results->[0]->[10];
+ # If this is a bridge or a bond, use that name for the interface.
+ if ($bridge_name)
+ {
+ $interface_name = $bridge_name;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_name => $interface_name }});
+ }
+ if ($bond_name)
+ {
+ $interface_name = $bond_name;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_name => $interface_name }});
+ }
+
+ $anvil->data->{network}{$host}{interface}{$interface_name}{network_interface_uuid} = $results->[0]->[0];
+ $anvil->data->{network}{$host}{interface}{$interface_name}{mac_address} = $interface_mac;
+ $anvil->data->{network}{$host}{interface}{$interface_name}{ip} = $ip_address_address;
+ $anvil->data->{network}{$host}{interface}{$interface_name}{subnet_mask} = $ip_address_subnet_mask;
+ $anvil->data->{network}{$host}{interface}{$interface_name}{default_gateway} = $ip_address_default_gateway;
+ $anvil->data->{network}{$host}{interface}{$interface_name}{gateway} = $ip_address_gateway;
+ $anvil->data->{network}{$host}{interface}{$interface_name}{dns} = $ip_address_dns;
+ $anvil->data->{network}{$host}{interface}{$interface_name}{type} = $ip_address_on_type;
+ $anvil->data->{network}{$host}{interface}{$interface_name}{speed} = $results->[0]->[3];
+ $anvil->data->{network}{$host}{interface}{$interface_name}{mtu} = $results->[0]->[4];
+ $anvil->data->{network}{$host}{interface}{$interface_name}{link_state} = $results->[0]->[5];
+ $anvil->data->{network}{$host}{interface}{$interface_name}{operational} = $results->[0]->[6];
+ $anvil->data->{network}{$host}{interface}{$interface_name}{duplex} = $results->[0]->[7];
+ $anvil->data->{network}{$host}{interface}{$interface_name}{medium} = $results->[0]->[8];
+ $anvil->data->{network}{$host}{interface}{$interface_name}{bond_uuid} = defined $results->[0]->[9] ? $results->[0]->[9] : "";
+ $anvil->data->{network}{$host}{interface}{$interface_name}{bridge_uuid} = defined $results->[0]->[10] ? $results->[0]->[10] : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"network::${host}::interface::${interface_name}::network_interface_uuid" => $anvil->data->{network}{$host}{interface}{$interface_name}{network_interface_uuid},
"network::${host}::interface::${interface_name}::mac_address" => $anvil->data->{network}{$host}{interface}{$interface_name}{mac_address},
diff --git a/Anvil/Tools/ScanCore.pm b/Anvil/Tools/ScanCore.pm
index 968c5ba7..d1b670a5 100644
--- a/Anvil/Tools/ScanCore.pm
+++ b/Anvil/Tools/ScanCore.pm
@@ -404,15 +404,13 @@ sub call_scan_agents
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }});
# Tell the user this agent is about to run...
-# $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => $debug, key => "log_0252", variables => {
-# agent_name => $agent_name,
-# timeout => $timeout,
-# }});
- $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => $debug, key => "log_0701", variables => { agent_name => $agent_name }});
- ### TODO: Timeout, when called / set here, was hanging virsh calls. Unknown why yet, but temp
- ### fix is to just not use timeouts for calls.
- #my ($output, $return_code) = $anvil->System->call({timeout => $timeout, shell_call => $shell_call});
- my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => $debug, key => "log_0252", variables => {
+ agent_name => $agent_name,
+ timeout => $timeout,
+ }});
+# $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => $debug, key => "log_0701", variables => { agent_name => $agent_name }});
+ my ($output, $return_code) = $anvil->System->call({timeout => $timeout, shell_call => $shell_call});
+# my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output, return_code => $return_code }});
foreach my $line (split/\n/, $output)
{
diff --git a/Anvil/Tools/Server.pm b/Anvil/Tools/Server.pm
index 76bfec78..7efc0176 100644
--- a/Anvil/Tools/Server.pm
+++ b/Anvil/Tools/Server.pm
@@ -1385,7 +1385,7 @@ sub parse_definition
my $server = defined $parameter->{server} ? $parameter->{server} : "";
my $source = defined $parameter->{source} ? $parameter->{source} : "";
my $definition = defined $parameter->{definition} ? $parameter->{definition} : "";
- my $host = defined $parameter->{host} ? $parameter->{host} : $anvil->Get->short_host_name;
+ my $host = defined $parameter->{host} ? $parameter->{host} : "";
my $target = $anvil->Get->short_host_name();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
anvil_uuid => $anvil_uuid,
@@ -1395,6 +1395,12 @@ sub parse_definition
host => $host,
}});
+ if (not $target)
+ {
+ $target = $anvil->Get->short_host_name;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { target => $target }});
+ }
+
if (not $server)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->parse_definition()", parameter => "server" }});
@@ -1805,6 +1811,16 @@ sub parse_definition
"server::${target}::${server}::${source}::device::${device}::target::${device_target}::type" => $anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{type},
}});
+ if (($boot_order) && ($boot_order =~ /^\d+$/))
+ {
+ $anvil->data->{server}{$target}{$server}{$source}{boot_order}{$boot_order}{device_target} = $device_target;
+ $anvil->data->{server}{$target}{$server}{$source}{boot_order}{$boot_order}{device_type} = $device;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "server::${target}::${server}::${source}::boot_order::${boot_order}::device_target" => $anvil->data->{server}{$target}{$server}{$source}{boot_order}{$boot_order}{device_target},
+ "server::${target}::${server}::${source}::boot_order::${boot_order}::device_type" => $anvil->data->{server}{$target}{$server}{$source}{boot_order}{$boot_order}{device_type},
+ }});
+ }
+
# Record type-specific data
if ($device eq "disk")
{
@@ -1832,8 +1848,10 @@ sub parse_definition
my $on_lv = defined $anvil->data->{drbd}{config}{$host}{drbd_path}{$device_path}{on} ? $anvil->data->{drbd}{config}{$host}{drbd_path}{$device_path}{on} : "";
my $resource = defined $anvil->data->{drbd}{config}{$host}{drbd_path}{$device_path}{resource} ? $anvil->data->{drbd}{config}{$host}{drbd_path}{$device_path}{resource} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
- on_lv => $on_lv,
- resource => $resource,
+ 's1:host' => $host,
+ 's2:device_path' => $device_path,
+ 's3:on_lv' => $on_lv,
+ 's4:resource' => $resource,
}});
if ((not $resource) && ($anvil->data->{drbd}{config}{$host}{'by-res'}{$device_path}{resource}))
{
diff --git a/Anvil/Tools/Storage.pm b/Anvil/Tools/Storage.pm
index ec31d35b..f325390e 100644
--- a/Anvil/Tools/Storage.pm
+++ b/Anvil/Tools/Storage.pm
@@ -35,6 +35,7 @@ my $THIS_FILE = "Storage.pm";
# move_file
# parse_df
# parse_lsblk
+# push_file
# read_config
# read_file
# read_mode
@@ -3451,6 +3452,273 @@ sub parse_lsblk
}
+=head2 push_file
+
+This takes a file and pushes it to all other machines in the cluster, serially. For machines that can't be accessed, a job is registered to pull the file.
+
+If C<< switches::job-uuid >> is set, the corresponding job will be updated. The progress assumes that C<< sys::progress >> is set.
+
+Parameters;
+
+=head3 file (required)
+
+This is the source file to copy from locally and push it to all peers' C<< /mnt/shared/files/ >> directory.
+
+=cut
+sub push_file
+{
+ my $self = shift;
+ my $parameter = shift;
+ my $anvil = $self->parent;
+ my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Storage->push_file()" }});
+
+ # Setup default values
+ my $file = defined $parameter->{file} ? $parameter->{file} : "";
+ my $file_uuid = defined $parameter->{file_uuid} ? $parameter->{file_uuid} : "";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ file => $file,
+ file_uuid => $file_uuid,
+ }});
+
+ if (not $file)
+ {
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Storage->push_file()", parameter => "file" }});
+ return("!!error!!");
+ }
+ if (not -f $file)
+ {
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0105", variables => { file => $file }});
+ return("!!error!!");
+ }
+
+ $anvil->Database->get_files({debug => $debug});
+ my $file_size = 0;
+ my ($file_directory, $file_name) = ($file =~ /^(.*)\/(.*?)$/);
+ $file_directory =~ s/\/$//g;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ 's1:file_directory' => $file_directory,
+ 's2:file_name' => $file_name,
+ }});
+ if (not $file_uuid)
+ {
+ # Can we find the file?
+ foreach my $this_file_uuid (keys %{$anvil->data->{files}{file_uuid}})
+ {
+ my $this_file_name = $anvil->data->{files}{file_uuid}{$this_file_uuid}{file_name};
+ my $this_file_directory = $anvil->data->{files}{file_uuid}{$this_file_uuid}{file_directory};
+ $this_file_directory =~ s/\/$//g;
+ my $this_file_size = $anvil->data->{files}{file_uuid}{$this_file_uuid}{file_size};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ this_file_uuid => $this_file_uuid,
+ this_file_directory => $this_file_directory,
+ this_file_name => $this_file_name,
+ this_file_size => $this_file_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $this_file_size}).")",
+ }});
+
+ if (($file_name eq $this_file_name) &&
+ ($file_directory eq $this_file_directory))
+ {
+ # Found it.
+ $file_uuid = $this_file_uuid;
+ $file_size = $this_file_size;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ file_uuid => $file_uuid,
+ file_size => $file_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $file_size}).")",
+ }});
+ last;
+ }
+ }
+ }
+
+ if ((not $file_uuid) or (not $file_size))
+ {
+ $file_size = (stat($file))[7];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ file_size => $file_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $file_size}).")",
+ }});
+ }
+
+ # Now copy this to our peers. We're going to do this serially so that we don't overwhelm the system,
+ # Any hosts not currently online will have a job registered.
+ $anvil->Database->get_hosts;
+ my $host_uuid = $anvil->Get->host_uuid();
+ my $host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name};
+ my $target_directory = $anvil->data->{path}{directories}{shared}{files}."/";
+ foreach my $do_host_type ("striker", "node", "dr")
+ {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { do_host_type => $do_host_type }});
+ foreach my $target_host_name (sort {$a cmp $b} keys %{$anvil->data->{sys}{hosts}{by_name}})
+ {
+ my $target_host_uuid = $anvil->data->{sys}{hosts}{by_name}{$target_host_name};
+ my $target_host_type = $anvil->data->{hosts}{host_uuid}{$target_host_uuid}{host_type};
+ my $target_short_host_name = $anvil->data->{hosts}{host_uuid}{$target_host_uuid}{short_host_name};
+ next if $target_host_uuid eq $host_uuid;
+ next if $target_host_type ne $do_host_type;
+
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:target_host_name' => $target_host_name,
+ 's2:target_host_uuid' => $target_host_uuid,
+ 's3:target_host_type' => $target_host_type,
+ 's4:target_short_host_name' => $target_short_host_name,
+ }});
+
+ my $matches = $anvil->Network->find_access({
+ debug => 2,
+ target => $target_short_host_name,
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { matches => $matches }});
+ next if not $matches;
+ next if $matches =~ /\D/;
+
+ # Find a matching IP.
+ # We prefer to use least to most used networks, with the IFN being the last choice.
+ my $copied = 0;
+ foreach my $network ("mn", "bcn", "sn", "ifn")
+ {
+ next if $copied;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network => $network }});
+ foreach my $network_name (sort {$a cmp $b} keys %{$anvil->data->{network_access}})
+ {
+ next if $copied;
+ next if $network_name !~ /^$network/i;
+ my $local_interface = $anvil->data->{network_access}{$network_name}{local_interface};
+ my $local_speed = $anvil->data->{network_access}{$network_name}{local_speed};
+ my $local_ip_address = $anvil->data->{network_access}{$network_name}{local_ip_address};
+ my $local_subnet_mask = $anvil->data->{network_access}{$network_name}{local_subnet_mask};
+ my $target_interface = $anvil->data->{network_access}{$network_name}{target_interface};
+ my $target_speed = $anvil->data->{network_access}{$network_name}{target_speed};
+ my $target_ip_address = $anvil->data->{network_access}{$network_name}{target_ip_address};
+ my $target_subnet_mask = $anvil->data->{network_access}{$network_name}{target_subnet_mask};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:local_interface' => $local_interface,
+ 's2:local_speed' => $local_speed,
+ 's3:local_ip_address' => $local_ip_address,
+ 's4:local_subnet_mask' => $local_subnet_mask,
+ 's5:target_interface' => $target_interface,
+ 's6:target_speed' => $target_speed,
+ 's7:target_ip_address' => $target_ip_address,
+ 's8:target_subnet_mask' => $target_subnet_mask,
+ }});
+
+ my $access = $anvil->Remote->test_access({target => $target_ip_address});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { access => $access }});
+
+ if ($access)
+ {
+ ### Rsync!
+ # Estimate how long this will take. First, get the speed in
+ # Mbps and turn it into bytes per second, then into bytes per
+ # second. We'll take 10% off, then calculate how many seconds
+ # the copy will take.
+ my $link_mbps = $target_speed > $local_speed ? $target_speed : $local_speed;
+ my $link_bps = $link_mbps * 1000000;
+ my $link_bytes_sec = int($link_bps / 8);
+ my $adjusted_byptes_sec = int($link_bytes_sec * 0.9);
+ my $copy_seconds = int($file_size / $adjusted_byptes_sec);
+ my $say_copy_time = $anvil->Convert->time({'time' => $copy_seconds, translate => 1});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:link_mbps' => $anvil->Convert->add_commas({number => $link_mbps})." ".$anvil->Words->string({string => "#!string!suffix_0050!#"}),
+ 's2:link_bps' => $anvil->Convert->add_commas({number => $link_bps})." ".$anvil->Words->string({string => "#!string!suffix_0048!#"}),
+ 's3:link_bytes_sec' => $anvil->Convert->add_commas({number => $link_bytes_sec})." ".$anvil->Words->string({string => "#!string!suffix_0060!#"}),
+ 's4:adjusted_byptes_sec' => $anvil->Convert->add_commas({number => $adjusted_byptes_sec})." ".$anvil->Words->string({string => "#!string!suffix_0060!#"}),
+ 's5:copy_seconds' => $anvil->Convert->add_commas({number => $copy_seconds})." ".$anvil->Words->string({string => "#!string!suffix_0007!#"}),
+ 's6:say_copy_time' => $say_copy_time,
+ 's7:file_size' => $anvil->Convert->bytes_to_human_readable({"bytes" => $file_size}),
+ }});
+
+ my $variables = {
+ host => $target_short_host_name,
+ network => $network_name,
+ ip_address => $target_ip_address,
+ source_file => $file,
+ target_directory => $target_directory,
+ size => $anvil->Convert->bytes_to_human_readable({"bytes" => $file_size}),
+ link_speed => $anvil->Convert->add_commas({number => $link_mbps})." ".$anvil->Words->string({string => "#!string!suffix_0050!#"}),
+ eta_copy_time => $say_copy_time,
+ };
+ $anvil->data->{sys}{progress} += 2;
+ $anvil->data->{sys}{progress} = 90 if $anvil->data->{sys}{progress} > 90;
+ $anvil->Job->update_progress({
+ progress => $anvil->data->{sys}{progress},
+ message => "message_0195",
+ variables => $variables,
+ });
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0195", variables => $variables});
+ my $problem = $anvil->Storage->rsync({
+ debug => 2,
+ source => $file,
+ destination => "root\@".$target_ip_address.":".$target_directory,
+ try_again => 1,
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
+ if (not $problem)
+ {
+ $copied = 1;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { copied => $copied }});
+
+ $anvil->data->{sys}{progress} += 5;
+ $anvil->data->{sys}{progress} = 90 if $anvil->data->{sys}{progress} > 90;
+ $anvil->Job->update_progress({
+ progress => $anvil->data->{sys}{progress},
+ message => "message_0310",
+ });
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0310"});
+ }
+ }
+ }
+ }
+
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_uuid => $file_uuid }});
+ if ($file_uuid)
+ {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { copied => $copied }});
+ if (not $copied)
+ {
+ # Failed to connect, register a job instead.
+ my $variables = { host => $target_host_name };
+ $anvil->data->{sys}{progress} += 5;
+ $anvil->data->{sys}{progress} = 90 if $anvil->data->{sys}{progress} > 90;
+ $anvil->Job->update_progress({
+ progress => $anvil->data->{sys}{progress},
+ message => "message_0196",
+ variables => $variables,
+ });
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0196", variables => $variables});
+ my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
+ file => $THIS_FILE,
+ line => __LINE__,
+ job_command => $anvil->data->{path}{exe}{'anvil-sync-shared'}.$anvil->Log->switches,
+ job_data => "file_uuid=".$file_uuid,
+ job_name => "storage::pull_file",
+ job_title => "job_0132",
+ job_description => "job_0133",
+ job_progress => 0,
+ job_host_uuid => $target_host_uuid,
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }});
+ }
+
+ # Mark the file as being on this host
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { do_host_type => $do_host_type }});
+ if ($do_host_type ne "striker")
+ {
+ my $file_location_uuid = $anvil->Database->insert_or_update_file_locations({
+ debug => 2,
+ file_location_file_uuid => $file_uuid,
+ file_location_host_uuid => $target_host_uuid,
+ file_location_active => 1,
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_location_uuid => $file_location_uuid }});
+ }
+ }
+ }
+ }
+
+ return(0);
+}
+
+
=head2 read_config
This method is used to read 'Anvil::Tools' style configuration files. These configuration files are in the format:
@@ -5246,7 +5514,7 @@ Parameters;
This is the full path to the file. If the file is not found, C<< !!error!! >> is returned.
-=head3 delay (optional, default '2')
+=head3 delay (optional, default '10')
This is how long to wait before checking to see if the file has changed.
diff --git a/man/Makefile.am b/man/Makefile.am
index d614bf43..401676d5 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -19,6 +19,7 @@ dist_man8_MANS = \
anvil-manage-files.8 \
anvil-manage-keys.1 \
anvil-manage-server.8 \
+ anvil-manage-server-storage.8 \
anvil-manage-storage-groups.8 \
scancore.8 \
striker-initialize-host.8
diff --git a/man/anvil-manage-server-storage.8 b/man/anvil-manage-server-storage.8
new file mode 100644
index 00000000..e69de29b
diff --git a/notes b/notes
index b3c19c85..c4012abd 100644
--- a/notes
+++ b/notes
@@ -1,5 +1,8 @@
-Add 'lsof' and 'strace' to Required
+Common queries;
+* SELECT a.job_uuid, b.host_name, a.job_command, a.job_data, a.job_progress, a.job_status FROM jobs a, hosts b WHERE a.job_host_uuid = b.host_uuid AND a.job_progress != 100;
+* SELECT a.host_name, b.file_name, c.file_location_active FROM hosts a, files b, file_locations c WHERE a.host_uuid = c.file_location_host_uuid AND b.file_uuid = c.file_location_file_uuid ORDER BY b.file_name ASC, a.host_name ASC;
+* SELECT a.dr_link_uuid, b.host_name, c.anvil_name, a.dr_link_note FROM dr_links a, hosts b, anvils c WHERE a.dr_link_host_uuid = b.host_uuid AND a.dr_link_anvil_uuid = c.anvil_uuid ORDER BY c.anvil_name ASC, b.host_name ASC;
When pairing Striker, make sure new config goes to all known nodes!
diff --git a/scancore-agents/scan-drbd/scan-drbd b/scancore-agents/scan-drbd/scan-drbd
index 8307ba6c..69cdb8e6 100755
--- a/scancore-agents/scan-drbd/scan-drbd
+++ b/scancore-agents/scan-drbd/scan-drbd
@@ -914,6 +914,16 @@ sub process_volumes
"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)
{
diff --git a/share/anvil.sql b/share/anvil.sql
index da41e482..70074137 100644
--- a/share/anvil.sql
+++ b/share/anvil.sql
@@ -1230,24 +1230,24 @@ CREATE TRIGGER trigger_files
-- This tracks which files on Strikers should be on Anvils!
CREATE TABLE file_locations (
- file_location_uuid uuid not null primary key,
- file_location_file_uuid uuid not null, -- This is file to be moved to (or restored to) this machine.
- file_location_anvil_uuid uuid not null, -- This is the sum as calculated when the file_location is first uploaded. Once recorded, it can't change.
- file_location_active boolean not null default TRUE, -- This is set to true when the file should be on Anvil! machines, triggering rsyncs when needed. When set to false, the file will be deleted from members, if they exist.
- modified_date timestamp with time zone not null,
+ file_location_uuid uuid not null primary key,
+ file_location_file_uuid uuid not null, -- This is file to be moved to (or restored to) this machine.
+ file_location_host_uuid uuid not null, -- This is the sum as calculated when the file_location is first uploaded. Once recorded, it can't change.
+ file_location_active boolean not null default TRUE, -- This is set to true when the file should be on Anvil! machines, triggering rsyncs when needed. When set to false, the file will be deleted from members, if they exist.
+ modified_date timestamp with time zone not null,
FOREIGN KEY(file_location_file_uuid) REFERENCES files(file_uuid),
- FOREIGN KEY(file_location_anvil_uuid) REFERENCES anvils(anvil_uuid)
+ FOREIGN KEY(file_location_host_uuid) REFERENCES hosts(host_uuid)
);
ALTER TABLE file_locations OWNER TO admin;
CREATE TABLE history.file_locations (
- history_id bigserial,
- file_location_uuid uuid,
- file_location_file_uuid text,
- file_location_anvil_uuid uuid,
- file_location_active boolean,
- modified_date timestamp with time zone not null
+ history_id bigserial,
+ file_location_uuid uuid,
+ file_location_file_uuid text,
+ file_location_host_uuid uuid,
+ file_location_active boolean,
+ modified_date timestamp with time zone not null
);
ALTER TABLE history.file_locations OWNER TO admin;
@@ -1260,13 +1260,13 @@ BEGIN
INSERT INTO history.file_locations
(file_location_uuid,
file_location_file_uuid,
- file_location_anvil_uuid,
+ file_location_host_uuid,
file_location_active,
modified_date)
VALUES
(history_file_locations.file_location_uuid,
history_file_locations.file_location_file_uuid,
- history_file_locations.file_location_anvil_uuid,
+ history_file_locations.file_location_host_uuid,
history_file_locations.file_location_active,
history_file_locations.modified_date);
RETURN NULL;
diff --git a/share/words.xml b/share/words.xml
index 2341622f..25cae436 100644
--- a/share/words.xml
+++ b/share/words.xml
@@ -586,6 +586,7 @@ The definition data passed in was:
'. Available servers are;]]>
+
@@ -2236,7 +2237,7 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
We're online as: [#!variable!node_name!#], but we're not quorate yet. Continuing to wait.
We're online as: [#!variable!node_name!#] and quorate!
We're not online yet. Waiting for 'in_ccm/crmd/join': [#!variable!in_ccm!#/#!variable!crmd!#/#!variable!join!#]. ('in_ccm' = consensus cluster member, communication layer. 'crmd' = cluster resource manager daemon is up, 'join' = allowed to host resources).
- The file: [#!variable!file_name!#] is not recorded for the Anvil! [#!variable!anvil_name!#] yet. Registering it now as not sync'ed to this Anvil! system.
+ The file: [#!variable!file_name!#] is not recorded for the host [#!variable!host_name!#] yet. Registering it now as not sync'ed to this system.
Asking 'anvil-boot-server' to boot the servers now.
We were asked to delete the file: [#!variable!file!#], but it doesn't exist, so nothing to do.
The file: [#!variable!file!#] has been successfully removed.
@@ -2657,8 +2658,11 @@ About to try to download aproximately: [#!variable!packages!#] packages needed t
Moving the file: [#!variable!file!#] to: [#!data!path::directories::shared::files!#].
Calculating the md5sum. This can take a little while for large files, please be patient.
The md5sum is: [#!variable!md5sum!#]. Storing details in the database.
- Copying the file over to: [#!variable!host!#]. Please be patient, this could take a bit for large files.
- Registering the file to be downloaded to the Anvil!: [#!variable!anvil_name!#]. Anvil! members will sync this file shortly. Member machines that are not online will sync the file when they do return.
+
+Copying the file: [#!variable!source_file!#] over to: [#!variable!host!#:#!variable!target_directory!#] using: [#!variable!ip_address!# (#!variable!network!#)].
+The file size is: [#!variable!size!#], and the link speed appears to be: [#!variable!link_speed!#], for an estimated copy time of about: [#!variable!eta_copy_time!#].
+Please be patient, this could take a bit for large files.
+ Registering the file to be downloaded to host: [#!variable!host!#]. Hosts that are not online will sync the file when they do return.
Upload is complete!
Processing the pull of a file from Striker.
We're a DR host and there are: [#!variable!strikers!#] dashboards, so we will wait to pull the file until after the nodes are done. We're currently waiting on; Node 1? [#!variable!node1_waiting!#], Node 2? [#!variable!node2_waiting!#]. We'll check again at: [#!variable!wait_until!#].
@@ -2859,6 +2863,9 @@ Proceed? [y/N]
Proceed? [y/N]
This is a test alert message sent at alert level: [#!variable!level!#].
Failed to send a test alert at level: [#!variable!level!#]. Is anyone listening at that level? Is the mail server configured?
+ The DRBD config file was not found. A protect job needs to be run from the Anvil! node hosting the server to be protected.
+ Waiting a bit to make sure the file: [#!variable!file!#] is done uploading...
+ Upload complete.
Normal Password
@@ -3263,6 +3270,15 @@ If you are comfortable that the target has changed for a known reason, you can s
Zbps
Ybps
Bytes
+ Bytes/sec
+ KiB/sec
+ MiB/sec
+ GiB/sec
+ TiB/sec
+ PiB/sec
+ EiB/sec
+ ZiB/sec
+ YiB/sec
Test
diff --git a/tools/Makefile.am b/tools/Makefile.am
index e0e2b7ea..96f7b2e1 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -26,6 +26,7 @@ dist_sbin_SCRIPTS = \
anvil-manage-keys \
anvil-manage-power \
anvil-manage-server \
+ anvil-manage-server-storage \
anvil-manage-storage-groups \
anvil-migrate-server \
anvil-network-profiler \
@@ -76,4 +77,3 @@ sharedir = ${datarootdir}/anvil
dist_share_DATA = striker-auto-initialize-all.example
-# -rwxr-xr-x. 1 digimer digimer 34K Feb 1 2020 tool-fio-tester
diff --git a/tools/anvil-configure-host b/tools/anvil-configure-host
index ed03a1fb..f6bcb496 100755
--- a/tools/anvil-configure-host
+++ b/tools/anvil-configure-host
@@ -174,21 +174,48 @@ sub update_passwords
}
else
{
- my ($output, $return_code) = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{'anvil-change-password'}." -y --password-file ".$temp_file.$anvil->Log->switches });
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code }});
- foreach my $line (split/\n/, $output)
+ my $wait_until = time + 120;
+ my $waiting = 1;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ waiting => $waiting,
+ wait_until => $wait_until,
+ }});
+ while ($waiting)
{
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
+ my $shell_call = $anvil->data->{path}{exe}{'anvil-change-password'}." -y --password-file ".$temp_file.$anvil->Log->switches;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
+
+ my ($output, $return_code) = $anvil->System->call({debug => 2, timeout => 15, shell_call => $shell_call });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code }});
+ foreach my $line (split/\n/, $output)
+ {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
+ }
+
+ if ($return_code)
+ {
+ # Something went wrong
+ if (time > $wait_until)
+ {
+ # Give up.
+ $waiting = 0;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { waiting => $waiting }});
+ }
+ else
+ {
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "error_0011", variables => { return_code => $return_code }});
+ }
+ }
+ else
+ {
+ # Success
+ $waiting = 0;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { waiting => $waiting }});
+ }
}
# Unlink the temp file.
unlink $temp_file;
-
- if ($return_code)
- {
- # Something went wrong
- $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "error_0011", variables => { return_code => $return_code }});
- }
}
}
@@ -408,7 +435,7 @@ ORDER BY
}});
# An undefined interface will have the MAC address value set to '1', ignore those.
- next if $variable_value = 1;
+ next if $variable_value == 1;
if ($variable_name =~ /form::config_step2::(.*?)_mac_to_set::value/)
{
diff --git a/tools/anvil-daemon b/tools/anvil-daemon
index 9b20a131..bcd15b75 100755
--- a/tools/anvil-daemon
+++ b/tools/anvil-daemon
@@ -766,7 +766,7 @@ sub check_db_in_use_states
my ($anvil) = @_;
# We only reap db_in_use entries for us.
- $anvil->System->pids();
+ $anvil->System->pids({debug => 2});
my $query = "
SELECT
state_uuid,
diff --git a/tools/anvil-manage-dr b/tools/anvil-manage-dr
index 5fe20a2f..b28d93dc 100755
--- a/tools/anvil-manage-dr
+++ b/tools/anvil-manage-dr
@@ -6,6 +6,8 @@
# This behaviour is likely to change later as it's not ideal.
#
# TODO: --remove is not yet implemented, this needs to be done. Use anvil-delete-server for methods to delete.
+# EXAMPLES:
+# - anvil-manage-dr --link --dr-host vm-a01dr02 --anvil vm-anvil-01
#
# Exit codes;
# 0 = Normal exit.
@@ -2174,7 +2176,7 @@ sub process_protect
});
$anvil->DRBD->gather_data({debug => 2});
-
+
my $server_ram = $anvil->data->{server}{$short_host_name}{$server_name}{'from_db'}{memory};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
server_ram => $anvil->Convert->add_commas({number => $server_ram})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $server_ram}).")",
@@ -2182,6 +2184,7 @@ sub process_protect
foreach my $resource (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{drbd}{resource}})
{
+ next if $resource eq "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { resource => $resource }});
foreach my $this_host_name (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$resource}{host}})
@@ -2559,6 +2562,15 @@ sub process_protect
my $record_job = 0;
if (not $anvil->data->{switches}{Yes})
{
+ # If there's no config file, this might be being run from DR which doesn't have info about
+ # the resource yet.
+ if ((not $config_file) && (not $anvil->data->{switches}{'job-uuid'}))
+ {
+ # Bail out.
+ print $anvil->Words->string({key => "message_0308"})."\n";
+ $anvil->nice_exit({exit_code => 1});
+ }
+
# Ask the user to confirm.
print "\n".$anvil->Words->string({key => "message_0021"})."\n";
my $answer = ;
diff --git a/tools/anvil-manage-files b/tools/anvil-manage-files
index 4a0257c1..1145ebed 100755
--- a/tools/anvil-manage-files
+++ b/tools/anvil-manage-files
@@ -564,10 +564,11 @@ sub check_incoming
}});
# Calculate the md5sum?
- my $file_md5sum = $recorded_md5sum;
+ my $added_to_db = 0;
+ my $file_md5sum = $recorded_md5sum;
if ((not $file_uuid) or ($file_size != $recorded_size))
{
- # It's possible the file is still uploading, so sleep for 2 seconds and see if the
+ # It's possible the file is still uploading, so sleep for a bit and see if the
# size is still changing.
my $last_size = $file_size;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
@@ -608,7 +609,7 @@ sub check_incoming
# Insert or update the files entry.
($file_uuid) = $anvil->Database->insert_or_update_files({
- debug => 3,
+ debug => 2,
file_uuid => $file_uuid,
file_name => $file_name,
file_directory => $file_directory,
@@ -617,15 +618,21 @@ sub check_incoming
file_mtime => $file_mtime,
file_type => $say_mimetype,
});
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { file_uuid => $file_uuid }});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_uuid => $file_uuid }});
+
+ if ($file_uuid)
+ {
+ $added_to_db = 1;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { added_to_db => $added_to_db }});
+ }
}
# If we still don't have a file UUID for some reason, skip this file.
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { file_uuid => $file_uuid }});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_uuid => $file_uuid }});
next if not $file_uuid;
# Are we in the incoming directory? If so, move the file.
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
full_path => $full_path,
incoming_directory => $incoming_directory,
}});
@@ -640,28 +647,34 @@ sub check_incoming
my $target = $say_mimetype eq "definition" ? $anvil->data->{path}{directories}{shared}{definitions} : $anvil->data->{path}{directories}{shared}{files};
$target .= "/";
$target =~ s/\/\//\//g;
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { target => $target }});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target => $target }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0268", variables => {
file => $full_path,
target => $target,
}});
- # Wait in case it's still being uploaded.
- $anvil->Storage->_wait_if_changing({
- file => $full_path,
- last_size => $file_size,
- });
-
- $anvil->Storage->move_file({
- debug => 3,
+ my $problem = $anvil->Storage->move_file({
+ debug => 2,
source_file => $full_path,
target_file => $target,
});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
+ if (not $problem)
+ {
+ $full_path = $target."/".$file_name;
+ $file_directory = $target;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ file_directory => $file_directory,
+ full_path => $full_path,
+ }});
+ }
# Update the file_directory.
- ($file_uuid) = $anvil->Database->insert_or_update_files({
- debug => 3,
+ $target =~ s/\/$//;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target => $target }});
+ ($file_uuid) = $anvil->Database->insert_or_update_files({
+ debug => 2,
file_uuid => $file_uuid,
file_name => $file_name,
file_directory => $target,
@@ -670,7 +683,20 @@ sub check_incoming
file_mtime => $file_mtime,
file_type => $say_mimetype,
});
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { file_uuid => $file_uuid }});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_uuid => $file_uuid }});
+ }
+
+ if ($added_to_db)
+ {
+ # Push it to all other hosts now.
+ $anvil->Storage->push_file({
+ debug => 2,
+ file => $full_path,
+ file_uuid => $file_uuid,
+ });
+
+ # Call track_files, it'll make sure the file_locations are setup.
+ $anvil->Database->track_files({debug => 2});
}
}
@@ -729,6 +755,7 @@ WHERE
{
$query .= " file_name = ".$anvil->Database->quote($file_name)."\n";
}
+ $query .= ";";
$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};
diff --git a/tools/anvil-manage-host b/tools/anvil-manage-host
index ddc964db..28f37a86 100755
--- a/tools/anvil-manage-host
+++ b/tools/anvil-manage-host
@@ -24,26 +24,17 @@ if (($running_directory =~ /^\./) && ($ENV{PWD}))
my $anvil = Anvil::Tools->new();
# Read switches
-$anvil->data->{switches}{'age-out-database'} = "";
-$anvil->data->{switches}{'check-configured'} = "";
-$anvil->data->{switches}{'check-database'} = "";
-$anvil->data->{switches}{'database-active'} = "";
-$anvil->data->{switches}{'database-inactive'} = "";
-$anvil->data->{switches}{'mark-configured'} = "";
-$anvil->data->{switches}{'mark-unconfigured'} = "";
-$anvil->data->{switches}{'resync-database'} = "";
-$anvil->Get->switches;
-$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }});
-$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
- 'switches::age-out-database' => $anvil->data->{switches}{'age-out-database'},
- 'switches::check-configured' => $anvil->data->{switches}{'check-configured'},
- 'switches::check-database' => $anvil->data->{switches}{'check-database'},
- 'switches::database-active' => $anvil->data->{switches}{'database-active'},
- 'switches::database-inactive' => $anvil->data->{switches}{'database-inactive'},
- 'switches::mark-configured' => $anvil->data->{switches}{'mark-configured'},
- 'switches::mark-unconfigured' => $anvil->data->{switches}{'mark-unconfigured'},
- 'switches::resync-database' => $anvil->data->{switches}{'resync-database'},
-}});
+$anvil->Get->switches({list => [
+ "age-out-database",
+ "check-configured",
+ "check-database",
+ "database-active",
+ "database-inactive",
+ "mark-configured",
+ "mark-unconfigured",
+ "resync-database"], man => $THIS_FILE});
+$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}});
+$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }});
$anvil->Database->connect({all => 1});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
diff --git a/tools/anvil-manage-server-storage b/tools/anvil-manage-server-storage
new file mode 100755
index 00000000..06eeaf66
--- /dev/null
+++ b/tools/anvil-manage-server-storage
@@ -0,0 +1,398 @@
+#!/usr/bin/perl
+#
+# This program will manage servers; Changing RAM, CPU cores, Growing virtual disks, adding virtual disks,
+# inserting and ejecting ISO images into virtual optical media.
+#
+# Exit codes;
+# 0 = Normal exit.
+# 1 = No database connection.
+#
+# TODO:
+#
+
+use strict;
+use warnings;
+use Anvil::Tools;
+require POSIX;
+use Term::Cap;
+use Data::Dumper;
+
+my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
+my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
+if (($running_directory =~ /^\./) && ($ENV{PWD}))
+{
+ $running_directory =~ s/^\./$ENV{PWD}/;
+}
+
+# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete.
+$| = 1;
+
+my $anvil = Anvil::Tools->new();
+
+### TODO: Remove this before final release
+$anvil->Log->level({set => 2});
+$anvil->Log->secure({set => 1});
+##########################################
+
+# Read switches (target ([user@]host[:port]) and the file with the target's password.
+$anvil->Get->switches({list => [
+ "add",
+ "anvil",
+ "grow",
+ "server",
+ ], man => $THIS_FILE});
+$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}});
+$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }});
+
+# Connect to the database(s). If we have no connections, we'll proceed anyway as one of the 'run_once' tasks
+# is to setup the database server.
+$anvil->Database->connect();
+$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"});
+if (not $anvil->data->{sys}{database}{connections})
+{
+ # No databases, update the job, sleep for a bit and then exit. The daemon will pick it up and try
+ # again after we exit.
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0305"});
+ sleep 10;
+ $anvil->nice_exit({exit_code => 1});
+}
+
+# If we don't have a job UUID, try to find one.
+if (not $anvil->data->{switches}{'job-uuid'})
+{
+ # Load the job data.
+ $anvil->data->{switches}{'job-uuid'} = $anvil->Job->get_job_uuid({program => $THIS_FILE});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::job-uuid" => $anvil->data->{switches}{'job-uuid'} }});
+}
+
+$anvil->Database->get_hosts();
+$anvil->Database->get_anvils();
+$anvil->Database->get_servers();
+
+if ($anvil->data->{switches}{anvil})
+{
+ # Make sure they asked for a real anvil.
+ $anvil->Get->anvil_from_switch({string => $anvil->data->{switches}{anvil}});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ "switches::anvil_name" => $anvil->data->{switches}{anvil_name},
+ "switches::anvil_uuid" => $anvil->data->{switches}{anvil_uuid},
+ }});
+}
+
+if (not $anvil->data->{switches}{server})
+{
+ # Show the list of servers.
+ show_server_list($anvil);
+ print "\nPlease specify which server you want to modify using '--server '.\n\n";
+ $anvil->nice_exit({exit_code => 0});
+}
+manage_server($anvil);
+
+$anvil->nice_exit({exit_code => 0});
+
+
+#############################################################################################################
+# Functions #
+#############################################################################################################
+
+sub manage_server
+{
+ my ($anvil) = @_;
+
+ $anvil->Get->server_from_switch({
+ debug => 2,
+ string => $anvil->data->{switches}{server},
+ anvil_uuid => $anvil->data->{switches}{anvil_uuid},
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ "switches::server_name" => $anvil->data->{switches}{server_name},
+ "switches::server_uuid" => $anvil->data->{switches}{server_uuid},
+ }});
+
+ if (not $anvil->data->{switches}{server_uuid})
+ {
+ show_server_list($anvil);
+ if ($anvil->data->{switches}{anvil_uuid})
+ {
+ # Not found on the requested Anvil! node.
+ print "\nThe server: [".$anvil->data->{switches}{server}."] was not found on the Anvil! node: [".$anvil->data->{switches}{anvil_name}."]. Valid servers are above.\n\n";
+ }
+ else
+ {
+ # Not found at all.
+ print "\nThe server: [".$anvil->data->{switches}{server}."] was not found. Valid servers are above.\n\n";
+ }
+ $anvil->nice_exit({exit_code => 1});
+ }
+
+ print "Working with the server: [".$anvil->data->{switches}{server_name}."], UUID: [".$anvil->data->{switches}{server_uuid}."]\n";
+ my $short_host_name = $anvil->Get->short_host_name;
+ my $server_name = $anvil->data->{switches}{server_name};
+ my $server_uuid = $anvil->data->{switches}{server_uuid};
+ my $server_definition = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_definition_xml};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:short_host_name' => $short_host_name,
+ 's2:server_name' => $server_name,
+ 's3:server_uuid' => $server_uuid,
+ 's4:server_definition' => $server_definition,
+ }});
+
+ # Parse the definition.
+ $anvil->Server->parse_definition({
+ debug => 3,
+ host => $short_host_name,
+ server => $server_name,
+ source => "from_virsh",
+ definition => $server_definition,
+ });
+
+ #$anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{boot_order}
+ foreach my $device ("disk", "cdrom")
+ {
+ if ($device eq "disk")
+ {
+ print "\nDisk Drives:\n";
+ }
+ else
+ {
+ print "\nOptical Drives:\n";
+ }
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { device => $device }});
+ next if $device ne "cdrom" && $device ne "disk";
+ foreach my $device_target (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}})
+ {
+ my $alias = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{alias};
+ my $boot_order = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{boot_order};
+ my $say_boot = $boot_order eq "99" ? "--" : sprintf("%02d", $boot_order);
+ my $type = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{type};
+ my $address_type = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{address}{type};
+ my $address_bus = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{address}{bus};
+ my $driver_name = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{driver}{name};
+ my $device_bus = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{device_bus};
+ my $driver_type = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{driver}{type};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's01:device_target' => $device_target,
+ 's02:alias' => $alias,
+ 's03:boot_order' => $boot_order,
+ 's04:say_boot' => $say_boot,
+ 's05:type' => $type,
+ 's06:address_type' => $address_type,
+ 's07:address_bus' => $address_bus,
+ 's08:driver_name' => $driver_name,
+ 's09:device_bus' => $device_bus,
+ 's10:driver_type' => $driver_type,
+ }});
+ if ($device eq "disk")
+ {
+ my $address_domain = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{address}{domain};
+ my $address_slot = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{address}{slot};
+ my $address_function = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{address}{function};
+ my $device_path = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{path};
+ my $driver_io = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{driver}{io};
+ my $driver_cache = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{driver}{cache};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:address_domain' => $address_domain,
+ 's2:address_slot' => $address_slot,
+ 's3:address_function' => $address_function,
+ 's4:device_path' => $device_path,
+ 's5:driver_io' => $driver_io,
+ 's6:driver_cache' => $driver_cache,
+ }});
+ print "- Target: [".$device_target."], boot: [".$say_boot."], path: [".$device_path."], cache: [".$driver_cache."], driver type: [".$driver_type."]\n";
+ }
+ else
+ {
+ my $address_controller = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{address}{controller};
+ my $address_unit = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{address}{unit};
+ my $address_target = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{address}{target};
+ my $device_path = $anvil->data->{server}{$short_host_name}{$server_name}{from_virsh}{device}{$device}{target}{$device_target}{path};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:address_controller' => $address_controller,
+ 's2:address_unit' => $address_unit,
+ 's3:address_target' => $address_target,
+ 's4:device_path' => $device_path,
+ }});
+ print "- Target: [".$device_target."], boot: [".$say_boot."], ISO: [".$device_path."]\n";
+ }
+ }
+ }
+ print "\n";
+
+ my $drbd_resource = "";
+ foreach my $device_path (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{device}})
+ {
+ my $on_lv = $anvil->data->{server}{$short_host_name}{$server_name}{device}{$device_path}{on_lv};
+ $drbd_resource = $anvil->data->{server}{$short_host_name}{$server_name}{device}{$device_path}{resource};
+ my $device_target = $anvil->data->{server}{$short_host_name}{$server_name}{device}{$device_path}{target};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:device_path' => $device_path,
+ 's2:on_lv' => $on_lv,
+ 's3:drbd_resource' => $drbd_resource,
+ 's4:device_target' => $device_target,
+ }});
+ }
+ foreach my $drbd_resource (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{drbd}{resource}})
+ {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { drbd_resource => $drbd_resource }});
+ }
+
+ # Get the DRBD volume data
+ # Get the DRBD volume data
+ my $query = "
+SELECT
+ a.host_uuid,
+ b.scan_drbd_resource_xml,
+ c.scan_drbd_volume_number,
+ c.scan_drbd_volume_device_path,
+ c.scan_drbd_volume_device_minor,
+ c.scan_drbd_volume_size
+FROM
+ hosts a,
+ scan_drbd_resources b,
+ scan_drbd_volumes c
+WHERE
+ a.host_uuid = b.scan_drbd_resource_host_uuid
+AND
+ b.scan_drbd_resource_uuid = c.scan_drbd_volume_scan_drbd_resource_uuid
+AND
+ b.scan_drbd_resource_name = ".$anvil->Database->quote($drbd_resource)."
+;";
+ $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 $host_uuid = $row->[0];
+ my $short_host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{short_host_name};
+ my $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type};
+ my $scan_drbd_volume_number = $row->[2];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:host_uuid' => $host_uuid,
+ 's2:host_type' => $host_type,
+ 's3:short_host_name' => $short_host_name,
+ 's4:scan_drbd_volume_number' => $scan_drbd_volume_number,
+ }});
+
+ $anvil->data->{drbd_resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}{$scan_drbd_volume_number}{device_path} = $row->[3];
+ $anvil->data->{drbd_resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}{$scan_drbd_volume_number}{device_minor} = $row->[4];
+ $anvil->data->{drbd_resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}{$scan_drbd_volume_number}{volume_size} = $row->[5];
+ $anvil->data->{drbd_resource}{$drbd_resource}{host_type}{$host_type}{short_host_name}{$short_host_name}{host_uuid} = $host_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ "s1:drbd_resource::${drbd_resource}::host_uuid::${host_uuid}::volume_number::${scan_drbd_volume_number}::device_path" => $anvil->data->{drbd_resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}{$scan_drbd_volume_number}{device_path},
+ "s2:drbd_resource::${drbd_resource}::host_uuid::${host_uuid}::volume_number::${scan_drbd_volume_number}::device_minor" => $anvil->data->{drbd_resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}{$scan_drbd_volume_number}{device_minor},
+ "s3:drbd_resource::${drbd_resource}::host_uuid::${host_uuid}::volume_number::${scan_drbd_volume_number}::volume_size" => $anvil->data->{drbd_resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}{$scan_drbd_volume_number}{volume_size},
+ "s4:drbd_resource::${drbd_resource}::host_type::${host_type}::short_host_name::${short_host_name}::host_uuid" => $anvil->data->{drbd_resource}{$drbd_resource}{host_type}{$host_type}{short_host_name}{$short_host_name}{host_uuid},
+ }});
+
+ if (not exists $anvil->data->{drbd_resource}{$drbd_resource}{xml})
+ {
+ $anvil->data->{drbd_resource}{$drbd_resource}{xml} = $row->[1];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ "drbd_resource::${drbd_resource}::xml" => $anvil->data->{drbd_resource}{$drbd_resource}{xml},
+ }});
+ $anvil->DRBD->parse_resource({
+ debug => 2,
+ xml => $anvil->data->{drbd_resource}{$drbd_resource}{xml},
+ });
+ }
+ }
+
+ print "Sub-Nodes:\n";
+ show_volume($anvil, $drbd_resource, "node");
+
+ my $dr_count = keys %{$anvil->data->{drbd_resource}{$drbd_resource}{host_type}{dr}{short_host_name}};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { dr_count => $dr_count }});
+ if ($dr_count)
+ {
+ print "DR Hosts:\n";
+ show_volume($anvil, $drbd_resource, "dr");
+ }
+
+ return(0);
+}
+
+sub show_volume
+{
+ my ($anvil, $drbd_resource, $host_type) = @_;
+
+ foreach my $short_host_name (sort {$a cmp $b} keys %{$anvil->data->{drbd_resource}{$drbd_resource}{host_type}{$host_type}{short_host_name}})
+ {
+ my $host_uuid = $anvil->data->{drbd_resource}{$drbd_resource}{host_type}{$host_type}{short_host_name}{$short_host_name}{host_uuid};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:short_host_name' => $short_host_name,
+ 's2:host_uuid' => $host_uuid,
+ }});
+ print " |- Name: [".$short_host_name."], UUID: [".$host_uuid."]\n";
+ foreach my $volume_number (sort {$a cmp $b} keys %{$anvil->data->{drbd_resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}})
+ {
+ my $device_path = $anvil->data->{drbd_resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}{$volume_number}{device_path};
+ my $device_minor = $anvil->data->{drbd_resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}{$volume_number}{device_minor};
+ my $volume_size = $anvil->data->{drbd_resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}{$volume_number}{volume_size};
+ my $backing_disk = $anvil->data->{new}{resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}{$volume_number}{backing_disk};
+ my $meta_disk = $anvil->data->{new}{resource}{$drbd_resource}{host_uuid}{$host_uuid}{volume_number}{$volume_number}{meta_disk};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:volume_number' => $volume_number,
+ 's2:device_path' => $device_path,
+ 's3:device_minor' => $device_minor,
+ 's4:volume_size' => $volume_size,
+ 's5:backing_disk' => $backing_disk,
+ 's6:meta_disk' => $meta_disk,
+ }});
+ print " ^- Volume: [".$volume_number."], backing device: [".$backing_disk."], DRBD minor: [".$device_minor."], size: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $volume_size})."]\n";
+ }
+ }
+
+ return(0);
+}
+
+sub show_server_list
+{
+ my ($anvil) = @_;
+
+ # Loop through all Anvil! nodes, then all server in that Anvil!
+ foreach my $anvil_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_name}})
+ {
+ my $anvil_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_uuid};
+ my $anvil_description = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_description};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ anvil_name => $anvil_name,
+ anvil_uuid => $anvil_uuid,
+ anvil_description => $anvil_description,
+ }});
+ if (($anvil->data->{switches}{anvil_uuid}) && ($anvil->data->{switches}{anvil_uuid} ne $anvil_uuid))
+ {
+ next;
+ }
+ print "\nAnvil! Node: [".$anvil_name."], UUID: [".$anvil_uuid."] - Description: [".$anvil_description."]\n";
+
+ my $server_count = 0;
+ if (exists $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name})
+ {
+ $server_count = keys %{$anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_count => $server_count }});
+ }
+ if (not $server_count)
+ {
+ print "- No servers on this node yet\n";
+ }
+ else
+ {
+ foreach my $server_name (sort {$a cmp $b} keys %{$anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}})
+ {
+ my $server_uuid = $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$server_name}{server_uuid};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ server_name => $server_name,
+ server_uuid => $server_uuid,
+ }});
+ print "^- Server: [".$server_name."], UUID: [".$server_uuid."]\n";
+ }
+ }
+ }
+
+ return(0);
+}
diff --git a/tools/anvil-sync-shared b/tools/anvil-sync-shared
index a802d90b..4fb02354 100755
--- a/tools/anvil-sync-shared
+++ b/tools/anvil-sync-shared
@@ -48,10 +48,11 @@ if (not $anvil->data->{switches}{'job-uuid'})
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::job-uuid" => $anvil->data->{switches}{'job-uuid'} }});
}
-# If we still don't have a job-uuid, go into interactive mode.
+# If we have a job-uuid, process it.
if ($anvil->data->{switches}{'job-uuid'})
{
# Load the job data.
+ $anvil->Database->get_anvils({debug => 3});
$anvil->Job->get_job_details({debug => 3});
$anvil->Job->clear({debug => 3});
@@ -440,21 +441,31 @@ sub process_incoming_file
$anvil->nice_exit({exit_code => 1});
}
+ # Make sure the file actually done uploading.
+ $anvil->data->{sys}{progress} = 5;
+ $anvil->Job->update_progress({
+ progress => $anvil->data->{sys}{progress},
+ message => "message_0309,!!file!".$file."!!",
+ });
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0309", variables => { file => $file }});
+ $anvil->Storage->_wait_if_changing({
+ debug => 2,
+ file => $file,
+ });
+
# Move it over to files.
- $anvil->data->{sys}{progress} = 10;
+ $anvil->data->{sys}{progress} = 5;
$anvil->Job->update_progress({
progress => $anvil->data->{sys}{progress},
message => "message_0192,!!file!".$file."!!",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0192", variables => { file => $file }});
-
$anvil->Storage->move_file({
debug => 2,
overwrite => 1,
source_file => $file,
target_file => $anvil->data->{path}{directories}{shared}{files}."/",
});
-
my $file_name = ($file =~ /\/.*\/(.*?)$/)[0];
my $target_file = $anvil->data->{path}{directories}{shared}{files}."/".$file_name;
@@ -561,90 +572,16 @@ sub process_incoming_file
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_uuid => $file_uuid }});
- # Now copy this to our peers.
- foreach my $host_uuid (sort {$a cmp $b} keys %{$anvil->data->{database}})
- {
- # Periodically, autovivication causes and empty key to appear.
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }});
- next if ((not $host_uuid) or (not $anvil->Validate->uuid({uuid => $host_uuid})));
- next if $host_uuid eq $anvil->Get->host_uuid;
-
- my $host = $anvil->data->{database}{$host_uuid}{host};
- my $password = $anvil->data->{database}{$host_uuid}{password};
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
- host => $host,
- password => $anvil->Log->is_secure($password),
- }});
-
- my $striker_name = $anvil->Get->host_name_from_uuid({host_uuid => $host_uuid});
- my $say_host = $striker_name." (".$host.")";
-
- # Rsync the file.
- $anvil->data->{sys}{progress} += 10;
- $anvil->data->{sys}{progress} = 90 if $anvil->data->{sys}{progress} > 90;
- $anvil->Job->update_progress({
- progress => $anvil->data->{sys}{progress},
- message => "message_0195,!!host!".$say_host."!!",
- });
- $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0195", variables => { host => $say_host }});
-
- $anvil->Storage->rsync({
- debug => 2,
- source => $target_file,
- destination => "root\@".$host.":".$anvil->data->{path}{directories}{shared}{files}."/",
- try_again => 1,
- });
- }
+ # Now copy this to our peers. We're going to do this serially so that we don't overwhelm the system,
+ # Any hosts not currently online will have a job registered.
+ $anvil->Storage->push_file({
+ debug => 2,
+ file => $target_file,
+ file_uuid => $file_uuid,
+ });
- # Tell other Anvil! systems to download this file.
- $anvil->Database->get_anvils({debug => 2});
- foreach my $anvil_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_name}})
- {
- my $anvil_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_uuid};
- my $anvil_node1_host_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_node1_host_uuid};
- my $anvil_node2_host_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_node2_host_uuid};
- my $anvil_dr1_host_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_dr1_host_uuid};
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
- anvil_uuid => $anvil_uuid,
- anvil_node1_host_uuid => $anvil_node1_host_uuid,
- anvil_node2_host_uuid => $anvil_node2_host_uuid,
- anvil_dr1_host_uuid => $anvil_dr1_host_uuid,
- }});
-
- $anvil->data->{sys}{progress} += 5;
- $anvil->data->{sys}{progress} = 90 if $anvil->data->{sys}{progress} > 90;
- $anvil->Job->update_progress({
- progress => $anvil->data->{sys}{progress},
- message => "message_0196,!!anvil_name!".$anvil_name."!!",
- });
- $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0196", variables => { anvil_name => $anvil_name }});
-
- my $file_location_uuid = $anvil->Database->insert_or_update_file_locations({
- debug => 2,
- file_location_file_uuid => $file_uuid,
- file_location_anvil_uuid => $anvil_uuid,
- file_location_active => 1,
- });
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_location_uuid => $file_location_uuid }});
-
- # Register a job to call anvil-sync-shared
- foreach my $host_uuid ($anvil_node1_host_uuid, $anvil_node2_host_uuid, $anvil_dr1_host_uuid)
- {
- next if not $host_uuid;
- my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
- file => $THIS_FILE,
- line => __LINE__,
- job_command => $anvil->data->{path}{exe}{'anvil-sync-shared'}.$anvil->Log->switches,
- job_data => "file_uuid=".$file_uuid,
- job_name => "storage::pull_file",
- job_title => "job_0132",
- job_description => "job_0133",
- job_progress => 0,
- job_host_uuid => $host_uuid,
- });
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }});
- }
- }
+ # Call track_files, it'll make sure the file_locations are setup.
+ $anvil->Database->track_files({debug => 2});
# Done!
$anvil->Job->update_progress({
diff --git a/tools/anvil-version-changes b/tools/anvil-version-changes
index 66fe4ff3..ea0d4e4d 100755
--- a/tools/anvil-version-changes
+++ b/tools/anvil-version-changes
@@ -62,6 +62,10 @@ $anvil->nice_exit({exit_code => 0});
sub striker_checks
{
my ($anvil) = @_;
+
+ # This replaces anvil_uuid with host_uuid to support more granular location info to support the new
+ # multi-target DR system
+ update_file_locations($anvil);
# This converts the old/broken 'notifications' tables with the more appropriately named 'alert-override'
update_notifications($anvil);
@@ -365,6 +369,133 @@ CREATE TRIGGER trigger_storage_group_members
return(0);
}
+# This replaces anvil_uuid with host_uuid to support more granular location info to support the new
+# multi-target DR system
+sub update_file_locations
+{
+ my ($anvil) = @_;
+
+ my $updated = 0;
+ foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}})
+ {
+ my $query = "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'file_locations' AND column_name = 'file_location_anvil_uuid';";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
+
+ my $count = $anvil->Database->query({query => $query, uuid => $uuid, source => $THIS_FILE, line => __LINE__})->[0]->[0];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ uuid => $uuid,
+ count => $count,
+ }});
+
+ # Wipe it out, then re-add
+ if ($count)
+ {
+ $updated = 1;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { updated => $updated }});
+
+ my $queries = [];
+ push @{$queries}, "DROP TABLE public.file_locations;";
+ push @{$queries}, "DROP TABLE history.file_locations;";
+ push @{$queries}, "DROP FUNCTION history_file_locations() CASCADE;";
+ push @{$queries}, q|CREATE TABLE file_locations (
+ file_location_uuid uuid not null primary key,
+ file_location_file_uuid uuid not null, -- This is file to be moved to (or restored to) this machine.
+ file_location_host_uuid uuid not null, -- This is the sum as calculated when the file_location is first uploaded. Once recorded, it can't change.
+ file_location_active boolean not null default TRUE, -- This is set to true when the file should be on Anvil! machines, triggering rsyncs when needed. When set to false, the file will be deleted from members, if they exist.
+ modified_date timestamp with time zone not null,
+
+ FOREIGN KEY(file_location_file_uuid) REFERENCES files(file_uuid),
+ FOREIGN KEY(file_location_host_uuid) REFERENCES hosts(host_uuid)
+);
+ALTER TABLE file_locations OWNER TO admin;
+
+CREATE TABLE history.file_locations (
+ history_id bigserial,
+ file_location_uuid uuid,
+ file_location_file_uuid text,
+ file_location_host_uuid uuid,
+ file_location_active boolean,
+ modified_date timestamp with time zone not null
+);
+ALTER TABLE history.file_locations OWNER TO admin;
+
+CREATE FUNCTION history_file_locations() RETURNS trigger
+AS $$
+DECLARE
+ history_file_locations RECORD;
+BEGIN
+ SELECT INTO history_file_locations * FROM file_locations WHERE file_location_uuid = new.file_location_uuid;
+ INSERT INTO history.file_locations
+ (file_location_uuid,
+ file_location_file_uuid,
+ file_location_host_uuid,
+ file_location_active,
+ modified_date)
+ VALUES
+ (history_file_locations.file_location_uuid,
+ history_file_locations.file_location_file_uuid,
+ history_file_locations.file_location_host_uuid,
+ history_file_locations.file_location_active,
+ history_file_locations.modified_date);
+ RETURN NULL;
+END;
+$$
+LANGUAGE plpgsql;
+ALTER FUNCTION history_file_locations() OWNER TO admin;
+
+CREATE TRIGGER trigger_file_locations
+ AFTER INSERT OR UPDATE ON file_locations
+ FOR EACH ROW EXECUTE PROCEDURE history_file_locations();
+|;
+ foreach my $query (@{$queries})
+ {
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }});
+ }
+ $anvil->Database->write({debug => 2, uuid => $uuid, query => $queries, source => $THIS_FILE, line => __LINE__});
+ }
+ }
+
+ # Make sure all files are linked to all nodes and dr_hosts
+ if ($updated)
+ {
+ $anvil->Database->get_hosts();
+ $anvil->Database->get_files();
+ $anvil->Database->get_file_locations();
+ foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{files}{file_name}})
+ {
+ my $file_uuid = $anvil->data->{files}{file_name}{$file_name}{file_uuid};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:file_name' => $file_name,
+ 's2:file_uuid' => $file_uuid,
+ }});
+ foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{sys}{hosts}{by_name}})
+ {
+ my $host_uuid = $anvil->data->{sys}{hosts}{by_name}{$host_name};
+ my $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type};
+ my $host_key = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ 's1:host_name' => $host_name,
+ 's2:host_uuid' => $host_uuid,
+ 's3:host_type' => $host_type,
+ 's4:host_key' => $host_key,
+ }});
+ next if $host_type eq "striker";
+ next if $host_key eq "DELETED";
+
+ my $file_location_uuid = $anvil->Database->insert_or_update_file_locations({
+ debug => 2,
+ file_location_file_uuid => $file_uuid,
+ file_location_host_uuid => $host_uuid,
+ file_location_active => 1,
+ });
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_location_uuid => $file_location_uuid }});
+ }
+ }
+ }
+
+ return(0);
+}
+
# This converts the old/broken 'notifications' tables with the more appropriately named 'alert-override'
sub update_notifications
{
@@ -373,9 +504,9 @@ sub update_notifications
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}})
{
my $query = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public' AND table_catalog = 'anvil' AND table_name = 'notifications';";
- $anvil->Log->variables({source => $THIS_FILE, uuid => $uuid, line => __LINE__, level => 2, list => { query => $query }});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
- my $count = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
+ my $count = $anvil->Database->query({query => $query, uuid => $uuid, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
if ($count)
diff --git a/tools/striker-purge-target b/tools/striker-purge-target
index 11bd6b5e..e0bc6cc7 100755
--- a/tools/striker-purge-target
+++ b/tools/striker-purge-target
@@ -281,18 +281,9 @@ WHERE
}
}
- # If deleting an Anvil!, we need to clear any Anvil! references from file_locations and storage groups.
+ # If deleting an Anvil!, we need to clear any Anvil! references from storage groups.
if (($table eq "anvils") && ($anvil->data->{purge}{anvil_uuid}))
{
- #
- my $query = "DELETE FROM history.file_locations WHERE file_location_anvil_uuid = ".$anvil->Database->quote($anvil->data->{purge}{anvil_uuid}).";";
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
- push @{$queries}, $query;
-
- $query = "DELETE FROM file_locations WHERE file_location_anvil_uuid = ".$anvil->Database->quote($anvil->data->{purge}{anvil_uuid}).";";
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
- push @{$queries}, $query;
-
# Storage groups
$query = "
SELECT