* Added two new modules; Convert.pm for converting data types and Database.pm for managing all things related to databases.

* Created Convert->cidr() that will convert dotted decimal subnets to CIDR notation and vice versa.
* Created Database->get_local_id that returns the ID from striker.conf that matches the local host, if any,
* Created Get->network_details that returns the host name and a list of interfaces and their IP addresses (if any).
* Created System->call() that takes a shell call and returns the output.
* Created icon for the top-right bar that are "on" (lit up).
* Created a skeleton striker.conf file.
* Created the new scancore-database tool that will manage ScanCore databases.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 8 years ago
parent f948d7a762
commit 632f677f04
  1. 31
      AN/Tools.pm
  2. 187
      AN/Tools/Convert.pm
  3. 125
      AN/Tools/Database.pm
  4. 73
      AN/Tools/Get.pm
  5. 50
      AN/Tools/System.pm
  6. 1
      AN/an-tools.xml
  7. 8
      html/skins/alteeve/main.html
  8. 16
      striker.conf
  9. 40
      tools/scancore-database

@ -32,6 +32,8 @@ binmode(STDOUT, ':encoding(utf-8)');
# somewhat more OO style. I know some may wish to strike me down for this, but I like the idea of accessing
# methods via their containing module's name. (A La: C<< $an->Module->method >> rather than C<< $an->method >>).
use AN::Tools::Alert;
use AN::Tools::Database;
use AN::Tools::Convert;
use AN::Tools::Get;
use AN::Tools::Log;
use AN::Tools::Storage;
@ -104,6 +106,8 @@ sub new
my $self = {
HANDLE => {
ALERT => AN::Tools::Alert->new(),
DATABASE => AN::Tools::Database->new(),
CONVERT => AN::Tools::Convert->new(),
GET => AN::Tools::Get->new(),
LOG => AN::Tools::Log->new(),
STORAGE => AN::Tools::Storage->new(),
@ -130,6 +134,8 @@ sub new
# Get a handle on the various submodules
$an->Alert->parent($an);
$an->Database->parent($an);
$an->Convert->parent($an);
$an->Get->parent($an);
$an->Log->parent($an);
$an->Storage->parent($an);
@ -294,6 +300,30 @@ sub Alert
return ($self->{HANDLE}{ALERT});
}
=head2 Database
Access the C<Database.pm> methods via 'C<< $an->Database->method >>'.
=cut
sub Database
{
my $self = shift;
return ($self->{HANDLE}{DATABASE});
}
=head2 Convert
Access the C<Convert.pm> methods via 'C<< $an->Convert->method >>'.
=cut
sub Convert
{
my $self = shift;
return ($self->{HANDLE}{CONVERT});
}
=head2 Get
Access the C<Get.pm> methods via 'C<< $an->Get->method >>'.
@ -553,6 +583,7 @@ sub _set_paths
dmidecode => "/usr/sbin/dmidecode",
gethostip => "/usr/bin/gethostip",
hostname => "/bin/hostname",
ip => "/usr/sbin/ip",
logger => "/usr/bin/logger",
'mkdir' => "/usr/bin/mkdir",
},

