* Moved Server->_parse_definition() to -> parse_definition() to make it a publid method.

* Began (but haven't finished) Database->insert_or_update_servers().
* Created Storage->get_file_stats() to collect the (l)stat information for a file.
* Got more work done on scan-server.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 4 years ago
parent e240a32a19
commit e6e4c7d530
  1. 42
      Anvil/Tools/Cluster.pm
  2. 305
      Anvil/Tools/Database.pm
  3. 461
      Anvil/Tools/Server.pm
  4. 131
      Anvil/Tools/Storage.pm
  5. 90
      scancore-agents/scan-server/scan-server
  6. 1
      scancore-agents/scan-server/scan-server.xml
  7. 16
      share/anvil.sql
  8. 5
      share/words.xml
  9. 8
      tools/test.pl

@ -493,10 +493,12 @@ sub migrate_server
# Is the server already running? If so, where?
my $status = $anvil->data->{cib}{parsed}{data}{server}{$server}{status};
my $host = $anvil->data->{cib}{parsed}{data}{server}{$server}{host};
my $host = $anvil->data->{cib}{parsed}{data}{server}{$server}{host_name};
my $role = $anvil->data->{cib}{parsed}{data}{server}{$server}{role};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
status => $status,
host => $host,
role => $role,
}});
if ($status eq "off")
@ -517,11 +519,28 @@ sub migrate_server
}});
return(0);
}
elsif (lc($role) eq "stopping")
{
# It's stopping, don't migrate.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "warning_0064", variables => {
server => $server,
requested_node => $node,
}});
return('!!error!!');
}
elsif (lc($role) eq "migating")
{
# It's stopping, don't migrate.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "warning_0065", variables => {
server => $server,
requested_node => $node,
}});
return('!!error!!');
}
elsif ($status ne "running")
{
# The server is in an unknown state.
# It's in an unknown state, abort.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "warning_0060", variables => {
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "warning_0061", variables => {
server => $server,
current_host => $host,
current_state => $status,
@ -1117,18 +1136,15 @@ sub parse_cib
my $managed = $anvil->data->{crm_mon}{parsed}{'pacemaker-result'}{resources}{resource}{$server}{variables}{managed} eq "true" ? 1 : 0;
my $orphaned = $anvil->data->{crm_mon}{parsed}{'pacemaker-result'}{resources}{resource}{$server}{variables}{orphaned} eq "true" ? 1 : 0;
my $status = lc($role);
if ((lc($role) eq "started") or (lc($role) eq "starting"))
if ($role)
{
$status = "on";
### Known roles;
# Started
# Starting
# Migrating
# Stopping
$status = "running";
}
=cut
2020/09/24 18:14:42:Cluster.pm:1154; Variables:
|- server: ..... [srv07-el6]
|- host_name: .. [mk-a02n02] <- Old host
|- status: ..... [migrating]
|- role: ....... [Migrating]
\- active: ..... [1]
=cut
$anvil->data->{cib}{parsed}{data}{server}{$server}{status} = $status;
$anvil->data->{cib}{parsed}{data}{server}{$server}{host_name} = $host_name;
$anvil->data->{cib}{parsed}{data}{server}{$server}{host_id} = $host_id;

@ -8979,6 +8979,311 @@ WHERE
}
=head2 insert_or_update_servers
This updates (or inserts) a record in the 'sessions' table. The C<< server_uuid >> referencing the database row will be returned.
If there is an error, an empty string is returned.
Parameters;
=head3 delete (optional, default '0')
If set to C<< 1 >>, the server referenced but the C<< server_uuid >> is marked as deleted.
B<< Note >>: If this is set to C<< 1 >>, then only C<< server_uuid >> is required.
=head3 server_uuid (required)
This is the Server's UUID. In most tables, if a record doesn't exist then a random UUID is generated to create the new record.
In the C<< servers >> table however, the UUID used is the UUID in the server's definition file. As such, this parameter is always required.
=head3 server_name (required)
This is the name of the server being added.
=head3 server_anvil_uuid (required)
This is the C<< anvils >> -> C<< anvil_uuid >> that this server is currently hosted on.
=head3 server_clean_stop (optional, default '0')
This indicates when a server was stopped by a user. If this is set to C<< 1 >>, then the Anvil! will not boot the server (during an C<< anvil-safe-start >> run).
=head3 server_start_after_server_uuid (optional)
If the user wants to boot this server after another server, this can be set to C<< servers >> -> C<< server_uuid >>. When set, the server referenced will be booted (at least) C<< server_start_delay >> seconds before this server is booted.
=head3 server_start_delay (optional, default '30')
If C<< server_start_after_server_uuid >> is set, then this value controls the delay between when the referenced server boots and when this server boots.
B<< Note >>: This is the B<< minimum >> delay! It's possible that the actual delay could be a bit more than this value.
=head3 server_host_uuid (optional)
If the server is running, this is the C<< current hosts >> -> C<< host_uuid >> for this server. If the server is off, this will should be blank.
B<< Note >>: If the server is migating, this should be the old host until after the migration completes.
=head3 server_state (required)
This is the current status of the server. Valid values are;
* starting
* running
* stopping
* off
* migrating
* DELETED
B<< Note >>: The C<< DELETED >> state is special, in that it marks the server as no longer exists.
=head3 server_live_migration (optional, default '1')
Normally, when a server migrates the server keeps running, with changes to memory being tracked and copied. When most of the memory has been copied, the server is frozen for a brief moment, the last of the memory is copied, and then the server is thawed on the new host.
In some cases, with servers that have a lot of RAM or very quickly change the memory contents, a migation could take a very long time to complete, if it ever does at all.
For cases where a server can't be live migrated, set this to C<< 0 >>. When set to C<< 0 >>, the server is frozen before the RAM copy begins, and thawed on the new host when the migration is complete. In this way, the migration can be completed over a relatively short time.
B<< Note >>: Depending on the BCN network speed and the amount of RAM to copy, the server could be in a frozen state long enough for client connections to timeout. The server itself should handle the freeze fine in most modern systems.
=head3 server_pre_migration_file_uuid (optional)
This is set to the C<< files >> -> C<< file_uuid >> of a script to run B<< BEFORE >> migrating a server. If the file isn't found or can't be run, the script is ignored.
=head3 server_pre_migration_arguments (optional)
These are arguments to pass to the pre-migration script above.
=head3 server_post_migration_file_uuid (optional)
This is set to the C<< files >> -> C<< file_uuid >> of a script to run B<< AFTER >> migrating a server. If the file isn't found or can't run, the script is ignored.
=head3 server_post_migration_arguments (optional)
These are arguments to pass to the post-migration script above.
=cut
sub insert_or_update_servers
{
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->insert_or_update_servers()" }});
my $uuid = defined $parameter->{uuid} ? $parameter->{uuid} : "";
my $file = defined $parameter->{file} ? $parameter->{file} : "";
my $line = defined $parameter->{line} ? $parameter->{line} : "";
my $delete = defined $parameter->{'delete'} ? $parameter->{'delete'} : 0;
my $server_uuid = defined $parameter->{server_uuid} ? $parameter->{server_uuid} : "";
my $server_name = defined $parameter->{server_name} ? $parameter->{server_name} : "";
my $server_anvil_uuid = defined $parameter->{server_anvil_uuid} ? $parameter->{server_anvil_uuid} : "";
my $server_clean_stop = defined $parameter->{server_clean_stop} ? $parameter->{server_clean_stop} : 0;
my $server_start_after_server_uuid = defined $parameter->{server_start_after_server_uuid} ? $parameter->{server_start_after_server_uuid} : "";
my $server_start_delay = defined $parameter->{server_start_delay} ? $parameter->{server_start_delay} : 30;
my $server_host_uuid = defined $parameter->{server_host_uuid} ? $parameter->{server_host_uuid} : "";
my $server_state = defined $parameter->{server_state} ? $parameter->{server_state} : "";
my $server_live_migration = defined $parameter->{server_live_migration} ? $parameter->{server_live_migration} : 1;
my $server_pre_migration_file_uuid = defined $parameter->{server_pre_migration_file_uuid} ? $parameter->{server_pre_migration_file_uuid} : "";
my $server_pre_migration_arguments = defined $parameter->{server_pre_migration_arguments} ? $parameter->{server_pre_migration_arguments} : "";
my $server_post_migration_file_uuid = defined $parameter->{server_post_migration_file_uuid} ? $parameter->{server_post_migration_file_uuid} : "";
my $server_post_migration_arguments = defined $parameter->{server_post_migration_arguments} ? $parameter->{server_post_migration_arguments} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
'delete' => $delete,
uuid => $uuid,
file => $file,
line => $line,
server_uuid => $server_uuid,
server_name => $server_name,
server_anvil_uuid => $server_anvil_uuid,
server_clean_stop => $server_clean_stop,
server_start_after_server_uuid => $server_start_after_server_uuid,
server_start_delay => $server_start_delay,
server_host_uuid => $server_host_uuid,
server_state => $server_state,
server_live_migration => $server_live_migration,
server_pre_migration_file_uuid => $server_pre_migration_file_uuid,
server_pre_migration_arguments => $server_pre_migration_arguments,
server_post_migration_file_uuid => $server_post_migration_file_uuid,
server_post_migration_arguments => $server_post_migration_arguments,
}});
if (not $server_uuid)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_servers()", parameter => "server_uuid" }});
return("!!error!!");
}
if (not $anvil->Validate->uuid({uuid => $server_uuid}))
{
# invalid UUID
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0160", variables => { variable => "server_uuid", uuid => $server_uuid }});
return("!!error!!");
}
if (not $delete)
{
if (not $server_name)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_servers()", parameter => "server_name" }});
return("!!error!!");
}
if (not $server_anvil_uuid)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_servers()", parameter => "server_anvil_uuid" }});
return("!!error!!");
}
if (not $server_state)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_servers()", parameter => "server_state" }});
return("!!error!!");
}
}
# Do we already know about this
my $exists = 0;
my $query = "SELECT COUNT(*) FROM servers WHERE server_uuid = ".$anvil->Database->quote($server_uuid).";";
my $count = $anvil->Database->query({query => $function_query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { count => $count }});
if ($count)
{
$exists = 1;
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'exists' => $exists }});
if ($delete)
{
if (not $exists)
{
# Can't delete what doesn't exist...
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0161", variables => { server_uuid => "server_uuid" }});
return("!!error!!");
}
# Delete it
my $query = "SELECT server_state FROM servers WHERE server_uuid = ".$anvil->Database->quote($server_uuid).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({uuid => $uuid, query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
my $old_server_state = $results->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { old_server_state => $old_server_state }});
if ($old_server_name ne "DELETED")
{
my $query = "
UPDATE
servers
SET
server_state = 'DELETED',
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})."
WHERE
server_uuid = ".$anvil->Database->quote($server_uuid)."
;";
$anvil->Database->write({uuid => $uuid, query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__});
}
return($server_uuid);
}
### TODO: Left off here.
# Are we updating or inserting?
if (not $exists)
{
# INSERT
my $query = "
INSERT INTO
servers
(
server_uuid,
server_name,
modified_date
) VALUES (
".$anvil->Database->quote($server_uuid).",
".$anvil->Database->quote($server_name).",
".$anvil->Database->quote($).",
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})."
);
";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
$anvil->Database->write({uuid => $uuid, query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__});
}
else
{
# Query the rest of the values and see if anything changed.
my $query = "
SELECT
server_email,
server_language,
server_name,
server_level
FROM
servers
WHERE
server_uuid = ".$anvil->Database->quote($server_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({uuid => $uuid, query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
if (not $count)
{
# I have a server_uuid but no matching record. Probably an error.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0216", variables => { uuid_name => "server_uuid", uuid => $server_uuid }});
return("");
}
foreach my $row (@{$results})
{
my $old_server_email = $row->[0];
my $old_server_language = $row->[1];
my $old_server_name = $row->[2];
my $old_server_level = $row->[3];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
old_server_email => $old_server_email,
old_server_language => $old_server_language,
old_server_name => $old_server_name,
old_server_level => $old_server_level,
}});
# Anything change?
if (($old_server_email ne $server_email) or
($old_server_language ne $server_language) or
($old_server_name ne $server_name) or
($old_server_level ne $server_level))
{
# Something changed, save.
my $query = "
UPDATE
servers
SET
server_email = ".$anvil->Database->quote($server_email).",
server_language = ".$anvil->Database->quote($server_language).",
server_name = ".$anvil->Database->quote($server_name).",
server_level = ".$anvil->Database->quote($server_level).",
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})."
WHERE
server_uuid = ".$anvil->Database->quote($server_uuid)."
";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
$anvil->Database->write({uuid => $uuid, query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__});
}
}
}
return($server_uuid);
}
=head2 insert_or_update_sessions
This updates (or inserts) a record in the 'sessions' table. The C<< session_uuid >> referencing the database row will be returned.

