* Renamed striker-configure-host (back) to anvil-configure-host, and started updating it to work on any machine type.
* Created tools/anvil-check-memory to report how much RAM is used by a given program. * Added documentation for some previously undocumented methods. * Updated Database->archive_database() to take the 'tables' parameter. * Updated Storage->scan_directory() to record a directory's mode and type, even when recursive isn't used. * Finished System->check_memory(). * Updated ocf:alteeve:server to now NOT stop a DRBD resource unless 'stop_drbd_resources'. Signed-off-by: Digimer <digimer@alteeve.ca>
This commit is contained in:
parent
c0dd34334e
commit
8a2c86d088
@ -1000,6 +1000,8 @@ sub _set_paths
|
|||||||
},
|
},
|
||||||
exe => {
|
exe => {
|
||||||
'anvil-change-password' => "/usr/sbin/anvil-change-password",
|
'anvil-change-password' => "/usr/sbin/anvil-change-password",
|
||||||
|
'anvil-check-memory' => "/usr/sbin/anvil-check-memory",
|
||||||
|
'anvil-configure-host' => "/usr/sbin/anvil-configure-host",
|
||||||
'anvil-daemon' => "/usr/sbin/anvil-daemon",
|
'anvil-daemon' => "/usr/sbin/anvil-daemon",
|
||||||
'anvil-download-file' => "/usr/sbin/anvil-download-file",
|
'anvil-download-file' => "/usr/sbin/anvil-download-file",
|
||||||
'anvil-file-details' => "/usr/sbin/anvil-file-details",
|
'anvil-file-details' => "/usr/sbin/anvil-file-details",
|
||||||
@ -1066,7 +1068,6 @@ sub _set_paths
|
|||||||
'ssh-keyscan' => "/usr/bin/ssh-keyscan",
|
'ssh-keyscan' => "/usr/bin/ssh-keyscan",
|
||||||
stonith_admin => "/usr/sbin/stonith_admin",
|
stonith_admin => "/usr/sbin/stonith_admin",
|
||||||
strings => "/usr/bin/strings",
|
strings => "/usr/bin/strings",
|
||||||
'striker-configure-host' => "/usr/sbin/striker-configure-host",
|
|
||||||
'striker-manage-install-target' => "/usr/sbin/striker-manage-install-target",
|
'striker-manage-install-target' => "/usr/sbin/striker-manage-install-target",
|
||||||
'striker-manage-peers' => "/usr/sbin/striker-manage-peers",
|
'striker-manage-peers' => "/usr/sbin/striker-manage-peers",
|
||||||
'striker-prep-database' => "/usr/sbin/striker-prep-database",
|
'striker-prep-database' => "/usr/sbin/striker-prep-database",
|
||||||
|
@ -508,6 +508,7 @@ INSERT INTO
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### TODO: Write this, maybe? Or remove it and ->warning()?
|
||||||
=head2 error
|
=head2 error
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
@ -114,7 +114,15 @@ sub parent
|
|||||||
|
|
||||||
=head2 archive_database
|
=head2 archive_database
|
||||||
|
|
||||||
NOTE: Not implemented yet.
|
This method takes an array reference of database tables and check each to see if their history schema version needs to be archived or not.
|
||||||
|
|
||||||
|
Parameters;
|
||||||
|
|
||||||
|
=head3 tables (required, hash reference)
|
||||||
|
|
||||||
|
This is an B<< array reference >> of tables to archive.
|
||||||
|
|
||||||
|
B<< NOTE >>: The array is processed in B<< reverse >> order! This is done to allow the same array used to create/sync tables to be used without modification (foreign keys will be archived/removed before primary keys)
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
sub archive_database
|
sub archive_database
|
||||||
@ -125,6 +133,19 @@ sub archive_database
|
|||||||
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
|
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
|
||||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->archive_database()" }});
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->archive_database()" }});
|
||||||
|
|
||||||
|
my $tables = defined $parameter->{tables} ? $parameter->{tables} : "";
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
|
||||||
|
tables => $tables,
|
||||||
|
}});
|
||||||
|
|
||||||
|
# If the 'tables' parameter is an array reference, add it to 'sys::database::check_tables' (creating
|
||||||
|
# it, if needed).
|
||||||
|
if (ref($tables) ne "ARRAY")
|
||||||
|
{
|
||||||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0432"});
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
# Is archiving disabled?
|
# Is archiving disabled?
|
||||||
if (not $anvil->data->{sys}{database}{archive}{trigger})
|
if (not $anvil->data->{sys}{database}{archive}{trigger})
|
||||||
{
|
{
|
||||||
@ -140,18 +161,11 @@ sub archive_database
|
|||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
# If we don't have an array of tables, we have nothing to do.
|
|
||||||
if ((not exists $anvil->data->{sys}{database}{check_tables}) or (ref(@{$anvil->data->{sys}{database}{check_tables}} ne "ARRAY")))
|
|
||||||
{
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
# We'll use the list of tables created for _find_behind_databases()'s 'sys::database::check_tables'
|
# We'll use the list of tables created for _find_behind_databases()'s 'sys::database::check_tables'
|
||||||
# array, but in reverse so that tables with primary keys (first in the array) are archived last.
|
# array, but in reverse so that tables with primary keys (first in the array) are archived last.
|
||||||
foreach my $table (reverse(@{$anvil->data->{sys}{database}{check_tables}}))
|
foreach my $table (reverse(@{$tables}))
|
||||||
{
|
{
|
||||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { table => $table }});
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { table => $table }});
|
||||||
|
|
||||||
$anvil->Database->_archive_table({table => $table});
|
$anvil->Database->_archive_table({table => $table});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1555,6 +1569,12 @@ sub get_local_uuid
|
|||||||
|
|
||||||
This will initialize a database using a given file.
|
This will initialize a database using a given file.
|
||||||
|
|
||||||
|
Parameters;
|
||||||
|
|
||||||
|
=head3 sql_file (required)
|
||||||
|
|
||||||
|
This is the full (or relative) path and file nane to use when initializing the database.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
sub initialize
|
sub initialize
|
||||||
{
|
{
|
||||||
@ -5192,6 +5212,14 @@ WHERE
|
|||||||
|
|
||||||
This reads, sets or updates the database lock file timestamp.
|
This reads, sets or updates the database lock file timestamp.
|
||||||
|
|
||||||
|
Parameters;
|
||||||
|
|
||||||
|
=head3 do (required, default 'get')
|
||||||
|
|
||||||
|
This controls whether we're setting (C<< set >>) or checking for (C<< get >>) a lock file on the local system.
|
||||||
|
|
||||||
|
If setting, or if checking and a lock file is found, the timestamp (in unixtime) in the lock fike is returned. If a lock file isn't found, C<< 0 >> is returned.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
sub lock_file
|
sub lock_file
|
||||||
{
|
{
|
||||||
@ -5660,7 +5688,7 @@ sub query
|
|||||||
|
|
||||||
=head2 quote
|
=head2 quote
|
||||||
|
|
||||||
This quotes a string for safe use in database queries/writes.
|
This quotes a string for safe use in database queries/writes. It operates exactly as C<< DBI >>'s C<< quote >> method. This method is simply a wrapper that uses the C<< DBI >> handle set as the currently active read database.
|
||||||
|
|
||||||
Example;
|
Example;
|
||||||
|
|
||||||
|
@ -2013,7 +2013,41 @@ sub rsync
|
|||||||
|
|
||||||
=head2 scan_directory
|
=head2 scan_directory
|
||||||
|
|
||||||
TODO: Wtite this...
|
This takes a directory and scan its contents. What is found is stored in the following hashes;
|
||||||
|
|
||||||
|
scan::directories::<parent_directory>::directory = <parent directory>
|
||||||
|
scan::directories::<parent_directory>::name = <file or directory name>
|
||||||
|
scan::directories::<parent_directory>::type = 'file', 'directory' or 'symlink' (other special types are ignored entirely)
|
||||||
|
|
||||||
|
If the fule is a directory, this is also set;
|
||||||
|
|
||||||
|
scan::directories::<parent_directory>::mode = <the mode of the directory, already masked>
|
||||||
|
|
||||||
|
If the file is a symlink, this is also set;
|
||||||
|
|
||||||
|
scan::directories::<parent_directory>::target = <target file>
|
||||||
|
|
||||||
|
If the file is an actual file, the following information is set;
|
||||||
|
|
||||||
|
scan::directories::<parent_directory>::mode = <the mode of the file, already masked>
|
||||||
|
scan::directories::<parent_directory>::user_id = <numeric user ID of the owner>
|
||||||
|
scan::directories::<parent_directory>::group_id = <numeric group ID of the owner>
|
||||||
|
scan::directories::<parent_directory>::size = <size in bytes>
|
||||||
|
scan::directories::<parent_directory>::mtime = <last modification time, in unixtime>
|
||||||
|
scan::directories::<parent_directory>::mimetype = <mimetype, as returned by File::MimeInfo->mimetype>
|
||||||
|
scan::directories::<parent_directory>::executable = '0' or '1'
|
||||||
|
|
||||||
|
Parameters;
|
||||||
|
|
||||||
|
=head3 directory (required)
|
||||||
|
|
||||||
|
This is the full path to the directory to scan.
|
||||||
|
|
||||||
|
=head3 recursive (optional, default '0')
|
||||||
|
|
||||||
|
If set to C<< 1 >>, any directories found will be scanned as well.
|
||||||
|
|
||||||
|
B<< NOTE >>: Symlinks that point to directories will B<< NOT >> be scanned.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
### TODO: Make this work on remote systems
|
### TODO: Make this work on remote systems
|
||||||
@ -2065,14 +2099,20 @@ sub scan_directory
|
|||||||
"scan::directories::${full_path}::name" => $anvil->data->{scan}{directories}{$full_path}{name},
|
"scan::directories::${full_path}::name" => $anvil->data->{scan}{directories}{$full_path}{name},
|
||||||
full_path => $full_path,
|
full_path => $full_path,
|
||||||
}});
|
}});
|
||||||
if ((-d $full_path) && ($recursive))
|
if (-d $full_path)
|
||||||
{
|
{
|
||||||
# This is a directory, dive into it is asked.
|
# This is a directory, dive into it is asked.
|
||||||
|
my @details = stat($full_path);
|
||||||
$anvil->data->{scan}{directories}{$full_path}{type} = "directory";
|
$anvil->data->{scan}{directories}{$full_path}{type} = "directory";
|
||||||
|
$anvil->data->{scan}{directories}{$full_path}{mode} = sprintf("04%o", $details[2] & 07777);
|
||||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
|
||||||
"scan::directories::${full_path}::type" => $anvil->data->{scan}{directories}{$full_path}{type},
|
"scan::directories::${full_path}::type" => $anvil->data->{scan}{directories}{$full_path}{type},
|
||||||
|
"scan::directories::${full_path}::mode" => $anvil->data->{scan}{directories}{$full_path}{mode},
|
||||||
}});
|
}});
|
||||||
$anvil->Storage->scan_directory({debug => $debug, directory => $full_path, recursive => $recursive});
|
if ($recursive)
|
||||||
|
{
|
||||||
|
$anvil->Storage->scan_directory({debug => $debug, directory => $full_path, recursive => $recursive});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
elsif (-l $full_path)
|
elsif (-l $full_path)
|
||||||
{
|
{
|
||||||
|
@ -564,7 +564,13 @@ sub check_if_configured
|
|||||||
|
|
||||||
=head2 check_memory
|
=head2 check_memory
|
||||||
|
|
||||||
# Not yet written...
|
This calls 'anvil-check-memory' with the given program name, and looks at the output to see how much RAM that program uses (if it is even running).
|
||||||
|
|
||||||
|
Parameters;
|
||||||
|
|
||||||
|
=head3 program_name (required)
|
||||||
|
|
||||||
|
This is the name of the program (as seen in the output of C<< ps aux >>) to check the RAM of.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
sub check_memory
|
sub check_memory
|
||||||
@ -585,18 +591,19 @@ sub check_memory
|
|||||||
|
|
||||||
my $used_ram = 0;
|
my $used_ram = 0;
|
||||||
|
|
||||||
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{''}." --program $program_name"});
|
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{'anvil-check-memory'}." --program $program_name"});
|
||||||
foreach my $line (split/\n/, $output)
|
foreach my $line (split/\n/, $output)
|
||||||
{
|
{
|
||||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }});
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }});
|
||||||
if ($line =~ /= (\d+) /)
|
if ($line =~ /= (\d+) /)
|
||||||
{
|
{
|
||||||
$used_ram = $1;
|
$used_ram = $1;
|
||||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { used_ram => $used_ram }});
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
|
||||||
|
used_ram => $anvil->Convert->add_commas({number => $used_ram})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $used_ram}).")",
|
||||||
|
}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { used_ram => $used_ram }});
|
|
||||||
return($used_ram);
|
return($used_ram);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -919,6 +926,8 @@ sub get_free_memory
|
|||||||
|
|
||||||
This method tries to determine the host type and returns a value suitable for use is the C<< hosts >> table.
|
This method tries to determine the host type and returns a value suitable for use is the C<< hosts >> table.
|
||||||
|
|
||||||
|
my $type = $anvil->System->get_host_type();
|
||||||
|
|
||||||
First, it looks to see if C<< sys::host_type >> is set and, if so, uses that string as it is.
|
First, it looks to see if C<< sys::host_type >> is set and, if so, uses that string as it is.
|
||||||
|
|
||||||
If that isn't set, it then looks at the short host name. The following rules are used, in order;
|
If that isn't set, it then looks at the short host name. The following rules are used, in order;
|
||||||
|
@ -1255,7 +1255,7 @@ sub configure_striker
|
|||||||
debug => 3,
|
debug => 3,
|
||||||
file => $THIS_FILE,
|
file => $THIS_FILE,
|
||||||
line => __LINE__,
|
line => __LINE__,
|
||||||
job_command => $anvil->data->{path}{exe}{'striker-configure-host'},
|
job_command => $anvil->data->{path}{exe}{'anvil-configure-host'},
|
||||||
job_data => "form::config_step2",
|
job_data => "form::config_step2",
|
||||||
job_name => "configure::network",
|
job_name => "configure::network",
|
||||||
job_title => "job_0001",
|
job_title => "job_0001",
|
||||||
|
2
notes
2
notes
@ -504,6 +504,8 @@ pcs property set stonith-enabled=true
|
|||||||
|
|
||||||
pcs resource create hypervisor systemd:libvirtd op monitor interval=60
|
pcs resource create hypervisor systemd:libvirtd op monitor interval=60
|
||||||
pcs resource clone hypervisor clone-max=2 notify="false"
|
pcs resource clone hypervisor clone-max=2 notify="false"
|
||||||
|
pcs resource create drbd systemd:drbd op monitor interval=60
|
||||||
|
pcs resource clone drbd clone-max=2 notify="false"
|
||||||
|
|
||||||
pcs resource update test_server ocf:alteeve:server name="test_server" meta allow-migrate="true" op monitor interval="60"
|
pcs resource update test_server ocf:alteeve:server name="test_server" meta allow-migrate="true" op monitor interval="60"
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
# This is the resource agent used to manage servers on the Anvil! Intelligent Availability platform.
|
# This is the resource agent used to manage servers on the Anvil! Intelligent Availability platform.
|
||||||
#
|
#
|
||||||
# License: GNU General Public License (GPL) v2+
|
# License: GNU General Public License (GPL) v2+
|
||||||
# (c) 1997-2018 - Alteeve's Niche! Inc.
|
# (c) 1997-2019 - Alteeve's Niche! Inc.
|
||||||
#
|
#
|
||||||
# WARNING: This is a pretty purpose-specific resource agent. No effort was made to test this on an rgmanager
|
# WARNING: This is a pretty purpose-specific resource agent. No effort was made to test this on an rgmanager
|
||||||
# cluster or on any configuration outside how the Anvil! m3 uses it. If you plan to adapt it to
|
# cluster or on any configuration outside how the Anvil! m3 uses it. If you plan to adapt it to
|
||||||
@ -132,9 +132,23 @@ if ($anvil->data->{environment}{PCMK_debug})
|
|||||||
$anvil->Log->level({set => 3});
|
$anvil->Log->level({set => 3});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Originally, this was designed to start and stop a server's DRBD resources on demand. Early testing appears
|
||||||
|
# to show this prone to higher risk of fencing if something goes wrong. As such, we're changing the default
|
||||||
|
# behaviour to leave DRBD resources up. Set this to '1' (here or by switch) to revert back to the old
|
||||||
|
# behaviour.
|
||||||
|
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_stop_drbd_resources} = 0;
|
||||||
|
|
||||||
# Get any command line switches.
|
# Get any command line switches.
|
||||||
$anvil->Get->switches;
|
$anvil->Get->switches;
|
||||||
|
|
||||||
|
if ($anvil->data->{switches}{stop_drbd_resources})
|
||||||
|
{
|
||||||
|
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#$anvil->DRBD->get_status({debug => 2});
|
||||||
|
#die;
|
||||||
|
|
||||||
# Something for the logs
|
# Something for the logs
|
||||||
if ((not $anvil->data->{switches}{metadaata}) and (not $anvil->data->{switches}{'meta-data'}))
|
if ((not $anvil->data->{switches}{metadaata}) and (not $anvil->data->{switches}{'meta-data'}))
|
||||||
{
|
{
|
||||||
@ -315,7 +329,7 @@ sub start_server
|
|||||||
# Is the server already running somewhere?
|
# Is the server already running somewhere?
|
||||||
find_server($anvil);
|
find_server($anvil);
|
||||||
|
|
||||||
# Start the resource
|
# Start the resource, if needed.
|
||||||
start_drbd_resource($anvil);
|
start_drbd_resource($anvil);
|
||||||
|
|
||||||
# Still alive? Boot!
|
# Still alive? Boot!
|
||||||
@ -383,7 +397,7 @@ sub stop_drbd_resource
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
# This starts the drbd resource(s) for the requested server.
|
# This starts the drbd resource(s) for the requested server, if needed.
|
||||||
sub start_drbd_resource
|
sub start_drbd_resource
|
||||||
{
|
{
|
||||||
my ($anvil) = @_;
|
my ($anvil) = @_;
|
||||||
@ -397,6 +411,37 @@ sub start_drbd_resource
|
|||||||
peer => $peer,
|
peer => $peer,
|
||||||
}});
|
}});
|
||||||
|
|
||||||
|
# Do we need startup?
|
||||||
|
my $startup_needed = 0;
|
||||||
|
$anvil->DRBD->get_status({debug => 3});
|
||||||
|
foreach my $resource (sort {$a cmp $b} keys %{$anvil->data->{server}{$server}{resource}})
|
||||||
|
{
|
||||||
|
# Is the current resource up locally already? If it is, we're done.
|
||||||
|
my $role = $anvil->data->{drbd}{status}{$host}{resource}{$resource}{role};
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { role => $role }});
|
||||||
|
|
||||||
|
if ((lc($role) ne "secondary") && (lc($role) ne "primary"))
|
||||||
|
{
|
||||||
|
$startup_needed = 1;
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { startup_needed => $startup_needed }});
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0419", variables => {
|
||||||
|
resource => $resource,
|
||||||
|
role => $role,
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { startup_needed => $startup_needed }});
|
||||||
|
if (not $startup_needed)
|
||||||
|
{
|
||||||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0431"});
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
# Start DRBD locally.
|
# Start DRBD locally.
|
||||||
foreach my $resource (sort {$a cmp $b} keys %{$anvil->data->{server}{$server}{resource}})
|
foreach my $resource (sort {$a cmp $b} keys %{$anvil->data->{server}{$server}{resource}})
|
||||||
{
|
{
|
||||||
@ -578,7 +623,13 @@ sub stop_server
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Now stop the DRBD resource(s).
|
# Now stop the DRBD resource(s).
|
||||||
stop_drbd_resource($anvil);
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
||||||
|
'environment::OCF_RESKEY_CRM_meta_stop_drbd_resources' => $anvil->data->{environment}{OCF_RESKEY_CRM_meta_stop_drbd_resources},
|
||||||
|
}});
|
||||||
|
if ($anvil->data->{environment}{OCF_RESKEY_CRM_meta_stop_drbd_resources})
|
||||||
|
{
|
||||||
|
stop_drbd_resource($anvil);
|
||||||
|
}
|
||||||
|
|
||||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0324", variables => { server => $server }});
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0324", variables => { server => $server }});
|
||||||
$anvil->nice_exit({exit_code => 0});
|
$anvil->nice_exit({exit_code => 0});
|
||||||
|
@ -748,6 +748,9 @@ Failed to promote the DRBD resource: [#!variable!resource!#] primary. Expected a
|
|||||||
<key name="log_0428">[ Error ] - The server: [#!variable!server!#] can't by migrated to: [#!variable!target!#] because the resource: [#!variable!resource!#] isn't connected. The current connection state is: [#!variable!connection_state!#].</key>
|
<key name="log_0428">[ Error ] - The server: [#!variable!server!#] can't by migrated to: [#!variable!target!#] because the resource: [#!variable!resource!#] isn't connected. The current connection state is: [#!variable!connection_state!#].</key>
|
||||||
<key name="log_0429">[ Error ] - The server: [#!variable!server!#] can't by migrated to: [#!variable!target!#] because we can't reach it at all right now.</key>
|
<key name="log_0429">[ Error ] - The server: [#!variable!server!#] can't by migrated to: [#!variable!target!#] because we can't reach it at all right now.</key>
|
||||||
<key name="log_0430">The migration of the server: [#!variable!server!#] over to: [#!variable!target!#] isn't needed, it's already running on the target. Exiting successfully.</key>
|
<key name="log_0430">The migration of the server: [#!variable!server!#] over to: [#!variable!target!#] isn't needed, it's already running on the target. Exiting successfully.</key>
|
||||||
|
<key name="log_0431">All DRBD resources appear to be up, skipping individual DRBD resource startup.</key>
|
||||||
|
<key name="log_0432"><![CDATA[Database->archive_database() was not passed an array reference of tables to archive. Please pass an array reference using the 'tables' parameter.]]></key>
|
||||||
|
<key name="log_0433">The 'smaps' proc file for the process ID: [#!variable!pid!#] was not found. Did the program just close?</key>
|
||||||
|
|
||||||
<!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. -->
|
<!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. -->
|
||||||
<key name="t_0000">Test</key>
|
<key name="t_0000">Test</key>
|
||||||
@ -1033,6 +1036,8 @@ Failed to generate an RSA public key for the user: [#!variable!user!#]. The outp
|
|||||||
<key name="error_0062">The download job with UUID: [#!variable!job_uuid!#] is already being handled by another process.</key>
|
<key name="error_0062">The download job with UUID: [#!variable!job_uuid!#] is already being handled by another process.</key>
|
||||||
<key name="error_0063">Something went wrong trying to download: [#!variable!packages!#]. The return code should have been '0'. but: [#!variable!return_code!#] was received. Is a package missing upstream?</key>
|
<key name="error_0063">Something went wrong trying to download: [#!variable!packages!#]. The return code should have been '0'. but: [#!variable!return_code!#] was received. Is a package missing upstream?</key>
|
||||||
<key name="error_0064">A request to active the logical volume: [#!variable!path!#] was made, but that path doesn't exist or isn't a block device.</key>
|
<key name="error_0064">A request to active the logical volume: [#!variable!path!#] was made, but that path doesn't exist or isn't a block device.</key>
|
||||||
|
<key name="error_0065"><![CDATA[No program name given (via --program <name>), unable to proceed.]]></key>
|
||||||
|
<key name="error_0066"><![CDATA[The program: [#!variable!program!#] was not found to be running on this system.]]></key>
|
||||||
|
|
||||||
<!-- These are units, words and so on used when displaying information. -->
|
<!-- These are units, words and so on used when displaying information. -->
|
||||||
<key name="unit_0001">Yes</key>
|
<key name="unit_0001">Yes</key>
|
||||||
|
119
tools/anvil-check-memory
Executable file
119
tools/anvil-check-memory
Executable file
@ -0,0 +1,119 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
#
|
||||||
|
# This reports the total memory used by all processes with to passed-in program name.
|
||||||
|
#
|
||||||
|
# The size in bytes is returned. If '0' is reported, check the exit code to see why.
|
||||||
|
#
|
||||||
|
# This software was created by Alteeve's Niche! Inc. and has been released under the terms of the GNU GPL
|
||||||
|
# version 2.
|
||||||
|
#
|
||||||
|
# https://alteeve.com
|
||||||
|
#
|
||||||
|
# Exit Codes:
|
||||||
|
# 0 - Success
|
||||||
|
# 1 - No program name passed-in.
|
||||||
|
# 2 - No PIDs found for the passed-in program name.
|
||||||
|
# 3 - No PID returned by pgrep
|
||||||
|
#
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Anvil::Tools;
|
||||||
|
|
||||||
|
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
|
||||||
|
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
|
||||||
|
if (($running_directory =~ /^\./) && ($ENV{PWD}))
|
||||||
|
{
|
||||||
|
$running_directory =~ s/^\./$ENV{PWD}/;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete.
|
||||||
|
$| = 1;
|
||||||
|
|
||||||
|
my $anvil = Anvil::Tools->new({log_level => 2, log_secure => 1});
|
||||||
|
|
||||||
|
$anvil->data->{switches}{program} = "";
|
||||||
|
$anvil->Get->switches;
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
||||||
|
'switches::program' => $anvil->data->{switches}{program},
|
||||||
|
}});
|
||||||
|
|
||||||
|
$anvil->data->{memory}{total} = 0;
|
||||||
|
|
||||||
|
# If we weren't given a program, exit
|
||||||
|
if (not $anvil->data->{switches}{program})
|
||||||
|
{
|
||||||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0065"});
|
||||||
|
print "#!error!#\n";
|
||||||
|
$anvil->nice_exit({exit_code => 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find the PID(s) of the program.
|
||||||
|
$anvil->data->{sys}{pids} = $anvil->System->pids({ignore_me => 1, program_name => $anvil->data->{switches}{program}});
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { 'sys::pids' => $anvil->data->{sys}{pids} }});
|
||||||
|
|
||||||
|
my $pids_found = @{$anvil->data->{sys}{pids}};
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { pids_found => $pids_found }});
|
||||||
|
|
||||||
|
if (not $pids_found)
|
||||||
|
{
|
||||||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0066", variables => { prorgram => $anvil->data->{switches}{program} }});
|
||||||
|
print $anvil->data->{switches}{program}." = ".$anvil->data->{memory}{total}."\n";
|
||||||
|
$anvil->nice_exit({exit_code => 2});
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read in the smaps for each pid
|
||||||
|
foreach my $pid (sort {$a cmp $b} @{$anvil->data->{sys}{pids}})
|
||||||
|
{
|
||||||
|
my $smaps_path = "/proc/".$pid."/smaps";
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { smaps_path => $smaps_path }});
|
||||||
|
|
||||||
|
# This will store the amount of RAM used by this specific PID.
|
||||||
|
$an->data->{memory}{pid}{$pid} = 0;
|
||||||
|
|
||||||
|
if (not -e $smaps_path)
|
||||||
|
{
|
||||||
|
# It is possible that the program just closed.
|
||||||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 0, level => 1, key => "log_0433", variables => { pid => $pid }});
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read in the file.
|
||||||
|
my $body = $anvil->Storage->read_file({file => $smaps_path});
|
||||||
|
foreach my $line (split/\n/, $body)
|
||||||
|
{
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { line => $line }});
|
||||||
|
if ($line =~ /^Private_Dirty:\s+(\d+) (.*B)$/)
|
||||||
|
{
|
||||||
|
my $size = $1;
|
||||||
|
my $type = $2;
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
||||||
|
type => $type,
|
||||||
|
size => $size,
|
||||||
|
}});
|
||||||
|
next if not $size;
|
||||||
|
next if $size =~ /\D/;
|
||||||
|
|
||||||
|
# This uses 'kB' for 'KiB' >_>
|
||||||
|
$type = lc($type);
|
||||||
|
$type =~ s/b$/ib/ if $type !~ /ib$/;
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }});
|
||||||
|
|
||||||
|
my $size_in_bytes = $anvil->Convert->human_readable_to_bytes({size => $size, type => $type, base2 => 1});
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
||||||
|
size_in_bytes => $anvil->Convert->add_commas({number => $size_in_bytes})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $size_in_bytes}).")",
|
||||||
|
}});
|
||||||
|
|
||||||
|
$anvil->data->{memory}{pid}{$pid} += $size_in_bytes;
|
||||||
|
$anvil->data->{memory}{total} += $size_in_bytes;
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
||||||
|
"memory::pid::${pid}" => $anvil->Convert->add_commas({number => $anvil->data->{memory}{pid}{$pid}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{memory}{pid}{$pid}}).")",
|
||||||
|
'memory::total' => $anvil->Convert->add_commas({number => $anvil->data->{memory}{total}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{memory}{total}}).")",
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Report and exit.
|
||||||
|
print $anvil->data->{switches}{program}." = ".$an->data->{memory}{total}." # ".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{memory}{total}})."\n";
|
||||||
|
$anvil->nice_exit({exit_code => 0});
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
#
|
#
|
||||||
# This is called when striker needs to configure the local network and user accounts.
|
# This is called when striker, an node or a DR host needs to configure the local network and user accounts.
|
||||||
#
|
#
|
||||||
# Exit codes;
|
# Exit codes;
|
||||||
# 0 = Normal exit.
|
# 0 = Normal exit.
|
||||||
@ -114,47 +114,65 @@ sub update_passwords
|
|||||||
{
|
{
|
||||||
my ($anvil) = @_;
|
my ($anvil) = @_;
|
||||||
|
|
||||||
# Set the passwords
|
# Is this a striker dashboard, node or DR host?
|
||||||
my $password = $anvil->data->{variables}{form}{config_step2}{striker_password}{value};
|
my $type = $anvil->System->get_host_type();
|
||||||
my $temp_file = "/tmp/anvil-".$anvil->Get->uuid;
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, list => { type => $type }});
|
||||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, secure => 1, list => { password => $password }});
|
|
||||||
|
|
||||||
# Write the password into a temporary file.
|
if ($type eq "dashboard")
|
||||||
my $error = $anvil->Storage->write_file({
|
|
||||||
body => $password,
|
|
||||||
file => $temp_file,
|
|
||||||
group => "root",
|
|
||||||
mode => "0600",
|
|
||||||
overwrite => 1,
|
|
||||||
secure => 1,
|
|
||||||
user => "root",
|
|
||||||
});
|
|
||||||
|
|
||||||
# Call anvil-change-password
|
|
||||||
if ($error)
|
|
||||||
{
|
{
|
||||||
# Couldn't write the temp file.
|
# Set the passwords
|
||||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "message_0030", variables => { file => $temp_file }});
|
my $password = $anvil->data->{variables}{form}{config_step2}{striker_password}{value};
|
||||||
$anvil->nice_exit({code => 5});
|
my $temp_file = "/tmp/anvil-".$anvil->Get->uuid;
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, secure => 1, list => { password => $password }});
|
||||||
|
|
||||||
|
# Write the password into a temporary file.
|
||||||
|
my $error = $anvil->Storage->write_file({
|
||||||
|
body => $password,
|
||||||
|
file => $temp_file,
|
||||||
|
group => "root",
|
||||||
|
mode => "0600",
|
||||||
|
overwrite => 1,
|
||||||
|
secure => 1,
|
||||||
|
user => "root",
|
||||||
|
});
|
||||||
|
|
||||||
|
# Call anvil-change-password
|
||||||
|
if ($error)
|
||||||
|
{
|
||||||
|
# Couldn't write the temp file.
|
||||||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "message_0030", variables => { file => $temp_file }});
|
||||||
|
$anvil->nice_exit({code => 5});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my $return_code = "";
|
||||||
|
my ($output, $return_code) = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{'anvil-change-password'}." -y --password-file ".$temp_file });
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => { output => $output, return_code => $return_code }});
|
||||||
|
foreach my $line (split/\n/, $output)
|
||||||
|
{
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => { line => $line }});
|
||||||
|
}
|
||||||
|
|
||||||
|
# Unlink the temp file.
|
||||||
|
unlink $temp_file;
|
||||||
|
|
||||||
|
if ($return_code)
|
||||||
|
{
|
||||||
|
# Something went wrong
|
||||||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "error_0011", variables => { return_code => $return_code }});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
my $return_code = "";
|
if ($type eq "node")
|
||||||
my ($output, $return_code) = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{'anvil-change-password'}." -y --password-file ".$temp_file });
|
|
||||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => { output => $output, return_code => $return_code }});
|
|
||||||
foreach my $line (split/\n/, $output)
|
|
||||||
{
|
{
|
||||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => { line => $line }});
|
# We'll need to update pcsd's password as well.
|
||||||
}
|
}
|
||||||
|
|
||||||
# Unlink the temp file.
|
# Set passwords that are common to nodes and DR hosts.
|
||||||
unlink $temp_file;
|
|
||||||
|
|
||||||
if ($return_code)
|
|
||||||
{
|
|
||||||
# Something went wrong
|
|
||||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "error_0011", variables => { return_code => $return_code }});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$anvil->Job->update_progress({
|
$anvil->Job->update_progress({
|
||||||
@ -644,6 +662,7 @@ sub reconfigure_network
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# We're half-way there.
|
||||||
$anvil->Job->update_progress({
|
$anvil->Job->update_progress({
|
||||||
progress => 50,
|
progress => 50,
|
||||||
job_uuid => $anvil->data->{job}{uuid},
|
job_uuid => $anvil->data->{job}{uuid},
|
@ -75,7 +75,6 @@ if ((not $anvil->data->{switches}{abort}) && (not $anvil->data->{switches}{url})
|
|||||||
{
|
{
|
||||||
get_job_details($anvil);
|
get_job_details($anvil);
|
||||||
}
|
}
|
||||||
die;
|
|
||||||
|
|
||||||
# Do what now?
|
# Do what now?
|
||||||
if ($anvil->data->{switches}{abort})
|
if ($anvil->data->{switches}{abort})
|
||||||
|
Loading…
Reference in New Issue
Block a user