* Added a flag that tells anvil-daemon when a node is having it's network mapped. When this happens, open ssh connections are closed each loop and only tasks related to mapping the network run. This improves responsiveness in Striker when reporting which network links have come up or gone down.

* Fixed a bug in Database->insert_or_update_variables() where, if 'update_value_only' was set but not variable_uuid was passed or could be found, an (incomplete) INSERT would be attempted.
* Added support for generating module metadata when setting up local repos on Striker.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 5 years ago
parent 4cf9d6215c
commit 76e9352717
  1. 1
      Anvil/Tools.pm
  2. 23
      Anvil/Tools/Database.pm
  3. 2
      Anvil/Tools/Remote.pm
  4. 7
      Anvil/Tools/Striker.pm
  5. 43
      cgi-bin/striker
  6. 1
      html/skins/alteeve/anvil.html
  7. 2
      html/skins/alteeve/anvil.js
  8. 7
      rpm/SPECS/anvil.spec
  9. 5
      share/words.xml
  10. 80
      tools/anvil-daemon
  11. 2
      tools/striker-initialize-host
  12. 27
      tools/striker-manage-install-target

@ -1158,6 +1158,7 @@ sub _set_paths
lvscan => "/usr/sbin/lvscan",
md5sum => "/usr/bin/md5sum",
'mkdir' => "/usr/bin/mkdir",
modifyrepo_c => "/usr/bin/modifyrepo_c",
mv => "/usr/bin/mv",
nmap => "/usr/bin/nmap",
nmcli => "/bin/nmcli",

@ -7229,7 +7229,6 @@ sub insert_or_update_variables
variable_source_uuid => $variable_source_uuid,
variable_source_table => $variable_source_table,
update_value_only => $update_value_only,
log_level => $debug,
}});
# We'll need either the name or UUID.
@ -7292,10 +7291,18 @@ AND
}
}
# If I still don't have an variable_uuid, we're INSERT'ing .
# If I still don't have an variable_uuid, we're INSERT'ing (unless we've been told to update the
# value only, in which case we do nothing).
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { variable_uuid => $variable_uuid }});
if (not $variable_uuid)
{
# Were we asked to updat only?
if ($update_value_only)
{
# Nothing to do.
return("");
}
# INSERT
$variable_uuid = $anvil->Get->uuid();
my $query = "
@ -8495,7 +8502,17 @@ Parameters;
If specified, this specifies the variable UUID to read. When this parameter is specified, the C<< variable_name >> parameter is ignored.
=head3 variable_name
=head3 variable_name (required)
This is the name of the variable we're reading.
=head3 variable_source_table (optional)
If set along with C<< variable_source_uuid >>, the variable being read will be specified against this and the UUID.
=head3 variable_source_uuid (optional)
If set along with C<< variable_source_table >>, the variable being read will be specified against this and the source table.
=cut
sub read_variable

@ -273,7 +273,7 @@ sub call
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
# Get the target and port so that we can create the ssh_fh key
my $port = defined $parameter->{port} ? $parameter->{port} : 22;
my $port = $parameter->{port} ? $parameter->{port} : 22;
my $target = defined $parameter->{target} ? $parameter->{target} : "";
my $remote_user = defined $parameter->{remote_user} ? $parameter->{remote_user} : "root";
my $ssh_fh_key = $remote_user."\@".$target.":".$port;

@ -156,6 +156,10 @@ sub get_local_repo
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { base_url => $base_url }});
### NOTE: The 'module_hotfixes=1' is needed until we can figure out how to add libssh2 to
### 'modules.yaml' (from anvil-striker-extra, in turn from the RHEL 8.x repodata). See:
### - https://docs.fedoraproject.org/en-US/modularity/making-modules/defining-modules/
### - https://docs.fedoraproject.org/en-US/modularity/hosting-modules/
# Create the local repo file body
my $repo = "[".$anvil->_short_host_name."-repo]
name=Repo on ".$anvil->_host_name."
@ -163,7 +167,8 @@ name=Repo on ".$anvil->_host_name."
enabled=1
gpgcheck=0
timeout=5
skip_if_unavailable=1";
skip_if_unavailable=1
module_hotfixes=1";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { repo => $repo }});
return($repo);

