* Finished tools/anvil-configure-host! More notably, it can now update the network without a reboot, and it cleanly handles losing and reconnecting to dashboards.

* Added 'no_ping' to Database->connect() to disable pinging before connection, regardless of the anvil.conf setting.
* Created Network->read_nmcli() that reads, parses and stores the verbose output from 'nmcli'.

I can not properly explain in this commit message how much getting network manager working tripped me up. omg the complexity of what used to be such a simple process...

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 5 years ago
parent 414bf81f25
commit a16e86dc7c
  1. 8
      Anvil/Tools/Database.pm
  2. 207
      Anvil/Tools/Network.pm
  3. 8
      share/words.xml
  4. 428
      tools/anvil-configure-host
  5. 18
      tools/test.pl

@ -731,6 +731,10 @@ B<< Note >>: This is expensive, so should only be called periodically. This will
If set, the connection will be made only to the database server matching the UUID. If set, the connection will be made only to the database server matching the UUID.
=head3 no_ping (optional, default '0')
If set to C<< 1 >>, no attempt to ping a target before connection will happen, even if C<< database::<uuid>::ping = 1 >> is set.
=head3 source (optional) =head3 source (optional)
The C<< source >> parameter is used to check the special C<< updated >> table one all connected databases to see when that source (program name, usually) last updated a given database. If the date stamp is the same on all connected databases, nothing further happens. If one of the databases differ, however, a resync will be requested. The C<< source >> parameter is used to check the special C<< updated >> table one all connected databases to see when that source (program name, usually) last updated a given database. If the date stamp is the same on all connected databases, nothing further happens. If one of the databases differ, however, a resync will be requested.
@ -780,6 +784,7 @@ sub connect
my $check_if_configured = defined $parameter->{check_if_configured} ? $parameter->{check_if_configured} : 0; my $check_if_configured = defined $parameter->{check_if_configured} ? $parameter->{check_if_configured} : 0;
my $db_uuid = defined $parameter->{db_uuid} ? $parameter->{db_uuid} : ""; my $db_uuid = defined $parameter->{db_uuid} ? $parameter->{db_uuid} : "";
my $no_ping = defined $parameter->{no_ping} ? $parameter->{no_ping} : 0;
my $source = defined $parameter->{source} ? $parameter->{source} : "core"; my $source = defined $parameter->{source} ? $parameter->{source} : "core";
my $sql_file = defined $parameter->{sql_file} ? $parameter->{sql_file} : $anvil->data->{path}{sql}{'anvil.sql'}; my $sql_file = defined $parameter->{sql_file} ? $parameter->{sql_file} : $anvil->data->{path}{sql}{'anvil.sql'};
my $tables = defined $parameter->{tables} ? $parameter->{tables} : ""; my $tables = defined $parameter->{tables} ? $parameter->{tables} : "";
@ -787,6 +792,7 @@ sub connect
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
check_if_configured => $check_if_configured, check_if_configured => $check_if_configured,
db_uuid => $db_uuid, db_uuid => $db_uuid,
no_ping => $no_ping,
source => $source, source => $source,
sql_file => $sql_file, sql_file => $sql_file,
tables => $tables, tables => $tables,
@ -901,7 +907,7 @@ sub connect
db_connect_string => $db_connect_string, db_connect_string => $db_connect_string,
"database::${uuid}::ping" => $anvil->data->{database}{$uuid}{ping}, "database::${uuid}::ping" => $anvil->data->{database}{$uuid}{ping},
}}); }});
if ($anvil->data->{database}{$uuid}{ping}) if ((not $no_ping) && ($anvil->data->{database}{$uuid}{ping}))
{ {
# Can I ping? # Can I ping?
my ($pinged) = $anvil->Network->ping({ my ($pinged) = $anvil->Network->ping({

@ -25,6 +25,7 @@ my $THIS_FILE = "Network.pm";
# load_ips # load_ips
# match_gateway # match_gateway
# ping # ping
# read_nmcli
=pod =pod
@ -2250,6 +2251,212 @@ sub ping
return($pinged, $average_ping_time); return($pinged, $average_ping_time);
} }
=head2 read_nmcli
This method reads and parses the C<< nmcli >> data. The data is stored as;
nmcli::<host>::uuid::<uuid>::name
nmcli::<host>::uuid::<uuid>::type
nmcli::<host>::uuid::<uuid>::timestamp_unix
nmcli::<host>::uuid::<uuid>::timestamp
nmcli::<host>::uuid::<uuid>::autoconnect
nmcli::<host>::uuid::<uuid>::autoconnect_priority
nmcli::<host>::uuid::<uuid>::read_only
nmcli::<host>::uuid::<uuid>::dbus_path
nmcli::<host>::uuid::<uuid>::active
nmcli::<host>::uuid::<uuid>::device
nmcli::<host>::uuid::<uuid>::state
nmcli::<host>::uuid::<uuid>::active_path
nmcli::<host>::uuid::<uuid>::slave
nmcli::<host>::uuid::<uuid>::filename
Where C<< uuid >> is the UUID of the connection. For C<< host >>, please see the parameter below. For information on what each value means, please see C<< man nmcli >>.
For each of reference, the following to values are also stored;
nmcli::<host>::name_to_uuid::<name>
nmcli::<host>::device_to_uuid::<device>
Where C<< name >> is the value in the interface set by the C<< NAME= >> variable and C<< device >> is the interface name (as used in C<< ip >>) and as set in the C<< DEVICE= >> variable in the C<< ifcfg-X >> files.
Parameters;
=head3 host (optional, default 'target' or 'local')
This is the hash key under which the parsed C<< nmcli >> data is stored. By default, this is C<< local >> when called locally, or it will be C<< target >> if C<< target >> is passed.
=head3 password (optional)
This is the password used to access a remote machine. This is used when reading C<< nmcli >> data on a remote system.
=head3 port (optional, default '22')
This is the port used to access a remote machine. This is used when reading C<< nmcli >> data on a remote system.
=head3 remote_user (optional, default root)
If C<< target >> is set, this is the remote user we use to log into the remote system.
=head3 target (optional)
This is the host name or IP address of a remote machine that you want to read C<< nmcli >> data from.
=cut
sub read_nmcli
{
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 => "Network->read_nmcli()" }});
# If we were passed a target, try pinging from it instead of locally
my $password = defined $parameter->{password} ? $parameter->{password} : "";
my $host = defined $parameter->{host} ? $parameter->{host} : "";
my $port = defined $parameter->{port} ? $parameter->{port} : "";
my $remote_user = defined $parameter->{remote_user} ? $parameter->{remote_user} : "root";
my $target = defined $parameter->{target} ? $parameter->{target} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
host => $host,
password => $anvil->Log->is_secure($password),
port => $port,
remote_user => $remote_user,
target => $target,
}});
if (not $host)
{
$host = $target ? $target : "local";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host => $host }});
}
if (exists $anvil->data->{nmcli}{$host})
{
delete $anvil->data->{nmcli}{$host};
}
# Reading locally or remote?
my $shell_call = $anvil->data->{path}{exe}{nmcli}." --colors no --fields all --terse connection show";
my $output = "";
my $is_local = $anvil->Network->is_local({host => $target});
if ($is_local)
{
# Local call.
($output, my $return_code) = $anvil->System->call({debug => $debug, shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
's1:output' => $output,
's2:return_code' => $return_code,
}});
}
else
{
# Remote call
($output, my $error, my $return_code) = $anvil->Remote->call({
debug => $debug,
shell_call => $shell_call,
target => $target,
user => $remote_user,
password => $password,
remote_user => $remote_user,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
's1:output' => $output,
's2:error' => $error,
's3:return_code' => $return_code,
}});
}
foreach my $line (split/\n/, $output)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'line >>' => $line }});
$line =~ s/\\:/!col!/g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'line <<' => $line }});
# NAME UUID TYPE TIMESTAMP TIMESTAMP-REAL AUTOCONNECT AUTOCONNECT-PRIORITY READONLY DBUS-PATH ACTIVE DEVICE STATE ACTIVE-PATH SLAVE FILENAME
my ($name, $uuid, $type, $timestamp_unix, $timestamp, $autoconnect, $autoconnect_priority, $read_only, $dbus_path, $active, $device, $state, $active_path, $slave, $filename) = (split/:/, $line);
$timestamp =~ s/!col!/:/g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
's1:name' => $name,
's2:uuid' => $uuid,
's3:type' => $type,
's4:timestamp_unix' => $timestamp_unix,
's5:timestamp' => $timestamp,
's6:autoconnect' => $autoconnect,
's7:autoconnect_priority' => $autoconnect_priority,
's8:read_only' => $read_only,
's9:dbus_path' => $dbus_path,
's10:active' => $active,
's11:device' => $device,
's12:state' => $state,
's13:active_path' => $active_path,
's14:slave' => $slave,
's15:filename' => $filename,
}});
if ($uuid)
{
# Inactive interfaces have a name but not a device;
if (not $device)
{
$device = $name;
$device =~ s/ /_/g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { device => $device }});
}
# Make it easy to look up a device's UUID by device or name.
$anvil->data->{nmcli}{$host}{name_to_uuid}{$name} = $uuid;
$anvil->data->{nmcli}{$host}{device_to_uuid}{$device} = $uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"nmcli::${host}::name_to_uuid::${name}" => $anvil->data->{nmcli}{$host}{name_to_uuid}{$name},
"nmcli::${host}::device_to_uuid::${device}" => $anvil->data->{nmcli}{$host}{device_to_uuid}{$device},
}});
# Translate some values;
my $say_state = not $state ? 0 : 1;
my $say_active = $active eq "no" ? 0 : 1;
my $say_read_only = $read_only eq "no" ? 0 : 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
say_state => $say_state,
say_active => $say_active,
say_read_only => $say_read_only,
}});
# Now store the data
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{name} = $name;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{type} = $type;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{timestamp_unix} = $timestamp_unix;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{timestamp} = $timestamp;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{autoconnect} = $autoconnect;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{autoconnect_priority} = $autoconnect_priority;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{read_only} = $say_read_only;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{dbus_path} = $dbus_path;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{active} = $say_active;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{device} = $device;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{'state'} = $say_state;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{active_path} = $active_path;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{slave} = $slave;
$anvil->data->{nmcli}{$host}{uuid}{$uuid}{filename} = $filename;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"nmcli::${host}::uuid::${uuid}::name" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{name},
"nmcli::${host}::uuid::${uuid}::type" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{type},
"nmcli::${host}::uuid::${uuid}::timestamp_unix" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{timestamp_unix},
"nmcli::${host}::uuid::${uuid}::timestamp" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{timestamp},
"nmcli::${host}::uuid::${uuid}::autoconnect" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{autoconnect},
"nmcli::${host}::uuid::${uuid}::autoconnect_priority" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{autoconnect_priority},
"nmcli::${host}::uuid::${uuid}::read_only" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{read_only},
"nmcli::${host}::uuid::${uuid}::dbus_path" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{dbus_path},
"nmcli::${host}::uuid::${uuid}::active" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{active},
"nmcli::${host}::uuid::${uuid}::device" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{device},
"nmcli::${host}::uuid::${uuid}::state" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{'state'},
"nmcli::${host}::uuid::${uuid}::active_path" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{active_path},
"nmcli::${host}::uuid::${uuid}::slave" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{slave},
"nmcli::${host}::uuid::${uuid}::filename" => $anvil->data->{nmcli}{$host}{uuid}{$uuid}{filename},
}});
}
}
return(0);
}
############################################################################################################# #############################################################################################################
# Private functions # # Private functions #
############################################################################################################# #############################################################################################################

