Merge pull request #570 from ClusterLabs/log-collection

Log collection
main
digimer-bot 11 months ago committed by GitHub
commit 492983d7ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      Anvil/Tools.pm
  2. 14
      Anvil/Tools/Cluster.pm
  3. 383
      Anvil/Tools/Database.pm
  4. 2
      Anvil/Tools/Email.pm
  5. 24
      Anvil/Tools/Get.pm
  6. 105
      Anvil/Tools/Job.pm
  7. 4
      Anvil/Tools/Log.pm
  8. 1145
      Anvil/Tools/Network.pm
  9. 14
      Anvil/Tools/Storage.pm
  10. 2
      Anvil/Tools/Striker.pm
  11. 77
      Anvil/Tools/System.pm
  12. 6
      anvil.spec.in
  13. 9
      man/anvil-manage-host.8
  14. 447
      scancore-agents/scan-network/scan-network
  15. 2
      scancore-agents/scan-network/scan-network.xml
  16. 1
      scancore-agents/scan-server/scan-server
  17. 107
      share/anvil.sql
  18. 71
      share/words.xml
  19. 1
      tools/Makefile.am
  20. 6
      tools/anvil-check-memory
  21. 2856
      tools/anvil-configure-host
  22. 253
      tools/anvil-daemon
  23. 8
      tools/anvil-download-file
  24. 490
      tools/anvil-join-anvil
  25. 4
      tools/anvil-manage-dr
  26. 119
      tools/anvil-manage-host
  27. 505
      tools/anvil-monitor-network
  28. 4
      tools/anvil-parse-fence-agents
  29. 12
      tools/anvil-provision-server
  30. 9
      tools/anvil-safe-start
  31. 2
      tools/anvil-sync-shared
  32. 1161
      tools/anvil-update-states
  33. 301
      tools/anvil-version-changes
  34. 2
      tools/anvil-watch-servers
  35. 16
      tools/fence_pacemaker
  36. 6
      tools/scancore
  37. 1
      tools/striker-auto-initialize-all
  38. 20
      tools/striker-collect-debug
  39. 5
      tools/striker-initialize-host
  40. 2
      tools/striker-manage-install-target
  41. 6
      tools/striker-prep-database
  42. 16
      tools/unfence_pacemaker
  43. 1
      units/Makefile.am
  44. 12
      units/anvil-monitor-network.service

@ -1069,6 +1069,7 @@ sub _set_paths
'journald.conf' => "/etc/systemd/journald.conf",
'logind.conf' => "/etc/systemd/logind.conf",
'lvm.conf' => "/etc/lvm/lvm.conf",
'persistent-net' => "/etc/udev/rules.d/70-persistent-net.rules",
'pg_hba.conf' => "/var/lib/pgsql/data/pg_hba.conf",
'postgresql.conf' => "/var/lib/pgsql/data/postgresql.conf",
pxe_default => "/var/lib/tftpboot/pxelinux.cfg/default",
@ -1078,6 +1079,7 @@ sub _set_paths
postfix_relay_password => "/etc/postfix/relay_password",
'qemu.conf' => "/etc/libvirt/qemu.conf",
ssh_config => "/etc/ssh/ssh_config",
sshd_root_password => "/etc/ssh/sshd_config.d/01-permitrootlogin.conf",
'type.striker' => "/etc/anvil/type.striker",
'type.dr' => "/etc/anvil/type.dr",
'type.node' => "/etc/anvil/type.node",
@ -1129,6 +1131,7 @@ sub _set_paths
provision => "/mnt/shared/provision",
temp => "/mnt/shared/temp",
},
'sshd_config.d' => "/etc/ssh/sshd_config.d",
skins => "/var/www/html/skins",
status => "/var/www/html/status",
syslinux => "/usr/share/syslinux",
@ -1169,7 +1172,6 @@ sub _set_paths
'anvil-special-operations' => "/usr/sbin/anvil-special-operations",
'anvil-sync-shared' => "/usr/sbin/anvil-sync-shared",
'anvil-update-files' => "/usr/sbin/anvil-update-files",
'anvil-update-states' => "/usr/sbin/anvil-update-states",
'anvil-update-system' => "/usr/sbin/anvil-update-system",
'anvil-version-changes' => "/usr/sbin/anvil-version-changes",
augtool => "/usr/bin/augtool",
@ -1195,6 +1197,7 @@ sub _set_paths
df => "/usr/bin/df",
dmidecode => "/usr/sbin/dmidecode",
dnf => "/usr/bin/dnf",
dracut => "/usr/bin/dracut",
drbdadm => "/usr/sbin/drbdadm",
drbdsetup => "/usr/sbin/drbdsetup",
dropdb => "/usr/bin/dropdb",
@ -1210,6 +1213,7 @@ sub _set_paths
'grep' => "/usr/bin/grep",
groupadd => "/usr/sbin/groupadd",
head => "/usr/bin/head",
hostname => "/usr/bin/hostname",
hostnamectl => "/usr/bin/hostnamectl",
hpacucli => "/usr/sbin/hpacucli",
htpasswd => "/usr/bin/htpasswd",

@ -105,6 +105,10 @@ This takes a server name, finds where it is running and then adds it to pacemake
Parameters;
=head3 ok_if_exists (optional, default '0')
Normally, if the server is already in the cluster, C<< !!error!! >> is returned. If this is set to C<< 1 >> and the server is already in pacemaker, we'll return C<< 0 >> instead.
=head3 server_name (required)
This is the name of the server being added.
@ -118,9 +122,11 @@ sub add_server
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 2;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Cluster->add_server()" }});
my $server_name = defined $parameter->{server_name} ? $parameter->{server_name} : "";
my $ok_if_exists = defined $parameter->{ok_if_exists} ? $parameter->{ok_if_exists} : "";
my $server_name = defined $parameter->{server_name} ? $parameter->{server_name} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
server_name => $server_name,
ok_if_exists => $ok_if_exists,
server_name => $server_name,
}});
if (not $server_name)
@ -146,6 +152,10 @@ sub add_server
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"cib::parsed::cib::resources::primitive::${server_name}::type" => $anvil->data->{cib}{parsed}{cib}{resources}{primitive}{$server_name}{type},
}});
if ($ok_if_exists)
{
return(0);
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0213", variables => { server_name => $server_name }});
return("!!error!!");
}

@ -786,7 +786,11 @@ If the system is already configured, this method will do nothing, so it is safe
If the method completes, C<< 0 >> is returned. If this method is called without C<< root >> access, it returns C<< 1 >> without doing anything. If there is a problem, C<< !!error!! >> is returned.
This method takes no parameters.
Parameters;
=head3 check_db_exists (optional, default 0)
If set, the database will be checked to see if the schema exists. This is normally not needed, but can be triggered if the database was DROP'ed by a user.
=cut
### TODO: Much of this logic is in striker-prep-database, consolidate!
@ -798,6 +802,11 @@ sub configure_pgsql
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->configure_pgsql()" }});
my $check_db_exists = defined $parameter->{check_db_exists} ? $parameter->{check_db_exists} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
check_db_exists => $check_db_exists,
}});
# The local host_uuid is the ID of the local database, so get that.
my $uuid = $anvil->Get->host_uuid();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { uuid => $uuid }});
@ -971,7 +980,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}});
@ -1012,7 +1021,7 @@ sub configure_pgsql
's2:update_postgresql_file' => $update_postgresql_file,
's3:update_pg_hba_file' => $update_pg_hba_file,
}});
if (($initialized) or ($update_postgresql_file) or ($update_pg_hba_file))
if (($initialized) or ($update_postgresql_file) or ($update_pg_hba_file) or ($check_db_exists))
{
# Create the .pgpass file, if needed.
my $created_pgpass = 0;
@ -1366,7 +1375,11 @@ sub connect
# This method just returns if nothing is needed.
if (($local_host_type eq "striker") && ($check_if_configured) && ($< == 0) && ($> == 0))
{
$anvil->Database->configure_pgsql({debug => 2, uuid => $local_host_uuid});
$anvil->Database->configure_pgsql({
debug => 2,
uuid => $local_host_uuid,
check_db_exists => $check_if_configured,
});
}
# Now setup or however-many connections
@ -1675,7 +1688,6 @@ sub connect
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $count = $anvil->Database->query({uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { count => $count }});
if ($count < 1)
{
@ -1765,6 +1777,9 @@ sub connect
# Record this as successful
$anvil->data->{sys}{database}{connections}++;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"sys::database::connections" => $anvil->data->{sys}{database}{connections},
}});
push @{$successful_connections}, $uuid;
}
@ -1825,6 +1840,9 @@ sub connect
$anvil->data->{sys}{database}{primary_db} = "" if $anvil->data->{sys}{database}{read_active} eq $uuid;
$anvil->data->{sys}{database}{read_uuid} = "" if $anvil->data->{sys}{database}{read_uuid} eq $uuid;
$anvil->data->{sys}{database}{connections}--;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"sys::database::connections" => $anvil->data->{sys}{database}{connections},
}});
delete $anvil->data->{database}{$uuid};
next;
}
@ -3971,7 +3989,7 @@ AND
}});
$anvil->data->{host_from_uuid}{$host_uuid}{full} = $host_name;
$anvil->data->{host_from_uuid}{$host_uuid}{short} = $short_host_name;
$anvil->data->{host_from_uuid}{$host_uuid}{short} = $short_host_name ? $short_host_name : $host_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"host_from_uuid::${host_uuid}::full" => $anvil->data->{host_from_uuid}{$host_uuid}{full},
"host_from_uuid::${host_uuid}::short" => $anvil->data->{host_from_uuid}{$host_uuid}{short},
@ -4470,7 +4488,8 @@ AND
$query = "
SELECT
network_interface_uuid,
network_interface_name
network_interface_name,
network_interface_device
FROM
network_interfaces
WHERE
@ -4488,14 +4507,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},
}});
@ -4561,51 +4584,37 @@ AND
$on_interface = $anvil->data->{hosts}{host_uuid}{$host_uuid}{network_interfaces}{network_interface_uuid}{$ip_address_on_uuid}{network_interface_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { on_interface => $on_interface }});
}
my $on_network = ($on_interface =~ /^(.*?)_/)[0];
if (not defined $on_network)
{
# This isn't a network we should know about (ie: it might be a stray 'virbrX'
# birdge), delete this IP.
my $query = "
UPDATE
ip_addresses
SET
ip_address_note = 'DELETED',
modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
WHERE
ip_address_uuid = ".$anvil->Database->quote($ip_address_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
next;
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { on_network => $on_network }});
# Store it.
$anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{ip_address} = $ip_address_address;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{subnet_mask} = $ip_address_subnet_mask;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{on_interface} = $on_interface;
# We want to be able to map IPs to hosts.
$anvil->data->{ip_addresses}{$ip_address_address}{host_uuid} = $ip_address_host_uuid;
$anvil->data->{ip_addresses}{$ip_address_address}{ip_address_uuid} = $ip_address_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"hosts::host_uuid::${host_uuid}::network::${on_network}::ip_address" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{ip_address},
"hosts::host_uuid::${host_uuid}::network::${on_network}::subnet_mask" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{subnet_mask},
"hosts::host_uuid::${host_uuid}::network::${on_network}::on_interface" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{on_interface},
"ip_addresses::${ip_address_address}::host_uuid" => $anvil->data->{ip_addresses}{$ip_address_address}{host_uuid},
"ip_addresses::${ip_address_address}::ip_address_uuid" => $anvil->data->{ip_addresses}{$ip_address_address}{ip_address_uuid},
}});
$anvil->data->{hosts}{host_uuid}{$host_uuid}{ip_address}{$ip_address_address}{subnet_mask} = $ip_address_subnet_mask;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{ip_address}{$ip_address_address}{on_interface} = $on_interface;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{ip_address}{$ip_address_address}{on_network} = $on_network;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"hosts::host_uuid::${host_uuid}::ip_address::${ip_address_address}::subnet_mask" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{ip_address}{$ip_address_address}{subnet_mask},
"hosts::host_uuid::${host_uuid}::ip_address::${ip_address_address}::on_interface" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{ip_address}{$ip_address_address}{on_interface},
"hosts::host_uuid::${host_uuid}::ip_address::${ip_address_address}::on_network" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{ip_address}{$ip_address_address}{on_network},
}});
# We also want to be able to map IPs to hosts.
$anvil->data->{ip_addresses}{$ip_address_address}{host_uuid} = $ip_address_host_uuid;
$anvil->data->{ip_addresses}{$ip_address_address}{ip_address_uuid} = $ip_address_uuid;
# If this is an interface that doesn't belong to us, we're done.
my $on_network = ($on_interface =~ /^(.*?)_/)[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { on_network => $on_network }});
next if not $on_network;
# Store it by network.
$anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{ip_address} = $ip_address_address;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{subnet_mask} = $ip_address_subnet_mask;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{on_interface} = $on_interface;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{ip_address}{$ip_address_address}{on_network} = $on_network;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"ip_addresses::${ip_address_address}::host_uuid" => $anvil->data->{ip_addresses}{$ip_address_address}{host_uuid},
"ip_addresses::${ip_address_address}::ip_address_uuid" => $anvil->data->{ip_addresses}{$ip_address_address}{ip_address_uuid},
"hosts::host_uuid::${host_uuid}::network::${on_network}::ip_address" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{ip_address},
"hosts::host_uuid::${host_uuid}::network::${on_network}::subnet_mask" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{subnet_mask},
"hosts::host_uuid::${host_uuid}::network::${on_network}::on_interface" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{network}{$on_network}{on_interface},
"hosts::host_uuid::${host_uuid}::ip_address::${ip_address_address}::on_network" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{ip_address}{$ip_address_address}{on_network},
}});
}
@ -6948,6 +6957,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 +6978,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;
@ -7522,7 +7533,6 @@ WHERE
return($anvil_uuid);
}
=head2 insert_or_update_bridges
This updates (or inserts) a record in the 'bridges' table. The C<< bridge_uuid >> referencing the database row will be returned.
@ -7555,6 +7565,10 @@ This is the host that the IP address is on. If not passed, the local C<< sys::ho
This is the bridge's device name.
=head3 bridge_nm_uuid (optional)
This is the network manager UUID for the bridge.
=head3 bridge_id (optional)
This is the unique identifier for the bridge.
@ -7591,6 +7605,7 @@ sub insert_or_update_bridges
my $bridge_uuid = defined $parameter->{bridge_uuid} ? $parameter->{bridge_uuid} : "";
my $bridge_host_uuid = defined $parameter->{bridge_host_uuid} ? $parameter->{bridge_host_uuid} : $anvil->data->{sys}{host_uuid};
my $bridge_name = defined $parameter->{bridge_name} ? $parameter->{bridge_name} : "";
my $bridge_nm_uuid = $parameter->{bridge_nm_uuid} ? $parameter->{bridge_nm_uuid} : 'NULL';
my $bridge_id = defined $parameter->{bridge_id} ? $parameter->{bridge_id} : "";
my $bridge_mac_address = defined $parameter->{bridge_mac_address} ? $parameter->{bridge_mac_address} : "";
my $bridge_mtu = defined $parameter->{bridge_mtu} ? $parameter->{bridge_mtu} : "";
@ -7603,6 +7618,7 @@ sub insert_or_update_bridges
bridge_uuid => $bridge_uuid,
bridge_host_uuid => $bridge_host_uuid,
bridge_name => $bridge_name,
bridge_nm_uuid => $bridge_nm_uuid,
bridge_id => $bridge_id,
bridge_mac_address => $bridge_mac_address,
bridge_mtu => $bridge_mtu,
@ -7735,6 +7751,7 @@ INSERT INTO
(
bridge_uuid,
bridge_host_uuid,
bridge_nm_uuid,
bridge_name,
bridge_id,
bridge_mac_address,
@ -7744,6 +7761,7 @@ INSERT INTO
) VALUES (
".$anvil->Database->quote($bridge_uuid).",
".$anvil->Database->quote($bridge_host_uuid).",
".$anvil->Database->quote($bridge_nm_uuid).",
".$anvil->Database->quote($bridge_name).",
".$anvil->Database->quote($bridge_id).",
".$anvil->Database->quote($bridge_mac_address).",
@ -7752,6 +7770,7 @@ INSERT INTO
".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
);
";
$query =~ s/'NULL'/NULL/g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
$anvil->Database->write({uuid => $uuid, query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__});
}
@ -7761,6 +7780,7 @@ INSERT INTO
my $query = "
SELECT
bridge_host_uuid,
bridge_nm_uuid,
bridge_name,
bridge_id,
bridge_mac_address,
@ -7787,14 +7807,16 @@ WHERE
}
foreach my $row (@{$results})
{
my $old_bridge_host_uuid = $row->[0];
my $old_bridge_name = $row->[1];
my $old_bridge_id = $row->[2];
my $old_bridge_mac_address = $row->[3];
my $old_bridge_mtu = $row->[4];
my $old_bridge_stp_enabled = $row->[5];
my $old_bridge_host_uuid = $row->[0];
my $old_bridge_nm_uuid = defined $row->[1] ? $row->[1] : 'NULL';
my $old_bridge_name = $row->[2];
my $old_bridge_id = $row->[3];
my $old_bridge_mac_address = $row->[4];
my $old_bridge_mtu = $row->[5];
my $old_bridge_stp_enabled = $row->[6];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
old_bridge_host_uuid => $old_bridge_host_uuid,
old_bridge_nm_uuid => $old_bridge_nm_uuid,
old_bridge_name => $old_bridge_name,
old_bridge_id => $old_bridge_id,
old_bridge_mac_address => $old_bridge_mac_address,
@ -7804,6 +7826,7 @@ WHERE
# Anything change?
if (($old_bridge_host_uuid ne $bridge_host_uuid) or
($old_bridge_nm_uuid ne $bridge_nm_uuid) or
($old_bridge_name ne $bridge_name) or
($old_bridge_id ne $bridge_id) or
($old_bridge_mac_address ne $bridge_mac_address) or
@ -7816,6 +7839,7 @@ UPDATE
bridges
SET
bridge_host_uuid = ".$anvil->Database->quote($bridge_host_uuid).",
bridge_nm_uuid = ".$anvil->Database->quote($bridge_nm_uuid).",
bridge_name = ".$anvil->Database->quote($bridge_name).",
bridge_id = ".$anvil->Database->quote($bridge_id).",
bridge_mac_address = ".$anvil->Database->quote($bridge_mac_address).",
@ -7825,6 +7849,7 @@ SET
WHERE
bridge_uuid = ".$anvil->Database->quote($bridge_uuid)."
";
$query =~ s/'NULL'/NULL/g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
$anvil->Database->write({uuid => $uuid, query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__});
}
@ -7871,6 +7896,10 @@ This is the host that the IP address is on. If not passed, the local C<< sys::ho
This is the bond's device name.
=head3 bond_nm_uuid (optional)
This is the network manager UUID for this bond.
=head3 bond_mode (required)
This is the bonding mode used for this bond.
@ -7931,6 +7960,7 @@ sub insert_or_update_bonds
my $bond_uuid = defined $parameter->{bond_uuid} ? $parameter->{bond_uuid} : "";
my $bond_host_uuid = defined $parameter->{bond_host_uuid} ? $parameter->{bond_host_uuid} : $anvil->data->{sys}{host_uuid};
my $bond_name = defined $parameter->{bond_name} ? $parameter->{bond_name} : "";
my $bond_nm_uuid = $parameter->{bond_nm_uuid} ? $parameter->{bond_nm_uuid} : 'NULL';
my $bond_mode = defined $parameter->{bond_mode} ? $parameter->{bond_mode} : "";
my $bond_mtu = defined $parameter->{bond_mtu} ? $parameter->{bond_mtu} : "";
my $bond_primary_interface = defined $parameter->{bond_primary_interface} ? $parameter->{bond_primary_interface} : "";
@ -7941,7 +7971,7 @@ sub insert_or_update_bonds
my $bond_down_delay = defined $parameter->{bond_down_delay} ? $parameter->{bond_down_delay} : "";
my $bond_mac_address = defined $parameter->{bond_mac_address} ? $parameter->{bond_mac_address} : "";
my $bond_operational = defined $parameter->{bond_operational} ? $parameter->{bond_operational} : "";
my $bond_bridge_uuid = defined $parameter->{bond_bridge_uuid} ? $parameter->{bond_bridge_uuid} : 'NULL';
my $bond_bridge_uuid = $parameter->{bond_bridge_uuid} ? $parameter->{bond_bridge_uuid} : 'NULL';
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
uuid => $uuid,
file => $file,
@ -7950,6 +7980,7 @@ sub insert_or_update_bonds
bond_uuid => $bond_uuid,
bond_host_uuid => $bond_host_uuid,
bond_name => $bond_name,
bond_nm_uuid => $bond_nm_uuid,
bond_mode => $bond_mode,
bond_mtu => $bond_mtu,
bond_primary_interface => $bond_primary_interface,
@ -8101,6 +8132,7 @@ INSERT INTO
(
bond_uuid,
bond_host_uuid,
bond_nm_uuid,
bond_name,
bond_mode,
bond_mtu,
@ -8117,6 +8149,7 @@ INSERT INTO
) VALUES (
".$anvil->Database->quote($bond_uuid).",
".$anvil->Database->quote($bond_host_uuid).",
".$anvil->Database->quote($bond_nm_uuid).",
".$anvil->Database->quote($bond_name).",
".$anvil->Database->quote($bond_mode).",
".$anvil->Database->quote($bond_mtu).",
@ -8142,6 +8175,7 @@ INSERT INTO
my $query = "
SELECT
bond_host_uuid,
bond_nm_uuid,
bond_name,
bond_mode,
bond_mtu,
@ -8176,20 +8210,22 @@ WHERE
foreach my $row (@{$results})
{
my $old_bond_host_uuid = $row->[0];
my $old_bond_name = $row->[1];
my $old_bond_mode = $row->[2];
my $old_bond_mtu = $row->[3];
my $old_bond_primary_interface = $row->[4];
my $old_bond_primary_reselect = $row->[5];
my $old_bond_active_interface = $row->[6];
my $old_bond_mii_polling_interval = $row->[7];
my $old_bond_up_delay = $row->[8];
my $old_bond_down_delay = $row->[9];
my $old_bond_mac_address = $row->[10];
my $old_bond_operational = $row->[11];
my $old_bond_bridge_uuid = defined $row->[12] ? $row->[12] : 'NULL';
my $old_bond_nm_uuid = defined $row->[1] ? $row->[1] : 'NULL';
my $old_bond_name = $row->[2];
my $old_bond_mode = $row->[3];
my $old_bond_mtu = $row->[4];
my $old_bond_primary_interface = $row->[5];
my $old_bond_primary_reselect = $row->[6];
my $old_bond_active_interface = $row->[7];
my $old_bond_mii_polling_interval = $row->[8];
my $old_bond_up_delay = $row->[9];
my $old_bond_down_delay = $row->[10];
my $old_bond_mac_address = $row->[11];
my $old_bond_operational = $row->[12];
my $old_bond_bridge_uuid = defined $row->[13] ? $row->[12] : 'NULL';
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
old_bond_host_uuid => $old_bond_host_uuid,
old_bond_nm_uuid => $old_bond_nm_uuid,
old_bond_name => $old_bond_name,
old_bond_mode => $old_bond_mode,
old_bond_mtu => $old_bond_mtu,
@ -8206,6 +8242,7 @@ WHERE
# Anything change?
if (($old_bond_host_uuid ne $bond_host_uuid) or
($old_bond_nm_uuid ne $bond_nm_uuid) or
($old_bond_name ne $bond_name) or
($old_bond_mode ne $bond_mode) or
($old_bond_mtu ne $bond_mtu) or
@ -8225,6 +8262,7 @@ UPDATE
bonds
SET
bond_host_uuid = ".$anvil->Database->quote($bond_host_uuid).",
bond_nm_uuid = ".$anvil->Database->quote($bond_nm_uuid).",
bond_name = ".$anvil->Database->quote($bond_name).",
bond_mode = ".$anvil->Database->quote($bond_mode).",
bond_mtu = ".$anvil->Database->quote($bond_mtu).",
@ -9606,9 +9644,9 @@ sub insert_or_update_hosts
my $line = defined $parameter->{line} ? $parameter->{line} : "";
my $host_ipmi = defined $parameter->{host_ipmi} ? $parameter->{host_ipmi} : "";
my $host_key = defined $parameter->{host_key} ? $parameter->{host_key} : "";
my $host_name = defined $parameter->{host_name} ? $parameter->{host_name} : $anvil->Get->host_name;
my $host_type = defined $parameter->{host_type} ? $parameter->{host_type} : $anvil->Get->host_type;
my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : $anvil->Get->host_uuid;
my $host_name = defined $parameter->{host_name} ? $parameter->{host_name} : "";
my $host_type = defined $parameter->{host_type} ? $parameter->{host_type} : "";
my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : "";
my $host_status = defined $parameter->{host_status} ? $parameter->{host_status} : "no_change";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
uuid => $uuid,
@ -9624,15 +9662,34 @@ sub insert_or_update_hosts
if (not $host_name)
{
# Throw an error and exit.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_hosts()", parameter => "host_name" }});
return("");
# Can we get it?
$host_name = $anvil->Get->host_name({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_name => $host_name }});
if (not $host_name)
{
# Throw an error and exit.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_hosts()", parameter => "host_name" }});
return("");
}
}
if (not $host_type)
{
$host_type = $anvil->Get->host_type({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_type => $host_type }});
}
if (not $host_uuid)
{
# Throw an error and exit.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_hosts()", parameter => "host_uuid" }});
return("");
# Can we get it?
$host_uuid = $anvil->Get->host_uuid({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
if (not $host_uuid)
{
# Throw an error and exit.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_hosts()", parameter => "host_uuid" }});
return("");
}
}
# If we're looking at ourselves and we don't have the host_key, read it in.
@ -11364,6 +11421,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.
@ -11390,7 +11451,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_nm_uuid (optional)
This is the network manager's UUID for this interface.
=head3 network_interface_operational (optional)
@ -11420,6 +11485,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";
@ -11428,6 +11494,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_nm_uuid = defined $parameter->{network_interface_nm_uuid} ? $parameter->{network_interface_nm_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 => {
@ -11438,6 +11505,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,
@ -11446,6 +11514,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_nm_uuid => $network_interface_nm_uuid,
network_interface_speed => $network_interface_speed,
network_interface_uuid => $network_interface_uuid,
}});
@ -11504,6 +11573,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
@ -11522,6 +11592,68 @@ AND
$network_interface_uuid = $results->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { network_interface_uuid => $network_interface_uuid }});
}
elsif ($network_interface_device)
{
# Try again using the device name.
my $query = "
SELECT
network_interface_uuid
FROM
network_interfaces
WHERE ";
if ($network_interface_name !~ /^vnet/)
{
$query .= "
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_device = ".$anvil->Database->quote($network_interface_device)."
AND
network_interface_host_uuid = ".$anvil->Database->quote($network_interface_host_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({uuid => $uuid, query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
if ($count)
{
$network_interface_uuid = $results->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { network_interface_uuid => $network_interface_uuid }});
}
}
elsif ($network_interface_name !~ /^vnet/)
{
# Try finding it by MAC
my $query = "
SELECT
network_interface_uuid
FROM
network_interfaces
WHERE
network_interface_mac_address = ".$anvil->Database->quote($network_interface_mac_address)."
AND
network_interface_host_uuid = ".$anvil->Database->quote($network_interface_host_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({uuid => $uuid, query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
if ($count)
{
$network_interface_uuid = $results->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { network_interface_uuid => $network_interface_uuid }});
}
}
if (($link_only) && (not $network_interface_uuid))
{
@ -11585,8 +11717,10 @@ WHERE
my $query = "
SELECT
network_interface_host_uuid,
network_interface_nm_uuid,
network_interface_mac_address,
network_interface_name,
network_interface_device,
network_interface_speed,
network_interface_mtu,
network_interface_link_state,
@ -11617,20 +11751,24 @@ WHERE
foreach my $row (@{$results})
{
my $old_network_interface_host_uuid = $row->[0];
my $old_network_interface_nm_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_nm_uuid => $old_network_interface_nm_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,
@ -11644,7 +11782,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_nm_uuid ne $old_network_interface_nm_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
@ -11656,7 +11796,9 @@ UPDATE
network_interfaces
SET
network_interface_host_uuid = ".$anvil->Database->quote($network_interface_host_uuid).",
network_interface_nm_uuid = ".$anvil->Database->quote($network_interface_nm_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).",
@ -11676,7 +11818,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_nm_uuid ne $old_network_interface_nm_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
@ -11692,9 +11836,11 @@ UPDATE
network_interfaces
SET
network_interface_host_uuid = ".$anvil->Database->quote($network_interface_host_uuid).",
network_interface_nm_uuid = ".$anvil->Database->quote($network_interface_nm_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).",
@ -11723,9 +11869,11 @@ INSERT INTO
network_interfaces
(
network_interface_uuid,
network_interface_nm_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,
@ -11737,9 +11885,11 @@ INSERT INTO
modified_date
) VALUES (
".$anvil->Database->quote($network_interface_uuid).",
".$anvil->Database->quote($network_interface_nm_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).",
@ -17825,7 +17975,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,
}});
@ -18071,7 +18221,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,
@ -18494,7 +18644,6 @@ sub track_files
}});
next if $file_type eq "DELETED";
### TODO - Left off here, not adding DR links.
my $anvil_needs_file = 0;
foreach my $host_uuid ($anvil_node1_host_uuid, $anvil_node2_host_uuid)
{
@ -18679,6 +18828,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.
@ -18718,20 +18871,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)
@ -18765,7 +18921,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;
@ -18822,6 +18978,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)
{
@ -18852,6 +19012,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 }});
}
}
}
@ -18867,8 +19028,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 => {
@ -18886,7 +19050,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,
}});
}
@ -18905,6 +19069,7 @@ sub write
's1:test' => $test,
's2:$@' => $@,
}});
if (not $test)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0090", variables => {

