* Fixed up (though more testing/work needed) to ocf:alteeve:server to get it working with DRBD resources referenced using '/dev/drbd/by-res/...'.

* Added the anvil.conf option 'sys::privacy::strong' that controls if the Anvil! ever "calls home". Initially, this controls DRBD's usage flag.
* Updated DRBD->get_devices() to track resources by their 'by-res' names as well and by the normal '/dev/drbdX' devices.
* To mitigate https://bugzilla.redhat.com/show_bug.cgi?id=1868467, updated Get->bridges() to parse the normal (non-JSON) data if we get invalid JSON output.
* Updated anvil-join-anvil to not disable, and in fact enable, libvirtd on boot. With DRBD 9, the original fear of a user accidentally booting a VM that's running on the peer no longer is an issue. By enabling it and leaving it on, Striker dashboard users won't lose their virtual machine manager link unless the node powers off. Also enabled actually updating the job progress, completing this tool!

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 4 years ago
parent 39b4a912af
commit e35800c413
  1. 5
      Anvil/Tools.pm
  2. 38
      Anvil/Tools/DRBD.pm
  3. 182
      Anvil/Tools/Get.pm
  4. 47
      Anvil/Tools/Server.pm
  5. 9
      Anvil/Tools/Storage.pm
  6. 4
      anvil.conf
  7. 10
      notes
  8. 66
      ocf/alteeve/server
  9. 15
      share/words.xml
  10. 63
      tools/anvil-join-anvil
  11. 7
      tools/scancore
  12. 8
      tools/test.pl

@ -243,7 +243,7 @@ sub new
# I need to read the initial words early.
$anvil->Words->read({debug => $debug});
# If the local './tools.conf' file exists, read it in.
# If the local './anvil.conf' file exists, read it in.
if (-r $anvil->data->{path}{configs}{'anvil.conf'})
{
$anvil->Storage->read_config({debug => 3, file => $anvil->data->{path}{configs}{'anvil.conf'}});
@ -955,6 +955,9 @@ sub _set_defaults
hash_count => 500000,
salt_length => 16,
},
privacy => {
strong => 0,
},
# On actual RHEL systems, this will be used to ensure that given repos are enabled on given
# machines types. Obviously, this requires that the host has been subscribed.
rhel => {

@ -409,18 +409,22 @@ sub get_devices
}
foreach my $volume_href (@{$host_href->{volume}})
{
my $volume = $volume_href->{vnr};
my $drbd_path = $volume_href->{device}->[0]->{content};
my $lv_path = $volume_href->{disk}->[0];
$anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_path} = $drbd_path;
$anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_minor} = $volume_href->{device}->[0]->{minor};
$anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{'meta-disk'} = $volume_href->{'meta-disk'}->[0];
$anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{backing_lv} = $lv_path;
my $volume = $volume_href->{vnr};
my $drbd_path = $volume_href->{device}->[0]->{content};
my $lv_path = $volume_href->{disk}->[0];
my $by_res = "/dev/drbd/by-res/".$this_resource."/".$volume;
my $minor = $volume_href->{device}->[0]->{minor};
$anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_path} = "/dev/drbd".$minor;
$anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_path_by_res} = $by_res;
$anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_minor} = $minor;
$anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{'meta-disk'} = $volume_href->{'meta-disk'}->[0];
$anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{backing_lv} = $lv_path;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"drbd::config::${host}::resource::${this_resource}::volume::${volume}::drbd_path" => $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_path},
"drbd::config::${host}::resource::${this_resource}::volume::${volume}::drbd_minor" => $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_minor},
"drbd::config::${host}::resource::${this_resource}::volume::${volume}::meta-disk" => $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{'meta-disk'},
"drbd::config::${host}::resource::${this_resource}::volume::${volume}::backing_lv" => $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{backing_lv},
"drbd::config::${host}::resource::${this_resource}::volume::${volume}::drbd_path" => $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_path},
"drbd::config::${host}::resource::${this_resource}::volume::${volume}::drbd_path_by_res" => $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_path_by_res},
"drbd::config::${host}::resource::${this_resource}::volume::${volume}::drbd_minor" => $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{drbd_minor},
"drbd::config::${host}::resource::${this_resource}::volume::${volume}::meta-disk" => $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{'meta-disk'},
"drbd::config::${host}::resource::${this_resource}::volume::${volume}::backing_lv" => $anvil->data->{drbd}{config}{$host}{resource}{$this_resource}{volume}{$volume}{backing_lv},
}});
if (($anvil->data->{drbd}{config}{$host}{host}) && ($anvil->data->{drbd}{config}{$host}{host} eq $this_host))
{
@ -433,6 +437,18 @@ sub get_devices
"drbd::config::${host}::lv_path::${lv_path}::under" => $anvil->data->{drbd}{config}{$host}{lv_path}{$lv_path}{under},
}});
}
# If this is ourself, store the resource name and backing LV in the 'by-res'
# hash.
if ($anvil->Network->is_local({host => $this_host}))
{
$anvil->data->{drbd}{config}{$host}{'by-res'}{$by_res}{resource} = $this_resource;
$anvil->data->{drbd}{config}{$host}{'by-res'}{$by_res}{backing_lv} = $lv_path;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"drbd::config::${host}::by-res::${by_res}::resource" => $anvil->data->{drbd}{config}{$host}{'by-res'}{$by_res}{resource},
"drbd::config::${host}::by-res::${by_res}::backing_lv" => $anvil->data->{drbd}{config}{$host}{'by-res'}{$by_res}{backing_lv},
}});
}
}
}

