* Updated System->configure_ipmi() to auto-configure DR hosts once they've been assigned a BCN IP address.

Signed-off-by: digimer <mkelly@alteeve.ca>
main
digimer 2 years ago
parent 567abff9de
commit cf73d8ed36
  1. 6
      Anvil/Tools/ScanCore.pm
  2. 363
      Anvil/Tools/System.pm
  3. 1
      share/words.xml

@ -1459,7 +1459,11 @@ sub post_scan_analysis_dr
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "ScanCore->post_scan_analysis_dr()" }});
# Now that DR hosts are outside of specific Anvil! systems, auto-configuring their IPMI is more
# tricky. If there's no 'host_ipmi' set, and if there is a BCN1 IP, we'll configure using the BCN's
# third octet, plus 1. We'll use the password used for the database password. Later, if the IPMI
# is changed in the DB, we'll reconfigure to match.
$anvil->System->configure_ipmi({debug => $debug, dr => 1});
return(0);
}

@ -1897,6 +1897,10 @@ B<< NOTE >>: The password used to set the IPMI BMC access is included both in th
Parameters;
=head3 dr (Optional, default 0)
This indicates that a DR host is being configured. If used, C<< manifest_uuid >> is ignored.
=head3 manifest_uuid (Optional, default sys::manifest_uuid)
The C<< manifests >> -> C<< manifest_uuid >> used to pull out configuration data. This is required, but in most cases, it can be determined if not passed.
@ -1912,62 +1916,138 @@ sub configure_ipmi
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "System->configure_ipmi()" }});
my $dr = defined $parameter->{dr} ? $parameter->{dr} : "";
my $manifest_uuid = defined $parameter->{manifest_uuid} ? $parameter->{manifest_uuid} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
dr => $dr,
manifest_uuid => $manifest_uuid,
}});
if ((not $manifest_uuid) && (exists $anvil->data->{sys}{manifest_uuid}) && ($anvil->data->{sys}{manifest_uuid}))
{
$manifest_uuid = $anvil->data->{sys}{manifest_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { manifest_uuid => $manifest_uuid }});
}
if (not $manifest_uuid)
{
# Nothing more we can do.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->configure_ipmi()", parameter => "manifest_uuid" }});
return(0);
}
# Is this host in an Anvil!?
$anvil->Database->get_hosts();
$anvil->Database->get_anvils();
my $anvil_uuid = "";
my $host_uuid = $anvil->Get->host_uuid;
if ((exists $anvil->data->{hosts}{host_uuid}{$host_uuid}) && ($anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_uuid}))
{
# We're in an Anvil!
$anvil_uuid = $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { anvil_uuid => $anvil_uuid }});
my $host_uuid = $anvil->Get->host_uuid;
my $ipmi_ip_address = "";
my $ipmi_password = "";
my $password_length = 0;
my $subnet_mask = "";
my $gateway = "";
my $in_network = "";
if ($dr)
{
my $host_ipmi = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_ipmi => $host_ipmi }});
if (not $host_ipmi)
{
# Do initial config.
$anvil->Network->load_ips({
debug => $debug,
host_uuid => $host_uuid,
});
foreach my $interface_name (sort {$a cmp $b} keys %{$anvil->data->{network}{$host_uuid}{interface}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_name => $interface_name }});
next if $interface_name !~ /^bcn1_/;
my $ip_address_address = $anvil->data->{network}{$host_uuid}{interface}{$interface_name}{ip};
my $ip_address_subnet_mask = $anvil->data->{network}{$host_uuid}{interface}{$interface_name}{subnet_mask};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
ip_address_address => $ip_address_address,
ip_address_subnet_mask => $ip_address_subnet_mask,
}});
# We need this to be a /16
if ($ip_address_subnet_mask eq "255.255.0.0")
{
# Get the 3rd octet.
my ($first_octet, $second_octet, $third_octet, $fourth_octet) = ($ip_address_address =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
first_octet => $first_octet,
second_octet => $second_octet,
third_octet => $third_octet,
fourth_octet => $fourth_octet,
}});
$ipmi_ip_address = $first_octet.".".$second_octet.".".($third_octet+1).".".$fourth_octet;
$subnet_mask = $ip_address_subnet_mask;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
ipmi_ip_address => $ipmi_ip_address,
subnet_mask => $subnet_mask,
}});
last;
}
}
# Get the password using the Striker password.
my $db_uuid = $anvil->data->{sys}{database}{read_uuid};
$ipmi_password = $anvil->data->{database}{$db_uuid}{password};
$password_length = length(Encode::encode('UTF-8', $ipmi_password));
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
db_uuid => $db_uuid,
ipmi_password => $anvil->Log->is_secure($ipmi_password),
password_length => $password_length,
}});
if ((not $anvil->Validate->ipv4({debug => $debug, ip => $ipmi_ip_address})) or (not $ipmi_password))
{
# Can't proceed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "warning_0149"});
return(0);
}
}
else
{
# TODO: Check if the local IPMI config matches the value in host_ipmi and, if not,
# reconfigure to match.
return(0);
}
}
else
{
# Not in an Anvil!, return 0.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "err", key => "log_0498"});
return(0);
}
# Look for a match in the anvils table for this host uuid.
my $machine = "";
if ($anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid} eq $host_uuid)
{
$machine = "node1";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { machine => $machine }});
}
elsif ($anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid} eq $host_uuid)
{
$machine = "node2";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { machine => $machine }});
}
# TODO: Make sure this works on DR hosts.
if (not $machine)
{
# Look for a job for 'anvil-join-anvil' for this host. With it, we'll figure out the password
# and which machine we are.
my $query = "
if ((not $manifest_uuid) && (exists $anvil->data->{sys}{manifest_uuid}) && ($anvil->data->{sys}{manifest_uuid}))
{
$manifest_uuid = $anvil->data->{sys}{manifest_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { manifest_uuid => $manifest_uuid }});
}
if (not $manifest_uuid)
{
# Nothing more we can do.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->configure_ipmi()", parameter => "manifest_uuid" }});
return(0);
}
# Is this host in an Anvil!?
my $anvil_uuid = "";
if ((exists $anvil->data->{hosts}{host_uuid}{$host_uuid}) && ($anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_uuid}))
{
# We're in an Anvil!
$anvil_uuid = $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { anvil_uuid => $anvil_uuid }});
}
else
{
# Not in an Anvil!, return 0.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "err", key => "log_0498"});
return(0);
}
# Look for a match in the anvils table for this host uuid.
my $machine = "";
if ($anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid} eq $host_uuid)
{
$machine = "node1";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { machine => $machine }});
}
elsif ($anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid} eq $host_uuid)
{
$machine = "node2";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { machine => $machine }});
}
if (not $machine)
{
# Look for a job for 'anvil-join-anvil' for this host. With it, we'll figure out the password
# and which machine we are.
my $query = "
SELECT
job_uuid,
job_data
@ -1981,56 +2061,109 @@ ORDER BY
modified_date 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,
}});
my $job_uuid = defined $results->[0]->[0] ? $results->[0]->[0] : "";
my $job_data = defined $results->[0]->[1] ? $results->[0]->[1] : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
job_uuid => $job_uuid,
job_data => $anvil->Log->is_secure($job_data),
}});
if (not $job_uuid)
$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,
}});
my $job_uuid = defined $results->[0]->[0] ? $results->[0]->[0] : "";
my $job_data = defined $results->[0]->[1] ? $results->[0]->[1] : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
job_uuid => $job_uuid,
job_data => $anvil->Log->is_secure($job_data),
}});
if (not $job_uuid)
{
# Unable to proceed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "err", key => "log_0501"});
return(0);
}
($machine, $manifest_uuid, $anvil_uuid) = ($job_data =~ /as_machine=(.*?),manifest_uuid=(.*?),anvil_uuid=(.*?)$/);
$machine = "" if not defined $machine;
$manifest_uuid = "" if not defined $manifest_uuid;
$anvil_uuid = "" if not defined $anvil_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
machine => $machine,
manifest_uuid => $manifest_uuid,
anvil_uuid => $anvil_uuid,
}});
}
# Load the manifest.
my $problem = $anvil->Striker->load_manifest({debug => $debug, manifest_uuid => $manifest_uuid});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }});
if ($problem)
{
# Unable to proceed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "err", key => "log_0501"});
# The load_manifest method would log the details.
return(0);
}
($machine, $manifest_uuid, $anvil_uuid) = ($job_data =~ /as_machine=(.*?),manifest_uuid=(.*?),anvil_uuid=(.*?)$/);
$machine = "" if not defined $machine;
$manifest_uuid = "" if not defined $manifest_uuid;
$anvil_uuid = "" if not defined $anvil_uuid;
# Make sure the IPMI IP, subnet mask and password are available.
$ipmi_ip_address = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$machine}{ipmi_ip};
$ipmi_password = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password};
$password_length = length(Encode::encode('UTF-8', $ipmi_password));
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
machine => $machine,
manifest_uuid => $manifest_uuid,
anvil_uuid => $anvil_uuid,
ipmi_ip_address => $ipmi_ip_address,
ipmi_password => $anvil->Log->is_secure($ipmi_password),
password_length => $password_length,
}});
# Find the subnet the IPMI IP is in.
foreach my $network_type ("bcn", "ifn", "sn")
{
my $count = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{$network_type};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
network_type => $network_type,
count => $count,
}});
foreach my $i (1..$count)
{
my $network_name = $network_type.$i;
my $network = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{network};
my $this_subnet_mask = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{subnet};
my $this_gateway = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{gateway};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
network_name => $network_name,
network => $network,
this_subnet_mask => $this_subnet_mask,
this_gateway => $this_gateway,
}});
my $match = $anvil->Network->is_ip_in_network({
network => $network,
subnet_mask => $this_subnet_mask,
ip => $ipmi_ip_address,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { network_name => $match}});
if ($match)
{
$subnet_mask = $this_subnet_mask;
$gateway = $this_gateway;
$in_network = $network_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
subnet_mask => $subnet_mask,
gateway => $gateway,
in_network => $in_network,
}});
last;
}
}
}
# If we didn't find a network, we're done.
if (not $subnet_mask)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "err", key => "log_0502", variables => {
ip_address => $ipmi_ip_address,
manifest_uuid => $manifest_uuid,
}});
return(0);
}
}
# Load the manifest.
my $problem = $anvil->Striker->load_manifest({debug => $debug, manifest_uuid => $manifest_uuid});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }});
if ($problem)
{
# The load_manifest method would log the details.
return(0);
}
# Make sure the IPMI IP, subnet mask and password are available.
my $ipmi_ip_address = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$machine}{ipmi_ip};
my $ipmi_password = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password};
my $password_length = length(Encode::encode('UTF-8', $ipmi_password));
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
ipmi_ip_address => $ipmi_ip_address,
ipmi_password => $anvil->Log->is_secure($ipmi_password),
password_length => $password_length,
}});
# If the password has spaces, some IPMI BMCs won't allow them. If we need to use it, we'll take out
# the spaces and shrink the length.
my $ipmi_no_space_password = "";
@ -2041,61 +2174,7 @@ LIMIT 1
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 1, list => { ipmi_no_space_password => $ipmi_no_space_password }});
}
my $subnet_mask = "";
my $gateway = "";
my $in_network = "";
# Find the subnet the IPMI IP is in.
foreach my $network_type ("bcn", "ifn", "sn")
{
my $count = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{$network_type};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
network_type => $network_type,
count => $count,
}});
foreach my $i (1..$count)
{
my $network_name = $network_type.$i;
my $network = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{network};
my $this_subnet_mask = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{subnet};
my $this_gateway = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{gateway};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
network_name => $network_name,
network => $network,
this_subnet_mask => $this_subnet_mask,
this_gateway => $this_gateway,
}});
my $match = $anvil->Network->is_ip_in_network({
network => $network,
subnet_mask => $this_subnet_mask,
ip => $ipmi_ip_address,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { network_name => $match}});
if ($match)
{
$subnet_mask = $this_subnet_mask;
$gateway = $this_gateway;
$in_network = $network_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
subnet_mask => $subnet_mask,
gateway => $gateway,
in_network => $in_network,
}});
last;
}
}
}
# If we didn't find a network, we're done.
if (not $subnet_mask)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "err", key => "log_0502", variables => {
ip_address => $ipmi_ip_address,
manifest_uuid => $manifest_uuid,
}});
return(0);
}
# Call dmidecode to see if there even is an IPMI BMC on this host.
my $host_ipmi = "";

@ -3582,6 +3582,7 @@ The error was:
</key>
<key name="warning_0147">[ Warning ] - The interface: [#!variable!interface!#] appears to be down (state: [#!variable!state!#]). The system uptime is: [#!variable!uptime!#], so it might be a problem where the interface didn't start on boot as it should have. So we're going to bring the interface up.</key>
<key name="warning_0148">[ Warning ] - The IPMI stonith resource: [#!variable!resource!#] is in the role: [#!variable!role!#] (should be 'Started'). Will check the IPMI config now.</key>
<key name="warning_0149">[ Warning ] - Failed to find a valid IP address or password to be used to setup the DR host's IPMI.</key>
</language>
<!-- 日本語 -->
<language name="jp" long_name="日本語" description="Anvil! language file.">

Loading…
Cancel
Save