Fixed DB initialization bugs.

* More work done on the new network stack also.

Signed-off-by: digimer <mkelly@alteeve.ca>
main
digimer 12 months ago
parent 72325b9ed7
commit ec11335197
  1. 135
      Anvil/Tools/Database.pm
  2. 5
      Anvil/Tools/Get.pm
  3. 511
      Anvil/Tools/Network.pm
  4. 46
      Anvil/Tools/System.pm
  5. 454
      scancore-agents/scan-network/scan-network
  6. 15
      share/anvil.sql
  7. 3
      tools/anvil-configure-host
  8. 12
      tools/anvil-daemon
  9. 19
      tools/anvil-monitor-network
  10. 149
      tools/anvil-version-changes

@ -971,7 +971,7 @@ sub configure_pgsql
{
# Did we initialize?
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { initialized => $initialized }});
if ($initialized)
if (($initialized) or (not $running))
{
# Start the daemon.
my $return_code = $anvil->System->start_daemon({daemon => $anvil->data->{sys}{daemon}{postgresql}});
@ -4470,7 +4470,8 @@ AND
$query = "
SELECT
network_interface_uuid,
network_interface_name
network_interface_name,
network_interface_device
FROM
network_interfaces
WHERE
@ -4488,14 +4489,18 @@ AND
}});
foreach my $row (@{$results})
{
my $network_interface_uuid = $row->[0];
my $network_interface_name = $row->[1];
my $network_interface_uuid = $row->[0];
my $network_interface_name = $row->[1];
my $network_interface_device = $row->[2];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
network_interface_uuid => $network_interface_uuid,
network_interface_name => $network_interface_name,
network_interface_uuid => $network_interface_uuid,
network_interface_name => $network_interface_name,
network_interface_device => $network_interface_device,
}});
$anvil->data->{hosts}{host_uuid}{$host_uuid}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_name} = $network_interface_name;
# The interface_device is the name used by 'ip addr list', and the name is the 'enX'
# biosdevname device. So we only use the name now if there is no device.
$anvil->data->{hosts}{host_uuid}{$host_uuid}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_name} = $network_interface_device ? $network_interface_device : $network_interface_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"hosts::host_uuid::${host_uuid}::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_name" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_name},
}});
@ -6948,6 +6953,7 @@ sub initialize
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { sql => $sql }});
# In the off chance that the database user isn't 'admin', update the SQL file.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user => $user }});
if ($user ne "admin")
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0253", variables => { database_user => $user }});
@ -6968,11 +6974,12 @@ sub initialize
# Now that I am ready, disable autocommit, write and commit.
$anvil->Database->write({
debug => $debug,
uuid => $uuid,
query => $sql,
source => $THIS_FILE,
line => __LINE__,
debug => $debug,
uuid => $uuid,
query => $sql,
initializing => 1,
source => $THIS_FILE,
line => __LINE__,
});
$anvil->data->{sys}{db_initialized}{$uuid} = 1;
@ -11383,6 +11390,10 @@ If this interface is part of a bond, this UUID will be the C<< bonds >> -> C<< b
If this interface is connected to a bridge, this is the C<< bridges >> -> C<< bridge_uuid >> of that bridge.
=head3 network_interface_device (optional)
This is the device name (nmcli's GENERAL.IP-IFACE) of the device. This is the name shown in 'ip addr list'. When the interface is down, this will be blank. Use the MAC address ideally, or the 'connection.id' if needed, to find this interface.
=head3 network_interface_duplex (optional)
This can be set to C<< full >>, C<< half >> or C<< unknown >>, with the later being the default.
@ -11409,7 +11420,11 @@ This is the maximum transmit unit (MTU) that this interface supports, in bytes p
=head3 network_interface_name (required)
This is the current device name for this interface.
This is the nmcli 'connection.id' name (bios device name) for the current device of this interface. If the previously recorded MAC address is no longer found, but a new/unknown interface with this name is found, it is sane to configure the device with this name as the replacement 'network_interface_device'.
=head3 network_interface_nmcli_uuid (optional)
This is the network manager's UUID for this interface.
=head3 network_interface_operational (optional)
@ -11439,6 +11454,7 @@ sub insert_or_update_network_interfaces
my $link_only = defined $parameter->{link_only} ? $parameter->{link_only} : 0;
my $network_interface_bond_uuid = $parameter->{network_interface_bond_uuid} ? $parameter->{network_interface_bond_uuid} : 'NULL';
my $network_interface_bridge_uuid = $parameter->{network_interface_bridge_uuid} ? $parameter->{network_interface_bridge_uuid} : 'NULL';
my $network_interface_device = defined $parameter->{network_interface_device} ? $parameter->{network_interface_device} : "";
my $network_interface_duplex = defined $parameter->{network_interface_duplex} ? $parameter->{network_interface_duplex} : "unknown";
my $network_interface_host_uuid = defined $parameter->{network_interface_host_uuid} ? $parameter->{network_interface_host_uuid} : $anvil->Get->host_uuid;
my $network_interface_link_state = defined $parameter->{network_interface_link_state} ? $parameter->{network_interface_link_state} : "unknown";
@ -11447,6 +11463,7 @@ sub insert_or_update_network_interfaces
my $network_interface_medium = defined $parameter->{network_interface_medium} ? $parameter->{network_interface_medium} : "";
my $network_interface_mtu = defined $parameter->{network_interface_mtu} ? $parameter->{network_interface_mtu} : 0;
my $network_interface_name = defined $parameter->{network_interface_name} ? $parameter->{network_interface_name} : "";
my $network_interface_nmcli_uuid = defined $parameter->{network_interface_nmcli_uuid} ? $parameter->{network_interface_nmcli_uuid} : "";
my $network_interface_speed = defined $parameter->{network_interface_speed} ? $parameter->{network_interface_speed} : 0;
my $network_interface_uuid = defined $parameter->{network_interface_uuid} ? $parameter->{network_interface_uuid} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
@ -11457,6 +11474,7 @@ sub insert_or_update_network_interfaces
link_only => $link_only,
network_interface_bond_uuid => $network_interface_bond_uuid,
network_interface_bridge_uuid => $network_interface_bridge_uuid,
network_interface_device => $network_interface_device,
network_interface_duplex => $network_interface_duplex,
network_interface_host_uuid => $network_interface_host_uuid,
network_interface_link_state => $network_interface_link_state,
@ -11465,6 +11483,7 @@ sub insert_or_update_network_interfaces
network_interface_medium => $network_interface_medium,
network_interface_mtu => $network_interface_mtu,
network_interface_name => $network_interface_name,
network_interface_nmcli_uuid => $network_interface_nmcli_uuid,
network_interface_speed => $network_interface_speed,
network_interface_uuid => $network_interface_uuid,
}});
@ -11523,6 +11542,7 @@ WHERE ";
network_interface_mac_address = ".$anvil->Database->quote($network_interface_mac_address)."
AND ";
}
### TODO: We may need to switch this to 'device' if the name or MAC address isn't found
$query .= "
network_interface_name = ".$anvil->Database->quote($network_interface_name)."
AND
@ -11604,8 +11624,10 @@ WHERE
my $query = "
SELECT
network_interface_host_uuid,
network_interface_nmcli_uuid,
network_interface_mac_address,
network_interface_name,
network_interface_device,
network_interface_speed,
network_interface_mtu,
network_interface_link_state,
@ -11636,20 +11658,24 @@ WHERE
foreach my $row (@{$results})
{
my $old_network_interface_host_uuid = $row->[0];
my $old_network_interface_nmcli_uuid = defined $row->[1] ? $row->[1] : 'NULL';
my $old_network_interface_mac_address = $row->[1];
my $old_network_interface_name = $row->[2];
my $old_network_interface_speed = $row->[3];
my $old_network_interface_mtu = $row->[4];
my $old_network_interface_link_state = $row->[5];
my $old_network_interface_operational = $row->[6];
my $old_network_interface_duplex = $row->[7];
my $old_network_interface_medium = $row->[8];
my $old_network_interface_bond_uuid = defined $row->[9] ? $row->[9] : 'NULL';
my $old_network_interface_bridge_uuid = defined $row->[10] ? $row->[10] : 'NULL';
my $old_network_interface_device = $row->[3];
my $old_network_interface_speed = $row->[4];
my $old_network_interface_mtu = $row->[5];
my $old_network_interface_link_state = $row->[6];
my $old_network_interface_operational = $row->[7];
my $old_network_interface_duplex = $row->[8];
my $old_network_interface_medium = $row->[9];
my $old_network_interface_bond_uuid = defined $row->[10] ? $row->[10] : 'NULL';
my $old_network_interface_bridge_uuid = defined $row->[11] ? $row->[11] : 'NULL';
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
old_network_interface_host_uuid => $old_network_interface_host_uuid,
old_network_interface_nmcli_uuid => $old_network_interface_nmcli_uuid,
old_network_interface_mac_address => $old_network_interface_mac_address,
old_network_interface_name => $old_network_interface_name,
old_network_interface_device => $old_network_interface_device,
old_network_interface_speed => $old_network_interface_speed,
old_network_interface_mtu => $old_network_interface_mtu,
old_network_interface_link_state => $old_network_interface_link_state,
@ -11663,7 +11689,9 @@ WHERE
# If 'link_only' is set, we're only checking/updating a subset of values.
if ($link_only)
{
if (($network_interface_name ne $old_network_interface_name) or
if (($network_interface_nmcli_uuid ne $old_network_interface_nmcli_uuid) or
($network_interface_name ne $old_network_interface_name) or
($network_interface_device ne $old_network_interface_device) or
($network_interface_link_state ne $old_network_interface_link_state) or
($network_interface_operational ne $old_network_interface_operational) or
($network_interface_mac_address ne $old_network_interface_mac_address) or
@ -11675,7 +11703,9 @@ UPDATE
network_interfaces
SET
network_interface_host_uuid = ".$anvil->Database->quote($network_interface_host_uuid).",
network_interface_nmcli_uuid = ".$anvil->Database->quote($network_interface_nmcli_uuid).",
network_interface_name = ".$anvil->Database->quote($network_interface_name).",
network_interface_device = ".$anvil->Database->quote($network_interface_device).",
network_interface_link_state = ".$anvil->Database->quote($network_interface_link_state).",
network_interface_operational = ".$anvil->Database->quote($network_interface_operational).",
network_interface_mac_address = ".$anvil->Database->quote($network_interface_mac_address).",
@ -11695,7 +11725,9 @@ WHERE
# not passed in, we want to not compare it.
if (($network_interface_bond_uuid ne $old_network_interface_bond_uuid) or
($network_interface_bridge_uuid ne $old_network_interface_bridge_uuid) or
($network_interface_nmcli_uuid ne $old_network_interface_nmcli_uuid) or
($network_interface_name ne $old_network_interface_name) or
($network_interface_device ne $old_network_interface_device) or
($network_interface_duplex ne $old_network_interface_duplex) or
($network_interface_link_state ne $old_network_interface_link_state) or
($network_interface_operational ne $old_network_interface_operational) or
@ -11711,9 +11743,11 @@ UPDATE
network_interfaces
SET
network_interface_host_uuid = ".$anvil->Database->quote($network_interface_host_uuid).",
network_interface_nmcli_uuid = ".$anvil->Database->quote($network_interface_nmcli_uuid).",
network_interface_bond_uuid = ".$anvil->Database->quote($network_interface_bond_uuid).",
network_interface_bridge_uuid = ".$anvil->Database->quote($network_interface_bridge_uuid).",
network_interface_name = ".$anvil->Database->quote($network_interface_name).",
network_interface_device = ".$anvil->Database->quote($network_interface_device).",
network_interface_duplex = ".$anvil->Database->quote($network_interface_duplex).",
network_interface_link_state = ".$anvil->Database->quote($network_interface_link_state).",
network_interface_operational = ".$anvil->Database->quote($network_interface_operational).",
@ -11742,9 +11776,11 @@ INSERT INTO
network_interfaces
(
network_interface_uuid,
network_interface_nmcli_uuid,
network_interface_bond_uuid,
network_interface_bridge_uuid,
network_interface_name,
network_interface_device,
network_interface_duplex,
network_interface_host_uuid,
network_interface_link_state,
@ -11756,9 +11792,11 @@ INSERT INTO
modified_date
) VALUES (
".$anvil->Database->quote($network_interface_uuid).",
".$anvil->Database->quote($network_interface_nmcli_uuid).",
".$anvil->Database->quote($network_interface_bond_uuid).",
".$anvil->Database->quote($network_interface_bridge_uuid).",
".$anvil->Database->quote($network_interface_name).",
".$anvil->Database->quote($network_interface_device).",
".$anvil->Database->quote($network_interface_duplex).",
".$anvil->Database->quote($network_interface_host_uuid).",
".$anvil->Database->quote($network_interface_link_state).",
@ -17844,7 +17882,7 @@ sub resync_databases
$query .= " ORDER BY utc_modified_date DESC;";
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0074", variables => {
uuid => $anvil->Database->get_host_from_uuid({short => 1, host_uuid => $uuid}),
uuid => $anvil->Database->get_host_from_uuid({debug => $debug, short => 1, host_uuid => $uuid}),
query => $query,
}});
@ -18090,7 +18128,7 @@ sub resync_databases
# Already in, redirect to the history schema.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "warning_0029", variables => {
table => $table,
host_name => $anvil->Database->get_host_from_uuid({short => 1, host_uuid => $uuid}),
host_name => $anvil->Database->get_host_from_uuid({debug => $debug, short => 1, host_uuid => $uuid}),
host_uuid => $uuid,
column => $uuid_column,
uuid => $row_uuid,
@ -18698,6 +18736,10 @@ This records data to one or all of the databases. If a UUID is passed, the query
Parameters;
=head3 initializing (optional, default 0)
When set to C<< 1 >>, this tells the method that the database is being initialized, so some checks and lookups are disabled.
=head3 line (optional)
If you want errors to be traced back to the query called, this can be set (usually to C<< __LINE__ >>) along with the C<< source >> parameter. In such a case, if there is an error in this method, the caller's file and line are displayed in the logs.
@ -18737,20 +18779,23 @@ sub write
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->write()" }});
my $line = $parameter->{line} ? $parameter->{line} : __LINE__;
my $query = $parameter->{query} ? $parameter->{query} : "";
my $reenter = $parameter->{reenter} ? $parameter->{reenter} : "";
my $secure = $parameter->{secure} ? $parameter->{secure} : 0;
my $source = $parameter->{source} ? $parameter->{source} : $THIS_FILE;
my $transaction = $parameter->{transaction} ? $parameter->{transaction} : 0;
my $uuid = $parameter->{uuid} ? $parameter->{uuid} : "";
my $initializing = $parameter->{initializing} ? $parameter->{initializing} : 0;
my $line = $parameter->{line} ? $parameter->{line} : __LINE__;
my $query = $parameter->{query} ? $parameter->{query} : "";
my $reenter = $parameter->{reenter} ? $parameter->{reenter} : "";
my $secure = $parameter->{secure} ? $parameter->{secure} : 0;
my $source = $parameter->{source} ? $parameter->{source} : $THIS_FILE;
my $transaction = $parameter->{transaction} ? $parameter->{transaction} : 0;
my $uuid = $parameter->{uuid} ? $parameter->{uuid} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
uuid => $uuid,
line => $line,
query => (not $secure) ? $query : $anvil->Log->is_secure($query),
secure => $secure,
source => $source,
reenter => $reenter,
initializing => $initializing,
line => $line,
query => (not $secure) ? $query : $anvil->Log->is_secure($query),
reenter => $reenter,
secure => $secure,
source => $source,
transaction => $transaction,
uuid => $uuid,
}});
if ($uuid)
@ -18784,7 +18829,7 @@ sub write
}
# If I am still alive check if any locks need to be renewed.
$anvil->Database->check_lock_age({debug => $debug});
$anvil->Database->check_lock_age({debug => $debug}) if not $initializing;
# This array will hold either just the passed DB ID or all of them, if no ID was specified.
my @db_uuids;
@ -18841,6 +18886,10 @@ sub write
{
push @{$query_set}, $this_query;
$i++;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
this_query => $this_query,
i => $i,
}});
if ($i > $next)
{
@ -18871,6 +18920,7 @@ sub write
foreach my $this_query (@{$query})
{
push @{$query_set}, $this_query;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_query => $this_query }});
}
}
}
@ -18886,8 +18936,11 @@ sub write
foreach my $uuid (@db_uuids)
{
# Test access to the DB before we do the actual query
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { uuid => $uuid }});
$anvil->Database->_test_access({debug => $debug, uuid => $uuid});
if (not $initializing)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { uuid => $uuid }});
$anvil->Database->_test_access({debug => $debug, uuid => $uuid});
}
# Do the actual query(ies)
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
@ -18905,7 +18958,7 @@ sub write
if (($anvil->data->{sys}{database}{log_transactions}) or ($debug <= $anvil->Log->level))
{
$anvil->Log->entry({source => $source, line => $line, secure => $secure, level => 0, key => "log_0083", variables => {
uuid => $anvil->Database->get_host_from_uuid({short => 1, host_uuid => $uuid}),
uuid => $initializing ? $uuid : $anvil->Database->get_host_from_uuid({debug => 1, short => 1, host_uuid => $uuid}),
query => $query,
}});
}