@ -487,9 +487,9 @@ sub send_alerts
if ($alert_title)
{
my $title = "[ ".$alert_set_by." ] ".$anvil->Words->parse_banged_string({
debug => $debug,
language => $recipient_language,
key_string => $alert_title,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { title => $title }});

@ -1513,10 +1513,29 @@ sub host_name
{
# Failed to read the file, too. What the hell? Exit out.
print "Failed to query the hostname using 'hostnamectl --static' and failed to read the content of: [".$anvil->data->{path}{configs}{hostname}."]. Something is very wrong, exiting.\n";
$anvil->nice_exit({exit_code => 1});
}
}
else
{
# Did we get a real answer? If it's "unet", the string will be emtpy.
if (not $host_name)
{
# Try seeing if there is a transient hostname.
($host_name, my $return_code) = $anvil->System->call({debug => 9999, shell_call => $anvil->data->{path}{exe}{hostnamectl}." --transient"});
if (not $host_name)
{
# OK, can we get it from the 'hostname' command?
($host_name, my $return_code) = $anvil->System->call({debug => 9999, shell_call => $anvil->data->{path}{exe}{hostname}});
if (not $host_name)
{
# Failed to find the hostname at all.
print "Failed to query the hostname using 'hostnamectl --static', 'hostnamectl --transient' or 'hostname'. Something is very wrong, exiting.\n";
$anvil->nice_exit({exit_code => 1});
}
}
}
# Cache the answer
$anvil->data->{sys}{host_name} = $host_name;
}
@ -2146,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

@ -12,6 +12,7 @@ our $VERSION = "3.0.0";
my $THIS_FILE = "Job.pm";
### Methods;
# bump_progress
# clear
# get_job_details
# get_job_uuid
@ -80,6 +81,84 @@ sub parent
# Public methods #
#############################################################################################################
=head2 bump_progress
This method is meant to make it easier to bump the progress of a jump by some number of steps when a job doesn't run in a linear fashion.
It does this by storing the progress in the C<< sys::job_progress >> hash and incrementing it by the C<< steps >> parameter value (setting it to C<< 0 >> if it doesn't exist or exists with a non-digit value). If the progress goes over C<< 99 >>, it will return C<< 99 >>.
If you want to set the progress to C<< 0 >> or C<< 100 >>, use the C<< set >> parameter.
Parameters;
=head3 set (optional)
If you want to set the progress to a specific value, use this parameter.
B<< NOTE >>: If the set value is less than the current value, the current progress + 1 will be returns. This is meant to prevent progress bars from backing up.
=head3 steps (default '1')
This takes an integer and it will increase the job progress by that value. If this is not specified, or if it is set to a non-integer value, C<< 1 >> will be used.
=cut
sub bump_progress
{
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 => "Job->bump_progress()" }});
my $set = defined $parameter->{set} ? $parameter->{set} : "";
my $steps = defined $parameter->{steps} ? $parameter->{steps} : 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
set => $set,
steps => $steps,
}});
if ((not exists $anvil->data->{sys}{job_progress}) or ($anvil->data->{sys}{job_progress} !~ /^\d+$/))
{
$anvil->data->{sys}{job_progress} = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"sys::job_progress" => $anvil->data->{sys}{job_progress},
}});
}
if ($set =~ /^\d+$/)
{
if ($set > 100)
{
$anvil->data->{sys}{job_progress} = 100;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"sys::job_progress" => $anvil->data->{sys}{job_progress},
}});
}
elsif ($set > $anvil->data->{sys}{job_progress})
{
$anvil->data->{sys}{job_progress}++;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"sys::job_progress" => $anvil->data->{sys}{job_progress},
}});
}
}
$anvil->data->{sys}{job_progress} += $steps;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"sys::job_progress" => $anvil->data->{sys}{job_progress},
}});
if ($anvil->data->{sys}{job_progress} > 99)
{
$anvil->data->{sys}{job_progress} = 99;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"sys::job_progress" => $anvil->data->{sys}{job_progress},
}});
}
return($anvil->data->{sys}{job_progress});
}
=head2 clear
This clears the C<< job_picked_up_by >> value for the given job.
@ -501,8 +580,8 @@ sub html_list
}
# Convert the double-banged strings into a proper message.
my $say_title = $job_title ? $anvil->Words->parse_banged_string({key_string => $job_title}) : "";
my $say_description = $job_description ? $anvil->Words->parse_banged_string({key_string => $job_description}) : "";
my $say_title = $job_title ? $anvil->Words->parse_banged_string({debug => $debug, key_string => $job_title}) : "";
my $say_description = $job_description ? $anvil->Words->parse_banged_string({debug => $debug, key_string => $job_description}) : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
job_title => $job_title,
say_description => $say_description,
@ -537,10 +616,18 @@ B<< Note >>: Some special C<< job_status >> processing is done to support some s
Parameters;
=head3 file (optional)
When logging as well, this is the file causing the update. Use with C<< line >>. Ignored if C<< log_level >> is not set, or such that it wouldn't be logged anyway.
=head3 job_uuid (optional, default 'jobs::job_uuid')
This is the UUID of the job to update. If it isn't set, but C<< jobs::job_uuid >> is set, it will be used. If that is also not set,
=head3 line (optional_
When logging as well, this is the line the update came from. Use with C<< file >>. Ignored if C<< log_level >> is not set, or such that it wouldn't be logged anyway.
=head3 log_level (optional)
If set to a numeric level, the job's message will also be logged. This is designed to simplify code as most job progress messages will also want to be logged.
@ -584,7 +671,9 @@ sub update_progress
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Job->update_progress()" }});
my $file = defined $parameter->{file} ? $parameter->{file} : $THIS_FILE;
my $job_uuid = defined $parameter->{job_uuid} ? $parameter->{job_uuid} : "";
my $line = defined $parameter->{line} ? $parameter->{line} : __LINE__;
my $log_level = defined $parameter->{log_level} ? $parameter->{log_level} : "";
my $message = defined $parameter->{message} ? $parameter->{message} : "";
my $picked_up_by = defined $parameter->{picked_up_by} ? $parameter->{picked_up_by} : "";
@ -594,11 +683,13 @@ sub update_progress
my $secure = defined $parameter->{secure} ? $parameter->{secure} : "";
my $variables = defined $parameter->{variables} ? $parameter->{variables} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
file => $file,
job_uuid => $job_uuid,
line => $line,
log_level => $log_level,
picked_up_by => $picked_up_by,
'print' => $print,
progress => $progress,
log_level => $log_level,
message => $message,
variables => $variables,
secure => $secure,
@ -608,7 +699,7 @@ sub update_progress
if (($message ne "clear") && ($log_level =~ /^\d+$/))
{
# Log this message.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, 'print' => $print, secure => $secure, priority => $priority, key => $message, variables => $variables});
$anvil->Log->entry({source => $file, line => $line, level => $log_level, 'print' => $print, secure => $secure, priority => $priority, key => $message, variables => $variables});
}
if ($picked_up_by eq "")
@ -654,6 +745,12 @@ sub update_progress
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::last_update" => $anvil->data->{sys}{last_update} }});
}
# If we don't have a database connection, we're done.
if (not $anvil->data->{sys}{database}{connections})
{
return(0);
}
# Add variables to the message, if required
if (ref($variables) eq "HASH")
{

@ -491,7 +491,7 @@ sub entry
binmode($anvil->data->{HANDLE}{'log'}{main}, ':encoding(utf-8)');
print $THIS_FILE." ".__LINE__."; HANDLE::log::main: [".$anvil->data->{HANDLE}{'log'}{main}."]\n" if $test;
# Make sure it can be written to by apache.
# Make sure it can be written to by striker-ui-api.
$anvil->Storage->change_mode({test => $test, debug => $debug, path => $log_file, mode => "0666"});
}
@ -531,7 +531,7 @@ sub entry
$anvil->data->{HANDLE}{'log'}{alert} = $file_handle;
print $THIS_FILE." ".__LINE__."; HANDLE::log::alert: [".$anvil->data->{HANDLE}{'log'}{alert}."]\n" if $test;
# Make sure it can be written to by apache.
# Make sure it can be written to by striker-ui-api.
$anvil->Storage->change_mode({test => $test, debug => $debug, path => $log_file, mode => "0666"});
}

