* Got the 'anvil-provision-server' script to the point where it actually saves the new server job.

* Created the new method Cluster->get_primary_host_uuid() that returns the 'host_uuid' of the primary node in the given cluster. This is useful for external programs to figure out which node is primary. Example is provisioning a new server being assigned to the active node. Also created ->is_primary() that is a similar test to see if the active node is the primary node or not.
* Updated Cluster->parse_cib() and ->parse_crm_mon() to work on remote hosts.
* Updated Database->get_hosts() to store the short host names.
* Created Get->host_from_ip_address() that translates an IP address to a host_uuid and host_name, if it's an IP assigned currently to a known host.
* Created Network->find_target_ip() that simplifies finding which IP address to use when the caller wants to connect to a target host.
* Reworked the anvil-join-anvil to parse fence_arguments in a way that handles passwords with spaces in them.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 4 years ago
parent 68ea6da1d3
commit a7f0676a0f
  1. 1
      Anvil/Tools.pm
  2. 518
      Anvil/Tools/Cluster.pm
  3. 31
      Anvil/Tools/Database.pm
  4. 76
      Anvil/Tools/Get.pm
  5. 85
      Anvil/Tools/Network.pm
  6. 3
      html/skins/alteeve/anvil.html
  7. 4
      html/skins/alteeve/files.html
  8. 65
      share/words.xml
  9. 21
      tools/anvil-join-anvil
  10. 633
      tools/anvil-provision-server
  11. 74
      tools/anvil-sync-shared
  12. 54
      tools/test.pl

@ -1084,6 +1084,7 @@ sub _set_paths
'anvil-manage-keys' => "/usr/sbin/anvil-manage-keys", 'anvil-manage-keys' => "/usr/sbin/anvil-manage-keys",
'anvil-manage-power' => "/usr/sbin/anvil-manage-power", 'anvil-manage-power' => "/usr/sbin/anvil-manage-power",
'anvil-parse-fence-agents' => "/usr/sbin/anvil-parse-fence-agents", 'anvil-parse-fence-agents' => "/usr/sbin/anvil-parse-fence-agents",
'anvil-provision-server' => "/usr/sbib/anvil-provision-server",
'anvil-report-memory' => "/usr/sbin/anvil-report-memory", 'anvil-report-memory' => "/usr/sbin/anvil-report-memory",
'anvil-sync-shared' => "/usr/sbin/anvil-sync-shared", 'anvil-sync-shared' => "/usr/sbin/anvil-sync-shared",
'anvil-update-files' => "/usr/sbin/anvil-update-files", 'anvil-update-files' => "/usr/sbin/anvil-update-files",

