Merge pull request #536 from ClusterLabs/anvil-tools-dev

Anvil tools dev
main
digimer-bot 1 year ago committed by GitHub
commit 5a1ad20d7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      Anvil/Tools/Database.pm
  2. 28
      Anvil/Tools/Get.pm
  3. 7
      Anvil/Tools/Remote.pm
  4. 4
      Anvil/Tools/Server.pm
  5. 12
      man/anvil-manage-dr.8
  6. 20
      man/anvil-manage-server-system.8
  7. 36
      share/words.xml
  8. 37
      tools/anvil-manage-dr
  9. 857
      tools/anvil-manage-server-system
  10. 12
      tools/anvil-manage-storage-groups

@ -12907,7 +12907,17 @@ WHERE
return($server_uuid);
}
### TODO: Left off here.
### TODO: Remove this eventually. There is a bug somewhere that is storing RAM in KiB, not Bytes.
if (($server_configured_ram < 655360) or ($server_ram_in_use < 655360))
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0472", variables => {
server_name => $server_name,
configured_ram => $server_configured_ram,
ram_in_use => $server_ram_in_use,
}});
return("!!error!!");
}
# Are we updating or inserting?
if (not $exists)
{

@ -464,6 +464,7 @@ Data is store in the following hashes;
anvil_resources::<anvil_uuid>::cpu::cores
anvil_resources::<anvil_uuid>::cpu::threads
anvil_resources::<anvil_uuid>::cpu::available
anvil_resources::<anvil_uuid>::ram::available
anvil_resources::<anvil_uuid>::ram::allocated
anvil_resources::<anvil_uuid>::ram::hardware
@ -527,9 +528,10 @@ sub available_resources
}});
# This will store the available resources based on the least of the nodes.
$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores} = 0;
$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads} = 0;
$anvil->data->{anvil_resources}{$anvil_uuid}{ram}{hardware} = 0;
$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{cores} = 0;
$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads} = 0;
$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{available} = 0;
$anvil->data->{anvil_resources}{$anvil_uuid}{ram}{hardware} = 0;
foreach my $host_uuid ($node1_host_uuid, $node2_host_uuid)
{
my $this_is = "node1";
@ -637,6 +639,26 @@ WHERE
}});
}
# How many can be allocated to a single VM?
$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{available} = $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{threads};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"anvil_resources::${anvil_uuid}::cpu::available" => $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{available},
}});
if ($anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{available} <= 4)
{
$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{available} -= 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"anvil_resources::${anvil_uuid}::cpu::available" => $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{available},
}});
}
else
{
$anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{available} -= 2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"anvil_resources::${anvil_uuid}::cpu::available" => $anvil->data->{anvil_resources}{$anvil_uuid}{cpu}{available},
}});
}
if ((not $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{available}) or
($scan_hardware_ram_total < $anvil->data->{anvil_resources}{$anvil_uuid}{ram}{hardware}))
{

@ -1007,6 +1007,13 @@ sub test_access
user => $user,
}});
# Make sure we've got the target in our known_hosts file.
$anvil->Remote->add_target_to_known_hosts({
debug => $debug,
target => $target,
user => getpwuid($<),
});
# Call the target
my ($output, $error, $return_code) = $anvil->Remote->call({
debug => $debug,

@ -2461,6 +2461,7 @@ sub parse_definition
$anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{path} = $device_path;
$anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{driver}{io} = $driver_io;
$anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{driver}{cache} = $driver_cache;
$anvil->data->{server}{$target}{$server}{$source}{device_target}{$device_target}{type} = $device;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"server::${target}::${server}::${source}::device::${device}::target::${device_target}::address::domain" => $anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{address}{domain},
"server::${target}::${server}::${source}::device::${device}::target::${device_target}::address::slot" => $anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{address}{slot},
@ -2468,6 +2469,7 @@ sub parse_definition
"server::${target}::${server}::${source}::device::${device}::target::${device_target}::path" => $anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{path},
"server::${target}::${server}::${source}::device::${device}::target::${device_target}::driver::io" => $anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{driver}{io},
"server::${target}::${server}::${source}::device::${device}::target::${device_target}::driver::cache" => $anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{driver}{cache},
"server::${target}::${server}::${source}::device_target::${device_target}::type" => $anvil->data->{server}{$target}{$server}{$source}{device_target}{$device_target}{type},
}});
my $on_lv = defined $anvil->data->{drbd}{config}{$host}{drbd_path}{$device_path}{on} ? $anvil->data->{drbd}{config}{$host}{drbd_path}{$device_path}{on} : "";
@ -2524,11 +2526,13 @@ sub parse_definition
$anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{address}{unit} = $address_unit;
$anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{address}{target} = $address_target;
$anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{path} = $device_path;
$anvil->data->{server}{$target}{$server}{$source}{device_target}{$device_target}{type} = $device;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"server::${target}::${server}::${source}::device::${device}::target::${device_target}::address::controller" => $anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{address}{controller},
"server::${target}::${server}::${source}::device::${device}::target::${device_target}::address::unit" => $anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{address}{unit},
"server::${target}::${server}::${source}::device::${device}::target::${device_target}::address::target" => $anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{address}{target},
"server::${target}::${server}::${source}::device::${device}::target::${device_target}::path" => $anvil->data->{server}{$target}{$server}{$source}{device}{$device}{target}{$device_target}{path},
"server::${target}::${server}::${source}::device_target::${device_target}::type" => $anvil->data->{server}{$target}{$server}{$source}{device_target}{$device_target}{type},
}});
}