@ -792,6 +792,13 @@ Failed to promote the DRBD resource: [#!variable!resource!#] primary. Expected a
<key name="log_0458">Vacuuming the database to purge the removed records.</key> <key name="log_0458">Vacuuming the database to purge the removed records.</key>
<key name="log_0459">Skipping the table: [#!variable!table!#], it is excluded from archiving.</key> <key name="log_0459">Skipping the table: [#!variable!table!#], it is excluded from archiving.</key>
<key name="log_0460">Queing up to run: [#!variable!uuid!#]:[#!variable!query!#]</key> <key name="log_0460">Queing up to run: [#!variable!uuid!#]:[#!variable!query!#]</key>
<key name="log_0461">About to delete the network interface: [#!variable!interface!#]</key>
<key name="log_0462">About to take the network interface: [#!variable!interface!#] down</key>
<key name="log_0463">Requesting network manager reload config files.</key>
<key name="log_0464">About to bring up the network interface: [#!variable!interface!#]</key>
<key name="log_0465">About to rename the network interface: [#!variable!old_interface!#] to: [#!variable!new_interface!#]</key>
<key name="log_0466">Disconnected from all databases and closing all open SSH sessions. Will reconnect after the network configuration changes have taken effect.</key>
<key name="log_0467">Network reconfiguration is complete!</key>
<!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. --> <!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. -->
<key name="t_0000">Test</key> <key name="t_0000">Test</key>
@ -1300,6 +1307,7 @@ Failed to generate an RSA public key for the user: [#!variable!user!#]. The outp
<key name="error_0104">The parameter get_company_from_oui->mac must be a valid MAC address or be in the format 'xx:xx:xx'. Received: [#!variable!mac!#].</key> <key name="error_0104">The parameter get_company_from_oui->mac must be a valid MAC address or be in the format 'xx:xx:xx'. Received: [#!variable!mac!#].</key>
<key name="error_0105">The file: [#!variable!file!#] was not found.</key> <key name="error_0105">The file: [#!variable!file!#] was not found.</key>
<key name="error_0106"><![CDATA[The method Network->find_matches() was given the hash key: [#!variable!key!#], but it does not reference a hash. Are any IPs associated with this target?]]></key> <key name="error_0106"><![CDATA[The method Network->find_matches() was given the hash key: [#!variable!key!#], but it does not reference a hash. Are any IPs associated with this target?]]></key>
<key name="error_0107">Failed to reconnect after reconfiguring the network, exiting.</key>
<!-- These are units, words and so on used when displaying information. --> <!-- These are units, words and so on used when displaying information. -->
<key name="unit_0001">Yes</key> <key name="unit_0001">Yes</key>

@ -32,7 +32,6 @@ $anvil->Log->level({set => 2});
$anvil->Log->secure({set => 1}); $anvil->Log->secure({set => 1});
# Read switches # Read switches
$anvil->data->{switches}{'no-reboot'} = 0;
$anvil->Get->switches; $anvil->Get->switches;
# Make sure we're running as 'root' # Make sure we're running as 'root'
@ -40,18 +39,18 @@ $anvil->Get->switches;
if (($< != 0) && ($> != 0)) if (($< != 0) && ($> != 0))
{ {
# Not root # Not root
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "error_0005"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "error_0005"});
$anvil->nice_exit({code => 1}); $anvil->nice_exit({code => 1});
} }
# Connect # Connect
$anvil->Database->connect(); $anvil->Database->connect();
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0031"}); $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, secure => 0, key => "log_0132"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, secure => 0, key => "log_0132"});
if (not $anvil->data->{sys}{database}{connections}) if (not $anvil->data->{sys}{database}{connections})
{ {
# No databases, exit. # No databases, exit.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "error_0003"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "error_0003"});
$anvil->nice_exit({exit_code => 2}); $anvil->nice_exit({exit_code => 2});
} }
@ -60,8 +59,7 @@ pickup_job_details($anvil);
# Set maintenance mode # Set maintenance mode
$anvil->System->maintenance_mode({set => 1}); $anvil->System->maintenance_mode({set => 1});
my ($reboot_needed) = reconfigure_network($anvil); reconfigure_network($anvil);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => { reboot_needed => $reboot_needed }});
# Record that we've configured this machine. # Record that we've configured this machine.
$anvil->Database->insert_or_update_variables({ $anvil->Database->insert_or_update_variables({
@ -78,28 +76,15 @@ update_passwords($anvil);
$anvil->Job->update_progress({ $anvil->Job->update_progress({
debug => 3, debug => 3,
progress => 100, progress => 100,
message => $anvil->data->{switches}{'no-reboot'} ? "message_0065" : "", message => "",
job_uuid => $anvil->data->{job}{uuid}, job_uuid => $anvil->data->{job}{uuid},
}); });
# Clear maintenance mode. # Clear maintenance mode.
$anvil->System->maintenance_mode({set => 0}); $anvil->System->maintenance_mode({set => 0});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, secure => 0, key => "log_0132"});
### TODO: This is only until we can get the damn networking stable on reconfigure. # Done
# Set reboot needed so that things clean up properly on reboot.
if ($reboot_needed)
{
$anvil->System->reboot_needed({set => 1});
if (not $anvil->data->{switches}{'no-reboot'})
{
# Reboot, after waiting a few seconds to let the user's browser pick up the last messages in
# jobs.json. We'll also log the user out, in case we were re-configuring.
sleep 5;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0215"});
$anvil->Account->logout({debug => 2});
$anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{'anvil-manage-power'}." --reboot -y"});
}
}
$anvil->nice_exit({code => 0}); $anvil->nice_exit({code => 0});
@ -136,7 +121,7 @@ sub update_passwords
if ($error) if ($error)
{ {
# Couldn't write the temp file. # Couldn't write the temp file.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "message_0030", variables => { file => $temp_file }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "message_0030", variables => { file => $temp_file }});
$anvil->nice_exit({code => 5}); $anvil->nice_exit({code => 5});
} }
else else
@ -154,7 +139,7 @@ sub update_passwords
if ($return_code) if ($return_code)
{ {
# Something went wrong # Something went wrong
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "error_0011", variables => { return_code => $return_code }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "error_0011", variables => { return_code => $return_code }});
} }
} }
} }
@ -240,7 +225,7 @@ sub reconfigure_network
message => "message_0016,!!host_name!$new_host_name!!", message => "message_0016,!!host_name!$new_host_name!!",
job_uuid => $anvil->data->{job}{uuid}, job_uuid => $anvil->data->{job}{uuid},
}); });
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0016", variables => { host_name => $new_host_name }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "message_0016", variables => { host_name => $new_host_name }});
} }
else else
{ {
@ -250,7 +235,7 @@ sub reconfigure_network
message => "message_0017,!!host_name!$new_host_name!!,!!bad_host_name!$host_name!!", message => "message_0017,!!host_name!$new_host_name!!,!!bad_host_name!$host_name!!",
job_uuid => $anvil->data->{job}{uuid}, job_uuid => $anvil->data->{job}{uuid},
}); });
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "message_0017", variables => { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "message_0017", variables => {
host_name => $new_host_name, host_name => $new_host_name,
bad_host_name => $host_name, bad_host_name => $host_name,
}}); }});
@ -258,6 +243,9 @@ sub reconfigure_network
} }
} }
# Read the local network manager data.
$anvil->Network->read_nmcli({debug => 3});
# Get the current list of IPs and MAC addresses. # Get the current list of IPs and MAC addresses.
$anvil->Network->get_ips({debug => 3}); $anvil->Network->get_ips({debug => 3});
@ -276,6 +264,57 @@ sub reconfigure_network
gateway => $gateway, gateway => $gateway,
gateway_interface => $gateway_interface, 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")
{
$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; }
$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;
}
}
}
}
# 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, secure => 0, 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} }});
}
my $new_interfaces = [];
foreach my $network_type ("bcn", "sn", "ifn") foreach my $network_type ("bcn", "sn", "ifn")
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { network_type => $network_type }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { network_type => $network_type }});
@ -316,10 +355,33 @@ sub reconfigure_network
bridge => $bridge, 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;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_link1_nm_name => $old_link1_nm_name }});
if ((exists $anvil->data->{nmcli}{'local'}{device_to_uuid}{$old_link1_iface}) && ($anvil->data->{nmcli}{'local'}{device_to_uuid}{$old_link1_iface}))
{
$old_link1_nm_name = $anvil->data->{nmcli}{'local'}{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 }});
}
# Is there a link 2?
my $old_link2_nm_name = "";
if ($old_link2_iface)
{
$old_link2_nm_name = $old_link2_iface;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_link2_nm_name => $old_link2_nm_name }});
if ((exists $anvil->data->{nmcli}{'local'}{device_to_uuid}{$old_link2_iface}) && ($anvil->data->{nmcli}{'local'}{device_to_uuid}{$old_link2_iface}))
{
$old_link2_nm_name = $anvil->data->{nmcli}{'local'}{device_to_uuid}{$old_link2_iface};
$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. # 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}) 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 }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0176", variables => { ip_key => $ip_key }});
next; next;
} }
else else
@ -331,7 +393,7 @@ sub reconfigure_network
(not $anvil->Validate->is_ipv4({ip => $anvil->data->{variables}{form}{config_step2}{$ip_key}{value}}))) (not $anvil->Validate->is_ipv4({ip => $anvil->data->{variables}{form}{config_step2}{$ip_key}{value}})))
{ {
# Something was set, but it isn't valid. # Something was set, but it isn't valid.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "log_0148", variables => { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "log_0148", variables => {
network => $this_network, network => $this_network,
ip => $anvil->data->{variables}{form}{config_step2}{$ip_key}{value}, ip => $anvil->data->{variables}{form}{config_step2}{$ip_key}{value},
}}); }});
@ -386,8 +448,6 @@ sub reconfigure_network
my $new_link1_iface = $say_interface."_link1"; my $new_link1_iface = $say_interface."_link1";
my $new_link2_iface = $say_interface."_link2"; my $new_link2_iface = $say_interface."_link2";
my $boot_proto = $ip_address eq "dhcp" ? "dhcp" : "none"; my $boot_proto = $ip_address eq "dhcp" ? "dhcp" : "none";
my $bridge_uuid = get_uuid_from_interface_file($anvil, $bridge_file);
my $bond_uuid = get_uuid_from_interface_file($anvil, $bond_file);
my $link1_uuid = get_uuid_from_interface_file($anvil, $old_link1_file); my $link1_uuid = get_uuid_from_interface_file($anvil, $old_link1_file);
my $link2_uuid = get_uuid_from_interface_file($anvil, $old_link2_file); my $link2_uuid = get_uuid_from_interface_file($anvil, $old_link2_file);
if ((exists $anvil->data->{network}{mac_address}{$link1_mac}{iface}) && ($anvil->data->{network}{mac_address}{$link1_mac}{iface})) if ((exists $anvil->data->{network}{mac_address}{$link1_mac}{iface}) && ($anvil->data->{network}{mac_address}{$link1_mac}{iface}))
@ -400,10 +460,8 @@ sub reconfigure_network
} }
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
bond_file => $bond_file, bond_file => $bond_file,
bond_uuid => $bond_uuid,
boot_proto => $boot_proto, boot_proto => $boot_proto,
bridge_file => $bridge_file, bridge_file => $bridge_file,
bridge_uuid => $bridge_uuid,
cidr => $cidr, cidr => $cidr,
link1_uuid => $link1_uuid, link1_uuid => $link1_uuid,
link2_uuid => $link2_uuid, link2_uuid => $link2_uuid,
@ -418,27 +476,36 @@ sub reconfigure_network
say_defroute => $say_defroute, 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? # Are we building a bridge interface?
my $bridge_config = ""; my $bridge_config = "";
if ($bridge) 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! # Yup!
$bridge_config = "# $say_network - Bridge 1\n"; $bridge_config = "# $say_network - Bridge 1\n";
$bridge_config .= "UUID=\"".$bond_uuid."\"\n";
$bridge_config .= "TYPE=\"Bridge\"\n";
$bridge_config .= "DEVICE=\"".$new_bridge_iface."\"\n"; $bridge_config .= "DEVICE=\"".$new_bridge_iface."\"\n";
$bridge_config .= "NAME=\"".$interface_prefix." ".$network_count." - Bridge 1\"\n"; $bridge_config .= "NAME=\"".$new_bridge1_nm_name."\"\n";
$bridge_config .= "ONBOOT=\"yes\"\n"; $bridge_config .= "TYPE=\"Bridge\"\n";
$bridge_config .= "STP=\"yes\"\n"; $bridge_config .= "STP=\"yes\"\n";
$bridge_config .= "BRIDGING_OPTS=\"priority=32768\"\n"; $bridge_config .= "BRIDGING_OPTS=\"priority=32768\"\n";
$bridge_config .= "PROXY_METHOD=\"none\"\n";
$bridge_config .= "BROWSER_ONLY=\"no\"\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"; $bridge_config .= "BOOTPROTO=\"".$boot_proto."\"\n";
# If the IP is NOT 'dhcp', set it. # If the IP is NOT 'dhcp', set it.
if ($ip_address ne "dhcp") if ($ip_address ne "dhcp")
{ {
$bridge_config .= "IPADDR=\"".$ip_address."\"\n"; $bridge_config .= "IPADDR=\"".$ip_address."\"\n";
$bridge_config .= $cidr ? "PREFIX=\"".$cidr."\"\n" : "NETMASK=\"".$subnet_mask."\"\n"; $bridge_config .= $cidr ? "PREFIX=\"".$cidr."\"\n" : "NETMASK=\"".$subnet_mask."\"\n";
}
# If this is the default gateway, add that info. # If this is the default gateway, add that info.
if ($is_gateway) if ($is_gateway)
@ -449,39 +516,55 @@ sub reconfigure_network
$bridge_config .= "DNS".($i+1)."=\"".$dns->[$i]."\"\n"; $bridge_config .= "DNS".($i+1)."=\"".$dns->[$i]."\"\n";
} }
} }
}
$bridge_config .= "DEFROUTE=\"".$say_defroute."\"\n"; $bridge_config .= "DEFROUTE=\"".$say_defroute."\"\n";
$bridge_config .= "ONBOOT=\"yes\"\n";
$bridge_config .= "ZONE=\"".uc($say_interface)."\"\n"; $bridge_config .= "ZONE=\"".uc($say_interface)."\"\n";
} }
# If this is DHCP, but there is a bridge, the bond's boot proto in 'none'. # If this is DHCP, but there is a bridge, the bond's boot proto in 'none'.
$boot_proto = "none" if $bridge; $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. # Build the Bond config.
my $bond_config = "# $say_network - Bond 1\n"; my $bond_config = "# $say_network - Bond 1\n";
$bond_config .= "UUID=\"".$bond_uuid."\"\n";
$bond_config .= "NAME=\"".$interface_prefix." ".$network_count." - Bond 1\"\n";
$bond_config .= "DEVICE=\"".$new_bond_iface."\"\n"; $bond_config .= "DEVICE=\"".$new_bond_iface."\"\n";
$bond_config .= "BONDING_OPTS=\"mode=active-backup primary=".$say_interface."_link1 updelay=120000 downdelay=0 miimon=100 primary_reselect=better\"\n"; $bond_config .= "NAME=\"".$new_bond1_nm_name."\"\n";
$bond_config .= "TYPE=\"Bond\"\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 .= "BONDING_MASTER=\"yes\"\n";
$bond_config .= "IPV6INIT=\"no\"\n";
$bond_config .= "ONBOOT=\"yes\"\n"; $bond_config .= "ONBOOT=\"yes\"\n";
$bond_config .= "BOOTPROTO=\"".$boot_proto."\"\n";
# If this is a connected to a bridge, we specify as much. # Is this connected to a bridge?
if ($bridge) if ($bridge)
{ {
$bond_config .= "BRIDGE=\"".$new_bridge_iface."\"\n"; $bond_config .= "BRIDGE=\"".$new_bridge_iface."\"\n";
} }
else else
{ {
# If the ip is NOT 'dhcp', set the ip and subnet # 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") if ($ip_address ne "dhcp")
{ {
# This bond has an IP, set it
$bond_config .= "IPADDR=\"".$ip_address."\"\n"; $bond_config .= "IPADDR=\"".$ip_address."\"\n";
$bond_config .= $cidr ? "PREFIX=\"".$cidr."\"\n" : "NETMASK=\"".$subnet_mask."\"\n"; $bond_config .= $cidr ? "PREFIX=\"".$cidr."\"\n" : "NETMASK=\"".$subnet_mask."\"\n";
}
# Is this the default gateway? # If this is the default gateway, add that info.
if ($is_gateway) if ($is_gateway)
{ {
$bond_config .= "GATEWAY=\"".$gateway."\"\n"; $bond_config .= "GATEWAY=\"".$gateway."\"\n";
@ -490,14 +573,17 @@ sub reconfigure_network
$bond_config .= "DNS".($i+1)."=\"".$dns->[$i]."\"\n"; $bond_config .= "DNS".($i+1)."=\"".$dns->[$i]."\"\n";
} }
} }
}
$bond_config .= "DEFROUTE=\"".$say_defroute."\"\n"; $bond_config .= "DEFROUTE=\"".$say_defroute."\"\n";
} }
# Rest of the config
$bond_config .= "ZONE=\"".uc($say_interface)."\"\n"; $bond_config .= "ZONE=\"".uc($say_interface)."\"\n";
# Now build the links
my $link1_config = "# $say_network - Link 1\n"; my $link1_config = "# $say_network - Link 1\n";
$link1_config .= "HWADDR=\"".uc($link1_mac)."\"\n"; $link1_config .= "HWADDR=\"".uc($link1_mac)."\"\n";
$link1_config .= "UUID=\"".$link1_uuid."\"\n"; $link1_config .= "UUID=\"".$link1_uuid."\"\n";
$link1_config .= "NAME=\"".$interface_prefix." ".$network_count." - Link 1\"\n"; $link1_config .= "NAME=\"".$new_link1_nm_name."\"\n";
$link1_config .= "DEVICE=\"".$new_link1_iface."\"\n"; $link1_config .= "DEVICE=\"".$new_link1_iface."\"\n";
$link1_config .= "TYPE=\"Ethernet\"\n"; $link1_config .= "TYPE=\"Ethernet\"\n";
$link1_config .= "BOOTPROTO=\"none\"\n"; $link1_config .= "BOOTPROTO=\"none\"\n";
@ -513,7 +599,7 @@ sub reconfigure_network
my $link2_config = "# $say_network - Link 2\n"; my $link2_config = "# $say_network - Link 2\n";
$link2_config .= "HWADDR=\"".uc($link2_mac)."\"\n"; $link2_config .= "HWADDR=\"".uc($link2_mac)."\"\n";
$link2_config .= "UUID=\"".$link2_uuid."\"\n"; $link2_config .= "UUID=\"".$link2_uuid."\"\n";
$link2_config .= "NAME=\"".$interface_prefix." ".$network_count." - Link 2\"\n"; $link2_config .= "NAME=\"".$new_link2_nm_name."\"\n";
$link2_config .= "DEVICE=\"".$new_link2_iface."\"\n"; $link2_config .= "DEVICE=\"".$new_link2_iface."\"\n";
$link2_config .= "TYPE=\"Ethernet\"\n"; $link2_config .= "TYPE=\"Ethernet\"\n";
$link2_config .= "BOOTPROTO=\"none\"\n"; $link2_config .= "BOOTPROTO=\"none\"\n";
@ -559,91 +645,85 @@ sub reconfigure_network
$anvil->Storage->backup({debug => 2, file => $new_link2_file}); $anvil->Storage->backup({debug => 2, file => $new_link2_file});
} }
### Write out the new configs # Remove the old link if it was different, of down and up it if the same.
# Are we writing a bridge config?
if ($bridge)
{
$anvil->Storage->write_file({file => $bridge_file, body => $bridge_config, user => "root", group => "root", mode => "0644", overwrite => 1});
}
# Bond, Link 1 and Link 2
$anvil->Storage->write_file({file => $bond_file, body => $bond_config, user => "root", group => "root", mode => "0644", overwrite => 1});
$anvil->Storage->write_file({file => $new_link1_file, body => $link1_config, user => "root", group => "root", mode => "0644", overwrite => 1});
$anvil->Storage->write_file({file => $new_link2_file, body => $link2_config, user => "root", group => "root", mode => "0644", overwrite => 1});
### NOTE: Everything except the unlink is disabled until we sort out the
### reload without reboot.
# Shut down (and rename) Link 1
if ($old_link1_iface)
{
# Take down and rename the old link 1 interface
#print "Downing: ..... [$old_link1_iface]\n";
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ifdown}." ".$old_link1_iface});
#print "Disconnecting: [$old_link1_iface]\n";
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ip}." link set ".$old_link1_iface." down"});
}
if ($old_link1_iface ne $new_link1_iface) if ($old_link1_iface ne $new_link1_iface)
{ {
# Rename it # Delete the old interface
#print "Renaming: .... [$old_link1_iface] -> [$new_link1_iface]\n"; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0461", variables => { interface => $old_link1_nm_name }});
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ip}." link set ".$old_link1_iface." name ".$new_link1_iface}); my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $anvil->data->{path}{exe}{nmcli}." connection delete ".$old_link1_nm_name});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => {
output => $output,
return_code => $return_code,
}});
# Unllnk the old one, if it exists.
if (-e $old_link1_file) if (-e $old_link1_file)
{ {
#print "Deleting: .... [$old_link1_file]\n";
unlink $old_link1_file; unlink $old_link1_file;
} }
} }
# Drop the new link, too, in case it still has the old config else
#print "Downing: ..... [$new_link1_iface]\n";
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ifdown}." ".$new_link1_iface});
# Shut down (and rename) Link 2
if ($old_link2_iface)
{ {
# Take down and rename the old link 1 interface # Down the interface
#print "Downing: ..... [$old_link2_iface]\n"; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0462", variables => { interface => $old_link1_nm_name }});
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ifdown}." ".$old_link2_iface}); my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $anvil->data->{path}{exe}{nmcli}." connection down ".$old_link1_nm_name});
#print "Disconnecting: [$old_link2_iface]\n"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => {
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ip}." link set ".$old_link2_iface." down"}); output => $output,
return_code => $return_code,
}});
} }
# Shut down (and rename) Link 2
if ($old_link2_iface ne $new_link2_iface) if ($old_link2_iface ne $new_link2_iface)
{ {
# Rename it # Delete the old interface
#print "Renaming ..... [$old_link2_iface] -> [$new_link2_iface]\n"; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0461", variables => { interface => $old_link2_nm_name }});
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ip}." link set ".$old_link2_iface." name ".$new_link2_iface}); my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $anvil->data->{path}{exe}{nmcli}." connection delete ".$old_link2_nm_name});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => {
output => $output,
return_code => $return_code,
}});
# Unllnk the old one, if it exists. sleep 1;
if (-e $old_link2_file) if (-e $old_link2_file)
{ {
#print "Deleting: .... [$old_link2_file]\n";
unlink $old_link2_file; unlink $old_link2_file;
} }
} }
# Drop the new link, too, in case it still has the old config else
#print "Downing: ..... [$new_link2_iface]\n"; {
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ifdown}." ".$new_link2_iface}); # Down the interface
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0462", variables => { interface => $old_link2_nm_name }});
# Start the bond. my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $anvil->data->{path}{exe}{nmcli}." connection down ".$old_link2_nm_name});
#print "Uping: ....... [$new_bond_iface]\n"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => {
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ifup}." ".$new_bond_iface}); output => $output,
return_code => $return_code,
# Reconnect and up link 1 }});
#print "Uping: ....... [$new_link1_iface]\n"; }
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ifup}." ".$new_link1_iface});
#print "Reconnecting: [$new_link1_iface]\n";
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ip}." link set ".$new_link1_iface." up"});
# Reconnect and up link 2 ### Write out the new configs
#print "Uping: ....... [$new_link2_iface]\n"; # Are we writing a bridge config?
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ifup}." ".$new_link2_iface}); if ($bridge)
#print "Reconnecting: [$new_link2_iface]\n"; {
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ip}." link set ".$new_link2_iface." up"}); $anvil->Storage->write_file({file => $bridge_file, body => $bridge_config, user => "root", group => "root", mode => "0644", overwrite => 1});
}
# Bond, Link 1 and Link 2
$anvil->Storage->write_file({file => $bond_file, body => $bond_config, user => "root", group => "root", mode => "0644", overwrite => 1});
$anvil->Storage->write_file({file => $new_link1_file, body => $link1_config, user => "root", group => "root", mode => "0644", overwrite => 1});
$anvil->Storage->write_file({file => $new_link2_file, body => $link2_config, user => "root", group => "root", mode => "0644", overwrite => 1});
# Connect the bond (in case it isn't already)r # If the NICs names have changed, rename them now.
#print "Connecting: .. [$new_bond_iface]\n"; if ((exists $anvil->data->{network}{mac_address}{$link1_mac}{iface}) &&
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ip}." link set ".$new_bond_iface." up"}); ($anvil->data->{network}{mac_address}{$link1_mac}{iface}) &&
($anvil->data->{network}{mac_address}{$link1_mac}{iface} ne $new_link1_iface))
{
rename_interface($anvil, $anvil->data->{network}{mac_address}{$link1_mac}{iface}, $new_link1_iface);
}
if ((exists $anvil->data->{network}{mac_address}{$link2_mac}{iface}) &&
($anvil->data->{network}{mac_address}{$link2_mac}{iface}) &&
($anvil->data->{network}{mac_address}{$link2_mac}{iface} ne $new_link2_iface))
{
rename_interface($anvil, $anvil->data->{network}{mac_address}{$link2_mac}{iface}, $new_link2_iface);
}
} }
elsif ((exists $anvil->data->{variables}{form}{config_step2}{$link1_key}{value}) && ($anvil->Validate->is_mac({mac => $anvil->data->{variables}{form}{config_step2}{$link1_key}{value}}))) elsif ((exists $anvil->data->{variables}{form}{config_step2}{$link1_key}{value}) && ($anvil->Validate->is_mac({mac => $anvil->data->{variables}{form}{config_step2}{$link1_key}{value}})))
{ {
@ -692,6 +772,10 @@ sub reconfigure_network
say_defroute => $say_defroute, 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 # Gather (or create) UUIDs
my $link1_uuid = get_uuid_from_interface_file($anvil, $old_link1_file); 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 }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { link1_uuid => $link1_uuid }});
@ -699,7 +783,7 @@ sub reconfigure_network
my $link1_config = "# $say_network - Link 1\n"; my $link1_config = "# $say_network - Link 1\n";
$link1_config .= "HWADDR=\"".uc($link1_mac)."\"\n"; $link1_config .= "HWADDR=\"".uc($link1_mac)."\"\n";
$link1_config .= "UUID=\"".$link1_uuid."\"\n"; $link1_config .= "UUID=\"".$link1_uuid."\"\n";
$link1_config .= "NAME=\"".$interface_prefix." ".$network_count." - Link 1\"\n"; $link1_config .= "NAME=\"".$new_link1_nm_name."\"\n";
$link1_config .= "DEVICE=\"".$new_link1_iface."\"\n"; $link1_config .= "DEVICE=\"".$new_link1_iface."\"\n";
$link1_config .= "TYPE=\"Ethernet\"\n"; $link1_config .= "TYPE=\"Ethernet\"\n";
$link1_config .= "BOOTPROTO=\"none\"\n"; $link1_config .= "BOOTPROTO=\"none\"\n";
@ -730,41 +814,62 @@ sub reconfigure_network
# Write out the link1 config file. # Write out the link1 config file.
$anvil->Storage->write_file({file => $new_link1_file, body => $link1_config, user => "root", group => "root", mode => "0644", overwrite => 1}); $anvil->Storage->write_file({file => $new_link1_file, body => $link1_config, user => "root", group => "root", mode => "0644", overwrite => 1});
if ($old_link1_iface) # If the name differs from old, delete the old interface.
if ((exists $anvil->data->{network}{mac_address}{$link1_mac}{iface}) &&
($anvil->data->{network}{mac_address}{$link1_mac}{iface}) &&
($anvil->data->{network}{mac_address}{$link1_mac}{iface} ne $new_link1_iface))
{ {
# Take down and rename the old link 1 interface # Delete the old interface
#print "Downing: ..... [$old_link1_iface]\n"; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "log_0461", variables => { interface => $old_link1_nm_name }});
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ifdown}." ".$old_link1_iface}); $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{nmcli}." connection delete ".$old_link1_nm_name});
#print "Disconnecting: [$old_link1_iface]\n";
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ip}." link set ".$old_link1_iface." down"});
}
if ($old_link1_iface ne $new_link1_iface)
{
# Rename it
#print "Renaming: .... [$old_link1_iface] -> [$new_link1_iface]\n";
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ip}." link set ".$old_link1_iface." name ".$new_link1_iface});
# Unllnk the old one, if it exists. rename_interface($anvil, $anvil->data->{network}{mac_address}{$link1_mac}{iface}, $new_link1_iface);
if (-e $old_link1_file) }
else
{ {
#print "Deleting: .... [$old_link1_file]\n"; # Down the interface
unlink $old_link1_file; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0462", variables => { interface => $old_link1_nm_name }});
$anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{nmcli}." connection down ".$old_link1_nm_name});
} }
} }
# Drop the new link, too, in case it still has the old config
#print "Downing: ..... [$new_link1_iface]\n";
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{ifdown}." ".$new_link1_iface});
}
else else
{ {
# Doesn't exist, skip. # Doesn't exist, skip.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "log_0149", variables => { network => $this_network }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "log_0149", variables => { network => $this_network }});
next; next;
} }
} }
} }
# Re-read the config
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0463"});
my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $anvil->data->{path}{exe}{nmcli}." connection reload"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => {
output => $output,
return_code => $return_code,
}});
# Wait for a DB connection. We'll wait up to 130 seconds (updelay is 120 seconds, plus a small buffer).
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, secure => 0, key => "log_0132"});
if (not $anvil->data->{sys}{database}{connections})
{
if (time > $wait_until)
{
# Failed to reconnect, exit.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, priority => "err", key => "error_0107"});
$anvil->nice_exit({code => 2});
}
# No databases, sleep and then try again.
sleep 2;
}
}
# We're half-way there. # We're half-way there.
$anvil->Job->update_progress({ $anvil->Job->update_progress({
progress => 50, progress => 50,
@ -773,7 +878,7 @@ sub reconfigure_network
# If any virtio bridges exist, remove it/them. # If any virtio bridges exist, remove it/them.
my $start = 0; my $start = 0;
my ($bridges, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." net-list"}); (my $bridges, $return_code) = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{virsh}." net-list"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridges => $bridges, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridges => $bridges, return_code => $return_code }});
foreach my $line (split/\n/, $bridges) foreach my $line (split/\n/, $bridges)
{ {
@ -808,13 +913,6 @@ sub reconfigure_network
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { undefine => $undefine, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { undefine => $undefine, return_code => $return_code }});
} }
### TODO: This isn't working... The route table won't set the IFN as the default route properly and
### the IFN links seem to drop out and not return when trying to fix it. For now, we'll do a
### closing reboot which seems to always comes up OK.
# Reload the network
#print "reloading nmcli\n";
#$anvil->System->call({shell_call => $anvil->data->{path}{exe}{nmcli}." connection reload"});
$anvil->Job->update_progress({ $anvil->Job->update_progress({
progress => 75, progress => 75,
job_uuid => $anvil->data->{job}{uuid}, job_uuid => $anvil->data->{job}{uuid},
@ -823,12 +921,46 @@ sub reconfigure_network
return(0); 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 ($output, $return_code) = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{ip}." link set ".$old_link_name." down"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => {
output => $output,
return_code => $return_code,
}});
# Rename
($output, $return_code) = $anvil->System->call({debug => 2, 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, secure => 0, list => {
output => $output,
return_code => $return_code,
}});
# Bring up the new interface
($output, $return_code) = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{ip}." link set ".$new_link_name." up"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, 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 # 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. # UUID was not found, a new UUID is generated and returned.
sub get_uuid_from_interface_file sub get_uuid_from_interface_file
{ {
my ($anvil, $file) = @_; my ($anvil, $file) = @_;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, key => "log_0131", variables => { function => "get_uuid_from_interface_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 }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { file => $file }});
my $uuid = ""; my $uuid = "";
@ -896,7 +1028,7 @@ sub pickup_job_details
if ($job_picked_up_by) if ($job_picked_up_by)
{ {
# The previous job is gone if we're still alive, we'll take this over. # The previous job is gone if we're still alive, we'll take this over.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, key => "log_0147", variables => { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, 'print' => 1, key => "log_0147", variables => {
pid => $job_picked_up_by, pid => $job_picked_up_by,
percent => $job_progress, percent => $job_progress,
}}); }});

@ -28,20 +28,6 @@ $anvil->Log->level({set => 2});
$anvil->Database->connect({debug => 3, check_if_configured => 1}); $anvil->Database->connect({debug => 3, check_if_configured => 1});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
my $ip = "10.255.4.1"; $anvil->Network->read_nmcli({debug => 2});
my $subnet = "255.255.0.0"; print Dumper $anvil->data->{nmcli}{'local'};
my $test1 = "10.255.255.254";
my $test2 = "10.200.255.254";
my $block = Net::Netmask->new($ip."/".$subnet);
foreach my $this_gw ($test1, $test2)
{
if ($block->match($this_gw))
{
print "The gateway: [".$this_gw."] DOES apply to: [".$ip."/".$subnet."]\n";
}
else
{
print "The gateway: [".$this_gw."] DOES NOT apply to: [".$ip."/".$subnet."]\n";
}
}

Loading…
Cancel
Save