Merge pull request #231 from ClusterLabs/anvil-tools-dev

* Updated anvil-provision-server to handle human-readable sizes for d…
main
Digimer 3 years ago committed by GitHub
commit aa64b0f7fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      Anvil/Tools/Database.pm
  2. 53
      Anvil/Tools/Network.pm
  3. 19
      Anvil/Tools/ScanCore.pm
  4. 19
      Anvil/Tools/System.pm
  5. 9
      notes
  6. 148
      ocf/alteeve/server
  7. 19
      scancore-agents/scan-hardware/scan-hardware
  8. 1
      scancore-agents/scan-hardware/scan-hardware.xml
  9. 34
      scancore-agents/scan-network/scan-network
  10. 83
      scancore-agents/scan-server/scan-server
  11. 3
      share/words.xml
  12. 2
      tools/anvil-daemon
  13. 919
      tools/anvil-manage-server
  14. 431
      tools/anvil-provision-server
  15. 73
      tools/anvil-test-alerts
  16. 11
      tools/scancore
  17. 2
      tools/striker-prep-database

@ -2711,11 +2711,15 @@ WHERE
next if not $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active}; next if not $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active};
my $file_uuid = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_file_uuid}; my $file_uuid = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_file_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_uuid => $file_uuid }}); my $file_name = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
file_uuid => $file_uuid,
file_name => $file_name,
}});
# If the file was deleted, this won't exist # If the file was deleted, this won't exist
next if not exists $anvil->data->{files}{file_uuid}{$file_uuid}; next if not exists $anvil->data->{files}{file_uuid}{$file_uuid};
$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_name} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name}; $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_name} = $file_name;
$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_directory}; $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_directory};
$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_size}; $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_size};
$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_md5sum}; $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_md5sum};
@ -2727,6 +2731,12 @@ WHERE
"anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_md5sum" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum}, "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_md5sum" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum},
"anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_type" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type}, "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_type" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type},
}}); }});
# Make it so that we can list the files by name.
$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid} = $file_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"anvils::anvil_uuid::${anvil_uuid}::file_name::${file_name}::file_uuid" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid},
}});
} }
} }
@ -4993,6 +5003,7 @@ ORDER BY
{ {
my $query = " my $query = "
SELECT SELECT
scan_lvm_vg_name,
scan_lvm_vg_size, scan_lvm_vg_size,
scan_lvm_vg_free scan_lvm_vg_free
FROM FROM
@ -5011,9 +5022,11 @@ WHERE
if ($count) if ($count)
{ {
$anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_size} = $results->[0]->[0]; $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_name} = $results->[0]->[0];
$anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_free} = $results->[0]->[1]; $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_size} = $results->[0]->[1];
$anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_free} = $results->[0]->[2];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"storage_groups::anvil_uuid::${storage_group_anvil_uuid}::storage_group_uuid::${storage_group_uuid}::host_uuid::${storage_group_member_host_uuid}::vg_name" => $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_name},
"storage_groups::anvil_uuid::${storage_group_anvil_uuid}::storage_group_uuid::${storage_group_uuid}::host_uuid::${storage_group_member_host_uuid}::vg_size" => $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_size}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_size}}).")", "storage_groups::anvil_uuid::${storage_group_anvil_uuid}::storage_group_uuid::${storage_group_uuid}::host_uuid::${storage_group_member_host_uuid}::vg_size" => $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_size}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_size}}).")",
"storage_groups::anvil_uuid::${storage_group_anvil_uuid}::storage_group_uuid::${storage_group_uuid}::host_uuid::${storage_group_member_host_uuid}::vg_free" => $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_free}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_free}}).")", "storage_groups::anvil_uuid::${storage_group_anvil_uuid}::storage_group_uuid::${storage_group_uuid}::host_uuid::${storage_group_member_host_uuid}::vg_free" => $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_free}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{storage_groups}{anvil_uuid}{$storage_group_anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$storage_group_member_host_uuid}{vg_free}}).")",
}}); }});
@ -5058,11 +5071,13 @@ WHERE
my $storage_group_member_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$this_host_uuid}{storage_group_member_uuid}; my $storage_group_member_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$this_host_uuid}{storage_group_member_uuid};
my $internal_vg_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$this_host_uuid}{vg_internal_uuid}; my $internal_vg_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$this_host_uuid}{vg_internal_uuid};
my $vg_size = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$this_host_uuid}{vg_size}; my $vg_size = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$this_host_uuid}{vg_size};
my $vg_name = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$this_host_uuid}{vg_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
this_host_uuid => $this_host_uuid, this_host_uuid => $this_host_uuid,
storage_group_member_uuid => $storage_group_member_uuid, storage_group_member_uuid => $storage_group_member_uuid,
internal_vg_uuid => $internal_vg_uuid, internal_vg_uuid => $internal_vg_uuid,
vg_size => $anvil->Convert->add_commas({number => $vg_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size}).")", vg_size => $anvil->Convert->add_commas({number => $vg_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size}).")",
vg_name => $vg_name,
}}); }});
if ($vg_size > $size_to_match) if ($vg_size > $size_to_match)

