@ -41,13 +41,16 @@ $anvil->Get->switches({list => [
"anvil",
"boot",
"boot-menu",
"boot-order",
"confirm",
"cpu",
"disk",
"eject",
"job-uuid",
"grow",
"insert",
"optical",
"ram",
"server",
"storage-group",
], man => $THIS_FILE});
@ -102,15 +105,15 @@ validate_server($anvil);
if ($anvil->data->{switches}{cpu})
{
# manage_cpu($anvil);
manage_cpu($anvil);
}
elsif ($anvil->data->{switches}{ram})
{
# manage_ram($anvil);
manage_ram($anvil);
}
elsif ($anvil->data->{switches}{boot})
elsif ($anvil->data->{switches}{' boot-order' })
{
manage_boot($anvil);
manage_boot_order ($anvil);
}
elsif ($anvil->data->{switches}{'boot-menu'})
{
@ -133,7 +136,603 @@ $anvil->nice_exit({exit_code => 0});
# Functions #
#############################################################################################################
sub manage_boot
sub manage_cpu
{
my ($anvil) = @_;
my $short_host_name = $anvil->Get->short_host_name;
my $host_uuid = $anvil->Get->host_uuid;
my $server_name = $anvil->data->{switches}{server_name};
my $server_uuid = $anvil->data->{switches}{server_uuid};
my $server_host_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_host_uuid};
my $anvil_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_anvil_uuid};
my $anvil_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name};
my $server_host_name = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:short_host_name' => $short_host_name,
's2:host_uuid' => $host_uuid,
's3:server_name' => $server_name,
's4:server_uuid' => $server_uuid,
's5:server_host_uuid' => $server_host_uuid,
's6:anvil_uuid' => $anvil_uuid,
's7:anvil_name' => $anvil_name,
}});
my $from_source = get_definition_source($anvil);
my $server_state = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
from_source => $from_source,
server_state => $server_state,
}});
if ($server_state eq "running")
{
$server_host_name = $anvil->Database->get_host_from_uuid({
short => 1,
host_uuid => $server_host_uuid,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_host_name => $server_host_name }});
}
# Get available resources.
$anvil->Get->available_resources({
debug => 2,
anvil_uuid => $anvil_uuid,
});
### TODO: Add support for changing the model, fallback, etc, and features
my $total_cores = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{cpu}{total_cores};
my $sockets = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{cpu}{sockets};
my $cores = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{cpu}{cores};
my $threads = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{cpu}{threads};
my $model_name = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{cpu}{model_name};
my $model_fallback = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{cpu}{model_fallback};
my $match = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{cpu}{match};
my $vendor = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{cpu}{vendor};
my $mode = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{cpu}{mode};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
total_cores => $total_cores,
sockets => $sockets,
cores => $cores,
threads => $threads,
model_name => $model_name,
model_fallback => $model_fallback,
match => $match,
vendor => $vendor,
mode => $mode,
}});
foreach my $name (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{cpu}{feature}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
's1:name' => $name,
's2:value' => $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{cpu}{feature}{$name},
}});
}
my $host_cores = $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores};
my $host_threads = $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads};
my $max_cores = $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{available};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:host_cores' => $host_cores,
's2:host_threads' => $host_threads,
's3:max_cores' => $max_cores,
}});
my $recommended_max = $host_cores - 2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { recommended_max => $recommended_max }});
if ($host_cores <= 2)
{
$recommended_max = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { recommended_max => $recommended_max }});
}
# Show the user or change?
if ($anvil->data->{switches}{cpu} eq "#!SET!#")
{
# Show the CPU info
my $variables = {
total_cores => $total_cores,
sockets => $sockets,
cores => $cores,
threads => $threads,
host_cores => $host_cores,
host_threads => $host_threads,
max_cores => $max_cores,
recommended_max => $recommended_max,
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0380", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "message_0380",
variables => $variables,
}) if $anvil->data->{switches}{'job-uuid'};
return(0);
}
my $new_sockets = 1;
my $new_cores = 1;
my $new_threads = 1;
if ($anvil->data->{switches}{cpu} =~ /^(\d+),(\d+),(\d+)$/)
{
$new_sockets = $1;
$new_cores = $2;
$new_threads = $3;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:new_sockets' => $new_sockets,
's2:new_cores' => $new_cores,
's3:new_threads' => $new_threads,
}});
}
elsif ($anvil->data->{switches}{cpu} =~ /^(\d+),(\d+)$/)
{
$new_sockets = $1;
$new_cores = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:new_sockets' => $new_sockets,
's2:new_cores' => $new_cores,
}});
}
elsif ($anvil->data->{switches}{cpu} =~ /^(\d+)$/)
{
$new_cores = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_cores => $new_cores }});
}
else
{
# Bad formatting.
my $variables = { requested_cpu => $anvil->data->{switches}{cpu} };
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0476", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "error_0476",
variables => $variables,
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
# Is the requested number of cores sane?
my $requested_cores = $new_sockets * $new_cores * $new_threads;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { requested_cores => $requested_cores }});
if (($requested_cores < 1) or ($requested_cores > $max_cores))
{
my $variables = {
requested_cores => $requested_cores,
new_sockets => $new_sockets,
new_cores => $new_cores,
new_threads => $new_threads,
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0477", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "error_0477",
variables => $variables,
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
# Still alive?
my $in_cpu = 0;
my $topology_seen = 0;
my $topology_line = "<topology sockets=\"".$new_sockets."\" dies=\"1\" cores=\"".$new_cores."\" threads=\"".$new_threads."\"/>";
my $new_server_definition = "";
foreach my $line (split/\n/, $anvil->data->{servers}{server_uuid}{$server_uuid}{server_definition_xml})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
if ($line =~ /<vcpu/)
{
$line =~ s/<vcpu (.*?)>\d+<\/vcpu>/<vcpu $1>$requested_cores<\/vcpu>/;
$line =~ s/<vcpu>\d+<\/vcpu>/<vcpu>$requested_cores<\/vcpu>/;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
}
if ($in_cpu)
{
if ($line =~ /<\/cpu>/)
{
if (not $topology_seen)
{
$new_server_definition .= " ".$topology_line."\n";
}
$in_cpu = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_cpu => $in_cpu }});
}
if ($line =~ /<topology /)
{
$line = " ".$topology_line;
$topology_seen = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { topology_seen => $topology_seen }});
}
}
if ($line =~ /<cpu/)
{
# <cpu mode="host-passthrough" check="none" migratable="on"/>
if ($line =~ /<cpu (.*?)\/>/)
{
# Adjust to add topology
my $arguments = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { arguments => $arguments }});
$new_server_definition .= " <cpu ".$arguments.">\n";
$new_server_definition .= " ".$topology_line."\n";
$new_server_definition .= " </cpu>\n";
next;
}
$in_cpu = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_cpu => $in_cpu }});
}
$new_server_definition .= $line."\n";
}
# Confirm the new definition is valid
my $problem = $anvil->Server->parse_definition({
debug => 2,
host => $short_host_name,
server => $server_name,
source => "test_xml",
definition => $new_server_definition,
});
if ($problem)
{
# The new definition is bad
my $variables = { new_server_definition => $new_server_definition };
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0470", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "error_0470",
variables => $variables,
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
# Did the user confirm?
if ($anvil->data->{switches}{'job-uuid'})
{
# Running as a job, don't prompt
$anvil->Job->update_progress({
progress => 75,
message => "job_0480",
});
}
elsif ($anvil->data->{switches}{confirm})
{
# User confirmed
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0359"});
}
else
{
# Ask the user to confirm.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0381", variables => {
old_total_cores => $total_cores,
old_sockets => $sockets,
old_cores => $cores,
old_threads => $threads,
new_total_cores => $requested_cores,
new_sockets => $new_sockets,
new_cores => $new_cores,
new_threads => $new_threads,
}});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0021"});
my $answer = <STDIN>;
chomp $answer;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "log_0828", variables => { answer => $answer }});
if ((lc($answer) eq "y") or (lc($answer) eq "yes"))
{
# Proceed
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0175"});
}
else
{
# Abort
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0022"});
$anvil->nice_exit({exit_code => 0});
}
}
# Record the new config.
$problem = $anvil->Server->update_definition({
debug => 2,
server => $server_uuid,
new_definition_xml => $new_server_definition,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
if ($problem)
{
# Failed!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0471"});
$anvil->Job->update_progress({
progress => 100,
message => "error_0471",
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
else
{
# Done!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "log_0750"});
$anvil->Job->update_progress({
progress => 100,
message => "log_0750",
}) if $anvil->data->{switches}{'job-uuid'};
}
return(0);
}
sub manage_ram
{
my ($anvil) = @_;
my $short_host_name = $anvil->Get->short_host_name;
my $host_uuid = $anvil->Get->host_uuid;
my $server_name = $anvil->data->{switches}{server_name};
my $server_uuid = $anvil->data->{switches}{server_uuid};
my $server_host_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_host_uuid};
my $anvil_uuid = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_anvil_uuid};
my $anvil_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name};
my $server_host_name = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:short_host_name' => $short_host_name,
's2:host_uuid' => $host_uuid,
's3:server_name' => $server_name,
's4:server_uuid' => $server_uuid,
's5:server_host_uuid' => $server_host_uuid,
's6:anvil_uuid' => $anvil_uuid,
's7:anvil_name' => $anvil_name,
}});
my $from_source = get_definition_source($anvil);
my $server_state = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
from_source => $from_source,
server_state => $server_state,
}});
if ($server_state eq "running")
{
$server_host_name = $anvil->Database->get_host_from_uuid({
short => 1,
host_uuid => $server_host_uuid,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_host_name => $server_host_name }});
}
# Get available resources.
$anvil->Get->available_resources({
debug => 2,
anvil_uuid => $anvil_uuid,
});
# The RAM In the database is stored in KiB
my $server_ram_in_use = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_ram_in_use};
my $server_configured_ram = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_configured_ram};
my $server_definition_ram = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{memory};
my $available_ram = $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available};
my $max_ram = $available_ram + $server_configured_ram;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
server_ram_in_use => $server_ram_in_use." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $server_ram_in_use}).")",
server_configured_ram => $server_configured_ram." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $server_configured_ram}).")",
server_definition_ram => $server_definition_ram." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $server_definition_ram}).")",
available_ram => $available_ram." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $available_ram}).")",
max_ram => $max_ram." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $max_ram}).")",
}});
if ($anvil->data->{switches}{ram} eq "#!SET!#")
{
my $variables = {
ram_in_use => $anvil->Convert->bytes_to_human_readable({'bytes' => $server_ram_in_use}),
configured_ram => $anvil->Convert->bytes_to_human_readable({'bytes' => $server_configured_ram}),
max_ram => $anvil->Convert->bytes_to_human_readable({'bytes' => $max_ram}),
available_ram => $anvil->Convert->bytes_to_human_readable({'bytes' => $available_ram}),
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0378", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "message_0378",
variables => $variables,
}) if $anvil->data->{switches}{'job-uuid'};
return(0);
}
# Is the requested RAM valid?
my $requested_ram = $anvil->Convert->human_readable_to_bytes({
debug => 2,
size => $anvil->data->{switches}{ram},
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { requested_ram => $requested_ram }});
if ($requested_ram eq "!!error!!")
{
my $variables = { requested_ram => $anvil->data->{switches}{ram} };
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0473", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "error_0473",
variables => $variables,
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
elsif ($requested_ram > $max_ram)
{
my $variables = {
requested_ram => $anvil->Convert->bytes_to_human_readable({'bytes' => $requested_ram}),
max_ram => $anvil->Convert->bytes_to_human_readable({'bytes' => $max_ram}),
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0474", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "error_0474",
variables => $variables,
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
elsif ($requested_ram < 655360)
{
my $variables = { requested_ram => $anvil->Convert->bytes_to_human_readable({'bytes' => $requested_ram}) };
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0475", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "error_0475",
variables => $variables,
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
# Convert the requested bytes to KiB
my $new_requested_ram = $anvil->Convert->bytes_to_human_readable({
debug => 2,
'bytes' => $requested_ram,
base2 => 1,
unit => "k",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ">>new_requested_ram" => $new_requested_ram }});
$new_requested_ram =~ s/\s.*$//;
$new_requested_ram =~ s/\..*$//;
$new_requested_ram =~ s/,//g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<<new_requested_ram" => $new_requested_ram }});
# Still here? Update the definition!
my $new_server_definition = "";
foreach my $line (split/\n/, $anvil->data->{servers}{server_uuid}{$server_uuid}{server_definition_xml})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
if ($line =~ /<memory unit='(.*?)'>(\d+)<\/memory>/)
{
my $old_unit = $1;
my $old_size = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
old_unit => $old_unit,
old_size => $old_size,
}});
$line =~ s/<memory unit='.*?'>\d+<\/memory>/<memory unit='KiB'>$new_requested_ram<\/memory>/;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
}
if ($line =~ /<currentMemory unit='(.*?)'>(\d+)<\/currentMemory>/)
{
my $old_unit = $1;
my $old_size = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
old_unit => $old_unit,
old_size => $old_size,
}});
$line =~ s/<currentMemory unit='.*?'>\d+<\/currentMemory>/<currentMemory unit='KiB'>$new_requested_ram<\/currentMemory>/;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
}
$new_server_definition .= $line."\n";
}
# Confirm the new definition is valid
my $problem = $anvil->Server->parse_definition({
debug => 2,
host => $short_host_name,
server => $server_name,
source => "test_xml",
definition => $new_server_definition,
});
if ($problem)
{
# The new definition is bad
my $variables = { new_server_definition => $new_server_definition };
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0470", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "error_0470",
variables => $variables,
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
# Did the user confirm?
if ($anvil->data->{switches}{'job-uuid'})
{
# Running as a job, don't prompt
$anvil->Job->update_progress({
progress => 75,
message => "job_0480",
});
}
elsif ($anvil->data->{switches}{confirm})
{
# User confirmed
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0359"});
}
else
{
# Ask the user to confirm.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0379", variables => {
configured_ram => $anvil->Convert->bytes_to_human_readable({'bytes' => $server_configured_ram}),
requested_ram => $anvil->Convert->bytes_to_human_readable({'bytes' => $requested_ram}),
}});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0021"});
my $answer = <STDIN>;
chomp $answer;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "log_0828", variables => { answer => $answer }});
if ((lc($answer) eq "y") or (lc($answer) eq "yes"))
{
# Proceed
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0175"});
}
else
{
# Abort
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0022"});
$anvil->nice_exit({exit_code => 0});
}
}
# Record the new config.
$problem = $anvil->Server->update_definition({
debug => 2,
server => $server_uuid,
new_definition_xml => $new_server_definition,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
if ($problem)
{
# Failed!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0471"});
$anvil->Job->update_progress({
progress => 100,
message => "error_0471",
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
else
{
# Update the server_configured_ram (making sure we've got the current DB data first)
$anvil->Database->get_servers();
$anvil->Database->insert_or_update_servers({
debug => 2,
server_uuid => $server_uuid,
server_name => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_name},
server_anvil_uuid => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_anvil_uuid},
server_user_stop => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_user_stop},
server_start_after_server_uuid => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_after_server_uuid},
server_start_delay => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_start_delay},
server_host_uuid => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_host_uuid},
server_state => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state},
server_live_migration => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_live_migration},
server_pre_migration_file_uuid => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_pre_migration_file_uuid},
server_pre_migration_arguments => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_pre_migration_arguments},
server_post_migration_file_uuid => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_post_migration_file_uuid},
server_post_migration_arguments => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_post_migration_arguments},
server_ram_in_use => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_ram_in_use},
server_configured_ram => $requested_ram,
server_updated_by_user => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_updated_by_user},
server_boot_time => $anvil->data->{servers}{server_uuid}{$server_uuid}{server_boot_time},
});
# Done!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "log_0750"});
$anvil->Job->update_progress({
progress => 100,
message => "log_0750",
}) if $anvil->data->{switches}{'job-uuid'};
}
return(0);
}
sub manage_boot_order
{
my ($anvil) = @_;
@ -166,20 +765,258 @@ sub manage_boot
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_host_name => $server_host_name }});
}
if ($anvil->data->{switches}{boot} eq "#!SET!#")
if ($anvil->data->{switches}{' boot-order' } eq "#!SET!#")
{
print "Boot device order for: [".$server_name."]\n";
# Show the existing boot devices and their boot order
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0372", variables => { server_name => $server_name }});
foreach my $boot_order (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{boot_order}})
{
my $device_target = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{boot_order}{$boot_order}{device_target};
my $device = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{boot_order}{$boot_order}{device_type};
my $path = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{device}{$device}{target}{$device_target}{path};
print " ".$boot_order.") Target: [".$device_target."], Device: [".$device."], Path: [".$path."]\n";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0373", variables => {
boot_order => $boot_order,
device_target => $device_target,
device => $device,
path => $path,
}});
}
print "To change the boot device, use '--boot <target>' or --boot <target1>,<target2>,...\n";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0374"}) ;
return(0);
}
print "Updating boot devices.\n";
else
{
# Updating boot devices.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0375"});
$anvil->Job->update_progress({
progress => 25,
message => "message_0375",
}) if $anvil->data->{switches}{'job-uuid'};
# Parse the user's input.
my $boot_order = $anvil->data->{switches}{'boot-order'};
my $boot_count = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { boot_order => $boot_order }});
foreach my $device_target (split/,/, $boot_order)
{
$boot_count++;
$anvil->data->{new_boot_order}{$device_target}{order} = $boot_count;
$anvil->data->{new_boot_order}{$device_target}{device_type} = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
device_target => $device_target,
boot_count => $boot_count,
"new_boot_order::${device_target}" => $anvil->data->{new_boot_order}{$device_target},
}});
if (not exists $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{device_target}{$device_target}{type})
{
# The device was not found, exit.
my $variables = { device_target => $device_target };
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0469", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "error_0469",
variables => $variables,
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
else
{
my $device = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{device_target}{$device_target}{type};
$anvil->data->{new_boot_order}{$device_target}{device_type} = $device;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"new_boot_order::${device_target}::device_type" => $anvil->data->{new_boot_order}{$device_target}{device_type},
}});
}
}
# Find any unlisted devices and bump up their boot order as needed.
foreach my $boot_order (sort {$a cmp $b} keys %{$anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{boot_order}})
{
my $device_target = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{boot_order}{$boot_order}{device_target};
my $device = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{boot_order}{$boot_order}{device_type};
if (not exists $anvil->data->{new_boot_order}{$device_target})
{
$anvil->data->{new_boot_order}{$device_target}{order} = $boot_order + $boot_count;
$anvil->data->{new_boot_order}{$device_target}{device_type} = $device;
}
}
# Make sortable
foreach my $device_target (sort {$a cmp $b} keys %{$anvil->data->{new_boot_order}})
{
my $boot_order = $anvil->data->{new_boot_order}{$device_target}{order};
my $device = $anvil->data->{new_boot_order}{$device_target}{device_type};
$anvil->data->{new_boot_order}{$device_target}{order} = $boot_order;
$anvil->data->{new_boot_order}{$device_target}{target} = $device_target;
$anvil->data->{new_boot_order}{$device_target}{device} = $device;
$anvil->data->{new_boot_order}{$device_target}{path} = $anvil->data->{server}{$short_host_name}{$server_name}{$from_source}{device}{$device}{target}{$device_target}{path};
$anvil->data->{new_order}{$boot_order}{target} = $device_target;
}
# Show what the new boot order will be
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0376"});
$anvil->data->{'say'}{cdrom} = $anvil->Words->string({key => "type_0001"});
$anvil->data->{'say'}{disk} = $anvil->Words->string({key => "type_0004"});
foreach my $boot_order (sort {$a <=> $b} keys %{$anvil->data->{new_order}})
{
my $device_target = $anvil->data->{new_order}{$boot_order}{target};
my $device = $anvil->data->{new_boot_order}{$device_target}{device};
my $path = $anvil->data->{new_boot_order}{$device_target}{path};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0377", variables => {
boot_order => $boot_order,
path => $path,
device_target => $device_target,
device => $anvil->data->{'say'}{$device},
}});
}
# Tell the job we're about to create the new definition
$anvil->Job->update_progress({
progress => 50,
message => "job_0478",
}) if $anvil->data->{switches}{'job-uuid'};
# Update the definition.
my $in_disk = 0;
my $device_target = "";
my $boot_order_seen = 0;
my $new_server_definition = "";
foreach my $line (split/\n/, $anvil->data->{servers}{server_uuid}{$server_uuid}{server_definition_xml})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
if ($line =~ /<disk /)
{
$in_disk = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_disk => $in_disk }});
}
if ($in_disk)
{
if ($line =~ /<\/disk>/)
{
# If we didn't see the old boot order, or if it was too soon, add the
# boot order now.
if ((not $boot_order_seen) && ($device_target))
{
my $new_boot_order = $anvil->data->{new_boot_order}{$device_target}{order};
$new_server_definition .= " <boot order='".$new_boot_order."'/>\n";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_boot_order => $new_boot_order }});
}
$in_disk = 0;
$boot_order_seen = 0;
$device_target = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
in_disk => $in_disk,
boot_order_seen => $boot_order_seen,
device_target => $device_target,
}});
}
elsif ($line =~ /<target dev='(.*?)'/)
{
$device_target = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { device_target => $device_target }});
}
elsif ($line =~ /boot order='(\d+)'/)
{
# If we have a device_target, update the line. Otherwise, skip it and
# we'll insert it later.
my $old_boot_order = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_boot_order => $old_boot_order }});
if ($device_target)
{
$boot_order_seen = 1;
my $new_boot_order = $anvil->data->{new_boot_order}{$device_target}{order};
$line =~ s/boot order='.*?'/boot order='$new_boot_order'/;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { boot_order_seen => $boot_order_seen }});
}
}
}
$new_server_definition .= $line."\n";
}
my $problem = $anvil->Server->parse_definition({
debug => 2,
host => $short_host_name,
server => $server_name,
source => "test_xml",
definition => $new_server_definition,
});
if ($problem)
{
# The new definition is bad
my $variables = { new_server_definition => $new_server_definition };
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0470", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "error_0470",
variables => $variables,
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
# Did the user confirm?
if ($anvil->data->{switches}{'job-uuid'})
{
# Running as a job, don't prompt
$anvil->Job->update_progress({
progress => 75,
message => "job_0480",
});
}
elsif ($anvil->data->{switches}{confirm})
{
# User confirmed
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0359"});
}
else
{
# Ask the user to confirm.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0021"});
my $answer = <STDIN>;
chomp $answer;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "log_0828", variables => { answer => $answer }});
if ((lc($answer) eq "y") or (lc($answer) eq "yes"))
{
# Proceed
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0175"});
}
else
{
# Abort
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0022"});
$anvil->nice_exit({exit_code => 0});
}
}
# Record the new config.
$problem = $anvil->Server->update_definition({
debug => 2,
server => $server_uuid,
new_definition_xml => $new_server_definition,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
if ($problem)
{
# Failed!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0471"});
$anvil->Job->update_progress({
progress => 100,
message => "error_0471",
}) if $anvil->data->{switches}{'job-uuid'};
$anvil->nice_exit({exit_code => 1});
}
else
{
# Done!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "log_0750"});
$anvil->Job->update_progress({
progress => 100,
message => "log_0750",
}) if $anvil->data->{switches}{'job-uuid'};
}
}
return(0);
}