Skip to content

Commit b3fbba8

Browse files
authored
Merge pull request #633 from ClusterLabs/stonith-fixes
Stonith fixes
2 parents 083c262 + 259febe commit b3fbba8

File tree

8 files changed

+287
-271
lines changed

8 files changed

+287
-271
lines changed

Anvil/Tools/Cluster.pm

Lines changed: 78 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,13 +1127,11 @@ sub check_stonith_config
11271127

11281128
### NOTE: This was copied from 'anvil-join-anvil' and modified.
11291129
# Now I know what I have, lets see what I should have.
1130-
my $host_name = $anvil->Get->host_name;
1131-
my $new_password = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password};
1132-
my $escaped_password = shell_quote($new_password);
1130+
my $host_name = $anvil->Get->host_name;
1131+
my $new_password = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password};
11331132
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
1134-
host_name => $host_name,
1135-
new_password => $anvil->Log->is_secure($new_password),
1136-
escaped_password => $anvil->Log->is_secure($escaped_password),
1133+
host_name => $host_name,
1134+
new_password => $anvil->Log->is_secure($new_password),
11371135
}});
11381136

11391137
$anvil->data->{machine}{node1}{host_name} = "";
@@ -1184,9 +1182,6 @@ sub check_stonith_config
11841182
# This will store the fence level order. If something changes
11851183
$fence_order->{$node_name} = [];
11861184

1187-
# This will switch to '1' if something changed, triggering a reconfig of the fencing levels.
1188-
$something_changed->{$node_name} = 0;
1189-
11901185
# Does this stonith method already exist?
11911186
my $create_entry = 0;
11921187
my $delete_old = 0;
@@ -1352,9 +1347,6 @@ sub check_stonith_config
13521347
}});
13531348
return(1);
13541349
}
1355-
1356-
$something_changed->{$node_name} = 1;
1357-
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }});
13581350
}
13591351
if ($create_entry)
13601352
{
@@ -1379,12 +1371,8 @@ sub check_stonith_config
13791371
}});
13801372
return(1);
13811373
}
1382-
1383-
$something_changed->{$node_name} = 1;
1384-
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }});
13851374
}
13861375

1387-
13881376
### Now any other fence devices.
13891377
foreach my $device (sort {$a cmp $b} keys %{$anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$node}{fence}})
13901378
{
@@ -1592,9 +1580,6 @@ sub check_stonith_config
15921580
}});
15931581
return(1);
15941582
}
1595-
1596-
$something_changed->{$node_name} = 1 if not $delete_old;
1597-
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }});
15981583
}
15991584
if (($create_entry) && (not $dont_create))
16001585
{
@@ -1619,9 +1604,6 @@ sub check_stonith_config
16191604
}});
16201605
return(1);
16211606
}
1622-
1623-
$something_changed->{$node_name} = 1 if not $delete_old;
1624-
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }});
16251607
}
16261608
}
16271609

@@ -1664,78 +1646,109 @@ sub check_stonith_config
16641646
# Setup fence levels.
16651647
foreach my $node_name (sort {$a cmp $b} keys %{$fence_order})
16661648
{
1667-
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }});
1668-
if ($something_changed->{$node_name})
1649+
# Update our view of the cluster.
1650+
my $problem = $anvil->Cluster->parse_cib({debug => 2});
1651+
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }});
1652+
1653+
# Check our current levels and update if needed.
1654+
my $index = 1;
1655+
foreach my $fence_agent (@{$fence_order->{$node_name}})
16691656
{
1670-
# Update our view of the cluster.
1671-
my $problem = $anvil->Cluster->parse_cib({debug => 2});
1672-
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }});
1657+
my $key_name = "fl-".$node_name."-".$index;
1658+
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
1659+
fence_agent => $fence_agent,
1660+
key_name => $key_name,
1661+
}});
16731662