@ -2165,6 +2165,11 @@ sub os_type
$os_type = "centos-stream".$1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { os_type => $os_type }});
}
elsif ($release =~ /AlmaLinux .*? (\d+)/)
{
$os_type = "alma".$1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { os_type => $os_type }});
}
elsif ($release =~ /CentOS .*? (\d+)\./)
{
# CentOS, with the major version number appended

@ -17,6 +17,7 @@ my $THIS_FILE = "Network.pm";
# check_firewall
# check_network
# check_internet
# collect_data
# download
# find_access
# find_matches
@ -382,6 +383,7 @@ sub check_firewall
}
### TODO: Phase this out when EL8 / ifcfg-X file support is ended.
=head2 check_network
B<< NOTE >>: This method is not yet implemented.
@ -472,7 +474,7 @@ sub check_network
my $is_bond = "";
# Read in the file.
my $file_body = $anvil->Storage->read_file({debug => ($debug+1), file => $full_path});
my $file_body = $anvil->Storage->read_file({debug => $debug, file => $full_path});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_body => $file_body }});
foreach my $line (split/\n/, $file_body)
@ -572,7 +574,7 @@ sub check_network
if (-e $carrier_file)
{
my $carrier = $anvil->Storage->read_file({debug => ($debug+1), file => $carrier_file});
my $carrier = $anvil->Storage->read_file({debug => $debug, file => $carrier_file});
chomp $carrier;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { carrier => $carrier }});
@ -587,7 +589,7 @@ sub check_network
if (-e $operstate_file)
{
my $operstate = $anvil->Storage->read_file({debug => ($debug+1), file => $operstate_file});
my $operstate = $anvil->Storage->read_file({debug => $debug, file => $operstate_file});
chomp $operstate;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { operstate => $operstate }});
@ -904,6 +906,503 @@ sub check_internet
return($access);
}
### NOTE: This is the new way of collecting data from nmcli, it is the method to use going forward.
=head2 collect_data
This method uses Network Manager, sysfs and procfs to collect data about the current state of the network.
Stored data:
* nmcli::uuid::<uuid>::device = 'connection.interface-name', or 'GENERAL.DEVICES'. See note below
* nmcli::uuid::<uuid>::type = interface, bond, bridge, etc
* nmcli::uuid::<uuid>::active = 1,0
* nmcli::uuid::<uuid>::state = activated,activating,etc
* nmcli::uuid::<uuid>::<variable> = all 'variable: value' pairs returned by 'nmcli connection show <uuid>'
* nmcli::uuid::<uuid>::mac_address = MAC address (in lower case)
* nmcli::uuid::<uuid>::connected = 0 is down, unix timestamp (seconds since epoch) of when it connected if up.
* nmcli::uuid::<uuid>::mtu = This is the MTU (maximum transimssion unit in bytes) of the interface.
To make it easier to map a device by name or MAC address to a UUID, this lookup hash is provided. Note that 'device' is 'connection.interface-name' when available, falling back to 'GENERAL.DEVICES' otherwise.
B<< NOTE >>: An inactive interface will not report the 'connection.interface-name', and the bios device name will be returned (which is what is stored in 'GENERAL.DEVICES'. If you're trying to find a device, and the expected name doesn't exist, look up the device by MAC address. If that's not found, then the old GENERAL.DEVICES name can help you identify a replaced interface.
* nmcli::device::<device>::uuid = interface name (or device name)
* nmcli::mac_address::<mac_address>::uuid = MAC address (lower case)
Given that a single interface can have multiple IP addresses and routes, the IPs on a given interface are stored using a sequence number <1, 2, 3 ... n>. To make it easier to find what device has an IP, the IPs are stored with a quick access hash.
* nmcli::ipv4::<ip_address>::on_uuid = interface UUID
* nmcli::ipv4::<ip_address>::sequence = sequence number
* nmcli::uuid::<uuid>::ipv{4,6}::ip::<sequence>::ip_address = IP address
* nmcli::uuid::<uuid>::ipv{4,6}::ip::<sequence>::subnet_mask = subnet mask (CIDR notation)
* nmcli::uuid::<uuid>::ipv{4,6}::dns = comma-separated list of DNS IP addresses
* nmcli::uuid::<uuid>::ipv{4,6}::gateway = comma-separated list of DNS IP addresses
* nmcli::uuid::<uuid>::ipv{4,6}::route::<sequence> = Route info (ie: 'dst = 0.0.0.0/0, nh = 192.168.255.254, mt = 428', or 'dst = 192.168.0.0/16, nh = 0.0.0.0, mt = 428'.)
Bond data is stored in these hashes;
* nmcli::bond::<bond_device>::uuid = The UUID on the bond
* nmcli::bond::<bond_device>::carrier = 1,0 - indicates if the bond has a connection or not.
* nmcli::bond::<bond_device>::operstate = 1,0 - indicates if the bond is operational or not.
* nmcli::bond::<bond_device>::up = 1,0 - indicates if the bond up up or not.
* nmcli::bond::<bond_device>::interface::<interface>::up = 1,0 - indicates if the child interface is up or not.
Bridge data is simple, but also made easy to find. The only real data is the hash references for the interfaces connected to the bridge.
* nmcli::bridge::<device>::uuid = The UUID of the bridge
* nmcli::bridge::<device>::interface::<interface>::status = This is the link data for the connected interface (ie: 'BROADCAST,MULTICAST,MASTER,UP,LOWER_UP').
To make it easier to find interfaces, the following look up hash is available.
* nmcli::interface::<device>::uuid = The UUID of the interface
* nmcli::mac_address::<mac_address>::uuid = $anvil->data->{nmcli}{mac_address}{$mac_address}{uuid},
This method takes no parameters
=cut
sub collect_data
{
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->check_internet()" }});
# Use nmcli to collect the data.
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";
if ($type eq "802-3-ethernet")
{
$type = "interface";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }});
}
$anvil->data->{nmcli}{uuid}{$uuid}{type} = $type;
$anvil->data->{nmcli}{uuid}{$uuid}{active} = lc($active) eq "yes" ? 1 : 0;
$anvil->data->{nmcli}{uuid}{$uuid}{'state'} = lc($state);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::type" => $anvil->data->{nmcli}{uuid}{$uuid}{type},
"nmcli::uuid::${uuid}::active" => $anvil->data->{nmcli}{uuid}{$uuid}{active},
"nmcli::uuid::${uuid}::state" => $anvil->data->{nmcli}{uuid}{$uuid}{'state'},
}});
}
}
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{nmcli}{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 => 2, list => { line => $line }});
if ($line =~ /^(.*?):\s+(.*)$/)
{
my $variable = $1;
my $value = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:variable' => $variable,
's2:value' => $value,
}});
$anvil->data->{nmcli}{uuid}{$uuid}{$variable} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::${variable}" => $anvil->data->{nmcli}{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->{nmcli}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{ip_address} = $1;
$anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{subnet_mask} = $2;
$anvil->data->{nmcli}{ipv4}{$ip_address}{on_uuid} = $uuid;
$anvil->data->{nmcli}{ipv4}{$ip_address}{sequence} = $sequence;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::${hash_key}::ip::${sequence}::ip_address" => $anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{ip_address},
"nmcli::uuid::${uuid}::${hash_key}::ip::${sequence}::subnet_mask" => $anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{subnet_mask},
"nmcli::ipv4::${ip_address}::on_uuid" => $anvil->data->{nmcli}{ipv4}{$ip_address}{on_uuid},
"nmcli::ipv4::${ip_address}::sequence" => $anvil->data->{nmcli}{ipv4}{$ip_address}{sequence},
}});
}
else
{
$anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{ip_address} = $value;
$anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{subnet_mask} = "";
$anvil->data->{nmcli}{ipv4}{$value}{on_uuid} = $value;
$anvil->data->{nmcli}{ipv4}{$value}{sequence} = $sequence;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::${hash_key}::ip::${sequence}::ip_address" => $anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{ip_address},
"nmcli::uuid::${uuid}::${hash_key}::ip::${sequence}::subnet_mask" => $anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{ip}{$sequence}{subnet_mask},
"nmcli::ipv4::${value}::on_uuid" => $anvil->data->{nmcli}{ipv4}{$value}{on_uuid},
"nmcli::ipv4::${value}::sequence" => $anvil->data->{nmcli}{ipv4}{$value}{sequence},
}});
}
# Make sure the DNS key exists.
if (not exists $anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{dns})
{
$anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{dns} = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::${hash_key}::dns" => $anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{dns},
}});
}
if (not exists $anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{gateway})
{
$anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{gateway} = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::${hash_key}::gateway" => $anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{gateway},
}});
}
$anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{gateway} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::${hash_key}::gateway" => $anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{gateway},
}});
}
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->{nmcli}{uuid}{$uuid}{$hash_key}{route}{$sequence} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::${hash_key}::route::${sequence}" => $anvil->data->{nmcli}{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->{nmcli}{uuid}{$uuid}{$hash_key}{dns}) and ($anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{dns} ne ""))
{
$anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{dns} .= ",".$value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::${hash_key}::dns" => $anvil->data->{nmcli}{uuid}{$uuid}{$sequence}{dns},
}});
}
else
{
$anvil->data->{nmcli}{uuid}{$uuid}{$hash_key}{dns} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::${hash_key}::dns" => $anvil->data->{nmcli}{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->{nmcli}{uuid}{$uuid}{$hash_key}{gateway} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::${hash_key}::gateway" => $anvil->data->{nmcli}{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->{nmcli}{uuid}})
{
my $connection_interface_name = $anvil->data->{nmcli}{uuid}{$uuid}{'connection.interface-name'} // "";
my $general_devices = $anvil->data->{nmcli}{uuid}{$uuid}{'GENERAL.DEVICES'} // "";
my $device_type = $anvil->data->{nmcli}{uuid}{$uuid}{'connection.type'} // "";
my $device = $connection_interface_name ne "--" ? $connection_interface_name : $general_devices;
$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_type' => $device_type,
's5:device' => $device,
}});
if ($device)
{
$anvil->data->{nmcli}{device}{$device}{uuid} = $uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::device::${device}::uuid" => $anvil->data->{nmcli}{device}{$device}{uuid},
}});
### Get some data from sysfs.
$anvil->data->{nmcli}{uuid}{$uuid}{device} = $device;
$anvil->data->{nmcli}{uuid}{$uuid}{mac_address} = "";
$anvil->data->{nmcli}{uuid}{$uuid}{type} = "";
$anvil->data->{nmcli}{uuid}{$uuid}{mtu} = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::device" => $anvil->data->{nmcli}{uuid}{$uuid}{device},
}});
# The 'connection.timestamp' seems to be where the 'connected' (as in, have an IP)
# comes from.
$anvil->data->{nmcli}{uuid}{$uuid}{connected} = $anvil->data->{nmcli}{uuid}{$uuid}{'connection.timestamp'} ? $anvil->data->{nmcli}{uuid}{$uuid}{'connection.timestamp'} : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::connected" => $anvil->data->{nmcli}{uuid}{$uuid}{connected},
}});
if ($device_type eq "bond")
{
$anvil->data->{nmcli}{bond}{$device}{uuid} = $uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::bond::${device}::uuid" => $anvil->data->{nmcli}{bond}{$device}{uuid},
}});
# Read the interface's carrier
my $carrier_file = "/sys/class/net/".$device."/carrier";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { carrier_file => $carrier_file }});
if (-e $carrier_file)
{
my $carrier = $anvil->Storage->read_file({debug => $debug, file => $carrier_file});
chomp $carrier;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { carrier => $carrier }});
$anvil->data->{nmcli}{bond}{$device}{carrier} = $carrier;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"nmcli::bond::${device}::carrier" => $anvil->data->{nmcli}{bond}{$device}{carrier},
}});
}
my $operstate_file = "/sys/class/net/".$device."/operstate";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { operstate_file => $operstate_file }});
if (-e $operstate_file)
{
my $operstate = $anvil->Storage->read_file({debug => $debug, file => $operstate_file});
chomp $operstate;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { operstate => $operstate }});
$anvil->data->{nmcli}{bond}{$device}{up} = $operstate eq "up" ? 1 : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"nmcli::bond::${device}::operstate" => $anvil->data->{nmcli}{bond}{$device}{operstate},
}});
}
# Read in the /proc file.
my $proc_file = "/proc/net/bonding/".$device;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { proc_file => $proc_file }});
my $in_link = "";
my $file_body = $anvil->Storage->read_file({debug => $debug, file => $proc_file});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_body => $file_body }});
foreach my $line (split/\n/, $file_body)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }});
if ($line =~ /Slave Interface: (.*)$/)
{
$in_link = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { in_link => $in_link }});
next;
}
if (not $line)
{
$in_link = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { in_link => $in_link }});
next;
}
if ($in_link)
{
if ($line =~ /MII Status: (.*)$/)
{
my $status = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { status => $status }});
if ($status eq "up")
{
$anvil->data->{nmcli}{bond}{$device}{interface}{$in_link}{up} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"nmcli::bond::${device}::interface::${in_link}::up" => $anvil->data->{nmcli}{bond}{$device}{interface}{$in_link}{up},
}});
}
else
{
$anvil->data->{nmcli}{bond}{$device}{interface}{$in_link}{up} = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"nmcli::bond::${device}::interface::${in_link}::up" => $anvil->data->{nmcli}{bond}{$device}{interface}{$in_link}{up},
}});
}
next;
}
}
else
{
if ($line =~ /MII Status: (.*)$/)
{
my $status = $1;
$anvil->data->{nmcli}{bond}{$device}{up} = $status eq "up" ? 1 : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
status => $status,
"nmcli::bond::${device}::up" => $anvil->data->{nmcli}{bond}{$device}{up},
}});
next;
}
}
}
}
elsif ($device_type eq "bridge")
{
$anvil->data->{nmcli}{bridge}{$device}{uuid} = $uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::bridge::${device}::uuid" => $anvil->data->{nmcli}{bridge}{$device}{uuid},
}});
# See what interfaces are connected to the bridge.
my $shell_call = $anvil->data->{path}{exe}{ip}." link show master ".$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,
}});
foreach my $line (split/\n/, $output)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
if ($line =~ /^\d+: (.*?): <(.*?)>/)
{
my $interface = $1;
my $status = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
interface => $interface,
status => $status,
}});
$anvil->data->{nmcli}{bridge}{$device}{interface}{$interface}{status} = $status;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::bridge::${device}::interface::${interface}::status" => $anvil->data->{nmcli}{bridge}{$device}{interface}{$interface}{status},
}});
}
}
}
elsif (($device_type eq "802-3-ethernet") or ($device_type eq "interface"))
{
$anvil->data->{nmcli}{interface}{$device}{uuid} = $uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::interface::${device}::uuid" => $anvil->data->{nmcli}{interface}{$device}{uuid},
}});
# 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->{nmcli}{uuid}{$uuid}{mac_address} = $mac_address;
$anvil->data->{nmcli}{mac_address}{$mac_address}{uuid} = $uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::mac_address" => $anvil->data->{nmcli}{uuid}{$uuid}{mac_address},
"nmcli::mac_address::${mac_address}::uuid" => $anvil->data->{nmcli}{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->{nmcli}{uuid}{$uuid}{type} = $type;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::type" => $anvil->data->{nmcli}{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->{nmcli}{uuid}{$uuid}{mtu} = $mtu;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::uuid::${uuid}::mtu" => $anvil->data->{nmcli}{uuid}{$uuid}{mtu},
}});
}
}
}
}
}
return(0);
}
=head2 download
This downloads a file from a network target and saves it to a local file. This must be called on a local system so that the download progress can be reported.
@ -3922,6 +4421,8 @@ sub ping
return($pinged, $average_ping_time);
}
### TODO: Phase this out when EL8 / ifcfg-X file support is ended.
=head2 read_nmcli
This method reads and parses the C<< nmcli >> data. The data is stored as;
@ -4060,7 +4561,7 @@ sub read_nmcli
# Read the file, see if we can find it there.
if (-e $filename)
{
my $file_body = $anvil->Storage->read_file({debug => ($debug+1), file => $filename});
my $file_body = $anvil->Storage->read_file({debug => $debug, file => $filename});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_body => $file_body }});
foreach my $line (split/\n/, $file_body)
@ -4326,7 +4827,7 @@ sub _get_drbd_ports
$full_path =~ s/\/\//\//g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { full_path => $full_path }});
my $file_body = $anvil->Storage->read_file({debug => ($debug+1), file => $full_path});
my $file_body = $anvil->Storage->read_file({debug => $debug, file => $full_path});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_body => $file_body }});
foreach my $line (split/\n/, $file_body)

