#!/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->{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
# 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};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
anvil_uuid => $anvil_uuid,
server_name => $server_name,
server_host_uuid => $server_host_uuid,
node1_host_uuid => $node1_host_uuid,
node2_host_uuid => $node2_host_uuid,
}});
$anvil->data->{target_server}{anvil_uuid} = $anvil_uuid;
$anvil->data->{target_server}{server_name} = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_name};
$anvil->data->{target_server}{server_state} = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state};
$anvil->data->{target_server}{anvil_name} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name};
$anvil->data->{target_server}{anvil_description} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_description};
$anvil->data->{target_server}{anvil_node1_host_uuid} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid};
$anvil->data->{target_server}{anvil_node1_host_name} = $anvil->data->{hosts}{host_uuid}{$node1_host_uuid}{host_name};
$anvil->data->{target_server}{anvil_node2_host_uuid} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
$anvil->data->{target_server}{anvil_node2_host_name} = $anvil->data->{hosts}{host_uuid}{$node2_host_uuid}{host_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"target_server::anvil_uuid" => $anvil->data->{target_server}{anvil_uuid},
"target_server::server_name" => $anvil->data->{target_server}{server_name},
"target_server::server_state" => $anvil->data->{target_server}{server_state},
"target_server::anvil_description" => $anvil->data->{target_server}{anvil_description},
"target_server::anvil_node1_host_uuid" => $anvil->data->{target_server}{anvil_node1_host_uuid},
"target_server::anvil_node1_host_name" => $anvil->data->{target_server}{anvil_node1_host_name},
"target_server::anvil_node2_host_uuid" => $anvil->data->{target_server}{anvil_node2_host_uuid},
"target_server::anvil_node2_host_name" => $anvil->data->{target_server}{anvil_node2_host_name},
}});
### Pull out details of the server.
# How much RAM are we using and how much is configured?
$anvil->data->{target_server}{ram_in_use} = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_ram_in_use};
$anvil->data->{target_server}{configured_ram} = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_configured_ram};
$anvil->data->{target_server}{server_host_uuid} = $server_host_uuid;
$anvil->data->{target_server}{server_host_name} = $anvil->data->{hosts}{host_uuid}{$server_host_uuid}{host_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"target_server::ram_in_use" => $anvil->Convert->add_commas({number => $anvil->data->{target_server}{ram_in_use}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{target_server}{ram_in_use}}).")",
"target_server::configured_ram" => $anvil->Convert->add_commas({number => $anvil->data->{target_server}{configured_ram}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{target_server}{configured_ram}}).")",
"target_server::server_host_uuid" => $anvil->data->{target_server}{server_host_uuid},
"target_server::server_host_name" => $anvil->data->{target_server}{server_host_name},
}});
if ($anvil->data->{target_server}{server_state} eq "shut off")
{
$anvil->data->{target_server}{ram_in_use} = 0;
$anvil->data->{target_server}{server_host_uuid} = "";
$anvil->data->{target_server}{server_host_name} = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"target_server::ram_in_use" => $anvil->Convert->add_commas({number => $anvil->data->{target_server}{ram_in_use}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{target_server}{ram_in_use}}).")",
"target_server::server_host_uuid" => $anvil->data->{target_server}{server_host_uuid},
"target_server::server_host_name" => $anvil->data->{target_server}{server_host_name},
}});
}
# Does this server boot after others, or stay off?
$anvil->data->{target_server}{boot}{after_server_name} = "";
$anvil->data->{target_server}{boot}{after_server_uuid} = "";
$anvil->data->{target_server}{boot}{start_delay} = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"servers::server_uuid::${server_uuid}::server_start_after_server_uuid" => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_after_server_uuid},
}});
if (($anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_after_server_uuid}) && ($anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_after_server_uuid} ne "NULL"))
{
my $start_after_server_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_after_server_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { start_after_server_uuid => $start_after_server_uuid }});
if ($start_after_server_uuid eq "00000000-0000-0000-0000-000000000000")
{
# Stay off
$anvil->data->{target_server}{boot}{after_server_name} = $anvil->Words->string({key => "striker_0292"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"target_server::boot::after_server_name" => $anvil->data->{target_server}{boot}{after_server_name},
}});
}
else
{
# Server proper
$anvil->data->{target_server}{boot}{after_server_name} = $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$start_after_server_uuid}{server_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"target_server::boot::after_server_name" => $anvil->data->{target_server}{boot}{after_server_name},
}});
}
$anvil->data->{target_server}{boot}{after_server_uuid} = "00000000-0000-0000-0000-000000000000";
$anvil->data->{target_server}{boot}{start_delay} = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_delay};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"target_server::boot::after_server_uuid" => $anvil->data->{target_server}{boot}{after_server_uuid},
"target_server::boot::start_delay" => $anvil->data->{target_server}{boot}{start_delay},
}});
}
# Get a list of files on this Anvil!
foreach my $file_uuid (keys %{$anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}})
{
my $file_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_name};
my $file_type = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
file_uuid => $file_uuid,
file_name => $file_name,
file_type => $file_type,
}});
$anvil->data->{files}{$file_type}{name}{$file_name}{directory} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory};
$anvil->data->{files}{$file_type}{name}{$file_name}{file_size} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size};
$anvil->data->{files}{$file_type}{name}{$file_name}{md5sum} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum};
$anvil->data->{files}{$file_type}{name}{$file_name}{file_uuid} = $file_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"files::${file_type}::name::${file_name}::directory" => $anvil->data->{files}{$file_type}{name}{$file_name}{directory},
"files::${file_type}::name::${file_name}::file_size" => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->Convert->add_commas({number => $anvil->data->{files}{$file_type}{name}{$file_name}{file_size}})})." (".$anvil->data->{files}{$file_type}{name}{$file_name}{file_size}.")",
"files::${file_type}::name::${file_name}::md5sum" => $anvil->data->{files}{$file_type}{name}{$file_name}{md5sum},
"files::${file_type}::name::${file_name}::file_uuid" => $anvil->data->{files}{$file_type}{name}{$file_name}{file_uuid},
}});
}
# Get and parse the server's definition.
$anvil->Database->get_server_definitions({
debug => 2,
server_uuid => $server_uuid,
});
my $short_host_name = $anvil->Get->short_host_name();
my $definition_uuid = $anvil->data->{server_definitions}{server_definition_server_uuid}{$server_uuid}{server_definition_uuid};
my $definition_xml = $anvil->data->{server_definitions}{server_definition_server_uuid}{$server_uuid}{server_definition_xml};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
's1:short_host_name' => $short_host_name,
's2:definition_uuid' => $definition_uuid,
's3:definition_xml' => $definition_xml,
}});
$anvil->Server->parse_definition({
debug => 2,
source => "from_db",
server => $anvil->data->{target_server}{server_name},
definition => $definition_xml,
host => $short_host_name,
});
# If only VCPU is set, cores and threads will both be '1' but 'total' will be higher.
# Windows (and others?) interprets this as X number of single core sockets.
$anvil->data->{target_server}{server_cpu_total} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{cpu}{total_cores} if not defined $anvil->data->{target_server}{server_cpu_total};
$anvil->data->{target_server}{server_cpu_sockets} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{cpu}{sockets} if not defined $anvil->data->{target_server}{server_cpu_sockets};
$anvil->data->{target_server}{server_cpu_cores} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{cpu}{threads} if not defined $anvil->data->{target_server}{server_cpu_cores};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:target_server::server_cpu_sockets' => $anvil->data->{target_server}{server_cpu_sockets},
's2:target_server::server_cpu_cores' => $anvil->data->{target_server}{server_cpu_cores},
's3:target_server::server_cpu_total' => $anvil->data->{target_server}{server_cpu_total},
}});
if (($anvil->data->{target_server}{server_cpu_sockets} == 1) && ($anvil->data->{target_server}{server_cpu_cores} == 1) && ($anvil->data->{target_server}{server_cpu_total} > 1))
{
$anvil->data->{target_server}{server_cpu_sockets} = $anvil->data->{target_server}{server_cpu_total};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:target_server::server_cpu_sockets' => $anvil->data->{target_server}{server_cpu_sockets},
}});
}
# Pull out the existing disks.
foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target => $target }});
$anvil->data->{target_server}{disk}{$target}{device_bus} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{device_bus};
$anvil->data->{target_server}{disk}{$target}{boot_order} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{boot_order} ? $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{boot_order} : 0;
$anvil->data->{target_server}{disk}{$target}{cache} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{driver}{cache};
$anvil->data->{target_server}{disk}{$target}{io} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{driver}{io};
$anvil->data->{target_server}{disk}{$target}{path} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{disk}{target}{$target}{path};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"target_server::disk::${target}::device_bus" => $anvil->data->{target_server}{disk}{$target}{device_bus},
"target_server::disk::${target}::boot_order" => $anvil->data->{target_server}{disk}{$target}{boot_order},
"target_server::disk::${target}::cache" => $anvil->data->{target_server}{disk}{$target}{cache},
"target_server::disk::${target}::io" => $anvil->data->{target_server}{disk}{$target}{io},
"target_server::disk::${target}::path" => $anvil->data->{target_server}{disk}{$target}{path},
}});
if ($anvil->data->{target_server}{disk}{$target}{boot_order})
{
my $boot_order = $anvil->data->{target_server}{disk}{$target}{boot_order};
$anvil->data->{target_server}{boot_order}{$boot_order} = $target;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"target_server::boot_order::${boot_order}::${target}" => $anvil->data->{target_server}{boot_order}{$boot_order},
}});
}
}
foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{cdrom}{target}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target => $target }});
$anvil->data->{target_server}{cdrom}{$target}{device_bus} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{cdrom}{target}{$target}{device_bus};
$anvil->data->{target_server}{cdrom}{$target}{boot_order} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{cdrom}{target}{$target}{boot_order} ? $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{cdrom}{target}{$target}{boot_order} : 0;
$anvil->data->{target_server}{cdrom}{$target}{path} = $anvil->data->{server}{$short_host_name}{$server_name}{from_db}{device}{cdrom}{target}{$target}{path};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"target_server::cdrom::${target}::device_bus" => $anvil->data->{target_server}{cdrom}{$target}{device_bus},
"target_server::cdrom::${target}::boot_order" => $anvil->data->{target_server}{cdrom}{$target}{boot_order},
"target_server::cdrom::${target}::path" => $anvil->data->{target_server}{cdrom}{$target}{path},
}});
if ($anvil->data->{target_server}{cdrom}{$target}{boot_order})
{
my $boot_order = $anvil->data->{target_server}{cdrom}{$target}{boot_order};
$anvil->data->{target_server}{boot_order}{$boot_order} = $target;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"target_server::boot_order::${boot_order}::${target}" => $anvil->data->{target_server}{boot_order}{$boot_order},
}});
}
}
foreach my $script ("pre_migration", "post_migration")
{
my $file_uuid_key = "server_".$script."_file_uuid";
my $argument_key = "server_".$script."_arguments";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
script => $script,
file_uuid_key => $file_uuid_key,
}});
$anvil->data->{target_server}{scripts}{$script}{file_uuid} = "";
$anvil->data->{target_server}{scripts}{$script}{file_name} = "";
$anvil->data->{target_server}{scripts}{$script}{arguments} = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"servers::server_uuid::${server_uuid}::${file_uuid_key}" => $anvil->data->{servers}{server_uuid}{$server_uuid}{$file_uuid_key},
}});
if (($anvil->data->{servers}{server_uuid}{$server_uuid}{$file_uuid_key}) && ($anvil->data->{servers}{server_uuid}{$server_uuid}{$file_uuid_key} ne "NULL"))
{
my $file_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{$file_uuid_key};
my $file_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
file_uuid => $file_uuid,
file_name => $file_name,
}});
$anvil->data->{target_server}{scripts}{$script}{file_uuid} = $file_uuid;
$anvil->data->{target_server}{scripts}{$script}{file_name} = $file_name;
$anvil->data->{target_server}{scripts}{$script}{arguments} = $anvil->data->{servers}{server_uuid}{$server_uuid}{$argument_key};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"target_server::scripts::${script}::file_uuid" => $anvil->data->{target_server}{scripts}{$script}{file_uuid},
"target_server::scripts::${script}::file_name" => $anvil->data->{target_server}{scripts}{$script}{file_name},
"target_server::scripts::${script}::arguments" => $anvil->data->{target_server}{scripts}{$script}{arguments},
}});
}
}
# Get the available resources.
$anvil->Get->available_resources({debug => 2});
}
else
{
# Bad server UUID. If it's a job, abort. Otherwise, clear and go back to
my $variables = { server_uuid => $anvil->data->{target_server}{server_uuid} };
$anvil->Jobs->update_progress({
progress => 100,
message => "error_0318",
variables => $variables,
job_status => "failed",
log_level => 1,
priority => "err",
});
if ($anvil->data->{switches}{'job-uuid'})
{
$anvil->nice_exit({exit_code => 1});
}
$anvil->data->{target_server}{server_uuid} = "";
}
}
# If we don't have an Anvil! UUID at this point, we need to ask the user.
my $termios = new POSIX::Termios;
$termios->getattr;
my $ospeed = $termios->getospeed;
my $terminal = Tgetent Term::Cap { TERM => undef, OSPEED => $ospeed };
$terminal->Trequire(qw/ce ku kd/);
if (not $anvil->data->{target_server}{anvil_uuid})
{
interactive_ask_anvil_name($anvil, $terminal);
}
if (not $anvil->data->{target_server}{server_uuid})
{
interactive_ask_server_name($anvil, $terminal);
}
# Made it here? Show the menu.
interactive_configure_main($anvil, $terminal);
return(0);
}
sub interactive_configure_main
{
my ($anvil, $terminal) = @_;
while(1)
{
print $terminal->Tputs('cl');
print $anvil->Words->string({key => "job_0355", variables => {
anvil_name => $anvil->data->{target_server}{anvil_name},
server_name => $anvil->data->{target_server}{server_name},
}})."\n";
my $changes = 0;
my $cpu_star = "";
my $ram_star = "";
my $storage_star = "";
if (($anvil->data->{new_config}{cpu}{sockets}) or ($anvil->data->{new_config}{cpu}{cores}))
{
$cpu_star = "*";
$changes = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
cpu_star => $cpu_star,
changes => $changes,
}});
}
if ($anvil->data->{new_config}{ram}{'bytes'})
{
$ram_star = "*";
$changes = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
ram_star => $ram_star,
changes => $changes,
}});
}
if (exists $anvil->data->{new_config}{storage_group_data})
{
foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"new_config::storage_group_data::${storage_group_name}::new_drive_size" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size},
}});
if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size})
{
$storage_star = "*";
$changes = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
storage_star => $storage_star,
changes => $changes,
}});
}
foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target => $target }});
if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes})
{
$storage_star = "*";
$changes = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
storage_star => $storage_star,
changes => $changes,
}});
}
}
}
}
print "[ 1 ] - CPU".$cpu_star."\n";
print "[ 2 ] - RAM".$ram_star."\n";
print "[ 3 ] - Storage".$storage_star."\n";
print "[ 4 ] - Network\n";
print "[ 5 ] - Boot Order\n";
print "[ 6 ] - Cluster Management\n";
print "\n";
print "[ B ] - Back\n";
print "[ Q ] - Quit\n";
if ($changes)
{
if (($anvil->data->{new_config}{cpu}{sockets}) or ($anvil->data->{new_config}{cpu}{cores}))
{
$changes++;
my $say_old_cpu = $anvil->data->{old_config}{cpu}{sockets}." socket(s), ".$anvil->data->{old_config}{cpu}{cores}." core(s)";
my $say_new_cpu = $anvil->data->{new_config}{cpu}{sockets}." socket(s), ".$anvil->data->{new_config}{cpu}{cores}." core(s)";
print " - Change CPU from: [".$say_old_cpu."] to: [".$say_new_cpu."]\n";
}
if ($anvil->data->{new_config}{ram}{'bytes'})
{
$changes++;
my $say_old_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old_config}{ram}{'bytes'}});
my $say_new_ram = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new_config}{ram}{'bytes'}});
print " - Change RAM from: [".$say_old_ram."] to: [".$say_new_ram."]\n";
}
if (exists $anvil->data->{new_config}{storage_group_data})
{
foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"new_config::storage_group_data::${storage_group_name}::new_drive_size" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size},
}});
if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{new_drive_size} =~ /new:(\d+)$/)
{
my $say_new_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $1});
$changes++;
print " - Create a new drive that is: [".$say_new_size."] large.\n";
}
foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"new_config::storage_group_data::${storage_group_name}::target::${target}::changes" => $anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes},
}});
if ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} =~ /grow:(\d+)$/)
{
my $say_new_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $1});
my $say_old_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size}});
$changes++;
print " - Grow: [".$storage_group_name."/".$target."] from: [".$say_old_size."] to: [".$say_new_size."]\n";
}
elsif ($anvil->data->{new_config}{storage_group_data}{$storage_group_name}{target}{$target}{changes} eq "delete")
{
my $say_old_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old_config}{storage_group_data}{$storage_group_name}{target}{$target}{size}});
$changes++;
print " - Delete: [".$storage_group_name."/".$target."], freeing up: [".$say_old_size."].\n";
}
}
}
}
print "[ S ] - Save and commit the changes.\n";
}
print "\n";
print $terminal->Tgoto('cm', 0, (10+$changes))."? ";
my $answer = <STDIN>;
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
<list drives>
1. Insert / change
<file list>
2. Eject
2. Disks
1. New
<storage groups (size available)>
<list drives>
1. Grow
2. Delete
3. Move <when 2+ storage groups>
3. Boot order
<list disks, 0 == don't boot>
4. Network
<interface list>
1. MAC Address
2. emulation type
3. <toggle> 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 = "<unknwon>";
}
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 " - <Storage group not used by this server yet>\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} : "<ejected>";
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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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 "[ - ] - <Cannot delete the boot disk>.\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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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 = <STDIN>;
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);
}