@ -39,20 +39,17 @@ This is the path to the license file, needed when setting up "long-throw" DR for
\fB\-\-link\fR
This takes an --anvil and a --dr-host to enable using the DR host as a target for the Anvil! node.
.TP
\fB\-\-list\fR
This will show the list of available Anvil! nodes, DR hosts and servers.
.TP
\fB\-\-protect\fR
The sets up the server to be imaged on DR, if it isn't already protected.
.TP
Notes: If the server is not running, the DRBD resource volume(s) will be brought up. Both nodes need to be online and in the cluster.
.TP
\fB\-\-protocol\fR <sync,async,long-throw>, default 'async'
This allows the protocol used to replicate data to the DR host to be configured. By default, 'async' is used.
\fB\-\-protocol\fR <sync,short-throw,long-throw>, default 'short-throw'
This allows the protocol used to replicate data to the DR host to be configured. By default, 'short-throw' is used.
.br
Modes:
.br
async (default)
short-throw (default)
This tells the storage layer to consider the write to be completed once the data is on the active node's network transmit buffer. In this way, the DR host is allowed to fall behind a small amount, but the active nodes will not slow down because of higher network transit times to the DR location.
.br
@ -85,6 +82,9 @@ long-throw
\fB\-\-remove\fB
This removes the DR image from the DR host for the server, freeing up space on DR but removing the protection afforded by DR.
.TP
\fB\-\-show\fR
This will show the list of available Anvil! nodes, DR hosts and servers.
.TP
\fB\-\-server\fB <server name or uuid> (required)
This is the name or UUID of the server being worked on.
.TP

@ -24,14 +24,28 @@ Set the log level to 1, 2 or 3 respectively. Be aware that level 3 generates a s
.SS "Commands:"
.TP
\fB\-\-boot\-menu\fR <yes,no>
.TP
When called without a value, it shows if the boot menu is enabled or not. If called with 'yes', it enables the boot menu. If called with 'no', the boot meny is disabled.
.TP
\fB\-\-boot\-order\fR <dev1,dev2,...,devN>
When called without a value, it shows if the current order of boot devices. To set a new boot device order, use a comma-separated list of boot devices. Note that any boot devices that are not specified will be moved in their original order to boot after the specified devices are moved up. For this reason, you can just specify the device you want to boot, and it will be moved to the front of the list.
.TP
\fB\-\-cpu\fR <cores or sockets,cores or sockets,cores,threads>
If called without a value, the current CPU core allocation is shown. To change it, you can specify simply a core count, which will appear as a single socket CPU with the specified number of cores. The maximum total number of cores is two-less than the total cores on the host Anvil! node.
.TP
.BR
Alternatively, you can specify '--cput x,y', where 'x' will be the number of sockets to emulate, and 'y' will be the number of cores per socket. Example; '--cpu 2,4' would give 8 total cores, emulates as 2 sockets, each with a 4-core CPU.
.TP
.BR
Lastly, you can specify '--cput x,y,z', where the 'z' adds how many threads to use. Example; '--cpu 1,2,2' would give 8 total cores, emulates as 1 socket, each with a 2-core CPU, and each core being 2 threads.
.TP
\fB\-\-job\-uuid\fR
This is the jobs -> job_uuid to execute. Generally this is only used by other programs.
.TP
\fB\-\-\fR
\fB\-\-ram\fR <size>
If this is called without a value, the current RAM allocated to the server is displayed. If it is passed with a size, and if that size is available, the amount of RAM allocated to the server will be updated.
.TP
.BR
The size can be in bytes, or a human-readible size, using base-2 notation. Ie: '8GiB' (no space) and '8589934592' are the same.
.IP
.SH AUTHOR
Written by Madison Kelly, Alteeve staff and the Anvil! project contributors.