@ -26,6 +26,7 @@ my $THIS_FILE = "System.pm";
# check_if_configured
# check_ssh_keys
# check_memory
# check_network_type
# check_storage
# collect_ipmi_data
# configure_ipmi
@ -1279,6 +1280,51 @@ sub check_ssh_keys
}
=head2 check_network_type
This method checks to see if this host is using network manager to configure the network, versus the older C<< ifcfg-X >> based config. It does this by looking for any C<< ifcfg-X >> files in C<< /etc/sysconfig/network-scripts >>.
If any 'ifcfg-X' files are found, C<< ifcfg >> is returned. Otherwise, C<< nm >> is returned.
This method takes no parameters.
=cut
sub check_network_type
{
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 => "System->check_storage()" }});
# Open the 'ifcfg' directory, if it exists, and see if there are any 'ifcfg-X' files.
my $type = "nm";
my $directory = $anvil->data->{path}{directories}{ifcfg};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { directory => $directory }});
if (-e $directory)
{
local(*DIRECTORY);
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0018", variables => { directory => $directory }});
opendir(DIRECTORY, $directory);
while(my $file = readdir(DIRECTORY))
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file => $file }});
if ($file =~ /^ifcfg-(.*)$/)
{
$type = "ifcfg";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { type => $type }});
last;
}
}
closedir(DIRECTORY);
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { type => $type }});
return($type);
}
=head2 check_storage
Thic gathers LVM data from the local system.

