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. 227
      Anvil/Tools/DRBD.pm
  3. 1058
      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. 179
      tools/anvil-daemon
  11. 1597
      tools/anvil-manage-dr
  12. 2
      tools/anvil-manage-firewall
  13. 2
      tools/anvil-parse-fence-agents
  14. 4
      tools/anvil-provision-server
  15. 12
      tools/striker-manage-install-target
  16. 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,32 +729,135 @@ sub gather_data
foreach my $connection ($name->findnodes('./connection'))
{
my $peer = "";
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 }});
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 => {
host1_name => $host1_name,
host1_ip_address => $host1_ip_address,
host1_tcp_port => $host1_tcp_port,
}});
}
else
{
$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 => {
host2_name => $host2_name,
host2_ip_address => $host2_ip_address,
host2_tcp_port => $host2_tcp_port,
}});
}
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');;
$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},
}});
# $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})
# 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))
{
# 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
{
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol} = "unknown";
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{fencing} = "unknown";
# 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}::protocol" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol},
"s2:new::resource::${resource}::peer::${peer}::fencing" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{fencing},
"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'))
{
my $section = $name->{name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { section => $section }});
foreach my $option_name ($name->findnodes('./option'))
{
my $variable = $option_name->{name};
my $value = $option_name->{value};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
's1:variable' => $variable,
's2:value' => $value,
}});
if ($section eq "net")
{
if ($variable eq "protocol")
{
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"new::resource::${resource}::peer::${peer}::protocol" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol},
}});
}
if ($variable eq "fencing")
{
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{fencing} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"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";
@ -760,40 +870,6 @@ sub gather_data
$anvil->data->{new}{resource}{$resource}{volume}{$volume}{peer}{$peer}{estimated_time_to_sync} = 0;
}
}
foreach my $name ($connection->findnodes('./section'))
{
my $section = $name->{name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { section => $section }});
foreach my $option_name ($name->findnodes('./option'))
{
my $variable = $option_name->{name};
my $value = $option_name->{value};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
's1:variable' => $variable,
's2:value' => $value,
}});
if ($section eq "net")
{
if ($variable eq "protocol")
{
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"new::resource::${resource}::peer::${peer}::protocol" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{protocol},
}});
}
if ($variable eq "fencing")
{
$anvil->data->{new}{resource}{$resource}{peer}{$peer}{fencing} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"new::resource::${resource}::peer::${peer}::fencing" => $anvil->data->{new}{resource}{$resource}{peer}{$peer}{fencing},
}});
}
}
}
}
}
}
}
@ -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,
}});
@ -1387,7 +1469,7 @@ ORDER BY
's6:scan_drbd_volume_device_minor' => $scan_drbd_volume_device_minor,
's7:scan_drbd_peer_host_name' => $scan_drbd_peer_host_name,
's8:scan_drbd_peer_ip_address' => $scan_drbd_peer_ip_address,
's9:scan_drbd_peer_protocol' => $scan_drbd_peer_protocol,
's9:scan_drbd_peer_protocol' => $scan_drbd_peer_protocol,
's10:scan_drbd_peer_fencing' => $scan_drbd_peer_fencing,
's11:scan_drbd_peer_tcp_port' => $scan_drbd_peer_tcp_port,
}});
@ -1434,22 +1516,55 @@ ORDER BY
}
}
$looking = 1;
$free_port = 7788;
$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
{
$looking = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { looking => $looking }});
$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,
free_port => $free_port,

File diff suppressed because it is too large Load Diff

@ -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. -->

@ -171,19 +171,23 @@ 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}{daily_checks} = 86400;
$anvil->data->{timing}{repo_update_interval} = 86400;
$anvil->data->{timing}{next_minute_check} = $now_time - 1;
$anvil->data->{timing}{next_daily_check} = ($now_time + $delay) - 1;
$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},
"s1:timing::minute_checks" => $anvil->data->{timing}{minute_checks},
"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},
}});
}
@ -418,10 +422,11 @@ sub handle_periodic_tasks
my $now_time = time;
my $type = $anvil->Get->host_type();
$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,
"s1:now_time" => $now_time,
"s2:timing::next_minute_check" => $anvil->data->{timing}{next_minute_check},
"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},
}});

@ -161,8 +161,8 @@ sub run_jobs
# Sanity checks passed
$anvil->Job->update_progress({
progress => 10,
message => "job_0185",
progress => 10,
message => "job_0185",
});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0185"});

@ -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