#!/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. # # Exit codes; # 0 = Normal exit. # 1 = No database connection. # # TODO: # use strict; use warnings; use Anvil::Tools; require POSIX; use Term::Cap; use Data::Dumper; my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; if (($running_directory =~ /^\./) && ($ENV{PWD})) { $running_directory =~ s/^\./$ENV{PWD}/; } # Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete. $| = 1; my $anvil = Anvil::Tools->new(); ### TODO: Remove this before final release $anvil->Log->level({set => 2}); $anvil->Log->secure({set => 1}); ########################################## # 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->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 }}); # Connect to the database(s). If we have no connections, we'll proceed anyway as one of the 'run_once' tasks # is to setup the database server. $anvil->Database->connect(); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"}); if (not $anvil->data->{sys}{database}{connections}) { # No databases, update the job, sleep for a bit and then exit. The daemon will pick it up and try # again after we exit. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0305"}); sleep 10; $anvil->nice_exit({exit_code => 1}); } # If we don't have a job UUID, try to find one. if (not $anvil->data->{switches}{'job-uuid'}) { # Load the job data. $anvil->data->{switches}{'job-uuid'} = $anvil->Job->get_job_uuid({program => $THIS_FILE}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::job-uuid" => $anvil->data->{switches}{'job-uuid'} }}); } # If we still don't have a job-uuit, go into interactive mode. if ($anvil->data->{switches}{'job-uuid'}) { # Load the job data. $anvil->Job->clear(); $anvil->Job->get_job_details(); $anvil->Job->update_progress({ progress => 1, job_picked_up_by => $$, job_picked_up_at => time, message => "message_0251", }); # Job data will be in $anvil->data->{jobs}{job_data} run_jobs($anvil); } else { 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); } $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->{target_server}{anvil_dr1_host_uuid} = "" if not exists $anvil->data->{target_server}{anvil_dr1_host_uuid}; $anvil->data->{target_server}{anvil_dr1_host_name} = "" if not exists $anvil->data->{target_server}{anvil_dr1_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 { my ($anvil) = @_; $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->data->{target_server}{anvil_dr1_host_uuid} = "" if not defined $anvil->data->{target_server}{anvil_dr1_host_uuid}; $anvil->data->{target_server}{anvil_dr1_host_name} = "" if not defined $anvil->data->{target_server}{anvil_dr1_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->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::server" => $anvil->data->{switches}{server}, }}); 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}; my $dr1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_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, dr1_host_uuid => $dr1_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->data->{target_server}{anvil_dr1_host_uuid} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; $anvil->data->{target_server}{anvil_dr1_host_name} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; $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}, "target_server::anvil_dr1_host_uuid" => $anvil->data->{target_server}{anvil_dr1_host_uuid}, "target_server::anvil_dr1_host_name" => $anvil->data->{target_server}{anvil_dr1_host_name}, }}); if ($dr1_host_uuid) { $anvil->data->{target_server}{anvil_dr1_host_uuid} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid}; $anvil->data->{target_server}{anvil_dr1_host_name} = $anvil->data->{hosts}{host_uuid}{$dr1_host_uuid}{host_name};; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "target_server::anvil_dr1_host_uuid" => $anvil->data->{target_server}{anvil_dr1_host_uuid}, "target_server::anvil_dr1_host_name" => $anvil->data->{target_server}{anvil_dr1_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) { # 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); } } 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}; $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, }}); 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) { 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; } } 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) { 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; } } 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"; # 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); }