@ -460,19 +460,9 @@ sub collect_data
{
my ($anvil) = @_;
$anvil->Network->get_ips({debug => 2});
# Read the data from the ifcfg files, if available. We'll use this to check for bond interfaces that
# didn't start.
$anvil->Network->check_network();
my $uptime = $anvil->Get->uptime();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uptime => $uptime }});
if ($uptime < 600)
{
$anvil->Network->read_nmcli({debug => 2})
}
# The 'local_host' is needed to pull data recorded by Network->get_ips();
$anvil->Network->get_ips({debug => 2});
my $local_host = $anvil->Get->short_host_name();
my $directory = "/sys/class/net";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
@ -480,6 +470,7 @@ sub collect_data
directory => $directory,
}});
### TODO: Convert this to use Sys::Virt
# Make sure there are no virsh bridges, removing any found.
my $host_type = $anvil->Get->host_type();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }});
@ -516,60 +507,407 @@ sub collect_data
set_by => $THIS_FILE,
});
}
=cut
my $shell_call = $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." net-list --all --name";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
# This often hangs.
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,
}});
if (not $return_code)
}
### TODO: Remove this check when ifcfg-X support is dropped.
my $network_type = $anvil->System->check_network_type();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_type => $network_type }});
if ($network_type eq "ifcfg")
{
# Using the old 'ifcfg-X' style.
collect_data_ifcfg($anvil);
return(0);
}
# Collect data from nmcli
$anvil->Network->collect_data({debug => 2});
# Walk through the sysfs files.
local(*DIRECTORY);
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0018", variables => { directory => $directory }});
opendir(DIRECTORY, $directory);
while(my $file = readdir(DIRECTORY))
{
next if $file eq ".";
next if $file eq "..";
next if $file eq "lo";
my $full_path = $directory."/".$file;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { full_path => $full_path }});
if (-d $full_path)
{
# Virsh is up.
foreach my $line (split/\n/, $output)
# Pull out the data I want. Note that some of these don't exist with virtio-net interfaces.
my $interface = $file;
my $link_state = -e $full_path."/carrier" ? $anvil->Storage->read_file({file => $full_path."/carrier"}) : 0;
my $mtu = -e $full_path."/mtu" ? $anvil->Storage->read_file({file => $full_path."/mtu"}) : 0;
my $duplex = -e $full_path."/duplex" ? $anvil->Storage->read_file({file => $full_path."/duplex"}) : "unknown"; # full or half?
my $operational = -e $full_path."/operstate" ? $anvil->Storage->read_file({file => $full_path."/operstate"}) : "unknown"; # up or down
my $modalias = -e $full_path."/device/modalias" ? $anvil->Storage->read_file({file => $full_path."/device/modalias"}) : "unknown";
my $speed = $link_state ? $anvil->Storage->read_file({file => $full_path."/speed"}) : 0; # Mbps (ie: 1000 = Gbps), gives a very high number for unplugged link
my $media = "unknown";
my $type = "interface";
my $driver = "";
my $tx_bytes = 0; # How many bytes transmitted
my $rx_bytes = 0; # How many bytes received
# Clean up some newlines.
$link_state =~ s/\n$//;
$mtu =~ s/\n$//;
$duplex =~ s/\n$//;
$operational =~ s/\n$//;
$speed =~ s/\n$//;
$modalias =~ s/\n$//;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
interface => $interface,
link_state => $link_state,
mtu => $mtu,
duplex => $duplex,
operational => $operational,
speed => $speed,
modalias => $modalias,
}});
### NOTE: This only parses virtio so far.
# Pick out our driver.
if ($modalias =~ /^virtio:/)
{
$line =~ s/^\s+//;
$line =~ s/\s+$//;
next if not $line;
next if $line =~ /^error/;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "striker_0287", variables => { bridge => $line }});
my $shell_call = $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." net-destroy ".$line;
$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});
$driver = "virtio";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { driver => $driver }});
}
# The MAC address can faked by a number of ways, so we make an explicit call to 'ethtool' to get the permanent mac address.
my $mac_address = "";
my $shell_call = $anvil->data->{path}{exe}{ethtool}." -P ".$interface;
$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,
}});
if ($output =~ /(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)$/)
{
$mac_address = lc($1);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }});
}
else
{
# Get it by reading the address file.
if (-e $full_path."/bonding_slave/perm_hwaddr")
{
$mac_address = $anvil->Storage->read_file({file => $full_path."/bonding_slave/perm_hwaddr"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }});
}
elsif (-e $full_path."/address")
{
$mac_address = $anvil->Storage->read_file({file => $full_path."/address"});
$mac_address =~ s/\n//;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }});
}
}
# These are variables that will be needed if this is a bond interface.
my $ip_address = "";
my $subnet_mask = "";
my $bond_mode = "";
my $primary_interface = "";
my $primary_reselect = "";
my $active_interface = "";
my $mii_polling_interval = "";
my $up_delay = "";
my $down_delay = "";
my $bond_master = "";
# These are variables that will be needed if this is a bridge interface
my $bridge_id = "";
my $bridge_stp_enabled = "";
# Explicitly check for the existing of the hash so that we don't auto-vivivate the interface.
if (exists $anvil->data->{network}{$local_host}{interface}{$interface})
{
$ip_address = defined $anvil->data->{network}{$local_host}{interface}{$interface}{ip} ? $anvil->data->{network}{$local_host}{interface}{$interface}{ip} : "";
$subnet_mask = defined $anvil->data->{network}{$local_host}{interface}{$interface}{subnet_mask} ? $anvil->data->{network}{$local_host}{interface}{$interface}{subnet_mask} : "";
$type = defined $anvil->data->{network}{$local_host}{interface}{$interface}{type} ? $anvil->data->{network}{$local_host}{interface}{$interface}{type} : "interface";
$tx_bytes = defined $anvil->data->{network}{$local_host}{interface}{$interface}{tx_bytes} ? $anvil->data->{network}{$local_host}{interface}{$interface}{tx_bytes} : 0;
$rx_bytes = defined $anvil->data->{network}{$local_host}{interface}{$interface}{rx_bytes} ? $anvil->data->{network}{$local_host}{interface}{$interface}{rx_bytes} : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
ip_address => $ip_address,
subnet_mask => $subnet_mask,
type => $type,
rx_bytes => $rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $rx_bytes}).")",
tx_bytes => $tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $tx_bytes}).")",
}});
$shell_call = $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." net-undefine ".$line;
$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});
}
# If this interface is already a bond slave, the real mac address will be in a
# sub-directory.
my $mac_bond_file = $directory."/".$file."/bonding_slave/perm_hwaddr";
if (-e $mac_bond_file)
{
# It's a slave.
$mac_address = $anvil->Storage->read_file({file => $mac_bond_file});
$mac_address =~ s/\n$//;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }});
}
# If this is a virtual interface, set some fake values that don't actually exist on
# the system for the sake of a cleaner display.
if (($mac_address =~ /^52:54:00/) or ($driver eq "virtio"))
{
### Set some fake values.
# Speed is "as fast as possible", so we'll record 100 Gbps, but that is really kind of arbitrary.
if ((not $speed) or ($speed eq "-1"))
{
$speed = 10000;
}
if ((not $duplex) or ($duplex eq "unknown"))
{
$duplex = "full";
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
speed => $speed,
duplex => $duplex,
}});
}
# If the state is 'down', set the speed to '0'.
if (not $link_state)
{
$speed = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { speed => $speed }});
}
# Is this a bond interface?
if (-e "/proc/net/bonding/".$interface)
{
# Yup, we'll neet to dig into the bond proc files to get the proper slaved
# interface MAC addresses.
$type = "bond";
# Register an alert
my $variables = {
bridge => $line,
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0001", variables => $variables});
$anvil->Alert->register({
alert_level => "notice",
message => "scan_network_alert_0001",
variables => $variables,
set_by => $THIS_FILE,
});
# Read the bond mode.
$bond_mode = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/mode"});
$primary_interface = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/primary"});
$primary_reselect = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/primary_reselect"});
$active_interface = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/active_slave"});
$mii_polling_interval = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/miimon"});
$up_delay = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/updelay"});
$down_delay = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/downdelay"});
$bond_mode =~ s/\s.*//;
$bond_mode =~ s/\n$//;
$primary_interface =~ s/\n$//;
$primary_reselect =~ s/\s.*//;
$primary_reselect =~ s/\n$//;
$active_interface =~ s/\n$//;
$mii_polling_interval =~ s/\n$//;
$up_delay =~ s/\n$//;
$down_delay =~ s/\n$//;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
active_interface => $active_interface,
bond_mode => $bond_mode,
mii_polling_interval => $mii_polling_interval,
primary_reselect => $primary_reselect,
primary_interface => $primary_interface,
type => $type,
}});
}
elsif ((-e $full_path."/master") && ($interface !~ /^vnet/))
{
# We're in a bond.
my $target = readlink($full_path."/master");
$bond_master = ($target =~ /^.*\/(.*)$/)[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
target => $target,
bond_master => $bond_master,
}});
}
elsif (-d $full_path."/bridge")
{
# It's a bridge
$type = "bridge";
$bridge_id = $anvil->Storage->read_file({debug => 3, file => $full_path."/bridge/bridge_id"});
$bridge_stp_enabled = $anvil->Storage->read_file({debug => 3, file => $full_path."/bridge/stp_state"});
$bridge_id =~ s/\n$//;
$bridge_stp_enabled =~ s/\n$//;
$speed = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
bridge_id => $bridge_id,
bridge_stp_enabled => $bridge_stp_enabled,
type => $type,
}});
if ($bridge_stp_enabled eq "0")
{
$bridge_stp_enabled = "disabled";
}
elsif ($bridge_stp_enabled eq "1")
{
$bridge_stp_enabled = "enabled_kernel";
}
elsif ($bridge_stp_enabled eq "2")
{
$bridge_stp_enabled = "enabled_userland";
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridge_stp_enabled => $bridge_stp_enabled }});
}
# If this is a 'vnet' device, set 'operational' to up
if ($interface =~ /^vnet/)
{
$operational = "up";
$media = "virtual";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
operational => $operational,
media => $media,
}});
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
active_interface => $active_interface,
bond_master => $bond_master,
bond_mode => $bond_mode,
bridge_id => $bridge_id,
bridge_stp_enabled => $bridge_stp_enabled,
down_delay => $down_delay,
duplex => $duplex,
interface => $interface,
mac_address => $mac_address,
mii_polling_interval => $mii_polling_interval,
mtu => $mtu,
operational => $operational,
primary_reselect => $primary_reselect,
primary_interface => $primary_interface,
speed => $speed,
subnet_mask => $subnet_mask,
type => $type,
up_delay => $up_delay,
}});
# If the MAC address starts with '52:54:00', we've got a virtio NIC.
if ((not defined $speed) or ($speed eq ""))
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_error_0001", variables => { file => $full_path."/speed" }});
next;
}
if ($speed =~ /\D/)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_error_0002", variables => {
file => $full_path."/speed",
speed => $speed,
}});
next;
}
if ($speed > 100000)
{
# NOTE: This is probably 0 now... Though someday >100 Gbps will be reasonable
# and we'll need to change this.
$speed = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { speed => $speed }});
}
# Find the media, if possible.
(my $ethtool, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{ethtool}." $interface"});
foreach my $line (split/\n/, $ethtool)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
if ($line =~ /Supported ports: \[ (.*?) \]/i)
{
$media = lc($1);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { media => $media }});
# This can be 'tp mii', which breaks json.
if ($media =~ /\t/)
{
$media =~ s/\t/,/g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { media => $media }});
}
last;
}
}
# Store new information we found.
$anvil->data->{network}{$local_host}{interface}{$interface}{active_interface} = $active_interface;
$anvil->data->{network}{$local_host}{interface}{$interface}{bond_mode} = $bond_mode;
$anvil->data->{network}{$local_host}{interface}{$interface}{bond_master} = $bond_master;
$anvil->data->{network}{$local_host}{interface}{$interface}{bridge_id} = $bridge_id;
$anvil->data->{network}{$local_host}{interface}{$interface}{bridge_stp_enabled} = $bridge_stp_enabled;
$anvil->data->{network}{$local_host}{interface}{$interface}{down_delay} = $down_delay;
$anvil->data->{network}{$local_host}{interface}{$interface}{duplex} = $duplex;
$anvil->data->{network}{$local_host}{interface}{$interface}{ip} = $ip_address;
$anvil->data->{network}{$local_host}{interface}{$interface}{link_state} = $link_state;
$anvil->data->{network}{$local_host}{interface}{$interface}{mac_address} = $mac_address;
$anvil->data->{network}{$local_host}{interface}{$interface}{media} = $media;
$anvil->data->{network}{$local_host}{interface}{$interface}{mii_polling_interval} = $mii_polling_interval;
$anvil->data->{network}{$local_host}{interface}{$interface}{mtu} = $mtu;
$anvil->data->{network}{$local_host}{interface}{$interface}{operational} = $operational;
$anvil->data->{network}{$local_host}{interface}{$interface}{primary_reselect} = $primary_reselect;
$anvil->data->{network}{$local_host}{interface}{$interface}{primary_interface} = $primary_interface;
$anvil->data->{network}{$local_host}{interface}{$interface}{speed} = $speed;
$anvil->data->{network}{$local_host}{interface}{$interface}{subnet_mask} = $subnet_mask;
$anvil->data->{network}{$local_host}{interface}{$interface}{type} = $type;
$anvil->data->{network}{$local_host}{interface}{$interface}{up_delay} = $up_delay;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"network::${local_host}::interface::${interface}::active_interface" => $anvil->data->{network}{$local_host}{interface}{$interface}{active_interface},
"network::${local_host}::interface::${interface}::bond_mode" => $anvil->data->{network}{$local_host}{interface}{$interface}{bond_mode},
"network::${local_host}::interface::${interface}::bond_master" => $anvil->data->{network}{$local_host}{interface}{$interface}{bond_master},
"network::${local_host}::interface::${interface}::bridge_id" => $anvil->data->{network}{$local_host}{interface}{$interface}{bridge_id},
"network::${local_host}::interface::${interface}::bridge_stp_enabled" => $anvil->data->{network}{$local_host}{interface}{$interface}{bridge_stp_enabled},
"network::${local_host}::interface::${interface}::down_delay" => $anvil->data->{network}{$local_host}{interface}{$interface}{down_delay},
"network::${local_host}::interface::${interface}::duplex" => $anvil->data->{network}{$local_host}{interface}{$interface}{duplex},
"network::${local_host}::interface::${interface}::ip" => $anvil->data->{network}{$local_host}{interface}{$interface}{ip},
"network::${local_host}::interface::${interface}::link_state" => $anvil->data->{network}{$local_host}{interface}{$interface}{link_state},
"network::${local_host}::interface::${interface}::mac_address" => $anvil->data->{network}{$local_host}{interface}{$interface}{mac_address},
"network::${local_host}::interface::${interface}::media" => $anvil->data->{network}{$local_host}{interface}{$interface}{media},
"network::${local_host}::interface::${interface}::mii_polling_interval" => $anvil->data->{network}{$local_host}{interface}{$interface}{mii_polling_interval},
"network::${local_host}::interface::${interface}::mtu" => $anvil->data->{network}{$local_host}{interface}{$interface}{mtu},
"network::${local_host}::interface::${interface}::operational" => $anvil->data->{network}{$local_host}{interface}{$interface}{operational},
"network::${local_host}::interface::${interface}::primary_reselect" => $anvil->data->{network}{$local_host}{interface}{$interface}{primary_reselect},
"network::${local_host}::interface::${interface}::primary_interface" => $anvil->data->{network}{$local_host}{interface}{$interface}{primary_interface},
"network::${local_host}::interface::${interface}::speed" => $anvil->data->{network}{$local_host}{interface}{$interface}{speed},
"network::${local_host}::interface::${interface}::subnet_mask" => $anvil->data->{network}{$local_host}{interface}{$interface}{subnet_mask},
"network::${local_host}::interface::${interface}::type" => $anvil->data->{network}{$local_host}{interface}{$interface}{type},
"network::${local_host}::interface::${interface}::up_delay" => $anvil->data->{network}{$local_host}{interface}{$interface}{up_delay},
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"network::${local_host}::interface::${interface}::link_state" => $anvil->data->{network}{$local_host}{interface}{$interface}{link_state},
"network::${local_host}::interface::${interface}::operational" => $anvil->data->{network}{$local_host}{interface}{$interface}{operational},
}});
# If this is a link and there's no database connections, cache the data.
if (($type eq "interface") && (not $anvil->data->{sys}{database}{connections}))
{
$anvil->data->{cache}{new_file} .= $interface.",".$anvil->Database->refresh_timestamp.",".$mac_address.",".$speed.",".$link_state.",".$operational."\n";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"cache::new_file" => $anvil->data->{cache}{new_file},
}});
}
}
=cut
}
closedir(DIRECTORY);
die;
return(0);
}
### TODO: Remove this when ifcfg support is dropped.
sub collect_data_ifcfg
{
my ($anvil) = @_;
# Read the data from the ifcfg files, if available. We'll use this to check for bond interfaces that
# didn't start.
$anvil->Network->check_network();
my $uptime = $anvil->Get->uptime();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uptime => $uptime }});
if ($uptime < 600)
{
$anvil->Network->read_nmcli({debug => 2})
}
# The 'local_host' is needed to pull data recorded by Network->get_ips();
my $local_host = $anvil->Get->short_host_name();
my $directory = "/sys/class/net";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
local_host => $local_host,
directory => $directory,
}});
# Walk through the sysfs files.
local(*DIRECTORY);
@ -2413,6 +2751,8 @@ sub check_interfaces
new_rx_bytes => $new_rx_bytes,
}});
my $new_nmcli_uuid = "";
# Find the bridge, if any, and the bond UUID, if there's a bond name.
if ($new_bond_name)
{
@ -2815,9 +3155,11 @@ sub check_interfaces
{
my $network_interface_uuid = $anvil->Database->insert_or_update_network_interfaces({
debug => 2,
network_interface_nmcli_uuid => $new_nmcli_uuid,
network_interface_bond_uuid => $new_bond_uuid,
network_interface_bridge_uuid => $new_bridge_uuid,
network_interface_name => $network_interface_name,
network_interface_device => $network_interface_device,
network_interface_duplex => $new_duplex,
network_interface_link_state => $new_link_state,
network_interface_operational => $new_operational,
@ -2948,9 +3290,11 @@ sub check_interfaces
# Record the interface
my $network_interface_uuid = $anvil->Database->insert_or_update_network_interfaces({
debug => 2,
network_interface_nmcli_uuid => $new_nmcli_uuid,
network_interface_bond_uuid => $new_bond_uuid,
network_interface_bridge_uuid => $new_bridge_uuid,
network_interface_name => $network_interface_name,
network_interface_device => $network_interface_device,
network_interface_duplex => $new_duplex,
network_interface_link_state => $new_link_state,
network_interface_operational => $new_operational,

@ -1011,8 +1011,10 @@ CREATE TRIGGER trigger_bonds
CREATE TABLE network_interfaces (
network_interface_uuid uuid not null primary key,
network_interface_host_uuid uuid not null,
network_interface_mac_address text not null,
network_interface_name text not null, -- This is the current name of the interface.
network_interface_nmcli_uuid uuid, -- This is the nmcli UUID used to track the device. It can change, so we can't used this as the main UUID
network_interface_mac_address text not null, -- This is the interface MAC address, and it can change if a failed controller it replaced.
network_interface_name text not null, -- This is the current name (network manager's connection.id) of the interface.
network_interface_device text not null, -- This is the current device name (network manager's ) of the interface.
network_interface_speed bigint not null, -- This is the speed, in bits-per-second, of the interface.
network_interface_mtu bigint not null, -- This is the MTU (Maximum Transmitable Size), in bytes, for this interface.
network_interface_link_state text not null, -- 0 or 1
@ -1033,8 +1035,10 @@ CREATE TABLE history.network_interfaces (
history_id bigserial,
network_interface_uuid uuid not null,
network_interface_host_uuid uuid,
network_interface_nmcli_uuid uuid,
network_interface_mac_address text,
network_interface_name text,
network_interface_device text,
network_interface_speed bigint,
network_interface_mtu bigint,
network_interface_link_state text,
@ -1056,8 +1060,10 @@ BEGIN
INSERT INTO history.network_interfaces
(network_interface_uuid,
network_interface_host_uuid,
network_interface_nmcli_uuid,
network_interface_mac_address,
network_interface_name,
network_interface_device,
network_interface_speed,
network_interface_mtu,
network_interface_link_state,
@ -1070,8 +1076,10 @@ BEGIN
VALUES
(history_network_interfaces.network_interface_uuid,
history_network_interfaces.network_interface_host_uuid,
history_network_interfaces.network_interface_nmcli_uuid,
history_network_interfaces.network_interface_mac_address,
history_network_interfaces.network_interface_name,
history_network_interfaces.network_interface_device,
history_network_interfaces.network_interface_speed,
history_network_interfaces.network_interface_mtu,
history_network_interfaces.network_interface_link_state,
@ -1167,6 +1175,8 @@ CREATE TRIGGER trigger_ip_addresses
FOR EACH ROW EXECUTE PROCEDURE history_ip_addresses();
/*
TODO - This will be added only if we need to use it if the existing network tables aren't sufficient
-- This stores information about network interfaces on hosts. It is mainly used to match a MAC address to a
-- host. Given that it is possible that network devices can move, the linkage to the host_uuid can change.
CREATE TABLE network_manager (
@ -1247,6 +1257,7 @@ ALTER FUNCTION history_network_manager() OWNER TO admin;
CREATE TRIGGER trigger_network_manager
AFTER INSERT OR UPDATE ON network_manager
FOR EACH ROW EXECUTE PROCEDURE history_network_manager();
*/
-- This stores files made available to Anvil! systems and DR hosts.

@ -494,6 +494,7 @@ ORDER BY
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_type => $network_type }});
=cut
my $count = 0;
if ($network_type eq "bcn") { $count = $bcn_count; }
elsif ($network_type eq "sn") { $count = $sn_count; }
@ -1355,7 +1356,9 @@ ORDER BY
next;
}
}
=cut
}
die;
# If we should reset, do so now.
if ($anvil->data->{sys}{reboot})

@ -75,6 +75,7 @@ $anvil->System->wait_on_dnf();
$anvil->Database->connect({
check_if_configured => 1,
check_for_resync => 2,
debug => 2,
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0132"});
@ -425,6 +426,9 @@ sub set_delay
return($delay);
}
### NOTE: This used to call 'Network->check_network', which is now 'scan_network' and no longer tries to
### bring up downed connections. Likely this entire method can be removed, now that we're not using
### ifcfg-X files.
# This checks to see if it's time to see if the network is ok and, if the system has been up long enough,
# checks and tries to repair network issues.
sub check_network
@ -450,19 +454,11 @@ sub check_network
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { return_code => $return_code }});
}
#$anvil->Network->check_network({heal => "all"});
$anvil->data->{sys}{network}{initial_checks} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
"sys::network::initial_checks" => $anvil->data->{sys}{network}{initial_checks},
}});
}
else
{
### NOTE: This is constantly trying to "fix" healthy bonds, without a know way to
### trigger to debug. As such, disabling for now.
#$anvil->Network->check_network({heal => "down_only"});
}
check_firewall($anvil);
}