@ -271,59 +271,167 @@ sub bridges
delete $anvil->data->{'local'}{network}{bridges};
};
my $bridge_data = "";
my $json = JSON->new->allow_nonref;
my $bridge_data = $json->decode($output);
#print Dumper $bridge_data;
foreach my $hash_ref (@{$bridge_data})
eval { $bridge_data = $json->decode($output); };
if ($@)
{
# If the ifname and master are the same, it's a bridge.
my $type = "interface";
my $interface = $hash_ref->{ifname};
my $master_bridge = $hash_ref->{master};
if ($interface eq $master_bridge)
{
$type = "bridge";
$anvil->data->{'local'}{network}{bridges}{bridge}{$interface}{found} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::bridge::${interface}::found" => $anvil->data->{'local'}{network}{bridges}{bridge}{$interface}{found},
}});
}
else
{
# Store this interface under the bridge.
$anvil->data->{'local'}{network}{bridges}{bridge}{$master_bridge}{connected_interface}{$interface} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::bridge::${master_bridge}::connected_interface::${interface}" => $anvil->data->{'local'}{network}{bridges}{bridge}{$master_bridge}{connected_interface}{$interface},
}});
}
# JSON parse failed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "error_0140", variables => {
json => $output,
error => $@,
}});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0519"});
# NOTE: This is not design to be normally used. It was created as a stop-gap while waiting
# for resolution on: https://bugzilla.redhat.com/show_bug.cgi?id=1868467
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{bridge}." -details link show"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
interface => $interface,
master_bridge => $master_bridge,
type => $type,
output => $output,
return_code => $return_code,
}});
foreach my $key (sort {$a cmp $b} keys %{$hash_ref})
my $interface = "";
my $type = "";
foreach my $line (split/\n/, $output)
{
if (ref($hash_ref->{$key}) eq "ARRAY")
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }});
if ($line =~ /^\d+:\s+(.*?):/)
{
$anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key} = [];
foreach my $value (sort {$a cmp $b} @{$hash_ref->{$key}})
$interface = $1;
$type = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
interface => $interface,
type => $type,
}});
$anvil->data->{'local'}{network}{bridges}{bridge}{$interface}{found} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::bridge::${interface}::found" => $anvil->data->{'local'}{network}{bridges}{bridge}{$interface}{found},
}});
}
if ($interface)
{
if (($line =~ /master (.*?) /) or ($line =~ /master (.*?)$/))
{
push @{$anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key}}, $value;
my $master_bridge = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { master_bridge => $master_bridge }});
if ($master_bridge eq $interface)
{
# This is the bridge
$type = "bridge";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { type => $type }});
}
else
{
# It's an interface, store it under the bridge.
$type = "interface";
$anvil->data->{'local'}{network}{bridges}{bridge}{$master_bridge}{connected_interface}{$interface} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
type => $type,
"local::network::bridges::bridge::${master_bridge}::connected_interface::${interface}" => $anvil->data->{'local'}{network}{bridges}{bridge}{$master_bridge}{connected_interface}{$interface},
}});
}
}
for (my $i = 0; $i < @{$anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key}}; $i++)
}
if (($interface) && ($type))
{
if ($line =~ /<(.*?)>/)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::${type}::${interface}::${key}->[$i]" => $anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key}->[$i],
}});
my $flags = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { flags => $flags }});
my $i = 0;
foreach my $flag (split/,/, $flags)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { flag => $flag }});
push @{$anvil->data->{'local'}{network}{bridges}{$type}{$interface}{flags}}, $flag;
}
}
}
if ($line =~ /^\s+(.*?)$interface/)
{
# Break out settings.
my $values = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'values' => $values }});
my $variable = "";
foreach my $word (split/ /, $values)
{
if (($variable) && (($word eq "on") or ($word eq "off")))
{
my $value = $word;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { value => $value }});
$anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$variable} = $value eq "on" ? "true" : "false";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::${type}::${interface}::${variable}" => $anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$variable},
}});
$variable = "";
}
else
{
$variable = $word;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { variable => $variable }});
}
}
}
}
}
else
{
foreach my $hash_ref (@{$bridge_data})
{
# If the ifname and master are the same, it's a bridge.
my $type = "interface";
my $interface = $hash_ref->{ifname};
my $master_bridge = $hash_ref->{master};
if ($interface eq $master_bridge)
{
$type = "bridge";
$anvil->data->{'local'}{network}{bridges}{bridge}{$interface}{found} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::bridge::${interface}::found" => $anvil->data->{'local'}{network}{bridges}{bridge}{$interface}{found},
}});
}
else
{
$anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key} = $hash_ref->{$key};
# Store this interface under the bridge.
$anvil->data->{'local'}{network}{bridges}{bridge}{$master_bridge}{connected_interface}{$interface} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::${type}::${interface}::${key}" => $anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key},
"local::network::bridges::bridge::${master_bridge}::connected_interface::${interface}" => $anvil->data->{'local'}{network}{bridges}{bridge}{$master_bridge}{connected_interface}{$interface},
}});
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
interface => $interface,
master_bridge => $master_bridge,
type => $type,
}});
foreach my $key (sort {$a cmp $b} keys %{$hash_ref})
{
if (ref($hash_ref->{$key}) eq "ARRAY")
{
$anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key} = [];
foreach my $value (sort {$a cmp $b} @{$hash_ref->{$key}})
{
push @{$anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key}}, $value;
}
for (my $i = 0; $i < @{$anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key}}; $i++)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::${type}::${interface}::${key}->[$i]" => $anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key}->[$i],
}});
}
}
else
{
$anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key} = $hash_ref->{$key};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::${type}::${interface}::${key}" => $anvil->data->{'local'}{network}{bridges}{$type}{$interface}{$key},
}});
}
}
}
}