@ -1077,6 +1077,13 @@ sub find_matches
} }
elsif (ref($anvil->data->{network}{$first}) ne "HASH") elsif (ref($anvil->data->{network}{$first}) ne "HASH")
{ {
$anvil->Network->load_ips({
debug => $debug,
host => $first,
});
if (ref($anvil->data->{network}{$first}) ne "HASH")
{
# Well, we tried.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0106", variables => { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0106", variables => {
key => "first -> network::".$first, key => "first -> network::".$first,
source => $source, source => $source,
@ -1084,6 +1091,7 @@ sub find_matches
}}); }});
return(""); return("");
} }
}
if (not $second) if (not $second)
{ {
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Network->find_matches()", parameter => "second" }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Network->find_matches()", parameter => "second" }});
@ -1091,13 +1099,22 @@ sub find_matches
} }
elsif (ref($anvil->data->{network}{$second}) ne "HASH") elsif (ref($anvil->data->{network}{$second}) ne "HASH")
{ {
$anvil->Network->load_ips({
debug => $debug,
host => $second,
});
if (ref($anvil->data->{network}{$second}) ne "HASH")
{
# Well, we tried.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0106", variables => { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0106", variables => {
key => "second -> network::".$second, key => "second -> network::".$second,
source => $source, source => $source,
line => $line, line => $line,
}}); }});
die;
return(""); return("");
} }
}
# Loop through the first, and on each interface with an IP/subnet mask, look for a match in the second. # Loop through the first, and on each interface with an IP/subnet mask, look for a match in the second.
my $match = {}; my $match = {};
@ -1683,6 +1700,7 @@ sub load_ips
if (($clear) && (exists $anvil->data->{network}{$host})) if (($clear) && (exists $anvil->data->{network}{$host}))
{ {
delete $anvil->data->{network}{$host}; delete $anvil->data->{network}{$host};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0700", variables => { hash => "network::${host}" }});
} }
# Read in all IPs, so that we know which to remove. # Read in all IPs, so that we know which to remove.
@ -1734,8 +1752,17 @@ AND
{ {
my $query = " my $query = "
SELECT SELECT
network_interface_uuid,
network_interface_name, network_interface_name,
network_interface_mac_address network_interface_mac_address,
network_interface_speed,
network_interface_mtu,
network_interface_link_state,
network_interface_operational,
network_interface_duplex,
network_interface_medium,
network_interface_bond_uuid,
network_interface_bridge_uuid
FROM FROM
network_interfaces network_interfaces
WHERE WHERE
@ -1752,13 +1779,14 @@ AND
}}); }});
next if not $count; next if not $count;
$interface_name = $results->[0]->[0]; $interface_name = $results->[0]->[1];
$interface_mac = $results->[0]->[1]; $interface_mac = $results->[0]->[2];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
interface_name => $interface_name, interface_name => $interface_name,
interface_mac => $interface_mac, interface_mac => $interface_mac,
}}); }});
$anvil->data->{network}{$host}{interface}{$interface_name}{network_interface_uuid} = $results->[0]->[0];
$anvil->data->{network}{$host}{interface}{$interface_name}{mac_address} = $interface_mac; $anvil->data->{network}{$host}{interface}{$interface_name}{mac_address} = $interface_mac;
$anvil->data->{network}{$host}{interface}{$interface_name}{ip} = $ip_address_address; $anvil->data->{network}{$host}{interface}{$interface_name}{ip} = $ip_address_address;
$anvil->data->{network}{$host}{interface}{$interface_name}{subnet_mask} = $ip_address_subnet_mask; $anvil->data->{network}{$host}{interface}{$interface_name}{subnet_mask} = $ip_address_subnet_mask;
@ -1766,7 +1794,16 @@ AND
$anvil->data->{network}{$host}{interface}{$interface_name}{gateway} = $ip_address_gateway; $anvil->data->{network}{$host}{interface}{$interface_name}{gateway} = $ip_address_gateway;
$anvil->data->{network}{$host}{interface}{$interface_name}{dns} = $ip_address_dns; $anvil->data->{network}{$host}{interface}{$interface_name}{dns} = $ip_address_dns;
$anvil->data->{network}{$host}{interface}{$interface_name}{type} = $ip_address_on_type; $anvil->data->{network}{$host}{interface}{$interface_name}{type} = $ip_address_on_type;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->data->{network}{$host}{interface}{$interface_name}{speed} = $results->[0]->[3];
$anvil->data->{network}{$host}{interface}{$interface_name}{mtu} = $results->[0]->[4];
$anvil->data->{network}{$host}{interface}{$interface_name}{link_state} = $results->[0]->[5];
$anvil->data->{network}{$host}{interface}{$interface_name}{operational} = $results->[0]->[6];
$anvil->data->{network}{$host}{interface}{$interface_name}{duplex} = $results->[0]->[7];
$anvil->data->{network}{$host}{interface}{$interface_name}{medium} = $results->[0]->[8];
$anvil->data->{network}{$host}{interface}{$interface_name}{bond_uuid} = $results->[0]->[9];
$anvil->data->{network}{$host}{interface}{$interface_name}{bridge_uuid} = $results->[0]->[10];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"network::${host}::interface::${interface_name}::network_interface_uuid" => $anvil->data->{network}{$host}{interface}{$interface_name}{network_interface_uuid},
"network::${host}::interface::${interface_name}::mac_address" => $anvil->data->{network}{$host}{interface}{$interface_name}{mac_address}, "network::${host}::interface::${interface_name}::mac_address" => $anvil->data->{network}{$host}{interface}{$interface_name}{mac_address},
"network::${host}::interface::${interface_name}::ip" => $anvil->data->{network}{$host}{interface}{$interface_name}{ip}, "network::${host}::interface::${interface_name}::ip" => $anvil->data->{network}{$host}{interface}{$interface_name}{ip},
"network::${host}::interface::${interface_name}::subnet_mask" => $anvil->data->{network}{$host}{interface}{$interface_name}{subnet_mask}, "network::${host}::interface::${interface_name}::subnet_mask" => $anvil->data->{network}{$host}{interface}{$interface_name}{subnet_mask},
@ -1774,6 +1811,14 @@ AND
"network::${host}::interface::${interface_name}::gateway" => $anvil->data->{network}{$host}{interface}{$interface_name}{gateway}, "network::${host}::interface::${interface_name}::gateway" => $anvil->data->{network}{$host}{interface}{$interface_name}{gateway},
"network::${host}::interface::${interface_name}::dns" => $anvil->data->{network}{$host}{interface}{$interface_name}{dns}, "network::${host}::interface::${interface_name}::dns" => $anvil->data->{network}{$host}{interface}{$interface_name}{dns},
"network::${host}::interface::${interface_name}::type" => $anvil->data->{network}{$host}{interface}{$interface_name}{type}, "network::${host}::interface::${interface_name}::type" => $anvil->data->{network}{$host}{interface}{$interface_name}{type},
"network::${host}::interface::${interface_name}::speed" => $anvil->data->{network}{$host}{interface}{$interface_name}{speed},
"network::${host}::interface::${interface_name}::mtu" => $anvil->data->{network}{$host}{interface}{$interface_name}{mtu},
"network::${host}::interface::${interface_name}::link_state" => $anvil->data->{network}{$host}{interface}{$interface_name}{link_state},
"network::${host}::interface::${interface_name}::operational" => $anvil->data->{network}{$host}{interface}{$interface_name}{operational},
"network::${host}::interface::${interface_name}::duplex" => $anvil->data->{network}{$host}{interface}{$interface_name}{duplex},
"network::${host}::interface::${interface_name}::medium" => $anvil->data->{network}{$host}{interface}{$interface_name}{medium},
"network::${host}::interface::${interface_name}::bond_uuid" => $anvil->data->{network}{$host}{interface}{$interface_name}{bond_uuid},
"network::${host}::interface::${interface_name}::bridge_uuid" => $anvil->data->{network}{$host}{interface}{$interface_name}{bridge_uuid},
}}); }});
} }
elsif ($ip_address_on_type eq "bond") elsif ($ip_address_on_type eq "bond")

