* Created Database->check_for_schema() (not finished) that will check/add a schema for a scan agent.

* Renamed the scan-network skeleton scan agent to scan-hardware and started work on it based on the M2 version.
* Updated Database->get_recipients() to take the 'include_deleted' parameter, and changed the default behaviour to only return active records.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 4 years ago
parent dc5ec9c264
commit 925664762a
  1. 8
      Anvil/Tools/Alert.pm
  2. 64
      Anvil/Tools/Database.pm
  3. 12
      Anvil/Tools/Email.pm
  4. 2
      cgi-bin/striker
  5. 22
      notes
  6. 10
      scancore-agents/scan-hardware/scan-hardware
  7. 155
      scancore-agents/scan-hardware/scan-hardware.sql
  8. 6
      scancore-agents/scan-hardware/scan-hardware.xml
  9. 0
      scancore-agents/scan-network/scan-network.sql
  10. 27
      share/words.xml
  11. 16
      tools/scancore
  12. 3
      tools/test.pl

@ -437,10 +437,10 @@ sub register
if (($show_header) && (not $title))
{
# Set it based on the alert_level.
if ($alert_level == 1) { $title = $clear_alert ? "alert_title_0005" : "alert_title_0001"; } # Critical (or Critical Cleared)
elsif ($alert_level == 2) { $title = $clear_alert ? "alert_title_0006" : "alert_title_0002"; } # Warning (or Warning Cleared)
elsif ($alert_level == 3) { $title = $clear_alert ? "alert_title_0007" : "alert_title_0003"; } # Notice (or Notice Cleared)
elsif ($alert_level == 4) { $title = $clear_alert ? "alert_title_0008" : "alert_title_0004"; } # Info (or Info Cleared)
if ($alert_level == 1) { $title = $clear_alert ? "title_0005" : "title_0001"; } # Critical (or Critical Cleared)
elsif ($alert_level == 2) { $title = $clear_alert ? "title_0006" : "title_0002"; } # Warning (or Warning Cleared)
elsif ($alert_level == 3) { $title = $clear_alert ? "title_0007" : "title_0003"; } # Notice (or Notice Cleared)
elsif ($alert_level == 4) { $title = $clear_alert ? "title_0008" : "title_0004"; } # Info (or Info Cleared)
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { title => $title }});
}

@ -354,6 +354,50 @@ sub check_lock_age
}
=head2 check_for_schema
This reads in a SQL schema file and checks if the first table seen exists in the database. If it isn't, the schema file is loaded into the database main.
If the table exists (and loading isn't needed), C<< 0 >> is returned. If the schema is loaded, C<< 1 >> is returned. If there is any problem, C<< !!error!! >> is returned.
B<< Note >>: This does not check for schema changes!
This method is meant to be used by ScanCore scan agents to see if they're running for the first time.
Parameters;
=head3 file (required)
This is the file to be read in.
=cut
sub check_for_schema
{
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 => "Database->check_for_schema()" }});
my $loaded = 0;
my $file = defined $parameter->{file} ? $parameter->{file} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
file => $file,
}});
if (not $file)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->check_for_schema()", parameter => "file" }});
return("!!error!!");
}
my $body = $anvil->Storage->read_file({file => $file});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { body => $body }});
return($loaded);
}
=head2 configure_pgsql
This configures the local database server. Specifically, it checks to make sure the daemon is running and starts it if not. It also checks the C<< pg_hba.conf >> configuration to make sure it is set properly to listen on this machine's IP addresses and interfaces.
@ -3058,7 +3102,11 @@ FROM
This returns a list of users listening to alerts for a given host, along with their alert level.
This method takes no parameters.
Parameters;
=head3 include_deleted (optional, default '0')
When a recipient is deleted, the C<< recipient_name >> is set to C<< DELETED >>. If you want these to be loaded as well, set this to C<< 1 >>
=cut
sub get_recipients
@ -3069,6 +3117,11 @@ sub get_recipients
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->get_recipients()" }});
my $include_deleted = defined $parameter->{include_deleted} ? $parameter->{include_deleted} : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
include_deleted => $include_deleted,
}});
# We're going to include the alert levels for this host based on overrides that might exist in the
# 'notifications' table. If the data hasn't already been loaded, we'll load it now.
if (not $anvil->data->{notifications}{notification_uuid})
@ -3085,7 +3138,14 @@ SELECT
recipient_language,
recipient_level
FROM
recipients
recipients";
if (not $include_deleted)
{
$query .= "
WHERE
recipient_name != 'DELETED'";
}
$query .= "
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});