@ -1628,6 +1628,18 @@ sub process_prep_network
# Are we saving?
if ($anvil->data->{cgi}{save}{value} eq "true")
{
# Clear the network map variable.
$anvil->Database->insert_or_update_variables({
debug => 2,
variable_name => "config::map_network",
variable_value => 0,
variable_default => 0,
variable_description => "striker_0202",
variable_section => "config",
variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value},
variable_source_table => "hosts",
});
# Is the form sane?
my $sane = 1;
my $interfaces = "";
@ -2079,6 +2091,20 @@ sub process_prep_network
return(0);
}
}
else
{
# We're mapping
$anvil->Database->insert_or_update_variables({
debug => 2,
variable_name => "config::map_network",
variable_value => 1,
variable_default => 0,
variable_description => "striker_0202",
variable_section => "config",
variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value},
variable_source_table => "hosts",
});
}
my $interface_form = "";
# NOTE: We don't assign IPs at this point, unless the user manually sets one. We'll set all to 'dhcp'
@ -2241,6 +2267,7 @@ sub process_prep_host_page
my ($anvil) = @_;
my $host_name = defined $anvil->data->{cgi}{host_name}{value} ? $anvil->data->{cgi}{host_name}{value} : "";
my $host_uuid = defined $anvil->data->{cgi}{host_uuid}{value} ? $anvil->data->{cgi}{host_uuid}{value} : "";
my $default_host_name = defined $anvil->data->{cgi}{default_host_name}{value} ? $anvil->data->{cgi}{default_host_name}{value} : "";
my $host_ip_address = defined $anvil->data->{cgi}{host_ip_address}{value} ? $anvil->data->{cgi}{host_ip_address}{value} : "";
my $host_password = defined $anvil->data->{cgi}{host_password}{value} ? $anvil->data->{cgi}{host_password}{value} : "";
@ -2251,6 +2278,7 @@ sub process_prep_host_page
my $confirm = defined $anvil->data->{cgi}{confirm}{value} ? $anvil->data->{cgi}{confirm}{value} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host_name => $host_name,
host_uuid => $host_uuid,
default_host_name => $default_host_name,
host_ip_address => $host_ip_address,
host_password => $anvil->Log->is_secure($host_password),
@ -2283,6 +2311,21 @@ sub process_prep_host_page
password => $anvil->Log->is_secure($host_password),
}});
# Update the database to mark this machine as unconfigured (in case we're rebuilding a
# previously known system). This is needed to get the netweork link state info updating.
if ($host_uuid)
{
$anvil->Database->insert_or_update_variables({
debug => 2,
variable_name => "system::configured",
variable_source_uuid => $host_uuid,
variable_source_table => "hosts",
variable_value => 0,
update_value_only => 1,
});
}
# Are we setting a host name?
my $say_host_name = "host_name=\n";
if (($host_name) && ($host_name ne $default_host_name))
{

@ -521,6 +521,7 @@
</td>
<td class="padded_cell">
<span class="fixed_width">#!variable!host_uuid!#</span>
<input type="hidden" name="host_uuid" id="host_uuid" value="#!variable!host_uuid!#">
</td>
</tr>
#!variable!redhat_form!#

@ -107,7 +107,7 @@ $( window ).on( "load", function()
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_row_value_fixed"><a class="available" href="?anvil=true&task=prep-network&host_uuid='+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>';

@ -3,7 +3,7 @@
%define anvilgroup admin
Name: anvil
Version: 3.0
Release: 31%{?dist}
Release: 32%{?dist}
Summary: Alteeve Anvil! complete package.
License: GPLv2+
@ -211,7 +211,7 @@ sed -i "1s/^.*$/%{version}-%{release}/" /%{_sysconfdir}/anvil/anvil.version
systemctl enable chronyd.service
systemctl start chronyd.service
systemctl enable anvil-daemon.service
systemctl start anvil-daemon.service
systemctl restart anvil-daemon.service
%post striker
@ -354,6 +354,9 @@ fi
%changelog
* tbd Madison Kelly <mkelly@alteeve.ca> 3.0-32
- Updated source.
* Mon Jan 6 2020 Madison Kelly <mkelly@alteeve.ca> 3.0-31
- Added perl-Mail-RFC822-Address to core requirements.
- Updated source.

@ -233,7 +233,7 @@ About to try to download aproximately: [#!variable!packages!#] packages needed t
<key name="message_0126">The attempt to disabled the 'Install Target' function failed! Please check the logs for details.</key>
<key name="message_0127">The 'Install Target' function has been enabled.</key>
<key name="message_0128">The attempt to enable the 'Install Target' function failed! Please check the logs for details.</key>
<key name="message_0129">[ Error ] - The comps.xml file: [#!variable!comps_xml!#] was found, but something failed when we tried to copy it to: [#!variable!target!#].</key>
<key name="message_0129">[ Error ] - The comps.xml file: [#!variable!comps_xml!#] was found, but something failed when we tried to copy it to: [#!variable!target_comps!#].</key>
<key name="message_0130">Updated repository data.</key>
<key name="message_0131">Back-Channel Network ##!variable!number!# - Used for all inter-machine communication in the Anvil!, as well as communication for foundation pack devices. Should be VLAN-isolated from the IFN and, thus, trusted.</key>
<key name="message_0132">Storage Network ##!variable!number!# - Used for DRBD communication between nodes and DR hosts. Should be VLAN-isolated from the IFN and, thus, trusted.</key>
@ -262,6 +262,8 @@ About to try to download aproximately: [#!variable!packages!#] packages needed t
<key name="message_0155">When alert emails are sent, they are stored locally and then forwarded to a mail server. This is where you can configure the mail server that alerts are forwarded to for delivery to recipients.</key>
<key name="message_0156">Alert recipient Configuration</key>
<key name="message_0157">When a system alert is recorded, any alert recipient interested in that alert will be notified by email. This is determined by the alert's level, and the recipients alert level interest. If the alert's level is equal to or higher than a given alert, an email will be crafted for them, in their chosen language and units.</key>
<key name="message_0158">[ Error ] - The modules.yaml file: [#!variable!modules_yaml!#] was found, but something failed when we tried to copy it to: [#!variable!target_modules!#].</key>
<key name="message_0159">Updated module metadata.</key>
<!-- Log entries -->
<key name="log_0001">Starting: [#!variable!program!#].</key>
@ -1063,6 +1065,7 @@ If you are comfortable that the target has changed for a known reason, you can s
<key name="striker_0199">Does the user want imperial or metric units?</key>
<key name="striker_0200">The alert level used for new (and existing) Anvil! systems.</key>
<key name="striker_0201">Existing alert recipients:</key>
<key name="striker_0202">This puts the host into network mapping mode. In this most, most functions are disabled and the link status of network interfaces are closely monitored.</key>
<!-- These are generally units and appended to numbers -->
<key name="suffix_0001">#!variable!number!#/sec</key>

@ -179,18 +179,22 @@ while(1)
# Reload defaults, re-read the config and then connect to the database(s)
$anvil->refresh();
$anvil->Database->connect({check_if_configured => $check_if_database_is_configured});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, secure => 0, key => "log_0132"});
# Mark that we don't want to check the database now.
$check_if_database_is_configured = 0;
# If this host is mapping the network, we'll skip a lot of stuff. If set for over an hour, we'll
# clear it.
$anvil->data->{sys}{mapping_network} = check_if_mapping($anvil);
if ($anvil->data->{sys}{database}{connections})
{
# Run the normal tasks
keep_running($anvil);
# Handle periodic tasks
handle_periodic_tasks($anvil);
handle_periodic_tasks($anvil) if not $anvil->data->{sys}{mapping_network};
}
else
{
@ -198,7 +202,6 @@ while(1)
# network mapped and the interface used to talk to the databases went down. That's all we
# can do though.
update_state_file($anvil);
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, secure => 0, key => "log_0202"});
}
@ -221,6 +224,71 @@ $anvil->nice_exit({code => 0});
# Functions #
#############################################################################################################
# Check to see if we're mapping the network on this host.
sub check_if_mapping
{
my ($anvil) = @_;
$anvil->data->{sys}{mapping_network} = 0;
if ($anvil->data->{sys}{database}{connections})
{
my ($map_network_value, $map_network_uuid, $map_network_modified_date) = $anvil->Database->read_variable({
variable_name => "config::map_network",
variable_source_table => "hosts",
variable_source_uuid => $anvil->data->{sys}{host_uuid},
});
my $map_network_age = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:map_network_value' => $map_network_value,
's2:map_network_modified_date' => $map_network_modified_date,
's3:map_network_uuid' => $map_network_uuid,
}});
if ($map_network_uuid)
{
$map_network_age = time - $map_network_modified_date;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { map_network_age => $map_network_age }});
}
if ($map_network_value)
{
# How long ago was it set?
if ($map_network_age > 1800)
{
# Clear it.
$anvil->Database->insert_or_update_variables({
debug => 2,
variable_value => 0,
variable_uuid => $map_network_uuid,
update_value_only => 1,
});
}
else
{
# Mark it so we only track the network.
$anvil->data->{sys}{mapping_network} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::mapping_network" => $anvil->data->{sys}{mapping_network} }});
# Close any open ssh connections.
foreach my $ssh_fh_key (keys %{$anvil->data->{cache}{ssh_fh}})
{
my $ssh_fh = $anvil->data->{cache}{ssh_fh}{$ssh_fh_key};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
ssh_fh_key => $ssh_fh_key,
ssh_fh => $ssh_fh,
}});
if ($ssh_fh =~ /^Net::OpenSSH/)
{
$ssh_fh->disconnect();
}
delete $anvil->data->{cache}{ssh_fh}{$ssh_fh_key};
}
}
}
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::mapping_network" => $anvil->data->{sys}{mapping_network} }});
return($anvil->data->{sys}{mapping_network});
}
# This decides if the local system will delay daily runs on start-up.
sub set_delay
{
@ -1161,7 +1229,7 @@ sub keep_running
my ($anvil) = @_;
# Check for jobs that were running and now exited.
if (exists $anvil->data->{processes})
if ((not $anvil->data->{sys}{mapping_network}) && (exists $anvil->data->{processes}))
{
foreach my $job_uuid (%{$anvil->data->{jobs}{handles}})
{
@ -1192,7 +1260,7 @@ sub keep_running
# If we're confiugured, write out the status JSON file. If we're not configured, Update hardware state files.
my $configured = $anvil->System->check_if_configured;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { configured => $configured }});
if ($configured)
if ((not $anvil->data->{sys}{mapping_network}) && ($configured))
{
# Write out state information for all known Anvil! systems and the information from
# unconfigured nods and DR hosts, using just database data (hence, fast enough to run
@ -1206,7 +1274,7 @@ sub keep_running
}
# Run any pending jobs by calling 'anvil-jobs' with the 'job_uuid' as a background process.
run_jobs($anvil);
run_jobs($anvil) if not $anvil->data->{sys}{mapping_network};
return(0);
}