@ -20,6 +20,8 @@ my $THIS_FILE = "Cluster.pm";
# get_anvil_name # get_anvil_name
# get_anvil_uuid # get_anvil_uuid
# get_peers # get_peers
# get_primary_host_uuid
# is_primary
# migrate_server # migrate_server
# parse_cib # parse_cib
# shutdown_server # shutdown_server
@ -797,6 +799,364 @@ sub get_peers
} }
=head2 get_primary_host_uuid
This takes an Anvil! UUID and returns with node is currently the "primary" node. That is to say, which node has the most servers running on it, by allocated RAM. For example, if node 1 has two servers, each with 8 GiB of RAN and node 2 has one VM with 32 GiB of RAM, node 2 will be considered primary as it would take longest to migrate servers off.
If all is equal, node 1 is considered primary. If only one node is a cluster member, it is considered primary. If neither node is up, an empty string is returned.
Parameters;
=head3 anvil_uuid (optional, default Cluster->get_anvil_uuid)
This is the Anvil! UUID we're looking for the primary node in.
=cut
sub get_primary_host_uuid
{
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 => "Cluster->get_primary_host_uuid()" }});
my $anvil_uuid = defined $parameter->{anvil_uuid} ? $parameter->{anvil_uuid} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
anvil_uuid => $anvil_uuid,
}});
if (not $anvil_uuid)
{
my $anvil_uuid = $anvil->Cluster->get_anvil_uuid({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { anvil_uuid => $anvil_uuid }});
}
if (not $anvil_uuid)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Cluster->get_primary_host_uuid()", parameter => "anvil_uuid" }});
return("");
}
# Get the two node UUIDs.
$anvil->Database->get_anvils({debug => $debug});
if (not exists $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid})
{
# Invalid Anvil! UUID.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0169", variables => { anvil_uuid => $anvil_uuid }});
return("");
}
my $node1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid};
my $node1_target_ip = $anvil->Network->find_target_ip({debug => $debug, host_uuid => $node1_host_uuid});
my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
my $node2_target_ip = $anvil->Network->find_target_ip({debug => $debug, host_uuid => $node2_host_uuid});
my $password = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
node1_host_uuid => $node1_host_uuid,
node1_target_ip => $node1_target_ip,
node2_host_uuid => $node2_host_uuid,
node2_target_ip => $node2_target_ip,
password => $anvil->Log->is_secure($password),
}});
# Are the nodes up?
my $node1_access = $anvil->Remote->test_access({
debug => $debug,
target => $node1_target_ip,
password => $password,
});
my $node2_access = $anvil->Remote->test_access({
debug => $debug,
target => $node2_target_ip,
password => $password,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
node1_access => $node1_access,
node2_access => $node2_access,
}});
# Can we parse the CIB from node 1?
my $cib_from = "";
if ($node1_access)
{
my $problem = $anvil->Cluster->parse_cib({
debug => $debug,
target => $node1_target_ip,
password => $password,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }});
if (not $problem)
{
$cib_from = "node1";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { cib_from => $cib_from }});
}
elsif ($node2_access)
{
# Try to read the CIB from node 2.
my $problem = $anvil->Cluster->parse_cib({
debug => $debug,
target => $node2_target_ip,
password => $password,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }});
if (not $problem)
{
$cib_from = "node2";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { cib_from => $cib_from }});
}
}
}
# If we failed to load the CIB, we're done.
if (not $cib_from)
{
return("");
}
# Is the node we got the CIB from fully in the cluster?
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"cib::parsed::local::ready" => $anvil->data->{cib}{parsed}{'local'}{ready},
"cib::parsed::peer::ready" => $anvil->data->{cib}{parsed}{peer}{ready},
}});
if (($anvil->data->{cib}{parsed}{'local'}{ready}) && (not $anvil->data->{cib}{parsed}{peer}{ready}))
{
# The node we got the CIB from is ready, the other node is not.
if ($cib_from eq "node1")
{
# Node 1 is primary
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { node1_host_uuid => $node1_host_uuid }});
return($node1_host_uuid);
}
else
{
# Node 2 is primary
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { node2_host_uuid => $node2_host_uuid }});
return($node2_host_uuid);
}
}
elsif ((not $anvil->data->{cib}{parsed}{'local'}{ready}) && ($anvil->data->{cib}{parsed}{peer}{ready}))
{
# Opposite; the other node is ready and the node we read from was not.
if ($cib_from eq "node1")
{
# Node 2 is primary
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { node2_host_uuid => $node2_host_uuid }});
return($node2_host_uuid);
}
else
{
# Node 1 is primary
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { node1_host_uuid => $node1_host_uuid }});
return($node1_host_uuid);
}
}
# Still alive? Both nodes are in the cluster. Start counting RAM allocated to servers.
my $node1_ram_in_use_by_servers = 0;
my $node2_ram_in_use_by_servers = 0;
# Loop through servers.
foreach my $server_name (sort {$a cmp $b} keys %{$anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}})
{
my $server_uuid = $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$server_name}{server_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
server_name => $server_name,
server_uuid => $server_uuid,
}});
my $server_host_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_host_uuid};
my $server_state = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state};
my $server_ram_in_use = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_ram_in_use};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
server_host_uuid => $server_host_uuid,
server_state => $server_state,
server_ram_in_use => $server_ram_in_use." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $server_ram_in_use}).")"
}});
next if $server_state ne "running";
if ($server_host_uuid eq $node1_host_uuid)
{
$node1_ram_in_use_by_servers += $server_ram_in_use;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
node1_ram_in_use_by_servers => $node1_ram_in_use_by_servers." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $node1_ram_in_use_by_servers}).")"
}});
}
elsif ($server_host_uuid eq $node2_host_uuid)
{
$node2_ram_in_use_by_servers += $server_ram_in_use;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
node2_ram_in_use_by_servers => $node2_ram_in_use_by_servers." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $node2_ram_in_use_by_servers}).")"
}});
}
}
# if we're node 1 and have equal RAM, or we have more RAM, we're primary.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
node1_ram_in_use_by_servers => $node1_ram_in_use_by_servers." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $node1_ram_in_use_by_servers}).")",
node2_ram_in_use_by_servers => $node2_ram_in_use_by_servers." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $node2_ram_in_use_by_servers}).")",
}});
if (($node1_ram_in_use_by_servers == $node2_ram_in_use_by_servers) or
($node1_ram_in_use_by_servers > $node2_ram_in_use_by_servers))
{
# Matching RAM, node 1 wins, or node 1 has more RAM.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { node1_host_uuid => $node1_host_uuid }});
return($node1_host_uuid);
}
else
{
# Node 2 has more RAM in use, it's primary
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { node2_host_uuid => $node2_host_uuid }});
return($node2_host_uuid);
}
# This should never be hit
return("");
}
=head2 is_primary
This methid returns C<< 1 >> if the caller is the "primary" node in the cluster, C<< 0 >> in all other cases.
"Primary", in this context, means;
" The node that is running the servers.
" If both nodes are running servers, then the node with the most active RAM (summed from the RAM allocated to running servers) is deemed "primary" (would take the longest to migrate servers off).
" If both nodes have no servers, or the amount of RAM allocated to running servers is the same, node 1 is deemed primary.
" If only one node is up, it is deemed primary.
This method takes no parameters.
=cut
sub is_primary
{
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 => "Cluster->is_primary()" }});
my $host_uuid = $anvil->Get->host_uuid({debug => $debug});
my $host_type = $anvil->Get->host_type({debug => $debug});
my $anvil_uuid = $anvil->Cluster->get_anvil_uuid({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
host_uuid => $host_uuid,
host_type => $host_type,
anvil_uuid => $anvil_uuid,
}});
if ($host_type ne "node")
{
# Not a node? not primary.
return(0);
}
if (not $anvil_uuid)
{
# Not an Anvil! member, so, ya...
return(0);
}
# Are we in the cluster? If not, we're not primary.
my $problem = $anvil->Cluster->parse_cib({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }});
if ($problem)
{
# Nope.
return(0);
}
# Is this node fully in the cluster?
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"cib::parsed::local::ready" => $anvil->data->{cib}{parsed}{'local'}{ready},
}});
if (not $anvil->data->{cib}{parsed}{'local'}{ready})
{
# Nope.
return(0);
}
# Still alive? Excellent! What state is our peer in?
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"cib::parsed::peer::ready" => $anvil->data->{cib}{parsed}{peer}{ready},
}});
if (not $anvil->data->{cib}{parsed}{peer}{ready})
{
# Our peer is not ready, so we're primary
return(1);
}
# If we're alive, both we and our peer is online. Who is primary?
$anvil->Cluster->get_peers();
my $peer_is = $anvil->data->{sys}{anvil}{peer_is};
my $my_host_uuid = $anvil->Get->host_uuid;
my $peer_host_uuid = $peer_is eq "node2" ? $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid} : $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
peer_is => $peer_is,
my_host_uuid => $my_host_uuid,
peer_host_uuid => $peer_host_uuid,
}});
my $my_ram_in_use_by_servers = 0;
my $peer_ram_in_use_by_servers = 0;
# Loop through servers.
foreach my $server_name (sort {$a cmp $b} keys %{$anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}})
{
my $server_uuid = $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$server_name}{server_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
server_name => $server_name,
server_uuid => $server_uuid,
}});
my $server_host_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_host_uuid};
my $server_state = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state};
my $server_ram_in_use = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_ram_in_use};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
server_host_uuid => $server_host_uuid,
server_state => $server_state,
server_ram_in_use => $server_ram_in_use." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $server_ram_in_use}).")"
}});
next if $server_state ne "running";
if ($server_host_uuid eq $my_host_uuid)
{
$my_ram_in_use_by_servers += $server_ram_in_use;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
my_ram_in_use_by_servers => $my_ram_in_use_by_servers." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $my_ram_in_use_by_servers}).")"
}});
}
elsif ($server_host_uuid eq $peer_host_uuid)
{
$peer_ram_in_use_by_servers += $server_ram_in_use;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
peer_ram_in_use_by_servers => $peer_ram_in_use_by_servers." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $peer_ram_in_use_by_servers}).")"
}});
}
}
# if we're node 1 and have equal RAM, or we have more RAM, we're primary.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
my_ram_in_use_by_servers => $my_ram_in_use_by_servers." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $my_ram_in_use_by_servers}).")",
peer_ram_in_use_by_servers => $peer_ram_in_use_by_servers." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $peer_ram_in_use_by_servers}).")",
}});
if (($my_ram_in_use_by_servers == $peer_ram_in_use_by_servers) && ($peer_is eq "node2"))
{
# Matching RAM and we're node 1, so we're primary.
return(1);
}
elsif ($my_ram_in_use_by_servers > $peer_ram_in_use_by_servers)
{
# More RAM allocated to us than our peer, we're primary.
return(1);
}
# Any other condition, and we're not primary.
return(0);
}
=head2 migrate_server =head2 migrate_server
This manipulates pacemaker's location constraints to trigger a pacemaker-controlled migration of one or more servers. This manipulates pacemaker's location constraints to trigger a pacemaker-controlled migration of one or more servers.
@ -984,14 +1344,15 @@ sub migrate_server
} }
} }
return(0); return(0);
} }
=head2 parse_cib =head2 parse_cib
This reads in the CIB XML and parses it. On success, it returns C<< 0 >>. On failure (ie: pcsd isn't running), returns C<< 1 >>. This reads in the CIB XML and parses it from a local or remote system. On success, it returns C<< 0 >>. On failure (ie: pcsd isn't running), returns C<< 1 >>.
If you call this against a remote machine, the data will be loaded the same as if it had been run locally. As such, if this is used from a Striker, be mindful of if it was called on Node 1 or 2.
Parameters; Parameters;
@ -1001,6 +1362,22 @@ B<< Note >>: Generally this should not be used.
By default, the CIB is read by calling C<< pcs cluster cib >>. However, this parameter can be used to pass in a CIB instead. If this is set, the live CIB is B<< NOT >> read. By default, the CIB is read by calling C<< pcs cluster cib >>. However, this parameter can be used to pass in a CIB instead. If this is set, the live CIB is B<< NOT >> read.
=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.
=head3 port (optional)
This is the TCP port to use when connecting to a remote machine. If not set, but C<< target >> is, C<< 22 >> will be used.
=head3 remote_user (optional, default root)
If C<< target >> is set, this will be the user we connect to the remote machine as.
=head3 target (optional)
This is the IP or host name of the machine to read the version of. If this is not set, the local system's version is checked.
=cut =cut
sub parse_cib sub parse_cib
{ {
@ -1010,9 +1387,17 @@ sub parse_cib
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Cluster->parse_cib()" }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Cluster->parse_cib()" }});
my $cib = defined $parameter->{cib} ? $parameter->{cib} : ""; my $cib = defined $parameter->{cib} ? $parameter->{cib} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { my $password = defined $parameter->{password} ? $parameter->{password} : "";
cib => $cib, 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 => {
cib => $cib,
password => $anvil->Log->is_secure($password),
port => $port,
remote_user => $remote_user,
target => $target,
}}); }});
# If we parsed before, delete it. # If we parsed before, delete it.
@ -1039,11 +1424,32 @@ sub parse_cib
my $shell_call = $anvil->data->{path}{exe}{pcs}." cluster cib"; my $shell_call = $anvil->data->{path}{exe}{pcs}." cluster cib";
$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 }});
($cib_data, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call}); if ($anvil->Network->is_local({host => $target}))
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { {
cib_data => $cib_data, # Local call
return_code => $return_code, ($cib_data, $return_code) = $anvil->System->call({debug => $debug, shell_call => $shell_call});
}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
cib_data => $cib_data,
return_code => $return_code,
}});
}
else
{
# Remote call.
($cib_data, my $error, $return_code) = $anvil->Remote->call({
debug => $debug,
shell_call => $shell_call,
target => $target,
port => $port,
password => $password,
remote_user => $remote_user,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
error => $error,
cib_data => $cib_data,
return_code => $return_code,
}});
}
} }
if ($return_code) if ($return_code)
{ {
@ -1376,10 +1782,35 @@ sub parse_cib
"cib::parsed::data::node::${node_name}::node_state::ready" => $anvil->data->{cib}{parsed}{data}{node}{$node_name}{node_state}{ready}, "cib::parsed::data::node::${node_name}::node_state::ready" => $anvil->data->{cib}{parsed}{data}{node}{$node_name}{node_state}{ready},
}}); }});
# Is this me or the peer? # Is this me or the peer? Or if we're being called remotely, is the target (the short host
if (($node_name eq $anvil->Get->host_name) or ($node_name eq $anvil->Get->short_host_name)) # name) the same?
my $target_host_uuid = "";
my $target_host_name = "";
my $target_short_host_name = "";
if ($target)
{ {
# Me. ($target_host_uuid, $target_host_name) = $anvil->Get->host_from_ip_address({
debug => $debug,
ip_address => $target,
});
$target_short_host_name = $target_host_name;
$target_short_host_name =~ s/\..*$//;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
target_host_uuid => $target_host_uuid,
target_host_name => $target_host_name,
target_short_host_name => $target_short_host_name,
}});
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
node_name => $node_name,
target => $target,
target_short_host_name => $target_short_host_name,
}});
if (($node_name eq $anvil->Get->host_name) or
($node_name eq $anvil->Get->short_host_name) or
(($target_short_host_name) && ($node_name =~ /^$target_short_host_name/)))
{
# Me (or the node the CIB was read from).
$anvil->data->{cib}{parsed}{'local'}{ready} = $node_name; $anvil->data->{cib}{parsed}{'local'}{ready} = $node_name;
$anvil->data->{cib}{parsed}{'local'}{name} = $node_name; $anvil->data->{cib}{parsed}{'local'}{name} = $node_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
@ -1540,7 +1971,13 @@ sub parse_cib
# Now call 'crm_mon --output-as=xml' to determine which resource are running where. As of the time # Now call 'crm_mon --output-as=xml' to determine which resource are running where. As of the time
# of writting this (late 2020), stopped resources are not displayed. So the principle purpose of this # of writting this (late 2020), stopped resources are not displayed. So the principle purpose of this
# call is to determine what resources are running, and where they are running. # call is to determine what resources are running, and where they are running.
$anvil->Cluster->parse_crm_mon({debug => $debug}); $anvil->Cluster->parse_crm_mon({
debug => $debug,
password => $anvil->Log->is_secure($password),
port => $port,
remote_user => $remote_user,
target => $target,
});
foreach my $server (sort {$a cmp $b} keys %{$anvil->data->{crm_mon}{parsed}{'pacemaker-result'}{resources}{resource}}) foreach my $server (sort {$a cmp $b} keys %{$anvil->data->{crm_mon}{parsed}{'pacemaker-result'}{resources}{resource}})
{ {
my $host_name = $anvil->data->{crm_mon}{parsed}{'pacemaker-result'}{resources}{resource}{$server}{host}{node_name}; my $host_name = $anvil->data->{crm_mon}{parsed}{'pacemaker-result'}{resources}{resource}{$server}{host}{node_name};
@ -1655,6 +2092,22 @@ B<< Note >>: At this time, this method only pulls out the host for running serve
Parameters; Parameters;
=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.
=head3 port (optional)
This is the TCP port to use when connecting to a remote machine. If not set, but C<< target >> is, C<< 22 >> will be used.
=head3 remote_user (optional, default root)
If C<< target >> is set, this will be the user we connect to the remote machine as.
=head3 target (optional)
This is the IP or host name of the machine to read the version of. If this is not set, the local system's version is checked.
=head3 xml (optional) =head3 xml (optional)
B<< Note >>: Generally this should not be used. B<< Note >>: Generally this should not be used.
@ -1670,7 +2123,11 @@ sub parse_crm_mon
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Cluster->parse_crm_mon()" }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Cluster->parse_crm_mon()" }});
my $xml = defined $parameter->{xml} ? $parameter->{xml} : ""; my $xml = defined $parameter->{xml} ? $parameter->{xml} : "";
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->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
xml => $xml, xml => $xml,
}}); }});
@ -1688,11 +2145,32 @@ sub parse_crm_mon
my $shell_call = $anvil->data->{path}{exe}{crm_mon}." --output-as=xml"; my $shell_call = $anvil->data->{path}{exe}{crm_mon}." --output-as=xml";
$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 }});
($crm_mon_data, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call}); if ($anvil->Network->is_local({host => $target}))
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { {
crm_mon_data => $crm_mon_data, # Local call
return_code => $return_code, ($crm_mon_data, $return_code) = $anvil->System->call({debug => $debug, shell_call => $shell_call});
}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
crm_mon_data => $crm_mon_data,
return_code => $return_code,
}});
}
else
{
# Remote call.
($crm_mon_data, my $error, $return_code) = $anvil->Remote->call({
debug => $debug,
shell_call => $shell_call,
target => $target,
port => $port,
password => $password,
remote_user => $remote_user,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
error => $error,
crm_mon_data => $crm_mon_data,
return_code => $return_code,
}});
}
} }
if ($return_code) if ($return_code)
{ {

@ -2664,20 +2664,25 @@ FROM
modified_date => $modified_date, modified_date => $modified_date,
}; };
my $short_host_name = $host_name;
$short_host_name =~ s/\..*$//;
# Record the data in the hash, too. # Record the data in the hash, too.
$anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name} = $host_name; $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name} = $host_name;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type} = $host_type; $anvil->data->{hosts}{host_uuid}{$host_uuid}{short_host_name} = $short_host_name;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key} = $host_key; $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type} = $host_type;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi} = $host_ipmi; $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key} = $host_key;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_name} = $anvil_name; $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi} = $host_ipmi;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_uuid} = $anvil_uuid; $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_name} = $anvil_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_uuid} = $anvil_uuid;
"hosts::host_uuid::${host_uuid}::host_name" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name}, $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"hosts::host_uuid::${host_uuid}::host_type" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}, "hosts::host_uuid::${host_uuid}::host_name" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name},
"hosts::host_uuid::${host_uuid}::host_key" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key}, "hosts::host_uuid::${host_uuid}::short_host_name" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{short_host_name},
"hosts::host_uuid::${host_uuid}::host_ipmi" => $host_ipmi =~ /passw/ ? $anvil->Log->is_secure($anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi}) : $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi}, "hosts::host_uuid::${host_uuid}::host_type" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type},
"hosts::host_uuid::${host_uuid}::anvil_name" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_name}, "hosts::host_uuid::${host_uuid}::host_key" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key},
"hosts::host_uuid::${host_uuid}::anvil_uuid" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_uuid}, "hosts::host_uuid::${host_uuid}::host_ipmi" => $host_ipmi =~ /passw/ ? $anvil->Log->is_secure($anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi}) : $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi},
"hosts::host_uuid::${host_uuid}::anvil_name" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_name},
"hosts::host_uuid::${host_uuid}::anvil_uuid" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_uuid},
}}); }});
# Record the host_uuid in a hash so that the name can be easily retrieved. # Record the host_uuid in a hash so that the name can be easily retrieved.

