#!/usr/bin/perl # # This allows users to link volume groups across machines into storage groups. # # NOTE: This will be expanded on much more later. For now, it's "enough". # # Exit codes; # 0 = Normal exit. # 1 = Any problem that causes an early exit. # # Examples; # - TODO: Write the man page! # - anvil-manage-storage-groups -vv --log-secure --anvil mk-anvil-07 --rename --group "Storage group 2" --new-name "HDD Group 1" # - anvil-manage-storage-groups -vv --log-secure --anvil mk-anvil-07 --add --group "HDD Group 1" --member xidRiS-KT4K-cmVN-MRbK-tI2c-jhK6-VCCLau use strict; use warnings; use Anvil::Tools; require POSIX; use Term::Cap; use Text::Diff; 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(); $anvil->Get->switches({list => [ "add", "anvil", "remove", "rename", "group", "host", "member", "new-name", "show", "vg"], 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(); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 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_0306"}); sleep 10; $anvil->nice_exit({exit_code => 1}); } $anvil->Database->get_hosts({include_deleted => 1}); $anvil->Database->get_anvils(); $anvil->Database->get_storage_group_data({debug => 2}); get_vg_data($anvil); get_storage_data($anvil); if ($anvil->data->{switches}{show}) { show_data($anvil); $anvil->nice_exit({exit_code => 0}); } if ($anvil->data->{switches}{member}) { manage_group_member($anvil); } if ($anvil->data->{switches}{group}) { manage_group($anvil); } show_data($anvil); $anvil->nice_exit({exit_code => 0}); ############################################################################################################# # Functions # ############################################################################################################# sub manage_group { my ($anvil) = @_; my $group = $anvil->data->{switches}{group}; my $new_name = $anvil->data->{switches}{'new-name'}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { group => $group, new_name => $new_name }}); if ($group eq "#!SET!#") { print "When adding, removing or renaming a group, '--group' needs to be set to the (new) group name.\n"; $anvil->nice_exit({exit_code => 1}); } # If both are set, what? if ((($anvil->data->{switches}{add}) && ($anvil->data->{switches}{remove})) or (($anvil->data->{switches}{add}) && ($anvil->data->{switches}{'rename'})) or (($anvil->data->{switches}{remove}) && ($anvil->data->{switches}{'rename'}))) { print "You can only use '--add', '--remove' or '--rename', please use only one at a time.\n"; $anvil->nice_exit({exit_code => 1}); } my $anvil_uuid = $anvil->Database->get_anvil_uuid_from_string({string => $anvil->data->{switches}{anvil}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); if (not $anvil_uuid) { if ($anvil->data->{switches}{anvil}) { print "The Anvil! node: [".$anvil->data->{switches}{anvil}."] was not found.\n"; } else { print "When managing a storage group, '--anvil ' is required as storage group names are not globally unique.\n"; } $anvil->nice_exit({exit_code => 1}); } my $anvil_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_name => $anvil_name }}); # If the group is 'DELETED', um, what the fuck? if (($group eq "DELETED") or ($new_name eq "DELETED")) { print "You want to name your group 'DELETED'? Well that's cheaky... Exiting.\n"; $anvil->nice_exit({exit_code => 1}); } my $storage_group_uuid = ""; my $storage_group_name = ""; if (exists $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_name}{$group}) { $storage_group_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_name}{$group}{storage_group_uuid}; $storage_group_name = $group; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_uuid => $storage_group_uuid, storage_group_name => $storage_group_name, }}); } elsif (exists $anvil->data->{storage_groups}{storage_group_uuid}{$group}) { $storage_group_uuid = $group; $storage_group_name = $anvil->data->{storage_groups}{storage_group_uuid}{$group}{anvil_uuid}{$anvil_uuid}{storage_group_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_uuid => $storage_group_uuid, storage_group_name => $storage_group_name, }}); } if ($anvil->data->{switches}{add}) { # Does it already exist? if ($storage_group_uuid) { print "The storage group: [".$storage_group_name."] on the Anvil! node: [".$anvil_name."] already exists, nothing to do.\n"; $anvil->nice_exit({exit_code => 0}); } # Add it. $storage_group_uuid = $anvil->Database->insert_or_update_storage_groups({ debug => 2, storage_group_anvil_uuid => $anvil_uuid, storage_group_name => $storage_group_name, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_uuid => $storage_group_uuid }}); print "The storage group: [".$storage_group_name."] on the Anvil! node: [".$anvil_name."] has been created with the UUID: [".$storage_group_uuid."].\n"; $anvil->nice_exit({exit_code => 0}); } elsif ($anvil->data->{switches}{remove}) { # Does it exist? if (not $storage_group_uuid) { print "The storage group: [".$group."] wasn't found on the Anvil! node: [".$anvil_name."], nothing to do.\n"; $anvil->nice_exit({exit_code => 0}); } # Remove it. $storage_group_uuid = $anvil->Database->insert_or_update_storage_groups({ debug => 2, storage_group_anvil_uuid => $anvil_uuid, storage_group_name => "DELETED", storage_group_name => $storage_group_uuid, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_uuid => $storage_group_uuid }}); print "The storage group: [".$storage_group_name."] on the Anvil! node: [".$anvil_name."] has been deleted.\n"; $anvil->nice_exit({exit_code => 0}); } elsif ($anvil->data->{switches}{'rename'}) { # Do we have a new name? if (not $new_name) { print "The storage group: [".$storage_group_name."] exists on the Anvil! node: [".$anvil_name."], but no new name was given via '--new-name ' nothing to do.\n"; $anvil->nice_exit({exit_code => 1}); } # Has the name changed? if (($storage_group_name) eq ($new_name)) { print "The storage group: [".$new_name."] already has the desired name on the: [".$anvil_name."], nothing to do.\n"; $anvil->nice_exit({exit_code => 0}); } # Rename it. $storage_group_uuid = $anvil->Database->insert_or_update_storage_groups({ debug => 2, storage_group_uuid => $storage_group_uuid, storage_group_anvil_uuid => $anvil_uuid, storage_group_name => $new_name, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_uuid => $storage_group_uuid }}); print "The storage group: [".$storage_group_name."] on the Anvil! node: [".$anvil_name."] has been renamed to: [".$new_name."].\n"; $anvil->nice_exit({exit_code => 0}); } return(0); } sub manage_group_member { my ($anvil) = @_; my $group = $anvil->data->{switches}{group}; my $anvil_uuid = $anvil->Database->get_anvil_uuid_from_string({string => $anvil->data->{switches}{anvil}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); if (not $anvil_uuid) { if ($anvil->data->{switches}{anvil}) { print "The Anvil! node: [".$anvil->data->{switches}{anvil}."] was not found.\n"; } else { print "When managing a storage group members, '--anvil ' is required as storage group names are not globally unique.\n"; } $anvil->nice_exit({exit_code => 1}); } my $anvil_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_name => $anvil_name }}); my $storage_group_uuid = ""; my $storage_group_name = ""; foreach my $this_storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_name}}) { my $this_storage_group_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_name}{$this_storage_group_name}{storage_group_uuid}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { this_storage_group_name => $this_storage_group_name, this_storage_group_uuid => $this_storage_group_uuid, }}); if (($group eq $this_storage_group_name) or ($group eq $this_storage_group_uuid)) { # Found it. $storage_group_uuid = $this_storage_group_uuid; $storage_group_name = $this_storage_group_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_uuid => $storage_group_uuid, storage_group_name => $storage_group_name, }}); last; } } if (not $storage_group_uuid) { # Group not found. print "The storage group: [".$group."] was not found on the Anvil! node: [".$anvil_name."].\n"; print "Call with '--show' to see Anvil! nodes, DR hosts and existing storage groups.\n"; $anvil->nice_exit({exit_code => 1}); } my $internal_vg_uuid = ""; my $host_uuid = ""; my $short_host_name = ""; my $lvm_vg_name = ""; if (($anvil->data->{switches}{add}) or ($anvil->data->{switches}{remove})) { # If both are set, what? if (($anvil->data->{switches}{add}) && ($anvil->data->{switches}{remove})) { print "Both '--add' and '--remove' specified, please use only one at a time.\n"; $anvil->nice_exit({exit_code => 1}); } # These need to be valid VG internal UUID my $member_vg_uuid = $anvil->data->{switches}{member}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { member_vg_uuid => $member_vg_uuid }}); # Find the VG internal UUID. if (not exists $anvil->data->{vgs}{scan_lvm_vg_internal_uuid}{$member_vg_uuid}) { print "The volume group with the internal UUID: [".$member_vg_uuid."] was not found.\n"; print "Call with '--show' to see Anvil! nodes, DR hosts and existing storage groups.\n"; $anvil->nice_exit({exit_code => 1}); } # Now that we have an VG internal UUID, is it a node in the Anvil!, or a DR host? $internal_vg_uuid = $member_vg_uuid; $host_uuid = $anvil->data->{vgs}{scan_lvm_vg_internal_uuid}{$member_vg_uuid}{host_uuid}; my $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}; my $host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name}; $short_host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{short_host_name}; my $host_key = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key}; my $host_anvil_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_name}; my $host_anvil_uuid = $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_uuid}; $lvm_vg_name = $anvil->data->{vgs}{host_uuid}{$host_uuid}{scan_lvm_vg_internal_uuid}{$internal_vg_uuid}{scan_lvm_vg_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { internal_vg_uuid => $internal_vg_uuid, lvm_vg_name => $lvm_vg_name, host_uuid => $host_uuid, host_type => $host_type, short_host_name => $short_host_name, host_key => $host_key, host_anvil_name => $host_anvil_name, host_anvil_uuid => $host_anvil_uuid, }}); if ($host_key eq "DELETED") { print "The volume group: [".$lvm_vg_name."] is on the deleted host: [".$host_name."]\n"; print "Call with '--show' to see Anvil! nodes, DR hosts and existing storage groups.\n"; $anvil->nice_exit({exit_code => 1}); } if ($host_type eq "striker") { print "The volume group: [".$lvm_vg_name."] is on the Striker dashboard: [".$host_name."].\n"; print "There's no point in a Striker being part of a storage group.\n"; print "Call with '--show' to see Anvil! nodes, DR hosts and existing storage groups.\n"; $anvil->nice_exit({exit_code => 1}); } if (($host_type eq "node") && ($anvil_uuid ne $host_anvil_uuid)) { print "The volume group: [".$lvm_vg_name."] is on the sub node: [".$host_name."]. This is part of\n"; print "the Anvil! node: [".$host_anvil_name."], but: [".$anvil_name."] was specified with '--anvil'.\n"; $anvil->nice_exit({exit_code => 1}); } } # Add needs to be the internal UUID if ($anvil->data->{switches}{add}) { # Add the VG, if needed. if (exists $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$host_uuid}) { # If the note is not 'DELETED', we don't need to add it. my $storage_group_member_note = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$host_uuid}{storage_group_member_note}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_member_note => $storage_group_member_note }}); if ($storage_group_member_note ne "DELETED") { # Nothing to do. print "The volume group: [".$lvm_vg_name."] on the host: [".$short_host_name."] is already a member of the storage group: [".$storage_group_name."]. Nothing to do.\n"; $anvil->nice_exit({exit_code => 0}); } } # Still here? Add or update! my $storage_group_member_uuid = $anvil->Database->insert_or_update_storage_group_members({ debug => 2, storage_group_member_storage_group_uuid => $storage_group_uuid, storage_group_member_host_uuid => $host_uuid, storage_group_member_vg_uuid => $internal_vg_uuid, storage_group_member_note => "user-created", }); print "Added the volume group: [".$lvm_vg_name."] on the host: [".$short_host_name."] to the storage group: [".$storage_group_name."]. The new member UUID is: [".$storage_group_member_uuid."].\n"; $anvil->nice_exit({exit_code => 0}); } else { # If there's no existing entry, there's nothing to remove. if (not exists $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$host_uuid}) { # Nothing to do. print "The volume group: [".$lvm_vg_name."] on the host: [".$short_host_name."] has never been a member of the storage group: [".$storage_group_name."]. Nothing to do.\n"; $anvil->nice_exit({exit_code => 0}); } # If the note is not 'DELETED', we don't need to add it. if ($anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$host_uuid}{storage_group_member_note} eq "DELETED") { # Nothing to do. print "The volume group: [".$lvm_vg_name."] on the host: [".$short_host_name."] has already been removed from the storage group: [".$storage_group_name."]. Nothing to do.\n"; $anvil->nice_exit({exit_code => 0}); } # Still here? update! my $storage_group_member_uuid = $anvil->Database->insert_or_update_storage_group_members({ debug => 2, storage_group_member_storage_group_uuid => $storage_group_uuid, storage_group_member_host_uuid => $host_uuid, storage_group_member_vg_uuid => $internal_vg_uuid, storage_group_member_note => "DELETED", }); print "Added the volume group: [".$lvm_vg_name."] on the host: [".$short_host_name."] has been removed from storage group: [".$storage_group_name."].\n"; $anvil->nice_exit({exit_code => 0}); } return(0); } sub show_data { my ($anvil) = @_; my $show_anvil_uuid = $anvil->Database->get_anvil_uuid_from_string({string => $anvil->data->{switches}{anvil}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { show_anvil_uuid => $show_anvil_uuid }}); 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}; 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}; if (($show_anvil_uuid) && ($anvil_uuid ne $show_anvil_uuid)) { next; } print "Anvil Node: [".$anvil_name."] - ".$anvil_description."\n"; foreach my $node_host_uuid ($anvil_node1_host_uuid, $anvil_node2_host_uuid) { my $node_host_name = $anvil->data->{hosts}{host_uuid}{$node_host_uuid}{short_host_name}; print "- Subnode: [".$node_host_name."] volume groups;\n"; foreach my $scan_lvm_vg_name (sort {$a cmp $b} keys %{$anvil->data->{vgs}{host_uuid}{$node_host_uuid}{scan_lvm_vg_name}}) { my $scan_lvm_vg_internal_uuid = $anvil->data->{vgs}{host_uuid}{$node_host_uuid}{scan_lvm_vg_name}{$scan_lvm_vg_name}{scan_lvm_vg_internal_uuid}; my $scan_lvm_vg_size = $anvil->data->{vgs}{host_uuid}{$node_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_size}; my $scan_lvm_vg_free = $anvil->data->{vgs}{host_uuid}{$node_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_free}; my $say_size_hr = $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_size}); my $say_free_hr = $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_free}); print " - [".$scan_lvm_vg_name."], size: [".$say_size_hr."], free: [".$say_free_hr."], internal UUID: [".$scan_lvm_vg_internal_uuid."]\n"; } } foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_name}}) { my $storage_group_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_name}{$storage_group_name}{storage_group_uuid}; print "- Storage group: [".$storage_group_name."], UUID: [".$storage_group_uuid."]\n"; foreach my $member_short_host_name (sort {$a cmp $b} keys %{$anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{short_host_name}}) { my $member_host_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{short_host_name}{$member_short_host_name}{host_uuid}; my $storage_group_member_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$member_host_uuid}{storage_group_member_uuid}; my $vg_internal_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$member_host_uuid}{vg_internal_uuid}; my $vg_name = $anvil->data->{vgs}{host_uuid}{$member_host_uuid}{scan_lvm_vg_internal_uuid}{$vg_internal_uuid}{scan_lvm_vg_name}; print " - [".$member_short_host_name."]:[".$vg_name."]\n"; } } print "\n"; } # Show DR hosts and their VGs print "Disaster Recovery Hosts:\n"; 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 $short_host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{short_host_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid, host_name => $host_name, host_type => $host_type, short_host_name => $short_host_name, }}); next if $host_type ne "dr"; print "- DR Host: [".$short_host_name."] VGs:\n"; foreach my $vg_name (sort {$a cmp $b} keys %{$anvil->data->{vgs}{host_uuid}{$host_uuid}{scan_lvm_vg_name}}) { my $vg_internal_uuid = $anvil->data->{vgs}{host_uuid}{$host_uuid}{scan_lvm_vg_name}{$vg_name}{scan_lvm_vg_internal_uuid}; my $vg_size = $anvil->data->{vgs}{host_uuid}{$host_uuid}{scan_lvm_vg_internal_uuid}{$vg_internal_uuid}{scan_lvm_vg_size}; my $vg_free = $anvil->data->{vgs}{host_uuid}{$host_uuid}{scan_lvm_vg_internal_uuid}{$vg_internal_uuid}{scan_lvm_vg_free}; my $say_size_hr = $anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size}); my $say_free_hr = $anvil->Convert->bytes_to_human_readable({'bytes' => $vg_free}); print " - [".$vg_name."], size: [".$say_size_hr."], free: [".$say_free_hr."], internal UUID: [".$vg_internal_uuid."]\n"; } } print "\n"; return(0); } sub get_vg_data { my ($anvil) = @_; my $query = " SELECT scan_lvm_vg_uuid, scan_lvm_vg_host_uuid, scan_lvm_vg_internal_uuid, scan_lvm_vg_name, scan_lvm_vg_attributes, scan_lvm_vg_extent_size, scan_lvm_vg_size, scan_lvm_vg_free FROM scan_lvm_vgs ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, 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 => 3, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { my $scan_lvm_vg_uuid = $row->[0]; my $scan_lvm_vg_host_uuid = $row->[1]; my $scan_lvm_vg_internal_uuid = $row->[2]; my $scan_lvm_vg_name = $row->[3]; my $scan_lvm_vg_attributes = $row->[4]; my $scan_lvm_vg_extent_size = $row->[5]; my $scan_lvm_vg_size = $row->[6]; my $scan_lvm_vg_free = $row->[7]; my $host_name = $anvil->data->{hosts}{host_uuid}{$scan_lvm_vg_host_uuid}{host_name}; my $host_type = $anvil->data->{hosts}{host_uuid}{$scan_lvm_vg_host_uuid}{host_type}; my $host_key = $anvil->data->{hosts}{host_uuid}{$scan_lvm_vg_host_uuid}{host_key}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { scan_lvm_vg_uuid => $scan_lvm_vg_uuid, scan_lvm_vg_host_uuid => $scan_lvm_vg_host_uuid, scan_lvm_vg_internal_uuid => $scan_lvm_vg_internal_uuid, scan_lvm_vg_name => $scan_lvm_vg_name, scan_lvm_vg_attributes => $scan_lvm_vg_attributes, scan_lvm_vg_extent_size => $scan_lvm_vg_extent_size, scan_lvm_vg_size => $scan_lvm_vg_size, scan_lvm_vg_free => $scan_lvm_vg_free, host_name => $host_name, host_type => $host_type, host_key => $host_type, }}); next if $host_key eq "DELETED"; next if $host_type eq "striker"; $anvil->data->{vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{host_uuid} = $scan_lvm_vg_host_uuid; $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_name}{$scan_lvm_vg_name}{scan_lvm_vg_internal_uuid} = $scan_lvm_vg_internal_uuid; $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_uuid} = $scan_lvm_vg_uuid; $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_name} = $scan_lvm_vg_name; $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_attributes} = $scan_lvm_vg_attributes; $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_extent_size} = $scan_lvm_vg_extent_size; $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_size} = $scan_lvm_vg_size; $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_free} = $scan_lvm_vg_free; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "vgs::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::host_uuid" => $anvil->data->{vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{host_uuid}, "vgs::host_uuid::${scan_lvm_vg_host_uuid}::scan_lvm_vg_name::${scan_lvm_vg_name}::scan_lvm_vg_internal_uuid" => $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_name}{$scan_lvm_vg_name}{scan_lvm_vg_internal_uuid}, "vgs::host_uuid::${scan_lvm_vg_host_uuid}::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_uuid" => $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_uuid}, "vgs::host_uuid::${scan_lvm_vg_host_uuid}::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_name" => $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_name}, "vgs::host_uuid::${scan_lvm_vg_host_uuid}::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_attributes" => $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_attributes}, "vgs::host_uuid::${scan_lvm_vg_host_uuid}::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_extent_size" => $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_extent_size}, "vgs::host_uuid::${scan_lvm_vg_host_uuid}::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_size" => $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_size}, "vgs::host_uuid::${scan_lvm_vg_host_uuid}::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_free" => $anvil->data->{vgs}{host_uuid}{$scan_lvm_vg_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_free}, }}); } } sub get_storage_data { my ($anvil) = @_; if (exists $anvil->data->{duplicate_check}) { delete $anvil->data->{duplicate_check}; } my $query = " SELECT storage_group_uuid, storage_group_anvil_uuid, storage_group_name FROM storage_groups ;"; $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 $storage_group_uuid = $row->[0]; my $storage_group_anvil_uuid = $row->[1]; my $storage_group_name = $row->[2]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_uuid => $storage_group_uuid, storage_group_anvil_uuid => $storage_group_anvil_uuid, storage_group_name => $storage_group_name, }}); # Check for duplicate groups. if (exists $anvil->data->{duplicate_check}{$storage_group_name}) { # Pick one to delete. Does one of the groups have DR and the other doesn't? my $other_storage_group_uuid = $anvil->data->{duplicate_check}{$storage_group_name}{storage_group_uuid}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { other_storage_group_uuid => $other_storage_group_uuid }}); my $this_query = "SELECT COUNT(*) FROM storage_group_members WHERE storage_group_member_storage_group_uuid = ".$anvil->Database->quote($storage_group_uuid).";"; my $other_query = "SELECT COUNT(*) FROM storage_group_members WHERE storage_group_member_storage_group_uuid = ".$anvil->Database->quote($other_storage_group_uuid).";"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { this_query => $this_query, other_query => $other_query, }}); my $this_member_count = $anvil->Database->query({query => $this_query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; my $other_member_count = $anvil->Database->query({query => $other_query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { this_member_count => $this_member_count, other_member_count => $other_member_count, }}); # We'll delete this storage group uuid, UNLESS we've got more members. if ($this_member_count > $other_member_count) { # We have more members, we need to delete the other. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "warning_0158", variables => { group_name => $storage_group_name, keep_uuid => $storage_group_uuid, delete_uuid => $other_storage_group_uuid, }}); my $queries = []; push @{$queries}, "DELETE FROM history.storage_group_members WHERE storage_group_member_storage_group_uuid = ".$anvil->Database->quote($other_storage_group_uuid).";"; push @{$queries}, "DELETE FROM storage_group_members WHERE storage_group_member_storage_group_uuid = ".$anvil->Database->quote($other_storage_group_uuid).";"; push @{$queries}, "DELETE FROM history.storage_groups WHERE storage_group_uuid = ".$anvil->Database->quote($other_storage_group_uuid).";"; push @{$queries}, "DELETE FROM storage_groups WHERE storage_group_uuid = ".$anvil->Database->quote($other_storage_group_uuid).";"; foreach my $query (@{$queries}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, list => { query => $query }}); } $anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); } else { # Delete this one. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, priority => "alert", key => "warning_0158", variables => { group_name => $storage_group_name, keep_uuid => $other_storage_group_uuid, delete_uuid => $storage_group_uuid, }}); my $queries = []; push @{$queries}, "DELETE FROM history.storage_group_members WHERE storage_group_member_storage_group_uuid = ".$anvil->Database->quote($storage_group_uuid).";"; push @{$queries}, "DELETE FROM storage_group_members WHERE storage_group_member_storage_group_uuid = ".$anvil->Database->quote($storage_group_uuid).";"; push @{$queries}, "DELETE FROM history.storage_groups WHERE storage_group_uuid = ".$anvil->Database->quote($storage_group_uuid).";"; push @{$queries}, "DELETE FROM storage_groups WHERE storage_group_uuid = ".$anvil->Database->quote($storage_group_uuid).";"; foreach my $query (@{$queries}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); } $anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); # We don't want to clobber the previously read data, so move on to the next group now. next; } } # Used to check for duplicates. We can't use the real data as it could have been loaded before here. $anvil->data->{duplicate_check}{$storage_group_name}{storage_group_uuid} = $storage_group_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "duplicate_check::${storage_group_name}::storage_group_uuid" => $anvil->data->{duplicate_check}{$storage_group_name}{storage_group_uuid}, }}); # Store the real data $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_name}{$storage_group_name}{storage_group_uuid} = $storage_group_uuid; $anvil->data->{storage_groups}{storage_group_uuid}{$storage_group_uuid}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_name} = $storage_group_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "storage_groups::anvil_uuid::${storage_group_anvil_uuid}::storage_group_name::${storage_group_name}::storage_group_uuid" => $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_name}{$storage_group_name}{storage_group_uuid}, "storage_groups::storage_group_uuid::${storage_group_uuid}::storage_group_anvil_uuid::${storage_group_anvil_uuid}::storage_group_name" => $anvil->data->{storage_groups}{storage_group_uuid}{$storage_group_uuid}{storage_group_anvil_uuid}{$storage_group_anvil_uuid}{storage_group_name}, }}); } delete $anvil->data->{duplicate_check}; return(0); }