Merge pull request #78 from ClusterLabs/anvil-tools-dev

* Finished anvil-rename-server!
main
digimer-bot 4 years ago committed by GitHub
commit 4304fbe6dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Anvil/Tools.pm
  2. 163
      Anvil/Tools/Storage.pm
  3. 19
      share/words.xml
  4. 516
      tools/anvil-rename-server

@ -1161,7 +1161,9 @@ sub _set_paths
lspci => "/usr/sbin/lspci", lspci => "/usr/sbin/lspci",
lvchange => "/usr/sbin/lvchange", lvchange => "/usr/sbin/lvchange",
lvcreate => "/usr/sbin/lvcreate", lvcreate => "/usr/sbin/lvcreate",
lvdisplay => "/usr/sbin/lvdisplay",
lvremove => "/usr/sbin/lvremove", lvremove => "/usr/sbin/lvremove",
lvrename => "/usr/sbin/lvrename",
lvs => "/usr/sbin/lvs", lvs => "/usr/sbin/lvs",
lvscan => "/usr/sbin/lvscan", lvscan => "/usr/sbin/lvscan",
mailx => "/usr/bin/mailx", mailx => "/usr/bin/mailx",

@ -21,6 +21,7 @@ my $THIS_FILE = "Storage.pm";
# change_owner # change_owner
# check_md5sums # check_md5sums
# copy_file # copy_file
# delete_file
# find # find
# get_file_stats # get_file_stats
# get_storage_group_details # get_storage_group_details
@ -1007,6 +1008,7 @@ fi
return(1); return(1);
} }
=head2 copy_file =head2 copy_file
This copies a file, with a few additional checks like creating the target directory if it doesn't exist, aborting if the file has already been backed up before, etc. It can copy files on the local or a remote machine. This copies a file, with a few additional checks like creating the target directory if it doesn't exist, aborting if the file has already been backed up before, etc. It can copy files on the local or a remote machine.
@ -1257,6 +1259,167 @@ fi";
} }
=head3 delete_file
This deletes a file. Pretty much what it says on the tin. When run locally, it uses C<< unlink >>. When run on a remote machine, it uses C<< rm -f >>. As such, this will not delete directories, nor will it delete recursively.
# Example
$anvil->Storage->delete_file({file => "/some/file"});
On success, or if the file is already gone, C<< 0 >> is returned. On failure, C<< 1 >> is returned.
Parameters;
=head3 port (optional, default 22)
If C<< target >> is set, this is the TCP port number used to connect to the remote machine.
=head3 password (optional)
If C<< target >> is set, this is the password used to log into the remote system as the C<< remote_user >>. If it is not set, an attempt to connect without a password will be made (though this will usually fail).
=head3 file (required)
This is the file to delete.
=head3 target (optional)
If set, the file will be copied on the target machine. This must be either an IP address or a resolvable host name.
=head3 remote_user (optional, default root)
If C<< target >> is set, this is the user account that will be used when connecting to the remote system.
=cut
sub delete_file
{
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 => "Storage->delete_file()" }});
my $file = defined $parameter->{file} ? $parameter->{file} : "";
my $password = defined $parameter->{password} ? $parameter->{password} : "";
my $port = defined $parameter->{port} ? $parameter->{port} : 22;
my $remote_user = defined $parameter->{remote_user} ? $parameter->{remote_user} : "root";
my $target = defined $parameter->{target} ? $parameter->{target} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
file => $file,
password => $anvil->Log->is_secure($password),
port => $port,
remote_user => $remote_user,
target => $target,
}});
if (not $file)
{
# No source passed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Storage->delete_file()", parameter => "file" }});
return(1);
}
if ($anvil->Network->is_local({host => $target}))
{
# Deleting locally
if (not -e $file)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0615", variables => { file => $file }});
return(0);
}
unlink $file;
if (-e $file)
{
# Failed to delete.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0284", variables => { file => $file, error => $! }});
return(1);
}
else
{
# Success
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0616", variables => { file => $file }});
}
}
else
{
# Deleting on a remote system
my $proceed = 1;
my $shell_call = "
if [ -e '".$file."' ];
then
rm -f ".$file.";
if [ -e '".$file."' ];
then
echo 'delete_failed'
else
echo 'deleted'
fi;
else
echo 'not_found'
fi
";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0166", variables => {
shell_call => $shell_call,
target => $target,
remote_user => $remote_user,
}});
my ($output, $error, $return_code) = $anvil->Remote->call({
debug => $debug,
target => $target,
port => $port,
user => $remote_user,
password => $password,
remote_user => $remote_user,
shell_call => $shell_call,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
error => $error,
output => $output,
return_code => $return_code,
}});
if ($output eq "deleted")
{
# File existed and was deleted.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0618", variables => {
file => $file,
target => $target,
}});
}
elsif ($output eq "not_found")
{
# File is already gone.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0617", variables => {
file => $file,
target => $target,
}});
}
elsif ($output eq "delete_failed")
{
# Delete failed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0285", variables => {
file => $file,
target => $target,
}});
return(1);
}
else
{
# Huh? Lost connection?
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0286", variables => {
file => $file,
target => $target,
error => $error,
output => $output,
}});
return(1);
}
}
return(0);
}
=head2 find =head2 find
This searches for the given file on the system. It will search in the directories returned by C<< $anvil->Storage->search_directories() >>. This searches for the given file on the system. It will search in the directories returned by C<< $anvil->Storage->search_directories() >>.