@ -24,6 +24,7 @@ my $THIS_FILE = "Get.pm";
# date_and_time # date_and_time
# domain_name # domain_name
# free_memory # free_memory
# host_from_ip_address
# host_name # host_name
# host_name_from_uuid # host_name_from_uuid
# host_uuid_from_name # host_uuid_from_name
@ -1122,6 +1123,81 @@ sub domain_name
} }
=head2 host_from_ip_address
This takes an IP address and looks for the host that has the IP. If the given IP is not in the database (or was but is deleted now), an empty string is returned. Otherwise, the host name and host UUID are returned.
my ($host_uuid, $host_name) = $anvil->Get->host_from_ip_address({ip_address => "10.201.10.1"});
Parameters;
=head3 host_from_ip_address (required)
This is the IP address being converted.
=cut
sub host_from_ip_address
{
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 => "Get->host_from_ip_address()" }});
my $host_uuid = "";
my $host_name = "";
my $ip_address = defined $parameter->{ip_address} ? $parameter->{ip_address} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
ip_address => $ip_address,
}});
if (not $ip_address)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Get->host_from_ip_address()", parameter => "ip_address" }});
return($host_uuid, $host_name);
}
if (not $anvil->Validate->ipv4({ip => $ip_address}))
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "warning_0010", variables => { ip_address => $ip_address }});
return($host_uuid, $host_name);
}
my $query = "
SELECT
a.host_uuid,
a.host_name
FROM
hosts a,
ip_addresses b
WHERE
a.host_uuid = b.ip_address_host_uuid
AND
b.ip_address_note != 'DELETED'
AND
b.ip_address_address = ".$anvil->Database->quote($ip_address).";
";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
if ($count == 1)
{
# Found it
$host_uuid = defined $results->[0]->[0] ? $results->[0]->[0] : "";
$host_name = defined $results->[0]->[1] ? $results->[0]->[1] : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
host_uuid => $host_uuid,
host_name => $host_name,
}});
}
return($host_uuid, $host_name);
}
=head2 host_name =head2 host_name
This returns the full host name for the local machine. This returns the full host name for the local machine.

@ -17,6 +17,7 @@ my $THIS_FILE = "Network.pm";
# check_internet # check_internet
# download # download
# find_matches # find_matches
# find_target_ip
# get_company_from_mac # get_company_from_mac
# get_ips # get_ips
# get_network # get_network
@ -615,6 +616,7 @@ sub download
return($save_to); return($save_to);
} }
=head2 find_matches =head2 find_matches
This takes two hash keys from prior C<< Network->get_ips() >> or C<< ->load_ips() >> runs and finds which are on the same network. This takes two hash keys from prior C<< Network->get_ips() >> or C<< ->load_ips() >> runs and finds which are on the same network.
@ -743,6 +745,89 @@ sub find_matches
return($match); return($match);
} }
=head2 find_target_ip
This uses the IP information for the local machine and a target host UUID, and returns an IP address that can be used to contact it. When multiple networks are shared, the BCN IP is used. If no match is found, an empty string is returned.
Parameters;
=head3 host_uuid (required)
This is the target's C<< host_uuid >> that we're looking to contact.
=cut
sub find_target_ip
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Network->find_target_ip()" }});
my $target_ip = "";
my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
host_uuid => $host_uuid,
}});
if (not $host_uuid)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Network->find_target_ip()", parameter => "host_uuid" }});
return("");
}
$anvil->Database->get_hosts();
if (not exists $anvil->data->{hosts}{host_uuid}{$host_uuid})
{
# Unknown host
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0031", variables => { host_uuid => $host_uuid }});
return("");
}
my $target_host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{short_host_name};
my $short_host_name = $anvil->Get->short_host_name({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
target_host_name => $target_host_name,
short_host_name => $short_host_name,
}});
$anvil->Network->load_ips({
debug => $debug,
host_uuid => $anvil->Get->host_uuid,
host => $short_host_name,
clear => 1,
});
$anvil->Network->load_ips({
debug => $debug,
host_uuid => $host_uuid,
host => $target_host_name,
clear => 1,
});
my ($match) = $anvil->Network->find_matches({
debug => $debug,
first => $short_host_name,
second => $target_host_name,
});
if ($match)
{
# Yup!
my $match_found = 0;
foreach my $interface (sort {$a cmp $b} keys %{$match->{$target_host_name}})
{
$target_ip = $match->{$target_host_name}{$interface}{ip};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { target_ip => $target_ip }});
last;
}
}
return($target_ip);
}
=head2 load_interfces =head2 load_interfces
This loads all network information for the given host UUID. This loads all network information for the given host UUID.

@ -2281,9 +2281,12 @@
<a href="?anvil=true&task=create"><img src="#!data!skin::url!#/images/build-anvil_icon.png" class="top_icon" ></a> <a href="?anvil=true&task=create"><img src="#!data!skin::url!#/images/build-anvil_icon.png" class="top_icon" ></a>
</td> </td>
<td class="main_option"> <td class="main_option">
<!-- Create a new Anvil! -->
<a href="?anvil=true&task=create">#!string!striker_0114!#</a> <a href="?anvil=true&task=create">#!string!striker_0114!#</a>
</td> </td>
</tr> </tr>
<!-- List of existing Anvil! systems -->
</table> </table>
<!-- end main-menu --> <!-- end main-menu -->

@ -190,8 +190,8 @@
</tr> </tr>
<tr> <tr>
<td style="text-align: left;"> <td style="text-align: left;">
<!-- Back --> <!-- Close -->
&nbsp; <a href="?files=true" class="button">#!string!striker_0284!#</a> &nbsp; <a href="?files=true" class="button">#!string!striker_0285!#</a>
</td> </td>
<td> <td>
&nbsp; &nbsp;

