Added support for multiple IP's per interface

* Created Database->get_mac_to_ip()
* Updated Database->insert_or_update_mac_to_ip() to find an entry using
  both the IP and MAC address.
* Updated Network->get_ips() to store only the first IP it finds on an
  interface as the main IP (for use in /etc/hosts, etc) and to store it
  and any other IPs in a new hash.
* Updated scan-network to use the new hash above to record them in the
  'mac_to_ip' table. Similarly, before marking an IP as removed, it
  checks to see if it's an alternate IP.

Signed-off-by: digimer <mkelly@alteeve.ca>
main
digimer 10 months ago
parent bc910b14e4
commit 870c990632
  1. 80
      Anvil/Tools/Database.pm
  2. 31
      Anvil/Tools/Network.pm
  3. 83
      scancore-agents/scan-network/scan-network
  4. 1
      scancore-agents/scan-network/scan-network.xml
  5. 2
      tools/striker-scan-network

@ -44,6 +44,7 @@ my $THIS_FILE = "Database.pm";
# get_jobs # get_jobs
# get_local_uuid # get_local_uuid
# get_lvm_data # get_lvm_data
# get_mac_to_ip
# get_mail_servers # get_mail_servers
# get_manifests # get_manifests
# get_recipients # get_recipients
@ -5325,6 +5326,83 @@ FROM
} }
=head2 get_mac_to_ip
This loads the C<< mac_to_ip >> data.
This method takes no parameters.
=cut
sub get_mac_to_ip
{
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 => "Database->get_mac_to_ip()" }});
if (exists $anvil->data->{mac_to_ip})
{
delete $anvil->data->{mac_to_ip};
}
my $query = "
SELECT
mac_to_ip_uuid,
mac_to_ip_mac_address,
mac_to_ip_ip_address,
mac_to_ip_note,
modified_date
FROM
mac_to_ip
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $mac_to_ip_uuid = $row->[0];
my $mac_to_ip_mac_address = $row->[1];
my $mac_to_ip_ip_address = $row->[2];
my $mac_to_ip_note = $row->[3];
my $modified_date = $row->[4];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
mac_to_ip_uuid => $mac_to_ip_uuid,
mac_to_ip_mac_address => $mac_to_ip_mac_address,
mac_to_ip_ip_address => $mac_to_ip_ip_address,
mac_to_ip_note => $mac_to_ip_note,
modified_date => $modified_date,
}});
$anvil->data->{mac_to_ip}{mac_to_ip_uuid}{$mac_to_ip_uuid}{mac_to_ip_mac_address} = $mac_to_ip_mac_address;
$anvil->data->{mac_to_ip}{mac_to_ip_uuid}{$mac_to_ip_uuid}{mac_to_ip_ip_address} = $mac_to_ip_ip_address;
$anvil->data->{mac_to_ip}{mac_to_ip_uuid}{$mac_to_ip_uuid}{mac_to_ip_note} = $mac_to_ip_note;
$anvil->data->{mac_to_ip}{mac_to_ip_uuid}{$mac_to_ip_uuid}{modified_date} = $modified_date;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:mac_to_ip::mac_to_ip_uuid::${mac_to_ip_uuid}::mac_to_ip_mac_address" => $anvil->data->{mac_to_ip}{mac_to_ip_uuid}{$mac_to_ip_uuid}{mac_to_ip_mac_address},
"s2:mac_to_ip::mac_to_ip_uuid::${mac_to_ip_uuid}::mac_to_ip_ip_address" => $anvil->data->{mac_to_ip}{mac_to_ip_uuid}{$mac_to_ip_uuid}{mac_to_ip_ip_address},
"s3:mac_to_ip::mac_to_ip_uuid::${mac_to_ip_uuid}::mac_to_ip_note" => $anvil->data->{mac_to_ip}{mac_to_ip_uuid}{$mac_to_ip_uuid}{mac_to_ip_note},
"s4:mac_to_ip::mac_to_ip_uuid::${mac_to_ip_uuid}::modified_date" => $anvil->data->{mac_to_ip}{mac_to_ip_uuid}{$mac_to_ip_uuid}{modified_date},
}});
# Make it easier to look things up.
$anvil->data->{mac_to_ip}{mac_to_ip_mac_address}{$mac_to_ip_mac_address}{mac_to_ip_uuid} = $mac_to_ip_uuid;
$anvil->data->{mac_to_ip}{mac_to_ip_ip_address}{$mac_to_ip_ip_address}{mac_to_ip_uuid} = $mac_to_ip_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:mac_to_ip::mac_to_ip_mac_address::${mac_to_ip_mac_address}::mac_to_ip_uuid" => $anvil->data->{mac_to_ip}{mac_to_ip_mac_address}{$mac_to_ip_mac_address}{mac_to_ip_uuid},
"s2:mac_to_ip::mac_to_ip_ip_address::${mac_to_ip_ip_address}::mac_to_ip_uuid" => $anvil->data->{mac_to_ip}{mac_to_ip_ip_address}{$mac_to_ip_ip_address}{mac_to_ip_uuid},
}});
}
return(0);
}
=head2 get_mail_servers =head2 get_mail_servers
This gets the list of configured mail servers. This gets the list of configured mail servers.
@ -12001,6 +12079,8 @@ FROM
mac_to_ip mac_to_ip
WHERE WHERE
mac_to_ip_mac_address = ".$anvil->Database->quote($mac_to_ip_mac_address)." mac_to_ip_mac_address = ".$anvil->Database->quote($mac_to_ip_mac_address)."
AND
mac_to_ip_ip_address = ".$anvil->Database->quote($mac_to_ip_ip_address)."
;"; ;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});