@ -397,13 +397,22 @@ sub call_scan_agents
$shell_call .= " ".$anvil->data->{sys}{'log'}{level}; $shell_call .= " ".$anvil->data->{sys}{'log'}{level};
} }
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }});
if ($anvil->data->{switches}{purge})
{
$shell_call .= " --purge";
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }});
# Tell the user this agent is about to run... # Tell the user this agent is about to run...
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => $debug, key => "log_0252", variables => { # $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => $debug, key => "log_0252", variables => {
agent_name => $agent_name, # agent_name => $agent_name,
timeout => $timeout, # timeout => $timeout,
}}); # }});
my ($output, $return_code) = $anvil->System->call({timeout => $timeout, shell_call => $shell_call}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => $debug, key => "log_0701", variables => { agent_name => $agent_name }});
### TODO: Timeout, when called / set here, was hanging virsh calls. Unknown why yet, but temp
### fix is to just not use timeouts for calls.
#my ($output, $return_code) = $anvil->System->call({timeout => $timeout, shell_call => $shell_call});
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output, return_code => $return_code }});
foreach my $line (split/\n/, $output) foreach my $line (split/\n/, $output)
{ {

@ -2865,15 +2865,15 @@ sub generate_state_json
} }
else else
{ {
my $speed = $anvil->data->{network}{$host}{interface}{$interface}{speed}; my $speed = $anvil->data->{network}{$host}{interface}{$interface}{speed} ? $anvil->data->{network}{$host}{interface}{$interface}{speed} : 0;
my $say_speed = $anvil->Convert->add_commas({number => $anvil->data->{network}{$host}{interface}{$interface}{speed}})." ".$anvil->Words->string({key => "suffix_0050"}); my $say_speed = $anvil->Convert->add_commas({number => $anvil->data->{network}{$host}{interface}{$interface}{speed}})." ".$anvil->Words->string({key => "suffix_0050"});
my $link_state = $anvil->data->{network}{$host}{interface}{$interface}{link_state}; my $link_state = $anvil->data->{network}{$host}{interface}{$interface}{link_state} ? $anvil->data->{network}{$host}{interface}{$interface}{link_state} : "";
my $operational = $anvil->data->{network}{$host}{interface}{$interface}{operational}; my $operational = $anvil->data->{network}{$host}{interface}{$interface}{operational} ? $anvil->data->{network}{$host}{interface}{$interface}{operational} : "";
my $duplex = $anvil->data->{network}{$host}{interface}{$interface}{duplex}; my $duplex = $anvil->data->{network}{$host}{interface}{$interface}{duplex} ? $anvil->data->{network}{$host}{interface}{$interface}{duplex} : "unknown";
my $medium = $anvil->data->{network}{$host}{interface}{$interface}{medium}; my $medium = $anvil->data->{network}{$host}{interface}{$interface}{medium} ? $anvil->data->{network}{$host}{interface}{$interface}{medium} : "unknown";
my $bond_uuid = $anvil->data->{network}{$host}{interface}{$interface}{bond_uuid}; my $bond_uuid = $anvil->data->{network}{$host}{interface}{$interface}{bond_uuid} ? $anvil->data->{network}{$host}{interface}{$interface}{bond_uuid} : "";
my $bond_name = $anvil->data->{network}{$host}{interface}{$interface}{bond_name} ? $anvil->data->{network}{$host}{interface}{$interface}{bond_name} : $anvil->Words->string({key => "unit_0005"}); my $bond_name = $anvil->data->{network}{$host}{interface}{$interface}{bond_name} ? $anvil->data->{network}{$host}{interface}{$interface}{bond_name} : $anvil->Words->string({key => "unit_0005"});
my $bridge_uuid = $anvil->data->{network}{$host}{interface}{$interface}{bridge_uuid}; my $bridge_uuid = $anvil->data->{network}{$host}{interface}{$interface}{bridge_uuid} ? $anvil->data->{network}{$host}{interface}{$interface}{bridge_uuid} : "";
my $bridge_name = $anvil->data->{network}{$host}{interface}{$interface}{bridge_name} ? $anvil->data->{network}{$host}{interface}{$interface}{bridge_name} : $anvil->Words->string({key => "unit_0005"}); my $bridge_name = $anvil->data->{network}{$host}{interface}{$interface}{bridge_name} ? $anvil->data->{network}{$host}{interface}{$interface}{bridge_name} : $anvil->Words->string({key => "unit_0005"});
my $changed_order = $anvil->data->{network}{$host}{interface}{$interface}{changed_order}; my $changed_order = $anvil->data->{network}{$host}{interface}{$interface}{changed_order};
my $say_link_state = $link_state; my $say_link_state = $link_state;
@ -4955,7 +4955,7 @@ sub test_ipmi
next if $test_password eq ""; next if $test_password eq "";
# Build the shell call. # Build the shell call.
$shell_call = $anvil->data->{path}{directories}{fence_agents}."/fence_ipmilan ".$lanplus_switch." --ip ".$ipmi_target." --username ".$ipmi_user." --password ".$test_password." --action status"; $shell_call = $anvil->data->{path}{directories}{fence_agents}."/fence_ipmilan ".$lanplus_switch." --ip ".$ipmi_target." --username ".$ipmi_user." --password \"".$test_password."\" --action status";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 1, list => { shell_call => $shell_call }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 1, list => { shell_call => $shell_call }});
my $output = ""; my $output = "";
@ -4967,7 +4967,7 @@ sub test_ipmi
($output, my $error, $return_code) = $anvil->Remote->call({ ($output, my $error, $return_code) = $anvil->Remote->call({
debug => $debug, debug => $debug,
secure => 1, secure => 1,
timeout => 30, timeout => 2,
shell_call => $shell_call, shell_call => $shell_call,
target => $target, target => $target,
password => $password, password => $password,
@ -4984,6 +4984,7 @@ sub test_ipmi
($output, $return_code) = $anvil->System->call({ ($output, $return_code) = $anvil->System->call({
debug => $debug, debug => $debug,
secure => 1, secure => 1,
timeout => 2,
shell_call => $shell_call, shell_call => $shell_call,
}); });
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {

@ -1,3 +1,12 @@
When pairing Striker, make sure new config goes to all known nodes!
Immediately set drbdadm to 'secondary' after 'primary --force'
dnf -y update && dnf -y install https://www.alteeve.com/an-repo/m3/anvil-release-latest.noarch.rpm && alteeve-repo-setup -y && dnf -y install anvil-striker --allowerasing
dnf -y update && dnf -y install https://www.alteeve.com/an-repo/m3/anvil-release-latest.noarch.rpm && alteeve-repo-setup -y && dnf -y install anvil-node --allowerasing
dnf -y update && dnf -y install https://www.alteeve.com/an-repo/m3/anvil-release-latest.noarch.rpm && alteeve-repo-setup -y && dnf -y install anvil-dr --allowerasing
# Configure APC PDUs and UPSes # Configure APC PDUs and UPSes
tcpip -i 10.201.2.3 -s 255.255.0.0 -g 10.201.255.254 tcpip -i 10.201.2.3 -s 255.255.0.0 -g 10.201.255.254
web -h enable web -h enable

@ -357,8 +357,9 @@ sub check_daemons
if ($task eq "start") if ($task eq "start")
{ {
### It doesn't look like we need to start drbd. Up'ing the first resource works without it. ### It doesn't look like we need to start drbd. Up'ing the first resource works without it.
#foreach my $daemon ("libvirtd.service", "drbd.service") ### libvirtd also starts on-demand.
foreach my $daemon ("libvirtd.service") =cut
foreach my $daemon ("libvirtd.service", "drbd.service")
{ {
my $running_local = 0; my $running_local = 0;
my $running_peer = 0; my $running_peer = 0;
@ -503,149 +504,8 @@ sub check_daemons
} }
} }
} }
}
=cut # It's simpler (and thus safer) to not stop daemons.
if ($task eq "stop")
{
print "Stopping daemons\n";
my $stop = 0;
# Check both nodes if a server is running on either node.
my $local_vm_count = 0;
my $remote_vm_count = 0;
# Call virsh list --all
my ($local_output, $local_return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." list --all"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
local_output => $local_output,
local_return_code => $local_return_code,
}});
if (not $local_return_code)
{
# Parse output
foreach my $line (split/\n/, $local_output)
{
$line = $anvil->Words->clean_spaces({ string => $line });
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
if ($line =~ /(\d+)\s+(.*?)\s+running/)
{
$local_vm_count++;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { local_vm_count => $local_vm_count }});
}
}
}
my ($remote_output, $remote_error, $remote_return_code) = $anvil->Remote->call({
target => $peer_name,
shell_call => $anvil->data->{path}{exe}{virsh}." list --all",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
remote_output => $remote_output,
remote_error => $remote_error,
remote_return_code => $remote_return_code,
}});
if (not $remote_return_code)
{
# Parse output
foreach my $line (split/\n/, $remote_output)
{
$line = $anvil->Words->clean_spaces({ string => $line });
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
if ($line =~ /(\d+)\s+(.*?)\s+running/)
{
$remote_vm_count++;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { remote_vm_count => $remote_vm_count }});
}
}
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
local_vm_count => $local_vm_count,
remote_vm_count => $remote_vm_count,
}});
if ((not $local_vm_count) && (not $remote_vm_count))
{
if ($peer_ready)
{
# No servers running on either node.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0490"});
}
else
{
# No servers running here and the peer is not in the cluster.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0491"});
}
foreach my $daemon ("libvirtd.service", "drbd.service")
{
my $running_local = 0;
my $running_peer = 0;
my ($local_output, $local_return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{systemctl}." status ".$daemon});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
local_output => $local_output,
local_return_code => $local_return_code,
}});
if ($local_return_code eq "3")
{
# Already stopped.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0492", variables => { daemon => $daemon }});
}
elsif ($local_return_code eq "0")
{
# Running, stop it.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0493", variables => { daemon => $daemon }});
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{systemctl}." stop ".$daemon});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
}
my ($remote_output, $remote_error, $remote_return_code) = $anvil->Remote->call({
target => $peer_name,
shell_call => $anvil->data->{path}{exe}{systemctl}." status ".$daemon,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
remote_output => $remote_output,
remote_error => $remote_error,
remote_return_code => $remote_return_code,
}});
if ($remote_return_code eq "3")
{
# Already stopped.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0494", variables => {
daemon => $daemon,
host => $peer_name,
}});
}
elsif ($remote_return_code eq "0")
{
# Running, stop it.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0495", variables => {
daemon => $daemon,
host => $peer_name,
}});
my ($output, $error, $return_code) = $anvil->Remote->call({
target => $peer_name,
shell_call => $anvil->data->{path}{exe}{systemctl}." stop ".$daemon,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
error => $error,
return_code => $return_code,
}});
}
}
}
else
{
# Servers are still running, don't stop the daemons.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0496"});
}
}
=cut =cut
}
return(0); return(0);
} }

