You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
853 lines
35 KiB
853 lines
35 KiB
#!/usr/bin/perl |
|
# |
|
# Exit codes; |
|
# 0 == OK |
|
# 1 == Host UUID not available yet. |
|
# |
|
|
|
use strict; |
|
use warnings; |
|
use AN::Tools; |
|
use Data::Dumper; |
|
|
|
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(); |
|
|
|
# Print the html headers, with a new line to break the header from the body. |
|
print $an->Template->get({file => "shared.html", name => "http_headers"})."\n"; |
|
|
|
# Set the log level to 2. Setting 3 slows he program down a LOT. |
|
$an->Log->level({set => 3}); |
|
|
|
# Read in our words file. |
|
$an->Words->read({file => $an->data->{path}{directories}{'cgi-bin'}."/words.xml"}); |
|
|
|
# Read the config and then connect to the database. |
|
$an->Storage->read_config({file => "/etc/striker/striker.conf"}); |
|
|
|
# Make sure I can read the host UUID. |
|
if (not $an->Get->host_uuid) |
|
{ |
|
# Too early, exit. |
|
print $an->Words->string({key => "striker_error_0002"}); |
|
$an->nice_exit({exit_code => 1}); |
|
} |
|
|
|
my $connections = $an->Database->connect({ |
|
sql_file => $an->data->{sys}{database}{schema}, |
|
test_table => "network_interfaces", |
|
}); |
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0132", variables => { connections => $connections }}); |
|
if (not $connections) |
|
{ |
|
# No databases, exit. |
|
print $an->Words->string({key => "striker_error_0003"}); |
|
$an->nice_exit({exit_code => 2}); |
|
} |
|
|
|
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete. |
|
$| = 1; |
|
|
|
### Setup some variables. |
|
$an->data->{form}{error_massage} = " "; |
|
## Network stuff... The second octet auto-increments to handle N-number of netowrks. As such, we need to use |
|
## a wider spread between the BCNs, SNs and IFNs than we had in v2. |
|
# BCN starts at 10.(0+n)/16 |
|
$an->data->{'default'}{bcn}{subnet} = "10.0.0.0"; |
|
$an->data->{'default'}{bcn}{netmask} = "255.255.0.0"; |
|
$an->data->{'default'}{bcn}{pdu_octet3} = "1"; |
|
$an->data->{'default'}{bcn}{ups_octet3} = "2"; |
|
$an->data->{'default'}{bcn}{switch_octet3} = "3"; |
|
$an->data->{'default'}{bcn}{striker_octet3} = "4"; |
|
# SN starts at 10.(40+n)/16 |
|
$an->data->{'default'}{sn}{subnet} = "10.40.0.0"; |
|
$an->data->{'default'}{sn}{netmask} = "255.255.0.0"; |
|
# IFN starts at 10.(80+)/16 |
|
$an->data->{'default'}{ifn}{subnet} = "10.80.0.0"; |
|
$an->data->{'default'}{ifn}{netmask} = "255.255.0.0"; |
|
|
|
# Read in any CGI variables, if needed. |
|
$an->Get->cgi(); |
|
|
|
$an->data->{skin}{url} = $an->data->{path}{urls}{skins}."/".$an->Template->skin; |
|
my $header = $an->Template->get({file => "main.html", name => "header", variables => { language => $an->Words->language }}); |
|
my $body = ""; |
|
# This will be true when the dashboard is unconfigured. |
|
if (not $an->data->{cgi}{step}{value}) |
|
{ |
|
$body = config_step1($an); |
|
} |
|
elsif ($an->data->{cgi}{step}{value} eq "step1") |
|
{ |
|
# Sanity check step1. |
|
my $sane = sanity_check_step1($an); |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { sane => $sane }}); |
|
if ($sane) |
|
{ |
|
# Step 1 was sanem show step 2. |
|
$body = config_step2($an); |
|
} |
|
else |
|
{ |
|
# No good |
|
$body = config_step1($an); |
|
} |
|
} |
|
else |
|
{ |
|
$body = get_network_details_form($an); |
|
} |
|
my $buttons = $an->Template->get({file => "main.html", name => "button_bar"}); |
|
my $footer = $an->Template->get({file => "main.html", name => "footer"}); |
|
|
|
# Display the page. |
|
my $template = $an->Template->get({file => "main.html", name => "master", variables => { |
|
header => $header, |
|
skin_url => $an->data->{path}{urls}{skins}."/".$an->Template->skin, |
|
left_top_bar => " ", |
|
center_top_bar => $an->data->{form}{error_massage}, |
|
right_top_bar => $buttons, |
|
center_body => $body, |
|
left_bottom_bar => " ", |
|
center_bottom_bar => " ", |
|
right_bottom_bar => " ", |
|
footer => $footer, |
|
}}); |
|
|
|
print $template; |
|
|
|
$an->nice_exit({exit_code => 0}); |
|
|
|
|
|
############################################################################################################# |
|
# Functions # |
|
############################################################################################################# |
|
|
|
# This is step2 where the user maps their network. |
|
sub config_step2 |
|
{ |
|
my ($an) = @_; |
|
|
|
# We need to decide how many IFNs there is, decide if we have enough NICs and then build the form |
|
# either complaining about insufficient NICs or a list of interfaces (single or bond, depending on |
|
# iface count), the IPs to assign and mapping MACs to ifaces. We'll also offer an option to |
|
# "blind-map" as we did in v2. |
|
get_network_details($an); |
|
my $required_interfaces_for_single = 1 + $an->data->{cgi}{ifn_count}{value}; |
|
my $required_interfaces_for_bonds = 2 * $required_interfaces_for_single; |
|
my $interface_count = keys %{$an->data->{interfaces}}; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
required_interfaces_for_single => $required_interfaces_for_single, |
|
required_interfaces_for_bonds => $required_interfaces_for_bonds, |
|
interface_count => $interface_count, |
|
}}); |
|
|
|
my $interface_options = []; |
|
foreach my $interface (sort {$a cmp $b} keys %{$an->data->{interfaces}}) |
|
{ |
|
my $this_mac = $an->data->{interfaces}{$interface}{mac}; |
|
push @{$interface_options}, $this_mac."#!#".$this_mac." (".$interface.")"; |
|
} |
|
|
|
my $problem = 0; |
|
my $interface_form = ""; |
|
my $cgi = ""; |
|
my $links = []; |
|
if ($interface_count >= $required_interfaces_for_bonds) |
|
{ |
|
### Show the bonded ifaces form. |
|
# BCN |
|
my $bcn_count = $an->data->{cgi}{bcn_count}{value} ? $an->data->{cgi}{bcn_count}{value} : 1; |
|
foreach my $bcn (1..$bcn_count) |
|
{ |
|
push @{$links}, "bcn_link".$bcn; |
|
my $this_bcn_key = "bcn".$bcn; |
|
my $this_ip_key = "bcn".$bcn."_ip"; |
|
my $this_subnet_key = "bcn".$bcn."_subnet"; |
|
my $this_iface1_key = "bcn".$bcn."_iface1_mac"; |
|
my $this_iface2_key = "bcn".$bcn."_iface2_mac"; |
|
$cgi .= $this_ip_key.",".$this_subnet_key.",".$this_iface1_key.",".$this_iface2_key.","; |
|
my $this_ip = generate_ip($an, "bcn", 1, $an->data->{cgi}{sequence}{value}); |
|
my $this_ip_class = $an->data->{cgi}{$this_ip_key}{alert} ? "input_alert" : "input_clear"; |
|
my $this_subnet_class = $an->data->{cgi}{$this_subnet_key}{alert} ? "input_alert" : "input_clear"; |
|
my $this_iface1_class = $an->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear"; |
|
my $this_iface2_class = $an->data->{cgi}{$this_iface2_key}{alert} ? "input_alert" : "input_clear"; |
|
|
|
# Build the interface select boxes... |
|
my $this_iface1_form = $an->Template->select_form({ |
|
name => $this_iface1_key, |
|
options => $interface_options, |
|
blank => 1, |
|
selected => defined $an->data->{cgi}{$this_iface1_key}{value} ? $an->data->{cgi}{$this_iface1_key}{value} : "", |
|
class => $an->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear", |
|
}); |
|
my $this_iface2_form = $an->Template->select_form({ |
|
name => $this_iface2_key, |
|
options => $interface_options, |
|
blank => 1, |
|
selected => defined $an->data->{cgi}{$this_iface2_key}{value} ? $an->data->{cgi}{$this_iface2_key}{value} : "", |
|
class => $an->data->{cgi}{$this_iface2_key}{alert} ? "input_alert" : "input_clear", |
|
}); |
|
|
|
# Assemble the form |
|
$interface_form .= $an->Template->get({file => "main.html", name => "bonded_interface_form", variables => { |
|
field => $an->Words->string({key => "striker_0018", variables => { number => $bcn }}), |
|
description => "#!string!striker_0019!#", |
|
ip_key => $this_ip_key, |
|
ip_value => defined $an->data->{cgi}{$this_ip_key}{value} ? $an->data->{cgi}{$this_ip_key}{value} : $this_ip, |
|
ip_class => $this_ip_class, |
|
subnet_key => $this_subnet_key, |
|
subnet_value => defined $an->data->{cgi}{$this_subnet_key}{value} ? $an->data->{cgi}{$this_subnet_key}{value} : $an->data->{'default'}{bcn}{netmask}, |
|
subnet_class => $this_subnet_class, |
|
iface1_select => $this_iface1_form, |
|
iface2_select => $this_iface2_form, |
|
}}); |
|
} |
|
|
|
my $ifn_count = $an->data->{cgi}{ifn_count}{value} ? $an->data->{cgi}{ifn_count}{value} : 1; |
|
foreach my $ifn (1..$ifn_count) |
|
{ |
|
push @{$links}, "ifn_link".$ifn; |
|
my $this_ifn_key = "ifn".$ifn; |
|
my $this_ip_key = "ifn".$ifn."_ip"; |
|
my $this_subnet_key = "ifn".$ifn."_subnet"; |
|
my $this_iface1_key = "ifn".$ifn."_iface1_mac"; |
|
my $this_iface2_key = "ifn".$ifn."_iface2_mac"; |
|
$cgi .= $this_ip_key.",".$this_subnet_key.",".$this_iface1_key.",".$this_iface2_key.","; |
|
my $this_ip = generate_ip($an, "ifn", 1, $an->data->{cgi}{sequence}{value}); |
|
my $this_ip_class = $an->data->{cgi}{$this_ip_key}{alert} ? "input_alert" : "input_clear"; |
|
my $this_subnet_class = $an->data->{cgi}{$this_subnet_key}{alert} ? "input_alert" : "input_clear"; |
|
my $this_iface1_class = $an->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear"; |
|
my $this_iface2_class = $an->data->{cgi}{$this_iface2_key}{alert} ? "input_alert" : "input_clear"; |
|
|
|
# Build the interface select boxes... |
|
my $this_iface1_form = $an->Template->select_form({ |
|
name => $this_iface1_key, |
|
options => $interface_options, |
|
blank => 1, |
|
selected => defined $an->data->{cgi}{$this_iface1_key}{value} ? $an->data->{cgi}{$this_iface1_key}{value} : "", |
|
class => $an->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear", |
|
}); |
|
my $this_iface2_form = $an->Template->select_form({ |
|
name => $this_iface2_key, |
|
options => $interface_options, |
|
blank => 1, |
|
selected => defined $an->data->{cgi}{$this_iface2_key}{value} ? $an->data->{cgi}{$this_iface2_key}{value} : "", |
|
class => $an->data->{cgi}{$this_iface2_key}{alert} ? "input_alert" : "input_clear", |
|
}); |
|
|
|
# Assemble the form |
|
$interface_form .= $an->Template->get({file => "main.html", name => "bonded_interface_form", variables => { |
|
field => $an->Words->string({key => "striker_0022", variables => { number => $ifn }}), |
|
description => "#!string!striker_0023!#", |
|
ip_key => $this_ip_key, |
|
ip_value => defined $an->data->{cgi}{$this_ip_key}{value} ? $an->data->{cgi}{$this_ip_key}{value} : $this_ip, |
|
ip_class => $this_ip_class, |
|
subnet_key => $this_subnet_key, |
|
subnet_value => defined $an->data->{cgi}{$this_subnet_key}{value} ? $an->data->{cgi}{$this_subnet_key}{value} : $an->data->{'default'}{ifn}{netmask}, |
|
subnet_class => $this_subnet_class, |
|
iface1_select => $this_iface1_form, |
|
iface2_select => $this_iface2_form, |
|
}}); |
|
} |
|
} |
|
else |
|
{ |
|
### Show the single iface per network form. |
|
} |
|
|
|
### TODO: Add a form for Gateway, DNS and which interface to use |
|
# Gateway |
|
my $say_default_gateway = ""; |
|
my $gateway_class = $an->data->{cgi}{gateway}{alert} ? "input_alert" : "input_clear"; |
|
my $say_gateway = $an->Template->get({file => "main.html", name => "input_text_form", variables => { |
|
name => "gateway", |
|
id => "gateway", |
|
field => "#!string!striker_0035!#", |
|
description => "#!string!striker_0036!#", |
|
value => defined $an->data->{cgi}{gateway}{value} ? $an->data->{cgi}{gateway}{value} : $say_default_gateway, |
|
class => $gateway_class, |
|
extra => "", |
|
}}); |
|
|
|
# DNS |
|
my $dns_class = $an->data->{cgi}{dns}{alert} ? "input_alert" : "input_clear"; |
|
my $say_dns = $an->Template->get({file => "main.html", name => "input_text_form", variables => { |
|
name => "dns", |
|
id => "dns", |
|
field => "#!string!striker_0037!#", |
|
description => "#!string!striker_0038!#", |
|
value => defined $an->data->{cgi}{dns}{value} ? $an->data->{cgi}{dns}{value} : "8.8.8.8, 8.8.4.4", |
|
class => $dns_class, |
|
extra => "", |
|
}}); |
|
|
|
# Which interface gets the route? |
|
my $default_dg_iface = defined $an->data->{cgi}{dg_iface}{value} ? $an->data->{cgi}{dg_iface}{value} : "ifn_link1"; |
|
my $dg_iface_select = $an->Template->select_form({ |
|
name => "dg_iface", |
|
options => $links, |
|
blank => 0, |
|
selected => $default_dg_iface, |
|
class => $an->data->{cgi}{dg_iface}{alert} ? "input_alert" : "input_clear", |
|
}); |
|
my $dg_iface_class = $an->data->{cgi}{dg_iface}{alert} ? "input_alert" : "input_clear"; |
|
my $say_dg_iface = $an->Template->get({file => "main.html", name => "input_select_form", variables => { |
|
field => "#!string!striker_0039!#", |
|
description => "#!string!striker_0040!#", |
|
'select' => "", |
|
}}); |
|
|
|
# Hostname |
|
my $say_default_hostname = $an->data->{cgi}{prefix}{value}."-striker0".$an->data->{cgi}{sequence}{value}.".".$an->data->{cgi}{domain}{value}; |
|
my $hostname_class = $an->data->{cgi}{hostname}{alert} ? "input_alert" : "input_clear"; |
|
my $say_hostname = $an->Template->get({file => "main.html", name => "input_text_form", variables => { |
|
name => "hostname", |
|
id => "hostname", |
|
field => "#!string!striker_0016!#", |
|
description => "#!string!striker_0017!#", |
|
value => defined $an->data->{cgi}{hostname}{value} ? $an->data->{cgi}{hostname}{value} : $say_default_hostname, |
|
class => $hostname_class, |
|
extra => "", |
|
}}); |
|
|
|
# Admin user |
|
my $say_default_striker_user = "striker"; |
|
my $striker_user_class = $an->data->{cgi}{striker_user}{alert} ? "input_alert" : "input_clear"; |
|
my $say_striker_user = $an->Template->get({file => "main.html", name => "input_text_form", variables => { |
|
name => "striker_user", |
|
id => "striker_user", |
|
field => "#!string!striker_0031!#", |
|
description => "#!string!striker_0032!#", |
|
value => defined $an->data->{cgi}{striker_user}{value} ? $an->data->{cgi}{striker_user}{value} : $say_default_striker_user, |
|
class => $striker_user_class, |
|
extra => "", |
|
}}); |
|
|
|
# Password |
|
my $say_default_striker_password = ""; |
|
my $striker_password_class = $an->data->{cgi}{striker_password}{alert} ? "input_alert" : "input_clear"; |
|
my $say_striker_password = $an->Template->get({file => "main.html", name => "input_text_form", variables => { |
|
name => "striker_password", |
|
id => "striker_password", |
|
field => "#!string!striker_0033!#", |
|
description => "#!string!striker_0034!#", |
|
value => defined $an->data->{cgi}{striker_password}{value} ? $an->data->{cgi}{striker_password}{value} : $say_default_striker_password, |
|
class => $striker_password_class, |
|
extra => "", |
|
}}); |
|
|
|
# Get the table that shows the current interface states. |
|
my $interface_states = get_network_details_form($an); |
|
|
|
# Store the previous CGI variables and display the new fields. |
|
my $step2_body = $an->Template->get({file => "main.html", name => "config_step2", variables => { |
|
step1_welcome_title_id => "", |
|
step1_welcome_message_id => "", |
|
organization => $an->data->{cgi}{organization}{value}, |
|
prefix => $an->data->{cgi}{prefix}{value}, |
|
domain => $an->data->{cgi}{domain}{value}, |
|
sequence => $an->data->{cgi}{sequence}{value}, |
|
ifn_count => $an->data->{cgi}{ifn_count}{value}, |
|
interface_form => $interface_form, |
|
interface_states => $interface_states, |
|
striker_user_form => $say_striker_user, |
|
striker_password_form => $say_striker_password, |
|
gateway_form => $say_gateway, |
|
dns_form => $say_dns, |
|
hostname_form => $say_hostname, |
|
cgi_list => $cgi."gateway,hostname,striker_user,striker_password", |
|
}}); |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { step2_body => $step2_body }}); |
|
|
|
return($step2_body); |
|
} |
|
|
|
# This sanity-checks step 2 and returns '1' if there was a problem. |
|
sub sanity_check_step2 |
|
{ |
|
my ($an) = @_; |
|
|
|
# This will flip if we run into a problem. We start by running through step1's sanity checks again. |
|
# This should only fail is someone was passing raw data to us and screwed something up. |
|
my $sane = sanity_check_step1($an); |
|
|
|
# Do we have a host name, striker user and password? |
|
if ((not defined $an->data->{cgi}{hostname}{value}) or (not $an->data->{cgi}{hostname}{value})) |
|
{ |
|
$an->data->{cgi}{hostname}{alert} = 1; |
|
$sane = 0; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::hostname::alert" => $an->data->{cgi}{hostname}{alert} }}); |
|
} |
|
if ((not defined $an->data->{cgi}{striker_user}{value}) or (not $an->data->{cgi}{striker_user}{value})) |
|
{ |
|
$an->data->{cgi}{striker_user}{alert} = 1; |
|
$sane = 0; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::striker_user::alert" => $an->data->{cgi}{striker_user}{alert} }}); |
|
} |
|
if ((not defined $an->data->{cgi}{striker_password}{value}) or (not $an->data->{cgi}{striker_password}{value})) |
|
{ |
|
$an->data->{cgi}{striker_password}{alert} = 1; |
|
$sane = 0; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::striker_password::alert" => $an->data->{cgi}{striker_password}{alert} }}); |
|
} |
|
|
|
# Now it gets a bit tricker as we'll need to loop through the BCNs and IFNs. |
|
my $bcn_count = $an->data->{cgi}{bcn_count}{value} ? $an->data->{cgi}{bcn_count}{value} : 1; |
|
foreach my $bcn (1..$bcn_count) |
|
{ |
|
my $this_bcn_key = "bcn".$bcn; |
|
my $this_ip_key = "bcn".$bcn."_ip"; |
|
my $this_subnet_key = "bcn".$bcn."_subnet"; |
|
my $this_iface1_key = "bcn".$bcn."_iface1_mac"; |
|
my $this_iface2_key = "bcn".$bcn."_iface2_mac"; |
|
|
|
# If I only have the iface1, we'll create a non-bonded interface (even if the option for a |
|
# bond was presented to the user). So to be sane, we need a valid IP, subnet |
|
|
|
} |
|
my $ifn_count = $an->data->{cgi}{ifn_count}{value} ? $an->data->{cgi}{ifn_count}{value} : 1; |
|
foreach my $ifn (1..$ifn_count) |
|
{ |
|
my $this_ifn_key = "ifn".$ifn; |
|
my $this_ip_key = "ifn".$ifn."_ip"; |
|
my $this_subnet_key = "ifn".$ifn."_subnet"; |
|
my $this_iface1_key = "ifn".$ifn."_iface1_mac"; |
|
my $this_iface2_key = "ifn".$ifn."_iface2_mac"; |
|
} |
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { sane => $sane }}); |
|
return($sane); |
|
} |
|
|
|
|
|
# This sanity-checks step 1 and returns '1' if there was a problem. |
|
sub sanity_check_step1 |
|
{ |
|
my ($an) = @_; |
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0131", variables => { function => "sanity_check_step1()" }}); |
|
|
|
# This will flip if we run into a problem. |
|
my $sane = 1; |
|
|
|
# Organization just needs *something* |
|
if ((not defined $an->data->{cgi}{organization}{value}) or (not $an->data->{cgi}{organization}{value})) |
|
{ |
|
$an->data->{cgi}{organization}{alert} = 1; |
|
$sane = 0; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::organization::alert" => $an->data->{cgi}{organization}{alert} }}); |
|
} |
|
else |
|
{ |
|
# Record the answer. |
|
$an->Database->insert_or_update_variables({ |
|
variable_name => "form::config_step1::organization::value", |
|
variable_value => $an->data->{cgi}{organization}{value}, |
|
variable_default => "", |
|
variable_description => "striker_0004", |
|
variable_section => "config_step1", |
|
variable_source_uuid => $an->Get->host_uuid, |
|
variable_source_table => "hosts", |
|
update_value_only => 1, |
|
}); |
|
} |
|
|
|
# The prefix needs to be alphanumeric and be between 1 ~ 5 chatacters. |
|
if ((not $an->Validate->is_alphanumeric({string => $an->data->{cgi}{prefix}{value}})) or (length($an->data->{cgi}{prefix}{value}) > 5)) |
|
{ |
|
$an->data->{cgi}{prefix}{alert} = 1; |
|
$sane = 0; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::prefix::alert" => $an->data->{cgi}{prefix}{alert} }}); |
|
} |
|
else |
|
{ |
|
# Record the answer. |
|
$an->Database->insert_or_update_variables({ |
|
variable_name => "form::config_step1::prefix::value", |
|
variable_value => $an->data->{cgi}{prefix}{value}, |
|
variable_default => "", |
|
variable_description => "striker_0006", |
|
variable_section => "config_step1", |
|
variable_source_uuid => $an->Get->host_uuid, |
|
variable_source_table => "hosts", |
|
update_value_only => 1, |
|
}); |
|
} |
|
|
|
# We can use Validate to check the domain. |
|
if (not $an->Validate->is_domain_name({name => $an->data->{cgi}{domain}{value}})) |
|
{ |
|
$an->data->{cgi}{domain}{alert} = 1; |
|
$sane = 0; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::domain::alert" => $an->data->{cgi}{domain}{alert} }}); |
|
} |
|
else |
|
{ |
|
# Record the answer. |
|
$an->Database->insert_or_update_variables({ |
|
variable_name => "form::config_step1::domain::value", |
|
variable_value => $an->data->{cgi}{domain}{value}, |
|
variable_default => "", |
|
variable_description => "striker_0008", |
|
variable_section => "config_step1", |
|
variable_source_uuid => $an->Get->host_uuid, |
|
variable_source_table => "hosts", |
|
update_value_only => 1, |
|
}); |
|
} |
|
|
|
# The sequence and IFN count need to be integers. |
|
if (not $an->Validate->is_positive_integer({number => $an->data->{cgi}{sequence}{value}})) |
|
{ |
|
$an->data->{cgi}{sequence}{alert} = 1; |
|
$sane = 0; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::sequence::alert" => $an->data->{cgi}{sequence}{alert} }}); |
|
} |
|
else |
|
{ |
|
# Record the answer. |
|
$an->Database->insert_or_update_variables({ |
|
variable_name => "form::config_step1::sequence::value", |
|
variable_value => $an->data->{cgi}{sequence}{value}, |
|
variable_default => "", |
|
variable_description => "striker_0010", |
|
variable_section => "config_step1", |
|
variable_source_uuid => $an->Get->host_uuid, |
|
variable_source_table => "hosts", |
|
update_value_only => 1, |
|
}); |
|
} |
|
|
|
if (not $an->Validate->is_positive_integer({number => $an->data->{cgi}{ifn_count}{value}})) |
|
{ |
|
$an->data->{cgi}{ifn_count}{alert} = 1; |
|
$sane = 0; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::ifn_count::alert" => $an->data->{cgi}{ifn_count}{alert} }}); |
|
} |
|
|
|
# Make sure we have enough interfaces. |
|
get_network_details($an); |
|
my $required_interfaces_for_single = 1 + $an->data->{cgi}{ifn_count}{value}; |
|
my $interface_count = keys %{$an->data->{interfaces}}; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
required_interfaces_for_single => $required_interfaces_for_single, |
|
interface_count => $interface_count, |
|
}}); |
|
|
|
if ($interface_count < $required_interfaces_for_single) |
|
{ |
|
# Build the error message. |
|
my $say_message = $an->Words->string({key => "striker_error_0001", variables => { |
|
interface_count => $interface_count, |
|
required_interfaces_for_single => $required_interfaces_for_single, |
|
}}); |
|
|
|
# Not enough interfaces found. |
|
$an->data->{form}{error_massage} = $an->Template->get({file => "main.html", name => "error_message", variables => { error_message => $say_message }}); |
|
|
|
# We're not sane |
|
$an->data->{cgi}{ifn_count}{alert} = 1; |
|
$sane = 0; |
|
} |
|
else |
|
{ |
|
# Record the answer. |
|
$an->Database->insert_or_update_variables({ |
|
variable_name => "form::config_step1::ifn_count::value", |
|
variable_value => $an->data->{cgi}{ifn_count}{value}, |
|
variable_default => "", |
|
variable_description => "striker_0012", |
|
variable_section => "config_step1", |
|
variable_source_uuid => $an->Get->host_uuid, |
|
variable_source_table => "hosts", |
|
update_value_only => 1, |
|
}); |
|
} |
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { sane => $sane }}); |
|
return($sane); |
|
} |
|
|
|
# This is step 1 in asking the user how to configure Striker. |
|
sub config_step1 |
|
{ |
|
my ($an) = @_; |
|
|
|
if (not $an->data->{cgi}{'next'}{value}) |
|
{ |
|
# First load. See if we can read old data. |
|
my ($organization) = $an->Database->read_variable({ |
|
variable_name => "form::config_step1::organization::value", |
|
variable_source_uuid => $an->Get->host_uuid, |
|
variable_source_table => "hosts", |
|
}); |
|
my ($prefix) = $an->Database->read_variable({ |
|
variable_name => "form::config_step1::prefix::value", |
|
variable_source_uuid => $an->Get->host_uuid, |
|
variable_source_table => "hosts", |
|
}); |
|
my ($domain) = $an->Database->read_variable({ |
|
variable_name => "form::config_step1::domain::value", |
|
variable_source_uuid => $an->Get->host_uuid, |
|
variable_source_table => "hosts", |
|
}); |
|
my ($sequence) = $an->Database->read_variable({ |
|
variable_name => "form::config_step1::sequence::value", |
|
variable_source_uuid => $an->Get->host_uuid, |
|
variable_source_table => "hosts", |
|
}); |
|
my ($ifn_count) = $an->Database->read_variable({ |
|
variable_name => "form::config_step1::ifn_count::value", |
|
variable_source_uuid => $an->Get->host_uuid, |
|
variable_source_table => "hosts", |
|
}); |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
organization => $organization, |
|
prefix => $prefix, |
|
domain => $domain, |
|
sequence => $sequence, |
|
ifn_count => $ifn_count, |
|
}}); |
|
|
|
$an->data->{cgi}{organization}{value} = $organization ne "" ? $organization : ""; |
|
$an->data->{cgi}{prefix}{value} = $prefix ne "" ? $prefix : ""; |
|
$an->data->{cgi}{domain}{value} = $domain ne "" ? $domain : ""; |
|
$an->data->{cgi}{sequence}{value} = $sequence ne "" ? $sequence : 1; |
|
$an->data->{cgi}{ifn_count}{value} = $ifn_count ne "" ? $ifn_count : 1; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
'cgi::organization::value' => $an->data->{cgi}{organization}{value}, |
|
'cgi::prefix::value' => $an->data->{cgi}{prefix}{value}, |
|
'cgi::domain::value' => $an->data->{cgi}{domain}{value}, |
|
'cgi::sequence::value' => $an->data->{cgi}{sequence}{value}, |
|
'cgi::ifn_count::value' => $an->data->{cgi}{ifn_count}{value}, |
|
}}); |
|
} |
|
|
|
my $organization_class = $an->data->{cgi}{organization}{alert} ? "input_alert" : "input_clear"; |
|
my $say_organization = $an->Template->get({file => "main.html", name => "input_text_form", variables => { |
|
name => "organization", |
|
id => "organization", |
|
field => "#!string!striker_0003!#", |
|
description => "#!string!striker_0004!#", |
|
value => defined $an->data->{cgi}{organization}{value} ? $an->data->{cgi}{organization}{value} : "", |
|
class => $organization_class, |
|
extra => "", |
|
}}); |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_organization => $say_organization }}); |
|
my $prefix_class = $an->data->{cgi}{prefix}{alert} ? "input_alert" : "input_clear"; |
|
my $say_prefix = $an->Template->get({file => "main.html", name => "input_text_form", variables => { |
|
name => "prefix", |
|
id => "prefix", |
|
field => "#!string!striker_0005!#", |
|
description => "#!string!striker_0006!#", |
|
value => defined $an->data->{cgi}{prefix}{value} ? $an->data->{cgi}{prefix}{value} : "", |
|
class => $prefix_class, |
|
extra => "maxlength=\"5\"", |
|
}}); |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_prefix => $say_prefix }}); |
|
my $domain_class = $an->data->{cgi}{domain}{alert} ? "input_alert" : "input_clear"; |
|
my $say_domain = $an->Template->get({file => "main.html", name => "input_text_form", variables => { |
|
name => "domain", |
|
id => "domain", |
|
field => "#!string!striker_0007!#", |
|
description => "#!string!striker_0008!#", |
|
value => defined $an->data->{cgi}{domain}{value} ? $an->data->{cgi}{domain}{value} : "", |
|
class => $domain_class, |
|
extra => "maxlength=\"255\"", |
|
}}); |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_domain => $say_domain }}); |
|
my $sequence_class = $an->data->{cgi}{sequence}{alert} ? "input_alert" : "input_clear"; |
|
my $say_sequence = $an->Template->get({file => "main.html", name => "input_number_form", variables => { |
|
name => "sequence", |
|
id => "sequence", |
|
field => "#!string!striker_0009!#", |
|
description => "#!string!striker_0010!#", |
|
value => defined $an->data->{cgi}{sequence}{value} ? $an->data->{cgi}{sequence}{value} : "", |
|
class => $sequence_class, |
|
extra => "min=\"1\" max=\"24\"", |
|
}}); |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_domain => $say_domain }}); |
|
my $ifn_count_class = $an->data->{cgi}{ifn_count}{alert} ? "input_alert" : "input_clear"; |
|
my $say_ifn_count = $an->Template->get({file => "main.html", name => "input_number_form", variables => { |
|
name => "ifn_count", |
|
id => "ifn_count", |
|
field => "#!string!striker_0011!#", |
|
description => "#!string!striker_0012!#", |
|
value => defined $an->data->{cgi}{ifn_count}{value} ? $an->data->{cgi}{ifn_count}{value} : "", |
|
class => $ifn_count_class, |
|
extra => "min=\"1\" max=\"24\"", |
|
}}); |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_ifn_count => $say_ifn_count }}); |
|
|
|
my $step1_body = $an->Template->get({file => "main.html", name => "config_step1", variables => { |
|
step1_welcome_title_id => "", |
|
step1_welcome_message_id => "", |
|
organization_form => $say_organization, |
|
prefix_form => $say_prefix, |
|
domain_form => $say_domain, |
|
sequence_form => $say_sequence, |
|
ifn_count_form => $say_ifn_count, |
|
cgi_list => "organization,prefix,domain,sequence,ifn_count", |
|
}}); |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { step1_body => $step1_body }}); |
|
|
|
return($step1_body); |
|
} |
|
|
|
# This reads the network status XML file and loads the data into $an->data->{network}{{...}. |
|
sub get_network_details |
|
{ |
|
my ($an) = @_; |
|
|
|
### TODO: Daemonize this or solve selinux issues |
|
### Refresh the network.xml |
|
#$an->System->call({shell_call => $an->data->{path}{exe}{'scancore-update-states'}}); |
|
|
|
# Now read the network.xml |
|
my $file = $an->data->{path}{directories}{html}."/status/network.xml"; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { file => $file }}); |
|
|
|
# Parse... |
|
my $xml = XML::Simple->new(); |
|
my $data = ""; |
|
my $network = ""; |
|
eval { $data = $xml->XMLin($file, KeyAttr => { interface => 'name', key => 'name' }, ForceArray => [ 'interface', 'key' ]) }; |
|
if ($@) |
|
{ |
|
chomp $@; |
|
my $error = "[ Error ] - The was a problem reading: [$file]. The error was:\n"; |
|
$error .= "===========================================================\n"; |
|
$error .= $@."\n"; |
|
$error .= "===========================================================\n"; |
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", raw => $error}); |
|
} |
|
else |
|
{ |
|
foreach my $interface (sort {$a cmp $b} keys %{$data->{interface}}) |
|
{ |
|
$an->data->{interfaces}{$interface} = { |
|
mac => $data->{interface}{$interface}{mac}, |
|
speed => $data->{interface}{$interface}{speed}, |
|
'link' => $data->{interface}{$interface}{'link'} |
|
}; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { |
|
"interfaces::${interface}::mac" => $an->data->{interfaces}{$interface}{mac}, |
|
"interfaces::${interface}::speed" => $an->data->{interfaces}{$interface}{speed}, |
|
"interfaces::${interface}::link" => $an->data->{interfaces}{$interface}{'link'}, |
|
}}); |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
sub get_network_details_form |
|
{ |
|
my ($an) = @_; |
|
|
|
my $file = $an->data->{path}{directories}{html}."/status/network.xml"; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { file => $file }}); |
|
my $xml = XML::Simple->new(); |
|
my $data = ""; |
|
my $network = ""; |
|
eval { $data = $xml->XMLin($file, KeyAttr => { interface => 'name', key => 'name' }, ForceArray => [ 'interface', 'key' ]) }; |
|
if ($@) |
|
{ |
|
chomp $@; |
|
my $error = "[ Error ] - The was a problem reading: [$file]. The error was:\n"; |
|
$error .= "===========================================================\n"; |
|
$error .= $@."\n"; |
|
$error .= "===========================================================\n"; |
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", raw => $error}); |
|
} |
|
else |
|
{ |
|
my $interface_list = ""; |
|
$network = $an->Template->get({file => "main.html", name => "network_header"}); |
|
foreach my $interface (sort {$a cmp $b} keys %{$data->{interface}}) |
|
{ |
|
$interface_list .= "$interface,"; |
|
$network .= $an->Template->get({file => "main.html", name => "network_entry", variables => { |
|
#mac => $data->{interface}{$interface}{mac}, |
|
mac => "", |
|
mac_id => $interface."_mac", |
|
name => $interface, |
|
name_id => $interface."_name", |
|
#speed => $data->{interface}{$interface}{speed}, |
|
speed => "", |
|
speed_id => $interface."_speed", |
|
#'link' => $data->{interface}{$interface}{'link'}, |
|
'link' => "", |
|
link_id => $interface."_link", |
|
}}); |
|
} |
|
$interface_list =~ s/,$//; |
|
$network .= $an->Template->get({file => "main.html", name => "network_footer", variables => { interface_list => $interface_list }}); |
|
} |
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { network => $network }}); |
|
return($network); |
|
} |
|
|
|
# This is a rudimentary function for generating default Striker IPs. |
|
sub generate_ip |
|
{ |
|
my ($an, $network, $network_sequence, $device_sequence) = @_; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
network => $network, |
|
network_sequence => $network_sequence, |
|
device_sequence => $device_sequence, |
|
}}); |
|
|
|
# An empty string is returned if we can't make a sane guess at what should be set. |
|
my $ip = ""; |
|
|
|
# The subnet's second octet will be '+X' where 'X' is the sequence. |
|
my $default_ip = $an->data->{'default'}{$network}{subnet}; |
|
my $default_netmark = $an->data->{'default'}{$network}{netmask}; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
default_ip => $default_ip, |
|
default_netmark => $default_netmark, |
|
}}); |
|
|
|
if (($an->Validate->is_ipv4({ip => $default_ip})) && ($an->Validate->is_ipv4({ip => $default_netmark}))) |
|
{ |
|
# Valid values. |
|
my ($ip_octet1, $ip_octet2, $ip_octet3, $ip_octet4) = (split/\./, $default_ip); |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
ip_octet1 => $ip_octet1, |
|
ip_octet2 => $ip_octet2, |
|
ip_octet3 => $ip_octet3, |
|
ip_octet4 => $ip_octet4, |
|
}}); |
|
|
|
if ($default_netmark eq "255.255.0.0") |
|
{ |
|
# We can work with this. |
|
$ip_octet2 += $network_sequence; |
|
$ip_octet3 = $an->data->{'default'}{bcn}{striker_octet3}; |
|
$ip_octet4 = $device_sequence; |
|
$ip = $ip_octet1.".".$ip_octet2.".".$ip_octet3.".".$ip_octet4; |
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"s1:ip_octet2" => $ip_octet2, |
|
"s2:ip_octet3" => $ip_octet3, |
|
"s3:ip_octet4" => $ip_octet4, |
|
"s4:ip" => $ip, |
|
}}); |
|
} |
|
} |
|
else |
|
{ |
|
# Something wrong with our defaults. |
|
$ip = "#!error!#"; |
|
} |
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip => $ip }}); |
|
return($ip); |
|
}
|
|
|