diff --git a/Anvil/Tools/DRBD.pm b/Anvil/Tools/DRBD.pm index 3fd91272..7c2e892c 100644 --- a/Anvil/Tools/DRBD.pm +++ b/Anvil/Tools/DRBD.pm @@ -1045,6 +1045,10 @@ This finds all of the configured '/dev/drbdX' devices and maps them to their res Parameters; +=head3 anvil_uuid (optional) + +If set, the C<< drbdadm dump-xml >> is not called, instead the most recent version as recorded in C<< scan_drbd -> scan_drbd_common_xml >> is loaded from one of the hosts. + =head3 password (optional) This is the password to use when connecting to a remote machine. If not set, but C<< target >> is, an attempt to connect without a password will be made. @@ -1070,48 +1074,102 @@ sub get_devices my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "DRBD->get_devices()" }}); + my $anvil_uuid = defined $parameter->{anvil_uuid} ? $parameter->{anvil_uuid} : ""; my $password = defined $parameter->{password} ? $parameter->{password} : ""; my $port = defined $parameter->{port} ? $parameter->{port} : ""; my $remote_user = defined $parameter->{remote_user} ? $parameter->{remote_user} : "root"; my $target = defined $parameter->{target} ? $parameter->{target} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + anvil_uuid => $anvil_uuid, password => $anvil->Log->is_secure($password), port => $port, remote_user => $remote_user, target => $target, }}); - # Is this a local call or a remote call? - my $host = $anvil->Get->short_host_name; - my $shell_call = $anvil->data->{path}{exe}{drbdadm}." dump-xml"; - my $output = ""; - if ($anvil->Network->is_local({host => $target})) + # If we've got an anvil_uuid, search for the drbd common XML from the database. + my $host = $anvil->Get->short_host_name; + my $output = ""; + if ($anvil_uuid) { - # Local. - ($output, $anvil->data->{drbd}{'drbdadm-xml'}{return_code}) = $anvil->System->call({shell_call => $shell_call}); + if (not exists $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}) + { + $anvil->Database->get_anvils({debug => $debug}); + if (not exists $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}) + { + # Failed to find the Anvil! data. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0360", variables => { anvil_uuid => $anvil_uuid }}); + return("!!error!!"); + } + } + 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 => $debug, list => { + node1_host_uuid => $node1_host_uuid, + node2_host_uuid => $node2_host_uuid, + }}); + + my $query = " +SELECT + scan_drbd_common_xml +FROM + scan_drbd +WHERE + scan_drbd_host_uuid = '618e8007-3a0b-4bbf-a616-a64fd7d2dc30' +OR + scan_drbd_host_uuid = '75070e21-a0e3-4ba5-b4f7-476bf5d08107' +ORDER BY modified_date DESC +LIMIT 1 +;"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }}); + + my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); + my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - output => $output, - "drbd::drbdadm-xml::return_code" => $anvil->data->{drbd}{'drbdadm-xml'}{return_code}, + results => $results, + count => $count, }}); + if (not $count) + { + # Nothing found + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0361", variables => { anvil_uuid => $anvil_uuid }}); + return("!!error!!"); + } + $output = $results->[0]->[0]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output }}); } else { - # Remote call. - ($output, my $error, $anvil->data->{drbd}{'drbdadm-xml'}{return_code}) = $anvil->Remote->call({ - debug => $debug, - shell_call => $shell_call, - target => $target, - port => $port, - password => $password, - remote_user => $remote_user, - }); - $host = $target; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - host => $host, - error => $error, - output => $output, - "drbd::drbdadm-xml::return_code" => $anvil->data->{drbd}{'drbdadm-xml'}{return_code}, - }}); + # Is this a local call or a remote call? + my $shell_call = $anvil->data->{path}{exe}{drbdadm}." dump-xml"; + if ($anvil->Network->is_local({host => $target})) + { + # Local. + ($output, $anvil->data->{drbd}{'drbdadm-xml'}{return_code}) = $anvil->System->call({shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + output => $output, + "drbd::drbdadm-xml::return_code" => $anvil->data->{drbd}{'drbdadm-xml'}{return_code}, + }}); + } + else + { + # Remote call. + ($output, my $error, $anvil->data->{drbd}{'drbdadm-xml'}{return_code}) = $anvil->Remote->call({ + debug => $debug, + shell_call => $shell_call, + target => $target, + port => $port, + password => $password, + remote_user => $remote_user, + }); + $host = $target; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + host => $host, + error => $error, + output => $output, + "drbd::drbdadm-xml::return_code" => $anvil->data->{drbd}{'drbdadm-xml'}{return_code}, + }}); + } } # Clear the hash where we'll store the data. @@ -1225,6 +1283,9 @@ sub get_devices my $by_res = "/dev/drbd/by-res/".$this_resource."/".$volume; my $minor = $volume_href->{device}->[0]->{minor}; $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_path} = "/dev/drbd".$minor; + ### TODO: Anything using these are broken as the values get rewritten and + ### only store the last DRBD node's data. Switch to using the + ### 'this_host' stored values below $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_path_by_res} = $by_res; $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_minor} = $minor; $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{'meta-disk'} = $volume_href->{'meta-disk'}->[0]; @@ -1236,12 +1297,13 @@ sub get_devices "drbd::config::${host}::resource::${this_resource}::volume::${volume}::meta-disk" => $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{'meta-disk'}, "drbd::config::${host}::resource::${this_resource}::volume::${volume}::backing_lv" => $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{backing_lv}, }}); + if (($anvil->data->{drbd}{config}{$host}{host}) && ($anvil->data->{drbd}{config}{$host}{host} eq $this_host)) { $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_path}{on} = $lv_path; $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_path}{resource} = $this_resource; $anvil->data->{drbd}{config}{$host}{lv_path}{$lv_path}{under} = $drbd_path; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "drbd::config::${host}::drbd_path::${drbd_path}::on" => $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_path}{on}, "drbd::config::${host}::drbd_path::${drbd_path}::resource" => $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_path}{resource}, "drbd::config::${host}::lv_path::${lv_path}::under" => $anvil->data->{drbd}{config}{$host}{lv_path}{$lv_path}{under}, @@ -1259,6 +1321,20 @@ sub get_devices "drbd::config::${host}::by-res::${by_res}::backing_lv" => $anvil->data->{drbd}{config}{$host}{'by-res'}{$by_res}{backing_lv}, }}); } + + # This records the backing LV data for all hosts in this resource. + $anvil->data->{drbd}{drbd_node}{$this_host}{config}{resource}{$this_resource}{volume}{$volume}{drbd_path} = "/dev/drbd".$minor; + $anvil->data->{drbd}{drbd_node}{$this_host}{config}{resource}{$this_resource}{volume}{$volume}{drbd_path_by_res} = $by_res; + $anvil->data->{drbd}{drbd_node}{$this_host}{config}{resource}{$this_resource}{volume}{$volume}{drbd_minor} = $minor; + $anvil->data->{drbd}{drbd_node}{$this_host}{config}{resource}{$this_resource}{volume}{$volume}{'meta-disk'} = $volume_href->{'meta-disk'}->[0]; + $anvil->data->{drbd}{drbd_node}{$this_host}{config}{resource}{$this_resource}{volume}{$volume}{backing_lv} = $lv_path; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "drbd::drbd_node::${this_host}::config::resource::${this_resource}::volume::${volume}::drbd_path" => $anvil->data->{drbd}{drbd_node}{$this_host}{config}{resource}{$this_resource}{volume}{$volume}{drbd_path}, + "drbd::drbd_node::${this_host}::config::resource::${this_resource}::volume::${volume}::drbd_path_by_res" => $anvil->data->{drbd}{drbd_node}{$this_host}{config}{resource}{$this_resource}{volume}{$volume}{drbd_path_by_res}, + "drbd::drbd_node::${this_host}::config::resource::${this_resource}::volume::${volume}::drbd_minor" => $anvil->data->{drbd}{drbd_node}{$this_host}{config}{resource}{$this_resource}{volume}{$volume}{drbd_minor}, + "drbd::drbd_node::${this_host}::config::resource::${this_resource}::volume::${volume}::meta-disk" => $anvil->data->{drbd}{drbd_node}{$this_host}{config}{resource}{$this_resource}{volume}{$volume}{'meta-disk'}, + "drbd::drbd_node::${this_host}::config::resource::${this_resource}::volume::${volume}::backing_lv" => $anvil->data->{drbd}{drbd_node}{$this_host}{config}{resource}{$this_resource}{volume}{$volume}{backing_lv}, + }}); } } diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm index 98a23f23..efbe20bf 100644 --- a/Anvil/Tools/Database.pm +++ b/Anvil/Tools/Database.pm @@ -1696,7 +1696,7 @@ sub connect uuid => $uuid, variable_name => "database::".$uuid."::active", }); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { active_value => $active_value }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { active_value => $active_value }}); if (not $active_value) { # If we're "retry", we just started up. @@ -16053,11 +16053,12 @@ sub resync_databases $query =~ s/, $/ /; $query .= "FROM ".$schema.".".$table; - # Restrict to this host if a host column was found. - if ($host_column) - { - $query .= " WHERE ".$host_column." = ".$anvil->Database->quote($anvil->data->{sys}{host_uuid}); - } + ### NOTE: No longer restricting to the host, given only the strikers can do resyncs now. +# # Restrict to this host if a host column was found. +# if ($host_column) +# { +# $query .= " WHERE ".$host_column." = ".$anvil->Database->quote($anvil->data->{sys}{host_uuid}); +# } $query .= " ORDER BY utc_modified_date DESC;"; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0074", variables => { uuid => $uuid, query => $query }}); @@ -17633,7 +17634,7 @@ sub _find_column This returns the most up to date database ID, the time it was last updated and an array or DB IDs that are behind. -If there is a problem, C<< !!error!! >> is returned. +If there is a problem, C<< !!error!! >> is returned. If this is called by a host that isn't a Striker, C<< 0 >> is returned and no actions are take. Parameters; @@ -17661,6 +17662,14 @@ sub _find_behind_databases tables => $tables, }}); + # If we're not a striker, return. + my $host_type = $anvil->Get->host_type(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_type => $host_type }}); + if ($host_type ne "striker") + { + return(0); + } + # This should always be set, but just in case... if (not $source) { @@ -17774,18 +17783,19 @@ sub _find_behind_databases "database::${uuid}::password" => $anvil->Log->is_secure($anvil->data->{database}{$uuid}{password}), }}); + ### Only Strikers resync, so limiting to the host_uuid doesn't make sense anymore. my $schema = $has_history ? "history" : "public"; $query = " SELECT DISTINCT round(extract(epoch from modified_date)) AS unix_modified_date FROM ".$schema.".".$table." "; - if ($host_column) - { - $query .= " -WHERE - ".$host_column." = ".$anvil->Database->quote($anvil->data->{sys}{host_uuid}) ; - } +# if ($host_column) +# { +# $query .= " +# WHERE +# ".$host_column." = ".$anvil->Database->quote($anvil->data->{sys}{host_uuid}) ; +# } $query .= " ORDER BY unix_modified_date DESC diff --git a/Anvil/Tools/Network.pm b/Anvil/Tools/Network.pm index 9620ee97..32d6b10d 100644 --- a/Anvil/Tools/Network.pm +++ b/Anvil/Tools/Network.pm @@ -21,6 +21,7 @@ my $THIS_FILE = "Network.pm"; # find_target_ip # get_company_from_mac # get_ips +# get_ip_from_mac # get_network # is_local # is_our_interface @@ -1943,6 +1944,50 @@ sub get_company_from_mac return($company); } + +=head2 get_ip_from_mac + +This takes a MAC address and tries to convert it to an IP address. If no IP is found, an empty string is returned. + +Parameters; + +=head3 mac (required) + +This is the MAC address we're looking for an IP to match to. The format must be C<< aa:bb:cc:dd:ee:ff >>. + +=cut +sub get_ip_from_mac +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Network->get_ip_from_mac()" }}); + + my $ip = ""; + my $mac = defined $parameter->{mac} ? $parameter->{mac} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + mac => $mac, + }}); + + my $query = "SELECT mac_to_ip_ip_address FROM mac_to_ip WHERE mac_to_ip_mac_address = ".$anvil->Database->quote(lc($mac)).";"; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0124", variables => { query => $query }}); + my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); + my $count = @{$results}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + results => $results, + count => $count, + }}); + if ($count) + { + $ip = $results->[0]->[0]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { ip => $ip }}); + } + + return($ip); +} + + =head2 get_ips This method checks the local system for interfaces and stores them in: diff --git a/Anvil/Tools/Server.pm b/Anvil/Tools/Server.pm index 7ca03ec1..c5ed6079 100644 --- a/Anvil/Tools/Server.pm +++ b/Anvil/Tools/Server.pm @@ -1259,6 +1259,10 @@ B<< Note >>: This method currently parses out data needed for specific tasks, an Parameters; +=head3 anvil_uuid (optional) + +If passed, the C<< anvil_uuid >> will be passed on to C<< DRBD->get_devices >>. + =head3 server (required) This is the name of the server whose XML is being parsed. @@ -1297,12 +1301,14 @@ sub parse_definition $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Server->parse_definition()" }}); # Source is required. + my $anvil_uuid = defined $parameter->{anvil_uuid} ? $parameter->{anvil_uuid} : ""; my $server = defined $parameter->{server} ? $parameter->{server} : ""; my $source = defined $parameter->{source} ? $parameter->{source} : ""; my $definition = defined $parameter->{definition} ? $parameter->{definition} : ""; my $host = defined $parameter->{host} ? $parameter->{host} : $anvil->Get->short_host_name; my $target = $anvil->Get->short_host_name(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + anvil_uuid => $anvil_uuid, server => $server, source => $source, definition => $definition, @@ -1344,7 +1350,10 @@ sub parse_definition $anvil->data->{server}{$target}{$server}{$source}{parsed} = $server_xml; # Get the DRBD data that this server will almost certainly be using. - $anvil->DRBD->get_devices({debug => $debug}); + $anvil->DRBD->get_devices({ + debug => $debug, + anvil_uuid => $anvil_uuid, + }); # Pull out some basic server info. $anvil->data->{server}{$target}{$server}{$source}{info}{uuid} = $server_xml->{uuid}->[0]; diff --git a/Anvil/Tools/System.pm b/Anvil/Tools/System.pm index 07ec0fb0..fe8d6aec 100644 --- a/Anvil/Tools/System.pm +++ b/Anvil/Tools/System.pm @@ -5407,16 +5407,18 @@ sub _check_anvil_conf admin_uid => $admin_uid, admin_gid => $admin_gid, }}); - if (not $admin_gid) + if ((not $admin_uid) && (not $admin_gid)) { - # Create the admin group - my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $anvil->data->{path}{exe}{groupadd}." --system admin"}); + # Create the admin user and group + my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $anvil->data->{path}{exe}{useradd}." --create-home --comment \"Anvil! user account\" admin"}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output, return_code => $return_code, }}); + $admin_uid = getpwnam('admin'); $admin_gid = getgrnam('admin'); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "warning_0119", variables => { uid => $admin_uid }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "warning_0118", variables => { gid => $admin_gid }}); } if (not $admin_uid) @@ -5428,8 +5430,20 @@ sub _check_anvil_conf return_code => $return_code, }}); - my $admin_uid = getpwnam('admin'); - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "warning_0119", variables => { uid => $admin_gid }}); + $admin_uid = getpwnam('admin'); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "warning_0119", variables => { uid => $admin_uid }}); + } + if (not $admin_gid) + { + # Create the admin group + my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $anvil->data->{path}{exe}{groupadd}." admin"}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + output => $output, + return_code => $return_code, + }}); + + $admin_gid = getgrnam('admin'); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "warning_0118", variables => { gid => $admin_gid }}); } # Does the file exist? diff --git a/ocf/alteeve/server b/ocf/alteeve/server index 01c7f9b0..1a28d7d3 100755 --- a/ocf/alteeve/server +++ b/ocf/alteeve/server @@ -937,13 +937,14 @@ sub start_drbd_resource } } + ### NOTE: We always check the peer now, in case it's resource is down and ours happens to be up. # Do we need to start the resource on our peers? - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer_startup_needed => $peer_startup_needed }}); - if (not $peer_startup_needed) - { - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0431"}); - return(0); - } + #$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer_startup_needed => $peer_startup_needed }}); + #if (not $peer_startup_needed) + #{ + # $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0431"}); + # return(0); + #} # Start DRBD on the peer(s). foreach my $resource (sort {$a cmp $b} keys %{$anvil->data->{server}{$local_host}{$server}{resource}}) @@ -1244,17 +1245,18 @@ sub server_status } else { + # On EL8 and above, libvirtd starts on demand, so this error isn't if (not $warning_shown) { - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0522", variables => { wait_time => ($wait_until - time) }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0522", variables => { wait_time => ($wait_until - time) }}); $warning_shown = 1; } sleep 1; if (time > $wait_until) { # Libvirtd isn't running, try to find the PID of the server (in case it's - # running a libvirtd isn't) - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "warning_0057"}); + # running and libvirtd isn't) + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, priority => "alert", key => "warning_0057"}); $look_for_pid = 1; $libvirtd_wait = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { diff --git a/scancore-agents/scan-network/scan-network b/scancore-agents/scan-network/scan-network index 249db986..baace99b 100755 --- a/scancore-agents/scan-network/scan-network +++ b/scancore-agents/scan-network/scan-network @@ -85,6 +85,9 @@ process_health($anvil); # This clears the TX and RX variable data for interfaces older than 'scancore::database::age_out'. clear_old_variables($anvil); +# This removes network interfaces that have been marked as DELETED for a while now. +clear_old_interfaces($anvil); + # Shut down. $anvil->ScanCore->agent_shutdown({agent => $THIS_FILE}); @@ -93,6 +96,81 @@ $anvil->ScanCore->agent_shutdown({agent => $THIS_FILE}); # Functions # ############################################################################################################# +# This removes network interfaces that have been marked as DELETED for a while now. +sub clear_old_interfaces +{ + my ($anvil) = @_; + + # Read in all interfaces and for each, delete historical records over the age-out time. + my $age = $anvil->data->{scancore}{database}{age_out}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { age => $age }}); + + if ($age =~ /\D/) + { + # Age is not valid, set it to defaults. + $age = 24; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { age => $age }}); + } + + my $query = "SELECT now() - '".$age."h'::interval;"; + my $old_timestamp = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + query => $query, + old_timestamp => $old_timestamp, + }}); + + $query = " +SELECT + network_interface_uuid, + network_interface_mac_address, + network_interface_name +FROM + network_interfaces +WHERE + network_interface_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." +AND + network_interface_operational = 'DELETED' +AND + modified_date < '".$old_timestamp."' +ORDER BY + network_interface_name ASC; +;"; + 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 $network_interface_uuid = $row->[0]; + my $network_interface_mac_address = $row->[1]; + my $network_interface_name = $row->[2]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:network_interface_uuid' => $network_interface_uuid, + 's2:network_interface_mac_address' => $network_interface_mac_address, + 's3:network_interface_name' => $network_interface_name, + }}); + + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_log_0002", variables => { + age => $age, + mac => $network_interface_mac_address, + name => $network_interface_name, + }}); + + my $queries = []; + push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_uuid = '".$network_interface_uuid."';"; + push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_uuid = '".$network_interface_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__}); + } + + return(0); +} + # This clears the TX and RX variable data for interfaces older than 'scancore::database::age_out'. sub clear_old_variables { @@ -310,13 +388,15 @@ sub collect_data { # Pull out the data I want. Note that some of these don't exist with virtio-net interfaces. my $interface = $file; - my $link_state = -e $full_path."/carrier" ? $anvil->Storage->read_file({file => $full_path."/carrier"}) : 0; - my $mtu = -e $full_path."/mtu" ? $anvil->Storage->read_file({file => $full_path."/mtu"}) : 0; - my $duplex = -e $full_path."/duplex" ? $anvil->Storage->read_file({file => $full_path."/duplex"}) : "unknown"; # full or half? - my $operational = -e $full_path."/operstate" ? $anvil->Storage->read_file({file => $full_path."/operstate"}) : "unknown"; # up or down + my $link_state = -e $full_path."/carrier" ? $anvil->Storage->read_file({file => $full_path."/carrier"}) : 0; + my $mtu = -e $full_path."/mtu" ? $anvil->Storage->read_file({file => $full_path."/mtu"}) : 0; + my $duplex = -e $full_path."/duplex" ? $anvil->Storage->read_file({file => $full_path."/duplex"}) : "unknown"; # full or half? + my $operational = -e $full_path."/operstate" ? $anvil->Storage->read_file({file => $full_path."/operstate"}) : "unknown"; # up or down + my $modalias = -e $full_path."/device/modalias" ? $anvil->Storage->read_file({file => $full_path."/device/modalias"}) : "unknown"; my $speed = $link_state ? $anvil->Storage->read_file({file => $full_path."/speed"}) : 0; # Mbps (ie: 1000 = Gbps), gives a very high number for unplugged link my $media = "unknown"; my $type = "interface"; + my $driver = ""; my $tx_bytes = 0; # How many bytes transmitted my $rx_bytes = 0; # How many bytes received @@ -326,6 +406,7 @@ sub collect_data $duplex =~ s/\n$//; $operational =~ s/\n$//; $speed =~ s/\n$//; + $modalias =~ s/\n$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { interface => $interface, link_state => $link_state, @@ -333,8 +414,17 @@ sub collect_data duplex => $duplex, operational => $operational, speed => $speed, + modalias => $modalias, }}); + ### NOTE: This only parses virtio so far. + # Pick out our driver. + if ($modalias =~ /^virtio:/) + { + $driver = "virtio"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { driver => $driver }}); + } + # The MAC address can faked by a number of ways, so we make an explicit call to 'ethtool' to get the permanent mac address. my $mac_address = ""; my $shell_call = $anvil->data->{path}{exe}{ethtool}." -P ".$interface; @@ -412,12 +502,18 @@ sub collect_data # If this is a virtual interface, set some fake values that don't actually exist on # the system for the sake of a cleaner display. - if ($mac_address =~ /^52:54:00/) + if (($mac_address =~ /^52:54:00/) or ($driver eq "virtio")) { ### Set some fake values. # Speed is "as fast as possible", so we'll record 100 Gbps, but that is really kind of arbitrary. - $speed = 1000 if ((not $speed) or ($speed eq "-1")); - $duplex = "full" if not $duplex; + if ((not $speed) or ($speed eq "-1")) + { + $speed = 10000; + } + if ((not $duplex) or ($duplex eq "unknown")) + { + $duplex = "full"; + } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { speed => $speed, duplex => $duplex, @@ -885,9 +981,31 @@ ORDER BY uuid => $bridge_uuid, }}); + # If there's a bond connected to this bridge, get it's bond_uuid so + # we can remove any interfaces linked to it. + my $bond_uuid = ""; + my $query = "SELECT bond_uuid FROM bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { 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, + }}); + if ($count) + { + $bond_uuid = $results->[0]->[0]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bond_uuid => $bond_uuid }}); + } + my $queries = []; push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; + if ($bond_uuid) + { + push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; + push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; + } push @{$queries}, "DELETE FROM history.bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; push @{$queries}, "DELETE FROM bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; push @{$queries}, "DELETE FROM history.bridges WHERE bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; @@ -917,9 +1035,31 @@ ORDER BY uuid => $bridge_uuid, }}); + # If there's a bond connected to this bridge, get it's bond_uuid so + # we can remove any interfaces linked to it. + my $bond_uuid = ""; + my $query = "SELECT bond_uuid FROM bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { 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, + }}); + if ($count) + { + $bond_uuid = $results->[0]->[0]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bond_uuid => $bond_uuid }}); + } + my $queries = []; push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; + if ($bond_uuid) + { + push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; + push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; + } push @{$queries}, "DELETE FROM history.bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; push @{$queries}, "DELETE FROM bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; push @{$queries}, "DELETE FROM history.bridges WHERE bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; diff --git a/scancore-agents/scan-network/scan-network.xml b/scancore-agents/scan-network/scan-network.xml index 84081118..459a172a 100644 --- a/scancore-agents/scan-network/scan-network.xml +++ b/scancore-agents/scan-network/scan-network.xml @@ -215,5 +215,6 @@ This mode is NOT supported by the Anvil! Intelligent Availability™ platform! Aging out RX and TX data under: [#!variable!records!#] interfaces. These have 1 or more historical records older than: [#!variable!age!#] hours old from the database host: [#!variable!host!#]. + The old network interface: [#!variable!name!#] with the MAC address: [#!variable!mac!#] was marked as deleted more than: [#!variable!age!#] hours ago. Purging it from the database. diff --git a/share/words.xml b/share/words.xml index bf3e9147..586d4a6b 100644 --- a/share/words.xml +++ b/share/words.xml @@ -504,6 +504,9 @@ The output, if any, was; Failed to read the kernel release on the host: [#!variable!target!#]. The return code was: [#!variable!return_code!#] (expected '0') and the release output, if any, was: [#!variable!output!#]. The program: [#!variable!program!#] is using: [#!variable!ram_used!#] (#!variable!ram_used_bytes!# Bytes). This is probably caused by a memory leak, so we will now exit so that systemctl can restart us. If this is happening repeatedly, please contact support. This is not a Striker host. + There are no databases available, exiting. + Unable to find the Anvil! information for the Anvil! UUID: [#!variable!anvil_uuid!#]. + Unable to find the DRBD config from either node in the Anvil! with the Anvil! UUID: [#!variable!anvil_uuid!#]. Has scan_drbd (as part of scancore) run on either nodes? @@ -845,6 +848,23 @@ resource #!variable!server!# { Table public history + Server + CPU + RAM + Disk + Size + Storage Group + Bridge + Model + Last Known IP + Description + RAM Used + RAM Free + Bridges + Storage Group + Used + Free + Anvil! Node Pair Configure Network @@ -2509,6 +2529,10 @@ Available options; I was asked to resync. Calling the resync now. Aging out data to thin down the database(s). Prior to resync, we will check to see if any scan agent schemas need to be loaded. + #!variable!total_cores!#c (#!variable!sockets!#s) + #!variable!total_cores!#c (#!variable!sockets!#s, #!variable!cores!#c, #!variable!threads!#t), #!variable!model!#, #!variable!mode!# + #!variable!cores!#c (#!variable!threads!#t) + -=] Server Usage and Anvil! Node Resource Availability Saved the mail server information successfully! @@ -3188,15 +3212,19 @@ We will sleep a bit and try again. + + + + + + + - - - - + @@ -3204,6 +3232,8 @@ We will sleep a bit and try again. + + @@ -3230,6 +3260,7 @@ We will sleep a bit and try again. + @@ -3255,6 +3286,12 @@ We will sleep a bit and try again. + + + + + + @@ -3262,11 +3299,15 @@ We will sleep a bit and try again. + + + + @@ -3347,6 +3388,7 @@ We will sleep a bit and try again. + @@ -3355,7 +3397,10 @@ We will sleep a bit and try again. - + + + + @@ -3385,15 +3430,14 @@ We will sleep a bit and try again. + + - - - @@ -3408,6 +3452,8 @@ We will sleep a bit and try again. + + @@ -3453,6 +3499,7 @@ We will sleep a bit and try again. + @@ -3460,12 +3507,18 @@ We will sleep a bit and try again. + + + + + + @@ -3484,6 +3537,7 @@ We will sleep a bit and try again. + @@ -3516,6 +3570,7 @@ We will sleep a bit and try again. + @@ -3547,6 +3602,7 @@ We will sleep a bit and try again. + @@ -3587,9 +3643,13 @@ We will sleep a bit and try again. + + + + @@ -3614,6 +3674,8 @@ We will sleep a bit and try again. + + @@ -3632,6 +3694,7 @@ We will sleep a bit and try again. + @@ -3719,6 +3782,7 @@ We will sleep a bit and try again. + @@ -3741,6 +3805,13 @@ We will sleep a bit and try again. + + + + + + + @@ -3772,14 +3843,16 @@ We will sleep a bit and try again. + + - - + + @@ -3787,6 +3860,7 @@ We will sleep a bit and try again. + @@ -3805,6 +3879,7 @@ We will sleep a bit and try again. + @@ -3826,6 +3901,7 @@ We will sleep a bit and try again. + @@ -3846,8 +3922,10 @@ We will sleep a bit and try again. - + + + @@ -3859,6 +3937,7 @@ We will sleep a bit and try again. + @@ -3869,6 +3948,7 @@ We will sleep a bit and try again. + @@ -3886,7 +3966,6 @@ We will sleep a bit and try again. - diff --git a/tools/anvil-daemon b/tools/anvil-daemon index 6fdf464e..c9411601 100755 --- a/tools/anvil-daemon +++ b/tools/anvil-daemon @@ -404,21 +404,21 @@ sub set_delay { my ($anvil) = @_; - my $delay = 7200; - my $type = $anvil->Get->host_type(); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { type => $type }}); - if ($type eq "striker") + my $delay = 7200; + my $host_type = $anvil->Get->host_type(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }}); + if ($host_type eq "striker") { - foreach my $uuid (keys %{$anvil->data->{database}}) + foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{database}}) { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::host_uuid" => $anvil->data->{sys}{host_uuid}, uuid => $uuid, }}); if ($uuid eq $anvil->data->{sys}{host_uuid}) { $delay = 0; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { delay => $delay }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { delay => $delay }}); } last; } @@ -516,14 +516,14 @@ sub handle_periodic_tasks { my ($anvil) = @_; - my $now_time = time; - my $type = $anvil->Get->host_type(); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + my $now_time = time; + my $host_type = $anvil->Get->host_type(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:now_time" => $now_time, "s2:timing::next_minute_check" => $anvil->data->{timing}{next_minute_check}, "s3:timing::next_ten_minute_check" => $anvil->data->{timing}{next_ten_minute_check}, "s4:timing::next_daily_check" => $anvil->data->{timing}{next_daily_check}, - "s5:type" => $type, + "s5:host_type" => $host_type, }}); # Time to run once per minute tasks. @@ -625,74 +625,6 @@ sub handle_periodic_tasks # down our database. if ($host_type eq "striker") { - ### NOTE: Database shutdown logic is disabled. Too flaky. -=cut - if ($anvil->data->{sys}{database}{connections} > 1) - { - # Make sure that all active databases are in the host's table. If they're - # not, we're still early in setup. To do this, we create an array of hosts - # and then query both/all DBs to ensure they all have all hosts. - my $all_in_hosts = 1; - my $db_hosts = []; - foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}}) - { - push @{$db_hosts}, $uuid; - } - foreach my $db_uuid (@{$db_hosts}) - { - my $query = "SELECT COUNT(*) FROM hosts WHERE host_uuid = ".$anvil->Database->quote($db_uuid).";"; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - 's1:db_uuid' => $db_uuid, - 's2:query' => $query, - }}); - foreach my $host_uuid (@{$db_hosts}) - { - my $count = $anvil->Database->query({debug => 2, uuid => $db_uuid, query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - 's1:host_uuid' => $host_uuid, - 's2:db_uuid' => $db_uuid, - 's2:count' => $count, - }}); - if (not $count) - { - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "warning_0143", variables => { - db_uuid => $db_uuid, - host_uuid => $host_uuid, - }}); - - $all_in_hosts = 0; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { all_in_hosts => $all_in_hosts }}); - } - } - } - - # Sort by UUID, skip the first, and see if we're one of the others. - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { all_in_hosts => $all_in_hosts }}); - if ($all_in_hosts) - { - my $first_uuid = ""; - foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { uuid => $uuid }}); - if (not $first_uuid) - { - $first_uuid = $uuid; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { first_uuid => $first_uuid }}); - - # Skip the first UUID so it doesn't evaluate for - # shutdown. - next; - } - elsif ($uuid eq $host_uuid) - { - # This won't return until we're down. - $anvil->Database->shutdown({debug => 2}); - } - } - } - } -=cut - # If we're the active database, dump our database out and rsync it to our peers. my $peers = keys %{$anvil->data->{database}}; my $connections = $anvil->data->{sys}{database}{connections}; @@ -763,7 +695,7 @@ sub handle_periodic_tasks ### NOTE: We call it once/day, but this will also trigger on restart of anvil-daemon. As such, we ### don't use '--force' and let striker-manage-install-target skip the repo update if it happened ### recently enough. - if ($type eq "striker") + if ($host_type eq "striker") { # Age out old data. This takes up to a minute. $anvil->Database->_age_out_data(); @@ -817,7 +749,7 @@ sub handle_periodic_tasks # Update the next check time. $anvil->data->{timing}{next_daily_check} = $now_time + $anvil->data->{timing}{daily_checks}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:timing::daily_checks" => $anvil->data->{timing}{daily_checks}, "s2:timing::next_daily_check" => $anvil->data->{timing}{next_daily_check}, }}); @@ -1378,7 +1310,7 @@ AND $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }}); if ($host_type eq "striker") { - $anvil->Striker->check_httpd_conf({debug => 2}); + $anvil->Striker->check_httpd_conf({debug => 3}); } return(0); diff --git a/tools/anvil-report-usage b/tools/anvil-report-usage new file mode 100755 index 00000000..8db8f287 --- /dev/null +++ b/tools/anvil-report-usage @@ -0,0 +1,1005 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Anvil::Tools; +use Data::Dumper; +use Text::Diff; + +$| = 1; + +my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; +my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; +if (($running_directory =~ /^\./) && ($ENV{PWD})) +{ + $running_directory =~ s/^\./$ENV{PWD}/; +} + +my $anvil = Anvil::Tools->new(); + +$anvil->data->{switches}{detailed} = 0; +$anvil->Get->switches(); +$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "switches::detailed" => $anvil->data->{switches}{detailed}, +}}); + +$anvil->Database->connect(); +$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0132"}); +if (not $anvil->data->{sys}{database}{connections}) +{ + # No databases, exit. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, priority => "err", key => "error_0359"}); + $anvil->nice_exit({exit_code => 1}); +} + +$anvil->data->{display}{lines} = []; +collect_server_data($anvil); +collect_anvil_data($anvil); +show_servers($anvil); +show_anvils($anvil); + +# Show the results +foreach my $line (@{$anvil->data->{display}{lines}}) +{ + print $line."\n"; +} + +$anvil->nice_exit({exit_code => 0}); + + +############################################################################################################# +# Functions # +############################################################################################################# + +sub collect_anvil_data +{ + $anvil->data->{longest}{anvil_name} = 0; + $anvil->data->{longest}{description} = 0; + $anvil->data->{longest}{host_cpu_string} = 0; + $anvil->data->{longest}{ram_used} = 0; + $anvil->data->{longest}{ram_free} = 0; + $anvil->data->{longest}{bridge_string} = 0; + $anvil->data->{longest}{storage_group} = 0; + $anvil->data->{longest}{sg_used} = 0; + $anvil->data->{longest}{sg_free} = 0; + 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}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:anvil_name" => $anvil_name, + "s2:anvil_uuid" => $anvil_uuid, + }}); + + $anvil->data->{anvil_data}{$anvil_name}{description} = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_description}; + $anvil->data->{anvil_data}{$anvil_name}{node1_host_uuid} = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_node1_host_uuid}; + $anvil->data->{anvil_data}{$anvil_name}{node2_host_uuid} = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_node2_host_uuid}; + $anvil->data->{anvil_data}{$anvil_name}{dr1_host_uuid} = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_dr1_host_uuid}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:anvil_data::${anvil_name}::anvil_description" => $anvil->data->{anvil_data}{$anvil_name}{description}, + "s2:anvil_data::${anvil_name}::node1_host_uuid" => $anvil->data->{anvil_data}{$anvil_name}{node1_host_uuid}, + "s3:anvil_data::${anvil_name}::node2_host_uuid" => $anvil->data->{anvil_data}{$anvil_name}{node2_host_uuid}, + "s4:anvil_data::${anvil_name}::dr1_host_uuid" => $anvil->data->{anvil_data}{$anvil_name}{dr1_host_uuid}, + }}); + + if (length($anvil_name) > $anvil->data->{longest}{anvil_name}) + { + $anvil->data->{longest}{anvil_name} = length($anvil_name); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::anvil_name' => $anvil->data->{longest}{anvil_name}, + }}); + } + + if (length($anvil->data->{anvil_data}{$anvil_name}{description}) > $anvil->data->{longest}{description}) + { + $anvil->data->{longest}{description} = length($anvil->data->{anvil_data}{$anvil_name}{description}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::description' => $anvil->data->{longest}{description}, + }}); + } + + my $node1_host_uuid = $anvil->data->{anvil_data}{$anvil_name}{node1_host_uuid}; + my $node2_host_uuid = $anvil->data->{anvil_data}{$anvil_name}{node2_host_uuid}; + my $dr1_host_uuid = $anvil->data->{anvil_data}{$anvil_name}{dr1_host_uuid}; + if ($anvil->data->{switches}{detailed}) + { + $anvil->data->{anvil_data}{$anvil_name}{node1_host_name} = $anvil->data->{hosts}{host_uuid}{$node1_host_uuid}{host_name}; + $anvil->data->{anvil_data}{$anvil_name}{node2_host_name} = $anvil->data->{hosts}{host_uuid}{$node2_host_uuid}{host_name}; + $anvil->data->{anvil_data}{$anvil_name}{dr1_host_name} = ""; + if ($dr1_host_uuid) + { + $anvil->data->{anvil_data}{$anvil_name}{dr1_host_name} = $anvil->data->{hosts}{host_uuid}{$dr1_host_uuid}{host_name}; + } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:anvil_data::${anvil_name}::node1_host_name" => $anvil->data->{anvil_data}{$anvil_name}{node1_host_name}, + "s2:anvil_data::${anvil_name}::node2_host_name" => $anvil->data->{anvil_data}{$anvil_name}{node2_host_name}, + "s3:anvil_data::${anvil_name}::dr1_host_name" => $anvil->data->{anvil_data}{$anvil_name}{dr1_host_name}, + }}); + } + else + { + $anvil->data->{anvil_data}{$anvil_name}{node1_host_name} = $anvil->data->{hosts}{host_uuid}{$node1_host_uuid}{short_host_name}; + $anvil->data->{anvil_data}{$anvil_name}{node2_host_name} = $anvil->data->{hosts}{host_uuid}{$node2_host_uuid}{short_host_name}; + if ($dr1_host_uuid) + { + $anvil->data->{anvil_data}{$anvil_name}{dr1_host_name} = $anvil->data->{hosts}{host_uuid}{$dr1_host_uuid}{short_host_name}; + } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:anvil_data::${anvil_name}::node1_host_name" => $anvil->data->{anvil_data}{$anvil_name}{node1_host_name}, + "s2:anvil_data::${anvil_name}::node2_host_name" => $anvil->data->{anvil_data}{$anvil_name}{node2_host_name}, + "s3:anvil_data::${anvil_name}::dr1_host_name" => $anvil->data->{anvil_data}{$anvil_name}{dr1_host_name}, + }}); + } + + $anvil->Get->available_resources({anvil_uuid => $anvil_uuid}); + my $cpu_cores = $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores}; + my $cpu_threads = $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}; + my $say_cpu = $anvil->Words->string({key => "message_0289", variables => { + cores => $cpu_cores, + threads => $cpu_threads, + }}); + my $ram_available = $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}; + my $say_ram_available = $anvil->Convert->bytes_to_human_readable({'bytes' => $ram_available}); + my $ram_used = $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{allocated}; + my $say_ram_used = $anvil->Convert->bytes_to_human_readable({'bytes' => $ram_used}); + my $ram_hardware = $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{hardware}; + my $say_ram_hardware = $anvil->Convert->bytes_to_human_readable({'bytes' => $ram_hardware}); + + my $bridges = ""; + foreach my $bridge_name (sort {$a cmp $b} keys %{$anvil->data->{anvil_resources}{$anvil_uuid}{bridges}}) + { + $bridges .= $bridge_name.", "; + } + $bridges =~ s/, $//; + + # Store + $anvil->data->{anvil_data}{$anvil_name}{cpu_string} = $say_cpu; + $anvil->data->{anvil_data}{$anvil_name}{ram_used_string} = $say_ram_hardware; + $anvil->data->{anvil_data}{$anvil_name}{ram_free_string} = $say_ram_available; + $anvil->data->{anvil_data}{$anvil_name}{bridge_string} = $bridges; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:anvil_data::${anvil_name}::cpu_string" => $anvil->data->{anvil_data}{$anvil_name}{cpu_string}, + "s2:anvil_data::${anvil_name}::ram_used_string" => $anvil->data->{anvil_data}{$anvil_name}{ram_used_string}, + "s3:anvil_data::${anvil_name}::ram_free_string" => $anvil->data->{anvil_data}{$anvil_name}{ram_free_string}, + "s4:anvil_data::${anvil_name}::bridge_string" => $anvil->data->{anvil_data}{$anvil_name}{bridge_string}, + }}); + + if (length($anvil->data->{anvil_data}{$anvil_name}{cpu_string}) > $anvil->data->{longest}{host_cpu_string}) + { + $anvil->data->{longest}{host_cpu_string} = length($anvil->data->{anvil_data}{$anvil_name}{cpu_string}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::host_cpu_string' => $anvil->data->{longest}{host_cpu_string}, + }}); + } + + if (length($anvil->data->{anvil_data}{$anvil_name}{ram_used_string}) > $anvil->data->{longest}{ram_used}) + { + $anvil->data->{longest}{ram_used} = length($anvil->data->{anvil_data}{$anvil_name}{ram_used_string}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::ram_used' => $anvil->data->{longest}{ram_used}, + }}); + } + + if (length($anvil->data->{anvil_data}{$anvil_name}{ram_free_string}) > $anvil->data->{longest}{ram_free}) + { + $anvil->data->{longest}{ram_free} = length($anvil->data->{anvil_data}{$anvil_name}{ram_free_string}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::ram_free' => $anvil->data->{longest}{ram_free}, + }}); + } + + if (length($anvil->data->{anvil_data}{$anvil_name}{bridge_string}) > $anvil->data->{longest}{bridge_string}) + { + $anvil->data->{longest}{bridge_string} = length($anvil->data->{anvil_data}{$anvil_name}{bridge_string}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::bridge_string' => $anvil->data->{longest}{bridge_string}, + }}); + } + + my $storage_groups = []; + foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{anvil_resources}{$anvil_uuid}{storage_group_name}}) + { + my $storage_group_uuid = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group_name}{$storage_group_name}{storage_group_uuid}; + my $vg_size = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{vg_size}; + my $free_size = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size}; + my $sg_used = $vg_size - $free_size; + my $vg_size_on_dr = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{vg_size_on_dr}; + my $free_size_on_dr = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{available_on_dr}; + my $sg_used_on_dr = $vg_size_on_dr - $free_size_on_dr; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:storage_group_name' => $storage_group_name, + 's2:storage_group_uuid' => $storage_group_uuid, + 's3:vg_size' => $anvil->Convert->add_commas({number => $vg_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size}).")", + 's4:free_size' => $anvil->Convert->add_commas({number => $free_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $free_size}).")", + 's5:sg_used' => $anvil->Convert->add_commas({number => $sg_used})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $sg_used}).")", + 's6:vg_size_on_dr' => $anvil->Convert->add_commas({number => $vg_size_on_dr})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size_on_dr}).")", + 's7:free_size_on_dr' => $anvil->Convert->add_commas({number => $free_size_on_dr})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $free_size_on_dr}).")", + 's8:sg_used_on_dr' => $anvil->Convert->add_commas({number => $sg_used_on_dr})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $sg_used_on_dr}).")", + }}); + + $anvil->data->{anvil_data}{$anvil_name}{storage_group}{$storage_group_name}{say_used_size} = $anvil->Convert->bytes_to_human_readable({'bytes' => $sg_used}); + $anvil->data->{anvil_data}{$anvil_name}{storage_group}{$storage_group_name}{say_free_size} = $anvil->Convert->bytes_to_human_readable({'bytes' => $free_size}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:anvil_data::${anvil_name}::storage_group::${storage_group_name}::say_used_size" => $anvil->data->{anvil_data}{$anvil_name}{storage_group}{$storage_group_name}{say_used_size}, + "s2:anvil_data::${anvil_name}::storage_group::${storage_group_name}::say_free_size" => $anvil->data->{anvil_data}{$anvil_name}{storage_group}{$storage_group_name}{say_free_size}, + }}); + + if (length($storage_group_name) > $anvil->data->{longest}{storage_group}) + { + $anvil->data->{longest}{storage_group} = length($storage_group_name); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::storage_group' => $anvil->data->{longest}{storage_group}, + }}); + } + + if (length($anvil->data->{anvil_data}{$anvil_name}{storage_group}{$storage_group_name}{say_used_size}) > $anvil->data->{longest}{sg_used}) + { + $anvil->data->{longest}{sg_used} = length($anvil->data->{anvil_data}{$anvil_name}{storage_group}{$storage_group_name}{say_used_size}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::sg_used' => $anvil->data->{longest}{sg_used}, + }}); + } + + if (length($anvil->data->{anvil_data}{$anvil_name}{storage_group}{$storage_group_name}{say_free_size}) > $anvil->data->{longest}{sg_free}) + { + $anvil->data->{longest}{sg_free} = length($anvil->data->{anvil_data}{$anvil_name}{storage_group}{$storage_group_name}{say_free_size}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::sg_used' => $anvil->data->{longest}{sg_used}, + }}); + } + } + } +} + +sub show_anvils +{ + my ($anvil) = @_; + + my $anvil_header = $anvil->Words->string({key => "header_0081"}); + my $longest_anvil_name = length($anvil_header) > $anvil->data->{longest}{anvil_name} ? length($anvil_header) : $anvil->data->{longest}{anvil_name}; + my $description_header = $anvil->Words->string({key => "header_0074"}); + my $longest_description = length($description_header) > $anvil->data->{longest}{description} ? length($description_header) : $anvil->data->{longest}{description}; + my $cpu_header = $anvil->Words->string({key => "header_0066"}); + my $longest_cpu_string = length($cpu_header) > $anvil->data->{longest}{host_cpu_string} ? length($cpu_header) : $anvil->data->{longest}{host_cpu_string}; + my $ram_used_header = $anvil->Words->string({key => "header_0075"}); + my $longest_ram_used = length($ram_used_header) > $anvil->data->{longest}{ram_used} ? length($ram_used_header) : $anvil->data->{longest}{ram_used}; + my $ram_free_header = $anvil->Words->string({key => "header_0076"}); + my $longest_ram_free = length($ram_free_header) > $anvil->data->{longest}{ram_free} ? length($ram_free_header) : $anvil->data->{longest}{ram_free}; + my $bridge_header = $anvil->Words->string({key => "header_0077"}); + my $longest_bridge_string = length($bridge_header) > $anvil->data->{longest}{bridge_string} ? length($bridge_header) : $anvil->data->{longest}{bridge_string}; + my $storage_group_header = $anvil->Words->string({key => "header_0078"}); + my $longest_storage_group = length($storage_group_header) > $anvil->data->{longest}{storage_group} ? length($storage_group_header) : $anvil->data->{longest}{storage_group}; + my $sg_used_header = $anvil->Words->string({key => "header_0079"}); + my $longest_sg_used = length($sg_used_header) > $anvil->data->{longest}{sg_used} ? length($sg_used_header) : $anvil->data->{longest}{sg_used}; + my $sg_free_header = $anvil->Words->string({key => "header_0080"}); + my $longest_sg_free = length($sg_free_header) > $anvil->data->{longest}{sg_free} ? length($sg_free_header) : $anvil->data->{longest}{sg_free}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:longest_anvil_name' => $longest_anvil_name, + 's2:longest_description' => $longest_description, + 's3:longest_cpu_string' => $longest_cpu_string, + 's4:longest_ram_used' => $longest_ram_used, + 's5:longest_ram_free' => $longest_ram_free, + 's6:longest_bridge_string' => $longest_bridge_string, + 's7:longest_storage_group' => $longest_storage_group, + 's8:longest_sg_used' => $longest_sg_used, + 's9:longest_sg_free' => $longest_sg_free, + }}); + + # Anvil! + my $break_line = "+-".sprintf("%0${longest_anvil_name}d", 0); + my $header_line = "| ".sprintf("%-${longest_anvil_name}s", $anvil_header)." "; + my $blank_lead = "| ".sprintf("%-${longest_anvil_name}s", $anvil_header)." "; + if ($anvil->data->{switches}{detailed}) + { + # Description + $break_line .= "-+-".sprintf("%0${longest_description}d", 0); + $header_line .= "| ".sprintf("%-${longest_description}s", $description_header)." "; + $blank_lead .= " ".sprintf("%-${longest_description}s", $description_header)." "; + + } + # CPU String + $break_line .= "-+-".sprintf("%0${longest_cpu_string}d", 0); + $header_line .= "| ".sprintf("%-${longest_cpu_string}s", $cpu_header)." "; + $blank_lead .= " ".sprintf("%-${longest_cpu_string}s", $cpu_header)." "; + + if ($anvil->data->{switches}{detailed}) + { + # RAM used + $break_line .= "-+-".sprintf("%0${longest_ram_used}d", 0); + $header_line .= "| ".sprintf("%-${longest_ram_used}s", $ram_used_header)." "; + $blank_lead .= " ".sprintf("%-${longest_ram_used}s", $ram_used_header)." "; + } + + # RAM Free + $break_line .= "-+-".sprintf("%0${longest_ram_free}d", 0); + $header_line .= "| ".sprintf("%-${longest_ram_free}s", $ram_free_header)." "; + $blank_lead .= " ".sprintf("%-${longest_ram_free}s", $ram_free_header)." "; + + # Bridges + $break_line .= "-+-".sprintf("%0${longest_bridge_string}d", 0); + $header_line .= "| ".sprintf("%-${longest_bridge_string}s", $bridge_header)." "; + $blank_lead .= " ".sprintf("%-${longest_bridge_string}s", $bridge_header)." "; + + # Storage Group + $break_line .= "-+-".sprintf("%0${longest_storage_group}d", 0); + $header_line .= "| ".sprintf("%-${longest_storage_group}s", $storage_group_header)." "; + + if ($anvil->data->{switches}{detailed}) + { + # Storage Group Used + $break_line .= "-+-".sprintf("%0${longest_sg_used}d", 0); + $header_line .= "| ".sprintf("%-${longest_sg_used}s", $sg_used_header)." "; + } + + # Storage Group Free Space + $break_line .= "-+-".sprintf("%0${longest_sg_free}d", 0)."-+"; + $header_line .= "| ".sprintf("%-${longest_sg_free}s", $sg_free_header)." |"; + + $break_line =~ s/0/-/g; + + push @{$anvil->data->{display}{lines}}, ""; + push @{$anvil->data->{display}{lines}}, $break_line; + push @{$anvil->data->{display}{lines}}, $header_line; + push @{$anvil->data->{display}{lines}}, $break_line; + foreach my $anvil_name (sort {$a cmp $b} keys %{$anvil->data->{anvil_data}}) + { + my $anvil_description = $anvil->data->{anvil_data}{$anvil_name}{description}; + my $cpu_string = $anvil->data->{anvil_data}{$anvil_name}{cpu_string}; + my $ram_used_string = $anvil->data->{anvil_data}{$anvil_name}{ram_used_string}; + my $ram_free_string = $anvil->data->{anvil_data}{$anvil_name}{ram_free_string}; + my $bridge_string = $anvil->data->{anvil_data}{$anvil_name}{bridge_string}; + + my $first_line = "| ".sprintf("%-${longest_anvil_name}s", $anvil_name); + if ($anvil->data->{switches}{detailed}) + { + $first_line .= " | ".sprintf("%-${longest_description}s", $anvil_description); + } + $first_line .= " | ".sprintf("%-${longest_cpu_string}s", $cpu_string); + if ($anvil->data->{switches}{detailed}) + { + $first_line .= " | ".sprintf("%-${longest_ram_used}s", $ram_used_string); + } + $first_line .= " | ".sprintf("%-${longest_ram_free}s", $ram_used_string); + $first_line .= " | ".sprintf("%-${longest_bridge_string}s", $bridge_string); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { first_line => $first_line }}); + + my $storage_groups = []; + foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{anvil_data}{$anvil_name}{storage_group}}) + { + my $say_used_size = $anvil->data->{anvil_data}{$anvil_name}{storage_group}{$storage_group_name}{say_used_size}; + my $say_free_size = $anvil->data->{anvil_data}{$anvil_name}{storage_group}{$storage_group_name}{say_free_size}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:storage_group_name' => $storage_group_name, + 's2:say_used_size' => $say_used_size, + 's3:say_free_size' => $say_free_size, + }}); + + my $storage_line = " | ".sprintf("%-${longest_storage_group}s", $storage_group_name); + if ($anvil->data->{switches}{detailed}) + { + $storage_line .= " | ".sprintf("%-${longest_sg_used}s", $say_used_size); + } + $storage_line .= " | ".sprintf("%-${longest_sg_free}s", $say_free_size)." |"; + + push @{$storage_groups}, $storage_line; + } + + my $line_count = @{$storage_groups}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line_count => $line_count }}); + foreach (my $i = 0; $i < $line_count; $i++) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { i => $i }}); + if ($i == 0) + { + push @{$anvil->data->{display}{lines}}, $first_line.$storage_groups->[$i]; + } + else + { + push @{$anvil->data->{display}{lines}}, $blank_lead.$storage_groups->[$i]; + } + } + + } + push @{$anvil->data->{display}{lines}}, $break_line; + + return(0); +} + +sub show_servers +{ + my ($anvil) = @_; + + my $server_header = $anvil->Words->string({key => "header_0065"}); + my $longest_server_name = length($server_header) > $anvil->data->{longest}{server_name} ? length($server_header) : $anvil->data->{longest}{server_name}; + my $anvil_header = $anvil->Words->string({key => "brand_0002"}); + my $longest_anvil_name = length($anvil_header) > $anvil->data->{longest}{anvil_name} ? length($anvil_header) : $anvil->data->{longest}{anvil_name}; + my $cpu_header = $anvil->Words->string({key => "header_0066"}); + my $longest_cpu_string = length($cpu_header) > $anvil->data->{longest}{cpu_string} ? length($cpu_header) : $anvil->data->{longest}{cpu_string}; + my $ram_header = $anvil->Words->string({key => "header_0067"}); + my $longest_ram_string = length($ram_header) > $anvil->data->{longest}{ram_string} ? length($ram_header) : $anvil->data->{longest}{ram_string}; + my $resource_header = $anvil->Words->string({key => "header_0068"}); + my $longest_resource_name = length($resource_header) > $anvil->data->{longest}{resource_name} ? length($resource_header) : $anvil->data->{longest}{resource_name}; + my $disk_header = $anvil->Words->string({key => "header_0069"}); + my $longest_disk_size = length($disk_header) > $anvil->data->{longest}{disk_size} ? length($disk_header) : $anvil->data->{longest}{disk_size}; + my $storage_group_header = $anvil->Words->string({key => "header_0070"}); + my $longest_storage_group = length($storage_group_header) > $anvil->data->{longest}{storage_group} ? length($storage_group_header) : $anvil->data->{longest}{storage_group}; + my $bridge_header = $anvil->Words->string({key => "header_0071"}); + my $longest_bridge_name = length($bridge_header) > $anvil->data->{longest}{bridge_name} ? length($bridge_header) : $anvil->data->{longest}{bridge_name}; + my $net_model_header = $anvil->Words->string({key => "header_0072"}); + my $longest_net_model_name = length($net_model_header) > $anvil->data->{longest}{net_model_name} ? length($net_model_header) : $anvil->data->{longest}{net_model_name}; + my $mac_address_header = $anvil->Words->string({key => "header_0002"}); + my $longest_mac_address = length($mac_address_header) > $anvil->data->{longest}{mac_address} ? length($mac_address_header) : $anvil->data->{longest}{mac_address}; + my $ip_address_header = $anvil->Words->string({key => "header_0073"}); + my $longest_ip_address = length($ip_address_header) > $anvil->data->{longest}{ip_address} ? length($ip_address_header) : $anvil->data->{longest}{ip_address}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's01:longest_server_name' => $longest_server_name, + 's02:longest_anvil_name' => $longest_anvil_name, + 's03:longest_cpu_string' => $longest_cpu_string, + 's04:longest_ram_string' => $longest_ram_string, + 's05:longest_resource_name' => $longest_resource_name, + 's06:longest_disk_size' => $longest_disk_size, + 's07:longest_storage_group' => $longest_storage_group, + 's08:longest_bridge_name' => $longest_bridge_name, + 's09:longest_net_model_name' => $longest_net_model_name, + 's10:longest_mac_address' => $longest_mac_address, + 's11:longest_ip_address' => $longest_ip_address, + }}); + + my $break_line = "+-".sprintf("%0${longest_server_name}d", 0); + $break_line .= "-+-".sprintf("%0${longest_anvil_name}d", 0); + $break_line .= "-+-".sprintf("%0${longest_cpu_string}d", 0); + $break_line .= "-+-".sprintf("%0${longest_ram_string}d", 0); + $break_line .= "-+-".sprintf("%0${longest_resource_name}d", 0); + $break_line .= "-+-".sprintf("%0${longest_disk_size}d", 0); + if ($anvil->data->{switches}{detailed}) + { + $break_line .= "-+-".sprintf("%0${longest_storage_group}d", 0); + } + $break_line .= "-+-".sprintf("%0${longest_bridge_name}d", 0); + if ($anvil->data->{switches}{detailed}) + { + $break_line .= "-+-".sprintf("%0${longest_net_model_name}d", 0); + $break_line .= "-+-".sprintf("%0${longest_mac_address}d", 0); + } + $break_line .= "-+-".sprintf("%0${longest_ip_address}d", 0)."-+"; + $break_line =~ s/0/-/g; + + my $header_line = "| ".sprintf("%-${longest_server_name}s", $server_header)." "; + $header_line .= "| ".sprintf("%-${longest_anvil_name}s", $anvil_header)." "; + $header_line .= "| ".sprintf("%-${longest_cpu_string}s", $cpu_header)." "; + $header_line .= "| ".sprintf("%-${longest_ram_string}s", $ram_header)." "; + $header_line .= "| ".sprintf("%-${longest_resource_name}s", $resource_header)." "; + $header_line .= "| ".sprintf("%-${longest_disk_size}s", $disk_header)." "; + if ($anvil->data->{switches}{detailed}) + { + $header_line .= "| ".sprintf("%-${longest_storage_group}s", $storage_group_header)." "; + } + $header_line .= "| ".sprintf("%-${longest_bridge_name}s", $bridge_header)." "; + if ($anvil->data->{switches}{detailed}) + { + $header_line .= "| ".sprintf("%-${longest_net_model_name}s", $net_model_header)." "; + $header_line .= "| ".sprintf("%-${longest_mac_address}s", $mac_address_header)." "; + } + $header_line .= "| ".sprintf("%-${longest_ip_address}s", $ip_address_header)." |"; + + my $blank_lead = "| ".sprintf("%-${longest_server_name}s", " ")." "; + $blank_lead .= " ".sprintf("%-${longest_anvil_name}s", " ")." "; + $blank_lead .= " ".sprintf("%-${longest_cpu_string}s", " ")." "; + $blank_lead .= " ".sprintf("%-${longest_ram_string}s", " ")." "; + my $blank_drbd = ""; + my $blank_net = ""; + + push @{$anvil->data->{display}{lines}}, $anvil->Words->string({key => "message_0290"}); + push @{$anvil->data->{display}{lines}}, $break_line; + push @{$anvil->data->{display}{lines}}, $header_line; + push @{$anvil->data->{display}{lines}}, $break_line; + #push @{$anvil->data->{display}{lines}}, $blank_lead; + foreach my $server_name (sort {$a cmp $b} keys %{$anvil->data->{server_data}}) + { + # There should only ever be one UUID for a given name, but it's not impossible for there to be two. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_name => $server_name }}); + foreach my $server_uuid (sort {$a cmp $b} keys %{$anvil->data->{server_data}{$server_name}{server_uuid}}) + { + my $anvil_name = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{anvil_name}; + my $anvil_uuid = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{anvil_uuid}; + my $say_cpu = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{say_cpu}; + my $ram_used = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{ram_used}; + my $say_ram_used = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{say_ram_used}; + my $first_line = "| ".sprintf("%-${longest_server_name}s", $server_name); + $first_line .= " | ".sprintf("%-${longest_anvil_name}s", $anvil_name); + $first_line .= " | ".sprintf("%-${longest_cpu_string}s", $say_cpu); + $first_line .= " | ".sprintf("%-${longest_ram_string}s", $say_ram_used)." | "; + + my $drbd_lines = []; + foreach my $resource (sort {$a cmp $b} keys %{$anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}}) + { + foreach my $volume (sort {$a cmp $b} keys %{$anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}}) + { + my $say_size = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{say_size}; + my $storage_group = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{storage_group}; + my $say_resource = $resource."/".$volume; + my $storage_line = sprintf("%-${longest_resource_name}s", $say_resource)." | "; + $storage_line .= sprintf("%-${longest_disk_size}s", $say_size)." | "; + if ($anvil->data->{switches}{detailed}) + { + $storage_line .= sprintf("%-${longest_storage_group}s", $storage_group)." | "; + } + + push @{$drbd_lines}, $storage_line; + foreach my $drbd_node (sort {$a cmp $b} keys %{$anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}}) + { + my $drbd_path = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{drbd_path}; + my $drbd_path_by_res = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{drbd_path_by_res}; + my $drbd_minor = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{drbd_minor}; + my $meta_disk = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{'meta-disk'}; + my $backing_lv = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{backing_lv}; + my $node_host_uuid = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{host_uuid}; + } + + if (not length($blank_drbd)) + { + $blank_drbd = sprintf("%-${longest_resource_name}s", " ")." "; + if ($anvil->data->{switches}{detailed}) + { + $blank_drbd .= sprintf("%-${longest_disk_size}s", " ")." "; + $blank_drbd .= sprintf("%-${longest_storage_group}s", " ")." | "; + } + else + { + $blank_drbd .= sprintf("%-${longest_disk_size}s", " ")." |"; + } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { blank_drbd => $blank_drbd }}); + } + } + } + + my $net_lines = []; + foreach my $bridge (sort {$a cmp $b} keys %{$anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}}) + { + foreach my $alias (sort {$a cmp $b} keys %{$anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}}) + { + foreach my $mac (sort {$a cmp $b} keys %{$anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}}) + { + my $model = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{model}; + my $ip = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{ip}; + if (not $ip) + { + $ip = "--"; + } + my $net_line = sprintf("%-${longest_bridge_name}s", $bridge)." | "; + if ($anvil->data->{switches}{detailed}) + { + $net_line .= sprintf("%-${longest_net_model_name}s", $model)." | "; + $net_line .= sprintf("%-${longest_mac_address}s", $mac)." | "; + } + $net_line .= sprintf("%-${longest_ip_address}s", $ip)." |"; + + push @{$net_lines}, $net_line; + + if (not length($blank_net)) + { + $blank_net = sprintf("%-${longest_bridge_name}s", " ")." "; + if ($anvil->data->{switches}{detailed}) + { + $blank_net .= sprintf("%-${longest_net_model_name}s", " ")." "; + $blank_net .= sprintf("%-${longest_mac_address}s", " ")." "; + } + $blank_net .= sprintf("%-${longest_ip_address}s", " ")." |"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { blank_net => $blank_net }}); + } + } + } + } + + my $drbd_count = @{$drbd_lines}; + my $net_count = @{$net_lines}; + my $line_count = $drbd_count > $net_count ? $drbd_count : $net_count; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:drbd_count' => $drbd_count, + 's2:net_count' => $net_count, + 's3:line_count' => $line_count, + }}); + foreach (my $i = 0; $i < $line_count; $i++) + { + my $drbd_line = $drbd_lines->[$i] ? $drbd_lines->[$i] : $blank_drbd; + my $net_line = $net_lines->[$i] ? $net_lines->[$i] : "-- | -- | -- "; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:i' => $i, + 's2:drbd_line' => $drbd_line, + 's3:drbd_line' => $net_line, + }}); + if ($i == 0) + { + push @{$anvil->data->{display}{lines}}, $first_line.$drbd_line.$net_line; + } + else + { + push @{$anvil->data->{display}{lines}}, $blank_lead.$drbd_line.$net_line; + } + } + } + } + push @{$anvil->data->{display}{lines}}, $break_line; + + return(0); +} + +sub collect_server_data +{ + my ($anvil) = @_; + + $anvil->Database->get_anvils(); + $anvil->Database->get_servers(); + $anvil->Database->get_server_definitions(); + + $anvil->data->{longest}{server_name} = 0; + $anvil->data->{longest}{anvil_name} = 0; + $anvil->data->{longest}{cpu_string} = 0; + $anvil->data->{longest}{ram_string} = 0; + $anvil->data->{longest}{resource_name} = 0; + $anvil->data->{longest}{disk_size} = 0; + $anvil->data->{longest}{storage_group} = 0; + $anvil->data->{longest}{bridge_name} = 0; + $anvil->data->{longest}{net_model_name} = 0; + $anvil->data->{longest}{mac_address} = 0; + $anvil->data->{longest}{ip_address} = 0; + foreach my $server_uuid (sort {$a cmp $b} keys %{$anvil->data->{servers}{server_uuid}}) + { + my $server_name = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_name}; + my $anvil_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_anvil_uuid}; + my $anvil_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name}; + my $server_definition = $anvil->data->{server_definitions}{server_definition_server_uuid}{$server_uuid}{server_definition_xml}; + my $server_ram = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_ram_in_use}; + if ($anvil->data->{servers}{server_uuid}{$server_uuid}{server_configured_ram} > $server_ram) + { + $server_ram = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_configured_ram}; + } + my $say_server_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $server_ram}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:server_name' => $server_name, + 's2:anvil_name' => $anvil_name, + 's3:server_ram' => $anvil->Convert->add_commas({number => $server_ram})." (".$say_server_ram.")", + }}); + + my $target = $anvil->Get->short_host_name; + my $source = "from_db"; + $anvil->Server->parse_definition({ + debug => 2, + source => $source, + server => $server_name, + definition => $server_definition, + anvil_uuid => $anvil_uuid, + }); + + # CPU info + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{anvil_name} = $anvil_name; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{anvil_uuid} = $anvil_uuid; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{ram_used} = $server_ram; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{say_ram_used} = $say_server_ram; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{total_cores} = $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{total_cores}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{sockets} = $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{sockets}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{cores} = $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{cores}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{threads} = $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{threads}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{model_name} = $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{model_name}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{model_fallback} = $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{model_fallback}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{match} = $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{match}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{vendor} = $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{vendor}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{mode} = $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{mode}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{say_cpu} = $anvil->Words->string({key => "message_0287", variables => { + total_cores => $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{total_cores}, + sockets => $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{sockets}, + }}); + if ($anvil->data->{switches}{detailed}) + { + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{say_cpu} = $anvil->Words->string({key => "message_0288", variables => { + total_cores => $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{total_cores}, + sockets => $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{sockets}, + cores => $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{cores}, + threads => $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{threads}, + model => $anvil->data->{server}{$target}{$server_name}{$source}{cpu}{model_name}, + mode => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{mode}, + }}); + } + + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:server_data::${server_name}::server_uuid::${server_uuid}::anvil_name" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{anvil_name}, + "s2:server_data::${server_name}::server_uuid::${server_uuid}::anvil_uuid" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{anvil_uuid}, + "s3:server_data::${server_name}::server_uuid::${server_uuid}::ram_used" => $anvil->Convert->add_commas({number => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{ram_used}})." (".$anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{say_ram_used}.")", , + "s4:server_data::${server_name}::server_uuid::${server_uuid}::cpu::total_cores" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{total_cores}, + "s5:server_data::${server_name}::server_uuid::${server_uuid}::cpu::sockets" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{sockets}, + "s5:server_data::${server_name}::server_uuid::${server_uuid}::cpu::cores" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{cores}, + "s6:server_data::${server_name}::server_uuid::${server_uuid}::cpu::threads" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{threads}, + "s7:server_data::${server_name}::server_uuid::${server_uuid}::cpu::model_name" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{model_name}, + "s8:server_data::${server_name}::server_uuid::${server_uuid}::cpu::model_fallback" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{model_fallback}, + "s9:server_data::${server_name}::server_uuid::${server_uuid}::cpu::match" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{match}, + "s10:server_data::${server_name}::server_uuid::${server_uuid}::cpu::vendor" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{vendor}, + "s11:server_data::${server_name}::server_uuid::${server_uuid}::cpu::mode" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{mode}, + "s12:server_data::${server_name}::server_uuid::${server_uuid}::cpu::say_cpu" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{say_cpu}, + }}); + + if (length($server_name) > $anvil->data->{longest}{server_name}) + { + $anvil->data->{longest}{server_name} = length($server_name); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'longest::server_name' => $anvil->data->{longest}{server_name} }}); + } + if (length($anvil_name) > $anvil->data->{longest}{anvil_name}) + { + $anvil->data->{longest}{anvil_name} = length($anvil_name); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'longest::anvil_name' => $anvil->data->{longest}{anvil_name} }}); + } + if (length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{say_cpu}) > $anvil->data->{longest}{cpu_string}) + { + $anvil->data->{longest}{cpu_string} = length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{cpu}{say_cpu}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'longest::cpu_string' => $anvil->data->{longest}{cpu_string} }}); + } + if (length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{say_ram_used}) > $anvil->data->{longest}{ram_string}) + { + $anvil->data->{longest}{ram_string} = length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{say_ram_used}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'longest::ram_string' => $anvil->data->{longest}{ram_string} }}); + } + + # I need to know what nodes are in this cluster, so I don't look at another node that may + # have a matching node 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}; + my $dr1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid}; + + # Get names. + my $node1_host_name = $anvil->data->{hosts}{host_uuid}{$node1_host_uuid}{host_name}; + my $node1_short_host_name = $anvil->data->{hosts}{host_uuid}{$node1_host_uuid}{short_host_name}; + my $node2_host_name = $anvil->data->{hosts}{host_uuid}{$node2_host_uuid}{host_name}; + my $node2_short_host_name = $anvil->data->{hosts}{host_uuid}{$node2_host_uuid}{short_host_name}; + my $dr1_host_name = ""; + my $dr1_short_host_name = ""; + if (($dr1_host_uuid) && (exists $anvil->data->{hosts}{host_uuid}{$dr1_host_uuid})) + { + $dr1_host_name = $anvil->data->{hosts}{host_uuid}{$dr1_host_uuid}{host_name}; + $dr1_short_host_name = $anvil->data->{hosts}{host_uuid}{$dr1_host_uuid}{short_host_name}; + } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:node1_host_name' => $node1_host_name, + 's2:node1_short_host_name' => $node1_short_host_name, + 's3:node2_host_name' => $node2_host_name, + 's4:node2_short_host_name' => $node2_short_host_name, + 's5:dr1_host_name' => $dr1_host_name, + 's6:dr1_short_host_name' => $dr1_short_host_name, + }}); + + # Storage info. + foreach my $device_target (sort {$a cmp $b} keys %{$anvil->data->{server}{$target}{$server_name}{$source}{device}{disk}{target}}) + { + my $address_domain = $anvil->data->{server}{$target}{$server_name}{$source}{device}{disk}{target}{$device_target}{address}{domain}; + my $address_slot = $anvil->data->{server}{$target}{$server_name}{$source}{device}{disk}{target}{$device_target}{address}{slot}; + my $address_function = $anvil->data->{server}{$target}{$server_name}{$source}{device}{disk}{target}{$device_target}{address}{function}; + my $device_path = $anvil->data->{server}{$target}{$server_name}{$source}{device}{disk}{target}{$device_target}{path}; + my $driver_io = $anvil->data->{server}{$target}{$server_name}{$source}{device}{disk}{target}{$device_target}{driver}{io}; + my $driver_cache = $anvil->data->{server}{$target}{$server_name}{$source}{device}{disk}{target}{$device_target}{driver}{cache}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:device_target' => $device_target, + 's2:address_domain' => $address_domain, + 's3:address_slot' => $address_slot, + 's4:address_function' => $address_function, + 's5:device_path' => $device_path, + 's6:driver_io' => $driver_io, + 's7:driver_cache' => $driver_cache, + }}); + + # What is the DRBD resource name? + my ($resource, $volume) = ($device_path =~ /\/dev\/drbd\/by-res\/(.*?)\/(\d+)$/); + my $say_resource = $resource."/".$volume; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:resource' => $resource, + 's2:volume' => $volume, + 's3:say_resource' => $say_resource, + }}); + if (length($say_resource) > $anvil->data->{longest}{resource_name}) + { + $anvil->data->{longest}{resource_name} = length($say_resource); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'longest::resource_name' => $anvil->data->{longest}{resource_name} }}); + } + + # This will store the largest size LV becking the volume + my $disk_size = 0; + my $storage_group_name = ""; + foreach my $drbd_node (sort {$a cmp $b} keys %{$anvil->data->{drbd}{drbd_node}}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { drbd_node => $drbd_node }}); + if (($drbd_node eq $node1_host_name) or + ($drbd_node eq $node1_short_host_name) or + ($drbd_node eq $node2_host_name) or + ($drbd_node eq $node2_short_host_name) or + (($dr1_host_name) && ($drbd_node eq $dr1_host_name)) or + (($dr1_short_host_name) && ($drbd_node eq $dr1_short_host_name))) + { + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{drbd_path} = $anvil->data->{drbd}{drbd_node}{$drbd_node}{config}{resource}{$resource}{volume}{$volume}{drbd_path}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{drbd_path_by_res} = $anvil->data->{drbd}{drbd_node}{$drbd_node}{config}{resource}{$resource}{volume}{$volume}{drbd_path_by_res}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{drbd_minor} = $anvil->data->{drbd}{drbd_node}{$drbd_node}{config}{resource}{$resource}{volume}{$volume}{drbd_minor}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{'meta-disk'} = $anvil->data->{drbd}{drbd_node}{$drbd_node}{config}{resource}{$resource}{volume}{$volume}{'meta-disk'}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{backing_lv} = $anvil->data->{drbd}{drbd_node}{$drbd_node}{config}{resource}{$resource}{volume}{$volume}{backing_lv}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:server_data::${server_name}::server_uuid::${server_uuid}::disk::${resource}::${volume}::node::${drbd_node}::drbd_path" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{drbd_path}, + "s2:server_data::${server_name}::server_uuid::${server_uuid}::disk::${resource}::${volume}::node::${drbd_node}::drbd_path_by_res" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{drbd_path_by_res}, + "s3:server_data::${server_name}::server_uuid::${server_uuid}::disk::${resource}::${volume}::node::${drbd_node}::drbd_minor" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{drbd_minor}, + "s4:server_data::${server_name}::server_uuid::${server_uuid}::disk::${resource}::${volume}::node::${drbd_node}::meta_disk" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{'meta-disk'}, + "s5:server_data::${server_name}::server_uuid::${server_uuid}::disk::${resource}::${volume}::node::${drbd_node}::backing_lv" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{backing_lv}, + }}); + + # What this node's host uuid? + my $node_host_uuid = ""; + if (($drbd_node eq $node1_host_name) or ($drbd_node eq $node1_short_host_name)) + { + $node_host_uuid = $node1_host_uuid; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { node_host_uuid => $node_host_uuid }}); + } + elsif (($drbd_node eq $node2_host_name) or ($drbd_node eq $node2_short_host_name)) + { + $node_host_uuid = $node2_host_uuid; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { node_host_uuid => $node_host_uuid }}); + } + elsif (($drbd_node eq $dr1_host_name) or ($drbd_node eq $dr1_short_host_name)) + { + $node_host_uuid = $dr1_host_uuid; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { node_host_uuid => $node_host_uuid }}); + } + + # How big is this LV? + my $backing_lv = $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{backing_lv}; + my $query = " +SELECT + a.scan_lvm_lv_size, + d.storage_group_name +FROM + scan_lvm_lvs a, + scan_lvm_vgs b, + storage_group_members c, + storage_groups d +WHERE + a.scan_lvm_lv_path = ".$anvil->Database->quote($backing_lv); + if ($node_host_uuid) + { + $query .= " +AND + a.scan_lvm_lv_host_uuid = ".$anvil->Database->quote($node_host_uuid); + } + $query .= " +AND + a.scan_lvm_lv_on_vg = b.scan_lvm_vg_name"; + if ($node_host_uuid) + { + $query .= " +AND + b.scan_lvm_vg_host_uuid = ".$anvil->Database->quote($node_host_uuid); + } + $query .= " +AND + b.scan_lvm_vg_internal_uuid = c.storage_group_member_vg_uuid"; + if ($node_host_uuid) + { + $query .= " +AND + c.storage_group_member_host_uuid = ".$anvil->Database->quote($node_host_uuid); + } + $query .= " +AND + c.storage_group_member_storage_group_uuid = d.storage_group_uuid +;"; + if ($node_host_uuid) + { + # Store the host_uuid as well. + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{host_uuid} = $node_host_uuid; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:server_data::${server_name}::server_uuid::${server_uuid}::disk::${resource}::${volume}::node::${drbd_node}::host_uuid" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{node}{$drbd_node}{host_uuid}, + }}); + } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); + my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); + my $count = @{$results}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + results => $results, + count => $count, + }}); + + if ($count) + { + my $size = $results->[0]->[0]; + my $in_storage_group = $results->[0]->[1]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + size => $anvil->Convert->add_commas({number => $size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $size}).")", + in_storage_group => $in_storage_group, + }}); + if ($size > $disk_size) + { + $disk_size = $size; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + disk_size => $anvil->Convert->add_commas({number => $disk_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $disk_size}).")", + }}); + } + + if ((not $storage_group_name) && ($in_storage_group)) + { + $storage_group_name = $in_storage_group; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_name => $storage_group_name }}); + } + } + } + } + + # Store the disk size. + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{size} = $disk_size; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{say_size} = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{size}}); + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{storage_group} = $storage_group_name; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:server_data::${server_name}::server_uuid::${server_uuid}::disk::${resource}::${volume}::size" => $anvil->Convert->add_commas({number => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{size}})." (".$anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{say_size}.")", + "s2:server_data::${server_name}::server_uuid::${server_uuid}::disk::${resource}::${volume}::storage_group" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{storage_group}, + }}); + + if (length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{say_size}) > $anvil->data->{longest}{disk_size}) + { + $anvil->data->{longest}{disk_size} = length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{say_size}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'longest::disk_size' => $anvil->data->{longest}{disk_size} }}); + } + + if (length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{storage_group}) > $anvil->data->{longest}{storage_group}) + { + $anvil->data->{longest}{storage_group} = length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{disk}{$resource}{$volume}{storage_group}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'longest::storage_group' => $anvil->data->{longest}{storage_group} }}); + } + } + + # Find networks + foreach my $mac (sort {$a cmp $b} keys %{$anvil->data->{server}{$target}{$server_name}{$source}{device}{interface}}) + { + my $bridge = $anvil->data->{server}{$target}{$server_name}{$source}{device}{interface}{$mac}{bridge}; + my $alias = $anvil->data->{server}{$target}{$server_name}{$source}{device}{interface}{$mac}{alias}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:mac" => $mac, + "s2:bridge" => $bridge, + "s3:alias" => $alias, + }}); + + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{target} = $anvil->data->{server}{$target}{$server_name}{$source}{device}{interface}{$mac}{target}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{model} = $anvil->data->{server}{$target}{$server_name}{$source}{device}{interface}{$mac}{model}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{bus} = $anvil->data->{server}{$target}{$server_name}{$source}{device}{interface}{$mac}{address}{bus}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{domain} = $anvil->data->{server}{$target}{$server_name}{$source}{device}{interface}{$mac}{address}{domain}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{type} = $anvil->data->{server}{$target}{$server_name}{$source}{device}{interface}{$mac}{address}{type}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{slot} = $anvil->data->{server}{$target}{$server_name}{$source}{device}{interface}{$mac}{address}{slot}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{function} = $anvil->data->{server}{$target}{$server_name}{$source}{device}{interface}{$mac}{address}{function}; + $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{ip} = $anvil->Network->get_ip_from_mac({debug => 2, mac => $mac}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:server_data::${server_name}::server_uuid::${server_uuid}::net::${bridge}::${alias}::${mac}::target" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{target}, + "s2:server_data::${server_name}::server_uuid::${server_uuid}::net::${bridge}::${alias}::${mac}::model" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{model}, + "s3:server_data::${server_name}::server_uuid::${server_uuid}::net::${bridge}::${alias}::${mac}::bus" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{bus}, + "s4:server_data::${server_name}::server_uuid::${server_uuid}::net::${bridge}::${alias}::${mac}::domain" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{domain}, + "s5:server_data::${server_name}::server_uuid::${server_uuid}::net::${bridge}::${alias}::${mac}::type" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{type}, + "s6:server_data::${server_name}::server_uuid::${server_uuid}::net::${bridge}::${alias}::${mac}::slot" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{slot}, + "s7:server_data::${server_name}::server_uuid::${server_uuid}::net::${bridge}::${alias}::${mac}::function" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{function}, + "s8:server_data::${server_name}::server_uuid::${server_uuid}::net::${bridge}::${alias}::${mac}::ip" => $anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{ip}, + }}); + + if (length($bridge) > $anvil->data->{longest}{bridge_name}) + { + $anvil->data->{longest}{bridge_name} = length($bridge); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'longest::bridge_name' => $anvil->data->{longest}{bridge_name} }}); + } + + if (length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{model}) > $anvil->data->{longest}{net_model_name}) + { + $anvil->data->{longest}{net_model_name} = length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{model}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'longest::net_model_name' => $anvil->data->{longest}{net_model_name} }}); + } + + if (length($mac) > $anvil->data->{longest}{mac_address}) + { + $anvil->data->{longest}{mac_address} = length($mac); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'longest::mac_address' => $anvil->data->{longest}{mac_address} }}); + } + + if (length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{ip}) > $anvil->data->{longest}{ip_address}) + { + $anvil->data->{longest}{ip_address} = length($anvil->data->{server_data}{$server_name}{server_uuid}{$server_uuid}{net}{$bridge}{$alias}{$mac}{ip}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'longest::ip_address' => $anvil->data->{longest}{ip_address} }}); + } + } + } + + return(0); +} diff --git a/tools/anvil-update-states b/tools/anvil-update-states index 759a891d..7c9365f8 100755 --- a/tools/anvil-update-states +++ b/tools/anvil-update-states @@ -202,13 +202,15 @@ sub update_network { # Pull out the data I want. Note that some of these don't exist with virtio-net interfaces. my $interface = $file; - my $link_state = -e $full_path."/carrier" ? $anvil->Storage->read_file({file => $full_path."/carrier"}) : 0; - my $mtu = -e $full_path."/mtu" ? $anvil->Storage->read_file({file => $full_path."/mtu"}) : 0; - my $duplex = -e $full_path."/duplex" ? $anvil->Storage->read_file({file => $full_path."/duplex"}) : "unknown"; # full or half? - my $operational = -e $full_path."/operstate" ? $anvil->Storage->read_file({file => $full_path."/operstate"}) : "unknown"; # up or down + my $link_state = -e $full_path."/carrier" ? $anvil->Storage->read_file({file => $full_path."/carrier"}) : 0; + my $mtu = -e $full_path."/mtu" ? $anvil->Storage->read_file({file => $full_path."/mtu"}) : 0; + my $duplex = -e $full_path."/duplex" ? $anvil->Storage->read_file({file => $full_path."/duplex"}) : "unknown"; # full or half? + my $operational = -e $full_path."/operstate" ? $anvil->Storage->read_file({file => $full_path."/operstate"}) : "unknown"; # up or down + my $modalias = -e $full_path."/device/modalias" ? $anvil->Storage->read_file({file => $full_path."/device/modalias"}) : "unknown"; my $speed = $link_state ? $anvil->Storage->read_file({file => $full_path."/speed"}) : 0; # Mbps (ie: 1000 = Gbps), gives a very high number for unplugged link my $media = "unknown"; my $type = "interface"; + my $driver = ""; # Clean up some newlines. $link_state =~ s/\n$//; @@ -216,15 +218,25 @@ sub update_network $duplex =~ s/\n$//; $operational =~ s/\n$//; $speed =~ s/\n$//; + $modalias =~ s/\n$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { interface => $interface, link_state => $link_state, - mtu => $mtu, + mtu => $mtu, duplex => $duplex, - operational => $operational, + operational => $operational, speed => $speed, + modalias => $modalias, }}); + ### NOTE: This only parses virtio so far. + # Pick out our driver. + if ($modalias =~ /^virtio:/) + { + $driver = "virtio"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { driver => $driver }}); + } + # The MAC address can faked by a number of ways, so we make an explicit call to 'ethtool' to get the permanent mac address. my $mac_address = ""; my $shell_call = $anvil->data->{path}{exe}{ethtool}." -P ".$interface; @@ -298,13 +310,19 @@ sub update_network # If this is a virtual interface, set some fake values that don't actually exist on # the system for the sake of a cleaner display. - if ($mac_address =~ /^52:54:00/) + if (($mac_address =~ /^52:54:00/) or ($driver eq "virtio")) { ### Set some fake values. # Speed is "as fast as possible", so we'll record 100 Gbps, but that is really kind of arbitrary. - $speed = 1000 if ((not $speed) or ($speed eq "-1")); - $duplex = "full" if not $duplex; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + if ((not $speed) or ($speed eq "-1")) + { + $speed = 10000; + } + if ((not $duplex) or ($duplex eq "unknown")) + { + $duplex = "full"; + } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { speed => $speed, duplex => $duplex, }}); @@ -313,7 +331,7 @@ sub update_network if (not $link_state) { $speed = 0; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { speed => $speed }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { speed => $speed }}); } # Is this a bond interface? diff --git a/tools/striker-parse-os-list b/tools/striker-parse-os-list index de75b973..8c09a1ed 100755 --- a/tools/striker-parse-os-list +++ b/tools/striker-parse-os-list @@ -22,8 +22,14 @@ $| = 1; my $anvil = Anvil::Tools->new(); # Read switches (target ([user@]host[:port]) and the file with the target's password. +$anvil->data->{switches}{new} = 0; +$anvil->data->{switches}{xml} = 0; $anvil->Get->switches; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }}); +$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'switches::new' => $anvil->data->{switches}{new}, + 'switches::xml' => $anvil->data->{switches}{xml}, +}}); my $words_file = $anvil->data->{path}{words}{'words.xml'}; my $language = $anvil->Words->language; @@ -50,10 +56,26 @@ foreach my $line (split/\n/, $output) }}); my $os_key = "os_list_".$os_code; - if ((not exists $anvil->data->{words}{$words_file}{language}{$language}{key}{$os_key}) or (not $anvil->data->{words}{$words_file}{language}{$language}{key}{$os_key}{content})) + if ($anvil->data->{switches}{new}) + { + # --xml only makes sense with '--new'. Without --new, we're comparing against the + if ((not exists $anvil->data->{words}{$words_file}{language}{$language}{key}{$os_key}) or (not $anvil->data->{words}{$words_file}{language}{$language}{key}{$os_key}{content})) + { + # Print already known. + print "\t\t\n"; + } + } + else { - # Print already known. - print "\t\t\n"; + # Which format? + if ($anvil->data->{switches}{xml}) + { + print "\t\t\n"; + } + else + { + print "key=".$os_code.",name=\"".$os_name."\"\n"; + } } } diff --git a/tools/striker-scan-network b/tools/striker-scan-network index 9daff95b..39583a1f 100755 --- a/tools/striker-scan-network +++ b/tools/striker-scan-network @@ -270,33 +270,42 @@ sub scan $anvil->Network->get_ips(); my $target = "local"; my $to_scan = []; - foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{network}{$target}{interface}}) + foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{network}}) { - my $ip = $anvil->data->{network}{$target}{interface}{$interface}{ip}; - my $subnet_mask = $anvil->data->{network}{$target}{interface}{$interface}{subnet_mask}; + my $is_local = $anvil->Network->is_local({host => $target}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - ip => $ip, - subnet_mask => $subnet_mask, + target => $target, + is_local => $is_local, }}); - if (($ip) && ($subnet_mask)) + next if not $is_local; + foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{network}{$target}{interface}}) { - my $network = $anvil->Network->get_network({ip => $ip, subnet_mask => $subnet_mask}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network => $network }}); - - if ($network) + my $ip = $anvil->data->{network}{$target}{interface}{$interface}{ip}; + my $subnet_mask = $anvil->data->{network}{$target}{interface}{$interface}{subnet_mask}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + ip => $ip, + subnet_mask => $subnet_mask, + }}); + if (($ip) && ($subnet_mask)) { - # Scan it. - my $address = $network."/".$subnet_mask; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { address => $address }}); - push @{$to_scan}, $address; + my $network = $anvil->Network->get_network({ip => $ip, subnet_mask => $subnet_mask}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network => $network }}); + + if ($network) + { + # Scan it. + my $address = $network."/".$subnet_mask; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { address => $address }}); + push @{$to_scan}, $address; + } } } - } - - # Scan what we found - foreach my $address (sort {$a cmp $b} @{$to_scan}) - { - call_nmap($anvil, $address); + + # Scan what we found + foreach my $address (sort {$a cmp $b} @{$to_scan}) + { + call_nmap($anvil, $address); + } } } @@ -350,7 +359,8 @@ sub call_nmap my $this_ip = ""; my $this_mac = ""; my $section = ""; - my $shell_call = $anvil->data->{path}{exe}{nmap}." -sP -T4 --min-parallelism 100 --max-parallelism 256 ".$address; + my $shell_call = $anvil->data->{path}{exe}{nmap}." -sP -T4 -n --min-parallelism 100 --max-parallelism 256 ".$address; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); open (my $file_handle, $shell_call." 2>&1 |") or $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, secure => 0, priority => "err", key => "log_0014", variables => { shell_call => $shell_call, error => $! }}); while(<$file_handle>) {