diff --git a/man/anvil-manage-server.8 b/man/anvil-manage-server.8 index 02eb746d..2a3677eb 100644 --- a/man/anvil-manage-server.8 +++ b/man/anvil-manage-server.8 @@ -1,13 +1,13 @@ .\" Manpage for the Alteeve! anvil-manage-server tool .\" Contact mkelly@alteeve.com to report issues, concerns or suggestions. -.TH anvil-manage-server "8" "October 19 2022" "Anvil! Intelligent Availability™ Platform" +.TH anvil-manage-server "8" "Mar 21 2024" "Anvil! Intelligent Availability™ Platform" .SH NAME -anvil-manage-server \- Tool used to manage a server running on an Anvil! cluster. +anvil-manage-server \- Tool used to manage a server, like resync'ing servers on a rebuilt host. .SH SYNOPSIS .B anvil-manage-server \fI\, \/\fR[\fI\,options\/\fR] .SH DESCRIPTION -anvil-manage-server \- This tool allow the management of a server's hardware. +anvil-manage-server \- This tool allow the management of a server. .TP .SH OPTIONS .TP @@ -25,49 +25,11 @@ Set the log level for this run to 1, 2 or 3 (higher == more verbose). .TP .SS "Commands:" .TP -\-k, \fB\-\-anvil\fR -If specified, and \fBserver\fR is not specified, this will list the servers running on the Anvil! system currently. If, in the unlikely event that two servers exist on different Anvil! systems but with the same name, this will help identify which server you want to work on. +\fB\-\-server\fR all, or +This is the server to work on. .TP -\-k, \fB\-\-server\fR - -.TP -\-k, \fB\-\-\fR - -.TP -\-k, \fB\-\-\fR - -.TP -\-k, \fB\-\-\fR - -.TP -\-k, \fB\-\-\fR - -.TP -\-k, \fB\-\-\fR - -.TP -\-k, \fB\-\-\fR - -.TP -\-k, \fB\-\-\fR - -.TP -\-k, \fB\-\-\fR - -.TP -\-k, \fB\-\-\fR - -$anvil->data->{switches}{boot} = ""; # This is a comma-separated list of ordered boot devices -$anvil->data->{switches}{cores} = ""; # This sets the server to use this number of CPU cores. -$anvil->data->{switches}{drive} = ""; # drive being modified (insert/eject ISO, growing drive) -$anvil->data->{switches}{eject} = ""; # This will eject whatever ISO (if any) in the '--drive'. -$anvil->data->{switches}{'expand-to'} = ""; # When the drive is a disk (backed by a DRBD resource), this is the new desired size to grow to. -$anvil->data->{switches}{insert} = ""; # This is the ISO to insert into the --drive -$anvil->data->{switches}{'job-uuid'} = ""; -$anvil->data->{switches}{ram} = ""; # This is the amount of RAM to set the server to use. -$anvil->data->{switches}{server} = ""; # server name or uuid -$anvil->data->{switches}{y} = ""; # Don't prompt for confirmation. Only useful when there isn't a job UUID. - +\fB\-\-resync\fR +This will check to see if the server is sync'ing on this host. If it is not, and if there are sufficient free resources, the server will be configured locally. This will create a local logical volume, which will be used to connect to the peer's replicated storage. The definition file will be written out, if needed. If '\fB\-\-server\fR' isn't used, all servers will be sync'ed (alphatically, stopping if there are insufficient resources). .IP .SH AUTHOR Written by Madison Kelly, Alteeve staff and the Anvil! project contributors. diff --git a/scancore-agents/scan-drbd/scan-drbd b/scancore-agents/scan-drbd/scan-drbd index 80ec7d84..d276359c 100755 --- a/scancore-agents/scan-drbd/scan-drbd +++ b/scancore-agents/scan-drbd/scan-drbd @@ -100,6 +100,8 @@ find_changes($anvil); check_config($anvil); +find_missing_resources($anvil); + fix_things($anvil); # Shut down. @@ -110,6 +112,17 @@ $anvil->ScanCore->agent_shutdown({agent => $THIS_FILE}); # Functions # ############################################################################################################# +# If this node has been rebuilt, we'll need to add missing DRBD resources. This isn't done in +# anvil-join-anvil as the backing VG may not show free space if the user simply deleted the '/home' +# partition. +sub find_missing_resources +{ + my ($anvil) = @_; + + + return(0); +} + # This looks for issues that we can fix, and if any are found, we try to fix them. sub fix_things { diff --git a/tools/anvil-manage-server b/tools/anvil-manage-server index 438f0250..06171c2d 100755 --- a/tools/anvil-manage-server +++ b/tools/anvil-manage-server @@ -1,7 +1,6 @@ #!/usr/bin/perl # -# This program will manage servers; Changing RAM, CPU cores, Growing virtual disks, adding virtual disks, -# inserting and ejecting ISO images into virtual optical media. +# This server handles tasks like restoring servers on a rebuilt peer, and other (future) tasks. # # Exit codes; # 0 = Normal exit. @@ -30,7 +29,11 @@ $| = 1; my $anvil = Anvil::Tools->new(); # Read switches (target ([user@]host[:port]) and the file with the target's password. -$anvil->Get->switches({list => ["anvil", "boot", "cores", "drive", "eject", "expand-to", "insert", "ram", "server", "y"], man => $THIS_FILE}); +$anvil->Get->switches({list => [ + "resync", + "server", + "y" +], man => $THIS_FILE}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }}); @@ -47,6 +50,8 @@ if (not $anvil->data->{sys}{database}{connections}) $anvil->nice_exit({exit_code => 1}); } +### TODO: We don't yet run as a job. For now, the only thing this tool does is find/resync servers, which +### happens automatically. # If we still don't have a job-uuit, go into interactive mode. if ($anvil->data->{switches}{'job-uuid'}) { @@ -63,18 +68,10 @@ if ($anvil->data->{switches}{'job-uuid'}) # Job data will be in $anvil->data->{jobs}{job_data} run_jobs($anvil); } -else + +if ($anvil->data->{switches}{resync}) { - process_interactive($anvil); - - - ### TODO: Old way - # Interactive! -# $anvil->data->{new_config}{cpu}{sockets} = ""; -# $anvil->data->{new_config}{cpu}{cores} = ""; -# $anvil->data->{new_config}{ram}{'bytes'} = ""; -# $anvil->data->{old_config}{ram}{'bytes'} = ""; -# interactive_question($anvil); + handle_resync($anvil); } $anvil->nice_exit({exit_code => 0}); @@ -84,2324 +81,52 @@ $anvil->nice_exit({exit_code => 0}); # Functions # ############################################################################################################# -sub process_interactive -{ - my ($anvil) = @_; - - # Preset values. - $anvil->data->{target_server}{anvil_uuid} = "" if not exists $anvil->data->{target_server}{anvil_uuid}; - $anvil->data->{target_server}{anvil_name} = "" if not exists $anvil->data->{target_server}{anvil_uuid}; - $anvil->data->{target_server}{server_uuid} = "" if not exists $anvil->data->{target_server}{anvil_uuid}; - $anvil->data->{target_server}{server_uuid} = "" if not exists $anvil->data->{target_server}{anvil_uuid}; - $anvil->data->{target_server}{server_state} = "" if not exists $anvil->data->{target_server}{server_state}; - $anvil->data->{target_server}{anvil_description} = "" if not exists $anvil->data->{target_server}{anvil_description}; - $anvil->data->{target_server}{anvil_node1_host_uuid} = "" if not exists $anvil->data->{target_server}{anvil_node1_host_uuid}; - $anvil->data->{target_server}{anvil_node1_host_name} = "" if not exists $anvil->data->{target_server}{anvil_node1_host_name}; - $anvil->data->{target_server}{anvil_node2_host_uuid} = "" if not exists $anvil->data->{target_server}{anvil_node2_host_uuid}; - $anvil->data->{target_server}{anvil_node2_host_name} = "" if not exists $anvil->data->{target_server}{anvil_node2_host_name}; - - - $anvil->data->{new_config}{cpu}{sockets} = ""; - $anvil->data->{new_config}{cpu}{cores} = ""; - $anvil->data->{new_config}{ram}{'bytes'} = ""; - - $anvil->data->{old_config}{ram}{'bytes'} = ""; - - # Did they specify an Anvil! system? - if (not $anvil->data->{switches}{anvil}) - { - # Is this machine in an Anvil!? - $anvil->Database->get_hosts(); - my $host_uuid = $anvil->Get->host_uuid(); - $anvil->data->{switches}{anvil} = $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_uuid}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - host_uuid => $host_uuid, - "switches::anvil" => $anvil->data->{switches}{anvil}, - }}); - } - if ($anvil->data->{switches}{anvil}) - { - $anvil->Get->anvil_from_switch({anvil => $anvil->data->{switches}{anvil}}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "switches::anvil_name" => $anvil->data->{switches}{anvil_name}, - "switches::anvil_uuid" => $anvil->data->{switches}{anvil_uuid}, - }}); - } - - # Did they specify a server? - if ($anvil->data->{switches}{server}) - { - $anvil->Get->server_from_switch({server => $anvil->data->{switches}{server}}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "switches::anvil_name" => $anvil->data->{switches}{anvil_name}, - "switches::anvil_uuid" => $anvil->data->{switches}{anvil_uuid}, - }}); - } - - # If we don't habe a server, show the list of servers. - if (not $anvil->data->{switches}{server}) - { - # If we've got an Anvil!, show the VMs on it. Otherwise, show all VMs. - if ($anvil->data->{switches}{anvil_name}) - { - - } - } - - return(0); -} - - - - - - - - - - - - - - - - - - - - - - -### NOTE: Old functions, likely to be removed ### - -sub run_jobs -{ - my ($anvil) = @_; - - - - return(0); -} - -sub interactive_question +# This looks for a server (or all servers) and if any aren't found locally, they're connected. +sub handle_resync { my ($anvil) = @_; + # If the cluster is up and both nodes are online, make sure all DRBD resources are connected. $anvil->Database->get_hosts(); - $anvil->Database->get_anvils(); - $anvil->Database->get_servers(); - - $anvil->data->{target_server}{server_uuid} = "" if not defined $anvil->data->{target_server}{server_uuid}; - $anvil->data->{target_server}{server_name} = "" if not defined $anvil->data->{target_server}{server_name}; - $anvil->data->{target_server}{server_state} = "" if not defined $anvil->data->{target_server}{server_state}; - $anvil->data->{target_server}{anvil_uuid} = "" if not defined $anvil->data->{target_server}{anvil_uuid}; - $anvil->data->{target_server}{anvil_name} = "" if not defined $anvil->data->{target_server}{anvil_name}; - $anvil->data->{target_server}{anvil_description} = "" if not defined $anvil->data->{target_server}{anvil_description}; - $anvil->data->{target_server}{anvil_node1_host_uuid} = "" if not defined $anvil->data->{target_server}{anvil_node1_host_uuid}; - $anvil->data->{target_server}{anvil_node1_host_name} = "" if not defined $anvil->data->{target_server}{anvil_node1_host_name}; - $anvil->data->{target_server}{anvil_node2_host_uuid} = "" if not defined $anvil->data->{target_server}{anvil_node2_host_uuid}; - $anvil->data->{target_server}{anvil_node2_host_name} = "" if not defined $anvil->data->{target_server}{anvil_node2_host_name}; - - ### Anvil - # If 'switches::anvil' is set, see if it's a UUID and then set either 'anvil-uuid' or 'anvil-name'. - if ($anvil->data->{switches}{anvil}) - { - if ($anvil->Validate->uuid({uuid => $anvil->data->{switches}{anvil}})) - { - $anvil->data->{target_server}{anvil_uuid} = $anvil->data->{switches}{anvil}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::anvil_uuid" => $anvil->data->{target_server}{anvil_uuid}, - }}); - } - else - { - $anvil->data->{target_server}{anvil_name} = $anvil->data->{switches}{anvil}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::anvil_name" => $anvil->data->{target_server}{anvil_name}, - }}); - } - } - - # Do we know or can we find the Anvil! UUID? - if ((not $anvil->data->{target_server}{anvil_name}) && ($anvil->data->{switches}{'anvil-name'})) - { - $anvil->data->{target_server}{anvil_name} = $anvil->data->{switches}{'anvil-name'}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::anvil_name" => $anvil->data->{target_server}{anvil_name}, - }}); - } - if ((not $anvil->data->{target_server}{anvil_uuid}) && ($anvil->data->{switches}{'anvil-uuid'})) - { - $anvil->data->{target_server}{anvil_uuid} = $anvil->data->{switches}{'anvil-uuid'}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::anvil_uuid" => $anvil->data->{target_server}{anvil_uuid}, - }}); - } - - if ((not $anvil->data->{target_server}{anvil_uuid}) && (not $anvil->data->{target_server}{anvil_name})) - { - # Nothing given. Is this host a node, perhaps? - my $anvil_uuid = $anvil->Cluster->get_anvil_uuid(); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); - - if ($anvil_uuid) - { - $anvil->data->{target_server}{anvil_uuid} = $anvil_uuid; - $anvil->data->{target_server}{anvil_name} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::anvil_name" => $anvil->data->{target_server}{anvil_name}, - "target_server::anvil_uuid" => $anvil->data->{target_server}{anvil_uuid}, - }}); - } - else - { - # If there is only one Anvil!, choose it - my $known_anvils = keys %{$anvil->data->{anvils}{anvil_name}}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { known_anvils => $known_anvils }}); - if (not $known_anvils) - { - my $variables = { server_uuid => $anvil->data->{target_server}{server_uuid} }; - $anvil->Jobs->update_progress({ - progress => 100, - message => "error_0321", - job_status => "failed", - log_level => 1, - priority => "err", - }); - $anvil->nice_exit({exit_code => 1}); - } - elsif ($known_anvils == 1) - { - foreach my $anvil_name (keys %{$anvil->data->{anvils}{anvil_name}}) - { - $anvil->data->{target_server}{anvil_name} = $anvil_name; - $anvil->data->{target_server}{anvil_uuid} = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_uuid}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::anvil_name" => $anvil->data->{target_server}{anvil_name}, - "target_server::anvil_uuid" => $anvil->data->{target_server}{anvil_uuid}, - }}); - } - } - } - } - elsif (not $anvil->data->{target_server}{anvil_uuid}) - { - # We have a name, get the UUID. - $anvil->data->{target_server}{anvil_uuid} = $anvil->Cluster->get_anvil_uuid({anvil_name => $anvil->data->{target_server}{anvil_name}}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "target_server::anvil_uuid" => $anvil->data->{target_server}{anvil_uuid} }}); - - # If the name is bad, error out if not interactive - if (not $anvil->data->{target_server}{anvil_uuid}) - { - # Bad server UUID. If it's a job, abort. Otherwise, clear and go back to - my $variables = { anvil_name => $anvil->data->{target_server}{anvil_name} }; - $anvil->Jobs->update_progress({ - progress => 100, - message => "error_0319", - variables => $variables, - job_status => "failed", - log_level => 1, - priority => "err", - }); - if ($anvil->data->{switches}{'job-uuid'}) - { - $anvil->nice_exit({exit_code => 1}); - } - $anvil->data->{target_server}{anvil_name} = ""; - } - } - elsif (not $anvil->data->{target_server}{anvil_name}) - { - $anvil->data->{target_server}{anvil_name} = $anvil->Cluster->get_anvil_name({anvil_uuid => $anvil->data->{target_server}{anvil_uuid}}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "target_server::anvil_name" => $anvil->data->{target_server}{anvil_name} }}); - - # If the name is bad, error out if not interactive - if (not $anvil->data->{target_server}{anvil_name}) - { - # Bad server UUID. If it's a job, abort. Otherwise, clear and go back to - my $variables = { anvil_uuid => $anvil->data->{target_server}{anvil_uuid} }; - $anvil->Jobs->update_progress({ - progress => 100, - message => "error_0320", - variables => $variables, - job_status => "failed", - log_level => 1, - priority => "err", - }); - if ($anvil->data->{switches}{'job-uuid'}) - { - $anvil->nice_exit({exit_code => 1}); - } - $anvil->data->{target_server}{anvil_uuid} = ""; - } - } - - ### Server - # First, has the user specified a server? If so, and if it's by name, make sure it's unique. If the - # name exists on two or more Anvil! systems, we'll need an Anvil! name as well. If it's unique, we - # can devine the Anvil! UUID. + $anvil->DRBD->get_status(); + my $host_uuid = $anvil->Get->host_uuid(); + my $host_type = $anvil->Get->host_type(); + my $short_host_name = $anvil->Get->short_host_name(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "switches::server" => $anvil->data->{switches}{server}, + host_uuid => $host_uuid, + host_type => $host_type, + short_host_name => $short_host_name, }}); - if ($anvil->data->{switches}{server}) - { - my $server = $anvil->data->{switches}{server}; - if ($anvil->Validate->uuid({uuid => $server})) - { - $anvil->data->{target_server}{server_uuid} = $server; - $anvil->data->{target_server}{server_name} = exists $anvil->data->{servers}{server_uuid}{$server} ? $anvil->data->{servers}{server_uuid}{$server}{server_name} : ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::server_uuid" => $anvil->data->{target_server}{server_uuid}, - "target_server::server_name" => $anvil->data->{target_server}{server_name}, - }}); - } - else - { - $anvil->data->{target_server}{server_name} = $server; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::server_name" => $anvil->data->{target_server}{server_name}, - }}); - if ($anvil->data->{target_server}{anvil_uuid}) - { - my $anvil_uuid = $anvil->data->{target_server}{anvil_uuid}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); - - $anvil->data->{target_server}{server_uuid} = exists $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$server} ? $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$server}{server_uuid} : ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::server_uuid" => $anvil->data->{target_server}{server_uuid}, - }}); - } - } - } - - # If we have a server UUID, make sure it's valid. - if ($anvil->data->{target_server}{server_uuid}) - { - # Pull up the server data. - my $server_uuid = $anvil->data->{target_server}{server_uuid}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_uuid => $server_uuid }}); - if (exists $anvil->data->{servers}{server_uuid}{$server_uuid}) - { - # We can divine everthing from this. - my $anvil_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_anvil_uuid}; - my $server_name = $anvil->data->{target_server}{server_name}; - my $server_host_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_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_node1_host_uuid}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - anvil_uuid => $anvil_uuid, - server_name => $server_name, - server_host_uuid => $server_host_uuid, - node1_host_uuid => $node1_host_uuid, - node2_host_uuid => $node2_host_uuid, - }}); - - $anvil->data->{target_server}{anvil_uuid} = $anvil_uuid; - $anvil->data->{target_server}{server_name} = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_name}; - $anvil->data->{target_server}{server_state} = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state}; - $anvil->data->{target_server}{anvil_name} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name}; - $anvil->data->{target_server}{anvil_description} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_description}; - $anvil->data->{target_server}{anvil_node1_host_uuid} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; - $anvil->data->{target_server}{anvil_node1_host_name} = $anvil->data->{hosts}{host_uuid}{$node1_host_uuid}{host_name}; - $anvil->data->{target_server}{anvil_node2_host_uuid} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; - $anvil->data->{target_server}{anvil_node2_host_name} = $anvil->data->{hosts}{host_uuid}{$node2_host_uuid}{host_name}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::anvil_uuid" => $anvil->data->{target_server}{anvil_uuid}, - "target_server::server_name" => $anvil->data->{target_server}{server_name}, - "target_server::server_state" => $anvil->data->{target_server}{server_state}, - "target_server::anvil_description" => $anvil->data->{target_server}{anvil_description}, - "target_server::anvil_node1_host_uuid" => $anvil->data->{target_server}{anvil_node1_host_uuid}, - "target_server::anvil_node1_host_name" => $anvil->data->{target_server}{anvil_node1_host_name}, - "target_server::anvil_node2_host_uuid" => $anvil->data->{target_server}{anvil_node2_host_uuid}, - "target_server::anvil_node2_host_name" => $anvil->data->{target_server}{anvil_node2_host_name}, - }}); - - ### Pull out details of the server. - # How much RAM are we using and how much is configured? - $anvil->data->{target_server}{ram_in_use} = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_ram_in_use}; - $anvil->data->{target_server}{configured_ram} = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_configured_ram}; - $anvil->data->{target_server}{server_host_uuid} = $server_host_uuid; - $anvil->data->{target_server}{server_host_name} = $anvil->data->{hosts}{host_uuid}{$server_host_uuid}{host_name}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::ram_in_use" => $anvil->Convert->add_commas({number => $anvil->data->{target_server}{ram_in_use}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{target_server}{ram_in_use}}).")", - "target_server::configured_ram" => $anvil->Convert->add_commas({number => $anvil->data->{target_server}{configured_ram}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{target_server}{configured_ram}}).")", - "target_server::server_host_uuid" => $anvil->data->{target_server}{server_host_uuid}, - "target_server::server_host_name" => $anvil->data->{target_server}{server_host_name}, - }}); - if ($anvil->data->{target_server}{server_state} eq "shut off") - { - $anvil->data->{target_server}{ram_in_use} = 0; - $anvil->data->{target_server}{server_host_uuid} = ""; - $anvil->data->{target_server}{server_host_name} = ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::ram_in_use" => $anvil->Convert->add_commas({number => $anvil->data->{target_server}{ram_in_use}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{target_server}{ram_in_use}}).")", - "target_server::server_host_uuid" => $anvil->data->{target_server}{server_host_uuid}, - "target_server::server_host_name" => $anvil->data->{target_server}{server_host_name}, - }}); - } - - # Does this server boot after others, or stay off? - $anvil->data->{target_server}{boot}{after_server_name} = ""; - $anvil->data->{target_server}{boot}{after_server_uuid} = ""; - $anvil->data->{target_server}{boot}{start_delay} = ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "servers::server_uuid::${server_uuid}::server_start_after_server_uuid" => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_after_server_uuid}, - }}); - if (($anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_after_server_uuid}) && ($anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_after_server_uuid} ne "NULL")) - { - my $start_after_server_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_after_server_uuid}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { start_after_server_uuid => $start_after_server_uuid }}); - - if ($start_after_server_uuid eq "00000000-0000-0000-0000-000000000000") - { - # Stay off - $anvil->data->{target_server}{boot}{after_server_name} = $anvil->Words->string({key => "striker_0292"}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::boot::after_server_name" => $anvil->data->{target_server}{boot}{after_server_name}, - }}); - } - else - { - # Server proper - $anvil->data->{target_server}{boot}{after_server_name} = $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$start_after_server_uuid}{server_uuid}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::boot::after_server_name" => $anvil->data->{target_server}{boot}{after_server_name}, - }}); - } - $anvil->data->{target_server}{boot}{after_server_uuid} = "00000000-0000-0000-0000-000000000000"; - $anvil->data->{target_server}{boot}{start_delay} = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_delay}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::boot::after_server_uuid" => $anvil->data->{target_server}{boot}{after_server_uuid}, - "target_server::boot::start_delay" => $anvil->data->{target_server}{boot}{start_delay}, - }}); - } - - # Get a list of files on this Anvil! - foreach my $file_uuid (keys %{$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}}) - { - my $file_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_name}; - my $file_type = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - file_uuid => $file_uuid, - file_name => $file_name, - file_type => $file_type, - }}); - - $anvil->data->{files}{$file_type}{name}{$file_name}{directory} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory}; - $anvil->data->{files}{$file_type}{name}{$file_name}{file_size} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size}; - $anvil->data->{files}{$file_type}{name}{$file_name}{md5sum} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum}; - $anvil->data->{files}{$file_type}{name}{$file_name}{file_uuid} = $file_uuid; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "files::${file_type}::name::${file_name}::directory" => $anvil->data->{files}{$file_type}{name}{$file_name}{directory}, - "files::${file_type}::name::${file_name}::file_size" => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->Convert->add_commas({number => $anvil->data->{files}{$file_type}{name}{$file_name}{file_size}})})." (".$anvil->data->{files}{$file_type}{name}{$file_name}{file_size}.")", - "files::${file_type}::name::${file_name}::md5sum" => $anvil->data->{files}{$file_type}{name}{$file_name}{md5sum}, - "files::${file_type}::name::${file_name}::file_uuid" => $anvil->data->{files}{$file_type}{name}{$file_name}{file_uuid}, - }}); - } - - # Get and parse the server's definition. - $anvil->Database->get_server_definitions({ - debug => 2, - server_uuid => $server_uuid, - }); - - my $short_host_name = $anvil->Get->short_host_name(); - my $definition_uuid = $anvil->data->{server_definitions}{server_definition_server_uuid}{$server_uuid}{server_definition_uuid}; - my $definition_xml = $anvil->data->{server_definitions}{server_definition_server_uuid}{$server_uuid}{server_definition_xml}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { - 's1:short_host_name' => $short_host_name, - 's2:definition_uuid' => $definition_uuid, - 's3:definition_xml' => $definition_xml, - }}); - - $anvil->Server->parse_definition({ - debug => 2, - source => "from_db", - server => $anvil->data->{target_server}{server_name}, - definition => $definition_xml, - host => $short_host_name, - }); - - # If only VCPU is set, cores and threads will both be '1' but 'total' will be higher. - # Windows (and others?) interprets this as X number of single core sockets. - $anvil->data->{target_server}{server_cpu_total} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{cpu}{total_cores} if not defined $anvil->data->{target_server}{server_cpu_total}; - $anvil->data->{target_server}{server_cpu_sockets} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{cpu}{sockets} if not defined $anvil->data->{target_server}{server_cpu_sockets}; - $anvil->data->{target_server}{server_cpu_cores} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{cpu}{threads} if not defined $anvil->data->{target_server}{server_cpu_cores}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - 's1:target_server::server_cpu_sockets' => $anvil->data->{target_server}{server_cpu_sockets}, - 's2:target_server::server_cpu_cores' => $anvil->data->{target_server}{server_cpu_cores}, - 's3:target_server::server_cpu_total' => $anvil->data->{target_server}{server_cpu_total}, - }}); - - if (($anvil->data->{target_server}{server_cpu_sockets} == 1) && ($anvil->data->{target_server}{server_cpu_cores} == 1) && ($anvil->data->{target_server}{server_cpu_total} > 1)) - { - $anvil->data->{target_server}{server_cpu_sockets} = $anvil->data->{target_server}{server_cpu_total}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - 's1:target_server::server_cpu_sockets' => $anvil->data->{target_server}{server_cpu_sockets}, - }}); - } - - # Pull out the existing disks. - foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target => $target }}); - - $anvil->data->{target_server}{disk}{$target}{device_bus} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{device_bus}; - $anvil->data->{target_server}{disk}{$target}{boot_order} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{boot_order} ? $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{boot_order} : 0; - $anvil->data->{target_server}{disk}{$target}{cache} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{driver}{cache}; - $anvil->data->{target_server}{disk}{$target}{io} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{driver}{io}; - $anvil->data->{target_server}{disk}{$target}{path} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{path}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::disk::${target}::device_bus" => $anvil->data->{target_server}{disk}{$target}{device_bus}, - "target_server::disk::${target}::boot_order" => $anvil->data->{target_server}{disk}{$target}{boot_order}, - "target_server::disk::${target}::cache" => $anvil->data->{target_server}{disk}{$target}{cache}, - "target_server::disk::${target}::io" => $anvil->data->{target_server}{disk}{$target}{io}, - "target_server::disk::${target}::path" => $anvil->data->{target_server}{disk}{$target}{path}, - }}); - - if ($anvil->data->{target_server}{disk}{$target}{boot_order}) - { - my $boot_order = $anvil->data->{target_server}{disk}{$target}{boot_order}; - $anvil->data->{target_server}{boot_order}{$boot_order} = $target; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::boot_order::${boot_order}::${target}" => $anvil->data->{target_server}{boot_order}{$boot_order}, - }}); - } - } - - foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{cdrom}{target}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target => $target }}); - - $anvil->data->{target_server}{cdrom}{$target}{device_bus} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{cdrom}{target}{$target}{device_bus}; - $anvil->data->{target_server}{cdrom}{$target}{boot_order} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{cdrom}{target}{$target}{boot_order} ? $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{cdrom}{target}{$target}{boot_order} : 0; - $anvil->data->{target_server}{cdrom}{$target}{path} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{cdrom}{target}{$target}{path}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::cdrom::${target}::device_bus" => $anvil->data->{target_server}{cdrom}{$target}{device_bus}, - "target_server::cdrom::${target}::boot_order" => $anvil->data->{target_server}{cdrom}{$target}{boot_order}, - "target_server::cdrom::${target}::path" => $anvil->data->{target_server}{cdrom}{$target}{path}, - }}); - - if ($anvil->data->{target_server}{cdrom}{$target}{boot_order}) - { - my $boot_order = $anvil->data->{target_server}{cdrom}{$target}{boot_order}; - $anvil->data->{target_server}{boot_order}{$boot_order} = $target; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::boot_order::${boot_order}::${target}" => $anvil->data->{target_server}{boot_order}{$boot_order}, - }}); - } - } - - foreach my $script ("pre_migration", "post_migration") - { - my $file_uuid_key = "server_".$script."_file_uuid"; - my $argument_key = "server_".$script."_arguments"; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - script => $script, - file_uuid_key => $file_uuid_key, - }}); - - $anvil->data->{target_server}{scripts}{$script}{file_uuid} = ""; - $anvil->data->{target_server}{scripts}{$script}{file_name} = ""; - $anvil->data->{target_server}{scripts}{$script}{arguments} = ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "servers::server_uuid::${server_uuid}::${file_uuid_key}" => $anvil->data->{servers}{server_uuid}{$server_uuid}{$file_uuid_key}, - }}); - if (($anvil->data->{servers}{server_uuid}{$server_uuid}{$file_uuid_key}) && ($anvil->data->{servers}{server_uuid}{$server_uuid}{$file_uuid_key} ne "NULL")) - { - my $file_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{$file_uuid_key}; - my $file_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_name}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - file_uuid => $file_uuid, - file_name => $file_name, - }}); - - $anvil->data->{target_server}{scripts}{$script}{file_uuid} = $file_uuid; - $anvil->data->{target_server}{scripts}{$script}{file_name} = $file_name; - $anvil->data->{target_server}{scripts}{$script}{arguments} = $anvil->data->{servers}{server_uuid}{$server_uuid}{$argument_key}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::scripts::${script}::file_uuid" => $anvil->data->{target_server}{scripts}{$script}{file_uuid}, - "target_server::scripts::${script}::file_name" => $anvil->data->{target_server}{scripts}{$script}{file_name}, - "target_server::scripts::${script}::arguments" => $anvil->data->{target_server}{scripts}{$script}{arguments}, - }}); - } - } - - # Get the available resources. - $anvil->Get->available_resources({debug => 2}); - } - else - { - # Bad server UUID. If it's a job, abort. Otherwise, clear and go back to - my $variables = { server_uuid => $anvil->data->{target_server}{server_uuid} }; - $anvil->Jobs->update_progress({ - progress => 100, - message => "error_0318", - variables => $variables, - job_status => "failed", - log_level => 1, - priority => "err", - }); - if ($anvil->data->{switches}{'job-uuid'}) - { - $anvil->nice_exit({exit_code => 1}); - } - $anvil->data->{target_server}{server_uuid} = ""; - } - } - - # If we don't have an Anvil! UUID at this point, we need to ask the user. - my $termios = new POSIX::Termios; - $termios->getattr; - my $ospeed = $termios->getospeed; - - my $terminal = Tgetent Term::Cap { TERM => undef, OSPEED => $ospeed }; - $terminal->Trequire(qw/ce ku kd/); - - if (not $anvil->data->{target_server}{anvil_uuid}) - { - interactive_ask_anvil_name($anvil, $terminal); - } - if (not $anvil->data->{target_server}{server_uuid}) - { - interactive_ask_server_name($anvil, $terminal); - } - - # Made it here? Show the menu. - interactive_configure_main($anvil, $terminal); - - return(0); -} - -sub interactive_configure_main -{ - my ($anvil, $terminal) = @_; - - while(1) - { - print $terminal->Tputs('cl'); - print $anvil->Words->string({key => "job_0355", variables => { - anvil_name => $anvil->data->{target_server}{anvil_name}, - server_name => $anvil->data->{target_server}{server_name}, - }})."\n"; - - my $changes = 0; - my $cpu_star = ""; - my $ram_star = ""; - my $storage_star = ""; - if (($anvil->data->{new_config}{cpu}{sockets}) or ($anvil->data->{new_config}{cpu}{cores})) - { - $cpu_star = "*"; - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - cpu_star => $cpu_star, - changes => $changes, - }}); - } - if ($anvil->data->{new_config}{ram}{'bytes'}) - { - $ram_star = "*"; - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - ram_star => $ram_star, - changes => $changes, - }}); - } - if (exists $anvil->data->{new_config}{storage_group_data}) - { - foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::storage_group_data::${storage_group_name}::new_drive_size" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size}, - }}); - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size}) - { - $storage_star = "*"; - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - storage_star => $storage_star, - changes => $changes, - }}); - } - foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target => $target }}); - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes}) - { - $storage_star = "*"; - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - storage_star => $storage_star, - changes => $changes, - }}); - } - } - } - } - - print "[ 1 ] - CPU".$cpu_star."\n"; - print "[ 2 ] - RAM".$ram_star."\n"; - print "[ 3 ] - Storage".$storage_star."\n"; - print "[ 4 ] - Network\n"; - print "[ 5 ] - Boot Order\n"; - print "[ 6 ] - Cluster Management\n"; - print "\n"; - print "[ B ] - Back\n"; - print "[ Q ] - Quit\n"; - if ($changes) - { - if (($anvil->data->{new_config}{cpu}{sockets}) or ($anvil->data->{new_config}{cpu}{cores})) - { - $changes++; - my $say_old_cpu = $anvil->data->{old_config}{cpu}{sockets}." socket(s), ".$anvil->data->{old_config}{cpu}{cores}." core(s)"; - my $say_new_cpu = $anvil->data->{new_config}{cpu}{sockets}." socket(s), ".$anvil->data->{new_config}{cpu}{cores}." core(s)"; - print " - Change CPU from: [".$say_old_cpu."] to: [".$say_new_cpu."]\n"; - } - if ($anvil->data->{new_config}{ram}{'bytes'}) - { - $changes++; - my $say_old_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old_config}{ram}{'bytes'}}); - my $say_new_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new_config}{ram}{'bytes'}}); - print " - Change RAM from: [".$say_old_ram."] to: [".$say_new_ram."]\n"; - } - if (exists $anvil->data->{new_config}{storage_group_data}) - { - foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::storage_group_data::${storage_group_name}::new_drive_size" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size}, - }}); - - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size} =~ /new:(\d+)$/) - { - my $say_new_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $1}); - $changes++; - print " - Create a new drive that is: [".$say_new_size."] large.\n"; - } - foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::storage_group_data::${storage_group_name}::target::${target}::changes" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes}, - }}); - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} =~ /grow:(\d+)$/) - { - my $say_new_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $1}); - my $say_old_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size}}); - $changes++; - print " - Grow: [".$storage_group_name."/".$target."] from: [".$say_old_size."] to: [".$say_new_size."]\n"; - } - elsif ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} eq "delete") - { - my $say_old_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size}}); - $changes++; - print " - Delete: [".$storage_group_name."/".$target."], freeing up: [".$say_old_size."].\n"; - } - } - } - } - - print "[ S ] - Save and commit the changes.\n"; - } - print "\n"; - print $terminal->Tgoto('cm', 0, (10+$changes))."? "; - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - - if ($answer eq "1") - { - interactive_configure_cpu($anvil, $terminal); - } - elsif ($answer eq "2") - { - interactive_configure_ram($anvil, $terminal); - } - elsif ($answer eq "3") - { - interactive_configure_storage($anvil, $terminal); - } - elsif ($answer eq "4") - { - print "Going to Network menu\n"; - sleep 1; - } - elsif ($answer eq "5") - { - print "Going to Boot order menu\n"; - sleep 1; - } - elsif ($answer eq "6") - { - print "Going to cluster manager menu\n"; - sleep 1; - } - elsif (lc($answer) eq "b") - { - $anvil->data->{target_server}{server_name} = ""; - $anvil->data->{target_server}{server_uuid} = ""; - $anvil->data->{switches}{server} = ""; - interactive_ask_server_name($anvil, $terminal); - } - elsif (lc($answer) eq "s") - { - # Confirm changes - print "Confirm chagnes menu\n"; - sleep 1; - } - else - { - print "Invalid selection, please enter the digit for the menu you want.\n"; - sleep 1; - } -=cut -1. CPU - * Max (threads): X - 1. Sockets: - 2. Cores: -2. RAM - * Available: X - * In use: y - * Configured: z - 1. Size: -3. Storage - 1. Optical media - - 1. Insert / change - - 2. Eject - 2. Disks - 1. New - - - 1. Grow - 2. Delete - 3. Move - 3. Boot order - -4. Network - - 1. MAC Address - 2. emulation type - 3. Plug in / Unplug - 4. Bridge - 5. Delete - 1. Add -5. Boot Order -=cut - } - - return(0); -} - -sub interactive_configure_storage -{ - my ($anvil, $terminal) = @_; - - while(1) - { - # Here, we'll list each storage pool and for each indicate if it's used and, if so - $anvil->Database->get_storage_group_data(); - my $index = 1; - my $lines = 2; - my $changes = ""; - - print $terminal->Tputs('cl'); - print $anvil->Words->string({key => "job_0355", variables => { - anvil_name => $anvil->data->{target_server}{anvil_name}, - server_name => $anvil->data->{target_server}{server_name}, - }})."\n"; - print "* Storage configuration.\n"; - my $anvil_uuid = $anvil->data->{target_server}{anvil_uuid}; - foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_name}}) - { - my $storage_group_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_name}{$storage_group_name}{storage_group_uuid}; - my $vg_size = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{vg_size}; - my $free_size = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{free_size}; - my $vg_size_on_dr = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{vg_size_on_dr}; - my $available_on_dr = $anvil->data->{anvil_resources}{$anvil_uuid}{storage_group}{$storage_group_uuid}{available_on_dr}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - 's1:storage_group_name' => $storage_group_name, - 's2:storage_group_uuid' => $storage_group_uuid, - 's3:vg_size' => $vg_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size}).")", - 's4:free_size' => $free_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $free_size}).")", - 's5:vg_size_on_dr' => $vg_size_on_dr." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size_on_dr}).")", - 's6:available_on_dr' => $free_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $available_on_dr}).")", - }}); - - # Store the SG options so we can pull up the details when a user selects one to work - # with - $anvil->data->{storage_group_data}{$index}{name} = $storage_group_name; - $anvil->data->{storage_group_data}{$index}{uuid} = $storage_group_uuid; - $anvil->data->{storage_group_data}{$index}{size} = $vg_size; - $anvil->data->{storage_group_data}{$index}{free} = $free_size; - $anvil->data->{storage_group_data}{$index}{used} = $vg_size - $free_size; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:storage_group_data::${index}::name" => $anvil->data->{storage_group_data}{$index}{name}, - "s2:storage_group_data::${index}::uuid" => $anvil->data->{storage_group_data}{$index}{uuid}, - "s3:storage_group_data::${index}::size" => $anvil->data->{storage_group_data}{$index}{size}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{storage_group_data}{$index}{size}}).")", - "s4:storage_group_data::${index}::free" => $anvil->data->{storage_group_data}{$index}{free}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{storage_group_data}{$index}{free}}).")", - "s5:storage_group_data::${index}::used" => $anvil->data->{storage_group_data}{$index}{used}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{storage_group_data}{$index}{used}}).")", - }}); - - if (not exists $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size}) - { - $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size} = ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::storage_group_data::${storage_group_name}::new_drive_size" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size}, - }}); - } - - foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{target_server}{disk}}) - { - my $device_bus = $anvil->data->{target_server}{disk}{$target}{device_bus}; - my $cache = $anvil->data->{target_server}{disk}{$target}{cache}; - my $io = $anvil->data->{target_server}{disk}{$target}{io}; - my $this_path = $anvil->data->{target_server}{disk}{$target}{path}; - my $boot_order = $anvil->data->{target_server}{disk}{$target}{boot_order} ? $anvil->data->{target_server}{disk}{$target}{boot_order} : ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - target => $target, - device_bus => $device_bus, - cache => $cache, - io => $io, - this_path => $this_path, - boot_order => $boot_order, - }}); - - my $this_storage_group_uuid = $anvil->Storage->get_storage_group_from_path({ - debug => 2, - anvil_uuid => $anvil_uuid, - path => $this_path, - }); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { this_storage_group_uuid => $this_storage_group_uuid }}); - - if (($this_storage_group_uuid) && ($storage_group_uuid eq $this_storage_group_uuid)) - { - $anvil->data->{storage_group_data}{$index}{target}{$target}{path} = $this_path; - $anvil->data->{storage_group_data}{$index}{target}{$target}{boot_order} = $boot_order; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:storage_group_data::${index}::target::${target}::path" => $anvil->data->{storage_group_data}{$index}{target}{$target}{path}, - "s2:storage_group_data::${index}::target::${target}::boot_order" => $anvil->data->{storage_group_data}{$index}{target}{$target}{boot_order}, - }}); - - if (not exists $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes}) - { - $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} = ""; - } - $changes = $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} ? "*" : ""; - } - } - - $lines += 2; - print "[ ".$index." ] - Name: \"".$storage_group_name."\" - Size: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size})."], Free: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $free_size})."]".$changes."\n"; - - my $path_count = keys %{$anvil->data->{storage_group_data}{$index}{target}}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { path_count => $path_count }}); - if ($path_count) - { - foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{storage_group_data}{$index}{target}}) - { - my $path = $anvil->data->{storage_group_data}{$index}{target}{$target}{path}; - my $boot_order = $anvil->data->{storage_group_data}{$index}{target}{$target}{boot_order}; - my $size = $anvil->Storage->get_size_of_block_device({path => $path}); - my $say_size = ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - size => $size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $size}).")", - }}); - if ($size !~ /^\d+$/) - { - $say_size = ""; - } - else - { - $say_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $size}) - } - - print " - Target: [".$target."], boot order: [".$boot_order."], backed by: [".$path."], Size: [".$say_size."]\n"; - $lines++; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { lines => $lines }}); - - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes}) - { - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} =~ /grow:(\d+)$/) - { - my $new_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $1}); - $lines++; - print " - Will grow to: [".$new_size."]\n"; - } - elsif ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} eq "delete") - { - $lines++; - print " - Marked for deletion!\n"; - } - } - } - } - else - { - print " - \n"; - } - - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size} =~ /new:(\d+)/) - { - print " - New drive will be created that is: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $1})."] large.\n"; - $lines++; - } - $index++; - } - - # Optical drives - foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{target_server}{cdrom}}) - { - $anvil->data->{optical_drives}{$index}{target} = $target; - $anvil->data->{optical_drives}{$index}{device_bus} = $anvil->data->{target_server}{cdrom}{$target}{device_bus}; - $anvil->data->{optical_drives}{$index}{boot_order} = $anvil->data->{target_server}{cdrom}{$target}{boot_order}; - $anvil->data->{optical_drives}{$index}{iso} = $anvil->data->{target_server}{cdrom}{$target}{path}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "optical_drives::${index}::target" => $anvil->data->{optical_drives}{$index}{target}, - "optical_drives::${index}::device_bus" => $anvil->data->{optical_drives}{$index}{device_bus}, - "optical_drives::${index}::boot_order" => $anvil->data->{optical_drives}{$index}{boot_order}, - "optical_drives::${index}::iso" => $anvil->data->{optical_drives}{$index}{iso}, - }}); - - my $say_disc = $anvil->data->{optical_drives}{$index}{iso} ? $anvil->data->{optical_drives}{$index}{iso} : ""; - print "[ ".$index." ] - Optical drive: [".$anvil->data->{optical_drives}{$index}{device_bus}."/".$target."], boot order: [".$anvil->data->{optical_drives}{$index}{boot_order}."], ISO: [".$say_disc."]\n"; - $index++; - $lines++; - } - - foreach my $boot_order (sort {$a <=> $b} keys %{$anvil->data->{target_server}{boot_order}}) - { - my $target = $anvil->data->{target_server}{boot_order}{$boot_order}; - my $path = exists $anvil->data->{target_server}{disk}{$target} ? $anvil->data->{target_server}{disk}{$target}{boot_order} : $anvil->data->{target_server}{cdrom}{$target}{path}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:boot_order" => $boot_order, - "s2:target" => $target, - "s3:path" => $path, - }}); - } - - print "\n"; - print "[ B ] - Back\n"; - print "[ Q ] - Quit\n"; - if ($changes) - { - print "- Changes can be committed on the main page.\n"; - print $terminal->Tgoto('cm', 0, ($lines+3))."? "; - } - else - { - print $terminal->Tgoto('cm', 0, ($lines+2))."? "; - } - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - if ($answer =~ /^\d+$/) - { - if (exists $anvil->data->{storage_group_data}{$answer}) - { - interactive_configure_storage_group($anvil, $terminal, $answer); - } - elsif (exists $anvil->data->{optical_drives}{$index}) - { - interactive_configure_optical_disk($anvil, $terminal, $answer); - } - } - elsif (lc($answer) eq "b") - { - interactive_configure_main($anvil, $terminal); - } - } - - return(0); -} - -sub interactive_configure_optical_disk -{ - my ($anvil, $terminal, $index) = @_; - - while(1) + if ($host_type ne "node") { - # This refreshes files as well. - $anvil->Database->get_anvils(); - - my $lines = 3; - my $target = $anvil->data->{optical_drives}{$index}{target}; - my $device_bus = $anvil->data->{optical_drives}{$index}{device_bus}; - my $boot_order = $anvil->data->{optical_drives}{$index}{boot_order}; - my $iso = $anvil->data->{optical_drives}{$index}{iso}; - my $changes = 0; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:target" => $target, - "s2:device_bus" => $device_bus, - "s3:boot_order" => $boot_order, - "s4:iso" => $iso, - }}); - - if (not exists $anvil->data->{new_config}{optical}{$target}) - { - $anvil->data->{new_config}{optical}{$target}{changes} = ""; - $anvil->data->{old_config}{optical}{$target}{disc} = $iso; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:new_config::optical::${target}::changes" => $anvil->data->{new_config}{optical}{$target}{changes}, - "s1:old_config::optical::${target}::disc" => $anvil->data->{old_config}{optical}{$target}{disc}, - }}); - } - if ($anvil->data->{new_config}{optical}{$target}{changes}) - { - $changes = 1; - } - - print $terminal->Tputs('cl'); - print $anvil->Words->string({key => "job_0355", variables => { - anvil_name => $anvil->data->{target_server}{anvil_name}, - server_name => $anvil->data->{target_server}{server_name}, - }})."\n"; - print "* Managing: [".$device_bus."/".$target."]\n"; - if ($iso) - { - print "[ E ] - Eject: [".$iso."]\n"; - if ($anvil->data->{new_config}{optical}{$target}{changes} eq "eject") - { - print " - To be ejected.\n"; - $lines++; - } - print "[ C ] - Change disc.\n"; - $lines += 2; - } - else - { - print "[ I ] - Insert ISO\n"; - $lines++; - } - - print "\n"; - print "[ B ] - Back\n"; - print "[ Q ] - Quit\n"; - if ($changes) - { - print "- Changes can be committed on the main page.\n"; - print $terminal->Tgoto('cm', 0, ($lines+3))."? "; - } - else - { - print $terminal->Tgoto('cm', 0, ($lines+2))."? "; - } - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - if ((lc($answer) eq "e") && ($iso)) - { - $anvil->data->{new_config}{optical}{$target}{changes} = "eject"; - $anvil->data->{old_config}{optical}{$target}{disc} = $iso; - print "The disc: [".$iso."] will be ejected.\n"; - hold_for_input($anvil); - } - elsif ((lc($answer) eq "c") && (lc($answer) eq "i")) - { - my $file_uuid = pick_file($anvil, $terminal, $index); - if ($file_uuid) - { - my $file_name = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name}; - $anvil->data->{new_config}{optical}{$target}{changes} = "insert:".$file_uuid; - if ($iso) - { - print "- Will replace the disc with: [".$file_name."].\n" - } - else - { - print "- Will insert the disc: [".$file_name."].\n"; - } - hold_for_input($anvil); - } - } - elsif (lc($answer) eq "b") - { - interactive_configure_storage($anvil, $terminal); - } + # Not a node, nothing to do. + return(0); } - return(0); -} - -sub pick_file -{ - my ($anvil, $terminal, $drive_index) = @_; - - my $file_uuid = ""; - my $anvil_uuid = $anvil->data->{target_server}{anvil_uuid}; - my $target = $anvil->data->{optical_drives}{$drive_index}{target}; - my $device_bus = $anvil->data->{optical_drives}{$drive_index}{device_bus}; - my $boot_order = $anvil->data->{optical_drives}{$drive_index}{boot_order}; - my $iso = $anvil->data->{optical_drives}{$drive_index}{iso}; + # We can only proceed if the peer is online. + my $problem = $anvil->Cluster->parse_cib({debug => 3}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:drive_index" => $drive_index, - "s2:anvil_uuid" => $anvil_uuid, - "s3:target" => $target, - "s4:device_bus" => $device_bus, - "s5:boot_order" => $boot_order, - "s6:iso" => $iso, + problem => $problem, + "cib::parsed::local::ready" => $anvil->data->{cib}{parsed}{'local'}{ready}, + "cib::parsed::peer::ready" => $anvil->data->{cib}{parsed}{peer}{ready}, }}); - while(1) - { - $anvil->Database->get_anvils(); - - print $terminal->Tputs('cl'); - print $anvil->Words->string({key => "job_0355", variables => { - anvil_name => $anvil->data->{target_server}{anvil_name}, - server_name => $anvil->data->{target_server}{server_name}, - }})."\n"; - - my $index = 1; - my $lines = 3; - - print "* What file do you want to insert into: [".$device_bus."/".$target."]?\n"; - foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}}) - { - my $file_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid}; - my $file_directory = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory}; - my $file_size = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size}; - my $file_md5sum = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum}; - my $file_type = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:file_name" => $file_name, - "s2:file_uuid" => $file_uuid, - "s3:file_directory" => $file_directory, - "s4:file_size" => $file_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $file_size}).")", - "s5:file_md5sum" => $file_md5sum, - "s6:file_type" => $file_type, - }}); - - next if $file_type ne "iso"; - print "[ ".$index."] - ".$file_name.", size: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $file_size})."], md5_sum: [".$file_md5sum."]\n"; - - $anvil->data->{iso_files}{$index}{file_uuid} = $file_uuid; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:iso_files::${index}::file_uuid" => $anvil->data->{iso_files}{$index}{file_uuid}, - }}); - } - - print "\n"; - print "[ B ] - Back\n"; - print "[ Q ] - Quit\n"; - print $terminal->Tgoto('cm', 0, ($lines+2))."? "; - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - if (($answer =~ /^\d+$/) && (exists $anvil->data->{iso_files}{$answer})) - { - return($anvil->data->{iso_files}{$answer}{file_uuid}); - } - elsif (lc($answer) eq "b") - { - return(""); - } - } - - return(0); -} - -sub interactive_configure_storage_group -{ - my ($anvil, $terminal, $selected_sg) = @_; - - while(1) - { - $anvil->Database->get_storage_group_data(); - my $storage_group_name = $anvil->data->{storage_group_data}{$selected_sg}{name}; - my $storage_group_uuid = $anvil->data->{storage_group_data}{$selected_sg}{uuid}; - my $storage_group_size = $anvil->data->{storage_group_data}{$selected_sg}{size}; - my $storage_group_free = $anvil->data->{storage_group_data}{$selected_sg}{free}; - my $storage_group_used = $anvil->data->{storage_group_data}{$selected_sg}{used}; - my $say_max_free = $anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_free}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:storage_group_name" => $storage_group_name, - "s2:storage_group_uuid" => $storage_group_uuid, - "s3:storage_group_size" => $storage_group_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_size}).")", - "s4:storage_group_free" => $storage_group_free." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_free}).")", - "s5:storage_group_used" => $storage_group_used." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_used}).")", - "s6:say_max_free" => $say_max_free, - }}); - - print $terminal->Tputs('cl'); - print $anvil->Words->string({key => "job_0355", variables => { - anvil_name => $anvil->data->{target_server}{anvil_name}, - server_name => $anvil->data->{target_server}{server_name}, - }})."\n"; - - foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}}) - { - foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}}) - { - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} =~ /grow:(\d+)$/) - { - my $added = $1 - $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size}; - $storage_group_used += $added; - $storage_group_free -= $added; - $say_max_free = $anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_free}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:added" => $added." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $added}).")", - "s2:storage_group_used" => $storage_group_used." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_used}).")", - "s3:storage_group_free" => $storage_group_free." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_free}).")", - "s4:say_max_free" => $say_max_free, - }}); - } - elsif ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} eq "delete") - { - my $old_size = $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size}; - $storage_group_used -= $old_size; - $storage_group_free -= $old_size; - $say_max_free = $anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_free}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:old_size" => $old_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_size}).")", - "s2:storage_group_used" => $storage_group_used." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_used}).")", - "s3:storage_group_free" => $storage_group_free." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_free}).")", - "s4:say_max_free" => $say_max_free, - }}); - } - } - } - - my $changes = ""; - my $index = 1; - my $lines = 2; - my $drive = {}; - - print "* Storage Group: [".$storage_group_name."] configuration.\n"; - foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{storage_group_data}{$selected_sg}{target}}) - { - my $path = $anvil->data->{storage_group_data}{$selected_sg}{target}{$target}{path}; - my $boot_order = $anvil->data->{storage_group_data}{$selected_sg}{target}{$target}{boot_order}; - my $size = $anvil->Storage->get_size_of_block_device({path => $path}); - my $say_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $size}); - - $drive->{$index} = $target; - - $changes = $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} ? "*" : ""; - print "[ ".$index." ] - Manage: [".$target."], boot order: [".$boot_order."], backed by: [".$path."], Size: [".$say_size."]".$changes."\n"; - $index++; - $lines++; - if ($changes) - { - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} =~ /grow:(\d+)$/) - { - my $new_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $1}); - $lines++; - print " - Will grow to: [".$new_size."]\n"; - } - elsif ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} eq "delete") - { - $lines++; - print " - Marked for deletion!\n"; - - } - } - } - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size}) - { - my $say_requested = ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size} =~ /new:(\d+)$/)[0]; - $say_requested = $anvil->Convert->bytes_to_human_readable({'bytes' => $say_requested}); - print "[ C ] - Cancel creation of new: [".$say_requested."] sized drive.\n"; - } - else - { - print "[ N ] - New Drive\n"; - } - - print "\n"; - print "[ B ] - Back\n"; - print "[ Q ] - Quit\n"; - if ($changes) - { - print "- Changes can be committed on the main page.\n"; - print $terminal->Tgoto('cm', 0, ($lines+5))."? "; - } - else - { - print $terminal->Tgoto('cm', 0, ($lines+4))."? "; - } - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - if (($answer =~ /^\d+$/) && (exists $drive->{$answer})) - { - my $target = $drive->{$answer}; - interactive_configure_storage_group_manage_drive($anvil, $terminal, $selected_sg, $target); - } - elsif (lc($answer) eq "n") - { - print "- How big would you like the new drive to be? Maximum is: [".$say_max_free."]\n"; - my $answer = ; - chomp $answer; - $answer =~ s/^\s+//; - $answer =~ s/\s+$//; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - - if ($answer) - { - # Convert to bytes - my $requested_bytes = $answer; - if ($requested_bytes =~ /\D/) - { - $requested_bytes = $anvil->Convert->human_readable_to_bytes({ - base2 => 1, - size => $requested_bytes, - }); - if ($requested_bytes eq "!!error!!") - { - # Problem. - $requested_bytes = ""; - print "[ Error ] - The answer: [".$answer."] could not be interpretted as a size.\n"; - hold_for_input($anvil); - } - } - - if (($requested_bytes =~ /^\d+$/) && ($requested_bytes > $storage_group_free)) - { - $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size} = ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::storage_group_data::${storage_group_name}::new_drive_size" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size}, - }}); - print "[ Error ] - You asked for: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $requested_bytes})."] (".$anvil->Convert->add_commas({number => $requested_bytes})." bytes), but the max available is: [".$say_max_free."] (".$anvil->Convert->add_commas({number => $storage_group_free})." bytes).\n"; - hold_for_input($anvil); - } - elsif ($requested_bytes) - { - $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size} = "new:".$requested_bytes; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::storage_group_data::${storage_group_name}::new_drive_size" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size}, - }}); - } - } - } - elsif ((lc($answer) eq "c") && ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size})) - { - $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size} = ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::storage_group_data::${storage_group_name}::new_drive_size" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size}, - }}); - print "- New volume will NOT be created.\n"; - hold_for_input($anvil); - } - elsif (lc($answer) eq "b") - { - interactive_configure_storage($anvil, $terminal); - } - } - - return(0); -} - -sub interactive_configure_storage_group_manage_drive -{ - my ($anvil, $terminal, $selected_sg, $target) = @_; - - while(1) - { - $anvil->Database->get_storage_group_data(); - my $storage_group_name = $anvil->data->{storage_group_data}{$selected_sg}{name}; - my $storage_group_uuid = $anvil->data->{storage_group_data}{$selected_sg}{uuid}; - my $storage_group_size = $anvil->data->{storage_group_data}{$selected_sg}{size}; - my $storage_group_free = $anvil->data->{storage_group_data}{$selected_sg}{free}; - my $storage_group_used = $anvil->data->{storage_group_data}{$selected_sg}{used}; - my $path = $anvil->data->{storage_group_data}{$selected_sg}{target}{$target}{path}; - my $boot_order = $anvil->data->{storage_group_data}{$selected_sg}{target}{$target}{boot_order}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:selected_sg" => $selected_sg, - "s2:target" => $target, - "s3:storage_group_name" => $storage_group_name, - "s4:storage_group_uuid" => $storage_group_uuid, - "s5:storage_group_size" => $storage_group_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_size}).")", - "s6:storage_group_free" => $storage_group_free." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_free}).")", - "s6:storage_group_used" => $storage_group_used." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_used}).")", - "s7:path" => $path, - "s8:boot_order" => $boot_order, - }}); - - my $size = $anvil->Storage->get_size_of_block_device({path => $path}); - my $say_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $size}); - my $max_assignable = ($size + $storage_group_free); - my $say_max_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $max_assignable}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:size" => $size, - "s2:max_assignable" => $say_size, - "s3:say_max_size" => $say_max_size, - }}); - - foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::storage_group_data::${storage_group_name}::new_drive_size" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size}, - }}); - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size} =~ /new:(\d+)$/) - { - my $to_create = $1; - $storage_group_used += $to_create; - $storage_group_free -= $to_create; - $max_assignable = $size + $storage_group_free; - $say_max_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $max_assignable}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:to_create" => $to_create." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $to_create}).")", - "s2:storage_group_used" => $storage_group_used." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_used}).")", - "s3:storage_group_free" => $storage_group_free." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_free}).")", - "s4:max_assignable" => $max_assignable, - "s5:say_max_size" => $say_max_size, - }}); - } - foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}}) - { - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} =~ /grow:(\d+)$/) - { - my $added = $1 - $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size}; - $storage_group_used += $added; - $storage_group_free -= $added; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:added" => $added." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $added}).")", - "s2:storage_group_used" => $storage_group_used." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_used}).")", - "s3:storage_group_free" => $storage_group_free." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_free}).")", - }}); - } - elsif ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} eq "delete") - { - my $old_size = $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size}; - $storage_group_used -= $old_size; - $storage_group_free += $old_size; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:old_size" => $old_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_size}).")", - "s2:storage_group_used" => $storage_group_used." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_used}).")", - "s3:storage_group_free" => $storage_group_free." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_free}).")", - }}); - } - } - } - - my $say_new_max_size = $say_max_size; - my $new_max_assignable = $max_assignable; - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} =~ /grow:(\d+)$/) - { - # Add the space assigned to the max size - my $added = $1; - $max_assignable = ($size + $storage_group_free + $added); - $say_max_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $max_assignable}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "s1:added" => $added." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $added}).")", - "s2:max_assignable" => $say_size, - "s3:say_max_size" => $say_max_size, - }}); - } - - print $terminal->Tputs('cl'); - print $anvil->Words->string({key => "job_0355", variables => { - anvil_name => $anvil->data->{target_server}{anvil_name}, - server_name => $anvil->data->{target_server}{server_name}, - }})."\n"; - - my $say_requested = ""; - my $say_delete = ""; - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes}) - { - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} =~ /grow:(\d+)$/) - { - $say_requested = $anvil->Convert->bytes_to_human_readable({'bytes' => $1}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_requested => $say_requested }}); - } - } - my $changes = $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} ? "*" : " "; - print "* Manage: [".$target."], boot order: [".$boot_order."], backed by: [".$path."], Size: [".$say_size."]\n"; - print " - In storage Group: [".$storage_group_name."], Size: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_size})."], Free space: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $storage_group_free})."].\n"; - print "[ G ] - Grow (Current size: [".$say_size."], Requested: [".$say_requested."], Max: [".$say_max_size."]".$changes."\n"; - if ($boot_order == 1) - { - print "[ - ] - .\n"; - } - else - { - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} eq "delete") - { - print "[ D ] - Abort Deletion (Currently scheduled for deletion!)\n"; - } - else - { - print "[ D ] - Delete\n"; - } - } - - print "\n"; - print "[ B ] - Back\n"; - print "[ Q ] - Quit\n"; - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes}) - { - print "- Changes can be committed on the main page.\n"; - print $terminal->Tgoto('cm', 0, 9)."? "; - } - else - { - print $terminal->Tgoto('cm', 0, 8)."? "; - } - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - if (lc($answer) eq "g") - { - my $say_new_max_size = $say_max_size; - my $new_max_assignable = $max_assignable; - # Ask what size they want. - print "- How big do you want the drive to be? You can enter up to: [".$say_max_size."];\n"; - my $answer = ; - chomp $answer; - $answer =~ s/^\s+//; - $answer =~ s/\s+$//; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - if (not $answer) - { - # Go back - interactive_configure_storage_group_manage_drive($anvil, $terminal, $selected_sg, $target); - } - else - { - # Convert to bytes - my $requested_bytes = $answer; - if ($requested_bytes =~ /\D/) - { - $requested_bytes = $anvil->Convert->human_readable_to_bytes({ - base2 => 1, - size => $requested_bytes, - }); - if ($requested_bytes eq "!!error!!") - { - # Problem. - $requested_bytes = ""; - print "[ Error ] - The answer: [".$answer."] could not be interpretted as a size.\n"; - hold_for_input($anvil); - } - } - - if (($requested_bytes =~ /^\d+$/) && ($requested_bytes > $max_assignable)) - { - $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} = ""; - print "[ Error ] - You asked for: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $requested_bytes})."] (".$anvil->Convert->add_commas({number => $requested_bytes})." bytes), but the max available is: [".$say_max_size."] (".$anvil->Convert->add_commas({number => $max_assignable})." bytes).\n"; - hold_for_input($anvil); - interactive_configure_storage_group_manage_drive($anvil, $terminal, $selected_sg, $target); - } - elsif ($requested_bytes) - { - $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} = "grow:".$requested_bytes; - $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size} = $size; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::storage_group_data::${storage_group_name}::target::${target}::changes" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes}, - "old_config::storage_group_data::${storage_group_name}::target::${target}::size" => $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size}, - }}); - } - } - } - if (lc($answer) eq "d") - { - if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} eq "delete") - { - $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} = ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::storage_group_data::${storage_group_name}::target::${target}::changes" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes}, - }}); - } - else - { - $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} = "delete"; - $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size} = $size; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::storage_group_data::${storage_group_name}::target::${target}::changes" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes}, - "old_config::storage_group_data::${storage_group_name}::target::${target}::size" => $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size}, - }}); - } - } - elsif (lc($answer) eq "b") - { - interactive_configure_storage_group($anvil, $terminal, $selected_sg); - } - } - - return(0); -} - -sub hold_for_input -{ - my ($anvil) = @_; - - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - - return(0); -} - -sub check_answer -{ - my ($anvil, $answer) = @_; - - if (lc($answer) eq "q") - { - print "NO CARRIER, good bye.\n"; - $anvil->nice_exit({exit_code => 0}); - } - - return(0); -} - -sub interactive_configure_ram -{ - my ($anvil, $terminal) = @_; - - while(1) - { - # Threads will be the maximum, even without hyperthreading being available. - my $anvil_uuid = $anvil->data->{target_server}{anvil_uuid}; - my $say_current_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{target_server}{configured_ram}}); - my $say_total_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{hardware}}); - my $say_available_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}}); - my $max_assignable = $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available} + $anvil->data->{target_server}{configured_ram}; - my $say_max_assignable = $anvil->Convert->bytes_to_human_readable({'bytes' => $max_assignable}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - anvil_uuid => $anvil_uuid, - say_current_ram => $say_current_ram, - say_total_ram => $say_total_ram, - say_available_ram => $say_available_ram, - say_max_assignable => $say_max_assignable, - }}); - - my $changes = 0; - my $say_new_ram = 0; - if ($anvil->data->{new_config}{ram}{'bytes'}) - { - $say_new_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new_config}{ram}{'bytes'}}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_new_ram => $say_new_ram }}); - } - - my $ram_star = " "; - if (($anvil->data->{new_config}{ram}{'bytes'}) && ($anvil->data->{new_config}{ram}{'bytes'} ne $anvil->data->{target_server}{server_ram_bytes})) - { - $ram_star = "*"; - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - ram_star => $ram_star, - changes => $changes, - }}); - $anvil->data->{old_config}{ram}{'bytes'} = $anvil->data->{target_server}{configured_ram}; - } - - print $terminal->Tputs('cl'); - print $anvil->Words->string({key => "job_0355", variables => { - anvil_name => $anvil->data->{target_server}{anvil_name}, - server_name => $anvil->data->{target_server}{server_name}, - }})."\n"; - print "* RAM configuration. Currently allocated: [".$say_current_ram."], Maximum RAM: [".$say_max_assignable."] (current + free).\n"; - print "[ 1 ] - RAM".$ram_star." (currently: [".$say_current_ram."], new: [".$say_new_ram."])\n"; - - print "\n"; - print "[ B ] - Back\n"; - print "[ Q ] - Quit\n"; - if ($changes) - { - print "- Changes can be committed on the main page.\n"; - print $terminal->Tgoto('cm', 0, 7)."? "; - } - else - { - print $terminal->Tgoto('cm', 0, 6)."? "; - } - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - - if ($answer eq "1") - { - print "- Can specify in bytes or base2 human readible (ie: '4 GiB', '4G', etc)\n"; - print "How much RAM would you like? "; - my $answer = ; - chomp $answer; - $answer =~ s/^\s+//; - $answer =~ s/\s+$//; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - if (not $answer) - { - # Go back - interactive_configure_ram($anvil, $terminal); - } - else - { - # Convert to bytes - my $requested_bytes = $answer; - if ($requested_bytes =~ /\D/) - { - $requested_bytes = $anvil->Convert->human_readable_to_bytes({ - base2 => 1, - size => $requested_bytes, - }); - if ($requested_bytes eq "!!error!!") - { - # Problem. - print "[ Error ] - The answer: [".$answer."] could not be interpretted.\n"; - hold_for_input($anvil); - interactive_configure_ram($anvil, $terminal); - } - } - elsif (not $requested_bytes) - { - interactive_configure_ram($anvil, $terminal); - } - - if (($requested_bytes =~ /^\d+$/) && ($requested_bytes > $max_assignable)) - { - $anvil->data->{new_config}{ram}{'bytes'} = 0; - print "[ Error ] - You asked for: [".$anvil->Convert->bytes_to_human_readable({'bytes' => $requested_bytes})."] (".$anvil->Convert->add_commas({number => $max_assignable})." bytes) RAM, but the max available is: [".$say_max_assignable."] (".$anvil->Convert->add_commas({number => $max_assignable})." bytes).\n"; - hold_for_input($anvil); - interactive_configure_ram($anvil, $terminal); - } - else - { - $anvil->data->{new_config}{ram}{'bytes'} = $requested_bytes; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::ram::bytes" => $anvil->data->{new_config}{ram}{'bytes'}, - }}); - } - } - } - elsif (lc($answer) eq "b") - { - interactive_configure_main($anvil, $terminal); - } - else - { - interactive_configure_ram($anvil, $terminal); - } - } - - return(0); -} - -sub interactive_configure_cpu -{ - my ($anvil, $terminal) = @_; - - while(1) - { - # Threads will be the maximum, even without hyperthreading being available. - my $anvil_uuid = $anvil->data->{target_server}{anvil_uuid}; - my $maximum_cores = $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads}; - my $current_cores = $anvil->data->{target_server}{server_cpu_cores}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - anvil_uuid => $anvil_uuid, - maximum_cores => $maximum_cores, - current_cores => $current_cores, - }}); - - my $changes = 0; - my $star_cores = " "; - if (($anvil->data->{new_config}{cpu}{cores}) && ($anvil->data->{new_config}{cpu}{cores} ne $anvil->data->{target_server}{server_cpu_cores})) - { - $star_cores = "*"; - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - star_cores => $star_cores, - changes => $changes, - }}); - $anvil->data->{old_config}{cpu}{cores} = $anvil->data->{target_server}{server_cpu_cores}; - } - my $star_sockets = " "; - if (($anvil->data->{new_config}{cpu}{sockets}) && ($anvil->data->{new_config}{cpu}{sockets} ne $anvil->data->{target_server}{server_cpu_sockets})) - { - $star_sockets = "*"; - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - star_sockets => $star_sockets, - changes => $changes, - }}); - $anvil->data->{old_config}{cpu}{sockets} = $anvil->data->{target_server}{server_cpu_sockets}; - } - - print $terminal->Tputs('cl'); - print $anvil->Words->string({key => "job_0355", variables => { - anvil_name => $anvil->data->{target_server}{anvil_name}, - server_name => $anvil->data->{target_server}{server_name}, - }})."\n"; - print "* CPU configuration. Maximum cores X sockets is: [".$maximum_cores."]\n"; - print "[ 1 ] - Cores per socket".$star_cores." (currently: [".$anvil->data->{target_server}{server_cpu_cores}."], new: [".$anvil->data->{new_config}{cpu}{cores}."])\n"; - print "[ 2 ] - Sockets".$star_sockets." (currently: [".$anvil->data->{target_server}{server_cpu_sockets}."], new: [".$anvil->data->{new_config}{cpu}{sockets}."])\n"; - - print "\n"; - print "[ B ] - Back\n"; - print "[ Q ] - Quit\n"; - if ($changes) - { - print "- Changes can be committed on the main page.\n"; - print $terminal->Tgoto('cm', 0, 8)."? "; - } - else - { - print $terminal->Tgoto('cm', 0, 7)."? "; - } - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - - if ($answer eq "1") - { - print "How many cores per socket would you like? "; - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - if (not $answer) - { - # Go back - interactive_configure_cpu($anvil, $terminal); - } - elsif ($answer =~ /\D/) - { - print "[ Error ] - The answer: [".$answer."] is not valid. You need to specify a digit.\n"; - print "Press any key to continue.\n"; - hold_for_input($anvil); - interactive_configure_cpu($anvil, $terminal); - } - else - { - # Did they ask for too many? - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::cpu::sockets" => $anvil->data->{new_config}{cpu}{sockets}, - "target_server::server_cpu_sockets" => $anvil->data->{target_server}{server_cpu_sockets}, - maximum_cores => $maximum_cores, - }}); - if (($anvil->data->{new_config}{cpu}{sockets}) && (($answer * $anvil->data->{new_config}{cpu}{sockets}) > $maximum_cores)) - { - print "[ Error ] - With the current socket count of: [".$anvil->data->{new_config}{cpu}{sockets}."], the requested number of cores: [".$answer."] would result in: [".($answer * $anvil->data->{new_config}{cpu}{sockets})."] total cores.\n"; - print " The maximum available on this Anvil! is: [".$maximum_cores."].\n"; - if ($anvil->data->{new_config}{cpu}{sockets} > 1) - { - print " You may wish to reduce the socket count first.\n"; - } - print __LINE__."; Press any key to continue.\n"; - my $answer = ; - interactive_configure_cpu($anvil, $terminal); - } - elsif ((not $anvil->data->{new_config}{cpu}{sockets}) && (($answer * $anvil->data->{target_server}{server_cpu_sockets}) > $maximum_cores)) - { - print "[ Error ] - With the current socket count of: [".$anvil->data->{target_server}{server_cpu_sockets}."], the requested number of cores: [".$answer."] would result in: [".($answer * $anvil->data->{target_server}{server_cpu_sockets})."] total cores.\n"; - print " The maximum available on this Anvil! is: [".$maximum_cores."].\n"; - if ($anvil->data->{target_server}{server_cpu_sockets} > 1) - { - print " You may wish to reduce the socket count first.\n"; - } - print __LINE__."; Press any key to continue.\n"; - hold_for_input($anvil); - interactive_configure_cpu($anvil, $terminal); - } - else - { - $anvil->data->{new_config}{cpu}{cores} = $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::cpu::cores" => $anvil->data->{new_config}{cpu}{cores}, - }}); - } - } - } - elsif ($answer eq "2") - { - print "How many sockets would you like? "; - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - if (not $answer) - { - # Go back - interactive_configure_cpu($anvil, $terminal); - } - elsif ($answer =~ /\D/) - { - print "[ Error ] - The answer: [".$answer."] is not valid. You need to specify a digit.\n"; - print "Press any key to continue.\n"; - hold_for_input($anvil); - interactive_configure_cpu($anvil, $terminal); - } - else - { - # Did they ask for too many? - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::cpu::cores" => $anvil->data->{new_config}{cpu}{cores}, - "target_server::server_cpu_cores" => $anvil->data->{target_server}{server_cpu_cores}, - maximum_cores => $maximum_cores, - }}); - if (($anvil->data->{new_config}{cpu}{cores}) && (($answer * $anvil->data->{new_config}{cpu}{cores}) > $maximum_cores)) - { - print "[ Error ] - With the current core count of: [".$anvil->data->{new_config}{cpu}{cores}."], the requested number of sockets: [".$answer."] would result in: [".($answer * $anvil->data->{new_config}{cpu}{cores})."] total cores.\n"; - print " The maximum available on this Anvil! is: [".$maximum_cores."].\n"; - if ($anvil->data->{new_config}{cpu}{cores} > 1) - { - print " You may wish to reduce the core count first.\n"; - } - print __LINE__."; Press any key to continue.\n"; - hold_for_input($anvil); - interactive_configure_cpu($anvil, $terminal); - } - elsif ((not $anvil->data->{new_config}{cpu}{cores}) && (($answer * $anvil->data->{target_server}{server_cpu_cores}) > $maximum_cores)) - { - print "[ Error ] - With the current core count of: [".$anvil->data->{target_server}{server_cpu_cores}."], the requested number of sockets: [".$answer."] would result in: [".($answer * $anvil->data->{target_server}{server_cpu_cores})."] total cores.\n"; - print " The maximum available on this Anvil! is: [".$maximum_cores."].\n"; - if ($anvil->data->{target_server}{server_cpu_sockets} > 1) - { - print " You may wish to reduce the core count first.\n"; - } - print __LINE__."; Press any key to continue.\n"; - hold_for_input($anvil); - interactive_configure_cpu($anvil, $terminal); - } - else - { - $anvil->data->{new_config}{cpu}{sockets} = $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "new_config::cpu::sockets" => $anvil->data->{new_config}{cpu}{sockets}, - }}); - } - } - } - elsif (lc($answer) eq "b") - { - interactive_configure_main($anvil, $terminal); - } - else - { - interactive_configure_cpu($anvil, $terminal); - } - } - - return(0); -} - -sub interactive_ask_anvil_name -{ - my ($anvil, $terminal) = @_; - - my $retry = 0; - while(1) + if (($problem) or (not $anvil->data->{cib}{parsed}{peer}{ready}) or (not $anvil->data->{cib}{parsed}{'local'}{ready})) { - my $default = ""; - if ($anvil->data->{target_server}{anvil_name}) - { - $default = $anvil->data->{target_server}{anvil_name}; - } - print $terminal->Tputs('cl'); - print $anvil->Words->string({key => "message_0257"})."\n"; - - my $anvil_selection = []; - push @{$anvil_selection}, "NULL"; - - my $anvil_count = 0; - my $longest_anvil_name = 0; - foreach my $anvil_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_name}}) - { - my $anvil_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_uuid}; - my $anvil_description = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_description}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - anvil_name => $anvil_name, - anvil_uuid => $anvil_uuid, - anvil_description => $anvil_description, - }}); - next if $anvil_description eq "DELETED"; - - $anvil_count++; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_count => $anvil_count }}); - push @{$anvil_selection}, $anvil_name; - - if (length($anvil_name) > $longest_anvil_name) - { - $longest_anvil_name = length($anvil_name); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { longest_anvil_name => $longest_anvil_name }}); - } - } - - my $number_length = length($anvil_count + 1); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { number_length => $number_length }}); - for (my $i = 1; $i < @{$anvil_selection}; $i++) - { - my $anvil_name = $anvil_selection->[$i]; - next if $anvil_name eq "NULL"; - my $anvil_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_uuid}; - my $anvil_description = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_description}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - i => $i, - anvil_name => $anvil_name, - anvil_uuid => $anvil_uuid, - anvil_description => $anvil_description, - }}); - - print $anvil->Words->string({key => "message_0258", variables => { - number => sprintf("%-${number_length}s", $i), - anvil_name => sprintf("%-${longest_anvil_name}s", $anvil_name), - anvil_description => $anvil_description, - }})."\n"; - } - print "\n"; - print "[ Q ] - Quit\n"; - print "\n"; - - my $column = 3 + $anvil_count; - print $terminal->Tgoto('cm', 0, $column)."? "; - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - - if ((not $answer) && ($default)) - { - $answer = $default; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - } - - # Reload in case a new anvil! was saved while we waited. - $anvil->Database->get_anvils(); - if (($answer =~ /^\d+$/) && (exists $anvil_selection->[$answer]) && (not exists $anvil->data->{anvils}{anvil_name}{$answer})) - { - $answer = $anvil_selection->[$answer]; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - - $anvil->data->{target_server}{anvil_name} = $answer; - $anvil->data->{target_server}{anvil_uuid} = $anvil->Cluster->get_anvil_uuid({anvil_name => $answer}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::anvil_name" => $anvil->data->{target_server}{anvil_name}, - "target_server::anvil_uuid" => $anvil->data->{target_server}{anvil_uuid}, - }}); - last; - } - elsif ((exists $anvil->data->{anvils}{anvil_name}{$answer}) && (ref($anvil->data->{anvils}{anvil_name}{$answer}) eq "HASH")) - { - # Valid. - $anvil->data->{target_server}{anvil_name} = $answer; - $anvil->data->{target_server}{anvil_uuid} = $anvil->Cluster->get_anvil_uuid({anvil_name => $answer}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::anvil_name" => $anvil->data->{target_server}{anvil_name}, - "target_server::anvil_uuid" => $anvil->data->{target_server}{anvil_uuid}, - }}); - last; - } - else - { - $retry = 1; - } + # Not in the cluster, nothing to do. + return(0); } - - interactive_question($anvil); - - return(0); -} - -sub interactive_ask_server_name -{ - my ($anvil, $terminal) = @_; - $anvil->Database->get_servers({debug => 2}); - - ### TODO: Figure out how many rows we have and break the server list into columns if too long. - ### tput cols - ### tput rows - my $retry = 0; - my $not_found = ""; - while(1) + # Walk through all resources and make sure the peer and local disks are attached and + # the connection established. + foreach my $resource (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}}) { - my $default = ""; - if ($anvil->data->{target_server}{server_name}) - { - $default = $anvil->data->{target_server}{server_name}; - } - print $terminal->Tputs('cl'); - - # Show all the current server names. - if ($retry) - { - print $anvil->Words->string({key => "job_0353"})."\n\n"; - } - my $anvil_uuid = $anvil->data->{target_server}{anvil_uuid}; - print $anvil->Words->string({key => "job_0354", variables => { anvil_name => $anvil->data->{target_server}{anvil_name} }})."\n"; - - # Push the server names into an array, with '0' being null so the list we show the user - # starts at '1'. - my $server_selection = []; - push @{$server_selection}, "NULL"; - - my $server_count = 0; - my $longest_server_name = 0; - 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}; - my $server_state = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - server_name => $server_name, - server_uuid => $server_uuid, - server_state => $server_state, - }}); - next if $server_state eq "DELETED"; - - $server_count++; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_count => $server_count }}); - push @{$server_selection}, $server_name; - - if (length($server_name) > $longest_server_name) - { - $longest_server_name = length($server_name); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { longest_server_name => $longest_server_name }}); - } - } - - my $number_length = length($server_count + 1); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { number_length => $number_length }}); - for (my $i = 1; $i < @{$server_selection}; $i++) - { - my $server_name = $server_selection->[$i]; - next if $server_name eq "NULL"; - my $server_uuid = $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$server_name}{server_uuid}; - my $server_state = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - server_name => $server_name, - server_uuid => $server_uuid, - server_state => $server_state, - }}); - - print $anvil->Words->string({key => "message_0256", variables => { - number => sprintf("%-${number_length}s", $i), - server_name => sprintf("%-${longest_server_name}s", $server_name), - server_state => $server_state, - }})."\n"; - } - print "\n"; - print "[ B ] - Back\n"; - print "[ Q ] - Quit\n"; - print "\n"; - - my $column = 4 + $server_count; - print $terminal->Tgoto('cm', 0, $column)."? "; - my $answer = ; - chomp $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - check_answer($anvil, $answer); - - if ((not $answer) && ($default)) - { - $answer = $default; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - } - - # Reload in case a new anvil! was saved while we waited. - $anvil->Database->get_servers(); - if ($answer) - { - # Found? - if (($answer =~ /^\d+$/) && (exists $server_selection->[$answer]) && (not exists $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$answer})) - { - $answer = $server_selection->[$answer]; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - } - if ((exists $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$answer}) && (ref($anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$answer}) eq "HASH")) - { - # Valid - $anvil->data->{target_server}{server_name} = $answer; - $anvil->data->{target_server}{server_uuid} = $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$answer}{server_uuid}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "target_server::server_name" => $anvil->data->{target_server}{server_name}, - "target_server::server_uuid" => $anvil->data->{target_server}{server_uuid}, - }}); - last; - } - elsif (lc($answer) eq "b") - { - $anvil->data->{target_server}{anvil_name} = ""; - $anvil->data->{target_server}{anvil_uuid} = ""; - $anvil->data->{switches}{anvil} = ""; - $anvil->data->{switches}{'anvil-name'} = ""; - $anvil->data->{switches}{'anvil-uuid'} = ""; - print "Going back\n"; - interactive_ask_anvil_name($anvil, $terminal); - } - else - { - # Inalid. - $not_found = $answer; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { not_found => $not_found }}); - } - last; - } - else - { - $retry = 1; - } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { resource => $resource }}); } - interactive_question($anvil); - - return(0); -} - -sub show_stats -{ - my ($anvil) = @_; - - # Load the server's details. - my $server_xml = $anvil->Server->get_definition({server_uuid => $anvil->data->{sys}{server_uuid}}); - my $server_name = $anvil->data->{sys}{server_name}; - my $short_host_name = $anvil->Get->short_host_name(); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - 's1:short_host_name' => $short_host_name, - 's2:server_name' => $server_name, - 's3:server_xml' => $server_xml, - }}); - - $anvil->Server->parse_definition({ - debug => 2, - source => "from_db", - definition => $server_xml, - server => $server_name, - }); - my $cpu_cores = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{cpu}{total_cores}; - my $ram_bytes = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{memory}; - my $say_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $ram_bytes}); - print "Cores: [".$cpu_cores."], RAM: [".$say_ram."] (".$ram_bytes." bytes)\n"; + $anvil->Database->get_hosts; + $anvil->Database->get_servers; - # Show disks - foreach my $device ("disk", "cdrom") - { - print "- Device: [".$device."]\n"; - foreach my $device_target (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{$device}{target}}) - { - my $boot_order = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{$device}{target}{$device_target}{boot_order}; - my $type = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{$device}{target}{$device_target}{type}; - my $device_bus = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{$device}{target}{$device_target}{device_bus}; - my $path = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{$device}{target}{$device_target}{path}; - print " - Target: [".$device_target."], type: [".$type."], boot order: [".$boot_order."], bus: [".$device_bus."]\n"; - print " - Path: [".$path."]\n"; - if ($device eq "disk") - { - # Pull the size - my $volume = ($path =~ /\/(\d+)$/)[0]; - print " - Volume: [".$volume."]\n"; - foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$server_name}{host}}) - { - my $host_uuid = $anvil->Get->host_uuid_from_name({host_name => $host_name}); - my $device_path = $anvil->data->{new}{resource}{$server_name}{host}{$host_name}{volume}{$volume}{device_path}; - my $backing_disk = $anvil->data->{new}{resource}{$server_name}{host}{$host_name}{volume}{$volume}{backing_disk}; - print " - Host: [".$host_name."] (".$host_uuid."), path: [".$device_path."], backing disk: [".$backing_disk."]\n"; - } - } - else - { - } - } - } return(0); }