@ -1433,7 +1433,7 @@ FROM
WHERE WHERE
scan_hardware_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." scan_hardware_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)."
;"; ;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results}; my $count = @{$results};
@ -1441,6 +1441,21 @@ WHERE
results => $results, results => $results,
count => $count, count => $count,
}}); }});
# If there are 2, then we've hit a bug where, somehow, we got listed twice.
if ($count > 1)
{
# Delete all and exit.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "scan_hardware_log_0002", variables => { count => $count }});
my $queries = [];
push @{$queries}, "DELETE FROM history.scan_hardware_ram_modules WHERE scan_hardware_ram_module_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid).";";
push @{$queries}, "DELETE FROM scan_hardware_ram_modules WHERE scan_hardware_ram_module_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid).";";
push @{$queries}, "DELETE FROM history.scan_hardware WHERE scan_hardware_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid).";";
push @{$queries}, "DELETE FROM scan_hardware WHERE scan_hardware_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { query => $query }});
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__});
}
foreach my $row (@{$results}) foreach my $row (@{$results})
{ {
# We've got an entry in the 'scan_hardware' table, so now we'll look for data in the node and # We've got an entry in the 'scan_hardware' table, so now we'll look for data in the node and
@ -1460,7 +1475,7 @@ WHERE
my $scan_hardware_led_css = $row->[12]; my $scan_hardware_led_css = $row->[12];
my $scan_hardware_led_error = $row->[13]; my $scan_hardware_led_error = $row->[13];
my $scan_hardware_modified_date = $row->[14]; my $scan_hardware_modified_date = $row->[14];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"scan_hardware_uuid" => $scan_hardware_uuid, "scan_hardware_uuid" => $scan_hardware_uuid,
"scan_hardware_cpu_model" => $scan_hardware_cpu_model, "scan_hardware_cpu_model" => $scan_hardware_cpu_model,
"scan_hardware_cpu_cores" => $scan_hardware_cpu_cores, "scan_hardware_cpu_cores" => $scan_hardware_cpu_cores,

@ -157,6 +157,7 @@ If the RAM is being updated, this alert will clear once this node has been upgra
<!-- Log entries --> <!-- Log entries -->
<key name="scan_hardware_log_0001">Starting: [#!variable!program!#].</key> <key name="scan_hardware_log_0001">Starting: [#!variable!program!#].</key>
<key name="scan_hardware_log_0002">[ Note ] - There were: [#!variable!count!#] entries for this host. This should not happen! Deleting all entries and then exiting. Entries will be recreated on the next run.</key>
<!-- Message entries (usually meant to be alerts) --> <!-- Message entries (usually meant to be alerts) -->
<key name="scan_hardware_message_0001">Unknown</key> <key name="scan_hardware_message_0001">Unknown</key>

@ -321,9 +321,42 @@ sub collect_data
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }});
if (($host_type eq "node") or ($host_type eq "dr")) if (($host_type eq "node") or ($host_type eq "dr"))
{ {
my $default_network = "/etc/libvirt/qemu/networks/default.xml";
if (-e $default_network)
{
my $shell_call = $anvil->data->{path}{exe}{virsh}." net-destroy default";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
$shell_call = $anvil->data->{path}{exe}{virsh}." net-undefine default";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
# Register an alert
my $variables = {
bridge => "default",
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0001", variables => $variables});
$anvil->Alert->register({
alert_level => "notice",
message => "scan_network_alert_0001",
variables => $variables,
set_by => $THIS_FILE,
});
}
=cut
my $shell_call = $anvil->data->{path}{exe}{virsh}." net-list --all --name"; my $shell_call = $anvil->data->{path}{exe}{virsh}." net-list --all --name";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
# This often hangs.
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output, output => $output,
@ -371,6 +404,7 @@ sub collect_data
}); });
} }
} }
=cut
} }
# Walk through the sysfs files. # Walk through the sysfs files.

@ -11,6 +11,10 @@
# 1 = Startup failure (not running as root, no DB, bad file read, etc) # 1 = Startup failure (not running as root, no DB, bad file read, etc)
# 2 = libvirtd is not running. # 2 = libvirtd is not running.
# #
# BUG:
# - Check that an update on disk is not overwritten by the old config still being in memory for a still-
# running VM (specifically, RAM updates)
#
# TODO: # TODO:
# - Move location constraints to the host node if the server is not on the preferred host (this happens after # - Move location constraints to the host node if the server is not on the preferred host (this happens after
# recovering from a node loss). # recovering from a node loss).
@ -132,7 +136,10 @@ sub check_vnc
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__}); my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
foreach my $line (split/\n/, $output) foreach my $line (split/\n/, $output)
{ {
if ($line =~ /\d.*?:(\d+)$/) if ($line =~ /\d.*?:(\d+)$/)
@ -282,8 +289,14 @@ sub collect_data
} }
} }
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." list --all", source => $THIS_FILE, line => __LINE__}); my $shell_call = $anvil->data->{path}{exe}{virsh}." list --all";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
foreach my $line (split/\n/, $output) foreach my $line (split/\n/, $output)
{ {
$line = $anvil->Words->clean_spaces({string => $line}); $line = $anvil->Words->clean_spaces({string => $line});
@ -445,16 +458,28 @@ DELETED - Marks a server as no longer existing
# The definition was likely changed by the user while it was running. We # The definition was likely changed by the user while it was running. We
# should have already picked up the changes, but just to be safe, check for # should have already picked up the changes, but just to be safe, check for
# differences. # differences.
my ($virsh_definition, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." dumpxml --inactive ".$server_name, source => $THIS_FILE, line => __LINE__}); my $shell_call = $anvil->data->{path}{exe}{virsh}." dumpxml --inactive ".$server_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $virsh_definition, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($virsh_definition, $return_code) = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $virsh_definition,
return_code => $return_code,
}});
# The definition may have certainly changed, so update it in case # The definition may have certainly changed, so update it in case
# needed. # needed.
update_definitions_from_virsh($anvil, $server_name, $server_uuid, $virsh_definition); update_definitions_from_virsh($anvil, $server_name, $server_uuid, $virsh_definition);
# Now undefine the server # Now undefine the server
(my $output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." undefine ".$server_name, source => $THIS_FILE, line => __LINE__}); $shell_call = $anvil->data->{path}{exe}{virsh}." undefine ".$server_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
(my $output, $return_code) = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
} }
# Set the boot time back to zero. # Set the boot time back to zero.
@ -590,8 +615,11 @@ DELETED - Marks a server as no longer existing
$anvil->Alert->register({alert_level => "notice", message => "scan_server_alert_0003", variables => $variables, set_by => $THIS_FILE}); $anvil->Alert->register({alert_level => "notice", message => "scan_server_alert_0003", variables => $variables, set_by => $THIS_FILE});
} }
my ($virsh_live_definition, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." dumpxml ".$server_name, source => $THIS_FILE, line => __LINE__}); my $shell_call = $anvil->data->{path}{exe}{virsh}." dumpxml ".$server_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $virsh_definition, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($virsh_live_definition, $return_code) = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $virsh_definition, return_code => $return_code }});
$anvil->Server->parse_definition({ $anvil->Server->parse_definition({
server => $server_name, server => $server_name,
source => "from_live_virsh", source => "from_live_virsh",
@ -909,12 +937,15 @@ DELETED - Marks a server as no longer existing
if ($peer_access) if ($peer_access)
{ {
# Get a list of servers running on our peer. # Get a list of servers running on our peer.
my $shell_call = $anvil->data->{path}{exe}{virsh}." list --all";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($output, $error, $return_code) = $anvil->Remote->call({ my ($output, $error, $return_code) = $anvil->Remote->call({
target => $peer_name, target => $peer_name,
password => $password, password => $password,
shell_call => $anvil->data->{path}{exe}{virsh}." list --all", shell_call => $shell_call,
}); });
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
error => $error, error => $error,
output => $output, output => $output,
return_code => $return_code, return_code => $return_code,
@ -1039,8 +1070,14 @@ sub get_and_parse_virsh_definition
my ($anvil, $server_name) = @_; my ($anvil, $server_name) = @_;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { server_name => $server_name }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { server_name => $server_name }});
my ($virsh_definition, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." dumpxml --inactive ".$server_name, source => $THIS_FILE, line => __LINE__}); my $shell_call = $anvil->data->{path}{exe}{virsh}." dumpxml --inactive ".$server_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $virsh_definition, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($virsh_definition, $return_code) = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $virsh_definition,
return_code => $return_code,
}});
$anvil->Server->parse_definition({ $anvil->Server->parse_definition({
server => $server_name, server => $server_name,
@ -1062,12 +1099,24 @@ sub redefine_server_from_disk
# Push the new definition into virsh (it won't take effect until a reboot likely, but it will update # Push the new definition into virsh (it won't take effect until a reboot likely, but it will update
# the 'inactive' definition immediately. # the 'inactive' definition immediately.
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." defined ".$xml_file, source => $THIS_FILE, line => __LINE__}); my $shell_call = $anvil->data->{path}{exe}{virsh}." defined ".$xml_file;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
# Now undefine the server again so it disappears when stopped. # Now undefine the server again so it disappears when stopped.
($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." undefine ".$server_name, source => $THIS_FILE, line => __LINE__}); $shell_call = $anvil->data->{path}{exe}{virsh}." undefine ".$server_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
($output, $return_code) = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
output => $output,
return_code => $return_code,
}});
# Re-read and parse the new (inactive) definition # Re-read and parse the new (inactive) definition
my $virsh_definition = get_and_parse_virsh_definition($anvil, $server_name); my $virsh_definition = get_and_parse_virsh_definition($anvil, $server_name);