@ -259,6 +259,17 @@ The error was:
<key name="error_0184">Moving the file failed. The problem should be logged. We'll sleep for a minute and then exit. We'll try again after that.</key> <key name="error_0184">Moving the file failed. The problem should be logged. We'll sleep for a minute and then exit. We'll try again after that.</key>
<key name="error_0185">Unable to check the file mode because a file UUID wasn't set (or failed to parse) from the 'job_data' in the job: [#!variable!job_uuid!#].</key> <key name="error_0185">Unable to check the file mode because a file UUID wasn't set (or failed to parse) from the 'job_data' in the job: [#!variable!job_uuid!#].</key>
<key name="error_0186">Unable to check the file mode because the file UUID: [#!variable!file_uuid!#] is either invalid or doesn't exist in the database.</key> <key name="error_0186">Unable to check the file mode because the file UUID: [#!variable!file_uuid!#] is either invalid or doesn't exist in the database.</key>
<key name="error_0187">Unable to find the new server name from the job UUID: [#!variable!job_uuid!#].</key>
<key name="error_0188">Unable to get the number of CPU cores for the new server: [#!variable!server_name!#] from the job UUID: [#!variable!job_uuid!#].</key>
<key name="error_0189">The new server: [#!variable!server_name!#] was asked to have: [#!variable!requested_cores!#] CPU cores, but only: [#!variable!available_cores!#] are available.</key>
<key name="error_0190">Unable to get the amount of RAM for the new server: [#!variable!server_name!#] from the job UUID: [#!variable!job_uuid!#].</key>
<key name="error_0191">The new server: [#!variable!server_name!#] was asked to have: [#!variable!requested_ram!#] RAM, but only: [#!variable!available_ram!#] is available.</key>
<key name="error_0192">Unable to get the storage group UUID for the new server: [#!variable!server_name!#] from the job UUID: [#!variable!job_uuid!#].</key>
<key name="error_0193">Unable to get the amount of storage to use for the new server: [#!variable!server_name!#] from the job UUID: [#!variable!job_uuid!#].</key>
<key name="error_0194">The new server: [#!variable!server_name!#] was asked to have: [#!variable!requested_size!#] disk space, but only: [#!variable!available_size!#] is available on the requested storage group: [#!variable!storage_group!#].</key>
<key name="error_0195">Unable to get the install ISO to use for the new server: [#!variable!server_name!#] from the job UUID: [#!variable!job_uuid!#].</key>
<key name="error_0196">The install disc ISO: [#!variable!install_iso!#] to be used for the new server: [#!variable!server_name!#] wasn't found on this system.</key>
<key name="error_0197">The driver disc ISO: [#!variable!install_iso!#] to be used for the new server: [#!variable!server_name!#] wasn't found on this system.</key>
<!-- Table headers --> <!-- Table headers -->
<key name="header_0001">Current Network Interfaces and States</key> <key name="header_0001">Current Network Interfaces and States</key>
@ -466,6 +477,55 @@ Failure! The return code: [#!variable!return_code!#] was received ('0' was expec
<key name="job_0144">This is used when a file type changes, setting the executable bits when the type is script, and removing the executable bits when set to another type.</key> <key name="job_0144">This is used when a file type changes, setting the executable bits when the type is script, and removing the executable bits when set to another type.</key>
<key name="job_0145">The file: [#!variable!file_path!#]'s mode has been set to: [#!variable!new_mode!#].</key> <key name="job_0145">The file: [#!variable!file_path!#]'s mode has been set to: [#!variable!new_mode!#].</key>
<key name="job_0146">No need to set the mode on the file: [#!variable!file_path!#], it doesn't exist here.</key> <key name="job_0146">No need to set the mode on the file: [#!variable!file_path!#], it doesn't exist here.</key>
<key name="job_0147">Provision a new server</key>
<key name="job_0148">This takes the information and creates a new server.</key>
<key name="job_0149">There are no known Anvil! systems at this time. Please setup an Anvil! and try again later.</key>
<key name="job_0150">Provision a new server menu:</key>
<key name="job_0151">Anvil! name: ... [#!variable!anvil_name!#]</key>
<key name="job_0152">* That was not a recognized Anvil! name. please try again.</key>
<key name="job_0153">-=] Existing Anvil! systems [=-</key>
<key name="job_0154">Loading available resources for: [#!variable!anvil_name!#] (#!variable!anvil_uuid!#)</key>
<key name="job_0155">There is not enough RAM available on this Anvil! to provision new servers.</key>
<key name="job_0156"> - Available RAM: [#!variable!available_ram!#]</key>
<key name="job_0157">Server name: ... [#!variable!server_name!#]</key>
<key name="job_0158">CPU Cores: ..... [#!variable!cpu_cores!#]</key>
<key name="job_0159">* Please enter a unique server name.</key>
<key name="job_0160">-=] Existing Servers on the Anvil! [#!variable!anvil_name!#] [=-</key>
<key name="job_0161">* Please enter a number between 1 and #!variable!max_cores!#.</key>
<key name="job_0162">-=] Available cores / threads: [#!variable!cores!# / #!variable!threads!#]</key>
<key name="job_0163"> - Node #!variable!core!# CPU Model: [#!variable!model!#]</key>
<key name="job_0164"> - DR Host CPU: .... [#!variable!model!#], [#!variable!cores!#c]/[#!variable!threads!#t]</key>
<key name="job_0165">RAM: ........... [#!variable!ram!#]</key>
<key name="job_0166">* Please enter a valid amount up to: [#!variable!ram_total!# / #!variable!ram_available!#].</key>
<key name="job_0167">-=] Available RAM: [#!variable!ram_available!#]
- Reserved by host: ... [#!variable!ram_reserved!#]
- Allocated to servers: [#!variable!ram_allocated!#]
- Node 1 RAM (total): . [#!variable!ram_node1!#]
- Node 2 RAM (total): . [#!variable!ram_node2!#]</key>
<key name="job_0168"> - DR Host RAM (total): [#!variable!ram_available!#]</key>
<key name="job_0169"> Available on Anvil!: [#!variable!vg_free!#], Total: [#!variable!vg_size!#]
Available on DR: ... [#!variable!dr_free!#], Total: [#!variable!dr_size!#]</key>
<key name="job_0170">Storage Group: . [#!variable!storage_group!#]</key>
<key name="job_0171">* Please enter a number beside the storage group you want to use.</key>
<key name="job_0172">-=] Storage groups</key>
<key name="job_0173">Storage Size: .. [#!variable!storage_size!#]</key>
<key name="job_0174">* Please enter a size up to: [#!variable!max_size!#].</key>
<key name="job_0175">-=] Storage group: [#!variable!storage_group!#], Available Space: [#!variable!available_size!#]
- Note: You can add additional drives later.</key>
<key name="job_0176">Install Media: . [#!variable!install_media!#]</key>
<key name="job_0177">* Please enter a number that corresponds to an install disc.</key>
<key name="job_0178">-=] Installation media</key>
<key name="job_0179"> - 0) #!string!unit_0005!#</key>
<key name="job_0180">Driver Disc: ... [#!variable!driver_disc!#]</key>
<key name="job_0181">* Please enter a number that corresponds to a driver disc.</key>
<key name="job_0182">-=] Driver disc</key>
<key name="job_0183">Saving the job details to create this server. Please wait a few moments.
Job Data:
====
#!variable!job_data!#
====</key>
<key name="job_0184">The job to create the new server has been registered as job: [#!variable!job_uuid!#].
It should be provisioned in the next minute or two.</key>
<!-- Log entries --> <!-- Log entries -->
<key name="log_0001">Starting: [#!variable!program!#].</key> <key name="log_0001">Starting: [#!variable!program!#].</key>
@ -1136,6 +1196,7 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="log_0574">The host: [#!variable!host_name!#] was powered off because of power loss. Power is back and the UPSes are sufficiently charged. Booting it back up now.</key> <key name="log_0574">The host: [#!variable!host_name!#] was powered off because of power loss. Power is back and the UPSes are sufficiently charged. Booting it back up now.</key>
<key name="log_0575">The host: [#!variable!host_name!#] was powered off for thermal reasons. All available thermal sensors read as OK now. Booting it back up now.</key> <key name="log_0575">The host: [#!variable!host_name!#] was powered off for thermal reasons. All available thermal sensors read as OK now. Booting it back up now.</key>
<key name="log_0576">The file: [#!variable!file_path!#] isn't on (or isn't the right size on) Striker: [#!variable!host_name!#]. Not using it to pull from.</key> <key name="log_0576">The file: [#!variable!file_path!#] isn't on (or isn't the right size on) Striker: [#!variable!host_name!#]. Not using it to pull from.</key>
<key name="log_0577">The job: [#!variable!job_uuid!#] was assigned to our Anvil! and this is the primary node. Assigning the job to this machine.</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>
@ -1158,7 +1219,7 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="message_0018">What would you like the new password to be?</key> <key name="message_0018">What would you like the new password to be?</key>
<key name="message_0019">Please enter the password again to confirm.</key> <key name="message_0019">Please enter the password again to confirm.</key>
<key name="message_0020">About to update the local passwords (shell users, database and web interface).</key> <key name="message_0020">About to update the local passwords (shell users, database and web interface).</key>
<key name="message_0021">Proceed? [y/N]</key> <key name="message_0021">Proceed? [y/N]</key> <!-- Default Yes is at message_0206 -->
<key name="message_0022">Aborting.</key> <key name="message_0022">Aborting.</key>
<key name="message_0023">Auto-approved by command line switch, proceeding.</key> <key name="message_0023">Auto-approved by command line switch, proceeding.</key>
<key name="message_0024">Updating the Striker user: [#!variable!user!#] password... </key> <key name="message_0024">Updating the Striker user: [#!variable!user!#] password... </key>
@ -1436,6 +1497,7 @@ About to try to download aproximately: [#!variable!packages!#] packages needed t
<key name="message_0203">Processing a file purge.</key> <key name="message_0203">Processing a file purge.</key>
<key name="message_0204">Processing an uploaded file.</key> <key name="message_0204">Processing an uploaded file.</key>
<key name="message_0205">Processing a file mode check.</key> <key name="message_0205">Processing a file mode check.</key>
<key name="message_0206">Proceed? [Y/n]</key> <!-- Default no is message_0021 -->
<!-- Success messages shown to the user --> <!-- Success messages shown to the user -->
<key name="ok_0001">Saved the mail server information successfully!</key> <key name="ok_0001">Saved the mail server information successfully!</key>
@ -1754,6 +1816,7 @@ If you are comfortable that the target has changed for a known reason, you can s
<key name="striker_0282">This will remove the file from all systems.</key> <key name="striker_0282">This will remove the file from all systems.</key>
<key name="striker_0283">There are no #!string!brand_0006!# configured yet. Existing files will automatically sync to new clusters.</key> <key name="striker_0283">There are no #!string!brand_0006!# configured yet. Existing files will automatically sync to new clusters.</key>
<key name="striker_0284">Cancel</key> <key name="striker_0284">Cancel</key>
<key name="striker_0285">Close</key>
<!-- These are generally units and appended to numbers --> <!-- These are generally units and appended to numbers -->
<key name="suffix_0001">#!variable!number!#/sec</key> <key name="suffix_0001">#!variable!number!#/sec</key>

@ -723,15 +723,22 @@ sub configure_pacemaker
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
pcs_add_command => $pcs_add_command =~ /passw/ ? $anvil->Log->is_secure($pcs_add_command) : $pcs_add_command, pcs_add_command => $pcs_add_command =~ /passw/ ? $anvil->Log->is_secure($pcs_add_command) : $pcs_add_command,
}}); }});
foreach my $pair (split/ /, $fence_arguments) while ($fence_arguments =~ /=/)
{ {
# Ignore 'delay', we handle that in Cluster->set_delay(); # Ignore 'delay', we handle that in Cluster->set_delay();
my ($argument, $value) = ($pair =~ /^(.*)="(.*?)"$/); my $pair = ($fence_arguments =~ /(\S*?=".*?")/)[0];
$fence_arguments =~ s/$pair//;
$fence_arguments =~ s/^\s+//;
$fence_arguments =~ s/\s+$//;
my ($argument, $value) = ($pair =~ /(.*)="(.*)"/);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
pair => $pair =~ /passw/ ? $anvil->Log->is_secure($pair) : $pair, 's1:fence_arguments' => $fence_arguments,
argument => $argument, 's2:pair' => $pair =~ /passw/ ? $anvil->Log->is_secure($pair) : $pair,
value => $argument =~ /passw/ ? $anvil->Log->is_secure($value) : $value, 's3:argument' => $argument,
's4:value' => $argument =~ /passw/ ? $anvil->Log->is_secure($value) : $value,
}}); }});
# Ignore 'delay', we handle that in Cluster->set_delay();
if (($argument ne "pcmk_off_action") && ($anvil->data->{fence_data}{$fence_agent}{switch}{$argument}{name} eq "delay")) if (($argument ne "pcmk_off_action") && ($anvil->data->{fence_data}{$fence_agent}{switch}{$argument}{name} eq "delay"))
{ {
next; next;
@ -931,6 +938,10 @@ sub configure_pacemaker
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }});
if ($something_changed->{$node_name}) if ($something_changed->{$node_name})
{ {
# Update our view of the cluster.
my $problem = $anvil->Cluster->parse_cib({debug => 2});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { problem => $problem }});
# Delete any existing fence levels # Delete any existing fence levels
if (exists $anvil->data->{cib}{parsed}{data}{node}{$node_name}) if (exists $anvil->data->{cib}{parsed}{data}{node}{$node_name})
{ {

@ -81,6 +81,7 @@ 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);
} }
else else
{ {
@ -96,6 +97,229 @@ $anvil->nice_exit({exit_code => 0});
# Functions # # Functions #
############################################################################################################# #############################################################################################################
# This actually provisions a VM.
sub run_jobs
{
my ($anvil) = @_;
# If we're here, the job has been assigned to us, so we use our own anvil! uuid.
my $anvil_uuid = $anvil->Cluster->get_anvil_uuid();
$anvil->Get->available_resources({
debug => 2,
anvil_uuid => $anvil_uuid,
});
$anvil->Database->get_files();
$anvil->Database->get_file_locations();
my $server_name = "";
my $cpu_cores = "";
my $ram = "";
my $storage_group_uuid = "";
my $storage_size = "";
my $install_iso_uuid = "";
my $driver_iso_uuid = "";
foreach my $line (split/\n/, $anvil->data->{jobs}{job_data})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
if ($line =~ /server_name=(.*)$/)
{
$anvil_uuid = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_name => $server_name }});
}
if ($line =~ /cpu_cores=(.*)$/)
{
$cpu_cores = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cpu_cores => $cpu_cores }});
}
if ($line =~ /ram=(.*)$/)
{
$ram = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cpu_cores => $cpu_cores }});
}
if ($line =~ /storage_group_uuid=(.*)$/)
{
$storage_group_uuid = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_uuid => $storage_group_uuid }});
}
if ($line =~ /storage_size=(.*)$/)
{
$storage_size = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_size => $storage_size }});
}
if ($line =~ /install_iso=(.*)$/)
{
$install_iso_uuid = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { install_iso_uuid => $install_iso_uuid }});
}
if ($line =~ /driver_iso=(.*)$/)
{
$driver_iso_uuid = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { driver_iso_uuid => $driver_iso_uuid }});
}
}
if (not $server_name)
{
$anvil->Job->update_progress({
progress => 100,
message => "error_0187,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!",
job_status => "failed",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0187", variables => { job_uuid => $anvil->data->{switches}{'job-uuid'} }});
$anvil->nice_exit({exit_code => 1});
}
if (not $cpu_cores)
{
$anvil->Job->update_progress({
progress => 100,
message => "error_0188,!!server_name!".$server_name."!!,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!",
job_status => "failed",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0188", variables => {
server_name => $server_name,
job_uuid => $anvil->data->{switches}{'job-uuid'},
}});
$anvil->nice_exit({exit_code => 1});
}
elsif ($cpu_cores > $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads})
{
# Too many cores requested
$anvil->Job->update_progress({
progress => 100,
message => "error_0189,!!server_name!".$server_name."!!,!!available_cores!".$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}."!!,!!requested_cores!".$cpu_cores."!!",
job_status => "failed",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0189", variables => {
server_name => $server_name,
available_cores => $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads},
requested_cores => $cpu_cores,
}});
$anvil->nice_exit({exit_code => 1});
}
if (not $ram)
{
$anvil->Job->update_progress({
progress => 100,
message => "error_0190,!!server_name!".$server_name."!!,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!",
job_status => "failed",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0190", variables => {
server_name => $server_name,
job_uuid => $anvil->data->{switches}{'job-uuid'},
}});
$anvil->nice_exit({exit_code => 1});
}
elsif ($ram > $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available})
{
# Too many cores requested
my $say_available_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}})." (".$anvil->Convert->add_commas({number => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}}).")";
my $say_requested_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $ram})." (".$anvil->Convert->add_commas({number => $ram}).")";
$anvil->Job->update_progress({
progress => 100,
message => "error_0191,!!server_name!".$server_name."!!,!!available_ram!".$say_available_ram."!!,!!requested_ram!".$say_requested_ram."!!",
job_status => "failed",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0191", variables => {
server_name => $server_name,
available_ram => $say_available_ram,
requested_ram => $say_requested_ram,
}});
$anvil->nice_exit({exit_code => 1});
}
if (not $storage_group_uuid)
{
$anvil->Job->update_progress({
progress => 100,
message => "error_0192,!!server_name!".$server_name."!!,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!",
job_status => "failed",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0192", variables => {
server_name => $server_name,
job_uuid => $anvil->data->{switches}{'job-uuid'},
}});
$anvil->nice_exit({exit_code => 1});
}
if (not $storage_size)
{
$anvil->Job->update_progress({
progress => 100,
message => "error_0193,!!server_name!".$server_name."!!,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!",
job_status => "failed",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0193", variables => {
server_name => $server_name,
job_uuid => $anvil->data->{switches}{'job-uuid'},
}});
$anvil->nice_exit({exit_code => 1});
}
if ($storage_size > $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' => $storage_size})." (".$anvil->Convert->add_commas({number => $storage_size}).")";
my $say_storage_group = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{group_name};
$anvil->Job->update_progress({
progress => 100,
message => "error_0194,!!server_name!".$server_name."!!,!!available_size!".$say_available_size."!!,!!requested_size!".$say_requested_size."!!,!!storage_group!".$say_storage_group."!!",
job_status => "failed",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0194", variables => {
server_name => $server_name,
available_size => $say_available_size,
requested_size => $say_requested_size,
storage_group => $say_storage_group,
}});
$anvil->nice_exit({exit_code => 1});
}
if (not $install_iso_uuid)
{
$anvil->Job->update_progress({
progress => 100,
message => "error_0195,!!server_name!".$server_name."!!,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!",
job_status => "failed",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0195", variables => {
server_name => $server_name,
job_uuid => $anvil->data->{switches}{'job-uuid'},
}});
$anvil->nice_exit({exit_code => 1});
}
my $install_iso = $anvil->data->{files}{file_uuid}{$install_iso_uuid}{file_directory}."/".$anvil->data->{files}{file_uuid}{$install_iso_uuid}{file_name};
if (not -e $install_iso)
{
$anvil->Job->update_progress({
progress => 100,
message => "error_0196,!!server_name!".$server_name."!!,!!install_iso!".$install_iso."!!",
job_status => "failed",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0196", variables => {
server_name => $server_name,
install_iso => $install_iso,
}});
$anvil->nice_exit({exit_code => 1});
}
# Driver disc is optional.
if ($driver_iso_uuid)
{
my $driver_iso = $anvil->data->{files}{file_uuid}{$driver_iso_uuid}{file_directory}."/".$anvil->data->{files}{file_uuid}{$driver_iso_uuid}{file_name};
if (not -e $driver_iso)
{
$anvil->Job->update_progress({
progress => 100,
message => "error_0197,!!server_name!".$server_name."!!,!!driver_iso!".$driver_iso."!!",
job_status => "failed",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0197", variables => {
server_name => $server_name,
driver_iso => $driver_iso,
}});
$anvil->nice_exit({exit_code => 1});
}
}
return(0);
}
# Go through a series of questions to ask the user how they want to build their server. # Go through a series of questions to ask the user how they want to build their server.
sub interactive_question sub interactive_question
{ {
@ -149,6 +373,9 @@ sub interactive_question
interactive_ask_server_ram($anvil, $terminal); interactive_ask_server_ram($anvil, $terminal);
interactive_ask_server_storage_group($anvil, $terminal); interactive_ask_server_storage_group($anvil, $terminal);
interactive_ask_server_storage_size($anvil, $terminal); interactive_ask_server_storage_size($anvil, $terminal);
interactive_ask_server_install_media($anvil, $terminal);
interactive_ask_server_driver_disc($anvil, $terminal);
interactive_ask_server_confirm($anvil, $terminal);
return(0); return(0);
} }
@ -170,7 +397,7 @@ sub interactive_ask_anvil_name
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { known_anvils => $known_anvils }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { known_anvils => $known_anvils }});
if (not $known_anvils) if (not $known_anvils)
{ {
print "There are no known Anvil! systems at this time. Please setup an Anvil! and try again later.\n"; print $anvil->Words->string({key => "job_0149"})."\n";
$anvil->nice_exit({exit_code => 1}); $anvil->nice_exit({exit_code => 1});
} }
elsif ($known_anvils == 1) elsif ($known_anvils == 1)
@ -183,15 +410,15 @@ sub interactive_ask_anvil_name
} }
} }
print $terminal->Tputs('cl'); print $terminal->Tputs('cl');
print "Provision a new server menu:\n"; print $anvil->Words->string({key => "job_0150"})."\n";
print "Anvil name: .. [".$default_anvil."]\n\n\n"; print $anvil->Words->string({key => "job_0151", variables => { anvil_name => $default_anvil }})."\n\n\n";
# Show all the current server names. # Show all the current server names.
if ($retry) if ($retry)
{ {
print "* That was not a recognized Anvil! name. please try again.\n\n"; print $anvil->Words->string({key => "job_0152"})."\n\n";
} }
print "-=] Existing Anvil! systems [=-\n"; print $anvil->Words->string({key => "job_0153"})."\n";
foreach my $anvil_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_name}}) foreach my $anvil_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_name}})
{ {
print "- ".$anvil_name.": - ".$anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_description}."\n"; print "- ".$anvil_name.": - ".$anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_description}."\n";
@ -220,7 +447,10 @@ sub interactive_ask_anvil_name
"new_server::anvil_uuid" => $anvil->data->{new_server}{anvil_uuid}, "new_server::anvil_uuid" => $anvil->data->{new_server}{anvil_uuid},
}}); }});
print "Loading available resources for: [".$anvil->data->{new_server}{anvil_name}."] (".$anvil->data->{new_server}{anvil_uuid}.")\n"; print $anvil->Words->string({key => "job_0154", variables => {
anvil_name => $anvil->data->{new_server}{anvil_name},
anvil_uuid => $anvil->data->{new_server}{anvil_uuid},
}})."\n";
$anvil->Get->available_resources({ $anvil->Get->available_resources({
debug => 2, debug => 2,
anvil_uuid => $anvil->data->{new_server}{anvil_uuid}, anvil_uuid => $anvil->data->{new_server}{anvil_uuid},
@ -241,12 +471,11 @@ sub interactive_ask_anvil_name
}}); }});
if ($anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available} < (1**20)) if ($anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available} < (1**20))
{ {
print "There is not enough RAM available on this Anvil! to provision new servers.\n"; print $anvil->Words->string({key => "job_0155"})."\n";
print " - Available RAM: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}})."]\n"; print $anvil->Words->string({key => "job_0156", variables => { available_ram => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}}) }})."\n";
$anvil->nice_exit({exit_code => 2}); $anvil->nice_exit({exit_code => 2});
} }
return(0); return(0);
} }
@ -266,17 +495,17 @@ sub interactive_ask_server_name
$default = $anvil->data->{switches}{name}; $default = $anvil->data->{switches}{name};
} }
print $terminal->Tputs('cl'); print $terminal->Tputs('cl');
print "Provision a new server menu:\n"; print $anvil->Words->string({key => "job_0150"})."\n";
print "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";
print "Server name: [".$anvil->data->{new_server}{name}."]\n\n\n"; print $anvil->Words->string({key => "job_0157", variables => { server_name => $anvil->data->{new_server}{name} }})."\n\n\n";
# Show all the current server names. # Show all the current server names.
if ($retry) if ($retry)
{ {
print "* Please enter a unique server name.\n\n"; print $anvil->Words->string({key => "job_0159"})."\n\n";
} }
my $anvil_uuid = $anvil->data->{new_server}{anvil_uuid}; my $anvil_uuid = $anvil->data->{new_server}{anvil_uuid};
print "-=] Existing Servers on the Anvil! [".$anvil->data->{new_server}{anvil_name}."] [=-\n"; print $anvil->Words->string({key => "job_0160", variables => { anvil_name => $anvil->data->{new_server}{anvil_name} }})."\n";
foreach my $server_name (sort {$a cmp $b} keys %{$anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}}) foreach my $server_name (sort {$a cmp $b} keys %{$anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}})
{ {
print "- ".$server_name."\n"; print "- ".$server_name."\n";
@ -333,26 +562,33 @@ sub interactive_ask_server_cpu
} }
print $terminal->Tputs('cl'); print $terminal->Tputs('cl');
print "Provision a new server menu:\n"; print $anvil->Words->string({key => "job_0150"})."\n";
print "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";
print "Server name: . [".$anvil->data->{new_server}{name}."]\n"; print $anvil->Words->string({key => "job_0157", variables => { server_name => $anvil->data->{new_server}{name} }})."\n";
print "CPU Cores: ... [".$default_cpu."]\n\n\n"; print $anvil->Words->string({key => "job_0158", variables => { cpu_cores => $default_cpu }})."\n\n\n";
if ($retry) if ($retry)
{ {
print "* Please enter a number between 1 and ".$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}.".\n\n"; print $anvil->Words->string({key => "job_0161", variables => { max_cores => $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads} }})."\n\n";
} }
print "-=] Available cores / threads: [".$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores}." / ".$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}."]\n"; print $anvil->Words->string({key => "job_0162", variables => {
cores => $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores},
threads => $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads},
}})."\n";
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};
my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
my $dr1_host_uuid = $anvil->data->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid} : ""; my $dr1_host_uuid = $anvil->data->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid} : "";
print " - Node 1 CPU Model: [".$anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node1_host_uuid}{cpu}{model}."]\n"; print $anvil->Words->string({key => "job_0163", variables => { core => 1, model => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node1_host_uuid}{cpu}{model} }})."\n";
print " - Node 2 CPU Model: [".$anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node2_host_uuid}{cpu}{model}."]\n"; print $anvil->Words->string({key => "job_0163", variables => { core => 2, model => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node2_host_uuid}{cpu}{model} }})."\n";
if ($anvil->data->{anvil_resources}{$anvil_uuid}{has_dr}) if ($anvil->data->{anvil_resources}{$anvil_uuid}{has_dr})
{ {
print " - DR Host CPU: .... [".$anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node1_host_uuid}{cpu}{model}."], [".$anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$dr1_host_uuid}{cpu}{cores}."c]/[".$anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$dr1_host_uuid}{cpu}{threads}."t]\n"; print $anvil->Words->string({key => "job_0164", variables => {
model => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node1_host_uuid}{cpu}{model},
cores => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$dr1_host_uuid}{cpu}{cores},
threads => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$dr1_host_uuid}{cpu}{threads},
}})."\n";
} }
print $terminal->Tgoto('cm', 0, 4)."? "; print $terminal->Tgoto('cm', 0, 4)."? ";
@ -412,28 +648,35 @@ sub interactive_ask_server_ram
} }
print $terminal->Tputs('cl'); print $terminal->Tputs('cl');
print "Provision a new server menu:\n"; print $anvil->Words->string({key => "job_0150"})."\n";
print "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";
print "Server name: . [".$anvil->data->{new_server}{name}."]\n"; print $anvil->Words->string({key => "job_0157", variables => { server_name => $anvil->data->{new_server}{name} }})."\n";
print "CPU Cores: ... [".$anvil->data->{new_server}{cpu}."]\n"; print $anvil->Words->string({key => "job_0158", variables => { cpu_cores => $anvil->data->{new_server}{cpu} }})."\n";
print "RAM: ......... [".$default_ram."]\n\n\n"; print $anvil->Words->string({key => "job_0165", variables => { ram => $default_ram }})."\n\n\n";
if ($retry) if ($retry)
{ {
print "* Please enter a valid amount up to: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{hardware}})." / ".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}})."].\n\n"; print $anvil->Words->string({key => "job_0166", variables => {
ram_total => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{hardware}}),
ram_available => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}}),
}})."\n\n";
} }
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};
my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
my $dr1_host_uuid = $anvil->data->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid} : ""; my $dr1_host_uuid = $anvil->data->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid} : "";
print "-=] Available RAM: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}})."] (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}, unit => "M"}).")\n"; print $anvil->Words->string({key => "job_0167", variables => {
print " - Reserved by host: ... [".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{reserved}})."]\n"; ram_available => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}, unit => "M"}).")",
print " - Allocated to servers: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{allocated}})."] (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{allocated}, unit => "M"}).")\n"; ram_reserved => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{reserved}}),
print " - Node 1 RAM (total): . [".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node1_host_uuid}{ram}{hardware}})."] (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node1_host_uuid}{ram}{hardware}, unit => "M"}).")\n"; ram_allocated => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{allocated}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{allocated}, unit => "M"}).")",
print " - Node 2 RAM (total): . [".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node2_host_uuid}{ram}{hardware}})."] (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node2_host_uuid}{ram}{hardware}, unit => "M"}).")\n"; ram_node1 => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node1_host_uuid}{ram}{hardware}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node1_host_uuid}{ram}{hardware}, unit => "M"}).")",
ram_node2 => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node2_host_uuid}{ram}{hardware}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$node2_host_uuid}{ram}{hardware}, unit => "M"}).")",
}})."\n";
if ($anvil->data->{anvil_resources}{$anvil_uuid}{has_dr}) if ($anvil->data->{anvil_resources}{$anvil_uuid}{has_dr})
{ {
print " - DR Host RAM (total): [".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$dr1_host_uuid}{ram}{hardware}})."] (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$dr1_host_uuid}{ram}{hardware}, unit => "M"}).")\n"; print $anvil->Words->string({key => "job_0168", variables => {
ram_available => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$dr1_host_uuid}{ram}{hardware}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{host_uuid}{$dr1_host_uuid}{ram}{hardware}, unit => "M"}).")",
}})."\n";
} }
print $terminal->Tgoto('cm', 0, 5)."? "; print $terminal->Tgoto('cm', 0, 5)."? ";
@ -523,15 +766,12 @@ sub interactive_ask_server_storage_group
} }
push @{$storage_groups}, $storage_group_uuid; push @{$storage_groups}, $storage_group_uuid;
$show_list .= " - ".$position.") ".$storage_group_name." (".$storage_group_uuid.")\n"; $show_list .= " - ".$position.") ".$storage_group_name." (".$storage_group_uuid.")\n";
$show_list .= " Available on Anvil!: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_free})."], Total: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size})."]\n"; $show_list .= $anvil->Words->string({key => "job_0169", variables => {
if ($anvil->data->{anvil_resources}{$anvil_uuid}{has_dr}) vg_free => $anvil->Convert->bytes_to_human_readable({'bytes' => $vg_free}),
{ vg_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size}),
$show_list .= " Available on DR: ... [".$anvil->Convert->bytes_to_human_readable({'bytes' => $dr_free})."], Total: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $dr_size})."]\n"; dr_free => $anvil->data->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->Convert->bytes_to_human_readable({'bytes' => $dr_free}) : "--",
} dr_size => $anvil->data->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->Convert->bytes_to_human_readable({'bytes' => $dr_size}) : "--",
else }})."\n";
{
$show_list .= " Available on DR: ... [--], Total: [--]\n";
}
} }
if (not $default_storage_group) if (not $default_storage_group)
@ -541,22 +781,22 @@ sub interactive_ask_server_storage_group
} }
print $terminal->Tputs('cl'); print $terminal->Tputs('cl');
print "Provision a new server menu:\n"; print $anvil->Words->string({key => "job_0150"})."\n";
print "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";
print "Server name: . [".$anvil->data->{new_server}{name}."]\n"; print $anvil->Words->string({key => "job_0157", variables => { server_name => $anvil->data->{new_server}{name} }})."\n";
print "CPU Cores: ... [".$anvil->data->{new_server}{cpu}."]\n"; print $anvil->Words->string({key => "job_0158", variables => { cpu_cores => $anvil->data->{new_server}{cpu} }})."\n";
print "RAM: ......... [".$anvil->data->{new_server}{ram}."]\n"; print $anvil->Words->string({key => "job_0165", variables => { ram => $anvil->Convert->bytes_to_human_readable({"bytes" => $anvil->data->{new_server}{ram}}) }})."\n";
print "Storage Group: [".$default_storage_group."]\n\n\n"; print $anvil->Words->string({key => "job_0170", variables => { storage_group => $default_storage_group }})."\n\n\n";
if ($retry) if ($retry)
{ {
print "* Please enter a number beside the storage group you want to use.\n\n"; print $anvil->Words->string({key => "job_0171"})."\n\n";
} }
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};
my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
my $dr1_host_uuid = $anvil->data->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid} : ""; my $dr1_host_uuid = $anvil->data->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid} : "";
print "-=] Storage groups\n"; print $anvil->Words->string({key => "job_0171"})."\n";
print $show_list."\n"; print $show_list."\n";
print $terminal->Tgoto('cm', 0, 6)."? "; print $terminal->Tgoto('cm', 0, 6)."? ";
@ -617,24 +857,26 @@ sub interactive_ask_server_storage_size
my $say_storage_group = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{group_name}; my $say_storage_group = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{group_name};
print $terminal->Tputs('cl'); print $terminal->Tputs('cl');
print "Provision a new server menu:\n"; print $anvil->Words->string({key => "job_0150"})."\n";
print "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";
print "Server name: . [".$anvil->data->{new_server}{name}."]\n"; print $anvil->Words->string({key => "job_0157", variables => { server_name => $anvil->data->{new_server}{name} }})."\n";
print "CPU Cores: ... [".$anvil->data->{new_server}{cpu}."]\n"; print $anvil->Words->string({key => "job_0158", variables => { cpu_cores => $anvil->data->{new_server}{cpu} }})."\n";
print "RAM: ......... [".$anvil->data->{new_server}{ram}."]\n"; print $anvil->Words->string({key => "job_0165", variables => { ram => $anvil->Convert->bytes_to_human_readable({"bytes" => $anvil->data->{new_server}{ram}}) }})."\n";
print "Storage Group: [".$say_storage_group."]\n"; print $anvil->Words->string({key => "job_0170", variables => { storage_group => $say_storage_group }})."\n";
print "Storage Size: [".$default_storage_size."]\n\n\n"; print $anvil->Words->string({key => "job_0173", variables => { storage_size => $default_storage_size }})."\n\n\n";
if ($retry) if ($retry)
{ {
print "* Please enter a size up to: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_free})."].\n\n"; print $anvil->Words->string({key => "job_0174", variables => { max_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $vg_free}) }})."\n\n";
} }
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};
my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
my $dr1_host_uuid = $anvil->data->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid} : ""; my $dr1_host_uuid = $anvil->data->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid} : "";
print "-=] Storage group: [".$say_storage_group."], Available Space: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_free})."]\n"; print $anvil->Words->string({key => "job_0175", variables => {
print " - Note: You can add additional drives later.\n"; storage_group => $say_storage_group,
available_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $vg_free}),
}})."\n";
print $terminal->Tgoto('cm', 0, 7)."? "; print $terminal->Tgoto('cm', 0, 7)."? ";
my $answer = <STDIN>; my $answer = <STDIN>;
@ -679,3 +921,270 @@ sub interactive_ask_server_storage_size
return(0); return(0);
} }
sub interactive_ask_server_install_media
{
my ($anvil, $terminal) = @_;
my $retry = 0;
while(1)
{
$anvil->Database->get_files();
$anvil->Database->get_file_locations();
my $anvil_uuid = $anvil->data->{new_server}{anvil_uuid};
# Create an array of install ISOs.
my $install_isos = [""];
my $iso_list = "";
my $position = 0;
foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{files}{file_name}})
{
my $file_uuid = $anvil->data->{files}{file_name}{$file_name}{file_uuid};
my $file_directory = $anvil->data->{files}{file_name}{$file_name}{file_directory};
my $file_size = $anvil->data->{files}{file_name}{$file_name}{file_size};
my $file_type = $anvil->data->{files}{file_name}{$file_name}{file_type};
my $file_path = $file_directory."/".$file_name;
my $file_location_uuid = $anvil->data->{file_locations}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_location_uuid};
my $file_location_active = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
file_uuid => $file_uuid,
file_name => $file_name,
file_directory => $file_directory,
file_size => $file_size." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $file_size}).")",
file_type => $file_type,
file_path => $file_path,
file_location_uuid => $file_location_uuid,
file_location_active => $file_location_active,
}});
next if $file_type ne "iso";
next if not $file_location_active;
# Still here?
$position++;
push @{$install_isos}, $file_uuid;
$iso_list .= " - ".$position.") ".$file_name." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $file_size}).")\n";
}
my $storage_group_uuid = $anvil->data->{new_server}{storage_group};
my $say_storage_group = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{group_name};
my $say_storage_size = $anvil->Convert->bytes_to_human_readable({"bytes" => $anvil->data->{new_server}{storage_size}});
print $terminal->Tputs('cl');
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_0157", variables => { server_name => $anvil->data->{new_server}{name} }})."\n";
print $anvil->Words->string({key => "job_0158", variables => { cpu_cores => $anvil->data->{new_server}{cpu} }})."\n";
print $anvil->Words->string({key => "job_0165", variables => { ram => $anvil->Convert->bytes_to_human_readable({"bytes" => $anvil->data->{new_server}{ram}}) }})."\n";
print $anvil->Words->string({key => "job_0170", variables => { storage_group => $say_storage_group }})."\n";
print $anvil->Words->string({key => "job_0173", variables => { storage_size => $say_storage_size }})."\n";
print $anvil->Words->string({key => "job_0176", variables => { install_media => "" }})."\n\n\n";
if ($retry)
{
print $anvil->Words->string({key => "job_0177"})."\n\n";
}
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->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid} : "";
print $anvil->Words->string({key => "job_0178"})."\n";
print $iso_list."\n";
print $terminal->Tgoto('cm', 0, 8)."? ";
my $answer = <STDIN>;
chomp $answer;
if (($answer) && ($answer =~ /^\d+$/) && (exists $install_isos->[$answer]) && ($install_isos->[$answer]))
{
# Valid.
$anvil->data->{new_server}{install_media} = $install_isos->[$answer];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"new_server::install_media" => $anvil->data->{new_server}{install_media},
}});
last;
}
else
{
$retry = 1;
}
}
return(0);
}
sub interactive_ask_server_driver_disc
{
my ($anvil, $terminal) = @_;
my $retry = 0;
while(1)
{
$anvil->Database->get_files();
$anvil->Database->get_file_locations();
my $anvil_uuid = $anvil->data->{new_server}{anvil_uuid};
my $storage_group_uuid = $anvil->data->{new_server}{storage_group};
my $say_storage_group = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{group_name};
my $say_storage_size = $anvil->Convert->bytes_to_human_readable({"bytes" => $anvil->data->{new_server}{storage_size}});
my $install_media_file_uuid = $anvil->data->{new_server}{install_media};
my $say_install_media = $anvil->data->{files}{file_uuid}{$install_media_file_uuid}{file_name};
# Create an array of install ISOs.
my $driver_isos = ["none"];
my $iso_list = $anvil->Words->string({key => "job_0179"})."\n";
my $position = 0;
foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{files}{file_name}})
{
my $file_uuid = $anvil->data->{files}{file_name}{$file_name}{file_uuid};
my $file_directory = $anvil->data->{files}{file_name}{$file_name}{file_directory};
my $file_size = $anvil->data->{files}{file_name}{$file_name}{file_size};
my $file_type = $anvil->data->{files}{file_name}{$file_name}{file_type};
my $file_path = $file_directory."/".$file_name;
my $file_location_uuid = $anvil->data->{file_locations}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_location_uuid};
my $file_location_active = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
file_uuid => $file_uuid,
file_name => $file_name,
file_directory => $file_directory,
file_size => $file_size." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $file_size}).")",
file_type => $file_type,
file_path => $file_path,
file_location_uuid => $file_location_uuid,
file_location_active => $file_location_active,
}});
next if $file_type ne "iso";
next if not $file_location_active;
next if $file_uuid eq $install_media_file_uuid;
# Still here?
$position++;
push @{$driver_isos}, $file_uuid;
$iso_list .= " - ".$position.") ".$file_name." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $file_size}).")\n";
}
print $terminal->Tputs('cl');
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_0157", variables => { server_name => $anvil->data->{new_server}{name} }})."\n";
print $anvil->Words->string({key => "job_0158", variables => { cpu_cores => $anvil->data->{new_server}{cpu} }})."\n";
print $anvil->Words->string({key => "job_0165", variables => { ram => $anvil->Convert->bytes_to_human_readable({"bytes" => $anvil->data->{new_server}{ram}}) }})."\n";
print $anvil->Words->string({key => "job_0170", variables => { storage_group => $say_storage_group }})."\n";
print $anvil->Words->string({key => "job_0173", variables => { storage_size => $say_storage_size }})."\n";
print $anvil->Words->string({key => "job_0176", variables => { install_media => $say_install_media }})."\n";
print $anvil->Words->string({key => "job_0180", variables => { driver_disc => "#!string!unit_0005!#" }})."\n\n\n";
if ($retry)
{
print $anvil->Words->string({key => "job_0181"})."\n\n";
}
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->{anvil_resources}{$anvil_uuid}{has_dr} ? $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid} : "";
print $anvil->Words->string({key => "job_0182"})."\n";
print $iso_list."\n";
print $terminal->Tgoto('cm', 0, 9)."? ";
my $answer = <STDIN>;
chomp $answer;
$answer = 0 if $answer eq "";
if (($answer =~ /^\d+$/) && (exists $driver_isos->[$answer]) && ($driver_isos->[$answer]))
{
# Valid.
$anvil->data->{new_server}{driver_disc} = $driver_isos->[$answer];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"new_server::driver_disc" => $anvil->data->{new_server}{driver_disc},
}});
last;
}
else
{
$retry = 1;
}
}
return(0);
}
sub interactive_ask_server_confirm
{
my ($anvil, $terminal) = @_;
$anvil->Database->get_anvils();
$anvil->Database->get_files();
$anvil->Database->get_file_locations();
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 $storage_group_uuid = $anvil->data->{new_server}{storage_group};
my $say_storage_group = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{group_name};
my $say_storage_size = $anvil->Convert->bytes_to_human_readable({"bytes" => $anvil->data->{new_server}{storage_size}});
my $install_media_file_uuid = $anvil->data->{new_server}{install_media};
my $say_install_media = $anvil->data->{files}{file_uuid}{$install_media_file_uuid}{file_name};
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};
print $terminal->Tputs('cl');
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_0157", variables => { server_name => $anvil->data->{new_server}{name} }})."\n";
print $anvil->Words->string({key => "job_0158", variables => { cpu_cores => $anvil->data->{new_server}{cpu} }})."\n";
print $anvil->Words->string({key => "job_0165", variables => { ram => $anvil->Convert->bytes_to_human_readable({"bytes" => $anvil->data->{new_server}{ram}}) }})."\n";
print $anvil->Words->string({key => "job_0170", variables => { storage_group => $say_storage_group }})."\n";
print $anvil->Words->string({key => "job_0173", variables => { storage_size => $say_storage_size }})."\n";
print $anvil->Words->string({key => "job_0176", variables => { install_media => $say_install_media }})."\n";
print $anvil->Words->string({key => "job_0180", variables => { driver_disc => $say_driver_disc }})."\n";
print $anvil->Words->string({key => "message_0206"})." ";
my $answer = <STDIN>;
chomp $answer;
$answer = "y" if $answer eq "";
if ($answer =~ /^y/i)
{
# Valid.
my $job_data = "server_name=".$anvil->data->{new_server}{name}."
cpu_cores=".$anvil->data->{new_server}{cpu}."
ram=".$anvil->data->{new_server}{ram}."
storage_group_uuid=".$anvil->data->{new_server}{storage_group}."
storage_size=".$anvil->data->{new_server}{storage_size}."
install_iso=".$anvil->data->{new_server}{install_media}."
driver_iso=".$anvil->data->{new_server}{driver_disc};
print $anvil->Words->string({key => "job_0183", variables => { job_data => $job_data }})."\n";
# Register the job with the primary node on the Anvil! (or node 1, if neither node is primary).
my $target_host_uuid = $anvil->Cluster->get_primary_host_uuid({debug => 2, anvil_uuid => $anvil_uuid});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target_host_uuid => $target_host_uuid }});
if (not $target_host_uuid)
{
$target_host_uuid = $node1_host_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target_host_uuid => $target_host_uuid }});
}
my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
debug => 2,
job_command => $anvil->data->{path}{exe}{'anvil-provision-server'},
job_data => $job_data,
job_name => "server::provision",
job_title => "job_0147",
job_description => "job_0148",
job_progress => 0,
job_host_uuid => $target_host_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";
}
else
{
# Abort
print $anvil->Words->string({key => "message_0022"})."\n";
}
return(0);
}

