* Finished the jquery/css stuff for showing the list of hosts that can have their network configured.

* Fixed unclear error logging in Network->find_matches().
* Updated System->generate_state_json() Striker->parse_all_status_json() to determine if another machine can be reached from the local dashboard. If it can be reached, the first matching interface and IP are recorded.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 5 years ago
parent c608ebb232
commit 0b2439edc3
  1. 16
      Anvil/Tools/Network.pm
  2. 59
      Anvil/Tools/Striker.pm
  3. 41
      Anvil/Tools/System.pm
  4. 6
      Anvil/Tools/Words.pm
  5. 21
      html/skins/alteeve/anvil.html
  6. 124
      html/skins/alteeve/anvil.js
  7. 28
      html/skins/alteeve/main.css
  8. 6
      share/words.xml
  9. 42
      tools/test.pl

@ -648,16 +648,26 @@ sub find_matches
second => $second,
}});
if (ref($anvil->data->{network}{$first}) ne "HASH")
if (not $first)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Network->find_matches()", parameter => "first" }});
return("");
}
if (ref($anvil->data->{network}{$second}) ne "HASH")
elsif (ref($anvil->data->{network}{$first}) ne "HASH")
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0106", variables => { key => "first -> network::".$first }});
return("");
}
if (not $second)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Network->find_matches()", parameter => "second" }});
return("");
}
elsif (ref($anvil->data->{network}{$second}) ne "HASH")
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0106", variables => { key => "second -> network::".$second }});
return("");
}
# Loop through the first, and on each interface with an IP/subnet mask, look for a match in the second.
my $match = {};
@ -1165,7 +1175,7 @@ FROM
ip_addresses
WHERE
ip_address_host_uuid = ".$anvil->Database->quote($host_uuid)."
";
;";
$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};

