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

Anvil tools dev
main
Digimer 3 years ago committed by GitHub
commit f5f55d70b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      Anvil/Tools/ScanCore.pm
  2. 304
      Anvil/Tools/Storage.pm
  3. 121
      scancore-agents/scan-network/scan-network
  4. 3
      share/words.xml
  5. 95
      tools/anvil-manage-server
  6. 33
      tools/anvil-safe-stop
  7. 1
      tools/scancore

@ -2415,7 +2415,7 @@ LIMIT 1;";
$stop_reason = "unknown";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { stop_reason => $stop_reason }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0565", variables => { host_name => $host_name }});
next;
}
if ($stop_reason eq "user")
@ -2424,7 +2424,7 @@ LIMIT 1;";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0566", variables => { host_name => $host_name }});
next;
}
elsif ($stop_reason eq "power")
elsif (($stop_reason eq "power") or ($stop_reason eq "unknown"))
{
# Check now if the power is OK
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0567", variables => { host_name => $host_name }});

@ -24,6 +24,7 @@ my $THIS_FILE = "Storage.pm";
# delete_file
# find
# get_file_stats
# get_size_of_block_device
# get_storage_group_details
# get_storage_group_from_path
# make_directory
@ -1626,6 +1627,305 @@ sub get_file_stats
}
=head2 get_size_of_block_device
This takes a block device path (DRBD or LVM LV path) and tries to find the size of the device as it was recorded in the database. If found, the size in bytes is returned. If there is a problem, C<< !!error!! >> is returned. If the device in not found in the database, an empty string is returned.
B<< Note >>: If there are multiple results, the first found will be returned. If the results span multiple Anvil! systems, this could be a problem. If this is a concern, specifify either the C<< host_uuid >> or C<< anvil_uuid >> parameters.
Parameters;
=head3 anvil_uuid (optional)
In the case of an ambiguous path (a path found on multiple Anvil! systems), this can be set to specify which Anvil! we're searching for.
=head3 host_uuid (optional)
In the case of an ambiguous path (a path found on multiple hosts), this can be set to specify which host we're searching for.
=head3 path (required)
This is the full block device path.
=cut
sub get_size_of_block_device
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Storage->get_size_of_block_device()" }});
my $anvil_uuid = defined $parameter->{anvil_uuid} ? $parameter->{anvil_uuid} : "";
my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : "";
my $path = defined $parameter->{path} ? $parameter->{path} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
anvil_uuid => $anvil_uuid,
host_uuid => $host_uuid,
path => $path,
}});
if (not $path)
{
# No source passed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Storage->get_size_of_block_device()", parameter => "path" }});
return('!!error!!');
}
$anvil->Database->get_anvils({debug => $debug});
my $node1_host_uuid = "";
my $node2_host_uuid = "";
my $dr1_host_uuid = "";
if ($anvil_uuid)
{
$node1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid};
$node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
$dr1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
node1_host_uuid => $node1_host_uuid,
node1_host_uuid => $node2_host_uuid,
dr1_host_uuid => $dr1_host_uuid,
}});
}
# Is this a DRBD path?
if ($path !~ /drbd/)
{
# See if we can find this in LVs
my $query = "
SELECT
scan_lvm_lv_host_uuid,
scan_lvm_lv_size
FROM
scan_lvm_lvs
WHERE
scan_lvm_lv_name != 'DELETED'
AND
scan_lvm_lv_path = ".$anvil->Database->quote($path);
if ($host_uuid)
{
$query .= "
AND
scan_lvm_lv_host_uuid = ".$anvil->Database->quote($host_uuid);
}
elsif ($anvil_uuid)
{
$query .= "
AND
(
scan_lvm_lv_host_uuid = ".$anvil->Database->quote($node1_host_uuid)."
OR
scan_lvm_lv_host_uuid = ".$anvil->Database->quote($node2_host_uuid);
if ($dr1_host_uuid)
{
$query .= "
OR
scan_lvm_lv_host_uuid = ".$anvil->Database->quote($dr1_host_uuid);
}
$query .= "
)";
}
$query .= "
LIMIT 1
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
if (not $count)
{
# Not found
return("");
}
my $scan_lvm_lv_host_uuid = $results->[0]->[0];
my $scan_lvm_lv_size = $results->[0]->[1];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
scan_lvm_lv_host_uuid => $scan_lvm_lv_host_uuid,
scan_lvm_lv_size => $scan_lvm_lv_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_lv_size}).")",
}});
return($scan_lvm_lv_size);
}
else
{
# Looks like it. If the device path is '/dev/drbd/by-res/...' we'll need to pull out the
# resource name (server name) and volume number as the path only actually exists when DRBD is
# up and isn't referenced in the config file.
my $resource = "";
my $volume = "";
$anvil->DRBD->gather_data({debug => $debug});
if ($path =~ /\/dev\/drbd\/by-res\/(.*)\/(\d+)$/)
{
$resource = $1;
$volume = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
resource => $resource,
volume => $volume,
}});
}
elsif ($path =~ /\/dev\/drbd_(.*)_(\d+)$/)
{
$resource = $1;
$volume = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
resource => $resource,
volume => $volume,
}});
}
elsif ($path =~ /\/dev\/drbd(\d+)$/)
{
# This is a direct path to a minor device, we'll need to find it in the config.
my $minor = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { minor => $minor }});
# If we were passed an anvil_uuid but not a host_uuid, don't use this machine's host UUID
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
# These will be set if multiple options are found in the database.
foreach my $this_resource (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_resource => $this_resource }});
foreach my $this_host_name (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$this_resource}{host}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_host_name => $this_host_name }});
foreach my $this_volume (sort {$a cmp $b} keys %{$$anvil->data->{new}{resource}{$this_resource}{host}{$this_host_name}{volume}})
{
my $this_minor = $anvil->data->{new}{resource}{$this_resource}{host}{$this_host_name}{volume}{$this_volume}{device_minor};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
this_volume => $this_volume,
this_minor => $this_minor,
}});
next if $this_minor ne $minor;
my $this_host_uuid = $anvil->Get->host_uuid_from_name({host_name => $this_host_name});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_host_uuid => $this_host_uuid }});
next if not $this_host_uuid;
# Sorry, this is a bit of a mess. Logic is; If we're given a
# host_uuid, and it matches, use it. Otherwise, if an
# anvil_uuid is passed, and either node 1 or 2's UUID, or if
# there is a DR host, if it's host UUID matches, then we can
# use this.
if (
(
($host_uuid) && ($host_uuid eq $this_host_uuid)
)
or
(
($anvil_uuid) &&
(
($this_host_uuid eq $node1_host_uuid) or
($this_host_uuid eq $node2_host_uuid) or
(
($dr1_host_uuid) &&
($this_host_uuid eq $dr1_host_uuid)
)
)
)
)
{
# This is a node in the requested cluster.
$resource = $this_resource;
$volume = $this_volume;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
resource => $resource,
volume => $volume,
}});
last;
if (not $host_uuid)
{
$host_uuid = $this_host_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
}
}
}
}
}
}
if (not $resource)
{
# Not found.
return("");
}
# The DRBD query is sorted by size because 'Secondary' resources can't have their size read
# and get set to '0'.
my $query = "
SELECT
a.scan_drbd_resource_host_uuid,
b.scan_drbd_volume_size
FROM
scan_drbd_resources a,
scan_drbd_volumes b
WHERE
a.scan_drbd_resource_uuid = b.scan_drbd_volume_scan_drbd_resource_uuid
AND
a.scan_drbd_resource_xml != 'DELETED'
AND
a.scan_drbd_resource_name = ".$anvil->Database->quote($resource)."
AND
b.scan_drbd_volume_number = ".$anvil->Database->quote($volume);
if ($host_uuid)
{
$query .= "
AND
a.scan_drbd_resource_host_uuid = ".$anvil->Database->quote($host_uuid);
}
elsif ($anvil_uuid)
{
$query .= "
AND
(
a.scan_drbd_resource_host_uuid = ".$anvil->Database->quote($node1_host_uuid)."
OR
a.scan_drbd_resource_host_uuid = ".$anvil->Database->quote($node2_host_uuid);
if ($dr1_host_uuid)
{
$query .= "
OR
a.scan_drbd_resource_host_uuid = ".$anvil->Database->quote($dr1_host_uuid);
}
$query .= "
)";
}
$query .= "
ORDER BY
scan_drbd_volume_size DESC
LIMIT 1;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
if (not $count)
{
# Not found
return("");
}
my $scan_drbd_resource_host_uuid = $results->[0]->[0];
my $scan_drbd_volume_size = $results->[0]->[1];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
scan_drbd_resource_host_uuid => $scan_drbd_resource_host_uuid,
scan_drbd_volume_size => $scan_drbd_volume_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_drbd_volume_size}).")",
}});
return($scan_drbd_volume_size);
}
return("");
}
=head2 get_storage_group_details
This takes a C<< storage_group_uuid >> and loads information about members into the following hash;
@ -1825,10 +2125,6 @@ sub get_storage_group_from_path
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { minor => $minor }});
$anvil->Database->get_anvils({debug => $debug});
my $local_host_uuid = $anvil->Get->host_uuid({debug => $debug});
my $local_anvil_uuid = $anvil->Cluster->get_anvil_uuid({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { local_anvil_uuid => $local_anvil_uuid }});
my $node1_host_uuid = "";
my $node2_host_uuid = "";
my $dr1_host_uuid = "";

