fcbace6713
* Fixed a minor bug and added logging of maintenance_mode calls in anvil-configure-host. Signed-off-by: digimer <mkelly@alteeve.ca>
1736 lines
71 KiB
Perl
Executable File
1736 lines
71 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
#
|
|
# This is called when striker, a node or a DR host needs to configure the local network and user accounts.
|
|
#
|
|
# Exit codes;
|
|
# 0 = Normal exit.
|
|
# 1 = The program is not running as root.
|
|
# 2 = Failed to connect to database(s).
|
|
# 3 = Job was already picked up by another running instance.
|
|
# 4 = The host name did not update properly.
|
|
# 5 = Failed to write the temp file with the new password needed to call anvil-change-password.
|
|
# 6 = The job-uuid was not found.
|
|
# 7 = The host is an active cluster member.
|
|
# 8 = Duplicate NICs assigned to the same MAC address
|
|
#
|
|
# TODO:
|
|
# - Add MTU support
|
|
# - Check to see if this is a cluster node and/or running VMs, and if so, refuse to run.
|
|
#
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Anvil::Tools;
|
|
use Data::Dumper;
|
|
use Text::Diff;
|
|
|
|
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
|
|
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
|
|
if (($running_directory =~ /^\./) && ($ENV{PWD}))
|
|
{
|
|
$running_directory =~ s/^\./$ENV{PWD}/;
|
|
}
|
|
|
|
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete.
|
|
$| = 1;
|
|
|
|
my $anvil = Anvil::Tools->new();
|
|
|
|
# Read switches
|
|
$anvil->Get->switches({list => ["job-uuid"], man => $THIS_FILE});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}});
|
|
|
|
# Make sure we're running as 'root'
|
|
# $< == real UID, $> == effective UID
|
|
if (($< != 0) && ($> != 0))
|
|
{
|
|
# Not root
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "error_0005"});
|
|
$anvil->nice_exit({exit_code => 1});
|
|
}
|
|
|
|
# Connect
|
|
$anvil->Database->connect();
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "message_0031"});
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "log_0132"});
|
|
if (not $anvil->data->{sys}{database}{connections})
|
|
{
|
|
# No databases, exit.
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "error_0003"});
|
|
$anvil->nice_exit({exit_code => 2});
|
|
}
|
|
|
|
pickup_job_details($anvil);
|
|
overwrite_variables_with_switches($anvil);
|
|
|
|
# Set maintenance mode
|
|
$anvil->System->maintenance_mode({set => 1, debug => 2});
|
|
|
|
reconfigure_network($anvil);
|
|
|
|
# Record that we've configured this machine.
|
|
$anvil->Database->insert_or_update_variables({
|
|
variable_name => "system::configured",
|
|
variable_value => 1,
|
|
variable_default => "",
|
|
variable_description => "striker_0048",
|
|
variable_section => "system",
|
|
variable_source_uuid => $anvil->data->{sys}{host_uuid},
|
|
variable_source_table => "hosts",
|
|
});
|
|
|
|
update_passwords($anvil);
|
|
$anvil->Job->update_progress({
|
|
debug => 3,
|
|
progress => 100,
|
|
message => "",
|
|
job_uuid => $anvil->data->{job}{uuid},
|
|
});
|
|
|
|
# Clear maintenance mode.
|
|
$anvil->System->maintenance_mode({set => 0, debug => 2});
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "log_0467"});
|
|
|
|
### TODO: As of now, the network doesn't come up reliably, so reboot. We add a 60 second delay to make it
|
|
### easier to log in and disable anvil-daemon in case of reboot loops caused by this program thinking
|
|
### it needs to reconfigure the system every run.
|
|
# if ($anvil->data->{sys}{reboot})
|
|
# {
|
|
# do_reboot($anvil);
|
|
# }
|
|
|
|
$anvil->nice_exit({exit_code => 0});
|
|
|
|
|
|
#############################################################################################################
|
|
# Functions #
|
|
#############################################################################################################
|
|
|
|
# This does a reboot.
|
|
sub do_reboot
|
|
{
|
|
my ($anvil) = @_;
|
|
|
|
# Mark that a reboot is needed, in case something kills us before we actually reboot.
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0687", variables => { reason => "#!string!log_0693!#" }});
|
|
my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
|
|
file => $THIS_FILE,
|
|
line => __LINE__,
|
|
job_command => $anvil->data->{path}{exe}{'anvil-manage-power'}." --reboot -y".$anvil->Log->switches,
|
|
job_data => "",
|
|
job_name => "reboot::system",
|
|
job_title => "job_0009",
|
|
job_description => "job_0006",
|
|
job_progress => 0,
|
|
});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }});
|
|
|
|
my $time_left = 60;
|
|
while ($time_left)
|
|
{
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "log_0626", variables => { seconds => $time_left }});
|
|
sleep 10;
|
|
$time_left -= 10;
|
|
}
|
|
my $shell_call = $anvil->data->{path}{exe}{systemctl}." reboot";
|
|
$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__});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code }});
|
|
|
|
return(0);
|
|
}
|
|
|
|
# This updates the passwords on the root user, admin user, database and apache user.
|
|
sub update_passwords
|
|
{
|
|
my ($anvil) = @_;
|
|
|
|
# Have we been asked to set a password?
|
|
$anvil->data->{variables}{form}{config_step2}{striker_password}{value} = "" if not defined $anvil->data->{variables}{form}{config_step2}{striker_password}{value};
|
|
if ($anvil->data->{variables}{form}{config_step2}{striker_password}{value})
|
|
{
|
|
# Set the passwords
|
|
my $password = $anvil->data->{variables}{form}{config_step2}{striker_password}{value};
|
|
my $temp_file = "/tmp/anvil-".$anvil->Get->uuid;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { password => $password }});
|
|
|
|
# Write the password into a temporary file.
|
|
my $error = $anvil->Storage->write_file({
|
|
body => $password,
|
|
file => $temp_file,
|
|
group => "root",
|
|
mode => "0600",
|
|
overwrite => 1,
|
|
secure => 1,
|
|
user => "root",
|
|
});
|
|
|
|
# Call anvil-change-password
|
|
if ($error)
|
|
{
|
|
# Couldn't write the temp file.
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "message_0030", variables => { file => $temp_file }});
|
|
$anvil->nice_exit({exit_code => 5});
|
|
}
|
|
else
|
|
{
|
|
my $wait_until = time + 120;
|
|
my $waiting = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
waiting => $waiting,
|
|
wait_until => $wait_until,
|
|
}});
|
|
while ($waiting)
|
|
{
|
|
my $shell_call = $anvil->data->{path}{exe}{'anvil-change-password'}." -y --password-file ".$temp_file.$anvil->Log->switches;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
|
|
|
|
my ($output, $return_code) = $anvil->System->call({debug => 2, timeout => 15, shell_call => $shell_call });
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code }});
|
|
foreach my $line (split/\n/, $output)
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
|
|
}
|
|
|
|
if ($return_code)
|
|
{
|
|
# Something went wrong
|
|
if (time > $wait_until)
|
|
{
|
|
# Give up.
|
|
$waiting = 0;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { waiting => $waiting }});
|
|
}
|
|
else
|
|
{
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "error_0011", variables => { return_code => $return_code }});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Success
|
|
$waiting = 0;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { waiting => $waiting }});
|
|
}
|
|
}
|
|
|
|
# Unlink the temp file.
|
|
unlink $temp_file;
|
|
}
|
|
}
|
|
|
|
$anvil->Job->update_progress({
|
|
progress => 95,
|
|
job_uuid => $anvil->data->{job}{uuid},
|
|
});
|
|
|
|
return(0);
|
|
}
|
|
|
|
# This does the work of reconfiguring the network
|
|
sub reconfigure_network
|
|
{
|
|
my ($anvil) = @_;
|
|
|
|
my $local_host = $anvil->Get->short_host_name();
|
|
my $reboot_needed = 0;
|
|
my $prefix = exists $anvil->data->{variables}{form}{config_step1}{prefix}{value} ? $anvil->data->{variables}{form}{config_step1}{prefix}{value} : "";
|
|
my $sequence = exists $anvil->data->{variables}{form}{config_step1}{sequence}{value} ? $anvil->data->{variables}{form}{config_step1}{sequence}{value} : "";
|
|
my $domain = exists $anvil->data->{variables}{form}{config_step1}{domain}{value} ? $anvil->data->{variables}{form}{config_step1}{domain}{value} : "";
|
|
my $organization = exists $anvil->data->{variables}{form}{config_step1}{organization}{value} ? $anvil->data->{variables}{form}{config_step1}{organization}{value} : "";
|
|
my $bcn_count = exists $anvil->data->{variables}{form}{config_step1}{bcn_count}{value} ? $anvil->data->{variables}{form}{config_step1}{bcn_count}{value} : 1;
|
|
my $sn_count = exists $anvil->data->{variables}{form}{config_step1}{sn_count}{value} ? $anvil->data->{variables}{form}{config_step1}{sn_count}{value} : 0;
|
|
my $mn_count = exists $anvil->data->{variables}{form}{config_step1}{mn_count}{value} ? $anvil->data->{variables}{form}{config_step1}{mn_count}{value} : 0;
|
|
my $ifn_count = exists $anvil->data->{variables}{form}{config_step1}{ifn_count}{value} ? $anvil->data->{variables}{form}{config_step1}{ifn_count}{value} : 1;
|
|
my $new_host_name = exists $anvil->data->{variables}{form}{config_step2}{host_name}{value} ? $anvil->data->{variables}{form}{config_step2}{host_name}{value} : "";
|
|
my $type = $anvil->Get->host_type();
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
prefix => $prefix,
|
|
sequence => $sequence,
|
|
domain => $domain,
|
|
organization => $organization,
|
|
bcn_count => $bcn_count,
|
|
sn_count => $sn_count,
|
|
mn_count => $mn_count,
|
|
ifn_count => $ifn_count,
|
|
new_host_name => $new_host_name,
|
|
type => $type,
|
|
}});
|
|
|
|
# If we're configuring a dashboard and no host name was given, generate it.
|
|
if (($type eq "striker") && (not $new_host_name))
|
|
{
|
|
$new_host_name = $prefix."-striker".sprintf("%02d", $sequence).".".$domain;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_host_name => $new_host_name }});
|
|
}
|
|
|
|
if ($new_host_name)
|
|
{
|
|
my $type_name = "";
|
|
if ($type eq "striker")
|
|
{
|
|
$type_name = $anvil->Words->string({key => "brand_0003"});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { type_name => $type_name }});
|
|
}
|
|
elsif ($type eq "node")
|
|
{
|
|
$type_name = $anvil->Words->string({key => "brand_0007"});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { type_name => $type_name }});
|
|
}
|
|
elsif ($type eq "dr")
|
|
{
|
|
$type_name = $anvil->Words->string({key => "brand_0008"});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { type_name => $type_name }});
|
|
}
|
|
my $pretty_host_name = $new_host_name;
|
|
if (($organization) && ($sequence))
|
|
{
|
|
$pretty_host_name = $organization." - ".$type_name." ".sprintf("%02d", $sequence);
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { pretty_host_name => $pretty_host_name }});
|
|
}
|
|
|
|
# Set the host_name
|
|
my ($host_name, $descriptive_host_name) = $anvil->System->host_name({set => $new_host_name, pretty => $pretty_host_name, debug => 3});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
|
|
host_name => $host_name,
|
|
descriptive_host_name => $descriptive_host_name,
|
|
}});
|
|
if ($host_name eq $new_host_name)
|
|
{
|
|
# Success
|
|
$anvil->Job->update_progress({
|
|
progress => 10,
|
|
message => "message_0016,!!host_name!$new_host_name!!",
|
|
job_uuid => $anvil->data->{job}{uuid},
|
|
});
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "message_0016", variables => { host_name => $new_host_name }});
|
|
}
|
|
else
|
|
{
|
|
# Failed
|
|
$anvil->Job->update_progress({
|
|
progress => 0,
|
|
message => "message_0017,!!host_name!$new_host_name!!,!!bad_host_name!$host_name!!",
|
|
job_uuid => $anvil->data->{job}{uuid},
|
|
});
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "message_0017", variables => {
|
|
host_name => $new_host_name,
|
|
bad_host_name => $host_name,
|
|
}});
|
|
$anvil->nice_exit({exit_code => 4});
|
|
}
|
|
}
|
|
|
|
# Read the local network manager data.
|
|
$anvil->Network->read_nmcli({debug => 2});
|
|
|
|
# Get the current list of IPs and MAC addresses.
|
|
$anvil->Network->get_ips({debug => 2});
|
|
|
|
# If we're a striker, check apache's config.
|
|
if ($type eq "striker")
|
|
{
|
|
$anvil->Striker->check_httpd_conf({debug => 2});
|
|
}
|
|
|
|
# Now configure the network.
|
|
my $dns = defined $anvil->data->{variables}{form}{config_step2}{dns}{value} ? [split/,/, $anvil->data->{variables}{form}{config_step2}{dns}{value}] : [];
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { dns => $dns }});
|
|
for (my $i = 0; $i < @{$dns}; $i++)
|
|
{
|
|
$dns->[$i] = $anvil->Words->clean_spaces({ string => $dns->[$i] });
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "dns->[$i]" => $dns->[$i] }});
|
|
}
|
|
|
|
my $gateway = defined $anvil->data->{variables}{form}{config_step2}{gateway}{value} ? $anvil->data->{variables}{form}{config_step2}{gateway}{value} : "";
|
|
my $gateway_interface = defined $anvil->data->{variables}{form}{config_step2}{gateway_interface}{value} ? $anvil->data->{variables}{form}{config_step2}{gateway_interface}{value} : "";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
|
|
gateway => $gateway,
|
|
gateway_interface => $gateway_interface,
|
|
}});
|
|
|
|
# If there is no default gateway device, and one of the interfaces are set to DHCP, use it.
|
|
if (not $gateway_interface)
|
|
{
|
|
# IFN first, BCN second, SN last
|
|
foreach my $network_type ("ifn", "bcn", "sn", "mn")
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_type => $network_type }});
|
|
|
|
my $count = 0;
|
|
if ($network_type eq "bcn") { $count = $bcn_count; }
|
|
elsif ($network_type eq "sn") { $count = $sn_count; }
|
|
elsif ($network_type eq "ifn") { $count = $ifn_count; }
|
|
elsif ($network_type eq "mn") { $count = $mn_count; }
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
|
|
|
|
next if not $count;
|
|
foreach my $network_count (1..$count)
|
|
{
|
|
my $ip_key = $network_type.$network_count."_ip";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_key => $ip_key }});
|
|
if ((exists $anvil->data->{variables}{form}{config_step2}{$ip_key}{value}) && ($anvil->data->{variables}{form}{config_step2}{$ip_key}{value} eq "dhcp"))
|
|
{
|
|
$gateway_interface = $network_type.$network_count;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { gateway_interface => $gateway_interface }});
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
### NOTE: Not disconnecting anymore, we'll reboot on changes.
|
|
# Disconnect from the database, as we're about to tear down our connection.
|
|
# $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "log_0466"});
|
|
# $anvil->Database->disconnect();
|
|
|
|
# # Close all open SSH connections
|
|
# foreach my $ssh_fh_key (sort {$a cmp $b} keys %{$anvil->data->{cache}{ssh_fh}})
|
|
# {
|
|
# my $ssh_fh = $anvil->data->{cache}{ssh_fh}{$ssh_fh_key};
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ssh_fh => $ssh_fh }});
|
|
#
|
|
# next if $ssh_fh !~ /^Net::OpenSSH/;
|
|
# $ssh_fh->disconnect();
|
|
# $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "message_0009", variables => { target => $ssh_fh_key }});
|
|
#
|
|
# # For good measure, blank both variables.
|
|
# $anvil->data->{cache}{ssh_fh}{$ssh_fh_key} = "";
|
|
# $ssh_fh = "";
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cache::ssh_fh::${ssh_fh_key}" => $anvil->data->{cache}{ssh_fh}{$ssh_fh_key} }});
|
|
# }
|
|
|
|
# Before we continue, see if there's two interfaces pointing at the same NIC. If so, the node would
|
|
# endlessly reboot.
|
|
my $macs = {};
|
|
my $query = "
|
|
SELECT
|
|
variable_uuid,
|
|
variable_name,
|
|
variable_value
|
|
FROM
|
|
variables
|
|
WHERE
|
|
variable_name LIKE '\%_mac_to_set::value'
|
|
AND
|
|
variable_source_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)."
|
|
ORDER BY
|
|
variable_name ASC;";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, 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 => 2, list => {
|
|
results => $results,
|
|
count => $count,
|
|
}});
|
|
foreach my $row (@{$results})
|
|
{
|
|
my $variable_uuid = $row->[0];
|
|
my $variable_name = $row->[1];
|
|
my $variable_value = $row->[2];
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
's1:variable_uuid' => $variable_uuid,
|
|
's2:variable_name' => $variable_name,
|
|
's3:variable_value' => $variable_value,
|
|
}});
|
|
|
|
# An undefined interface will have the MAC address value set to '1', ignore those.
|
|
next if $variable_value eq "1";
|
|
|
|
if ($variable_name =~ /form::config_step2::(.*?)_mac_to_set::value/)
|
|
{
|
|
my $device = lc($1);
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { device => $device}});
|
|
|
|
if (not exists $macs->{$variable_value})
|
|
{
|
|
$macs->{$variable_value} = $device;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
"macs->${variable_value}" => $macs->{$variable_value},
|
|
}});
|
|
}
|
|
else
|
|
{
|
|
# Fail out!
|
|
my $variables = {
|
|
mac_address => $variable_value,
|
|
iface1 => $macs->{$variable_value},
|
|
iface2 => $device,
|
|
};
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "error_0376", variables => $variables});
|
|
$anvil->Job->update_progress({
|
|
progress => 100,
|
|
message => "error_0376",
|
|
variables => $variables,
|
|
job_status => "failed",
|
|
});
|
|
$anvil->nice_exit({exit_code => 8});
|
|
}
|
|
}
|
|
}
|
|
|
|
# We'll set this to '1' if we reconfigure the network
|
|
$anvil->data->{sys}{reboot} = 0;
|
|
|
|
# This will be set to '1' if we make a change.
|
|
my $changes = 0;
|
|
my $new_interfaces = [];
|
|
foreach my $network_type ("bcn", "sn", "mn", "ifn")
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_type => $network_type }});
|
|
|
|
my $count = 0;
|
|
if ($network_type eq "bcn") { $count = $bcn_count; }
|
|
elsif ($network_type eq "sn") { $count = $sn_count; }
|
|
elsif ($network_type eq "ifn") { $count = $ifn_count; }
|
|
elsif ($network_type eq "mn") { $count = $mn_count; }
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
|
|
|
|
next if not $count;
|
|
foreach my $network_count (1..$count)
|
|
{
|
|
# If the user had the option to create a network but didn't, there will be no link1
|
|
# mac to set.
|
|
my $this_network = $network_type.$network_count;
|
|
my $link1_key = $this_network."_link1_mac_to_set";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
this_network => $this_network,
|
|
link1_key => $link1_key,
|
|
}});
|
|
|
|
next if not exists $anvil->data->{variables}{form}{config_step2}{$link1_key};
|
|
next if not $anvil->data->{variables}{form}{config_step2}{$link1_key}{value};
|
|
my $link2_key = $this_network."_link2_mac_to_set";
|
|
my $subnet_mask_key = $this_network."_subnet_mask";
|
|
my $ip_key = $this_network."_ip";
|
|
my $bridge_key = $this_network."_create_bridge";
|
|
my $link1_mac = $anvil->data->{variables}{form}{config_step2}{$link1_key}{value};
|
|
my $is_gateway = $this_network eq $gateway_interface ? 1 : 0;
|
|
my $link2_mac = defined $anvil->data->{variables}{form}{config_step2}{$link2_key}{value} ? $anvil->data->{variables}{form}{config_step2}{$link2_key}{value} : "";
|
|
my $old_link1_iface = $anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface} ? $anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface} : "";
|
|
my $old_link2_iface = defined $anvil->data->{network}{$local_host}{mac_address}{$link2_mac}{interface} ? $anvil->data->{network}{$local_host}{mac_address}{$link2_mac}{interface} : "";
|
|
my $bridge = defined $anvil->data->{variables}{form}{config_step2}{$bridge_key}{value} ? $anvil->data->{variables}{form}{config_step2}{$bridge_key}{value} : 0;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
ip_key => $ip_key,
|
|
is_gateway => $is_gateway,
|
|
link1_mac => $link1_mac,
|
|
link2_key => $link2_key,
|
|
link2_mac => $link2_mac,
|
|
bridge_key => $bridge_key,
|
|
old_link1_iface => $old_link1_iface,
|
|
old_link2_iface => $old_link2_iface,
|
|
subnet_mask_key => $subnet_mask_key,
|
|
bridge => $bridge,
|
|
}});
|
|
|
|
# Dig out the name that network manager knows the old interface(s) as. The
|
|
# 'old_link1_iface' is the name reported by 'ip', the 'DEVICE=xxx' value in the
|
|
# ifcfg-xxx file.
|
|
my $old_link1_nm_name = $old_link1_iface;
|
|
my $link1_nm_uuid = $anvil->data->{nmcli}{$local_host}{device_to_uuid}{$old_link1_iface};
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
old_link1_nm_name => $old_link1_nm_name,
|
|
link1_nm_uuid => $link1_nm_uuid,
|
|
}});
|
|
if ((exists $anvil->data->{nmcli}{$local_host}{uuid}{$link1_nm_uuid}) && ($anvil->data->{nmcli}{$local_host}{uuid}{$link1_nm_uuid}{name}))
|
|
{
|
|
$old_link1_nm_name = $anvil->data->{nmcli}{$local_host}{uuid}{$link1_nm_uuid}{name};
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_link1_nm_name => $old_link1_nm_name }});
|
|
}
|
|
|
|
# Is there a link 2?
|
|
my $old_link2_nm_name = "";
|
|
if ($old_link2_iface)
|
|
{
|
|
$old_link2_nm_name = $old_link2_iface;
|
|
my $link2_nm_uuid = $anvil->data->{nmcli}{$local_host}{device_to_uuid}{$old_link2_nm_name};
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
old_link2_nm_name => $old_link2_nm_name,
|
|
link2_nm_uuid => $link2_nm_uuid,
|
|
}});
|
|
if ((exists $anvil->data->{nmcli}{$local_host}{uuid}{$link2_nm_uuid}) && ($anvil->data->{nmcli}{$local_host}{uuid}{$link2_nm_uuid}{name}))
|
|
{
|
|
$old_link2_nm_name = $anvil->data->{nmcli}{$local_host}{uuid}{$link2_nm_uuid}{name};
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_link2_nm_name => $old_link2_nm_name }});
|
|
}
|
|
}
|
|
|
|
# Skip if this doesn't exist or isn't a valid IPv4 address.
|
|
if (not exists $anvil->data->{variables}{form}{config_step2}{$ip_key}{value})
|
|
{
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0176", variables => { ip_key => $ip_key }});
|
|
next;
|
|
}
|
|
else
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "variables::form::config_step2::${ip_key}::value" => $anvil->data->{variables}{form}{config_step2}{$ip_key}{value} }});
|
|
}
|
|
if (($anvil->data->{variables}{form}{config_step2}{$ip_key}{value}) &&
|
|
($anvil->data->{variables}{form}{config_step2}{$ip_key}{value} ne "dhcp") &&
|
|
(not $anvil->Validate->ipv4({ip => $anvil->data->{variables}{form}{config_step2}{$ip_key}{value}})))
|
|
{
|
|
# Something was set, but it isn't valid.
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "log_0148", variables => {
|
|
network => $this_network,
|
|
ip => $anvil->data->{variables}{form}{config_step2}{$ip_key}{value},
|
|
}});
|
|
next;
|
|
}
|
|
|
|
# The IP could be 'dhcp', we'll handle that in a bit.
|
|
my $ip_address = $anvil->data->{variables}{form}{config_step2}{$ip_key}{value};
|
|
my $subnet_mask = defined $anvil->data->{variables}{form}{config_step2}{$subnet_mask_key}{value} ? $anvil->data->{variables}{form}{config_step2}{$subnet_mask_key}{value} : "";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
ip_address => $ip_address,
|
|
subnet_mask => $subnet_mask,
|
|
}});
|
|
|
|
# Are we building bonded interfaces?
|
|
if ($anvil->Validate->mac({mac => $link2_mac}))
|
|
{
|
|
# Yup!
|
|
my $say_network = "";
|
|
my $say_interface = "";
|
|
my $interface_prefix = "";
|
|
my $say_defroute = $is_gateway ? "yes" : "no";
|
|
if ($network_type eq "bcn")
|
|
{
|
|
$say_network = "Back-Channel Network ".$network_count;
|
|
$say_interface = "bcn".$network_count;
|
|
$interface_prefix = "BCN";
|
|
}
|
|
elsif ($network_type eq "sn")
|
|
{
|
|
$say_network = "Storage Network ".$network_count;
|
|
$say_interface = "sn".$network_count;
|
|
$interface_prefix = "SN";
|
|
}
|
|
elsif ($network_type eq "mn")
|
|
{
|
|
$say_network = "Migration Network ".$network_count;
|
|
$say_interface = "mn".$network_count;
|
|
$interface_prefix = "MN";
|
|
}
|
|
elsif ($network_type eq "ifn")
|
|
{
|
|
$say_network = "Internet-Facing Network ".$network_count;
|
|
$say_interface = "ifn".$network_count;
|
|
$interface_prefix = "IFN";
|
|
}
|
|
|
|
# Gather variables
|
|
my $cidr = $ip_address eq "dhcp" ? "" : $anvil->Convert->cidr({subnet_mask => $subnet_mask});
|
|
my $bridge_file = $anvil->data->{path}{directories}{ifcfg}."/ifcfg-".$interface_prefix."_".$network_count."_-_Bridge_1";
|
|
my $bond_file = $anvil->data->{path}{directories}{ifcfg}."/ifcfg-".$interface_prefix."_".$network_count."_-_Bond_1";
|
|
my $new_link1_file = $anvil->data->{path}{directories}{ifcfg}."/ifcfg-".$interface_prefix."_".$network_count."_-_Link_1";
|
|
my $new_link2_file = $anvil->data->{path}{directories}{ifcfg}."/ifcfg-".$interface_prefix."_".$network_count."_-_Link_2";
|
|
my $old_link1_file = $new_link1_file;
|
|
my $old_link2_file = $new_link2_file;
|
|
my $new_bridge_iface = $say_interface."_bridge1";
|
|
my $new_bond_iface = $say_interface."_bond1";
|
|
my $new_link1_iface = $say_interface."_link1";
|
|
my $new_link2_iface = $say_interface."_link2";
|
|
my $boot_proto = $ip_address eq "dhcp" ? "dhcp" : "none";
|
|
my $link1_uuid = get_uuid_from_interface_file($anvil, $old_link1_file);
|
|
my $link2_uuid = get_uuid_from_interface_file($anvil, $old_link2_file);
|
|
if ((exists $anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface}) && ($anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface}))
|
|
{
|
|
# This is the device name (ie: bcn1_link1, ens0, etc). If it doesn't
|
|
# exist, see if the new name exists already.
|
|
$old_link1_file = $anvil->data->{path}{directories}{ifcfg}."/ifcfg-".$anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface};
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_link1_file => $old_link1_file }});
|
|
if (not -f $old_link1_file)
|
|
{
|
|
# Does the new file already exist?
|
|
if (-f $new_link1_file)
|
|
{
|
|
# Set the old file to the new one.
|
|
$old_link1_file = $new_link1_file;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_link1_file => $old_link1_file }});
|
|
}
|
|
}
|
|
}
|
|
if ((exists $anvil->data->{network}{$local_host}{mac_address}{$link2_mac}{interface}) && ($anvil->data->{network}{$local_host}{mac_address}{$link2_mac}{interface}))
|
|
{
|
|
$old_link2_file = $anvil->data->{path}{directories}{ifcfg}."/ifcfg-".$anvil->data->{network}{$local_host}{mac_address}{$link2_mac}{interface};
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_link2_file => $old_link2_file }});
|
|
if (not -f $old_link2_file)
|
|
{
|
|
# Does the new file already exist?
|
|
if (-f $new_link2_file)
|
|
{
|
|
# Set the old file to the new one.
|
|
$old_link2_file = $new_link2_file;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_link2_file => $old_link2_file }});
|
|
}
|
|
}
|
|
}
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
bond_file => $bond_file,
|
|
boot_proto => $boot_proto,
|
|
bridge_file => $bridge_file,
|
|
cidr => $cidr,
|
|
link1_uuid => $link1_uuid,
|
|
link2_uuid => $link2_uuid,
|
|
new_bond_iface => $new_bond_iface,
|
|
new_bridge_iface => $new_bridge_iface,
|
|
new_link1_file => $new_link1_file,
|
|
new_link1_iface => $new_link1_iface,
|
|
new_link2_file => $new_link2_file,
|
|
new_link2_iface => $new_link2_iface,
|
|
old_link1_file => $old_link1_file,
|
|
old_link2_file => $old_link2_file,
|
|
say_defroute => $say_defroute,
|
|
}});
|
|
|
|
### NOTE: Bridges and bonds take a UUID, but it can be temperamental. It
|
|
### works more reliably without defining it, so we don't.
|
|
# Are we building a bridge interface?
|
|
my $bridge_config = "";
|
|
if ($bridge)
|
|
{
|
|
my $new_bridge1_nm_name = $interface_prefix." ".$network_count." - Bridge 1";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_bridge1_nm_name => $new_bridge1_nm_name }});
|
|
|
|
# Record that we need to start this.
|
|
push @{$new_interfaces}, $new_bridge1_nm_name;
|
|
|
|
# Yup!
|
|
$bridge_config = "# $say_network - Bridge 1\n";
|
|
$bridge_config .= "DEVICE=\"".$new_bridge_iface."\"\n";
|
|
$bridge_config .= "NAME=\"".$new_bridge1_nm_name."\"\n";
|
|
$bridge_config .= "TYPE=\"Bridge\"\n";
|
|
$bridge_config .= "STP=\"yes\"\n";
|
|
$bridge_config .= "BRIDGING_OPTS=\"priority=32768\"\n";
|
|
$bridge_config .= "PROXY_METHOD=\"none\"\n";
|
|
$bridge_config .= "BROWSER_ONLY=\"no\"\n";
|
|
$bridge_config .= "IPV4_FAILURE_FATAL=\"no\"\n";
|
|
$bridge_config .= "IPV6INIT=\"no\"\n";
|
|
$bridge_config .= "BOOTPROTO=\"".$boot_proto."\"\n";
|
|
|
|
# If the IP is NOT 'dhcp', set it.
|
|
if ($ip_address ne "dhcp")
|
|
{
|
|
$bridge_config .= "IPADDR=\"".$ip_address."\"\n";
|
|
$bridge_config .= $cidr ? "PREFIX=\"".$cidr."\"\n" : "NETMASK=\"".$subnet_mask."\"\n";
|
|
|
|
# If this is the default gateway, add that info.
|
|
if ($is_gateway)
|
|
{
|
|
$bridge_config .= "GATEWAY=\"".$gateway."\"\n";
|
|
for (my $i = 0; $i < @{$dns}; $i++)
|
|
{
|
|
$bridge_config .= "DNS".($i+1)."=\"".$dns->[$i]."\"\n";
|
|
}
|
|
}
|
|
}
|
|
$bridge_config .= "DEFROUTE=\"".$say_defroute."\"\n";
|
|
$bridge_config .= "ONBOOT=\"yes\"\n";
|
|
$bridge_config .= "ZONE=\"".uc($say_interface)."\"\n";
|
|
}
|
|
|
|
# If this is DHCP, but there is a bridge, the bond's boot proto in 'none'.
|
|
$boot_proto = "none" if $bridge;
|
|
|
|
# Make the rest of the network names.
|
|
my $new_bond1_nm_name = $interface_prefix." ".$network_count." - Bond 1";
|
|
my $new_link1_nm_name = $interface_prefix." ".$network_count." - Link 1";
|
|
my $new_link2_nm_name = $interface_prefix." ".$network_count." - Link 2";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
new_bond1_nm_name => $new_bond1_nm_name,
|
|
new_link1_nm_name => $new_link1_nm_name,
|
|
new_link2_nm_name => $new_link2_nm_name,
|
|
}});
|
|
|
|
# Record that we need to start this.
|
|
push @{$new_interfaces}, $new_bond1_nm_name;
|
|
push @{$new_interfaces}, $new_link1_nm_name;
|
|
push @{$new_interfaces}, $new_link2_nm_name;
|
|
|
|
# Build the Bond config.
|
|
my $bond_config = "# $say_network - Bond 1\n";
|
|
$bond_config .= "DEVICE=\"".$new_bond_iface."\"\n";
|
|
$bond_config .= "NAME=\"".$new_bond1_nm_name."\"\n";
|
|
$bond_config .= "TYPE=\"Bond\"\n";
|
|
$bond_config .= "BONDING_OPTS=\"downdelay=0 miimon=100 mode=active-backup primary=".$say_interface."_link1 updelay=120000\"\n";
|
|
$bond_config .= "BONDING_MASTER=\"yes\"\n";
|
|
$bond_config .= "ONBOOT=\"yes\"\n";
|
|
|
|
# Is this connected to a bridge?
|
|
if ($bridge)
|
|
{
|
|
$bond_config .= "BRIDGE=\"".$new_bridge_iface."\"\n";
|
|
}
|
|
else
|
|
{
|
|
# Does this bond have an IP?
|
|
# If the IP is NOT 'dhcp', set it.
|
|
$bond_config .= "BOOTPROTO=\"".$boot_proto."\"\n";
|
|
if ($ip_address ne "dhcp")
|
|
{
|
|
$bond_config .= "IPADDR=\"".$ip_address."\"\n";
|
|
$bond_config .= $cidr ? "PREFIX=\"".$cidr."\"\n" : "NETMASK=\"".$subnet_mask."\"\n";
|
|
|
|
# If this is the default gateway, add that info.
|
|
if ($is_gateway)
|
|
{
|
|
$bond_config .= "GATEWAY=\"".$gateway."\"\n";
|
|
for (my $i = 0; $i < @{$dns}; $i++)
|
|
{
|
|
$bond_config .= "DNS".($i+1)."=\"".$dns->[$i]."\"\n";
|
|
}
|
|
}
|
|
}
|
|
$bond_config .= "DEFROUTE=\"".$say_defroute."\"\n";
|
|
}
|
|
# Rest of the config
|
|
$bond_config .= "ZONE=\"".uc($say_interface)."\"\n";
|
|
|
|
# Now build the links
|
|
my $link1_config = "# $say_network - Link 1\n";
|
|
$link1_config .= "HWADDR=\"".uc($link1_mac)."\"\n";
|
|
$link1_config .= "UUID=\"".$link1_uuid."\"\n";
|
|
$link1_config .= "NAME=\"".$new_link1_nm_name."\"\n";
|
|
$link1_config .= "DEVICE=\"".$new_link1_iface."\"\n";
|
|
$link1_config .= "TYPE=\"Ethernet\"\n";
|
|
$link1_config .= "BOOTPROTO=\"none\"\n";
|
|
$link1_config .= "IPV6INIT=\"no\"\n";
|
|
$link1_config .= "ONBOOT=\"yes\"\n";
|
|
$link1_config .= "USERCTL=\"no\"\n";
|
|
# $link1_config .= "MTU=\"1500\"\n"; # TODO: Make the MTU user-adjustable
|
|
$link1_config .= "NM_CONTROLLED=\"yes\"\n";
|
|
$link1_config .= "SLAVE=\"yes\"\n";
|
|
$link1_config .= "MASTER=\"".$say_interface."_bond1\"\n";
|
|
$link1_config .= "ZONE=\"".uc($say_interface)."\"\n";
|
|
|
|
my $link2_config = "# $say_network - Link 2\n";
|
|
$link2_config .= "HWADDR=\"".uc($link2_mac)."\"\n";
|
|
$link2_config .= "UUID=\"".$link2_uuid."\"\n";
|
|
$link2_config .= "NAME=\"".$new_link2_nm_name."\"\n";
|
|
$link2_config .= "DEVICE=\"".$new_link2_iface."\"\n";
|
|
$link2_config .= "TYPE=\"Ethernet\"\n";
|
|
$link2_config .= "BOOTPROTO=\"none\"\n";
|
|
$link2_config .= "IPV6INIT=\"no\"\n";
|
|
$link2_config .= "ONBOOT=\"yes\"\n";
|
|
$link2_config .= "USERCTL=\"no\"\n";
|
|
# $link2_config .= "MTU=\"1500\"\n"; # TODO: Make the MTU user-adjustable
|
|
$link2_config .= "NM_CONTROLLED=\"yes\"\n";
|
|
$link2_config .= "SLAVE=\"yes\"\n";
|
|
$link2_config .= "MASTER=\"".$say_interface."_bond1\"\n";
|
|
$link2_config .= "ZONE=\"".uc($say_interface)."\"\n";
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
bridge_config => $bridge_config,
|
|
bond_config => $bond_config,
|
|
link1_config => $link1_config,
|
|
link2_config => $link2_config,
|
|
}});
|
|
|
|
# Decide if we need to reboot.
|
|
if (($old_link1_file ne $new_link1_file) && (-e $new_link1_file))
|
|
{
|
|
$changes = 1;
|
|
$anvil->data->{sys}{reboot} = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
changes => $changes,
|
|
"sys::reboot" => $anvil->data->{sys}{reboot},
|
|
}});
|
|
}
|
|
if (($old_link2_file ne $new_link2_file) && (-e $new_link2_file))
|
|
{
|
|
$changes = 1;
|
|
$anvil->data->{sys}{reboot} = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
changes => $changes,
|
|
"sys::reboot" => $anvil->data->{sys}{reboot},
|
|
}});
|
|
}
|
|
|
|
### Write out the new configs, if needed
|
|
# Are we writing a bridge config?
|
|
if ($bridge)
|
|
{
|
|
# If the file already exists, see if it changed.
|
|
my $update = 1;
|
|
if (-e $bridge_file)
|
|
{
|
|
# Read it in to see if there is a difference.
|
|
my $old_body = $anvil->Storage->read_file({file => $bridge_file});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_body => $old_body }});
|
|
|
|
my $difference = diff \$old_body, \$bridge_config, { STYLE => 'Unified' };
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { difference => $difference }});
|
|
if ($difference)
|
|
{
|
|
# Backup the old file.
|
|
$anvil->Storage->backup({debug => 2, file => $bridge_file});
|
|
$changes = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
|
|
}
|
|
else
|
|
{
|
|
# No need to update
|
|
$update = 0;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }});
|
|
}
|
|
}
|
|
|
|
if ($update)
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => {
|
|
bridge_file => $bridge_file,
|
|
bridge_config => $bridge_config,
|
|
}});
|
|
$anvil->Storage->write_file({
|
|
file => $bridge_file,
|
|
body => $bridge_config,
|
|
user => "root",
|
|
group => "root",
|
|
mode => "0644",
|
|
overwrite => 1
|
|
});
|
|
}
|
|
}
|
|
|
|
# Bond, Link 1 and Link 2
|
|
my $update_bond = 1;
|
|
if (-f $bond_file)
|
|
{
|
|
# Read it in to see if there is a difference.
|
|
my $old_body = $anvil->Storage->read_file({file => $bond_file});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_body => $old_body }});
|
|
|
|
my $difference = diff \$old_body, \$bond_config, { STYLE => 'Unified' };
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { difference => $difference }});
|
|
if ($difference)
|
|
{
|
|
# Backup the old file.
|
|
$anvil->Storage->backup({debug => 2, file => $bond_file});
|
|
$changes = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
|
|
}
|
|
else
|
|
{
|
|
# No need to update
|
|
$update_bond = 0;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_bond => $update_bond }});
|
|
}
|
|
}
|
|
if ($update_bond)
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => {
|
|
bond_file => $bond_file,
|
|
bond_config => $bond_config,
|
|
}});
|
|
$anvil->Storage->write_file({
|
|
file => $bond_file,
|
|
body => $bond_config,
|
|
user => "root",
|
|
group => "root",
|
|
mode => "0644",
|
|
overwrite => 1
|
|
});
|
|
}
|
|
|
|
# Link 1
|
|
my $update_link1 = 1;
|
|
if (-f $new_link1_file)
|
|
{
|
|
# Read it in to see if there is a difference.
|
|
my $old_body = $anvil->Storage->read_file({file => $new_link1_file});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_body => $old_body }});
|
|
|
|
my $difference = diff \$old_body, \$link1_config, { STYLE => 'Unified' };
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { difference => $difference }});
|
|
if ($difference)
|
|
{
|
|
# Backup the old file.
|
|
$anvil->Storage->backup({debug => 2, file => $new_link1_file});
|
|
$changes = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
|
|
}
|
|
else
|
|
{
|
|
# No need to update
|
|
$update_link1 = 0;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_link1 => $update_link1 }});
|
|
}
|
|
}
|
|
if ($update_link1)
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => {
|
|
link1_file => $new_link1_file,
|
|
link1_config => $link1_config,
|
|
}});
|
|
$anvil->Storage->write_file({
|
|
file => $new_link1_file,
|
|
body => $link1_config,
|
|
user => "root",
|
|
group => "root",
|
|
mode => "0644",
|
|
overwrite => 1
|
|
});
|
|
}
|
|
|
|
# Link 2
|
|
my $update_link2 = 1;
|
|
if (-f $new_link2_file)
|
|
{
|
|
# Read it in to see if there is a difference.
|
|
my $old_body = $anvil->Storage->read_file({file => $new_link2_file});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_body => $old_body }});
|
|
|
|
my $difference = diff \$old_body, \$link2_config, { STYLE => 'Unified' };
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { difference => $difference }});
|
|
if ($difference)
|
|
{
|
|
# Backup the old file.
|
|
$anvil->Storage->backup({debug => 2, file => $new_link2_file});
|
|
$changes = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
|
|
}
|
|
else
|
|
{
|
|
# No need to update
|
|
$update_link2 = 0;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_link2 => $update_link2 }});
|
|
}
|
|
}
|
|
if ($update_link2)
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => {
|
|
link2_file => $new_link2_file,
|
|
link2_config => $link2_config,
|
|
}});
|
|
$anvil->Storage->write_file({
|
|
file => $new_link2_file,
|
|
body => $link2_config,
|
|
user => "root",
|
|
group => "root",
|
|
mode => "0644",
|
|
overwrite => 1
|
|
});
|
|
}
|
|
|
|
# Backup the old config files, if needed.
|
|
if (-e $old_link1_file)
|
|
{
|
|
$anvil->Storage->backup({file => $old_link1_file});
|
|
}
|
|
if (-e $old_link2_file)
|
|
{
|
|
$anvil->Storage->backup({file => $old_link2_file});
|
|
}
|
|
|
|
# If the NICs names have changed, rename them now.
|
|
if ((exists $anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface}) &&
|
|
($anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface}) &&
|
|
($anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface} ne $new_link1_iface))
|
|
{
|
|
rename_interface($anvil, $anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface}, $new_link1_iface);
|
|
$changes = 1;
|
|
$anvil->data->{sys}{reboot} = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
changes => $changes,
|
|
"sys::reboot" => $anvil->data->{sys}{reboot},
|
|
}});
|
|
}
|
|
if ((exists $anvil->data->{network}{$local_host}{mac_address}{$link2_mac}{interface}) &&
|
|
($anvil->data->{network}{$local_host}{mac_address}{$link2_mac}{interface}) &&
|
|
($anvil->data->{network}{$local_host}{mac_address}{$link2_mac}{interface} ne $new_link2_iface))
|
|
{
|
|
rename_interface($anvil, $anvil->data->{network}{$local_host}{mac_address}{$link2_mac}{interface}, $new_link2_iface);
|
|
$changes = 1;
|
|
$anvil->data->{sys}{reboot} = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
changes => $changes,
|
|
"sys::reboot" => $anvil->data->{sys}{reboot},
|
|
}});
|
|
}
|
|
|
|
# Remove the old link if it was different, of down and up it if the same.
|
|
if ($old_link1_iface ne $new_link1_iface)
|
|
{
|
|
# Delete the old interface
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0461", variables => { interface => $old_link1_nm_name }});
|
|
|
|
# my $shell_call = $anvil->data->{path}{exe}{nmcli}." connection delete ".$old_link1_nm_name;
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
|
|
# my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
# output => $output,
|
|
# return_code => $return_code,
|
|
# }});
|
|
|
|
if (-e $old_link1_file)
|
|
{
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0589", variables => { file => $old_link1_file }});
|
|
unlink $old_link1_file;
|
|
}
|
|
|
|
$changes = 1;
|
|
$anvil->data->{sys}{reboot} = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
changes => $changes,
|
|
"sys::reboot" => $anvil->data->{sys}{reboot},
|
|
}});
|
|
}
|
|
elsif ($update_link1)
|
|
{
|
|
# Down the interface
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0462", variables => { interface => $old_link1_nm_name }});
|
|
|
|
# my $shell_call = $anvil->data->{path}{exe}{nmcli}." connection down ".$old_link1_nm_name;
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
|
|
# my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
# output => $output,
|
|
# return_code => $return_code,
|
|
# }});
|
|
#
|
|
# $changes = 1;
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
|
|
|
|
$changes = 1;
|
|
$anvil->data->{sys}{reboot} = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
changes => $changes,
|
|
"sys::reboot" => $anvil->data->{sys}{reboot},
|
|
}});
|
|
}
|
|
|
|
# Shut down (and rename) Link 2
|
|
if ($old_link2_iface ne $new_link2_iface)
|
|
{
|
|
# Delete the old interface
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0461", variables => { interface => $old_link2_nm_name }});
|
|
|
|
# my $shell_call = $anvil->data->{path}{exe}{nmcli}." connection delete ".$old_link2_nm_name;
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
|
|
# my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
# output => $output,
|
|
# return_code => $return_code,
|
|
# }});
|
|
|
|
if (-e $old_link2_file)
|
|
{
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0589", variables => { file => $old_link2_file }});
|
|
unlink $old_link2_file;
|
|
}
|
|
|
|
$changes = 1;
|
|
$anvil->data->{sys}{reboot} = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
changes => $changes,
|
|
"sys::reboot" => $anvil->data->{sys}{reboot},
|
|
}});
|
|
}
|
|
elsif ($update_link1)
|
|
{
|
|
# Down the interface
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0462", variables => { interface => $old_link2_nm_name }});
|
|
|
|
# my $shell_call = $anvil->data->{path}{exe}{nmcli}." connection down ".$old_link2_nm_name;
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
|
|
# my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
# output => $output,
|
|
# return_code => $return_code,
|
|
# }});
|
|
#
|
|
# $changes = 1;
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
|
|
|
|
$changes = 1;
|
|
$anvil->data->{sys}{reboot} = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
changes => $changes,
|
|
"sys::reboot" => $anvil->data->{sys}{reboot},
|
|
}});
|
|
}
|
|
}
|
|
elsif ((exists $anvil->data->{variables}{form}{config_step2}{$link1_key}{value}) && ($anvil->Validate->mac({mac => $anvil->data->{variables}{form}{config_step2}{$link1_key}{value}})))
|
|
{
|
|
### NOTE: This only applies when configuring Striker dashboards. They can't
|
|
### be 'dhcp', either, so no checks are made for those cases. Likewise,
|
|
### bridges are not used.
|
|
# Single interface, set it up
|
|
my $link1_mac = $anvil->data->{variables}{form}{config_step2}{$link1_key}{value};
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { link1_mac => $link1_mac }});
|
|
|
|
my $say_network = "";
|
|
my $say_interface = "";
|
|
my $interface_prefix = "";
|
|
if ($network_type eq "bcn")
|
|
{
|
|
$say_network = "Back-Channel Network ".$network_count;
|
|
$say_interface = "bcn".$network_count;
|
|
$interface_prefix = "BCN";
|
|
}
|
|
elsif ($network_type eq "sn")
|
|
{
|
|
$say_network = "Storage Network ".$network_count;
|
|
$say_interface = "sn".$network_count;
|
|
$interface_prefix = "SN";
|
|
}
|
|
elsif ($network_type eq "ifn")
|
|
{
|
|
$say_network = "Internet-Facing Network ".$network_count;
|
|
$say_interface = "ifn".$network_count;
|
|
$interface_prefix = "IFN";
|
|
}
|
|
elsif ($network_type eq "mn")
|
|
{
|
|
$say_network = "Migration Network ".$network_count;
|
|
$say_interface = "mn".$network_count;
|
|
$interface_prefix = "MN";
|
|
}
|
|
my $say_defroute = $is_gateway ? "yes" : "no";
|
|
my $cidr = $anvil->Convert->cidr({subnet_mask => $subnet_mask});
|
|
my $new_link1_file = $anvil->data->{path}{directories}{ifcfg}."/ifcfg-".$interface_prefix."_".$network_count."_-_Link_1";
|
|
my $old_link1_file = $new_link1_file;
|
|
my $new_link1_iface = $say_interface."_link1";
|
|
if ((exists $anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface}) && ($anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface}))
|
|
{
|
|
$old_link1_file = $anvil->data->{path}{directories}{ifcfg}."/ifcfg-".$anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface};
|
|
if (not -f $old_link1_file)
|
|
{
|
|
# Does the new file already exist?
|
|
if (-f $new_link1_file)
|
|
{
|
|
# Set the old file to the new one.
|
|
$old_link1_file = $new_link1_file;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_link1_file => $old_link1_file }});
|
|
}
|
|
}
|
|
}
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
cidr => $cidr,
|
|
new_link1_file => $new_link1_file,
|
|
new_link1_iface => $new_link1_iface,
|
|
old_link1_file => $old_link1_file,
|
|
say_defroute => $say_defroute,
|
|
}});
|
|
|
|
my $new_link1_nm_name = $interface_prefix." ".$network_count." - Link 1";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_link1_nm_name => $new_link1_nm_name }});
|
|
push @{$new_interfaces}, $new_link1_nm_name;
|
|
|
|
# Gather (or create) UUIDs
|
|
my $link1_uuid = get_uuid_from_interface_file($anvil, $old_link1_file);
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { link1_uuid => $link1_uuid }});
|
|
|
|
my $link1_config = "# $say_network - Link 1\n";
|
|
$link1_config .= "HWADDR=\"".uc($link1_mac)."\"\n";
|
|
$link1_config .= "UUID=\"".$link1_uuid."\"\n";
|
|
$link1_config .= "NAME=\"".$new_link1_nm_name."\"\n";
|
|
$link1_config .= "DEVICE=\"".$new_link1_iface."\"\n";
|
|
$link1_config .= "TYPE=\"Ethernet\"\n";
|
|
$link1_config .= "BOOTPROTO=\"none\"\n";
|
|
$link1_config .= "IPV6INIT=\"no\"\n";
|
|
$link1_config .= "ONBOOT=\"yes\"\n";
|
|
$link1_config .= "IPADDR=\"".$ip_address."\"\n";
|
|
$link1_config .= $cidr ? "PREFIX=\"".$cidr."\"\n" : "NETMASK=\"".$subnet_mask."\"\n";
|
|
if ($is_gateway)
|
|
{
|
|
$link1_config .= "GATEWAY=\"".$gateway."\"\n";
|
|
for (my $i = 0; $i < @{$dns}; $i++)
|
|
{
|
|
$link1_config .= "DNS".($i+1)."=\"".$dns->[$i]."\"\n";
|
|
}
|
|
}
|
|
$link1_config .= "DEFROUTE=\"".$say_defroute."\"\n";
|
|
$link1_config .= "USERCTL=\"no\"\n";
|
|
# $link1_config .= "MTU=\"1500\"\n"; # TODO: Make the MTU user-adjustable
|
|
$link1_config .= "NM_CONTROLLED=\"yes\"\n";
|
|
$link1_config .= "ZONE=\"".uc($say_interface)."\"";
|
|
|
|
# Link 1
|
|
my $update_link1 = 1;
|
|
if (-f $new_link1_file)
|
|
{
|
|
# Read it in to see if there is a difference.
|
|
my $old_body = $anvil->Storage->read_file({file => $new_link1_file});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_body => $old_body }});
|
|
|
|
my $difference = diff \$old_body, \$link1_config, { STYLE => 'Unified' };
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { difference => $difference }});
|
|
if ($difference)
|
|
{
|
|
# Backup the old file.
|
|
$anvil->Storage->backup({debug => 2, file => $new_link1_file});
|
|
$changes = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
|
|
}
|
|
else
|
|
{
|
|
# No need to update
|
|
$update_link1 = 0;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_link1 => $update_link1 }});
|
|
}
|
|
}
|
|
if ($update_link1)
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => {
|
|
link1_file => $new_link1_file,
|
|
link1_config => $link1_config,
|
|
}});
|
|
$anvil->Storage->write_file({
|
|
file => $new_link1_file,
|
|
body => $link1_config,
|
|
user => "root",
|
|
group => "root",
|
|
mode => "0644",
|
|
overwrite => 1
|
|
});
|
|
}
|
|
|
|
# Backup the existing link1 file, if it exists and is different.
|
|
if (-e $old_link1_file)
|
|
{
|
|
$anvil->Storage->backup({file => $old_link1_file});
|
|
}
|
|
|
|
# If the name differs from old, delete the old interface.
|
|
if ((exists $anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface}) &&
|
|
($anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface}) &&
|
|
($anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface} ne $new_link1_iface))
|
|
{
|
|
# Delete the old interface
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "log_0461", variables => { interface => $old_link1_nm_name }});
|
|
|
|
# my $shell_call = $anvil->data->{path}{exe}{nmcli}." connection delete ".$old_link1_nm_name;
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
|
|
# $anvil->System->call({debug => 2, shell_call => $shell_call});
|
|
#
|
|
# rename_interface($anvil, $anvil->data->{network}{$local_host}{mac_address}{$link1_mac}{interface}, $new_link1_iface);
|
|
|
|
$changes = 1;
|
|
$anvil->data->{sys}{reboot} = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
changes => $changes,
|
|
"sys::reboot" => $anvil->data->{sys}{reboot},
|
|
}});
|
|
}
|
|
elsif ($update_link1)
|
|
{
|
|
# Down the interface
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0462", variables => { interface => $old_link1_nm_name }});
|
|
|
|
# my $shell_call = $anvil->data->{path}{exe}{nmcli}." connection down ".$old_link1_nm_name;
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
|
|
# $anvil->System->call({debug => 2, shell_call => $shell_call});
|
|
#
|
|
# $changes = 1;
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
|
|
|
|
$changes = 1;
|
|
$anvil->data->{sys}{reboot} = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
changes => $changes,
|
|
"sys::reboot" => $anvil->data->{sys}{reboot},
|
|
}});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Doesn't exist, skip.
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "log_0149", variables => { network => $this_network }});
|
|
next;
|
|
}
|
|
}
|
|
}
|
|
|
|
# If we should reset, do so now.
|
|
if ($anvil->data->{sys}{reboot})
|
|
{
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0687", variables => { reason => "#!string!log_0631!#" }});
|
|
do_reboot($anvil);
|
|
}
|
|
|
|
if ($changes)
|
|
{
|
|
# In an attempt to make network changes more reliable, we'll just reboot. This shouldn't
|
|
# actually be hit anymore as any change should have triggered the reboot above.
|
|
$anvil->data->{sys}{reboot} = 1;
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0687", variables => { reason => "#!string!log_0631!#" }});
|
|
do_reboot($anvil);
|
|
|
|
# # Re-read the config
|
|
# $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0463"});
|
|
#
|
|
# my $shell_call = $anvil->data->{path}{exe}{nmcli}." connection reload";
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
|
|
# my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
# output => $output,
|
|
# return_code => $return_code,
|
|
# }});
|
|
#
|
|
# # Give a couple seconds for the reload
|
|
# sleep 2;
|
|
#
|
|
# # Now check the bonds
|
|
# my $repaired = $anvil->Network->check_network({heal => "all"});
|
|
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { repaired => $repaired }});
|
|
# if ($repaired)
|
|
# {
|
|
# # It can take a bit for the bonds to allow traffic, so sleep for a bit.
|
|
# sleep 30;
|
|
# }
|
|
}
|
|
|
|
# Wait for a DB connection. We'll wait up to 130 seconds, as sometimes it takes a while for the network
|
|
# to start routing traffic.
|
|
# my $wait_until = time + 130;
|
|
# until ($anvil->data->{sys}{database}{connections})
|
|
# {
|
|
# $anvil->refresh();
|
|
# $anvil->Database->connect();
|
|
# $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "log_0132"});
|
|
# if (not $anvil->data->{sys}{database}{connections})
|
|
# {
|
|
# if (time > $wait_until)
|
|
# {
|
|
# # Failed to reconnect, reboot. Hopefully the network comes up cleanly
|
|
# # next time..
|
|
# $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, priority => "err", key => "error_0107"});
|
|
# do_reboot($anvil);
|
|
# }
|
|
#
|
|
# # No databases, sleep and then try again.
|
|
# sleep 10;
|
|
# }
|
|
# }
|
|
|
|
# We're half-way there.
|
|
$anvil->Job->update_progress({
|
|
progress => 50,
|
|
job_uuid => $anvil->data->{job}{uuid},
|
|
});
|
|
|
|
# If any virtio bridges exist, remove it/them.
|
|
my $start = 0;
|
|
my ($bridges, $return_code) = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." net-list"});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridges => $bridges, return_code => $return_code }});
|
|
if ($return_code)
|
|
{
|
|
### NOTE: We're doing a bunch of deletes, so to be safe we statically define the directory
|
|
### here.
|
|
# Libvirtd isn't running, check the directory directly.
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0478"});
|
|
my $directory = "/etc/libvirt/qemu/networks/autostart";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { directory => $directory }});
|
|
|
|
if (-d $directory)
|
|
{
|
|
# Delete all files.
|
|
local(*DIRECTORY);
|
|
opendir(DIRECTORY, $directory);
|
|
while(my $file = readdir(DIRECTORY))
|
|
{
|
|
next if $file eq ".";
|
|
next if $file eq "..";
|
|
my $full_path = $directory."/".$file;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
|
|
file => $file,
|
|
full_path => $full_path,
|
|
}});
|
|
if (-l $full_path)
|
|
{
|
|
# It's a symlink, remove it.
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0479", variables => { 'symlink' => $full_path }});
|
|
unlink $full_path;
|
|
if (-l $full_path)
|
|
{
|
|
# It didn't work...
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 0, priority => "err", key => "error_0132", variables => { 'symlink' => $full_path }});;
|
|
}
|
|
}
|
|
}
|
|
closedir(DIRECTORY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach my $line (split/\n/, $bridges)
|
|
{
|
|
$line = $anvil->Words->clean_spaces({string => $line});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
|
|
if ($line =~ /^----------/)
|
|
{
|
|
$start = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { start => $start }});
|
|
next;
|
|
}
|
|
next if not $start;
|
|
my $bridge = ($line =~ /(.*?)\s/)[0];
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridge => $bridge }});
|
|
|
|
$anvil->data->{virsh}{bridge}{$bridge} = 1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "virsh::bridge::$bridge" => $anvil->data->{virsh}{bridge}{$bridge} }});
|
|
}
|
|
|
|
foreach my $bridge (sort {$a cmp $b} keys %{$anvil->data->{virsh}{bridge}})
|
|
{
|
|
# Destroy (stop) it.
|
|
my ($destroy, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." net-destroy ".$bridge});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { destroy => $destroy, return_code => $return_code }});
|
|
|
|
# Disable it from auto-start.
|
|
(my $disable, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." net-autostart ".$bridge." --disable"});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { disable => $disable, return_code => $return_code }});
|
|
|
|
# Undefine (delete)
|
|
(my $undefine, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." net-undefine ".$bridge});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { undefine => $undefine, return_code => $return_code }});
|
|
}
|
|
}
|
|
|
|
$anvil->Job->update_progress({
|
|
progress => 75,
|
|
job_uuid => $anvil->data->{job}{uuid},
|
|
});
|
|
|
|
return(0);
|
|
}
|
|
|
|
# This renames a network interface
|
|
sub rename_interface
|
|
{
|
|
my ($anvil, $old_link_name, $new_link_name) = @_;
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0465", variables => {
|
|
old_interface => $old_link_name,
|
|
new_interface => $new_link_name,
|
|
}});
|
|
|
|
# Take the old name down.
|
|
my $shell_call = $anvil->data->{path}{exe}{ip}." link set ".$old_link_name." down";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
|
|
my ($output, $return_code) = $anvil->System->call({debug => 2, shell_call => $shell_call});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
output => $output,
|
|
return_code => $return_code,
|
|
}});
|
|
|
|
# Rename
|
|
$shell_call = $anvil->data->{path}{exe}{ip}." link set ".$old_link_name." name ".$new_link_name;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
|
|
($output, $return_code) = $anvil->System->call({debug => 2, shell_call => $shell_call});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
output => $output,
|
|
return_code => $return_code,
|
|
}});
|
|
|
|
# Bring up the new interface
|
|
$shell_call = $anvil->data->{path}{exe}{ip}." link set ".$new_link_name." up";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
|
|
($output, $return_code) = $anvil->System->call({debug => 2, shell_call => $shell_call});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
output => $output,
|
|
return_code => $return_code,
|
|
}});
|
|
|
|
return(0);
|
|
}
|
|
|
|
# This will read a network interface file and return the UUID="x" value. If the file doesn't exist or the
|
|
# UUID was not found, a new UUID is generated and returned.
|
|
sub get_uuid_from_interface_file
|
|
{
|
|
my ($anvil, $file) = @_;
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, 'print' => 1, key => "log_0131", variables => { function => "get_uuid_from_interface_file" }});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { file => $file }});
|
|
|
|
my $uuid = "";
|
|
if (-e $file)
|
|
{
|
|
my $body = $anvil->Storage->read_file({file => $file});
|
|
foreach my $line (split/\n/, $body)
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }});
|
|
$line =~ s/#.*//;
|
|
if ($line =~ /UUID=\"(.*?)\"/)
|
|
{
|
|
my $test_uuid = $1;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { test_uuid => $test_uuid }});
|
|
if ($anvil->Validate->uuid({uuid => $test_uuid}))
|
|
{
|
|
$uuid = $test_uuid;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { uuid => $uuid }});
|
|
}
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
if (not $uuid)
|
|
{
|
|
$uuid = $anvil->Get->uuid();
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { uuid => $uuid }});
|
|
}
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { uuid => $uuid }});
|
|
return($uuid);
|
|
}
|
|
|
|
# This will pick up the job, or exit.
|
|
sub pickup_job_details
|
|
{
|
|
my ($anvil) = @_;
|
|
|
|
# If this returns '1', the job-uuid was bad. If it returns '2', another process is running.
|
|
my $return = $anvil->Job->get_job_details({
|
|
check => 1,
|
|
job_uuid => $anvil->data->{switches}{'job-uuid'},
|
|
});
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'return' => $return }});
|
|
if ($return == 1)
|
|
{
|
|
# It's not a valid UUID.
|
|
$anvil->nice_exit({exit_code => 6});
|
|
}
|
|
if ($return == 2)
|
|
{
|
|
# This job is being handled by another process that is still alive.
|
|
$anvil->nice_exit({exit_code => 3});
|
|
}
|
|
|
|
# Still alive? Good.
|
|
my $job_picked_up_by = $anvil->data->{jobs}{job_picked_up_by};
|
|
my $job_progress = $anvil->data->{jobs}{job_progress};
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
job_picked_up_by => $job_picked_up_by,
|
|
job_progress => $job_progress,
|
|
}});
|
|
|
|
# See if the job was picked up by another running instance.
|
|
if ($job_picked_up_by)
|
|
{
|
|
# The previous job is gone if we're still alive, we'll take this over.
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "log_0147", variables => {
|
|
pid => $job_picked_up_by,
|
|
percent => $job_progress,
|
|
}});
|
|
}
|
|
|
|
# This will store the variables from the database
|
|
$anvil->data->{variables} = {};
|
|
|
|
# If we're still alive, pick up the details.
|
|
my $query = "
|
|
SELECT
|
|
variable_name,
|
|
variable_value
|
|
FROM
|
|
variables
|
|
WHERE
|
|
variable_name
|
|
LIKE
|
|
'form::config_step%'
|
|
AND
|
|
variable_source_table = 'hosts'
|
|
AND
|
|
variable_source_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)."
|
|
;";
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, 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 => 2, list => {
|
|
results => $results,
|
|
count => $count,
|
|
}});
|
|
foreach my $row (@{$results})
|
|
{
|
|
my $this_variable = $row->[0];
|
|
my $this_value = $row->[1];
|
|
my $secure = $this_variable =~ /passw/ ? 1 : 0;
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
's1:this_variable' => $this_variable,
|
|
's2:this_value' => $anvil->Log->is_secure($this_value),
|
|
}});
|
|
|
|
$anvil->_make_hash_reference($anvil->data->{variables}, $this_variable, $this_value);
|
|
}
|
|
|
|
# Overwrite variables with job data.
|
|
foreach my $line (split/\n/, $anvil->data->{jobs}{job_data})
|
|
{
|
|
if ($line =~ /^(form::config_step[^\s]+)=(.*?)$/)
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
'job_data::variable_name' => $1,
|
|
'job_data::variable_value' => $anvil->Log->is_secure($2),
|
|
}});
|
|
$anvil->_make_hash_reference($anvil->data->{variables}, $1, $2);
|
|
}
|
|
}
|
|
|
|
# Clear previous data
|
|
$anvil->Job->update_progress({
|
|
progress => 0,
|
|
message => "clear",
|
|
job_uuid => $anvil->data->{job}{uuid},
|
|
});
|
|
|
|
# Record that we've picked up this job.
|
|
$anvil->Job->update_progress({
|
|
progress => 1,
|
|
message => "message_0015",
|
|
job_uuid => $anvil->data->{job}{uuid},
|
|
});
|
|
|
|
# If we're in a cluster, abort.
|
|
if (-e $anvil->data->{path}{exe}{pcs})
|
|
{
|
|
# To make logs more sensible, we'll call 'problem' as 'out_of_cluster'.
|
|
$anvil->data->{cib}{parsed}{'local'}{ready} = "" if not defined $anvil->data->{cib}{parsed}{'local'}{ready};
|
|
my ($out_of_cluster) = $anvil->Cluster->parse_cib();
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
out_of_cluster => $out_of_cluster,
|
|
"cib::parsed::local::ready" => $anvil->data->{cib}{parsed}{'local'}{ready},
|
|
}});
|
|
if ((not $out_of_cluster) && ($anvil->data->{cib}{parsed}{'local'}{ready}))
|
|
{
|
|
# We're in a cluster, abort.
|
|
$anvil->Job->update_progress({
|
|
progress => 100,
|
|
message => "error_0250",
|
|
job_uuid => $anvil->data->{job}{uuid},
|
|
});
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "error_0250"});
|
|
$anvil->nice_exit({exit_code => 7});
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
sub overwrite_variables_with_switches
|
|
{
|
|
my ($anvil) = @_;
|
|
|
|
if (not defined $anvil->data->{variables})
|
|
{
|
|
$anvil->data->{variables} = {};
|
|
}
|
|
|
|
foreach my $switch_name (keys %{$anvil->data->{switches}})
|
|
{
|
|
my $switch_value = $anvil->data->{switches}{$switch_name};
|
|
|
|
if ($switch_name =~ /^form::config_step[^\s]+$/)
|
|
{
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
|
'switches::variable_name' => $switch_name,
|
|
'switches::variable_value' => $anvil->Log->is_secure($switch_value),
|
|
}});
|
|
$anvil->_make_hash_reference($anvil->data->{variables}, $switch_name, $switch_value);
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|