* Created System->find_matching_ip() which takes a host and finds which local network (if any) is on the same subnet.

* Continued work on managing Striker peers.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 6 years ago
parent 4bf048054b
commit 2a03663ecf
  1. 84
      Anvil/Tools/System.pm
  2. 37
      cgi-bin/striker
  3. 3
      html/skins/alteeve/main.css
  4. 70
      html/skins/alteeve/striker.html
  5. 5
      share/words.xml
  6. 4
      tools/anvil-manage-striker-peers
  7. 13
      units/anvil-boot-time.service

@ -10,6 +10,7 @@ use Net::SSH2;
use Scalar::Util qw(weaken isweak); use Scalar::Util qw(weaken isweak);
use Time::HiRes qw(gettimeofday tv_interval); use Time::HiRes qw(gettimeofday tv_interval);
use Proc::Simple; use Proc::Simple;
use NetAddr::IP;
our $VERSION = "3.0.0"; our $VERSION = "3.0.0";
my $THIS_FILE = "System.pm"; my $THIS_FILE = "System.pm";
@ -22,6 +23,7 @@ my $THIS_FILE = "System.pm";
# check_memory # check_memory
# determine_host_type # determine_host_type
# enable_daemon # enable_daemon
# find_matching_ip
# get_ips # get_ips
# hostname # hostname
# is_local # is_local
@ -620,6 +622,88 @@ sub enable_daemon
return($return); return($return);
} }
=head2 find_matching_ip
This takes an IP (or hostname, which is translated to an IP using local resources), and tries to figure out which local IP address is on the same subnet.
If no match is found, an empty string is returned. If there is an error, C<< !!error!! >> is returned.
Parameters;
=head3 host (required)
This is the IP address or host name we're going to use when searching for a local IP address that can reach it.
=cut
sub find_matching_ip
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
my $local_ip = "";
my $host = defined $parameter->{host} ? $parameter->{host} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host => $host }});
# Do I have a host?
if (not $host)
{
# Woops!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->find_matching_ip()", parameter => "host" }});
return("!!error!!");
}
# Translate the host name to an IP address, if it isn't already an IP address.
if (not $anvil->Validate->is_ipv4({ip => $host}))
{
# This will be '0' if it failed, and pre-validated if it returns an IP.
$host = $anvil->Convert->hostname_to_ip({hostname => $host});
if (not $host)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "log_0211", variables => { host => $parameter->{host} }});
return(0);
}
}
# Get my local IPs
$anvil->System->get_ips({debug => $debug});
my $ip = NetAddr::IP->new($host);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { ip => $ip }});
# Look through our IPs. First match wins.
foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{sys}{network}{interface}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface => $interface }});
next if not $anvil->data->{sys}{network}{interface}{$interface}{ip};
my $this_ip = $anvil->data->{sys}{network}{interface}{$interface}{ip};
my $this_subnet = $anvil->data->{sys}{network}{interface}{$interface}{subnet};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:this_ip" => $this_ip,
"s2:this_subnet" => $this_subnet,
}});
my $network_range = $this_ip."/".$this_subnet;
my $network = NetAddr::IP->new($network_range);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:network_range" => $network_range,
"s2:network" => $network,
}});
if ($ip->within($network))
{
$local_ip = $this_ip;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { local_ip => $local_ip }});
last;
}
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { local_ip => $local_ip }});
return($local_ip);
}
=head2 get_ips =head2 get_ips
This method checks the local system for interfaces and stores them in: This method checks the local system for interfaces and stores them in:

