Merge pull request #108 from Tsu-ba-me/issues/5-get-shared-storage

Web UI: add new `get_shared_storage` endpoint; move old to `get_filesystems`
main
Digimer 4 years ago committed by GitHub
commit 2327c8cefd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 183
      cgi-bin/get_filesystems
  2. 236
      cgi-bin/get_shared_storage

@ -0,0 +1,183 @@
#!/usr/bin/perl
#
# This prints JSON formated data reporting the status of an file systems on nodes and DR hosts.
#
use strict;
use warnings;
use Anvil::Tools;
use Data::Dumper;
use JSON;
$| = 1;
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
if (($running_directory =~ /^\./) && ($ENV{PWD}))
{
$running_directory =~ s/^\./$ENV{PWD}/;
}
my $anvil = Anvil::Tools->new();
$anvil->Get->switches;
$anvil->Database->connect;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
if (not $anvil->data->{sys}{database}{connections})
{
# No databases, exit.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, priority => "err", key => "error_0003"});
$anvil->nice_exit({exit_code => 1});
}
# Read in any CGI variables, if needed.
$anvil->Get->cgi();
$anvil->Database->get_hosts();
$anvil->Database->get_anvils();
print $anvil->Template->get({file => "shared.html", name => "json_headers", show_name => 0})."\n";
my $hash = { file_systems => [] };
my $anvil_uuid = "";
if ($anvil->data->{cgi}{anvil_uuid}{value})
{
$anvil_uuid = $anvil->data->{cgi}{anvil_uuid}{value};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }});
}
elsif ($anvil->data->{switches}{'anvil-uuid'})
{
$anvil_uuid = $anvil->data->{switches}{'anvil-uuid'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }});
}
if ((not $anvil_uuid) or (not exists $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}))
{
$anvil->data->{anvil_status}{anvil_name} = "!!invalid!anvil_uuid!!";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'anvil_status::anvil_name' => $anvil->data->{anvil_status}{anvil_name} }});
}
else
{
my $node1_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid};
my $node2_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
my $dr1_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
node1_uuid => $node1_uuid,
node2_uuid => $node2_uuid,
dr1_uuid => $dr1_uuid,
}});
my $query = "
SELECT
a.host_uuid,
a.host_name,
b.scan_filesystem_mount_point,
b.scan_filesystem_size,
b.scan_filesystem_used
FROM
hosts a,
scan_filesystems b
WHERE
a.host_uuid = b.scan_filesystem_host_uuid
AND
(
a.host_uuid = ".$anvil->Database->quote($node1_uuid)."
OR
a.host_uuid = ".$anvil->Database->quote($node2_uuid);
if ($dr1_uuid)
{
$query .= "
OR
a.host_uuid = ".$anvil->Database->quote($dr1_uuid);
}
$query .= "
)
ORDER BY
a.host_name ASC,
b.scan_filesystem_mount_point DESC
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $host_uuid = $row->[0];
my $host_name = $row->[1];
my $mount_point = $row->[2];
my $size = $row->[3];
my $used = $row->[4];
my $free = $size - $used;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host_uuid => $host_uuid,
host_name => $host_name,
mount_point => $mount_point,
size => $anvil->Convert->add_commas({number => $size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $size}).")",,
used => $anvil->Convert->add_commas({number => $used})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $used}).")",,
free => $anvil->Convert->add_commas({number => $free})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $free}).")",,
}});
$anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{host_name} = $host_name;
$anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{total} = $size;
$anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{free} = $free;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"raw::file_systems::${mount_point}::nodes::${host_uuid}::host_name" => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{host_name},
"raw::file_systems::${mount_point}::nodes::${host_uuid}::total" => $anvil->Convert->add_commas({number => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{total}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{total}}).")",,
"raw::file_systems::${mount_point}::nodes::${host_uuid}::free" => $anvil->Convert->add_commas({number => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{free}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{free}}).")",,
}});
}
foreach my $mount_point (sort {$a cmp $b} keys %{$anvil->data->{raw}{file_systems}})
{
# Make a FS hash, which will be pushed into the file_systems array in the response body.
my $file_system = {};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mount_point => $mount_point }});
$file_system->{mount_point} = $mount_point;
$file_system->{hosts} = [];
my $nodes = [$node1_uuid, $node2_uuid];
if ($dr1_uuid)
{
push @{$nodes}, $dr1_uuid;
}
foreach my $host_uuid (@{$nodes})
{
my $host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host_uuid => $host_uuid,
host_name => $host_name,
}});
if (exists $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid})
{
push @{$file_system->{hosts}}, {
host_uuid => $host_uuid,
host_name => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{host_name},
# \1 will be transformed to the JSON boolean "true" by the JSON module.
is_mounted => \1,
# FS total size is required by the spec to be an JSON number rather than string.
total => int($anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{total}),
free => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{free},
}
}
else
{
push @{$file_system->{hosts}}, {
host_uuid => $host_uuid,
host_name => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name},
# \0 will be transformed to the JSON boolean "false" by the JSON module.
is_mounted => \0,
total => 0,
free => 0,
}
}
}
# Push the filled FS has into the response body's file_systems array.
push(@{$hash->{file_systems}}, $file_system);
}
}
print JSON->new->utf8->encode($hash)."\n";

