From 925664762aeba953fab3310319603542265b2207 Mon Sep 17 00:00:00 2001 From: Digimer Date: Tue, 8 Sep 2020 01:07:23 -0400 Subject: [PATCH] * 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 --- Anvil/Tools/Alert.pm | 8 +- Anvil/Tools/Database.pm | 64 +++++++- Anvil/Tools/Email.pm | 12 ++ cgi-bin/striker | 2 +- notes | 22 +-- .../scan-hardware} | 10 +- .../scan-hardware/scan-hardware.sql | 155 ++++++++++++++++++ .../scan-hardware.xml} | 6 +- scancore-agents/scan-network/scan-network.sql | 0 share/words.xml | 27 ++- tools/scancore | 16 +- tools/test.pl | 3 +- 12 files changed, 268 insertions(+), 57 deletions(-) rename scancore-agents/{scan-network/scan-network => scan-hardware/scan-hardware} (77%) create mode 100644 scancore-agents/scan-hardware/scan-hardware.sql rename scancore-agents/{scan-network/scan-network.xml => scan-hardware/scan-hardware.xml} (66%) delete mode 100644 scancore-agents/scan-network/scan-network.sql diff --git a/Anvil/Tools/Alert.pm b/Anvil/Tools/Alert.pm index a557d8f1..ff46e3fd 100644 --- a/Anvil/Tools/Alert.pm +++ b/Anvil/Tools/Alert.pm @@ -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 }}); } diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm index a673c6b9..18fefbf8 100644 --- a/Anvil/Tools/Database.pm +++ b/Anvil/Tools/Database.pm @@ -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 }}); diff --git a/Anvil/Tools/Email.pm b/Anvil/Tools/Email.pm index 0357e1fb..7606edc3 100755 --- a/Anvil/Tools/Email.pm +++ b/Anvil/Tools/Email.pm @@ -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}); diff --git a/cgi-bin/striker b/cgi-bin/striker index c4584164..489fa173 100755 --- a/cgi-bin/striker +++ b/cgi-bin/striker @@ -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, diff --git a/notes b/notes index 81c83b21..24baed68 100644 --- a/notes +++ b/notes @@ -286,27 +286,6 @@ Bridge * STP=no is default, we'll test 'yes'. * 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. diff --git a/scancore-agents/scan-network/scan-network b/scancore-agents/scan-hardware/scan-hardware similarity index 77% rename from scancore-agents/scan-network/scan-network rename to scancore-agents/scan-hardware/scan-hardware index e1744e9f..c6b65a68 100755 --- a/scancore-agents/scan-network/scan-network +++ b/scancore-agents/scan-hardware/scan-hardware @@ -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}); diff --git a/scancore-agents/scan-hardware/scan-hardware.sql b/scancore-agents/scan-hardware/scan-hardware.sql new file mode 100644 index 00000000..4e4c3c7c --- /dev/null +++ b/scancore-agents/scan-hardware/scan-hardware.sql @@ -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(); diff --git a/scancore-agents/scan-network/scan-network.xml b/scancore-agents/scan-hardware/scan-hardware.xml similarity index 66% rename from scancore-agents/scan-network/scan-network.xml rename to scancore-agents/scan-hardware/scan-hardware.xml index 6f8d300a..4a5544ee 100644 --- a/scancore-agents/scan-network/scan-network.xml +++ b/scancore-agents/scan-hardware/scan-hardware.xml @@ -5,16 +5,16 @@ Company: Alteeve's Niche, Inc. License: GPL v2+ Author: Madison Kelly -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'. --> - + - Starting: [#!variable!program!#]. + Starting: [#!variable!program!#]. diff --git a/scancore-agents/scan-network/scan-network.sql b/scancore-agents/scan-network/scan-network.sql deleted file mode 100644 index e69de29b..00000000 diff --git a/share/words.xml b/share/words.xml index 16ac731d..d57ba1de 100644 --- a/share/words.xml +++ b/share/words.xml @@ -11,20 +11,6 @@ Author: Madison Kelly - - - Critical - - Warning - - Notice - - Info - - Critical Cleared! - - Warning Cleared! - - Notice Cleared! - - Info Cleared! - - - 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. - ScanCore has started. - Alteeve Anvil! @@ -1042,6 +1028,7 @@ The file: [#!variable!file!#] needs to be updated. The difference is: This host UUID is: [#!variable!uuid!#] and the database identifier is: [#!variable!identifier!#]. Writing out alert email to: [#!variable!file!#]. Sending email to: [#!variable!to!#]. + I was asked to process alerts, but there are no configured email servers. No sense proceeding.. The host name: [#!variable!target!#] does not resolve to an IP address. @@ -1311,6 +1298,8 @@ About to try to download aproximately: [#!variable!packages!#] packages needed t ############################################################################################################# Hosts added or updated by the #!string!brand_0002!# on: [#!variable!date!#]: + ScanCore has started. + 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. Saved the mail server information successfully! @@ -1694,6 +1683,16 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st This string embeds 't_0001': [#!string!t_0001!#] + + - Critical + - Warning + - Notice + - Info + - Critical Cleared! + - Warning Cleared! + - Notice Cleared! + - Info Cleared! + Yes No diff --git a/tools/scancore b/tools/scancore index b0c33b18..3b210218 100755 --- a/tools/scancore +++ b/tools/scancore @@ -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."!!"}); } } diff --git a/tools/test.pl b/tools/test.pl index 77d0d97e..626b1b6a 100755 --- a/tools/test.pl +++ b/tools/test.pl @@ -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, }); }