|
|
|
#!/usr/bin/perl
|
|
|
|
#
|
|
|
|
# This walks through all installed fence agents, parses their man page, and records their description and
|
|
|
|
# STDIN parameters.
|
|
|
|
#
|
|
|
|
# TODO:
|
|
|
|
# - Look at the mtime of the fence agents and record them as variables. Only process if an agenti is new or
|
|
|
|
# the mtime has changed.
|
|
|
|
#
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
use Anvil::Tools;
|
|
|
|
use Data::Dumper;
|
|
|
|
|
|
|
|
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete.
|
|
|
|
$| = 1;
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
$anvil->data->{switches}{refresh} = 0;
|
|
|
|
$anvil->Get->switches;
|
|
|
|
$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},
|
|
|
|
}});
|
|
|
|
|
|
|
|
refresh_unified_metadata($anvil);
|
|
|
|
|
|
|
|
$anvil->nice_exit({exit_code => 0});
|
|
|
|
|
|
|
|
|
|
|
|
#############################################################################################################
|
|
|
|
# Functions #
|
|
|
|
#############################################################################################################
|
|
|
|
|
|
|
|
# See if the unified fence metadata need to be (re)generated.
|
|
|
|
sub refresh_unified_metadata
|
|
|
|
{
|
|
|
|
my ($anvil) = @_;
|
|
|
|
|
|
|
|
my $refresh = 0;
|
|
|
|
if (not -e $anvil->data->{path}{data}{fences_unified_metadata})
|
|
|
|
{
|
|
|
|
$refresh = 1;
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0472"});
|
|
|
|
}
|
|
|
|
elsif ($anvil->data->{switches}{refresh})
|
|
|
|
{
|
|
|
|
$refresh = 1;
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0473"});
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
# How old is the file?
|
|
|
|
my $modified_time = (stat($anvil->data->{path}{data}{fences_unified_metadata}))[9];
|
|
|
|
my $age = time - $modified_time;
|
|
|
|
my $maximum_age = ((60 * 60) * 24);
|
* Moved the fences_unified_metadata file from /tmp, which apache can not read, to /var/www/html/.
* Fixed a bug (well, made a work-around for an issue without a known reproducer) where, on some occassion, a record will end up in the public table without being copied into the history schema. When this happens, the next resync would crash out because the resynd reads in the history table only. Now, when about to INSERT a record into the public schema during a resync, an explicit check is made to see if the record alread
y exists. If it does, the INSERT is instead redirected to the history schema.
* Cleaned up the fence agent metadata when displaying to a user, converting the shell codes to underline a string with square brackets instead. We also now replace newlines with <br /> tags. Lastly, to help fence_azure_arm's metadata description to display cleanly, a check is made to format the table correctly.
* Began work on the Striker menu for handling fence device management
Signed-off-by: Digimer <digimer@alteeve.ca>
5 years ago
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
|
|
|
|
modified_time => $modified_time,
|
|
|
|
age => $age,
|
|
|
|
maximum_age => $maximum_age,
|
|
|
|
}});
|
|
|
|
if ($age > $maximum_age)
|
|
|
|
{
|
|
|
|
$refresh = 1;
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, key => "log_0474"});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($refresh)
|
|
|
|
{
|
|
|
|
# This will store the new unified XML, when regenerating the output.
|
|
|
|
$anvil->data->{fences}{unified_xml} = "<\?xml version=\"1.0\" \?>\n\n";
|
|
|
|
$anvil->data->{fences}{unified_xml} .= "<unified>\n";
|
|
|
|
|
|
|
|
# Get a list of fence agents on this system.
|
|
|
|
get_fences_metadata($anvil);
|
|
|
|
|
|
|
|
$anvil->data->{fences}{unified_xml} .= "</unified>\n";
|
|
|
|
|
|
|
|
$anvil->Storage->write_file({
|
|
|
|
overwrite => 1,
|
|
|
|
backup => 0,
|
|
|
|
file => $anvil->data->{path}{data}{fences_unified_metadata},
|
|
|
|
body => $anvil->data->{fences}{unified_xml},
|
|
|
|
user => "apache",
|
|
|
|
group => "apache",
|
|
|
|
mode => "0666",
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not -e $anvil->data->{path}{data}{fences_unified_metadata})
|
|
|
|
{
|
|
|
|
# Failed...
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, priority => "err", key => "error_0113"});
|
|
|
|
$anvil->nice_exit({exit_code => 1});
|
|
|
|
}
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
# The walks through the found fence_X files and reads their metadata.
|
|
|
|
sub get_fences_metadata
|
|
|
|
{
|
|
|
|
my ($anvil) = @_;
|
|
|
|
|
|
|
|
my ($ethtool, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{ls}." ".$anvil->data->{path}{directories}{fence_agents}."/fence_*"});
|
|
|
|
foreach my $line (split/\n/, $ethtool)
|
|
|
|
{
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }});
|
|
|
|
|
|
|
|
# fence_pacemaker is out fence handler for DRBD 9 and it isn't a fence agent, skip it.
|
|
|
|
next if $line eq $anvil->data->{path}{directories}{fence_agents}."/fence_pacemaker";
|
|
|
|
|
|
|
|
# fence_virtd is the host daemon component of 'fence_virt', ignore it
|
|
|
|
next if $line eq $anvil->data->{path}{directories}{fence_agents}."/fence_virtd";
|
|
|
|
|
|
|
|
my $fence_agent_path = $line;
|
|
|
|
my $fence_agent_file = ($fence_agent_path =~ /^.*\/(.*)$/)[0];
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
|
|
|
|
fence_agent_path => $fence_agent_path,
|
|
|
|
fence_agent_file => $fence_agent_file,
|
|
|
|
}});
|
|
|
|
|
|
|
|
# Add it's metadata to the unify XML.
|
|
|
|
unify_metadata($anvil, $fence_agent_path, $fence_agent_file);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
# This does the actual call to collect the agent's metadata.
|
|
|
|
sub unify_metadata
|
|
|
|
{
|
|
|
|
my ($anvil, $fence_agent_path, $fence_agent_file) = @_;
|
|
|
|
|
|
|
|
my ($metadata, $return_code) = $anvil->System->call({debug => 3, shell_call => $fence_agent_path." -o metadata"});
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
|
|
|
|
metadata => $metadata,
|
|
|
|
return_code => $return_code,
|
|
|
|
}});
|
|
|
|
|
|
|
|
# Test that the metadata is valid XML.
|
|
|
|
local $@;
|
|
|
|
my $dom = eval { XML::LibXML->load_xml(string => $metadata); };
|
|
|
|
if ($@)
|
|
|
|
{
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "warning_0128", variables => {
|
|
|
|
agent => $fence_agent_file,
|
|
|
|
metadata => $metadata,
|
|
|
|
error => $@,
|
|
|
|
}});
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($metadata =~ /<\?xml version="1.0" \?>/gs)
|
|
|
|
{
|
|
|
|
$metadata =~ s/<\?xml version="1.0" \?>/<agent name="$fence_agent_file">/gs;
|
|
|
|
$anvil->data->{fences}{unified_xml} .= $metadata."\n";
|
|
|
|
$anvil->data->{fences}{unified_xml} .= "</agent>\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
# Bad, ignore it.
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1, priority => "alert", key => "warning_0028", variables => { agent => $fence_agent_file }});
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|