Merge pull request #189 from ClusterLabs/anvil-tools-dev

Anvil tools dev
main
digimer-bot 3 years ago committed by GitHub
commit 13a4824db3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      Anvil/Tools.pm
  2. 165
      Anvil/Tools/DRBD.pm
  3. 786
      Anvil/Tools/Database.pm
  4. 92
      Anvil/Tools/Storage.pm
  5. 7
      Anvil/Tools/System.pm
  6. 7
      anvil.conf
  7. 44
      notes
  8. 2
      scancore-agents/scan-drbd/scan-drbd
  9. 139
      share/words.xml
  10. 163
      tools/anvil-daemon
  11. 1597
      tools/anvil-manage-dr
  12. 2
      tools/anvil-manage-firewall
  13. 2
      tools/anvil-parse-fence-agents
  14. 12
      tools/striker-manage-install-target
  15. 6
      tools/striker-prep-database

@ -874,10 +874,14 @@ sub _set_defaults
locking_reap_age => 300,
log_transactions => 0,
maximum_batch_size => 25000,
# NOTE: Do NOT change this unless you are certain all machines that use this host
# have been likewise updated!
name => "anvil",
read_uuid => "",
test_table => "hosts",
timestamp => "",
# NOTE: Do NOT change this unless you are certain all machines that use this host
# have been likewise updated!
user => "admin",
use_handle => "",
},
@ -1077,6 +1081,7 @@ sub _set_paths
html => "/var/www/html",
ifcfg => "/etc/sysconfig/network-scripts",
journald => "/var/log/journal",
pgsql => "/var/lib/pgsql/",
resource_status => "/sys/kernel/debug/drbd/resources",
scan_agents => "/usr/sbin/scancore-agents",
shared => {
@ -1109,6 +1114,7 @@ sub _set_paths
'anvil-get-server-screenshot' => "/usr/sbin/anvil-get-server-screenshot",
'anvil-join-anvil' => "/usr/sbin/anvil-join-anvil",
'anvil-maintenance-mode' => "/usr/sbin/anvil-maintenance-mode",
'anvil-manage-dr' => "/usr/sbin/anvil-manage-dr",
'anvil-manage-firewall' => "/usr/sbin/anvil-manage-firewall",
'anvil-manage-keys' => "/usr/sbin/anvil-manage-keys",
'anvil-manage-power' => "/usr/sbin/anvil-manage-power",
@ -1146,6 +1152,7 @@ sub _set_paths
dnf => "/usr/bin/dnf",
drbdadm => "/usr/sbin/drbdadm",
drbdsetup => "/usr/sbin/drbdsetup",
dropdb => "/usr/bin/dropdb",
echo => "/usr/bin/echo",
ethtool => "/usr/sbin/ethtool",
expect => "/usr/bin/expect",
@ -1167,6 +1174,10 @@ sub _set_paths
ip => "/usr/sbin/ip",
'ipmi-oem' => "/usr/sbin/ipmi-oem",
ipmitool => "/usr/bin/ipmitool",
### NOTE: When System->manage_firewall() is done, search for and replace all
### instances where iptables is called and replace with firewall-cmd
### calls
iptables => "/usr/sbin/iptables",
'iptables-save' => "/usr/sbin/iptables-save",
journalctl => "/usr/bin/journalctl",
logger => "/usr/bin/logger",
@ -1196,6 +1207,7 @@ sub _set_paths
pcs => "/usr/sbin/pcs",
perccli64 => "/opt/MegaRAID/perccli/perccli64",
ping => "/usr/bin/ping",
pg_dump => "/usr/bin/pg_dump",
pgrep => "/usr/bin/pgrep",
ps => "/usr/bin/ps",
psql => "/usr/bin/psql",

@ -20,6 +20,7 @@ my $THIS_FILE = "DRBD.pm";
# delete_resource
# gather_data
# get_devices
# get_next_resource
# get_status
# manage_resource
# reload_defaults
@ -617,6 +618,12 @@ sub gather_data
$anvil->data->{new}{scan_drbd}{scan_drbd_timeout} = 6; # Default is '60', 6 seconds
$anvil->data->{new}{scan_drbd}{scan_drbd_total_sync_speed} = 0;
my $local_host_name = $anvil->Get->host_name;
my $local_short_host_name = $anvil->Get->short_host_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
local_host_name => $local_host_name,
local_short_host_name => $local_short_host_name,
}});
foreach my $name ($dom->findnodes('/config/common/section'))
{
my $section = $name->{name};
@ -705,7 +712,7 @@ sub gather_data
}});
# Record the local data only.
if (($this_host_name eq $anvil->Get->host_name) or ($this_host_name eq $anvil->Get->short_host_name))
if (($this_host_name eq $local_host_name) or ($this_host_name eq $local_short_host_name))
{
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{device_path} = $volume_vnr->findvalue('./device');
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{backing_disk} = $volume_vnr->findvalue('./disk');
@ -722,43 +729,99 @@ sub gather_data
foreach my $connection ($name->findnodes('./connection'))
{
my $host1_name = "";
my $host1_ip_address = "";
my $host1_tcp_port = "";
my $host2_name = "";
my $host2_ip_address = "";
my $host2_tcp_port = "";
my $peer = "";
foreach my $host ($connection->findnodes('./host'))
{
my $this_host_name = $host->{name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_host_name => $this_host_name }});
next if (($this_host_name eq $anvil->Get->host_name) or ($this_host_name eq $anvil->Get->short_host_name));
$peer = $this_host_name;
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{peer_ip_address} = $host->findvalue('./address');
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{tcp_port} = $host->findvalue('./address/@port');;
if (not $host1_name)
{
$host1_name = $this_host_name;
$host1_ip_address = $host->findvalue('./address');
$host1_tcp_port = $host->findvalue('./address/@port');
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:new::resource::${resource}::peer::${peer}::peer_ip_address" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{peer_ip_address},
"s2:new::resource::${resource}::peer::${peer}::tcp_port" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{tcp_port},
host1_name => $host1_name,
host1_ip_address => $host1_ip_address,
host1_tcp_port => $host1_tcp_port,
}});
if (not exists $anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol})
}
else
{
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol} = "unknown";
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{fencing} = "unknown";
$host2_name = $this_host_name;
$host2_ip_address = $host->findvalue('./address');
$host2_tcp_port = $host->findvalue('./address/@port');
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:new::resource::${resource}::peer::${peer}::protocol" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol},
"s2:new::resource::${resource}::peer::${peer}::fencing" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{fencing},
host2_name => $host2_name,
host2_ip_address => $host2_ip_address,
host2_tcp_port => $host2_tcp_port,
}});
}
foreach my $volume (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$resource}{volume}})
# $peer = $this_host_name;
# $anvil->data->{new}{resource}{$resource}{peer}{$peer}{peer_ip_address} = $host->findvalue('./address');
# $anvil->data->{new}{resource}{$resource}{peer}{$peer}{tcp_port} = $host->findvalue('./address/@port');
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
# "s1:new::resource::${resource}::peer::${peer}::peer_ip_address" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{peer_ip_address},
# "s2:new::resource::${resource}::peer::${peer}::tcp_port" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{tcp_port}." (".$host->findvalue('./address/@port').")",
# }});
# if (not exists $anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol})
# {
# $anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol} = "unknown";
# $anvil->data->{new}{resource}{$resource}{peer}{$peer}{fencing} = "unknown";
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
# "s1:new::resource::${resource}::peer::${peer}::protocol" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol},
# "s2:new::resource::${resource}::peer::${peer}::fencing" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{fencing},
# }});
# }
#
# foreach my $volume (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$resource}{volume}})
# {
# $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{connection_state} = "disconnected";
# $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{local_disk_state} = "down";
# $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{peer_disk_state} = "unknown";
# $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{local_role} = "down";
# $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{peer_role} = "unknown";
# $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{out_of_sync_size} = -1;
# $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{replication_speed} = 0;
# $anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{estimated_time_to_sync} = 0;
# }
}
if (($host1_name eq $local_short_host_name) or
($host1_name eq $local_host_name) or
($host2_name eq $local_short_host_name) or
($host2_name eq $local_host_name))
{
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{connection_state} = "disconnected";
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{local_disk_state} = "down";
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{peer_disk_state} = "unknown";
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{local_role} = "down";
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{peer_role} = "unknown";
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{out_of_sync_size} = -1;
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{replication_speed} = 0;
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{estimated_time_to_sync} = 0;
# This is one of our connections.
my $peer = "";
if (($host1_name eq $local_short_host_name) or ($host1_name eq $local_host_name))
{
# Our peer is host2
$peer = $host2_name;
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{peer_ip_address} = $host2_ip_address;
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{tcp_port} = $host2_tcp_port;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:new::resource::${resource}::peer::${peer}::peer_ip_address" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{peer_ip_address},
"s2:new::resource::${resource}::peer::${peer}::tcp_port" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{tcp_port},
}});
}
else
{
# Our peer is host1
$peer = $host1_name;
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{peer_ip_address} = $host1_ip_address;
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{tcp_port} = $host1_tcp_port;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:new::resource::${resource}::peer::${peer}::peer_ip_address" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{peer_ip_address},
"s2:new::resource::${resource}::peer::${peer}::tcp_port" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{tcp_port},
}});
}
foreach my $name ($connection->findnodes('./section'))
@ -794,6 +857,19 @@ sub gather_data
}
}
}
foreach my $volume (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$resource}{volume}})
{
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{connection_state} = "disconnected";
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{local_disk_state} = "down";
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{peer_disk_state} = "unknown";
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{local_role} = "down";
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{peer_role} = "unknown";
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{out_of_sync_size} = -1;
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{replication_speed} = 0;
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{estimated_time_to_sync} = 0;
}
}
}
}
}
@ -1249,6 +1325,10 @@ Parameters;
This is the Anvil! in which we're looking for the next free resources. It's required, but generally it doesn't need to be specified as we can find it via C<< Cluster->get_anvil_uuid() >>.
=head3 dr_tcp_ports (optional, default '0')
If set, the 'free_port' returned will be a comma-separated pair of TCP ports. This is meant to help find two TCP ports needed to connect a resource from both nodes to a DR host.
=head3 resource_name (optional)
If this is set, and the resource is found to already exist, the first DRBD minor number and first used TCP port are returned. Alternatively, if C<< force_unique >> is set to C<< 1 >>, and the resource is found to exist, empty strings are returned.
@ -1267,10 +1347,12 @@ sub get_next_resource
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "DRBD->get_next_resource()" }});
my $anvil_uuid = defined $parameter->{anvil_uuid} ? $parameter->{anvil_uuid} : "";
my $dr_tcp_ports = defined $parameter->{dr_tcp_ports} ? $parameter->{dr_tcp_ports} : "";
my $resource_name = defined $parameter->{resource_name} ? $parameter->{resource_name} : "";
my $force_unique = defined $parameter->{force_unique} ? $parameter->{force_unique} : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
anvil_uuid => $anvil_uuid,
dr_tcp_ports => $dr_tcp_ports,
resource_name => $resource_name,
force_unique => $force_unique,
}});
@ -1436,19 +1518,52 @@ ORDER BY
$looking = 1;
$free_port = 7788;
my $tcp_pair = "";
while($looking)
{
if (exists $anvil->data->{drbd}{used_resources}{tcp_port}{$free_port})
if ((exists $anvil->data->{drbd}{used_resources}{tcp_port}{$free_port}) &&
($anvil->data->{drbd}{used_resources}{tcp_port}{$free_port}{used}))
{
$free_port++;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { free_port => $free_port }});
}
else
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { free_port => $free_port }});
if ($dr_tcp_ports)
{
if (not $tcp_pair)
{
$tcp_pair = $free_port;
$free_port++;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
tcp_pair => $tcp_pair,
free_port => $free_port,
}});
}
elsif ($tcp_pair !~ /,/)
{
$tcp_pair .= ",".$free_port;
$looking = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
tcp_pair => $tcp_pair,
looking => $looking,
}});
}
}
else
{
$looking = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { looking => $looking }});
}
}
}
if ($dr_tcp_ports)
{
$free_port = $tcp_pair;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { free_port => $free_port }});
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
free_minor => $free_minor,