@ -628,6 +628,10 @@ sub read_last_scan
{
my ($anvil) = @_;
### NOTE: There is a bug somewhere where interfaces are periodically being added twice per host. This
### checks for / cleans those up. Remove this when the core issue is resolved.
clear_duplicate_nics($anvil);
# Read in the old bridge data.
load_bridge_data($anvil);
load_bond_data($anvil);
@ -637,6 +641,123 @@ sub read_last_scan
return(0);
}
# There is a bug somewhere where interfaces are periodically being added twice per host. This checks
# for / cleans those up. Remove this when the core issue is resolved.
sub clear_duplicate_nics
{
my ($anvil) = @_;
my $query = "
SELECT
network_interface_uuid,
network_interface_name,
network_interface_mac_address,
network_interface_operational
FROM
network_interfaces
WHERE
network_interface_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)."
ORDER BY
network_interface_name ASC;";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $network_interface_uuid = $row->[0];
my $network_interface_name = $row->[1];
my $network_interface_mac_address = $row->[2];
my $network_interface_operational = $row->[3];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
network_interface_uuid => $network_interface_uuid,
network_interface_name => $network_interface_name,
network_interface_mac_address => $network_interface_mac_address,
network_interface_operational => $network_interface_operational,
}});
if (not exists $anvil->data->{duplicate_nics}{seen}{$network_interface_name})
{
$anvil->data->{duplicate_nics}{seen}{$network_interface_name} = [];
}
push @{$anvil->data->{duplicate_nics}{seen}{$network_interface_name}}, $network_interface_uuid;
$anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_name} = $network_interface_name;
$anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address} = $network_interface_mac_address;
$anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational} = $network_interface_operational;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"duplicate_nics::network_interface_uuid::${network_interface_uuid}::network_interface_name" => $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_name},
"duplicate_nics::network_interface_uuid::${network_interface_uuid}::network_interface_mac_address" => $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address},
"duplicate_nics::network_interface_uuid::${network_interface_uuid}::network_interface_operational" => $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational},
}});
}
foreach my $network_interface_name (sort {$a cmp $b} keys %{$anvil->data->{duplicate_nics}{seen}})
{
my $count = @{$anvil->data->{duplicate_nics}{seen}{$network_interface_name}};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:network_interface_name' => $network_interface_name,
's2:count' => $count,
}});
if ($count > 1)
{
# Duplicate! Is one of them marked as DELETED?
foreach my $network_interface_uuid (@{$anvil->data->{duplicate_nics}{seen}{$network_interface_name}})
{
# Is this one deleted?
my $network_interface_mac_address = $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address};
my $network_interface_operational = $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
network_interface_uuid => $network_interface_uuid,
network_interface_mac_address => $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address},
network_interface_operational => $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational},
}});
if ($network_interface_operational eq "DELETED")
{
# Take this one out.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0647", variables => {
name => $network_interface_name,
uuid => $network_interface_uuid,
}});
my $query = "DELETE FROM network_interfaces WHERE network_interface_uuid = ".$anvil->Database->quote($network_interface_uuid).";";
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
$count--;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
}
last if $count == 1;
}
# If count is still > 1, we need to arbitrarily delete an interface.
if ($count > 1)
{
foreach my $network_interface_uuid (@{$anvil->data->{duplicate_nics}{seen}{$network_interface_name}})
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0647", variables => {
name => $network_interface_name,
uuid => $network_interface_uuid,
}});
my $query = "DELETE FROM network_interfaces WHERE network_interface_uuid = ".$anvil->Database->quote($network_interface_uuid).";";
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
$count--;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
}
last if $count == 1;
}
}
}
delete $anvil->data->{duplicate_nics};
return(0);
}
sub load_ip_address_data
{
my ($anvil) = @_;

@ -1786,7 +1786,7 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="log_0562">The host: [#!variable!host_name!#] is up, no need to check if it needs booting.</key>
<key name="log_0563">The host: [#!variable!host_name!#] couldn't be reached directly, but IPMI reports that it is up. Could the IPMI BMC be hung or unplugged?</key>
<key name="log_0564">The host: [#!variable!host_name!#] is off. Will check now if it should be booted.</key>
<key name="log_0565">The host: [#!variable!host_name!#] has no stop reason, so we'll leave it off.</key>
<key name="log_0565">The host: [#!variable!host_name!#] has no stop reason, so we'll boot it up in case it lost power without warning.</key>
<key name="log_0566">The host: [#!variable!host_name!#] was stopped by the user, so we'll leave it off.</key>
<key name="log_0567">The host: [#!variable!host_name!#] was powered off because of power loss. Checking to see if it is now safe to restart it.</key>
<key name="log_0568">The host: [#!variable!host_name!#] was powered off because of thermal issues. Checking to see if it is now safe to restart it.</key>
@ -1876,6 +1876,7 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="log_0644">Synchronizing corosync config.</key>
<key name="log_0645">Reloading corosync config.</key>
<key name="log_0646">#!variable!program!# is disabled in anvil.conf. and '--force' was not used. Exiting.</key>
<key name="log_0647">[ Note ] - The network interface: [#!variable!name!#] with 'network_interface_uuid': [#!variable!uuid!#] is a duplicate, removing it from the database(s).</key>
<!-- Messages for users (less technical than log entries), though sometimes used for logs, too. -->
<key name="message_0001">The host name: [#!variable!target!#] does not resolve to an IP address.</key>

@ -768,12 +768,24 @@ sub interactive_configure_storage
while(1)
{
# Here, we'll list each storage pool and for each indicate if it's used and, if so
my $index = 1;
my $lines = 2;
my $changes = 0;
my $storage_group_selection = [];
push @{$storage_group_selection}, "NULL";
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 $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 => {
@ -785,20 +797,95 @@ sub interactive_configure_storage
's6:available_on_dr' => $free_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $available_on_dr}).")",
}});
my $paths = {};
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 $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 $path = $anvil->data->{target_server}{disk}{$target}{path};
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,
path => $path,
this_path => $this_path,
boot_order => $boot_order,
}});
my $this_storage_group_uuid = $anvil->Storage->get_storage_group_from_path({
debug => 3,
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))
{
$paths->{$target}{path} = $this_path;
$paths->{$target}{boot_order} = $boot_order;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"s1:paths->{".$target."}{path}" => $paths->{$target}{path},
"s2:paths->{".$target."}{boot_order}" => $paths->{$target}{boot_order},
}});
}
}
$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})."]\n";
my $path_count = keys %{$paths};
$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 %{$paths})
{
my $path = $paths->{$target}{path};
my $boot_order = $paths->{$target}{boot_order};
my $size = $anvil->Storage->get_size_of_block_device({
debug => 2,
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 }});
}
}
else
{
print " - <Storage group not used by this server>\n";
}
$index++;
}
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 }});
}
return(0);