@ -507,6 +507,7 @@ The output, if any, was;
<key name="error_0359">There are no databases available, exiting.</key> <key name="error_0359">There are no databases available, exiting.</key>
<key name="error_0360">Unable to find the Anvil! information for the Anvil! UUID: [#!variable!anvil_uuid!#].</key> <key name="error_0360">Unable to find the Anvil! information for the Anvil! UUID: [#!variable!anvil_uuid!#].</key>
<key name="error_0361">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?</key> <key name="error_0361">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?</key>
<key name="error_0362"><![CDATA[The level: [#!variable!level!#] is invalid. Please use '--level <critical,warning,notice,info>' to specify the alert level of the test message.]]></key>
<!-- Files templates --> <!-- Files templates -->
<!-- NOTE: Translating these files requires an understanding of which lines are translatable --> <!-- NOTE: Translating these files requires an understanding of which lines are translatable -->
@ -2117,6 +2118,8 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="log_0697">All clients using our database are gone, ready to stop the postgresql daemon.</key> <key name="log_0697">All clients using our database are gone, ready to stop the postgresql daemon.</key>
<key name="log_0698">[ Note ] - Marking our database as active.</key> <key name="log_0698">[ Note ] - Marking our database as active.</key>
<key name="log_0699">[ Note ] - The Striker database host: [#!variable!host!#] is inactive, skipping it.</key> <key name="log_0699">[ Note ] - The Striker database host: [#!variable!host!#] is inactive, skipping it.</key>
<key name="log_0700">[ Note ] - Deleting the contents of the hash: [#!variable!hash!#].</key>
<key name="log_0701">Running the scan agent: [#!variable!agent_name!#]...</key>
<!-- Messages for users (less technical than log entries), though sometimes used for logs, too. --> <!-- Messages for users (less technical than log entries), though sometimes used for logs, too. -->
<key name="message_0001">The host name: [#!variable!target!#] does not resolve to an IP address.</key> <key name="message_0001">The host name: [#!variable!target!#] does not resolve to an IP address.</key>

@ -1455,7 +1455,7 @@ sub keep_running
# Write out state information for all known Anvil! systems and the information from # Write out state information for all known Anvil! systems and the information from
# unconfigured nods and DR hosts, using just database data (hence, fast enough to run # unconfigured nods and DR hosts, using just database data (hence, fast enough to run
# constantly). # constantly).
$anvil->System->generate_state_json({debug => 3}); $anvil->System->generate_state_json({debug => 2});
} }
else else
{ {

File diff suppressed because it is too large Load Diff

@ -18,6 +18,7 @@ use warnings;
use Anvil::Tools; use Anvil::Tools;
require POSIX; require POSIX;
use Term::Cap; use Term::Cap;
use Data::Dumper;
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
@ -36,10 +37,16 @@ my $anvil = Anvil::Tools->new();
$anvil->data->{switches}{anvil} = ""; $anvil->data->{switches}{anvil} = "";
$anvil->data->{switches}{'anvil-name'} = ""; $anvil->data->{switches}{'anvil-name'} = "";
$anvil->data->{switches}{'anvil-uuid'} = ""; $anvil->data->{switches}{'anvil-uuid'} = "";
$anvil->data->{switches}{os} = ""; $anvil->data->{switches}{'ci-test'} = ""; # If set, all we do is read the switches and submit the job
$anvil->data->{switches}{'driver-disc'} = "";
$anvil->data->{switches}{cpu} = ""; $anvil->data->{switches}{cpu} = "";
$anvil->data->{switches}{'install-media'} = "";
$anvil->data->{switches}{'job-uuid'} = ""; $anvil->data->{switches}{'job-uuid'} = "";
$anvil->data->{switches}{machine} = "";
$anvil->data->{switches}{name} = ""; $anvil->data->{switches}{name} = "";
$anvil->data->{switches}{options} = "";
$anvil->data->{switches}{os} = "";
$anvil->data->{switches}{'pre-test'} = "";
$anvil->data->{switches}{uuid} = ""; $anvil->data->{switches}{uuid} = "";
$anvil->data->{switches}{ram} = ""; $anvil->data->{switches}{ram} = "";
$anvil->data->{switches}{'storage-group'} = ""; $anvil->data->{switches}{'storage-group'} = "";
@ -51,10 +58,16 @@ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list
'switches::anvil' => $anvil->data->{switches}{anvil}, 'switches::anvil' => $anvil->data->{switches}{anvil},
'switches::anvil-name' => $anvil->data->{switches}{'anvil-name'}, 'switches::anvil-name' => $anvil->data->{switches}{'anvil-name'},
'switches::anvil-uuid' => $anvil->data->{switches}{'anvil-uuid'}, 'switches::anvil-uuid' => $anvil->data->{switches}{'anvil-uuid'},
'switches::os' => $anvil->data->{switches}{os}, 'switches::ci-test' => $anvil->data->{switches}{'ci-test'},
'switches::driver-disc' => $anvil->data->{switches}{'driver-disc'},
'switches::cpu' => $anvil->data->{switches}{cpu}, 'switches::cpu' => $anvil->data->{switches}{cpu},
'switches::install-media' => $anvil->data->{switches}{'install-media'},
'switches::job-uuid' => $anvil->data->{switches}{'job-uuid'}, 'switches::job-uuid' => $anvil->data->{switches}{'job-uuid'},
'switches::machine' => $anvil->data->{switches}{machine},
'switches::name' => $anvil->data->{switches}{name}, 'switches::name' => $anvil->data->{switches}{name},
'switches::options' => $anvil->data->{switches}{options},
'switches::os' => $anvil->data->{switches}{os},
'switches::pre-test' => $anvil->data->{switches}{'pre-test'},
'switches::uuid' => $anvil->data->{switches}{uuid}, 'switches::uuid' => $anvil->data->{switches}{uuid},
'switches::ram' => $anvil->data->{switches}{ram}, 'switches::ram' => $anvil->data->{switches}{ram},
'switches::storage-group' => $anvil->data->{switches}{'storage-group'}, 'switches::storage-group' => $anvil->data->{switches}{'storage-group'},
@ -96,6 +109,10 @@ if ($anvil->data->{switches}{'job-uuid'})
# Job data will be in $anvil->data->{jobs}{job_data} # Job data will be in $anvil->data->{jobs}{job_data}
run_jobs($anvil); run_jobs($anvil);
} }
elsif ($anvil->data->{switches}{'ci-test'})
{
interactive_ask_server_confirm($anvil, "");
}
else else
{ {
# Interactive! # Interactive!
@ -504,7 +521,7 @@ sub provision_server
progress => 70, progress => 70,
message => "job_0199,!!shell_call!".$shell_call."!!", message => "job_0199,!!shell_call!".$shell_call."!!",
}); });
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0199", variables => { shell_call => $shell_call }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0199", variables => { shell_call => $shell_call }});
# Write the command out to /mnt/shared/provision/ # Write the command out to /mnt/shared/provision/
my $provision_file = $anvil->data->{path}{directories}{shared}{provision}."/".$server.".sh"; my $provision_file = $anvil->data->{path}{directories}{shared}{provision}."/".$server.".sh";
@ -1092,11 +1109,29 @@ sub create_lv
} }
else else
{ {
# Make sure we have enough space. # Make sure we have enough space. This checks on the local system as the other node could
# record less free space before we create our LV.
my $anvil_uuid = $anvil->data->{job}{anvil_uuid}; my $anvil_uuid = $anvil->data->{job}{anvil_uuid};
my $storage_group_uuid = $anvil->data->{job}{storage_group_uuid}; my $storage_group_uuid = $anvil->data->{job}{storage_group_uuid};
if ($anvil->data->{job}{storage_size} > $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size}) if ($anvil->data->{job}{storage_size} > $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size})
{ {
# How's the local storage?
$anvil->System->check_storage({debug => 2});
my $host_name = $anvil->Get->short_host_name();
my $host_uuid = $anvil->Get->host_uuid();
my $vg_name = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$host_uuid}{vg_name};
my $free_space = $anvil->data->{lvm}{$host_name}{vg}{$vg_name}{free_space};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:host_name' => $host_name,
's2:host_uuid' => $host_uuid,
's3:vg_name' => $vg_name,
's4:free_space' => $free_space." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $free_space}).")",
's5:job::storage_size' => $anvil->data->{job}{storage_size}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{job}{storage_size}}).")"
}});
if ((not $free_space) or ($free_space =~ /\D/) or ($anvil->data->{job}{storage_size} > $free_space))
{
# We're out.
my $say_available_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size}})." (".$anvil->Convert->add_commas({number => $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size}}).")"; my $say_available_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size}})." (".$anvil->Convert->add_commas({number => $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size}}).")";
my $say_requested_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{job}{storage_size}})." (".$anvil->Convert->add_commas({number => $anvil->data->{job}{storage_size}}).")"; my $say_requested_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{job}{storage_size}})." (".$anvil->Convert->add_commas({number => $anvil->data->{job}{storage_size}}).")";
my $say_storage_group = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{group_name}; my $say_storage_group = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{group_name};
@ -1113,6 +1148,7 @@ sub create_lv
}}); }});
$anvil->nice_exit({exit_code => 1}); $anvil->nice_exit({exit_code => 1});
} }
}
# Create the LV. # Create the LV.
my $host_uuid = $anvil->Get->host_uuid(); my $host_uuid = $anvil->Get->host_uuid();
@ -1248,6 +1284,13 @@ sub parse_job_data
{ {
$anvil->data->{job}{ram} = $1; $anvil->data->{job}{ram} = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'job::ram' => $anvil->data->{job}{ram} }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'job::ram' => $anvil->data->{job}{ram} }});
# If needed, convert the RAM to bytes.
if ($anvil->data->{job}{ram} =~ /\D/)
{
$anvil->data->{job}{ram} = $anvil->Convert->human_readable_to_bytes({debug => 2, size => $anvil->data->{job}{ram}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'job::ram' => $anvil->data->{job}{ram} }});
}
} }
if ($line =~ /storage_group_uuid=(.*)$/) if ($line =~ /storage_group_uuid=(.*)$/)
{ {
@ -1258,6 +1301,13 @@ sub parse_job_data
{ {
$anvil->data->{job}{storage_size} = $1; $anvil->data->{job}{storage_size} = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'job::storage_size' => $anvil->data->{job}{storage_size} }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'job::storage_size' => $anvil->data->{job}{storage_size} }});
# If needed, convert the disk size to bytes.
if ($anvil->data->{job}{storage_size} =~ /\D/)
{
$anvil->data->{job}{storage_size} = $anvil->Convert->human_readable_to_bytes({debug => 2, size => $anvil->data->{job}{storage_size}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'job::storage_size' => $anvil->data->{job}{storage_size} }});
}
} }
if ($line =~ /install_iso=(.*)$/) if ($line =~ /install_iso=(.*)$/)
{ {
@ -1514,12 +1564,10 @@ sub parse_job_data
return(0); return(0);
} }
# Go through a series of questions to ask the user how they want to build their server. sub check_anvil
sub interactive_question
{ {
my ($anvil) = @_; my ($anvil) = @_;
# If 'switches::anvil' is set, see if it's a UUID and then set either 'anvil-uuid' or 'anvil-name'.
if (($anvil->data->{switches}{anvil}) && (not $anvil->data->{switches}{'anvil-uuid'}) && (not $anvil->data->{switches}{'anvil-name'})) if (($anvil->data->{switches}{anvil}) && (not $anvil->data->{switches}{'anvil-uuid'}) && (not $anvil->data->{switches}{'anvil-name'}))
{ {
if ($anvil->Validate->uuid({uuid => $anvil->data->{switches}{anvil}})) if ($anvil->Validate->uuid({uuid => $anvil->data->{switches}{anvil}}))
@ -1569,6 +1617,17 @@ sub interactive_question
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "new_server::anvil_name" => $anvil->data->{new_server}{anvil_name} }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "new_server::anvil_name" => $anvil->data->{new_server}{anvil_name} }});
} }
return(0);
}
# Go through a series of questions to ask the user how they want to build their server.
sub interactive_question
{
my ($anvil) = @_;
# Process the anvil switch
check_anvil($anvil);
$anvil->data->{new_server}{name} = $anvil->data->{switches}{name} ? $anvil->data->{switches}{name} : ""; $anvil->data->{new_server}{name} = $anvil->data->{switches}{name} ? $anvil->data->{switches}{name} : "";
$anvil->data->{new_server}{uuid} = $anvil->data->{switches}{uuid} ? $anvil->data->{switches}{uuid} : ""; $anvil->data->{new_server}{uuid} = $anvil->data->{switches}{uuid} ? $anvil->data->{switches}{uuid} : "";
@ -2249,7 +2308,7 @@ sub interactive_ask_server_install_media
my $install_isos = [""]; my $install_isos = [""];
my $iso_list = ""; my $iso_list = "";
my $position = 0; my $position = 0;
foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{files}{file_name}}) foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}})
{ {
my $file_uuid = $anvil->data->{files}{file_name}{$file_name}{file_uuid}; my $file_uuid = $anvil->data->{files}{file_name}{$file_name}{file_uuid};
my $file_directory = $anvil->data->{files}{file_name}{$file_name}{file_directory}; my $file_directory = $anvil->data->{files}{file_name}{$file_name}{file_directory};
@ -2527,9 +2586,346 @@ sub interactive_ask_server_confirm
{ {
my ($anvil, $terminal) = @_; my ($anvil, $terminal) = @_;
# terminal isn't set with --ci-test set.
check_anvil($anvil);
$anvil->Database->get_anvils(); $anvil->Database->get_anvils();
$anvil->Database->get_files(); $anvil->Database->get_files();
$anvil->Database->get_file_locations(); $anvil->Database->get_file_locations();
if ($anvil->data->{switches}{'ci-test'})
{
### NOTE: Show available options;
# anvil-provision-server --ci-test --options
check_anvil($anvil);
if (not $anvil->data->{new_server}{anvil_uuid})
{
# Instantly fatal
print "Missing '--anvil <name_or_uuid>'\n";
$anvil->nice_exit({exit_code => 1});
}
my $anvil_uuid = $anvil->data->{new_server}{anvil_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }});
$anvil->Get->available_resources({anvil_uuid => $anvil_uuid, debug => 2});
$anvil->data->{new_server}{name} = "";
$anvil->data->{new_server}{uuid} = "";
$anvil->data->{new_server}{os} = "";
$anvil->data->{new_server}{cpu} = "";
$anvil->data->{new_server}{ram} = "";
$anvil->data->{new_server}{storage_group} = "";
$anvil->data->{new_server}{storage_size} = "";
$anvil->data->{new_server}{install_media} = "";
$anvil->data->{new_server}{driver_disc} = "";
my $problem = 0;
if (not $anvil->data->{switches}{name})
{
print "Missing '--name <server_name>'\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
if (not $anvil->data->{switches}{os})
{
print "Missing '--os <os_variant>', valid options match 'virt-install --os-variant' (run: 'osinfo-query os' and reference the 'Short ID' column).\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
else
{
# Make sure it's valid.
my $os_key = "os_list_".$anvil->data->{switches}{os};
my $os_name = $anvil->Words->string({key => $os_key});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
os_key => $os_key,
os_name => $os_name,
}});
if ($os_name =~ /#!not_found/)
{
print "The OS: [".$anvil->data->{switches}{os}."] was not found. If you're sure the OS is valid, please run 'striker-parse-os-list --xml --new' and add the output to 'words.xml'.\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
}
if (not $anvil->data->{switches}{cpu})
{
print "Missing '--cpu <1 ~ ".$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}.">'\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
elsif (($anvil->data->{switches}{cpu} =~ /\D/) or ($anvil->data->{switches}{cpu} > $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}) or ($anvil->data->{switches}{cpu} < 1))
{
print "The number of CPU cores: [".$anvil->data->{switches}{cpu}."] is invalid. Must be between 1 and ".$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}.".\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
my $max_ram = $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available};
my $say_max_ram = $anvil->Convert->bytes_to_human_readable({"bytes" => $max_ram});
my $requested_ram = $anvil->Convert->human_readable_to_bytes({
base2 => 1,
size => $anvil->data->{switches}{ram},
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
max_ram => $max_ram,
say_max_ram => $say_max_ram,
requested_ram => $requested_ram,
}});
if (not $anvil->data->{switches}{ram})
{
print "Missing '--ram <bytes or human readable, min is 64KiB, max is ".$say_max_ram.">'\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
elsif (($requested_ram eq "!!error!!") or
(not $requested_ram) or
($requested_ram < (640*1024)) or
($requested_ram > $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}))
{
# Invalid
print "The requested RAM: [".$anvil->data->{switches}{ram}."] is not valid. Must be between: [64KiB] and: [".$say_max_ram."]\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
my $max_storage_group_size = 0;
my $storage_group_uuid = "";
if (not $anvil->data->{switches}{'storage-group'})
{
print "Missing '--storage-group <name or uuid>. Valid options are:'\n" if not $anvil->data->{switches}{options};
foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{anvil_resources}{$anvil_uuid}{storage_group_name}})
{
print "- Name: [".$storage_group_name."], UUID: [".$anvil->data->{anvil_resources}{$anvil_uuid}{storage_group_name}{$storage_group_name}{storage_group_uuid}."]\n" if not $anvil->data->{switches}{options};
}
$problem = 1;
}
else
{
# Make sure it's valid.
my $storage_group = $anvil->data->{switches}{'storage-group'};
if (exists $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group_name}{$storage_group})
{
$storage_group_uuid = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group_name}{$storage_group}{storage_group_uuid};
$max_storage_group_size = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
storage_group_uuid => $storage_group_uuid,
max_storage_group_size => $max_storage_group_size." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $max_storage_group_size}).")",
}});
}
elsif (exists $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group})
{
$storage_group_uuid = $storage_group;
$max_storage_group_size = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
storage_group_uuid => $storage_group_uuid,
max_storage_group_size => $max_storage_group_size." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $max_storage_group_size}).")",
}});
}
else
{
# Invalid
print "- The requested storage group: [".$storage_group."] does not appear to be valid. Valid options are;\n" if not $anvil->data->{switches}{options};
foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{anvil_resources}{$anvil_uuid}{storage_group_name}})
{
print "- Name: [".$storage_group_name."], UUID: [".$anvil->data->{anvil_resources}{$anvil_uuid}{storage_group_name}{$storage_group_name}{storage_group_uuid}."]\n" if not $anvil->data->{switches}{options};
}
$problem = 1;
}
}
my $say_max_storage_group_size = $max_storage_group_size ? $anvil->Convert->bytes_to_human_readable({"bytes" => $max_storage_group_size}) : "";
if (not $anvil->data->{switches}{'storage-size'})
{
if ($max_storage_group_size)
{
print "Missing '--storage-size <bytes or human readable. max is ".$say_max_storage_group_size.">'\n" if not $anvil->data->{switches}{options};
}
else
{
print "Missing '--storage-size <bytes or human readable>. Max will depend on selected --storage-group.'\n" if not $anvil->data->{switches}{options};
}
$problem = 1;
}
else
{
my $requested_disk = $anvil->Convert->human_readable_to_bytes({
base2 => 1,
size => $anvil->data->{switches}{'storage-size'},
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { requested_disk => $requested_disk }});
if (($requested_disk eq "!!error!!") or
($requested_disk < (10*(2**20))) or
($requested_disk > $max_storage_group_size))
{
# Invalid
print "The requested disk size: [".$anvil->data->{switches}{'storage-size'}."] is not valid. Must be between: [10MiB] and: [".$say_max_storage_group_size."]\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
}
if ($anvil->Validate->uuid({uuid => $anvil->data->{switches}{uuid}}))
{
$anvil->data->{new_server}{uuid} = $anvil->data->{switches}{uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'new_server::uuid' => $anvil->data->{new_server}{uuid},
}});
}
if (not $anvil->data->{switches}{'install-media'})
{
print "Missing '--install-media <file name or file_uuid>'\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
else
{
# Make sure the file is valid
my $found = 0;
foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}})
{
my $file_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid};
my $file_type = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type};
my $file_directory = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory};
if ($file_name eq $anvil->data->{switches}{'install-media'})
{
# Found it.
$found = 1;
if ($file_type eq "iso")
{
# We're good
$anvil->data->{new_server}{install_media} = $file_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'new_server::install_media' => $anvil->data->{new_server}{install_media},
}});
}
else
{
# Not an ISO.
print "The install file: [".$anvil->data->{switches}{'install-media'}."] is not an ISO, so it can't be used to install.\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
}
last if $found;
}
if (not $found)
{
print "The install file: [".$anvil->data->{switches}{'install-media'}."] was not found on this Anvil!.\n" if not $anvil->data->{switches}{options};
print "Is it in '/mnt/shared/files/' and are the daemons running?\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
}
if ($anvil->data->{switches}{'driver-disc'})
{
# Make sure it exists
my $found = 0;
foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}})
{
my $file_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid};
my $file_type = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type};
my $file_directory = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory};
if ($file_name eq $anvil->data->{switches}{'driver-disc'})
{
# Found it.
$found = 1;
if ($file_type eq "iso")
{
# We're good
$anvil->data->{new_server}{driver_disc} = $file_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'new_server::driver_disc' => $anvil->data->{new_server}{driver_disc},
}});
}
else
{
# Not an ISO.
print "The driver file: [".$anvil->data->{switches}{'driver-disc'}."] is not an ISO, so it can't be used as an optical disc.\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
}
last if $found;
}
if (not $found)
{
print "The driver file: [".$anvil->data->{switches}{'driver-disc'}."] was not found on this Anvil!.\n" if not $anvil->data->{switches}{options};
print "Is it in '/mnt/shared/files/' and are the daemons running?\n" if not $anvil->data->{switches}{options};
$problem = 1;
}
}
if ($anvil->data->{switches}{options})
{
if ($anvil->data->{switches}{machine})
{
print "# Sizes are in bytes\n";
print "ram:min=65536,max=".$max_ram."\n";
print "cpu:min=1,max=".$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}."\n";
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->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_name}{$storage_group_name}{storage_group_uuid};
print "storage_group:name=".$storage_group_name.",uuid=".$anvil->data->{anvil_resources}{$anvil_uuid}{storage_group_name}{$storage_group_name}{storage_group_uuid}.",free_space=".$anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size}."\n";
}
foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}})
{
my $file_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid};
my $file_type = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type};
my $file_size = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:file_name' => $file_name,
's2:file_uuid' => $file_uuid,
's3:file_type' => $file_type,
's4:file_size' => $file_size,
}});
next if $file_type ne "iso";
my $say_size = $anvil->Convert->bytes_to_human_readable({"bytes" => $file_size});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_size => $say_size }});
print "iso_file:name=".$file_name.",uuid=".$file_uuid.",size=".$say_size."\n";
}
}
else
{
# Show valid options to build a VM in a machine-parsable way.
print "Available options
--name - alphanumeric, 1~16 characters long.
--os - Valid options; run: 'osinfo-query os' and reference the 'Short ID' column.
--cpu - 1 ~ ".$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}."
--ram - bytes or human readable, min is 64KiB, max is ".$say_max_ram."
--storage-group - name or uuid. Valid options are:\n";
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->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_name}{$storage_group_name}{storage_group_uuid};
my $max_storage_group_size = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size};
my $say_max_storage_group_size = $anvil->Convert->bytes_to_human_readable({"bytes" => $max_storage_group_size});
print " - Name: [".$storage_group_name."], UUID: [".$anvil->data->{anvil_resources}{$anvil_uuid}{storage_group_name}{$storage_group_name}{storage_group_uuid}."], free space: [".$say_max_storage_group_size."]\n";
}
print " --storage-size - Disk size, see above for space available
--install-media - file name or file UUID. Available discs are:\n";
foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}})
{
my $file_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid};
my $file_type = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type};
my $file_size = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size};
next if $file_type ne "iso";
my $say_size = $anvil->Convert->bytes_to_human_readable({"bytes" => $file_size});
print " - File name: [".$file_name."], file UUID: [".$file_uuid."], size: [".$say_size."]\n";
}
print " --driver-disc - (optional) A driver disc to be added as a second optical drive. Valid options are above.\n";
}
$anvil->nice_exit({exit_code => 0});
}
if ($problem)
{
$anvil->nice_exit({exit_code => 1});
}
# Save the values.
$anvil->data->{new_server}{name} = $anvil->data->{switches}{name};
$anvil->data->{new_server}{os} = $anvil->data->{switches}{os};
$anvil->data->{new_server}{cpu} = $anvil->data->{switches}{cpu};
$anvil->data->{new_server}{ram} = $anvil->data->{switches}{ram};
$anvil->data->{new_server}{storage_group} = $storage_group_uuid;
$anvil->data->{new_server}{storage_size} = $anvil->data->{switches}{'storage-size'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:new_server::name' => $anvil->data->{new_server}{name},
's1:new_server::uuid' => $anvil->data->{new_server}{uuid},
's2:new_server::os' => $anvil->data->{new_server}{os},
's3:new_server::cpu' => $anvil->data->{new_server}{cpu},
's4:new_server::ram' => $anvil->data->{new_server}{ram},
's5:new_server::storage_group' => $anvil->data->{new_server}{storage_group},
's6:new_server::storage_size' => $anvil->data->{new_server}{storage_size}." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $max_storage_group_size}).")",
's7:new_server::install_media' => $anvil->data->{new_server}{install_media},
's8:new_server::driver_disc' => $anvil->data->{new_server}{driver_disc},
}});
}
my $anvil_uuid = $anvil->data->{new_server}{anvil_uuid}; my $anvil_uuid = $anvil->data->{new_server}{anvil_uuid};
my $node1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; my $node1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid};
@ -2542,6 +2938,8 @@ sub interactive_ask_server_confirm
my $driver_disc_file_uuid = $anvil->data->{new_server}{driver_disc}; my $driver_disc_file_uuid = $anvil->data->{new_server}{driver_disc};
my $say_driver_disc = $driver_disc_file_uuid eq "none" ? "#!string!unit_0005!#" : $anvil->data->{files}{file_uuid}{$driver_disc_file_uuid}{file_name}; my $say_driver_disc = $driver_disc_file_uuid eq "none" ? "#!string!unit_0005!#" : $anvil->data->{files}{file_uuid}{$driver_disc_file_uuid}{file_name};
if (not $anvil->data->{switches}{'ci-test'})
{
print $terminal->Tputs('cl'); print $terminal->Tputs('cl');
print $anvil->Words->string({key => "job_0150"})."\n"; print $anvil->Words->string({key => "job_0150"})."\n";
print $anvil->Words->string({key => "job_0151", variables => { anvil_name => $anvil->data->{new_server}{anvil_name} }})."\n"; print $anvil->Words->string({key => "job_0151", variables => { anvil_name => $anvil->data->{new_server}{anvil_name} }})."\n";
@ -2559,9 +2957,14 @@ sub interactive_ask_server_confirm
$answer = "y" if $answer eq ""; $answer = "y" if $answer eq "";
if ($answer =~ /^y/i) if ($answer !~ /^y/i)
{ {
# Valid. # Abort
print $anvil->Words->string({key => "message_0022"})."\n";
$anvil->nice_exit({exit_code => 0});
}
}
my $job_data = "server_name=".$anvil->data->{new_server}{name}." my $job_data = "server_name=".$anvil->data->{new_server}{name}."
os=".$anvil->data->{new_server}{os}." os=".$anvil->data->{new_server}{os}."
cpu_cores=".$anvil->data->{new_server}{cpu}." cpu_cores=".$anvil->data->{new_server}{cpu}."
@ -2573,7 +2976,7 @@ driver_iso=".$anvil->data->{new_server}{driver_disc};
if ($anvil->data->{new_server}{uuid}) if ($anvil->data->{new_server}{uuid})
{ {
$job_data .= " $job_data .= "
server_uuid=".$anvil->data->{new_server}{name}; server_uuid=".$anvil->data->{new_server}{uuid};
} }
print "\n".$anvil->Words->string({key => "job_0183", variables => { job_data => $job_data }})."\n"; print "\n".$anvil->Words->string({key => "job_0183", variables => { job_data => $job_data }})."\n";
@ -2598,12 +3001,6 @@ server_uuid=".$anvil->data->{new_server}{name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }});
print $anvil->Words->string({key => "job_0184", variables => { job_uuid => $job_uuid }})."\n"; print $anvil->Words->string({key => "job_0184", variables => { job_uuid => $job_uuid }})."\n";
}
else
{
# Abort
print $anvil->Words->string({key => "message_0022"})."\n";
}
return(0); return(0);
} }