@ -44,10 +44,16 @@ $anvil->data->{network_manager}{want}{interface}{sn1_link1}{device} = "enp
$anvil->data->{network_manager}{want}{interface}{sn1_link2}{mac_address} = "52:54:00:2f:02:1b";
$anvil->data->{network_manager}{want}{interface}{sn1_link2}{device} = "enp11s0";
$anvil->data->{network_manager}{want}{interface}{mn1_link1}{mac_address} = "";
$anvil->data->{network_manager}{want}{interface}{mn1_link1}{device} = "";
$anvil->data->{network_manager}{want}{interface}{mn1_link2}{mac_address} = "";
$anvil->data->{network_manager}{want}{interface}{mn1_link2}{device} = "";
# Bonds
$anvil->data->{network_manager}{want}{bond}{ifn1_bond1}{interfaces} = ["ifn1_link1", "ifn1_link2"]; # First interface is primary
$anvil->data->{network_manager}{want}{bond}{bcn1_bond1}{interfaces} = ["bcn1_link1", "bcn1_link2"];
$anvil->data->{network_manager}{want}{bond}{sn1_bond1}{interfaces} = ["sn1_link1", "sn1_link2"];
$anvil->data->{network_manager}{want}{bond}{mn1_bond1}{interfaces} = ["mn1_link1", "mn1_link2"];
# Bridges
$anvil->data->{network_manager}{want}{bridge}{ifn1_bridge1}{on} = "ifn1_bond1";
@ -59,15 +65,20 @@ $anvil->data->{network_manager}{want}{ip_on}{ifn1_bridge1}{subnet_mask} = "255.2
$anvil->data->{network_manager}{want}{ip_on}{ifn1_bridge1}{gateway} = "192.168.255.254";
$anvil->data->{network_manager}{want}{ip_on}{ifn1_bridge1}{dns} = "8.8.8.8,8.8.4.4";
$anvil->data->{network_manager}{want}{ip_on}{bcn1_bridge1}{ip_address} = "10.201.4.42";
$anvil->data->{network_manager}{want}{ip_on}{bcn1_bridge1}{subnet_mask} = "255.255.0.0";
$anvil->data->{network_manager}{want}{ip_on}{bcn1_bridge1}{gateway} = "";
$anvil->data->{network_manager}{want}{ip_on}{bcn1_bridge1}{dns} = "";
$anvil->data->{network_manager}{want}{ip_on}{sn1_bond1}{ip_address} = "10.101.4.42";
$anvil->data->{network_manager}{want}{ip_on}{sn1_bond1}{subnet_mask} = "255.255.0.0";
$anvil->data->{network_manager}{want}{ip_on}{sn1_bond1}{gateway} = "";
$anvil->data->{network_manager}{want}{ip_on}{sn1_bond1}{dns} = "";
$anvil->data->{network_manager}{want}{ip_on}{bcn1_bridge1}{ip_address} = "10.201.4.42";
$anvil->data->{network_manager}{want}{ip_on}{bcn1_bridge1}{subnet_mask} = "255.255.0.0";
$anvil->data->{network_manager}{want}{ip_on}{bcn1_bridge1}{gateway} = "";
$anvil->data->{network_manager}{want}{ip_on}{bcn1_bridge1}{dns} = "";
$anvil->data->{network_manager}{want}{ip_on}{mn1_bond1}{ip_address} = "10.199.4.42";
$anvil->data->{network_manager}{want}{ip_on}{mn1_bond1}{subnet_mask} = "255.255.0.0";
$anvil->data->{network_manager}{want}{ip_on}{mn1_bond1}{gateway} = "";
$anvil->data->{network_manager}{want}{ip_on}{mn1_bond1}{dns} = "";
$anvil->data->{sys}{reboot_needed} = 0;
$anvil->data->{sys}{make_changes} = 1;