@ -559,6 +559,37 @@ sub map_network
return(0);
}
=head2 provision
This method creates a new (virtual) server on an Anvil! system.
Parameters;
=cut
sub provision
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
=cut
Provision order:
1. Create LVs and register the storage.
- NOTE: If the LV is already in the DB (from a past install) and the peer is not available and the local
DRBD resource doesn't show Consistent, abort. If the peer is alive but we can't contact it, it's
possible the peer is UpToDate.
2. Create the DRBD resource. If "Inconsistent" on both nodes, force up to date
3. Wait for install media/image to be ready
4. Provision VM and add to Pacemaker.
=cut
return(0);
}
=head2 migrate
This will migrate (push or pull) a server from one node to another. If the migration was successful, C<< 1 >> is returned. Otherwise, C<< 0 >> is returned with a (hopefully) useful error being logged.
@ -1319,6 +1350,20 @@ sub _parse_definition
my $on_lv = defined $anvil->data->{drbd}{config}{$host}{drbd_path}{$device_path}{on} ? $anvil->data->{drbd}{config}{$host}{drbd_path}{$device_path}{on} : "";
my $resource = defined $anvil->data->{drbd}{config}{$host}{drbd_path}{$device_path}{resource} ? $anvil->data->{drbd}{config}{$host}{drbd_path}{$device_path}{resource} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
on_lv => $on_lv,
resource => $resource,
}});
if ((not $resource) && ($anvil->data->{drbd}{config}{$host}{'by-res'}{$device_path}{resource}))
{
$resource = $anvil->data->{drbd}{config}{$host}{'by-res'}{$device_path}{resource};
$on_lv = $anvil->data->{drbd}{config}{$host}{'by-res'}{$device_path}{backing_lv};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
on_lv => $on_lv,
resource => $resource,
}});
}
$anvil->data->{server}{$target}{$server}{device}{$device_path}{on_lv} = $on_lv;
$anvil->data->{server}{$target}{$server}{device}{$device_path}{resource} = $resource;
$anvil->data->{server}{$target}{$server}{device}{$device_path}{target} = $device_target;
@ -1332,7 +1377,7 @@ sub _parse_definition
}});
# Keep a list of DRBD resources used by this server.
my $drbd_resource = $anvil->data->{server}{$target}{$server}{device}{$device_path}{resource};
my $drbd_resource = $anvil->data->{server}{$target}{$server}{device}{$device_path}{resource};
$anvil->data->{server}{$target}{$server}{drbd}{resource}{$drbd_resource} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"server::${target}::${server}::drbd::resource::${drbd_resource}" => $anvil->data->{server}{$target}{$server}{drbd}{resource}{$drbd_resource},