@ -0,0 +1,73 @@
#!/usr/bin/perl
#
use strict;
use warnings;
use Anvil::Tools;
use Data::Dumper;
# Disable buffering
$| = 1;
# Prevent a discrepency between UID/GID and EUID/EGID from throwing an error.
$< = $>;
$( = $);
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
if (($running_directory =~ /^\./) && ($ENV{PWD}))
{
$running_directory =~ s/^\./$ENV{PWD}/;
}
my $anvil = Anvil::Tools->new();
# Make sure we're running as 'root'
# $< == real UID, $> == effective UID
if (($< != 0) && ($> != 0))
{
# Not root
print $anvil->Words->string({key => "error_0005"})."\n";
$anvil->nice_exit({exit_code => 1});
}
$anvil->data->{switches}{level} = "";
$anvil->data->{switches}{message} = "";
$anvil->Get->switches;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0115", variables => { program => $THIS_FILE }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'switches::level' => $anvil->data->{switches}{level},
'switches::message' => $anvil->data->{switches}{message},
}});
my $level = "";
if (($anvil->data->{switches}{level} eq "1") or (lc($anvil->data->{switches}{level}) eq "critical"))
{
$level = "critical";
}
elsif (($anvil->data->{switches}{level} eq "2") or (lc($anvil->data->{switches}{level}) eq "warning"))
{
$level = "warning";
}
elsif (($anvil->data->{switches}{level} eq "3") or (lc($anvil->data->{switches}{level}) eq "notice"))
{
$level = "notice";
}
elsif (($anvil->data->{switches}{level} eq "4") or (lc($anvil->data->{switches}{level}) eq "info"))
{
$level = "info";
}
if ((not $anvil->data->{switches}{level}) or (not $level))
{
print $anvil->Words->string({key => "error_0362", variables => { level => $anvil->data->{switches}{level} }})."\n";
$anvil->nice_exit({exit_code => 1});
}
$anvil->nice_exit({exit_code => 0});
#############################################################################################################
# Functions #
#############################################################################################################