@ -17,6 +17,7 @@ my $THIS_FILE = "Database.pm";
### Methods;
# archive_database
# backup_database
# check_file_locations
# check_lock_age
# check_for_schema
@ -78,6 +79,7 @@ my $THIS_FILE = "Database.pm";
# insert_or_update_upses
# insert_or_update_users
# insert_or_update_variables
# load_database
# lock_file
# locking
# manage_anvil_conf
@ -300,6 +302,81 @@ sub archive_database
}
=head2 backup_database
This backs up the database to the C<< path::directories::pgsql >> directory as the file name C<< anvil_pg_dump.<host_uuid>.out >>.
If the backup is successful, the full path to the backup file is returned. If there is a problem, C<< !!error!! >> is returned.
B<< Note >>: This method must be called by the root user.
B<< Note >>: If C<< sys::database::name >> has been changed, the dump file name will match.
This method takes no parameters.
=cut
sub backup_database
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->backup_database()" }});
# Only the root user can do this
if (($< != 0) && ($> != 0))
{
# Not root
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0352"});
return('!!error!!');
}
my $start_time = time;
my $dump_file = $anvil->data->{path}{directories}{pgsql}."/".$anvil->data->{sys}{database}{name}."_db_dump.".$anvil->Get->host_uuid().".sql";
$dump_file =~ s/\/\//\//g;
my $dump_call = $anvil->data->{path}{exe}{su}." - postgres -c \"".$anvil->data->{path}{exe}{pg_dump}." ".$anvil->data->{sys}{database}{name}." > ".$dump_file."\"";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
dump_file => $dump_file,
dump_call => $dump_call,
}});
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $dump_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
if ($return_code)
{
# Dump failed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0351", variables => {
shell_call => $dump_call,
return_code => $return_code,
output => $output,
}});
# Clear the out file.
if (-e $dump_file)
{
unlink $dump_file;
}
return('!!error!!');
}
# Record the stats
$anvil->Storage->get_file_stats({debug => $debug, file_path => $dump_file});
my $dump_time = time - $start_time;
my $size = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{file_stat}{$dump_file}{size}});
my $size_bytes = $anvil->Convert->add_commas({number => $anvil->data->{file_stat}{$dump_file}{size}});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0654", variables => {
file => $dump_file,
took => $dump_time,
size => $size,
size_bytes => $size_bytes,
}});
return($dump_file);
}
=head2 check_file_locations
This method checks to see that there is a corresponding entry in C<< file_locations >> for all Anvil! systems and files in the database. Any that are found to be missing will be set to C<< file_location_active >> -> c<< false >>.
@ -722,18 +799,15 @@ sub configure_pgsql
return(1);
}
# First, is it running?
# First, is it running and is it initialized?
my $initialized = 0;
my $running = $anvil->System->check_daemon({debug => $debug, daemon => $anvil->data->{sys}{daemon}{postgresql}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { running => $running }});
if (not $running)
{
# Do we need to initialize the databae?
if (not -e $anvil->data->{path}{configs}{'pg_hba.conf'})
{
# Initialize.
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $anvil->data->{path}{exe}{'postgresql-setup'}." initdb", source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output, return_code => $return_code }});
# Initialize. Record that we did so, so that we know to start the daemon.
my ($output, $return_code) = $anvil->System->call({debug => 1, shell_call => $anvil->data->{path}{exe}{'postgresql-setup'}." initdb", source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { output => $output, return_code => $return_code }});
# Did it succeed?
if (not -e $anvil->data->{path}{configs}{'pg_hba.conf'})
@ -747,10 +821,12 @@ sub configure_pgsql
# Initialized!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0055"});
# Enable it on boot.
my $return_code = $anvil->System->enable_daemon({debug => $debug, daemon => $anvil->data->{sys}{daemon}{postgresql}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { return_code => $return_code }});
}
$initialized = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { initialized => $initialized }});
### NOTE: We no longer enable postgres on boot. When the first call is made to
### Database->connect on a striker, and no databases are available, it will
### start up the local daemon then.
}
}
@ -835,7 +911,7 @@ sub configure_pgsql
{
# Back up the existing one, if needed.
my $pg_hba_backup = $anvil->data->{path}{directories}{backups}."/pgsql/pg_hba.conf";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { pg_hba_backup => $pg_hba_backup }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { pg_hba_backup => $pg_hba_backup }});
if (not -e $pg_hba_backup)
{
$anvil->Storage->copy_file({
@ -858,10 +934,13 @@ sub configure_pgsql
# Start or restart the daemon?
if (not $running)
{
# Did we initialize?
if ($initialized)
{
# Start the daemon.
my $return_code = $anvil->System->start_daemon({daemon => $anvil->data->{sys}{daemon}{postgresql}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { return_code => $return_code }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { return_code => $return_code }});
if ($return_code eq "0")
{
# Started the daemon.
@ -874,11 +953,12 @@ sub configure_pgsql
return("!!error!!");
}
}
}
elsif (($update_postgresql_file) or ($update_pg_hba_file))
{
# Reload
my $return_code = $anvil->System->start_daemon({daemon => $anvil->data->{sys}{daemon}{postgresql}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { return_code => $return_code }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { return_code => $return_code }});
if ($return_code eq "0")
{
# Reloaded the daemon.
@ -891,6 +971,9 @@ sub configure_pgsql
}
}
# Do user and DB checks only if we're made a change above.
if (($initialized) or ($update_postgresql_file) or ($update_pg_hba_file))
{
# Create the .pgpass file, if needed.
my $created_pgpass = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 1, list => {
@ -1037,6 +1120,7 @@ sub configure_pgsql
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "log_0107"});
}
}
}
# Make sure the psql TCP port is open.
$anvil->data->{database}{$uuid}{port} = 5432 if not $anvil->data->{database}{$uuid}{port};
@ -1104,6 +1188,10 @@ If set, the connection will be made only to the database server matching the UUI
If set to C<< 1 >>, no attempt to ping a target before connection will happen, even if C<< database::<uuid>::ping = 1 >> is set.
=head3 retry (optional, default '0')
This method will try to recall itself if this is a Striker and it found no available databases, and so became primary. If this is set, it won't try to become primary a second time.
=head3 sensitive (optional, default '0')
If set to C<< 1 >>, the caller is considered time sensitive and most checks are skipped. This is used when a call must respond as quickly as possible.
@ -1164,8 +1252,9 @@ sub connect
my $check_if_configured = defined $parameter->{check_if_configured} ? $parameter->{check_if_configured} : 0;
my $db_uuid = defined $parameter->{db_uuid} ? $parameter->{db_uuid} : "";
my $no_ping = defined $parameter->{no_ping} ? $parameter->{no_ping} : 0;
my $check_for_resync = defined $parameter->{check_for_resync} ? $parameter->{check_for_resync} : 0;
my $no_ping = defined $parameter->{no_ping} ? $parameter->{no_ping} : 0;
my $retry = defined $parameter->{retry} ? $parameter->{retry} : 0;
my $sensitive = defined $parameter->{sensitive} ? $parameter->{sensitive} : 0;
my $source = defined $parameter->{source} ? $parameter->{source} : "core";
my $sql_file = defined $parameter->{sql_file} ? $parameter->{sql_file} : $anvil->data->{path}{sql}{'anvil.sql'};
@ -1174,8 +1263,9 @@ sub connect
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
check_if_configured => $check_if_configured,
db_uuid => $db_uuid,
no_ping => $no_ping,
check_for_resync => $check_for_resync,
no_ping => $no_ping,
retry => $retry,
sensitive => $sensitive,
source => $source,
sql_file => $sql_file,
@ -1228,6 +1318,23 @@ sub connect
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { check_for_resync => $check_for_resync }});
}
# If we're a Striker, see if we're configured.
my $local_host_type = $anvil->Get->host_type();
my $local_host_uuid = $anvil->Get->host_uuid();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
local_host_type => $local_host_type,
local_host_uuid => $local_host_uuid,
check_if_configured => $check_if_configured,
real_uid => $<,
effective_uid => $>,
}});
# If requested, and if running with root access, set it up (or update it) if needed.
# 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});
}
# Now setup or however-many connections
my $seen_connections = [];
my $failed_connections = [];
@ -1369,8 +1476,9 @@ sub connect
}});
if (not $test)
{
# Something went wrong...
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "log_0064", variables => {
# Either the Striker hosting this is down, or it's not primary and stopped its
# database.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, priority => "alert", key => "log_0064", variables => {
uuid => $uuid,
host => $host,
name => $name,
@ -1422,7 +1530,7 @@ sub connect
port => $port,
};
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => $message_key, variables => $variables });
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, priority => "alert", key => $message_key, variables => $variables });
next;
}
@ -1549,24 +1657,12 @@ sub connect
}
# Before we try to connect, see if this is a local database and, if so, make sure it's setup.
my $is_local = $anvil->Network->is_local({debug => $debug, host => $host});
my $is_local = $anvil->Network->is_local({debug => 2, host => $host});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { is_local => $is_local }});
if ($is_local)
{
$anvil->data->{sys}{database}{read_uuid} = $uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::database::read_uuid" => $anvil->data->{sys}{database}{read_uuid} }});
# If requested, and if running with root access, set it up (or update it) if needed.
# This method just returns if nothing is needed.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
check_if_configured => $check_if_configured,
real_uid => $<,
effective_uid => $>,
}});
if (($check_if_configured) && ($< == 0) && ($> == 0))
{
$anvil->Database->configure_pgsql({debug => $debug, uuid => $uuid});
}
}
elsif (not $anvil->data->{sys}{database}{read_uuid})
{
@ -1602,14 +1698,177 @@ sub connect
target_version => $remote_schema_version,
}});
# Delete the information about this database. We'll try again on nexy
# Delete the information about this database. We'll try again on next
# ->connect().
delete $anvil->data->{database}{$uuid};
$anvil->data->{sys}{database}{connections}--;
next;
}
}
}
# If we're a striker and no connections were found, start our database.
if (($local_host_type eq "striker") && (not $anvil->data->{sys}{database}{connections}))
{
# Tell the user we're going to try to load and start.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "log_0650"});
# Look for pgdumps. "Youngest" is the one with the highest mtime.
my $use_dump = "";
my $backup_age = 0;
my $youngest_dump = 0;
my $directory = $anvil->data->{path}{directories}{pgsql};
my $db_name = $anvil->data->{sys}{database}{name};
my $dump_files = [];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { directory => $directory }});
local(*DIRECTORY);
opendir(DIRECTORY, $directory);
while(my $file = readdir(DIRECTORY))
{
next if $file eq ".";
next if $file eq "..";
my $db_dump_uuid = "";
my $full_path = $directory."/".$file;
$full_path =~ s/\/\//\//g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
file => $file,
full_path => $full_path,
}});
if ($file =~ /\Q$db_name\E_db_dump\.(.*).sql/)
{
$db_dump_uuid = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { directory => $directory }});
# Is this one of our own dumps?
if ($db_dump_uuid eq $local_host_uuid)
{
# How recent is it?
$anvil->Storage->get_file_stats({debug => $debug, file_path => $full_path});
my $mtime = $anvil->data->{file_stat}{$full_path}{modified_time};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mtime => $mtime }});
if ($mtime > $backup_age)
{
$backup_age = $mtime;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { backup_age => $backup_age }});
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0653", variables => { full_path => $full_path }});
next;
}
# Record this dump file for later purging.
push @{$dump_files}, $full_path;
# Is this a database we're configured to use?
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0651", variables => { full_path => $full_path }});
if ((not exists $anvil->data->{database}{$db_dump_uuid}) or (not $anvil->data->{database}{$db_dump_uuid}{host}))
{
# Not a database we're peered with anymore, ignore it.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0652", variables => {
full_path => $full_path,
host_uuid => $db_dump_uuid,
}});
next;
}
# Still here? This is a candidate for loading. What's the mtime on this file?
$anvil->Storage->get_file_stats({debug => $debug, file_path => $full_path});
my $mtime = $anvil->data->{file_stat}{$full_path}{modified_time};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { directory => $directory }});
if ($mtime > $youngest_dump)
{
# This is the youngest, so far.
$youngest_dump = $mtime;
$use_dump = $full_path;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
youngest_dump => $youngest_dump,
full_path => $full_path,
}});
}
}
else
{
# Not a dump file, ignore it.
next;
}
}
closedir(DIRECTORY);
# Did I find a dump to load that's newer than my most recent backup?
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { use_dump => $use_dump }});
if ($use_dump)
{
# Is one of our dumps newer? If so, don't load.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
youngest_dump => $youngest_dump,
backup_age => $backup_age,
}});
if ($backup_age > $youngest_dump)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0661"});
}
else
{
# Yup! This will start the database, if needed.
my $file_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{file_stat}{$use_dump}{size}});
my $file_size_bytes = $anvil->Convert->add_commas({number => $anvil->data->{file_stat}{$use_dump}{size}});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0656", variables => {
file => $use_dump,
size => $file_size,
size_bytes => $file_size_bytes,
}});
my $problem = $anvil->Database->load_database({
debug => 2,
backup => 0,
load_file => $use_dump,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
if ($problem)
{
# Failed, delete the file we tried to load.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "err", key => "error_0355", variables => { file => $use_dump }});
unlink $use_dump;
}
else
{
# Success! Delete all backups we found from other hosts so we don't
# reload them in the future.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0657"});
foreach my $full_path (@{$dump_files})
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0589", variables => { file => $full_path }});
unlink $full_path;
}
}
}
}
# Check if the dameon is running
my $running = $anvil->System->check_daemon({daemon => $anvil->data->{sys}{daemon}{postgresql}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { running => $running }});
if (not $running)
{
my $return_code = $anvil->System->start_daemon({daemon => $anvil->data->{sys}{daemon}{postgresql}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { return_code => $return_code }});
if ($return_code eq "0")
{
# Started the daemon.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0059"});
}
}
# Reconnect
if (not $retry)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0662"});
$anvil->Database->connect({debug => $debug, retry => 1});
}
}
my $total = tv_interval ($start_time, [gettimeofday]);
#print "Total runtime: [".$total."]\n";
@ -1635,17 +1894,11 @@ sub connect
"database::${uuid}::password" => $anvil->Log->is_secure($anvil->data->{database}{$uuid}{password}),
}});
# Copy my alert hash before I delete the uuid.
# my $error_array = [];
# Delete this DB so that we don't try to use it later. This is a quiet alert because the
# original connection error was likely logged.
my $say_server = $anvil->data->{database}{$uuid}{host}.":".$anvil->data->{database}{$uuid}{port}." -> ".$database_name;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, priority => "alert", key => "log_0092", variables => { server => $say_server, uuid => $uuid }});
# Delete it from the list of known databases for this run.
delete $anvil->data->{database}{$uuid};
# If I've not sent an alert about this DB loss before, send one now.
# my $set = $anvil->Alert->check_alert_sent({
# debug => $debug,
@ -4564,7 +4817,7 @@ SELECT
FROM
scan_lvm_vgs
WHERE
scan_lvm_vg_internal_uuid = ".$anvil->Database->quote($storage_group_member_vg_uuid).";
scan_lvm_vg_internal_uuid = ".$anvil->Database->quote($storage_group_member_vg_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
@ -4585,6 +4838,221 @@ WHERE
}});
}
}
# Also load the Storage group extended data.
$anvil->Storage->get_storage_group_details({
debug => $debug,
storage_group_uuid => $storage_group_uuid,
});
}
# If the Anvil! members have changed, we'll need to update the storage groups. This checks for that.
$anvil->Database->get_anvils({debug => $debug});
foreach my $anvil_uuid (keys %{$anvil->data->{storage_groups}{anvil_uuid}})
{
my $anvil_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name};
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 $dr1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
anvil_name => $anvil_name,
node1_host_uuid => $node1_host_uuid,
node2_host_uuid => $node2_host_uuid,
dr1_host_uuid => $dr1_host_uuid,
}});
foreach my $storage_group_uuid (keys %{$anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}})
{
my $group_name = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{group_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
storage_group_uuid => $storage_group_uuid,
group_name => $group_name,
}});
my $size_to_match = 0;
my $node1_seen = 0;
my $node2_seen = 0;
my $dr1_seen = $dr1_host_uuid ? 0 : 1; # Only set to '0' if DR exists.
foreach my $this_host_uuid (keys %{$anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}})
{
my $storage_group_member_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$this_host_uuid}{storage_group_member_uuid};
my $internal_vg_uuid = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$this_host_uuid}{vg_internal_uuid};
my $vg_size = $anvil->data->{storage_groups}{anvil_uuid}{$anvil_uuid}{storage_group_uuid}{$storage_group_uuid}{host_uuid}{$this_host_uuid}{vg_size};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
this_host_uuid => $this_host_uuid,
storage_group_member_uuid => $storage_group_member_uuid,
internal_vg_uuid => $internal_vg_uuid,
vg_size => $anvil->Convert->add_commas({number => $vg_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $vg_size}).")",
}});
if ($vg_size > $size_to_match)
{
$size_to_match = $vg_size;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
size_to_match => $anvil->Convert->add_commas({number => $size_to_match})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $size_to_match}).")",
}});
}
if ($this_host_uuid eq $node1_host_uuid)
{
$node1_seen = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { node1_seen => $node1_seen }});
}
elsif ($this_host_uuid eq $node2_host_uuid)
{
$node2_seen = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { node2_seen => $node2_seen }});
}
elsif (($dr1_host_uuid) && ($this_host_uuid eq $dr1_host_uuid))
{
$dr1_seen = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { dr1_seen => $dr1_seen }});
}
else
{
# This host doesn't belong in this group anymore. Delete it.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "warning_0130", variables => {
storage_group_name => $group_name,
host_name => $anvil->Get->host_name_from_uuid({host_uuid => $this_host_uuid}),
anvil_name => $anvil_name,
}});
my $query = "DELETE FROM storage_group_members WHERE storage_group_member_uuid = ".$anvil->Database->quote($storage_group_member_uuid).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { query => $query }});
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
}
}
if ((not $node1_seen) or
(not $node2_seen) or
(not $dr1_seen))
{
my $hosts = [$node1_host_uuid, $node2_host_uuid];
if ($dr1_host_uuid)
{
push @{$hosts}, $dr1_host_uuid;
}
my $reload = 0;
foreach my $this_host_uuid (@{$hosts})
{
# If we didn't see a host, look for a compatible VG to add.
my $minimum_size = $size_to_match - (2**30);
my $maximum_size = $size_to_match + (2**30);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
minimum_size => $anvil->Convert->add_commas({number => $minimum_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $minimum_size}).")",
maximum_size => $anvil->Convert->add_commas({number => $maximum_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $maximum_size}).")",
}});
my $smallest_difference = (2**30);
my $closest_internal_uuid = "";
my $closest_scan_lvm_vg_uuid = "";
my $quoted_minimum_size = $anvil->Database->quote($minimum_size);
$quoted_minimum_size =~ s/^'(.*)'$/$1/;
my $quoted_maximum_size = $anvil->Database->quote($maximum_size);
$quoted_maximum_size =~ s/^'(.*)'$/$1/;
my $query = "
SELECT
scan_lvm_vg_uuid,
scan_lvm_vg_internal_uuid,
scan_lvm_vg_size
FROM
scan_lvm_vgs
WHERE
scan_lvm_vg_size > ".$quoted_minimum_size."
AND
scan_lvm_vg_size < ".$quoted_maximum_size."
AND
scan_lvm_vg_host_uuid = ".$anvil->Database->quote($this_host_uuid)."
ORDER BY
scan_lvm_vg_size ASC
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $scan_lvm_vg_uuid = $row->[0];
my $scan_lvm_vg_internal_uuid = $row->[1];
my $scan_lvm_vg_size = $row->[2];
my $difference = abs($scan_lvm_vg_size - $size_to_match);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
scan_lvm_vg_uuid => $scan_lvm_vg_uuid,
scan_lvm_vg_internal_uuid => $scan_lvm_vg_internal_uuid,
scan_lvm_vg_size => $anvil->Convert->add_commas({number => $scan_lvm_vg_size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_vg_size}).")",
difference => $anvil->Convert->add_commas({number => $difference})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $difference}).")",
}});
# Is this Internal UUID already in a storage group?
my $query = "SELECT COUNT(*) FROM storage_group_members WHERE storage_group_member_vg_uuid = ".$anvil->Database->quote($scan_lvm_vg_internal_uuid).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, 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 => $debug, list => { count => $count }});
if (not $count)
{
# This VG isn't in a storage group. Is this the closest in size yet?
if ($difference < $smallest_difference)
{
# Closest yet!
$smallest_difference = $difference;
$closest_scan_lvm_vg_uuid = $scan_lvm_vg_internal_uuid;
$closest_internal_uuid = $scan_lvm_vg_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
smallest_difference => $anvil->Convert->add_commas({number => $smallest_difference})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $smallest_difference}).")",
closest_internal_uuid => $closest_internal_uuid,
closest_scan_lvm_vg_uuid => $closest_scan_lvm_vg_uuid,
}});
}
}
}
# Did we find a matching VG?
if ($closest_scan_lvm_vg_uuid)
{
# Yup, add it!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "log_0649", variables => {
anvil_name => $anvil_name,
storage_group => $group_name,
host_name => $anvil->Get->host_name_from_uuid({host_uuid => $this_host_uuid}),
vg_internal_uuid => $closest_scan_lvm_vg_uuid,
}});
my $storage_group_member_uuid = $anvil->Get->uuid();
my $query = "
INSERT INTO
storage_group_members
(
storage_group_member_uuid,
storage_group_member_storage_group_uuid,
storage_group_member_host_uuid,
storage_group_member_vg_uuid,
modified_date
) VALUES (
".$anvil->Database->quote($storage_group_member_uuid).",
".$anvil->Database->quote($storage_group_uuid).",
".$anvil->Database->quote($this_host_uuid).",
".$anvil->Database->quote($closest_scan_lvm_vg_uuid).",
".$anvil->Database->quote($anvil->Database->refresh_timestamp)."
);";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { query => $query }});
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
# Reload
$reload = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { reload => $reload }});
}
}
if ($reload)
{
$anvil->Database->get_storage_group_data({debug => $debug});
}
}
}
}
return(0);
@ -13546,6 +14014,242 @@ WHERE
}
=head2 load_database
This takes a path to an uncompressed SQL database dump file, and loads it into the C<< anvil >> database. During the duration of this operation, remote access to the database will be disabled via C<< iptables >> drop on port 5432!
If necessary, the database server will be started.
If the dump is successfully loaded, C<< 0 >> is returned. If there is a problem, C<< !!error!! >> is returned.
B<< Note >>: This method must be called by the root user.
B<< Note >>: This always and only works on the local database server's C<< anvil >> database.
Parameters;
=head3 backup (optional, default '1')
This controls whether the data in the existing database is saved to a file prior to the passed-in database file being loaded.
=head3 load_file (required)
This is the full path to the SQL file to load into the database.
=cut
sub load_database
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->load_database()" }});
my $backup = defined $parameter->{backup} ? $parameter->{backup} : 1;
my $load_file = defined $parameter->{load_file} ? $parameter->{load_file} : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
backup => $backup,
load_file => $load_file,
}});
# Only the root user can do this
if (($< != 0) && ($> != 0))
{
# Not root
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0350"});
return('!!error!!');
}
# Does the file exist?
if (not $load_file)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->load_database()", parameter => "load_file" }});
}
elsif (not -e $load_file)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0103", variables => { file => $load_file }});
return('!!error!!');
}
my $start_time = time;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { start_time => $start_time }});
### TODO: Replace this with System->manage_firewall().
# Throw up the firewall. Have the open call ready in case we hit an error.
my $block_call = $anvil->data->{path}{exe}{iptables}." -I INPUT -p tcp --dport 5432 -j REJECT";
my $open_call = $anvil->data->{path}{exe}{iptables}." -D INPUT -p tcp --dport 5432 -j REJECT";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { block_call => $block_call }});
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $block_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
# Start the database, if needed.
my $running = $anvil->System->check_daemon({debug => $debug, daemon => $anvil->data->{sys}{daemon}{postgresql}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { running => $running }});
if (not $running)
{
# Start it up.
my $return_code = $anvil->System->start_daemon({daemon => $anvil->data->{sys}{daemon}{postgresql}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { return_code => $return_code }});
if ($return_code eq "0")
{
# Started the daemon.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0059"});
}
else
{
# Failed to start
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0094"});
# Drop the firewall block
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { open_call => $open_call }});
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $open_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
return("!!error!!");
}
}
# Backup, if needed.
if ($backup)
{
# Backup the database.
my $dump_file = $anvil->Database->backup_database({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { dump_file => $dump_file }});
if ($dump_file eq "!!error!!")
{
# Drop the firewall block
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { open_call => $open_call }});
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $open_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
return("!!error!!");
}
}
# Drop the existing database.
my $drop_call = $anvil->data->{path}{exe}{su}." - postgres -c \"".$anvil->data->{path}{exe}{dropdb}." ".$anvil->data->{sys}{database}{name}."\"";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { drop_call => $drop_call }});
$output = "";
$return_code = "";
($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $drop_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
if ($return_code)
{
# This is a failure, but it could be that the database simply didn't exist (was already
# dumped). If that's the case, we'll keep going.
my $proceed = 0;
if ($output =~ /database ".*?" does not exist/gs)
{
# proceed.
$proceed = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { proceed => $proceed }});
}
if (not $proceed)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0353", variables => {
shell_call => $drop_call,
return_code => $return_code,
output => $output,
}});
# Drop the firewall block
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { open_call => $open_call }});
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $open_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
return('!!error!!');
}
}
# Recreate the DB.
my $create_call = $anvil->data->{path}{exe}{su}." - postgres -c \"".$anvil->data->{path}{exe}{createdb}." --owner ".$anvil->data->{sys}{database}{user}." ".$anvil->data->{sys}{database}{name}."\"";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { create_call => $create_call }});
$output = "";
$return_code = "";
($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $create_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
if ($return_code)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0354", variables => {
shell_call => $create_call,
return_code => $return_code,
output => $output,
}});
# Drop the firewall block
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { open_call => $open_call }});
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $open_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
return('!!error!!');
}
# Finally, load the database.
my $load_call = $anvil->data->{path}{exe}{su}." - postgres -c \"".$anvil->data->{path}{exe}{psql}." ".$anvil->data->{sys}{database}{name}." < ".$load_file."\"";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { load_call => $load_call }});
$output = "";
$return_code = "";
($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $load_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
if ($return_code)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0355", variables => {
shell_call => $load_call,
return_code => $return_code,
output => $output,
}});
# Drop the firewall block
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { open_call => $open_call }});
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $open_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
return('!!error!!');
}
# Open the firewall back up
$output = "";
$return_code = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { open_call => $open_call }});
($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $open_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
# Done!
my $took_time = time - $start_time;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0655", variables => {
file => $load_file,
took => $took_time,
}});
return(0);
}
=head2 lock_file
This reads, sets or updates the database lock file timestamp.