File diff suppressed because it is too large Load Diff

@ -3232,6 +3232,8 @@ fi;";
=head2 manage_lvm_conf
B<< Note >>: This only works on EL8. If used on another distro, this method will return without actually doing anything.
This method configures C<< lvm.conf >> to add the C<< filter = [ ... ] >> to ensure DRBD devices aren't scanned.
If there was a problem, C<< 1 >> is returned. Otherwise, C<< 0 >> is returned.
@ -3274,6 +3276,18 @@ sub manage_lvm_conf
target => $target,
}});
### NOTE: Only add the filter on EL8 machines.
my ($os_type, $os_arch) = $anvil->Get->os_type({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
os_type => $os_type,
os_arch => $os_arch,
}});
if ($os_type !~ /\D8/)
{
# Not EL8, return
return(0);
}
my $body = $anvil->Storage->read_file({
debug => $debug,
file => $anvil->data->{path}{configs}{'lvm.conf'},

@ -14,7 +14,7 @@ our $VERSION = "3.0.0";
my $THIS_FILE = "Striker.pm";
### Methods;
# check_httpd_conf
# check_httpd_conf - Deprecated
# generate_manifest
# get_fence_data
# get_local_repo

@ -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,62 @@ 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.
The results are cached in C<< sys::network_type >>.
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()" }});
if ((exists $anvil->data->{sys}{network_type}) && ($anvil->data->{sys}{network_type}))
{
# Cached.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::network_type" => $anvil->data->{sys}{network_type} }});
return($anvil->data->{sys}{network_type});
}
# 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);
}
# Cache the results
$anvil->data->{sys}{network_type} = $type;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::network_type" => $anvil->data->{sys}{network_type} }});
return($anvil->data->{sys}{network_type});
}
=head2 check_storage
Thic gathers LVM data from the local system.
@ -2790,6 +2847,7 @@ sub disable_daemon
return($return_code);
}
=head2 generate_state_json
This method generates the C<< all_status.json >> file.
@ -2879,13 +2937,14 @@ sub generate_state_json
my $mac_address = $anvil->data->{network}{$host}{interface}{$interface}{mac_address};
my $iface_hash = {};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:interface" => $interface,
"s2:mac_address" => $mac_address,
"s3:type" => $type,
"s4:mtu" => $mtu,
"s5:configured" => $configured,
"s6:host_uuid" => $host_uuid,
"s7:host_key" => $host_key,
"s1:host" => $host,
"s2:interface" => $interface,
"s3:mac_address" => $mac_address,
"s4:type" => $type,
"s5:mtu" => $mtu,
"s6:configured" => $configured,
"s7:host_uuid" => $host_uuid,
"s8:host_key" => $host_key,
}});
$iface_hash->{name} = $interface;
$iface_hash->{type} = $type;
@ -3191,8 +3250,8 @@ sub generate_state_json
backup => 0,
file => $json_file,
body => $json,
group => "apache",
user => "apache",
group => "striker-ui-api",
user => "striker-ui-api",
mode => "0644",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { error => $error }});

@ -247,6 +247,7 @@ setenforce 0
### TODO: check it if was disabled (if it existed before) and, if so, leave it disabled.
systemctl enable --now chronyd.service
systemctl enable --now anvil-daemon.service
systemctl enable --now anvil-monitor-network.service
systemctl enable --now scancore.service
%pre striker
@ -285,11 +286,6 @@ then
systemctl enable gdm.service
fi
### This is handled by anvil-daemon now
#echo "Preparing the database"
#striker-prep-database
#anvil-update-states
# Touch the system type file.
echo "Touching the system type file"
if [ -e '/etc/anvil/type.node' ]

@ -35,9 +35,6 @@ Check to see if the host is marked as configured or yet.
\fB\-\-check\-database\fR
This checks to see if the database is enabled or not.
.TP
\fB\-\-check\-network\-mapping\fR
This reports if the host is currently in network mapping (this disables several features and watches the network states much more frequently)
.TP
\fB\-\-confirm\fR
This confirms actions that would normally prompt the user to confirm before proceeding.
.TP
@ -47,12 +44,6 @@ This enables the database on the local Striker dashboard.
\fB\-\-database\-inactive\fR
This disables the database on the local Striker dashboard.
.TP
\fB\-\-disable\-network\-mapping\fR
This disables the network mapping mode.
.TP
\fB\-\-enable\-network\-mapping\fR
This enables the network mapping mode.
.TP
\fB\-\-mark\-configured\fR
This marks the host as having been configured.
.TP