@ -2253,12 +2253,31 @@ fi";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { subnet_mask => $subnet_mask }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { subnet_mask => $subnet_mask }});
} }
$anvil->data->{network}{$host}{interface}{$in_iface}{ip} = $ip; # For multiple IPs on an interface, we'll store the first we see as the "main" IP (used in
$anvil->data->{network}{$host}{interface}{$in_iface}{subnet_mask} = $subnet_mask; # /etc/hosts, etc).
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { if ((not $anvil->data->{network}{$host}{interface}{$in_iface}{ip}) or
"s1:network::${host}::interface::${in_iface}::ip" => $anvil->data->{network}{$host}{interface}{$in_iface}{ip}, (not $anvil->Validate->ip({ip => $anvil->data->{network}{$host}{interface}{$in_iface}{ip}})))
"s2:network::${host}::interface::${in_iface}::subnet_mask" => $anvil->data->{network}{$host}{interface}{$in_iface}{subnet_mask}, {
}}); # First IP for this interface, save it in the traditional hash.
$anvil->data->{network}{$host}{interface}{$in_iface}{ip} = $ip;
$anvil->data->{network}{$host}{interface}{$in_iface}{subnet_mask} = $subnet_mask;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:network::${host}::interface::${in_iface}::ip" => $anvil->data->{network}{$host}{interface}{$in_iface}{ip},
"s2:network::${host}::interface::${in_iface}::subnet_mask" => $anvil->data->{network}{$host}{interface}{$in_iface}{subnet_mask},
}});
}
# Now store the IPs in hash that handles multiple IPs per interface properly. This
# should never be duplicate, buuuuut...
if (not exists $anvil->data->{network}{$host}{ip_address}{$ip})
{
$anvil->data->{network}{$host}{ip_address}{$ip}{interface} = $in_iface;
$anvil->data->{network}{$host}{ip_address}{$ip}{subnet_mask} = $subnet_mask;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:network::${host}::ip_address::${ip}::interface" => $anvil->data->{network}{$host}{ip_address}{$ip}{interface},
"s2:network::${host}::ip_address::${ip}::subnet_mask" => $anvil->data->{network}{$host}{ip_address}{$ip}{subnet_mask},
}});
}
} }
if ($line =~ /ether (.*?) /i) if ($line =~ /ether (.*?) /i)
{ {

@ -2398,12 +2398,24 @@ sub check_ip_addresses
} }
# Look for left over / deleted bonds. # Look for left over / deleted bonds.
$anvil->Database->get_mac_to_ip({debug => 2});
my $host = $anvil->Get->short_host_name();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host => $host }});
foreach my $ip_address_uuid (keys %{$anvil->data->{old}{ip_addresses}{ip_address_uuid}}) foreach my $ip_address_uuid (keys %{$anvil->data->{old}{ip_addresses}{ip_address_uuid}})
{ {
# Skip if already deleted. # Skip if already deleted.
next if $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_note} eq "DELETED"; next if $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_note} eq "DELETED";
my $ip_address_address = $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_address}; my $ip_address_address = $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_address};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_address_address => $ip_address_address }});
# Is this an alternate IP?
if ((exists $anvil->data->{network}{$host}{ip_address}{$ip_address_address}) &&
($anvil->data->{network}{$host}{ip_address}{$ip_address_address}{interface}))
{
# This is an alternate IP, don't delete it.
next;
}
my $variables = { ip => $ip_address_address }; my $variables = { ip => $ip_address_address };
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0060", variables => $variables}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0060", variables => $variables});
@ -2422,6 +2434,77 @@ sub check_ip_addresses
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_address_uuid => $ip_address_uuid }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_address_uuid => $ip_address_uuid }});
} }
# Look for alternate IPs
foreach my $ip_address (sort {$a cmp $b} keys %{$anvil->data->{network}{$host}{ip_address}})
{
my $interface = $anvil->data->{network}{$host}{ip_address}{$ip_address}{interface};
my $subnet_mask = $anvil->data->{network}{$host}{ip_address}{$ip_address}{subnet_mask};
my $mac_address = $anvil->data->{network}{$host}{interface}{$interface}{mac_address};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"s1:ip_address" => $ip_address,
"s2:interface" => $interface,
"s3:subnet_mask" => $subnet_mask,
"s4:mac_address" => $mac_address,
}});
# Is this a new IP?
if (($interface) && ($mac_address))
{
if (not exists $anvil->data->{mac_to_ip}{mac_to_ip_ip_address}{$ip_address})
{
# Record it.
my ($mac_to_ip_uuid) = $anvil->Database->insert_or_update_mac_to_ip({
debug => 2,
mac_to_ip_mac_address => $mac_address,
mac_to_ip_ip_address => $ip_address,
mac_to_ip_note => "on ".$host.":".$interface,
update_note => 0,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_to_ip_uuid => $mac_to_ip_uuid }});
# reload the mac_to_ips.
$anvil->Database->get_mac_to_ip({debug => 2});
my $variables = {
ip_address => $ip_address,
interface => $interface,
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0064", variables => $variables});
$anvil->Alert->register({
alert_level => "notice",
message => "scan_network_alert_0064",
variables => $variables,
set_by => $THIS_FILE,
});
}
}
if ($anvil->data->{mac_to_ip}{mac_to_ip_ip_address}{$ip_address}{mac_to_ip_uuid})
{
# Add a note that we've got the IP.
my $mac_to_ip_uuid = $anvil->data->{mac_to_ip}{mac_to_ip_ip_address}{$ip_address}{mac_to_ip_uuid};
my $mac_to_ip_note = $anvil->data->{mac_to_ip}{mac_to_ip_uuid}{$mac_to_ip_uuid}{mac_to_ip_note};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:ip_address' => $ip_address,
's2:mac_to_ip_uuid' => $mac_to_ip_uuid,
's3:mac_to_ip_note' => $mac_to_ip_note,
}});
if (($mac_to_ip_uuid) && (not $mac_to_ip_note))
{
my ($mac_to_ip_uuid) = $anvil->Database->insert_or_update_mac_to_ip({
debug => 2,
mac_to_ip_uuid => $mac_to_ip_uuid,
mac_to_ip_mac_address => $mac_address,
mac_to_ip_ip_address => $ip_address,
mac_to_ip_note => "on ".$host.":".$interface,
update_note => 0,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_to_ip_uuid => $mac_to_ip_uuid }});
}
}
}
return(0); return(0);
} }