@ -0,0 +1,187 @@
package AN::Tools::Convert;
#
# This module contains methods used to convert data between types
#
use strict;
use warnings;
use Data::Dumper;
our $VERSION = "3.0.0";
my $THIS_FILE = "Convert.pm";
### Methods;
# cidr
=pod
=encoding utf8
=head1 NAME
AN::Tools::Convert
Provides all methods related to converting data.
=head1 SYNOPSIS
use AN::Tools;
# Get a common object handle on all AN::Tools modules.
my $an = AN::Tools->new();
# Access to methods using '$an->Convert->X'.
#
# Example using 'cidr()';
my $subnet = $an->Convert->codr({cidr => "24"});
=head1 METHODS
Methods in this module;
=cut
sub new
{
my $class = shift;
my $self = {};
bless $self, $class;
return ($self);
}
# Get a handle on the AN::Tools object. I know that technically that is a sibling module, but it makes more
# sense in this case to think of it as a parent.
sub parent
{
my $self = shift;
my $parent = shift;
$self->{HANDLE}{TOOLS} = $parent if $parent;
return ($self->{HANDLE}{TOOLS});
}
#############################################################################################################
# Public methods #
#############################################################################################################
=head2 cidr
This takes an IPv4 CIDR notation and returns the dotted-decimal subnet, or the reverse.
# Convert a CIDR notation to a subnet.
my $subnet = $an->Convert->cidr({cidr => "24"});
In the other direction;
# Convert a subnet to a CIDR notation.
my $cidr = $an->Convert->cidr({subnet => "255.255.255.0"});
If the input data is invalid, an empty string will be returned.
=head2 Parameters;
There are two parameters, each of which is optional, but one of them is required.
=head3 cidr (optional)
This is a CIDR notation (between 0 and 24) to convert to a dotted-decimal address.
=head3 subnet (optional)
This is a dotted-decimal subnet to convert to a CIDR notation.
=cut
sub cidr
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
my $cidr = defined $parameter->{cidr} ? $parameter->{cidr} : "";
my $subnet = defined $parameter->{subnet} ? $parameter->{subnet} : "";
my $output = "";
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
cidr => $cidr,
subnet => $subnet,
}});
if ($cidr)
{
# Convert a cidr to a subnet
if ($cidr eq "0") { $output = "0.0.0.0"; }
elsif ($cidr eq "1") { $output = "128.0.0.0"; }
elsif ($cidr eq "2") { $output = "192.0.0.0"; }
elsif ($cidr eq "3") { $output = "224.0.0.0"; }
elsif ($cidr eq "4") { $output = "240.0.0.0"; }
elsif ($cidr eq "5") { $output = "248.0.0.0"; }
elsif ($cidr eq "6") { $output = "252.0.0.0"; }
elsif ($cidr eq "7") { $output = "254.0.0.0"; }
elsif ($cidr eq "8") { $output = "255.0.0.0"; }
elsif ($cidr eq "9") { $output = "255.128.0.0"; }
elsif ($cidr eq "10") { $output = "255.192.0.0"; }
elsif ($cidr eq "11") { $output = "255.224.0.0"; }
elsif ($cidr eq "12") { $output = "255.240.0.0"; }
elsif ($cidr eq "13") { $output = "255.248.0.0"; }
elsif ($cidr eq "14") { $output = "255.252.0.0"; }
elsif ($cidr eq "15") { $output = "255.254.0.0"; }
elsif ($cidr eq "16") { $output = "255.255.0.0"; }
elsif ($cidr eq "17") { $output = "255.255.128.0"; }
elsif ($cidr eq "18") { $output = "255.255.192.0"; }
elsif ($cidr eq "19") { $output = "255.255.224.0"; }
elsif ($cidr eq "20") { $output = "255.255.240.0"; }
elsif ($cidr eq "21") { $output = "255.255.248.0"; }
elsif ($cidr eq "22") { $output = "255.255.252.0"; }
elsif ($cidr eq "23") { $output = "255.255.254.0"; }
elsif ($cidr eq "24") { $output = "255.255.255.0"; }
elsif ($cidr eq "25") { $output = "255.255.255.128"; }
elsif ($cidr eq "26") { $output = "255.255.255.192"; }
elsif ($cidr eq "27") { $output = "255.255.255.224"; }
elsif ($cidr eq "28") { $output = "255.255.255.240"; }
elsif ($cidr eq "29") { $output = "255.255.255.248"; }
elsif ($cidr eq "30") { $output = "255.255.255.252"; }
elsif ($cidr eq "31") { $output = "255.255.255.254"; }
elsif ($cidr eq "32") { $output = "255.255.255.255"; }
}
elsif ($subnet)
{
if ($subnet eq "0.0.0.0" ) { $output = "0"; }
elsif ($output eq "128.0.0.0" ) { $output = "1"; }
elsif ($output eq "192.0.0.0" ) { $output = "2"; }
elsif ($output eq "224.0.0.0" ) { $output = "3"; }
elsif ($output eq "240.0.0.0" ) { $output = "4"; }
elsif ($output eq "248.0.0.0" ) { $output = "5"; }
elsif ($output eq "252.0.0.0" ) { $output = "6"; }
elsif ($output eq "254.0.0.0" ) { $output = "7"; }
elsif ($output eq "255.0.0.0" ) { $output = "8"; }
elsif ($output eq "255.128.0.0" ) { $output = "9"; }
elsif ($output eq "255.192.0.0" ) { $output = "10"; }
elsif ($output eq "255.224.0.0" ) { $output = "11"; }
elsif ($output eq "255.240.0.0" ) { $output = "12"; }
elsif ($output eq "255.248.0.0" ) { $output = "13"; }
elsif ($output eq "255.252.0.0" ) { $output = "14"; }
elsif ($output eq "255.254.0.0" ) { $output = "15"; }
elsif ($output eq "255.255.0.0" ) { $output = "16"; }
elsif ($output eq "255.255.128.0" ) { $output = "17"; }
elsif ($output eq "255.255.192.0" ) { $output = "18"; }
elsif ($output eq "255.255.224.0" ) { $output = "19"; }
elsif ($output eq "255.255.240.0" ) { $output = "20"; }
elsif ($output eq "255.255.248.0" ) { $output = "21"; }
elsif ($output eq "255.255.252.0" ) { $output = "22"; }
elsif ($output eq "255.255.254.0" ) { $output = "23"; }
elsif ($output eq "255.255.255.0" ) { $output = "24"; }
elsif ($output eq "255.255.255.128" ) { $output = "25"; }
elsif ($output eq "255.255.255.192" ) { $output = "26"; }
elsif ($output eq "255.255.255.224" ) { $output = "27"; }
elsif ($output eq "255.255.255.240" ) { $output = "28"; }
elsif ($output eq "255.255.255.248" ) { $output = "29"; }
elsif ($output eq "255.255.255.252" ) { $output = "30"; }
elsif ($output eq "255.255.255.254" ) { $output = "31"; }
elsif ($output eq "255.255.255.255" ) { $output = "32"; }
}
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output }});
return($output);
}

