diff --git a/tools/anvil-update-states b/tools/anvil-update-states
index 400a83e8..76b3a31e 100755
--- a/tools/anvil-update-states
+++ b/tools/anvil-update-states
@@ -37,7 +37,7 @@ if (not $connections)
$anvil->nice_exit({exit_code => 2});
}
-report_network($anvil);
+update_network($anvil);
$anvil->nice_exit({exit_code => 0});
@@ -46,7 +46,7 @@ $anvil->nice_exit({exit_code => 0});
#############################################################################################################
# This reports the current network interface states, tracked by the MAC address.
-sub report_network
+sub update_network
{
my ($anvil) = @_;
@@ -59,6 +59,14 @@ sub report_network
my $directory = "/sys/class/net";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { directory => $directory }});
+ # We'll need to know what interfaces to remove, if any. This will store the interfaces we've seen and
+ # any others will be removed.
+ $anvil->data->{seen} = {
+ interfaces => {},
+ bonds => {},
+ bridges => {},
+ };
+
local(*DIRECTORY);
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0018", variables => { directory => $directory }});
opendir(DIRECTORY, $directory);
@@ -222,6 +230,10 @@ sub report_network
}
}
+ # Record this interface
+ $anvil->data->{seen}{$type}{$interface} = 1;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "seen::${type}::${interface}" => $anvil->data->{seen}{$type}{$interface} }});
+
# Log
$anvil->data->{network}{interfaces}{by_name}{$interface} = {
active_slave => $active_slave,
@@ -427,7 +439,9 @@ SELECT
FROM
bonds
WHERE
- bond_host_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->Get->host_uuid)."
+ bond_host_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->Get->host_uuid)."
+AND
+ bond_mode != 'DELETED'
;";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, key => "log_0124", variables => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
@@ -439,8 +453,9 @@ WHERE
foreach my $row (@{$results})
{
my $bond_uuid = $row->[0];
+ my $bond_name = $row->[1];
$anvil->data->{bonds}{$bond_uuid} = {
- bond_name => $row->[1],
+ bond_name => $bond_name,
bond_mode => $row->[2],
bond_mtu => $row->[3],
bond_primary_slave => $row->[4],
@@ -465,6 +480,17 @@ WHERE
"bonds::${bond_uuid}::bond_mac_address" => $anvil->data->{bonds}{$bond_uuid}{bond_mac_address},
"bonds::${bond_uuid}::bond_operational" => $anvil->data->{bonds}{$bond_uuid}{bond_operational},
}});
+
+ # Make sure I've seen this interface in this scan and, if not, update this entry to remove it.
+ if ((not exists $anvil->data->{seen}{bond}{$bond_name}) or (not $anvil->data->{seen}{bond}{$bond_name}))
+ {
+ # Mark it as deleted.
+ my $query = "UPDATE bonds SET bond_mode = 'DELETED' WHERE bond_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($bond_uuid).";";
+ $anvil->Database->write({debug => 2, query => $query, source => $THIS_FILE, line => __LINE__});
+
+ # Remove it from the hash so we don't add it to the .json and .xml files.
+ delete $anvil->data->{bonds}{$bond_uuid};
+ }
}
$query = "
@@ -476,7 +502,9 @@ SELECT
FROM
bridges
WHERE
- bridge_host_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->Get->host_uuid)."
+ bridge_host_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->Get->host_uuid)."
+AND
+ bridge_id != 'DELETED'
;";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, key => "log_0124", variables => { query => $query }});
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
@@ -488,8 +516,9 @@ WHERE
foreach my $row (@{$results})
{
my $bridge_uuid = $row->[0];
+ my $bridge_name = $row->[1];
$anvil->data->{bridges}{$bridge_uuid} = {
- bridge_name => $row->[1],
+ bridge_name => $bridge_name,
bridge_id => $row->[2],
bridge_stp_enabled => $row->[3],
};
@@ -498,6 +527,17 @@ WHERE
"bridges::${bridge_uuid}::bridge_id" => $anvil->data->{bridges}{$bridge_uuid}{bridge_id},
"bridges::${bridge_uuid}::bridge_stp_enabled" => $anvil->data->{bridges}{$bridge_uuid}{bridge_stp_enabled},
}});
+
+ # Make sure I've seen this interface in this scan and, if not, update this entry to remove it.
+ if ((not exists $anvil->data->{seen}{bridge}{$bridge_name}) or (not $anvil->data->{seen}{bridge}{$bridge_name}))
+ {
+ # Mark it as deleted.
+ my $query = "UPDATE bridges SET bridge_id = 'DELETED' WHERE bridge_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($bridge_uuid).";";
+ $anvil->Database->write({debug => 2, query => $query, source => $THIS_FILE, line => __LINE__});
+
+ # Remove it from the hash so we don't add it to the .json and .xml files.
+ delete $anvil->data->{bridges}{$bridge_uuid};
+ }
}
$query = "
@@ -516,11 +556,13 @@ SELECT
FROM
network_interfaces
WHERE
- network_interface_host_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->Get->host_uuid)."
+ network_interface_host_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->Get->host_uuid)."
+AND
+ network_interface_operational != 'DELETED'
ORDER BY
modified_date DESC
;";
- $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, key => "log_0124", variables => { query => $query }});
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }});
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
$count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
@@ -536,9 +578,10 @@ ORDER BY
foreach my $row (@{$results})
{
my $network_interface_uuid = $row->[0];
+ my $network_interface_name = $row->[2];
$anvil->data->{network_interfaces}{$network_interface_uuid} = {
network_interface_mac_address => $row->[1],
- network_interface_name => $row->[2],
+ network_interface_name => $network_interface_name,
network_interface_speed => $row->[3],
network_interface_mtu => $row->[4],
network_interface_link_state => $row->[5],
@@ -548,7 +591,7 @@ ORDER BY
network_interface_bond_uuid => defined $row->[9] ? $row->[9] : 'NULL',
network_interface_bridge_uuid => defined $row->[10] ? $row->[10] : 'NULL',
};
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"network_interfaces::${network_interface_uuid}::network_interface_mac_address" => $anvil->data->{network_interfaces}{$network_interface_uuid}{network_interface_mac_address},
"network_interfaces::${network_interface_uuid}::network_interface_name" => $anvil->data->{network_interfaces}{$network_interface_uuid}{network_interface_name},
"network_interfaces::${network_interface_uuid}::network_interface_speed" => $anvil->data->{network_interfaces}{$network_interface_uuid}{network_interface_speed},
@@ -561,6 +604,21 @@ ORDER BY
"network_interfaces::${network_interface_uuid}::network_interface_bridge_uuid" => $anvil->data->{network_interfaces}{$network_interface_uuid}{network_interface_bridge_uuid},
order => $order,
}});
+
+ # Make sure I've seen this interface in this scan and, if not, update this entry to remove it.
+ if ((not exists $anvil->data->{seen}{interface}{$network_interface_name}) or (not $anvil->data->{seen}{interface}{$network_interface_name}))
+ {
+ # Mark it as deleted.
+ my $query = "UPDATE network_interfaces SET network_interface_operational = 'DELETED' WHERE network_interface_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($network_interface_uuid).";";
+ $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
+
+ # Remove it from the hash so we don't add it to the .json and .xml files.
+ delete $anvil->data->{interfaces}{$network_interface_uuid};
+
+ # Loop so we don't try to process any further.
+ next;
+ }
+
my $say_bond = "";
my $network_interface_bond_uuid = $anvil->data->{network_interfaces}{$network_interface_uuid}{network_interface_bond_uuid};
my $network_interface_bridge_uuid = $anvil->data->{network_interfaces}{$network_interface_uuid}{network_interface_bridge_uuid};
@@ -597,7 +655,9 @@ SELECT
FROM
ip_addresses
WHERE
- ip_address_host_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->Get->host_uuid)."
+ ip_address_host_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->Get->host_uuid)."
+ AND
+ ip_address_on_type != 'DELETED'
;";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, key => "log_0124", variables => { query => $query }});
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
@@ -626,25 +686,52 @@ WHERE
ip_address_dns => $ip_address_dns,
}});
- my $say_on = "";
- if ($ip_address_on_type eq "interface")
+ # Did we see this IP on this scan? If not, set on_type to DELETEd.
+ my $found = 0;
+ foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{sys}{network}{interface}})
{
- $say_on = $anvil->data->{network_interfaces}{$ip_address_on_uuid}{network_interface_name};
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_on => $say_on }});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ interface => $interface,
+ ip_address_address => $ip_address_address,
+ "sys::network::interface::${interface}::ip" => $anvil->data->{sys}{network}{interface}{$interface}{ip},
+ }});
+ if ((defined $anvil->data->{sys}{network}{interface}{$interface}{ip}) && ($anvil->data->{sys}{network}{interface}{$interface}{ip} eq $ip_address_address))
+ {
+ $found = 1;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { found => $found }});
+ last;
+ }
}
- elsif ($ip_address_on_type eq "bond")
+
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { found => $found }});
+ if ($found)
{
- $say_on = $anvil->data->{bonds}{$ip_address_on_uuid}{bond_name};
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_on => $say_on }});
+ my $say_on = "";
+ if ($ip_address_on_type eq "interface")
+ {
+ $say_on = $anvil->data->{network_interfaces}{$ip_address_on_uuid}{network_interface_name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_on => $say_on }});
+ }
+ elsif ($ip_address_on_type eq "bond")
+ {
+ $say_on = $anvil->data->{bonds}{$ip_address_on_uuid}{bond_name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_on => $say_on }});
+ }
+ elsif ($ip_address_on_type eq "bridge")
+ {
+ $say_on = $anvil->data->{bridges}{$ip_address_on_uuid}{bridge_name};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_on => $say_on }});
+ }
+
+ $network_json .= " { \"address\":\"$ip_address_address\", \"on\":\"$say_on\", \"subnet\":\"$ip_address_subnet_mask\", \"gateway\":\"$ip_address_gateway\", \"default_gateway\":\"$ip_address_default_gateway\", \"dns\":\"$ip_address_dns\" },\n";
+ $network_xml .= " \n";
}
- elsif ($ip_address_on_type eq "bridge")
+ else
{
- $say_on = $anvil->data->{bridges}{$ip_address_on_uuid}{bridge_name};
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_on => $say_on }});
+ # Stale, mark it as deleted.
+ my $query = "UPDATE ip_addresses SET ip_address_on_type = 'DELETED' WHERE ip_address_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($ip_address_uuid).";";
+ $anvil->Database->write({debug => 2, query => $query, source => $THIS_FILE, line => __LINE__});
}
-
- $network_json .= " { \"address\":\"$ip_address_address\", \"on\":\"$say_on\", \"subnet\":\"$ip_address_subnet_mask\", \"gateway\":\"$ip_address_gateway\", \"default_gateway\":\"$ip_address_default_gateway\", \"dns\":\"$ip_address_dns\" },\n";
- $network_xml .= " \n";
}
$network_json =~ s/,$//s;