@ -1243,6 +1243,15 @@ fi";
return(0);
}
=head2 create_lv
This creates a logical volume on the local host.
=cut
sub create_lv
{
}
=head2 find
This searches for the given file on the system. It will search in the directories returned by C<< $anvil->Storage->search_directories() >>.

@ -1,5 +1,9 @@
### This is the main Anvil! configuration file.
# To help understand how the Anvil! is used, some features will "call home" to record anonymous information
# about a machine participating in an Anvil! system. If you wish to not have this happen, set this to '1'.
sys::privacy::strong = 0
### Database
# Database connections;
#

10
notes

@ -293,9 +293,9 @@ pcs resource clone hypervisor clone-max=2 notify="false"
pcs resource create drbd systemd:drbd op monitor interval=60
pcs resource clone drbd clone-max=2 notify="false"
pcs resource create test_server ocf:alteeve:server name="test_server" meta allow-migrate="true" op monitor interval="60"
pcs resource create srv01-sql ocf:alteeve:server name="srv01-sql" meta allow-migrate="true" op monitor interval="60" on-fail="block"
- or -
pcs resource update test_server ocf:alteeve:server name="test_server" meta allow-migrate="true" op monitor interval="60"
pcs resource update srv01-sql ocf:alteeve:server name="srv01-sql" meta allow-migrate="true" op monitor interval="60" on-fail="block"
# Test
stonith_admin --fence el8-a01n02 --verbose; crm_error $?
@ -911,13 +911,13 @@ virt-install --connect qemu:///system \
# Migration;
pcs resource move test_server
pcs resource move srv01-sql
# (then remove the constraint);
pcs constraint show --full
pcs constraint remove cli-ban-test_server-on-el8-a01n01
pcs constraint remove cli-ban-srv01-sql-on-el8-a01n01
pcs constraint remove $(pcs constraint show --full | grep ban-test_server | perl -pe 's/^.*?id:(.*?)\)/$1/')
pcs constraint remove $(pcs constraint show --full | grep ban-srv01-sql | perl -pe 's/^.*?id:(.*?)\)/$1/')
DRBD 9 - Check;

