|
|
@ -24,6 +24,7 @@ my $THIS_FILE = "Storage.pm"; |
|
|
|
# delete_file |
|
|
|
# delete_file |
|
|
|
# find |
|
|
|
# find |
|
|
|
# get_file_stats |
|
|
|
# get_file_stats |
|
|
|
|
|
|
|
# get_size_of_block_device |
|
|
|
# get_storage_group_details |
|
|
|
# get_storage_group_details |
|
|
|
# get_storage_group_from_path |
|
|
|
# get_storage_group_from_path |
|
|
|
# make_directory |
|
|
|
# make_directory |
|
|
@ -1626,6 +1627,305 @@ sub get_file_stats |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=head2 get_size_of_block_device |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This takes a block device path (DRBD or LVM LV path) and tries to find the size of the device as it was recorded in the database. If found, the size in bytes is returned. If there is a problem, C<< !!error!! >> is returned. If the device in not found in the database, an empty string is returned. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
B<< Note >>: If there are multiple results, the first found will be returned. If the results span multiple Anvil! systems, this could be a problem. If this is a concern, specifify either the C<< host_uuid >> or C<< anvil_uuid >> parameters. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Parameters; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=head3 anvil_uuid (optional) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In the case of an ambiguous path (a path found on multiple Anvil! systems), this can be set to specify which Anvil! we're searching for. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=head3 host_uuid (optional) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In the case of an ambiguous path (a path found on multiple hosts), this can be set to specify which host we're searching for. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=head3 path (required) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This is the full block device path. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=cut |
|
|
|
|
|
|
|
sub get_size_of_block_device |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
my $self = shift; |
|
|
|
|
|
|
|
my $parameter = shift; |
|
|
|
|
|
|
|
my $anvil = $self->parent; |
|
|
|
|
|
|
|
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; |
|
|
|
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Storage->get_size_of_block_device()" }}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
my $anvil_uuid = defined $parameter->{anvil_uuid} ? $parameter->{anvil_uuid} : ""; |
|
|
|
|
|
|
|
my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : ""; |
|
|
|
|
|
|
|
my $path = defined $parameter->{path} ? $parameter->{path} : ""; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { |
|
|
|
|
|
|
|
anvil_uuid => $anvil_uuid, |
|
|
|
|
|
|
|
host_uuid => $host_uuid, |
|
|
|
|
|
|
|
path => $path, |
|
|
|
|
|
|
|
}}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (not $path) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
# No source passed. |
|
|
|
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Storage->get_size_of_block_device()", parameter => "path" }}); |
|
|
|
|
|
|
|
return('!!error!!'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$anvil->Database->get_anvils({debug => $debug}); |
|
|
|
|
|
|
|
my $node1_host_uuid = ""; |
|
|
|
|
|
|
|
my $node2_host_uuid = ""; |
|
|
|
|
|
|
|
my $dr1_host_uuid = ""; |
|
|
|
|
|
|
|
if ($anvil_uuid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$node1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; |
|
|
|
|
|
|
|
$node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; |
|
|
|
|
|
|
|
$dr1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid}; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { |
|
|
|
|
|
|
|
node1_host_uuid => $node1_host_uuid, |
|
|
|
|
|
|
|
node1_host_uuid => $node2_host_uuid, |
|
|
|
|
|
|
|
dr1_host_uuid => $dr1_host_uuid, |
|
|
|
|
|
|
|
}}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Is this a DRBD path? |
|
|
|
|
|
|
|
if ($path !~ /drbd/) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
# See if we can find this in LVs |
|
|
|
|
|
|
|
my $query = " |
|
|
|
|
|
|
|
SELECT |
|
|
|
|
|
|
|
scan_lvm_lv_host_uuid, |
|
|
|
|
|
|
|
scan_lvm_lv_size |
|
|
|
|
|
|
|
FROM |
|
|
|
|
|
|
|
scan_lvm_lvs |
|
|
|
|
|
|
|
WHERE |
|
|
|
|
|
|
|
scan_lvm_lv_name != 'DELETED' |
|
|
|
|
|
|
|
AND |
|
|
|
|
|
|
|
scan_lvm_lv_path = ".$anvil->Database->quote($path); |
|
|
|
|
|
|
|
if ($host_uuid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$query .= " |
|
|
|
|
|
|
|
AND |
|
|
|
|
|
|
|
scan_lvm_lv_host_uuid = ".$anvil->Database->quote($host_uuid); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
elsif ($anvil_uuid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$query .= " |
|
|
|
|
|
|
|
AND |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
scan_lvm_lv_host_uuid = ".$anvil->Database->quote($node1_host_uuid)." |
|
|
|
|
|
|
|
OR |
|
|
|
|
|
|
|
scan_lvm_lv_host_uuid = ".$anvil->Database->quote($node2_host_uuid); |
|
|
|
|
|
|
|
if ($dr1_host_uuid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$query .= " |
|
|
|
|
|
|
|
OR |
|
|
|
|
|
|
|
scan_lvm_lv_host_uuid = ".$anvil->Database->quote($dr1_host_uuid); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
$query .= " |
|
|
|
|
|
|
|
)"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
$query .= " |
|
|
|
|
|
|
|
LIMIT 1 |
|
|
|
|
|
|
|
;"; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, 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 => $debug, list => { |
|
|
|
|
|
|
|
results => $results, |
|
|
|
|
|
|
|
count => $count, |
|
|
|
|
|
|
|
}}); |
|
|
|
|
|
|
|
if (not $count) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
# Not found |
|
|
|
|
|
|
|
return(""); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
my $scan_lvm_lv_host_uuid = $results->[0]->[0]; |
|
|
|
|
|
|
|
my $scan_lvm_lv_size = $results->[0]->[1]; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { |
|
|
|
|
|
|
|
scan_lvm_lv_host_uuid => $scan_lvm_lv_host_uuid, |
|
|
|
|
|
|
|
scan_lvm_lv_size => $scan_lvm_lv_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_lvm_lv_size}).")", |
|
|
|
|
|
|
|
}}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return($scan_lvm_lv_size); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
# Looks like it. If the device path is '/dev/drbd/by-res/...' we'll need to pull out the |
|
|
|
|
|
|
|
# resource name (server name) and volume number as the path only actually exists when DRBD is |
|
|
|
|
|
|
|
# up and isn't referenced in the config file. |
|
|
|
|
|
|
|
my $resource = ""; |
|
|
|
|
|
|
|
my $volume = ""; |
|
|
|
|
|
|
|
$anvil->DRBD->gather_data({debug => $debug}); |
|
|
|
|
|
|
|
if ($path =~ /\/dev\/drbd\/by-res\/(.*)\/(\d+)$/) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$resource = $1; |
|
|
|
|
|
|
|
$volume = $2; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { |
|
|
|
|
|
|
|
resource => $resource, |
|
|
|
|
|
|
|
volume => $volume, |
|
|
|
|
|
|
|
}}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
elsif ($path =~ /\/dev\/drbd_(.*)_(\d+)$/) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$resource = $1; |
|
|
|
|
|
|
|
$volume = $2; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { |
|
|
|
|
|
|
|
resource => $resource, |
|
|
|
|
|
|
|
volume => $volume, |
|
|
|
|
|
|
|
}}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
elsif ($path =~ /\/dev\/drbd(\d+)$/) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
# This is a direct path to a minor device, we'll need to find it in the config. |
|
|
|
|
|
|
|
my $minor = $1; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { minor => $minor }}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# If we were passed an anvil_uuid but not a host_uuid, don't use this machine's host UUID |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# These will be set if multiple options are found in the database. |
|
|
|
|
|
|
|
foreach my $this_resource (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}}) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_resource => $this_resource }}); |
|
|
|
|
|
|
|
foreach my $this_host_name (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$this_resource}{host}}) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_host_name => $this_host_name }}); |
|
|
|
|
|
|
|
foreach my $this_volume (sort {$a cmp $b} keys %{$$anvil->data->{new}{resource}{$this_resource}{host}{$this_host_name}{volume}}) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
my $this_minor = $anvil->data->{new}{resource}{$this_resource}{host}{$this_host_name}{volume}{$this_volume}{device_minor}; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { |
|
|
|
|
|
|
|
this_volume => $this_volume, |
|
|
|
|
|
|
|
this_minor => $this_minor, |
|
|
|
|
|
|
|
}}); |
|
|
|
|
|
|
|
next if $this_minor ne $minor; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
my $this_host_uuid = $anvil->Get->host_uuid_from_name({host_name => $this_host_name}); |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { this_host_uuid => $this_host_uuid }}); |
|
|
|
|
|
|
|
next if not $this_host_uuid; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Sorry, this is a bit of a mess. Logic is; If we're given a |
|
|
|
|
|
|
|
# host_uuid, and it matches, use it. Otherwise, if an |
|
|
|
|
|
|
|
# anvil_uuid is passed, and either node 1 or 2's UUID, or if |
|
|
|
|
|
|
|
# there is a DR host, if it's host UUID matches, then we can |
|
|
|
|
|
|
|
# use this. |
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
($host_uuid) && ($host_uuid eq $this_host_uuid) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
or |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
($anvil_uuid) && |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
($this_host_uuid eq $node1_host_uuid) or |
|
|
|
|
|
|
|
($this_host_uuid eq $node2_host_uuid) or |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
($dr1_host_uuid) && |
|
|
|
|
|
|
|
($this_host_uuid eq $dr1_host_uuid) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
# This is a node in the requested cluster. |
|
|
|
|
|
|
|
$resource = $this_resource; |
|
|
|
|
|
|
|
$volume = $this_volume; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { |
|
|
|
|
|
|
|
resource => $resource, |
|
|
|
|
|
|
|
volume => $volume, |
|
|
|
|
|
|
|
}}); |
|
|
|
|
|
|
|
last; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (not $host_uuid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$host_uuid = $this_host_uuid; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (not $resource) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
# Not found. |
|
|
|
|
|
|
|
return(""); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# The DRBD query is sorted by size because 'Secondary' resources can't have their size read |
|
|
|
|
|
|
|
# and get set to '0'. |
|
|
|
|
|
|
|
my $query = " |
|
|
|
|
|
|
|
SELECT |
|
|
|
|
|
|
|
a.scan_drbd_resource_host_uuid, |
|
|
|
|
|
|
|
b.scan_drbd_volume_size |
|
|
|
|
|
|
|
FROM |
|
|
|
|
|
|
|
scan_drbd_resources a, |
|
|
|
|
|
|
|
scan_drbd_volumes b |
|
|
|
|
|
|
|
WHERE |
|
|
|
|
|
|
|
a.scan_drbd_resource_uuid = b.scan_drbd_volume_scan_drbd_resource_uuid |
|
|
|
|
|
|
|
AND |
|
|
|
|
|
|
|
a.scan_drbd_resource_xml != 'DELETED' |
|
|
|
|
|
|
|
AND |
|
|
|
|
|
|
|
a.scan_drbd_resource_name = ".$anvil->Database->quote($resource)." |
|
|
|
|
|
|
|
AND |
|
|
|
|
|
|
|
b.scan_drbd_volume_number = ".$anvil->Database->quote($volume); |
|
|
|
|
|
|
|
if ($host_uuid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$query .= " |
|
|
|
|
|
|
|
AND |
|
|
|
|
|
|
|
a.scan_drbd_resource_host_uuid = ".$anvil->Database->quote($host_uuid); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
elsif ($anvil_uuid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$query .= " |
|
|
|
|
|
|
|
AND |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
a.scan_drbd_resource_host_uuid = ".$anvil->Database->quote($node1_host_uuid)." |
|
|
|
|
|
|
|
OR |
|
|
|
|
|
|
|
a.scan_drbd_resource_host_uuid = ".$anvil->Database->quote($node2_host_uuid); |
|
|
|
|
|
|
|
if ($dr1_host_uuid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$query .= " |
|
|
|
|
|
|
|
OR |
|
|
|
|
|
|
|
a.scan_drbd_resource_host_uuid = ".$anvil->Database->quote($dr1_host_uuid); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
$query .= " |
|
|
|
|
|
|
|
)"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
$query .= " |
|
|
|
|
|
|
|
ORDER BY |
|
|
|
|
|
|
|
scan_drbd_volume_size DESC |
|
|
|
|
|
|
|
LIMIT 1;"; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, 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 => $debug, list => { |
|
|
|
|
|
|
|
results => $results, |
|
|
|
|
|
|
|
count => $count, |
|
|
|
|
|
|
|
}}); |
|
|
|
|
|
|
|
if (not $count) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
# Not found |
|
|
|
|
|
|
|
return(""); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
my $scan_drbd_resource_host_uuid = $results->[0]->[0]; |
|
|
|
|
|
|
|
my $scan_drbd_volume_size = $results->[0]->[1]; |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { |
|
|
|
|
|
|
|
scan_drbd_resource_host_uuid => $scan_drbd_resource_host_uuid, |
|
|
|
|
|
|
|
scan_drbd_volume_size => $scan_drbd_volume_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $scan_drbd_volume_size}).")", |
|
|
|
|
|
|
|
}}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return($scan_drbd_volume_size); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return(""); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=head2 get_storage_group_details |
|
|
|
=head2 get_storage_group_details |
|
|
|
|
|
|
|
|
|
|
|
This takes a C<< storage_group_uuid >> and loads information about members into the following hash; |
|
|
|
This takes a C<< storage_group_uuid >> and loads information about members into the following hash; |
|
|
@ -1825,10 +2125,6 @@ sub get_storage_group_from_path |
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { minor => $minor }}); |
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { minor => $minor }}); |
|
|
|
|
|
|
|
|
|
|
|
$anvil->Database->get_anvils({debug => $debug}); |
|
|
|
$anvil->Database->get_anvils({debug => $debug}); |
|
|
|
my $local_host_uuid = $anvil->Get->host_uuid({debug => $debug}); |
|
|
|
|
|
|
|
my $local_anvil_uuid = $anvil->Cluster->get_anvil_uuid({debug => $debug}); |
|
|
|
|
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { local_anvil_uuid => $local_anvil_uuid }}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
my $node1_host_uuid = ""; |
|
|
|
my $node1_host_uuid = ""; |
|
|
|
my $node2_host_uuid = ""; |
|
|
|
my $node2_host_uuid = ""; |
|
|
|
my $dr1_host_uuid = ""; |
|
|
|
my $dr1_host_uuid = ""; |
|
|
|