1674-
# Delete any existing fence levels
1675-
if (exists $anvil->data->{cib}{parsed}{data}{node}{$node_name})
1663+
# Does the fence level exist, and is it for the right fence agent?
1664+
if (exists $anvil->data->{cib}{parsed}{configuration}{'fencing-topology'}{'fencing-level'}{$key_name})
16761665
{
1677-
foreach my $index (sort {$a cmp $b} keys %{$anvil->data->{cib}{parsed}{data}{node}{$node_name}{fencing}{order}})
1666+
# If there's multiple fence devices in this method, crop off the extra ones.
1667+
my $old_fence_name = $anvil->data->{cib}{parsed}{configuration}{'fencing-topology'}{'fencing-level'}{$key_name}{devices};
1668+
$old_fence_name =~ s/,.*//;
1669+
my $old_fence_agent = exists $anvil->data->{crm_mon}{parsed}{'pacemaker-result'}{resources}{stonith}{$old_fence_name} ?
1670+
$anvil->data->{crm_mon}{parsed}{'pacemaker-result'}{resources}{stonith}{$old_fence_name}{variables}{resource_agent} : "";
1671+
$old_fence_agent =~ s/^stonith://;
1672+
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
1673+
old_fence_name => $old_fence_name,
1674+
old_fence_agent => $old_fence_agent,
1675+
}});
1676+
if ($fence_agent eq $old_fence_agent)
16781677
{
1679-
# pcs stonith level delete <index> <target>
1678+
# The fence level exists and it's the same fence agent, nothing to do.
1679+
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0848"});
1680+
$index++;
1681+
next;
1682+
}
1683+
else
1684+
{
1685+
# The fence level exists, but it's for a different fence agent, deleting it
1686+
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0849", variables => {
1687+
old_fence_name => $old_fence_name,
1688+
old_fence_agent => $old_fence_agent,
1689+
}});
1690+
16801691
my $shell_call = $anvil->data->{path}{exe}{pcs}." stonith level delete ".$index." ".$node_name;
16811692
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }});
16821693

1683-
my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
1694+
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $shell_call});
16841695
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
16851696
output => $output,
16861697
return_code => $return_code,
16871698
}});
16881699
if ($return_code)
16891700
{
1690-
# Something went wrong.
1701+
# Something went wrong. We'll not exit, but this is probably not going to end well.
16911702
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0138", variables => {
16921703
shell_call => $shell_call,
16931704
output => $output,
16941705
return_code => $return_code,
16951706
}});
1696-
return(1);
16971707
}
16981708
}
16991709
}
1710+
else
1711+
{
1712+
# The fence level doesn't exist.
1713+
}
17001714

1701-
# Create the new fence levels
1702-
my $i = 1;
1703-
foreach my $fence_agent (@{$fence_order->{$node_name}})
1715+
# Create the fence level now.
1716+
my $devices = "";
1717+
foreach my $device (sort {$a cmp $b} @{$fence_devices->{$node_name}{$fence_agent}})
17041718
{
1705-
my $devices = "";
1706-
foreach my $device (sort {$a cmp $b} @{$fence_devices->{$node_name}{$fence_agent}})
1707-
{
1708-
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { device => $device }});
1709-
$devices .= $device.",";
1710-
}
1711-
$devices =~ s/,$//;
1712-
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { devices => $devices }});
1713-
1714-
my $shell_call = $anvil->data->{path}{exe}{pcs}." stonith level add ".$i." ".$node_name." ".$devices;
1715-
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }});
1716-
1717-
my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
1718-
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
1719-
output => $output,
1719+
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { device => $device }});
1720+
$devices .= $device.",";
1721+
}
1722+
$devices =~ s/,$//;
1723+
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0850", variables => {
1724+
key_name => $key_name,
1725+
fence_agent => $fence_agent,
1726+
devices => $devices,
1727+
}});
1728+
1729+
my $shell_call = $anvil->data->{path}{exe}{pcs}." stonith level add ".$index." ".$node_name." ".$devices;
1730+
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }});
1731+
1732+
my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call});
1733+
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
1734+
output => $output,
1735+
return_code => $return_code,
1736+
}});
1737+
if ($return_code)
1738+
{
1739+
# Something went wrong.
1740+
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0138", variables => {
1741+
shell_call => $shell_call,
1742+
output => $output,
17201743
return_code => $return_code,
17211744
}});
1722-
if ($return_code)
1723-
{
1724-
# Something went wrong.
1725-
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0138", variables => {
1726-
shell_call => $shell_call,
1727-
output => $output,
1728-
return_code => $return_code,
1729-
}});
1730-
return(1);
1731-
}
1732-
1733-
$i++;
1745+
return(1);
17341746
}
1747+
1748+
$index++;
17351749
}
17361750
}
17371751