@ -736,6 +736,20 @@ The XML that failed sanity check was:
<key name="error_0465"><![CDATA[The file: [#!variable!file!#] doesn't exist on the target: [#!variable!target!#].]]></key>
<key name="error_0466"><![CDATA[The Anvil! string (name or UUID): [#!variable!string!#] didn't match any known Anvil! in the database.]]></key>
<key name="error_0467"><![CDATA[[ Error ] - The repartition attemp failed! Reloading the partition table now!]]]></key>
<key name="error_0468">We need: [#!variable!space_needed!# (#!variable!space_needed_bytes!# Bytes)] from the storage group: [#!variable!storage_group!#], but the requested DR host does not appear to have a volume group in this storage group. Hint, please use 'anvil-manage-storage-groups' to resolve. Unable to proceed.</key>
<key name="error_0469">[ Error ] - The device: [#!variable!device_target!#] was not found, exiting.</key>
<key name="error_0470">[ Error ] - The new definition is bad:
========
#!variable!new_server_definition!#
========
[ Error ] - The new definition, shown above failed its test parsing, aborting.</key>
<key name="error_0471">[ Error ] - There was a problem trying to save the new definition. Details should be in the logs. It's possible the update partially applied.</key>
<key name="error_0472">[ Error ] - The RAM being recorded for the server: [#!variable!server_name!#] is too low, and likely a program error. The minimum RAM that can be allocated to a server is 640 KiB (655,360 bytes), but this server tried to record allocated: [#!variable!allocated_ram!#] and in-use: [#!variable!ram_in_use!#] RAM.</key>
<key name="error_0473">[ Error ] - The requested size: [#!variable!requested_ram!#] is not a valid size. Please specify the size in bytes, or specify the size with a base-2 suffix, like '8GiB'.</key>
<key name="error_0474">[ Error ] - The requested size: [#!variable!requested_ram!#] is greater than the maximum RAM: [#!variable!max_ram!#].</key>
<key name="error_0475">[ Error ] - The requested size: [#!variable!requested_ram!#] is less than 640 KiB, this must be a mistake.</key>
<key name="error_0476">[ Error ] - The requested CPU: [#!variable!requested_cpu!#] is not valid. Valid options are '--cpu X', '--cpu Y,X' or '--cpu 'Y,X,Z' where 'X' is the number of cores per socket, 'Y' is the number of sockets and 'Z' is the number of threads per core.</key>
<key name="error_0477">[ Error ] - The requested number of cores: [#!variable!requested_cores!#] (sockets: [#!variable!new_sockets!], cores per socket: [#!variable!new_cores!#], threads per core: [#!variable!new_threads!#]).</key>
<!-- Files templates -->
<!-- NOTE: Translating these files requires an understanding of which lines are translatable -->
@ -1705,6 +1719,9 @@ Note: This is a permanent action! If you protect this server again later, a full
<key name="job_0475">The subnode: [#!variable!subnode!#] is not ready. Configured: [#!variable!configured!#], maintenance mode: [#!variable!maintenance_mode!#], job_running: [#!variable!job_running!#].</key>
<key name="job_0476">Waiting for a bit, then will check again.</key>
<key name="job_0477">Waiting for both subnodes to be configured and out of maintenance mode.</key>
<key name="job_0478">Preparing the new definition file</key>
<key name="job_0479">The new definition is ready, saving it.</key>
<key name="job_0480">Running as a job, not prompting the user to confirm.</key>
<!-- Log entries -->
<key name="log_0001">Starting: [#!variable!program!#].</key>
@ -3236,6 +3253,24 @@ proceeding.
<key name="message_0369">- No DR hosts exist yet</key>
<key name="message_0370">- Server name: [#!variable!server_name!#] on Anvil! Node: [#!variable!anvil_name!#]</key>
<key name="message_0371">- No servers yet installed</key>
<key name="message_0372">Boot device order for: [#!variable!server_name!#]</key>
<key name="message_0373"> #!variable!boot_order!#) Target: [#!variable!device_target!#], Device: [#!variable!device!#], Path: [#!variable!path!#]</key>
<key name="message_0374"><![CDATA[To change the boot device, use '--boot-order <target>' or --boot-order <target1>,<target2>,...]]></key>
<key name="message_0375">Updating boot devices.</key>
<key name="message_0376">- New boot order will be:</key>
<key name="message_0377"> - #!variable!boot_order!#: Path: [#!variable!path!#], Device: [#!variable!device_target!#] (#!variable!device!#)</key>
<key name="message_0378">- RAM in use, [#!variable!ram_in_use!#], configured: [#!variable!configured_ram!#], maximum: [#!variable!max_ram!#]
- RAM Available: [#!variable!available_ram!#]</key>
<key name="message_0379">Update the system RAM from: [#!variable!configured_ram!#] to: [#!variable!requested_ram!#]?</key>
<key name="message_0380">- The CPU core count is: [#!variable!total_cores!#] specified as;
- Sockets: [#!variable!sockets!#], Cores per socket: [#!variable!cores!#], Threads per code: [#!variable!threads!#]
- The Anvil! node has: [#!variable!host_cores!#] cores and: [#!variable!host_threads!#] threads.
- The maximum that can be allocated is: [#!variable!max_cores!#], with the recommended max cores being: [#!variable!recommended_max!#].</key>
<key name="message_0381"><![CDATA[- Changing the CPU allocation;
- Sockets: ........ [#!variable!old_sockets!#] -> [#!variable!new_sockets!#]
- Cores per Socket: [#!variable!old_cores!#] -> [#!variable!new_cores!#]
- Threads per Core: [#!variable!old_threads!#] -> [#!variable!new_threads!#]
- Total Cores: .... [#!variable!old_total_cores!#] -> [#!variable!new_total_cores!#]]]></key>
<!-- Translate names (protocols, etc) -->
<key name="name_0001">Normal Password</key> <!-- none in mail-server -->
@ -3688,6 +3723,7 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="type_0001">ISO (optical disc)</key>
<key name="type_0002">Script (program)</key>
<key name="type_0003">Other file type</key>
<key name="type_0004">Disk (virtual drive)</key>
<!-- These are units, words and so on used when displaying information. -->
<key name="unit_0001">Yes</key>

@ -42,11 +42,11 @@ $anvil->Get->switches({list => [
"job-uuid",
"license-file",
"link",
"list",
"protect",
"protocol",
"remove",
"server",
"show",
"unlink",
"update",
"Yes"], man => $THIS_FILE});
@ -2485,20 +2485,15 @@ sub process_protect
# Is there enough space on DR?
my $space_on_dr = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$dr_host_uuid}{vg_free};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
space_on_dr => $anvil->Convert->add_commas({number => $space_on_dr})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $space_on_dr}).")",
space_needed => $anvil->Convert->add_commas({number => $space_needed})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $space_needed}).")",
}});
if ($space_needed > $space_on_dr)
if ((not defined $space_on_dr) or ($space_on_dr !~ /^\d+$/))
{
# The DR host doesn't have a VG in the SG.
my $variables = {
space_needed => $anvil->Convert->bytes_to_human_readable({'bytes' => $space_needed}),
space_needed_bytes => $anvil->Convert->add_commas({number => $space_needed}),
storage_group => $storage_group_name,
space_on_dr => $anvil->Convert->bytes_to_human_readable({'bytes' => $space_on_dr}),
space_on_dr_bytes => $anvil->Convert->add_commas({number => $space_on_dr}),
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "error_0344", variables => $variables});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "error_0468", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "error_0344",
@ -2506,6 +2501,30 @@ sub process_protect
});
$problem = 1;
}
else
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
space_on_dr => $anvil->Convert->add_commas({number => $space_on_dr})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $space_on_dr}).")",
space_needed => $anvil->Convert->add_commas({number => $space_needed})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $space_needed}).")",
}});
if ($space_needed > $space_on_dr)
{
my $variables = {
space_needed => $anvil->Convert->bytes_to_human_readable({'bytes' => $space_needed}),
space_needed_bytes => $anvil->Convert->add_commas({number => $space_needed}),
storage_group => $storage_group_name,
space_on_dr => $anvil->Convert->bytes_to_human_readable({'bytes' => $space_on_dr}),
space_on_dr_bytes => $anvil->Convert->add_commas({number => $space_on_dr}),
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "error_0344", variables => $variables});
$anvil->Job->update_progress({
progress => 100,
message => "error_0344",
variables => $variables
});
$problem = 1;
}
}
}
if ($problem)
{

@ -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,7 @@ $anvil->nice_exit({exit_code => 0});
# Functions #
#############################################################################################################
sub manage_boot
sub manage_cpu
{
my ($anvil) = @_;
@ -142,6 +145,8 @@ sub manage_boot
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,
@ -149,6 +154,8 @@ sub manage_boot
'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);
@ -166,20 +173,850 @@ 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!#")
# 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'})
{
print "Boot device order for: [".$server_name."]\n";
# 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) = @_;
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 $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,
}});
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 }});
}
if ($anvil->data->{switches}{'boot-order'} eq "#!SET!#")
{
# 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);
}

@ -376,6 +376,7 @@ sub manage_group_member
storage_group_member_note => "user-created",
});
print "Added the volume group: [".$lvm_vg_name."] on the host: [".$short_host_name."] to the storage group: [".$storage_group_name."]. The new member UUID is: [".$storage_group_member_uuid."].\n";
$anvil->nice_exit({exit_code => 0});
}
else
{
@ -404,6 +405,7 @@ sub manage_group_member
storage_group_member_note => "DELETED",
});
print "Added the volume group: [".$lvm_vg_name."] on the host: [".$short_host_name."] has been removed from storage group: [".$storage_group_name."].\n";
$anvil->nice_exit({exit_code => 0});
}
return(0);
@ -427,11 +429,11 @@ sub show_data
next;
}
print "Anvil: [".$anvil_name."] - ".$anvil_description."\n";
print "Anvil Node: [".$anvil_name."] - ".$anvil_description."\n";
foreach my $node_host_uuid ($anvil_node1_host_uuid, $anvil_node2_host_uuid)
{
my $node_host_name = $anvil->data->{hosts}{host_uuid}{$node_host_uuid}{short_host_name};
print "- Node: [".$node_host_name."] volume groups;\n";
print "- Subnode: [".$node_host_name."] volume groups;\n";
foreach my $scan_lvm_vg_name (sort {$a cmp $b} keys %{$anvil->data->{vgs}{host_uuid}{$node_host_uuid}{scan_lvm_vg_name}})
{
my $scan_lvm_vg_internal_uuid = $anvil->data->{vgs}{host_uuid}{$node_host_uuid}{scan_lvm_vg_name}{$scan_lvm_vg_name}{scan_lvm_vg_internal_uuid};
@ -439,7 +441,7 @@ sub show_data
my $scan_lvm_vg_free = $anvil->data->{vgs}{host_uuid}{$node_host_uuid}{scan_lvm_vg_internal_uuid}{$scan_lvm_vg_internal_uuid}{scan_lvm_vg_free};
my $say_size_hr = $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_size});
my $say_free_hr = $anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_free});
print " ^- [".$scan_lvm_vg_name."], size: [".$say_size_hr."], free: [".$say_free_hr."], internal UUID: [".$scan_lvm_vg_internal_uuid."]\n";
print " - [".$scan_lvm_vg_name."], size: [".$say_size_hr."], free: [".$say_free_hr."], internal UUID: [".$scan_lvm_vg_internal_uuid."]\n";
}
}
foreach my $storage_group_name (sort {$a cmp $b} keys %{$anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_name}})
@ -452,7 +454,7 @@ sub show_data
my $storage_group_member_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$member_host_uuid}{storage_group_member_uuid};
my $vg_internal_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$member_host_uuid}{vg_internal_uuid};
my $vg_name = $anvil->data->{vgs}{host_uuid}{$member_host_uuid}{scan_lvm_vg_internal_uuid}{$vg_internal_uuid}{scan_lvm_vg_name};
print " ^- [".$member_short_host_name."]:[".$vg_name."]\n";
print " - [".$member_short_host_name."]:[".$vg_name."]\n";
}
}
@ -482,7 +484,7 @@ sub show_data
my $vg_free = $anvil->data->{vgs}{host_uuid}{$host_uuid}{scan_lvm_vg_internal_uuid}{$vg_internal_uuid}{scan_lvm_vg_free};
my $say_size_hr = $anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size});
my $say_free_hr = $anvil->Convert->bytes_to_human_readable({'bytes' => $vg_free});
print " ^- [".$vg_name."], size: [".$say_size_hr."], free: [".$say_free_hr."], internal UUID: [".$vg_internal_uuid."]\n";
print " - [".$vg_name."], size: [".$say_size_hr."], free: [".$say_free_hr."], internal UUID: [".$vg_internal_uuid."]\n";
}
}
print "\n";

Loading…
Cancel
Save