@ -135,6 +135,7 @@ Note: If this is a Storage Network directly connected to the peer, and the peer
<key name="scan_network_alert_0061">The network interface: [#!variable!name!#] MAC address has changed from: [#!variable!old!#] to: [#!variable!new!#]. This is normal when a server boots or migrates.</key> <key name="scan_network_alert_0061">The network interface: [#!variable!name!#] MAC address has changed from: [#!variable!old!#] to: [#!variable!new!#]. This is normal when a server boots or migrates.</key>
<key name="scan_network_alert_0062">The network interface: [#!variable!name!#] network manager's 'connection.id' name (biosdevname) has changed from: [#!variable!old!#] to: [#!variable!new!#].</key> <key name="scan_network_alert_0062">The network interface: [#!variable!name!#] network manager's 'connection.id' name (biosdevname) has changed from: [#!variable!old!#] to: [#!variable!new!#].</key>
<key name="scan_network_alert_0063">The network interface: [#!variable!name!#] network manager's 'GENERAL.IP-IFACE' name (ip addr name) has changed from: [#!variable!old!#] to: [#!variable!new!#].</key> <key name="scan_network_alert_0063">The network interface: [#!variable!name!#] network manager's 'GENERAL.IP-IFACE' name (ip addr name) has changed from: [#!variable!old!#] to: [#!variable!new!#].</key>
<key name="scan_network_alert_0064">The IP address: [#!variable!ip_address!#] was found on the interface: [#!variable!interface!#].</key>
<!-- Error entries --> <!-- Error entries -->
<key name="scan_network_error_0001">Failed to read the network interface speed from the file: [#!variable!file!#]. Ignoring interface.</key> <key name="scan_network_error_0001">Failed to read the network interface speed from the file: [#!variable!file!#]. Ignoring interface.</key>

@ -267,7 +267,7 @@ sub scan
else else
{ {
# Scan all the networks we have. # Scan all the networks we have.
$anvil->Network->get_ips(); $anvil->Network->get_ips({debug => 2});
my $target = "local"; my $target = "local";
my $to_scan = []; my $to_scan = [];
foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{network}}) foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{network}})

Loading…
Cancel
Save