@ -100,9 +100,9 @@ $anvil->Log->secure({set => 1});
### Read or Set the environment variables
# This is the name of the server we're managing. # Example values:
$anvil->data->{environment}{OCF_RESKEY_name} = defined $ENV{OCF_RESKEY_name} ? $ENV{OCF_RESKEY_name} : ""; # srv01-c7
$anvil->data->{environment}{OCF_RESKEY_name} = defined $ENV{OCF_RESKEY_name} ? $ENV{OCF_RESKEY_name} : ""; # srv01-sql
# This is our node name
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_on_node} = defined $ENV{OCF_RESKEY_CRM_meta_on_node} ? $ENV{OCF_RESKEY_CRM_meta_on_node} : ""; # el8-a01n01.digimer.ca
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_on_node} = defined $ENV{OCF_RESKEY_CRM_meta_on_node} ? $ENV{OCF_RESKEY_CRM_meta_on_node} : ""; # mk-a02n01.digimer.ca
# This says "UUID", but it's the node ID.
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_on_node_uuid} = defined $ENV{OCF_RESKEY_CRM_meta_on_node_uuid} ? $ENV{OCF_RESKEY_CRM_meta_on_node_uuid} : ""; # 1
# This is the timeout for the called action in millisecond.
@ -119,8 +119,8 @@ $anvil->data->{environment}{OCF_RESOURCE_PROVIDER} = defined $ENV{O
$anvil->data->{environment}{OCF_RESOURCE_TYPE} = defined $ENV{OCF_RESOURCE_TYPE} ? $ENV{OCF_RESOURCE_TYPE} : ""; # server
$anvil->data->{environment}{OCF_ROOT} = defined $ENV{OCF_ROOT} ? $ENV{OCF_ROOT} : ""; # /usr/lib/ocf
# These are set during a migration
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source} = defined $ENV{OCF_RESKEY_CRM_meta_migrate_source} ? $ENV{OCF_RESKEY_CRM_meta_migrate_source} : ""; # el8-a01n01.digimer.ca
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_target} = defined $ENV{OCF_RESKEY_CRM_meta_migrate_target} ? $ENV{OCF_RESKEY_CRM_meta_migrate_target} : ""; # el8-a01n02.digimer.ca
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source} = defined $ENV{OCF_RESKEY_CRM_meta_migrate_source} ? $ENV{OCF_RESKEY_CRM_meta_migrate_source} : ""; # mk-a02n01.digimer.ca
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_target} = defined $ENV{OCF_RESKEY_CRM_meta_migrate_target} ? $ENV{OCF_RESKEY_CRM_meta_migrate_target} : ""; # mk-a02n02.digimer.ca
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_record_pending} = defined $ENV{OCF_RESKEY_CRM_meta_record_pending} ? $ENV{OCF_RESKEY_CRM_meta_record_pending} : ""; # true
# If pacemaker is in debug, so are we,
@ -149,27 +149,27 @@ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 0, level
### TEST: to be removed later
if ($anvil->data->{switches}{test1})
{
$anvil->data->{environment}{OCF_RESKEY_name} = "test_server";
$anvil->data->{environment}{OCF_RESKEY_name} = "srv01-sql";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_timeout} = 20000;
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_on_node} = "el8-a01n01.digimer.ca";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source} = "el8-a01n01.digimer.ca";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_target} = "el8-a01n02.digimer.ca";
#print "Running test 1; Migrate: [".$anvil->data->{environment}{OCF_RESKEY_name}."] from: [".$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source}."] to: [".$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_target}."]\n";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_on_node} = "mk-a02n01.digimer.ca";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source} = "mk-a02n01.digimer.ca";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_target} = "mk-a02n02.digimer.ca";
print "Running test 1; Migrate: [".$anvil->data->{environment}{OCF_RESKEY_name}."] from: [".$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source}."] to: [".$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_target}."]\n";
}
if ($anvil->data->{switches}{test2})
{
$anvil->data->{environment}{OCF_RESKEY_name} = "test_server";
$anvil->data->{environment}{OCF_RESKEY_name} = "srv01-sql";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_timeout} = 20000;
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_on_node} = "el8-a01n02.digimer.ca";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source} = "el8-a01n02.digimer.ca";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_target} = "el8-a01n01.digimer.ca";
#print "Running test 2; Migrate: [".$anvil->data->{environment}{OCF_RESKEY_name}."] from: [".$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source}."] to: [".$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_target}."]\n";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_on_node} = "mk-a02n02.digimer.ca";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source} = "mk-a02n02.digimer.ca";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_target} = "mk-a02n01.digimer.ca";
print "Running test 2; Migrate: [".$anvil->data->{environment}{OCF_RESKEY_name}."] from: [".$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source}."] to: [".$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_target}."]\n";
}
if ($anvil->data->{switches}{test3})
{
$anvil->data->{environment}{OCF_RESKEY_name} = "test_server";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_on_node} = "el8-a01n01.digimer.ca";
#print "Running test 3; Boot or shutdown of: [".$anvil->data->{environment}{OCF_RESKEY_name}."].\n";
$anvil->data->{environment}{OCF_RESKEY_name} = "srv01-sql";
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_on_node} = "mk-a02n01.digimer.ca";
print "Running test 3; Boot or shutdown of: [".$anvil->data->{environment}{OCF_RESKEY_name}."].\n";
}
# This is for debugging.
@ -275,6 +275,7 @@ sub check_daemons
{
my ($anvil, $task) = @_;
print "Parsing CIB\n";
my $problem = $anvil->Cluster->parse_cib();
if ($problem)
{
@ -285,7 +286,7 @@ sub check_daemons
}
# Is the peer running? We'll use this to know whether to try and start daemons on the peer.
my $peer_name = $anvil->Cluster->get_peers();
my $peer_name = $anvil->data->{cib}{parsed}{peer}{name};
my $peer_ready = $anvil->data->{cib}{parsed}{peer}{ready};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
peer_name => $peer_name,
@ -294,7 +295,8 @@ sub check_daemons
if ($task eq "start")
{
foreach my $daemon ("libvirtd.service", "drbd.service")
#foreach my $daemon ("libvirtd.service", "drbd.service")
foreach my $daemon ("libvirtd.service")
{
my $running_local = 0;
my $running_peer = 0;
@ -353,7 +355,6 @@ sub check_daemons
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0485", variables => { daemon => $daemon }});
}
### TODO: Left off here.
if ($peer_ready)
{
my ($output, $error, $return_code) = $anvil->Remote->call({
@ -441,8 +442,10 @@ sub check_daemons
}
}
}
=cut # It's simpler (and thus safer) to not stop daemons.
if ($task eq "stop")
{
print "Stopping daemons\n";
my $stop = 0;
# Check both nodes if a server is running on either node.
@ -580,6 +583,7 @@ sub check_daemons
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0496"});
}
}
=cut
return(0);
}
@ -1313,7 +1317,7 @@ sub validate_storage
{
my ($anvil) = @_;
### TODO: When checking on a running server, use 'from_memory'.
# When checking on a running server, use 'from_memory'.
my $server = $anvil->data->{environment}{OCF_RESKEY_name};
my $source = "from_disk";
if ($anvil->data->{server}{'local'}{$server}{from_memory}{host})
@ -1380,7 +1384,7 @@ sub validate_storage_drbd
foreach my $device_path (sort {$a cmp $b} keys %{$anvil->data->{server}{'local'}{$server}{device}})
{
next if not $device_path;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"server::local::${server}::device::${device_path}::resource" => $anvil->data->{server}{'local'}{$server}{device}{$device_path}{resource},
}});
if (not $anvil->data->{server}{'local'}{$server}{device}{$device_path}{resource})
@ -1392,15 +1396,25 @@ sub validate_storage_drbd
foreach my $device_target (sort {$a cmp $b} keys %{$anvil->data->{server}{'local'}{$server}{$source}{device}{disk}{target}})
{
my $drbd_device = $anvil->data->{server}{'local'}{$server}{$source}{device}{disk}{target}{$device_target}{path};
my $drbd_resource = $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_device}{resource};
my $on_lv = $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_device}{on};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
my $drbd_device = $anvil->data->{server}{'local'}{$server}{$source}{device}{disk}{target}{$device_target}{path};
my $drbd_resource = defined $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_device}{resource} ? $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_device}{resource} : "";
my $on_lv = defined $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_device}{on} ? $anvil->data->{drbd}{config}{$host}{drbd_path}{$drbd_device}{on} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host => $host,
drbd_device => $drbd_device,
drbd_resource => $drbd_resource,
on_lv => $on_lv,
}});
if (not $drbd_resource)
{
# See if we can find the resource in the 'by-res' hash.
$drbd_resource = defined $anvil->data->{drbd}{config}{$host}{'by-res'}{$drbd_device}{resource} ? $anvil->data->{drbd}{config}{$host}{'by-res'}{$drbd_device}{resource} : "";
$on_lv = defined $anvil->data->{drbd}{config}{$host}{'by-res'}{$drbd_device}{backing_lv} ? $anvil->data->{drbd}{config}{$host}{'by-res'}{$drbd_device}{backing_lv} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
drbd_resource => $drbd_resource,
on_lv => $on_lv,
}});
}
# If the logical volume here here and active?
if ((not $on_lv) or (not exists $anvil->data->{lvm}{'local'}{lv}{$on_lv}))