@ -79,14 +79,12 @@ if ($anvil->data->{switches}{'job-uuid'})
{ {
process_file_mode($anvil); process_file_mode($anvil);
} }
# Job data will be in $anvil->data->{jobs}{job_data}
} }
else else
{ {
# Do a normal periodic search. # This checks to see if there are any files that need to be pulled, renamed, removed, or mode
### NOTE: When finding new files, check the size, sleep for 30 seconds, and check again. If a file's # updated.
### size changed, skip it, it's likely still being updated. #run_checks($anvil);
} }
$anvil->nice_exit({exit_code => 0}); $anvil->nice_exit({exit_code => 0});
@ -96,6 +94,72 @@ $anvil->nice_exit({exit_code => 0});
# Functions # # Functions #
############################################################################################################# #############################################################################################################
### TODO: Left off here. Run periodic checks for files that need to be pulled/removed, mode changed,
### etc. For 3.0, we'll ignore files people add manually though later we'll probably want to
### auto-sync them.
### NOTE: When finding new files, check the size, sleep for 30 seconds, and check again. If a file's
### size changed, skip it, it's likely still being updated.
### NOTE: This isn't finished, and likely won't be for a while.
sub run_checks
{
my ($anvil) = @_;
# First, get a list of files we're expected to have.
$anvil->Database->get_files({debug => 3, include_deleted => 1});
$anvil->Database->get_file_locations({debug => 3});
if ($anvil->Get->host_type eq "striker")
{
# Look for files to add
}
else
{
# Are we an Anvil! member?
my $anvil_uuid = $anvil->Cluster->get_anvil_uuid();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }});
if (not $anvil_uuid)
{
# Nothing to do.
$anvil->nice_exit({exit_code => 0});
}
# What files should we have?
foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{files}{file_name}})
{
# TODO: Once per day, calculate the md5sums and compare against the DB.
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_size = $anvil->data->{files}{file_name}{$file_name}{file_size};
my $file_type = $anvil->data->{files}{file_name}{$file_name}{file_type};
my $file_path = $file_directory."/".$file_name;
my $file_location_uuid = $anvil->data->{file_locations}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_location_uuid};
my $file_location_active = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
file_uuid => $file_uuid,
file_name => $file_name,
file_directory => $file_directory,
file_size => $file_size." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $file_size}).")",
file_type => $file_type,
file_path => $file_path,
file_location_uuid => $file_location_uuid,
file_location_active => $file_location_active,
}});
if (-e $file_path)
{
# File exists, should it?
}
else
{
# File doesn't exist, should it?
}
}
}
return(0);
}
sub process_file_mode sub process_file_mode
{ {
my ($anvil) = @_; my ($anvil) = @_;

@ -26,48 +26,26 @@ $anvil->Get->switches;
$anvil->Database->connect({debug => 3}); $anvil->Database->connect({debug => 3});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0132"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0132"});
exit; my $anvil_uuid = "2ac4dbcb-25d2-44b2-ae07-59707b0551ca";
my $node1_host_uuid = "92d0106c-8717-45da-a413-663d50323982";
my $node2_host_uuid = "8da3d2fe-783a-4619-abb5-8ccae58f7bd6";
my $anvil_uuid = $anvil->data->{switches}{'anvil-uuid'}; my $primary_host_uuid = $anvil->Cluster->get_primary_host_uuid({debug => 2, anvil_uuid => $anvil_uuid});
print "Anvil! UUID: [".$anvil_uuid."]\n"; if (not $primary_host_uuid)
$anvil->Database->get_anvils(); {
$anvil->Get->available_resources({ print "Neither node is primary.\n";
debug => 2, }
anvil_uuid => $anvil_uuid, elsif ($primary_host_uuid eq $node1_host_uuid)
}); {
print "Node 1 is primary\n";
my $has_dr = $anvil->data->{anvil_resources}{$anvil_uuid}{has_dr} ? "Yes" : "No"; }
print "- Anvil! Name: ..... [".$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name}."] available resources;\n"; elsif ($primary_host_uuid eq $node2_host_uuid)
print "- Has DR Host? ..... [".$has_dr."]\n";
print "- CPU Cores/Threads: [".$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores}." / ".$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}."]\n";
print "- RAM Total/Free: .. [".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{hardware}})." / ".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}})."] (".$anvil->Convert->add_commas({number => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{hardware}})." / ".$anvil->Convert->add_commas({number => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}}).")\n";
print "- Networks;\n";
foreach my $bridge_name (sort {$a cmp $b} keys %{$anvil->data->{anvil_resources}{$anvil_uuid}{bridges}})
{ {
if ($anvil->data->{anvil_resources}{$anvil_uuid}{bridges}{$bridge_name}{on_nodes}) print "Node 2 is primary\n";
{
if ($anvil->data->{anvil_resources}{$anvil_uuid}{bridges}{$bridge_name}{on_dr})
{
print " - ".$bridge_name."\n";
}
else
{
print " - ".$bridge_name." (not on DR)\n";
}
}
} }
print "- Storage:\n"; else
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}; print "wtf? [".$primary_host_uuid."]\n";
my $vg_size = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{vg_size};
my $vg_free = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size};
my $dr_size = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{vg_size_on_dr};
my $dr_free = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{available_on_dr};
print " - Storage group: [".$storage_group_uuid."]\n";
print " |- Name: ....... [".$storage_group_name."]\n";
print " |- Size/Free: .. [".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size})." / ".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_free})."] (".$anvil->Convert->add_commas({number => $vg_size})." / ".$anvil->Convert->add_commas({number => $vg_free}).")\n";
print " \\- DR Size/Free: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $dr_size})." / ".$anvil->Convert->bytes_to_human_readable({'bytes' => $dr_free})."] (".$anvil->Convert->add_commas({number => $dr_size})." / ".$anvil->Convert->add_commas({number => $dr_free}).")\n";
} }
$anvil->nice_exit({exit_code => 0}); $anvil->nice_exit({exit_code => 0});

Loading…
Cancel
Save