@ -350,6 +350,13 @@ sub parse_all_status_json
delete $anvil->data->{json}{all_status};
}
# We're going to look for matches as we go, so look
$anvil->Network->load_ips({
debug => $debug,
host => 'local',
host_uuid => $anvil->data->{sys}{host_uuid},
});
# We'll be adding data to this JSON file over time. So this will be an ever evolving method.
foreach my $host_hash (@{$data->{hosts}})
{
@ -361,12 +368,54 @@ sub parse_all_status_json
$anvil->data->{json}{all_status}{hosts}{$host_name}{short_host_name} = $host_hash->{short_name};
$anvil->data->{json}{all_status}{hosts}{$host_name}{configured} = $host_hash->{configured};
$anvil->data->{json}{all_status}{hosts}{$host_name}{ssh_fingerprint} = $host_hash->{ssh_fingerprint};
$anvil->data->{json}{all_status}{hosts}{$host_name}{matched_interface} = $host_hash->{matched_interface};
$anvil->data->{json}{all_status}{hosts}{$host_name}{matched_ip_address} = $host_hash->{matched_ip_address};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"json::all_status::hosts::${host_name}::host_uuid" => $anvil->data->{json}{all_status}{hosts}{$host_name}{host_uuid},
"json::all_status::hosts::${host_name}::type" => $anvil->data->{json}{all_status}{hosts}{$host_name}{type},
"json::all_status::hosts::${host_name}::short_host_name" => $anvil->data->{json}{all_status}{hosts}{$host_name}{short_host_name},
"json::all_status::hosts::${host_name}::configured" => $anvil->data->{json}{all_status}{hosts}{$host_name}{configured},
"json::all_status::hosts::${host_name}::ssh_fingerprint" => $anvil->data->{json}{all_status}{hosts}{$host_name}{ssh_fingerprint},
"json::all_status::hosts::${host_name}::matched_interface" => $anvil->data->{json}{all_status}{hosts}{$host_name}{matched_interface},
"json::all_status::hosts::${host_name}::matched_ip_address" => $anvil->data->{json}{all_status}{hosts}{$host_name}{matched_ip_address},
}});
# Find what interface on this host we can use to talk to it (if we're not looking at ourselves).
my $matched_interface = "";
my $matched_ip_address = "";
if ($host_name ne $anvil->_host_name)
{
$anvil->Network->load_ips({
debug => $debug,
host => $short_name,
host_uuid => $anvil->data->{json}{all_status}{hosts}{$host_name}{host_uuid},
});
my ($match) = $anvil->Network->find_matches({
debug => 3,
first => 'local',
second => $short_name,
});
if ($match)
{
# Yup!
my $match_found = 0;
foreach my $interface (sort {$a cmp $b} keys %{$match->{$short_name}})
{
$matched_interface = $interface;
$matched_ip_address = $match->{$short_name}{$interface}{ip};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
matched_interface => $matched_interface,
matched_ip_address => $matched_ip_address,
}});
last;
}
}
}
$anvil->data->{json}{all_status}{hosts}{$host_name}{matched_interface} = $matched_interface;
$anvil->data->{json}{all_status}{hosts}{$host_name}{matched_ip_address} = $matched_ip_address;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"json::all_status::hosts::${host_name}::host_uuid" => $anvil->data->{json}{all_status}{hosts}{$host_name}{host_uuid},
"json::all_status::hosts::${host_name}::type" => $anvil->data->{json}{all_status}{hosts}{$host_name}{type},
"json::all_status::hosts::${host_name}::short_host_name" => $anvil->data->{json}{all_status}{hosts}{$host_name}{short_host_name},
"json::all_status::hosts::${host_name}::configured" => $anvil->data->{json}{all_status}{hosts}{$host_name}{configured},
"json::all_status::hosts::${host_name}::ssh_fingerprint" => $anvil->data->{json}{all_status}{hosts}{$host_name}{ssh_fingerprint},
"json::all_status::hosts::${host_name}::matched_interface" => $anvil->data->{json}{all_status}{hosts}{$host_name}{matched_interface},
"json::all_status::hosts::${host_name}::matched_ip_address" => $anvil->data->{json}{all_status}{hosts}{$host_name}{matched_ip_address},
}});
foreach my $interface_hash (@{$host_hash->{network_interfaces}})

@ -813,6 +813,13 @@ sub generate_state_json
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "System->generate_state_json()" }});
# We're going to look for matches as we go, so look
$anvil->Network->load_ips({
debug => $debug,
host => 'local',
host_uuid => $anvil->data->{sys}{host_uuid},
});
$anvil->data->{json}{all_systems}{hosts} = [];
$anvil->Database->get_hosts_info({debug => 3});
foreach my $host_uuid (keys %{$anvil->data->{machine}{host_uuid}})
@ -824,7 +831,7 @@ sub generate_state_json
my $configured = defined $anvil->data->{machine}{host_uuid}{$host_uuid}{variables}{'system::configured'} ? $anvil->data->{machine}{host_uuid}{$host_uuid}{variables}{'system::configured'} : 0;
my $ifaces_array = [];
my $host = $short_host_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"s1:host_name" => $host_name,
"s2:short_host_name" => $short_host_name,
"s3:host_type" => $host_type,
@ -838,6 +845,36 @@ sub generate_state_json
host_uuid => $host_uuid,
host => $short_host_name,
});
# Find what interface on this host we can use to talk to it (if we're not looking at ourselves).
my $matched_interface = "";
my $matched_ip_address = "";
if ($host_name ne $anvil->_host_name)
{
# Don't need to call 'local_ips', it was called by load_interfaces above.
my ($match) = $anvil->Network->find_matches({
debug => $debug,
first => 'local',
second => $short_host_name,
});
if ($match)
{
# Yup!
my $match_found = 0;
foreach my $interface (sort {$a cmp $b} keys %{$match->{$short_host_name}})
{
$matched_interface = $interface;
$matched_ip_address = $match->{$short_host_name}{$interface}{ip};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
matched_interface => $matched_interface,
matched_ip_address => $matched_ip_address,
}});
last;
}
}
}
foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{network}{$host}{interface}})
{
my $type = $anvil->data->{network}{$host}{interface}{$interface}{type};
@ -1138,6 +1175,8 @@ sub generate_state_json
host_uuid => $host_uuid,
configured => $configured,
ssh_fingerprint => $host_key,
matched_interface => $matched_interface,
matched_ip_address => $matched_ip_address,
network_interfaces => $ifaces_array,
};
}