@ -69,6 +69,9 @@ if ($anvil->data->{switches}{purge})
$anvil->nice_exit({exit_code => 0});
}
# If there's no DB (or cached data isn't recorded to the database yet), this will store those records.
$anvil->data->{cache}{new_file} = "# interface (nm_device),timestamp,mac_address,speed,link_state,operational,nm_uuid,nm_name\n";
process_interface_cache($anvil);
# Read the data.
collect_data($anvil);
@ -88,6 +91,18 @@ clear_old_variables($anvil);
# This removes network interfaces that have been marked as DELETED for a while now.
clear_old_interfaces($anvil);
# Write out the interface cache
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
"cache::new_file" => $anvil->data->{cache}{new_file},
"path::data::network_cache" => $anvil->data->{path}{data}{network_cache},
}});
$anvil->Storage->write_file({
body => $anvil->data->{cache}{new_file},
file => $anvil->data->{path}{data}{network_cache},
overwrite => 1,
backup => 0,
});
# Shut down.
$anvil->ScanCore->agent_shutdown({agent => $THIS_FILE});
@ -96,6 +111,66 @@ $anvil->ScanCore->agent_shutdown({agent => $THIS_FILE});
# Functions #
#############################################################################################################
# This reads in the interface cache file and looks for records that haven't been stored in the database yet.
sub process_interface_cache
{
my ($anvil) = @_;
# Does the file exist? If so, read it in.
if (-e $anvil->data->{path}{data}{network_cache})
{
my $body = $anvil->Storage->read_file({debug => 2, cache => 0, force_read => 1, file => $anvil->data->{path}{data}{network_cache}});
foreach my $line (split/\n/, $body)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
next if $line =~ /^#/;
my ($nm_device, $timestamp, $mac_address, $speed, $link_state, $operational, $nm_uuid, $nm_name) = (split/,/, $line);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
timestamp => $timestamp,
speed => $speed,
mac_address => $mac_address,
link_state => $link_state,
operational => $operational,
nm_uuid => $nm_uuid,
nm_device => $nm_device,
}});
if ($anvil->data->{sys}{database}{connections})
{
my ($network_interface_uuid) = $anvil->Database->insert_or_update_network_interfaces({
debug => 2,
link_only => 1,
timestamp => $timestamp,
network_interface_name => $nm_device,
network_interface_link_state => $link_state,
network_interface_mac_address => $mac_address,
network_interface_operational => $operational,
network_interface_speed => $speed,
network_interface_nm_uuid => $nm_uuid,
network_interface_device => $nm_device,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { network_interface_uuid => $network_interface_uuid }});
if (not $network_interface_uuid)
{
# Failed to update, could be that we cached data for an interface not yet
# seen. If so, the coming scan will add it and this cache should flush out
# next time.
$anvil->data->{cache}{new_file} .= $line."\n";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "cache::new_file" => $anvil->data->{cache}{new_file} }});
}
}
else
{
# No database, re-cache
$anvil->data->{cache}{new_file} .= $line."\n";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "cache::new_file" => $anvil->data->{cache}{new_file} }});
}
}
}
return(0);
}
# This removes network interfaces that have been marked as DELETED for a while now.
sub clear_old_interfaces
{
@ -124,7 +199,7 @@ sub clear_old_interfaces
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
uuid => $anvil->Database->get_host_from_uuid({short => 1, host_uuid => $uuid})." (".$uuid.")",
uuid => $anvil->Database->get_host_from_uuid({debug => 2, short => 1, host_uuid => $uuid})." (".$uuid.")",
}});
my $query = "
SELECT
@ -460,19 +535,12 @@ 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})
}
# Read in data from Network Manager
$anvil->Network->collect_data({debug => 2});
### TODO: We can get the IPs from collect_data, we should phase this out.
# 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 +548,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,61 +585,11 @@ 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)
{
# Virsh is up.
foreach my $line (split/\n/, $output)
{
$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});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
$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});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
# 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,
});
}
}
=cut
}
# 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 }});
@ -584,27 +603,27 @@ sub collect_data
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { full_path => $full_path }});
if (-d $full_path)
{
### NOTE: The 'interface' maps to the network manager 'GENERAL.IP-IFACE', which is
### 'network_interface_device'. The 'network_interface_name' is the biosdevname.
# 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;
$link_state =~ s/\n$//;
my $mtu = -e $full_path."/mtu" ? $anvil->Storage->read_file({file => $full_path."/mtu"}) : 0;
$mtu =~ s/\n$//;
my $duplex = -e $full_path."/duplex" ? $anvil->Storage->read_file({file => $full_path."/duplex"}) : "unknown"; # full or half?
$duplex =~ s/\n$//;
my $operational = -e $full_path."/operstate" ? $anvil->Storage->read_file({file => $full_path."/operstate"}) : "unknown"; # up or down
$operational =~ s/\n$//;
my $modalias = -e $full_path."/device/modalias" ? $anvil->Storage->read_file({file => $full_path."/device/modalias"}) : "unknown";
$modalias =~ s/\n$//;
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$//;
$speed =~ s/\n$//;
my $media = "unknown";
my $type = "interface";
my $driver = "";
my $tx_bytes = 0; # How many bytes transmitted
my $rx_bytes = 0; # How many bytes received
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
interface => $interface,
link_state => $link_state,
@ -615,6 +634,31 @@ sub collect_data
modalias => $modalias,
}});
# Try to find the nm_uuid
my $nm_uuid = "";
if ((exists $anvil->data->{nmcli}{name}{$interface}) && ($anvil->data->{nmcli}{name}{$interface}{uuid}))
{
$nm_uuid = $anvil->data->{nmcli}{name}{$interface}{uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { nm_uuid => $nm_uuid }});
}
elsif ((exists $anvil->data->{nmcli}{device}{$interface}) && ($anvil->data->{nmcli}{device}{$interface}{uuid}))
{
$nm_uuid = $anvil->data->{nmcli}{device}{$interface}{uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { nm_uuid => $nm_uuid }});
}
my $nm_device = ""; # biosdevname
my $nm_name = ""; # ip name
if ($nm_uuid)
{
$nm_device = $anvil->data->{nmcli}{uuid}{$nm_uuid}{device};
$nm_name = $anvil->data->{nmcli}{uuid}{$nm_uuid}{name};
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
nm_device => $nm_device,
nm_name => $nm_name,
}});
### NOTE: This only parses virtio so far.
# Pick out our driver.
if ($modalias =~ /^virtio:/)
@ -729,7 +773,12 @@ sub collect_data
{
# Yup, we'll neet to dig into the bond proc files to get the proper slaved
# interface MAC addresses.
$type = "bond";
$type = "bond";
$nm_uuid = $anvil->data->{nmcli}{bond}{$interface}{uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
type => $type,
nm_uuid => $nm_uuid,
}});
# Read the bond mode.
$bond_mode = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/mode"});
@ -777,9 +826,9 @@ sub collect_data
$bridge_stp_enabled =~ s/\n$//;
$speed = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
type => $type,
bridge_id => $bridge_id,
bridge_stp_enabled => $bridge_stp_enabled,
type => $type,
}});
if ($bridge_stp_enabled eq "0")
{
@ -851,7 +900,7 @@ sub collect_data
}
# Find the media, if possible.
(my $ethtool, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{ethtool}." $interface"});
(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 }});
@ -871,6 +920,9 @@ sub collect_data
}
# Store new information we found.
$anvil->data->{network}{$local_host}{interface}{$interface}{nm_uuid} = $nm_uuid;
$anvil->data->{network}{$local_host}{interface}{$interface}{nm_device} = $nm_device;
$anvil->data->{network}{$local_host}{interface}{$interface}{nm_name} = $nm_name;
$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;
@ -892,6 +944,9 @@ sub collect_data
$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}::nm_uuid" => $anvil->data->{network}{$local_host}{interface}{$interface}{nm_uuid},
"network::${local_host}::interface::${interface}::nm_device" => $anvil->data->{network}{$local_host}{interface}{$interface}{nm_device},
"network::${local_host}::interface::${interface}::nm_name" => $anvil->data->{network}{$local_host}{interface}{$interface}{nm_name},
"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},
@ -921,7 +976,12 @@ sub collect_data
# 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 => {
nm_name => $nm_name,
nm_device => $nm_device,
}});
# nm_device,timestamp,mac_address,speed,link_state,operational,nm_uuid,nm_name
$anvil->data->{cache}{new_file} .= $nm_device.",".$anvil->Database->refresh_timestamp.",".$mac_address.",".$speed.",".$link_state.",".$operational.",".$nm_uuid.",".$nm_name."\n";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"cache::new_file" => $anvil->data->{cache}{new_file},
}});
@ -950,6 +1010,7 @@ sub collect_data
if ($type eq "bridge")
{
# Store the bridge
$anvil->data->{new}{bridge}{$interface}{nm_uuid} = $anvil->data->{network}{$local_host}{interface}{$interface}{nm_uuid};
$anvil->data->{new}{bridge}{$interface}{id} = $anvil->data->{network}{$local_host}{interface}{$interface}{bridge_id};
$anvil->data->{new}{bridge}{$interface}{mac_address} = $anvil->data->{network}{$local_host}{interface}{$interface}{mac_address};
$anvil->data->{new}{bridge}{$interface}{mtu} = $anvil->data->{network}{$local_host}{interface}{$interface}{mtu};
@ -957,6 +1018,7 @@ sub collect_data
$anvil->data->{new}{bridge}{$interface}{tx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{tx_bytes};
$anvil->data->{new}{bridge}{$interface}{rx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{rx_bytes};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"new::bridge::${interface}::nm_uuid" => $anvil->data->{new}{bridge}{$interface}{nm_uuid},
"new::bridge::${interface}::id" => $anvil->data->{new}{bridge}{$interface}{id},
"new::bridge::${interface}::mac_address" => $anvil->data->{new}{bridge}{$interface}{mac_address},
"new::bridge::${interface}::mtu" => $anvil->data->{new}{bridge}{$interface}{mtu},
@ -968,6 +1030,7 @@ sub collect_data
elsif ($type eq "bond")
{
# Store the bond
$anvil->data->{new}{bond}{$interface}{nm_uuid} = $anvil->data->{network}{$local_host}{interface}{$interface}{nm_uuid};
$anvil->data->{new}{bond}{$interface}{mode} = $anvil->data->{network}{$local_host}{interface}{$interface}{bond_mode};
$anvil->data->{new}{bond}{$interface}{mtu} = $anvil->data->{network}{$local_host}{interface}{$interface}{mtu};
$anvil->data->{new}{bond}{$interface}{master} = $anvil->data->{network}{$local_host}{interface}{$interface}{bond_master};
@ -984,6 +1047,7 @@ sub collect_data
$anvil->data->{new}{bond}{$interface}{tx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{tx_bytes};
$anvil->data->{new}{bond}{$interface}{rx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{rx_bytes};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"new::bond::${interface}::nm_uuid" => $anvil->data->{new}{bond}{$interface}{nm_uuid},
"new::bond::${interface}::mode" => $anvil->data->{new}{bond}{$interface}{mode},
"new::bond::${interface}::mtu" => $anvil->data->{new}{bond}{$interface}{mtu},
"new::bond::${interface}::master" => $anvil->data->{new}{bond}{$interface}{master},
@ -1004,6 +1068,9 @@ sub collect_data
elsif ($type eq "interface")
{
# Store the interface
$anvil->data->{new}{interface}{$interface}{nm_uuid} = $anvil->data->{network}{$local_host}{interface}{$interface}{nm_uuid};
$anvil->data->{new}{interface}{$interface}{nm_device} = $anvil->data->{network}{$local_host}{interface}{$interface}{nm_device};
$anvil->data->{new}{interface}{$interface}{nm_name} = $anvil->data->{network}{$local_host}{interface}{$interface}{nm_name};
$anvil->data->{new}{interface}{$interface}{bond_uuid} = "";
$anvil->data->{new}{interface}{$interface}{bond_name} = $anvil->data->{network}{$local_host}{interface}{$interface}{bond_master};
$anvil->data->{new}{interface}{$interface}{bridge_uuid} = "";
@ -1018,6 +1085,9 @@ sub collect_data
$anvil->data->{new}{interface}{$interface}{tx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{tx_bytes};
$anvil->data->{new}{interface}{$interface}{rx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{rx_bytes};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"new::interface::${interface}::nm_uuid" => $anvil->data->{new}{interface}{$interface}{nm_uuid},
"new::interface::${interface}::nm_device" => $anvil->data->{new}{interface}{$interface}{nm_device},
"new::interface::${interface}::nm_name" => $anvil->data->{new}{interface}{$interface}{nm_name},
"new::interface::${interface}::bond_uuid" => $anvil->data->{new}{interface}{$interface}{bond_uuid},
"new::interface::${interface}::bond_name" => $anvil->data->{new}{interface}{$interface}{bond_name},
"new::interface::${interface}::bridge_uuid" => $anvil->data->{new}{interface}{$interface}{bridge_uuid},
@ -1032,48 +1102,6 @@ sub collect_data
"new::interface::${interface}::tx_bytes" => $anvil->data->{new}{interface}{$interface}{tx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new}{interface}{$interface}{tx_bytes}}).")",
"new::interface::${interface}::rx_bytes" => $anvil->data->{new}{interface}{$interface}{rx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new}{interface}{$interface}{rx_bytes}}).")",
}});
# On some occassions, an interface that is in a bond won't start. If the host uptime
# is less than ten minutes, and a bond's member interface is down, up it.
if ($uptime < 600)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"nmcli::${local_host}::device_to_uuid::${interface}" => $anvil->data->{nmcli}{$local_host}{device_to_uuid}{$interface},
}});
my $uuid = $anvil->data->{nmcli}{$local_host}{device_to_uuid}{$interface};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uuid => $uuid }});
if ($uuid)
{
my $state = $anvil->data->{nmcli}{$local_host}{uuid}{$uuid}{'state'};
my $filename = $anvil->data->{nmcli}{$local_host}{uuid}{$uuid}{filename};
my $name = ($filename =~ /ifcfg-(.*?)$/)[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
filename => $filename,
name => $name,
'state' => $state,
}});
# This could be 'active' or 'activated'
if ($state !~ /activ/)
{
# Try brinding the interface up.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "warning_0147", variables => {
interface => $interface,
uptime => $uptime,
'state' => $state,
}});
my $shell_call = $anvil->data->{path}{exe}{ifup}." ".$name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
}
}
}
}
# Record the IP address info.
@ -1779,8 +1807,10 @@ sub load_interface_data
my $query = "
SELECT
network_interface_uuid,
network_interface_nm_uuid,
network_interface_mac_address,
network_interface_name,
network_interface_device,
network_interface_speed,
network_interface_mtu,
network_interface_link_state,
@ -1805,12 +1835,14 @@ WHERE
foreach my $row (@{$results})
{
my $network_interface_uuid = $row->[0];
my $network_interface_mac_address = $row->[1];
my $network_interface_name = $row->[2];
my $network_interface_mac_address = $row->[2];
my $network_interface_name = $row->[3];
my $network_interface_device = $row->[4];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
network_interface_uuid => $network_interface_uuid,
network_interface_mac_address => $network_interface_mac_address,
network_interface_name => $network_interface_name,
network_interface_device => $network_interface_device,
}});
# Read in the RX/TX values, set to '0' if not found.
@ -1833,23 +1865,27 @@ WHERE
tx_variable_uuid => $tx_variable_uuid,
}});
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_nm_uuid} = $row->[1];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address} = $network_interface_mac_address;
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_name} = $network_interface_name;
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_speed} = $row->[3];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mtu} = $row->[4];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_link_state} = $row->[5];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational} = $row->[6];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_duplex} = $row->[7];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_medium} = $row->[8];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid} = defined $row->[9] ? $row->[9] : '';
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid} = defined $row->[10] ? $row->[10] : '';
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_device} = $network_interface_device;
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_speed} = $row->[5];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mtu} = $row->[6];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_link_state} = $row->[7];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational} = $row->[8];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_duplex} = $row->[9];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_medium} = $row->[10];
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid} = defined $row->[11] ? $row->[11] : '';
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid} = defined $row->[12] ? $row->[12] : '';
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_bytes} = $rx_bytes =~ /^\d+$/ ? $rx_bytes : 0;
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_variable_uuid} = $rx_variable_uuid;
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_bytes} = $tx_bytes =~ /^\d+$/ ? $tx_bytes : 0;
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_variable_uuid} = $tx_variable_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_nm_uuid" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_nm_uuid},
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_mac_address" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address},
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_name" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_name},
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_device" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_device},
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_speed" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_speed},
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_mtu" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mtu},
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_link_state" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_link_state},
@ -1865,14 +1901,18 @@ WHERE
}});
$anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name} = $network_interface_uuid;
$anvil->data->{network_interfaces}{device_to_uuid}{$network_interface_device} = $network_interface_uuid;
$anvil->data->{network_interfaces}{uuid_to_name}{$network_interface_uuid} = $network_interface_name;
$anvil->data->{network_interfaces}{mac_to_uuid}{$network_interface_mac_address} = $network_interface_uuid;
$anvil->data->{interface}{name_to_uuid}{$network_interface_name} = $network_interface_uuid;
$anvil->data->{interface}{device_to_uuid}{$network_interface_device} = $network_interface_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"network_interfaces::name_to_uuid::${network_interface_name}" => $anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name},
"network_interfaces::device_to_uuid::${network_interface_device}" => $anvil->data->{network_interfaces}{device_to_uuid}{$network_interface_device},
"network_interfaces::uuid_to_name::${network_interface_name}" => $anvil->data->{network_interfaces}{uuid_to_name}{$network_interface_uuid},
"network_interfaces::mac_to_uuid::${network_interface_mac_address}" => $anvil->data->{network_interfaces}{mac_to_uuid}{$network_interface_mac_address},
"interface::name_to_uuid::${network_interface_name}" => $anvil->data->{interface}{name_to_uuid}{$network_interface_name},
"interface::device_to_uuid::${network_interface_device}" => $anvil->data->{interface}{device_to_uuid}{$network_interface_device},
}});
}
@ -2105,7 +2145,6 @@ sub check_ip_addresses
{
my $on_interface = $anvil->data->{new}{ip_address}{$ip_address}{on_interface};
my $new_on_type = $anvil->data->{interface}{name_to_type}{$on_interface};
my $new_on_uuid = $anvil->data->{interface}{name_to_uuid}{$on_interface};
my $new_subnet_mask = $anvil->data->{new}{ip_address}{$ip_address}{subnet_mask};
my $new_gateway = $anvil->data->{new}{ip_address}{$ip_address}{gateway};
my $new_default_gateway = $anvil->data->{new}{ip_address}{$ip_address}{default_gateway};
@ -2114,12 +2153,22 @@ sub check_ip_addresses
ip_address => $ip_address,
on_interface => $on_interface,
new_on_type => $new_on_type,
new_on_uuid => $new_on_uuid,
new_subnet_mask => $new_subnet_mask,
new_gateway => $new_gateway,
new_default_gateway => $new_default_gateway,
new_dns => $new_dns,
}});
my $new_on_uuid = "";
if ($anvil->data->{interface}{name_to_uuid}{$on_interface})
{
$new_on_uuid = $anvil->data->{interface}{name_to_uuid}{$on_interface};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_on_uuid => $new_on_uuid }});
}
elsif ($anvil->data->{interface}{device_to_uuid}{$on_interface})
{
$new_on_uuid = $anvil->data->{interface}{device_to_uuid}{$on_interface};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_on_uuid => $new_on_uuid }});
}
if (exists $anvil->data->{old}{ip_addresses}{ip_to_uuid}{$ip_address})
{
@ -2381,8 +2430,13 @@ sub check_interfaces
{
my ($anvil) = @_;
my $interfaces = keys %{$anvil->data->{new}{interface}};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { interfaces => $interfaces }});
foreach my $network_interface_name (sort {$a cmp $b} keys %{$anvil->data->{new}{interface}})
{
my $new_nm_uuid = $anvil->data->{new}{interface}{$network_interface_name}{nm_uuid};
my $new_nm_name = $anvil->data->{new}{interface}{$network_interface_name}{nm_name};
my $new_nm_device = $anvil->data->{new}{interface}{$network_interface_name}{nm_device};
my $new_bond_uuid = $anvil->data->{new}{interface}{$network_interface_name}{bond_uuid};
my $new_bond_name = $anvil->data->{new}{interface}{$network_interface_name}{bond_name};
my $new_bridge_uuid = $anvil->data->{new}{interface}{$network_interface_name}{bridge_uuid};
@ -2398,6 +2452,9 @@ sub check_interfaces
my $new_rx_bytes = $anvil->data->{new}{interface}{$network_interface_name}{rx_bytes};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
network_interface_name => $network_interface_name,
new_nm_uuid => $new_nm_uuid,
new_nm_name => $new_nm_name,
new_nm_device => $new_nm_device,
new_bond_uuid => $new_bond_uuid,
new_bond_name => $new_bond_name,
new_bridge_uuid => $new_bridge_uuid,
@ -2431,26 +2488,45 @@ sub check_interfaces
}
# New or existing?
my $network_interface_uuid = "";
if (exists $anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name})
{
$network_interface_uuid = $anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_interface_uuid => $network_interface_uuid }});
}
elsif (exists $anvil->data->{network_interfaces}{device_to_uuid}{$network_interface_name})
{
$network_interface_uuid = $anvil->data->{network_interfaces}{device_to_uuid}{$network_interface_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_interface_uuid => $network_interface_uuid }});
}
elsif (($new_mac_address) && (exists $anvil->data->{network_interfaces}{mac_to_uuid}{$new_mac_address}))
{
$network_interface_uuid = $anvil->data->{network_interfaces}{mac_to_uuid}{$new_mac_address};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_interface_uuid => $network_interface_uuid }});
}
if ($network_interface_uuid)
{
# Existing. Changes?
my $network_interface_uuid = $anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name};
my $old_bond_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid};
my $old_bond_name = "";
my $old_bridge_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid};
my $old_bridge_name = "";
my $old_duplex = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_duplex};
my $old_link_state = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_link_state};
my $old_operational = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational};
my $old_mac_address = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address};
my $old_medium = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_medium};
my $old_mtu = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mtu};
my $old_speed = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_speed};
my $old_rx_bytes = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_bytes};
my $rx_variable_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_variable_uuid};
my $old_tx_bytes = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_bytes};
my $tx_variable_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_variable_uuid};
my $old_nm_name = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_name};
my $old_nm_device = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_device};
my $old_bond_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid};
my $old_bond_name = "";
my $old_bridge_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid};
my $old_bridge_name = "";
my $old_duplex = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_duplex};
my $old_link_state = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_link_state};
my $old_operational = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational};
my $old_mac_address = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address};
my $old_medium = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_medium};
my $old_mtu = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mtu};
my $old_speed = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_speed};
my $old_rx_bytes = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_bytes};
my $rx_variable_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_variable_uuid};
my $old_tx_bytes = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_bytes};
my $tx_variable_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_variable_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
old_nm_name => $old_nm_name,
old_nm_device => $old_nm_device,
old_bond_uuid => $old_bond_uuid,
old_bridge_uuid => $old_bridge_uuid,
old_duplex => $old_duplex,
@ -2484,6 +2560,52 @@ sub check_interfaces
# Look for changes.
my $changes = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
new_nm_name => $new_nm_name,
old_nm_name => $old_nm_name,
}});
if ($new_nm_name ne $old_nm_name)
{
$changes = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
my $variables = {
name => $network_interface_name,
old => $old_nm_name,
new => $new_nm_name,
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0062", variables => $variables});
$anvil->Alert->register({
alert_level => "notice",
message => "scan_network_alert_0062",
variables => $variables,
set_by => $THIS_FILE,
});
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
new_nm_device => $new_nm_device,
old_nm_device => $old_nm_device,
}});
if ($new_nm_device ne $old_nm_device)
{
$changes = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
my $variables = {
name => $network_interface_name,
old => $old_nm_device,
new => $new_nm_device,
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0063", variables => $variables});
$anvil->Alert->register({
alert_level => "notice",
message => "scan_network_alert_0063",
variables => $variables,
set_by => $THIS_FILE,
});
}
if ($new_bond_uuid ne $old_bond_uuid)
{
# We're making this a warning level alert as it should not be changing.
@ -2813,11 +2935,17 @@ sub check_interfaces
if ($changes)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
new_nm_name => $new_nm_name,
new_nm_device => $new_nm_device,
}});
my $network_interface_uuid = $anvil->Database->insert_or_update_network_interfaces({
debug => 2,
network_interface_nm_uuid => $new_nm_uuid,
network_interface_bond_uuid => $new_bond_uuid,
network_interface_bridge_uuid => $new_bridge_uuid,
network_interface_name => $network_interface_name,
network_interface_name => $new_nm_name, # biosdevname
network_interface_device => $new_nm_device, # ip name
network_interface_duplex => $new_duplex,
network_interface_link_state => $new_link_state,
network_interface_operational => $new_operational,
@ -2946,11 +3074,18 @@ sub check_interfaces
else
{
# Record the interface
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
new_nm_name => $new_nm_name,
network_interface_name => $network_interface_name,
new_nm_device => $new_nm_device,
}});
my $network_interface_uuid = $anvil->Database->insert_or_update_network_interfaces({
debug => 2,
network_interface_nm_uuid => $new_nm_uuid,
network_interface_bond_uuid => $new_bond_uuid,
network_interface_bridge_uuid => $new_bridge_uuid,
network_interface_name => $network_interface_name,
network_interface_name => $new_nm_name,
network_interface_device => $network_interface_name,
network_interface_duplex => $new_duplex,
network_interface_link_state => $new_link_state,
network_interface_operational => $new_operational,
@ -2966,11 +3101,13 @@ sub check_interfaces
$anvil->data->{network_interfaces}{uuid_to_name}{$network_interface_uuid} = $network_interface_name;
$anvil->data->{network_interfaces}{mac_to_uuid}{$new_mac_address} = $network_interface_uuid;
$anvil->data->{interface}{name_to_uuid}{$network_interface_name} = $network_interface_uuid;
$anvil->data->{interface}{device_to_uuid}{$new_nm_device} = $network_interface_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"network_interfaces::name_to_uuid::${network_interface_name}" => $anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name},
"network_interfaces::uuid_to_name::${network_interface_uuid}" => $anvil->data->{network_interfaces}{uuid_to_name}{$network_interface_uuid},
"network_interfaces::mac_to_uuid::${new_mac_address}" => $anvil->data->{network_interfaces}{mac_to_uuid}{$new_mac_address},
"interface::name_to_uuid::${network_interface_name}" => $anvil->data->{interface}{name_to_uuid}{$network_interface_name},
"interface::device_to_uuid::${new_nm_device}" => $anvil->data->{interface}{device_to_uuid}{$new_nm_device},
}});
# Store the rx_bytes and tx_bytes
@ -3079,6 +3216,7 @@ sub check_bonds
foreach my $bond_name (sort {$a cmp $b} keys %{$anvil->data->{new}{bond}})
{
# Store the bond
my $new_nm_uuid = $anvil->data->{new}{bond}{$bond_name}{nm_uuid};
my $new_mode = $anvil->data->{new}{bond}{$bond_name}{mode};
my $new_mtu = $anvil->data->{new}{bond}{$bond_name}{mtu};
my $new_operational = $anvil->data->{new}{bond}{$bond_name}{operational};
@ -3449,6 +3587,7 @@ sub check_bonds
{
my $bond_uuid = $anvil->Database->insert_or_update_bonds({
debug => 2,
bond_nm_uuid => $new_nm_uuid,
bond_name => $bond_name,
bond_mode => $new_mode,
bond_mtu => $new_mtu,

@ -133,6 +133,8 @@ Note: If this is a Storage Network directly connected to the peer, and the peer
<key name="scan_network_alert_0059">The network interface: [#!variable!name!#] appears to have been removed. The last time we saw it, it had transmitted: [#!variable!tx!#] and received: [#!variable!rx!#].</key>
<key name="scan_network_alert_0060">The IP address: [#!variable!ip!#] appears to no longer be used on this machine.</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_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>
<!-- Error entries -->
<key name="scan_network_error_0001">Failed to read the network interface speed from the file: [#!variable!file!#]. Ignoring interface.</key>

@ -856,6 +856,7 @@ sub collect_data
new_anvil_name => $anvil->Get->anvil_name_from_uuid({anvil_uuid => $server_anvil_uuid}),
new_anvil_uuid => $server_anvil_uuid,
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_server_alert_0009", variables => $variables});
$anvil->Alert->register({alert_level => "notice", message => "scan_server_alert_0009", variables => $variables, set_by => $THIS_FILE});
$update = 1;

@ -855,6 +855,7 @@ CREATE TRIGGER trigger_jobs
CREATE TABLE bridges (
bridge_uuid uuid not null primary key,
bridge_host_uuid uuid not null,
bridge_nm_uuid uuid, -- This is the network manager UUID for this bridge interface
bridge_name text not null,
bridge_id text not null,
bridge_mac_address text not null,
@ -870,6 +871,7 @@ CREATE TABLE history.bridges (
history_id bigserial,
bridge_uuid uuid,
bridge_host_uuid uuid,
bridge_nm_uuid uuid,
bridge_name text,
bridge_id text,
bridge_mac_address text,
@ -888,6 +890,7 @@ BEGIN
INSERT INTO history.bridges
(bridge_uuid,
bridge_host_uuid,
bridge_nm_uuid,
bridge_name,
bridge_id,
bridge_mac_address,
@ -897,6 +900,7 @@ BEGIN
VALUES
(history_bridges.bridge_uuid,
history_bridges.bridge_host_uuid,
history_bridges.bridge_nm_uuid,
history_bridges.bridge_name,
history_bridges.bridge_id,
history_bridges.bridge_mac_address,
@ -918,6 +922,7 @@ CREATE TRIGGER trigger_bridges
CREATE TABLE bonds (
bond_uuid uuid not null primary key,
bond_host_uuid uuid not null,
bond_nm_uuid uuid, -- The is the network manager UUID for this bond.
bond_name text not null,
bond_mode text not null, -- This is the numerical bond type (will translate to the user's language in the Anvil!)
bond_mtu bigint not null,
@ -941,6 +946,7 @@ CREATE TABLE history.bonds (
history_id bigserial,
bond_uuid uuid,
bond_host_uuid uuid,
bond_nm_uuid uuid,
bond_name text,
bond_mode text,
bond_mtu bigint,
@ -966,6 +972,7 @@ BEGIN
INSERT INTO history.bonds
(bond_uuid,
bond_host_uuid,
bond_nm_uuid,
bond_name,
bond_mode,
bond_mtu,
@ -982,6 +989,7 @@ BEGIN
VALUES
(history_bonds.bond_uuid,
history_bonds.bond_host_uuid,
history_bonds.bond_nm_uuid,
history_bonds.bond_name,
history_bonds.bond_mode,
history_bonds.bond_mtu,
@ -1011,8 +1019,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_nm_uuid uuid, -- This is the network manager 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 GENERAL.IP-IFACE) 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 +1043,10 @@ CREATE TABLE history.network_interfaces (
history_id bigserial,
network_interface_uuid uuid not null,
network_interface_host_uuid uuid,
network_interface_nm_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 +1068,10 @@ BEGIN
INSERT INTO history.network_interfaces
(network_interface_uuid,
network_interface_host_uuid,
network_interface_nm_uuid,
network_interface_mac_address,
network_interface_name,
network_interface_device,
network_interface_speed,
network_interface_mtu,
network_interface_link_state,
@ -1070,8 +1084,10 @@ BEGIN
VALUES
(history_network_interfaces.network_interface_uuid,
history_network_interfaces.network_interface_host_uuid,
history_network_interfaces.network_interface_nm_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,
@ -1096,7 +1112,7 @@ CREATE TRIGGER trigger_network_interfaces
CREATE TABLE ip_addresses (
ip_address_uuid uuid not null primary key,
ip_address_host_uuid uuid not null,
ip_address_on_type text not null, -- Either 'interface', 'bond' or 'bridge'
ip_address_on_type text not null, -- Either 'interface', 'bond', 'bridge' or 'network_manager'
ip_address_on_uuid uuid not null, -- This is the UUID of the interface, bond or bridge that has this IP
ip_address_address text not null, -- The actual IP address
ip_address_subnet_mask text not null, -- The subnet mask (in dotted decimal format)
@ -1167,6 +1183,91 @@ 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 (
network_manager_uuid uuid not null primary key, -- Unlike most other tables, this UUID comes from nmcli itself, and so this matches what's displayed nmcli
network_manager_host_uuid uuid not null, -- The host_uuid for this interface
network_manager_device text not null, -- This is the nmcli "device" name
network_manager_name text not null, -- This is the nmcli "name" name
network_manager_mac text not null, -- This is the MAC address of the interface
network_manager_type text not null, -- This is the nmcli "type" string
network_manager_active text not null, -- This is the nmcli "active" field
network_manager_state text not null, -- This is the nmcli "state" field
network_manager_connected numeric not null, -- This is '0' if the connection is down, or a unix timestamp if it's up.
network_manager_mtu numeric not null, -- This is the MTU of the interface
modified_date timestamp with time zone not null,
FOREIGN KEY(network_manager_host_uuid) REFERENCES hosts(host_uuid)
);
ALTER TABLE network_manager OWNER TO admin;
CREATE TABLE history.network_manager (
history_id bigserial,
network_manager_uuid uuid not null,
network_manager_host_uuid uuid,
network_manager_mac_address text,
network_manager_name text,
network_manager_speed bigint,
network_manager_mtu bigint,
network_manager_link_state text,
network_manager_operational text,
network_manager_duplex text,
network_manager_medium text,
network_manager_bond_uuid uuid,
network_manager_bridge_uuid uuid,
modified_date timestamp with time zone not null
);
ALTER TABLE history.network_manager OWNER TO admin;
CREATE FUNCTION history_network_manager() RETURNS trigger
AS $$
DECLARE
history_network_manager RECORD;
BEGIN
SELECT INTO history_network_manager * FROM network_manager WHERE network_manager_uuid = new.network_manager_uuid;
INSERT INTO history.network_manager
(network_manager_uuid,
network_manager_host_uuid,
network_manager_mac_address,
network_manager_name,
network_manager_speed,
network_manager_mtu,
network_manager_link_state,
network_manager_operational,
network_manager_duplex,
network_manager_medium,
network_manager_bond_uuid,
network_manager_bridge_uuid,
modified_date)
VALUES
(history_network_manager.network_manager_uuid,
history_network_manager.network_manager_host_uuid,
history_network_manager.network_manager_mac_address,
history_network_manager.network_manager_name,
history_network_manager.network_manager_speed,
history_network_manager.network_manager_mtu,
history_network_manager.network_manager_link_state,
history_network_manager.network_manager_operational,
history_network_manager.network_manager_duplex,
history_network_manager.network_manager_medium,
history_network_manager.network_manager_bond_uuid,
history_network_manager.network_manager_bridge_uuid,
history_network_manager.modified_date);
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
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.
CREATE TABLE files (
file_uuid uuid not null primary key,

@ -752,6 +752,33 @@ The XML that failed sanity check was:
<key name="error_0477">[ Error ] - The requested number of cores: [#!variable!requested_cores!#] (sockets: [#!variable!new_sockets!], cores per socket: [#!variable!new_cores!#], threads per core: [#!variable!new_threads!#]).</key>
<key name="error_0478">[ Error ] - This program must be run on a subnode.</key>
<key name="error_0479">[ Error ] - This subnode is not in the cluster (failed to parse the CIB). Exiting.</key>
<key name="error_0480">[ Error ] - The wanted interface: [#!variable!interface_name!#] which should have the MAC address: [#!variable!mac_address!#] was not found in Network Manager. Unable to proceed.</key>
<key name="error_0481">[ Error ] - Failed to delete the 'connection.interface-name', got: [#!variable!output!#] and it should bhave been blank, aborting!</key>
<key name="error_0482">[ Error ] - Failed to create the 'match.interface-name' value. Expected: [#!variable!new_name!#,#!variable!old_device!#], got: [#!variable!output!#], aborting!</key>
<key name="error_0483">[ Error ] - The attempt to add the bond: [#!variable!bond_name!#] failed! The return code was: [#!variable!return_code!#]. The output, if any, was:
========
#!variable!output!#
========
</key>
<key name="error_0484">[ Error ] - The attempt to add the network link: [#!variable!link_name!#] to the bond: [#!variable!bond_name!#] failed! The return code was: [#!variable!return_code!#]. The output, if any, was:
========
#!variable!output!#
========
</key>
<key name="error_0485">[ Error ] - The attempt to add the bridge: [#!variable!bridge_name!# failed! The return code was: [#!variable!return_code!#]. The output, if any, was:
========
#!variable!output!#
========
</key>
<key name="error_0486">[ Error ] - The attempt to add the device: [#!variable!on_device!#] to the bridge: [#!variable!bridge_name!#] failed! The return code was: [#!variable!return_code!#]. The output, if any, was:
========
#!variable!output!#
========
</key>
<key name="error_0487">[ Error ] - The subnet_mask: [#!variable!subnet_mask!#] is not valid. It must be either a CIDR notation, or a dotted-decimal mask that can be translated to CIDR notation.</key>
<key name="error_0488">[ Error ] - Can't find a device to assign the: [#!variable!network!#] IP address: [#!variable!ip_address!#/#!variable!subnet_mask!#] to!</key>
<key name="error_0489">[ Error ] - Failed to map the IP address: [#!variable!ip_address!#] to a network manager connection UUID!</key>
<key name="error_0490">[ Error ] - Both the netbios name: [#!variable!wanted_link_name!#] and the old device name: [#!variable!old_device!#] are the same, 'match.interface-name' would break!</key>
<!-- Files templates -->
<!-- NOTE: Translating these files requires an understanding of which lines are translatable -->
@ -2681,6 +2708,13 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
</key>
<key name="log_0827">The physical volume: [#!variable!pv_name!#] has been resized!</key>
<key name="log_0828">The user answered: [#!variable!answer!#]</key>
<key name="log_0829">Failed to connect to any database, waiting before trying to connect again. We will reboot if we do not connect in: [#!variable!time_left!#] second.</key>
<key name="log_0830">The host: [#!variable!host_name!#] was found in the '/etc/hosts' file with the expected IP: [#!variable!ip_address!#]!</key>
<key name="log_0831">The host: [#!variable!host_name!#] was found in the '/etc/hosts' file, but the expected IP: [#!variable!ip_address!#] doesn't match the found IP: [#!variable!found_ip!#]! Ignoring this entry.</key>
<key name="log_0832">The host: [#!variable!host_name!#] was found not found in the '/etc/hosts' file! We'll wait a few seconds and check again.</key>
<key name="log_0833">All host names were found in '/etc/hosts', ready to proceed!</key>
<key name="log_0834">One or more hosts are not yet in the '/etc/hosts' file with expected IPs. We'll wait a short bit and check again.</key>
<key name="log_0835">There are entries we need to add to the '/etc/hosts' file before we can form the cluster, updating it now.</key>
<!-- Messages for users (less technical than log entries), though sometimes used for logs, too. -->
<key name="message_0001">The host name: [#!variable!target!#] does not resolve to an IP address.</key>
@ -3284,6 +3318,42 @@ proceeding.
- Threads per Core: [#!variable!old_threads!#] -> [#!variable!new_threads!#]
- Total Cores: .... [#!variable!old_total_cores!#] -> [#!variable!new_total_cores!#]]]></key>
<key name="message_0382"><![CDATA[-=] Updated: #!variable!date!# - Press '<ctrl> + <c>' to exit]]></key>
<key name="message_0383">Renaming old device/name: [#!variable!old_device!#/#!variable!old_name!#] with MAC: [#!variable!mac_address!#] to: [#!variable!new_name!#] using UUID: [#!variable!nm_uuid!#].</key>
<key name="message_0384">- Updating the udev file: [#!variable!file!#].</key>
<key name="message_0385">- Removing the old 'connection.interface-name': [#!variable!name!#].</key>
<key name="message_0386">- Matching the new interface name: [#!variable!new_name!#] to the bios device name: [#!variable!old_device!#].</key>
<key name="message_0387">- Setting the connection.id to the bios device name: [#!variable!old_device!#]</key>
<key name="message_0388">The new interface names need a reboot to take effect.</key>
<key name="message_0389">Rebooting NOW! The job will restart on reboot.</key>
<key name="message_0390">Checking if the bond: [#!variable!bond_name!#] exists or not.</key>
<key name="message_0391">- It does, its UUID is: [#!variable!nm_uuid!#].</key>
<key name="message_0392">- The bond: [#!variable!bond_name!#] doesn't exist. Will create it using the primary interface: [#!variable!link1_name!#] (MAC: [#!variable!link1_mac!#], NM UUID: [#!variable!link1_nm_uuid!#) and the backup interface: [#!variable!link2_name!#] (MAC: [#!variable!link2_mac!#], NM UUID: [#!variable!link2_nm_uuid!#).</key>
<key name="message_0393">Checking to see if the IP address: [#!variable!ip_address!#/#!variable!subnet_mask!#] is assigned to: [#!variable!device!#] yet.</key>
<key name="message_0394"> - Done! Rescanning the network config.</key>
<key name="message_0395">- The interface: [#!variable!link_name!#] (#!variable!nm_uuid!#) is already a member of the bond.</key>
<key name="message_0396">- The interface: [#!variable!link_name!#] (#!variable!nm_uuid!#) is a member of the bond: [#!variable!old_bond!#], switching it to this bond.</key>
<key name="message_0397">- The interface: [#!variable!link_name!#] (#!variable!nm_uuid!#) needs to be connected to the bond.</key>
<key name="message_0398">- The IP exists, checking if it needs to be updated.</key>
<key name="message_0399"> - Connecting the interface: [#!variable!link_name!#] to the bond: [#!variable!bond_name!#].</key>
<key name="message_0400">Checking if the bridge: [#!variable!bridge_name!#] exists and that it is on: [#!variable!on_device!#]</key>
<key name="message_0401">- The bridge exists!</key>
<key name="message_0402">- The IP address is on: [#!variable!device!#], will move the IP.</key>
<key name="message_0403"> - Resetting the device: [#!variable!device!#] (#!variable!device_uuid!#) to make sure the new config takes effect.</key>
<key name="message_0404">- Checking that the device: [#!variable!on_device!#] is connected to this bridge.</key>
<key name="message_0405">- The device is connected to the bridge already.</key>
<key name="message_0406">- The device is on the bridge: [#!variable!on_device_parent!#], moving it.</key>
<key name="message_0407">- The device is not on this bridge, connecting it.</key>
<key name="message_0408"> - Disabling DHCP on the device: [#!variable!device!#] (#!variable!device_uuid!#).</key>
<key name="message_0409"> - Connecting it now.</key>
<key name="message_0410">- The current subnet mask is: [#!variable!current_subnet_mask!#], will update.</key>
<key name="message_0411">- The current gateway is: [#!variable!current_gateway!#], will update.</key>
<key name="message_0412">- The current DNS is: [#!variable!current_dns!#], will update.</key>
<key name="message_0413">- No update is needed.</key>
<key name="message_0414">- The IP address needs to be assigned.</key>
<key name="message_0415">[ Note ] - Reconfiguring the network will break connections. Disconnecting from the database before starting. It might take a bit before this system reconnects and progress can be seen.</key>
<key name="message_0416">[ Note ] - The network has reconnected to the database, configuring will complete shortly.</key>
<key name="message_0417">[ Note ] - The old 'ifcfg' style config file: [#!variable!file!#] will be backed up and then removed!</key>
<key name="message_0418">[ Note ] - Updated the ssh daemon config file: [#!variable!file!#] to enable ssh access for the root user.</key>
<!-- Translate names (protocols, etc) -->
<key name="name_0001">Normal Password</key> <!-- none in mail-server -->
@ -4094,6 +4164,7 @@ We will try to proceed anyway.</key>
====
</key>
<key name="warning_0168">Please specify a storage group to use to add the new drive to.</key>
<key name="warning_0169">[ Warning ] - After reconfiguring the network, we've failed to connect to any database for two minutes. Rebooting in case this fixes the connection.</key>
</language>
<!-- 日本語 -->

@ -42,7 +42,6 @@ dist_sbin_SCRIPTS = \
anvil-test-alerts \
anvil-update-definition \
anvil-update-issue \
anvil-update-states \
anvil-update-system \
anvil-version-changes \
anvil-virsh-wrapper \

@ -84,7 +84,7 @@ foreach my $pid (sort {$a cmp $b} @{$anvil->data->{sys}{pids}})
{
my $size = $1;
my $type = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
type => $type,
size => $size,
}});
@ -94,10 +94,10 @@ foreach my $pid (sort {$a cmp $b} @{$anvil->data->{sys}{pids}})
# This uses 'kB' for 'KiB' >_>
$type = lc($type);
$type =~ s/b$/ib/ if $type !~ /ib$/;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { type => $type }});
my $size_in_bytes = $anvil->Convert->human_readable_to_bytes({size => $size, type => $type, base2 => 1});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
size_in_bytes => $anvil->Convert->add_commas({number => $size_in_bytes})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $size_in_bytes}).")",
}});

File diff suppressed because it is too large Load Diff

@ -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"});
@ -100,6 +101,9 @@ if (not $anvil->data->{sys}{database}{connections})
}
else
{
# Striker can't initialize us unless it can ssh into us, so make sure root login is enabled.
chech_sshd($anvil);
# Wait until we have one.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0075"});
@ -200,7 +204,7 @@ while(1)
# Reload defaults, re-read the config and then connect to the database(s)
$anvil->refresh();
# If, so some reason, anvil.conf is lost, create it.
# If, for some reason, anvil.conf is lost, create it.
$anvil->System->_check_anvil_conf();
$anvil->Database->connect({check_if_configured => $check_if_database_is_configured, check_for_resync => 2});
@ -208,26 +212,13 @@ while(1)
# Mark that we don't want to check the database now.
$check_if_database_is_configured = 0;
# If this host is mapping the network, we'll skip a lot of stuff. If set for over an hour, we'll
# clear it.
$anvil->data->{sys}{mapping_network} = check_if_mapping($anvil);
if ($anvil->data->{sys}{database}{connections})
{
# Run the normal tasks
keep_running($anvil);
# Handle periodic tasks
handle_periodic_tasks($anvil) if not $anvil->data->{sys}{mapping_network};
}
else
{
# No databases available, we'll update the state file in case this host is having it's
# network mapped and the interface used to talk to the databases went down. That's all we
# can do though.
update_state_file($anvil);
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "log_0202"});
handle_periodic_tasks($anvil);
}
# Exit if 'run-once' selected.
@ -312,85 +303,6 @@ sub check_ram
return(0);
}
# Check to see if we're mapping the network on this host.
sub check_if_mapping
{
my ($anvil) = @_;
$anvil->data->{sys}{mapping_network} = 0;
if ($anvil->data->{sys}{database}{connections})
{
my ($map_network_value, $map_network_uuid, $map_network_mtime, $map_network_modified_date) = $anvil->Database->read_variable({
debug => 3,
variable_name => "config::map_network",
variable_source_table => "hosts",
variable_source_uuid => $anvil->data->{sys}{host_uuid},
});
# We'll run for a day (should be cancelled by the program when the user's done, so this
# shouldn't fire in practice).
my $expire_age = 86400;
my $map_network_age = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:map_network_value' => $map_network_value,
's2:map_network_mtime' => $map_network_mtime,
's3:map_network_modified_date' => $map_network_modified_date,
's4:map_network_uuid' => $map_network_uuid,
}});
if ($map_network_uuid)
{
$map_network_age = time - $map_network_mtime;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { map_network_age => $map_network_age }});
}
if ($map_network_value)
{
# How long ago was it set?
$anvil->data->{switches}{'clear-mapping'} = "" if not defined $anvil->data->{switches}{'clear-mapping'};
if (($map_network_age >= $expire_age) or ($anvil->data->{switches}{'clear-mapping'}))
{
# Clear it.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0470"});
$anvil->Database->insert_or_update_variables({
debug => 3,
variable_value => 0,
variable_uuid => $map_network_uuid,
update_value_only => 1,
});
}
else
{
# Mark it so we only track the network.
my $say_age = $anvil->Convert->add_commas({number => $expire_age});
my $timeout = $anvil->Convert->add_commas({number => ($expire_age - $map_network_age)});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0471", variables => {
age => $say_age,
timeout => $timeout,
}});
$anvil->data->{sys}{mapping_network} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "sys::mapping_network" => $anvil->data->{sys}{mapping_network} }});
# Close any open ssh connections.
foreach my $ssh_fh_key (keys %{$anvil->data->{cache}{ssh_fh}})
{
my $ssh_fh = $anvil->data->{cache}{ssh_fh}{$ssh_fh_key};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
ssh_fh_key => $ssh_fh_key,
ssh_fh => $ssh_fh,
}});
if ($ssh_fh =~ /^Net::OpenSSH/)
{
$ssh_fh->disconnect();
}
delete $anvil->data->{cache}{ssh_fh}{$ssh_fh_key};
}
}
}
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "sys::mapping_network" => $anvil->data->{sys}{mapping_network} }});
return($anvil->data->{sys}{mapping_network});
}
# This decides if the local system will delay daily runs on start-up.
sub set_delay
{
@ -431,6 +343,7 @@ sub check_network
{
my ($anvil) = @_;
### TODO: Remove this when EL8 support is dropped. This was an issue with the old ifcfg configured bonds
# The network sometimes doesn't come up, but we don't want to try recovering it too soon. As such,
# we'll start watching the network after the uptime is 2 minutes.
my $uptime = $anvil->Get->uptime;
@ -450,19 +363,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);
}
@ -500,6 +405,27 @@ sub check_network
}
}
# Check that there's at least one entry in 'network_interfaces' and, if not, call scan-network.
if (1)
{
my $query = "SELECT COUNT(*) FROM network_interfaces WHERE network_interface_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
my $count = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
if (not $count)
{
# Run scan-network
my $shell_call = $anvil->data->{path}{directories}{scan_agents}."/scan-network/scan-network".$anvil->Log->switches;
$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,
}});
}
}
return(0);
}
@ -530,7 +456,7 @@ sub handle_periodic_tasks
# Check that the users we care about have ssh public keys and they're recorded in ssh_keys.
$anvil->System->check_ssh_keys({debug => 2});
$anvil->System->update_hosts({debug => 3});
$anvil->System->update_hosts({debug => 2});
# Check if the files on disk have changed. Even if it is time to check, don't if a job is
# running.
@ -560,9 +486,6 @@ sub handle_periodic_tasks
return_code => $return_code,
}});
# Scan the local network.
update_state_file($anvil);
# Check shared files.
check_files($anvil);
@ -1100,6 +1023,9 @@ sub run_once
# Check journald is configured for persistent storage.
check_journald($anvil);
# Make sure root can ssh
chech_sshd($anvil);
if ($anvil->data->{switches}{'startup-only'})
{
$anvil->nice_exit({exit_code => 0});
@ -1108,6 +1034,50 @@ sub run_once
return(0);
}
sub chech_sshd
{
my ($anvil) = @_;
# On EL8, the 'sshd_config.d' directory doesn't exist and root is enabled.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'path::directories::sshd_config.d' => $anvil->data->{path}{directories}{'sshd_config.d'} }});
if (not -d $anvil->data->{path}{directories}{'sshd_config.d'})
{
return(0);
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'path::configs::sshd_root_password' => $anvil->data->{path}{configs}{sshd_root_password} }});
if (not -f $anvil->data->{path}{configs}{sshd_root_password})
{
# Write it out
my $body = "# This file was added to enable root login by password, which is needed while
# forming the Anvil! cluster. Once the cluster is formed, passwordless SSH
# should be enabled and you can disable this feature. Please remove during a
# maintanence window or after testing in a lab environment.
PermitRootLogin yes
";
# Update the config
$anvil->Storage->write_file({
debug => 2,
secure => 0,
file => $anvil->data->{path}{configs}{sshd_root_password},
body => $body,
mode => "0644",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0418", variables => { file => $anvil->data->{path}{configs}{sshd_root_password} }});
# Restart the journald service.
my $shell_call = $anvil->data->{path}{exe}{systemctl}." restart sshd.service";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
}
return(0);
}
sub check_journald
{
my ($anvil) = @_;
@ -1200,7 +1170,7 @@ sub check_journald
return(0);
}
# This creates, as needed, the setuid wrappers used by apache to make certain system calls.
# This creates, as needed, the setuid wrappers used by striker-ui-api to make certain system calls.
sub check_setuid_wrappers
{
my ($anvil) = @_;
@ -1432,7 +1402,7 @@ AND
}
# Make sure /etc/hosts is updated.
$anvil->System->update_hosts();
$anvil->System->update_hosts({debug => 2});
# This handles weird bits for things like bug work-arounds.
handle_special_cases($anvil);
@ -1443,14 +1413,6 @@ AND
# Check the firewall needs to be updated.
check_firewall($anvil);
# If we're a striker, check apache
my $host_type = $anvil->Get->host_type;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }});
if ($host_type eq "striker")
{
$anvil->Striker->check_httpd_conf({debug => 3});
}
return(0);
}
@ -1541,7 +1503,7 @@ sub keep_running
my ($anvil) = @_;
# Check for jobs that were running and now exited.
if ((not $anvil->data->{sys}{mapping_network}) && (exists $anvil->data->{processes}))
if (exists $anvil->data->{processes})
{
foreach my $job_uuid (%{$anvil->data->{jobs}{handles}})
{
@ -1572,18 +1534,13 @@ sub keep_running
# If we're configured, write out the status JSON file. If we're not configured, Update hardware state files.
my $configured = $anvil->System->check_if_configured;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { configured => $configured }});
if ((not $anvil->data->{sys}{mapping_network}) && ($configured))
if ($configured)
{
# Write out state information for all known Anvil! systems and the information from
# unconfigured nods and DR hosts, using just database data (hence, fast enough to run
# constantly).
$anvil->System->generate_state_json({debug => 2});
}
else
{
# Run this to monitor the network in real time.
update_state_file($anvil);
}
# Run any pending jobs by calling 'anvil-jobs' with the 'job_uuid' as a background process.
run_jobs($anvil, 0);
@ -1620,10 +1577,6 @@ sub run_jobs
# changed on disk.
$anvil->data->{sys}{jobs_running} = 0;
# If we're not configured, we won't hold on starting jobs
my $configured = $anvil->System->check_if_configured;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { configured => $configured }});
# We'll also update the jobs.json file.
my $jobs_file = "{\"jobs\":[\n";
@ -1676,11 +1629,16 @@ sub run_jobs
's12:job_status' => $job_status,
's13:started_seconds_ago' => $started_seconds_ago,
's14:updated_seconds_ago' => $updated_seconds_ago,
's15:sys::mapping_network' => $anvil->data->{sys}{mapping_network},
}});
# If we're mapping, we'll only run 'anvil-configure-host' jobs on this host.
next if (($anvil->data->{sys}{mapping_network}) && ($job_command !~ /anvil-configure-host/));
# If we're not configured, we will only run the 'anvil-configure-host' job
my $configured = $anvil->System->check_if_configured;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { configured => $configured }});
if ((not $configured) && ($job_command !~ /anvil-configure-host/))
{
next;
}
# To minimize the chance of race conditions, any given command will be called only
# once at a time. If two jobs of the same command exist, only one will be called.
@ -1793,9 +1751,9 @@ sub run_jobs
}
# Convert the double-banged strings into a proper message.
my $say_title = $job_title ? $anvil->Words->parse_banged_string({key_string => $job_title}) : "";
my $say_description = $job_description ? $anvil->Words->parse_banged_string({key_string => $job_description}) : "";
my $say_status = $job_status ? $anvil->Words->parse_banged_string({key_string => $job_status}) : "";
my $say_title = $job_title ? $anvil->Words->parse_banged_string({debug => 2, key_string => $job_title}) : "";
my $say_description = $job_description ? $anvil->Words->parse_banged_string({debug => 2, key_string => $job_description}) : "";
my $say_status = $job_status ? $anvil->Words->parse_banged_string({debug => 2, key_string => $job_status}) : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
job_title => $job_title,
say_description => $say_description,
@ -1963,8 +1921,8 @@ sub run_jobs
overwrite => 1,
backup => 0,
mode => "0644",
user => "apache",
group => "apache",
user => "striker-ui-api",
group => "striker-ui-api",
});
return(0);
@ -2004,8 +1962,8 @@ sub check_files
{
my $failed = $anvil->Storage->make_directory({
directory => $directory,
group => "apache",
user => "apache",
group => "striker-ui-api",
user => "striker-ui-api",
mode => "0777",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { failed => $failed }});
@ -2032,24 +1990,3 @@ sub check_files
return(0);
}
# This calls 'anvil-update-states' which will scan the local machine's state (hardware and software) and
# record write it out to an HTML file
sub update_state_file
{
my ($anvil) = @_;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, key => "log_0480"});
#my $shell_call = $anvil->data->{path}{exe}{'anvil-update-states'}.$anvil->Log->switches;
my $shell_call = $anvil->data->{path}{exe}{'anvil-update-states'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { shell_call => $shell_call }});
my ($states_output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
states_output => $states_output,
return_code => $return_code,
}});
return(0);
}

@ -222,8 +222,8 @@ sub download_file
debug => 2,
directory => $save_to,
mode => "0777",
user => "apache",
group => "apache",
user => "striker-ui-api",
group => "striker-ui-api",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { failed => $failed }});
}
@ -233,8 +233,8 @@ sub download_file
debug => 2,
directory => $anvil->data->{path}{directories}{shared}{temp},
mode => "0777",
user => "apache",
group => "apache",
user => "striker-ui-api",
group => "striker-ui-api",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { failed => $failed }});
}

@ -22,6 +22,7 @@ use Anvil::Tools;
use Data::Dumper;
use String::ShellQuote;
use Text::Diff;
use NetAddr::IP;
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
@ -54,6 +55,9 @@ if (not $anvil->data->{sys}{database}{connections})
# Get the job details
load_job($anvil);
# Make sure the hosts file has entries for all nets for both subnodes
wait_for_etc_hosts($anvil);
# Hold until both subnodes are marked as configured and not in maintenance mode.
wait_for_subnodes($anvil);
@ -63,6 +67,10 @@ update_passwords($anvil);
# Check if we need to change any IPs or our hostname.
check_local_network($anvil);
# Wait until we can ping our peer on all networks.
wait_for_access($anvil);
### TODO: Change corosync.conf to use IPs, including MN if it exists.
# (wait for out peer and) Configure pacemaker
configure_pacemaker($anvil);
@ -98,6 +106,426 @@ $anvil->nice_exit({exit_code => 0});
# Functions #
#############################################################################################################
# Make sure the hosts file has entries for all nets for both subnodes
sub wait_for_etc_hosts
{
my ($anvil) = @_;
my $anvil_uuid = $anvil->data->{sys}{anvil_uuid};
my $node1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid};
my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
my $manifest_uuid = $anvil->data->{sys}{manifest_uuid};
my $i_am = $anvil->data->{sys}{machine};
my $peer_is = $i_am eq "node1" ? "node2" : "node1";
my $peer_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{"anvil_".$peer_is."_host_uuid"};
my $peer_short_host_name = $anvil->data->{hosts}{host_uuid}{$peer_host_uuid}{short_host_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:anvil_uuid' => $anvil_uuid,
's2:manifest_uuid' => $manifest_uuid,
's3:node1_host_uuid' => $node1_host_uuid,
's4:node2_host_uuid' => $node2_host_uuid,
's5:i_am' => $i_am,
's6:peer_is' => $peer_is,
's7:peer_host_uuid' => $peer_host_uuid,
's8:peer_short_host_name' => $peer_short_host_name,
}});
my $problem = $anvil->Striker->load_manifest({debug => 2, manifest_uuid => $manifest_uuid});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
manifest_uuid => $anvil->data->{sys}{manifest_uuid},
problem => $problem,
}});
if ($problem)
{
# Something went wrong, fatally. Abort the job.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "job_0076", variables => { uuid => $anvil->data->{sys}{manifest_uuid} }});
update_progress($anvil, 100, "job_0076,!!uuid!".$anvil->data->{sys}{manifest_uuid}."!!");
$anvil->nice_exit({exit_code => 2});
}
# Create the list of host names we need to see in /etc/hosts and the hostnames to use in corosync.
foreach my $machine (sort {$a cmp $b} keys %{$anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}})
{
my $this_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{"anvil_".$machine."_host_uuid"};
my $this_short_host_name = $anvil->data->{hosts}{host_uuid}{$this_host_uuid}{short_host_name};
my $bcn_name = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { machine => $machine }});
foreach my $network_name (sort {$a cmp $b} keys %{$anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$machine}{network}})
{
my $host_name = $this_short_host_name.".".$network_name;
my $ip_address = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$machine}{network}{$network_name}{ip};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:network_name' => $network_name,
's2:host_name' => $host_name,
's3:ip_address' => $ip_address,
}});
$anvil->data->{networks}{$host_name}{ip_address} = $ip_address;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"s1:networks::${host_name}::ip_address" => $anvil->data->{networks}{$host_name}{ip_address},
}});
# If this is the first BCN, record it's name (in case BCN1 isn't used here) and IP
# address, and add the short and full host names.
if (($network_name =~ /^bcn/) && (not $bcn_name))
{
$bcn_name = $network_name;
my $this_host_name = $anvil->data->{hosts}{host_uuid}{$this_host_uuid}{host_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bcn_name => $bcn_name }});
$anvil->data->{networks}{$this_short_host_name}{ip_address} = $ip_address;
$anvil->data->{networks}{$this_host_name}{ip_address} = $ip_address;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"s1:networks::${this_short_host_name}::ip_address" => $anvil->data->{networks}{$this_short_host_name}{ip_address},
"s2:networks::${this_host_name}::ip_address" => $anvil->data->{networks}{$this_host_name}{ip_address},
}});
}
}
}
my $waiting = 1;
update_progress($anvil, ($anvil->data->{job}{progress} += 2), "job_0477");
while($waiting)
{
# Update the /etc/hosts file. Note that this doesn't add hosts that are not yet trusted, so
# anything not found will be inserted here.
$anvil->System->update_hosts({debug => 2});
# Now lets see if all expected hosts names are in the /etc/hosts file yet.
my $ready = 1;
my $hosts_file = $anvil->Storage->read_file({
file => $anvil->data->{path}{configs}{hosts},
force_read => 1,
cache => 0,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { hosts_file => $hosts_file }});
foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{networks}})
{
my $found = 0;
my $ip_address = $anvil->data->{networks}{$host_name}{ip_address};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:host_name' => $host_name,
's2:ip_address' => $ip_address,
}});
foreach my $line (split/\n/, $hosts_file)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
$line =~ s/#.*$//;
if ($line =~ /^(\d.*?)\s+(.*)$/)
{
my $this_ip = $1;
my $hosts = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
this_ip => $this_ip,
hosts => $hosts,
}});
if ($anvil->Validate->ip({ip => $this_ip}))
{
foreach my $this_host (split/\s+/, $hosts)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { this_host => $this_host }});
if ($host_name eq $this_host)
{
my $variables = {
host_name => $host_name,
ip_address => $ip_address,
found_ip => $this_ip,
};
if ($ip_address eq $this_ip)
{
# Found it
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0830", variables => $variables });
$found = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { found => $found }});
}
else
{
# Found the host, but the IP doesn't match.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0831", variables => $variables });
}
}
last if $found;
}
}
}
last if $found;
}
if (not $found)
{
$ready = 0;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0832", variables => { host_name => $host_name }});
# Add the IP to be added to /etc/hosts.
$anvil->data->{to_add}{$host_name} = $ip_address;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "to_add::${ip_address}" => $anvil->data->{to_add}{$host_name} }});
}
}
if ($ready)
{
# Ready!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0833"});
$waiting = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { waiting => $waiting }});
}
else
{
# Not ready, wait a bit.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0834"});
# Add the values to /etc/hosts.
my $new_hosts_body = "";
foreach my $line (split/\n/, $hosts_file)
{
# See if this line needs to be modified.
if ($line =~ /^(\d.*?)\s+(.*)$/)
{
my $this_ip = $1;
my $hosts = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
this_ip => $this_ip,
hosts => $hosts,
}});
if ($anvil->Validate->ip({ip => $this_ip}))
{
my $changes = 0;
my $new_hosts = "";
my $comment = ($hosts =~ /(#.*)$/)[0];
$comment = "" if not defined $comment;
$hosts =~ s/#.*?//;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
comment => $comment,
hosts => $hosts,
}});
foreach my $host_name (split/\s+/, $hosts)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_name => $host_name }});
if ((exists $anvil->data->{to_add}{$host_name}) &&
($anvil->data->{to_add}{$host_name}) &&
($this_ip ne $anvil->data->{to_add}{$host_name}))
{
# Remove this host.
$changes = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
delete $anvil->data->{to_add}{$host_name};
next;
}
$new_hosts .= $host_name." ";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_hosts => $new_hosts }});
}
# Do we have any names to add to this IP?
foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{to_add}})
{
if ($this_ip eq $anvil->data->{to_add}{$host_name})
{
# Add it.
$new_hosts .= $host_name." ";
$changes = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
delete $anvil->data->{to_add}{$host_name};
}
}
if ($changes)
{
$new_hosts_body .= $this_ip."\t".$new_hosts.$comment."\n";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }});
next;
}
}
}
# If we're alive here, just add the old line.
$new_hosts_body .= $line."\n";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_hosts_body => $new_hosts_body }});
}
# Add any hosts still not processed.
foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{to_add}})
{
$new_hosts_body .= $anvil->data->{to_add}{$host_name}."\t".$host_name."\n";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_hosts_body => $new_hosts_body }});
delete $anvil->data->{to_add}{$host_name};
}
# If there's a difference, write the new hosts file.
my $difference = diff \$new_hosts_body, \$hosts_file, { STYLE => 'Unified' };
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { difference => $difference }});
if ($difference)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 3, key => "job_0112"});
update_progress($anvil, ($anvil->data->{job}{progress} += 2), "job_0112");
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0835"});
my $failed = $anvil->Storage->write_file({
debug => 2,
overwrite => 1,
file => $anvil->data->{path}{configs}{hosts},
body => $new_hosts_body,
user => "root",
group => "root",
mode => "0644",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { failed => $failed }});
}
sleep 1;
}
}
return(0);
}
sub wait_for_access
{
my ($anvil) = @_;
# NOTE: This logic is a copy of anvil-safe-start.
$anvil->Database->get_hosts();
$anvil->Database->get_anvils();
my $host_uuid = $anvil->Get->host_uuid();
my $short_host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{short_host_name};
my $peer_host_uuid = $anvil->data->{sys}{peer_host_uuid};
my $peer_short_host_name = $anvil->data->{hosts}{host_uuid}{$peer_host_uuid}{short_host_name};
my $peer_password = $anvil->data->{sys}{peer_password};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host_uuid => $host_uuid,
short_host_name => $short_host_name,
peer_host_uuid => $peer_host_uuid,
peer_short_host_name => $peer_short_host_name,
peer_password => $anvil->Log->is_secure($peer_password),
}});
my $waiting = 1;
while ($waiting)
{
# This will get set back to '1' if
$waiting = 0;
# Load IPs (again, to catch changes that might be delaying startup)
$anvil->Network->load_ips({
clear => 1,
host => $short_host_name,
host_uuid => $host_uuid,
});
$anvil->Network->load_ips({
clear => 1,
host => $peer_short_host_name,
host_uuid => $peer_host_uuid,
});
# Loop through our interfaces and then loop our peers. Test access over them and set
# 'waiting' back to '1' if the connection fails.
foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{network}{$short_host_name}{interface}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
interface => $interface,
waiting => $waiting,
}});
# Only care about our networks.
next if $waiting;
if (not $anvil->Network->is_our_interface({interface => $interface}))
{
# Not an interface we care about
next;
}
my $this_network = ($interface =~ /^(.*?)_/)[0];
my $ip_address = $anvil->data->{network}{$short_host_name}{interface}{$interface}{ip};
my $subnet_mask = $anvil->data->{network}{$short_host_name}{interface}{$interface}{subnet_mask};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:this_network' => $this_network,
's2:ip_address' => $ip_address,
's3:subnet_mask' => $subnet_mask,
}});
### NOTE: I know I could match interface names, but that's not certain enough. It's
### possible (if unlikely) that the network name+numbre differs on our peer. So
### this is safer.
# Loop through my peer's interfaces and see if we're sharing this one.
my $local_network = NetAddr::IP->new($ip_address."/".$subnet_mask);
my $peer_match_found = 0;
foreach my $peer_interface (sort {$a cmp $b} keys %{$anvil->data->{network}{$peer_short_host_name}{interface}})
{
last if $peer_match_found;
my $peer_ip_address = $anvil->data->{network}{$peer_short_host_name}{interface}{$peer_interface}{ip};
my $peer_subnet_mask = $anvil->data->{network}{$peer_short_host_name}{interface}{$peer_interface}{subnet_mask};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
peer_interface => $peer_interface,
peer_ip_address => $peer_ip_address,
peer_subnet_mask => $peer_subnet_mask,
}});
# This the matching network?
next if $subnet_mask ne $peer_subnet_mask;
my $peer_network = NetAddr::IP->new($peer_ip_address."/".$peer_subnet_mask);
if ($peer_network->within($local_network))
{
# Match, test access.
$peer_match_found = 1;
my $access = $anvil->Remote->test_access({
target => $peer_ip_address,
password => $peer_password,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { access => $access }});
if ($access)
{
# This network is good.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0604", variables => {
peer => $peer_short_host_name,
network => $this_network,
peer_ip => $peer_ip_address,
}});
$anvil->data->{sys}{peer_target_ip} = $peer_ip_address;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"sys::peer_target_ip" => $anvil->data->{sys}{peer_target_ip},
}});
}
else
{
# No access, wait and try it again.
$waiting = 1;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, priority => "alert", key => "log_0605", variables => {
peer => $peer_short_host_name,
network => $this_network,
peer_ip => $peer_ip_address,
}});
}
}
}
}
if ($waiting)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, priority => "alert", key => "log_0606", variables => { peer => $peer_short_host_name }});
sleep 5;
}
}
# All networks are up.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, priority => "alert", key => "log_0607", variables => { peer => $peer_short_host_name }});
return(0);
}
# Configure DRBD
sub configure_drbd
{
@ -495,20 +923,52 @@ sub configure_pacemaker
}
if (time > $start_again)
{
# Call cluster start again.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0272"});
$start_again = time + 60;
my $shell_call = $anvil->data->{path}{exe}{pcs}." cluster start --all";
### NOTE: We can't just call 'start --all' again anymore. Now we need to
### stop -> start. Before we do this, make sure there are no servers
### running.
$start_again = time + 60;
my $restart = 1;
my $server_count = keys %{$anvil->data->{cib}{parsed}{data}{server}};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
start_again => $start_again,
shell_call => $shell_call,
start_again => $start_again,
server_count => $server_count,
}});
foreach my $server (sort {$a cmp $b} keys %{$anvil->data->{cib}{parsed}{data}{server}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"cib::parsed::data::server::${server}::active" => $anvil->data->{cib}{parsed}{data}{server}{$server}{active},
}});
if ($anvil->data->{cib}{parsed}{data}{server}{$server}{active})
{
$restart = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { restart => $restart }});
}
}
my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { restart => $restart }});
if ($restart)
{
# Call cluster start again.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0272"});
my $shell_call = $anvil->data->{path}{exe}{pcs}." cluster stop --all";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
start_again => $start_again,
shell_call => $shell_call,
}});
my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
$shell_call = $anvil->data->{path}{exe}{pcs}." cluster start --all";
($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
}
}
sleep 5 if not $both_online;
}
@ -1155,7 +1615,7 @@ sub configure_pacemaker
}
}
# Update (if needed) corosync.conf to use the BCN1 and SN1 as knet networks.
# Update (if needed) corosync.conf to use the BCN1, MN1 and SN1 as knet networks.
if ($machine eq "node1")
{
update_progress($anvil, ($anvil->data->{job}{progress} += 1), "job_0344");
@ -1189,6 +1649,7 @@ sub check_corosync
my $new_password = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password};
while ($waiting)
{
### TODO: Add MN where appropriate
my $problem = $anvil->Cluster->parse_cib({debug => 3});
my $peer_ready = $anvil->data->{cib}{parsed}{peer}{ready};
my $peer_name = $anvil->data->{cib}{parsed}{peer}{name};
@ -2258,11 +2719,6 @@ sub check_local_network
}
}
# Update the hosts file.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 3, key => "job_0112"});
update_progress($anvil, ($anvil->data->{job}{progress} += 2), "job_0112");
$anvil->System->update_hosts({debug => 3});
# Configure SSH by adding ours and our peer's SSH keys to ~/.ssh/known_hosts
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 3, key => "job_0113"});
update_progress($anvil, ($anvil->data->{job}{progress} += 2), "job_0113");