@ -0,0 +1,125 @@
package AN::Tools::Database;
#
# This module contains methods related to databases.
#
use strict;
use warnings;
use Data::Dumper;
our $VERSION = "3.0.0";
my $THIS_FILE = "Database.pm";
### Methods;
# get_local_id
=pod
=encoding utf8
=head1 NAME
AN::Tools::Database
Provides all methods related to managing and accessing databases.
=head1 SYNOPSIS
use AN::Tools;
# Get a common object handle on all AN::Tools modules.
my $an = AN::Tools->new();
# Access to methods using '$an->Database->X'.
#
# Example using 'get_local_id()';
my $local_id = $an->Database->get_local_id;
=head1 METHODS
Methods in this module;
=cut
sub new
{
my $class = shift;
my $self = {};
bless $self, $class;
return ($self);
}
# Get a handle on the AN::Tools object. I know that technically that is a sibling module, but it makes more
# sense in this case to think of it as a parent.
sub parent
{
my $self = shift;
my $parent = shift;
$self->{HANDLE}{TOOLS} = $parent if $parent;
return ($self->{HANDLE}{TOOLS});
}
#############################################################################################################
# Public methods #
#############################################################################################################
=head2 get_local_id
This returns the database ID from 'C<< striker.conf >>' based on matching the 'C<< database::<id>::host >>' to the local machine's host name or one of the active IP addresses on the host.
# Get the local ID
my $local_id = $an->Database->get_local_id;
This will return a blank string if no match is found.
=cut
sub get_local_id
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
my $local_id = "";
my $network_details = $an->Get->network_details;
foreach my $id (sort {$a cmp $b} keys %{$an->data->{database}})
{
if ($network_details->{hostname} eq $an->data->{database}{$id}{host})
{
$local_id = $id;
last;
}
}
if (not $local_id)
{
foreach my $interface (sort {$a cmp $b} keys %{$network_details->{interface}})
{
my $ip_address = $network_details->{interface}{$interface}{ip};
my $subnet_mask = $network_details->{interface}{$interface}{netmask};
foreach my $id (sort {$a cmp $b} keys %{$an->data->{database}})
{
if ($ip_address eq $an->data->{database}{$id}{host})
{
$local_id = $id;
last;
}
}
}
}
return($local_id);
}
# =head3
#
# Private Functions;
#
# =cut
#############################################################################################################
# Private functions #
#############################################################################################################