@ -20,6 +20,7 @@ my $THIS_FILE = "Storage.pm";
# change_mode
# change_owner
# check_md5sums
# compress
# copy_file
# delete_file
# find
@ -27,6 +28,7 @@ my $THIS_FILE = "Storage.pm";
# get_size_of_block_device
# get_storage_group_details
# get_storage_group_from_path
# get_vg_name
# make_directory
# manage_lvm_conf
# move_file
@ -1793,7 +1795,7 @@ LIMIT 1
foreach my $this_host_name (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$this_resource}{host}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_host_name => $this_host_name }});
foreach my $this_volume (sort {$a cmp $b} keys %{$$anvil->data->{new}{resource}{$this_resource}{host}{$this_host_name}{volume}})
foreach my $this_volume (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$this_resource}{host}{$this_host_name}{volume}})
{
my $this_minor = $anvil->data->{new}{resource}{$this_resource}{host}{$this_host_name}{volume}{$this_volume}{device_minor};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
@ -1938,6 +1940,8 @@ This takes a C<< storage_group_uuid >> and loads information about members into
On success, C<< 0 >> is returned. On failure, C<< !!error!! >> is returned.
B<< Note >>: This method is called by C<< Database->get_storage_group_data() >> so generally calling it direcly isn't needed.
Parameters;
=head3 storage_group_uuid (required)
@ -2150,7 +2154,7 @@ sub get_storage_group_from_path
foreach my $this_host_name (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$this_resource}{host}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_host_name => $this_host_name }});
foreach my $this_volume (sort {$a cmp $b} keys %{$$anvil->data->{new}{resource}{$this_resource}{host}{$this_host_name}{volume}})
foreach my $this_volume (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$this_resource}{host}{$this_host_name}{volume}})
{
my $this_minor = $anvil->data->{new}{resource}{$this_resource}{host}{$this_host_name}{volume}{$this_volume}{device_minor};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
@ -2382,6 +2386,86 @@ LIMIT 1
}
=head2 get_vg_name
This method takes a Storage Group UUID and a host UUID, and returns the volume group name associated with those. If there is a problem, C<< !!error!! >> is returned.
my $vg_name = $anvil->Storage->get_vg_name({
host_uuid => $dr_host_uuid,
storage_group_uuid => $storage_group_uuid,
});
Parameters;
=head3 host_uuid (optional, default Get->host_uuid)
This is the host's UUID that holds the VG name being searched for.
=head3 storage_group_uuid (required)
This is the Storage Group UUID being searched for.
=cut
sub get_vg_name
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
my $test = defined $parameter->{test} ? $parameter->{test} : 0;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Storage->get_vg_name()" }});
my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : "";
my $storage_group_uuid = defined $parameter->{storage_group_uuid} ? $parameter->{storage_group_uuid} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
host_uuid => $host_uuid,
storage_group_uuid => $storage_group_uuid,
}});
if (not $host_uuid)
{
$host_uuid = $anvil->Get->host_uuid();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
}
if (not $storage_group_uuid)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Storage->get_vg_name()", parameter => "storage_group_uuid" }});
return('!!error!!');
}
my $query = "
SELECT
b.scan_lvm_vg_name
FROM
storage_group_members a,
scan_lvm_vgs b
WHERE
a.storage_group_member_vg_uuid = b.scan_lvm_vg_internal_uuid
AND
a.storage_group_member_storage_group_uuid = ".$anvil->Database->quote($storage_group_uuid)."
AND
a.storage_group_member_host_uuid = ".$anvil->Database->quote($host_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
if (not $count)
{
# Not found
return("");
}
my $scan_lvm_vg_name = $results->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { scan_lvm_vg_name => $scan_lvm_vg_name }});
return($scan_lvm_vg_name);
}
=head2 make_directory
This creates a directory (and any parent directories).
@ -4872,9 +4956,9 @@ fi";
my $shell_call = "
if [ -d '".$directory."' ];
then
".$anvil->data->{path}{exe}{echo}." 'exists';
echo 'exists';
else
".$anvil->data->{path}{exe}{echo}." 'not found';
echo 'not found';
fi";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0166", variables => { shell_call => $shell_call, target => $target, remote_user => $remote_user }});
(my $output, $error, my $return_code) = $anvil->Remote->call({

@ -1568,6 +1568,11 @@ sub collect_ipmi_data
$current_value = $1;
$units = "degrees C";
}
if ($current_value =~ /^(.*?)\s+Volts/)
{
$current_value = $1;
$units = "V";
}
my $new_sensor_name = $sensor_name." (".$hex_address.")";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
new_sensor_name => $new_sensor_name,
@ -4439,7 +4444,7 @@ sub start_daemon
This method stops a daemon. The return code from the stop request will be returned.
If the return code for the stop command wasn't read, C<< !!error!! >> is returned.
If the return code for the stop command is returned.
Parameters;

@ -116,7 +116,7 @@ sys::database::log_transactions = 0
# lot of log traffic. If you want to silence these log alerts, you can set the value below to be higher than
# your current active log level (default is '1', so set to '2' or '3' to silence).
# NOTE: It's important to only use this temporarily.
sys::database::failed_connection_log_level = 1
#sys::database::failed_connection_log_level = 2
# This controls what log facility to use by default.
# NOTE: This will always be 'authpriv' when a log entry is marked as secure.
@ -204,3 +204,8 @@ sys::manage::firewall = 1
# Logging can be set on a per-agent basis with:
#scancore::scan-network::log_level = 2
#scancore::scan-network::log_secure = 1
# By default, the Anvil! will manage the /etc/hosts file. If this is causing you issue, you can disable this
# behavious by setting this to '0'. Be aware of course that you will need to manually update or add entries
# going forward.
#sys::hosts::manage = 0

44
notes

@ -8,51 +8,14 @@ TODO:
============
# Dump
su - postgres -c "pg_dump anvil > /tmp/anvil.out" && mv /tmp/anvil.out /root/
su - postgres -c "pg_dump --schema-only anvil > /tmp/anvil.out" && mv /tmp/anvil.out /root/
su - postgres -c "pg_dump anvil > /var/lib/pgsql/anvil.out"
su - postgres -c "pg_dump --schema-only anvil > /var/lib/pgsql/anvil_schema.out"
cp /root/anvil.out /; su - postgres -c "dropdb anvil" && su - postgres -c "createdb --owner admin anvil" && su - postgres -c "psql anvil < /anvil.out"
su - postgres -c "dropdb anvil" && su - postgres -c "createdb --owner admin anvil" && su - postgres -c "psql anvil < /var/lib/pgsql/anvil.out"
su postgres -c "psql anvil"
============
# ScanCore post-scan logic;
Sole node:
1. Evaluate critical shutdown only, if hosting VMs.
2. If not hosting VMs, load-shed if over-heat / power loss for more than 120 seconds
Action options;
1. Do nothing
2. Pull servers
3. Shut down (once servers are gone)
4. Shut down (gracefully stop servers)
* Peer not available
- Thermal is critical, gracefully shut down.
- Power is strongest UPS below ten minutes and time on batteries is over 2 minutes, graceful shut down
* Peer available
- If one node is healthier than the other;
- If we're sicker, do nothing until we have no servers
- If we're healthier, after two minutes, pull
- If health is equal;
- Both nodes have servers;
- Decide who can be evacuated fastest, in case load shed needed.
- Both nodes on batteries or in warning temp for more than 2 minutes;
- If we're the designated survivor, pull servers.
- If we're the sacrifice, wait for the servers to be taken off of us, then shut down.
- Peer has servers, we don't
- If thermal warning or both/all UPSes on batter for two minutes+, shut down
- We have servers, peer doesn't.
- Keep running
1.1 - Our peer may pull from us.
2. - Not Hosting Servers
2.1 -
Jenkins;
@ -696,7 +659,6 @@ drbdadm connect <res>
==================
# Server srv01-sql, example showing two disks in one VM.
resource srv01-sql {
on mk-a02n01 {
node-id 0;
volume 0 {

@ -79,7 +79,7 @@ if ($anvil->data->{switches}{purge})
$anvil->nice_exit({exit_code => 0});
}
if ($anvil->DRBD->gather_data())
if ($anvil->DRBD->gather_data({debug => 2}))
{
# DRBD not found or configured.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "scan_drbd_error_0001"});

@ -454,6 +454,53 @@ Failed to parse the XML in the new definition file. The error was:
Giving up.
</key>
<key name="error_0332">This must be run on a node active in the cluster hosting the server being managed. Exiting.</key>
<key name="error_0333">This Anvil! does not seem to have a DR host. Exiting.</key>
<key name="error_0334">Failed to find an IP we can access the DR host: [#!variable!host_name!#]. Has it been configured? Is it running? Exiting.</key>
<key name="error_0335">Failed to access the DR host: [#!variable!host_name!#] using the IP: [#!variable!ip_address!#]. Is it running? Exiting.</key>
<key name="error_0336">Failed to parse the CIB. Is this node in the cluster? Exiting.</key>
<key name="error_0337">We're not a full member of the cluster yet. Please try again once we're fully in. Exiting.</key>
<key name="error_0338">We can't setup a server to be protected unless both nodes are up, and the peer isn't at this time. Exiting.</key>
<key name="error_0339">We can't remove a server from DR unless both nodes are up, and the peer isn't at this time. Exiting.</key>
<key name="error_0340"><![CDATA[Please specify the server to manager using '--server <name or uuid>'. Exiting.]]></key>
<key name="error_0341">Failed to find the server: [#!variable!server!#] by name or UUID? Exiting.</key>
<key name="error_0342">The protocol: [#!variable!protocol!#] is invalid. Please use '--help' for more information.</key>
<key name="error_0343">The DR host: [#!variable!host_name!#] doesn't appear to be storage group: [#!variable!storage_group!#]. Unable to proceed.</key>
<key name="error_0344">We need: [#!variable!space_needed!# (#!variables!space_needed_bytes!# Bytes)] from the storage group: [#!variable!storage_group!#], but only: [#!variables!space_on_dr!# (#!variable!space_on_dr_bytes!# bytes)] is available on DR. Unable to proceed.</key>
<key name="error_0345">[ Error ] - The check appears to have failed. Expected a return code of '0', but got: [#!variable!return_code!#]
The output, if any, was
====
#!variable!output!#
====
</key>
<key name="error_0346">- Restoring the old config now.</key>
<key name="error_0347">- The problematic new config has been saved as: [#!variable!file!#].</key>
<key name="error_0348">- The old config has been restored. Exiting.</key>
<key name="error_0349">- The logical volume: [#!variable!lv_path!#] creation failed. Unable to proceed.</key>
<key name="error_0350">Only the root user can load a database file and start the database.</key>
<key name="error_0351">[ Error ] - The 'pg_dump' call to backup the database failed. Expected a return code of '0', but got: [#!variable!return_code!#].
Full command called: [#!variable!shell_call!#]
The output, if any, was
====
#!variable!output!#
====
</key>
<key name="error_0352">Only the root user can backup a database.</key>
<key name="error_0353">[ Error ] - The 'dropdb' call to drop the database failed. Expected a return code of '0', but got: [#!variable!return_code!#].
Full command called: [#!variable!shell_call!#]
The output, if any, was
====
#!variable!output!#
====
</key>
<key name="error_0354">[ Error ] - The 'createdb' call to create the database failed. Expected a return code of '0', but got: [#!variable!return_code!#].
Full command called: [#!variable!shell_call!#]
The output, if any, was;
====
#!variable!output!#
====
</key>
<key name="error_0355">Failed to load the database file: [#!variable!file!#]. Deleting it so it's not considered in the next load attempt.</key>
<!-- Files templates -->
<!-- NOTE: Translating these files requires an understanding of which lines are translatable -->
@ -693,6 +740,41 @@ sys::manage::firewall = 1
# This is the "short list" of servers shown when provisioning a new server. To see the full list of options,
# run '/usr/bin/osinfo-query os' on any machine in the Anvil!.
#sys::servers::os_short_list = debian10,fedora32,freebsd12.1,gentoo,macosx10.7,msdos6.22,openbsd6.7,opensuse15.2,rhel5.11,rhel6.10,rhel7.9,rhel8.3,sles12sp5,solaris11,ubuntu20.04,win10,win2k16,win2k19
]]></key>
<key name="file_0003"><![CDATA[
on #!variable!short_host_name!# {
node-id #!variable!node_id!#;
#!variable!volumes!#
}
]]></key>
<key name="file_0004"><![CDATA[
volume #!variable!volume!# {
device #!variable!drbd_path!# minor #!variable!minor!#;
disk #!variable!lv_path!#;
meta-disk internal;
}
]]></key>
<key name="file_0005"><![CDATA[
connection {
host #!variable!host1_short_name!# address #!variable!host1_sn_ip!#:#!variable!tcp_port!#;
host #!variable!host2_short_name!# address #!variable!host2_sn_ip!#:#!variable!tcp_port!#;
disk {
# The variable bit rate caps at 100 MiB/sec, setting this changes the maximum
# variable rate.
c-max-rate #!variable!c-rate-maximum!#M;
}
net {
protocol #!variable!protocol!#;
fencing #!variable!fencing!#;
}
}
]]></key>
<key name="file_0006"><![CDATA[# Resource for #!variable!server!#
resource #!variable!server!# {
#!variable!hosts!#
#!variable!connections!#
}
]]></key>
<!-- Table headers -->
@ -1143,13 +1225,48 @@ It should be provisioned in the next minute or two.</key>
<key name="job_0349">Loading the new corosync config exited with return code: [#!variable!return_code!#] and output: [#!variable!output!#]</key>
<key name="job_0350">Manage VNC Pipes</key>
<key name="job_0351">Perform VNC pipe operation [#!variable!operation!#] for server UUID [#!variable!server_uuid!#] from host UUID [#!variable!host_uuid!#].</key>
<key name="job_0352">Manage a server menu:</key>
<key name="job_0353">* Please enter the name of the server you want to manage</key>
<key name="job_0354">-=] Servers available to manage on the Anvil! [#!variable!anvil_name!#] [=-</key>
<key name="job_0355">-=] Managing the server: [#!variable!server_name!#] on the Anvil!: [#!variable!anvil_name!#]</key>
<key name="job_0356">Get Server VM Screenshot</key>
<key name="job_0357">Fetch a screenshot of the specified server VM and represent it as a Base64 string.</key>
<key name="job_0358">Running sanity checks.</key>
<key name="job_0359">Sanity checks complete!</key>
<key name="job_0360">Beginning to protect the server: [#!variable!server!#]!</key>
<key name="job_0361">Verified that there is enough space on DR to proceed.
* The connection protocol will be: ..... [#!variable!protocol!#]
* Node 1 to DR will use TCP port: ...... [#!variable!node1_to_dr_port!#]
* Node 2 to DR will use TCP port: ...... [#!variable!node2_to_dr_port!#]
* We will update the DRBD resource file: [#!variable!config_file!#]
The following LV(s) will be created:
</key>
<key name="job_0362">- Resource: [#!variable!resource!#], Volume: [#!variable!volume!#]</key>
<key name="job_0363"> - The LV: [#!variable!lv_path!#] with the size: [#!variable!lv_size!# (#!variable!lv_size_bytes!# Bytes)] will be created.</key>
<key name="job_0364">The resource file: [#!variable!file!#] doesn't need to be updated.</key>
<key name="job_0365">- Backed up old config as: [#!variable!backup_file!#]. Updating it now.</key>
<key name="job_0366">- Updated! Verifying...</key>
<key name="job_0367">- The new config looks good!</key>
<key name="job_0368">- Updating the peers now...</key>
<key name="job_0369">- Updating the resource file: [#!variable!file!#] on the host: [#!variable!host_name!#] via IP: [#!variable!ip_address!#].</key>
<key name="job_0370">- Creating logical volumes on DR, if needed. New LVs will have metadata created.</key>
<key name="job_0371">- Volume: [#!variable!volume!#], logical volume: [#!variable!lv_path!#].</key>
<key name="job_0372">- The logical volume: [#!variable!lv_path!#] already exists, skipping it, and NOT create DRBD meta data.</key>
<key name="job_0373">- Reloading the local DRBD resource config.</key>
<key name="job_0374">- Reloading the resource: [#!variable!server!#] on the host: [#!variable!host_name!#].</key>
<key name="job_0375">- Checking, and starting where needed, the: [#!variable!server!#] resource locally and on peers.
- Checking locally.</key>
<key name="job_0376"> - Checking the host: [#!variable!host_name!#]</key>
<key name="job_0377">- Checking to see if the DR host has connected to this resource yet.</key>
<key name="job_0378">- Not up yet, will check again at: [#!variable!next_check!#].</key>
<key name="job_0379">- Up!</key>
<key name="job_0380">Done! The server: [#!variable!server!#] is now being protected on DR!
It will take time for it to initialize, please be patient.</key>
<key name="job_0381">- Running the scan agent 'scan-drbd' locally to record the newly used TCP ports.</key>
<key name="job_0382">- Running the scan agent 'scan-drbd' on: [#!variable!host_name!#] to record the newly used TCP ports.</key>
<key name="job_0383">The job has been recorded with the UUID: [#!variable!job_uuid!#], it will start in just a moment if anvil-daemon is running.</key>
<key name="job_0384">Manage DR tasks for a given server</key>
<key name="job_0385">This job can protect, remove (unprotect), connect, disconnect or update (connect, sync, disconnect) a given server.</key>
<!-- Log entries -->
<key name="log_0001">Starting: [#!variable!program!#].</key>
@ -1229,7 +1346,7 @@ Connecting to Database with configuration ID: [#!variable!uuid!#]
<key name="log_0061"><![CDATA[[ Error ] - The method Get->users_home() was asked to find the home directory for the user: [#!variable!user!#], but was unable to do so.]]></key>
<key name="log_0062">SSH session opened without a password to: [#!variable!target!#].</key>
<key name="log_0063"><![CDATA[The database: [#!variable!host!# -> #!variable!name!#] with the UUID: [#!variable!uuid!#] did not respond to pings and 'database::#!variable!uuid!#::ping' is not set to '0' in '#!data!path::configs::anvil.conf!#', skipping it.]]></key>
<key name="log_0064">[ Warning ] - The database: [#!variable!name!#] on host: [#!variable!host!#] with UUID: [#!variable!uuid!#] can not be used, skipping it.</key>
<key name="log_0064">[ Note ] - The database: [#!variable!name!#] on host: [#!variable!host!#] with UUID: [#!variable!uuid!#] is not available, skipping it.</key>
<key name="log_0065">
The database connection error was:
----------
@ -1900,6 +2017,20 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="log_0646">#!variable!program!# is disabled in anvil.conf. and '--force' was not used. Exiting.</key>
<key name="log_0647">[ Note ] - The network interface: [#!variable!name!#] with 'network_interface_uuid': [#!variable!uuid!#] is a duplicate, removing it from the database(s).</key>
<key name="log_0648">[ Note ] - Managing /etc/hosts has been disabled.</key>
<key name="log_0649">[ Note ] - The Anvil!: [#!variable!anvil_name!#]'s storage group: [#!variable!storage_group!#] didn't have an entry for the host: [#!variable!host_name!#]. The volume group: [#!variable!vg_internal_uuid!#] is a close fit and not in another storage group, so adding it to this storage group now.</key>
<key name="log_0650">[ Note ] - We're a Striker and we did not connect to a peer's database. Will check now if we can load a recent backup, then start postgres locally (with or without a load).</key>
<key name="log_0651">Evaluating the dump file: [#!variable!full_path!#].</key>
<key name="log_0652">The database host UUID: [#!variable!host_uuid!#] is not configured here, ignoring: [#!variable!full_path!#].</key>
<key name="log_0653">We created the database dump file: [#!variable!full_path!#], will compare it's modidified time to other dumps we may find.</key>
<key name="log_0654">The database was dumped to: [#!variable!file!#] in: [#!variable!took!#] second(s). The size of the dump file is: [#!variable!size!#] (#!variable!size_bytes) bytes).</key>
<key name="log_0655">The database was loaded successfull from the file: [#!variable!file!#] in: [#!variable!took!#] second(s)!</key>
<key name="log_0656">No databases were available, so we will become primary after loading: [#!variable!file!#], which is: [#!variable!size!#] (#!variable!size_bytes!# bytes). Please be patient, this could take a moment.</key>
<key name="log_0657">The database was loaded, clear it and other DB dumps out now so that they don't get reloaded again in the future.</key>
<key name="log_0658">Sync'ed the file: [#!variable!file!#] to the peer Striker: [#!variable!host_name!#]. The sync took: [#!variable!took!#] seconds, and the file was: [#!variable!size!#] (#!variable!size_bytes!# bytes).</key>
<key name="log_0659">We're going to shut down our database. Creating a backup first.</key>
<key name="log_0660">Stopped the postgresql daemon as a peer is currently primary.</key>
<key name="log_0661">Our most recent database dump is newer than any from our peers. As such, we'll just start the database without a load.</key>
<key name="log_0662">Retrying to connect to the database.</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>
@ -2261,7 +2392,8 @@ Are you sure that you want to delete the server: [#!variable!server_name!#]? [Ty
<key name="message_0263">Preparing to get server VM screenshot.</key>
<key name="message_0264">Finished getting server VM screenshot.</key>
<key name="message_0265">Failed to get server VM screenshot; got non-zero return code.</key>
<key name="message_0266">Finished attempting to get server VM screenshot; no operations happened because requirements not met.</key>
<key name="message_0266">Finished attempting to get server VM screenshot; no operations happened because requirements not met.</key>>>> master
<key name="message_0267">Preparing to manage DR for a server.</key>
<!-- Success messages shown to the user -->
<key name="ok_0001">Saved the mail server information successfully!</key>
@ -2922,6 +3054,7 @@ The error was:
We will sleep a bit and try again.
</key>
<key name="warning_0130">[ Warning ] - The storage group: [#!variable!storage_group_name!#] had the host: [#!variable!host_name!#] as a member. This host is not a member (anymore?) of the Anvil!: [#!variable!anvil_name!#]. Removing it from the storage group now.</key>
<!-- The entries below here are not sequential, but use a key to find the entry. -->
<!-- Run 'striker-parse-os-list to find new entries. -->

@ -172,18 +172,22 @@ my $delay = set_delay($anvil);
# Once a minute, we'll check the md5sums and see if we should restart.
# Once a day, we'll refresh an Install Target's RPM repository (has no effect on non-Striker dashboards).
$anvil->data->{timing}{minute_checks} = 60;
$anvil->data->{timing}{ten_minute_checks} = 600;
$anvil->data->{timing}{daily_checks} = 86400;
$anvil->data->{timing}{repo_update_interval} = 86400;
$anvil->data->{timing}{next_minute_check} = $now_time - 1;
$anvil->data->{timing}{next_ten_minute_check} = $now_time - 1;
$anvil->data->{timing}{next_daily_check} = ($now_time + $delay) - 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"s1:timing::minute_checks" => $anvil->data->{timing}{minute_checks},
"s2:timing::daily_checks" => $anvil->data->{timing}{daily_checks},
"s3:timing::repo_update_interval" => $anvil->data->{timing}{repo_update_interval},
"s4:now_time" => $now_time,
"s5:delay" => $delay,
"s6:timing::next_minute_check" => $anvil->data->{timing}{next_minute_check},
"s7:timing::next_daily_check" => $anvil->data->{timing}{next_daily_check},
"s2:timing::ten_minute_checks" => $anvil->data->{timing}{ten_minute_checks},
"s3:timing::daily_checks" => $anvil->data->{timing}{daily_checks},
"s4:timing::repo_update_interval" => $anvil->data->{timing}{repo_update_interval},
"s5:now_time" => $now_time,
"s6:delay" => $delay,
"s7:timing::next_minute_check" => $anvil->data->{timing}{next_minute_check},
"s8:timing::next_ten_minute_check" => $anvil->data->{timing}{next_ten_minute_check},
"s9:timing::next_daily_check" => $anvil->data->{timing}{next_daily_check},
}});
# Disconnect. We'll reconnect inside the loop
@ -374,26 +378,26 @@ sub check_network
# 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;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uptime => $uptime }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { uptime => $uptime }});
if ($uptime > 120)
{
# Check that bonds are up. Degraded bonds will be left alone.
if (not $anvil->data->{sys}{network}{initial_checks})
{
my $running = $anvil->System->check_daemon({daemon => "NetworkManager"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { running => $running }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { running => $running }});
if (not $running)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0250", variables => { daemon => "NetworkManager" }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0250", variables => { daemon => "NetworkManager" }});
my $return_code = $anvil->System->start_daemon({daemon => "NetworkManager"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { return_code => $return_code }});
$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 => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
"sys::network::initial_checks" => $anvil->data->{sys}{network}{initial_checks},
}});
}
@ -420,8 +424,9 @@ sub handle_periodic_tasks
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
"s1:now_time" => $now_time,
"s2:timing::next_minute_check" => $anvil->data->{timing}{next_minute_check},
"s3:timing::next_daily_check" => $anvil->data->{timing}{next_daily_check},
"s4:type" => $type,
"s3:timing::next_ten_minute_check" => $anvil->data->{timing}{next_ten_minute_check},
"s4:timing::next_daily_check" => $anvil->data->{timing}{next_daily_check},
"s5:type" => $type,
}});
# Time to run once per minute tasks.
@ -503,6 +508,126 @@ sub handle_periodic_tasks
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { problem => $problem }});
}
# Now check to see if it's time to run less frequent tasks.
if ($now_time >= $anvil->data->{timing}{next_ten_minute_check})
{
my $host_type = $anvil->Get->host_type();
my $host_uuid = $anvil->Get->host_uuid();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host_type => $host_type,
host_uuid => $host_uuid,
}});
# Are we a Striker and is there two or more connections? If so, evaluate if we should shut down our
# database.
if ($host_type eq "striker")
{
if ($anvil->data->{sys}{database}{connections} > 1)
{
# Sort by UUID, skip the first, and see if we're one of the others.
my $first_uuid = "";
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { uuid => $uuid }});
if (not $first_uuid)
{
$first_uuid = $uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { first_uuid => $first_uuid }});
}
elsif ($uuid eq $host_uuid)
{
# This is us, backup and shut down.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0659"});
# Switch the read_uuid and then close
$anvil->data->{sys}{database}{read_uuid} = $first_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "sys::database::read_uuid" => $anvil->data->{sys}{database}{read_uuid} }});
# Disconnect
$anvil->data->{cache}{database_handle}{$uuid}->disconnect;
delete $anvil->data->{cache}{database_handle}{$uuid};
# Create a backup, this is useful also for setting the mtime of the last time
# we were up.
my $dump_file = $anvil->Database->backup_database({debug => 3});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { dump_file => $dump_file }});
# Stop the daemon
my $return_code = $anvil->System->stop_daemon({daemon => $anvil->data->{sys}{daemon}{postgresql}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { return_code => $return_code }});
if ($return_code eq "0")
{
# Stopped the daemon.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0660"});
}
}
}
}
# If we're the active database, dump out database out and rsync it to our peers.
my $peers = keys %{$anvil->data->{database}};
my $connections = $anvil->data->{sys}{database}{connections};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
peers => $peers,
connections => $connections,
}});
if (exists $anvil->data->{cache}{database_handle}{$host_uuid})
{
# Verify that the database is up.
my $running = $anvil->System->check_daemon({daemon => $anvil->data->{sys}{daemon}{postgresql}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { running => $running }});
if ($running)
{
# Backup our DB.
my $dump_file = $anvil->Database->backup_database({debug => 2});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { dump_file => $dump_file }});
# Now rsync it to our peer(s)
foreach my $this_host_uuid (sort {$a cmp $b} keys %{$anvil->data->{database}})
{
next if $this_host_uuid eq $host_uuid;
my $destination = "root\@".$anvil->data->{database}{$this_host_uuid}{host}.":".$anvil->data->{path}{directories}{pgsql}."/";
my $password = $anvil->data->{database}{$this_host_uuid}{password};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
this_host_uuid => $this_host_uuid,
destination => $destination,
password => $anvil->Log->is_secure($password),
}});
my $start_time = time;
my $failed = $anvil->Storage->rsync({
debug => 3,
destination => $destination,
password => $password,
source => $dump_file,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { failed => $failed }});
my $rsync_time = time - $start_time;
my $size = $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{file_stat}{$dump_file}{size}});
my $size_bytes = $anvil->Convert->add_commas({number => $anvil->data->{file_stat}{$dump_file}{size}});
my $target_name = $anvil->Get->host_name_from_uuid({debug => 3, host_uuid => $this_host_uuid});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0658", variables => {
file => $dump_file,
host_name => $target_name,
took => $rsync_time,
size => $size,
size_bytes => $size_bytes,
}});
}
}
}
}
# Update the next check time.
$anvil->data->{timing}{next_ten_minute_check} = $now_time + $anvil->data->{timing}{ten_minute_checks};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"s1:timing::ten_minute_checks" => $anvil->data->{timing}{ten_minute_checks},
"s2:timing::next_ten_minute_check" => $anvil->data->{timing}{next_ten_minute_check},
}});
}
# Now check to see if it's time to run daily tasks.
if ($now_time >= $anvil->data->{timing}{next_daily_check})
{
@ -1030,6 +1155,16 @@ sub prep_database
{
my ($anvil) = @_;
# If there's a backup file, we're configured and possibly just off.
my $dump_file = $anvil->data->{path}{directories}{pgsql}."/".$anvil->data->{sys}{database}{name}."_db_dump.".$anvil->Get->host_uuid().".out";
$dump_file =~ s/\/\//\//g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { dump_file => $dump_file }});
if (-e $dump_file)
{
# No need to prepare.
return(0);
}
# Only run this if we're a dashboard.
my $host_type = $anvil->Get->host_type();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }});
@ -1368,7 +1503,7 @@ sub update_state_file
#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 => 2, list => { shell_call => $shell_call }});
$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 => {

File diff suppressed because it is too large Load Diff

@ -48,7 +48,7 @@ if (not $anvil->data->{sys}{manage}{firewall})
# Do nothing.
$anvil->nice_exit({exit_code => 0});
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 3, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }});
# Read switches
$anvil->data->{switches}{'y'} = "";

@ -27,7 +27,7 @@ my $anvil = Anvil::Tools->new();
$anvil->data->{switches}{refresh} = 0;
$anvil->Get->switches;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
"switches::refresh" => $anvil->data->{switches}{refresh},
}});

@ -76,7 +76,7 @@ $anvil->data->{switches}{'no-refresh'} = 0;
$anvil->data->{switches}{refresh} = 0;
$anvil->data->{switches}{status} = "";
$anvil->Get->switches();
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
'switches::check' => $anvil->data->{switches}{check},
'switches::disable' => $anvil->data->{switches}{disable},
@ -176,7 +176,7 @@ if ($anvil->data->{switches}{disable})
# Exit if we're not configured yet
my $configured = $anvil->System->check_if_configured;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { configured => $configured }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { configured => $configured }});
if (not $configured)
{
print $anvil->Words->string({key => "error_0046"})."\n";
@ -584,7 +584,7 @@ sub setup_boot_environment
}
### PXE UEFI 'grub.cfg' file.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "host_os::os_type" => $anvil->data->{host_os}{os_type} }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "host_os::os_type" => $anvil->data->{host_os}{os_type} }});
my $say_os = "#!string!brand_0010!#";
if ($anvil->data->{host_os}{os_type} eq "centos8")
{
@ -594,7 +594,7 @@ sub setup_boot_environment
{
$say_os = "#!string!brand_0012!#";
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_os => $say_os }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_os => $say_os }});
my $uefi_grub_body = $anvil->Template->get({file => "pxe.txt", show_name => 0, name => "tftp_grub", variables => {
base_url => $base_url,
@ -2735,7 +2735,7 @@ sub load_packages
my ($os_type, $os_arch) = $anvil->Get->os_type();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
os_type => $os_type,
os_arch => $os_arch,
}});
@ -2772,7 +2772,7 @@ sub load_packages
my $rhel8_test_source = $anvil->data->{path}{directories}{html}."/rhel8";
my $centos8_test_source = $anvil->data->{path}{directories}{html}."/centos8";
my $centos_stream8_test_source = $anvil->data->{path}{directories}{html}."/centos-stream8";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
rhel8_test_source => $rhel8_test_source,
centos8_test_source => $centos8_test_source,
centos_stream8_test_source => $centos_stream8_test_source,

@ -199,9 +199,9 @@ if ($local_uuid)
# Started the daemon.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0059"});
# Make sure it is enabled on boot.
my $return_code = $anvil->System->enable_daemon({debug => 2, daemon => $anvil->data->{sys}{daemon}{postgresql}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { return_code => $return_code }});
### NOTE: We no longer enable postgres on boot. When the first call is made to
### Database->connect on a striker, and no databases are available, it will
### start up the local daemon then.
}
else
{

Loading…
Cancel
Save