@ -349,6 +349,8 @@ sub get_next_server
This method looks for registered alerts, creates an email for recipients, and sends the resulting emails into the mail server queue for dispatch.
B<< Note >>: If there is no configured mail servers, this method returns with C<< 1 >> without actually doing anything. Otherwise, it returns C<< 0 >>.
This method takes no parameters.
=cut
@ -360,6 +362,16 @@ sub send_alerts
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Email->send_alerts()" }});
# If we don't have a configured mail server, there's no reason processing alerts.
my $active_mail_server = $anvil->Email->get_current_server({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { active_mail_server => $active_mail_server }});
if (not $active_mail_server)
{
# No mail server, no sense proceeding.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0543"});
return(1);
}
# Load the alerts
$anvil->Database->get_alerts({debug => 2});
$anvil->Database->get_recipients({debug => 2});

@ -487,7 +487,7 @@ WHERE
if ($confirm)
{
# Delete.
$anvil->Database->insert_or_update_recipientss({
$anvil->Database->insert_or_update_recipients({
debug => 2,
'delete' => 1,
recipient_uuid => $recipient_uuid,

22
notes

@ -286,27 +286,6 @@ Bridge
* STP=no is default, we'll test 'yes'.
* DOMAIN="<client_domain>"
# Network Setup
hostnamectl set-hostname m3-a02n01.alteeve.com --static
hostnamectl set-hostname --pretty "Alteeve's Niche! - Anvil! 02, Node 01"
hostname m3-a02n01.alteeve.com
ssh-keygen -t rsa -N "" -b 8191 -f ~/.ssh/id_rsa
hosts:
====
10.1.20.1 m3-a02n01.bcn m3-a02n01 m3-a02n01.alteeve.com
10.41.20.1 m3-a02n01.sn
10.255.20.1 m3-a02n01.ifn
10.1.20.2 m3-a02n02.bcn m3-a02n02 m3-a02n02.alteeve.com
10.41.20.2 m3-a02n02.sn
10.255.20.2 m3-a02n02.ifn
10.1.22.1 m3-a02dr01.bcn m3-a02dr01 m3-a02dr01.alteeve.com
10.41.22.1 m3-a02dr01.sn
10.255.22.1 m3-a02dr01.ifn
====
=======
virt-manager stores information in dconf-editor -> /org/virt-manager/virt-manager/connections ($HOME/.config/dconf/user)
@ -372,6 +351,7 @@ pcs stonith level add 3 mk-a02n02 delay_node2
pcs property set stonith-max-attempts=INFINITY
pcs property set stonith-enabled=true
### TODO: Look into 'priority-fencing-delay'
# Create a new server resource, stopped, create the location constraint (higher == preferred), then start.

@ -1,6 +1,6 @@
#!/usr/bin/perl
#
# This scans the local network (interfaces, bonds and bridges).
# This scans the hardware, like RAM modules, CSS LED status, CPU information, etc.
#
# Examples;
#
@ -28,8 +28,16 @@ if (($running_directory =~ /^\./) && ($ENV{PWD}))
my $anvil = Anvil::Tools->new({log_level => 2, log_secure => 1});
$anvil->Storage->read_config();
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0115", variables => { program => $THIS_FILE }});
# Read switches
$anvil->Get->switches;
# Make sure our schema is loaded.
$anvil->Database->check_for_schema({file => $anvil->data->{path}{directories}{scan_agents}."/".$THIS_FILE."/".$THIS_FILE.".sql"});
$anvil->nice_exit({exit_code => 0});

@ -0,0 +1,155 @@
-- This is the database schema for the 'hardware Scan Agent'.
CREATE TABLE hardware (
hardware_uuid uuid primary key,
hardware_host_uuid uuid not null,
hardware_cpu_model text not null,
hardware_cpu_cores numeric not null, -- We don't care about individual sockets / chips
hardware_cpu_threads numeric not null,
hardware_cpu_bugs text not null,
hardware_cpu_flags text not null, --
hardware_ram_total numeric not null, -- This is the sum of the hardware memory module capacity
hardware_memory_total numeric not null, -- This is the amount seen by the OS, minus shared memory, like that allocated to video
hardware_memory_free numeric not null, --
hardware_swap_total numeric not null, --
hardware_swap_free numeric not null, --
hardware_led_id text not null, --
hardware_led_css text not null, --
hardware_led_error text not null, --
modified_date timestamp with time zone not null,
FOREIGN KEY(hardware_host_uuid) REFERENCES hosts(host_uuid)
);
ALTER TABLE hardware OWNER TO admin;
CREATE TABLE history.hardware (
history_id bigserial,
hardware_uuid uuid,
hardware_host_uuid uuid,
hardware_cpu_model text,
hardware_cpu_cores numeric,
hardware_cpu_threads numeric,
hardware_cpu_bugs text,
hardware_cpu_flags text,
hardware_ram_total numeric,
hardware_memory_total numeric,
hardware_memory_free numeric,
hardware_swap_total numeric,
hardware_swap_free numeric,
hardware_led_id text,
hardware_led_css text,
hardware_led_error text,
modified_date timestamp with time zone not null
);
ALTER TABLE history.hardware OWNER TO admin;
CREATE FUNCTION history_hardware() RETURNS trigger
AS $$
DECLARE
history_hardware RECORD;
BEGIN
SELECT INTO history_hardware * FROM hardware WHERE hardware_uuid=new.hardware_uuid;
INSERT INTO history.hardware
(hardware_uuid,
hardware_host_uuid,
hardware_cpu_model,
hardware_cpu_cores,
hardware_cpu_threads,
hardware_cpu_bugs,
hardware_cpu_flags,
hardware_ram_total,
hardware_memory_total,
hardware_memory_free,
hardware_swap_total,
hardware_swap_free,
hardware_led_id,
hardware_led_css,
hardware_led_error,
modified_date)
VALUES
(history_hardware.hardware_uuid,
history_hardware.hardware_host_uuid,
history_hardware.hardware_cpu_model,
history_hardware.hardware_cpu_cores,
history_hardware.hardware_cpu_threads,
history_hardware.hardware_cpu_bugs,
history_hardware.hardware_cpu_flags,
history_hardware.hardware_ram_total,
history_hardware.hardware_memory_total,
history_hardware.hardware_memory_free,
history_hardware.hardware_swap_total,
history_hardware.hardware_swap_free,
history_hardware.hardware_led_id,
history_hardware.hardware_led_css,
history_hardware.hardware_led_error,
history_hardware.modified_date);
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
ALTER FUNCTION history_hardware() OWNER TO admin;
CREATE TRIGGER trigger_hardware
AFTER INSERT OR UPDATE ON hardware
FOR EACH ROW EXECUTE PROCEDURE history_hardware();
CREATE TABLE hardware_ram_modules (
hardware_ram_module_uuid uuid primary key,
hardware_ram_module_host_uuid uuid not null,
hardware_ram_module_locator text not null,
hardware_ram_module_size numeric not null,
hardware_ram_module_manufacturer text not null,
hardware_ram_module_model text not null,
hardware_ram_module_serial_number text not null,
modified_date timestamp with time zone not null,
FOREIGN KEY(hardware_ram_module_host_uuid) REFERENCES hosts(host_uuid)
);
ALTER TABLE hardware_ram_modules OWNER TO admin;
CREATE TABLE history.hardware_ram_modules (
history_id bigserial,
hardware_ram_module_uuid uuid,
hardware_ram_module_host_uuid uuid,
hardware_ram_module_locator text,
hardware_ram_module_size numeric,
hardware_ram_module_manufacturer text,
hardware_ram_module_model text,
hardware_ram_module_serial_number text,
modified_date timestamp with time zone not null
);
ALTER TABLE history.hardware_ram_modules OWNER TO admin;
CREATE FUNCTION history_hardware_ram_modules() RETURNS trigger
AS $$
DECLARE
history_hardware_ram_modules RECORD;
BEGIN
SELECT INTO history_hardware_ram_modules * FROM hardware_ram_modules WHERE hardware_ram_module_uuid=new.hardware_ram_module_uuid;
INSERT INTO history.hardware_ram_modules
(hardware_ram_module_uuid,
hardware_ram_module_host_uuid,
hardware_ram_module_locator,
hardware_ram_module_size,
hardware_ram_module_manufacturer,
hardware_ram_module_model,
hardware_ram_module_serial_number,
modified_date)
VALUES
(history_hardware_ram_modules.hardware_ram_module_uuid,
history_hardware_ram_modules.hardware_ram_module_host_uuid,
history_hardware_ram_modules.hardware_ram_module_locator,
history_hardware_ram_modules.hardware_ram_module_size,
history_hardware_ram_modules.hardware_ram_module_manufacturer,
history_hardware_ram_modules.hardware_ram_module_model,
history_hardware_ram_modules.hardware_ram_module_serial_number,
history_hardware_ram_modules.modified_date);
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
ALTER FUNCTION history_hardware_ram_modules() OWNER TO admin;
CREATE TRIGGER trigger_hardware_ram_modules
AFTER INSERT OR UPDATE ON hardware_ram_modules
FOR EACH ROW EXECUTE PROCEDURE history_hardware_ram_modules();

@ -5,16 +5,16 @@ Company: Alteeve's Niche, Inc.
License: GPL v2+
Author: Madison Kelly <mkelly@alteeve.ca>
NOTE: All string keys MUST be prefixed with the agent name! ie: 'scan_network_log_0001'.
NOTE: All string keys MUST be prefixed with the agent name! ie: 'scan_hardware_log_0001'.
-->
<words>
<meta version="3.0.0" languages="en_CA,jp"/>
<!-- Canadian English -->
<language name="en_CA" long_name="Canadian English" description="ScanCore scan agent that monitors local network interfaces, bonds and bridges.">
<language name="en_CA" long_name="Canadian English" description="ScanCore scan agent that monitors hardware, like RAM modules, CSS LED status, CPU information, etc.">
<!-- Log entries -->
<key name="scan_network_log_0001">Starting: [#!variable!program!#].</key>
<key name="scan_hardware_log_0001">Starting: [#!variable!program!#].</key>
</language>
</words>

@ -11,20 +11,6 @@ Author: Madison Kelly <mkelly@alteeve.ca>
<!-- Canadian English -->
<language name="en_CA" long_name="Canadian English" description="Anvil! language file.">
<!-- Alert titles -->
<key name="alert_title_0001">- Critical</key>
<key name="alert_title_0002">- Warning</key>
<key name="alert_title_0003">- Notice</key>
<key name="alert_title_0004">- Info</key>
<key name="alert_title_0005">- Critical Cleared!</key>
<key name="alert_title_0006">- Warning Cleared!</key>
<key name="alert_title_0007">- Notice Cleared!</key>
<key name="alert_title_0008">- Info Cleared!</key>
<!-- Alert messages -->
<key name="alert_message_0001">The scan agent: [#!variable!agent_name!#] timed out! It was given: [#!variable!timeout!#] seconds to run, but it didn't return, so it was terminated.</key>
<key name="alert_message_0002">ScanCore has started.</key>
<!-- Branded strings reskinners may wish to change. -->
<key name="brand_0001">Alteeve</key>
<key name="brand_0002">Anvil!</key>
@ -1042,6 +1028,7 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="log_0540">This host UUID is: [#!variable!uuid!#] and the database identifier is: [#!variable!identifier!#].</key>
<key name="log_0541">Writing out alert email to: [#!variable!file!#].</key>
<key name="log_0542">Sending email to: [#!variable!to!#].</key>
<key name="log_0543">I was asked to process alerts, but there are no configured email servers. No sense proceeding..</key>
<!-- Messages for users (less technical than log entries), though sometimes used for logs, too. -->
<key name="message_0001">The host name: [#!variable!target!#] does not resolve to an IP address.</key>
@ -1311,6 +1298,8 @@ About to try to download aproximately: [#!variable!packages!#] packages needed t
#############################################################################################################
</key> <!-- Translation note: System->update_hosts() looks for '##] anvil-daemon [##' to know if this alert was added to /etc/hosts. As such, please retain that exact string in your translation. -->
<key name="message_0178">Hosts added or updated by the #!string!brand_0002!# on: [#!variable!date!#]:</key>
<key name="message_0179">ScanCore has started.</key>
<key name="message_0180">The scan agent: [#!variable!agent_name!#] timed out! It was given: [#!variable!timeout!#] seconds to run, but it didn't return, so it was terminated.</key>
<!-- Success messages shown to the user -->
<key name="ok_0001">Saved the mail server information successfully!</key>
@ -1694,6 +1683,16 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
</key>
<key name="t_0006">This string embeds 't_0001': [#!string!t_0001!#]</key>
<!-- Titles, usually for alerts -->
<key name="title_0001">- Critical</key>
<key name="title_0002">- Warning</key>
<key name="title_0003">- Notice</key>
<key name="title_0004">- Info</key>
<key name="title_0005">- Critical Cleared!</key>
<key name="title_0006">- Warning Cleared!</key>
<key name="title_0007">- Notice Cleared!</key>
<key name="title_0008">- Info Cleared!</key>
<!-- These are units, words and so on used when displaying information. -->
<key name="unit_0001">Yes</key>
<key name="unit_0002">No</key>

@ -45,10 +45,10 @@ wait_for_database($anvil);
# If we're not configured, sleep.
wait_until_configured($anvil);
# Send a startup
$anvil->Mail->check_config;
$anvil->Alert->register
exit;
# Send a startup message immediately
$anvil->Email->check_config();
$anvil->Alert->register({alert_level => "notice", message => "message_0179", set_by => $THIS_FILE});
$anvil->Email->send_alerts();
# Disconnect. We'll reconnect inside the loop
$anvil->Database->disconnect();
@ -86,6 +86,8 @@ while(1)
if ($anvil->data->{switches}{'run-once'})
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0055"});
$anvil->Alert->register({set_by => $THIS_FILE, alert_level => "notice", message => "message_0055"});
$anvil->Email->send_alerts();
$anvil->nice_exit({exit_code => 0});
}
@ -179,11 +181,7 @@ sub call_agents
if ($return_code eq "124")
{
# Register an alert...
$anvil->Alert->register({
alert_level => "notice",
set_by => $THIS_FILE,
message => "alert_message_0001,!!agent_name!".$agent_name."!!,!!timeout!".$timeout."!!",
});
$anvil->Alert->register({set_by => $THIS_FILE, alert_level => "notice", message => "message_0180,!!agent_name!".$agent_name."!!,!!timeout!".$timeout."!!"});
}
}

@ -34,8 +34,7 @@ if (0)
$anvil->Alert->register({
debug => 2,
alert_level => "warning",
title => "alert_title_0002",
message => "alert_message_0002",
message => "message_0002",
set_by => $THIS_FILE,
});
}

Loading…
Cancel
Save