diff --git a/Anvil/Tools/Cluster.pm b/Anvil/Tools/Cluster.pm
index f752347a..cd99bc71 100644
--- a/Anvil/Tools/Cluster.pm
+++ b/Anvil/Tools/Cluster.pm
@@ -5,14 +5,16 @@ package Anvil::Tools::Cluster;
use strict;
use warnings;
-use Scalar::Util qw(weaken isweak);
use Data::Dumper;
+use XML::Simple qw(:strict);
+use XML::LibXML;
+use Scalar::Util qw(weaken isweak);
our $VERSION = "3.0.0";
my $THIS_FILE = "Cluster.pm";
### Methods;
-# get_peer
+# parse_cib
=pod
@@ -72,23 +74,398 @@ sub parent
# Public methods #
#############################################################################################################
-=head2 get_peer
+=head2 parse_cib
-This method will return the peer's host name, B<< if >> this host is itself a node in a cluster.
+This reads in the CIB XML and parses it. On success, it returns C<< 0 >>. On failure (ie: pcsd isn't running), returns C<< 1 >>.
=cut
-sub get_peer
+sub parse_cib
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
- $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->_test_access()" }});
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Cluster->parse_cib()" }});
+
+ # If we parsed before, delete it.
+ if (exists $anvil->data->{cib}{parsed})
+ {
+ delete $anvil->data->{cib}{parsed};
+ }
+
+ my $problem = 1;
+ my $shell_call = $anvil->data->{path}{exe}{pcs}." cluster cib";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }});
- my $peer_host_name = "";
+ my ($cib_data, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ cib_data => $cib_data,
+ return_code => $return_code,
+ }});
+ if ($return_code)
+ {
+ # Failed to read the CIB.
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "warning_0052"});
+ }
+ else
+ {
+ my $dom = eval { XML::LibXML->load_xml(string => $cib_data); };
+ if ($@)
+ {
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "warning_0053", variables => {
+ cib => $cib_data,
+ error => $@,
+ }});
+ }
+ else
+ {
+ # Successful parse!
+=cut
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+==================
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+================== First fence
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+================== Second fence
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+================ Enable stonith
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+=cut
+ $problem = 0;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }});
+ foreach my $primitive ($dom->findnodes('/cib/configuration/resources/primitive'))
+ {
+ my $class = $primitive->{class};
+ my $id = $primitive->{id};
+ my $type = $primitive->{type};
+ $anvil->data->{cib}{parsed}{cib}{resources}{primitive}{$class}{$id}{type} = $type;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "cib::parsed::cib::resources::primitive:${class}::${id}::type" => $anvil->data->{cib}{parsed}{cib}{resources}{primitive}{$class}{$id}{type},
+ }});
+ foreach my $nvpair ($primitive->findnodes('./instance_attributes/nvpair'))
+ {
+ my $name = $nvpair->{name};
+ foreach my $variable (sort {$a cmp $b} keys %{$nvpair})
+ {
+ next if $variable eq "name";
+ $anvil->data->{cib}{parsed}{cib}{resources}{primitive}{$class}{$id}{instance_attributes}{$name}{$variable} = $nvpair->{$variable};;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "cib::parsed::cib::resources::primitive::${class}::${id}::instance_attributes::${name}::${variable}" => $anvil->data->{cib}{parsed}{cib}{resources}{primitive}{$class}{$id}{instance_attributes}{$name}{$variable},
+ }});
+ }
+ }
+ foreach my $nvpair ($primitive->findnodes('./operations/op'))
+ {
+ my $id = $nvpair->{id};
+ foreach my $variable (sort {$a cmp $b} keys %{$nvpair})
+ {
+ next if $variable eq "id";
+ $anvil->data->{cib}{parsed}{cib}{resources}{primitive}{$class}{$id}{operations}{op}{$id}{$variable} = $nvpair->{$variable};;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "cib::parsed::cib::resources::primitive::${class}::${id}::operations::op::${id}::${variable}" => $anvil->data->{cib}{parsed}{cib}{resources}{primitive}{$class}{$id}{operations}{op}{$id}{$variable},
+ }});
+ }
+ }
+ }
+ die;
+ foreach my $attribute ($dom->findnodes('/cib'))
+ {
+ foreach my $variable (sort {$a cmp $b} keys %{$attribute})
+ {
+ $anvil->data->{cib}{parsed}{cib}{$variable} = $attribute->{$variable};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "cib::parsed::cib::${variable}" => $anvil->data->{cib}{parsed}{cib}{$variable},
+ }});
+ }
+ }
+ foreach my $nvpair ($dom->findnodes('/cib/configuration/crm_config/cluster_property_set/nvpair'))
+ {
+ my $name = $nvpair->{name};
+ $anvil->data->{cib}{parsed}{configuration}{crm_config}{cluster_property_set}{nvpair}{$name}{id} = $nvpair->{id};
+ $anvil->data->{cib}{parsed}{configuration}{crm_config}{cluster_property_set}{nvpair}{$name}{value} = $nvpair->{value};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "cib::parsed::configuration::crm_config::cluster_property_set::nvpair::${name}::id" => $anvil->data->{cib}{parsed}{configuration}{crm_config}{cluster_property_set}{nvpair}{$name}{id},
+ "cib::parsed::configuration::crm_config::cluster_property_set::nvpair::${name}::value" => $anvil->data->{cib}{parsed}{configuration}{crm_config}{cluster_property_set}{nvpair}{$name}{value},
+ }});
+ }
+ foreach my $node ($dom->findnodes('/cib/configuration/nodes/node'))
+ {
+ my $uname = $node->{uname};
+ $anvil->data->{cib}{parsed}{configuration}{nodes}{$uname}{id} = $node->{id};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "cib::parsed::configuration::nodes::${uname}::id" => $anvil->data->{cib}{parsed}{configuration}{nodes}{$uname}{id},
+ }});
+ }
+ # Status isn't available until the cluster has been up for a bit.
+ foreach my $node_state ($dom->findnodes('/cib/status/node_state'))
+ {
+ my $uname = $node_state->{uname};
+ foreach my $variable (sort {$a cmp $b} keys %{$node_state})
+ {
+ next if $variable eq "uname";
+ $anvil->data->{cib}{parsed}{cib}{node_state}{$uname}{$variable} = $node_state->{$variable};;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "cib::parsed::cib::node_state::${uname}::${variable}" => $anvil->data->{cib}{parsed}{cib}{node_state}{$uname}{$variable},
+ }});
+ }
+ }
+ }
+ }
+ #print Dumper $anvil->data->{cib}{parsed};
- return($peer_host_name);
+ return($problem);
}
# =head3
diff --git a/cgi-bin/striker b/cgi-bin/striker
index b90b3984..34fff277 100755
--- a/cgi-bin/striker
+++ b/cgi-bin/striker
@@ -5,7 +5,7 @@
# 1 == Host UUID not available yet.
#
# TODO:
-# * Switch out XML::Simple to XML::Twig or libXML
+# * Switch out XML::Simple to XML::Twig or libXML - Started in Cluster->parse_cib();
# - 15:05 < perlbot> XML::Simple commits the fatal flaw of trying to massage complicated and often
# irregular XML into the simple and highly regular world of perl data structures.
# Irregularities cause "not a hashref" sort of errors in your program. Use a real
diff --git a/notes b/notes
index 94d0d707..2dcced3a 100644
--- a/notes
+++ b/notes
@@ -255,10 +255,10 @@ systemctl stop libvirtd.service
==== One node
pcs host auth el8-a01n01 el8-a01n02 -u hacluster -p "secret"
-pcs cluster setup m3-anvil-01 m3-a01n01 m3-a01n02
+pcs cluster setup m3-anvil-01 el8-a01n01 el8-a01n02
pcs cluster start --all
-pcs stonith create virsh_node1 fence_virsh pcmk_host_list="m3-a01n01" ipaddr="192.168.122.1" passwd="secret" login="root" delay="15" port="m3-a01n01" op monitor interval="60"
-pcs stonith create virsh_node2 fence_virsh pcmk_host_list="m3-a01n02" ipaddr="192.168.122.1" passwd="secret" login="root" port="m3-a01n02" op monitor interval="60"
+pcs stonith create virsh_node1 fence_virsh pcmk_host_list="el8-a01n01" ipaddr="192.168.122.1" passwd="secret" login="root" delay="15" port="el8-a01n01" op monitor interval="60"
+pcs stonith create virsh_node2 fence_virsh pcmk_host_list="el8-a01n02" ipaddr="192.168.122.1" passwd="secret" login="root" port="el8-a01n02" op monitor interval="60"
pcs property set stonith-enabled=true
pcs resource create hypervisor systemd:libvirtd op monitor interval=60
@@ -271,7 +271,7 @@ pcs resource create test_server ocf:alteeve:server name="test_server" meta allow
pcs resource update test_server ocf:alteeve:server name="test_server" meta allow-migrate="true" op monitor interval="60"
# Test
-stonith_admin --fence m3-a01n02 --verbose; crm_error $?
+stonith_admin --fence el8-a01n02 --verbose; crm_error $?
==== DRBD notes
@@ -302,16 +302,16 @@ firewall-cmd --reload
* Provision the server via virt-install
* push the new XML to striker such that the peer's anvil daemon picks it up and writes it out.
-[root@m3-a01n01 drbd.d]# drbdsetup status r0 --verbose --statistics
+[root@el8-a01n01 drbd.d]# drbdsetup status r0 --verbose --statistics
r0 node-id:1 role:Primary suspended:no
write-ordering:flush
volume:0 minor:0 disk:UpToDate quorum:yes
size:10485404 read:9682852 written:0 al-writes:0 bm-writes:0 upper-pending:0 lower-pending:0 al-suspended:no blocked:no
- m3-a01n02.alteeve.com node-id:0 connection:Connected role:Secondary congested:no
+ el8-a01n02.alteeve.com node-id:0 connection:Connected role:Secondary congested:no
volume:0 replication:SyncSource peer-disk:Inconsistent done:92.29 resync-suspended:no
received:0 sent:9679140 out-of-sync:808144 pending:6 unacked:3
-[root@m3-a01n02 ~]# cat /sys/kernel/debug/drbd/resources/r0/connections/m3-a01n01.alteeve.com/0/proc_drbd
+[root@el8-a01n02 ~]# cat /sys/kernel/debug/drbd/resources/r0/connections/el8-a01n01.alteeve.com/0/proc_drbd
0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
ns:24360 nr:10485404 dw:10485404 dr:25420 al:0 bm:0 lo:0 pe:[0;0] ua:0 ap:[0;0] ep:1 wo:2 oos:10461044
[>....................] sync'ed: 0.3% (10212/10236)M
@@ -321,12 +321,12 @@ r0 node-id:1 role:Primary suspended:no
act_log: used:0/1237 hits:0 misses:0 starving:0 locked:0 changed:0
blocked on activity log: 0
-[root@m3-a01n02 ~]# drbdadm primary r0
+[root@el8-a01n02 ~]# drbdadm primary r0
r0: State change failed: (-1) Multiple primaries not allowed by config
Command 'drbdsetup primary r0' terminated with exit code 11
-[root@m3-a01n02 ~]# drbdadm net-options --allow-two-primaries=yes r0
-[root@m3-a01n02 ~]# drbdadm net-options --allow-two-primaries=no r0
+[root@el8-a01n02 ~]# drbdadm net-options --allow-two-primaries=yes r0
+[root@el8-a01n02 ~]# drbdadm net-options --allow-two-primaries=no r0
drbdsetup show all
drbdsetup show all --show-defaults
diff --git a/rpm/SPECS/anvil.spec b/rpm/SPECS/anvil.spec
index b0a81187..06f90d8c 100644
--- a/rpm/SPECS/anvil.spec
+++ b/rpm/SPECS/anvil.spec
@@ -64,6 +64,7 @@ Requires: perl-Sys-Syslog
Requires: perl-Text-Diff
Requires: perl-Time-HiRes
Requires: perl-UUID-Tiny
+Requires: perl-XML-LibXML
Requires: perl-XML-Simple
Requires: postfix
Requires: postgresql-contrib
diff --git a/share/words.xml b/share/words.xml
index f6cb674f..7bb5892d 100644
--- a/share/words.xml
+++ b/share/words.xml
@@ -1008,7 +1008,7 @@ NOTE: Please be patient!
Output: [#!variable!line!#].
Error: [#!variable!line!#].
- #!string!brand_0006!# - Install Target Menu
+ #!string!brand_0002!# - Install Target Menu
Will boot the next device as configured in your BIOS in # second{,s}.
key to edit the boot parameters of the highlighted option.]]>
Editing of this option is disabled.
@@ -1651,6 +1651,18 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
[ Warning ] - The passwords do not match.
[ Warning ] - The host: [#!variable!host!#] now belongs to the #!string!brand_0006!#, it can't be used here anymore.
[ Warning ] - The IP address: [#!variable!ip!#] is not valid. Ignoring associated hosts: [#!variable!hosts!#].
+ [ Warning ] - Failed to read the CIB. Is 'pcsd' running and is the cluster started?
+ [ Warning ] - Failed to parse the CIB. The CIB read was:
+========
+#!variable!cib!#
+========
+
+The error was:
+
+========
+#!variable!error!#
+========
+
diff --git a/tools/test.pl b/tools/test.pl
index d7cfdb37..dea61171 100755
--- a/tools/test.pl
+++ b/tools/test.pl
@@ -21,8 +21,8 @@ my $anvil = Anvil::Tools->new();
$anvil->Log->level({set => 2});
$anvil->Log->secure({set => 1});
-print "Connecting to the database(s);\n";
-$anvil->Database->connect();
-$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, secure => 0, key => "log_0132"});
+# print "Connecting to the database(s);\n";
+# $anvil->Database->connect();
+# $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, secure => 0, key => "log_0132"});
-$anvil->System->parse_corosync_conf({debug => 2});
+$anvil->Cluster->parse_cib({debug => 2});