@ -68,10 +68,21 @@ $anvil->data->{scancore} = {
$anvil->Storage->read_config(); $anvil->Storage->read_config();
# Read switches # Read switches
$anvil->data->{switches}{purge} = "";
$anvil->data->{switches}{'run-once'} = ""; $anvil->data->{switches}{'run-once'} = "";
$anvil->Get->switches; $anvil->Get->switches;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0115", variables => { program => $THIS_FILE }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0115", variables => { program => $THIS_FILE }});
# If purging, also set 'run-once'.
if ($anvil->data->{switches}{purge})
{
$anvil->data->{switches}{'run-once'} = 1;
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"switches::purge" => $anvil->data->{switches}{purge},
"switches::run-once" => $anvil->data->{switches}{'run-once'},
}});
# Calculate my sum so that we can exit if it changes later. # Calculate my sum so that we can exit if it changes later.
$anvil->Storage->record_md5sums(); $anvil->Storage->record_md5sums();

@ -195,7 +195,7 @@ if ($local_uuid)
foreach my $line (split/\n/, $pg_hba_conf) foreach my $line (split/\n/, $pg_hba_conf)
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
if ($line =~ /^host\s+all\s+all\s+\all\s+md5$/) if ($line =~ /^host\s+all\s+all\s+all\s+md5$/)
{ {
# No need to update. # No need to update.
$update_file = 0; $update_file = 0;

Loading…
Cancel
Save