* Created System->get_bridges() that gets a list of bridges (and connected interfaces, and data). Also created ->get_free_memory() that returns the amount of available RAM.

* Got ocf:alteeve:server validating bridges.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 5 years ago
parent 4a93682447
commit 16f79ca244
  1. 29
      Anvil/Tools/Server.pm
  2. 135
      Anvil/Tools/System.pm
  3. 66
      ocf/alteeve/server

@ -281,6 +281,7 @@ sub _parse_definition
$anvil->data->{server}{$server}{$source}{parsed} = $server_xml;
#print Dumper $server_xml;
#die;
# Pull out some basic server info.
$anvil->data->{server}{$server}{$source}{info}{uuid} = $server_xml->{uuid}->[0];
@ -691,5 +692,33 @@ sub _parse_definition
}
}
# Pull out console data
foreach my $hash_ref (@{$server_xml->{devices}->[0]->{interface}})
{
#print Dumper $hash_ref;
my $mac = $hash_ref->{mac}->[0]->{address};
$anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{bridge} = $hash_ref->{source}->[0]->{bridge};
$anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{alias} = $hash_ref->{alias}->[0]->{name};
$anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{target} = $hash_ref->{target}->[0]->{dev};
$anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{model} = $hash_ref->{model}->[0]->{type};
$anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{address}{bus} = $hash_ref->{address}->[0]->{bus};
$anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{address}{domain} = $hash_ref->{address}->[0]->{domain};
$anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{address}{type} = $hash_ref->{address}->[0]->{type};
$anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{address}{slot} = $hash_ref->{address}->[0]->{slot};
$anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{address}{function} = $hash_ref->{address}->[0]->{function};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"server::${server}::${source}::device::interface::${mac}::bridge" => $anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{bridge},
"server::${server}::${source}::device::interface::${mac}::alias" => $anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{alias},
"server::${server}::${source}::device::interface::${mac}::target" => $anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{target},
"server::${server}::${source}::device::interface::${mac}::model" => $anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{model},
"server::${server}::${source}::device::interface::${mac}::address::bus" => $anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{address}{bus},
"server::${server}::${source}::device::interface::${mac}::address::domain" => $anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{address}{domain},
"server::${server}::${source}::device::interface::${mac}::address::type" => $anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{address}{type},
"server::${server}::${source}::device::interface::${mac}::address::slot" => $anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{address}{slot},
"server::${server}::${source}::device::interface::${mac}::address::function" => $anvil->data->{server}{$server}{$source}{device}{interface}{$mac}{address}{function},
}});
}
return(0);
}

@ -20,6 +20,8 @@ my $THIS_FILE = "System.pm";
# check_daemon
# check_if_configured
# check_memory
# get_bridges
# get_free_memory
# get_host_type
# enable_daemon
# find_matching_ip
@ -541,6 +543,139 @@ sub check_memory
return($used_ram);
}
=hed2 get_bridges
This finds a list of bridges on the host. Bridges that are found are stored is '
=cut
sub get_bridges
{
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 => "System->get_bridges()" }});
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{bridge}." -json -details link show"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
}});
# Delete any previously known data
if (exists $anvil->data->{'local'}{network}{bridges})
{
delete $anvil->data->{'local'}{network}{bridges};
};
my $json = JSON->new->allow_nonref;
my $bridge_data = $json->decode($output);
#print Dumper $bridge_data;
foreach my $hash_ref (@{$bridge_data})
{
# If the ifname and master are the same, it's a bridge.
my $type = "interface";
my $interface_name = $hash_ref->{ifname};
my $master_bridge = $hash_ref->{master};
if ($interface_name eq $master_bridge)
{
$type = "bridge";
$anvil->data->{'local'}{network}{bridges}{bridge}{$interface_name}{found} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::bridge::${interface_name}::found" => $anvil->data->{'local'}{network}{bridges}{bridge}{$interface_name}{found},
}});
}
else
{
# Store this interface under the bridge.
$anvil->data->{'local'}{network}{bridges}{bridge}{$master_bridge}{connected_interface}{$interface_name} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::bridge::${master_bridge}::connected_interface::${interface_name}" => $anvil->data->{'local'}{network}{bridges}{bridge}{$master_bridge}{connected_interface}{$interface_name},
}});
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
interface_name => $interface_name,
master_bridge => $master_bridge,
type => $type,
}});
foreach my $key (sort {$a cmp $b} keys %{$hash_ref})
{
if (ref($hash_ref->{$key}) eq "ARRAY")
{
$anvil->data->{'local'}{network}{bridges}{$type}{$interface_name}{$key} = [];
foreach my $value (sort {$a cmp $b} @{$hash_ref->{$key}})
{
push @{$anvil->data->{'local'}{network}{bridges}{$type}{$interface_name}{$key}}, $value;
}
for (my $i = 0; $i < @{$anvil->data->{'local'}{network}{bridges}{$type}{$interface_name}{$key}}; $i++)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::${type}::${interface_name}::${key}->[$i]" => $anvil->data->{'local'}{network}{bridges}{$type}{$interface_name}{$key}->[$i],
}});
}
}
else
{
$anvil->data->{'local'}{network}{bridges}{$type}{$interface_name}{$key} = $hash_ref->{$key};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::${type}::${interface_name}::${key}" => $anvil->data->{'local'}{network}{bridges}{$type}{$interface_name}{$key},
}});
}
}
}
# Summary of found bridges.
foreach my $interface_name (sort {$a cmp $b} keys %{$anvil->data->{'local'}{network}{bridges}{bridge}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"local::network::bridges::bridge::${interface_name}::found" => $anvil->data->{'local'}{network}{bridges}{bridge}{$interface_name}{found},
}});
}
return(0);
}
=head2 get_free_memory
This returns, in bytes, host much free memory is available on the local system.
=cut
### TODO: Make this work on remote systems.
sub get_free_memory
{
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 => "System->get_free_memory()" }});
my $available = 0;
my ($free_output, $free_rc) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{free}." --bytes"});
foreach my $line (split/\n/, $free_output)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }});
if ($line =~ /Mem:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/)
{
my $total = $1;
my $used = $2;
my $free = $3;
my $shared = $4;
my $cache = $5;
$available = $6;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
total => $total." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $total})."})",
used => $used." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $used})."})",
free => $free." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $free})."})",
shared => $shared." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $shared})."})",
cache => $cache." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $cache})."})",
available => $available." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $available})."})",
}});
}
}
return($available);
}
=head2 get_host_type
This method tries to determine the host type and returns a value suitable for use is the C<< hosts >> table.