@ -572,6 +572,7 @@ sub add_sync_peer
my $user = $anvil->data->{sys}{database}{user}; my $user = $anvil->data->{sys}{database}{user};
my $host = $anvil->data->{cgi}{new_peer_access}{value}; my $host = $anvil->data->{cgi}{new_peer_access}{value};
my $name = $anvil->data->{sys}{database}{name}; my $name = $anvil->data->{sys}{database}{name};
my $ping = $anvil->data->{cgi}{new_peer_ping}{value} eq "on" 1 : 0;
my $port = 5432; my $port = 5432;
my $ssh_tcp = 22; my $ssh_tcp = 22;
my $peer_uuid = ""; my $peer_uuid = "";
@ -716,6 +717,42 @@ sub add_sync_peer
if ($anvil->data->{cgi}{confirm}{value}) if ($anvil->data->{cgi}{confirm}{value})
{ {
# OK, save the job! # OK, save the job!
my $job_command = "anvil-manage-striker-peers --add ";
$job_command .= "--host-uuid ".$peer_uuid." ";
$job_command .= "--host ".$host." ";
$job_command .= "--port ".$port." ";
$job_command .= "--ping ".$ping;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_command => $job_command }});
# my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
# file => $THIS_FILE,
# line => __LINE__,
# job_command => $job_command,
# job_data => "password=".$anvil->data->{cgi}{new_peer_password}{value},
# job_name => "striker-peer::add",
# job_title => "job_0011",
# job_description => "job_0012",
# });
# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }});
# Are we adding ourselves to the peer?
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::new_peer_bidirection::value" => $anvil->data->{cgi}{new_peer_bidirection}{value} }});
if ($anvil->data->{cgi}{new_peer_bidirection}{value} eq "on")
{
my $use_ip = $anvil->System->find_matching_ip({debug => 2, host => $host});
# See which of our IPs match theirs. If the peer is a hostname, first
}
# We don't need to store anything as hidden variables, we'll read it back from the database
# later.
$anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "system_update_recorded", variables => {
title_id => "",
message_id => "",
title => "#!string!striker_0044!#",
description => $ping ? "#!string!striker_0103!#" : "#!string!striker_0102!#",
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }});
} }
else else
{ {

@ -301,7 +301,8 @@ td {
} }
.menu_title { .menu_title {
font-size: 1.1em; color: #dbe0e5;
font-size: 2em;
padding-top: 30px; padding-top: 30px;
padding-left: 20px; padding-left: 20px;
padding-bottom: 10px; padding-bottom: 10px;

@ -1,3 +1,38 @@
<!-- start confirm-action -->
<table align="center">
<form name="confirm-update" action="" method="post">
<div id="confirm-update">
<tr>
<td class="menu_title" colspan="2">
#!variable!title!#
</td>
</tr>
<tr>
<td class="menu_details" colspan="2">
#!variable!message!#
</td>
</tr>
<tr>
<td colspan="2">
&nbsp;
</td>
</tr>
<tr>
<td class="button_cell" style="text-align: left;">
<a href="/cgi-bin/striker?striker=true" class="button">#!string!striker_0098!#</a>
</td>
<td class="button_cell" style="text-align: right;">
<input type="submit" name="confirm" id="confirm" class="button" value="#!string!striker_0082!#">
</td>
</tr>
<input type="hidden" name="striker" id="striker" value="#!data!cgi::striker::value!#">
<input type="hidden" name="task" id="task" value="#!data!cgi::task::value!#">
<input type="hidden" name="save" id="save" value="#!data!cgi::save::value!#">
</form>
</div>
</table>
<!-- end confirm-action -->
<!-- start confirm-new-peer --> <!-- start confirm-new-peer -->
<table align="center"> <table align="center">
<tr> <tr>
@ -102,41 +137,6 @@
</table> </table>
<!-- end confirm-reconfig --> <!-- end confirm-reconfig -->
<!-- start confirm-action -->
<table align="center">
<form name="confirm-update" action="" method="post">
<div id="confirm-update">
<tr>
<td class="menu_title" colspan="2">
#!variable!title!#
</td>
</tr>
<tr>
<td class="menu_details" colspan="2">
#!variable!message!#
</td>
</tr>
<tr>
<td colspan="2">
&nbsp;
</td>
</tr>
<tr>
<td class="button_cell" style="text-align: left;">
<a href="/cgi-bin/striker?striker=true" class="button">#!string!striker_0098!#</a>
</td>
<td class="button_cell" style="text-align: right;">
<input type="submit" name="confirm" id="confirm" class="button" value="#!string!striker_0082!#">
</td>
</tr>
<input type="hidden" name="striker" id="striker" value="#!data!cgi::striker::value!#">
<input type="hidden" name="task" id="task" value="#!data!cgi::task::value!#">
<input type="hidden" name="save" id="save" value="#!data!cgi::save::value!#">
</form>
</div>
</table>
<!-- end confirm-action -->
<!-- start reconfig-done --> <!-- start reconfig-done -->
<table> <table>
<tr> <tr>

@ -348,6 +348,7 @@ The database connection error was:
<key name="log_0208"><![CDATA[Job->update_progress() called with the 'job_uuid': [#!variable!job_uuid!#], which was not found. Unable to find the job to update.]]></key> <key name="log_0208"><![CDATA[Job->update_progress() called with the 'job_uuid': [#!variable!job_uuid!#], which was not found. Unable to find the job to update.]]></key>
<key name="log_0209"><![CDATA[Job->update_progress() called with 'progress' set to an invalid value: [#!variable!progress!#]. This must be a whole number between '0' and '100' (fractions not allowed).]]></key> <key name="log_0209"><![CDATA[Job->update_progress() called with 'progress' set to an invalid value: [#!variable!progress!#]. This must be a whole number between '0' and '100' (fractions not allowed).]]></key>
<key name="log_0210"><![CDATA[Requesting the job: [#!variable!command!#] be run by 'anvil-daemon'.]]></key> <key name="log_0210"><![CDATA[Requesting the job: [#!variable!command!#] be run by 'anvil-daemon'.]]></key>
<key name="log_0211"><![CDATA[The host: [#!variable!host!#] was passed to System->find_matching_ip(), but it failed to resolve to an IP address.]]></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>
@ -488,6 +489,8 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="striker_0099">Job</key> <key name="striker_0099">Job</key>
<key name="striker_0100">Reboot this system? If you proceed, you will be logged out and this system will be rebooted. Please be sure you have access in the rare chance that the system fails to boot back up.</key> <key name="striker_0100">Reboot this system? If you proceed, you will be logged out and this system will be rebooted. Please be sure you have access in the rare chance that the system fails to boot back up.</key>
<key name="striker_0101">Power off this system? If you proceed, you will be logged out and this system will be powered off. You will need physical access to the machine to turn it back on in most cases. A properly condigured Striker dashboard will power on after a power cycle (via a PDU) or any machine with IPMI if you have access to a machine on the BCN.</key> <key name="striker_0101">Power off this system? If you proceed, you will be logged out and this system will be powered off. You will need physical access to the machine to turn it back on in most cases. A properly condigured Striker dashboard will power on after a power cycle (via a PDU) or any machine with IPMI if you have access to a machine on the BCN.</key>
<key name="striker_0102">The peer will be added to the local configuration shortly. Expect slight performance impacts if there is a lot of data to synchronize.</key>
<key name="striker_0103">The peer will be added to the local configuration shortly, and we will be added to their configuration as well. Expect slight performance impacts if there is a lot of data to synchronize.</key>
<!-- Strings used by jobs --> <!-- Strings used by jobs -->
<key name="job_0001">Configure Network</key> <key name="job_0001">Configure Network</key>
@ -500,6 +503,8 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="job_0008">This system will be powered off momentarily. It will not respond until it has turned back on.</key> <key name="job_0008">This system will be powered off momentarily. It will not respond until it has turned back on.</key>
<key name="job_0009">Reboot..</key> <key name="job_0009">Reboot..</key>
<key name="job_0010">Powering off...</key> <key name="job_0010">Powering off...</key>
<key name="job_0011">Add a Striker Peer</key>
<key name="job_0012">The Striker peer will now be added to the local configuration.</key>
<!-- Warnings --> <!-- Warnings -->
<key name="striker_warning_0001">The IP address will change. You will need to reconnect after applying these changes.</key> <key name="striker_warning_0001">The IP address will change. You will need to reconnect after applying these changes.</key>

@ -13,12 +13,16 @@
# #
### Show existing entries ### Show existing entries
# /usr/sbin/anvil-manage-striker-peers --list # /usr/sbin/anvil-manage-striker-peers --list
#
### Add a new entry, or edit an existing one ### Add a new entry, or edit an existing one
# /usr/sbin/anvil-manage-striker-peers --add --host-uuid e20c3f10-c35d-4543-b5e6-8a373f27977a --host localhost --port 5432 --password-file /tmp/anvil-manage-striker-peers.2e410b43-42a0-4eaf-985c-670f92c482b8 --ping 0 # /usr/sbin/anvil-manage-striker-peers --add --host-uuid e20c3f10-c35d-4543-b5e6-8a373f27977a --host localhost --port 5432 --password-file /tmp/anvil-manage-striker-peers.2e410b43-42a0-4eaf-985c-670f92c482b8 --ping 0
#
### Edit an existing entry, but don't add it if it wasn't found. ### Edit an existing entry, but don't add it if it wasn't found.
# /usr/sbin/anvil-manage-striker-peers --host-uuid e20c3f10-c35d-4543-b5e6-8a373f27977a --host localhost --port 5432 --password-file /tmp/anvil-manage-striker-peers.2e410b43-42a0-4eaf-985c-670f92c482b8 --ping 0 # /usr/sbin/anvil-manage-striker-peers --host-uuid e20c3f10-c35d-4543-b5e6-8a373f27977a --host localhost --port 5432 --password-file /tmp/anvil-manage-striker-peers.2e410b43-42a0-4eaf-985c-670f92c482b8 --ping 0
#
### Remove an entry ### Remove an entry
# /usr/sbin/anvil-manage-striker-peers --remove --host-uuid e20c3f10-c35d-4543-b5e6-8a373f27977a # /usr/sbin/anvil-manage-striker-peers --remove --host-uuid e20c3f10-c35d-4543-b5e6-8a373f27977a
#
use strict; use strict;

@ -1,13 +0,0 @@
[Unit]
Description=Anvil! Intelligent Availability Platform - Boot-time tasks
# Don't run until we can talk to our and our peer's databases.
Wants=network.target
Wants=postgresql.service
[Service]
Type=simple
ExecStart=/usr/sbin/anvil-clear-reboot
ExecStop=/bin/kill -WINCH ${MAINPID}
[Install]
WantedBy=default.target
Loading…
Cancel
Save