@ -16,6 +16,7 @@ my $THIS_FILE = "Server.pm";
# find
# get_status
# map_network
# parse_definition
# migrate_virsh
# shutdown_virsh
@ -402,7 +403,7 @@ sub get_status
else
{
$anvil->data->{server}{$host}{$server}{from_memory}{host} = $this_host;
$anvil->Server->_parse_definition({
$anvil->Server->parse_definition({
debug => $debug,
host => $this_host,
server => $server,
@ -431,7 +432,7 @@ sub get_status
}
else
{
$anvil->Server->_parse_definition({
$anvil->Server->parse_definition({
debug => $debug,
host => $this_host,
server => $server,
@ -749,237 +750,50 @@ sub migrate_virsh
return($success);
}
=head2 shutdown_virsh
=head2
This takes a server name and tries to shut it down. If the server was found locally, the shut down is requested and this method will wait for the server to actually shut down before returning.
This method parses a server's C<< virsh >> XML definition. On successful parse, C<< 0 >> is returned. If there is a problem, C<< !!error!! >> is returned.
If shut down, C<< 1 >> is returned. If the server wasn't found or another problem occurs, C<< 0 >> is returned.
my ($shutdown) = $anvil->Server->shutdown_virsh({server => "test_server"});
B<< Note >>: This method currently parses out data needed for specific tasks, and not the entire data structure.
Parameters;
=head3 force (optional, default '0')
Normally, a graceful shutdown is requested. This requires that the guest respond to ACPI power button events. If the guest won't respond, or for some other reason you want to immediately force the server off, set this to C<< 1 >>.
B<WARNING>: Setting this to C<< 1 >> results in the immediate shutdown of the server! Same as if you pulled the power out of a traditional machine.
=head3 server (required)
This is the name of the server (as it appears in C<< virsh >>) to shut down.
This is the name of the server whose XML is being parsed.
=head3 wait (optional, default '0')
=head3 source (required)
By default, this method will wait indefinetly for the server to shut down before returning. If this is set to a non-zero number, the method will wait that number of seconds for the server to shut dwwn. If the server is still not off by then, C<< 0 >> is returned.
=cut
sub shutdown_virsh
{
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 => "Server->shutdown_virsh()" }});
my $server = defined $parameter->{server} ? $parameter->{server} : "";
my $force = defined $parameter->{force} ? $parameter->{force} : 0;
my $wait = defined $parameter->{'wait'} ? $parameter->{'wait'} : 0;
my $success = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
force => $force,
server => $server,
}});
This is the source of the XML. This is done to simplify looking for differences between definitions for the same server. It should be;
if (not $server)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->shutdown_virsh()", parameter => "server" }});
return($success);
}
if (($wait) && ($wait =~ /\D/))
{
# Bad value.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0422", variables => { server => $server, 'wait' => $wait }});
return($success);
}
=head4 C<< from_disk >>
# Is the server running?
$anvil->Server->find({debug => $debug});
The XML was read from a file on the host's storage.
# And?
if (exists $anvil->data->{server}{location}{$server})
{
my $shutdown = 1;
my $status = $anvil->data->{server}{location}{$server}{status};
my $task = "shutdown";
if ($force)
{
$task = "destroy";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "log_0424", variables => { server => $server }});
}
else
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0425", variables => { server => $server }});
}
if ($status eq "shut off")
{
# Already off.
$success = 1;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0423", variables => { server => $server }});
return($success);
}
elsif ($status eq "paused")
{
# The server is paused. Resume it, wait a few, then proceed with the shutdown.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0314", variables => { server => $server }});
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." resume $server"});
if ($return_code)
{
# Looks like virsh isn't running.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "log_0315", variables => {
server => $server,
return_code => $return_code,
output => $output,
}});
$anvil->nice_exit({exit_code => 1});
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0316"});
sleep 3;
}
elsif ($status eq "pmsuspended")
{
# The server is suspended. Resume it, wait a few, then proceed with the shutdown.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0317", variables => { server => $server }});
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." dompmwakeup $server"});
if ($return_code)
{
# Looks like virsh isn't running.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "log_0318", variables => {
server => $server,
return_code => $return_code,
output => $output,
}});
$anvil->nice_exit({exit_code => 1});
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0319"});
sleep 30;
}
elsif (($status eq "idle") or ($status eq "crashed"))
{
# The server needs to be destroyed.
$task = "destroy";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0322", variables => {
server => $server,
status => $status,
}});
}
elsif ($status eq "in shutdown")
{
# The server is already shutting down
$shutdown = 0;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0320", variables => { server => $server }});
}
elsif ($status ne "running")
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "log_0325", variables => {
server => $server,
status => $status,
}});
return($success);
}
=head4 C<< from_memory >>
# Shut it down.
if ($shutdown)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0520", variables => { server => $server }});
my ($output, $return_code) = $anvil->System->call({
debug => $debug,
shell_call => $anvil->data->{path}{exe}{virsh}." ".$task." ".$server,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
}
}
else
{
# Server wasn't found, assume it's off.
$success = 1;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0423", variables => { server => $server }});
return($success);
}
The XML was dumped by C<< virsh >> from memory.
# Wait indefinetely for the server to exit.
my $stop_waiting = 0;
if ($wait)
{
$stop_waiting = time + $wait;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { stop_waiting => $stop_waiting }});
};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'wait' => $wait }});
until($success)
{
# Update
$anvil->Server->find({debug => $debug});
if ((exists $anvil->data->{server}{location}{$server}) && ($anvil->data->{server}{location}{$server}{status}))
{
my $status = $anvil->data->{server}{location}{$server}{status};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { status => $status }});
=head4 C<< from_db >>
if ($status eq "shut off")
{
# Success! It should be undefined, but we're not the place to worry about
# that.
$success = 1;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0426", variables => { server => $server }});
}
}
else
{
# Success!
$success = 1;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0426", variables => { server => $server }});
}
The XML was read from the C<< definitions >> database table.
if (($stop_waiting) && (time > $stop_waiting))
{
# Give up waiting.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0427", variables => {
server => $server,
'wait' => $wait,
}});
}
else
{
# Sleep a second and then try again.
sleep 1;
}
}
=head3 definition (required)
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { success => $success }});
return($success);
}
This is the actual XML to be parsed.
# =head3
#
# Private Functions;
#
# =cut
=head3 host (optional, default 'Get->short_host_name')
#############################################################################################################
# Private functions #
#############################################################################################################
This is the host name of the Anvil! node or DR host that the XML was generated on or read from.
### NOTE: This is a work in progress. As of now, it parses out what ocf:alteeve:server needs.
# This pulls apart specific data out of a definition file.
sub _parse_definition
=cut
sub parse_definition
{
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 => "Server->_parse_definition()" }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Server->parse_definition()" }});
# Source is required.
my $server = defined $parameter->{server} ? $parameter->{server} : "";
@ -996,20 +810,21 @@ sub _parse_definition
if (not $server)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->_parse_definition()", parameter => "server" }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->parse_definition()", parameter => "server" }});
return(1);
}
if (not $source)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->_parse_definition()", parameter => "source" }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->parse_definition()", parameter => "source" }});
return(1);
}
if (not $definition)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->_parse_definition()", parameter => "definition" }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->parse_definition()", parameter => "definition" }});
return(1);
}
### TODO: Switch this away from XML::Simple
local $@;
my $xml = XML::Simple->new();
my $server_xml = "";
@ -1507,3 +1322,227 @@ sub _parse_definition
return(0);
}
=head2 shutdown_virsh
This takes a server name and tries to shut it down. If the server was found locally, the shut down is requested and this method will wait for the server to actually shut down before returning.
If shut down, C<< 1 >> is returned. If the server wasn't found or another problem occurs, C<< 0 >> is returned.
my ($shutdown) = $anvil->Server->shutdown_virsh({server => "test_server"});
Parameters;
=head3 force (optional, default '0')
Normally, a graceful shutdown is requested. This requires that the guest respond to ACPI power button events. If the guest won't respond, or for some other reason you want to immediately force the server off, set this to C<< 1 >>.
B<WARNING>: Setting this to C<< 1 >> results in the immediate shutdown of the server! Same as if you pulled the power out of a traditional machine.
=head3 server (required)
This is the name of the server (as it appears in C<< virsh >>) to shut down.
=head3 wait (optional, default '0')
By default, this method will wait indefinetly for the server to shut down before returning. If this is set to a non-zero number, the method will wait that number of seconds for the server to shut dwwn. If the server is still not off by then, C<< 0 >> is returned.
=cut
sub shutdown_virsh
{
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 => "Server->shutdown_virsh()" }});
my $server = defined $parameter->{server} ? $parameter->{server} : "";
my $force = defined $parameter->{force} ? $parameter->{force} : 0;
my $wait = defined $parameter->{'wait'} ? $parameter->{'wait'} : 0;
my $success = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
force => $force,
server => $server,
}});
if (not $server)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->shutdown_virsh()", parameter => "server" }});
return($success);
}
if (($wait) && ($wait =~ /\D/))
{
# Bad value.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0422", variables => { server => $server, 'wait' => $wait }});
return($success);
}
# Is the server running?
$anvil->Server->find({debug => $debug});
# And?
if (exists $anvil->data->{server}{location}{$server})
{
my $shutdown = 1;
my $status = $anvil->data->{server}{location}{$server}{status};
my $task = "shutdown";
if ($force)
{
$task = "destroy";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "log_0424", variables => { server => $server }});
}
else
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0425", variables => { server => $server }});
}
if ($status eq "shut off")
{
# Already off.
$success = 1;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0423", variables => { server => $server }});
return($success);
}
elsif ($status eq "paused")
{
# The server is paused. Resume it, wait a few, then proceed with the shutdown.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0314", variables => { server => $server }});
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." resume $server"});
if ($return_code)
{
# Looks like virsh isn't running.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "log_0315", variables => {
server => $server,
return_code => $return_code,
output => $output,
}});
$anvil->nice_exit({exit_code => 1});
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0316"});
sleep 3;
}
elsif ($status eq "pmsuspended")
{
# The server is suspended. Resume it, wait a few, then proceed with the shutdown.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0317", variables => { server => $server }});
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." dompmwakeup $server"});
if ($return_code)
{
# Looks like virsh isn't running.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "log_0318", variables => {
server => $server,
return_code => $return_code,
output => $output,
}});
$anvil->nice_exit({exit_code => 1});
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0319"});
sleep 30;
}
elsif (($status eq "idle") or ($status eq "crashed"))
{
# The server needs to be destroyed.
$task = "destroy";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0322", variables => {
server => $server,
status => $status,
}});
}
elsif ($status eq "in shutdown")
{
# The server is already shutting down
$shutdown = 0;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0320", variables => { server => $server }});
}
elsif ($status ne "running")
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "log_0325", variables => {
server => $server,
status => $status,
}});
return($success);
}
# Shut it down.
if ($shutdown)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0520", variables => { server => $server }});
my ($output, $return_code) = $anvil->System->call({
debug => $debug,
shell_call => $anvil->data->{path}{exe}{virsh}." ".$task." ".$server,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
}
}
else
{
# Server wasn't found, assume it's off.
$success = 1;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0423", variables => { server => $server }});
return($success);
}
# Wait indefinetely for the server to exit.
my $stop_waiting = 0;
if ($wait)
{
$stop_waiting = time + $wait;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { stop_waiting => $stop_waiting }});
};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'wait' => $wait }});
until($success)
{
# Update
$anvil->Server->find({debug => $debug});
if ((exists $anvil->data->{server}{location}{$server}) && ($anvil->data->{server}{location}{$server}{status}))
{
my $status = $anvil->data->{server}{location}{$server}{status};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { status => $status }});
if ($status eq "shut off")
{
# Success! It should be undefined, but we're not the place to worry about
# that.
$success = 1;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0426", variables => { server => $server }});
}
}
else
{
# Success!
$success = 1;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0426", variables => { server => $server }});
}
if (($stop_waiting) && (time > $stop_waiting))
{
# Give up waiting.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0427", variables => {
server => $server,
'wait' => $wait,
}});
}
else
{
# Sleep a second and then try again.
sleep 1;
}
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { success => $success }});
return($success);
}
# =head3
#
# Private Functions;
#
# =cut
#############################################################################################################
# Private functions #
#############################################################################################################