@ -192,7 +192,7 @@ sub add_databases
db_port => $db_port,
db_password => $db_password,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { failed => $failed }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { failed => $failed }});
if ($failed)
{
# Something went wrong

@ -1098,9 +1098,11 @@ sub update_install_source
# Create the repodata
print $anvil->Words->string({key => "message_0118"})."\n";
my $repo_path = "/var/www/html/".$anvil->data->{host_os}{os_type}."/".$anvil->data->{host_os}{os_arch}."/os";
my $comps_xml = $repo_path."/comps.xml";
my $target = $repo_path."/repodata/comps.xml";
my $repo_path = "/var/www/html/".$anvil->data->{host_os}{os_type}."/".$anvil->data->{host_os}{os_arch}."/os";
my $repo_data_path = $repo_path."/repodata";
my $comps_xml = $repo_path."/comps.xml";
my $modules_yaml = $repo_path."/modules.yaml";
my $target_comps = $repo_data_path."/comps.xml";
if (not -e $comps_xml)
{
# We can't install properly without the comps.xml file, it provides grouping needed by the
@ -1112,14 +1114,14 @@ sub update_install_source
$anvil->Storage->copy_file({
debug => 2,
source_file => $comps_xml,
target_file => $target,
target_file => $target_comps,
overwrite => 1,
});
if (not -e $target)
if (not -e $target_comps)
{
# Something appears to have happened and it failed to copy.
print $anvil->Words->string({key => "message_0129", variables => { comps_xml => $comps_xml, target => $target }})."\n";
update_progress($anvil, 100, "message_0129,!!comps_xml!".$comps_xml."!!,!!target!".$target."!!");
print $anvil->Words->string({key => "message_0129", variables => { comps_xml => $comps_xml, target_comps => $target_comps }})."\n";
update_progress($anvil, 100, "message_0129,!!comps_xml!".$comps_xml."!!,!!target_comps!".$target_comps."!!");
$anvil->nice_exit({code => 6});
}
update_progress($anvil, 85, "");
@ -1130,6 +1132,15 @@ sub update_install_source
print $anvil->Words->string({key => "message_0130"})."\n";
update_progress($anvil, 90, "message_0130");
### NOTE: This doesn't work for libssh2 yet (haven't figured out how to add it to 'modules.yaml'
### sourced from RHEL 8.1 ISO yet). Once that's fixed, remove 'module_hotfixes=1' from
### Striker->get_local_repo().
$output = "";
($output, $return_code) = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{modifyrepo_c}." --mdtype=modules ".$modules_yaml." ".$repo_data_path });
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }});
print $anvil->Words->string({key => "message_0159"})."\n";
update_progress($anvil, 95, "message_0159");
# Update the refresh time to now.
$anvil->Database->insert_or_update_variables({
debug => 2,
@ -1835,6 +1846,7 @@ sub load_packages
],
'm' => [
"mailcap.noarch",
"mailx.x86_64",
"man-db.x86_64",
"mcpp.x86_64",
"mdadm.x86_64",
@ -2036,6 +2048,7 @@ sub load_packages
"perl-Proc-Simple.noarch",
"perl-Ref-Util-XS.x86_64",
"perl-Ref-Util.noarch",
"perl-Mail-RFC822-Address.noarch",
"perl-Role-Tiny.noarch",
"perl-Scalar-List-Utils.x86_64",
"perl-SelfLoader.noarch",

Loading…
Cancel
Save