1738-
17391752
return(0);
17401753
}
17411754

Anvil/Tools/Convert.pm

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ my $THIS_FILE = "Convert.pm";
2121
# format_mmddyy_to_yymmdd
2222
# host_name_to_ip
2323
# human_readable_to_bytes
24+
# to_ipmi_password
2425
# round
2526
# time
2627

@@ -1190,6 +1191,87 @@ sub human_readable_to_bytes
11901191
}
11911192

11921193

1194+
=head2 to_ipmi_password
1195+
1196+
This takes a password (a string) and returns it in a format suitable for use by most any IPMI BMC. More specifically, spaces are removed, special characters are removed, and it is shortened to 16 characters.
1197+
1198+
If no password is given, a password will be generated.
1199+
1200+
parameters;
1201+
1202+
=head3 password (required)
1203+
1204+
This is the string to convert into an IPMI compatible password.
1205+
1206+
=cut
1207+
sub to_ipmi_password
1208+
{
1209+
my $self = shift;
1210+
my $parameter = shift;
1211+
my $anvil = $self->parent;
1212+
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
1213+
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Convert->to_ipmi_password()" }});
1214+
1215+
# Setup my numbers.
1216+
my $password = $parameter->{password} ? $parameter->{password} : 0;
1217+
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
1218+
password => $anvil->Log->is_secure($password),,
1219+
}});
1220+
1221+
if (not $password)
1222+
{
1223+
$password = $anvil->Get->uuid({debug => $debug});
1224+
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
1225+
password => $anvil->Log->is_secure($password),,
1226+
}});
1227+
}
1228+
1229+
my $ipmi_password = $password;
1230+
$ipmi_password =~ s/ //g;
1231+
$ipmi_password =~ s/'//g;
1232+
$ipmi_password =~ s/"//g;
1233+
$ipmi_password =~ s/!//g;
1234+
$ipmi_password =~ s/#//g;
1235+
$ipmi_password =~ s/\$//g;
1236+
$ipmi_password =~ s/&//g;
1237+
$ipmi_password =~ s/\*//g;
1238+
$ipmi_password =~ s/://g;
1239+
$ipmi_password =~ s/;//g;
1240+
$ipmi_password =~ s/,//g;
1241+
$ipmi_password =~ s/`//g;
1242+
$ipmi_password =~ s/\|//g;
1243+
$ipmi_password =~ s/\^//g;
1244+
$ipmi_password =~ s/\?//g;
1245+
$ipmi_password =~ s/\\//g;
1246+
$ipmi_password =~ s/\(//g;
1247+
$ipmi_password =~ s/\)//g;
1248+
$ipmi_password =~ s/{//g;
1249+
$ipmi_password =~ s/}//g;
1250+
$ipmi_password =~ s/<//g;
1251+
$ipmi_password =~ s/>//g;
1252+
$ipmi_password =~ s/\[//g;
1253+
$ipmi_password =~ s/\]//g;
1254+
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
1255+
ipmi_password => $anvil->Log->is_secure($ipmi_password),
1256+
}});
1257+
1258+
# If the length of the password is too short, pad / create it.
1259+
if (length($ipmi_password) < 7)
1260+
{
1261+
$ipmi_password .= "-".$anvil->Get->uuid({debug => $debug, short => 1});
1262+
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
1263+
ipmi_password => $anvil->Log->is_secure($ipmi_password),
1264+
}});
1265+
}
1266+
1267+
$ipmi_password = substr($ipmi_password, 0, 16);
1268+
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
1269+
ipmi_password => $anvil->Log->is_secure($ipmi_password),
1270+
}});
1271+
1272+
return($ipmi_password);
1273+
}
1274+
11931275
=head2 round
11941276
11951277
This takes a number and rounds it to a given number of places after the decimal (defaulting to an even integer). This does financial-type rounding.

Anvil/Tools/Get.pm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use JSON;
1212
use Net::Netmask;
1313
use Text::Diff;
1414
use UUID::Tiny qw(:std);
15+
use String::ShellQuote;
1516

1617
our $VERSION = "3.0.0";
1718
my $THIS_FILE = "Get.pm";

0 commit comments

Comments
 (0)