@ -393,6 +393,14 @@ The attempt to start the servers appears to have failed. The return code '0' was
<key name="error_0279"><![CDATA[The new name for the server was not given. Please use '--new-name <name>'. The new name can not contain spaces.]]></key> <key name="error_0279"><![CDATA[The new name for the server was not given. Please use '--new-name <name>'. The new name can not contain spaces.]]></key>
<key name="error_0280"><![CDATA[The new name for the server: [#!variable!new_name!#] is not valid. The new name can not contain spaces.]]></key> <key name="error_0280"><![CDATA[The new name for the server: [#!variable!new_name!#] is not valid. The new name can not contain spaces.]]></key>
<key name="error_0281">The server wasn't found in the cluster configuration... Did a previous attempt to rename fail? Aborting.</key> <key name="error_0281">The server wasn't found in the cluster configuration... Did a previous attempt to rename fail? Aborting.</key>
<key name="error_0282">Failed to read the file: [#!variable!file!#] from the host: [#!variable!host!#].</key>
<key name="error_0283">Failed to rename the old LV: [#!variable!old_lv!#] to: [#!variable!new_lv!#] on the host: [#!variable!host_name!#]! Aborting.</key>
<key name="error_0284">Failed to delete the file: [#!variable!file!#]. The error, if any, was: [#!variable!error!#].</key>
<key name="error_0285">Failed to delete the file: [#!variable!file!#] on the host: [#!variable!target!#].</key>
<key name="error_0286">Failed to delete the file: [#!variable!file!#] on the host: [#!variable!target!#]. This might be a connection issue. The call's error was: [#!variable!error!#] output was: [#!variable!output!#].</key>
<key name="error_0287">Failed to write the file: [#!variable!file!#] on the host: [#!variable!target!#].</key>
<key name="error_0288">Failed to add the server: [#!variable!server_name!#] to the cluster. The return code from the pcs command was: [#!variable!return_code!#]. The output, if any, was: [#!variable!output!#].</key>
<key name="error_0289">The server: [#!variable!server!#] already exists on this Anvil!. Please use a different new name.</key>
<!-- Files templates --> <!-- Files templates -->
<!-- NOTE: Translating these files requires an understanding of which likes are translatable --> <!-- NOTE: Translating these files requires an understanding of which likes are translatable -->
@ -815,6 +823,13 @@ It should be provisioned in the next minute or two.</key>
<key name="job_0302">The DRBD resource behind the server is ready to be taken down.</key> <key name="job_0302">The DRBD resource behind the server is ready to be taken down.</key>
<key name="job_0303">Taking down the DRBD resource: [#!variable!resource!#] on the peer: [#!variable!peer!#] via the IP: [#!variable!ip!#].</key> <key name="job_0303">Taking down the DRBD resource: [#!variable!resource!#] on the peer: [#!variable!peer!#] via the IP: [#!variable!ip!#].</key>
<key name="job_0304">The DRBD resource is down.</key> <key name="job_0304">The DRBD resource is down.</key>
<key name="job_0305">On the host: [#!variable!host_name!#], we'll now rename the LV: [#!variable!old_lv!#] to: [#!variable!new_lv!#].</key>
<key name="job_0306">The new LV: [#!variable!new_lv!#] now exists on the host: [#!variable!host_name!#].</key>
<key name="job_0307">Successfully wrote the file: [#!variable!file!#] on the host: [#!variable!host_name!#].</key>
<key name="job_0308">Successfully added the new server name: [#!variable!server_name!#] to the cluster!</key>
<key name="job_0309">Verifying that the server name: [#!variable!server_name!#] is not defined.</key>
<key name="job_0310">Verifying that the server name: [#!variable!server_name!#] is not defined on: [#!variable!host_name!#].</key>
<key name="job_0311">Renamed the server name to: [#!variable!server_name!#] in the database.</key>
<!-- Log entries --> <!-- Log entries -->
<key name="log_0001">Starting: [#!variable!program!#].</key> <key name="log_0001">Starting: [#!variable!program!#].</key>
@ -1523,6 +1538,10 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="log_0612">We're not online yet. Waiting for 'in_ccm/crmd/join': [#!variable!in_ccm!#/#!variable!crmd!#/#!variable!join!#]. ('in_ccm' = consensus cluster member, communication layer. 'crmd' = cluster resource manager daemon is up, 'join' = allowed to host resources).</key> <key name="log_0612">We're not online yet. Waiting for 'in_ccm/crmd/join': [#!variable!in_ccm!#/#!variable!crmd!#/#!variable!join!#]. ('in_ccm' = consensus cluster member, communication layer. 'crmd' = cluster resource manager daemon is up, 'join' = allowed to host resources).</key>
<key name="log_0613">The file: [#!variable!file_name!#] is not recorded for the Anvil! [#!variable!anvil_name!#] yet. Registering it now as not sync'ed to this Anvil! system.</key> <key name="log_0613">The file: [#!variable!file_name!#] is not recorded for the Anvil! [#!variable!anvil_name!#] yet. Registering it now as not sync'ed to this Anvil! system.</key>
<key name="log_0614">Asking 'anvil-boot-server' to boot the servers now.</key> <key name="log_0614">Asking 'anvil-boot-server' to boot the servers now.</key>
<key name="log_0615">We were asked to delete the file: [#!variable!file!#], but it doesn't exist, so nothing to do.</key>
<key name="log_0616">The file: [#!variable!file!#] has been successfully removed.</key>
<key name="log_0617">We were asked to delete the file: [#!variable!file!#] on the target: [#!variable!target!#], but it doesn't exist, so nothing to do.</key>
<key name="log_0618">Successfully deleted the file: [#!variable!file!#] on the target: [#!variable!target!#].</key>
<!-- Messages for users (less technical than log entries), though sometimes used for logs, too. --> <!-- 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> <key name="message_0001">The host name: [#!variable!target!#] does not resolve to an IP address.</key>

@ -44,7 +44,7 @@ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list
}}); }});
$anvil->Database->connect(); $anvil->Database->connect();
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 3, secure => 0, key => "log_0132"});
if (not $anvil->data->{sys}{database}{connections}) if (not $anvil->data->{sys}{database}{connections})
{ {
# No databases, update the job, sleep for a bit and then exit. The daemon will pick it up and try # No databases, update the job, sleep for a bit and then exit. The daemon will pick it up and try
@ -164,11 +164,21 @@ if ($anvil->data->{switches}{'new-name'} =~ /\s/)
$anvil->nice_exit({exit_code => 1}); $anvil->nice_exit({exit_code => 1});
} }
# Make sure the new name isn't in use.
my $anvil_uuid = $anvil->data->{sys}{anvil_uuid};
my $new_server_name = $anvil->data->{switches}{'new-name'};
if (exists $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$new_server_name})
{
# Conflicting server name
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0289", variables => { server => $new_server_name }});
$anvil->Job->update_progress({progress => 100, message => "error_0289,!!server!".$new_server_name."!!"});
$anvil->nice_exit({exit_code => 1});
}
# We're going to need a server UUID. If we don't have it, find it from the current name. # We're going to need a server UUID. If we don't have it, find it from the current name.
if (not $anvil->data->{switches}{'server-uuid'}) if (not $anvil->data->{switches}{'server-uuid'})
{ {
# Convert the server name to a server_uuid. # Convert the server name to a server_uuid.
my $anvil_uuid = $anvil->data->{sys}{anvil_uuid};
my $server_name = $anvil->data->{switches}{'server'}; my $server_name = $anvil->data->{switches}{'server'};
if (not exists $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$server_name}) if (not exists $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$server_name})
{ {
@ -204,7 +214,7 @@ gather_server_data($anvil);
verify_server_is_off($anvil); verify_server_is_off($anvil);
# Now start renaming things. # Now start renaming things.
#rename_server($anvil); rename_server($anvil);
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0281"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0281"});
$anvil->Job->update_progress({progress => 100, message => "job_0281"}); $anvil->Job->update_progress({progress => 100, message => "job_0281"});
@ -218,6 +228,463 @@ $anvil->nice_exit({exit_code => 0});
# This does the actual rename. It removes the resource from the cluster, makes sure the DRBD resource is down # This does the actual rename. It removes the resource from the cluster, makes sure the DRBD resource is down
# on all machines, renames the XML definition file # on all machines, renames the XML definition file
sub rename_server
{
my ($anvil) = @_;
# Delete the server from pacemaker
my $old_server_name = $anvil->data->{switches}{'server'};
my $new_server_name = $anvil->data->{switches}{'new-name'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
old_server_name => $old_server_name,
new_server_name => $new_server_name,
}});
### NOTE: From this point on, failing out is a bad idea. Anything going wrong here wil mean the
### server could become inaccessible. As such, any errors need to be very verbose.
my $old_definition_file = $anvil->data->{path}{directories}{shared}{definitions}."/".$old_server_name.".xml";
my $new_definition_file = $anvil->data->{path}{directories}{shared}{definitions}."/".$new_server_name.".xml";
my $old_drbd_resource_file = $anvil->data->{path}{directories}{drbd_resources}."/".$old_server_name.".res";
my $new_drbd_resource_file = $anvil->data->{path}{directories}{drbd_resources}."/".$new_server_name.".res";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
old_definition_file => $old_definition_file,
new_definition_file => $new_definition_file,
old_drbd_resource_file => $old_drbd_resource_file,
new_drbd_resource_file => $new_drbd_resource_file,
}});
my $progress = 40;
# Log into the peer(s) and rename the LV, the rename our own LV.
foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{rename_server}{host}})
{
my $peer_ip = $anvil->data->{rename_server}{host}{$host_name}{is_peer} ? $anvil->data->{rename_server}{host}{$host_name}{use_ip} : "";
my $password = $anvil->data->{rename_server}{host}{$host_name}{is_peer} ? $anvil->data->{rename_server}{host}{$host_name}{password} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
peer_ip => $peer_ip,
password => $anvil->Log->is_secure($password),
}});
# Read the old DRBD resource file.
my $old_drbd_resource_body = $anvil->Storage->read_file({
cache => 0,
file => $old_drbd_resource_file,
force_read => 1,
password => $password,
target => $peer_ip,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_drbd_resource_body => $old_drbd_resource_body }});
if ($old_drbd_resource_body eq "!!error!!")
{
# Failed to read the file. Could we have already written the file?
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0282", variables => {
file => $old_drbd_resource_file,
host => $host_name,
}});
$progress += 3 if $progress < 90;
$anvil->Job->update_progress({progress => $progress, message => "error_0282,!!file!".$old_drbd_resource_file."!!,!!host!".$host_name."!!"});
$old_drbd_resource_body = $anvil->Storage->read_file({
cache => 0,
file => $new_drbd_resource_file,
force_read => 1,
password => $password,
target => $peer_ip,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_drbd_resource_body => $old_drbd_resource_body }});
if ($old_drbd_resource_body eq "!!error!!")
{
# No luck there, either.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0282", variables => {
file => $new_drbd_resource_file,
host => $host_name,
}});
$anvil->Job->update_progress({progress => 100, message => "error_0282,!!file!".$new_drbd_resource_file."!!,!!host!".$host_name."!!"});
$anvil->nice_exit({exit_code => 1});
}
}
# Read the old definition file.
my $old_definition_body = $anvil->Storage->read_file({
cache => 0,
file => $old_definition_file,
force_read => 1,
password => $password,
target => $peer_ip,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_definition_body => $old_definition_body }});
if ($old_definition_body eq "!!error!!")
{
# Failed to read the file. Could we have already written the file?
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0282", variables => {
file => $old_definition_file,
host => $host_name,
}});
$progress += 3 if $progress < 90;
$anvil->Job->update_progress({progress => $progress, message => "error_0282,!!file!".$old_definition_file."!!,!!host!".$host_name."!!"});
$old_definition_body = $anvil->Storage->read_file({
cache => 0,
file => $new_definition_file,
force_read => 1,
password => $password,
target => $peer_ip,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_definition_body => $old_definition_body }});
if ($old_definition_body eq "!!error!!")
{
# No luck there, either.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0282", variables => {
file => $new_definition_file,
host => $host_name,
}});
$anvil->Job->update_progress({progress => 100, message => "error_0282,!!file!".$new_definition_file."!!,!!host!".$host_name."!!"});
$anvil->nice_exit({exit_code => 1});
}
}
# Loop through the volumes and update the new definition and resource file bodies.
my $new_drbd_resource_body = $old_drbd_resource_body;
my $new_definition_body = $old_definition_body;
foreach my $volume (sort {$a cmp $b} keys %{$anvil->data->{rename_server}{host}{$host_name}{volume}})
{
my $old_device_path = $anvil->data->{rename_server}{host}{$host_name}{volume}{$volume}{old_device_path};
my $new_device_path = $anvil->data->{rename_server}{host}{$host_name}{volume}{$volume}{new_device_path};
my $old_backing_disk = $anvil->data->{rename_server}{host}{$host_name}{volume}{$volume}{old_backing_disk};
my $new_backing_disk = $anvil->data->{rename_server}{host}{$host_name}{volume}{$volume}{new_backing_disk};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
old_device_path => $old_device_path,
new_device_path => $new_device_path,
old_backing_disk => $old_backing_disk,
new_backing_disk => $new_backing_disk,
}});
$new_drbd_resource_body =~ s/$old_device_path/$new_device_path/sg;
$new_drbd_resource_body =~ s/$old_backing_disk/$new_backing_disk/sg;
$new_drbd_resource_body =~ s/$old_server_name/$new_server_name/sg;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drbd_resource_body => $new_drbd_resource_body }});
$new_definition_body =~ s/$old_device_path/$new_device_path/sg;
$new_definition_body =~ s/$old_backing_disk/$new_backing_disk/sg;
$new_definition_body =~ s/$old_server_name/$new_server_name/sg;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_definition_body => $new_definition_body }});
# Rename the LV, if needed.
my $shell_call = $anvil->data->{path}{exe}{lvdisplay}." ".$old_backing_disk;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my $output = "";
my $return_code = "";
if ($anvil->data->{rename_server}{host}{$host_name}{is_peer})
{
# Remote call
($output, my $error, $return_code) = $anvil->Remote->call({
debug => 2,
shell_call => $shell_call,
target => $peer_ip,
password => $password,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
error => $error,
output => $output,
return_code => $return_code,
}});
}
else
{
($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
}
if (not $return_code)
{
# Old LV exists, rename
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0305", variables => {
host_name => $host_name,
old_lv => $old_backing_disk,
new_lv => $new_backing_disk,
}});
$progress += 3 if $progress < 90;
$anvil->Job->update_progress({progress => $progress, message => "job_0305,!!host_name!".$host_name."!!,!!old_lv!".$old_backing_disk."!!,!!new_lv!".$new_backing_disk."!!"});
my $shell_call = $anvil->data->{path}{exe}{lvrename}." --autobackup y --yes ".$old_backing_disk." ".$new_backing_disk;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
# We don't verify the LV create here, we'll check it below.
if ($anvil->data->{rename_server}{host}{$host_name}{is_peer})
{
# Remote call
my ($output, $error, $return_code) = $anvil->Remote->call({
debug => 2,
shell_call => $shell_call,
target => $peer_ip,
password => $password,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
error => $error,
output => $output,
return_code => $return_code,
}});
}
else
{
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
}
}
# Verify the new LV exists.
$output = "";
$return_code = "";
$shell_call = $anvil->data->{path}{exe}{lvdisplay}." ".$new_backing_disk;
if ($anvil->data->{rename_server}{host}{$host_name}{is_peer})
{
# Remote call
($output, my $error, $return_code) = $anvil->Remote->call({
debug => 2,
shell_call => $shell_call,
target => $peer_ip,
password => $password,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
error => $error,
output => $output,
return_code => $return_code,
}});
}
else
{
($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
}
if ($return_code)
{
# Something went wrong.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0283", variables => {
old_lv => $old_backing_disk,
new_lv => $new_backing_disk,
host_name => $host_name,
}});
$anvil->Job->update_progress({progress => 100, message => "error_0283,!!host_name!".$host_name."!!,!!old_lv!".$old_backing_disk."!!,!!new_lv!".$new_backing_disk."!!"});
$anvil->nice_exit({exit_code => 1});
}
else
{
# Success
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0306", variables => {
host_name => $host_name,
new_lv => $new_backing_disk,
}});
$progress += 3 if $progress < 90;
$anvil->Job->update_progress({progress => $progress, message => "job_0306,!!host_name!".$host_name."!!,!!new_lv!".$new_backing_disk."!!"});
}
}
# Write out the new DRBD resource files.
my ($problem) = $anvil->Storage->write_file({
debug => 2,
backup => 1,
overwrite => 1,
body => $new_drbd_resource_body,
file => $new_drbd_resource_file,
group => "root",
user => "root",
mode => "0644",
password => $password,
target => $peer_ip,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
if ($problem)
{
# Failed. Details of why will already be in the logs.
$anvil->Job->update_progress({progress => 100, message => "error_0287,!!target!".$host_name."!!,!!file!".$new_drbd_resource_file."!!"});
$anvil->nice_exit({exit_code => 1});
}
else
{
# Success
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0307", variables => {
host_name => $host_name,
file => $new_drbd_resource_file,
}});
$progress += 3 if $progress < 90;
$anvil->Job->update_progress({progress => $progress, message => "job_0307,!!host_name!".$host_name."!!,!!file!".$new_drbd_resource_file."!!"});
# Delete the old file.
my ($problem) = $anvil->Storage->delete_file({
debug => 2,
file => $old_drbd_resource_file,
password => $password,
target => $peer_ip,
});
if ($problem)
{
# Details of why will be in the logs.
$anvil->Job->update_progress({progress => 100, message => "error_0285,!!target!".$host_name."!!,!!file!".$old_drbd_resource_file."!!"});
$anvil->nice_exit({exit_code => 1});
}
}
# Write out the new definition files.
undef $problem;
($problem) = $anvil->Storage->write_file({
debug => 2,
backup => 1,
overwrite => 1,
body => $new_definition_body,
file => $new_definition_file,
group => "root",
user => "root",
mode => "0644",
password => $password,
target => $peer_ip,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
if ($problem)
{
# Failed. Details of why will already be in the logs.
$anvil->Job->update_progress({progress => 100, message => "error_0287,!!target!".$host_name."!!,!!file!".$new_definition_file."!!"});
$anvil->nice_exit({exit_code => 1});
}
else
{
# Success
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0307", variables => {
host_name => $host_name,
file => $new_definition_file,
}});
$progress += 3 if $progress < 90;
$anvil->Job->update_progress({progress => $progress, message => "job_0307,!!host_name!".$host_name."!!,!!file!".$new_definition_file."!!"});
# Delete the old file.
my ($problem) = $anvil->Storage->delete_file({
debug => 2,
file => $old_definition_file,
password => $password,
target => $peer_ip,
});
if ($problem)
{
# Details of why will be in the logs.
$anvil->Job->update_progress({progress => 100, message => "error_0285,!!target!".$host_name."!!,!!file!".$old_definition_file."!!"});
$anvil->nice_exit({exit_code => 1});
}
}
# Make a 'virsh undefine <server>' just in case the old name is still defined. We don't care
# if this succeeds or fails as the server should not be defined anyway.
my $shell_call = $anvil->data->{path}{exe}{virsh}." undefine ".$old_server_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my $output = "";
my $return_code = "";
if ($anvil->data->{rename_server}{host}{$host_name}{is_peer})
{
# Remote call
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0310", variables => {
host_name => $host_name,
server_name => $old_server_name,
}});
$progress += 3 if $progress < 90;
$anvil->Job->update_progress({progress => $progress, message => "job_0310,!!host_name!".$host_name."!!,!!server_name!".$old_server_name."!!"});
($output, my $error, $return_code) = $anvil->Remote->call({
debug => 2,
shell_call => $shell_call,
target => $peer_ip,
password => $password,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
error => $error,
output => $output,
return_code => $return_code,
}});
}
else
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0309", variables => { server_name => $old_server_name }});
$progress += 3 if $progress < 90;
$anvil->Job->update_progress({progress => $progress, message => "job_0309,!!server_name!".$old_server_name."!!"});
($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
}
}
# Delete the old server from pacemaker.
my ($output, $return_code) = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{pcs}." resource delete ".$old_server_name});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
if (not $return_code)
{
# Success!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0587", variables => { server_name => $old_server_name }});
$anvil->Job->update_progress({progress => 90, message => "job_0304,!!server_name!".$old_server_name."!!"});
}
else
{
# Unexpected return code, bail out.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0226", variables => {
server_name => $old_server_name,
return_code => $return_code,
output => $output,
}});
$anvil->Job->update_progress({progress => 100, message => "job_0304,!!server_name!".$old_server_name."!!,!!return_code!".$return_code."!!,!!output!".$output."!!"});
$anvil->nice_exit({exit_code => 1});
}
# Add the server back to pacemaker
my $resource_command = $anvil->data->{path}{exe}{pcs}." resource create ".$new_server_name." ocf:alteeve:server name=\"".$new_server_name."\" meta allow-migrate=\"true\" target-role=\"stopped\" op monitor interval=\"60\" start timeout=\"300\" on-fail=\"block\" stop timeout=\"86400\" on-fail=\"block\" migrate_to timeout=\"86400\"";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { resource_command => $resource_command }});
$output = "";
$return_code = "";
($output, $return_code) = $anvil->System->call({shell_call => $resource_command});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
if ($return_code)
{
# Failed.
$anvil->Job->update_progress({progress => 100, message => "error_0288,!!server_name!".$new_server_name."!!,!!return_code!".$return_code."!!,!!output!".$output."!!"});
$anvil->nice_exit({exit_code => 1});
}
else
{
# Success
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0308", variables => { server_name => $new_server_name }});
$anvil->Job->update_progress({progress => 95, message => "job_0308,!!server_name!".$old_server_name."!!"});
}
# Rename the server in the database.
my $query = "
UPDATE
servers
SET
server_name = ".$anvil->Database->quote($new_server_name).",
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})."
WHERE
server_uuid = ".$anvil->Database->quote($anvil->data->{switches}{'server-uuid'})."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
# Done!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0311", variables => { server_name => $new_server_name }});
$anvil->Job->update_progress({progress => 99, message => "job_0311,!!server_name!".$old_server_name."!!"});
return(0);
}
# Calls virsh locally and on peer(s) to ensure that the server is not running. # Calls virsh locally and on peer(s) to ensure that the server is not running.
sub verify_server_is_off sub verify_server_is_off
@ -274,15 +741,15 @@ sub verify_server_is_off
foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{rename_server}{host}}) foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{rename_server}{host}})
{ {
next if $anvil->data->{rename_server}{host}{$host_name}{is_peer}; next if $anvil->data->{rename_server}{host}{$host_name}{is_peer};
my $peers_ip = $anvil->data->{rename_server}{host}{$host_name}{use_ip}; my $peer_ip = $anvil->data->{rename_server}{host}{$host_name}{use_ip};
my $password = $anvil->data->{rename_server}{host}{$host_name}{password}; my $password = $anvil->data->{rename_server}{host}{$host_name}{password};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
peers_ip => $peers_ip, peer_ip => $peer_ip,
password => $anvil->Log->is_secure($password), password => $anvil->Log->is_secure($password),
}}); }});
$anvil->Server->find({ $anvil->Server->find({
refresh => 0, refresh => 0,
target => $peers_ip, target => $peer_ip,
password => $password, password => $password,
}); });
} }
@ -317,15 +784,15 @@ sub verify_server_is_off
foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{rename_server}{host}}) foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{rename_server}{host}})
{ {
next if not $anvil->data->{rename_server}{host}{$host_name}{is_peer}; next if not $anvil->data->{rename_server}{host}{$host_name}{is_peer};
my $peers_ip = $anvil->data->{rename_server}{host}{$host_name}{use_ip}; my $peer_ip = $anvil->data->{rename_server}{host}{$host_name}{use_ip};
my $password = $anvil->data->{rename_server}{host}{$host_name}{password}; my $password = $anvil->data->{rename_server}{host}{$host_name}{password};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
peers_ip => $peers_ip, peer_ip => $peer_ip,
password => $anvil->Log->is_secure($password), password => $anvil->Log->is_secure($password),
}}); }});
$anvil->DRBD->get_status({ $anvil->DRBD->get_status({
debug => 2, debug => 2,
target => $peers_ip, target => $peer_ip,
password => $password, password => $password,
}); });
} }
@ -381,23 +848,23 @@ sub verify_server_is_off
foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{rename_server}{host}}) foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{rename_server}{host}})
{ {
next if not $anvil->data->{rename_server}{host}{$host_name}{is_peer}; next if not $anvil->data->{rename_server}{host}{$host_name}{is_peer};
my $peers_ip = $anvil->data->{rename_server}{host}{$host_name}{use_ip}; my $peer_ip = $anvil->data->{rename_server}{host}{$host_name}{use_ip};
my $password = $anvil->data->{rename_server}{host}{$host_name}{password}; my $password = $anvil->data->{rename_server}{host}{$host_name}{password};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
peers_ip => $peers_ip, peer_ip => $peer_ip,
password => $anvil->Log->is_secure($password), password => $anvil->Log->is_secure($password),
}}); }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0303", variables => { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0303", variables => {
peer => $host_name, peer => $host_name,
resource => $old_server_name, resource => $old_server_name,
ip => $peers_ip, ip => $peer_ip,
}}); }});
$anvil->Job->update_progress({progress => 35, message => "job_0303,!!peer!".$host_name."!!,!!resource!".$old_server_name."!!,!!ip!".$peers_ip."!!"}); $anvil->Job->update_progress({progress => 35, message => "job_0303,!!peer!".$host_name."!!,!!resource!".$old_server_name."!!,!!ip!".$peer_ip."!!"});
$anvil->DRBD->manage_resource({ $anvil->DRBD->manage_resource({
debug => 2, debug => 2,
resource => $old_server_name, resource => $old_server_name,
task => "down", task => "down",
target => $peers_ip, target => $peer_ip,
password => $password, password => $password,
}); });
} }
@ -422,17 +889,6 @@ sub gather_server_data
my $old_server_name = $anvil->data->{switches}{'server'}; my $old_server_name = $anvil->data->{switches}{'server'};
my $new_server_name = $anvil->data->{switches}{'new-name'}; my $new_server_name = $anvil->data->{switches}{'new-name'};
$anvil->data->{rename_server}{old_definition_file} = $anvil->data->{path}{directories}{shared}{definitions}."/".$old_server_name.".xml";
$anvil->data->{rename_server}{new_definition_file} = $anvil->data->{path}{directories}{shared}{definitions}."/".$new_server_name.".xml";
$anvil->data->{rename_server}{old_drbd_resource_file} = $anvil->data->{path}{directories}{drbd_resources}."/".$old_server_name.".res";
$anvil->data->{rename_server}{new_drbd_resource_file} = $anvil->data->{path}{directories}{drbd_resources}."/".$new_server_name.".res";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"rename_server::old_definition_file" => $anvil->data->{rename_server}{old_definition_file},
"rename_server::new_definition_file" => $anvil->data->{rename_server}{new_definition_file},
"rename_server::old_drbd_resource_file" => $anvil->data->{rename_server}{old_drbd_resource_file},
"rename_server::new_drbd_resource_file" => $anvil->data->{rename_server}{new_drbd_resource_file},
}});
# Parse the DRBD resource file to see if we have a DR target for this server. # Parse the DRBD resource file to see if we have a DR target for this server.
$anvil->DRBD->gather_data({debug => 2}); $anvil->DRBD->gather_data({debug => 2});
$anvil->Database->get_hosts(); $anvil->Database->get_hosts();
@ -509,7 +965,7 @@ sub gather_server_data
host_uuid => $host_uuid, host_uuid => $host_uuid,
}); });
my $peers_ip = ""; my $peer_ip = "";
my ($match) = $anvil->Network->find_matches({ my ($match) = $anvil->Network->find_matches({
debug => 2, debug => 2,
first => $local_drbd_node_name, first => $local_drbd_node_name,
@ -522,17 +978,17 @@ sub gather_server_data
# Yup! # Yup!
foreach my $interface (sort {$a cmp $b} keys %{$match->{$host_name}}) foreach my $interface (sort {$a cmp $b} keys %{$match->{$host_name}})
{ {
my $peers_ip = $match->{$host_name}{$interface}{ip}; my $peer_ip = $match->{$host_name}{$interface}{ip};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peers_ip => $peers_ip }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer_ip => $peer_ip }});
$access = $anvil->Remote->test_access({ $access = $anvil->Remote->test_access({
target => $peers_ip, target => $peer_ip,
password => $password, password => $password,
}); });
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { access => $access }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { access => $access }});
if ($access) if ($access)
{ {
$anvil->data->{rename_server}{host}{$host_name}{use_ip} = $peers_ip; $anvil->data->{rename_server}{host}{$host_name}{use_ip} = $peer_ip;
$anvil->data->{rename_server}{host}{$host_name}{password} = $password; $anvil->data->{rename_server}{host}{$host_name}{password} = $password;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"rename_server::host::${host_name}::use_ip" => $anvil->data->{rename_server}{host}{$host_name}{use_ip}, "rename_server::host::${host_name}::use_ip" => $anvil->data->{rename_server}{host}{$host_name}{use_ip},

Loading…
Cancel
Save