Local modifications to ClusterLabs/Anvil by Alteeve
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

167 lines
5.5 KiB

#!/usr/bin/perl
#
# This scans the cluster by processing the CIB and storing information about nodes, cluster states, etc.
#
# NOTE: The data stored here is not bound to a given host. As such, node 1 will run this agent and node 2
# won't, _except_ when node 1 is offline and only node 2 is up.
#
# Examples;
#
# Exit codes;
# 0 = Normal exit.
# 1 = Startup failure (not running as root, no DB, bad file read, etc)
#
# TODO:
# -
#
use strict;
use warnings;
use Anvil::Tools;
use Data::Dumper;
# Disable buffering
$| = 1;
# Prevent a discrepency between UID/GID and EUID/EGID from throwing an error.
$< = $>;
$( = $);
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
if (($running_directory =~ /^\./) && ($ENV{PWD}))
{
$running_directory =~ s/^\./$ENV{PWD}/;
}
my $anvil = Anvil::Tools->new({log_level => 2, log_secure => 1});
$anvil->Log->level({set => 2});
$anvil->Log->secure({set => 1});
# Make sure we're running as 'root'
# $< == real UID, $> == effective UID
if (($< != 0) && ($> != 0))
{
# Not root
print $anvil->Words->string({key => "error_0005"})."\n";
$anvil->nice_exit({exit_code => 1});
}
$anvil->data->{scancore}{'scan-cluster'}{disable} = 0;
$anvil->data->{switches}{force} = 0;
$anvil->Storage->read_config();
# Read switches
$anvil->Get->switches;
# If we're disabled and '--force' wasn't used, exit.
if (($anvil->data->{scancore}{'scan-cluster'}{disable}) && (not $anvil->data->{switches}{force}))
{
# Exit.
$anvil->nice_exit({exit_code => 0});
}
# These are the tables used by this agent. The order matters as it controls to order the tables are created
# and sync'ed. For purges, this array is walked backwards.
$anvil->data->{scancore}{'scan-cluster'}{tables} = ["scan_cluster"];
# Handle start-up tasks
my $problem = $anvil->ScanCore->agent_startup({
debug => 3,
agent => $THIS_FILE,
tables => $anvil->data->{scancore}{'scan-cluster'}{tables},
});
if ($problem)
{
$anvil->nice_exit({exit_code => 1});
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_cluster_log_0001", variables => { program => $THIS_FILE }});
if ($anvil->data->{switches}{purge})
{
# This can be called when doing bulk-database purges.
$anvil->Database->purge_data({
debug => 2,
tables => $anvil->data->{scancore}{'scan-cluster'}{tables},
});
$anvil->nice_exit({exit_code => 0});
}
# Before we do anything, are we a node in a pacemaker cluster?
my $host_type = $anvil->Get->host_type;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }});
if ($host_type ne "node")
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_cluster_log_0002", variables => { host_type => $host_type }});
$anvil->nice_exit({exit_code => 0});
}
# Read the data.
collect_data($anvil);
# Read last scan
$anvil->nice_exit({exit_code => 0});
#############################################################################################################
# Functions #
#############################################################################################################
# This reads in all the data we can find on the local system
sub collect_data
{
my ($anvil) = @_;
# Pick out core cluster details.
my $problem = $anvil->Cluster->parse_cib({debug => 2});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { offline => $offline }});
my $cluster_name = $anvil->data->{cib}{parsed}{data}{cluster}{name};
my $stonith_enabled = $anvil->data->{cib}{parsed}{data}{stonith}{enabled};
my $maintenance_mode = $anvil->data->{cib}{parsed}{data}{cluster}{'maintenance-mode'};
my $stonith_max_attempts = $anvil->data->{cib}{parsed}{data}{cluster}{'stonith-max-attempts'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
cluster_name => $cluster_name,
stonith_enabled => $stonith_enabled,
maintenance_mode => $maintenance_mode,
stonith_max_attempts => $stonith_max_attempts,
}});
### TODO: If we're node 2, or not in the cluster, only update our information in the
### 'scan_cluster_nodes' table. Node 1 will update everything else if it's 'ready' (else node 2
### will, if it's ready).
my $i_am = $anvil->Cluster->which_node({debug => 1});
my $my_node_name = $anvil->data->{cib}{parsed}{'local'}{name};
my $peer_node_name = $anvil->data->{cib}{parsed}{peer}{name};
my $peer_ready = $anvil->data->{cib}{parsed}{peer}{ready};
my $local_ready = $anvil->data->{cib}{parsed}{data}{node}{$my_node_name}{node_state}{ready};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
i_am => $i_am,
my_node_name => $my_node_name,
peer_node_name => $peer_node_name,
peer_ready => $peer_ready,
local_ready => $local_ready,
}});
### TODO: Change the logic so that when both nodes are in the cluster, the node with the lowest
### load does the scan (typically the node without VMs).
if (($i_am eq "node2") && ($peer_ready))
{
# We're not going to run.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_cluster_message_0001"});
$anvil->nice_exit({exit_code => 0});
}
# If we're still alive, we're either node 1, or we're node 2 and node 1 is not ready. If we're not ready,
if ($stonith_max_attempts ne "INFINITY")
{
### TODO: Call pcs to update
}
return(0);
}