@ -63,6 +63,9 @@ sub striker_checks
{
my ($anvil) = @_;
# This checks to make sure that the new 'file_locations' -> 'file_location_ready' column exists.
update_network_interfaces($anvil);
# This checks to make sure that the new 'file_locations' -> 'file_location_ready' column exists.
update_file_location_ready($anvil);
@ -243,12 +246,156 @@ CREATE TRIGGER trigger_dr_links
return(0);
}
sub update_network_interfaces
{
my ($anvil) = @_;
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}})
{
my $query = "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'network_interfaces' AND column_name = 'network_interface_device';";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
my $count = $anvil->Database->query({query => $query, uuid => $uuid, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
if (not $count)
{
my $queries = [];
push @{$queries}, "ALTER TABLE public.network_interfaces ADD COLUMN network_interface_device text not null DEFAULT '';";
push @{$queries}, "ALTER TABLE history.network_interfaces ADD COLUMN network_interface_device text;";
push @{$queries}, "DROP FUNCTION history_network_interfaces() CASCADE;";
push @{$queries}, q|CREATE FUNCTION history_network_interfaces() RETURNS trigger
AS $$
DECLARE
history_network_interfaces RECORD;
BEGIN
SELECT INTO history_network_interfaces * FROM network_interfaces WHERE network_interface_uuid = new.network_interface_uuid;
INSERT INTO history.network_interfaces
(network_interface_uuid,
network_interface_host_uuid,
network_interface_nmcli_uuid,
network_interface_mac_address,
network_interface_name,
network_interface_device,
network_interface_speed,
network_interface_mtu,
network_interface_link_state,
network_interface_operational,
network_interface_duplex,
network_interface_medium,
network_interface_bond_uuid,
network_interface_bridge_uuid,
modified_date)
VALUES
(history_network_interfaces.network_interface_uuid,
history_network_interfaces.network_interface_host_uuid,
history_network_interfaces.network_interface_nmcli_uuid,
history_network_interfaces.network_interface_mac_address,
history_network_interfaces.network_interface_name,
history_network_interfaces.network_interface_device,
history_network_interfaces.network_interface_speed,
history_network_interfaces.network_interface_mtu,
history_network_interfaces.network_interface_link_state,
history_network_interfaces.network_interface_operational,
history_network_interfaces.network_interface_duplex,
history_network_interfaces.network_interface_medium,
history_network_interfaces.network_interface_bond_uuid,
history_network_interfaces.network_interface_bridge_uuid,
history_network_interfaces.modified_date);
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
ALTER FUNCTION history_network_interfaces() OWNER TO admin;
CREATE TRIGGER trigger_network_interfaces
AFTER INSERT OR UPDATE ON network_interfaces
FOR EACH ROW EXECUTE PROCEDURE history_network_interfaces();
|;
foreach my $query (@{$queries})
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }});
}
$anvil->Database->write({debug => 2, uuid => $uuid, query => $queries, source => $THIS_FILE, line => __LINE__});
}
$query = "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'network_interfaces' AND column_name = 'network_interface_nmcli_uuid';";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$count = $anvil->Database->query({query => $query, uuid => $uuid, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
if (not $count)
{
my $queries = [];
push @{$queries}, "ALTER TABLE public.network_interfaces ADD COLUMN network_interface_nmcli_uuid uuid;";
push @{$queries}, "ALTER TABLE history.network_interfaces ADD COLUMN network_interface_nmcli_uuid uuid;";
push @{$queries}, "DROP FUNCTION history_network_interfaces() CASCADE;";
push @{$queries}, q|CREATE FUNCTION history_network_interfaces() RETURNS trigger
AS $$
DECLARE
history_network_interfaces RECORD;
BEGIN
SELECT INTO history_network_interfaces * FROM network_interfaces WHERE network_interface_uuid = new.network_interface_uuid;
INSERT INTO history.network_interfaces
(network_interface_uuid,
network_interface_host_uuid,
network_interface_nmcli_uuid,
network_interface_mac_address,
network_interface_name,
network_interface_device,
network_interface_speed,
network_interface_mtu,
network_interface_link_state,
network_interface_operational,
network_interface_duplex,
network_interface_medium,
network_interface_bond_uuid,
network_interface_bridge_uuid,
modified_date)
VALUES
(history_network_interfaces.network_interface_uuid,
history_network_interfaces.network_interface_host_uuid,
history_network_interfaces.network_interface_nmcli_uuid,
history_network_interfaces.network_interface_mac_address,
history_network_interfaces.network_interface_name,
history_network_interfaces.network_interface_device,
history_network_interfaces.network_interface_speed,
history_network_interfaces.network_interface_mtu,
history_network_interfaces.network_interface_link_state,
history_network_interfaces.network_interface_operational,
history_network_interfaces.network_interface_duplex,
history_network_interfaces.network_interface_medium,
history_network_interfaces.network_interface_bond_uuid,
history_network_interfaces.network_interface_bridge_uuid,
history_network_interfaces.modified_date);
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
ALTER FUNCTION history_network_interfaces() OWNER TO admin;
CREATE TRIGGER trigger_network_interfaces
AFTER INSERT OR UPDATE ON network_interfaces
FOR EACH ROW EXECUTE PROCEDURE history_network_interfaces();
|;
foreach my $query (@{$queries})
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }});
}
$anvil->Database->write({debug => 2, uuid => $uuid, query => $queries, source => $THIS_FILE, line => __LINE__});
}
}
return(0);
}
# This checks to make sure that the new 'file_locations' -> 'file_location_ready' column exists.
sub update_file_location_ready
{
my ($anvil) = @_;
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}})
{
my $query = "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'file_locations' AND column_name = 'file_location_ready';";

Loading…
Cancel
Save