@ -13,6 +13,8 @@ my $THIS_FILE = "Get.pm";
### Methods;
# date_and_time
# host_uuid
# local_db_id
# network_details
# switches
=pod
@ -79,7 +81,6 @@ This method returns the date and/or time using either the current time, or a spe
NOTE: This only returns times in 24-hour notation.
=head2 Parameters;
=head3 date_only (optional)
@ -215,7 +216,75 @@ sub host_uuid
return($an->data->{HOST}{UUID});
}
=head2
=head2 network_details
This method returns the local hostname and IP addresses.
It returns a hash reference containing data in the following keys:
C<< hostname >> = <name>
C<< interface::<interface>::ip >> = <ip_address>
C<< interface::<interface>::netmask >> = <dotted_decimal_subnet>
=cut
sub network_details
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
my $network = {};
my $hostname = $an->System->call({shell_call => $an->data->{path}{exe}{hostname}});
my $ip_addr_list = $an->System->call({shell_call => $an->data->{path}{exe}{ip}." addr list"});
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
hostname => $hostname,
ip_addr_list => $ip_addr_list,
}});
$network->{hostname} = $hostname;
my $in_interface = "";
my $ip_address = "";
my $subnet_mask = "";
foreach my $line (split/\n/, $ip_addr_list)
{
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }});
if ($line =~ /^\d+: (.*?):/)
{
$in_interface = $1;
$ip_address = "";
$subnet_mask = "";
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { in_interface => $in_interface }});
next if $in_interface eq "lo";
$network->{interface}{$in_interface}{ip} = "--";
$network->{interface}{$in_interface}{netmask} = "--";
}
if ($in_interface)
{
next if $in_interface eq "lo";
if ($line =~ /inet (.*?)\/(.*?) /)
{
$ip_address = $1;
$subnet_mask = $2;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
ip_address => $ip_address,
subnet_mask => $subnet_mask,
}});
if ((($subnet_mask =~ /^\d$/) or ($subnet_mask =~ /^\d\d$/)) && ($subnet_mask < 25))
{
$subnet_mask = $an->Convert->cidr({cidr => $subnet_mask});
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { subnet_mask => $subnet_mask }});
}
$network->{interface}{$in_interface}{ip} = $ip_address;
$network->{interface}{$in_interface}{netmask} = $subnet_mask;
}
}
}
return($network);
}
=head2 switches
This reads in the command line switches used to invoke the parent program.