@ -21,6 +21,7 @@ my $THIS_FILE = "Storage.pm";
# check_md5sums
# copy_file
# find
# get_file_stats
# make_directory
# move_file
# read_config
@ -1338,6 +1339,136 @@ sub find
return ($full_path);
}
=head2 get_file_stats
This method calls a C<< stat >> (or C<< lstat >> and pulls out the file information.
If successful, C<< 0 >> is returned. If there was a problem, like the file wasn't found, C<< 1 >> is returned.
Collected information is stored as (see C<< perldoc -f stat >> for details):
file_stat::<file_path>::device_number
file_stat::<file_path>::inode_number
file_stat::<file_path>::mode - raw mode information (you probably don't want this)
file_stat::<file_path>::unix_mode - decimal mode (bitwise'd 4-digit decimal version of the mode, you probably want this)
file_stat::<file_path>::number_of_hardlinks
file_stat::<file_path>::user_id
file_stat::<file_path>::user_name
file_stat::<file_path>::group_id
file_stat::<file_path>::group_name
file_stat::<file_path>::device_identifier
file_stat::<file_path>::size
file_stat::<file_path>::access_time
file_stat::<file_path>::modified_time
file_stat::<file_path>::inode_change_time
file_stat::<file_path>::block_size
file_stat::<file_path>::blocks
Parameters;
=head3 file_path (required)
This is the path to the file (or directory, symlink, etc) to be examined.
=cut
sub get_file_stats
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
my $test = defined $parameter->{test} ? $parameter->{test} : 0;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Storage->get_file_stats()" }});
my $file_path = defined $parameter->{file_path} ? $parameter->{file_path} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
file_path => $file_path,
}});
if (not $file_path)
{
# No source passed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Storage->get_file_stats()", parameter => "file_path" }});
return(1);
}
if (not -e $file_path)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0159", variables => { file_path => $file_path }});
return(1);
}
### Data collected by array position, from 'perldoc -f stat'.
# 0 dev device number of filesystem
# 1 ino inode number
# 2 mode file mode (type and permissions)
# 3 nlink number of (hard) links to the file
# 4 uid numeric user ID of file's owner
# 5 gid numeric group ID of file's owner
# 6 rdev the device identifier (special files only)
# 7 size total size of file, in bytes
# 8 atime last access time in seconds since the epoch
# 9 mtime last modify time in seconds since the epoch
# 10 ctime inode change time in seconds since the epoch (*)
# 11 blksize preferred I/O size in bytes for interacting with the file (may vary from file to file)
# 12 blocks actual number of system-specific blocks allocated on disk (often, but not always, 512 bytes each)
my ($device_number, $inode_number, $mode, $number_of_hardlinks, $user_id, $group_id, $device_identifier, $size, $access_time, $modified_time, $inode_change_time, $block_size, $blocks) = "";
if (-l $file_path)
{
# Use lstat
($device_number, $inode_number, $mode, $number_of_hardlinks, $user_id, $group_id, $device_identifier, $size, $access_time, $modified_time, $inode_change_time, $block_size, $blocks) = lstat($file_path);
}
else
{
# Use stat
($device_number, $inode_number, $mode, $number_of_hardlinks, $user_id, $group_id, $device_identifier, $size, $access_time, $modified_time, $inode_change_time, $block_size, $blocks) = stat($file_path);
}
# A little processing...
my $user_name = getpwuid($user_id);
my $group_name = getgrgid($group_id);
my $unix_mode = sprintf("%04s", sprintf("%o", ($mode & 07777)));
$anvil->data->{file_stat}{$file_path}{device_number} = $device_number;
$anvil->data->{file_stat}{$file_path}{inode_number} = $inode_number;
$anvil->data->{file_stat}{$file_path}{mode} = $mode;
$anvil->data->{file_stat}{$file_path}{unix_mode} = $unix_mode;
$anvil->data->{file_stat}{$file_path}{number_of_hardlinks} = $number_of_hardlinks;
$anvil->data->{file_stat}{$file_path}{user_id} = $user_id;
$anvil->data->{file_stat}{$file_path}{user_name} = $user_name;
$anvil->data->{file_stat}{$file_path}{group_id} = $group_id;
$anvil->data->{file_stat}{$file_path}{group_name} = $group_name;
$anvil->data->{file_stat}{$file_path}{device_identifier} = $device_identifier;
$anvil->data->{file_stat}{$file_path}{size} = $size;
$anvil->data->{file_stat}{$file_path}{access_time} = $access_time;
$anvil->data->{file_stat}{$file_path}{modified_time} = $modified_time;
$anvil->data->{file_stat}{$file_path}{inode_change_time} = $inode_change_time;
$anvil->data->{file_stat}{$file_path}{block_size} = $block_size;
$anvil->data->{file_stat}{$file_path}{blocks} = $blocks;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:file_stat::${file_path}::device_number" => $anvil->data->{file_stat}{$file_path}{device_number},
"s2:file_stat::${file_path}::inode_number" => $anvil->data->{file_stat}{$file_path}{inode_number},
"s3:file_stat::${file_path}::mode" => $anvil->data->{file_stat}{$file_path}{mode},
"s4:file_stat::${file_path}::unix_mode" => $anvil->data->{file_stat}{$file_path}{unix_mode},
"s5:file_stat::${file_path}::number_of_hardlinks" => $anvil->data->{file_stat}{$file_path}{number_of_hardlinks},
"s6:file_stat::${file_path}::user_id" => $anvil->data->{file_stat}{$file_path}{user_id},
"s7:file_stat::${file_path}::user_name" => $anvil->data->{file_stat}{$file_path}{user_name},
"s8:file_stat::${file_path}::group_id" => $anvil->data->{file_stat}{$file_path}{group_id},
"s9:file_stat::${file_path}::group_name" => $anvil->data->{file_stat}{$file_path}{group_name},
"s10:file_stat::${file_path}::device_identifier" => $anvil->data->{file_stat}{$file_path}{device_identifier},
"s11:file_stat::${file_path}::size" => $anvil->Convert->add_commas({number => $anvil->data->{file_stat}{$file_path}{size}})." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $anvil->data->{file_stat}{$file_path}{size}}).")",
"s12:file_stat::${file_path}::access_time" => $anvil->data->{file_stat}{$file_path}{access_time},
"s13:file_stat::${file_path}::modified_time" => $anvil->data->{file_stat}{$file_path}{modified_time},
"s14:file_stat::${file_path}::inode_change_time" => $anvil->data->{file_stat}{$file_path}{inode_change_time},
"s15:file_stat::${file_path}::block_size" => $anvil->data->{file_stat}{$file_path}{block_size},
"s16:file_stat::${file_path}::blocks" => $anvil->data->{file_stat}{$file_path}{blocks},
}});
return(0);
}
=head2 make_directory
This creates a directory (and any parent directories).

