#!/usr/bin/perl # # This scans the LVM (logical volume management) components (PV, VG and LV). # # Examples; # # Exit codes; # 0 = Normal exit. # 1 = Startup failure (not running as root, no DB, bad file read, etc) # # NOTE: # - LVM created UUIDs before RFC 4122, so the internal UUIDs are incompatible with modern UUIDs. As such, # they are treated as more of a "serial number" in this agent. # # TODO: # - # use strict; use warnings; use Anvil::Tools; use Data::Dumper; use JSON; # Disable buffering $| = 1; # Prevent a discrepency between UID/GID and EUID/EGID from throwing an error. $< = $>; $( = $); my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; if (($running_directory =~ /^\./) && ($ENV{PWD})) { $running_directory =~ s/^\./$ENV{PWD}/; } my $anvil = Anvil::Tools->new(); # Make sure we're running as 'root' # $< == real UID, $> == effective UID if (($< != 0) && ($> != 0)) { # Not root print $anvil->Words->string({key => "error_0005"})."\n"; $anvil->nice_exit({exit_code => 1}); } # These are the threasholds for when to alert when swap is running out. $anvil->data->{scancore}{'scan-lvm'}{disable} = 0; $anvil->data->{switches}{force} = 0; $anvil->Storage->read_config(); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }}); # Read switches $anvil->Get->switches; # Handle start-up tasks my $problem = $anvil->ScanCore->agent_startup({agent => $THIS_FILE}); if ($problem) { $anvil->nice_exit({exit_code => 1}); } if ($anvil->data->{switches}{purge}) { # This can be called when doing bulk-database purges. my $schema_file = $anvil->data->{path}{directories}{scan_agents}."/".$THIS_FILE."/".$THIS_FILE.".sql"; $anvil->Database->purge_data({ debug => 2, tables => $anvil->Database->get_tables_from_schema({schema_file => $schema_file}), }); $anvil->nice_exit({exit_code => 0}); } # Find the block devices on this host. collect_data($anvil); # Load stored data. read_last_scan($anvil); # Loog for changes find_changes($anvil); # Check storage for storage groups. check_storage_groups($anvil); # Shut down. $anvil->ScanCore->agent_shutdown({agent => $THIS_FILE}); $anvil->nice_exit({exit_code => 0}); ############################################################################################################# # Functions # ############################################################################################################# sub check_storage_groups { my ($anvil) = @_; # Are we in an Anvil!? If so, are there any storage groups yet? my $anvil_uuid = $anvil->Cluster->get_anvil_uuid(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); if ($anvil_uuid) { # If we're node 1, we'll try to assemble the storage group. Onle node 1 does this to help avoid race # conditions. This both loads storage group data and assembles ungrouped VGs into storage groups, # when possible. $anvil->Database->get_anvils(); my $host_uuid = $anvil->Get->host_uuid; my $anvil_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name}; my $node1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 's1:anvil_name' => $anvil_name, 's2:node1_host_uuid' => $node1_host_uuid, 's3:node2_host_uuid' => $node2_host_uuid, 's4:host_uuid' => $host_uuid, }}); if ($host_uuid eq $node1_host_uuid) { # Are there any storage groups yet? If not, try to assemble one. my $query = "SELECT COUNT(*) FROM storage_groups WHERE storage_group_anvil_uuid = ".$anvil->Database->quote($anvil_uuid).";"; $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]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); if (not $count) { $anvil->Cluster->assemble_storage_groups({ debug => 2, anvil_uuid => $anvil_uuid, }); } } } return(0); } sub find_changes { my ($anvil) = @_; # Changes in PVs? find_changes_in_pvs($anvil); # Changes in VGs? find_changes_in_vgs($anvil); # Changes in LVs? find_changes_in_lvs($anvil); return(0); } sub find_changes_in_lvs { my ($anvil) = @_; foreach my $scan_lvm_lv_internal_uuid (keys %{$anvil->data->{lvm}{scan_lvm_lv_internal_uuid}}) { my $scan_lvm_lv_name = $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{name}; my $scan_lvm_lv_attributes = $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{attributes}; my $scan_lvm_lv_on_vg = $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{on_vg}; my $scan_lvm_lv_size = $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{size}; my $scan_lvm_lv_path = $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{device_path}; my $scan_lvm_lv_on_pvs = $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{on_pvs}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_lvm_lv_internal_uuid => $scan_lvm_lv_internal_uuid, scan_lvm_lv_name => $scan_lvm_lv_name, scan_lvm_lv_attributes => $scan_lvm_lv_attributes, scan_lvm_lv_on_vg => $scan_lvm_lv_on_vg, scan_lvm_lv_size => $anvil->Convert->add_commas({number => $scan_lvm_lv_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_lv_size}), scan_lvm_lv_path => $scan_lvm_lv_path, scan_lvm_lv_on_pvs => $scan_lvm_lv_on_pvs, }}); # Have we seen this before? if (exists $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}) { # Yup, anything changed? my $scan_lvm_lv_uuid = $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_uuid}; my $old_scan_lvm_lv_name = $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_name}; my $old_scan_lvm_lv_attributes = $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_attributes}; my $old_scan_lvm_lv_on_vg = $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_on_vg}; my $old_scan_lvm_lv_size = $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_size}; my $old_scan_lvm_lv_path = $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_path}; my $old_scan_lvm_lv_on_pvs = $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_on_pvs}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_lvm_lv_uuid => $scan_lvm_lv_uuid, old_scan_lvm_lv_name => $old_scan_lvm_lv_name, old_scan_lvm_lv_attributes => $old_scan_lvm_lv_attributes, old_scan_lvm_lv_on_vg => $old_scan_lvm_lv_on_vg, old_scan_lvm_lv_size => $anvil->Convert->add_commas({number => $old_scan_lvm_lv_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_lv_size}), old_scan_lvm_lv_path => $old_scan_lvm_lv_path, old_scan_lvm_lv_on_pvs => $old_scan_lvm_lv_on_pvs, }}); my $update = 0; if ($scan_lvm_lv_name ne $old_scan_lvm_lv_name) { $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); if ($old_scan_lvm_lv_name eq "DELETED") { # A lost LV is back my $variables = { lv_uuid => $scan_lvm_lv_internal_uuid, lv_name => $scan_lvm_lv_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0021", variables => $variables}); $anvil->Alert->register({clear_alert => 1, alert_level => "warning", message => "scan_lvm_alert_0021", variables => $variables, set_by => $THIS_FILE}); } else { # LV name changed. my $variables = { lv_uuid => $scan_lvm_lv_internal_uuid, new_lv_name => $scan_lvm_lv_name, old_lv_name => $old_scan_lvm_lv_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0022", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0022", variables => $variables, set_by => $THIS_FILE}); } } if ($scan_lvm_lv_attributes ne $old_scan_lvm_lv_attributes) { # Attribute bits changed. $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { lv_uuid => $scan_lvm_lv_internal_uuid, lv_name => $scan_lvm_lv_name, new_attributes => $scan_lvm_lv_attributes, old_attributes => $old_scan_lvm_lv_attributes, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0023", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0023", variables => $variables, set_by => $THIS_FILE}); } if ($scan_lvm_lv_on_vg ne $old_scan_lvm_lv_on_vg) { # This happens when an VG is renamed. $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { lv_uuid => $scan_lvm_lv_internal_uuid, lv_name => $scan_lvm_lv_name, new_lv_on_vg => $scan_lvm_lv_on_vg, old_lv_on_vg => $old_scan_lvm_lv_on_vg, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0024", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_lvm_alert_0024", variables => $variables, set_by => $THIS_FILE}); } if ($scan_lvm_lv_size ne $old_scan_lvm_lv_size) { # VG size change; Did it grow or shrink? $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { lv_uuid => $scan_lvm_lv_internal_uuid, lv_name => $scan_lvm_lv_name, new_lv_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_lv_size}), new_lv_size_bytes => $anvil->Convert->add_commas({number => $scan_lvm_lv_size}), old_lv_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_lv_size}), old_lv_size_bytes => $anvil->Convert->add_commas({number => $old_scan_lvm_lv_size}), }; if ($scan_lvm_lv_size > $old_scan_lvm_lv_size) { # Grew, probably added a new PV $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0025", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0025", variables => $variables, set_by => $THIS_FILE}); } else { # Shrank, $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0026", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0026", variables => $variables, set_by => $THIS_FILE}); } } if ($scan_lvm_lv_path ne $old_scan_lvm_lv_path) { # VG size changed, Grows when an LV is removed, shrings when an existing LV is extended or a new LV is created. $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { lv_uuid => $scan_lvm_lv_internal_uuid, lv_name => $scan_lvm_lv_name, new_lv_path => $scan_lvm_lv_path, old_lv_path => $old_scan_lvm_lv_path, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0027", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0027", variables => $variables, set_by => $THIS_FILE}); } if ($scan_lvm_lv_on_pvs ne $old_scan_lvm_lv_on_pvs) { $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { lv_uuid => $scan_lvm_lv_internal_uuid, lv_name => $scan_lvm_lv_name, new_lv_on_pvs => $scan_lvm_lv_path, old_lv_on_pvs => $old_scan_lvm_lv_path, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0028", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0028", variables => $variables, set_by => $THIS_FILE}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); if ($update) { my $query = " UPDATE scan_lvm_lvs SET scan_lvm_lv_name = ".$anvil->Database->quote($scan_lvm_lv_name).", scan_lvm_lv_attributes = ".$anvil->Database->quote($scan_lvm_lv_attributes).", scan_lvm_lv_on_vg = ".$anvil->Database->quote($scan_lvm_lv_on_vg).", scan_lvm_lv_size = ".$anvil->Database->quote($scan_lvm_lv_size).", scan_lvm_lv_path = ".$anvil->Database->quote($scan_lvm_lv_path).", scan_lvm_lv_on_pvs = ".$anvil->Database->quote($scan_lvm_lv_on_pvs).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_lvm_lv_uuid = ".$anvil->Database->quote($scan_lvm_lv_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } # Delete the loaded entry so we can check for missing PVs later. delete $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}; } else { # New VG my $variables = { lv_uuid => $scan_lvm_lv_internal_uuid, lv_name => $scan_lvm_lv_name, attributes => $scan_lvm_lv_attributes, lv_on_vg => $scan_lvm_lv_on_vg, lv_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_lv_size}), lv_size_bytes => $anvil->Convert->add_commas({number => $scan_lvm_lv_size}), lv_path => $scan_lvm_lv_path, lv_on_pvs => $scan_lvm_lv_on_pvs, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0029", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0029", variables => $variables, set_by => $THIS_FILE}); my $scan_lvm_lv_uuid = $anvil->Get->uuid(); my $query = " INSERT INTO scan_lvm_lvs ( scan_lvm_lv_uuid, scan_lvm_lv_internal_uuid, scan_lvm_lv_host_uuid, scan_lvm_lv_name, scan_lvm_lv_on_vg, scan_lvm_lv_attributes, scan_lvm_lv_size, scan_lvm_lv_path, scan_lvm_lv_on_pvs, modified_date ) VALUES ( ".$anvil->Database->quote($scan_lvm_lv_uuid).", ".$anvil->Database->quote($scan_lvm_lv_internal_uuid).", ".$anvil->Database->quote($anvil->Get->host_uuid).", ".$anvil->Database->quote($scan_lvm_lv_name).", ".$anvil->Database->quote($scan_lvm_lv_on_vg).", ".$anvil->Database->quote($scan_lvm_lv_attributes).", ".$anvil->Database->quote($scan_lvm_lv_size).", ".$anvil->Database->quote($scan_lvm_lv_path).", ".$anvil->Database->quote($scan_lvm_lv_on_pvs).", ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." );"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } } # Any missing LVs? foreach my $scan_lvm_lv_internal_uuid (keys %{$anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}}) { # This one is missing. my $scan_lvm_lv_uuid = $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_uuid}; my $old_scan_lvm_lv_name = $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_lvm_lv_uuid => $scan_lvm_lv_uuid, old_scan_lvm_lv_name => $old_scan_lvm_lv_name, }}); next if $old_scan_lvm_lv_name eq "DELETED"; # Register an alert my $variables = { lv_uuid => $scan_lvm_lv_internal_uuid, lv_name => $old_scan_lvm_lv_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0031", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_lvm_alert_0031", variables => $variables, set_by => $THIS_FILE}); # Update it PV name to be 'DELTED' my $query = " UPDATE scan_lvm_lvs SET scan_lvm_lv_name = 'DELETED', modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_lvm_lv_uuid = ".$anvil->Database->quote($scan_lvm_lv_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } return(0); } sub find_changes_in_vgs { my ($anvil) = @_; foreach my $scan_lvm_vg_internal_uuid (keys %{$anvil->data->{lvm}{scan_lvm_vg_internal_uuid}}) { my $scan_lvm_vg_name = $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{name}; my $scan_lvm_vg_attributes = $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{attributes}; my $scan_lvm_vg_extent_size = $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{extent_size}; my $scan_lvm_vg_size = $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{size}; my $scan_lvm_vg_free = $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{free_space}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 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 => $anvil->Convert->add_commas({number => $scan_lvm_vg_extent_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_extent_size}), scan_lvm_vg_size => $anvil->Convert->add_commas({number => $scan_lvm_vg_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_size}), scan_lvm_vg_free => $anvil->Convert->add_commas({number => $scan_lvm_vg_free})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_free}), }}); # Have we seen this before? if (exists $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}) { # Yup, anything changed? my $scan_lvm_vg_uuid = $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_uuid}; my $old_scan_lvm_vg_name = $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_name}; my $old_scan_lvm_vg_attributes = $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_attributes}; my $old_scan_lvm_vg_extent_size = $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_extent_size}; my $old_scan_lvm_vg_size = $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_size}; my $old_scan_lvm_vg_free = $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_free}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_lvm_vg_uuid => $scan_lvm_vg_uuid, old_scan_lvm_vg_name => $old_scan_lvm_vg_name, old_scan_lvm_vg_attributes => $old_scan_lvm_vg_attributes, old_scan_lvm_vg_extent_size => $anvil->Convert->add_commas({number => $old_scan_lvm_vg_extent_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_vg_extent_size}),, old_scan_lvm_vg_size => $anvil->Convert->add_commas({number => $old_scan_lvm_vg_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_vg_size}), old_scan_lvm_vg_free => $anvil->Convert->add_commas({number => $old_scan_lvm_vg_free})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_vg_free}), }}); my $update = 0; if ($scan_lvm_vg_name ne $old_scan_lvm_vg_name) { $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); if ($old_scan_lvm_vg_name eq "DELETED") { # A lost PV is back my $variables = { vg_uuid => $scan_lvm_vg_internal_uuid, vg_name => $scan_lvm_vg_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0011", variables => $variables}); $anvil->Alert->register({clear_alert => 1, alert_level => "warning", message => "scan_lvm_alert_0011", variables => $variables, set_by => $THIS_FILE}); } else { # Device (name) changed... This can happen if the vg was renamed my $variables = { vg_uuid => $scan_lvm_vg_internal_uuid, new_vg_name => $scan_lvm_vg_name, old_vg_name => $old_scan_lvm_vg_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0012", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0012", variables => $variables, set_by => $THIS_FILE}); } } if ($scan_lvm_vg_attributes ne $old_scan_lvm_vg_attributes) { # Attribute bits changed. $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { vg_uuid => $scan_lvm_vg_internal_uuid, vg_name => $scan_lvm_vg_name, new_attributes => $scan_lvm_vg_attributes, old_attributes => $old_scan_lvm_vg_attributes, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0013", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0013", variables => $variables, set_by => $THIS_FILE}); } if ($scan_lvm_vg_extent_size ne $old_scan_lvm_vg_extent_size) { # This should never happen... $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { vg_uuid => $scan_lvm_vg_internal_uuid, vg_name => $scan_lvm_vg_name, new_vg_extent_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_extent_size}), new_vg_extent_size_bytes => $anvil->Convert->add_commas({number => $scan_lvm_vg_extent_size}), old_vg_extent_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_vg_extent_size}), old_vg_extent_size_bytes => $anvil->Convert->add_commas({number => $old_scan_lvm_vg_extent_size}), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0014", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_lvm_alert_0014", variables => $variables, set_by => $THIS_FILE}); } if ($scan_lvm_vg_size ne $old_scan_lvm_vg_size) { # VG size change; Did it grow or shrink? $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { vg_uuid => $scan_lvm_vg_internal_uuid, vg_name => $scan_lvm_vg_name, new_vg_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_size}), new_vg_size_bytes => $anvil->Convert->add_commas({number => $scan_lvm_vg_size}), old_vg_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_vg_size}), old_vg_size_bytes => $anvil->Convert->add_commas({number => $old_scan_lvm_vg_size}), }; if ($scan_lvm_vg_size > $old_scan_lvm_vg_size) { # Grew, probably added a new PV $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0015", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0015", variables => $variables, set_by => $THIS_FILE}); } else { # Shrank, wat? $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0016", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_lvm_alert_0016", variables => $variables, set_by => $THIS_FILE}); } } if ($scan_lvm_vg_free ne $old_scan_lvm_vg_free) { # VG size changed, Grows when an LV is removed, shrings when an existing LV is extended or a new LV is created. $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { vg_uuid => $scan_lvm_vg_internal_uuid, vg_name => $scan_lvm_vg_name, new_vg_free => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_free}), new_vg_free_bytes => $anvil->Convert->add_commas({number => $scan_lvm_vg_free}), old_vg_free => $anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_vg_free}), old_vg_free_bytes => $anvil->Convert->add_commas({number => $old_scan_lvm_vg_free}), }; if ($scan_lvm_vg_free < $old_scan_lvm_vg_free) { # Likely a new LV was created or an existing one was extended. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0017", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0017", variables => $variables, set_by => $THIS_FILE}); } else { # An old LV was probably removed. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0018", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0018", variables => $variables, set_by => $THIS_FILE}); } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); if ($update) { my $query = " UPDATE scan_lvm_vgs SET scan_lvm_vg_name = ".$anvil->Database->quote($scan_lvm_vg_name).", scan_lvm_vg_attributes = ".$anvil->Database->quote($scan_lvm_vg_attributes).", scan_lvm_vg_extent_size = ".$anvil->Database->quote($scan_lvm_vg_extent_size).", scan_lvm_vg_size = ".$anvil->Database->quote($scan_lvm_vg_size).", scan_lvm_vg_free = ".$anvil->Database->quote($scan_lvm_vg_free).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_lvm_vg_uuid = ".$anvil->Database->quote($scan_lvm_vg_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } # Delete the loaded entry so we can check for missing PVs later. delete $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}; } else { # New VG my $variables = { vg_uuid => $scan_lvm_vg_internal_uuid, vg_name => $scan_lvm_vg_name, attributes => $scan_lvm_vg_attributes, extent_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_extent_size}), extent_size_bytes => $anvil->Convert->add_commas({number => $scan_lvm_vg_extent_size}), vg_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_size}), vg_size_bytes => $anvil->Convert->add_commas({number => $scan_lvm_vg_size}), vg_free => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_free}), vg_free_bytes => $anvil->Convert->add_commas({number => $scan_lvm_vg_free}), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0020", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0020", variables => $variables, set_by => $THIS_FILE}); my $scan_lvm_vg_uuid = $anvil->Get->uuid(); my $query = " INSERT INTO scan_lvm_vgs ( scan_lvm_vg_uuid, scan_lvm_vg_internal_uuid, scan_lvm_vg_host_uuid, scan_lvm_vg_name, scan_lvm_vg_extent_size, scan_lvm_vg_attributes, scan_lvm_vg_size, scan_lvm_vg_free, modified_date ) VALUES ( ".$anvil->Database->quote($scan_lvm_vg_uuid).", ".$anvil->Database->quote($scan_lvm_vg_internal_uuid).", ".$anvil->Database->quote($anvil->Get->host_uuid).", ".$anvil->Database->quote($scan_lvm_vg_name).", ".$anvil->Database->quote($scan_lvm_vg_extent_size).", ".$anvil->Database->quote($scan_lvm_vg_attributes).", ".$anvil->Database->quote($scan_lvm_vg_size).", ".$anvil->Database->quote($scan_lvm_vg_free).", ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." );"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } } # Any missing VGs? foreach my $scan_lvm_vg_internal_uuid (keys %{$anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}}) { # This one is missing. my $scan_lvm_vg_uuid = $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_uuid}; my $old_scan_lvm_vg_name = $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_lvm_vg_uuid => $scan_lvm_vg_uuid, old_scan_lvm_vg_name => $old_scan_lvm_vg_name, }}); next if $old_scan_lvm_vg_name eq "DELETED"; # Register an alert my $variables = { vg_uuid => $scan_lvm_vg_internal_uuid, vg_name => $old_scan_lvm_vg_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0030", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_lvm_alert_0030", variables => $variables, set_by => $THIS_FILE}); # Update it PV name to be 'DELTED' my $query = " UPDATE scan_lvm_vgs SET scan_lvm_vg_name = 'DELETED', modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_lvm_vg_uuid = ".$anvil->Database->quote($scan_lvm_vg_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } return(0); } sub find_changes_in_pvs { my ($anvil) = @_; foreach my $scan_lvm_pv_internal_uuid (keys %{$anvil->data->{lvm}{scan_lvm_pv_internal_uuid}}) { my $scan_lvm_pv_name = $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{name}; my $scan_lvm_pv_used_by_vg = $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{used_by_vg}; my $scan_lvm_pv_attributes = $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{attributes}; my $scan_lvm_pv_size = $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{size}; my $scan_lvm_pv_free = $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{free_space}; my $scan_lvm_pv_sector_size = $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{sector_size}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_lvm_pv_internal_uuid => $scan_lvm_pv_internal_uuid, scan_lvm_pv_name => $scan_lvm_pv_name, scan_lvm_pv_used_by_vg => $scan_lvm_pv_used_by_vg, scan_lvm_pv_attributes => $scan_lvm_pv_attributes, scan_lvm_pv_size => $anvil->Convert->add_commas({number => $scan_lvm_pv_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_pv_size}), scan_lvm_pv_free => $anvil->Convert->add_commas({number => $scan_lvm_pv_free})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_pv_free}), scan_lvm_pv_sector_size => $anvil->Convert->add_commas({number => $scan_lvm_pv_sector_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_pv_sector_size}), }}); # Have we seen this before? if (exists $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}) { # Yup, anything changed? my $scan_lvm_pv_uuid = $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_uuid}; my $old_scan_lvm_pv_name = $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_name}; my $old_scan_lvm_pv_used_by_vg = $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_used_by_vg}; my $old_scan_lvm_pv_attributes = $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_attributes}; my $old_scan_lvm_pv_size = $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_size}; my $old_scan_lvm_pv_free = $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_free}; my $old_scan_lvm_pv_sector_size = $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_sector_size}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_scan_lvm_pv_name => $old_scan_lvm_pv_name, old_scan_lvm_pv_used_by_vg => $old_scan_lvm_pv_used_by_vg, old_scan_lvm_pv_attributes => $old_scan_lvm_pv_attributes, old_scan_lvm_pv_size => $anvil->Convert->add_commas({number => $old_scan_lvm_pv_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_pv_size}), old_scan_lvm_pv_free => $anvil->Convert->add_commas({number => $old_scan_lvm_pv_free})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_pv_free}), old_scan_lvm_pv_sector_size => $anvil->Convert->add_commas({number => $old_scan_lvm_pv_sector_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_pv_sector_size}), }}); my $update = 0; if ($scan_lvm_pv_name ne $old_scan_lvm_pv_name) { $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); if ($old_scan_lvm_pv_name eq "DELETED") { # A lost PV is back my $variables = { pv_uuid => $scan_lvm_pv_internal_uuid, pv_name => $scan_lvm_pv_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0001", variables => $variables}); $anvil->Alert->register({clear_alert => 1, alert_level => "warning", message => "scan_lvm_alert_0001", variables => $variables, set_by => $THIS_FILE}); } else { # Device (name) changed... This shouldn't normally happen. my $variables = { pv_uuid => $scan_lvm_pv_internal_uuid, new_pv_name => $scan_lvm_pv_name, old_pv_name => $old_scan_lvm_pv_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0002", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_lvm_alert_0002", variables => $variables, set_by => $THIS_FILE}); } } if ($scan_lvm_pv_used_by_vg ne $old_scan_lvm_pv_used_by_vg) { # If the old value was blank, then this PV was added to a VG and that's fine. $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); if (not $old_scan_lvm_pv_used_by_vg) { # Added to a VG my $variables = { pv_uuid => $scan_lvm_pv_internal_uuid, pv_name => $scan_lvm_pv_name, vg_name => $scan_lvm_pv_used_by_vg, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0004", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0004", variables => $variables, set_by => $THIS_FILE}); } else { # The VG was probably renamed. my $variables = { pv_uuid => $scan_lvm_pv_internal_uuid, pv_name => $scan_lvm_pv_name, new_vg_name => $scan_lvm_pv_used_by_vg, old_vg_name => $old_scan_lvm_pv_used_by_vg, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0005", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0005", variables => $variables, set_by => $THIS_FILE}); } } if ($scan_lvm_pv_attributes ne $old_scan_lvm_pv_attributes) { # Attribute bits changed. $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { pv_uuid => $scan_lvm_pv_internal_uuid, pv_name => $scan_lvm_pv_name, new_attributes => $scan_lvm_pv_attributes, old_attributes => $old_scan_lvm_pv_attributes, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0006", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0006", variables => $variables, set_by => $THIS_FILE}); } if ($scan_lvm_pv_size ne $old_scan_lvm_pv_size) { # PE size changed, likely grew. $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { pv_uuid => $scan_lvm_pv_internal_uuid, pv_name => $scan_lvm_pv_name, new_pv_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_pv_size}), new_pv_size_bytes => $anvil->Convert->add_commas({number => $scan_lvm_pv_size}), old_pv_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_pv_size}), old_pv_size_bytes => $anvil->Convert->add_commas({number => $old_scan_lvm_pv_size}), }; if ($scan_lvm_pv_size > $old_scan_lvm_pv_size) { # Yup $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0007", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0007", variables => $variables, set_by => $THIS_FILE}); } else { # Uhhhh... We'll make this a warning as it shouldn't happen. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0008", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_lvm_alert_0008", variables => $variables, set_by => $THIS_FILE}); } } if ($scan_lvm_pv_free ne $old_scan_lvm_pv_free) { # PE size changed, likely shrunk. $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { pv_uuid => $scan_lvm_pv_internal_uuid, pv_name => $scan_lvm_pv_name, new_pv_free => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_pv_free}), new_pv_free_bytes => $anvil->Convert->add_commas({number => $scan_lvm_pv_free}), old_pv_free => $anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_pv_free}), old_pv_free_bytes => $anvil->Convert->add_commas({number => $old_scan_lvm_pv_free}), }; if ($scan_lvm_pv_free < $old_scan_lvm_pv_free) { # Yup $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0009", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0009", variables => $variables, set_by => $THIS_FILE}); } else { # Uhhhh... We'll make this a warning as it shouldn't happen. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0010", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_lvm_alert_0010", variables => $variables, set_by => $THIS_FILE}); } } if ($scan_lvm_pv_sector_size ne $old_scan_lvm_pv_sector_size) { # This is always a warning as the sector size should never change. $update = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); my $variables = { pv_uuid => $scan_lvm_pv_internal_uuid, pv_name => $scan_lvm_pv_name, new_pv_sector_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_pv_sector_size}), new_pv_sector_size_bytes => $anvil->Convert->add_commas({number => $scan_lvm_pv_sector_size}), old_pv_sector_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $old_scan_lvm_pv_sector_size}), old_pv_sector_size_bytes => $anvil->Convert->add_commas({number => $old_scan_lvm_pv_sector_size}), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0032", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_lvm_alert_0032", variables => $variables, set_by => $THIS_FILE}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); if ($update) { my $query = " UPDATE scan_lvm_pvs SET scan_lvm_pv_name = ".$anvil->Database->quote($scan_lvm_pv_name).", scan_lvm_pv_used_by_vg = ".$anvil->Database->quote($scan_lvm_pv_used_by_vg).", scan_lvm_pv_attributes = ".$anvil->Database->quote($scan_lvm_pv_attributes).", scan_lvm_pv_size = ".$anvil->Database->quote($scan_lvm_pv_size).", scan_lvm_pv_free = ".$anvil->Database->quote($scan_lvm_pv_free).", scan_lvm_pv_sector_size = ".$anvil->Database->quote($scan_lvm_pv_sector_size).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_lvm_pv_uuid = ".$anvil->Database->quote($scan_lvm_pv_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } # Delete the loaded entry so we can check for missing PVs later. delete $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}; } else { # New PV my $variables = { pv_uuid => $scan_lvm_pv_internal_uuid, pv_name => $scan_lvm_pv_name, vg_name => $scan_lvm_pv_used_by_vg ? $scan_lvm_pv_used_by_vg : "--", attributes => $scan_lvm_pv_attributes, pv_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_pv_size}), pv_size_bytes => $anvil->Convert->add_commas({number => $scan_lvm_pv_size}), pv_free => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_pv_free}), pv_free_bytes => $anvil->Convert->add_commas({number => $scan_lvm_pv_free}), pv_sector_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_pv_sector_size}), pv_sector_size_bytes => $anvil->Convert->add_commas({number => $scan_lvm_pv_sector_size}), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0019", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0019", variables => $variables, set_by => $THIS_FILE}); my $scan_lvm_pv_uuid = $anvil->Get->uuid(); my $query = " INSERT INTO scan_lvm_pvs ( scan_lvm_pv_uuid, scan_lvm_pv_internal_uuid, scan_lvm_pv_host_uuid, scan_lvm_pv_name, scan_lvm_pv_used_by_vg, scan_lvm_pv_attributes, scan_lvm_pv_size, scan_lvm_pv_free, scan_lvm_pv_sector_size, modified_date ) VALUES ( ".$anvil->Database->quote($scan_lvm_pv_uuid).", ".$anvil->Database->quote($scan_lvm_pv_internal_uuid).", ".$anvil->Database->quote($anvil->Get->host_uuid).", ".$anvil->Database->quote($scan_lvm_pv_name).", ".$anvil->Database->quote($scan_lvm_pv_used_by_vg).", ".$anvil->Database->quote($scan_lvm_pv_attributes).", ".$anvil->Database->quote($scan_lvm_pv_size).", ".$anvil->Database->quote($scan_lvm_pv_free).", ".$anvil->Database->quote($scan_lvm_pv_sector_size).", ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." );"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } } # Any missing PVs? foreach my $scan_lvm_pv_internal_uuid (keys %{$anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}}) { # This one is missing. my $scan_lvm_pv_uuid = $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_uuid}; my $old_scan_lvm_pv_name = $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 's1:scan_lvm_pv_internal_uuid' => $scan_lvm_pv_internal_uuid, 's2:scan_lvm_pv_uuid' => $scan_lvm_pv_uuid, 's3:old_scan_lvm_pv_name' => $old_scan_lvm_pv_name, }}); next if $old_scan_lvm_pv_name eq "DELETED"; # Register an alert my $variables = { pv_uuid => $scan_lvm_pv_internal_uuid, pv_name => $old_scan_lvm_pv_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0003", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_lvm_alert_0003", variables => $variables, set_by => $THIS_FILE}); # Update it PV name to be 'DELTED' my $query = " UPDATE scan_lvm_pvs SET scan_lvm_pv_name = 'DELETED', modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_lvm_pv_uuid = ".$anvil->Database->quote($scan_lvm_pv_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } return(0); } # This reads in the last scan's data. sub read_last_scan { my ($anvil) = @_; # Load PV data my $query = " SELECT scan_lvm_pv_uuid, scan_lvm_pv_internal_uuid, scan_lvm_pv_name, scan_lvm_pv_used_by_vg, scan_lvm_pv_attributes, scan_lvm_pv_size, scan_lvm_pv_free, scan_lvm_pv_sector_size FROM scan_lvm_pvs WHERE scan_lvm_pv_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." ;"; $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 => 2, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { # We've got an entry in the 'scan_lvm_pv' table, so now we'll look for data in the node and # services tables. my $scan_lvm_pv_uuid = $row->[0]; my $scan_lvm_pv_internal_uuid = $row->[1]; my $scan_lvm_pv_name = $row->[2]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_lvm_pv_uuid => $scan_lvm_pv_uuid, scan_lvm_pv_internal_uuid => $scan_lvm_pv_internal_uuid, scan_lvm_pv_name => $scan_lvm_pv_name, }}); # If there's an existing entry, delete this one, it's somehow a duplicate. if (exists $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}) { # Duplicate! my $variables = { pv_name => $scan_lvm_pv_name, pv_uuid => $scan_lvm_pv_uuid, internal_uuid => $scan_lvm_pv_internal_uuid, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0033", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0033", variables => $variables, set_by => $THIS_FILE}); my $query = "DELETE FROM scan_lvm_pvs WHERE scan_lvm_pv_uuid = ".$anvil->Database->quote($scan_lvm_pv_uuid).";\n"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); next; } # Save $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_uuid} = $scan_lvm_pv_uuid; $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_name} = $scan_lvm_pv_name; $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_used_by_vg} = $row->[3]; $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_attributes} = $row->[4]; $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_size} = $row->[5]; $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_free} = $row->[6]; $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_sector_size} = $row->[7]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_lvm_pvs::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::scan_lvm_pv_uuid" => $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_uuid}, "sql::scan_lvm_pvs::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::scan_lvm_pv_name" => $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_name}, "sql::scan_lvm_pvs::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::scan_lvm_pv_used_by_vg" => $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_used_by_vg}, "sql::scan_lvm_pvs::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::scan_lvm_pv_attributes" => $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_attributes}, "sql::scan_lvm_pvs::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::scan_lvm_pv_size" => $anvil->Convert->add_commas({number => $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_size}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_size}}), "sql::scan_lvm_pvs::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::scan_lvm_pv_free" => $anvil->Convert->add_commas({number => $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_free}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_free}}), "sql::scan_lvm_pvs::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::scan_lvm_pv_sector_size" => $anvil->Convert->add_commas({number => $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_sector_size}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{sql}{scan_lvm_pvs}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{scan_lvm_pv_sector_size}}), }}); } undef $count; undef $results; # Load VG data $query = " SELECT scan_lvm_vg_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 WHERE scan_lvm_vg_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }}); $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { # We've got an entry in the 'scan_lvm_vg' table, so now we'll look for data in the node and # services tables. my $scan_lvm_vg_uuid = $row->[0]; my $scan_lvm_vg_internal_uuid = $row->[1]; my $scan_lvm_vg_name = $row->[2]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_lvm_vg_uuid => $scan_lvm_vg_uuid, scan_lvm_vg_internal_uuid => $scan_lvm_vg_internal_uuid, scan_lvm_vg_name => $scan_lvm_vg_name, }}); # If there's an existing entry, delete this one, it's somehow a duplicate. if (exists $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}) { # Duplicate! my $variables = { vg_name => $scan_lvm_vg_name, vg_uuid => $scan_lvm_vg_uuid, internal_uuid => $scan_lvm_vg_internal_uuid, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0034", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0034", variables => $variables, set_by => $THIS_FILE}); my $query = "DELETE FROM scan_lvm_vgs WHERE scan_lvm_vg_uuid = ".$anvil->Database->quote($scan_lvm_vg_uuid).";\n"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); next; } # Save $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_uuid} = $scan_lvm_vg_uuid; $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_name} = $scan_lvm_vg_name; $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_attributes} = $row->[3]; $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_extent_size} = $row->[4]; $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_size} = $row->[5]; $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_free} = $row->[6]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_lvm_vgs::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_uuid" => $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_uuid}, "sql::scan_lvm_vgs::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_name" => $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_name}, "sql::scan_lvm_vgs::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_attributes" => $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_attributes}, "sql::scan_lvm_vgs::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_extent_size" => $anvil->Convert->add_commas({number => $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_extent_size}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_extent_size}}), "sql::scan_lvm_vgs::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_size" => $anvil->Convert->add_commas({number => $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_size}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_size}}), "sql::scan_lvm_vgs::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::scan_lvm_vg_free" => $anvil->Convert->add_commas({number => $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_free}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{sql}{scan_lvm_vgs}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_free}}), }}); } undef $count; undef $results; # Load LV data $query = " SELECT scan_lvm_lv_uuid, scan_lvm_lv_internal_uuid, scan_lvm_lv_name, scan_lvm_lv_attributes, scan_lvm_lv_on_vg, scan_lvm_lv_size, scan_lvm_lv_path, scan_lvm_lv_on_pvs FROM scan_lvm_lvs WHERE scan_lvm_lv_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }}); $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { # We've got an entry in the 'scan_lvm_lv' table, so now we'll look for data in the node and # services tables. my $scan_lvm_lv_uuid = $row->[0]; my $scan_lvm_lv_internal_uuid = $row->[1]; my $scan_lvm_lv_name = $row->[2]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_lvm_lv_uuid => $scan_lvm_lv_uuid, scan_lvm_lv_internal_uuid => $scan_lvm_lv_internal_uuid, scan_lvm_lv_name => $scan_lvm_lv_name, }}); # If there's an existing entry, delete this one, it's somehow a duplicate. if (exists $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}) { # Duplicate! Is one of them DELETED? my $existing_name = $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_name}; my $existing_uuid = $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_uuid}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { existing_name => $existing_name, existing_uuid => $existing_uuid, }}); if ($anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_name} eq "DELETED") { # Delete the one we already read. my $variables = { lv_name => $existing_name, lv_uuid => $existing_uuid, internal_uuid => $scan_lvm_lv_internal_uuid, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0035", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0034", variables => $variables, set_by => $THIS_FILE}); my $query = "DELETE FROM scan_lvm_lvs WHERE scan_lvm_lv_uuid = ".$anvil->Database->quote($existing_uuid).";\n"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); delete $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}; } else { # Delete the new one my $variables = { lv_name => $scan_lvm_lv_name, lv_uuid => $scan_lvm_lv_uuid, internal_uuid => $scan_lvm_lv_internal_uuid, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_alert_0035", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_lvm_alert_0034", variables => $variables, set_by => $THIS_FILE}); my $query = "DELETE FROM scan_lvm_lvs WHERE scan_lvm_lv_uuid = ".$anvil->Database->quote($scan_lvm_lv_uuid).";\n"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); next; } } # Save $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_uuid} = $scan_lvm_lv_uuid; $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_name} = $scan_lvm_lv_name; $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_attributes} = $row->[3]; $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_on_vg} = $row->[4]; $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_size} = $row->[5]; $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_path} = $row->[6]; $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_on_pvs} = $row->[7]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_lvm_lvs::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::scan_lvm_lv_uuid" => $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_uuid}, "sql::scan_lvm_lvs::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::scan_lvm_lv_name" => $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_name}, "sql::scan_lvm_lvs::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::scan_lvm_lv_attributes" => $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_attributes}, "sql::scan_lvm_lvs::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::scan_lvm_lv_on_vg" => $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_on_vg}, "sql::scan_lvm_lvs::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::scan_lvm_lv_size" => $anvil->Convert->add_commas({number => $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_size}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_size}}), "sql::scan_lvm_lvs::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::scan_lvm_lv_path" => $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_path}, "sql::scan_lvm_lvs::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::scan_lvm_lv_on_pvs" => $anvil->data->{sql}{scan_lvm_lvs}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{scan_lvm_lv_on_pvs}, }}); } return(0); } sub collect_data { my ($anvil) = @_; ### TODO: Swap oput '--separator \#!\#' for '--reportformat json' collect_pvs_data($anvil); collect_vgs_data($anvil); collect_lvs_data($anvil); return(0); } sub collect_pvs_data { my ($anvil) = @_; my $shell_call = $anvil->data->{path}{exe}{pvscan}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); my ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); $shell_call = $anvil->data->{path}{exe}{pvs}." --noheadings --units b --reportformat json -o pv_uuid,pv_name,vg_name,pv_attr,pv_size,pv_free"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); my $json = JSON->new->allow_nonref; my $pvs_data = $json->decode($output); my $default_sector_size = 512; foreach my $hash_ref (@{$pvs_data->{report}->[0]->{pv}}) { my $scan_lvm_pv_internal_uuid = $hash_ref->{pv_uuid}; $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{name} = $hash_ref->{pv_name}; $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{used_by_vg} = $hash_ref->{vg_name}; $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{attributes} = $hash_ref->{pv_attr}; # TODO: Parse this out $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{size} = ($hash_ref->{pv_size} =~ /^(\d+)B/)[0]; $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{free_space} = ($hash_ref->{pv_free} =~ /^(\d+)B/)[0]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "lvm::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::name" => $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{name}, "lvm::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::used_by_vg" => $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{used_by_vg}, "lvm::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::attributes" => $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{attributes}, "lvm::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::size" => $anvil->Convert->add_commas({number => $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{size}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{size}}).")", "lvm::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::free_space" => $anvil->Convert->add_commas({number => $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{free_space}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{free_space}}).")", }}); # We need to find the sector size of this PV. my $partition = $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{name}; $partition =~ s/^.*\///; my $directory = "/sys/class/block/".$partition."/subsystem"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { partition => $partition, directory => $directory, }}); # Look for the parent device. For partitions like 'sda1', this is 'sda'. For 'nvmen0p1', this is 'nvmen0', etc. my $sector_size = 0; until ($sector_size) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { partition => $partition }}); if (not $partition) { # Weird... Default to 512. $sector_size = $default_sector_size; my $original_partition = $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{name}; my $sector_path = $directory."/".$original_partition."/queue/hw_sector_size"; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_warning_0001", variables => { device => $original_partition, sector_path => $sector_path, sector_size => $sector_size, }}); } my $sector_size_file = $directory."/".$partition."/queue/hw_sector_size"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sector_size_file => $sector_size_file }}); if (-e $sector_size_file) { $sector_size = $anvil->Storage->read_file({file => $sector_size_file }); chomp $sector_size; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sector_size => $sector_size }}); if ((not $sector_size) or ($sector_size =~ /\D/)) { # Something went wrong, default to 512. $sector_size = $default_sector_size; my $original_partition = $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{name}; my $sector_path = $directory."/".$original_partition."/queue/hw_sector_size"; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_warning_0001", variables => { device => $original_partition, sector_path => $sector_path, sector_size => $sector_size, }}); } } # Take a number off and try again. chop $partition; } $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{sector_size} = $sector_size; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "lvm::scan_lvm_pv_internal_uuid::${scan_lvm_pv_internal_uuid}::sector_size" => $anvil->Convert->add_commas({number => $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{sector_size}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{sector_size}}).")", }}); } return(0); } sub collect_vgs_data { my ($anvil) = @_; my $shell_call = $anvil->data->{path}{exe}{vgscan}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); my ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); $shell_call = $anvil->data->{path}{exe}{vgs}." --noheadings --units b --reportformat json -o vg_uuid,vg_name,vg_attr,vg_extent_size,vg_size,vg_free"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); my $json = JSON->new->allow_nonref; my $vgs_data = $json->decode($output); foreach my $hash_ref (@{$vgs_data->{report}->[0]->{vg}}) { my $scan_lvm_vg_internal_uuid = $hash_ref->{vg_uuid}; $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{name} = $hash_ref->{vg_name}; $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{attributes} = $hash_ref->{vg_attr}; $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{extent_size} = ($hash_ref->{vg_extent_size} =~ /^(\d+)B/)[0]; $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{size} = ($hash_ref->{vg_size} =~ /^(\d+)B/)[0]; $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{free_space} = ($hash_ref->{vg_free} =~ /^(\d+)B/)[0]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "lvm::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::name" => $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{name}, "lvm::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::attributes" => $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{attributes}, "lvm::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::extent_size" => $anvil->Convert->add_commas({number => $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{extent_size}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{extent_size}}), "lvm::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::size" => $anvil->Convert->add_commas({number => $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{size}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{size}}), "lvm::scan_lvm_vg_internal_uuid::${scan_lvm_vg_internal_uuid}::free_space" => $anvil->Convert->add_commas({number => $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{free_space}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{lvm}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{free_space}}), }}); } return(0); } sub collect_lvs_data { my ($anvil) = @_; my $shell_call = $anvil->data->{path}{exe}{lvscan}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); my ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); $shell_call = $anvil->data->{path}{exe}{lvs}." --noheadings --units b --reportformat json -o lv_name,vg_name,lv_attr,lv_size,lv_uuid,lv_path,devices"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); my $json = JSON->new->allow_nonref; my $lvs_data = $json->decode($output); foreach my $hash_ref (@{$lvs_data->{report}->[0]->{lv}}) { my $scan_lvm_lv_internal_uuid = $hash_ref->{lv_uuid}; my $on_pvs = $hash_ref->{devices}; $on_pvs =~ s/\(\d+\)//g; # In JSON format, there are 2+ hash references when there are 2+ PVs under an LV. So we # record all data on the first pass and append the additional PVs. if (not exists $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}) { $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{name} = $hash_ref->{lv_name}; $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{attributes} = $hash_ref->{lv_attr}; $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{on_vg} = $hash_ref->{vg_name}; $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{device_path} = $hash_ref->{lv_path}; $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{size} = ($hash_ref->{lv_size} =~ /^(\d+)B/)[0]; $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{on_pvs} = $on_pvs; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "lvm::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::name" => $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{name}, "lvm::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::attributes" => $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{attributes}, "lvm::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::on_vg" => $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{on_vg}, "lvm::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::device_path" => $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{device_path}, "lvm::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::size" => $anvil->Convert->add_commas({number => $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{size}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{size}}), "lvm::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::on_pvs" => $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{on_pvs}, }}); } else { $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{on_pvs} .= ",".$on_pvs; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "lvm::scan_lvm_lv_internal_uuid::${scan_lvm_lv_internal_uuid}::on_pvs" => $anvil->data->{lvm}{scan_lvm_lv_internal_uuid}{$scan_lvm_lv_internal_uuid}{on_pvs}, }}); } } return(0); }