@ -1945,7 +1945,7 @@ sub process_remove
### If we're here, we can now update the resource config file to remove the DR host.
# Refresh the IP info (usually scrubbed by this point)
$anvil->Database->get_ip_addresses();
$anvil->Database->get_ip_addresses({debug => 2});
# First loop to build the node sections, then we'll loop to build the connections
my $node1_volumes = "";
@ -2901,7 +2901,7 @@ sub process_protect
}
# Refresh the IP info (usually scrubbed by this point)
$anvil->Database->get_ip_addresses();
$anvil->Database->get_ip_addresses({debug => 2});
# The connections. Node 1 to 2 always uses the BCN, Either node to DR needs
my $storage_network = "sn1";

@ -29,12 +29,9 @@ $anvil->Get->switches({list => [
"auto-grow-pv",
"check-configured",
"check-database",
"check-network-mapping",
"confirm",
"database-active",
"database-inactive",
"disable-network-mapping",
"enable-network-mapping",
"mark-configured",
"mark-unconfigured",
"resync-database"], man => $THIS_FILE});
@ -58,10 +55,6 @@ elsif (($anvil->data->{switches}{'database-active'}) or ($anvil->data->{switches
{
update_database($anvil);
}
elsif (($anvil->data->{switches}{'enable-network-mapping'}) or ($anvil->data->{switches}{'disable-network-mapping'}) or ($anvil->data->{switches}{'check-network-mapping'}))
{
update_network_mapping($anvil);
}
elsif ($anvil->data->{switches}{'age-out-database'})
{
age_out_data($anvil);
@ -279,118 +272,6 @@ sub update_database
return(0);
}
sub update_network_mapping
{
my ($anvil) = @_;
my $variable_name = "config::map_network";
my ($map_network_value, $map_network_uuid, $map_network_mtime, $map_network_modified_date) = $anvil->Database->read_variable({
variable_name => $variable_name,
variable_source_table => "hosts",
variable_source_uuid => $anvil->data->{sys}{host_uuid},
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:variable_name' => $variable_name,
's2:map_network_value' => $map_network_value,
's3:map_network_mtime' => $map_network_mtime,
's4:map_network_modified_date' => $map_network_modified_date,
's5:map_network_uuid' => $map_network_uuid,
}});
if ($anvil->data->{switches}{'check-network-mapping'})
{
# We'll run for a day (should be cancelled by the program when the user's done, so this
# shouldn't fire in practice).
my $expire_age = 86400;
my $map_network_age = 0;
if ($map_network_uuid)
{
$map_network_age = time - $map_network_mtime;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { map_network_age => $map_network_age }});
}
if ($map_network_value)
{
# How long ago was it set?
$anvil->data->{switches}{'clear-mapping'} = "" if not defined $anvil->data->{switches}{'clear-mapping'};
if (($map_network_age >= $expire_age) or ($anvil->data->{switches}{'clear-mapping'}))
{
# Clear it.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0470"});
$anvil->Database->insert_or_update_variables({
debug => 3,
variable_value => 0,
variable_uuid => $map_network_uuid,
update_value_only => 1,
});
}
else
{
# Mark it so we only track the network.
my $say_age = $anvil->Convert->add_commas({number => $expire_age});
my $timeout = $anvil->Convert->add_commas({number => ($expire_age - $map_network_age)});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0471", variables => {
age => $say_age,
timeout => $timeout,
}});
}
}
else
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0820"});
}
return(0);
}
if ($anvil->data->{switches}{'enable-network-mapping'})
{
if ($map_network_value)
{
# Nothing to do.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0353"});
}
else
{
# Enable network configuring.
my $variable_uuid = $anvil->Database->insert_or_update_variables({
variable_name => $variable_name,
variable_value => 1,
variable_default => "",
variable_description => "striker_0202",
variable_section => "config",
variable_source_uuid => $anvil->Get->host_uuid,
variable_source_table => "hosts",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0354"});
}
}
if ($anvil->data->{switches}{'disable-network-mapping'})
{
if ($map_network_value)
{
# Disable network configuring.
my $variable_uuid = $anvil->Database->insert_or_update_variables({
variable_name => $variable_name,
variable_value => 0,
variable_default => "",
variable_description => "striker_0202",
variable_section => "config",
variable_source_uuid => $anvil->Get->host_uuid,
variable_source_table => "hosts",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0356"});
}
else
{
# Nothing to do.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0355"});
}
}
return(0);
}
sub update_config
{
my ($anvil) = @_;

@ -0,0 +1,505 @@
#!/usr/bin/perl
#
# This daemon watches for network interface link change (unplugged or plugged in network cables).
#
# At this point, the only thing this does is call 'scan-network' when a change is detected.
#
# NOTE: This is designed to be minimal overhead, so there is no attempt to connect to the database. As such,
# be mindful of what this daemon is used for.
#
use strict;
use warnings;
use Data::Dumper;
use Text::Diff;
use Anvil::Tools;
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
if (($running_directory =~ /^\./) && ($ENV{PWD}))
{
$running_directory =~ s/^\./$ENV{PWD}/;
}
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete.
$| = 1;
my $anvil = Anvil::Tools->new();
# Read switches
$anvil->Get->switches({list => [], man => $THIS_FILE});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }});
# Calculate my sum so that we can exit if it changes later.
$anvil->Storage->record_md5sums;
my $next_md5sum_check = time + 30;
my $directory = "/sys/class/net";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { directory => $directory }});
# Now go into the main loop
while(1)
{
### NOTE: A lot of this logic comes from scan-network
my $scan_time = time;
my $trigger = 0;
# Look for interfaces.
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)
{
# 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;
$link_state =~ s/\n$//;
my $mtu = -e $full_path."/mtu" ? $anvil->Storage->read_file({file => $full_path."/mtu"}) : 0;
$mtu =~ s/\n$//;
my $duplex = -e $full_path."/duplex" ? $anvil->Storage->read_file({file => $full_path."/duplex"}) : "unknown"; # full or half?
$duplex =~ s/\n$//;
my $operational = -e $full_path."/operstate" ? $anvil->Storage->read_file({file => $full_path."/operstate"}) : "unknown"; # up or down
$operational =~ s/\n$//;
my $modalias = -e $full_path."/device/modalias" ? $anvil->Storage->read_file({file => $full_path."/device/modalias"}) : "unknown";
$modalias =~ s/\n$//;
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
$speed =~ s/\n$//;
my $media = "unknown";
my $type = "interface";
my $driver = "";
my $tx_bytes = 0; # How many bytes transmitted
my $rx_bytes = 0; # How many bytes received
$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,
}});
# Get the 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_parent = "";
# These are variables that will be needed if this is a bridge interface
my $bridge_id = "";
my $bridge_stp_enabled = "";
# 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 }});
}
# Pick out our driver.
if ($modalias =~ /^virtio:/)
{
$driver = "virtio";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { driver => $driver }});
}
# 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 => {
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";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }});
# Read the bond mode.
$bond_mode = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/mode"});
$bond_mode =~ s/\s.*//;
$bond_mode =~ s/\n$//;
$primary_interface = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/primary"});
$primary_interface =~ s/\n$//;
$primary_reselect = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/primary_reselect"});
$primary_reselect =~ s/\s.*//;
$primary_reselect =~ s/\n$//;
$active_interface = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/active_slave"});
$active_interface =~ s/\n$//;
$mii_polling_interval = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/miimon"});
$mii_polling_interval =~ s/\n$//;
$up_delay = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/updelay"});
$up_delay =~ s/\n$//;
$down_delay = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/downdelay"});
$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_parent = ($target =~ /^.*\/(.*)$/)[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
target => $target,
bond_parent => $bond_parent,
}});
}
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_id =~ s/\n$//;
$bridge_stp_enabled = $anvil->Storage->read_file({debug => 3, file => $full_path."/bridge/stp_state"});
$bridge_stp_enabled =~ s/\n$//;
$speed = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
type => $type,
bridge_id => $bridge_id,
bridge_stp_enabled => $bridge_stp_enabled,
}});
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/)
{
### TODO: We can't assume this, we need to detect virsh net up/down
$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_parent => $bond_parent,
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,
}});
# 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;
}
}
# Trigger?
if (not exists $anvil->data->{last_scan}{$interface})
{
print "The interface: [".$interface."] has been found. We will now monitor it for changes.\n";
$trigger = 1;
}
else
{
# Now look for differences.
if ($anvil->data->{last_scan}{$interface}{active_interface} ne $active_interface)
{
print "The ".$type.": [".$interface."] has a different active interface: [".$anvil->data->{last_scan}{$interface}{active_interface}."] -> [".$active_interface."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{bond_mode} ne $bond_mode)
{
print "The ".$type.": [".$interface."] mode has changed from: [".$anvil->data->{last_scan}{$interface}{bond_mode}."] -> [".$bond_mode."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{bond_parent} ne $bond_parent)
{
print "The ".$type.": [".$interface."] bond parent has changed from: [".$anvil->data->{last_scan}{$interface}{bond_parent}."] -> [".$bond_parent."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{bridge_id} ne $bridge_id)
{
print "The ".$type.": [".$interface."] bridge ID has changed from: [".$anvil->data->{last_scan}{$interface}{bridge_id}."] -> [".$bridge_id."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{bridge_stp_enabled} ne $bridge_stp_enabled)
{
print "The ".$type.": [".$interface."] spanning tree protocol (STP) setting has changed from: [".$anvil->data->{last_scan}{$interface}{bridge_stp_enabled}."] -> [".$bridge_stp_enabled."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{down_delay} ne $down_delay)
{
print "The ".$type.": [".$interface."] down delay has changed from: [".$anvil->data->{last_scan}{$interface}{bridge_stp_enabled}."ms] -> [".$bridge_stp_enabled."ms].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{up_delay} ne $up_delay)
{
print "The ".$type.": [".$interface."] up delay has changed from: [".$anvil->data->{last_scan}{$interface}{up_delay}."ms] -> [".$up_delay."ms].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{duplex} ne $duplex)
{
print "The ".$type.": [".$interface."] duplex has changed from: [".$anvil->data->{last_scan}{$interface}{duplex}."] -> [".$duplex."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{ip_address} ne $ip_address)
{
print "The ".$type.": [".$interface."] ip address has changed from: [".$anvil->data->{last_scan}{$interface}{ip_address}."] -> [".$ip_address."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{subnet_mask} ne $subnet_mask)
{
print "The ".$type.": [".$interface."] subnet_mask has changed from: [".$anvil->data->{last_scan}{$interface}{subnet_mask}."] -> [".$subnet_mask."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{link_state} ne $link_state)
{
print "The ".$type.": [".$interface."] link status has changed from: [".$anvil->data->{last_scan}{$interface}{link_state}."] -> [".$link_state."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{mac_address} ne $mac_address)
{
print "The ".$type.": [".$interface."] MAC address has changed from: [".$anvil->data->{last_scan}{$interface}{mac_address}."] -> [".$mac_address."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{media} ne $media)
{
print "The ".$type.": [".$interface."] media has changed from: [".$anvil->data->{last_scan}{$interface}{media}."] -> [".$media."]. (Excuse me, how?!)\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{mii_polling_interval} ne $mii_polling_interval)
{
print "The ".$type.": [".$interface."] media independent interface (mii) polling interval has changed from: [".$anvil->data->{last_scan}{$interface}{mii_polling_interval}."ms] -> [".$mii_polling_interval."ms].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{mtu} ne $mtu)
{
print "The ".$type.": [".$interface."] maximum transmission unit (mtu) has changed from: [".$anvil->data->{last_scan}{$interface}{mtu}." bytes] -> [".$mtu." bytes].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{operational} ne $operational)
{
print "The ".$type.": [".$interface."] operational status has changed from: [".$anvil->data->{last_scan}{$interface}{operational}."] -> [".$operational."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{primary_reselect} ne $primary_reselect)
{
print "The ".$type.": [".$interface."] primary reselect policy has changed from: [".$anvil->data->{last_scan}{$interface}{primary_reselect}."] -> [".$primary_reselect."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{primary_interface} ne $primary_interface)
{
print "The ".$type.": [".$interface."] primary interface has changed from: [".$anvil->data->{last_scan}{$interface}{primary_interface}."] -> [".$primary_interface."].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{speed} ne $speed)
{
print "The ".$type.": [".$interface."] speed has changed from: [".$anvil->data->{last_scan}{$interface}{speed}." Mbps] -> [".$speed." Mbps].\n";
$trigger = 1;
}
if ($anvil->data->{last_scan}{$interface}{type} ne $type)
{
print "The device: [".$interface."] type has changed from: [".$anvil->data->{last_scan}{$interface}{type}."] -> [".$type."].\n";
$trigger = 1;
}
}
# We'll use this to determine when an interface has disappeared.
$anvil->data->{last_scan}{$interface}{seen} = $scan_time;
# Store new information we found.
$anvil->data->{last_scan}{$interface}{active_interface} = $active_interface;
$anvil->data->{last_scan}{$interface}{bond_mode} = $bond_mode;
$anvil->data->{last_scan}{$interface}{bond_parent} = $bond_parent;
$anvil->data->{last_scan}{$interface}{bridge_id} = $bridge_id;
$anvil->data->{last_scan}{$interface}{bridge_stp_enabled} = $bridge_stp_enabled;
$anvil->data->{last_scan}{$interface}{down_delay} = $down_delay;
$anvil->data->{last_scan}{$interface}{duplex} = $duplex;
$anvil->data->{last_scan}{$interface}{ip_address} = $ip_address;
$anvil->data->{last_scan}{$interface}{link_state} = $link_state;
$anvil->data->{last_scan}{$interface}{mac_address} = $mac_address;
$anvil->data->{last_scan}{$interface}{media} = $media;
$anvil->data->{last_scan}{$interface}{mii_polling_interval} = $mii_polling_interval;
$anvil->data->{last_scan}{$interface}{mtu} = $mtu;
$anvil->data->{last_scan}{$interface}{operational} = $operational;
$anvil->data->{last_scan}{$interface}{primary_reselect} = $primary_reselect;
$anvil->data->{last_scan}{$interface}{primary_interface} = $primary_interface;
$anvil->data->{last_scan}{$interface}{speed} = $speed;
$anvil->data->{last_scan}{$interface}{subnet_mask} = $subnet_mask;
$anvil->data->{last_scan}{$interface}{type} = $type;
$anvil->data->{last_scan}{$interface}{up_delay} = $up_delay;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"last_scan::${interface}::seen" => $anvil->data->{last_scan}{$interface}{seen},
"last_scan::${interface}::active_interface" => $anvil->data->{last_scan}{$interface}{active_interface},
"last_scan::${interface}::bond_mode" => $anvil->data->{last_scan}{$interface}{bond_mode},
"last_scan::${interface}::bond_parent" => $anvil->data->{last_scan}{$interface}{bond_parent},
"last_scan::${interface}::bridge_id" => $anvil->data->{last_scan}{$interface}{bridge_id},
"last_scan::${interface}::bridge_stp_enabled" => $anvil->data->{last_scan}{$interface}{bridge_stp_enabled},
"last_scan::${interface}::down_delay" => $anvil->data->{last_scan}{$interface}{down_delay},
"last_scan::${interface}::duplex" => $anvil->data->{last_scan}{$interface}{duplex},
"last_scan::${interface}::ip_address" => $anvil->data->{last_scan}{$interface}{ip_address},
"last_scan::${interface}::link_state" => $anvil->data->{last_scan}{$interface}{link_state},
"last_scan::${interface}::mac_address" => $anvil->data->{last_scan}{$interface}{mac_address},
"last_scan::${interface}::media" => $anvil->data->{last_scan}{$interface}{media},
"last_scan::${interface}::mii_polling_interval" => $anvil->data->{last_scan}{$interface}{mii_polling_interval},
"last_scan::${interface}::mtu" => $anvil->data->{last_scan}{$interface}{mtu},
"last_scan::${interface}::operational" => $anvil->data->{last_scan}{$interface}{operational},
"last_scan::${interface}::primary_reselect" => $anvil->data->{last_scan}{$interface}{primary_reselect},
"last_scan::${interface}::primary_interface" => $anvil->data->{last_scan}{$interface}{primary_interface},
"last_scan::${interface}::speed" => $anvil->data->{last_scan}{$interface}{speed},
"last_scan::${interface}::subnet_mask" => $anvil->data->{last_scan}{$interface}{subnet_mask},
"last_scan::${interface}::type" => $anvil->data->{last_scan}{$interface}{type},
"last_scan::${interface}::up_delay" => $anvil->data->{last_scan}{$interface}{up_delay},
}});
}
}
closedir(DIRECTORY);
# Now look for interfaces that disappeared.
foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{last_scan}})
{
next if $anvil->data->{last_scan}{$interface}{seen} == $scan_time;
print "The device: [".$interface."] appears to have disappeared!\n";
delete $anvil->data->{last_scan}{$interface};
$trigger = 1;
}
# Trigger?
if ($trigger)
{
my $shell_call = $anvil->data->{path}{directories}{scan_agents}."/scan-network/scan-network".$anvil->Log->switches;
print "Triggering the call to run: [".$shell_call."]\n";
$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 (time > $next_md5sum_check)
{
$next_md5sum_check = time + 30;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { next_md5sum_check => $next_md5sum_check }});
if ($anvil->Storage->check_md5sums)
{
# NOTE: We exit with '0' to prevent systemctl from showing a scary red message.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "message_0014"});
$anvil->nice_exit({exit_code => 0});
}
}
sleep 2;
}

@ -91,8 +91,8 @@ sub refresh_unified_metadata
backup => 0,
file => $anvil->data->{path}{data}{fences_unified_metadata},
body => $anvil->data->{fences}{unified_xml},
user => "apache",
group => "apache",
user => "striker-ui-api",
group => "striker-ui-api",
mode => "0666",
});
}

@ -321,8 +321,11 @@ sub run_jobs
# Make sure the VNC port is open.
$anvil->Network->manage_firewall();
# Add the server to the cluster.
add_server_to_cluster($anvil);
# If we're not the peer, add the server to the cluster.
if (not $anvil->data->{job}{peer_mode})
{
add_server_to_cluster($anvil);
}
# Update the database by calling select scan agents
$anvil->Job->update_progress({
@ -368,8 +371,9 @@ sub add_server_to_cluster
# Is our peer in the cluster? For that matter, are we?
my $problem = $anvil->Cluster->add_server({
debug => 2,
server_name => $anvil->data->{job}{server_name},
debug => 2,
server_name => $anvil->data->{job}{server_name},
ok_if_exists => 1,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
if ($problem)

@ -44,6 +44,11 @@ $anvil->Get->switches({list => [], man => $THIS_FILE});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }});
### TODO: Remove before PR!
# Force up the logging.
$anvil->Log->level({set => 2});
$anvil->Log->secure({set => 1});
# Make sure we're running as 'root'
# $< == real UID, $> == effective UID
if (($< != 0) && ($> != 0))
@ -94,7 +99,7 @@ if (not $anvil->data->{sys}{database}{connections})
# Check to see if we should run. Also checks/sets enable/disable requests.
prerun_checks($anvil);
# Wait until I can ping the peer on all three networks. This will not return until access is available on all
# Wait until I can ping the peer on all networks. This will not return until access is available on all
# networks. There is no timeout.
wait_for_access($anvil);
@ -343,7 +348,7 @@ sub start_pacemaker
while ($waiting)
{
$waiting = 0;
my ($problem) = $anvil->Cluster->parse_cib({debug => 3});
my ($problem) = $anvil->Cluster->parse_cib({debug => 2});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
if ($problem)
{

@ -483,7 +483,7 @@ sub process_incoming_file
$anvil->nice_exit({exit_code => 1});
}
# Change the owner as it'll be apache, which won't be a valid users on anvil members.
# Change the owner as it'll be striker-ui-api, which won't be a valid users on anvil members.
$anvil->Storage->change_owner({
debug => 2,
path => $target_file,

File diff suppressed because it is too large Load Diff

@ -63,13 +63,18 @@ sub striker_checks
{
my ($anvil) = @_;
# This checks to make sure that the new dr_links table exists, and that existing anvil_dr1_host_uuid
# entries are copied.
update_dr_links($anvil);
# This checks to make sure that the new network manager columns are in place
update_network_interfaces($anvil);
update_bonds($anvil);
update_bridges($anvil);
# This checks to make sure that the new 'file_locations' -> 'file_location_ready' column exists.
update_file_location_ready($anvil);
# This checks to make sure that the new dr_links table exists, and that existing anvil_dr1_host_uuid
# entries are copied.
update_dr_links($anvil);
# This replaces anvil_uuid with host_uuid to support more granular location info to support the new
# multi-target DR system
update_file_locations($anvil);
@ -243,12 +248,300 @@ CREATE TRIGGER trigger_dr_links
return(0);
}
sub update_bridges
{
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 = 'bridges' AND column_name = 'bridge_nm_uuid';";
$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.bridges ADD COLUMN bridge_nm_uuid uuid;";
push @{$queries}, "ALTER TABLE history.bridges ADD COLUMN bridge_nm_uuid uuid;";
push @{$queries}, "DROP FUNCTION history_bridges() CASCADE;";
push @{$queries}, q|CREATE FUNCTION history_bridges() RETURNS trigger
AS $$
DECLARE
history_bridges RECORD;
BEGIN
SELECT INTO history_bridges * FROM bridges WHERE bridge_uuid = new.bridge_uuid;
INSERT INTO history.bridges
(bridge_uuid,
bridge_host_uuid,
bridge_nm_uuid,
bridge_name,
bridge_id,
bridge_mac_address,
bridge_mtu,
bridge_stp_enabled,
modified_date)
VALUES
(history_bridges.bridge_uuid,
history_bridges.bridge_host_uuid,
history_bridges.bridge_nm_uuid,
history_bridges.bridge_name,
history_bridges.bridge_id,
history_bridges.bridge_mac_address,
history_bridges.bridge_mtu,
history_bridges.bridge_stp_enabled,
history_bridges.modified_date);
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
ALTER FUNCTION history_bridges() OWNER TO admin;
CREATE TRIGGER trigger_bridges
AFTER INSERT OR UPDATE ON bridges
FOR EACH ROW EXECUTE PROCEDURE history_bridges();
|;
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);
}
sub update_bonds
{
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 = 'bonds' AND column_name = 'bond_nm_uuid';";
$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.bonds ADD COLUMN bond_nm_uuid uuid;";
push @{$queries}, "ALTER TABLE history.bonds ADD COLUMN bond_nm_uuid uuid;";
push @{$queries}, "DROP FUNCTION history_bonds() CASCADE;";
push @{$queries}, q|CREATE FUNCTION history_bonds() RETURNS trigger
AS $$
DECLARE
history_bonds RECORD;
BEGIN
SELECT INTO history_bonds * FROM bonds WHERE bond_uuid = new.bond_uuid;
INSERT INTO history.bonds
(bond_uuid,
bond_host_uuid,
bond_nm_uuid,
bond_name,
bond_mode,
bond_mtu,
bond_primary_interface,
bond_primary_reselect,
bond_active_interface,
bond_mii_polling_interval,
bond_up_delay,
bond_down_delay,
bond_mac_address,
bond_operational,
bond_bridge_uuid,
modified_date)
VALUES
(history_bonds.bond_uuid,
history_bonds.bond_host_uuid,
history_bonds.bond_nm_uuid,
history_bonds.bond_name,
history_bonds.bond_mode,
history_bonds.bond_mtu,
history_bonds.bond_primary_interface,
history_bonds.bond_primary_reselect,
history_bonds.bond_active_interface,
history_bonds.bond_mii_polling_interval,
history_bonds.bond_up_delay,
history_bonds.bond_down_delay,
history_bonds.bond_mac_address,
history_bonds.bond_operational,
history_bonds.bond_bridge_uuid,
history_bonds.modified_date);
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
ALTER FUNCTION history_bonds() OWNER TO admin;
CREATE TRIGGER trigger_bonds
AFTER INSERT OR UPDATE ON bonds
FOR EACH ROW EXECUTE PROCEDURE history_bonds();
|;
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);
}
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_nm_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_nm_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_nm_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_nm_uuid uuid;";
push @{$queries}, "ALTER TABLE history.network_interfaces ADD COLUMN network_interface_nm_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_nm_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_nm_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';";

@ -132,7 +132,7 @@ sub show_status
if ($anvil->data->{switches}{watch})
{
my $date = $anvil->Get->date_and_time();
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0382", variables => { date => $date }});
print $anvil->Words->string({key => "message_0382", variables => { date => $date }})."\n";
}
print $anvil->data->{display}{status};

@ -192,19 +192,19 @@ sub create_constraint
my $rule_found = 0;
my $rule_name = "drbd-fenced_".$target_server;
my $shell_call = $conf->{path}{exe}{pcs}." constraint location config show ".$target_server;
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 1});
open (my $file_handle, $shell_call." 2>&1 |") or die "Failed to call: [".$shell_call."]. The error was: $!\n";
while(<$file_handle>)
{
# This should not generate output.
chomp;
my $line = $_;
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 1});
if ($line =~ /Expression: $rule_name /)
{
$rule_found = 1;
to_log($conf, {message => "rule_found: [".$rule_found."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "rule_found: [".$rule_found."]", 'line' => __LINE__, level => 1});
last;
}
}
@ -220,14 +220,14 @@ sub create_constraint
# Set the node attribute
my $rule_set = 0;
$shell_call = $conf->{path}{exe}{crm_attribute}." --type nodes --node ".$target_node." --name ".$rule_name." --update 1";
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 1});
open ($file_handle, $shell_call." 2>&1 |") or die "Failed to call: [".$shell_call."]. The error was: $!\n";
while(<$file_handle>)
{
# This should not generate output.
chomp;
my $line = $_;
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 1});
}
close $file_handle;
@ -235,19 +235,19 @@ sub create_constraint
$rule_set = 0;
my $rule_output = "";
$shell_call = $conf->{path}{exe}{crm_attribute}." --type nodes --node ".$target_node." --name ".$rule_name." --query";
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 1});
open ($file_handle, $shell_call." 2>&1 |") or die "Failed to call: [".$shell_call."]. The error was: $!\n";
while(<$file_handle>)
{
# This should not generate output.
chomp;
my $line = $_;
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 1});
if (($line =~ /name=$rule_name/) && ($line =~ /value=1/))
{
$rule_set = 1;
to_log($conf, {message => "rule_set: [".$rule_set."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "rule_set: [".$rule_set."]", 'line' => __LINE__, level => 1});
last;
}
else

@ -91,8 +91,10 @@ $anvil->Storage->record_md5sums();
# Connect to DBs.
wait_for_database($anvil);
### NOTE: We need to collect data from the start. Once confirmed this isn't introducing old problems, remove
### this function
# If we're not configured, sleep.
wait_until_configured($anvil);
#wait_until_configured($anvil);
# Startup tasks.
startup_tasks($anvil);
@ -141,7 +143,7 @@ while(1)
if ($anvil->data->{sys}{database}{connections})
{
# Run the normal tasks
$anvil->ScanCore->call_scan_agents();
$anvil->ScanCore->call_scan_agents({debug => 2});
# Do post-scan analysis.
$anvil->ScanCore->post_scan_analysis({debug => 2});

@ -1288,6 +1288,7 @@ fi;
remote_user => "root",
}});
my ($host_uuid, $error, $return_code) = $anvil->Remote->call({
debug => 2,
shell_call => $shell_call,
target => $ip,
password => $anvil->data->{base}{password}{desired},

@ -353,12 +353,13 @@ sub collect_remote_data
# Copying the file
print "Done! Copying to here... ";
$anvil->Storage->rsync({
debug => 2,
source => "root\@".$anvil->data->{peer}{$short_host_name}{access}{ip}.":/tmp/journalctl-previous-boot.log",
destination => $target_directory."/",
});
my $test_file = $target_directory."/tmp/journalctl-previous-boot.log";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { test_file => $test_file }});
if (not -e $test_file)
if (-e $test_file)
{
print "Done.\n";
}
@ -392,12 +393,13 @@ sub collect_remote_data
# Copying the file
print "Done! Copying to here... ";
$anvil->Storage->rsync({
debug => 2,
source => "root\@".$anvil->data->{peer}{$short_host_name}{access}{ip}.":/tmp/journalctl-current-boot.log",
destination => $target_directory."/",
});
$test_file = $target_directory."/journalctl-current-boot.log";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { test_file => $test_file }});
if (not -e $test_file)
if (-e $test_file)
{
print "Done.\n";
}
@ -431,12 +433,13 @@ sub collect_remote_data
{
print "- Grabbing cloud-init logs... ";
$anvil->Storage->rsync({
debug => 2,
source => "root\@".$anvil->data->{peer}{$short_host_name}{access}{ip}.":/var/log/cloud-init*",
destination => $target_directory."/",
});
$test_file = $target_directory."/cloud-init.log";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { test_file => $test_file }});
if (not -e $test_file)
if (-e $test_file)
{
print "Done.\n";
}
@ -499,12 +502,13 @@ sub collect_remote_data
print "- Grabbing hosts file... ";
$anvil->Storage->rsync({
debug => 2,
source => "root\@".$anvil->data->{peer}{$short_host_name}{access}{ip}.":/etc/hosts",
destination => $target_directory."/",
});
$test_file = $target_directory."/hosts";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { test_file => $test_file }});
if (not -e $test_file)
if (-e $test_file)
{
print "Done.\n";
}
@ -522,12 +526,13 @@ sub collect_remote_data
print "- Grabbing Anvil! log... ";
$anvil->Storage->rsync({
debug => 2,
source => "root\@".$anvil->data->{peer}{$short_host_name}{access}{ip}.":/var/log/anvil.log",
destination => $target_directory."/",
});
$test_file = $target_directory."/anvil.log";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { test_file => $test_file }});
if (not -e $test_file)
if (-e $test_file)
{
print "Done.\n";
}
@ -559,12 +564,13 @@ sub collect_remote_data
# Copying the file
print "Done! Copying to here... ";
$anvil->Storage->rsync({
debug => 2,
source => "root\@".$anvil->data->{peer}{$short_host_name}{access}{ip}.":/tmp/cib.xml",
destination => $target_directory."/",
});
my $test_file = $target_directory."/cib.xml";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { test_file => $test_file }});
if (not -e $test_file)
if (-e $test_file)
{
print "Done.\n";
}
@ -586,6 +592,7 @@ sub collect_remote_data
{
print "- Collecting server definitions... ";
$anvil->Storage->rsync({
debug => 2,
source => "root\@".$anvil->data->{peer}{$short_host_name}{access}{ip}.":/mnt/shared/definitions",
destination => $target_directory."/",
});
@ -593,6 +600,7 @@ sub collect_remote_data
print "- Collecting replicated storage config... ";
$anvil->Storage->rsync({
debug => 2,
source => "root\@".$anvil->data->{peer}{$short_host_name}{access}{ip}.":/etc/drbd.d",
destination => $target_directory."/",
});

@ -163,7 +163,7 @@ sub add_databases
$anvil->Network->get_ips({debug => 3});
$anvil->Network->get_ips({
debug => 3,
debug => 2,
target => $target,
remote_user => "root",
password => $anvil->data->{data}{password},
@ -171,7 +171,7 @@ sub add_databases
});
my $local_host = $anvil->Get->short_host_name();
my ($match) = $anvil->Network->find_matches({
debug => 3,
debug => 2,
first => $local_host,
second => $target,
source => $THIS_FILE,
@ -283,6 +283,7 @@ sub add_databases
# Find a match between the target and the peer.
my ($match) = $anvil->Network->find_matches({
debug => 2,
first => $target,
second => $uuid,
source => $THIS_FILE,

@ -709,7 +709,7 @@ sub setup_boot_environment
{
# Updated
$anvil->Storage->change_mode({path => $kickstart_file, mode => "0664"});
$anvil->Storage->change_owner({path => $kickstart_file, user => "apache", group => "apache" });
$anvil->Storage->change_owner({path => $kickstart_file, user => "striker-ui-api", group => "striker-ui-api" });
print $anvil->Words->string({key => "message_0097", variables => { file => $kickstart_file }})."\n";
update_progress($anvil, $progress, "message_0097,!!file!".$kickstart_file."!!");

@ -475,7 +475,7 @@ if ($local_uuid)
#####################################################################################################
### TODO: This will need to set the proper SELinux context.
# Apache run scripts can't call the system UUID, so we'll write it to a text file.
# striker-ui-api run scripts can't call the system UUID, so we'll write it to a text file.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "path::data::host_uuid" => $anvil->data->{path}{data}{host_uuid} }});
if (not -e $anvil->data->{path}{data}{host_uuid})
{
@ -483,8 +483,8 @@ if ($local_uuid)
debug => 3,
file => $anvil->data->{path}{data}{host_uuid},
body => $anvil->Get->host_uuid,
user => "apache",
group => "apache",
user => "striker-ui-api",
group => "striker-ui-api",
mode => "0666",
overwrite => 0,
});

@ -158,19 +158,19 @@ sub remove_constraint
my $rule_found = 0;
my $rule_output = "";
my $shell_call = $conf->{path}{exe}{crm_attribute}." --type nodes --node ".$target_node." --name ".$rule_name." --query";
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 1});
open (my $file_handle, $shell_call." 2>&1 |") or die "Failed to call: [".$shell_call."]. The error was: $!\n";
while(<$file_handle>)
{
# This should not generate output.
chomp;
my $line = $_;
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 1});
if (($line =~ /name=$rule_name/) && ($line =~ /value=0/))
{
$rule_set = 0;
to_log($conf, {message => "rule_set: [".$rule_set."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "rule_set: [".$rule_set."]", 'line' => __LINE__, level => 1});
last;
}
else
@ -189,33 +189,33 @@ sub remove_constraint
# Clear the node attribute
$shell_call = $conf->{path}{exe}{crm_attribute}." --type nodes --node ".$target_node." --name ".$rule_name." --update 0";
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 1});
open ($file_handle, $shell_call." 2>&1 |") or die "Failed to call: [".$shell_call."]. The error was: $!\n";
while(<$file_handle>)
{
# This should not generate output.
chomp;
my $line = $_;
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 3});
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 1});
}
close $file_handle;
# Check that the rule was set.
$rule_output = "";
$shell_call = $conf->{path}{exe}{crm_attribute}." --type nodes --node ".$target_node." --name ".$rule_name." --query";
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "Calling: [".$shell_call."]", 'line' => __LINE__, level => 1});
open ($file_handle, $shell_call." 2>&1 |") or die "Failed to call: [".$shell_call."]. The error was: $!\n";
while(<$file_handle>)
{
# This should not generate output.
chomp;
my $line = $_;
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "Output: [".$line."]", 'line' => __LINE__, level => 1});
if (($line =~ /name=$rule_name/) && ($line =~ /value=0/))
{
$rule_set = 0;
to_log($conf, {message => "rule_set: [".$rule_set."]", 'line' => __LINE__, level => 2});
to_log($conf, {message => "rule_set: [".$rule_set."]", 'line' => __LINE__, level => 1});
last;
}
else

@ -3,6 +3,7 @@ MAINTAINERCLEANFILES = Makefile.in
servicedir = $(SYSTEMD_UNIT_DIR)
dist_service_DATA = \
anvil-daemon.service \
anvil-monitor-network.service \
anvil-safe-start.service \
scancore.service \
striker-ui-api.service

@ -0,0 +1,12 @@
[Unit]
Description=Anvil! Intelligent Availability Platform - Network Monitor Daemon
Wants=network.target
[Service]
Type=simple
ExecStart=/usr/sbin/anvil-monitor-network
ExecStop=/bin/kill -WINCH ${MAINPID}
Restart=always
[Install]
WantedBy=multi-user.target
Loading…
Cancel
Save