@ -9,6 +9,7 @@
# Exit codes;
# 0 = Normal exit.
# 1 = Startup failure (no DB, bad file read, etc)
# 2 = libvirtd is not running.
#
# TODO:
# -
@ -93,9 +94,98 @@ sub collect_data
{
my ($anvil) = @_;
# Is 'libvirtd' running?
my $running = $anvil->System->check_daemon({daemon => "libvirtd"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { running => $running }});
if (not $running)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_server_log_0003"});
$anvil->nice_exit({exit_code => 2});
}
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." list --all", source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }});
foreach my $line (split/\n/, $output)
{
$line = $anvil->Words->clean_spaces({string => $line});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }});
if ($line =~ /^\d+ (.*?) (.*)$/)
{
my $server = $1;
my $state = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
server => $server,
'state' => $state,
}});
$anvil->data->{'scan-server'}{server}{$server}{'state'} = $state;
$anvil->data->{'scan-server'}{server}{$server}{undefine} = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"scan-server::server::${server}::state" => $anvil->data->{'scan-server'}{server}{$server}{'state'},
"scan-server::server::${server}::undefine" => $anvil->data->{'scan-server'}{server}{$server}{undefine},
}});
}
if ($line =~ /- (.*?) shut off/)
{
# The server is shut off. If this is a node, it shouldn't be defined.
my $server = $1;
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 eq "node")
{
$anvil->data->{'scan-server'}{server}{$server}{undefine} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"scan-server::server::${server}::undefine" => $anvil->data->{'scan-server'}{server}{$server}{undefine},
}});
}
}
}
# Now loop through the found servers and read their XML definition.
foreach my $server (sort {$a cmp $b} keys %{$anvil->data->{'scan-server'}{server}})
{
my ($definition, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." dumpxml ".$server, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $definition, return_code => $definition }});
my $target = $anvil->Get->short_host_name;
my $source = "from_memory";
my $problem = $anvil->Server->parse_definition({
debug => 2,
server => $server,
source => $source,
definition => $definition,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
if ($problem)
{
# Wat?
next;
}
my $server_uuid = $anvil->data->{server}{$target}{$server}{$source}{info}{uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { server_uuid => $server_uuid }});
# See if this server is in the database.
my $query = "SELECT COUNT(*) FROM servers WHERE server_uuid = ".$anvil->Database->quote($server_uuid).";";
my $count = $anvil->Database->query({query => $function_query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { count => $count }});
if (not $count)
{
# Add it.
}
### TODO: left off here, look for the XML file on disk. If it's not found, write it.
my $xml_file = $anvil->data->{path}{directories}{shared}{definitions}."/".$server.".xml";
if (-e $xml_file)
{
$anvil->Storage->get_file_stats({
debug => 2,
file_path => $xml_file,
});
}
}
return(0);
}