@ -11,7 +11,7 @@ our $VERSION = "3.0.0";
my $THIS_FILE = "System.pm";
### Methods;
#
# call
=pod
@ -32,8 +32,8 @@ Provides all methods related to storage on a system.
# Access to methods using '$an->System->X'.
#
# Example using '...()';
my $data = $an->System->...({file => "/tmp/foo"});
# Example using 'system_call()';
my $hostname = $an->System->call({shell_call => $an->data->{path}{exe}{hostname}});
=head1 METHODS
@ -67,6 +67,50 @@ sub parent
# Public methods #
#############################################################################################################
=head2 call
This method makes a system call and returns the output (with the last new-line removed). If there is a problem, 'C<< #!error!# >>' is returned and the error will be logged.
=cut
sub call
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
my $shell_call = defined $parameter->{shell_call} ? $parameter->{shell_call} : "";
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { shell_call => $shell_call }});
my $output = "#!error!#";
if (not $shell_call)
{
# wat?
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0043"});
}
else
{
# Make the system call
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, key => "log_0011", variables => { shell_call => $shell_call }});
open (my $file_handle, $shell_call." 2>&1 |") or $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0014", variables => { shell_call => $shell_call, error => $! }});
while(<$file_handle>)
{
chomp;
my $line = $_;
if ($output eq "#!error!#")
{
$output = "";
}
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, key => "log_0017", variables => { line => $line }});
$output .= $line."\n";
}
close $file_handle;
$output =~ s/\n$//s;
}
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output }});
return($output);
}
# =head3
#

@ -62,6 +62,7 @@ It also has replacement variables: [#!variable!first!#] and [#!variable!second!#
<key name="log_0040"><![CDATA[[ Error ] - The module Storage->write_file() was asked to write the file: [#!variable!file!#] but it already exists and 'overwrite' was not set. Aborting.]]></key>
<key name="log_0041"><![CDATA[[ Error ] - The module Storage->write_file() was asked to write the file: [#!variable!file!#] but it is not a full path. Aborting.]]></key>
<key name="log_0042"><![CDATA[[ Error ] - The module Words->string() was asked to process the string: [#!variable!string!#] which has insertion variables, but nothing was passed to the 'variables' parameter.]]></key>
<key name="log_0043"><![CDATA[[ Error ] - The module System->call() was called but 'shell_call' was not passed or was empty.]]></key>
<!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. -->
<key name="t_0000">Test</key>

@ -2,16 +2,16 @@
<table id="button_bar">
<tr>
<td>
<img src="#!data!skin::url!#/images/striker_icon.png" class="logo">
<img src="#!data!skin::url!#/images/striker_icon_on.png" class="top_icon">
</td>
<td>
<img src="#!data!skin::url!#/images/anvil_icon.png" class="top_icon">
<img src="#!data!skin::url!#/images/anvil_icon_on.png" class="top_icon">
</td>
<td>
<img src="#!data!skin::url!#/images/users_icon.png" class="top_icon">
<img src="#!data!skin::url!#/images/users_icon_on.png" class="top_icon">
</td>
<td>
<img src="#!data!skin::url!#/images/help_icon.png" class="top_icon">
<a href="https://alteeve.com/w/Support" target="_new"><img src="#!data!skin::url!#/images/help_icon_on.png" id="help_icon" class="top_icon"></a>
</td>
</tr>
</table>

@ -0,0 +1,16 @@
# This is the main Striker (and ScanCore) configuration file.
#
database::1::host = 192.168.122.201
database::1::port = 5432
database::1::name = scancore
database::1::user = admin
database::1::password = Initial1
database::1::ping_before_connect = 1
database::2::host = an-striker02.alteeve.com
database::2::port = 5432
database::2::name = scancore
database::2::user = admin
database::2::password = Initial1
database::2::ping_before_connect = 1

@ -0,0 +1,40 @@
#!/usr/bin/perl
#
# This checks the state of the database server and, if necessary, sets up the database.
use strict;
use warnings;
use Data::Dumper;
use AN::Tools;
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
if (($running_directory =~ /^\./) && ($ENV{PWD}))
{
$running_directory =~ s/^\./$ENV{PWD}/;
}
my $an = AN::Tools->new();
$an->Log->level(2);
$an->Storage->read_config({file => "/etc/striker/striker.conf"});
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete.
$| = 1;
my $local_id = $an->Database->get_local_id;
if ($local_id)
{
print "Local ID: [$local_id]\n";
}
else
{
print "Failed to find a local ID, no databases are stored on this machine.\n";
}
exit(0);
#############################################################################################################
# Functions #
#############################################################################################################
Loading…
Cancel
Save