@ -399,6 +399,16 @@ sub validate_all
# Make sure the emulator it wants is the one we have.
validate_emulator($anvil);
# These tests are only needed if we're about to boot the server
if (($anvil->data->{switches}{start}) or ($anvil->data->{switches}{migrate_from}))
{
# Check that we have enough RAM.
validate_ram($anvil);
}
# Validate bridges
validate_bridges($anvil);
# Which DRBD resources do I need?
@ -410,6 +420,40 @@ sub validate_bridges
{
my ($anvil) = @_;
# Get my bridge list
$anvil->System->get_bridges({debug => 2});
# Find the Optical drives and DRBD devices.
my $server = $anvil->data->{environment}{OCF_RESKEY_name};
foreach my $mac (sort {$a cmp $b} keys %{$anvil->data->{server}{$server}{from_disk}{device}{interface}})
{
# See if we have this bridge
my $found = 0;
my $bridge = $anvil->data->{server}{$server}{from_disk}{device}{interface}{$mac}{bridge};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridge => $bridge }});
foreach my $interface_name (sort {$a cmp $b} keys %{$anvil->data->{'local'}{network}{bridges}{bridge}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { interface_name => $interface_name }});
if ((exists $anvil->data->{'local'}{network}{bridges}{bridge}{$interface_name}) && ($anvil->data->{'local'}{network}{bridges}{bridge}{$interface_name}{found}))
{
$found = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { found => $found }});
last;
}
}
if ($found)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 3, key => "log_0368", variables => { bridge => $bridge }});
}
else
{
# Missing bridge.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "log_0369", variables => { bridge => $bridge }});
$anvil->nice_exit({exit_code => 5});
}
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0366"});
return(0);
}
@ -516,7 +560,27 @@ sub validate_ram
{
my ($anvil) = @_;
# How mcuh RAM does the server need and how much do we have free?
my $server = $anvil->data->{environment}{OCF_RESKEY_name};
my $server_ram_bytes = $anvil->data->{server}{$server}{from_disk}{memory};
my $available = $anvil->System->get_free_memory({debug => 2});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
server_ram_bytes => $anvil->Convert->add_commas({number => $server_ram_bytes})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $server_ram_bytes}).")",
available => $anvil->Convert->add_commas({number => $available})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $available}).")",
}});
if ($server_ram_bytes > $available)
{
# Not enough free memory.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "log_0404", variables => {
name => $server,
ram => $anvil->Convert->bytes_to_human_readable({'bytes' => $server_ram_bytes}),
ram_bytes => $anvil->Convert->add_commas({number => $server_ram_bytes}),
available_ram => $anvil->Convert->bytes_to_human_readable({'bytes' => $server_ram_bytes}),
available_ram_bytes => $anvil->Convert->add_commas({number => $available}),
}});
$anvil->nice_exit({exit_code => 1});
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0365"});
return(0);
}

Loading…
Cancel
Save