@ -19,6 +19,7 @@ NOTE: All string keys MUST be prefixed with the agent name! ie: 'scan_server_log
<!-- Log entries -->
<key name="scan_server_log_0001">Starting: [#!variable!program!#].</key>
<key name="scan_server_log_0002">This host is a: [#!variable!host_type!#], this agent is only useful on nodes and DR hosts. Exiting.</key>
<key name="scan_server_log_0003">The libvirtd daemon is not running. Exiting.</key>
<!-- Message entries (usually meant to be alerts) -->
<key name="scan_server_message_0001">We're node 2, and node 1 is running as well. Exiting as only one node needs to run this agent.</key>

@ -1240,16 +1240,16 @@ CREATE TABLE servers (
server_uuid uuid not null primary key,
server_name text not null, -- This is the server's name. It can change without re-uploading the server.
server_anvil_uuid uuid not null, -- This is the Anvil! system that the server lives on. It can move to another Anvil!, so this can change.
server_clean_stop boolean default FALSE, -- When set, the server was stopped by a user. The Anvil! will not start a server that has been cleanly stopped.
server_start_after_server_uuid uuid, -- This can be the server_uuid of another server. If set, this server will boot 'server_start_delay' seconds after the referenced server boots. A value of '00000000-0000-0000-0000-000000000000' will tell 'anvil-safe-start' to not boot the server at all. If a server is set not to start, any dependent servers will also stay off.
server_clean_stop boolean not null default FALSE, -- When set, the server was stopped by a user. The Anvil! will not start a server that has been cleanly stopped.
server_start_after_server_uuid uuid not null, -- This can be the server_uuid of another server. If set, this server will boot 'server_start_delay' seconds after the referenced server boots. A value of '00000000-0000-0000-0000-000000000000' will tell 'anvil-safe-start' to not boot the server at all. If a server is set not to start, any dependent servers will also stay off.
server_start_delay integer not null default 0, -- See above.
server_host_uuid uuid, -- This is the current hosts -> host_uuid for this server. If the server is off, this will be blank.
server_state text, -- This is the current state of this server.
server_host_uuid uuid not null, -- This is the current hosts -> host_uuid for this server. If the server is off, this will be blank.
server_state text not null, -- This is the current state of this server.
server_live_migration boolean not null default TRUE, -- When false, servers will be stopped and then rebooted when a migration is requested. Also, when false, preventative migrations will not happen.
server_pre_migration_file_uuid uuid, -- This is set to the files -> file_uuid of a script to run BEFORE migrating a server. If the file isn't found or can't run, the script is ignored.
server_pre_migration_arguments text, -- These are arguments to pass to the pre-migration script
server_post_migration_file_uuid uuid, -- This is set to the files -> file_uuid of a script to run AFTER migrating a server. If the file isn't found or can't run, the script is ignored.
server_post_migration_arguments text, -- These are arguments to pass to the post-migration script
server_pre_migration_file_uuid uuid not null, -- This is set to the files -> file_uuid of a script to run BEFORE migrating a server. If the file isn't found or can't run, the script is ignored.
server_pre_migration_arguments text not null, -- These are arguments to pass to the pre-migration script
server_post_migration_file_uuid uuid not null, -- This is set to the files -> file_uuid of a script to run AFTER migrating a server. If the file isn't found or can't run, the script is ignored.
server_post_migration_arguments text not null, -- These are arguments to pass to the post-migration script
modified_date timestamp with time zone not null,
FOREIGN KEY(server_anvil_uuid) REFERENCES anvils(anvil_uuid),

@ -231,6 +231,9 @@ The error was:
<key name="error_0156">Unable to migrate the server: [#!variable!server!#] as this node is not (yet) a full member of the cluster.</key>
<key name="error_0157">Unable to migrate the server: [#!variable!server!#] as the peer node is not (yet) a full member of the cluster.</key>
<key name="error_0158">Unable to migrate the server: [#!variable!server!#] as this server was not found in the cluster information base (CIB).</key>
<key name="error_0159">Unable to read the stat information for the file: [#!variable!file_path!#], the file doesn't appear to exist.</key>
<key name="error_0160">The '#!variable!name!#': [#!variable!uuid!#] is not valid.</key>
<key name="error_0161">Unable to mark the server with UUID: [#!variable!uuid!#] as "deleted" because it doesn't apprear to exist in the database in the first place.</key>
<!-- Table headers -->
<key name="header_0001">Current Network Interfaces and States</key>
@ -1852,6 +1855,8 @@ The error was:
#!variable!error!#
========
</key>
<key name="warning_0064">[ Warning ] - The server: [#!variable!server!#] was asked to be migrated to: [#!variable!requested_node!#], but the server is shutting down. Aborting.</key>
<key name="warning_0065">[ Warning ] - The server: [#!variable!server!#] was asked to be migrated to: [#!variable!requested_node!#], but the server is already in the middle of a migration. Aborting.</key>
</language>
<!-- 日本語 -->

@ -29,6 +29,11 @@ print "Connecting to the database(s);\n";
$anvil->Database->connect({debug => 3});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, secure => 0, key => "log_0132"});
$anvil->Storage->get_file_stats({
debug => 2,
file_path => "/root/test",
});
# $anvil->Cluster->shutdown_server({
# debug => 2,
# server => "srv07-el6",
@ -53,5 +58,8 @@ if (0)
}
}
if (0)
{
my $problem = $anvil->Cluster->parse_cib({debug => 2});
print "Problem: [".$problem."]\n";
}

Loading…
Cancel
Save