@ -357,6 +357,12 @@ sub parse_banged_string
while ($variable_string)
{
my $pair = ($variable_string =~ /^(!!.*?!.*?!!).*$/)[0];
if (not defined $pair)
{
print $THIS_FILE." ".__LINE__."; Failed to parse the pair from: [".$variable_string."]\n";
print $THIS_FILE." ".__LINE__."; Was parsing message: [".$message."] from key string: [".$key_string."]\n";
die;
}
my ($variable, $value) = ($pair =~ /^!!(.*?)!(.*?)!!$/);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:pair" => $pair,

@ -25,11 +25,26 @@
</td>
</tr>
<tr>
<td class="main_option_icon">
<a href="?anvil=true&task=prep-network"><img src="#!data!skin::url!#/images/configure-network.png" class="top_icon" ></a>
<td rowspan="2" class="main_option_icon" style="cursor: pointer;">
<span id="toggle_unconfigured_icon"><img src="#!data!skin::url!#/images/configure-network.png" class="top_icon" ></span>
</td>
<td class="main_option">
<a href="?anvil=true&task=prep-network">#!string!striker_0130!#</a>
<span id="toggle_unconfigured_text" style="cursor: pointer;">#!string!striker_0130!#</spam>
</td>
</tr>
<tr>
<td class="main_option_list">
<!-- See anvil.js for the in-JS generated HTML table that gets inserted here -->
<div id="unconfigured_hosts" style="display: none;"
data-none="#!string!unit_0003!#"
data-yes="#!string!unit_0001!#"
data-no="#!string!unit_0002!#"
data-configured="#!string!header_0018!#"
data-unconfigured="#!string!header_0016!#"
data-accessible="#!string!header_0017!#"
data-at-ip="#!string!header_0020!#"
data-type="#!string!header_0019!#"
/>
</td>
</tr>
<tr>

@ -12,13 +12,127 @@ $( window ).on( "load", function()
// Clears the URL to remove everything off after '?'.
//var newURL = location.href.split("?")[0];
//window.history.pushState('object', document.title, newURL);
//console.log('onload fired.');
// Toggle the table with the list of hosts that can be configured.
$("#toggle_unconfigured_icon").click(function(){
$("#unconfigured_hosts").toggle();
});
$("#toggle_unconfigured_text").click(function(){
$("#unconfigured_hosts").toggle();
});
// Walk through the network.json file and use it to pre-fill the form.
$.getJSON('/status/network.json', { get_param: 'value' }, function(data) {
$.each(data.ips, function(index, element) {
//console.log('- entry: ['+index+'], on: ['+element.on+'], address: ['+element.address+'], subnet_mask: ['+element.subnet_mask+'].');
//console.log('- gateway: ['+element.gateway+'], dns: ['+element.dns+'], default gateway: ['+element.default_gateway+'].');
$.getJSON('/status/all_status.json', { get_param: 'value' }, function(data) {
//console.log('read /status/all_status.json');
var show_none = 1;
var say_none = $('#unconfigured_hosts').data('none');
var say_yes = $('#unconfigured_hosts').data('yes');
var say_no = $('#unconfigured_hosts').data('no');
var say_unconfigured = $('#unconfigured_hosts').data('unconfigured');
var say_configured = $('#unconfigured_hosts').data('configured');
var say_type = $('#unconfigured_hosts').data('type');
var say_accessible = $('#unconfigured_hosts').data('accessible');
var say_at_ip = $('#unconfigured_hosts').data('at-ip');
// Open the table
var body = '<table id="unconfigured_hosts_table" class="data_table_nowrap">';
body += '<tr class="data_row">';
body += '<td class="column_header">'+say_unconfigured+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_header">'+say_type+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_header">'+say_accessible+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_header">'+say_at_ip+'</td>';
body += '</tr>';
$.each(data.hosts, function(index, element) {
if (element.type === 'dashboard') {
// Skip
return true;
};
if (element.configured != 1) {
show_none = 0;
if (element.matched_ip_address) {
//console.log('Show: ['+element.short_name+'], connect via: ['+element.matched_ip_address+']');
body += '<tr class="data_row">';
body += '<td class="column_row_value_fixed"><a class="available" href="?anvil=true&task=prep-network&host='+element.host_uuid+'">'+element.short_name+'</a></td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_row_value_fixed">'+element.type+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="available">'+say_yes+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_row_value_fixed">'+element.matched_ip_address+'</td>';
body += '</tr>';
} else {
//console.log('Show: ['+element.short_name+'], not accessible from here');
body += '<tr class="data_row">';
body += '<td class="column_row_value_fixed">'+element.short_name+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_row_value_fixed">'+element.type+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="unavailable">'+say_no+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_row_value_fixed">--</td>';
body += '</tr>';
}
}
});
if (show_none) {
body += '<tr class="data_row">';
body += '<td class="subtle_text" colspan="7">&lt;'+say_none+'&gt;</td>';
body += '</tr>' ;
}
// Now show configured ones (in case the user wants to reconfigure a host)
show_none = 1;
body += '<tr class="data_row">';
body += '<td class="column_header" style="padding-top: 0.5em;">'+say_configured+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_header" style="padding-top: 0.5em;">'+say_type+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_header" style="padding-top: 0.5em;">'+say_accessible+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_header" style="padding-top: 0.5em;">'+say_at_ip+'</td>';
body += '</tr>';
$.each(data.hosts, function(index, element) {
if (element.type === 'dashboard') {
// Skip
return true;
};
if (element.configured == 1) {
show_none = 0;
if (element.matched_ip_address) {
//console.log('Show: ['+element.short_name+'], connect via: ['+element.matched_ip_address+']');
body += '<tr class="data_row">';
body += '<td class="column_row_value_fixed"><a class="available" href="?anvil=true&task=prep-network&host='+element.host_uuid+'">'+element.short_name+'</a></td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_row_value_fixed">'+element.type+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="available">'+say_yes+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_row_value_fixed">'+element.matched_ip_address+'</td>';
body += '</tr>';
} else {
//console.log('Show: ['+element.short_name+'], not accessible from here');
body += '<tr class="data_row">';
body += '<td class="column_row_value_fixed">'+element.short_name+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_row_value_fixed">'+element.type+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="unavailable">'+say_no+'</td>';
body += '<td class="column_header"> &nbsp; </td>';
body += '<td class="column_row_value_fixed">--</td>';
body += '</tr>';
}
}
});
if (show_none) {
body += '<tr class="data_row">';
body += '<td class="subtle_text" style="text-align: center;" colspan="7">&lt;'+say_none+'&gt;</td>';
body += '</tr>' ;
}
// Close the table
body += '</table>';
$( "#unconfigured_hosts" ).append(body);
});
})

@ -232,11 +232,21 @@ input[type=text].input_clear, input[type=number].input_clear, select.input_clear
height: 100%;
}
.main_option_list {
/* border: 1px dotted red; */
color: #dbe0e5;
font-size: 1.3em;
padding-top: 5px;
padding-left: 20px;
padding-bottom: 5px;
height: 100%;
}
.main_option_icon {
/* border: 1px dotted blue; */
padding-top: 10px;
padding-bottom: 10px;
vertical-align: center;
vertical-align: top;
height: 100%;
}
@ -376,3 +386,19 @@ tr.data_row {
font-size: 1.1em;
font-weight: bold;
}
.available {
color: #00934d;
text-align: center;
}
.unavailable {
color: #dc9012;
text-align: center;
}
/* This is used for the 'configured' table as well */
table.unconfigured_table {
border: 1px solid blue;
border-radius: 4px;
}

@ -832,6 +832,11 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="header_0013">User</key>
<key name="header_0014">File</key>
<key name="header_0015">On Host</key>
<key name="header_0016">Unconfigured Hosts</key>
<key name="header_0017">Accessible?</key>
<key name="header_0018">Configured Hosts</key>
<key name="header_0019">Type</key>
<key name="header_0020">At IP</key>
<!-- General strings shown in Striker -->
<key name="striker_0001">Welcome! Lets setup your #!string!brand_0003!# dashboard...</key>
@ -1255,6 +1260,7 @@ Failed to generate an RSA public key for the user: [#!variable!user!#]. The outp
<key name="error_0103">The file: [#!variable!file!#] wasn't found.</key>
<key name="error_0104">The parameter get_company_from_oui->mac must be a valid MAC address or be in the format 'xx:xx:xx'. Received: [#!variable!mac!#].</key>
<key name="error_0105">The file: [#!variable!file!#] was not found.</key>
<key name="error_0106"><![CDATA[The method Network->find_matches() was given the hash key: [#!variable!key!#], but it does not reference a hash. Are any IPs associated with this target?]]></key>
<!-- These are units, words and so on used when displaying information. -->
<key name="unit_0001">Yes</key>

@ -31,47 +31,7 @@ $anvil->System->generate_state_json({debug => 3});
$anvil->Striker->parse_all_status_json({debug => 3});
# print Dumper $anvil->data->{json}{all_status}{hosts};
# die;
# foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{json}{all_status}{hosts}})
# {
# print $THIS_FILE." ".__LINE__."; Host: [".$host_name."]\n";
# foreach my $network_type (sort {$a cmp $b} keys %{$anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}})
# {
# print $THIS_FILE." ".__LINE__."; - Network type: [".$network_type."]\n";
# foreach my $interface_name (sort {$a cmp $b} keys %{$anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{$network_type}})
# {
# print $THIS_FILE." ".__LINE__."; - Interface: [".$interface_name."]\n";
# foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{$network_type}{$interface_name}})
# {
# if (ref ($anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{$network_type}{$interface_name}{$variable}) eq "HASH")
# {
# print $THIS_FILE." ".__LINE__."; - ".$variable.";\n";
# foreach my $value (sort {$a cmp $b} keys %{$anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{$network_type}{$interface_name}{$variable}})
# {
# print $THIS_FILE." ".__LINE__."; - ".$value." -> [".$anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{$network_type}{$interface_name}{$variable}{$value}{type}."]\n";
# }
# }
# elsif (ref ($anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{$network_type}{$interface_name}{$variable}) eq "ARRAY")
# {
# print $THIS_FILE." ".__LINE__."; - ".$variable.";\n";
# foreach my $value (sort {$a cmp $b} @{$anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{$network_type}{$interface_name}{$variable}})
# {
# print $THIS_FILE." ".__LINE__."; - ".$value."\n";
# }
# }
# else
# {
# print $THIS_FILE." ".__LINE__."; - ".$variable.": [".$anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{$network_type}{$interface_name}{$variable}."]\n";
# }
# }
# }
# }
# }
# print Dumper $anvil->data->{json}{all_status}{hosts};
# print Dumper $anvil->data->{json}{all_status}{hosts}{'el8-a01n02.digimer.ca'}{network_interface};
# die;
die;
#foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{json}{all_status}{hosts}})
foreach my $host_name ("el8-a01n02.digimer.ca")

Loading…
Cancel
Save