#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use Text::Diff; use Anvil::Tools; 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 => [], man => $THIS_FILE}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); # We'll try to connect in case we're adding additional peers. $anvil->Database->connect({debug => 3}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"}); #print "DBs: [".$anvil->data->{sys}{database}{connections}."]\n"; $anvil->data->{network_manager}{want}{ifn1_link1}{mac_address} = "52:54:00:d3:19:cc"; $anvil->data->{network_manager}{want}{ifn1_link1}{device} = "enp1s0"; $anvil->data->{network_manager}{want}{ifn1_link1}{found} = 0; $anvil->data->{network_manager}{want}{ifn1_link2}{mac_address} = "52:54:00:fc:82:b0"; $anvil->data->{network_manager}{want}{ifn1_link2}{device} = "enp7s0"; $anvil->data->{network_manager}{want}{ifn1_link2}{found} = 0; $anvil->data->{network_manager}{want}{bcn1_link1}{mac_address} = "52:54:00:86:f5:1d"; $anvil->data->{network_manager}{want}{bcn1_link1}{device} = "enp8s0"; $anvil->data->{network_manager}{want}{bcn1_link1}{found} = 0; $anvil->data->{network_manager}{want}{bcn1_link2}{mac_address} = "52:54:00:16:c5:33"; $anvil->data->{network_manager}{want}{bcn1_link2}{device} = "enp9s0"; $anvil->data->{network_manager}{want}{bcn1_link2}{found} = 0; $anvil->data->{network_manager}{want}{sn1_link1}{mac_address} = "52:54:00:37:6f:22"; $anvil->data->{network_manager}{want}{sn1_link1}{device} = "enp10s0"; $anvil->data->{network_manager}{want}{sn1_link1}{found} = 0; $anvil->data->{network_manager}{want}{sn1_link2}{mac_address} = "52:54:00:2f:02:1b"; $anvil->data->{network_manager}{want}{sn1_link2}{device} = "enp11s0"; $anvil->data->{network_manager}{want}{sn1_link2}{found} = 0; $anvil->data->{sys}{reboot_needed} = 0; scan($anvil); reconfigure($anvil); $anvil->nice_exit({exit_code => 0}); ############################################################################################################# # Functions # ############################################################################################################# sub reconfigure { my ($anvil) = @_; my $reconfigure_count = keys %{$anvil->data->{network_manager}{reconfigure}}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { reconfigure_count => $reconfigure_count }}); if (not $reconfigure_count) { return(0); } foreach my $wanted_interface (sort {$a cmp $b} keys %{$anvil->data->{network_manager}{reconfigure}}) { my $uuid = $anvil->data->{network_manager}{reconfigure}{$wanted_interface}{from_uuid}; my $old_device = $anvil->data->{interface}{uuid}{$uuid}{device}; my $name = $anvil->data->{interface}{uuid}{$uuid}{'connection.id'}; my $mac_address = $anvil->data->{interface}{uuid}{$uuid}{mac_address}; my $type = $anvil->data->{interface}{uuid}{$uuid}{type}; print "Renaming old device/name: [".$old_device."/".$name."] with MAC: [".$mac_address."] to: [".$wanted_interface."] using UUID: [".$uuid."]\n"; # Read persistent-net and see if it needs to be updated. my $new_persistent_net = ""; my $old_persistent_net = ""; if (-e $anvil->data->{path}{configs}{'persistent-net'}) { $old_persistent_net = $anvil->Storage->read_file({debug => 2, file => $anvil->data->{path}{configs}{'persistent-net'}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_persistent_net => $old_persistent_net }}); } foreach my $line (split/\n/, $old_persistent_net) { # If this MAC or device name exists already, delete the line. if (($line =~ /"$mac_address"/) or ($line =~ /"$wanted_interface"/)) { next; } $new_persistent_net .= $line."\n"; } $new_persistent_net .= "SUBSYSTEM==\"net\",ACTION==\"add\",ATTR{address}==\"".$mac_address."\",ATTR{type}==\"".$type."\",NAME=\"".$wanted_interface."\"\n"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_persistent_net => $new_persistent_net }}); my $difference = diff \$old_persistent_net, \$new_persistent_net, { STYLE => 'Unified' }; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { difference => $difference }}); # Write the new file. if ($difference) { print "- Updating the udev file: [".$anvil->data->{path}{configs}{'persistent-net'}."]\n"; my $problem = $anvil->Storage->write_file({ file => $anvil->data->{path}{configs}{'persistent-net'}, body => $new_persistent_net, overwrite => 1, user => "admin", group => "admin", mode => "0644", }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); if ($problem) { print "[ Error ] - Failed to write the new: [".$anvil->data->{path}{configs}{'persistent-net'}."] file, aborting!\n"; $anvil->nice_exit({exit_code => 1}); } } # Update the connection.interface-name my $connection_interface_name = $anvil->data->{interface}{uuid}{$uuid}{'connection.interface-name'} ? $anvil->data->{interface}{uuid}{$uuid}{'connection.interface-name'} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { connection_interface_name => $connection_interface_name }}); if ($connection_interface_name) { print "- Removing the old 'connection.interface-name': [".$connection_interface_name."]\n"; my $shell_call = $anvil->data->{path}{exe}{nmcli}." connection modify ".$uuid." connection.interface-name \"\""; $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}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); $shell_call = $anvil->data->{path}{exe}{nmcli}." --get-values connection.interface-name connection show ".$uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); ($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); if ($output) { # This should have been blank print "[ Error ] - Failed to delete the 'connection.interface-name', got: [".$output."] and it should bhave been blank, aborting!\n"; $anvil->nice_exit({exit_code => 1}); } } # We'll log what it was, and change it anyway my $match_interface_name = $anvil->data->{interface}{uuid}{$uuid}{'match.interface-name'} ? $anvil->data->{interface}{uuid}{$uuid}{'match.interface-name'} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { match_interface_name => $match_interface_name }}); if (1) { print "- Matching the new interface name: [".$wanted_interface."] to the bios device name: [".$old_device."]\n"; my $shell_call = $anvil->data->{path}{exe}{nmcli}." connection modify ".$uuid." match.interface-name \"".$wanted_interface." ".$old_device."\""; $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}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); # Read it back $shell_call = $anvil->data->{path}{exe}{nmcli}." --get-values match.interface-name connection show ".$uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); ($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); if (($output ne $wanted_interface.",".$old_device) && ($output ne $old_device.",".$wanted_interface)) { # This should have been blank print "[ Error ] - Failed to create the 'match.interface-name' value. Expected: [".$wanted_interface.",".$old_device."], got: [".$output."], aborting!\n"; $anvil->nice_exit({exit_code => 1}); } # Set the connection.id to the old name. print "- Setting the connection.id to the bios device name: [".$old_device."]\n"; $shell_call = $anvil->data->{path}{exe}{nmcli}." connection modify ".$uuid." connection.id \"".$old_device."\""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); ($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); # Read it back $shell_call = $anvil->data->{path}{exe}{nmcli}." --get-values connection.id connection show ".$uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); ($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); } # Set the reboot flag. $anvil->data->{sys}{reboot_needed} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::reboot_needed" => $anvil->data->{sys}{reboot_needed} }}); } if ($anvil->data->{sys}{reboot_needed}) { print "Reboot needed.\n"; print "- Regenerating dracute initrd image, this can take a moment...\n"; my $shell_call = $anvil->data->{path}{exe}{dracut}." --force"; $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}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); print "- New initrd image created, rebooting in 60 seconds (press 'ctrl + c' to abort).\n"; my $timeout = 60; while($timeout) { if ($timeout % 10) { print "." } else { print $timeout; } sleep 1; $timeout--; } print "0\n"; } return(0); } sub scan { my ($anvil) = @_; # Get a list of interfaces. get_interfaces($anvil); return(0); } sub get_interfaces { my ($anvil) = @_; my $shell_call = $anvil->data->{path}{exe}{nmcli}." --get-values uuid,type,active,state connection show"; $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}); $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 ($line =~ /^(.*?):(.*?):(.*?):(.*?)$/) { my $uuid = $1; my $type = $2; my $active = $3; my $state = $4; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uuid => $uuid, type => $type, active => $active, 'state' => $state, }}); next if $type eq "loopback"; $anvil->data->{interface}{uuid}{$uuid}{type} = $type; $anvil->data->{interface}{uuid}{$uuid}{active} = lc($active) eq "yes" ? 1 : 0; $anvil->data->{interface}{uuid}{$uuid}{'state'} = lc($state); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::type" => $anvil->data->{interface}{uuid}{$uuid}{type}, "interface::uuid::${uuid}::active" => $anvil->data->{interface}{uuid}{$uuid}{active}, "interface::uuid::${uuid}::state" => $anvil->data->{interface}{uuid}{$uuid}{'state'}, }}); } } foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{interface}{uuid}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uuid => $uuid }}); # Collect all the rest of the data now. my $shell_call = $anvil->data->{path}{exe}{nmcli}." connection show ".$uuid; $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}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code, }}); foreach my $line (split/\n/, $output) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }}); if ($line =~ /^(.*?):\s+(.*)$/) { my $variable = $1; my $value = $2; $anvil->data->{interface}{uuid}{$uuid}{$variable} = $value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::${variable}" => $anvil->data->{interface}{uuid}{$uuid}{$variable}, }}); if ($variable =~ /IP(\d).ADDRESS\[(\d+)\]/) { my $ip_type = $1; my $sequence = $2; my $hash_key = "ipv".$ip_type; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_type => $ip_type, sequence => $sequence, hash_key => $hash_key, }}); if (($ip_type == 4) && ($value =~ /^(.*?)\/(.*)$/)) { my $ip_address = $1; my $subnet_mask = $2; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_address => $ip_address, subnet_mask => $subnet_mask, }}); $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{ip_address} = $1; $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{subnet_mask} = $2; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::${hash_key}::ip::${sequence}::ip_address" => $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{ip_address}, "interface::uuid::${uuid}::${hash_key}::ip::${sequence}::subnet_mask" => $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{subnet_mask}, }}); } else { $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{ip_address} = $value; $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{subnet_mask} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::${hash_key}::ip::${sequence}::ip_address" => $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{ip_address}, "interface::uuid::${uuid}::${hash_key}::ip::${sequence}::subnet_mask" => $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{subnet_mask}, }}); } # Make sure the DNS key exists. if (not exists $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{dns}) { $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{dns} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::${hash_key}::dns" => $anvil->data->{interface}{uuid}{$uuid}{$sequence}{dns}, }}); } if (not exists $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{gateway}) { $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{gateway} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::${hash_key}::gateway" => $anvil->data->{interface}{uuid}{$uuid}{$sequence}{gateway}, }}); } $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{gateway} = $value; } if ($variable =~ /IP(\d).ROUTE\[(\d+)\]/) { my $ip_type = $1; my $sequence = $2; my $hash_key = "ipv".$ip_type; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_type => $ip_type, sequence => $sequence, hash_key => $hash_key, }}); $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{route}{$sequence} = $value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::${hash_key}::route::${sequence}" => $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{route}{$sequence}, }}); } if ($variable =~ /IP(\d).DNS\[(\d+)\]/) { my $ip_type = $1; my $sequence = $2; my $hash_key = "ipv".$ip_type; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_type => $ip_type, sequence => $sequence, hash_key => $hash_key, }}); if ((exists $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{dns}) and ($anvil->data->{interface}{uuid}{$uuid}{$hash_key}{dns} ne "")) { $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{dns} .= ",".$value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::${hash_key}::dns" => $anvil->data->{interface}{uuid}{$uuid}{$sequence}{dns}, }}); } else { $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{dns} = $value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::${hash_key}::dns" => $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{dns}, }}); } } if ($variable =~ /IP(\d).GATEWAY/) { my $ip_type = $1; my $hash_key = "ipv".$ip_type; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_type => $ip_type, hash_key => $hash_key, }}); $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{gateway} = $value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::${hash_key}::gateway" => $anvil->data->{interface}{uuid}{$uuid}{$hash_key}{gateway}, }}); } } } } # Now loop through and look for the name that maps to what's shown in 'ip addr list'. This can be a bit tricky. foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{interface}{uuid}}) { my $connection_interface_name = $anvil->data->{interface}{uuid}{$uuid}{'connection.interface-name'} // ""; my $general_devices = $anvil->data->{interface}{uuid}{$uuid}{'GENERAL.DEVICES'} // ""; my $device = $connection_interface_name ne "--" ? $connection_interface_name : $general_devices; my $name = $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 's1:uuid' => $uuid, 's2:connection_interface_name' => $connection_interface_name, 's3:general_devices' => $general_devices, 's4:device' => $device, }}); if ($device) { $anvil->data->{interface}{device}{$device}{uuid} = $uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::device::${device}::uuid" => $anvil->data->{interface}{device}{$device}{uuid}, }}); ### Get some data from sysfs. $anvil->data->{interface}{uuid}{$uuid}{device} = $device; $anvil->data->{interface}{uuid}{$uuid}{mac_address} = ""; $anvil->data->{interface}{uuid}{$uuid}{type} = ""; $anvil->data->{interface}{uuid}{$uuid}{mtu} = 0; # The 'connection.timestamp' seems to be where the 'connected' (as in, have an IP) # comes from. $anvil->data->{interface}{uuid}{$uuid}{connected} = $anvil->data->{interface}{uuid}{$uuid}{'connection.timestamp'} ? $anvil->data->{interface}{uuid}{$uuid}{'connection.timestamp'} : 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::connected" => $anvil->data->{interface}{uuid}{$uuid}{connected}, }}); # MAC address my $mac_address_file = "/sys/class/net/".$device."/address"; my $type_file = "/sys/class/net/".$device."/type"; my $mtu_file = "/sys/class/net/".$device."/mtu"; if (-e $mac_address_file) { my $mac_address = $anvil->Storage->read_file({file => $mac_address_file}); $mac_address =~ s/\n$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }}); if (($mac_address) && ($mac_address ne "!!error!!")) { $anvil->data->{interface}{uuid}{$uuid}{mac_address} = $mac_address; $anvil->data->{interface}{mac_address}{$mac_address}{uuid} = $uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::mac_address" => $anvil->data->{interface}{uuid}{$uuid}{mac_address}, "interface::mac_address::${mac_address}::uuid" => $anvil->data->{interface}{mac_address}{$mac_address}{uuid}, }}); } } if (-e $type_file) { my $type = $anvil->Storage->read_file({file => $type_file}); $type =~ s/\n$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); if (($type) && ($type ne "!!error!!")) { $anvil->data->{interface}{uuid}{$uuid}{type} = $type; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::type" => $anvil->data->{interface}{uuid}{$uuid}{type}, }}); } } if (-e $mtu_file) { my $mtu = $anvil->Storage->read_file({file => $mtu_file}); $mtu =~ s/\n$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mtu => $mtu }}); if (($mtu) && ($mtu ne "!!error!!")) { $anvil->data->{interface}{uuid}{$uuid}{mtu} = $mtu; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interface::uuid::${uuid}::mtu" => $anvil->data->{interface}{uuid}{$uuid}{mtu}, }}); } } } } # Now lets confirm we got all the interfaces, including the down'ed ones. foreach my $device (sort {$a cmp $b} keys %{$anvil->data->{interface}{device}}) { my $uuid = $anvil->data->{interface}{device}{$device}{uuid}; my $name = $anvil->data->{interface}{uuid}{$uuid}{'connection.id'}; my $mac_address = $anvil->data->{interface}{uuid}{$uuid}{mac_address}; my $type = $anvil->data->{interface}{uuid}{$uuid}{type}; my $mtu_type = $anvil->data->{interface}{uuid}{$uuid}{'802-3-ethernet.mtu'}; my $mtu = $anvil->data->{interface}{uuid}{$uuid}{mtu}; my $active = $anvil->data->{interface}{uuid}{$uuid}{active}; my $state = $anvil->data->{interface}{uuid}{$uuid}{'state'}; my $connected = $anvil->data->{interface}{uuid}{$uuid}{connected}; my $ipv4_dns = $anvil->data->{interface}{uuid}{$uuid}{ipv4}{dns} // "--"; my $ipv4_gateway = $anvil->data->{interface}{uuid}{$uuid}{ipv4}{gateway} // "--"; my $ip_count = keys %{$anvil->data->{interface}{uuid}{$uuid}{ipv4}{ip}}; my $route_count = keys %{$anvil->data->{interface}{uuid}{$uuid}{ipv4}{route}}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s01:device" => $device, "s02:uuid" => $uuid, "s03:name" => $name, "s04:mac_address" => $mac_address, "s05:type" => $type, "s06:mtu_type" => $mtu_type, "s07:active" => $active, "s08:state" => $state, "s09:connected" => $connected, "s10:ipv4_dns" => $ipv4_dns, "s11:ipv4_gateway" => $ipv4_gateway, "s12:ip_count" => $ip_count, "s13:route_count" => $route_count, }}); #print "- Device: [".$device."], Name: [".$name."], MAC: [".$mac_address."], UUID: [".$uuid."]\n"; # $anvil->data->{network_manager}{want}{ifn1_link1}{mac_address} = "52:54:00:d3:19:cc"; # $anvil->data->{network_manager}{want}{ifn1_link1}{device} = "enp1s0"; # $anvil->data->{network_manager}{want}{ifn1_link1}{found} = 0; if (exists $anvil->data->{network_manager}{want}{$device}) { # We know this device. Does it match the expected MAC address? my $wanted_mac_address = $anvil->data->{network_manager}{want}{ifn1_link1}{mac_address}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { wanted_mac_address => $wanted_mac_address }}); if (lc($wanted_mac_address) eq lc($mac_address)) { #print " - Interface is configured as desired.\n"; } else { #print " - The MAC address doesn't match the desired MAC address!\n"; } } else { #print " - This interface isn't one of the matched ones. Check if this should be reconfigured.\n"; my $reconfigure_to = ""; foreach my $wanted_interface (sort {$a cmp $b} keys %{$anvil->data->{network_manager}{want}}) { my $wanted_device = $anvil->data->{network_manager}{want}{$wanted_interface}{device}; my $wanted_mac_address = $anvil->data->{network_manager}{want}{$wanted_interface}{mac_address}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { wanted_interface => $wanted_interface, wanted_device => $wanted_device, wanted_mac_address => $wanted_mac_address, }}); # If this device already exists, skip it. if (exists $anvil->data->{interface}{device}{$wanted_interface}) { next; } if ($mac_address eq $wanted_mac_address) { # MAC address always takes priority. $reconfigure_to = $wanted_interface; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { reconfigure_to => $reconfigure_to }}); next; } elsif ((not $reconfigure_to) && ($wanted_device eq $name)) { $reconfigure_to = $wanted_interface; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { reconfigure_to => $reconfigure_to }}); next; } } if ($reconfigure_to) { # Reconfigure! #print " - This should be: [".$reconfigure_to."]\n"; $anvil->data->{network_manager}{reconfigure}{$reconfigure_to}{from_uuid} = $uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "network_manager::reconfigure::${reconfigure_to}::from_uuid" => $anvil->data->{network_manager}{reconfigure}{$reconfigure_to}{from_uuid}, }}); } } #print "- Device: [".$device."], UUID: [".$uuid."], name: [".$name."], state: [".$active."], active?: [".$active."], state: [".$state."], connected: [".$connected."]\n"; #print " - MAC: [".$mac_address."], Type: [".$type."], MTU: [".$mtu."] MTU type: [".$mtu_type."], IPv4 DNS: [".$ipv4_dns."], Gateway: [".$ipv4_gateway."], IPs: [".$ip_count."], routes: [".$route_count."]\n"; if ($ip_count) { foreach my $sequence (sort {$a <=> $b} keys %{$anvil->data->{interface}{uuid}{$uuid}{ipv4}{ip}}) { my $ip_address = $anvil->data->{interface}{uuid}{$uuid}{ipv4}{ip}{$sequence}{ip_address}; my $subnet_mask = $anvil->data->{interface}{uuid}{$uuid}{ipv4}{ip}{$sequence}{subnet_mask}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:sequence" => $sequence, "s2:ip_address" => $ip_address, "s3:subnet_mask" => $subnet_mask, }}); #print " - ".$sequence.": IPv4 IP: [".$ip_address."], subnet mask: [".$subnet_mask."]\n"; } } if ($route_count) { foreach my $sequence (sort {$a <=> $b} keys %{$anvil->data->{interface}{uuid}{$uuid}{ipv4}{route}}) { my $route = $anvil->data->{interface}{uuid}{$uuid}{ipv4}{route}{$sequence}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:sequence" => $sequence, "s2:route" => $route, }}); #print " - ".$sequence.": Route: [".$route."]\n"; } } #print "--------\n"; } return(0); }