@ -1,6 +1,6 @@
#!/usr/bin/perl #!/usr/bin/perl
# #
# This prints JSON formated data reporting the status of an file systems on nodes and DR hosts. # Prints JSON formatted data reporting the status of shared storage (a.k.a. storage groups/shared VGs)
# #
use strict; use strict;
@ -20,164 +20,136 @@ if (($running_directory =~ /^\./) && ($ENV{PWD}))
my $anvil = Anvil::Tools->new(); my $anvil = Anvil::Tools->new();
$anvil->Get->switches; sub handle_invalid_uuid
$anvil->Database->connect;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
if (not $anvil->data->{sys}{database}{connections})
{ {
# No databases, exit. my $parameters = shift;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, priority => "err", key => "error_0003"}); my $name = $parameters->{name};
$anvil->nice_exit({exit_code => 1}); my $uuid = $parameters->{uuid};
$anvil->Log->entry({
source => $THIS_FILE,
line => __LINE__,
level => 0,
'print' => 1,
priority => "err",
key => "error_0160",
variables => { name => $name, uuid => $uuid }
});
$anvil->nice_exit({ exit_code => 1 });
} }
# Read in any CGI variables, if needed. sub get_storage_groups
$anvil->Get->cgi();
$anvil->Database->get_hosts();
$anvil->Database->get_anvils();
print $anvil->Template->get({file => "shared.html", name => "json_headers", show_name => 0})."\n";
my $hash = { file_systems => [] };
my $anvil_uuid = "";
if ($anvil->data->{cgi}{anvil_uuid}{value})
{ {
$anvil_uuid = $anvil->data->{cgi}{anvil_uuid}{value}; my $parameters = shift;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); my $anvil_uuid = $parameters->{anvil_uuid};
}
elsif ($anvil->data->{switches}{'anvil-uuid'}) my $storage_groups = [];
{
$anvil_uuid = $anvil->data->{switches}{'anvil-uuid'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }});
}
if ((not $anvil_uuid) or (not exists $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}))
{
$anvil->data->{anvil_status}{anvil_name} = "!!invalid!anvil_uuid!!";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'anvil_status::anvil_name' => $anvil->data->{anvil_status}{anvil_name} }});
}
else
{
my $node1_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid};
my $node2_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid};
my $dr1_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
node1_uuid => $node1_uuid,
node2_uuid => $node2_uuid,
dr1_uuid => $dr1_uuid,
}});
# Use DISTINCT ON (...) to limit the occurence of a storage group to 1 and
# ORDER BY [free] ASC to only select the storage with lowest free space.
my $query = " my $query = "
SELECT SELECT
a.host_uuid, DISTINCT ON (sgr.storage_group_uuid) storage_group_uuid,
a.host_name, sgr.storage_group_name,
b.scan_filesystem_mount_point, slv.scan_lvm_vg_size,
b.scan_filesystem_size, slv.scan_lvm_vg_free
b.scan_filesystem_used
FROM FROM
hosts a, anvils anv,
scan_filesystems b storage_groups sgr,
storage_group_members sgm,
scan_lvm_vgs slv
WHERE WHERE
a.host_uuid = b.scan_filesystem_host_uuid anv.anvil_uuid = sgr.storage_group_anvil_uuid
AND AND
( sgr.storage_group_uuid = sgm.storage_group_member_storage_group_uuid
a.host_uuid = ".$anvil->Database->quote($node1_uuid)." AND
OR sgm.storage_group_member_vg_uuid = slv.scan_lvm_vg_internal_uuid
a.host_uuid = ".$anvil->Database->quote($node2_uuid); AND
if ($dr1_uuid) anv.anvil_uuid = ".$anvil->Database->quote($anvil_uuid)."
{
$query .= "
OR
a.host_uuid = ".$anvil->Database->quote($dr1_uuid);
}
$query .= "
)
ORDER BY ORDER BY
a.host_name ASC, sgr.storage_group_uuid ASC,
b.scan_filesystem_mount_point DESC slv.scan_lvm_vg_free ASC
;"; ;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results}; my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
results => $results, results => $results,
count => $count, count => $count
}}); }});
foreach my $row (@{$results}) foreach my $row (@{$results})
{ {
my $host_uuid = $row->[0]; my $storage_group_uuid = $row->[0];
my $host_name = $row->[1]; my $storage_group_name = $row->[1];
my $mount_point = $row->[2]; my $scan_lvm_vg_size = $row->[2];
my $size = $row->[3]; my $scan_lvm_vg_free = $row->[3];
my $used = $row->[4];
my $free = $size - $used;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host_uuid => $host_uuid, storage_group_uuid => $storage_group_uuid,
host_name => $host_name, storage_group_name => $storage_group_name,
mount_point => $mount_point, scan_lvm_vg_size => $scan_lvm_vg_size,
size => $anvil->Convert->add_commas({number => $size})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $size}).")",, scan_lvm_vg_free => $scan_lvm_vg_free
used => $anvil->Convert->add_commas({number => $used})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $used}).")",,
free => $anvil->Convert->add_commas({number => $free})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $free}).")",,
}}); }});
$anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{host_name} = $host_name; push(@{$storage_groups}, {
$anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{total} = $size; storage_group_uuid => $storage_group_uuid,
$anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{free} = $free; storage_group_name => $storage_group_name,
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_total => int($scan_lvm_vg_size),
"raw::file_systems::${mount_point}::nodes::${host_uuid}::host_name" => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{host_name}, storage_group_free => int($scan_lvm_vg_free)
"raw::file_systems::${mount_point}::nodes::${host_uuid}::total" => $anvil->Convert->add_commas({number => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{total}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{total}}).")",, });
"raw::file_systems::${mount_point}::nodes::${host_uuid}::free" => $anvil->Convert->add_commas({number => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{free}})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{free}}).")",,
}});
} }
foreach my $mount_point (sort {$a cmp $b} keys %{$anvil->data->{raw}{file_systems}}) return $storage_groups;
}
$anvil->Get->switches;
$anvil->Database->connect;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
if (not $anvil->data->{sys}{database}{connections})
{
# No databases, exit.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, priority => "err", key => "error_0003"});
$anvil->nice_exit({exit_code => 1});
}
# Read in any CGI variables, if needed.
$anvil->Get->cgi();
$anvil->Database->get_hosts();
$anvil->Database->get_anvils();
print $anvil->Template->get({file => "shared.html", name => "json_headers", show_name => 0})."\n";
my $anvil_uuid = exists $anvil->data->{cgi}{anvil_uuid}{value} ? $anvil->data->{cgi}{anvil_uuid}{value} : $anvil->data->{switches}{'anvil-uuid'};
my $anvil_uuid_variable_name = "anvil UUID";
my $response_body = {};
if ($anvil_uuid)
{
if (exists $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid})
{ {
# Make a FS hash, which will be pushed into the file_systems array in the response body. $anvil->Log->variables({
my $file_system = {}; source => $THIS_FILE,
line => __LINE__,
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mount_point => $mount_point }}); level => 2,
$file_system->{mount_point} = $mount_point; list => {
$file_system->{hosts} = []; message => "Valid ".$anvil_uuid_variable_name." received.",
my $nodes = [$node1_uuid, $node2_uuid]; anvil_uuid => $anvil_uuid
if ($dr1_uuid)
{
push @{$nodes}, $dr1_uuid;
}
foreach my $host_uuid (@{$nodes})
{
my $host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host_uuid => $host_uuid,
host_name => $host_name,
}});
if (exists $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid})
{
push @{$file_system->{hosts}}, {
host_uuid => $host_uuid,
host_name => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{host_name},
# \1 will be transformed to the JSON boolean "true" by the JSON module.
is_mounted => \1,
# FS total size is required by the spec to be an JSON number rather than string.
total => int($anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{total}),
free => $anvil->data->{raw}{file_systems}{$mount_point}{nodes}{$host_uuid}{free},
}
}
else
{
push @{$file_system->{hosts}}, {
host_uuid => $host_uuid,
host_name => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name},
# \0 will be transformed to the JSON boolean "false" by the JSON module.
is_mounted => \0,
total => 0,
free => 0,
}
} }
} });
# Push the filled FS has into the response body's file_systems array. $response_body->{storage_groups} = get_storage_groups({ anvil_uuid => $anvil_uuid });
push(@{$hash->{file_systems}}, $file_system); }
else
{
handle_invalid_uuid({ name => $anvil_uuid_variable_name, uuid => $anvil_uuid });
} }
} }
else
{
handle_invalid_uuid({ name => $anvil_uuid_variable_name, uuid => $anvil_uuid });
}
print JSON->new->utf8->encode($hash)."\n"; print JSON->new->utf8->encode($response_body)."\n";

Loading…
Cancel
Save