@ -27,17 +27,28 @@ $| = 1;
my $anvil = Anvil::Tools->new();
$anvil->data->{switches}{'job-uuid'} = "";
$anvil->data->{switches}{'poweroff'} = "";
$anvil->data->{switches}{'power-off'} = ""; # By default, the node is withdrawn. With this switch, the node will power off as well.
$anvil->data->{switches}{'stop-reason'} = ""; # Optionally used to set 'system::stop_reason' reason for this host. Valid values are 'user', 'power' and 'thermal'.
$anvil->data->{switches}{'stop-servers'} = ""; # Default behaviour is to migrate servers to the peer, if the peer is up. This overrides that and forces hosted servers to shut down.
$anvil->Get->switches;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'switches::job-uuid' => $anvil->data->{switches}{'job-uuid'},
'switches::poweroff' => $anvil->data->{switches}{'poweroff'},
'switches::power-off' => $anvil->data->{switches}{'power-off'},
'switches::stop-reason' => $anvil->data->{switches}{'stop-reason'},
'switches::stop-servers' => $anvil->data->{switches}{'stop-servers'},
}});
# Let 'poweroff' work as a mis-spell of 'power-off'
if (($anvil->data->{switches}{'poweroff'}) && (not $anvil->data->{switches}{'power-off'}))
{
$anvil->data->{switches}{'power-off'} = $anvil->data->{switches}{'poweroff'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'switches::power-off' => $anvil->data->{switches}{'power-off'},
}});
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0115", variables => { program => $THIS_FILE }});
# Make sure we're running as 'root'
@ -121,6 +132,9 @@ if (not $anvil->data->{sys}{anvil_uuid})
if (not $anvil->data->{switches}{'stop-reason'})
{
$anvil->data->{switches}{'stop-reason'} = "user";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'switches::stop-reason' => $anvil->data->{switches}{'stop-reason'},
}});
}
# Migrate or stop the servers, if any servers are running here.
@ -145,6 +159,25 @@ if ($anvil->data->{switches}{'power-off'})
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0325"});
$anvil->Job->update_progress({progress => 100, message => "job_0325"});
# Set the stop reason.
if ($anvil->data->{switches}{'stop-reason'})
{
if ($anvil->data->{switches}{'stop-reason'} eq "none")
{
$anvil->data->{switches}{'stop-reason'} = "";
}
my $variable_uuid = $anvil->Database->insert_or_update_variables({
variable_name => 'system::stop_reason',
variable_value => $anvil->data->{switches}{'stop-reason'},
variable_default => '',
variable_description => 'striker_0279',
variable_section => 'system',
variable_source_uuid => $anvil->Get->host_uuid(),
variable_source_table => 'hosts',
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { variable_uuid => $variable_uuid }});
}
my $shell_call = $anvil->data->{path}{exe}{systemctl}." poweroff";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});

@ -115,6 +115,7 @@ while(1)
# If we're in maintenance mode, do nothing.
my $maintenance_mode = $anvil->System->maintenance_mode();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { maintenance_mode => $maintenance_mode }});
if ($maintenance_mode)
{
# Sleep and skip.

Loading…
Cancel
Save