@ -199,6 +199,16 @@ The error was:
<key name="error_0137">All attempts to change the IPMI user: [#!variable!user_name!#] (number: [#!variable!user_number!#] failed. The last try's output (if any) was: [#!variable!output!#] (return code: [#!variable!return code!#]).</key>
<key name="error_0138">The system call: [#!variable!shell_call!#] failed. The output (if any) was: [#!variable!output!#] (return code: [#!variable!return code!#]).</key>
<key name="error_0139">The DRBD global common config file: [#!data!path::configs::global-common.conf!#] doesn't exist, unable to update it.</key>
<key name="error_0140">
Failed to parse the JSON string:
===========================================================
#!variable!json!#
===========================================================
The error was:
===========================================================
#!variable!error!#
===========================================================
</key>
<!-- Table headers -->
<key name="header_0001">Current Network Interfaces and States</key>
@ -372,6 +382,10 @@ Failure! The return code: [#!variable!return_code!#] was received ('0' was expec
<key name="job_0123">Adding a fence delay agent to provide time for the IPMI BMC to boot before trying it again.</key>
<key name="job_0124">Configuring the cluster to loop fence attempts indefinitely.</key>
<key name="job_0125">Enabling fencing!</key>
<key name="job_0126">Checking to see if: [#!data!path::configs::global-common.conf!#] needs to be configured or updated.</key>
<key name="job_0127">Update completed successfully.</key>
<key name="job_0128">Update not required, nothing changed.</key>
<key name="job_0129">Completed joining the #!string!brand_0002!#.</key>
<!-- Log entries -->
<key name="log_0001">Starting: [#!variable!program!#].</key>
@ -981,6 +995,7 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
====
</key>
<key name="log_0518">Appending the file: [#!variable!file!#] with the line: [#!variable!line!#].</key>
<key name="log_0519">Attempting to parse bridge information using standard output after failing to parse JSON status information.</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>

@ -66,6 +66,8 @@ configure_pacemaker($anvil);
# Configure DRBD
configure_drbd($anvil);
update_progress($anvil, 100, "job_0128");
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0128"});
$anvil->nice_exit({exit_code => 0});
#############################################################################################################
@ -78,7 +80,22 @@ sub configure_drbd
my ($anvil) = @_;
### TODO: See if there is a hardware RAID controller and, if so, auto-enable
# Read in the global_common.conf
update_progress($anvil, ($anvil->data->{job}{progress} += 1), "job_0126");
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0126"});
my $updated = $anvil->DRBD->update_global_common({
usage_count => $anvil->data->{sys}{privacy}{strong} ? 0 : 1,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { updated => $updated }});
if ($updated)
{
update_progress($anvil, ($anvil->data->{job}{progress} += 1), "job_0127");
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0127"});
}
else
{
update_progress($anvil, ($anvil->data->{job}{progress} += 1), "job_0128");
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0128"});
}
return(0);
}
@ -166,28 +183,35 @@ sub configure_pacemaker
}
### Run on both nodes.
# Enable pcsd and start the pcsd daemons.
my ($return_code) = $anvil->System->enable_daemon({daemon => "pcsd"});
# Enable pcsd and start the pcsd daemon.
my ($return_code) = $anvil->System->enable_daemon({daemon => "pcsd.service"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { return_code => $return_code }});
$return_code = undef;
($return_code) = $anvil->System->start_daemon({daemon => "pcsd.service"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { return_code => $return_code }});
$return_code = undef;
update_progress($anvil, ($anvil->data->{job}{progress} += 2), "job_0094,!!daemon!pcsd.service!!");
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0094", variables => { daemon => "pcsd.service" }});
# Enable libvirtd and start the libvirtd daemon.
($return_code) = $anvil->System->enable_daemon({daemon => "libvirtd.service"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { return_code => $return_code }});
$return_code = undef;
($return_code) = $anvil->System->start_daemon({daemon => "pcsd"});
($return_code) = $anvil->System->start_daemon({daemon => "libvirtd.service"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { return_code => $return_code }});
$return_code = undef;
update_progress($anvil, ($anvil->data->{job}{progress} += 2), "job_0094,!!daemon!pcsd!!");
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0094", variables => { daemon => "pcsd" }});
update_progress($anvil, ($anvil->data->{job}{progress} += 2), "job_0094,!!daemon!libvirtd.service!!");
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0094", variables => { daemon => "libvirtd.service" }});
# Disabled and stop the libvirtd daemon.
foreach my $daemon ("libvirtd.service", "drbd.service")
{
my ($return_code) = $anvil->System->disable_daemon({daemon => $daemon});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { return_code => $return_code }});
$return_code = undef;
($return_code) = $anvil->System->stop_daemon({daemon => $daemon});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { return_code => $return_code }});
$return_code = undef;
update_progress($anvil, ($anvil->data->{job}{progress} += 2), "job_0095,!!daemon!".$daemon."!!");
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0095", variables => { daemon => $daemon }});
}
($return_code) = $anvil->System->disable_daemon({daemon => "drbd.service"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { return_code => $return_code }});
$return_code = undef;
($return_code) = $anvil->System->stop_daemon({daemon => "drbd.service"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { return_code => $return_code }});
$return_code = undef;
update_progress($anvil, ($anvil->data->{job}{progress} += 2), "job_0095,!!daemon!drbd.service!!");
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0095", variables => { daemon => "drbd.service" }});
# If there is no corosync.conf, see if the peer has it. If so, copy it. If not, we'll initialize the
# cluster shortly.
@ -1901,10 +1925,7 @@ sub update_progress
's2:message' => $message,
}});
# Disabled for the moment
return(0);
$progress = 95 if $progress > 100;
$progress = 98 if $progress > 100;
if (not $anvil->data->{switches}{'job-uuid'})
{
return(0);

@ -145,9 +145,8 @@ sub call_agents
}
# Now call the agent.
my $start_time = time;
my $return_code = 9999;
my $timeout = $default_timeout;
my $start_time = time;
my $timeout = $default_timeout;
if ((exists $anvil->data->{scancore}{agent}{$agent_name}{agent_runtime}) && ($anvil->data->{scancore}{agent}{$agent_name}{agent_runtime} =~ /^\d+$/))
{
$timeout = $anvil->data->{scancore}{agent}{$agent_name}{agent_runtime};
@ -155,7 +154,7 @@ sub call_agents
my $shell_call = $anvil->data->{path}{exe}{timeout}." ".$timeout." ".$agent_path;
if ($anvil->data->{sys}{'log'}{level})
{
$shell_call .= ." ".$anvil->data->{sys}{'log'}{level};
$shell_call .= " ".$anvil->data->{sys}{'log'}{level};
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});

@ -29,7 +29,9 @@ $anvil->Database->connect();
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, secure => 0, key => "log_0132"});
$anvil->Get->switches;
my $updated = $anvil->DRBD->update_global_common({
debug => 2,
#$anvil->DRBD->get_devices({ debug => 2 }); die;
$anvil->Server->get_status({
debug => 2,
server => "srv01-sql",
});
print "DRBD global common updated? [".$updated."]\n";

Loading…
Cancel
Save