#!/usr/bin/perl # # Exit codes; # 0 == OK # 1 == Host UUID not available yet. # # TODO: # * Switch out XML::Simple to XML::Twig or libXML - Started in Cluster->parse_cib(); # - 15:05 < perlbot> XML::Simple commits the fatal flaw of trying to massage complicated and often # irregular XML into the simple and highly regular world of perl data structures. # Irregularities cause "not a hashref" sort of errors in your program. Use a real # parser. see: xml # - 15:06 < perlbot> Don't parse XML with regex! Use a real parser. Avoid XML::Simple (see the xml::simple # factoid). Choices are ::Easy, ::TreeBuilder, ::Twig, Mojo::DOM (in XML mode) for # simple stuff. LibXML is a good general purpose starting point. See also XML::All. # http://perl-xml.sf.net/faq/ # use strict; use warnings; use Anvil::Tools; use Data::Dumper; use NetAddr::IP; use CGI::Carp "fatalsToBrowser"; # Turn off buffering $| = 1; my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; if (($running_directory =~ /^\./) && ($ENV{PWD})) { $running_directory =~ s/^\./$ENV{PWD}/; } my $anvil = Anvil::Tools->new(); ### NOTE: We'll print the headers only when we need to. If we print them here, it will block cookies being set. # Setup some variables. $anvil->data->{skin}{url} = $anvil->data->{path}{urls}{skins}."/".$anvil->Template->skin; $anvil->data->{form}{body} = ""; $anvil->data->{form}{error_massage} = ""; $anvil->data->{form}{ok_message} = ""; $anvil->data->{form}{back_link} = ""; $anvil->data->{form}{refresh_link} = ""; # Read in any CGI variables, if needed. $anvil->Get->cgi(); # If we're being asked to get a file, do so now. if ($anvil->data->{cgi}{upload_file}{file_handle}) { # Save and exit. We've got ajax handling the UI so this invocation only saves the file. handle_upload($anvil); $anvil->nice_exit({exit_code => 0}); } # If the system hasn't initialized, there may be no host.uuid, and we'll need a better error to show the # user. if (not -e $anvil->data->{path}{data}{host_uuid}) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0002"}) }}); print_and_exit($anvil); } $anvil->Database->connect({debug => 3}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"}); if (not $anvil->data->{sys}{database}{connections}) { # No databases, exit. print $anvil->Template->get({file => "shared.html", name => "http_headers"})."\n"; print $anvil->Template->get({file => "main.html", name => "header", variables => { language => $anvil->Words->language }}); print $anvil->Words->string({key => "error_0003"}); $anvil->nice_exit({exit_code => 2}); } # If any jobs are pending/running, show the "unavailable" option. my $configured = $anvil->System->check_if_configured; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { configured => $configured }}); # Are we in maintenance mode? my $available = $configured ? check_availability($anvil) : 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {available => $available }}); if (not $configured) { # If there is no user account yet, then the system is new and needs to be reconfigured. configure_striker($anvil); } elsif (not $available) { # Set the body to 'say::maintenance'. $anvil->data->{form}{body} = $anvil->data->{say}{maintenance}; } else { # Normal operation process_task($anvil); } # Build the page to display my $refresh_button = ""; if ($anvil->data->{form}{refresh_link}) { $refresh_button = $anvil->Template->get({file => "main.html", name => "refresh_button_on", variables => { url => $anvil->data->{form}{refresh_link} }}); } else { $refresh_button = $anvil->Template->get({file => "main.html", name => "refresh_button_off"}); } print_and_exit($anvil); ############################################################################################################# # Functions # ############################################################################################################# # This handles uploading (downloading by our perspective) sub handle_upload { my ($anvil) = @_; # Get the file handle. my $cgi_file_handle = $anvil->data->{cgi}{upload_file}{file_handle}; my $file_name = $anvil->data->{cgi}{upload_file}{file_name}; my $mime_type = $anvil->data->{cgi}{upload_file}{mime_type}; my $output_file = $anvil->data->{path}{directories}{shared}{incoming}."/".$file_name; $output_file =~ s/\/\//\//g; # TODO: Make sure characters like spaces and whatnot don't need to be escaped. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cgi_file_handle => $cgi_file_handle, file_name => $file_name, mime_type => $mime_type, output_file => $output_file, }}); open (my $file_handle, ">", $output_file) or $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0015", variables => { shell_call => $output_file, error => $! }}); binmode $file_handle; while(<$file_handle>) { print $cgi_file_handle $_; } close $file_handle; if (not -f $output_file) { # Something went wrong $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "log_0257", variables => { file => $output_file }}); } else { # Looks like we got it. my $file_size = -s $output_file; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_size => $file_size }}); if (not $file_size) { # Looks like we didn't actually get the file... $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "log_0258", variables => { file => $output_file }}); unlink $output_file; } else { my $say_size_in_bytes = $anvil->Convert->add_commas({number => $file_size}); my $say_human_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $file_size}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0256", variables => { file => $output_file, size_in_bytes => $say_size_in_bytes, human_readable_size => $say_human_size, }}); } } return(0); } sub print_and_exit { my ($anvil) = @_; # Time for the header my $header = $anvil->Template->get({file => "main.html", name => "header", variables => { language => $anvil->Words->language }}); my $back_button = ""; if ($anvil->data->{form}{back_link}) { my $url = $THIS_FILE; if ($anvil->data->{form}{back_link} ne "?") { # Turn on the back button, $url = $anvil->data->{form}{back_link}; } $back_button = $anvil->Template->get({file => "main.html", name => "back_button_on", variables => { url => $url }}); } else { # Back is disabled. $back_button = $anvil->Template->get({file => "main.html", name => "back_button_off"}); } my $left_buttons = $anvil->Template->get({file => "main.html", name => "button_bar_left", variables => { back_button => $back_button, refresh_button => $refresh_button, }}); # The jobs button is "on" when the user is logged in and there is one or more jobs on this system # under 100% complete. my $say_jobs_button = $anvil->Template->get({file => "main.html", name => "jobs_button_off"}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_jobs_button => $say_jobs_button }}); if (($anvil->data->{sys}{users}{user_name}) && ($anvil->Job->running({debug => 3}))) { $say_jobs_button = $anvil->Template->get({file => "main.html", name => "jobs_button_on"}); } my $right_buttons = $anvil->Template->get({file => "main.html", name => "button_bar_right", variables => { anvil_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "anvil_button_on"}) : $anvil->Template->get({file => "main.html", name => "anvil_button_off"}), configure_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "configure_button_on"}) : $anvil->Template->get({file => "main.html", name => "configure_button_off"}), files_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "files_button_on"}) : $anvil->Template->get({file => "main.html", name => "files_button_off"}), jobs_button => $say_jobs_button, striker_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "striker_button_on"}) : $anvil->Template->get({file => "main.html", name => "striker_button_off"}), email_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "email_button_on"}) : $anvil->Template->get({file => "main.html", name => "email_button_off"}), user_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "user_button_on"}) : $anvil->Template->get({file => "main.html", name => "user_button_off"}), }}); my $footer = $anvil->Template->get({file => "main.html", name => "footer", variables => { user => $anvil->data->{sys}{users}{user_name} ? "#!string!message_0034!#" : " ", }}); # Display the page. my $say_center_top_bar = " "; if ($anvil->data->{form}{error_massage}) { $say_center_top_bar = $anvil->data->{form}{error_massage}; } elsif ($anvil->data->{form}{ok_message}) { $say_center_top_bar = $anvil->data->{form}{ok_message}; } my $body = $anvil->Template->get({file => "main.html", name => "master", variables => { header => $header, skin_url => $anvil->data->{path}{urls}{skins}."/".$anvil->Template->skin, center_top_bar => $say_center_top_bar, right_top_bar => $right_buttons, left_top_bar => $left_buttons, center_body => $anvil->data->{form}{body}, left_bottom_bar => " ", center_bottom_bar => " ", right_bottom_bar => " ", footer => $footer, }}); print $anvil->Template->get({file => "shared.html", name => "http_headers"})."\n"; print "$body"; $anvil->nice_exit({exit_code => 0}); return(0); } # This handles all the daily tasks of Striker. sub process_task { my ($anvil) = @_; # Is the user trying to log in? my $logged_in = 0; $anvil->data->{cgi}{login}{value} = "" if not defined $anvil->data->{cgi}{login}{value}; $anvil->data->{cgi}{logout}{value} = "" if not defined $anvil->data->{cgi}{logout}{value}; $anvil->data->{cgi}{save}{value} = "" if not defined $anvil->data->{cgi}{save}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::login::value" => $anvil->data->{cgi}{login}{value}, "cgi::logout::value" => $anvil->data->{cgi}{logout}{value}, "cgi::save::value" => $anvil->data->{cgi}{save}{value}, }}); if ($anvil->data->{cgi}{login}{value}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::login::value" => $anvil->data->{cgi}{login}{value} }}); # Woot! my $failed = $anvil->Account->login({debug => 2}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { failed => $failed }}); if (not $failed) { $logged_in = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { logged_in => $logged_in }}); } } elsif ($anvil->data->{cgi}{logout}{value}) { # Bye now! $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::logout::value" => $anvil->data->{cgi}{logout}{value} }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0215"}); $anvil->Account->logout({debug => 2}); } else { # Is the user logged in? # 0 - The cookies were read, the account was validated and the user's details were loaded. # 1 - No cookie was found or read. The user needs to log in # 2 - There was a problem reading the user's UUID (it wasn't found in the database), so the # cookies were deleted (via C<< Account->logout() >>. The user needs to log back in. # 3 - Their user's hash is invalid, it is probably expired. The user has been logged out and # needs to log back in. my $cookie_problem = $anvil->Account->read_cookies({debug => 2}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cookie_problem => $cookie_problem }}); if (not $cookie_problem) { $logged_in = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { logged_in => $logged_in }}); } } # Show the login screen, if the user isn't logged in. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { logged_in => $logged_in }}); if (not $logged_in) { $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "striker-login", variables => { user => $anvil->data->{cgi}{username}{value}, password => "", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); return(0); } # If we're here, the user is logged in! if ($anvil->data->{cgi}{striker}{value}) { process_striker_menu($anvil); } elsif ($anvil->data->{cgi}{anvil}{value}) { process_anvil_menu($anvil); } elsif ($anvil->data->{cgi}{files}{value}) { process_file_menu($anvil); } elsif ($anvil->data->{cgi}{jobs}{value}) { process_jobs_menu($anvil); } elsif ($anvil->data->{cgi}{email}{value}) { process_email_menu($anvil); } else { # Load the main page. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "striker-welcome"}); } # $anvil->data->{sys}{users}{user_name} = $user_name; # $anvil->data->{sys}{users}{user_uuid} = $user_uuid; # $anvil->data->{sys}{users}{user_password_hash} = $user_password_hash, # $anvil->data->{sys}{users}{user_salt} = $user_salt, # $anvil->data->{sys}{users}{user_algorithm} = $user_algorithm, # $anvil->data->{sys}{users}{user_hash_count} = $user_hash_count, # $anvil->data->{sys}{users}{user_language} = $user_language, # $anvil->data->{sys}{users}{user_is_admin} = $user_is_admin, # $anvil->data->{sys}{users}{user_is_experienced} = $user_is_experienced, # $anvil->data->{sys}{users}{user_is_trusted} = $user_is_trusted, return(0); } # This handles tasks related to email, mail servers and alert recipients. sub process_email_menu { my ($anvil) = @_; $anvil->data->{form}{back_link} = "?email=true"; $anvil->data->{cgi}{task}{value} = "" if not defined $anvil->data->{cgi}{task}{value}; $anvil->data->{cgi}{action}{value} = "" if not defined $anvil->data->{cgi}{action}{value}; $anvil->data->{cgi}{save}{value} = "" if not defined $anvil->data->{cgi}{save}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::back_link" => $anvil->data->{form}{back_link}, "cgi::task::value" => $anvil->data->{cgi}{task}{value}, "cgi::action::value" => $anvil->data->{cgi}{action}{value}, "cgi::save::value" => $anvil->data->{cgi}{save}{value}, }}); if ($anvil->data->{cgi}{task}{value} eq "email_server") { process_email_server_page($anvil); } elsif ($anvil->data->{cgi}{task}{value} eq "email_recipient") { process_email_recipient_page($anvil); } else { # What we show for the reboot icon and text depends on if a reboot is pending. my $reboot_needed = $anvil->System->reboot_needed(); my $reboot_icon = $reboot_needed ? "reboot_needed_icon.png" : "reboot_icon.png"; my $reboot_message = $reboot_needed ? "#!string!striker_0093!#" : "#!string!striker_0092!#"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { reboot_needed => $reboot_needed, reboot_icon => $reboot_icon, reboot_message => $reboot_message, }}); # The 'back' goes home $anvil->data->{form}{back_link} = "?"; $anvil->data->{form}{refresh_link} = "?email=true"; $anvil->data->{form}{body} = $anvil->Template->get({file => "email.html", name => "main-menu", variables => { }}); } return(0); } # This processes mail recipients. sub process_email_recipient_page { my ($anvil) = @_; my $recipient_uuid = defined $anvil->data->{cgi}{recipient_uuid}{value} ? $anvil->data->{cgi}{recipient_uuid}{value} : ""; my $recipient_name = defined $anvil->data->{cgi}{recipient_name}{value} ? $anvil->data->{cgi}{recipient_name}{value} : ""; my $recipient_email = defined $anvil->data->{cgi}{recipient_email}{value} ? $anvil->data->{cgi}{recipient_email}{value} : ""; my $recipient_language = defined $anvil->data->{cgi}{recipient_language}{value} ? $anvil->data->{cgi}{recipient_language}{value} : "en_CA"; my $recipient_level = defined $anvil->data->{cgi}{recipient_level}{value} ? $anvil->data->{cgi}{recipient_level}{value} : "2"; my $delete = defined $anvil->data->{cgi}{'delete'}{value} ? $anvil->data->{cgi}{'delete'}{value} : ""; my $back = defined $anvil->data->{cgi}{back}{value} ? $anvil->data->{cgi}{back}{value} : ""; my $save = defined $anvil->data->{cgi}{save}{value} ? $anvil->data->{cgi}{save}{value} : ""; my $confirm = defined $anvil->data->{cgi}{confirm}{value} ? $anvil->data->{cgi}{confirm}{value} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { recipient_uuid => $recipient_uuid, recipient_name => $recipient_name, recipient_email => $recipient_email, recipient_language => $recipient_language, recipient_level => $recipient_level, back => $back, save => $save, 'delete' => $delete, confirm => $confirm, }}); if ($back) { $save = ""; $delete = ""; $confirm = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { save => $save, 'delete' => $delete, confirm => $confirm, }}); } # If we have a recipient_uuid and we're not saving, load the information. if (($recipient_uuid) && (not $save)) { # Load. If we're deleting, we'll check 'mail_server_helo_domain' to see if it already was. my $query = " SELECT recipient_name, recipient_email, recipient_language, recipient_level FROM recipients WHERE recipient_uuid = ".$anvil->Database->quote($recipient_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { $recipient_name = $row->[0]; $recipient_email = $row->[1]; $recipient_language = $row->[2]; $recipient_level = $row->[3]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { recipient_name => $recipient_name, recipient_email => $recipient_email, recipient_language => $recipient_language, recipient_level => $recipient_level, }}); if ($delete) { # Has the user confirmed? if ($confirm) { # Delete. $anvil->Database->insert_or_update_recipients({ debug => 2, 'delete' => 1, recipient_uuid => $recipient_uuid, }); # Saved successfully. my $ok_message = $anvil->Words->string({key => "ok_0003", variables => { recipient_email => $recipient_email }}); $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => $ok_message }}); # Clear the form $recipient_name = ""; $recipient_email = ""; $recipient_language = "en_CA"; $recipient_level = "2"; } else { # Ask them to confirm. $anvil->data->{form}{back_link} = $anvil->data->{sys}{cgi_string}; $anvil->data->{form}{back_link} =~ s/save=.*?&//; $anvil->data->{form}{back_link} =~ s/save=.*?$//; $anvil->data->{form}{refresh_link} = ""; $anvil->data->{form}{body} = $anvil->Template->get({file => "email.html", name => "recipient-delete-confirm", variables => { recipient_name => $recipient_name, recipient_email => $recipient_email, recipient_uuid => $recipient_uuid, }}); return(0); } } } } # If we're saving, make sure we have a valid email address and a name. if ($save) { # Did the user give both an email address and name? if ((not $recipient_name) or (not $recipient_name)) { # Which was missing? if (not $recipient_name) { $anvil->data->{cgi}{recipient_name}{alert} = 1; } if (not $recipient_email) { $anvil->data->{cgi}{recipient_email}{alert} = 1; } $save = ""; $confirm = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { save => $save, confirm => $confirm, }}); } # Verify that the mail server and ports are sane. if (not $anvil->Validate->email({email => $recipient_email})) { # Bad domain my $error_message = $anvil->Words->string({key => "warning_0026"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); $anvil->data->{cgi}{recipient_email}{alert} = 1; $save = ""; $confirm = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { error_message => $error_message, "form::error_massage" => $anvil->data->{form}{error_massage}, "cgi::recipient_email::alert" => $anvil->data->{cgi}{recipient_email}{alert}, save => $save, confirm => $confirm, }}); } } # Are we still saving? if ($save) { # Have we confirmed? if ($confirm) { ($recipient_uuid) = $anvil->Database->insert_or_update_recipients({ debug => 2, recipient_uuid => $recipient_uuid, recipient_name => $recipient_name, recipient_email => $recipient_email, recipient_language => $recipient_language, recipient_level => $recipient_level, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { recipient_uuid => $recipient_uuid }}); if ($recipient_uuid) { # Saved successfully. my $ok_message = $anvil->Words->string({key => "ok_0004"}); $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => $ok_message }}); # Clear the form $recipient_uuid = ""; $recipient_name = ""; $recipient_email = ""; $recipient_language = "en_CA"; $recipient_level = "2"; } else { # Something went wrong... my $error_message = $anvil->Words->string({key => "warning_0027"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); } } else { # Ignore my $say_recipient_level = "#!string!unit_0023!#"; if ($recipient_level eq "1") { # Critical $say_recipient_level = "#!string!unit_0024!#"; } elsif ($recipient_level eq "2") { # Warning $say_recipient_level = "#!string!unit_0025!#"; } elsif ($recipient_level eq "3") { # Notice $say_recipient_level = "#!string!unit_0026!#"; } my $say_recipient_language = $anvil->Words->language({iso => $recipient_language, long => 1}); $say_recipient_language = "???" if not $say_recipient_language; # Ask the user to confirm $anvil->data->{form}{back_link} = $anvil->data->{sys}{cgi_string}; $anvil->data->{form}{back_link} =~ s/save=.*?&//; $anvil->data->{form}{back_link} =~ s/save=.*?$//; $anvil->data->{form}{refresh_link} = ""; $anvil->data->{form}{body} = $anvil->Template->get({file => "email.html", name => "recipient-confirm", variables => { recipient_uuid => $recipient_uuid, recipient_name => $recipient_name, recipient_email => $recipient_email, recipient_language => $recipient_language, say_recipient_language => $say_recipient_language, recipient_level => $recipient_level, say_recipient_level => $say_recipient_level, }}); return(0); } } # Get a list of existing alert recipients. my $query = "SELECT recipient_uuid, recipient_name, recipient_email FROM recipients WHERE recipient_name != 'DELETED' ORDER BY recipient_name ASC;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); my $recipients_form = ""; if ($count) { # Build the list of existing mail servers $recipients_form .= $anvil->Template->get({file => "email.html", name => "recipient-entry-open"});; foreach my $row (@{$results}) { my $recipient_uuid = $row->[0]; my $recipient_name = $row->[1]; my $recipient_email = $row->[2]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { recipient_uuid => $recipient_uuid, recipient_name => $recipient_name, recipient_email => $recipient_email, }}); $recipients_form .= $anvil->Template->get({file => "email.html", name => "recipient-entry", variables => { name => $recipient_name." (".$recipient_email.")", uuid => $recipient_uuid, }});; } $recipients_form .= $anvil->Template->get({file => "email.html", name => "recipient-entry-close"});; } # Name my $recipient_name_class = $anvil->data->{cgi}{recipient_name}{alert} ? "input_alert" : "input_clear"; my $recipient_name_form = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "recipient_name", id => "recipient_name", field => "#!string!striker_0194!#", description => "#!string!striker_0195!#", value => $recipient_name, default_value => "", class => $recipient_name_class, extra => "", }}); # Email my $recipient_email_class = $anvil->data->{cgi}{recipient_email}{alert} ? "input_alert" : "input_clear"; my $recipient_email_form = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "recipient_email", id => "recipient_email", field => "#!string!striker_0196!#", description => "#!string!striker_0197!#", value => $recipient_email, default_value => "", class => $recipient_email_class, extra => "", }}); # Language (select) $anvil->Words->language_list(); my $options = []; foreach my $iso (sort {$a cmp $b} keys %{$anvil->data->{sys}{languages}}) { push @{$options}, $iso."#!#".$anvil->data->{sys}{languages}{$iso}; } my $recipient_language_select = $anvil->Template->select_form({ name => "recipient_language", options => $options, blank => 0, selected => $recipient_language, class => $anvil->data->{cgi}{recipient_language}{alert} ? "input_alert" : "input_clear", }); # Log Level (select) my $recipient_level_select = $anvil->Template->select_form({ name => "recipient_level", options => [ "1#!#".$anvil->Words->string({key => "unit_0024"}), "2#!#".$anvil->Words->string({key => "unit_0025"}), "3#!#".$anvil->Words->string({key => "unit_0026"}), "4#!#".$anvil->Words->string({key => "unit_0027"}), "0#!#".$anvil->Words->string({key => "unit_0023"}), ], 'sort' => 0, blank => 0, selected => $recipient_level, class => $anvil->data->{cgi}{recipient_level}{alert} ? "input_alert" : "input_clear", }); # Show the menu. $anvil->data->{form}{back_link} = "?email=true"; $anvil->data->{form}{refresh_link} = "?email=true&task=email_recipient"; $anvil->data->{form}{body} = $anvil->Template->get({file => "email.html", name => "recipient-menu", variables => { recipients => $recipients_form, recipient_name => $recipient_name_form, recipient_email => $recipient_email_form, language => $recipient_language_select, new_level => $recipient_level_select, recipient_uuid => $recipient_uuid, }}); return(0); } # This configures mail servers sub process_email_server_page { my ($anvil) = @_; # Prep the cgi variables. my $mail_server_uuid = defined $anvil->data->{cgi}{mail_server_uuid}{value} ? $anvil->data->{cgi}{mail_server_uuid}{value} : ""; my $outgoing_mail_server = defined $anvil->data->{cgi}{outgoing_mail_server}{value} ? $anvil->data->{cgi}{outgoing_mail_server}{value} : ""; my $login_name = defined $anvil->data->{cgi}{login_name}{value} ? $anvil->data->{cgi}{login_name}{value} : ""; my $login_password = defined $anvil->data->{cgi}{login_password}{value} ? $anvil->data->{cgi}{login_password}{value} : ""; my $connection_security = defined $anvil->data->{cgi}{connection_security}{value} ? $anvil->data->{cgi}{connection_security}{value} : "ifn_link1"; my $authentication_method = defined $anvil->data->{cgi}{authentication_method}{value} ? $anvil->data->{cgi}{authentication_method}{value} : "normal_password"; my $port = defined $anvil->data->{cgi}{port}{value} ? $anvil->data->{cgi}{port}{value} : "143"; my $helo_domain = defined $anvil->data->{cgi}{helo_domain}{value} ? $anvil->data->{cgi}{helo_domain}{value} : ""; my $back = defined $anvil->data->{cgi}{back}{value} ? $anvil->data->{cgi}{back}{value} : ""; my $save = defined $anvil->data->{cgi}{save}{value} ? $anvil->data->{cgi}{save}{value} : ""; my $delete = defined $anvil->data->{cgi}{'delete'}{value} ? $anvil->data->{cgi}{'delete'}{value} : ""; my $confirm = defined $anvil->data->{cgi}{confirm}{value} ? $anvil->data->{cgi}{confirm}{value} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { outgoing_mail_server => $outgoing_mail_server, login_name => $login_name, login_password => $login_password, connection_security => $connection_security, authentication_method => $authentication_method, back => $back, save => $save, 'delete' => $delete, confirm => $confirm, }}); if ($back) { $save = ""; $delete = ""; $confirm = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { save => $save, 'delete' => $delete, confirm => $confirm, }}); } # Are we loading an existing record? if (($mail_server_uuid) && not ($save)) { # Load. If we're deleting, we'll check 'mail_server_helo_domain' to see if it already was. my $query = " SELECT mail_server_address, mail_server_authentication, mail_server_helo_domain, mail_server_password, mail_server_port, mail_server_security, mail_server_username FROM mail_servers WHERE mail_server_uuid = ".$anvil->Database->quote($mail_server_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { $outgoing_mail_server = $row->[0]; $authentication_method = $row->[1]; $helo_domain = $row->[2]; $login_password = $row->[3]; $port = $row->[4]; $connection_security = $row->[5]; $login_name = $row->[6]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { outgoing_mail_server => $outgoing_mail_server, authentication_method => $authentication_method, helo_domain => $helo_domain, login_password => $login_password, port => $port, connection_security => $connection_security, login_name => $login_name, }}); if ($delete) { # Has the user confirmed? if ($confirm) { # Delete. $anvil->Database->insert_or_update_mail_servers({ debug => 2, 'delete' => 1, mail_server_uuid => $mail_server_uuid, }); # Saved successfully. my $ok_message = $anvil->Words->string({key => "ok_0002", variables => { mail_server => $outgoing_mail_server }}); $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => $ok_message }}); # Clear the form $mail_server_uuid = ""; $outgoing_mail_server = ""; $login_name = ""; $login_password = ""; $connection_security = ""; $authentication_method = ""; } else { # Ask them to confirm. $anvil->data->{form}{back_link} = $anvil->data->{sys}{cgi_string}; $anvil->data->{form}{back_link} =~ s/save=.*?&//; $anvil->data->{form}{back_link} =~ s/save=.*?$//; $anvil->data->{form}{refresh_link} = ""; $anvil->data->{form}{body} = $anvil->Template->get({file => "email.html", name => "mail-server-delete-confirm", variables => { outgoing_mail_server => $outgoing_mail_server, mail_server_uuid => $mail_server_uuid, }}); return(0); } } } } # if the user put a port on the mail server, break it off now and override any passed in port. # Normally, the port is set via a hidden variable when the security check box is changed. my $test_outgoing_mail_server = $outgoing_mail_server; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { test_outgoing_mail_server => $test_outgoing_mail_server }}); if ($test_outgoing_mail_server =~ /^(.*):(\d+)$/) { $test_outgoing_mail_server = $1; $port = $2; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { test_outgoing_mail_server => $test_outgoing_mail_server, port => $port, }}); } elsif (not $port) { # Port wasn't passed. Use '587' unless $connection_security is 'ssl_tls' $port = 143; if ($connection_security eq "ssl_tls") { $port = 465; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { port => $port }}); } ### NOTE: For now, the HELO domain is not configurable by the user. # If we don't have $helo_domain, use the host's domain if (not $helo_domain) { $helo_domain = $anvil->Get->domain_name(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { helo_domain => $helo_domain }}); } # Sanity check our save if ($save) { # Did the user give an outgoing mail server? if (not $outgoing_mail_server) { # Just silently send them back to the form. $save = ""; $confirm = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { save => $save, confirm => $confirm, }}); } # Verify that the mail server and ports are sane. if ((not $anvil->Validate->ipv4({ip => $test_outgoing_mail_server})) and (not $anvil->Validate->domain_name({name => $test_outgoing_mail_server}))) { # Bad domain my $error_message = $anvil->Words->string({key => "warning_0023"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); $anvil->data->{cgi}{outgoing_mail_server}{alert} = 1; $save = ""; $confirm = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { error_message => $error_message, "form::error_massage" => $anvil->data->{form}{error_massage}, "cgi::outgoing_mail_server::alert" => $anvil->data->{cgi}{outgoing_mail_server}{alert}, save => $save, confirm => $confirm, }}); } if (not $anvil->Validate->port({port => $port})) { # Bad port my $error_message = $anvil->Words->string({key => "warning_0024"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); $anvil->data->{cgi}{outgoing_mail_server}{alert} = 1; $save = ""; $confirm = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { error_message => $error_message, "form::error_massage" => $anvil->data->{form}{error_massage}, "cgi::outgoing_mail_server::alert" => $anvil->data->{cgi}{outgoing_mail_server}{alert}, save => $save, confirm => $confirm, }}); } } # Still saving? if ($save) { # Confirmed? if ($confirm) { # Save! ($mail_server_uuid) = $anvil->Database->insert_or_update_mail_servers({ debug => 2, mail_server_uuid => $mail_server_uuid, mail_server_address => $test_outgoing_mail_server, mail_server_authentication => $authentication_method, mail_server_helo_domain => $helo_domain, mail_server_password => $login_password, mail_server_port => $port, mail_server_security => $connection_security, mail_server_username => $login_name, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mail_server_uuid => $mail_server_uuid }}); if ($mail_server_uuid) { # Saved successfully. my $ok_message = $anvil->Words->string({key => "ok_0001"}); $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => $ok_message }}); # Clear the form $mail_server_uuid = ""; $outgoing_mail_server = ""; $login_name = ""; $login_password = ""; $connection_security = ""; $authentication_method = ""; } else { # Something went wrong... my $error_message = $anvil->Words->string({key => "warning_0025"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); } } else { # Ask the user to confirm $anvil->data->{form}{back_link} = $anvil->data->{sys}{cgi_string}; $anvil->data->{form}{back_link} =~ s/save=.*?&//; $anvil->data->{form}{back_link} =~ s/save=.*?$//; $anvil->data->{form}{refresh_link} = ""; $anvil->data->{form}{body} = $anvil->Template->get({file => "email.html", name => "mail-server-confirm", variables => { say_outgoing_mail_server => $test_outgoing_mail_server.":".$port, outgoing_mail_server => $outgoing_mail_server, port => $port, login_name => $login_name, login_password => $login_password, connection_security => $connection_security, authentication_method => $authentication_method, helo_domain => $helo_domain, mail_server_uuid => $mail_server_uuid, }}); return(0); } } # Get a list of existing mail servers. my $query = "SELECT mail_server_uuid, mail_server_address FROM mail_servers WHERE mail_server_helo_domain != 'DELETED' ORDER BY mail_server_address ASC;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); my $mail_servers_form = ""; if ($count) { # Build the list of existing mail servers $mail_servers_form .= $anvil->Template->get({file => "email.html", name => "mail-server-entry-open"});; foreach my $row (@{$results}) { my $mail_server_uuid = $row->[0]; my $mail_server_address = $row->[1]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mail_server_uuid => $mail_server_uuid, mail_server_address => $mail_server_address, }}); $mail_servers_form .= $anvil->Template->get({file => "email.html", name => "mail-server-entry", variables => { name => $mail_server_address, uuid => $mail_server_uuid, }});; } $mail_servers_form .= $anvil->Template->get({file => "email.html", name => "mail-server-entry-close"});; } # Outgoing mail server my $outgoing_mail_server_class = $anvil->data->{cgi}{outgoing_mail_server}{alert} ? "input_alert" : "input_clear"; my $outgoing_mail_server_form = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "outgoing_mail_server", id => "outgoing_mail_server", field => "#!string!striker_0185!#", description => "#!string!striker_0169!#", value => $outgoing_mail_server, default_value => "", class => $outgoing_mail_server_class, extra => "", }}); # Login name my $login_name_class = $anvil->data->{cgi}{login_name}{alert} ? "input_alert" : "input_clear"; my $login_name_form = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "login_name", id => "login_name", field => "#!string!striker_0170!#", description => "#!string!striker_0171!#", value => $login_name, default_value => "", class => $login_name_class, extra => "", }}); # Password my $login_password_class = $anvil->data->{cgi}{login_password}{alert} ? "input_alert" : "input_clear"; my $login_password_form = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "login_password", id => "login_password", field => "#!string!striker_0172!#", description => "#!string!striker_0173!#", value => $login_password, default_value => "", class => $login_password_class, extra => "", }}); # connection security my $connection_security_select = $anvil->Template->select_form({ name => "connection_security", options => [ "none#!#".$anvil->Words->string({key => "striker_0174"}), "ssl_tls#!#".$anvil->Words->string({key => "striker_0175"}), "starttls#!#".$anvil->Words->string({key => "striker_0176"}) ], blank => 0, selected => $connection_security, class => $anvil->data->{cgi}{connection_security}{alert} ? "input_alert" : "input_clear", }); # Authentication method my $authentication_method_select = $anvil->Template->select_form({ name => "authentication_method", options => [ "normal_password#!#".$anvil->Words->string({key => "striker_0177"}), "encrypted_password#!#".$anvil->Words->string({key => "striker_0178"}), "kerberos_gssapi#!#".$anvil->Words->string({key => "striker_0179"}), "ntlm#!#".$anvil->Words->string({key => "striker_0180"}), "tls_certificate#!#".$anvil->Words->string({key => "striker_0181"}), "oauth2#!#".$anvil->Words->string({key => "striker_0182"}) ], blank => 0, selected => $authentication_method, class => $anvil->data->{cgi}{authentication_method}{alert} ? "input_alert" : "input_clear", }); # Show the menu. $anvil->data->{form}{back_link} = "?email=true"; $anvil->data->{form}{refresh_link} = "?email=true&task=email_server"; $anvil->data->{form}{body} = $anvil->Template->get({file => "email.html", name => "mail-server-menu", variables => { mail_servers => $mail_servers_form, outgoing_mail_server => $outgoing_mail_server_form, login_name => $login_name_form, login_password => $login_password_form, connection_security => $connection_security_select, authentication_method => $authentication_method_select, mail_server_uuid => $mail_server_uuid, port => $port, }}); return(0); } # This handles the "Striker" menu items. sub process_striker_menu { my ($anvil) = @_; $anvil->data->{form}{back_link} = "?striker=true"; $anvil->data->{cgi}{task}{value} = "" if not defined $anvil->data->{cgi}{task}{value}; $anvil->data->{cgi}{action}{value} = "" if not defined $anvil->data->{cgi}{action}{value}; $anvil->data->{cgi}{save}{value} = "" if not defined $anvil->data->{cgi}{save}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::back_link" => $anvil->data->{form}{back_link}, "cgi::task::value" => $anvil->data->{cgi}{task}{value}, "cgi::action::value" => $anvil->data->{cgi}{action}{value}, "cgi::save::value" => $anvil->data->{cgi}{save}{value}, }}); if ($anvil->data->{cgi}{task}{value} eq "sync") { process_sync_page($anvil); } elsif ($anvil->data->{cgi}{task}{value} eq "reconfig") { process_reconfig_page($anvil); } elsif ($anvil->data->{cgi}{task}{value} eq "update") { process_update($anvil); } elsif ($anvil->data->{cgi}{task}{value} eq "install-target") { process_install_target($anvil); } elsif ($anvil->data->{cgi}{task}{value} eq "reboot") { process_power($anvil, "reboot"); } elsif ($anvil->data->{cgi}{task}{value} eq "poweroff") { process_power($anvil, "poweroff"); } elsif ($anvil->data->{cgi}{task}{value} eq "keys") { process_keys($anvil, "poweroff"); } else { # What we show for the reboot icon and text depends on if a reboot is pending. my $reboot_needed = $anvil->System->reboot_needed(); my $reboot_icon = $reboot_needed ? "reboot_needed_icon.png" : "reboot_icon.png"; my $reboot_message = $reboot_needed ? "#!string!striker_0093!#" : "#!string!striker_0092!#"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { reboot_needed => $reboot_needed, reboot_icon => $reboot_icon, reboot_message => $reboot_message, }}); # What we show for the install target icon and text depends on if it is enabled or not. my $install_target_title = "#!string!striker_0109!#"; my $install_target_icon = "install_target_disabled.png"; my $install_target_subtask = "unavailable"; my ($install_manifest_status, $variable_uuid, $modified_date) = $anvil->Database->read_variable({ variable_name => "install-target::enabled", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { install_manifest_status => $install_manifest_status, variable_uuid => $variable_uuid, modified_date => $modified_date, }}); if ($install_manifest_status eq "enabled") { # Offer the button to disable it. $install_target_title = "#!string!striker_0108!#"; $install_target_icon = "install_target_enabled.png"; $install_target_subtask = "disable"; } elsif ($install_manifest_status eq "disabled") { # Offer the button to enable it. $install_target_title = "#!string!striker_0107!#"; $install_target_subtask = "enable"; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { install_target_title => $install_target_title, install_target_icon => $install_target_icon, install_target_subtask => $install_target_subtask, }}); # Are there any bad keys? my $query = "SELECT state_uuid, state_note FROM states WHERE state_name LIKE 'host_key_changed::%';"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { results => $results, count => $count, }}); my $broken_key_icon = $count ? "broken_key_icon_on.png" : "broken_key_icon_off.png"; my $broken_key_message = $count ? "#!string!striker_0132!#" : "#!string!striker_0131!#"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { broken_key_icon => $broken_key_icon, broken_key_message => $broken_key_message, }}); # The 'back' goes home $anvil->data->{form}{back_link} = "?"; $anvil->data->{form}{refresh_link} = "?striker=true"; $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "striker-setup", variables => { reboot_icon => $reboot_icon, reboot_message => $reboot_message, install_target_icon => $install_target_icon, install_target_title => $install_target_title, install_target_subtask => $install_target_subtask, broken_key_icon => $broken_key_icon, broken_key_message => $broken_key_message, }}); } return(0); } # This shows the user any running jobs. sub process_jobs_menu { my ($anvil) = @_; $anvil->data->{form}{refresh_link} = "?jobs=true"; $anvil->data->{form}{back_link} = "?striker=true"; $anvil->data->{cgi}{task}{value} = "" if not defined $anvil->data->{cgi}{task}{value}; $anvil->data->{cgi}{action}{value} = "" if not defined $anvil->data->{cgi}{action}{value}; $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "jobs", variables => { title_id => "", message_id => "", title => "#!string!striker_0096!#", description => "#!string!striker_0115!#", job_list => $anvil->Job->html_list({debug => 2, ended_within => 300}), }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'say::maintenance' => $anvil->data->{say}{maintenance} }}); return(0); } # This handles removing old keys. sub process_keys { my ($anvil) = @_; ### NOTE: This doesn't update Striker (the Alteeve) stack yet, just the base OS. my $show_list = 1; $anvil->data->{cgi}{'delete'}{value} = "" if not defined $anvil->data->{cgi}{'delete'}{value}; if ($anvil->data->{cgi}{'delete'}{value}) { # Record the job! my $job_data = {}; foreach my $key (sort {$a cmp $b} keys %{$anvil->data->{cgi}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { key => $key }}); if ($key =~ /^state_uuid_(.*)$/) { my $state_uuid = $1; $show_list = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { state_uuid => $state_uuid, show_list => $show_list, }}); my $query = "SELECT state_host_uuid FROM states WHERE state_uuid = ".$anvil->Database->quote($state_uuid).";"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); my $host_uuid = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; $host_uuid = "" if not defined $host_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); next if not $host_uuid; if (not exists $job_data->{$host_uuid}) { $job_data->{$host_uuid} = ""; } $job_data->{$host_uuid} .= $state_uuid.","; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "job_data->{$host_uuid}" => $job_data->{$host_uuid}, }}); } } my $show_template = 0; foreach my $host_uuid (keys %{$job_data}) { $job_data->{$host_uuid} =~ s/,$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "job_data->{$host_uuid}" => $job_data->{$host_uuid}, }}); if ($job_data->{$host_uuid}) { $show_template = 1; my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ file => $THIS_FILE, line => __LINE__, job_command => $anvil->data->{path}{exe}{'anvil-manage-keys'}.$anvil->Log->switches, job_data => $job_data->{$host_uuid}, job_name => "manage::broken_keys", job_title => "job_0056", job_description => "job_0057", job_progress => 0, job_host_uuid => $host_uuid, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { show_template => $show_template, job_uuid => $job_uuid, }}); } } if ($show_template) { # We don't need to store anything as hidden variables, we'll read it back from the # database later. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "job recorded", variables => { title_id => "", message_id => "", reload_url => "/cgi-bin/".$THIS_FILE, title => "#!string!job_0056!#", description => "#!string!job_0057!#", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { show_list => $show_list }}); if ($show_list) { # Get a list of bad keys we know about and ask the user which they want to remove my $query = " SELECT a.state_uuid, b.host_name, a.state_name, a.state_note FROM states a, hosts b WHERE a.state_host_uuid = b.host_uuid AND a.state_name LIKE 'host_key_changed::%' ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); if (not $count) { # No bad keys found on this host. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "no-bad-keys"}); } else { # Build a list of check-boxes / bad keys. my $bad_key_list = ""; foreach my $row (@{$results}) { my $state_uuid = $row->[0]; my $host_name = $row->[1]; my $state_name = $row->[2]; my $state_note = $row->[3]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { state_uuid => $state_uuid, host_name => $host_name, state_name => $state_name, state_note => $state_note, }}); my $bad_file = ""; my $bad_line = ""; foreach my $pair (split/,/, $state_note) { my ($variable, $value) = ($pair =~ /^(.*?)=(.*)$/); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pair => $pair, variable => $variable, value => $value, }}); if ($variable eq "file") { $bad_file = $value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bad_file => $bad_file }}); } if ($variable eq "line") { $bad_line = $value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bad_line => $bad_line }}); } } my ($target) = ($state_name =~ /host_key_changed::(.*)$/); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target => $target, bad_file => $bad_file, bad_line => $bad_line, }}); my $checkbox_key = "state_uuid_".$state_uuid; my $checked = ""; if ((exists $anvil->data->{cgi}{$checkbox_key}) && ($anvil->data->{cgi}{$checkbox_key}{value})) { $checked = "checked"; } $bad_key_list .= $anvil->Template->get({file => "striker.html", name => "broken-key-entry", variables => { checkbox_name => $checkbox_key, checkbox_checked => $checked, target => $target, file => $bad_file, host => $host_name, }}); } #Show the screen the confirm the addition. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "broken-key-list", variables => { bad_keys => $bad_key_list, }}); } } return(0); } # This processes changes to files, including deletions (purges). sub process_file_change { my ($anvil) = @_; # First, clear the 'save' and 'confirm' buttons. $anvil->data->{cgi}{save}{value} = ""; $anvil->data->{cgi}{confirm}{value} = ""; # Are we being asked to purge a file? $anvil->Database->get_anvils(); $anvil->Database->get_files(); $anvil->Database->get_file_locations(); my $file_uuid = $anvil->data->{cgi}{file_uuid}{value}; my $file_name = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name}; my $file_type = $anvil->data->{files}{file_uuid}{$file_uuid}{file_type}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_uuid => $file_uuid, file_name => $file_name, file_type => $file_type, }}); if ($anvil->data->{cgi}{purge}{value}) { # Update the file to set the file type to 'DELETED'. my $old_file_type = $anvil->data->{files}{file_uuid}{$file_uuid}{file_type}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_file_type => $old_file_type }}); if ($old_file_type ne "DELETED") { my $query = " UPDATE files SET file_type = 'DELETED', modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE file_uuid = ".$anvil->Database->quote($file_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } # Register jobs on all systems to remove this file. $anvil->Database->insert_or_update_jobs({ debug => 2, file => $THIS_FILE, line => __LINE__, job_host_uuid => "all", job_command => $anvil->data->{path}{exe}{'anvil-sync-shared'}.$anvil->Log->switches, job_data => "file_uuid=".$file_uuid, job_name => "storage::purge", job_title => "job_0136", job_description => "job_0137", job_progress => 0, }); $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => "#!string!ok_0012!#" }}); } else { ### Nope, we're doing other things. Possibly multiple things. # Did the file name change? my $ok_messages = ""; if (($anvil->data->{cgi}{new_file_name}{value}) && ($anvil->data->{cgi}{new_file_name}{value} ne $file_name)) { # Rename the file. my $old_file_name = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name}; my $new_file_name = $anvil->data->{cgi}{new_file_name}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_file_name => $old_file_name, new_file_name => $new_file_name, }}); if ($old_file_name ne $new_file_name) { my $query = " UPDATE files SET file_name = ".$anvil->Database->quote($new_file_name).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE file_uuid = ".$anvil->Database->quote($file_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } $anvil->Database->insert_or_update_jobs({ debug => 2, file => $THIS_FILE, line => __LINE__, job_host_uuid => "all", job_command => $anvil->data->{path}{exe}{'anvil-sync-shared'}.$anvil->Log->switches, job_data => "file_uuid=".$file_uuid."\nold_name=".$file_name."\nnew_name=".$anvil->data->{cgi}{new_file_name}{value}, job_name => "storage::rename", job_title => "job_0138", job_description => "job_0139", job_progress => 0, }); $ok_messages .= "#!string!ok_0013!# "; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ok_messages => $ok_messages }}); } # Did the file type change? $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::new_file_type::value" => $anvil->data->{cgi}{new_file_type}{value}, file_type => $file_type, }}); if (($anvil->data->{cgi}{new_file_type}{value}) && ($anvil->data->{cgi}{new_file_type}{value} ne $file_type)) { # Easy peasy, update the DBey. my $query = " UPDATE files SET file_type = ".$anvil->Database->quote($anvil->data->{cgi}{new_file_type}{value}).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE file_uuid = ".$anvil->Database->quote($file_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); # Register a job on all machines (that have this file) to set the mode. $anvil->Database->insert_or_update_jobs({ debug => 2, file => $THIS_FILE, line => __LINE__, job_host_uuid => "all", job_command => $anvil->data->{path}{exe}{'anvil-sync-shared'}.$anvil->Log->switches, job_data => "file_uuid=".$file_uuid, job_name => "storage::check_mode", job_title => "job_0143", job_description => "job_0144", job_progress => 0, }); $ok_messages .= "#!string!ok_0014!# "; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ok_messages => $ok_messages }}); } # Loop through the Anvil! systems and see if any have changed from sync to remove or vice # versa. foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{cgi}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); if ($variable =~ /anvil_uuid::(.*?)::sync/) { my $anvil_uuid = $1; my $anvil_name = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name}; my $sync_value = $anvil->data->{cgi}{$variable}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid, sync_value => $sync_value, }}); # Coming from the CGI, sync will be 'true' or 'false', while the 'active' # value from the database is '1' or '0'. We'll convert the database version # for comparison versions. my $file_location_uuid = $anvil->data->{file_locations}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_location_uuid}; my $old_file_location_active = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active} ? "true" : "false"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_location_uuid => $file_location_uuid, old_file_location_active => $old_file_location_active, }}); if ($sync_value ne $old_file_location_active) { # Update the database and create a job for the member nodes to purge # the file. my $new_active = "FALSE"; my $ok_key = "ok_0016"; my $job_type = "storage::purge"; my $job_title = "job_0136"; my $job_description = "job_0137"; if ($sync_value eq "true") { $new_active = "TRUE"; $ok_key = "ok_0015"; $job_type = "storage::pull_file"; $job_title = "job_0132"; $job_description = "job_0133"; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_active => $new_active, ok_key => $ok_key, job_type => $job_type, job_title => $job_title, job_description => $job_description, }}); $ok_messages .= $anvil->Words->string({key => $ok_key, variables => { anvil_name => $anvil_name }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ok_messages => $ok_messages }}); my $query = " UPDATE file_locations SET file_location_active = ".$anvil->Database->quote($new_active).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE file_location_uuid = ".$anvil->Database->quote($file_location_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); # Now create a job for each Anvil! member. my $member_uuids = []; push @{$member_uuids}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; push @{$member_uuids}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; if ($anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid}) { push @{$member_uuids}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid}; } foreach my $host_uuid (@{$member_uuids}) { my $job_uuid = $anvil->Database->insert_or_update_jobs({ debug => 2, file => $THIS_FILE, line => __LINE__, job_host_uuid => $host_uuid, job_command => $anvil->data->{path}{exe}{'anvil-sync-shared'}.$anvil->Log->switches, job_data => "file_uuid=".$file_uuid, job_name => $job_type, job_title => $job_title, job_description => $job_description, job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); } } } } $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => $ok_messages }}); } return(0); } # This handles files. sub process_file_menu { my ($anvil) = @_; $anvil->data->{cgi}{action}{value} = "" if not defined $anvil->data->{cgi}{action}{value}; $anvil->data->{cgi}{confirm}{value} = "" if not defined $anvil->data->{cgi}{confirm}{value}; $anvil->data->{cgi}{file_uuid}{value} = "" if not defined $anvil->data->{cgi}{file_uuid}{value}; $anvil->data->{cgi}{purge}{value} = "" if not defined $anvil->data->{cgi}{purge}{value}; $anvil->data->{cgi}{save}{value} = "" if not defined $anvil->data->{cgi}{save}{value}; $anvil->data->{cgi}{task}{value} = "" if not defined $anvil->data->{cgi}{task}{value}; $anvil->data->{form}{refresh_link} = "?files=true"; $anvil->Database->get_files(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::file_uuid::value" => $anvil->data->{cgi}{file_uuid}{value}, "cgi::save::value" => $anvil->data->{cgi}{save}{value}, "cgi::confirm::value" => $anvil->data->{cgi}{confirm}{value}, }}); if (($anvil->data->{cgi}{file_uuid}{value}) && ($anvil->data->{cgi}{save}{value}) && ($anvil->data->{cgi}{confirm}{value})) { process_file_change($anvil); } # Make sure that all files are registered with all Anvil! systems, This also (re)loads the data. $anvil->Database->check_file_locations({debug => 2}); # Build the list of existing files. my $file_list = $anvil->Template->get({file => "files.html", name => "open-file-list"}); foreach my $file_name (sort {$a cmp $b} keys %{$anvil->data->{files}{file_name}}) { my $file_uuid = $anvil->data->{files}{file_name}{$file_name}{file_uuid}; my $file_size = $anvil->data->{files}{file_name}{$file_name}{file_size}; my $say_file_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $file_size}); my $file_md5sum = $anvil->data->{files}{file_name}{$file_name}{file_md5sum}; my $file_type = $anvil->data->{files}{file_name}{$file_name}{file_type}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_name => $file_name, file_uuid => $file_uuid, file_size => $file_size." (".$say_file_size.")", file_md5sum => $file_md5sum, file_type => $file_type, }}); $file_list .= $anvil->Template->get({file => "files.html", name => "file-list-entry", variables => { file_uuid => $file_uuid, file_name => $file_name, file_type => $file_type, file_size => $say_file_size, md5sum => $file_md5sum, }}); if ($anvil->data->{cgi}{file_uuid}{value} eq $file_uuid) { $anvil->data->{form}{refresh_link} = "?files=true&file_uuid=".$anvil->data->{cgi}{file_uuid}{value}; $anvil->data->{form}{back_link} = "?files=true"; $anvil->data->{cgi}{new_file_name}{value} = $file_name if not defined $anvil->data->{cgi}{new_file_name}{value}; $anvil->data->{cgi}{new_file_name}{alert} = "" if not defined $anvil->data->{cgi}{new_file_name}{alert}; $anvil->data->{cgi}{new_file_type}{value} = $file_type if not defined $anvil->data->{cgi}{new_file_type}{value}; # Build the file type select my $file_type_options = [ "iso#!#".$anvil->Words->string({key => "type_0001"}), "script#!#".$anvil->Words->string({key => "type_0002"}), "other#!#".$anvil->Words->string({key => "type_0003"}) ]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::new_file_type::value" => $anvil->data->{cgi}{new_file_type}{value} }}); my $select_file_type = $anvil->Template->select_form({ name => "new_file_type", options => $file_type_options, blank => 0, 'sort' => 1, selected => $anvil->data->{cgi}{new_file_type}{value}, class => "input_clear", style => "", }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { select_file_type => $select_file_type }}); # Build the anvil list $anvil->Database->get_anvils({debug => 3}); $anvil->Database->get_file_locations({debug => 3}); my $say_save_confirm = " "; my $say_purge_confirm = " "; my $anvil_list = ""; if (not exists $anvil->data->{anvils}{anvil_name}) { $anvil_list .= $anvil->Template->get({file => "files.html", name => "file-list-manager-no-anvils"}); } else { foreach my $anvil_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_name}}) { my $anvil_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_uuid}; my $anvil_description = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_description}; my $file_location_uuid = $anvil->data->{file_locations}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_location_uuid}; my $synced = $anvil->data->{file_locations}{file_location_uuid}{$file_location_uuid}{file_location_active}; my $radio_key = "anvil_uuid::".$anvil_uuid."::sync"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:anvil_name" => $anvil_name, "s2:anvil_uuid" => $anvil_uuid, "s3:anvil_description" => $anvil_description, "s4:file_location_uuid" => $file_location_uuid, "s5:synced" => $synced, "s6:radio_key" => $radio_key, }}); $anvil->data->{cgi}{$radio_key}{value} = "" if not defined $anvil->data->{cgi}{$radio_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${radio_key}::value" => $anvil->data->{cgi}{$radio_key}{value}, }}); my $true_checked = "checked"; my $false_checked = ""; if ($anvil->data->{cgi}{$radio_key}{value}) { if ($anvil->data->{cgi}{$radio_key}{value} eq "false") { $true_checked = ""; $false_checked = "checked"; } } elsif (not $synced) { $true_checked = ""; $false_checked = "checked"; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:true_checked" => $true_checked, "s2:false_checked" => $false_checked, }}); if (($anvil->data->{cgi}{purge}{value}) && (not $anvil->data->{cgi}{confirm}{value})) { $say_purge_confirm = $anvil->Template->get({file => "files.html", name => "file-list-manager-confirm-purge-button", variables => { url => "?files=true&file_uuid=".$file_uuid."&purge=true&&save=true&confirm=true", }}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_save_confirm => $say_save_confirm }}); if (($anvil->data->{cgi}{save}{value}) && (not $anvil->data->{cgi}{confirm}{value})) { $say_save_confirm = $anvil->Template->get({file => "files.html", name => "file-list-manager-confirm-save-button"}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_save_confirm => $say_save_confirm }}); $anvil_list .= $anvil->Template->get({file => "files.html", name => "file-list-manager-anvil-entry", variables => { anvil_name => $anvil_name, anvil_description => $anvil_description, radio_name => $radio_key, true_checked => $true_checked, false_checked => $false_checked, }}); } } # Insert the file management section under the file entry. $file_list .= $anvil->Template->get({file => "files.html", name => "file-list-manager", variables => { file_uuid => $file_uuid, new_file_name => $anvil->data->{cgi}{new_file_name}{value}, new_file_type => $select_file_type, confirm_save_button => $say_save_confirm, confirm_purge_button => $say_purge_confirm, new_file_name_class => $anvil->data->{cgi}{new_file_name}{alert} ? "input_alert_fixed" : "input_clear_fixed", anvil_list => $anvil_list, }}); } } $file_list .= $anvil->Template->get({file => "files.html", name => "close-file-list"}); # The 'back' goes home $anvil->data->{form}{back_link} = "?"; $anvil->data->{form}{body} = $anvil->Template->get({file => "files.html", name => "main-menu", variables => { file_list => $file_list, }}); return(0); } # This handles the "Anvil" menu items. sub process_anvil_menu { my ($anvil) = @_; $anvil->data->{form}{refresh_link} = "striker?anvil=true"; $anvil->data->{form}{back_link} = "?striker=true"; $anvil->data->{cgi}{task}{value} = "" if not defined $anvil->data->{cgi}{task}{value}; $anvil->data->{cgi}{action}{value} = "" if not defined $anvil->data->{cgi}{action}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'cgi::task::value' => $anvil->data->{cgi}{task}{value}, 'cgi::action::value' => $anvil->data->{cgi}{action}{value}, }}); if ($anvil->data->{cgi}{task}{value} eq "prep-host") { process_prep_host_page($anvil); } elsif ($anvil->data->{cgi}{task}{value} eq "prep-network") { process_prep_network($anvil); } elsif ($anvil->data->{cgi}{task}{value} eq "create") { # This handles the main "create an anvil" page. process_create($anvil); } elsif ($anvil->data->{cgi}{task}{value} eq "fences") { process_fences($anvil); } elsif ($anvil->data->{cgi}{task}{value} eq "upses") { process_upses($anvil); } elsif ($anvil->data->{cgi}{task}{value} eq "manifests") { process_manifests($anvil); } else { # The 'back' goes home $anvil->data->{form}{back_link} = "?"; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "main-menu", variables => { }}); } return(0); } # This handles all aspects of Install Manifests. sub process_manifests { my ($anvil) = @_; # Are we creating a new manifest? $anvil->data->{cgi}{manifest_uuid}{value} = "" if not defined $anvil->data->{cgi}{manifest_uuid}{value}; $anvil->data->{cgi}{confirm}{value} = "" if not defined $anvil->data->{cgi}{confirm}{alert}; $anvil->data->{cgi}{run}{value} = "" if not defined $anvil->data->{cgi}{run}{value}; $anvil->data->{cgi}{step}{value} = 1 if not defined $anvil->data->{cgi}{step}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'cgi::manifest_uuid::value' => $anvil->data->{cgi}{manifest_uuid}{value}, }}); # Are we running a manifest, or creating/editing one? if (($anvil->data->{cgi}{run}{value}) && ($anvil->Validate->uuid({uuid => $anvil->data->{cgi}{manifest_uuid}{value}}))) { run_manifest($anvil); } else { handle_manifest($anvil); } return(0); } # This is an extension to 'handle_manifests' that specifically handles running an install manifest. sub run_manifest { my ($anvil) = @_; $anvil->data->{cgi}{description}{value} = "" if not defined $anvil->data->{cgi}{description}{value}; $anvil->data->{cgi}{description}{alert} = 0 if not defined $anvil->data->{cgi}{description}{alert}; $anvil->data->{cgi}{password}{value} = "" if not defined $anvil->data->{cgi}{password}{value}; $anvil->data->{cgi}{password}{alert} = 0 if not defined $anvil->data->{cgi}{password}{alert}; $anvil->Database->get_hosts({debug => 2}); my $manifest_uuid = $anvil->data->{cgi}{manifest_uuid}{value}; my $problem = $anvil->Striker->load_manifest({ debug => 2, manifest_uuid => $manifest_uuid, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { manifest_uuid => $manifest_uuid, problem => $problem, }}); if ($problem) { # Report a problem and send the user back to the manifests page. my $message = $anvil->Words->string({key => "warning_0046", variables => { uuid => $manifest_uuid }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } my $anvil_name = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{name}; my $prefix = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{prefix}; my $sequence = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{sequence}; my $domain = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{domain}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_name => $anvil_name, prefix => $prefix, sequence => $sequence, domain => $domain, }}); my $node1_name = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node1}{name}; my $node2_name = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node2}{name}; my $dr1_name = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{dr1}{name}; if ($domain) { $node1_name = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node1}{name}.".".$domain; $node2_name = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node2}{name}.".".$domain; $dr1_name = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{dr1}{name}.".".$domain; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { node1_name => $node1_name, node2_name => $node2_name, dr1_name => $dr1_name, }}); my $bcn_count = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{bcn}; my $sn_count = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{sn}; my $ifn_count = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{ifn}; my $mn_count = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{mn}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bcn_count => $bcn_count, sn_count => $sn_count, ifn_count => $ifn_count, mn_count => $mn_count, }}); # If confirmed, run! $anvil->data->{cgi}{confirm}{value} = "" if not defined $anvil->data->{cgi}{confirm}{value}; if ($anvil->data->{cgi}{confirm}{value}) { # Make sure the passwords match. my $problem = 0; if (not $anvil->data->{cgi}{password1}{value}) { # Didn't set a password $problem = 1; $anvil->data->{cgi}{password1}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => "#!string!warning_0047!#" }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem, "cgi::password1::alert" => $anvil->data->{cgi}{password1}{alert}, "form::error_massage" => $anvil->data->{form}{error_massage}, }}); } elsif (not $anvil->data->{cgi}{password2}{value}) { # Missing both passwords $problem = 1; $anvil->data->{cgi}{password2}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => "#!string!warning_0048!#" }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem, "cgi::password2::alert" => $anvil->data->{cgi}{password2}{alert}, "form::error_massage" => $anvil->data->{form}{error_massage}, }}); } elsif ($anvil->data->{cgi}{password1}{value} ne $anvil->data->{cgi}{password2}{value}) { $problem = 1; $anvil->data->{cgi}{password1}{alert} = 1; $anvil->data->{cgi}{password2}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => "#!string!warning_0049!#" }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem, "cgi::password1::alert" => $anvil->data->{cgi}{password1}{alert}, "cgi::password2::alert" => $anvil->data->{cgi}{password2}{alert}, "form::error_massage" => $anvil->data->{form}{error_massage}, }}); } # Check that the machines selected didn't get added to another anvil while looking. my $node1_host_uuid = $anvil->data->{cgi}{node1_host}{value}; my $node1_host_name = $anvil->data->{sys}{hosts}{by_uuid}{$node1_host_uuid}; my $node1_anvil = $anvil->data->{hosts}{host_uuid}{$node1_host_uuid}{anvil_name}; my $node2_host_uuid = $anvil->data->{cgi}{node2_host}{value}; my $node2_host_name = $anvil->data->{sys}{hosts}{by_uuid}{$node2_host_uuid}; my $node2_anvil = $anvil->data->{hosts}{host_uuid}{$node2_host_uuid}{anvil_name}; my $dr1_host_uuid = $anvil->data->{cgi}{dr1_host}{value}; my $dr1_host_name = $dr1_host_uuid ? $anvil->data->{sys}{hosts}{by_uuid}{$dr1_host_uuid} : ""; my $dr1_anvil = $dr1_host_uuid ? $anvil->data->{hosts}{host_uuid}{$dr1_host_uuid}{anvil_name} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { node1_host_name => $node1_host_name, node1_host_uuid => $node1_host_uuid, node1_anvil => $node1_anvil, node2_host_name => $node2_host_name, node2_host_uuid => $node2_host_uuid, node2_anvil => $node2_anvil, dr1_host_name => $dr1_host_name, dr1_host_uuid => $dr1_host_uuid, dr1_anvil => $dr1_anvil, }}); # Make sure the three options are unique. if ($node1_host_uuid eq $node2_host_uuid) { my $message = $anvil->Words->string({key => "warning_0054"}); $problem = 1; $anvil->data->{cgi}{node1_host}{alert} = 1; $anvil->data->{cgi}{node2_host}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem, "cgi::node1_host::alert" => $anvil->data->{cgi}{node1_host}{alert}, "cgi::node2_host::alert" => $anvil->data->{cgi}{node2_host}{alert}, "form::error_massage" => $anvil->data->{form}{error_massage}, }}); } if ($dr1_host_uuid) { if ($dr1_host_uuid eq $node1_host_uuid) { my $message = $anvil->Words->string({key => "warning_0055"}); $problem = 1; $anvil->data->{cgi}{dr1_host}{alert} = 1; $anvil->data->{cgi}{node1_host}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem, "cgi::dr1_host::alert" => $anvil->data->{cgi}{dr1_host}{alert}, "cgi::node1_host::alert" => $anvil->data->{cgi}{node1_host}{alert}, "form::error_massage" => $anvil->data->{form}{error_massage}, }}); } elsif ($dr1_host_uuid eq $node2_host_uuid) { my $message = $anvil->Words->string({key => "warning_0056"}); $problem = 1; $anvil->data->{cgi}{dr1_host}{alert} = 1; $anvil->data->{cgi}{node2_host}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem, "cgi::dr1_host::alert" => $anvil->data->{cgi}{dr1_host}{alert}, "cgi::node2_host::alert" => $anvil->data->{cgi}{node2_host}{alert}, "form::error_massage" => $anvil->data->{form}{error_massage}, }}); } } if (($node1_anvil) && ($node1_anvil ne $anvil_name)) { # The server belongs to another Anvil! system. my $message = $anvil->Words->string({key => "warning_0050", variables => { machine => $node1_host_name, anvil => $anvil_name, }}); $problem = 1; $anvil->data->{cgi}{node1_host}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem, "cgi::node1_host::alert" => $anvil->data->{cgi}{node1_host}{alert}, "form::error_massage" => $anvil->data->{form}{error_massage}, }}); } if (($node2_anvil) && ($node2_anvil ne $anvil_name)) { # The server belongs to another Anvil! system. my $message = $anvil->Words->string({key => "warning_0050", variables => { machine => $node2_host_name, anvil => $anvil_name, }}); $problem = 1; $anvil->data->{cgi}{node2_host}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem, "cgi::node2_host::alert" => $anvil->data->{cgi}{node2_host}{alert}, "form::error_massage" => $anvil->data->{form}{error_massage}, }}); } if ($anvil->data->{cgi}{dr1_host}{value}) { if (($dr1_anvil) && ($dr1_anvil ne $anvil_name)) { # The server belongs to another Anvil! system. my $message = $anvil->Words->string({key => "warning_0050", variables => { machine => $dr1_host_name, anvil => $anvil_name, }}); $problem = 1; $anvil->data->{cgi}{dr1_host}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem, "cgi::dr1_host::alert" => $anvil->data->{cgi}{dr1_host}{alert}, "form::error_massage" => $anvil->data->{form}{error_massage}, }}); } } if (not $problem) { # Record and entry in the 'anvils' table. my ($anvil_uuid) = $anvil->Database->insert_or_update_anvils({ debug => 2, anvil_description => $anvil->data->{cgi}{description}{value}, anvil_name => $anvil_name, anvil_password => $anvil->data->{cgi}{password1}{value}, anvil_node1_host_uuid => $node1_host_uuid, anvil_node2_host_uuid => $node2_host_uuid, anvil_dr1_host_uuid => $dr1_host_uuid, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); # Save the jobs! my ($node1_job_uuid) = $anvil->Database->insert_or_update_jobs({ debug => 2, file => $THIS_FILE, line => __LINE__, job_host_uuid => $node1_host_uuid, job_command => $anvil->data->{path}{exe}{'anvil-join-anvil'}.$anvil->Log->switches, job_data => "as_machine=node1,manifest_uuid=".$manifest_uuid.",anvil_uuid=".$anvil_uuid, job_name => "join_anvil::node1", job_title => "job_0072", job_description => "job_0073", job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { node1_job_uuid => $node1_job_uuid }}); my ($node2_job_uuid) = $anvil->Database->insert_or_update_jobs({ debug => 2, file => $THIS_FILE, line => __LINE__, job_host_uuid => $node2_host_uuid, job_command => $anvil->data->{path}{exe}{'anvil-join-anvil'}.$anvil->Log->switches, job_data => "as_machine=node2,manifest_uuid=".$manifest_uuid.",anvil_uuid=".$anvil_uuid, job_name => "join_anvil::node2", job_title => "job_0072", job_description => "job_0073", job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { node2_job_uuid => $node2_job_uuid }}); if ($anvil->data->{cgi}{dr1_host}{value}) { my ($dr1_job_uuid) = $anvil->Database->insert_or_update_jobs({ debug => 2, file => $THIS_FILE, line => __LINE__, job_host_uuid => $dr1_host_uuid, job_command => $anvil->data->{path}{exe}{'anvil-join-anvil'}.$anvil->Log->switches, job_data => "as_machine=dr1,manifest_uuid=".$manifest_uuid.",anvil_uuid=".$anvil_uuid, job_name => "join_anvil::dr1", job_title => "job_0072", job_description => "job_0073", job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { dr1_job_uuid => $dr1_job_uuid }}); } # Tell them we're done and send them back to the main page. $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => "#!string!ok_0011!#" }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::ok_message" => $anvil->data->{form}{ok_message} }}); process_create($anvil); return(0); } } # Ask the user to choose the targets and confirm the manifest settings. my $nodes = []; my $dr_hosts = []; foreach my $host_uuid (keys %{$anvil->data->{hosts}{host_uuid}}) { my $host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name}; my $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}; my $host_anvil = ""; if ((exists $anvil->data->{hosts}{host_uuid}{$host_uuid}) && ($anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_name} ne $anvil_name)) { $host_anvil = $anvil_name; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid, host_name => $host_name, host_type => $host_type, host_anvil => $host_anvil, }}); # Does this host belong to another Anvil! already? if (($host_anvil) && ($host_anvil ne $anvil_name)) { # yup, ignore it. next; } if ($host_type eq "node") { push @{$nodes}, $host_uuid."#!#".$host_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_name => $host_name }}); if ((not defined $anvil->data->{cgi}{node1_host}{value}) && ($host_name eq $node1_name)) { $anvil->data->{cgi}{node1_host}{value} = $host_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::node1_host::value" => $anvil->data->{cgi}{node1_host}{value} }}); } elsif ((not defined $anvil->data->{cgi}{node2_host}{value}) && ($host_name eq $node2_name)) { $anvil->data->{cgi}{node2_host}{value} = $host_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::node2_host::value" => $anvil->data->{cgi}{node2_host}{value} }}); } } elsif ($host_type eq "dr") { push @{$dr_hosts}, $host_uuid."#!#".$host_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_name => $host_name }}); if ((not defined $anvil->data->{cgi}{dr1_host}{value}) && ($host_name eq $dr1_name)) { $anvil->data->{cgi}{dr1_host}{value} = $host_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::dr1_host::value" => $anvil->data->{cgi}{dr1_host}{value} }}); } } } # We're going to need three selects; one for each node and one for DR. The DR is allowed to # be unselected so it has an empty entry. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::node1_host::value" => $anvil->data->{cgi}{node1_host}{value} }}); my $select_node1 = $anvil->Template->select_form({ debug => 2, name => "node1_host", options => $nodes, blank => 0, 'sort' => 1, selected => $anvil->data->{cgi}{node1_host}{value}, class => $anvil->data->{cgi}{node1_host}{alert} ? "input_alert" : "input_clear", style => "", }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { select_node1 => $select_node1 }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::node2_host::value" => $anvil->data->{cgi}{node2_host}{value} }}); my $select_node2 = $anvil->Template->select_form({ debug => 2, name => "node2_host", options => $nodes, blank => 0, 'sort' => 1, selected => $anvil->data->{cgi}{node2_host}{value}, class => $anvil->data->{cgi}{node2_host}{alert} ? "input_alert" : "input_clear", style => "", }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { select_node2 => $select_node2 }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::dr1_host::value" => $anvil->data->{cgi}{dr1_host}{value} }}); my $select_dr1 = $anvil->Template->select_form({ debug => 2, name => "dr1_host", options => $dr_hosts, blank => 1, 'sort' => 1, selected => $anvil->data->{cgi}{dr1_host}{value}, class => $anvil->data->{cgi}{dr1_host}{alert} ? "input_alert" : "input_clear", style => "", }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { select_dr1 => $select_dr1 }}); # Show the networks. my $networks = ""; my $default_seen = 0; foreach my $network ("bcn", "sn", "mn", "ifn") { my $count = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{$network}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network => $network, count => $count, }}); foreach my $i (1..$count) { my $network_name = $network.$i; my $network_range = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{network}; my $subnet = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{subnet}; my $gateway = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{gateway}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_name => $network_name, network_range => $network_range, subnet => $subnet, gateway => $gateway, }}); my $say_default = ""; if (($network eq "ifn") && (not $default_seen) && ($gateway)) { $default_seen = 1; $say_default = "(#!string!striker_0249!#)"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { default_seen => $default_seen, say_default => $say_default, }}); } my $network_key = "header_0036"; if ($network eq "sn") { $network_key = "header_0037"; } elsif ($network eq "ifn") { $network_key = "header_0038"; } elsif ($network eq "mn") { $network_key = "header_0106"; } $networks .= $anvil->Template->get({file => "anvil.html", name => "run-manifest-network", variables => { name => $anvil->Words->string({key => $network_key, variables => { number => $i }}), network => $network_range, subnet => $subnet, gateway => $gateway ? $gateway : "--", 'default' => $say_default, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { networks => $networks }}); } } # Pull out the IPs that will be assigned to servers. my $machine_ips = ""; foreach my $network ("bcn", "sn", "mn", "ifn") { if ($network eq "sn") { # Inject the IPMI data. my $node1_ipmi_ip = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node1}{ipmi_ip}; my $node2_ipmi_ip = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node2}{ipmi_ip}; my $dr1_ipmi_ip = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{dr1}{ipmi_ip}; $machine_ips .= $anvil->Template->get({file => "anvil.html", name => "run-manifest-ip", variables => { name => "#!string!striker_0258!#", node1 => $node1_ipmi_ip ? $node1_ipmi_ip : "--", node2 => $node2_ipmi_ip ? $node2_ipmi_ip : "--", dr1 => $dr1_ipmi_ip ? $dr1_ipmi_ip : "--", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { networks => $networks }}); } my $count = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{$network}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network => $network, count => $count, }}); foreach my $i (1..$count) { my $network_name = $network.$i; my $node1_ip = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node1}{network}{$network_name}{ip}; my $node2_ip = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node2}{network}{$network_name}{ip}; my $dr1_ip = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{dr1}{network}{$network_name}{ip}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_name => $network_name, node1_ip => $node1_ip, node2_ip => $node2_ip, dr1_ip => $dr1_ip, }}); my $network_key = "header_0036"; if ($network eq "sn") { $network_key = "header_0037"; } elsif ($network eq "ifn") { $network_key = "header_0038"; } elsif ($network eq "mn") { $network_key = "header_0106"; } $machine_ips .= $anvil->Template->get({file => "anvil.html", name => "run-manifest-ip", variables => { name => $anvil->Words->string({key => $network_key, variables => { number => $i }}), node1 => $node1_ip ? $node1_ip : "--", node2 => $node2_ip ? $node2_ip : "--", dr1 => $dr1_ip ? $dr1_ip : "--", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { networks => $networks }}); } } my $dns = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{dns}; my $ntp = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{ntp}; my $mtu = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{mtu}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { dns => $dns, ntp => $ntp, mtu => $mtu, }}); my $fences = ""; foreach my $fence_name (sort {$a cmp $b} keys %{$anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node1}{fence}}) { my $node1_port = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node1}{fence}{$fence_name}{port}; my $node2_port = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node2}{fence}{$fence_name}{port}; my $dr1_port = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{dr1}{fence}{$fence_name}{port}; $fences .= $anvil->Template->get({file => "anvil.html", name => "run-manifest-fence", variables => { name => $fence_name, node1 => $node1_port ? $node1_port : "--", node2 => $node2_port ? $node2_port : "--", dr1 => $dr1_port ? $dr1_port : "--", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { networks => $networks }}); } my $upses = ""; foreach my $ups_name (sort {$a cmp $b} keys %{$anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node1}{ups}}) { my $node1_uses = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node1}{ups}{$ups_name}{used}; my $node2_uses = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{node2}{ups}{$ups_name}{used}; my $dr1_uses = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{dr1}{ups}{$ups_name}{used}; $upses .= $anvil->Template->get({file => "anvil.html", name => "run-manifest-ups", variables => { name => $ups_name, node1 => $node1_uses ? '#!string!unit_0001!#' : '#!string!unit_0002!#', node2 => $node2_uses ? '#!string!unit_0001!#' : '#!string!unit_0002!#', dr1 => $dr1_uses ? '#!string!unit_0001!#' : '#!string!unit_0002!#', }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { networks => $networks }}); } $anvil->data->{form}{back_link} = "?anvil=true&task=create"; $anvil->data->{form}{refresh_link} = "?anvil=true&task=manifests&run=true&manifest_uuid=".$anvil->data->{cgi}{manifest_uuid}{value}; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "run-manifest", variables => { debug => 2, title => $anvil->Words->string({key => "striker_0270", variables => { name => $anvil_name }}), description => $anvil->data->{cgi}{description}{value}, description_class => $anvil->data->{cgi}{description}{alert} ? "input_alert" : "", password => $anvil->data->{cgi}{password}{value}, password_class => $anvil->data->{cgi}{password}{alert} ? "input_alert" : "", fences => $fences, upses => $upses, networks => $networks, dns => $dns ? $dns : "8.8.8.8,8.8.4.4", ntp => $ntp ? $ntp : "--", mtu => $mtu ? $mtu : "1500", select_node1 => $select_node1, select_node2 => $select_node2, select_dr1 => $select_dr1, hostname_node1 => $node1_name, hostname_node2 => $node2_name, hostname_dr1 => $dr1_name, machine_ips => $machine_ips, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); return(0); } # This handles creating or editing an Install Manifest. sub handle_manifest { my ($anvil) = @_; $anvil->data->{cgi}{step}{value} = 1 if not defined $anvil->data->{cgi}{step}{value}; $anvil->data->{cgi}{prefix}{value} = "" if not defined $anvil->data->{cgi}{prefix}{value}; $anvil->data->{cgi}{prefix}{alert} = 0 if not defined $anvil->data->{cgi}{prefix}{alert}; $anvil->data->{cgi}{domain}{value} = "" if not defined $anvil->data->{cgi}{domain}{value}; $anvil->data->{cgi}{domain}{alert} = 0 if not defined $anvil->data->{cgi}{domain}{alert}; $anvil->data->{cgi}{sequence}{value} = "" if not defined $anvil->data->{cgi}{sequence}{value}; $anvil->data->{cgi}{sequence}{alert} = 0 if not defined $anvil->data->{cgi}{sequence}{alert}; $anvil->data->{cgi}{bcn_count}{value} = 0 if not defined $anvil->data->{cgi}{bcn_count}{value}; $anvil->data->{cgi}{bcn_count}{alert} = 0 if not defined $anvil->data->{cgi}{bcn_count}{alert}; $anvil->data->{cgi}{sn_count}{value} = 0 if not defined $anvil->data->{cgi}{sn_count}{value}; $anvil->data->{cgi}{sn_count}{alert} = 0 if not defined $anvil->data->{cgi}{sn_count}{alert}; $anvil->data->{cgi}{mn_count}{value} = 0 if not defined $anvil->data->{cgi}{mn_count}{value}; $anvil->data->{cgi}{mn_count}{alert} = 0 if not defined $anvil->data->{cgi}{mn_count}{alert}; $anvil->data->{cgi}{ifn_count}{value} = 0 if not defined $anvil->data->{cgi}{ifn_count}{value}; $anvil->data->{cgi}{ifn_count}{alert} = 0 if not defined $anvil->data->{cgi}{ifn_count}{alert}; $anvil->data->{cgi}{dns}{value} = "8.8.8.8,8.8.4.4" if not defined $anvil->data->{cgi}{dns}{value}; $anvil->data->{cgi}{dns}{alert} = 0 if not defined $anvil->data->{cgi}{dns}{alert}; $anvil->data->{cgi}{ntp}{value} = "" if not defined $anvil->data->{cgi}{ntp}{value}; $anvil->data->{cgi}{ntp}{alert} = 0 if not defined $anvil->data->{cgi}{ntp}{alert}; $anvil->data->{cgi}{mtu}{value} = 1500 if not defined $anvil->data->{cgi}{mtu}{value}; $anvil->data->{cgi}{mtu}{alert} = 0 if not defined $anvil->data->{cgi}{mtu}{alert}; $anvil->data->{cgi}{'delete'}{value} = "" if not defined $anvil->data->{cgi}{'delete'}{alert}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::step::value" => $anvil->data->{cgi}{step}{value}, "cgi::prefix::value" => $anvil->data->{cgi}{prefix}{value}, "cgi::domain::value" => $anvil->data->{cgi}{domain}{value}, "cgi::sequence::value" => $anvil->data->{cgi}{sequence}{value}, "cgi::bcn_count::value" => $anvil->data->{cgi}{bcn_count}{value}, "cgi::sn_count::value" => $anvil->data->{cgi}{sn_count}{value}, "cgi::mn_count::value" => $anvil->data->{cgi}{mn_count}{value}, "cgi::ifn_count::value" => $anvil->data->{cgi}{ifn_count}{value}, "cgi::dns::value" => $anvil->data->{cgi}{dns}{value}, "cgi::ntp::value" => $anvil->data->{cgi}{ntp}{value}, "cgi::mtu::value" => $anvil->data->{cgi}{mtu}{value}, "cgi::delete::value" => $anvil->data->{cgi}{'delete'}{value}, }}); # Are we deleting a manifest? if (($anvil->data->{cgi}{'delete'}{value}) && ($anvil->data->{cgi}{manifest_uuid}{value})) { # Verify that the UUID is valid. $anvil->Database->get_manifests({debug => 2, include_deleted => 1}); my $manifest_uuid = $anvil->data->{cgi}{manifest_uuid}{value}; my $manifest_name = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{manifest_name}; my $manifest_last_ran = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{manifest_last_ran}; my $manifest_xml = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{manifest_xml}; my $manifest_note = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{manifest_note}; if (not exists $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}) { # Doesn't exist. my $message = $anvil->Words->string({key => "warning_0043", variables => { uuid => $manifest_uuid }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } elsif ($anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{manifest_note} eq "DELETED") { # Already deleted. my $message = $anvil->Words->string({key => "warning_0044", variables => { name => $manifest_name, uuid => $manifest_uuid, }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } # Has the user confirmed? if ($anvil->data->{cgi}{confirm}{value}) { # Delete it my ($manifest_uuid) = $anvil->Database->insert_or_update_manifests({ debug => 2, manifest_uuid => $manifest_uuid, manifest_name => $manifest_name, manifest_last_ran => $manifest_last_ran, manifest_xml => $manifest_xml, manifest_note => "DELETED", }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { manifest_uuid => $manifest_uuid }}); if ($manifest_uuid) { # Deleted successfully my $message = $anvil->Words->string({key => "ok_0010", variables => { name => $manifest_name }}); $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::ok_message" => $anvil->data->{form}{ok_message} }}); } else { # Something went wrong. my $message = $anvil->Words->string({key => "warning_0045", variables => { name => $manifest_name, uuid => $manifest_uuid, }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } # Go back to the main page. process_create($anvil); return(0); } else { # Ask the user to confirm. my $say_manifest = $manifest_name; if ($manifest_note) { $say_manifest = $manifest_name." : ".$manifest_note; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_manifest => $say_manifest }}); $anvil->data->{form}{back_link} = "?anvil=true&task=create"; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "manifest-delete-confirm", variables => { name => $manifest_name, say_manifest => $say_manifest, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'form::body' => $anvil->data->{form}{body} }}); return(0); } } if ($anvil->data->{cgi}{step}{value} > 1) { my ($sane) = sanity_check_manifest_step1($anvil); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); if (not $sane) { # Go back to the first page $anvil->data->{cgi}{step}{value} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::step::value" => $anvil->data->{cgi}{step}{value} }}); } elsif ($anvil->data->{cgi}{step}{value} > 2) { my ($sane) = sanity_check_manifest_step2($anvil); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); if (not $sane) { # Go back to the second page $anvil->data->{cgi}{step}{value} = 2; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::step::value" => $anvil->data->{cgi}{step}{value} }}); } elsif ($anvil->data->{cgi}{step}{value} > 3) { my ($sane) = sanity_check_manifest_step3($anvil); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); if (not $sane) { # Go back to the third page $anvil->data->{cgi}{step}{value} = 3; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::step::value" => $anvil->data->{cgi}{step}{value} }}); } else { # Save the manifest! my ($manifest_uuid, $manifest_name) = $anvil->Striker->generate_manifest({debug => 2}); if ($manifest_uuid) { # Success! my $message = $anvil->Words->string({key => "ok_0009", variables => { name => $manifest_name }}); $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::ok_message" => $anvil->data->{form}{ok_message} }}); # Go back to the main page. process_create($anvil); return(0); } else { # Something went wrong, go back to the third page $anvil->data->{cgi}{step}{value} = 3; my $message = $anvil->Words->string({key => "warning_0041"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } } } } } # If we have an actual manifest_uuid, load it and preset values. if ((exists $anvil->data->{cgi}{manifest_uuid}) && ($anvil->data->{cgi}{manifest_uuid}{value} ne "new")) { my $manifest_uuid = $anvil->data->{cgi}{manifest_uuid}{value}; my $failed = $anvil->Striker->load_manifest({ debug => 2, manifest_uuid => $manifest_uuid, }); if (not $failed) { # Walk through the parsed manifest and set any undefined CGI. if ($anvil->data->{cgi}{step}{value} eq "1") { if ($anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{name} =~ /^(.*?)-anvil-(\d+)$/) { my $prefix = $1; my $sequence = $2; $sequence =~ s/^0+//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { prefix => $prefix, sequence => $sequence, }}); if (not $anvil->data->{cgi}{prefix}{value}) { $anvil->data->{cgi}{prefix}{value} = $prefix; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::prefix::value" => $anvil->data->{cgi}{prefix}{value} }}); } if (not $anvil->data->{cgi}{sequence}{value}) { $anvil->data->{cgi}{sequence}{value} = $sequence; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::sequence::value" => $anvil->data->{cgi}{sequence}{value} }}); } } if (not $anvil->data->{cgi}{domain}{value}) { $anvil->data->{cgi}{domain}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{domain}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::domain::value" => $anvil->data->{cgi}{domain}{value} }}); } if (not $anvil->data->{cgi}{ifn_count}{value}) { $anvil->data->{cgi}{ifn_count}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{ifn}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::ifn_count::value" => $anvil->data->{cgi}{ifn_count}{value} }}); } if (not $anvil->data->{cgi}{sn_count}{value}) { $anvil->data->{cgi}{sn_count}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{sn}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::sn_count::value" => $anvil->data->{cgi}{sn_count}{value} }}); } if (not $anvil->data->{cgi}{mn_count}{value}) { $anvil->data->{cgi}{mn_count}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{mn}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::mn_count::value" => $anvil->data->{cgi}{mn_count}{value} }}); } if (not $anvil->data->{cgi}{bcn_count}{value}) { $anvil->data->{cgi}{bcn_count}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{count}{bcn}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::bcn_count::value" => $anvil->data->{cgi}{bcn_count}{value} }}); } } elsif ($anvil->data->{cgi}{step}{value} eq "2") { if (not $anvil->data->{cgi}{dns}{value}) { $anvil->data->{cgi}{dns}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{dns}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::dns::value" => $anvil->data->{cgi}{dns}{value} }}); } if (not $anvil->data->{cgi}{ntp}{value}) { $anvil->data->{cgi}{ntp}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{ntp}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::ntp::value" => $anvil->data->{cgi}{ntp}{value} }}); } if (not $anvil->data->{cgi}{mtu}{value}) { $anvil->data->{cgi}{mtu}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{mtu}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::mtu::value" => $anvil->data->{cgi}{mtu}{value} }}); } foreach my $network ("bcn", "sn", "mn", "ifn") { my $count_key = $network."_count"; foreach my $i (1..$anvil->data->{cgi}{$count_key}{value}) { my $network_name = $network.$i; my $network_key = $network_name."_network"; my $subnet_key = $network_name."_subnet"; my $gateway_key = $network_name."_gateway"; if (not defined $anvil->data->{cgi}{$network_key}{value}) { $anvil->data->{cgi}{$network_key}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{network}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value} }}); } if (not defined $anvil->data->{cgi}{$subnet_key}{value}) { $anvil->data->{cgi}{$subnet_key}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{subnet}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value} }}); } if (not defined $anvil->data->{cgi}{$gateway_key}{value}) { $anvil->data->{cgi}{$gateway_key}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{networks}{name}{$network_name}{gateway}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${gateway_key}::value" => $anvil->data->{cgi}{$gateway_key}{value} }}); } } } } elsif ($anvil->data->{cgi}{step}{value} eq "3") { foreach my $machine ("node1", "node2", "dr1") { my $ipmi_ip_key = $machine."_ipmi_ip"; if (not defined $anvil->data->{cgi}{$ipmi_ip_key}{value}) { $anvil->data->{cgi}{$ipmi_ip_key}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$machine}{ipmi_ip}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${ipmi_ip_key}::value" => $anvil->data->{cgi}{$ipmi_ip_key}{value} }}); } foreach my $network ("bcn", "sn", "mn", "ifn") { my $count_key = $network."_count"; foreach my $i (1..$anvil->data->{cgi}{$count_key}{value}) { my $network_name = $network.$i; my $ip_key = $machine."_".$network_name."_ip"; if (not defined $anvil->data->{cgi}{$ip_key}{value}) { $anvil->data->{cgi}{$ip_key}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$machine}{network}{$network_name}{ip}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${ip_key}::value" => $anvil->data->{cgi}{$ip_key}{value} }}); } } } # UPSes foreach my $ups_name (sort {$a cmp $b} keys %{$anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$machine}{ups}}) { my $checked = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$machine}{ups}{$ups_name}{used} ? "checked" : ""; my $ups_key = $machine."_ups_".$ups_name; if (not defined $anvil->data->{cgi}{$ups_key}{value}) { $anvil->data->{cgi}{$ups_key}{value} = $checked; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${ups_key}::value" => $anvil->data->{cgi}{$ups_key}{value} }}); } } # Fences foreach my $fence_name (sort {$a cmp $b} keys %{$anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$machine}{fence}}) { my $fence_key = $machine."_fence_".$fence_name; if (not defined $anvil->data->{cgi}{$fence_key}{value}) { $anvil->data->{cgi}{$fence_key}{value} = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$machine}{fence}{$fence_name}{port}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${fence_key}::value" => $anvil->data->{cgi}{$fence_key}{value} }}); } } } } } } # Step 1 is to ask for the sequence number, prefix, and the number of IFNs (and later, BCNs) if ($anvil->data->{cgi}{step}{value} eq "1") { if ($anvil->data->{cgi}{manifest_uuid}{value} eq "new") { # Pre-load values if (not $anvil->data->{cgi}{prefix}{value}) { $anvil->data->{cgi}{prefix}{value} = $anvil->Get->short_host_name() =~ /-/ ? $anvil->Get->short_host_name() : "xx"; $anvil->data->{cgi}{prefix}{value} =~ s/-.*$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::prefix::value" => $anvil->data->{cgi}{prefix}{value} }}); } if (not $anvil->data->{cgi}{domain}{value}) { $anvil->data->{cgi}{domain}{value} = $anvil->Get->host_name() =~ /\./ ? $anvil->Get->host_name() : "example.com"; $anvil->data->{cgi}{domain}{value} =~ s/^.*?\.//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::domain::value" => $anvil->data->{cgi}{domain}{value} }}); } if (not $anvil->data->{cgi}{sequence}{value}) { # Default to 1 $anvil->data->{cgi}{sequence}{value} = 1; # Count the number of existing manifests! systems with the default prefix to guess the next sequence. my $query = "SELECT manifest_name FROM manifests WHERE manifest_name LIKE ".$anvil->Database->quote($anvil->data->{cgi}{prefix}{value}."-%")." ORDER BY manifest_name ASC;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); if ($count) { # Yup, key has changed. foreach my $row (@{$results}) { my $manifest_name = $row->[0]; my $this_sequence = ($manifest_name =~ /-(\d+)$/)[0]; $this_sequence =~ s/^0//g; $this_sequence = 0 if not $this_sequence; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { manifest_name => $manifest_name, this_sequence => $this_sequence, }}); if ($this_sequence >= $anvil->data->{cgi}{sequence}{value}) { $anvil->data->{cgi}{sequence}{value} = $this_sequence + 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::sequence::value" => $anvil->data->{cgi}{sequence}{value} }}); } } } } if (not $anvil->data->{cgi}{ifn_count}{value}) { $anvil->data->{cgi}{ifn_count}{value} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::ifn_count::value" => $anvil->data->{cgi}{ifn_count}{value} }}); } # NOTE: The user can't choose the BCN or SN yet, but that might change so we treat it as configurable now. if (not $anvil->data->{cgi}{sn_count}{value}) { $anvil->data->{cgi}{sn_count}{value} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::sn_count::value" => $anvil->data->{cgi}{sn_count}{value} }}); } if (not $anvil->data->{cgi}{mn_count}{value}) { $anvil->data->{cgi}{mn_count}{value} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::mn_count::value" => $anvil->data->{cgi}{mn_count}{value} }}); } if (not $anvil->data->{cgi}{bcn_count}{value}) { $anvil->data->{cgi}{bcn_count}{value} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::bcn_count::value" => $anvil->data->{cgi}{bcn_count}{value} }}); } } # Step 1 menu. $anvil->data->{form}{back_link} = "?anvil=true&task=create"; $anvil->data->{form}{refresh_link} = "?anvil=true&task=manifests&manifest_uuid=".$anvil->data->{cgi}{manifest_uuid}{value}."&step=".$anvil->data->{cgi}{step}{value}; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "manifest-step1", variables => { title => $anvil->Words->string({key => "striker_0226", variables => { number => 1 }}), prefix => $anvil->data->{cgi}{prefix}{value}, prefix_class => $anvil->data->{cgi}{prefix}{alert} ? "input_alert" : "", domain => $anvil->data->{cgi}{domain}{value}, domain_class => $anvil->data->{cgi}{domain}{alert} ? "input_alert" : "", sequence => $anvil->data->{cgi}{sequence}{value}, sequence_class => $anvil->data->{cgi}{sequence}{alert} ? "input_alert" : "", ifn_count => $anvil->data->{cgi}{ifn_count}{value}, ifn_count_class => $anvil->data->{cgi}{ifn_count}{alert} ? "input_alert" : "", sn_count => $anvil->data->{cgi}{sn_count}{value}, sn_count_class => $anvil->data->{cgi}{sn_count}{alert} ? "input_alert" : "", mn_count => $anvil->data->{cgi}{mn_count}{value}, mn_count_class => $anvil->data->{cgi}{mn_count}{alert} ? "input_alert" : "", bcn_count => $anvil->data->{cgi}{bcn_count}{value}, bcn_count_class => $anvil->data->{cgi}{bcn_count}{alert} ? "input_alert" : "", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); } elsif ($anvil->data->{cgi}{step}{value} eq "2") { ### Ask for the network ranges. # Eventually, we'll support user-set BCN count. So for now, we treat as such even though it # will always be '1' for now. my $network_form = ""; foreach my $i (1..$anvil->data->{cgi}{bcn_count}{value}) { my $say_bcn = $anvil->Words->string({key => "striker_0018", variables => { number => $i }}); my $network_key = "bcn".$i."_network"; my $subnet_key = "bcn".$i."_subnet"; my $gateway_key = "bcn".$i."_gateway"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_bcn => $say_bcn, network_key => $network_key, subnet_key => $subnet_key, gateway_key => $gateway_key, }}); $anvil->data->{cgi}{$network_key}{value} = "10.20".$i.".0.0" if not defined $anvil->data->{cgi}{$network_key}{value}; $anvil->data->{cgi}{$network_key}{alert} = 0 if not defined $anvil->data->{cgi}{$network_key}{alert}; $anvil->data->{cgi}{$subnet_key}{value} = "255.255.0.0" if not defined $anvil->data->{cgi}{$subnet_key}{value}; $anvil->data->{cgi}{$subnet_key}{alert} = 0 if not defined $anvil->data->{cgi}{$subnet_key}{alert}; $anvil->data->{cgi}{$gateway_key}{value} = "" if not defined $anvil->data->{cgi}{$gateway_key}{value}; $anvil->data->{cgi}{$gateway_key}{alert} = 0 if not defined $anvil->data->{cgi}{$gateway_key}{alert}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, "cgi::${network_key}::alert" => $anvil->data->{cgi}{$network_key}{alert}, "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value}, "cgi::${subnet_key}::alert" => $anvil->data->{cgi}{$subnet_key}{alert}, "cgi::${gateway_key}::value" => $anvil->data->{cgi}{$gateway_key}{value}, "cgi::${gateway_key}::alert" => $anvil->data->{cgi}{$gateway_key}{alert}, }}); my $select = $anvil->Template->select_form({ name => $subnet_key, options => "subnet", blank => 0, 'sort' => 0, selected => $anvil->data->{cgi}{$subnet_key}{value}, class => $anvil->data->{cgi}{$subnet_key}{alert} ? "input_alert" : "input_clear", style => "width: 15em;", }); $network_form .= $anvil->Template->get({file => "anvil.html", name => "manifest-step2-network-entry", variables => { network => $say_bcn, network_name => $network_key, network_class => $anvil->data->{cgi}{$network_key}{alert} ? "input_alert" : "", network_value => $anvil->data->{cgi}{$network_key}{value}, subnet => $select, }}); } # There's only ever 1 SN. Just in case we change our mind later, we'll set it up as if it's # variable. foreach my $i (1..$anvil->data->{cgi}{sn_count}{value}) { my $say_sn = $anvil->Words->string({key => "striker_0020", variables => { number => '1' }}); my $network_key = "sn".$i."_network"; my $subnet_key = "sn".$i."_subnet"; my $gateway_key = "sn".$i."_gateway"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_sn => $say_sn, network_key => $network_key, subnet_key => $subnet_key, gateway_key => $gateway_key, }}); $anvil->data->{cgi}{$network_key}{value} = "10.10".$i.".0.0" if not defined $anvil->data->{cgi}{$network_key}{value}; $anvil->data->{cgi}{$network_key}{alert} = 0 if not defined $anvil->data->{cgi}{$network_key}{alert}; $anvil->data->{cgi}{$subnet_key}{value} = "255.255.0.0" if not defined $anvil->data->{cgi}{$subnet_key}{value}; $anvil->data->{cgi}{$subnet_key}{alert} = 0 if not defined $anvil->data->{cgi}{$subnet_key}{alert}; $anvil->data->{cgi}{$gateway_key}{value} = "" if not defined $anvil->data->{cgi}{$gateway_key}{value}; $anvil->data->{cgi}{$gateway_key}{alert} = 0 if not defined $anvil->data->{cgi}{$gateway_key}{alert}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, "cgi::${network_key}::alert" => $anvil->data->{cgi}{$network_key}{alert}, "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value}, "cgi::${subnet_key}::alert" => $anvil->data->{cgi}{$subnet_key}{alert}, "cgi::${gateway_key}::value" => $anvil->data->{cgi}{$gateway_key}{value}, "cgi::${gateway_key}::alert" => $anvil->data->{cgi}{$gateway_key}{alert}, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::sn1_network::value" => $anvil->data->{cgi}{sn1_network}{value} }}); $network_form .= $anvil->Template->get({file => "anvil.html", name => "manifest-step2-network-entry", variables => { network => $say_sn, network_name => $network_key, network_class => $anvil->data->{cgi}{$network_key}{alert} ? "input_alert" : "", network_value => $anvil->data->{cgi}{$network_key}{value}, subnet => '255.255.0.0 ', }}); } # There's only ever 1 MN. Just in case we change our mind later, we'll set it up as if it's # variable. if ($anvil->data->{cgi}{mn_count}{value}) { foreach my $i (1..$anvil->data->{cgi}{mn_count}{value}) { my $say_mn = $anvil->Words->string({key => "striker_0299", variables => { number => '1' }}); my $network_key = "mn".$i."_network"; my $subnet_key = "mn".$i."_subnet"; my $gateway_key = "mn".$i."_gateway"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_mn => $say_mn, network_key => $network_key, subnet_key => $subnet_key, gateway_key => $gateway_key, }}); $anvil->data->{cgi}{$network_key}{value} = "10.199.0.0" if not defined $anvil->data->{cgi}{$network_key}{value}; $anvil->data->{cgi}{$network_key}{alert} = 0 if not defined $anvil->data->{cgi}{$network_key}{alert}; $anvil->data->{cgi}{$subnet_key}{value} = "255.255.0.0" if not defined $anvil->data->{cgi}{$subnet_key}{value}; $anvil->data->{cgi}{$subnet_key}{alert} = 0 if not defined $anvil->data->{cgi}{$subnet_key}{alert}; $anvil->data->{cgi}{$gateway_key}{value} = "" if not defined $anvil->data->{cgi}{$gateway_key}{value}; $anvil->data->{cgi}{$gateway_key}{alert} = 0 if not defined $anvil->data->{cgi}{$gateway_key}{alert}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, "cgi::${network_key}::alert" => $anvil->data->{cgi}{$network_key}{alert}, "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value}, "cgi::${subnet_key}::alert" => $anvil->data->{cgi}{$subnet_key}{alert}, "cgi::${gateway_key}::value" => $anvil->data->{cgi}{$gateway_key}{value}, "cgi::${gateway_key}::alert" => $anvil->data->{cgi}{$gateway_key}{alert}, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::mn1_network::value" => $anvil->data->{cgi}{mn1_network}{value} }}); $network_form .= $anvil->Template->get({file => "anvil.html", name => "manifest-step2-network-entry", variables => { network => $say_mn, network_name => $network_key, network_class => $anvil->data->{cgi}{$network_key}{alert} ? "input_alert" : "", network_value => $anvil->data->{cgi}{$network_key}{value}, subnet => '255.255.0.0 ', }}); } } # Now IFNs foreach my $i (1..$anvil->data->{cgi}{ifn_count}{value}) { my $say_ifn = $anvil->Words->string({key => "striker_0022", variables => { number => $i }}); my $network_key = "ifn".$i."_network"; my $subnet_key = "ifn".$i."_subnet"; my $gateway_key = "ifn".$i."_gateway"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_bcn => $say_ifn, network_key => $network_key, subnet_key => $subnet_key, gateway_key => $gateway_key, }}); $anvil->data->{cgi}{$network_key}{value} = "" if not defined $anvil->data->{cgi}{$network_key}{value}; $anvil->data->{cgi}{$network_key}{alert} = 0 if not defined $anvil->data->{cgi}{$network_key}{alert}; $anvil->data->{cgi}{$subnet_key}{value} = "255.255.0.0" if not defined $anvil->data->{cgi}{$subnet_key}{value}; $anvil->data->{cgi}{$subnet_key}{alert} = 0 if not defined $anvil->data->{cgi}{$subnet_key}{alert}; $anvil->data->{cgi}{$gateway_key}{value} = "" if not defined $anvil->data->{cgi}{$gateway_key}{value}; $anvil->data->{cgi}{$gateway_key}{alert} = 0 if not defined $anvil->data->{cgi}{$gateway_key}{alert}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, "cgi::${network_key}::alert" => $anvil->data->{cgi}{$network_key}{alert}, "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value}, "cgi::${subnet_key}::alert" => $anvil->data->{cgi}{$subnet_key}{alert}, "cgi::${gateway_key}::value" => $anvil->data->{cgi}{$gateway_key}{value}, "cgi::${gateway_key}::alert" => $anvil->data->{cgi}{$gateway_key}{alert}, }}); my $select = $anvil->Template->select_form({ name => $subnet_key, options => "subnet", blank => 0, 'sort' => 0, selected => $anvil->data->{cgi}{$subnet_key}{value}, class => $anvil->data->{cgi}{$subnet_key}{alert} ? "input_alert" : "input_clear", style => "width: 15em;", }); $network_form .= $anvil->Template->get({file => "anvil.html", name => "manifest-step2-network-entry-gateway", variables => { network => $say_ifn, network_name => $network_key, network_class => $anvil->data->{cgi}{$network_key}{alert} ? "input_alert" : "", network_value => $anvil->data->{cgi}{$network_key}{value}, subnet => $select, gateway_name => $gateway_key, gateway_class => $anvil->data->{cgi}{$gateway_key}{alert} ? "input_alert" : "", gateway_value => $anvil->data->{cgi}{$gateway_key}{value}, }}); } my $back_link = $anvil->data->{sys}{cgi_string}; $back_link =~ s/step=2/step=1/; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { back_link => $back_link}}); $anvil->data->{form}{back_link} = $back_link; $anvil->data->{form}{refresh_link} = $anvil->data->{sys}{cgi_string}; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "manifest-step2", variables => { title => $anvil->Words->string({key => "striker_0226", variables => { number => 2 }}), networks => $network_form, dns => $anvil->data->{cgi}{dns}{value}, dns_class => $anvil->data->{cgi}{dns}{alert} ? "input_alert" : "", ntp => $anvil->data->{cgi}{ntp}{value}, ntp_class => $anvil->data->{cgi}{ntp}{alert} ? "input_alert" : "", mtu => $anvil->data->{cgi}{mtu}{value}, mtu_class => $anvil->data->{cgi}{mtu}{alert} ? "input_alert" : "", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); } elsif ($anvil->data->{cgi}{step}{value} eq "3") { # Build and show the main manifest page! $anvil->data->{cgi}{node1_ipmi_ip}{value} = "" if not defined $anvil->data->{cgi}{node1_ipmi_ip}{value}; $anvil->data->{cgi}{node1_ipmi_ip}{alert} = 0 if not defined $anvil->data->{cgi}{node1_ipmi_ip}{alert}; $anvil->data->{cgi}{node2_ipmi_ip}{value} = "" if not defined $anvil->data->{cgi}{node2_ipmi_ip}{value}; $anvil->data->{cgi}{node2_ipmi_ip}{alert} = 0 if not defined $anvil->data->{cgi}{node2_ipmi_ip}{alert}; $anvil->data->{cgi}{dr1_ipmi_ip}{value} = "" if not defined $anvil->data->{cgi}{dr1_ipmi_ip}{value}; $anvil->data->{cgi}{dr1_ipmi_ip}{alert} = 0 if not defined $anvil->data->{cgi}{dr1_ipmi_ip}{alert}; my $sequence = $anvil->data->{cgi}{sequence}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sequence => $sequence }}); my $network_form = ""; my $network_note = ""; foreach my $network ("bcn", "sn", "mn", "ifn") { if ($network eq "sn") { # We've finished BCN, inject the IPMI. $network_form .= $anvil->Template->get({file => "anvil.html", name => "manifest-step3-ipmi-entry", variables => { node1_value => $anvil->data->{cgi}{node1_ipmi_ip}{value}, node1_class => $anvil->data->{cgi}{node1_ipmi_ip}{alert} ? "input_alert" : "", node2_value => $anvil->data->{cgi}{node2_ipmi_ip}{value}, node2_class => $anvil->data->{cgi}{node2_ipmi_ip}{alert} ? "input_alert" : "", dr1_value => $anvil->data->{cgi}{dr1_ipmi_ip}{value}, dr1_class => $anvil->data->{cgi}{dr1_ipmi_ip}{alert} ? "input_alert" : "", }}); } my $count_key = $network."_count"; foreach my $i (1..$anvil->data->{cgi}{$count_key}{value}) { my $say_network_code = "striker_0018"; if ($network eq "sn") { $say_network_code = "striker_0020"; } elsif ($network eq "ifn") { $say_network_code = "striker_0022"; } elsif ($network eq "ifn") { $say_network_code = "striker_0299"; } my $say_network = $anvil->Words->string({key => $say_network_code, variables => { number => $i }}); my $network_key = $network.$i."_network"; my $subnet_key = $network.$i."_subnet"; my $gateway_key = $network.$i."_gateway"; my $node1_ip_key = "node1_".$network.$i."_ip"; my $node2_ip_key = "node2_".$network.$i."_ip"; my $dr1_ip_key = "dr1_".$network.$i."_ip"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_bcn => $say_network, network_key => $network_key, subnet_key => $subnet_key, gateway_key => $gateway_key, node1_ip_key => $node1_ip_key, node2_ip_key => $node2_ip_key, dr1_ip_key => $dr1_ip_key, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, "cgi::${network_key}::alert" => $anvil->data->{cgi}{$network_key}{alert}, "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value}, "cgi::${subnet_key}::alert" => $anvil->data->{cgi}{$subnet_key}{alert}, "cgi::${gateway_key}::value" => $anvil->data->{cgi}{$gateway_key}{value}, "cgi::${gateway_key}::alert" => $anvil->data->{cgi}{$gateway_key}{alert}, }}); # The note also shows the network range. my $message = $anvil->Words->string({key => "striker_0267", variables => { network => $anvil->data->{cgi}{$network_key}{value}."/".$anvil->data->{cgi}{$subnet_key}{value} }}); $network_note .= $anvil->Template->get({file => "anvil.html", name => "manifest-step3-network-note-entry", variables => { name => $say_network, message => $message, }}); # On the BCN and SN, we can confidently take the first two octets from # 'network' and add our guesses to the last two octets. We only guess the IFN # if it's /16 or a larger subnet. if ($anvil->data->{cgi}{$network_key}{value} =~ /^(\d{1,3}\.\d{1,3})\.0\.0/) { my $first_two_octets = $1; my $ip_third_octet = 8 + (2 * $sequence); # Thanks to Leigh Nunan (@leighnunan) for this elegant sequence formula my $host_ip = $first_two_octets.".".$ip_third_octet; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { first_two_octets => $first_two_octets, ip_third_octet => $ip_third_octet, host_ip => $host_ip, }}); $anvil->data->{cgi}{$node1_ip_key}{value} = $host_ip.".1" if not defined $anvil->data->{cgi}{$node1_ip_key}{value}; $anvil->data->{cgi}{$node2_ip_key}{value} = $host_ip.".2" if not defined $anvil->data->{cgi}{$node2_ip_key}{value}; $anvil->data->{cgi}{$dr1_ip_key}{value} = $host_ip.".3" if not defined $anvil->data->{cgi}{$dr1_ip_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${node1_ip_key}::value" => $anvil->data->{cgi}{$node1_ip_key}{value}, "cgi::${node2_ip_key}::value" => $anvil->data->{cgi}{$node2_ip_key}{value}, "cgi::${dr1_ip_key}::value" => $anvil->data->{cgi}{$dr1_ip_key}{value}, }}); # If this is the BCN and $i = 1, build the IPMI IP guess. if (($network eq "bcn") && ($i == 1)) { my $ipmi_third_octet = 8 + (2 * $sequence) + 1; my $ipmi_ip_guess = $first_two_octets.".".$ipmi_third_octet; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ipmi_third_octet => $ipmi_third_octet, ipmi_ip_guess => $ipmi_ip_guess, }}); $anvil->data->{cgi}{node1_ipmi_ip}{value} = $ipmi_ip_guess.".1" if not $anvil->data->{cgi}{node1_ipmi_ip}{value}; $anvil->data->{cgi}{node2_ipmi_ip}{value} = $ipmi_ip_guess.".2" if not $anvil->data->{cgi}{node2_ipmi_ip}{value}; $anvil->data->{cgi}{dr1_ipmi_ip}{value} = $ipmi_ip_guess.".3" if not $anvil->data->{cgi}{dr1_ipmi_ip}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::node1_ipmi_ip::value" => $anvil->data->{cgi}{node1_ipmi_ip}{value}, "cgi::node2_ipmi_ip::value" => $anvil->data->{cgi}{node2_ipmi_ip}{value}, "cgi::dr1_ipmi_ip::value" => $anvil->data->{cgi}{dr1_ipmi_ip}{value}, }}); } } # It should never happen, but in case the regex missed, set the guessed IPs to empty strings. $anvil->data->{cgi}{$node1_ip_key}{value} = "" if not $anvil->data->{cgi}{$node1_ip_key}{value}; $anvil->data->{cgi}{$node2_ip_key}{value} = "" if not $anvil->data->{cgi}{$node2_ip_key}{value}; $anvil->data->{cgi}{$dr1_ip_key}{value} = "" if not $anvil->data->{cgi}{$dr1_ip_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${node1_ip_key}::value" => $anvil->data->{cgi}{$node1_ip_key}{value}, "cgi::${node2_ip_key}::value" => $anvil->data->{cgi}{$node2_ip_key}{value}, "cgi::${dr1_ip_key}::value" => $anvil->data->{cgi}{$dr1_ip_key}{value}, }}); $network_form .= $anvil->Template->get({file => "anvil.html", name => "manifest-step3-network-entry", variables => { network => $say_network, network_name => $network_key, network_value => $anvil->data->{cgi}{$network_key}{value}, subnet_name => $subnet_key, subnet_value => $anvil->data->{cgi}{$subnet_key}{value}, gateway_name => $gateway_key, gateway_value => $anvil->data->{cgi}{$gateway_key}{value}, node1_ip_name => $node1_ip_key, node1_ip_value => $anvil->data->{cgi}{$node1_ip_key}{value}, node1_ip_class => $anvil->data->{cgi}{$node1_ip_key}{alert} ? "input_alert" : "", node2_ip_name => $node2_ip_key, node2_ip_value => $anvil->data->{cgi}{$node2_ip_key}{value}, node2_ip_class => $anvil->data->{cgi}{$node2_ip_key}{alert} ? "input_alert" : "", dr1_ip_name => $dr1_ip_key, dr1_ip_value => $anvil->data->{cgi}{$dr1_ip_key}{value}, dr1_ip_class => $anvil->data->{cgi}{$dr1_ip_key}{alert} ? "input_alert" : "", }}); } } # List any known fence devices. my $fence_form = ""; $anvil->Database->get_fences({}); foreach my $fence_name (sort {$a cmp $b} keys %{$anvil->data->{fences}{fence_name}}) { ### NOTE: For now, we don't care about DR fencing. As such, the code to track it is ### commented out (in case we decide to track it someday down the road). my $fence_uuid = $anvil->data->{fences}{fence_name}{$fence_name}{fence_uuid}; my $node1_fence_key = "node1_fence_".$fence_name; my $node2_fence_key = "node2_fence_".$fence_name; #my $dr1_fence_key = "dr1_fence_".$fence_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { fence_name => $fence_name, fence_uuid => $fence_uuid, node1_fence_key => $node1_fence_key, node2_fence_key => $node2_fence_key, # dr1_fence_key => $dr1_fence_key, }}); $anvil->data->{cgi}{$node1_fence_key}{value} = "" if not defined $anvil->data->{cgi}{$node1_fence_key}{value}; $anvil->data->{cgi}{$node1_fence_key}{alert} = 0 if not defined $anvil->data->{cgi}{$node1_fence_key}{alert}; $anvil->data->{cgi}{$node2_fence_key}{value} = "" if not defined $anvil->data->{cgi}{$node2_fence_key}{value}; $anvil->data->{cgi}{$node2_fence_key}{alert} = 0 if not defined $anvil->data->{cgi}{$node2_fence_key}{alert}; #$anvil->data->{cgi}{$dr1_fence_key}{value} = "" if not defined $anvil->data->{cgi}{$dr1_fence_key}{value}; #$anvil->data->{cgi}{$dr1_fence_key}{alert} = 0 if not defined $anvil->data->{cgi}{$dr1_fence_key}{alert}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${node1_fence_key}::value" => $anvil->data->{cgi}{$node1_fence_key}{value}, "cgi::${node1_fence_key}::alert" => $anvil->data->{cgi}{$node1_fence_key}{alert}, "cgi::${node2_fence_key}::value" => $anvil->data->{cgi}{$node2_fence_key}{value}, "cgi::${node2_fence_key}::alert" => $anvil->data->{cgi}{$node2_fence_key}{alert}, # "cgi::${dr1_fence_key}::value" => $anvil->data->{cgi}{$dr1_fence_key}{value}, # "cgi::${dr1_fence_key}::alert" => $anvil->data->{cgi}{$dr1_fence_key}{alert}, }}); $fence_form .= $anvil->Template->get({file => "anvil.html", name => "manifest-step3-fence-entry", variables => { name => $fence_name, fence_uuid_name => "fence_".$fence_name, fence_uuid_value => $fence_uuid, node1_fence_name => $node1_fence_key, node1_fence_value => $anvil->data->{cgi}{$node1_fence_key}{value}, node1_fence_class => $anvil->data->{cgi}{$node1_fence_key}{alert} ? "input_alert" : "", node2_fence_name => $node2_fence_key, node2_fence_value => $anvil->data->{cgi}{$node2_fence_key}{value}, node2_fence_class => $anvil->data->{cgi}{$node2_fence_key}{alert} ? "input_alert" : "", # dr1_fence_name => $dr1_fence_key, # dr1_fence_value => $anvil->data->{cgi}{$dr1_fence_key}{value}, # dr1_fence_class => $anvil->data->{cgi}{$dr1_fence_key}{alert} ? "input_alert" : "", }}); } my $ups_form = ""; $anvil->Database->get_upses({}); my $ups_count = keys %{$anvil->data->{upses}{ups_name}}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_count => $ups_count }}); if (not $ups_count) { # No UPSes, add a blank entry. $ups_form .= $anvil->Template->get({file => "anvil.html", name => "manifest-step3-ups-null-entry"}); } foreach my $ups_name (sort {$a cmp $b} keys %{$anvil->data->{upses}{ups_name}}) { ### NOTE: For now, we don't care about DR UPSes. As such, the code to track it is ### commented out (in case we decide to track it someday down the road). my $ups_uuid = $anvil->data->{upses}{ups_name}{$ups_name}{ups_uuid}; my $node1_ups_key = "node1_ups_".$ups_name; my $node2_ups_key = "node2_ups_".$ups_name; #my $dr1_ups_key = "dr1_ups_".$ups_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_name => $ups_name, ups_uuid => $ups_uuid, node1_ups_key => $node1_ups_key, node2_ups_key => $node2_ups_key, # dr1_ups_key => $dr1_ups_key, }}); # Checkboxes that are not checked do not return anything at all. To deal with this, # if we're reloading, we use 'undefined' as "not checked". Otherwise, "undefined" is # "checked" (default). if ((exists $anvil->data->{cgi}{reload}) && ($anvil->data->{cgi}{reload}{value})) { $anvil->data->{cgi}{$node1_ups_key}{value} = "" if not defined $anvil->data->{cgi}{$node1_ups_key}{value}; $anvil->data->{cgi}{$node2_ups_key}{value} = "" if not defined $anvil->data->{cgi}{$node2_ups_key}{value}; #$anvil->data->{cgi}{$dr1_ups_key}{value} = "" if not defined $anvil->data->{cgi}{$dr1_ups_key}{value}; } else { $anvil->data->{cgi}{$node1_ups_key}{value} = "checked" if not defined $anvil->data->{cgi}{$node1_ups_key}{value}; $anvil->data->{cgi}{$node2_ups_key}{value} = "checked" if not defined $anvil->data->{cgi}{$node2_ups_key}{value}; #$anvil->data->{cgi}{$dr1_ups_key}{value} = "" if not defined $anvil->data->{cgi}{$dr1_ups_key}{value}; } $anvil->data->{cgi}{$node1_ups_key}{value} = "checked" if $anvil->data->{cgi}{$node1_ups_key}{value} eq "on"; $anvil->data->{cgi}{$node2_ups_key}{value} = "checked" if $anvil->data->{cgi}{$node2_ups_key}{value} eq "on"; #$anvil->data->{cgi}{$dr1_ups_key}{value} = "checked" if $anvil->data->{cgi}{$dr1_ups_key}{value} eq "on"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${node1_ups_key}::value" => $anvil->data->{cgi}{$node1_ups_key}{value}, "cgi::${node2_ups_key}::value" => $anvil->data->{cgi}{$node2_ups_key}{value}, # "cgi::${dr1_ups_key}::value" => $anvil->data->{cgi}{$dr1_ups_key}{value}, }}); $ups_form .= $anvil->Template->get({file => "anvil.html", name => "manifest-step3-ups-entry", variables => { name => $ups_name, ups_uuid_name => "ups_".$ups_name, ups_uuid_value => $ups_uuid, node1_ups_name => $node1_ups_key, node1_ups_checked => $anvil->data->{cgi}{$node1_ups_key}{value}, node2_ups_name => $node2_ups_key, node2_ups_checked => $anvil->data->{cgi}{$node2_ups_key}{value}, # dr1_ups_name => $dr1_ups_key, # dr1_ups_checked => $anvil->data->{cgi}{$dr1_ups_key}{value}, }}); } my $back_link = $anvil->data->{sys}{cgi_string}; $back_link =~ s/step=3/step=2/; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { back_link => $back_link}}); $anvil->data->{form}{back_link} = $back_link; $anvil->data->{form}{refresh_link} = $anvil->data->{sys}{cgi_string}; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "manifest-step3", variables => { title => $anvil->Words->string({key => "striker_0226", variables => { number => 3 }}), networks => $network_form, fences => $fence_form, upses => $ups_form, network_note => $network_note, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); } return(0); } sub sanity_check_manifest_step3 { my ($anvil) = @_; my $sane = 1; # Check the IPMI values. They're allowed to be blank. If they're set, they need to be in a BCN or # IFN network. foreach my $machine ("node1", "node2", "dr1") { my $key = $machine."_ipmi_ip"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { machine => $machine, "cgi::${key}::value" => $anvil->data->{cgi}{$key}{value}, }}); if ($anvil->data->{cgi}{$key}{value}) { # Is it a valid IPv4 address? if (not $anvil->Validate->ipv4({ip => $anvil->data->{cgi}{$key}{value}})) { # Bad subnet my $say_network = "#!string!striker_0255!#"; if ($machine eq "node2") { $say_network = "#!string!striker_0256!#"; } elsif ($machine eq "dr1") { $say_network = "#!string!striker_0257!#"; } my $message = $anvil->Words->string({key => "error_0125", variables => { network => $say_network }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{$key}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::${key}::alert" => $anvil->data->{cgi}{$key}{alert}, "cgi::${key}::value" => $anvil->data->{cgi}{$key}{value}, }}); } else { # It's a valid IP. Does it match any BCN or IFN network? my $match_found = 0; foreach my $network ("bcn", "sn", "mn", "ifn") { my $count_key = $network."_count"; foreach my $i (1..$anvil->data->{cgi}{$count_key}{value}) { next if $match_found; my $network_key = $network.$i."_network"; my $subnet_key = $network.$i."_subnet"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${key}::value" => $anvil->data->{cgi}{$key}{value}, "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value}, }}); $match_found = $anvil->Network->is_ip_in_network({ debug => 2, ip => $anvil->data->{cgi}{$key}{value}, network => $anvil->data->{cgi}{$network_key}{value}, subnet_mask => $anvil->data->{cgi}{$subnet_key}{value}, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { match_found => $match_found }}); } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { match_found => $match_found }}); if (not $match_found) { # IP is valid, but not in any of the networks. my $message = $anvil->Words->string({key => "error_0124", variables => { ip => $anvil->data->{cgi}{$key}{value} }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{$key}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::${key}::alert" => $anvil->data->{cgi}{$key}{alert}, "cgi::${key}::value" => $anvil->data->{cgi}{$key}{value}, }}); } } } # Now check that the IPs are sane. foreach my $network ("bcn", "sn", "mn", "ifn") { my $count_key = $network."_count"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network => $network, count_key => $count_key, "cgi::${count_key}::value" => $anvil->data->{cgi}{$count_key}{value}, }}); foreach my $i (1..$anvil->data->{cgi}{$count_key}{value}) { my $say_network_code = "striker_0018"; if ($network eq "sn") { $say_network_code = "striker_0020"; } elsif ($network eq "ifn") { $say_network_code = "striker_0022"; } elsif ($network eq "mn") { $say_network_code = "striker_0299"; } my $say_network = $anvil->Words->string({key => $say_network_code, variables => { number => $i }}); my $network_key = $network.$i."_network"; my $subnet_key = $network.$i."_subnet"; my $machine_ip_key = $machine."_".$network.$i."_ip"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_network => $say_network, network_key => $network_key, subnet_key => $subnet_key, machine_ip_key => $machine_ip_key, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, "cgi::${network_key}::alert" => $anvil->data->{cgi}{$network_key}{alert}, "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value}, "cgi::${subnet_key}::alert" => $anvil->data->{cgi}{$subnet_key}{alert}, "cgi::${machine_ip_key}::value" => $anvil->data->{cgi}{$machine_ip_key}{value}, "cgi::${machine_ip_key}::alert" => $anvil->data->{cgi}{$machine_ip_key}{alert}, }}); # Is the IP valid? if (not $anvil->Validate->ipv4({ip => $anvil->data->{cgi}{$machine_ip_key}{value}, debug => 2})) { # Bad subnet. If this is DR IFN 1, and the value was empty, ignore it # as there simply is no DR on this cluster. if (($machine eq "dr1") && ($anvil->data->{cgi}{$machine_ip_key}{value} eq "")) { next; } my $say_network = "#!string!striker_0255!#"; if ($machine eq "node2") { $say_network = "#!string!striker_0256!#"; } elsif ($machine eq "dr1") { $say_network = "#!string!striker_0257!#"; } my $message = $anvil->Words->string({key => "error_0016", variables => { network => $say_network }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{$machine_ip_key}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::${machine_ip_key}::alert" => $anvil->data->{cgi}{$machine_ip_key}{alert}, "cgi::${machine_ip_key}::value" => $anvil->data->{cgi}{$machine_ip_key}{value}, }}); } else { # It's a valid IP. Is it in the network? my $match_found = $anvil->Network->is_ip_in_network({ debug => 2, ip => $anvil->data->{cgi}{$machine_ip_key}{value}, network => $anvil->data->{cgi}{$network_key}{value}, subnet_mask => $anvil->data->{cgi}{$subnet_key}{value}, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { match_found => $match_found }}); if (not $match_found) { # IP is valid, but not in any of the networks. my $message = $anvil->Words->string({key => "error_0126", variables => { ip => $anvil->data->{cgi}{$key}{value}, network => $anvil->data->{cgi}{$network_key}{value}."/".$anvil->data->{cgi}{$subnet_key}{value}, }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{$key}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::${key}::alert" => $anvil->data->{cgi}{$key}{alert}, "cgi::${key}::value" => $anvil->data->{cgi}{$key}{value}, }}); } } } } } ### TODO: We can't (at least yet) validate ports. They could be numeric or strings... To sanity check ### this, we'll need to look up the fence agent, look up the port type, and use that to decide ### how to check. That's more than we can do for 3.0. return($sane); } sub sanity_check_manifest_step2 { my ($anvil) = @_; my $sane = 1; foreach my $i (1..$anvil->data->{cgi}{bcn_count}{value}) { my $say_bcn = $anvil->Words->string({key => "striker_0018", variables => { number => $i }}); my $network_key = "bcn".$i."_network"; my $subnet_key = "bcn".$i."_subnet"; my $gateway_key = "bcn".$i."_gateway"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_key => $network_key, subnet_key => $subnet_key, gateway_key => $gateway_key, }}); # The BCN doesn't support setting the netmask (for now, anyway), so we'll set it here to /16. # If later support is added, this will pick it up. $anvil->data->{cgi}{$subnet_key}{value} = "255.255.0.0" if not defined $anvil->data->{cgi}{$subnet_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value}, "cgi::${gateway_key}::value" => $anvil->data->{cgi}{$gateway_key}{value}, }}); $sane = check_network($anvil, $sane, $say_bcn, $network_key, $subnet_key, $gateway_key); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); } # There's only ever 1 SN my $say_sn = $anvil->Words->string({key => "striker_0020", variables => { number => '1' }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_sn => $say_sn }}); # The storage network always uses the subnet /16 and has no gateway. $anvil->data->{cgi}{sn1_subnet}{value} = "255.255.0.0" if not defined $anvil->data->{cgi}{sn1_subnet}{value}; $anvil->data->{cgi}{sn1_gateway}{value} = "" if not defined $anvil->data->{cgi}{sn1_gateway}{value}; $sane = check_network($anvil, $sane, $say_sn, "sn1_network", "sn1_subnet", "sn1_gateway"); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); # There's only ever 1 MN my $say_mn = $anvil->Words->string({key => "striker_0299", variables => { number => '1' }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_mn => $say_mn }}); # The migration network always uses the subnet /16 and has no gateway. $anvil->data->{cgi}{mn1_subnet}{value} = "255.255.0.0" if not defined $anvil->data->{cgi}{mn1_subnet}{value}; $anvil->data->{cgi}{mn1_gateway}{value} = "" if not defined $anvil->data->{cgi}{mn1_gateway}{value}; $sane = check_network($anvil, $sane, $say_mn, "mn1_network", "mn1_subnet", "mn1_gateway"); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); # Now IFNs foreach my $i (1..$anvil->data->{cgi}{ifn_count}{value}) { my $say_ifn = $anvil->Words->string({key => "striker_0022", variables => { number => $i }}); my $network_key = "ifn".$i."_network"; my $subnet_key = "ifn".$i."_subnet"; my $gateway_key = "ifn".$i."_gateway"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_bcn => $say_ifn, network_key => $network_key, subnet_key => $subnet_key, gateway_key => $gateway_key, }}); $anvil->data->{cgi}{$network_key}{value} = "" if not defined $anvil->data->{cgi}{$network_key}{value}; $anvil->data->{cgi}{$network_key}{alert} = 0 if not defined $anvil->data->{cgi}{$network_key}{alert}; $anvil->data->{cgi}{$subnet_key}{value} = "255.255.0.0" if not defined $anvil->data->{cgi}{$subnet_key}{value}; $anvil->data->{cgi}{$subnet_key}{alert} = 0 if not defined $anvil->data->{cgi}{$subnet_key}{alert}; $anvil->data->{cgi}{$gateway_key}{value} = "" if not defined $anvil->data->{cgi}{$gateway_key}{value}; $anvil->data->{cgi}{$gateway_key}{alert} = 0 if not defined $anvil->data->{cgi}{$gateway_key}{alert}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, "cgi::${network_key}::alert" => $anvil->data->{cgi}{$network_key}{alert}, "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value}, "cgi::${subnet_key}::alert" => $anvil->data->{cgi}{$subnet_key}{alert}, "cgi::${gateway_key}::value" => $anvil->data->{cgi}{$gateway_key}{value}, "cgi::${gateway_key}::alert" => $anvil->data->{cgi}{$gateway_key}{alert}, }}); $sane = check_network($anvil, $sane, $say_ifn, $network_key, $subnet_key, $gateway_key); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); } # If DNS is specified, make sure it/they are valid. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::dns::value" => $anvil->data->{cgi}{dns}{value} }}); if ($anvil->data->{cgi}{dns}{value}) { foreach my $ip (split/,/, $anvil->data->{cgi}{dns}{value}) { $ip =~ s/^\s+//; $ip =~ s/\s+$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip => $ip }}); if (not $anvil->Validate->ipv4({ip => $ip})) { # Bad network my $message = $anvil->Words->string({key => "error_0015"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{dns}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, ip => $ip, "cgi::dns::alert" => $anvil->data->{cgi}{dns}{alert}, "cgi::dns::value" => $anvil->data->{cgi}{dns}{value}, }}); } } } # If NTP is specified, make sure it/they are valid. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::ntp::value" => $anvil->data->{cgi}{ntp}{value} }}); if ($anvil->data->{cgi}{ntp}{value}) { foreach my $ip (split/,/, $anvil->data->{cgi}{ntp}{value}) { $ip =~ s/^\s+//; $ip =~ s/\s+$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip => $ip }}); if (not $anvil->Validate->ipv4({ip => $ip})) { # Bad network my $message = $anvil->Words->string({key => "error_0122"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{ntp}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, ip => $ip, "cgi::ntp::alert" => $anvil->data->{cgi}{ntp}{alert}, "cgi::ntp::value" => $anvil->data->{cgi}{ntp}{value}, }}); } } } # Make sure the MTU is sane if (not $anvil->Validate->positive_integer({number => $anvil->data->{cgi}{mtu}{value}})) { my $message = $anvil->Words->string({key => "error_0123"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{mtu}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::mtu::alert" => $anvil->data->{cgi}{mtu}{alert}, "cgi::mtu::value" => $anvil->data->{cgi}{mtu}{value}, }}); } return($sane); } ### TODO: Make this a Validate module sub check_network { my ($anvil, $sane, $say_network, $network_key, $subnet_key, $gateway_key) = @_; # Make sure the network and subnet are valid my $local_sane = 1; if (not $anvil->Validate->ipv4({ip => $anvil->data->{cgi}{$network_key}{value}})) { # Bad network my $message = $anvil->Words->string({key => "error_0020", variables => { field => $say_network." - #!string!striker_0149!#" }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{$network_key}{alert} = 1; $sane = 0; $local_sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, local_sane => $local_sane, "cgi::${network_key}::alert" => $anvil->data->{cgi}{$network_key}{alert}, "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, }}); } if (not $anvil->Validate->ipv4({ip => $anvil->data->{cgi}{$subnet_key}{value}})) { # Bad subnet my $message = $anvil->Words->string({key => "error_0020", variables => { field => $say_network." - #!string!striker_0025!#" }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{$subnet_key}{alert} = 1; $sane = 0; $local_sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, local_sane => $local_sane, "cgi::${subnet_key}::alert" => $anvil->data->{cgi}{$subnet_key}{alert}, "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value}, }}); } # The gateway can be blank if (($anvil->data->{cgi}{$gateway_key}{value}) && (not $anvil->Validate->ipv4({ip => $anvil->data->{cgi}{$gateway_key}{value}}))) { # It's not a valid IP. my $message = $anvil->Words->string({key => "error_0118", variables => { ip => $anvil->data->{cgi}{$gateway_key}{value} }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{$gateway_key}{alert} = 1; $sane = 0; $local_sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, local_sane => $local_sane, "cgi::${gateway_key}::alert" => $anvil->data->{cgi}{$gateway_key}{alert}, "cgi::${gateway_key}::value" => $anvil->data->{cgi}{$gateway_key}{value}, }}); } # If I'm still sane, make sure that the network is actually the bottom of the subnet. if ($local_sane) { my $test_network = $anvil->Network->get_network({ip => $anvil->data->{cgi}{$network_key}{value}, subnet_mask => $anvil->data->{cgi}{$subnet_key}{value}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { test_network => $test_network }}); if (not $test_network) { # Something is invalid. my $message = $anvil->Words->string({key => "error_0120", variables => { network => $anvil->data->{cgi}{$network_key}{value}, subnet => $anvil->data->{cgi}{$subnet_key}{value}, }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{$network_key}{alert} = 1; $anvil->data->{cgi}{$subnet_key}{alert} = 1; $sane = 0; $local_sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, local_sane => $local_sane, "cgi::${network_key}::alert" => $anvil->data->{cgi}{$network_key}{alert}, "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, "cgi::${subnet_key}::alert" => $anvil->data->{cgi}{$subnet_key}{alert}, "cgi::${subnet_key}::value" => $anvil->data->{cgi}{$subnet_key}{value}, }}); } elsif ($test_network ne $anvil->data->{cgi}{$network_key}{value}) { # The user didn't give the base IP of the network. my $message = $anvil->Words->string({key => "error_0119", variables => { name => $say_network, ip => $test_network, }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{$network_key}{alert} = 1; $sane = 0; $local_sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, local_sane => $local_sane, "cgi::${network_key}::alert" => $anvil->data->{cgi}{$network_key}{alert}, "cgi::${network_key}::value" => $anvil->data->{cgi}{$network_key}{value}, }}); } # Lastly, if we've got a gateway, make sure it's in the network. if (($local_sane) && ($anvil->data->{cgi}{$gateway_key}{value})) { my $base_ip = $anvil->Network->get_network({ip => $anvil->data->{cgi}{$gateway_key}{value}, subnet_mask => $anvil->data->{cgi}{$subnet_key}{value}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { base_ip => $base_ip }}); if ($base_ip ne $anvil->data->{cgi}{$network_key}{value}) { # The gateway is not in the subnet my $message = $anvil->Words->string({key => "error_0121", variables => { gateway => $anvil->data->{cgi}{$gateway_key}{value}, network => $anvil->data->{cgi}{$network_key}{value}, subnet => $anvil->data->{cgi}{$subnet_key}{value}, }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{$gateway_key}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::${gateway_key}::alert" => $anvil->data->{cgi}{$gateway_key}{alert}, "cgi::${gateway_key}::value" => $anvil->data->{cgi}{$gateway_key}{value}, }}); } } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); return($sane); } sub sanity_check_manifest_step1 { my ($anvil) = @_; my $sane = 1; if ((not $anvil->Validate->alphanumeric({string => $anvil->data->{cgi}{prefix}{value}})) or (length($anvil->data->{cgi}{prefix}{value}) > 5)) { my $message = $anvil->Words->string({key => "error_0020", variables => { field => "#!string!striker_0228!#" }}); if ($anvil->data->{cgi}{prefix}{value}) { $message = $anvil->Words->string({key => "error_0021"}); } $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{prefix}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::prefix::alert" => $anvil->data->{cgi}{prefix}{alert}, "cgi::prefix::value" => $anvil->data->{cgi}{prefix}{value}, }}); } # We can use Validate to check the domain. if (not $anvil->Validate->domain_name({name => $anvil->data->{cgi}{domain}{value}, debug => 2})) { my $message = $anvil->Words->string({key => "error_0020", variables => { field => "#!string!striker_0007!#" }}); if ($anvil->data->{cgi}{domain}{value}) { $message = $anvil->Words->string({key => "error_0117", variables => { name => $anvil->data->{cgi}{domain}{value} }}); } $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{domain}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::domain::alert" => $anvil->data->{cgi}{domain}{alert}, "cgi::domain::value" => $anvil->data->{cgi}{domain}{value}, }}); } # The sequence and IFN count need to be integers. if (not $anvil->Validate->positive_integer({number => $anvil->data->{cgi}{sequence}{value}})) { my $message = $anvil->Words->string({key => "error_0020", variables => { field => "#!string!striker_0009!#" }}); if ($anvil->data->{cgi}{sequence}{value}) { $message = $anvil->Words->string({key => "error_0022", variables => { field => "#!string!striker_0009!#" }}); } $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{sequence}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::sequence::alert" => $anvil->data->{cgi}{sequence}{alert}, "cgi::sequence::value" => $anvil->data->{cgi}{sequence}{value}, }}); } if (not $anvil->Validate->positive_integer({number => $anvil->data->{cgi}{ifn_count}{value}})) { my $message = $anvil->Words->string({key => "error_0020", variables => { field => "#!string!striker_0230!#" }}); if ($anvil->data->{cgi}{ifn_count}{value}) { $message = $anvil->Words->string({key => "error_0022", variables => { field => "#!string!striker_0230!#" }}); } $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{ifn_count}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::ifn_count::alert" => $anvil->data->{cgi}{ifn_count}{alert}, "cgi::ifn_count::value" => $anvil->data->{cgi}{ifn_count}{value}, }}); } return($sane); } # Show the create manifest (and Fence devices and UPSes) menu sub process_create { my ($anvil) = @_; # Show existing manifests. $anvil->Database->get_manifests(); my $manifest_template = ""; foreach my $manifest_name (sort {$a cmp $b} keys %{$anvil->data->{manifests}{manifest_name}}) { my $manifest_uuid = $anvil->data->{manifests}{manifest_name}{$manifest_name}{manifest_uuid}; my $manifest_last_ran = $anvil->data->{manifests}{manifest_name}{$manifest_name}{manifest_last_ran}; my $manifest_xml = $anvil->data->{manifests}{manifest_name}{$manifest_name}{manifest_xml}; my $manifest_note = $anvil->data->{manifests}{manifest_name}{$manifest_name}{manifest_note}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { manifest_uuid => $manifest_uuid, manifest_name => $manifest_name, manifest_last_ran => $manifest_last_ran, manifest_xml => $manifest_xml, manifest_note => $manifest_note, }}); $manifest_template .= $anvil->Template->get({file => "anvil.html", name => "create-menu-existing-manifest-entry", variables => { manifest_uuid => $manifest_uuid, manifest_name => $manifest_name, }}); } # Store the previous CGI variables and display the new fields. $anvil->data->{form}{back_link} = "?anvil=true"; $anvil->data->{form}{refresh_link} = "?anvil=true&task=create"; $anvil->data->{cgi}{task}{value} = "" if not defined $anvil->data->{cgi}{task}{value}; $anvil->data->{cgi}{subtask}{value} = "" if not defined $anvil->data->{cgi}{subtask}{value}; $anvil->data->{cgi}{action}{value} = "" if not defined $anvil->data->{cgi}{action}{value}; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "create-menu", variables => { existing_manifests => $manifest_template, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); return(0); } # This allows the user to tell us about upses. sub process_upses { my ($anvil) = @_; # Pull the data of supported UPSes out of the specual 'ups_X' strings. $anvil->Striker->get_ups_data({debug => 3}); foreach my $key (sort {$a cmp $b} keys %{$anvil->data->{ups_data}}) { my $agent = $anvil->data->{ups_data}{$key}{agent}; my $brand = $anvil->data->{ups_data}{$key}{brand}; my $description = $anvil->data->{ups_data}{$key}{description}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "s1:key" => $key, "s2:agent" => $anvil->data->{ups_data}{$key}{agent}, "s3:brand" => $anvil->data->{ups_data}{$key}{brand}, "s4:description" => $anvil->data->{ups_data}{$key}{description}, }}); } $anvil->data->{cgi}{ups_agent}{value} = "" if not defined $anvil->data->{cgi}{ups_agent}{value}; $anvil->data->{cgi}{ups_count}{value} = 1 if not defined $anvil->data->{cgi}{ups_count}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::ups_agent::value" => $anvil->data->{cgi}{ups_agent}{value}, "cgi::ups_count::value" => $anvil->data->{cgi}{ups_count}{value}, }}); # Are we going back to the form? if ($anvil->data->{cgi}{back}{value}) { $anvil->data->{cgi}{save}{value} = ""; $anvil->data->{cgi}{confirm}{value} = ""; $anvil->data->{cgi}{delete_ups_uuid}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::save::value" => $anvil->data->{cgi}{save}{value}, "cgi::confirm::value" => $anvil->data->{cgi}{confirm}{value}, "cgi::delete_ups_uuid::value" => $anvil->data->{cgi}{delete_ups_uuid}{value}, }}); } # Are we deleting an agent? if ((exists $anvil->data->{cgi}{delete_ups_uuid}) && ($anvil->data->{cgi}{delete_ups_uuid}{value})) { # Verify that the UUID is valid. $anvil->Database->get_upses({debug => 2, include_deleted => 1}); my $ups_uuid = $anvil->data->{cgi}{delete_ups_uuid}{value}; my $ups_name = $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ups_name}; my $ups_agent = $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ups_agent}; if (not exists $anvil->data->{upses}{ups_uuid}{$ups_uuid}) { # Doesn't exist. my $message = $anvil->Words->string({key => "warning_0036", variables => { uuid => $ups_uuid }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } elsif ($anvil->data->{upses}{ups_uuid}{$ups_uuid}{ups_ip_address} eq "DELETED") { # Already deleted. my $message = $anvil->Words->string({key => "warning_0037", variables => { name => $ups_name, uuid => $ups_uuid, }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } # Has the user confirmed? if ((exists $anvil->data->{cgi}{confirm}) && ($anvil->data->{cgi}{confirm}{value})) { # Delete it my ($ups_uuid) = $anvil->Database->insert_or_update_upses({ debug => 2, ups_uuid => $ups_uuid, ups_name => $ups_name, ups_agent => $ups_agent, ups_ip_address => "DELETED", }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_uuid => $ups_uuid }}); if ($ups_uuid) { # Deleted successfully my $message = $anvil->Words->string({key => "ok_0008", variables => { name => $ups_name }}); $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::ok_message" => $anvil->data->{form}{ok_message} }}); } else { # Something went wrong. my $message = $anvil->Words->string({key => "warning_0040", variables => { name => $ups_name, uuid => $ups_uuid, }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } # Show the main menu and return. show_ups_config_main_menu($anvil); return(0); } else { # Ask the user to confirm. my $ups_name = $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ups_name}; my $ups_ip_address = $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ups_ip_address}; my $say_ups_device = $ups_name." - ".$ups_ip_address." (".$anvil->data->{ups_agent}{$ups_agent}{brand}.")"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_uuid => $ups_uuid, ups_agent => $ups_agent, ups_ip_address => $ups_ip_address, say_ups_device => $say_ups_device, }}); # Are we asking the user to confirm one or more? $anvil->data->{form}{back_link} = "?anvil=true&task=upses"; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "ups-delete-confirm", variables => { name => $ups_name, say_device => $say_ups_device, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); return(0); } } # Are we configuring an agent/device? $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::save::value" => $anvil->data->{cgi}{save}{value}, "cgi::confirm::value" => $anvil->data->{cgi}{confirm}{value}, }}); if ($anvil->data->{cgi}{save}{value}) { # Confirmed? if ($anvil->data->{cgi}{confirm}{value}) { # Confirmed. my $success = 1; my $message = ""; foreach my $i (1..$anvil->data->{cgi}{ups_count}{value}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { i => $i }}); my $ups_uuid_key = "ups_uuid_".$i; my $ups_name_key = "ups_name_".$i; my $ups_agent_key = "ups_agent_".$i; my $ups_ip_address_key = "ups_ip_address_".$i; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_uuid_key => $ups_uuid_key, ups_name_key => $ups_name_key, ups_agent_key => $ups_agent_key, ups_ip_address_key => $ups_ip_address_key, }}); my $ups_uuid = $anvil->data->{cgi}{$ups_uuid_key}{value}; my $ups_name = $anvil->data->{cgi}{$ups_name_key}{value}; my $ups_agent = $anvil->data->{cgi}{$ups_agent_key}{value}; my $ups_ip_address = $anvil->data->{cgi}{$ups_ip_address_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 's1:ups_uuid' => $ups_uuid, 's2:ups_name' => $ups_name, 's3:ups_agent' => $ups_agent, 's4:ups_ip_address' => $ups_ip_address, }}); # Save it ($ups_uuid) = $anvil->Database->insert_or_update_upses({ debug => 2, ups_uuid => $ups_uuid, ups_name => $ups_name, ups_agent => $ups_agent, ups_ip_address => $ups_ip_address, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_uuid => $ups_uuid }}); if ($ups_uuid) { $message .= $anvil->Words->string({key => "ok_0007", variables => { name => $ups_name }})."
"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message => $message }}); # Clear CGI values so the form isn't pre-filled below. foreach my $key (sort {$a cmp $b} keys %{$anvil->data->{cgi}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { key => $key }}); if ($key =~ /_$i$/) { $anvil->data->{cgi}{$key}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${key}::value" => $anvil->data->{cgi}{$key}{value} }}); } } } else { # Something went wrong. $success = 0; $message .= $anvil->Words->string({key => "warning_0038", variables => { name => $ups_name }})."
"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 's1:success' => $success, 's2:message' => $message, }}); } } # Show it in the top-center. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { success => $success }}); if ($success) { # Woot! $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::ok_message" => $anvil->data->{form}{ok_message} }}); # Show the main menu and return. show_ups_config_main_menu($anvil); return(0); } else { # Something went wrong. $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } } else { # Loop through the UPSes and ask for confirmation. my $sane = 1; my $upses_form = ""; foreach my $i (1..$anvil->data->{cgi}{ups_count}{value}) { my $say_device = $anvil->Words->string({key => "striker_0239", variables => { number => $i }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { i => $i, say_device => $say_device, }}); my $ups_uuid_key = "ups_uuid_".$i; my $ups_name_key = "ups_name_".$i; my $ups_agent_key = "ups_agent_".$i; my $ups_ip_address_key = "ups_ip_address_".$i; my $agent = $anvil->data->{cgi}{$ups_agent_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_uuid_key => $ups_uuid_key, ups_name_key => $ups_name_key, ups_agent_key => $ups_agent_key, ups_ip_address_key => $ups_ip_address_key, agent => $agent, }}); # Are any values insane? if (not $anvil->Validate->host_name({name => $anvil->data->{cgi}{$ups_name_key}{value}, debug => 2})) { # Bad host name $sane = 0; $anvil->data->{cgi}{$ups_name_key}{alert} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${ups_name_key}::alert" => $anvil->data->{cgi}{$ups_name_key}{alert}, sane => $sane, }}); } if (not $anvil->Validate->ipv4({ip => $anvil->data->{cgi}{$ups_ip_address_key}{value}})) { # Bad IP address. $sane = 0; $anvil->data->{cgi}{$ups_name_key}{alert} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${ups_name_key}::alert" => $anvil->data->{cgi}{$ups_name_key}{alert}, sane => $sane, }}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); if ($sane) { $upses_form .= $anvil->Template->get({file => "anvil.html", name => "ups-option-menu-confirm", variables => { device => $say_device, name_key => $ups_name_key, name => $anvil->data->{cgi}{$ups_name_key}{value}, agent_key => $ups_agent_key, agent => $anvil->data->{cgi}{$ups_agent_key}{value}, say_agent => $anvil->data->{ups_agent}{$agent}{brand}, ip_address_key => $ups_ip_address_key, ip_address => $anvil->data->{cgi}{$ups_ip_address_key}{value}, ups_uuid_key => $ups_uuid_key, ups_uuid => $anvil->data->{cgi}{$ups_uuid_key}{value}, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { upses_form => $upses_form }}); } } if ($sane) { $anvil->data->{form}{back_link} = "?anvil=true&task=upses"; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "ups-configuration-confirm", variables => { upses => $upses_form, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); return(0); } else { # Send the user back to the form. $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => "#!string!warning_0039!#" }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } } } if ($anvil->data->{cgi}{ups_agent}{value}) { my $ups_agent = $anvil->data->{cgi}{ups_agent}{value}; my $ups_brand = $anvil->data->{ups_agent}{$ups_agent}{brand}; my $ups_description = $anvil->data->{ups_agent}{$ups_agent}{description}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_agent => $ups_agent, ups_brand => $ups_brand, ups_description => $ups_description, }}); # Are we going back to the form? if ($anvil->data->{cgi}{back}{value}) { $anvil->data->{cgi}{save}{value} = ""; $anvil->data->{cgi}{confirm}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::save::value" => $anvil->data->{cgi}{save}{value}, "cgi::confirm::value" => $anvil->data->{cgi}{confirm}{value}, }}); } # This will be used in forms my $brands = []; my $description_form = ""; foreach my $key (sort {$a cmp $b} keys %{$anvil->data->{ups_data}}) { my $agent = $anvil->data->{ups_data}{$key}{agent}; my $brand = $anvil->data->{ups_data}{$key}{brand}; my $description = $anvil->data->{ups_data}{$key}{description}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:key" => $key, "s2:agent" => $anvil->data->{ups_data}{$key}{agent}, "s3:brand" => $anvil->data->{ups_data}{$key}{brand}, "s4:description" => $anvil->data->{ups_data}{$key}{description}, }}); push @{$brands}, $agent."#!#".$brand; } # Walk through the list of UPSes $anvil->Database->get_upses({debug => 3}); my $upses_form = ""; if ((not exists $anvil->data->{cgi}{ups_brand}) or (not defined $anvil->data->{cgi}{ups_brand}{value})) { $anvil->data->{cgi}{ups_brand}{value} = $ups_brand; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::ups_brand::value" => $anvil->data->{cgi}{ups_brand}{value}, }}); } foreach my $i (1..$anvil->data->{cgi}{ups_count}{value}) { my $say_device = $anvil->Words->string({key => "striker_0239", variables => { number => $i }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { i => $i, say_device => $say_device, }}); my $ups_uuid_key = "ups_uuid_".$i; my $ups_name_key = "ups_name_".$i; my $ups_agent_key = "ups_agent_".$i; my $ups_ip_address_key = "ups_ip_address_".$i; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_uuid_key => $ups_uuid_key, ups_name_key => $ups_name_key, ups_agent_key => $ups_agent_key, ups_ip_address_key => $ups_ip_address_key }}); # Make sure we don't get any undefined warnings if ((not exists $anvil->data->{cgi}{$ups_name_key}) or (not defined $anvil->data->{cgi}{$ups_name_key}{value})) { $anvil->data->{cgi}{$ups_name_key}{value} = ""; } if ((not exists $anvil->data->{cgi}{$ups_agent_key}) or (not defined $anvil->data->{cgi}{$ups_agent_key}{value})) { $anvil->data->{cgi}{$ups_agent_key}{value} = ""; } if ((not exists $anvil->data->{cgi}{$ups_uuid_key}) or (not defined $anvil->data->{cgi}{$ups_uuid_key}{value})) { $anvil->data->{cgi}{$ups_uuid_key}{value} = ""; } # If we have a ups_uuid_X, read in the details. if ($anvil->data->{cgi}{$ups_uuid_key}{value}) { my $ups_uuid = $anvil->data->{cgi}{$ups_uuid_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_uuid => $ups_uuid }}); if (exists $anvil->data->{upses}{ups_uuid}{$ups_uuid}) { my $old_ups_name = $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ups_name}; my $old_ups_agent = $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ups_agent}; my $old_ups_ip_address = $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ups_ip_address}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_ups_name => $old_ups_name, old_ups_agent => $old_ups_agent, old_ups_ip_address => $old_ups_ip_address, ups_name_key => $ups_name_key, ups_agent_key => $ups_agent_key, ups_ip_address_key => $ups_ip_address_key, }}); # Now if we don't have a value in CGI but do from the database, set the CGI. if ((not $anvil->data->{cgi}{$ups_name_key}{value}) && ($old_ups_name)) { $anvil->data->{cgi}{$ups_name_key}{value} = $old_ups_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${ups_name_key}::value" => $anvil->data->{cgi}{$ups_name_key}{value}, }}); } if ((not $anvil->data->{cgi}{$ups_agent_key}{value}) && ($old_ups_agent)) { $anvil->data->{cgi}{$ups_agent_key}{value} = $old_ups_agent; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${ups_agent_key}::value" => $anvil->data->{cgi}{$ups_agent_key}{value}, }}); } if ((not $anvil->data->{cgi}{$ups_ip_address_key}{value}) && ($old_ups_ip_address)) { $anvil->data->{cgi}{$ups_ip_address_key}{value} = $old_ups_ip_address; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${ups_ip_address_key}::value" => $anvil->data->{cgi}{$ups_ip_address_key}{value}, }}); } } } my $ups_agent_select = $anvil->Template->select_form({ name => $ups_agent_key, options => $brands, blank => 0, 'sort' => 1, selected => $anvil->data->{cgi}{$ups_agent_key}{value} ? $anvil->data->{cgi}{$ups_agent_key}{value} : $anvil->data->{cgi}{ups_agent}{value}, class => "input_clear", }); $upses_form .= $anvil->Template->get({file => "anvil.html", name => "ups-option-menu", variables => { device => $say_device, name_key => $ups_name_key, name => $anvil->data->{cgi}{$ups_name_key}{value}, agent => $ups_agent_select, ip_address_key => $ups_ip_address_key, ip_address => $anvil->data->{cgi}{$ups_ip_address_key}{value}, ups_uuid_key => $ups_uuid_key, ups_uuid => $anvil->data->{cgi}{$ups_uuid_key}{value}, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { upses_form => $upses_form }}); } $anvil->data->{form}{back_link} = "?anvil=true&task=upses"; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "ups-configuration", variables => { description => $ups_description, upses => $upses_form, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'form::body' => $anvil->data->{form}{body} }}); } else { # Show the main menu show_ups_config_main_menu($anvil); } return(0); } sub show_ups_config_main_menu { my ($anvil) = @_; # Read in known UPSes $anvil->Database->get_upses({debug => 3}); # Get a list of current ups agents. my $existing_upses = ""; if (exists $anvil->data->{upses}{ups_uuid}) { # How many do we have? my $ups_count = keys %{$anvil->data->{upses}{ups_name}}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_count => $ups_count }}); if ($ups_count) { # We've got devices. my $ups_devices = ""; foreach my $ups_name (sort {$a cmp $b} keys %{$anvil->data->{upses}{ups_name}}) { my $ups_uuid = $anvil->data->{upses}{ups_name}{$ups_name}{ups_uuid}; my $ups_agent = $anvil->data->{upses}{ups_name}{$ups_name}{ups_agent}; my $ups_ip_address = $anvil->data->{upses}{ups_name}{$ups_name}{ups_ip_address}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_uuid => $ups_uuid, ups_agent => $ups_agent, ups_ip_address => $ups_ip_address, }}); $ups_devices .= $anvil->Template->get({file => "anvil.html", name => "existing-ups-entry", variables => { name => $ups_name, ip_address => $ups_ip_address, ups_agent => $ups_agent, ups_uuid => $ups_uuid, }}); } $existing_upses .= $anvil->Template->get({file => "anvil.html", name => "existing-upses", variables => { upses => $ups_devices, }}); } } # For each agent, we'll create a
with it's options that will be shown/hidden basen on the agent # select box. my $brands = []; my $description_form = ""; foreach my $key (sort {$a cmp $b} keys %{$anvil->data->{ups_data}}) { my $agent = $anvil->data->{ups_data}{$key}{agent}; my $brand = $anvil->data->{ups_data}{$key}{brand}; my $description = $anvil->data->{ups_data}{$key}{description}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:key" => $key, "s2:agent" => $anvil->data->{ups_data}{$key}{agent}, "s3:brand" => $anvil->data->{ups_data}{$key}{brand}, "s4:description" => $anvil->data->{ups_data}{$key}{description}, }}); push @{$brands}, $agent."#!#".$brand; $description_form .= $anvil->Template->get({file => "anvil.html", name => "ups-agent-description", variables => { name => $brand, description => $description, }}); } my $ups_agent_select = $anvil->Template->select_form({ name => "ups_agent", options => $brands, blank => 0, 'sort' => 1, selected => $anvil->data->{cgi}{ups_agent}{value} ? $anvil->data->{cgi}{ups_agent}{value} : "scan-apc-ups", class => "input_clear", }); my $ups_count_select = $anvil->Template->select_form({ name => "ups_count", options => [1, 2, 3, 4], blank => 0, 'sort' => 0, selected => $anvil->data->{cgi}{ups_count}{value}, class => "input_clear", }); $anvil->data->{form}{back_link} = "?anvil=true&task=create"; $anvil->data->{form}{refresh_link} = "?anvil=true&task=upses"; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "ups-agent-menu", variables => { ups_select => $ups_agent_select, ups_count => $ups_count_select, descriptions => $description_form, existing_upses => $existing_upses, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); return(0); } # This allows the user to tell us about fence devices. sub process_fences { my ($anvil) = @_; # Read/process the unified fences metadata. $anvil->Striker->get_fence_data({debug => 3}); $anvil->data->{cgi}{fence_agent}{value} = "" if not defined $anvil->data->{cgi}{fence_agent}{value}; $anvil->data->{cgi}{fence_count}{value} = 1 if not defined $anvil->data->{cgi}{fence_count}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "cgi::fence_agent::value" => $anvil->data->{cgi}{fence_agent}{value}, "cgi::fence_count::value" => $anvil->data->{cgi}{fence_count}{value}, }}); # Are we deleting an agent? if ((exists $anvil->data->{cgi}{delete_fence_uuid}) && ($anvil->data->{cgi}{delete_fence_uuid}{value})) { # Verify that the UUID is valid. $anvil->Database->get_fences({debug => 2, include_deleted => 1}); my $fence_uuid = $anvil->data->{cgi}{delete_fence_uuid}{value}; my $fence_name = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_name}; my $fence_agent = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_agent}; if (not exists $anvil->data->{fences}{fence_uuid}{$fence_uuid}) { # Doesn't exist. my $message = $anvil->Words->string({key => "warning_0034", variables => { uuid => $fence_uuid }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } elsif ($anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_arguments} eq "DELETED") { # Already deleted. my $message = $anvil->Words->string({key => "warning_0033", variables => { name => $fence_name, uuid => $fence_uuid, }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } # Has the user confirmed? if ((exists $anvil->data->{cgi}{confirm}) && ($anvil->data->{cgi}{confirm}{value})) { # Delete it my ($fence_uuid) = $anvil->Database->insert_or_update_fences({ debug => 2, fence_uuid => $fence_uuid, fence_name => $fence_name, fence_agent => $fence_agent, fence_arguments => "DELETED", }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { fence_uuid => $fence_uuid }}); if ($fence_uuid) { # Deleted successfully my $message = $anvil->Words->string({key => "ok_0006", variables => { name => $fence_name }}); $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::ok_message" => $anvil->data->{form}{ok_message} }}); } else { # Something went wrong. my $message = $anvil->Words->string({key => "warning_0035", variables => { name => $fence_name, uuid => $fence_uuid, }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } # Show the main menu and return. show_fence_config_main_menu($anvil); return(0); } else { # Ask the user to confirm. my $fence_name = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_name}; my $fence_arguments = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_arguments}; my $say_fence_device = $fence_agent." ".$fence_arguments; $say_fence_device =~ s/passw(\w+)="(.*?)"/passw$1="--"/g; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { fence_uuid => $fence_uuid, fence_agent => $fence_agent, fence_arguments => $fence_arguments =~ /passw=/ ? $anvil->Log->is_secure($fence_arguments) : $fence_arguments, say_fence_device => $say_fence_device, }}); # Are we asking the user to confirm one or more? $anvil->data->{form}{back_link} = "?anvil=true&task=fences"; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "fence-agent-delete-confirm", variables => { name => $fence_name, say_device => $say_fence_device, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); return(0); } } # Are we configuring an agent/device? if ($anvil->data->{cgi}{fence_agent}{value}) { my $fence_agent = $anvil->data->{cgi}{fence_agent}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { fence_agent => $fence_agent }}); # Are we going back to the form? if ($anvil->data->{cgi}{back}{value}) { $anvil->data->{cgi}{save}{value} = ""; $anvil->data->{cgi}{confirm}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::save::value" => $anvil->data->{cgi}{save}{value}, "cgi::confirm::value" => $anvil->data->{cgi}{confirm}{value}, }}); } # Are we saving? if ($anvil->data->{cgi}{save}{value}) { # Sanity check my $sane = sanity_check_fence_agent_form($anvil, $fence_agent); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); if ($sane) { my $success = 0; if ($anvil->data->{cgi}{confirm}{value}) { # Build the table and ask the user to confirm. $success = 1; my $message = ""; foreach my $i (sort {$a cmp $b} keys %{$anvil->data->{fence}{$fence_agent}{set}}) { my $fence_name_key = "fence_name_".$i; my $fence_uuid_key = "fence_uuid_".$i; my $fence_name = defined $anvil->data->{cgi}{$fence_name_key}{value} ? $anvil->data->{cgi}{$fence_name_key}{value} : ""; my $fence_uuid = defined $anvil->data->{cgi}{$fence_uuid_key}{value} ? $anvil->data->{cgi}{$fence_uuid_key}{value} : ""; my $fence_arguments = ""; foreach my $name (sort {$a cmp $b} keys %{$anvil->data->{fence}{$fence_agent}{set}{$i}{parameter}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { name => $name }}); $fence_arguments .= $name."=\"".$anvil->data->{fence}{$fence_agent}{set}{$i}{parameter}{$name}{set}."\" "; } $fence_arguments =~ s/\s+$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 's1:i' => $i, 's2:fence_agent' => $fence_agent, 's3:fence_name' => $fence_name, 's4:fence_uuid' => $fence_uuid, 's5:fence_arguments' => $fence_arguments, }}); # Save it ($fence_uuid) = $anvil->Database->insert_or_update_fences({ debug => 2, fence_name => $fence_name, fence_agent => $fence_agent, fence_arguments => $fence_arguments, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { fence_uuid => $fence_uuid }}); if ($fence_uuid) { $message .= $anvil->Words->string({key => "ok_0005", variables => { name => $fence_name }})."
"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message => $message }}); # Clear CGI values so the form isn't pre-filled below. foreach my $key (sort {$a cmp $b} keys %{$anvil->data->{cgi}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { key => $key }}); if ($key =~ /_$i$/) { $anvil->data->{cgi}{$key}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${key}::value" => $anvil->data->{cgi}{$key}{value} }}); } } } else { # Something went wrong. $success = 0; $message .= $anvil->Words->string({key => "warning_0032", variables => { name => $fence_name }})."
"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 's1:success' => $success, 's2:message' => $message, }}); } } # Show it in the top-center. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { success => $success }}); if ($success) { # Woot! $anvil->data->{form}{ok_message} = $anvil->Template->get({file => "main.html", name => "ok_message", variables => { ok_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::ok_message" => $anvil->data->{form}{ok_message} }}); # Show the main menu and return. show_fence_config_main_menu($anvil); return(0); } else { # Something went wrong. $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); } } # Success is only true if confirm was set and we saved successfully. if ((not $anvil->data->{cgi}{confirm}{value}) or (not $success)) { my $header_columns = $anvil->Template->get({file => "anvil.html", name => "fence-agent-column", variables => { class => "column_header", value => " ", }}); foreach my $i (1..$anvil->data->{cgi}{fence_count}{value}) { # We stash the fence_uuid here as well. my $fence_uuid_key = "fence_uuid_".$i; $header_columns .= $anvil->Template->get({file => "anvil.html", name => "fence-agent-column-hidden-value", variables => { class => "column_header", say_value => $anvil->Words->string({key => "striker_0220", variables => { number => $i }}), name => $fence_uuid_key, value => $anvil->data->{cgi}{$fence_uuid_key}{value}, }}); } my $confirm_table = $anvil->Template->get({file => "anvil.html", name => "fence-agent-row", variables => { columns => $header_columns, }}); # Make sure 'fence_name' is always at the top. my $fence_name_seen = 0; foreach my $name ("fence_name", sort {$a cmp $b} keys %{$anvil->data->{fence}{confirm_table}{data}}) { if ($name eq "fence_name") { next if $fence_name_seen; $fence_name_seen = 1; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { name => $name }}); my $entry_row = $anvil->Template->get({file => "anvil.html", name => "fence-agent-column", variables => { class => "column_header", value => $name, }}); foreach my $i (sort {$a cmp $b} keys %{$anvil->data->{fence}{confirm_table}{data}{$name}}) { my $is_default = $anvil->data->{fence}{confirm_table}{data}{$name}{$i}{'default'}; my $say_value = $anvil->data->{fence}{confirm_table}{data}{$name}{$i}{say_value}; $say_value =~ s/"/"/g; my $value = $anvil->data->{fence}{confirm_table}{data}{$name}{$i}{value}; $value =~ s/"/"/g; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 's1:name' => $name, 's2:i' => $i, 's3:is_default' => $is_default, 's4:value' => $value, 's5:say_value' => $say_value, }}); $entry_row .= $anvil->Template->get({file => "anvil.html", name => "fence-agent-column-hidden-value", variables => { class => $is_default ? "default_value" : "changed_value", name => $name."_".$i, value => $value, say_value => $say_value, }}); } $confirm_table .= $anvil->Template->get({file => "anvil.html", name => "fence-agent-row", variables => { columns => $entry_row, }}); } # Are we asking the user to confirm one or more? my $confirm_string = $anvil->data->{cgi}{fence_count}{value} == 1 ? "#!string!striker_0222!#" : "#!string!striker_0221!#"; $anvil->data->{form}{back_link} = "?anvil=true&task=fences"; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "fence-agent-confirm", variables => { table => $confirm_table, span_count => $anvil->data->{cgi}{fence_count}{value}, confirm_string => $confirm_string, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); return(0); } } } my $agent_description = format_fence_description($anvil, $fence_agent, $anvil->data->{fence_data}{$fence_agent}{description}); # We add in 'name' $anvil->data->{fence_data}{$fence_agent}{parameters}{fence_name}{unique} = "0"; $anvil->data->{fence_data}{$fence_agent}{parameters}{fence_name}{required} = "1"; $anvil->data->{fence_data}{$fence_agent}{parameters}{fence_name}{description} = "#!string!striker_0223!#"; $anvil->data->{fence_data}{$fence_agent}{parameters}{fence_name}{content_type} = "string"; $anvil->data->{fence_data}{$fence_agent}{parameters}{fence_name}{'default'} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "fence_data::${fence_agent}::parameters::fence_name::unique" => $anvil->data->{fence_data}{$fence_agent}{parameters}{fence_name}{unique}, "fence_data::${fence_agent}::parameters::fence_name::required" => $anvil->data->{fence_data}{$fence_agent}{parameters}{fence_name}{required}, "fence_data::${fence_agent}::parameters::fence_name::description" => $anvil->data->{fence_data}{$fence_agent}{parameters}{fence_name}{description}, "fence_data::${fence_agent}::parameters::fence_name::content_type" => $anvil->data->{fence_data}{$fence_agent}{parameters}{fence_name}{content_type}, "fence_data::${fence_agent}::parameters::fence_name::default" => $anvil->data->{fence_data}{$fence_agent}{parameters}{fence_name}{'default'}, }}); # Walk through the list of options my $option_form = ""; foreach my $i (1..$anvil->data->{cgi}{fence_count}{value}) { my $say_device = $anvil->Words->string({key => "striker_0216", variables => { number => $i }}); my $device_options = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { i => $i, say_device => $say_device, }}); # If we have a fence_uuid_X, read in the details. my $fence_uuid_key = "fence_uuid_".$i; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { fence_uuid_key => $fence_uuid_key }}); if ((exists $anvil->data->{cgi}{$fence_uuid_key}) && ($anvil->data->{cgi}{$fence_uuid_key}{value})) { $anvil->Database->get_fences({debug => 2}); my $fence_uuid = $anvil->data->{cgi}{$fence_uuid_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { fence_uuid => $fence_uuid }}); if (exists $anvil->data->{fences}{fence_uuid}{$fence_uuid}) { my $old_fence_name = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_name}; my $old_fence_agent = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_agent}; my $old_fence_arguments = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_arguments}; my $fence_name_key = "fence_name_".$i; my $fence_agent_key = "fence_agent_".$i; my $fence_arguments_key = "fence_arguments_".$i; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_fence_name => $old_fence_name, old_fence_agent => $old_fence_agent, old_fence_arguments => $old_fence_arguments, fence_name_key => $fence_name_key, fence_agent_key => $fence_agent_key, fence_arguments_key => $fence_arguments_key, }}); # Make sure we don't get any undefined warnings if ((not exists $anvil->data->{cgi}{$fence_name_key}) or (not defined $anvil->data->{cgi}{$fence_name_key}{value})) { $anvil->data->{cgi}{$fence_name_key}{value} = ""; } if ((not exists $anvil->data->{cgi}{$fence_agent_key}) or (not defined $anvil->data->{cgi}{$fence_agent_key}{value})) { $anvil->data->{cgi}{$fence_agent_key}{value} = ""; } # For arguments, we need to break up the arguments string, append the integer to the variable, and see if that CGI is set yet. $old_fence_arguments =~ s/="(.*?)" /="$1",/; foreach my $pair (split/,/, $old_fence_arguments) { $pair =~ s/^\s+//; $pair =~ s/\s+$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pair => $pair }}); my ($variable, $value) = ($pair =~ /^(.*?)="(.*)"$/); my $cgi_key = $variable."_".$i; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 's1:variable' => $variable, 's2:value' => $variable =~ /passw=/ ? $anvil->Log->is_secure($value) : $value, 's3:cgi_key' => $cgi_key, }}); if ((not defined $anvil->data->{cgi}{$cgi_key}{value}) or ($anvil->data->{cgi}{$cgi_key}{value} eq "")) { $anvil->data->{cgi}{$cgi_key}{value} = $value; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${cgi_key}::value" => $anvil->data->{cgi}{$cgi_key}{value}, }}); } # Now if we don't have a value in CGI but do from the database, set the CGI. if ((not $anvil->data->{cgi}{$fence_name_key}{value}) && ($old_fence_name)) { $anvil->data->{cgi}{$fence_name_key}{value} = $old_fence_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${fence_name_key}::value" => $anvil->data->{cgi}{$fence_name_key}{value}, }}); } if ((not $anvil->data->{cgi}{$fence_agent_key}{value}) && ($old_fence_agent)) { $anvil->data->{cgi}{$fence_agent_key}{value} = $old_fence_agent; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${fence_agent_key}::value" => $anvil->data->{cgi}{$fence_agent_key}{value}, }}); } if ((not $anvil->data->{cgi}{$fence_arguments_key}{value}) && ($old_fence_arguments)) { $anvil->data->{cgi}{$fence_arguments_key}{value} = $old_fence_arguments; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${fence_arguments_key}::value" => $anvil->data->{cgi}{$fence_arguments_key}{value}, }}); } } } my $fence_name_seen = 0; foreach my $name ("fence_name", sort {$a cmp $b} keys %{$anvil->data->{fence_data}{$fence_agent}{parameters}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { fence_agent => $fence_agent, name => $name, }}); # We don't show deprecated or replaced options. next if $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{replacement}; next if $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{deprecated}; next if (($fence_name_seen) && ($name eq "fence_name")); # If this is the 'fence_name', it's artificial so pump in some data if ($name eq "fence_name") { $fence_name_seen = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { fence_name_seen => $fence_name_seen }}); } my $option_key = $name."_".$i; my $unique = $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{unique}; my $required = $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{required}; my $description = $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{description}; my $type = $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{content_type}; my $default = exists $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{'default'} ? $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{'default'} : ""; $default =~ s/"/"/g; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { option_key => $option_key, unique => $unique, required => $required, description => $description, type => $type, 'default' => $default, }}); # Set the cgi variable to the default, if not already set. $anvil->data->{cgi}{$option_key}{alert} = "" if not defined $anvil->data->{cgi}{$option_key}{alert}; $anvil->data->{cgi}{$option_key}{value} = $default if not defined $anvil->data->{cgi}{$option_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "cgi::".$option_key."::alert" => $anvil->data->{cgi}{$option_key}{alert}, "cgi::".$option_key."::value" => $anvil->data->{cgi}{$option_key}{value}, }}); # Set the CGI default if not already set. $anvil->data->{cgi}{$option_key}{value} = $default if not exists $anvil->data->{cgi}{$option_key}{value}; if ($type eq "select") { # Build the select box my $options = []; foreach my $option (sort {$a cmp $b} @{$anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{options}}) { push @{$options}, $option; } my $select_options = $anvil->Template->select_form({ name => $option_key, options => $options, blank => $required ? 0 : 1, 'sort' => 1, selected => $anvil->data->{cgi}{$option_key}{value}, class => $anvil->data->{cgi}{$option_key}{alert} ? "input_alert" : "input_clear", }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { select_options => $select_options }}); # Build the entry my $select_form .= $anvil->Template->get({file => "anvil.html", name => "fence-agent-option-entry", variables => { name_class => $required ? "say_required" : "", name => $name, option => $select_options, description => $description, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { select_form => $select_form }}); $device_options .= $select_form; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { device_options => $device_options }}); } elsif ($type eq "boolean") { # Build the entry my $checkbox_form .= $anvil->Template->get({file => "anvil.html", name => "fence-agent-checkbox-entry", variables => { name => $name, name_class => $required ? "say_required" : "", checkbox_name => $option_key, checkbox_checked => $anvil->data->{cgi}{$option_key}{value} ? "checked" : "", description => $description, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { checkbox_form => $checkbox_form }}); $device_options .= $checkbox_form; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { device_options => $device_options }}); } else { ### String, Second or Integer. # Build the entry my $string_options .= $anvil->Template->get({file => "anvil.html", name => "fence-agent-input-entry", variables => { name => $name, key => $option_key, value => $anvil->data->{cgi}{$option_key}{value}, 'default' => $default, name_class => $required ? "say_required" : "", input_class => $anvil->data->{cgi}{$option_key}{alert} ? "input_alert" : "input_clear", description => $description, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { string_options => $string_options }}); $device_options .= $string_options; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { device_options => $device_options }}); } } $option_form .= $anvil->Template->get({file => "anvil.html", name => "fence-agent-option-menu", variables => { device_name => $say_device, device_options => $device_options, fence_uuid_key => $fence_uuid_key, fence_uuid => defined $anvil->data->{cgi}{$fence_uuid_key}{value} ? $anvil->data->{cgi}{$fence_uuid_key}{value} : "", }}); } $anvil->data->{form}{back_link} = "?anvil=true&task=fences"; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "fence-agent-configuration", variables => { description => $agent_description, options => $option_form, note => $anvil->Words->string({key => "striker_0218", variables => { name => $fence_agent }}), }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); } else { # Show the main menu show_fence_config_main_menu($anvil); } return(0); } # This sanity checks the fence agent forms. sub sanity_check_fence_agent_form { my ($anvil, $fence_agent) = @_; my $sane = 1; my $confirn_form = ""; foreach my $i (1..$anvil->data->{cgi}{fence_count}{value}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { i => $i }}); # Make sure there is a fence name. my $fence_name_key = "fence_name_".$i; if (not $anvil->data->{cgi}{$fence_name_key}{value}) { $sane = 0; $anvil->data->{cgi}{$fence_name_key}{alert} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "cgi::${fence_name_key}::alert" => $anvil->data->{cgi}{$fence_name_key}{alert}, sane => $sane, }}); } else { # It's good, add it manually to the hash. $anvil->data->{fence}{confirm_table}{data}{fence_name}{$i}{'default'} = 0; $anvil->data->{fence}{confirm_table}{data}{fence_name}{$i}{value} = $anvil->data->{cgi}{$fence_name_key}{value}; $anvil->data->{fence}{confirm_table}{data}{fence_name}{$i}{say_value} = $anvil->data->{cgi}{$fence_name_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "fence::confirm_table::data::fence_name::${i}::default" => $anvil->data->{fence}{confirm_table}{data}{fence_name}{$i}{'default'}, "fence::confirm_table::data::fence_name::${i}::value" => $anvil->data->{fence}{confirm_table}{data}{fence_name}{$i}{value}, "fence::confirm_table::data::fence_name::${i}::say_value" => $anvil->data->{fence}{confirm_table}{data}{fence_name}{$i}{say_value}, }}); } # Read in the parameters for this agent, and compare to see if the value passed in differs. foreach my $name (sort {$a cmp $b} keys %{$anvil->data->{fence_data}{$fence_agent}{parameters}}) { # We don't show deprecated or replaced options. next if $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{replacement}; next if $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{deprecated}; my $option_key = $name."_".$i; my $unique = $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{unique}; my $required = $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{required}; my $description = $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{description}; my $type = $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{content_type}; my $default = exists $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{'default'} ? $anvil->data->{fence_data}{$fence_agent}{parameters}{$name}{'default'} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 's1:name' => $name, 's2:option_key' => $option_key, 's3:unique' => $unique, 's4:required' => $required, 's5:description' => $description, 's6:type' => $type, 's7:default' => $default, }}); # If this is 'boolean' and the default is '1', change the default to 'on' so that # it matches what we get from the form. if (($type eq "boolean") && ($default eq "1")) { $default = "on"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'default' => $default }}); } my $is_default = 1; my $passed_parameter_key = $name."_".$i; my $passed_value = defined $anvil->data->{cgi}{$passed_parameter_key}{value} ? $anvil->data->{cgi}{$passed_parameter_key}{value} : ""; my $say_value = $passed_value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { passed_parameter_key => $passed_parameter_key, passed_value => $passed_value, 'default' => $default, }}); if ($type eq "boolean") { $say_value = ""; if (defined $passed_value) { # Yes No $say_value = $passed_value ? "#!string!unit_0001!#" : "#!string!unit_0002!#"; } else { # Yes No $say_value = $default ? "#!string!unit_0001!#" : "#!string!unit_0002!#"; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_value => $say_value }}); } elsif ((($type eq "string") or ($type eq "select")) && ($passed_value eq "")) { $say_value = "--"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_value => $say_value }}); } # We always store the action, then anything else that isn't default. if (($passed_value ne $default) or ($name eq "action")) { # Something changed. Is it sane? $is_default = 0; if (($type eq "integer") or ($type eq "second")) { # Make sure the value is a bare integer if ($passed_value =~ /\D/) { # Problem. $sane = 0; $anvil->data->{cgi}{$passed_parameter_key}{alert} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "cgi::${passed_parameter_key}::alert" => $anvil->data->{cgi}{$passed_parameter_key}{alert}, sane => $sane, }}); } } # This will be used to assemble the base shell call later $anvil->data->{fence}{$fence_agent}{set}{$i}{parameter}{$name}{set} = $passed_value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "fence::${fence_agent}::set::${i}::parameter::${name}::set" => $anvil->data->{fence}{$fence_agent}{set}{$i}{parameter}{$name}{set}, }}); } $anvil->data->{fence}{confirm_table}{data}{$name}{$i}{'default'} = $is_default; $anvil->data->{fence}{confirm_table}{data}{$name}{$i}{value} = $passed_value ? $passed_value : $default; $anvil->data->{fence}{confirm_table}{data}{$name}{$i}{say_value} = $say_value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "fence::confirm_table::data::${name}::${i}::default" => $anvil->data->{fence}{confirm_table}{data}{$name}{$i}{'default'}, "fence::confirm_table::data::${name}::${i}::value" => $anvil->data->{fence}{confirm_table}{data}{$name}{$i}{value}, "fence::confirm_table::data::${name}::${i}::say_value" => $anvil->data->{fence}{confirm_table}{data}{$name}{$i}{say_value}, }}); } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { sane => $sane }}); return($sane); } sub show_fence_config_main_menu { my ($anvil) = @_; # Read in known fence devices $anvil->Database->get_fences({debug => 3}); # Get a list of current fence agents. my $existing_fences = ""; if (exists $anvil->data->{fences}{fence_uuid}) { # How many do we have? my $fence_count = keys %{$anvil->data->{fences}{fence_name}}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { fence_count => $fence_count }}); if ($fence_count) { # We've got devices. my $fence_devices = ""; foreach my $fence_name (sort {$a cmp $b} keys %{$anvil->data->{fences}{fence_name}}) { my $fence_uuid = $anvil->data->{fences}{fence_name}{$fence_name}{fence_uuid}; my $fence_agent = $anvil->data->{fences}{fence_name}{$fence_name}{fence_agent}; my $fence_arguments = $anvil->data->{fences}{fence_name}{$fence_name}{fence_arguments}; my $say_fence_device = $fence_agent." ".$fence_arguments; $say_fence_device =~ s/passw(\w+)="(.*?)"/passw$1="--"/g; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { fence_uuid => $fence_uuid, fence_agent => $fence_agent, fence_arguments => $fence_arguments =~ /passw=/ ? $anvil->Log->is_secure($fence_arguments) : $fence_arguments, say_fence_device => $say_fence_device, }}); $fence_devices .= $anvil->Template->get({file => "anvil.html", name => "existing-fence-device-entry", variables => { name => $fence_name, arguments => $say_fence_device, fence_agent => $fence_agent, fence_uuid => $fence_uuid, }}); } $existing_fences .= $anvil->Template->get({file => "anvil.html", name => "existing-fence-devices", variables => { devices => $fence_devices, }}); } } # For each agent, we'll create a
with it's options that will be shown/hidden basen on the agent # select box. my $agents = []; my $description_form = ""; foreach my $fence_agent (sort {$a cmp $b} keys %{$anvil->data->{fence_data}}) { # We don't care about IPMI-based fence agents here. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { fence_agent => $fence_agent }}); next if $fence_agent eq "fence_drac5"; next if $fence_agent eq "fence_idrac"; next if $fence_agent =~ /^fence_ilo/; next if $fence_agent eq "fence_imm"; next if $fence_agent eq "fence_ipmilan"; next if $fence_agent eq "fence_redfish"; next if $fence_agent eq "fence_rsa"; push @{$agents}, $fence_agent; my $agent_description = format_fence_description($anvil, $fence_agent, $anvil->data->{fence_data}{$fence_agent}{description}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { agent_description => $agent_description }}); $description_form .= $anvil->Template->get({file => "anvil.html", name => "fence-agent-description", variables => { name => $fence_agent, description => $agent_description, }}); } my $fence_agent_select = $anvil->Template->select_form({ name => "fence_agent", options => $agents, blank => 0, 'sort' => 1, selected => $anvil->data->{cgi}{fence_agent}{value} ? $anvil->data->{cgi}{fence_agent}{value} : "fence_apc_snmp", class => "input_clear", }); my $fence_count_select = $anvil->Template->select_form({ name => "fence_count", options => [1, 2, 3, 4], blank => 0, 'sort' => 0, selected => $anvil->data->{cgi}{fence_count}{value}, class => "input_clear", }); $anvil->data->{form}{back_link} = "?anvil=true&task=create"; $anvil->data->{form}{refresh_link} = "?anvil=true&task=fences"; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "fence-agent-menu", variables => { fence_select => $fence_agent_select, fence_count => $fence_count_select, descriptions => $description_form, existing_devices => $existing_fences, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); return(0); } sub format_fence_description { my ($anvil, $fence_agent, $agent_description) = @_; # Replace newlines with
elements. $agent_description =~ s/\n/
/gs; $agent_description =~ s/
/
\n/gs; # Handle fence_azure_arm. if ($fence_agent eq "fence_azure_arm") { my $in_pre = 0; my $break_number = 0; my $new_desctiption = ""; foreach my $line (split/\n/, $agent_description) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }}); if ($line =~ /\+---/) { $line =~ s/
//g; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { break_number => $break_number }}); if (not $break_number) { $in_pre = 1; $new_desctiption .= "
\n";
					$new_desctiption .= $line."\n";
					$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { new_desctiption => $new_desctiption }});
				}
				elsif ($break_number == 2)
				{
					$in_pre          =  0;
					$new_desctiption .= $line."\n";
					$new_desctiption .= "
\n"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { new_desctiption => $new_desctiption }}); } else { $new_desctiption .= $line."\n"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { new_desctiption => $new_desctiption }}); } $break_number++; } else { if ($in_pre) { $line =~ s/
//g; } $new_desctiption .= $line."\n"; } } $agent_description = $new_desctiption; } return($agent_description); } # This handles configuring a remote target's network interfaces (renaming them, bonding and bridging them). sub process_prep_network { my ($anvil) = @_; # Do I know which machine we're configuring? if (not $anvil->data->{cgi}{host_uuid}{value}) { # Nope, send the user back. $anvil->data->{cgi}{task}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::task::value" => $anvil->data->{cgi}{task}{value} }}); process_anvil_menu($anvil); return(0); } my $host_uuid = $anvil->data->{cgi}{host_uuid}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); # Pull the host's data out of the JSON file. $anvil->Striker->parse_all_status_json(); my $host_type = ""; my $host_name = ""; foreach my $host (sort {$a cmp $b} keys %{$anvil->data->{json}{all_status}{hosts}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "cgi::host_uuid::value" => $anvil->data->{cgi}{host_uuid}{value}, "json::all_status::hosts::${host}::host_uuid" => $anvil->data->{json}{all_status}{hosts}{$host}{host_uuid}, }}); if ($anvil->data->{cgi}{host_uuid}{value} eq $anvil->data->{json}{all_status}{hosts}{$host}{host_uuid}) { # Found it. $host_name = $host; $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_name => $host_name, host_type => $host_type, }}); last; } } if (not $host_name) { # Didn't find it. my $message = $anvil->Words->string({key => "warning_0014", variables => { host_uuid => $anvil->data->{cgi}{host_uuid}{value} } }); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $message }}); $anvil->data->{cgi}{task}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::task::value" => $anvil->data->{cgi}{task}{value}, "form::error_massage" => $anvil->data->{form}{error_massage}, }}); process_anvil_menu($anvil); return(0); } # Is the user going back to the form? if (($anvil->data->{cgi}{save}{value} eq "true") && ($anvil->data->{cgi}{back}{value})) { # User is going back. $anvil->data->{cgi}{save}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::save::value" => $anvil->data->{cgi}{save}{value} }}); } # How many actual interfaces do we have? We need at least six. For each two above that, we'll add an # additional bond option per network. my $interfaces = {}; my $interface_options = []; foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{interface}}) { # if any interfaces are called 'virbrX-nic', ignore it as it will be removed. Likewise, ignore any 'vnetX' devices. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { interface => $interface }}); if (($interface =~ /^virbr\d+-nic/) or ($interface =~ /^vnet\d+/)) { # Ignore it. next; } # Store the mac used in the select box my $mac_address = $anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{interface}{$interface}{mac_address}; push @{$interface_options}, $mac_address."#!#".$interface." (".$mac_address.")"; # Store the mac address . $interfaces->{$interface} = $mac_address; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "interfaces->{".$interface."}" => $interfaces->{$interface} }}); } # Get the interface count my $interface_count = keys %{$interfaces}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { interface_count => $interface_count }}); if (($host_type eq "node") && ($interface_count < 6)) { # Not enough interfaces. $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0015", variables => { interface_count => $interface_count } }) }}); $anvil->data->{cgi}{task}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "cgi::task::value" => $anvil->data->{cgi}{task}{value}, "form::error_massage" => $anvil->data->{form}{error_massage}, }}); process_anvil_menu($anvil); } # TODO: For now, we're only allowing one BCN, SN and MN. So at this time, we'll show one BCN pair, # one SN pair, one MN pair and N-IFN pairs. my $bcn_pair_count = 1; my $sn_pair_count = 1; my $mn_pair_count = $interface_count > 6 ? 1 : 0; my $ifn_pair_count = int(($interface_count - 6) / 2); $ifn_pair_count = 1 if $ifn_pair_count < 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bcn_pair_count => $bcn_pair_count, sn_pair_count => $sn_pair_count, ifn_pair_count => $ifn_pair_count, mn_pair_count => $mn_pair_count, }}); ### NOTE: The weird 'form::config_step2::::value is from reusing the logic used back when ### Striker's config was made. It's not the best, but it does the job. Would be nice to redo ### the logic later. # Are we saving? if ($anvil->data->{cgi}{save}{value} eq "true") { # Clear the network map variable. $anvil->Database->insert_or_update_variables({ variable_name => "config::map_network", variable_value => 0, variable_default => 0, variable_description => "striker_0202", variable_section => "config", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); # Is the form sane? my $sane = 1; my $interfaces = ""; my $error = 0; my $gateway_interface = ""; if ($anvil->data->{cgi}{host_name}{value}) { # Is the host name sane? if (not $anvil->Validate->domain_name({name => $anvil->data->{cgi}{host_name}{value}})) { # Nope my $error_message = $anvil->Words->string({key => "error_0012", variables => { host_name => $anvil->data->{cgi}{host_name}{value} }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); $anvil->data->{cgi}{host_name}{alert} = 1; } else { $anvil->Database->insert_or_update_variables({ variable_name => "form::config_step2::host_name::value", variable_value => $anvil->data->{cgi}{host_name}{value}, variable_default => "", variable_description => "striker_0159", variable_section => "config_step2", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); } } if ($anvil->data->{cgi}{gateway}{value}) { # Is if valid? if (not $anvil->Validate->ipv4({ip => $anvil->data->{cgi}{gateway}{value}})) { # Bad IP my $error_message = $anvil->Words->string({key => "warning_0010", variables => { ip_address => $anvil->data->{cgi}{gateway}{value} }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); $anvil->data->{cgi}{gateway}{alert} = 1; } else { # It's sane, record it. $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step2::gateway::value", variable_value => $anvil->data->{cgi}{gateway}{value}, variable_default => "", variable_description => "striker_0036", variable_section => "config_step2", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); } } if ($anvil->data->{cgi}{dns}{value}) { foreach my $dns (split/,/, $anvil->data->{cgi}{dns}{value}) { $dns =~ s/^\s+//; $dns =~ s/\s+$//; if (not $anvil->Validate->ipv4({ip => $dns})) { # Bad IP $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0010", variables => { ip_address => $anvil->data->{cgi}{dns}{value} }}) }}); $anvil->data->{cgi}{dns}{alert} = 1; } last if $anvil->data->{cgi}{dns}{alert}; } if (not $anvil->data->{cgi}{dns}{alert}) { # It's sane, record it. $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step2::dns::value", variable_value => $anvil->data->{cgi}{dns}{value}, variable_default => "", variable_description => "striker_0038", variable_section => "config_step2", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); } } foreach my $network ("bcn", "sn", "mn", "ifn") { my $count_key = $network."_count"; my $loops = $anvil->data->{cgi}{$count_key}{value}; # Store the network counts. $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step1::".$count_key."::value", variable_value => $anvil->data->{cgi}{$count_key}{value}, variable_default => "", variable_description => "striker_0163", variable_section => "config_step1", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); foreach my $i (1..$loops) { my $this_network = $network.$i; my $bridge_key = $this_network."_create_bridge"; my $ip_key = $this_network."_ip"; my $subnet_key = $this_network."_subnet_mask"; my $link1_key = $this_network."_link1_mac_to_set"; my $link2_key = $this_network."_link2_mac_to_set"; my $say_network = $anvil->Words->string({key => "striker_0018", variables => { number => $i }}); if ($network eq "sn") { $say_network = $anvil->Words->string({key => "striker_0020", variables => { number => $i }}); } elsif ($network eq "mn") { $say_network = $anvil->Words->string({key => "striker_0299", variables => { number => $i }}); } elsif ($network eq "ifn") { $say_network = $anvil->Words->string({key => "striker_0022", variables => { number => $i }}); } my $link1_interface = ""; my $link2_interface = ""; foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{interface}}) { my $mac_address = $anvil->data->{json}{all_status}{hosts}{$host_name}{network_interface}{interface}{$interface}{mac_address}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { interface => $interface, mac_address => $mac_address, }}); if ($mac_address eq $anvil->data->{cgi}{$link1_key}{value}) { $link1_interface = $interface; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { link1_interface => $link1_interface }}); } elsif ($mac_address eq $anvil->data->{cgi}{$link2_key}{value}) { $link2_interface = $interface; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { link2_interface => $link2_interface }}); } last if (($link1_interface) && ($link2_interface)); } my $say_bridge = "#!string!unit_0002!#"; if ($anvil->data->{cgi}{$bridge_key}{value}) { # We're making a bridge. $say_bridge = "#!string!unit_0001!#"; } my $say_ip_address = "#!string!striker_0152!#"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_ip_address => $say_ip_address }}); if (($anvil->data->{cgi}{$ip_key}{value}) && (not $anvil->Validate->ipv4({ip => $anvil->data->{cgi}{$ip_key}{value}}))) { # Bad IP $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0010", variables => { ip_address => $anvil->data->{cgi}{$ip_key}{value} }}) }}); $anvil->data->{cgi}{$ip_key}{alert} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::error_massage" => $anvil->data->{form}{error_massage}, "cgi::${ip_key}::alert" => $anvil->data->{cgi}{$ip_key}{alert}, }}); } elsif (($anvil->data->{cgi}{$subnet_key}{value}) && (not $anvil->Validate->subnet_mask({subnet_mask => $anvil->data->{cgi}{$subnet_key}{value}}))) { # Bad subnet $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0017"}) }}); $anvil->data->{cgi}{$subnet_key}{alert} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::error_massage" => $anvil->data->{form}{error_massage}, "cgi::${subnet_key}::alert" => $anvil->data->{cgi}{$subnet_key}{alert}, }}); } elsif (($anvil->data->{cgi}{$ip_key}{value}) && (not $anvil->data->{cgi}{$subnet_key}{value})) { # IP without a subnet $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0018"}) }}); $anvil->data->{cgi}{$subnet_key}{alert} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::error_massage" => $anvil->data->{form}{error_massage}, "cgi::${subnet_key}::alert" => $anvil->data->{cgi}{$subnet_key}{alert}, }}); } else { ### Things are sane. # Does this network have an IP or is it dhcp? $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "cgi::${ip_key}::value" => $anvil->data->{cgi}{$ip_key}{value} }}); if ($anvil->data->{cgi}{$ip_key}{value}) { $say_ip_address = $anvil->data->{cgi}{$ip_key}{value}."/".$anvil->data->{cgi}{$subnet_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_ip_address => $say_ip_address }}); $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step2::".$ip_key."::value", variable_value => $anvil->data->{cgi}{$ip_key}{value}, variable_default => "", variable_description => "striker_0153,!!say_network!".$say_network."!!", variable_section => "config_step2", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step2::".$subnet_key."::value", variable_value => $anvil->data->{cgi}{$subnet_key}{value}, variable_default => "", variable_description => "striker_0154,!!say_network!".$say_network."!!", variable_section => "config_step2", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); } # Is this the network with the subnet mask? if ((not $gateway_interface) && ($anvil->data->{cgi}{gateway}{value}) && (not $anvil->data->{cgi}{gateway}{alert}) && ($anvil->data->{cgi}{$ip_key}{value})) { my $match = $anvil->Network->is_ip_in_network({ network => $anvil->data->{cgi}{$ip_key}{value}, subnet_mask => $anvil->data->{cgi}{$subnet_key}{value}, ip => $anvil->data->{cgi}{gateway}{value}, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { match => $match }}); if ($match) { # Found the match! if ($anvil->data->{cgi}{$ip_key}{value}) { $say_ip_address .= ",
  #!string!striker_0026!#: ".$anvil->data->{cgi}{gateway}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_ip_address => $say_ip_address }}); } # DNS? if (($anvil->data->{cgi}{dns}{value}) && (not $anvil->data->{cgi}{dns}{alert}) && ($anvil->data->{cgi}{$ip_key}{value})) { $say_ip_address .= ",
  #!string!striker_0037!#: ".$anvil->data->{cgi}{dns}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_ip_address => $say_ip_address }}); } $gateway_interface = $this_network; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { gateway_interface => $gateway_interface }}); $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step2::gateway_interface::value", variable_value => $gateway_interface, variable_default => "", variable_description => "striker_0155", variable_section => "config_step2", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); } } } if (not $anvil->data->{cgi}{$ip_key}{value}) { # Record this as DHCP. $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step2::".$ip_key."::value", variable_value => "dhcp", variable_default => "", variable_description => "striker_0160", variable_section => "config_step2", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); } # Last check, are the interfaces defined? All $i == 1 interfaces need to be # defined. Any 2+ are allowed to be ignored, _IF_ neither link is selected # AND neither the IP/subnet are blank. if ((not $anvil->data->{cgi}{$link1_key}{value}) && (not $anvil->data->{cgi}{$link2_key}{value})) { # If this is network 1, both are required. if (($host_type eq "node") && ($i == 1)) { # Required. my $error_message = $anvil->Words->string({key => "warning_0021"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); $anvil->data->{cgi}{$link1_key}{value} = 1; $anvil->data->{cgi}{$link2_key}{value} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::error_massage" => $anvil->data->{form}{error_massage}, "cgi::${link1_key}::alert" => $anvil->data->{cgi}{$link1_key}{alert}, "cgi::${link2_key}::alert" => $anvil->data->{cgi}{$link2_key}{alert}, }}); } } elsif (not $anvil->data->{cgi}{$link1_key}{value}) { # link 1 is missing. my $error_message = $anvil->Words->string({key => "warning_0022"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); $anvil->data->{cgi}{$link1_key}{value} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::error_massage" => $anvil->data->{form}{error_massage}, "cgi::${link1_key}::alert" => $anvil->data->{cgi}{$link1_key}{alert}, }}); } elsif (not $anvil->data->{cgi}{$link2_key}{value}) { # link 2 is missing. my $error_message = $anvil->Words->string({key => "warning_0022"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); $anvil->data->{cgi}{$link2_key}{value} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::error_massage" => $anvil->data->{form}{error_massage}, "cgi::${link2_key}::alert" => $anvil->data->{cgi}{$link2_key}{alert}, }}); } elsif (($anvil->data->{cgi}{$ip_key}{value}) && (not $anvil->data->{cgi}{$link1_key}{value})) { # There's an IP address but no interfaces selected. my $error_message = $anvil->Words->string({key => "warning_0022"}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); $anvil->data->{cgi}{$link1_key}{value} = 1; $anvil->data->{cgi}{$link2_key}{value} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::error_massage" => $anvil->data->{form}{error_massage}, "cgi::${link1_key}::alert" => $anvil->data->{cgi}{$link1_key}{alert}, "cgi::${link2_key}::alert" => $anvil->data->{cgi}{$link2_key}{alert}, }}); } # Now save the link info, if selected. if ($anvil->data->{cgi}{$link1_key}{value}) { $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step2::".$link1_key."::value", variable_value => $anvil->data->{cgi}{$link1_key}{value}, variable_default => "", variable_description => "striker_0156", variable_section => "config_step2", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); } if ($anvil->data->{cgi}{$link2_key}{value}) { $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step2::".$link2_key."::value", variable_value => $anvil->data->{cgi}{$link2_key}{value}, variable_default => "", variable_description => "striker_0157", variable_section => "config_step2", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); } # Store the bridge key $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step2::".$bridge_key."::value", variable_value => $anvil->data->{cgi}{$bridge_key}{value}, variable_default => "", variable_description => "striker_0158", variable_section => "config_step2", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); $interfaces .= $anvil->Template->get({file => "anvil.html", name => "interface-entry", variables => { network => $say_network, primary => $link1_interface." (".$anvil->data->{cgi}{$link1_key}{value}.")", link1_key => $link1_key, link1_value => $anvil->data->{cgi}{$link1_key}{value}, secondary => $link2_interface." (".$anvil->data->{cgi}{$link2_key}{value}.")", link2_key => $link2_key, link2_value => $anvil->data->{cgi}{$link2_key}{value}, bridge => $say_bridge, say_ip => $say_ip_address, ip_key => $ip_key, ip_address => $anvil->data->{cgi}{$ip_key}{value}, subnet_key => $subnet_key, subnet_mask => $anvil->data->{cgi}{$subnet_key}{value}, bridge_key => $bridge_key, bridge_value => $anvil->data->{cgi}{$bridge_key}{value}, }}); } } # Did we see an error? $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); if ($anvil->data->{form}{error_massage}) { # Yup, not sane, send the user back to the form. $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); } # Confirmed? if (($anvil->data->{cgi}{confirm}{value}) && ($sane)) { # Yes, save the job. my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ debug => 3, file => $THIS_FILE, line => __LINE__, job_host_uuid => $anvil->data->{cgi}{host_uuid}{value}, job_command => $anvil->data->{path}{exe}{'anvil-configure-host'}.$anvil->Log->switches, job_data => "form::config_step2", job_name => "configure::network", job_title => "job_0001", job_description => "job_0071", job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { job_uuid => $job_uuid }}); # We don't need to store anything as hidden variables, we'll read it back from the database later. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "network_job_recorded", variables => { reload_url => "/cgi-bin/".$THIS_FILE."?anvil=true", title => "#!string!striker_0044!#", description => "#!string!striker_0045!#", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); return(0); } else { # Show the confirmation box. $anvil->data->{form}{back_link} = $anvil->data->{sys}{cgi_string}; $anvil->data->{form}{back_link} =~ s/step=step2//; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "config-network-confirm", variables => { host_name => $host_name, host_uuid => $anvil->data->{cgi}{host_uuid}{value}, gateway_interface => $gateway_interface, interfaces => $interfaces, bcn_count => $bcn_pair_count, sn_count => $sn_pair_count, ifn_count => $ifn_pair_count, mn_count => $mn_pair_count, gateway => $anvil->data->{cgi}{gateway}{value}, dns => $anvil->data->{cgi}{dns}{value}, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); return(0); } } else { # We're mapping $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "config::map_network", variable_value => 1, variable_default => 0, variable_description => "striker_0202", variable_section => "config", variable_source_uuid => $anvil->data->{cgi}{host_uuid}{value}, variable_source_table => "hosts", }); } my $interface_form = ""; # NOTE: We don't assign IPs at this point, unless the user manually sets one. We'll set all to 'dhcp' # until set during the Anvil! build later. foreach my $network ("bcn", "sn", "mn", "ifn") { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { network => $network }}); my $name_key = ""; my $description_key = ""; my $count = 1; if ($network eq "bcn") { $name_key = "striker_0018"; $description_key = "striker_0019"; $count = $bcn_pair_count; } elsif ($network eq "sn") { $name_key = "striker_0020"; $description_key = "striker_0021"; $count = $sn_pair_count; } elsif ($network eq "ifn") { $name_key = "striker_0022"; $description_key = "striker_0023"; $count = $ifn_pair_count; } elsif ($network eq "mn") { $name_key = "striker_0299"; $description_key = "striker_0300"; $count = $mn_pair_count; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { name_key => $name_key, description_key => $description_key, count => $count, }}); foreach my $i (1..$count) { my $this_ip_key = $network.$i."_ip"; my $this_subnet_mask_key = $network.$i."_subnet_mask"; my $this_iface1_key = $network.$i."_link1_mac_to_set"; my $this_iface2_key = $network.$i."_link2_mac_to_set"; my $this_ip = exists $anvil->data->{cgi}{$this_ip_key}{value} ? $anvil->data->{cgi}{$this_ip_key}{value} : "dhcp"; my $this_ip_class = $anvil->data->{cgi}{$this_ip_key}{alert} ? "input_alert" : "input_clear"; my $this_subnet_mask_class = $anvil->data->{cgi}{$this_subnet_mask_key}{alert} ? "input_alert" : "input_clear"; my $this_iface1_class = $anvil->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear"; my $this_iface2_class = $anvil->data->{cgi}{$this_iface2_key}{alert} ? "input_alert" : "input_clear"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { this_ip_key => $this_ip_key, this_subnet_mask_key => $this_subnet_mask_key, this_iface1_key => $this_iface1_key, this_iface2_key => $this_iface2_key, this_ip => $this_ip, this_ip_class => $this_ip_class, this_subnet_mask_class => $this_subnet_mask_class, this_iface1_class => $this_iface1_class, this_iface2_class => $this_iface2_class, }}); # Build the interface select boxes... my $this_iface1_form = $anvil->Template->select_form({ name => $this_iface1_key, options => $interface_options, blank => 1, 'sort' => 0, selected => defined $anvil->data->{cgi}{$this_iface1_key}{value} ? $anvil->data->{cgi}{$this_iface1_key}{value} : "", class => $anvil->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear", }); my $this_iface2_form = $anvil->Template->select_form({ name => $this_iface2_key, options => $interface_options, blank => 1, 'sort' => 0, selected => defined $anvil->data->{cgi}{$this_iface2_key}{value} ? $anvil->data->{cgi}{$this_iface2_key}{value} : "", class => $anvil->data->{cgi}{$this_iface2_key}{alert} ? "input_alert" : "input_clear", }); # Assemble the form $interface_form .= $anvil->Template->get({file => "anvil.html", name => "network_interface_form", variables => { field => $anvil->Words->string({key => $name_key, variables => { number => $i }}), description => "#!string!".$description_key."!#", ip_key => $this_ip_key, ip_value => defined $anvil->data->{cgi}{$this_ip_key}{value} ? $anvil->data->{cgi}{$this_ip_key}{value} : "", ip_value_default => $this_ip, ip_class => $this_ip_class, subnet_mask_key => $this_subnet_mask_key, subnet_mask_value => defined $anvil->data->{cgi}{$this_subnet_mask_key}{value} ? $anvil->data->{cgi}{$this_subnet_mask_key}{value} : "", subnet_mask_value_default => $anvil->data->{defaults}{network}{bcn}{subnet_mask}, subnet_mask_class => $this_subnet_mask_class, iface1_select => $this_iface1_form, iface2_select => $this_iface2_form, network_name => $network.$i, create_bridge => (($network eq "sn") or ($network eq "mn")) ? 0 : 1, }}); } } # Host name my $say_host_name = defined $anvil->data->{cgi}{host_name}{value} ? $anvil->data->{cgi}{host_name}{value} : $host_name; my $host_name_class = $anvil->data->{cgi}{host_name}{alert} ? "input_alert" : "input_clear"; my $host_name_form = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "host_name", id => "host_name", field => "#!string!striker_0016!#", description => "#!string!striker_0143!#", value => defined $anvil->data->{cgi}{host_name}{value} ? $anvil->data->{cgi}{host_name}{value} : $say_host_name, default_value => "", class => $host_name_class, extra => "", }}); ### NOTE: We'll figure out the IFN this belongs to by matching the DG to one of the IFN IPs. # Gateway my $gateway_class = $anvil->data->{cgi}{gateway}{alert} ? "input_alert" : "input_clear"; my $say_gateway = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "gateway", id => "gateway", field => "#!string!striker_0035!#", description => "#!string!striker_0144!#", value => defined $anvil->data->{cgi}{gateway}{value} ? $anvil->data->{cgi}{gateway}{value} : "", default_value => "", class => $gateway_class, extra => "", }}); # DNS my $dns_class = $anvil->data->{cgi}{dns}{alert} ? "input_alert" : "input_clear"; my $say_dns = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "dns", id => "dns", field => "#!string!striker_0037!#", description => "#!string!striker_0038!#", value => defined $anvil->data->{cgi}{dns}{value} ? $anvil->data->{cgi}{dns}{value} : "", default_value => $anvil->data->{defaults}{network}{dns}, class => $dns_class, extra => "", }}); # Store the previous CGI variables and display the new fields. $anvil->data->{form}{back_link} = "?anvil=true"; $anvil->data->{cgi}{task}{value} = "" if not defined $anvil->data->{cgi}{task}{value}; $anvil->data->{cgi}{action}{value} = "" if not defined $anvil->data->{cgi}{action}{value}; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "config-network-main", variables => { interface_form => $interface_form, gateway_form => $say_gateway, dns_form => $say_dns, host_name_form => $host_name_form, bcn_count => $bcn_pair_count, sn_count => $sn_pair_count, ifn_count => $ifn_pair_count, mn_count => $mn_pair_count, host_uuid => $anvil->data->{cgi}{host_uuid}{value}, host_name => $host_name, # This is the current host name, used to find the data in the all_status.json }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); return(0); } # This handles installing our repo, installing the appropriate 'anvil-X' rpm, running OS updates if selected # and configuring the network on a machine destined to be an Anvil! node or DR host. sub process_prep_host_page { my ($anvil) = @_; my $host_name = defined $anvil->data->{cgi}{host_name}{value} ? $anvil->data->{cgi}{host_name}{value} : ""; my $host_uuid = defined $anvil->data->{cgi}{host_uuid}{value} ? $anvil->data->{cgi}{host_uuid}{value} : ""; my $default_host_name = defined $anvil->data->{cgi}{default_host_name}{value} ? $anvil->data->{cgi}{default_host_name}{value} : ""; my $host_ip_address = defined $anvil->data->{cgi}{host_ip_address}{value} ? $anvil->data->{cgi}{host_ip_address}{value} : ""; my $host_password = defined $anvil->data->{cgi}{host_password}{value} ? $anvil->data->{cgi}{host_password}{value} : ""; my $rh_user = defined $anvil->data->{cgi}{rh_user}{value} ? $anvil->data->{cgi}{rh_user}{value} : ""; my $rh_password = defined $anvil->data->{cgi}{rh_password}{value} ? $anvil->data->{cgi}{rh_password}{value} : ""; my $type = defined $anvil->data->{cgi}{type}{value} ? $anvil->data->{cgi}{type}{value} : ""; my $connect = defined $anvil->data->{cgi}{'connect'}{value} ? $anvil->data->{cgi}{'connect'}{value} : ""; my $confirm = defined $anvil->data->{cgi}{confirm}{value} ? $anvil->data->{cgi}{confirm}{value} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_name => $host_name, host_uuid => $host_uuid, default_host_name => $default_host_name, host_ip_address => $host_ip_address, host_password => $anvil->Log->is_secure($host_password), rh_user => $rh_user, rh_password => $anvil->Log->is_secure($rh_password), type => $type, 'connect' => $connect, confirm => $confirm, }}); # Is the IP or host name valid? my $ssh_port = 22; if ($host_ip_address =~ /:(\d+)$/) { $ssh_port = $1; $host_ip_address =~ s/:(\d+)$//; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ssh_port => $ssh_port, host_ip_address => $host_ip_address, }}); # If we've been passed 'connect', verify we can connect. if (($connect) && ($confirm)) { # Save the job my $job_command = $anvil->data->{path}{exe}{'striker-initialize-host'}.$anvil->Log->switches; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_command => $job_command, password => $anvil->Log->is_secure($host_password), }}); # Update the database to mark this machine as unconfigured (in case we're rebuilding a # previously known system). This is needed to get the netweork link state info updating. if ($host_uuid) { $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "system::configured", variable_source_uuid => $host_uuid, variable_source_table => "hosts", variable_value => 0, update_value_only => 1, }); } # Are we setting a host name? my $say_host_name = "host_name=\n"; if (($host_name) && ($host_name ne $default_host_name)) { $say_host_name = "host_name=".$host_name."\n"; } # Store the peer's password as the job data my $job_data = "password=".$host_password."\n"; $job_data .= "rh_password=".$rh_password."\n"; $job_data .= "rh_user=".$rh_user."\n"; $job_data .= "host_ip_address=".$host_ip_address."\n"; $job_data .= "ssh_port=".$ssh_port."\n"; $job_data .= "type=".$type."\n"; $job_data .= $say_host_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { job_data => $job_data }}); # Store the job my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ debug => 3, file => $THIS_FILE, line => __LINE__, job_command => $job_command, job_data => $job_data, job_name => "initialize::".$type."::".$host_ip_address, job_title => $type eq "dr" ? "job_0021" : "job_0020", job_description => "job_0022", job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); # We don't need to store anything as hidden variables, we'll read it back from the database # later. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "job recorded", variables => { title_id => "", message_id => "", reload_url => "/cgi-bin/".$THIS_FILE."?anvil=true&", title => "#!string!striker_0044!#", description => "#!string!striker_0129!#", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); } elsif ($connect) { if (not $anvil->Validate->ipv4({ip => $host_ip_address})) { # Bad IP $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0010", variables => { ip_address => $host_ip_address }}) }}); } elsif (($ssh_port < 1) or ($ssh_port > 65535)) { # Bad port $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0011"}) }}); } else { # Can we connect? my $target_host_name = ""; my $target_host_uuid = ""; my $has_internet = 0; my ($connected, $data) = $anvil->Striker->get_peer_data({ debug => 2, target => $host_ip_address, password => $host_password, port => $ssh_port, }); foreach my $key (sort {$a cmp $b} keys %{$data}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "data->{$key}" => $data->{$key} }}); } if ($data->{host_name}) { # We collect this, but apparently not for any real reason... $target_host_name = $data->{host_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target_host_name => $target_host_name }}); } if ($data->{host_uuid}) { $target_host_uuid = $data->{host_uuid}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target_host_uuid => $target_host_uuid }}); } if ($data->{internet}) { $has_internet = $data->{internet}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { has_internet => $has_internet }}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target_host_name => $target_host_name, target_host_uuid => $target_host_uuid, }}); # If the target is RHEL and it is not registered, offer the user to provide the RH user and password. my $redhat_message = ""; my $redhat_form = ""; if (($data->{host_os} =~ /^rhel/) && ($data->{os_registered} ne "yes")) { # If we don't have internet access, tell the user they can register later. if ($has_internet) { $redhat_message = $anvil->Template->get({file => "anvil.html", name => "host-setup-redhat-message", variables => { message => "#!string!message_0148!#" }}); $redhat_form = $anvil->Template->get({file => "anvil.html", name => "host-setup-redhat-form", variables => { rh_user => $rh_user, rh_password => $rh_password, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { redhat_form => $redhat_form, redhat_message => $redhat_message, }}); } else { $redhat_message = $anvil->Template->get({file => "anvil.html", name => "host-setup-redhat-message", variables => { message => "#!string!message_0151!#" }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { redhat_message => $redhat_message }}); } } elsif (not $has_internet) { $redhat_message = $anvil->Template->get({file => "anvil.html", name => "host-setup-redhat-message", variables => { message => "#!string!message_01512#" }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { redhat_message => $redhat_message }}); } # Did we connect? if (not $connected) { # Nope. Is it because the target's key is bad or has changed? my $query = "SELECT state_uuid, state_note FROM states WHERE state_name LIKE ".$anvil->Database->quote("host_key_changed::".$host_ip_address).";"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); if ($count) { # Yup, key has changed. my $state_uuid = $results->[0]->[0]; my $state_note = $results->[0]->[1]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { state_uuid => $state_uuid, state_note => $state_note, }}); my $bad_file = ""; my $bad_line = ""; foreach my $pair (split/,/, $state_note) { my ($variable, $value) = ($pair =~ /^(.*?)=(.*)$/); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pair => $pair, variable => $variable, value => $value, }}); if ($variable eq "file") { $bad_file = $value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bad_file => $bad_file }}); } if ($variable eq "line") { $bad_line = $value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bad_line => $bad_line }}); } } my $error_message = $anvil->Words->string({key => "warning_0013", variables => { file => $bad_file, line => $bad_line, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { error_message => $error_message }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $error_message }}); } else { # Nope, some other issue $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0012"}) }}); } } elsif (not $target_host_uuid) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0005", variables => { uuid => $target_host_uuid }}) }}); } else { # Connected! Ask the user to confirm. my $new_host_name = "#!string!striker_0139!#"; if ((exists $anvil->data->{cgi}{host_name}) && ($anvil->data->{cgi}{host_name}{value})) { $new_host_name = $anvil->data->{cgi}{host_name}{value}; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_host_name => $new_host_name }}); $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "confirm-initialize-host", variables => { 'package' => $type eq "dr" ? "anvil-dr" : "anvil-node", redhat_message => $redhat_message, redhat_form => $redhat_form, access => "root\@".$host_ip_address.":".$ssh_port, current_host_name => $target_host_name, new_host_name => $new_host_name, host_uuid => $target_host_uuid, default_host_name => $default_host_name, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); } } } if ((not $anvil->data->{form}{body}) or ($anvil->data->{form}{error_massage})) { my $node_checked = "checked"; my $dr_checked = ""; if ($type eq "dr") { $node_checked = ""; $dr_checked = "checked"; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { node_checked => $node_checked, dr_checked => $dr_checked, }}); my $host_name = $anvil->Get->host_name; $host_name =~ s/striker\d\d/xxx/; my $default_host_name = $host_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { default_host_name => $default_host_name, host_name => $host_name, }}); if ((exists $anvil->data->{cgi}{host_name}) && ($anvil->data->{cgi}{host_name}{value})) { $host_name = $anvil->data->{cgi}{host_name}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_name => $host_name }}); } my $form_body = $anvil->Template->get({file => "anvil.html", name => "host-setup-menu1", variables => { host_name => $host_name, default_host_name => $default_host_name, host_ip_address => $host_ip_address, node_checked => $node_checked, dr_checked => $dr_checked, }}); $anvil->data->{form}{refresh_link} = "?anvil=true&task=prep-host"; $anvil->data->{form}{back_link} = "?anvil=true"; $anvil->data->{cgi}{task}{value} = "" if not defined $anvil->data->{cgi}{task}{value}; $anvil->data->{cgi}{action}{value} = "" if not defined $anvil->data->{cgi}{action}{value}; $anvil->data->{form}{body} = $anvil->Template->get({file => "anvil.html", name => "prep-host-main", variables => { form => $form_body, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'form::body' => $anvil->data->{form}{body} }}); } return(0); } # This enables or disables the Install Target feature sub process_install_target { my ($anvil) = @_; # NOTE: We don't ask for confirmation, it's a low risk task. # What are we doing? $anvil->data->{cgi}{subtask}{value} = "" if not defined $anvil->data->{cgi}{subtask}{value}; if (($anvil->data->{cgi}{subtask}{value} eq "enable") or ($anvil->data->{cgi}{subtask}{value} eq "disable")) { my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ file => $THIS_FILE, line => __LINE__, job_command => $anvil->data->{path}{exe}{'striker-manage-install-target'}." --".$anvil->data->{cgi}{subtask}{value}.$anvil->Log->switches, job_data => "", job_name => "install-target::".$anvil->data->{cgi}{task}{value}, job_title => "job_0015", job_description => "job_0016", job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); # Show the use that the job has been saved. my $message = "striker_0111"; if ($anvil->data->{cgi}{subtask}{value} eq "enable") { $message = "striker_0112"; } $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "job recorded", variables => { title_id => "", message_id => "", reload_url => "/cgi-bin/".$THIS_FILE."?striker=true", title => "#!string!striker_0044!#", description => "#!string!".$message."!#", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); } else { # Just ignore it, someone's mucking with the subask value. $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0009"}) }}); } return(0); } # This handles powering off or rebooting this machine sub process_power { my ($anvil, $task) = @_; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { task => $task }}); $anvil->data->{cgi}{confirm}{value} = "" if not defined $anvil->data->{cgi}{confirm}{value}; if ($anvil->data->{cgi}{confirm}{value}) { # Record the job! my $job_command = $anvil->data->{path}{exe}{'anvil-manage-power'}." --reboot -y".$anvil->Log->switches; my $job_title = "job_0009"; my $job_description = "job_0006"; my $say_title = "#!string!job_0005!#"; my $say_description = "#!string!job_0006!#"; my $say_reason = "log_0199"; if ($task eq "poweroff") { $job_command = $anvil->data->{path}{exe}{'anvil-manage-power'}." --poweroff -y".$anvil->Log->switches; $job_title = "job_0010"; $job_description = "job_0008"; $say_title = "#!string!job_0007!#"; $say_description = "#!string!job_0008!#"; $say_reason = "log_0200"; } $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0687", variables => { reason => "#!string!".$say_reason."!#" }}); my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ file => $THIS_FILE, line => __LINE__, job_command => $job_command, job_data => "", job_name => "reboot::system", job_title => $job_title, job_description => $job_description, job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); # We don't need to store anything as hidden variables, we'll read it back from the database # later. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "job recorded", variables => { title_id => "", message_id => "", reload_url => "/cgi-bin/".$THIS_FILE, title => $say_title, description => $say_description, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); # Log the user out, just to be safe. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0215"}); $anvil->Account->logout({debug => 2}); } else { # Show the screen the confirm the addition. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "confirm-action", variables => { title => $task eq "poweroff" ? "#!string!job_0007!#" : "#!string!job_0005!#", message => $task eq "poweroff" ? "#!string!striker_0101!#" : "#!string!striker_0100!#", hidden_fields => "", }}); } return(0); } # This handles updating this Striker. sub process_update { my ($anvil) = @_; $anvil->data->{cgi}{confirm}{value} = "" if not defined $anvil->data->{cgi}{confirm}{value}; if ($anvil->data->{cgi}{confirm}{value}) { # Record the job! my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ debug => 1, file => $THIS_FILE, line => __LINE__, job_command => $anvil->data->{path}{exe}{'anvil-update-system'}.$anvil->Log->switches, job_data => "", job_name => "update::system", job_title => "job_0003", job_description => "job_0004", job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); # We don't need to store anything as hidden variables, we'll read it back from the database # later. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "job recorded", variables => { title_id => "", message_id => "", reload_url => "/cgi-bin/".$THIS_FILE, title => "#!string!striker_0044!#", description => "#!string!striker_0088!#", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); # Set maintenance mode. $anvil->System->maintenance_mode({set => 1}); } else { # Show the screen the confirm the addition. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "confirm-action", variables => { title => "#!string!striker_0078!#", message => "#!string!striker_0086!#", hidden_fields => "", }}); } return(0); } # This handles reconfiguring the Striker system. sub process_reconfig_page { my ($anvil) = @_; # Later, this will let each piece be recondigured. For now, it simple reset the "configured flag so # the next load will trigger the initial config again. $anvil->data->{cgi}{confirm}{value} = "" if not defined $anvil->data->{cgi}{confirm}{value}; if ($anvil->data->{cgi}{confirm}{value}) { # Update the configured variable $anvil->Database->insert_or_update_variables({ variable_name => "system::configured", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", variable_value => 0, update_value_only => 1, }); # Done. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "reconfig-done"}); } else { # Show the screen the confirm the addition. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "confirm-reconfig"}); } return(0); } # This handles tasks related to setting up peer Strikers. sub process_sync_page { my ($anvil) = @_; # Setup some CGI values we might use. $anvil->data->{cgi}{new_peer_access}{value} = "" if not defined $anvil->data->{cgi}{new_peer_access}{value}; $anvil->data->{cgi}{new_peer_password}{value} = "" if not defined $anvil->data->{cgi}{new_peer_password}{value}; $anvil->data->{cgi}{save}{value} = "" if not defined $anvil->data->{cgi}{save}{value}; $anvil->data->{cgi}{confirm}{value} = "" if not defined $anvil->data->{cgi}{confirm}{value}; # This handles checkboxes if (defined $anvil->data->{cgi}{new_peer_ping}{value}) { $anvil->data->{cgi}{new_peer_ping}{value} = "" if $anvil->data->{cgi}{new_peer_ping}{value} ne "on"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::new_peer_ping::value" => $anvil->data->{cgi}{new_peer_ping}{value} }}); } else { $anvil->data->{cgi}{new_peer_ping}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::new_peer_ping::value" => $anvil->data->{cgi}{new_peer_ping}{value} }}); } if (defined $anvil->data->{cgi}{new_peer_bidirection}{value}) { $anvil->data->{cgi}{new_peer_bidirection}{value} = "" if $anvil->data->{cgi}{new_peer_bidirection}{value} ne "on"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::new_peer_bidirection::value" => $anvil->data->{cgi}{new_peer_bidirection}{value} }}); } else { $anvil->data->{cgi}{new_peer_bidirection}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::new_peer_bidirection::value" => $anvil->data->{cgi}{new_peer_bidirection}{value} }}); } # Are we deleting or adding a new peer? if ($anvil->data->{cgi}{'delete'}{value}) { delete_sync_peer($anvil); } elsif (($anvil->data->{cgi}{new_peer_access}{value}) && ($anvil->data->{cgi}{new_peer_password}{value} ne "")) { add_sync_peer($anvil); } # If we've got a body now, return. if ($anvil->data->{form}{body}) { # We're done return(0); } my $host_uuid = $anvil->Get->host_uuid; $anvil->Network->get_ips(); # We'll want to show the user way to access the local machine. For that, we'll loop through our own IPs. my $inbound_table = ""; my $local_host = $anvil->Get->short_host_name(); foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{network}{$local_host}{interface}}) { next if (($interface !~ /^bcn/) && ($interface !~ /^ifn/)); next if not $anvil->Validate->ipv4({ip => $anvil->data->{network}{$local_host}{interface}{$interface}{ip}}); next if not $anvil->Validate->subnet_mask({subnet_mask => $anvil->data->{network}{$local_host}{interface}{$interface}{subnet_mask}}); my ($network_type, $network_number) = ($interface =~ /^(.*?)(\d+)_/); my $database_user = $anvil->data->{database}{$host_uuid}{user} ? $anvil->data->{database}{$host_uuid}{user} : "admin"; my $database_port = $anvil->data->{database}{$host_uuid}{port}; my $network_key = $network_type eq "bcn" ? "striker_0018" : "striker_0022"; my $say_network = $anvil->Words->string({key => $network_key, variables => { number => $network_number }}); # The user 'admin' and the port 5432 are default, so only show them if they're non-standard. my $access_string = $database_user."\@".$anvil->data->{network}{$local_host}{interface}{$interface}{ip}.":".$database_port; if (($database_port eq "5432") && ($database_user eq "admin")) { $access_string = $anvil->data->{network}{$local_host}{interface}{$interface}{ip}; } elsif ($database_port eq "5432") { $access_string = $database_user."\@".$anvil->data->{network}{$local_host}{interface}{$interface}{ip}; } elsif ($database_user eq "admin") { $access_string = $anvil->data->{network}{$local_host}{interface}{$interface}{ip}.":".$database_port; } $inbound_table .= $anvil->Template->get({file => "striker.html", name => "striker-sync-inbound", variables => { access => $access_string, note => $say_network, }}); } # This needs to be loaded into a hash by target, then sorted. We'll build the table on sort. my $peer_table = ""; foreach my $uuid (keys %{$anvil->data->{database}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uuid => $uuid }}); next if not $anvil->Validate->uuid({uuid => $uuid}); next if $uuid eq $host_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uuid => $uuid }}); my $host = $anvil->data->{database}{$uuid}{host} ? $anvil->data->{database}{$uuid}{host} : ""; # This should fail my $port = $anvil->data->{database}{$uuid}{port} ? $anvil->data->{database}{$uuid}{port} : 5432; my $name = $anvil->data->{database}{$uuid}{name} ? $anvil->data->{database}{$uuid}{name} : "anvil"; my $user = $anvil->data->{database}{$uuid}{user} ? $anvil->data->{database}{$uuid}{user} : "admin"; my $ping = $anvil->data->{database}{$uuid}{ping} ? $anvil->data->{database}{$uuid}{ping} : 1; my $password = $anvil->data->{database}{$uuid}{password} ? $anvil->data->{database}{$uuid}{password} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host => $host, port => $port, name => $name, user => $user, ping => $ping, password => $anvil->Log->is_secure($password), }}); # Store it by name. $anvil->data->{peers}{$host}{port} = $port; $anvil->data->{peers}{$host}{name} = $name; $anvil->data->{peers}{$host}{user} = $user; $anvil->data->{peers}{$host}{ping} = $ping; $anvil->data->{peers}{$host}{uuid} = $uuid; $anvil->data->{peers}{$host}{password} = $password; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "peers::${host}::port" => $anvil->data->{peers}{$host}{port}, "peers::${host}::name" => $anvil->data->{peers}{$host}{name}, "peers::${host}::ping" => $anvil->data->{peers}{$host}{ping}, "peers::${host}::uuid" => $anvil->data->{peers}{$host}{uuid}, "peers::${host}::password" => $anvil->Log->is_secure($anvil->data->{peers}{$host}{password}), }}); } # Now peers are sortable by host name. foreach my $host (sort {$a cmp $b} keys %{$anvil->data->{peers}}) { my $port = $anvil->data->{peers}{$host}{port}; my $name = $anvil->data->{peers}{$host}{name}; my $user = $anvil->data->{peers}{$host}{user}; my $ping = $anvil->data->{peers}{$host}{ping}; my $uuid = $anvil->data->{peers}{$host}{uuid}; my $password = $anvil->data->{peers}{$host}{password}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host => $host, port => $port, name => $name, user => $user, ping => $ping, uuid => $uuid, password => $anvil->Log->is_secure($password), }}); $anvil->data->{cgi}{new_peer_password}{value} = "" if not defined $anvil->data->{cgi}{new_peer_password}{value}; $peer_table .= $anvil->Template->get({file => "striker.html", name => "striker-sync-entry", variables => { uuid => $uuid, access => $port eq 5432 ? $user."\@".$host : $user."\@".$host.":".$port, password => $anvil->data->{cgi}{new_peer_password}{value}, say_ping => $ping ? "#!string!unit_0001!#" : "#!string!unit_0002!#", }}); } # Build the menu. $anvil->data->{form}{refresh_link} = "?striker=true&task=sync"; $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "striker-sync", variables => { inbound_table => $inbound_table, peer_table => $peer_table, new_peer_access => defined $anvil->data->{cgi}{new_peer_access}{value} ? $anvil->data->{cgi}{new_peer_access}{value} : "", new_peer_password => defined $anvil->data->{cgi}{new_peer_password}{value} ? $anvil->data->{cgi}{new_peer_password}{value} : "", }}); return(0); } # This deletes a sync peer. sub delete_sync_peer { my ($anvil) = @_; my $uuid = $anvil->data->{cgi}{'delete'}{value}; my $host_name = $anvil->Get->host_name_from_uuid({host_uuid => $uuid}); my $host = $anvil->data->{database}{$uuid}{host} ? $anvil->data->{database}{$uuid}{host} : ""; # This should fail my $name = $anvil->data->{database}{$uuid}{name} ? $anvil->data->{database}{$uuid}{name} : "anvil"; my $user = $anvil->data->{database}{$uuid}{user} ? $anvil->data->{database}{$uuid}{user} : "admin"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uuid => $uuid, host_name => $host_name, host => $host, name => $name, user => $user, }}); # Is the delete confirmed? if ($anvil->data->{cgi}{confirm}{value}) { # OK, save the job! my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ debug => 3, file => $THIS_FILE, line => __LINE__, job_command => $anvil->data->{path}{exe}{'striker-manage-peers'}." --remove --host-uuid ".$uuid.$anvil->Log->switches, job_data => "", job_name => "striker-peer::remove", job_title => "job_0013", job_description => "job_0014", job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); # Show the use that the job has been saved. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "job recorded", variables => { title_id => "", message_id => "", reload_url => "/cgi-bin/".$THIS_FILE."?striker=true&task=sync", title => "#!string!striker_0044!#", description => "#!string!striker_0104!#", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); } else { # Show the screen the confirm the addition. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "confirm-action", variables => { title => "#!string!job_0013!#", message => $anvil->Words->string({key => "striker_0105", variables => { peer => $user."\@".$host_name }}), hidden_fields => "", }}); } return(0); } # This adds a new peer to anvil.conf. sub add_sync_peer { my ($anvil) = @_; # Break up the user, host and port. If anything goes wrong, we'll set an error and send it back. my $pgsql_user = "admin"; my $host = $anvil->data->{cgi}{new_peer_access}{value}; my $password = $anvil->data->{cgi}{new_peer_password}{value}; my $db_name = "anvil"; my $ping = $anvil->data->{cgi}{new_peer_ping}{value} eq "on" ? 1 : 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pgsql_user => $pgsql_user, host => $host, password => $anvil->Log->is_secure($password), db_name => $db_name, ping => $ping, }}); my $pgsql_port = 5432; my $ssh_port = 22; my $peer_host_uuid = ""; my $peer_host_name = ""; my $use_ip = ""; # This will contain the local IP to use for the peer to setup comms with us if ($host =~ /,ssh=(\d+)$/) { $ssh_port = $1; $host =~ s/,ssh=\d+$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ssh_port => $ssh_port, host => $host, }}); } if ($host =~ /^(.*?)\@(.*?):(\d+)$/) { $pgsql_user = $1; $host = $2; $pgsql_port = $3; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host => $host, pgsql_port => $pgsql_port, pgsql_user => $pgsql_user, }}); } elsif ($host =~ /^(.*?)\@(.*?)$/) { $pgsql_user = $1; $host = $2; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host => $host, pgsql_user => $pgsql_user, }}); } elsif ($host =~ /^(.*?):(\d+)$/) { $host = $1; $pgsql_port = $2; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host => $host, pgsql_port => $pgsql_port, }}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ssh_port => $ssh_port, host => $host, pgsql_port => $pgsql_port, pgsql_user => $pgsql_user, }}); # Is the host a domain or IP? # If so, and 'bi-directional' is set, verify we can ssh into the peer. my $is_domain = $anvil->Validate->domain_name({name => $host}); my $is_ipv4 = $anvil->Validate->ipv4({ip => $host}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { is_domain => $is_domain, is_ipv4 => $is_ipv4, pgsql_port => $pgsql_port, }}); if (((not $is_domain) && (not $is_ipv4)) or ($pgsql_port < 1) or ($pgsql_port > 65536)) { # Bad host. $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0002"}) }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage}, }}); } else { my ($connected, $data) = $anvil->Striker->get_peer_data({ debug => 2, target => $host, password => $password, port => $ssh_port, }); if ($data->{host_name}) { # We collect this, but apparently not for any real reason... $peer_host_name = $data->{host_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer_host_name => $peer_host_name }}); } if ($data->{host_uuid}) { $peer_host_uuid = $data->{host_uuid}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer_host_uuid => $peer_host_uuid }}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer_host_name => $peer_host_name, peer_host_uuid => $peer_host_uuid, }}); if ((not $connected) or (not $peer_host_uuid)) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0005", variables => { uuid => $peer_host_uuid }}) }}); } # Lastly, if bi-directional is set, make sure we have a way to talk to it. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::new_peer_bidirection::value" => $anvil->data->{cgi}{new_peer_bidirection}{value} }}); if ($anvil->data->{cgi}{new_peer_bidirection}{value} eq "on") { # See which of our IPs match theirs. If the peer is a host name, first, find the IP. $use_ip = $anvil->System->find_matching_ip({host => $host}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { use_ip => $use_ip }}); if ((not $use_ip) or ($use_ip eq "!!error!!")) { # Can't do bi-directional $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0008", variables => { host => $host }}) }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage}, }}); } } } # Now, verify we can access the peer database. This will involve writting out a .pgpass file, then making a local system call. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); if (not $anvil->data->{form}{error_massage}) { my $pgpass_file = "/tmp/.pgpass"; $password =~ s/:/\:/g; my $body = $host.":".$pgsql_port.":".$db_name.":".$pgsql_user.":".$password; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { body => $body, }}); $anvil->Storage->write_file({ file => $pgpass_file, body => $body, mode => "0600", secure => 1, overwrite => 1, }); # This will return '1' only, if it works. my ($db_access, $return_code) = $anvil->System->call({shell_call => "PGPASSFILE=\"".$pgpass_file."\" ".$anvil->data->{path}{exe}{psql}." --host ".$host." --port ".$pgsql_port." --dbname ".$db_name." --username ".$pgsql_user." --no-password --tuples-only --no-align --command \"SELECT 1\""}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { db_access => $db_access, return_code => $return_code }}); if ($db_access ne "1") { # Failed to connect. $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0004"}) }}); } # Delete the pgpass file. unlink $pgpass_file; } # If an error was set, clear the 'save' and 'confirm' values. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::error_massage" => $anvil->data->{form}{error_massage} }}); if ($anvil->data->{form}{error_massage}) { $anvil->data->{cgi}{save}{value} = ""; $anvil->data->{cgi}{confirm}{value} = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::save::value" => $anvil->data->{cgi}{save}{value}, "cgi::confirm::value" => $anvil->data->{cgi}{confirm}{value}, }}); } else { # Things look good. Is the save confirmed? if ($anvil->data->{cgi}{confirm}{value}) { # OK, save the job! my $job_command = $anvil->data->{path}{exe}{'striker-manage-peers'}." --add --host-uuid ".$peer_host_uuid." --host ".$host." --port ".$pgsql_port." --ping ".$ping.$anvil->Log->switches; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_command => $job_command, password => $anvil->Log->is_secure($password), }}); # The job data will always contain the password for the peer, but also contain the # command for the peer to add us if 'bidirectional' was selected. This has to be # stored separately and not added directly as a job, because the peer is likely not # in 'hosts' yet, and thus we can't reference it in 'job_host_uuid' at this point. my $job_data = "password=".$password; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { job_data => $job_data }}); # Are we adding ourselves to the peer? $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { use_ip => $use_ip }}); if ($use_ip) { # See which of our IPs match theirs. If the peer is a host name, first my $host_uuid = $anvil->Get->host_uuid; my $sql_port = $anvil->data->{database}{$host_uuid}{port}; my $job_command = $anvil->data->{path}{exe}{'striker-manage-peers'}." --add --host-uuid ".$host_uuid." --host ".$use_ip." --port ".$sql_port." --ping ".$ping.$anvil->Log->switches; $job_data .= "\npeer_job_command=".$job_command; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_command => $job_command, job_data => $anvil->Log->is_secure($job_data), }}); } # Store the job my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ debug => 3, file => $THIS_FILE, line => __LINE__, job_command => $job_command, job_data => $job_data, job_name => "striker-peer::add", job_title => "job_0011", job_description => "job_0012", job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); # We don't need to store anything as hidden variables, we'll read it back from the # database later. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "job recorded", variables => { title_id => "", message_id => "", reload_url => "/cgi-bin/".$THIS_FILE."?striker=true&task=sync", title => "#!string!striker_0044!#", description => $ping ? "#!string!striker_0103!#" : "#!string!striker_0102!#", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); } else { # Show the screen the confirm the addition. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "confirm-new-peer", variables => { access => $pgsql_user."@".$host.":".$pgsql_port, ping => $anvil->data->{cgi}{new_peer_ping}{value} ? "#!string!unit_0001!#" : "#!string!unit_0002!#", bidirectional => $anvil->data->{cgi}{new_peer_bidirection}{value} ? "#!string!unit_0001!#" : "#!string!unit_0002!#", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); } } return(0); } # This shows the menus for configuring Striker. sub configure_striker { my ($anvil) = @_; # This will be true when the dashboard is unconfigured. if (not $anvil->data->{cgi}{step}{value}) { $anvil->data->{form}{body} = config_step1($anvil); } elsif ($anvil->data->{cgi}{step}{value} eq "step1") { # Sanity check step1. my $sane = sanity_check_step1($anvil); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); if ($sane) { # We're mapping, so tell anvil-daemon to $anvil->Database->insert_or_update_variables({ debug => 2, variable_name => "config::map_network", variable_value => 1, variable_default => 0, variable_description => "striker_0202", variable_section => "config", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); # Step 1 was sane, show step 2. $anvil->data->{form}{body} = config_step2($anvil); } else { # No good $anvil->data->{form}{body} = config_step1($anvil); } } elsif ($anvil->data->{cgi}{step}{value} eq "step2") { # Sanity check step1. my $sane = sanity_check_step2($anvil); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); if ($sane) { # Also, we're done mapping $anvil->Database->insert_or_update_variables({ debug => 2, variable_name => "config::map_network", variable_value => 0, variable_default => 0, variable_description => "striker_0202", variable_section => "config", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); # Step 2 was sane, show step 3. $anvil->data->{form}{body} = config_step3($anvil); } else { # No good $anvil->data->{form}{body} = config_step2($anvil); } } elsif ($anvil->data->{cgi}{step}{value} eq "step3") { # User has confirmed, update the system! my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ debug => 3, file => $THIS_FILE, line => __LINE__, job_command => $anvil->data->{path}{exe}{'anvil-configure-host'}.$anvil->Log->switches, job_data => "form::config_step2", job_name => "configure::network", job_title => "job_0001", job_description => "job_0002", job_progress => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { job_uuid => $job_uuid }}); # Set maintenance mode. $anvil->System->maintenance_mode({set => 1}); # We don't need to store anything as hidden variables, we'll read it back from the database later. $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "network_job_recorded", variables => { title_id => "", message_id => "", reload_url => "/cgi-bin/".$THIS_FILE, title => "#!string!striker_0044!#", description => "#!string!striker_0045!#", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); } else { $anvil->data->{form}{body} = get_network_details_form($anvil); } return(0); } # This checks to see if anything is running that requires Striker being unavailable. If not, this returns # '1'. If there is a job pending/running, it returns '0' sub check_availability { my ($anvil) = @_; my $available = 1; # Check maintenance mode. my $maintenance_mode = $anvil->System->maintenance_mode({debug => 3}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { maintenance_mode => $maintenance_mode }}); if ($maintenance_mode) { $available = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { available => $available }}); # If we have any running or recently finished jobs, we'll desplay them below. $anvil->data->{say}{maintenance} = $anvil->Template->get({file => "striker.html", name => "striker-offline", variables => { title_id => "", message_id => "", title => "#!string!striker_0046!#", description => $anvil->Words->string({key => "striker_0090", variables => {} }), job_list => $anvil->Job->html_list({debug => 2, ended_within => 300}), }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'say::maintenance' => $anvil->data->{say}{maintenance} }}); } # TODO: Phase this out if ($available) { my $query = " SELECT job_progress, modified_date, extract(epoch from modified_date) FROM jobs WHERE job_name = 'configure::network' AND job_progress != 100 AND job_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { results => $results, count => $count, }}); if ($count) { # We're waiting for the network configuration my $percent = $results->[0]->[0]; my $timestamp = $results->[0]->[1]; my $unixtime = $results->[0]->[2]; my $seconds_ago = $anvil->Convert->add_commas({number => (time - $unixtime)}); $available = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { available => $available, percent => $percent, seconds_ago => $seconds_ago, timestamp => $timestamp, unixtime => $unixtime, }}); $anvil->data->{say}{maintenance} = $anvil->Template->get({file => "striker.html", name => "striker-offline", variables => { title_id => "", message_id => "", title => "#!string!striker_0046!#", description => $anvil->Words->string({key => "striker_0047", variables => { percent => $percent, timestamp => $timestamp, seconds_ago => $seconds_ago }}), }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'say::maintenance' => $anvil->data->{say}{maintenance} }}); } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { available => $available }}); return($available); } # This shows the user what is about to be done and asks the user to confirm. sub config_step3 { my ($anvil) = @_; # Read in all the variables from the database. We don't care what was passed, the data in the # database has been tested and is more valid than, say, a manipulated URL. my $cgi = ""; my $nets = {}; my $query = " SELECT variable_name, variable_value FROM variables WHERE (variable_section = 'config_step1' OR variable_section = 'config_step2') AND variable_source_table = 'hosts' AND variable_source_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." ORDER BY variable_name ASC;"; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { my $variable_name = $row->[0]; my $variable_value = $row->[1]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_name => $variable_name, variable_value => $variable_value, }}); if ($variable_name =~ /form::config_step2::(.*?)::value/) { my $variable = $1; $cgi .= $variable.","; $anvil->data->{cgi}{$variable}{value} = $variable_value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${variable}::value" => $anvil->data->{cgi}{$variable}{value} }}); if (($variable =~ /^(bcn\d+)_/) or ($variable =~ /^(ifn\d+)_/)) { my $this_net = $1; $nets->{$this_net} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "nets->this_net" => $nets->{$this_net} }}); } } } #foreach my $key (sort {$a cmp $b} keys %ENV) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ENV{$key}" => $ENV{$key} }}); } # Get the list of current IPs so that we can warn the user if committing the changes will require # reconnecting. $anvil->Network->get_ips({debug => 2}); my $matched_ip = 0; my $server_ip = $ENV{SERVER_ADDR}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_ip => $server_ip }}); # We'll need to show how networks will be configured. This depends on; # 1. Is it a bonded or single interface? # 2. Is it the interface with the gateway? # 3. If no gateway or DNS was specified, alert that there will be no outside access. get_network_details($anvil); my $networks = ""; foreach my $this_net (sort {$a cmp $b} keys %{$nets}) { my $ip_key = $this_net."_ip"; my $subnet_mask_key = $this_net."_subnet_mask"; my $iface1_key = $this_net."_link1_mac_to_set"; my $iface2_key = $this_net."_link2_mac_to_set"; my $ip = $anvil->data->{cgi}{$ip_key}{value}; my $subnet_mask = $anvil->data->{cgi}{$subnet_mask_key}{value}; my $iface1_mac = $anvil->data->{cgi}{$iface1_key}{value}; my $iface2_mac = ((defined $anvil->data->{cgi}{$iface2_key}{value}) && ($anvil->data->{cgi}{$iface2_key}{value})) ? $anvil->data->{cgi}{$iface2_key}{value} : ""; my $template = $iface2_mac ? "step3_bonded_interface" : "step3_single_interface"; my $gateway = $anvil->data->{cgi}{gateway_interface}{value} eq $this_net ? 1 : 0; my $link_number = ($this_net =~ /n(\d+)$/)[0]; my $column = $this_net =~ /^bcn/ ? "striker_0018" : "striker_0022"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:nets->this_net" => $nets->{$this_net}, "s2:ip" => $ip, "s3:subnet_mask" => $subnet_mask, "s4:iface1_mac" => $iface1_mac, "s5:iface2_mac" => $iface2_mac, "s6:template" => $template, "s7:gateway" => $gateway, "s8:link_number" => $link_number, }}); # Add to the networks template. my $say_ip = $ip."/".$subnet_mask; if (($gateway) && ($anvil->data->{cgi}{gateway}{value})) { $template .= "_with_gateway"; $anvil->data->{cgi}{dns}{value} = "--" if not $anvil->data->{cgi}{dns}{value}; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { template => $template }}); $networks .= $anvil->Template->get({file => "config.html", name => $template, variables => { column => $anvil->Words->string({key => $column, variables => { number => $link_number }}), ip_address => $say_ip, ip => $ip, subnet_mask => $subnet_mask, primary => $iface1_mac, backup => $iface2_mac, gateway => $anvil->data->{cgi}{gateway}{value}, dns => $anvil->data->{cgi}{dns}{value}, }})."\n"; # Does this interface's IP match the active one? if ($server_ip eq $ip) { # Yup! No need to warn the user $matched_ip = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { matched_ip => $matched_ip }}); } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { networks => $networks }}); # If the IP is going to change, warn the user. if (not $matched_ip) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "warning_0001"}) }}); } # We don't need to store anything as hidden variables, we'll read it back from the database later. my $step3_body = $anvil->Template->get({file => "config.html", name => "config_step3", variables => { step1_welcome_title_id => "", step1_welcome_message_id => "", organization => $anvil->data->{cgi}{organization}{value}, prefix => $anvil->data->{cgi}{prefix}{value}, host_name => $anvil->data->{cgi}{host_name}{value}, striker_user => $anvil->data->{cgi}{striker_user}{value}, striker_password => $anvil->data->{cgi}{striker_password}{value}, networks => $networks, show_name => 1, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { step3_body => $step3_body }}); return($step3_body); } # This is step2 where the user maps their network. sub config_step2 { my ($anvil) = @_; # If I am coming from stage 1, load any values from the database, if they exist. if ($anvil->data->{cgi}{step}{value} eq "step1") { # First load. See if we can read old data. We don't know for sure what variables will have # been set, so we'll load anything from the group 'config_step2'. my $query = " SELECT variable_name, variable_value FROM variables WHERE variable_section = 'config_step2' AND variable_source_table = 'hosts' AND variable_source_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." ORDER BY variable_name ASC;"; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { my $variable_name = $row->[0]; my $variable_value = $row->[1]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_name => $variable_name, variable_value => $variable_value, }}); if ($variable_name =~ /form::config_step2::(.*?)::value/) { my $variable = $1; $anvil->data->{cgi}{$variable}{value} = $variable_value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::${variable}::value" => $anvil->data->{cgi}{$variable}{value} }}); } } } # 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($anvil); my $required_interfaces_for_single = 1 + $anvil->data->{cgi}{ifn_count}{value}; my $required_interfaces_for_bonds = 2 * $required_interfaces_for_single; my $interface_count = keys %{$anvil->data->{interfaces}}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, 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 %{$anvil->data->{interfaces}}) { my $this_mac = $anvil->data->{interfaces}{$interface}{mac}; push @{$interface_options}, $this_mac."#!#".$interface." (".$this_mac.")"; } 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 = $anvil->data->{cgi}{bcn_count}{value} ? $anvil->data->{cgi}{bcn_count}{value} : 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bcn_count => $bcn_count }}); foreach my $bcn (1..$bcn_count) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bcn => $bcn }}); push @{$links}, "bcn_link".$bcn; my $this_ip_key = "bcn".$bcn."_ip"; my $this_subnet_mask_key = "bcn".$bcn."_subnet_mask"; my $this_iface1_key = "bcn".$bcn."_link1_mac_to_set"; my $this_iface2_key = "bcn".$bcn."_link2_mac_to_set"; $cgi .= $this_ip_key.",".$this_subnet_mask_key.",".$this_iface1_key.",".$this_iface2_key.","; my $this_ip = generate_ip($anvil, "bcn", $bcn, $anvil->data->{cgi}{sequence}{value}); my $this_ip_class = $anvil->data->{cgi}{$this_ip_key}{alert} ? "input_alert" : "input_clear"; my $this_subnet_mask_class = $anvil->data->{cgi}{$this_subnet_mask_key}{alert} ? "input_alert" : "input_clear"; my $this_iface1_class = $anvil->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear"; my $this_iface2_class = $anvil->data->{cgi}{$this_iface2_key}{alert} ? "input_alert" : "input_clear"; # Build the interface select boxes... my $this_iface1_form = $anvil->Template->select_form({ name => $this_iface1_key, options => $interface_options, blank => 1, 'sort' => 0, selected => defined $anvil->data->{cgi}{$this_iface1_key}{value} ? $anvil->data->{cgi}{$this_iface1_key}{value} : "", class => $anvil->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear", }); my $this_iface2_form = $anvil->Template->select_form({ name => $this_iface2_key, options => $interface_options, blank => 1, 'sort' => 0, selected => defined $anvil->data->{cgi}{$this_iface2_key}{value} ? $anvil->data->{cgi}{$this_iface2_key}{value} : "", class => $anvil->data->{cgi}{$this_iface2_key}{alert} ? "input_alert" : "input_clear", }); # Assemble the form $interface_form .= $anvil->Template->get({file => "config.html", name => "bonded_interface_form", variables => { field => $anvil->Words->string({key => "striker_0018", variables => { number => $bcn }}), description => "#!string!striker_0019!#", ip_key => $this_ip_key, ip_value => defined $anvil->data->{cgi}{$this_ip_key}{value} ? $anvil->data->{cgi}{$this_ip_key}{value} : "", ip_value_default => $this_ip, ip_class => $this_ip_class, subnet_mask_key => $this_subnet_mask_key, subnet_mask_value => defined $anvil->data->{cgi}{$this_subnet_mask_key}{value} ? $anvil->data->{cgi}{$this_subnet_mask_key}{value} : "", subnet_mask_value_default => $anvil->data->{defaults}{network}{bcn}{subnet_mask}, subnet_mask_class => $this_subnet_mask_class, iface1_select => $this_iface1_form, iface2_select => $this_iface2_form, }}); } # IFN my $ifn_count = $anvil->data->{cgi}{ifn_count}{value} ? $anvil->data->{cgi}{ifn_count}{value} : 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ifn_count => $ifn_count }}); foreach my $ifn (1..$ifn_count) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ifn => $ifn }}); push @{$links}, "ifn_link".$ifn; my $this_ip_key = "ifn".$ifn."_ip"; my $this_subnet_mask_key = "ifn".$ifn."_subnet_mask"; my $this_iface1_key = "ifn".$ifn."_link1_mac_to_set"; my $this_iface2_key = "ifn".$ifn."_link2_mac_to_set"; $cgi .= $this_ip_key.",".$this_subnet_mask_key.",".$this_iface1_key.",".$this_iface2_key.","; my $this_ip = generate_ip($anvil, "ifn", $ifn, $anvil->data->{cgi}{sequence}{value}); my $this_ip_class = $anvil->data->{cgi}{$this_ip_key}{alert} ? "input_alert" : "input_clear"; my $this_subnet_mask_class = $anvil->data->{cgi}{$this_subnet_mask_key}{alert} ? "input_alert" : "input_clear"; my $this_iface1_class = $anvil->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear"; my $this_iface2_class = $anvil->data->{cgi}{$this_iface2_key}{alert} ? "input_alert" : "input_clear"; # Build the interface select boxes... my $this_iface1_form = $anvil->Template->select_form({ name => $this_iface1_key, options => $interface_options, blank => 1, selected => defined $anvil->data->{cgi}{$this_iface1_key}{value} ? $anvil->data->{cgi}{$this_iface1_key}{value} : "", class => $anvil->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear", }); my $this_iface2_form = $anvil->Template->select_form({ name => $this_iface2_key, options => $interface_options, blank => 1, selected => defined $anvil->data->{cgi}{$this_iface2_key}{value} ? $anvil->data->{cgi}{$this_iface2_key}{value} : "", class => $anvil->data->{cgi}{$this_iface2_key}{alert} ? "input_alert" : "input_clear", }); # Assemble the form $interface_form .= $anvil->Template->get({file => "config.html", name => "bonded_interface_form", variables => { field => $anvil->Words->string({key => "striker_0022", variables => { number => $ifn }}), description => "#!string!striker_0023!#", ip_key => $this_ip_key, ip_value => defined $anvil->data->{cgi}{$this_ip_key}{value} ? $anvil->data->{cgi}{$this_ip_key}{value} : "", ip_value_default => $this_ip, ip_class => $this_ip_class, subnet_mask_key => $this_subnet_mask_key, subnet_mask_value => defined $anvil->data->{cgi}{$this_subnet_mask_key}{value} ? $anvil->data->{cgi}{$this_subnet_mask_key}{value} : "", subnet_mask_value_default => $anvil->data->{defaults}{network}{ifn}{subnet_mask}, subnet_mask_class => $this_subnet_mask_class, iface1_select => $this_iface1_form, iface2_select => $this_iface2_form, }}); } } else { ### Show the single iface per network form. # BCN my $bcn_count = $anvil->data->{cgi}{bcn_count}{value} ? $anvil->data->{cgi}{bcn_count}{value} : 1; foreach my $bcn (1..$bcn_count) { push @{$links}, "bcn_link".$bcn; my $this_ip_key = "bcn".$bcn."_ip"; my $this_subnet_mask_key = "bcn".$bcn."_subnet_mask"; my $this_iface1_key = "bcn".$bcn."_link1_mac_to_set"; $cgi .= $this_ip_key.",".$this_subnet_mask_key.",".$this_iface1_key.","; my $this_ip = generate_ip($anvil, "bcn", $bcn, $anvil->data->{cgi}{sequence}{value}); my $this_ip_class = $anvil->data->{cgi}{$this_ip_key}{alert} ? "input_alert" : "input_clear"; my $this_subnet_mask_class = $anvil->data->{cgi}{$this_subnet_mask_key}{alert} ? "input_alert" : "input_clear"; my $this_iface1_class = $anvil->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear"; # Build the interface select boxes... my $this_iface1_form = $anvil->Template->select_form({ name => $this_iface1_key, options => $interface_options, blank => 1, selected => defined $anvil->data->{cgi}{$this_iface1_key}{value} ? $anvil->data->{cgi}{$this_iface1_key}{value} : "", class => $anvil->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear", }); # Assemble the form $interface_form .= $anvil->Template->get({file => "config.html", name => "single_interface_form", variables => { field => $anvil->Words->string({key => "striker_0018", variables => { number => $bcn }}), description => "#!string!striker_0019!#", ip_key => $this_ip_key, ip_value => defined $anvil->data->{cgi}{$this_ip_key}{value} ? $anvil->data->{cgi}{$this_ip_key}{value} : "", ip_value_default => $this_ip, ip_class => $this_ip_class, subnet_mask_key => $this_subnet_mask_key, subnet_mask_value => defined $anvil->data->{cgi}{$this_subnet_mask_key}{value} ? $anvil->data->{cgi}{$this_subnet_mask_key}{value} : $anvil->data->{defaults}{network}{bcn}{subnet_mask}, subnet_mask_value_default => $anvil->data->{defaults}{network}{bcn}{subnet_mask}, subnet_mask_class => $this_subnet_mask_class, iface1_select => $this_iface1_form, }}); } # IFN my $ifn_count = $anvil->data->{cgi}{ifn_count}{value} ? $anvil->data->{cgi}{ifn_count}{value} : 1; foreach my $ifn (1..$ifn_count) { push @{$links}, "ifn_link".$ifn; my $this_ip_key = "ifn".$ifn."_ip"; my $this_subnet_mask_key = "ifn".$ifn."_subnet_mask"; my $this_iface1_key = "ifn".$ifn."_link1_mac_to_set"; $cgi .= $this_ip_key.",".$this_subnet_mask_key.",".$this_iface1_key.","; my $this_ip = generate_ip($anvil, "ifn", $ifn, $anvil->data->{cgi}{sequence}{value}); my $this_ip_class = $anvil->data->{cgi}{$this_ip_key}{alert} ? "input_alert" : "input_clear"; my $this_subnet_mask_class = $anvil->data->{cgi}{$this_subnet_mask_key}{alert} ? "input_alert" : "input_clear"; my $this_iface1_class = $anvil->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear"; # Build the interface select boxes... my $this_iface1_form = $anvil->Template->select_form({ name => $this_iface1_key, options => $interface_options, blank => 1, selected => defined $anvil->data->{cgi}{$this_iface1_key}{value} ? $anvil->data->{cgi}{$this_iface1_key}{value} : "", class => $anvil->data->{cgi}{$this_iface1_key}{alert} ? "input_alert" : "input_clear", }); # Assemble the form $interface_form .= $anvil->Template->get({file => "config.html", name => "single_interface_form", variables => { field => $anvil->Words->string({key => "striker_0022", variables => { number => $ifn }}), description => "#!string!striker_0023!#", ip_key => $this_ip_key, ip_value => defined $anvil->data->{cgi}{$this_ip_key}{value} ? $anvil->data->{cgi}{$this_ip_key}{value} : "", ip_value_default => $this_ip, ip_class => $this_ip_class, subnet_mask_key => $this_subnet_mask_key, subnet_mask_value => defined $anvil->data->{cgi}{$this_subnet_mask_key}{value} ? $anvil->data->{cgi}{$this_subnet_mask_key}{value} : $anvil->data->{defaults}{network}{ifn}{subnet_mask}, subnet_mask_value_default => $anvil->data->{defaults}{network}{ifn}{subnet_mask}, subnet_mask_class => $this_subnet_mask_class, iface1_select => $this_iface1_form, }}); } } ### TODO: Add a form for Gateway, DNS and which interface to use # Gateway my $gateway_class = $anvil->data->{cgi}{gateway}{alert} ? "input_alert" : "input_clear"; my $say_gateway = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "gateway", id => "gateway", field => "#!string!striker_0035!#", description => "#!string!striker_0036!#", value => defined $anvil->data->{cgi}{gateway}{value} ? $anvil->data->{cgi}{gateway}{value} : "", default_value => "", class => $gateway_class, extra => "", }}); # DNS my $dns_class = $anvil->data->{cgi}{dns}{alert} ? "input_alert" : "input_clear"; my $say_dns = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "dns", id => "dns", field => "#!string!striker_0037!#", description => "#!string!striker_0038!#", value => defined $anvil->data->{cgi}{dns}{value} ? $anvil->data->{cgi}{dns}{value} : "", default_value => $anvil->data->{defaults}{network}{dns}, class => $dns_class, extra => "", }}); # Which interface gets the route? my $default_dg_iface = defined $anvil->data->{cgi}{dg_iface}{value} ? $anvil->data->{cgi}{dg_iface}{value} : "ifn_link1"; my $dg_iface_select = $anvil->Template->select_form({ name => "dg_iface", options => $links, blank => 0, selected => $default_dg_iface, class => $anvil->data->{cgi}{dg_iface}{alert} ? "input_alert" : "input_clear", }); ### NOTE: I'll likely want this for choosing which interface to use as the default gateway when 2+ ### IFNs are used. # my $dg_iface_class = $anvil->data->{cgi}{dg_iface}{alert} ? "input_alert" : "input_clear"; # my $say_dg_iface = $anvil->Template->get({file => "main.html", name => "input_select_form", variables => { # field => "#!string!striker_0039!#", # description => "#!string!striker_0040!#", # 'select' => "", # }}); # $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { say_dg_iface => $say_dg_iface }}); # Hostname my $say_default_host_name = $anvil->data->{cgi}{prefix}{value}."-striker0".$anvil->data->{cgi}{sequence}{value}.".".$anvil->data->{cgi}{domain}{value}; my $host_name_class = $anvil->data->{cgi}{host_name}{alert} ? "input_alert" : "input_clear"; my $say_host_name = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "host_name", id => "host_name", field => "#!string!striker_0016!#", description => "#!string!striker_0017!#", value => defined $anvil->data->{cgi}{host_name}{value} ? $anvil->data->{cgi}{host_name}{value} : $say_default_host_name, default_value => "", class => $host_name_class, extra => "", }}); # Admin user my $striker_user_class = $anvil->data->{cgi}{striker_user}{alert} ? "input_alert" : "input_clear"; my $say_striker_user = $anvil->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 $anvil->data->{cgi}{striker_user}{value} ? $anvil->data->{cgi}{striker_user}{value} : $anvil->data->{sys}{user}{name}, default_value => "", class => $striker_user_class, extra => "", }}); # Password my $striker_password_class = $anvil->data->{cgi}{striker_password}{alert} ? "input_alert" : "input_clear"; my $say_striker_password = $anvil->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 $anvil->data->{cgi}{striker_password}{value} ? $anvil->data->{cgi}{striker_password}{value} : "", default_value => "", class => $striker_password_class, extra => "", }}); # Get the table that shows the current interface states. my $interface_states = get_network_details_form($anvil); # Store the previous CGI variables and display the new fields. my $step2_body = $anvil->Template->get({file => "config.html", name => "config_step2", variables => { step1_welcome_title_id => "", step1_welcome_message_id => "", organization => $anvil->data->{cgi}{organization}{value}, prefix => $anvil->data->{cgi}{prefix}{value}, domain => $anvil->data->{cgi}{domain}{value}, sequence => $anvil->data->{cgi}{sequence}{value}, bcn_count => $anvil->data->{cgi}{bcn_count}{value}, ifn_count => $anvil->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, host_name_form => $say_host_name, }}); $anvil->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 ($anvil) = @_; # This will flip if we run into a problem. my $sane = 1; # Do we have a host name, striker user and password? if (not $anvil->Validate->form_field({name => "host_name", type => "domain_name"})) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0012"}) }}); $anvil->data->{cgi}{host_name}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } else { # Record the answer. $anvil->Database->insert_or_update_variables({ variable_name => "form::config_step2::host_name::value", variable_value => $anvil->data->{cgi}{host_name}{value}, variable_default => "", variable_description => "striker_0017", variable_section => "config_step2", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } # The user name if ((not defined $anvil->data->{cgi}{striker_user}{value}) or (not $anvil->data->{cgi}{striker_user}{value})) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0013"}) }}); $anvil->data->{cgi}{striker_user}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::striker_user::alert" => $anvil->data->{cgi}{striker_user}{alert} }}); } else { # Record the answer. $anvil->Database->insert_or_update_variables({ variable_name => "form::config_step2::striker_user::value", variable_value => $anvil->data->{cgi}{striker_user}{value}, variable_default => "", variable_description => "striker_0032", variable_section => "config_step2", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } # The password if ((not defined $anvil->data->{cgi}{striker_password}{value}) or (not $anvil->data->{cgi}{striker_password}{value}) or (length($anvil->data->{cgi}{striker_password}{value}) < 6)) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0014"}) }}); $anvil->data->{cgi}{striker_password}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::striker_password::alert" => $anvil->data->{cgi}{striker_password}{alert} }}); } else { # Record the answer. $anvil->Database->insert_or_update_variables({ variable_name => "form::config_step2::striker_password::value", variable_value => $anvil->data->{cgi}{striker_password}{value}, variable_default => "", variable_description => "striker_0034", variable_section => "config_step2", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } # DNS can be multiple entries, comma-separated. It can also be blank, if the user doesn't need Internet access. my $dns_ok = 1; if ((defined $anvil->data->{cgi}{dns}{value}) and ($anvil->data->{cgi}{dns}{value})) { foreach my $ip (split/,/, $anvil->data->{cgi}{dns}{value}) { $ip =~ s/^\s+//; $ip =~ s/\s+$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { ip => $ip }}); if (not $anvil->Validate->ipv4({ip => $ip})) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0015"}) }}); $anvil->data->{cgi}{dns}{alert} = 1; $sane = 0; $dns_ok = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, dns_ok => $dns_ok, "cgi::dns::alert" => $anvil->data->{cgi}{dns}{alert} }}); } } } if ($dns_ok) { # Record the answer. $anvil->Database->insert_or_update_variables({ variable_name => "form::config_step2::dns::value", variable_value => $anvil->data->{cgi}{dns}{value}, variable_default => "", variable_description => "striker_0038", variable_section => "config_step2", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } # Look for interfaces and sanity check them. my $networks = {}; foreach my $network ("bcn", "ifn") { my $count_key = $network."_count"; my $network_count = $anvil->data->{cgi}{$count_key}{value} ? $anvil->data->{cgi}{$count_key}{value} : 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { network => $network, count_key => $count_key, network_count => $network_count, }}); foreach my $count (1..$network_count) { my $this_network = $network.$count; my $this_ip_key = $this_network."_ip"; my $this_subnet_mask_key = $this_network."_subnet_mask"; my $this_iface1_key = $this_network."_link1_mac_to_set"; my $this_iface2_key = $this_network."_link2_mac_to_set"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { count => $count, this_ip_key => $this_ip_key, this_subnet_mask_key => $this_subnet_mask_key, this_iface1_key => $this_iface1_key, this_iface2_key => $this_iface2_key, "cgi::${this_ip_key}::value" => $anvil->data->{cgi}{$this_ip_key}{value}, "cgi::${this_subnet_mask_key}::value" => $anvil->data->{cgi}{$this_subnet_mask_key}{value}, "cgi::${this_iface1_key}::value" => $anvil->data->{cgi}{$this_iface1_key}{value}, "cgi::${this_iface2_key}::value" => $anvil->data->{cgi}{$this_iface2_key}{value}, }}); # This will be used to tell the user which interface has a problem, if one exists. my $network_key = $network =~ /^bcn/ ? "striker_0018" : "striker_0022"; my $say_network = $anvil->Words->string({key => $network_key, variables => { number => $count }}); # Is the IP sane? my $ip_ok = 1; if (not $anvil->Validate->form_field({name => $this_ip_key, type => "ipv4"})) { # Nope $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0016", variables => { network => $say_network}}) }}); $anvil->data->{cgi}{$this_ip_key}{alert} = 1; $sane = 0; $ip_ok = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, ip_ok => $ip_ok }}); } else { # Save the IP $anvil->Database->insert_or_update_variables({ variable_name => "form::config_step2::${this_ip_key}::value", variable_value => $anvil->data->{cgi}{$this_ip_key}{value}, variable_default => "", variable_description => "striker_0024", variable_section => "config_step2", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } # What about the subnet mask? if (not $anvil->Validate->form_field({name => $this_subnet_mask_key, type => "subnet_mask"})) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0016", variables => { network => $say_network }}) }}); $anvil->data->{cgi}{$this_subnet_mask_key}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } elsif ($ip_ok) { # We'll use the dotted-decimal subnet_mask. If it already is, great. If not, convert it. my $say_subnet_mask = $anvil->data->{cgi}{$this_subnet_mask_key}{value} =~ /^\d{1,2}$/ ? $anvil->Convert->cide({cidr => $anvil->data->{cgi}{$this_subnet_mask_key}{value}}) : $anvil->data->{cgi}{$this_subnet_mask_key}{value}; my $full_ip = $anvil->data->{cgi}{$this_ip_key}{value}."/".$anvil->data->{cgi}{$this_subnet_mask_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_subnet_mask => $say_subnet_mask, full_ip => $full_ip }}); $networks->{$this_network} = $full_ip; # Save the subnet mask $anvil->Database->insert_or_update_variables({ variable_name => "form::config_step2::${this_subnet_mask_key}::value", variable_value => $anvil->data->{cgi}{$this_subnet_mask_key}{value}, variable_default => "", variable_description => "striker_0025", variable_section => "config_step2", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } # Interface 1 must be set if (not $anvil->Validate->form_field({name => $this_iface1_key, type => "mac"})) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0017", variables => { network => $say_network, 'link' => "1" }}) }}); $anvil->data->{cgi}{$this_iface1_key}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } else { # Valid MAC. Has it been assigned elsewhere? my $mac_address = $anvil->data->{cgi}{$this_iface1_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { mac_address => $mac_address }}); if ((not exists $anvil->data->{network}{$mac_address}{set_as}) or (not $anvil->data->{network}{$mac_address}{set_as})) { $anvil->data->{network}{$mac_address}{set_as} = $this_iface1_key; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "network::${mac_address}::set_as" => $anvil->data->{network}{$mac_address}{set_as} }}); # Record the answer. $anvil->Database->insert_or_update_variables({ variable_name => "form::config_step2::${this_iface1_key}::value", variable_value => $anvil->data->{cgi}{$this_iface1_key}{value}, variable_default => "", variable_description => "striker_0029", variable_section => "config_step2", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } else { # Conflict! Set the alert for this interface and the conflicting one. my $conflict_key = $anvil->data->{network}{$mac_address}{set_as}; $anvil->data->{cgi}{$conflict_key}{alert} = 1; $anvil->data->{cgi}{$this_iface1_key}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0018"}) }}); $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::${conflict_key}::alert" => $anvil->data->{cgi}{$conflict_key}{alert}, "cgi::${this_iface1_key}::alert" => $anvil->data->{cgi}{$this_iface1_key}{alert}, }}); } } # Interface 2 doesn't have to be set. if ((defined $anvil->data->{cgi}{$this_iface2_key}{value}) && ($anvil->data->{cgi}{$this_iface2_key}{value})) { if (not $anvil->Validate->form_field({name => $this_iface2_key, type => "mac"})) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0017", variables => { network => $say_network, 'link' => "2" }}) }}); $anvil->data->{cgi}{$this_iface2_key}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } else { # Valid MAC. Has it been assigned elsewhere? my $mac_address = $anvil->data->{cgi}{$this_iface2_key}{value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { mac_address => $mac_address }}); if ((not exists $anvil->data->{network}{$mac_address}{set_as}) or (not $anvil->data->{network}{$mac_address}{set_as})) { $anvil->data->{network}{$mac_address}{set_as} = $this_iface2_key; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "network::${mac_address}::set_as" => $anvil->data->{network}{$mac_address}{set_as} }}); # Record the answer. $anvil->Database->insert_or_update_variables({ variable_name => "form::config_step2::${this_iface2_key}::value", variable_value => $anvil->data->{cgi}{$this_iface2_key}{value}, variable_default => "", variable_description => "striker_0030", variable_section => "config_step2", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } else { # Conflict! Set the alert for this interface and the conflicting one. my $conflict_key = $anvil->data->{network}{$mac_address}{set_as}; $anvil->data->{cgi}{$conflict_key}{alert} = 1; $anvil->data->{cgi}{$this_iface2_key}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0018"}) }}); $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::${conflict_key}::alert" => $anvil->data->{cgi}{$conflict_key}{alert}, "cgi::${this_iface2_key}::alert" => $anvil->data->{cgi}{$this_iface2_key}{alert}, }}); } } } } } # The gateway, this has to be after the interfaces so that we can match it to an interface (and error # if not) if (not $anvil->Validate->form_field({name => "gateway", type => "ipv4", empty_ok => 1})) { $anvil->data->{cgi}{gateway}{alert} = 1; $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0019"}) }}); $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } else { # Convert the gateway strings to binary. my $gateway = defined $anvil->data->{cgi}{gateway}{value} ? $anvil->data->{cgi}{gateway}{value} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { gateway => $gateway }}); # If there is no gateway, that's OK, there just won't be any Internet access. my $gateway_interface = ""; if ($gateway) { # Match this gateway to one of the interfaces. foreach my $this_network (sort {$a cmp $b} keys %{$networks}) { my ($this_ip, $this_subnet_mask) = ($networks->{$this_network} =~ /^(.*?)\/(.*)$/); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "s1:this_network" => $this_network, "s2:networks->$this_network" => $networks->{$this_network}, "s3:this_ip" => $this_ip, "s4:this_subnet_mask" => $this_subnet_mask, }}); my $first = NetAddr::IP->new("$this_ip/$this_subnet_mask"); my $second = NetAddr::IP->new("$gateway/$this_subnet_mask"); if ($second->within($first)) { $gateway_interface = $this_network; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { gateway_interface => $gateway_interface }}); } } if (not $gateway_interface) { # Explain the problem $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0004"}) }}); $anvil->data->{cgi}{gateway}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::gateway::alert" => $anvil->data->{cgi}{gateway}{alert} }}); } } # If no alert was raised, record the values. if (not $anvil->data->{cgi}{gateway}{alert}) { # Record the answer. $anvil->Database->insert_or_update_variables({ variable_name => "form::config_step2::gateway::value", variable_value => $anvil->data->{cgi}{gateway}{value}, variable_default => "", variable_description => "striker_0036", variable_section => "config_step2", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); # Record the gateway interface $anvil->Database->insert_or_update_variables({ variable_name => "form::config_step2::gateway_interface::value", variable_value => $gateway_interface, variable_default => "", variable_description => "", variable_section => "config_step2", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } } $anvil->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 ($anvil) = @_; $anvil->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; $anvil->data->{cgi}{organization}{value} = "" if not defined $anvil->data->{cgi}{organization}{value}; # Organization just needs *something* $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::organization::alert" => $anvil->data->{cgi}{organization}{alert}, }}); if (not $anvil->data->{cgi}{organization}{value}) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0020", variables => { field => "striker_0003" }}) }}); $anvil->data->{cgi}{organization}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::organization::alert" => $anvil->data->{cgi}{organization}{alert} }}); } else { # Record the answer. $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step1::organization::value", variable_value => $anvil->data->{cgi}{organization}{value}, variable_default => "", variable_description => "striker_0004", variable_section => "config_step1", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } # The prefix needs to be alphanumeric and be between 1 ~ 5 chatacters. if ((not $anvil->Validate->alphanumeric({string => $anvil->data->{cgi}{prefix}{value}})) or (length($anvil->data->{cgi}{prefix}{value}) > 5)) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0021"}) }}); $anvil->data->{cgi}{prefix}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::prefix::alert" => $anvil->data->{cgi}{prefix}{alert} }}); } else { # Record the answer. $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step1::prefix::value", variable_value => $anvil->data->{cgi}{prefix}{value}, variable_default => "", variable_description => "striker_0006", variable_section => "config_step1", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } # We can use Validate to check the domain. if (not $anvil->Validate->form_field({name => "domain", type => "domain_name"})) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0020", variables => { field => "striker_0007" }}) }}); $anvil->data->{cgi}{domain}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane }}); } else { # Record the answer. $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step1::domain::value", variable_value => $anvil->data->{cgi}{domain}{value}, variable_default => "", variable_description => "striker_0008", variable_section => "config_step1", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } # The sequence and IFN count need to be integers. if (not $anvil->Validate->positive_integer({number => $anvil->data->{cgi}{sequence}{value}})) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0022", variables => { field => "striker_0009" }}) }}); $anvil->data->{cgi}{sequence}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::sequence::alert" => $anvil->data->{cgi}{sequence}{alert} }}); } else { # Record the answer. $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step1::sequence::value", variable_value => $anvil->data->{cgi}{sequence}{value}, variable_default => "", variable_description => "striker_0010", variable_section => "config_step1", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } if (not $anvil->Validate->positive_integer({number => $anvil->data->{cgi}{ifn_count}{value}})) { $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0022", variables => { field => "striker_0011" }}) }}); $anvil->data->{cgi}{ifn_count}{alert} = 1; $sane = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { sane => $sane, "cgi::ifn_count::alert" => $anvil->data->{cgi}{ifn_count}{alert} }}); } # Make sure we have enough interfaces. get_network_details($anvil); my $required_interfaces_for_single = 1 + $anvil->data->{cgi}{ifn_count}{value}; my $interface_count = keys %{$anvil->data->{interfaces}}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, 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 = $anvil->Words->string({key => "error_0001", variables => { interface_count => $interface_count, required_interfaces_for_single => $required_interfaces_for_single, }}); # Not enough interfaces found. $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $say_message }}); $anvil->data->{cgi}{ifn_count}{alert} = 1; $sane = 0; } else { # Sane, Record the answers. $anvil->Database->insert_or_update_variables({ debug => 3, variable_name => "form::config_step1::ifn_count::value", variable_value => $anvil->data->{cgi}{ifn_count}{value}, variable_default => "", variable_description => "striker_0012", variable_section => "config_step1", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }}); return($sane); } # This is step 1 in asking the user how to configure Striker. sub config_step1 { my ($anvil) = @_; if (not $anvil->data->{cgi}{'next'}{value}) { # First load. See if we can read old data. my ($organization) = $anvil->Database->read_variable({ variable_name => "form::config_step1::organization::value", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); my ($prefix) = $anvil->Database->read_variable({ variable_name => "form::config_step1::prefix::value", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); my ($domain) = $anvil->Database->read_variable({ variable_name => "form::config_step1::domain::value", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); my ($sequence) = $anvil->Database->read_variable({ variable_name => "form::config_step1::sequence::value", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); my ($ifn_count) = $anvil->Database->read_variable({ variable_name => "form::config_step1::ifn_count::value", variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { organization => $organization, prefix => $prefix, domain => $domain, sequence => $sequence, ifn_count => $ifn_count, }}); $anvil->data->{cgi}{organization}{value} = $organization ne "" ? $organization : ""; $anvil->data->{cgi}{prefix}{value} = $prefix ne "" ? $prefix : ""; $anvil->data->{cgi}{domain}{value} = $domain ne "" ? $domain : ""; $anvil->data->{cgi}{sequence}{value} = $sequence ne "" ? $sequence : ""; $anvil->data->{cgi}{ifn_count}{value} = $ifn_count ne "" ? $ifn_count : 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'cgi::organization::value' => $anvil->data->{cgi}{organization}{value}, 'cgi::prefix::value' => $anvil->data->{cgi}{prefix}{value}, 'cgi::domain::value' => $anvil->data->{cgi}{domain}{value}, 'cgi::sequence::value' => $anvil->data->{cgi}{sequence}{value}, 'cgi::ifn_count::value' => $anvil->data->{cgi}{ifn_count}{value}, }}); # If we don't have an organization name, prefix, domain name or sequence number, try to parse it from # the current static and pretty host_names. my ($traditional_host_name, $descriptive_host_name) = $anvil->System->host_name({debug => 2}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { traditional_host_name => $traditional_host_name, descriptive_host_name => $descriptive_host_name, }}); if ($descriptive_host_name =~ /^(.*?) - Striker (\d+)/) { my $organization = $1; my $sequence = $2; $sequence =~ s/^0+//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { organization => $organization, sequence => $sequence, }}); if (($organization) && ($anvil->data->{cgi}{organization}{value} eq "")) { $anvil->data->{cgi}{organization}{value} = $organization; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'cgi::organization::value' => $anvil->data->{cgi}{organization}{value}, }}); } if (($sequence =~ /^\d+$/) && ($anvil->data->{cgi}{sequence}{value} eq "")) { $anvil->data->{cgi}{sequence}{value} = $sequence; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'cgi::sequence::value' => $anvil->data->{cgi}{sequence}{value}, }}); } } if ($traditional_host_name =~ /^(.*?)-striker\d+\.(.*)$/) { my $prefix = $1; my $domain = $2; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { prefix => $prefix, domain => $domain, }}); if (($prefix) && ($anvil->data->{cgi}{prefix}{value} eq "")) { $anvil->data->{cgi}{prefix}{value} = $prefix; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'cgi::prefix::value' => $anvil->data->{cgi}{prefix}{value}, }}); } if (($domain) && ($anvil->data->{cgi}{domain}{value} eq "")) { $anvil->data->{cgi}{domain}{value} = $domain; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'cgi::domain::value' => $anvil->data->{cgi}{domain}{value}, }}); } } # If I still don't have a sequence number, set '1'. if ($anvil->data->{cgi}{sequence}{value} eq "") { $anvil->data->{cgi}{sequence}{value} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'cgi::sequence::value' => $anvil->data->{cgi}{sequence}{value}, }}); } } my $organization_class = $anvil->data->{cgi}{organization}{alert} ? "input_alert" : "input_clear"; my $say_organization = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "organization", id => "organization", field => "#!string!striker_0003!#", description => "#!string!striker_0004!#", value => defined $anvil->data->{cgi}{organization}{value} ? $anvil->data->{cgi}{organization}{value} : "", default_value => "", class => $organization_class, extra => "", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_organization => $say_organization }}); my $prefix_class = $anvil->data->{cgi}{prefix}{alert} ? "input_alert" : "input_clear"; my $say_prefix = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "prefix", id => "prefix", field => "#!string!striker_0005!#", description => "#!string!striker_0006!#", value => defined $anvil->data->{cgi}{prefix}{value} ? $anvil->data->{cgi}{prefix}{value} : "", default_value => "", class => $prefix_class, extra => "maxlength=\"5\"", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_prefix => $say_prefix }}); my $domain_class = $anvil->data->{cgi}{domain}{alert} ? "input_alert" : "input_clear"; my $say_domain = $anvil->Template->get({file => "main.html", name => "input_text_form", variables => { name => "domain", id => "domain", field => "#!string!striker_0007!#", description => "#!string!striker_0008!#", value => defined $anvil->data->{cgi}{domain}{value} ? $anvil->data->{cgi}{domain}{value} : "", default_value => "", class => $domain_class, extra => "maxlength=\"255\"", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_domain => $say_domain }}); my $sequence_class = $anvil->data->{cgi}{sequence}{alert} ? "input_alert" : "input_clear"; my $say_sequence = $anvil->Template->get({file => "main.html", name => "input_number_form", variables => { name => "sequence", id => "sequence", field => "#!string!striker_0009!#", description => "#!string!striker_0010!#", value => defined $anvil->data->{cgi}{sequence}{value} ? $anvil->data->{cgi}{sequence}{value} : "", class => $sequence_class, extra => "min=\"1\" max=\"24\"", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_domain => $say_domain }}); my $ifn_count_class = $anvil->data->{cgi}{ifn_count}{alert} ? "input_alert" : "input_clear"; my $say_ifn_count = $anvil->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 $anvil->data->{cgi}{ifn_count}{value} ? $anvil->data->{cgi}{ifn_count}{value} : "", class => $ifn_count_class, extra => "min=\"1\" max=\"24\"", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_ifn_count => $say_ifn_count }}); my $step1_body = $anvil->Template->get({file => "config.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, }}); $anvil->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 $anvil->data->{network}{{...}. sub get_network_details { my ($anvil) = @_; ### TODO: Daemonize this or solve selinux issues ### Refresh the network.xml #$anvil->System->call({shell_call => $anvil->data->{path}{exe}{'anvil-update-states'}.$anvil->Log->switches}); # Now read the network.xml my $file = $anvil->data->{path}{directories}{html}."/status/network.xml"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { file => $file }}); # Parse... local $@; my $xml = XML::Simple->new(); my $data = ""; my $network = ""; my $test = eval { $data = $xml->XMLin($file, KeyAttr => { interface => 'name', key => 'name', ip => 'address' }, ForceArray => [ 'interface', 'key' ] ) }; if (not $test) { chomp $@; my $error = "[ Error ] - The was a problem reading: [$file]. The error was:\n"; $error .= "===========================================================\n"; $error .= $@."\n"; $error .= "===========================================================\n"; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", raw => $error}); } else { foreach my $interface (sort {$a cmp $b} keys %{$data->{interface}}) { $anvil->data->{interfaces}{$interface} = { bond => $data->{interface}{$interface}{bond}, bridge => $data->{interface}{$interface}{bridge}, duplex => $data->{interface}{$interface}{duplex}, 'link' => $data->{interface}{$interface}{'link'}, mac => $data->{interface}{$interface}{mac}, media => $data->{interface}{$interface}{media}, mtu => $data->{interface}{$interface}{mtu}, order => $data->{interface}{$interface}{order}, speed => $data->{interface}{$interface}{speed}, 'state' => $data->{interface}{$interface}{'state'}, }; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "interfaces::${interface}::bond" => $anvil->data->{interfaces}{$interface}{bond}, "interfaces::${interface}::bridge" => $anvil->data->{interfaces}{$interface}{bridge}, "interfaces::${interface}::duplex" => $anvil->data->{interfaces}{$interface}{duplex}, "interfaces::${interface}::link" => $anvil->data->{interfaces}{$interface}{'link'}, "interfaces::${interface}::mac" => $anvil->data->{interfaces}{$interface}{mac}, "interfaces::${interface}::media" => $anvil->data->{interfaces}{$interface}{media}, "interfaces::${interface}::mtu" => $anvil->data->{interfaces}{$interface}{mtu}, "interfaces::${interface}::order" => $anvil->data->{interfaces}{$interface}{order}, "interfaces::${interface}::speed" => $anvil->data->{interfaces}{$interface}{speed}, "interfaces::${interface}::state" => $anvil->data->{interfaces}{$interface}{'state'}, }}); } ### TODO: Sort out how to read the XML using the proper KeyAttr to avoid this mess... # If there is only one IP, the details will be stored directly under the 'ip' key. If two or # more exist, each ip address will be the key after 'ip'. if (exists $data->{ip}{address}) { # Only one entry. Fix the hash. my $address = $data->{ip}{address}; my $on = $data->{ip}{on}; my $subnet_mask = $data->{ip}{subnet_mask}; my $gateway = $data->{ip}{gateway}; my $default_gateway = $data->{ip}{default_gateway}; my $dns = $data->{ip}{dns}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { address => $address, on => $on, subnet_mask => $subnet_mask, gateway => $gateway, default_gateway => $default_gateway, dns => $dns, }}); $anvil->data->{ip}{$address} = { on => $on, subnet_mask => $subnet_mask, gateway => $gateway, default_gateway => $default_gateway, dns => $dns, }; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ip::${address}::on" => $anvil->data->{ip}{$address}{on}, "ip::${address}::subnet_mask" => $anvil->data->{ip}{$address}{subnet_mask}, "ip::${address}::gateway" => $anvil->data->{ip}{$address}{gateway}, "ip::${address}::default_gateway" => $anvil->data->{ip}{$address}{default_gateway}, "ip::${address}::dns" => $anvil->data->{ip}{$address}{dns}, }}); } else { foreach my $address (sort {$a cmp $b} keys %{$data->{ip}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { address => $address }}); $anvil->data->{ip}{$address} = { on => $data->{ip}{$address}{on}, subnet_mask => $data->{ip}{$address}{subnet_mask}, gateway => $data->{ip}{$address}{gateway}, default_gateway => $data->{ip}{$address}{default_gateway}, dns => $data->{ip}{$address}{dns}, }; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "ip::${address}::on" => $anvil->data->{ip}{$address}{on}, "ip::${address}::subnet_mask" => $anvil->data->{ip}{$address}{subnet_mask}, "ip::${address}::gateway" => $anvil->data->{ip}{$address}{gateway}, "ip::${address}::default_gateway" => $anvil->data->{ip}{$address}{default_gateway}, "ip::${address}::dns" => $anvil->data->{ip}{$address}{dns}, }}); } } } return(0); } sub get_network_details_form { my ($anvil) = @_; my $file = $anvil->data->{path}{directories}{html}."/status/network.xml"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { file => $file }}); local $@; my $xml = XML::Simple->new(); my $data = ""; my $network = ""; my $test = eval { $data = $xml->XMLin($file, KeyAttr => { interface => 'name', key => 'name' }, ForceArray => [ 'interface', 'key' ]) }; if (not $test) { chomp $@; my $error = "[ Error ] - The was a problem reading: [$file]. The error was:\n"; $error .= "===========================================================\n"; $error .= $@."\n"; $error .= "===========================================================\n"; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", raw => $error}); } else { my $interface_list = ""; $network = $anvil->Template->get({file => "config.html", name => "network_header"}); foreach my $interface (sort {$a cmp $b} keys %{$data->{interface}}) { $interface_list .= "$interface,"; $network .= $anvil->Template->get({file => "config.html", name => "network_entry", variables => { mac => "", mac_id => $interface."_mac", name => $interface, name_id => $interface."_name", speed => "", speed_id => $interface."_speed", 'link' => "", link_id => $interface."_link", order => "", order_id => $interface."_order", }}); } $interface_list =~ s/,$//; $network .= $anvil->Template->get({file => "config.html", name => "network_footer", variables => { interface_list => $interface_list }}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { network => $network }}); return($network); } =cut Network planning; 10.x.y.z / 255.255.0.0 10.x.y.z / 255.255.0.0 x = Network; - BCN = 200 + network ie: BCN1 = 10.201.y.z BCN2 = 10.202.y.z - SN = 100 + network ie: SN1 = 10.101.y.z SN2 = 10.102.y.z - MN = 199 ie: MN1 = 10.199.y.z y = Device Type. Foudation Pack; 1. Switches 2. PDUs 3. UPSes 4. Switches 5. Strikers 6. Striker IPMI (BCN only) Anvil! systems; 1st - 10 = Node IP 11 = Node IPMI 2nd - 12 = Node IP 13 = Node IPMI 3rd - 14 = Node IP 15 = Node IPMI N... z = Device Sequence - Foundation pack devices are simple sequence - Anvils; .1 = node 1, .2 = node 2, .3 = DR host =cut # This is a rudimentary function for generating default Striker IPs. sub generate_ip { my ($anvil, $network, $network_sequence, $device_sequence) = @_; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, 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 mask's second octet will be '+X' where 'X' is the sequence. my $default_ip = $anvil->data->{defaults}{network}{$network}{network}; my $default_subnet_mask = $anvil->data->{defaults}{network}{$network}{subnet_mask}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { default_ip => $default_ip, default_subnet_mask => $default_subnet_mask, }}); if (($anvil->Validate->ipv4({ip => $default_ip})) && ($anvil->Validate->ipv4({ip => $default_subnet_mask}))) { # Valid values. my ($ip_octet1, $ip_octet2, $ip_octet3, $ip_octet4) = (split/\./, $default_ip); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { ip_octet1 => $ip_octet1, ip_octet2 => $ip_octet2, ip_octet3 => $ip_octet3, ip_octet4 => $ip_octet4, }}); if ($default_subnet_mask eq "255.255.0.0") { # We can work with this. if ($network ne "ifn") { $ip_octet2 += $network_sequence; } $ip_octet3 = $anvil->data->{defaults}{network}{$network}{striker_octet3}; $ip_octet4 = $device_sequence; $ip = $ip_octet1.".".$ip_octet2.".".$ip_octet3.".".$ip_octet4; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, 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!#"; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { ip => $ip }}); return($ip); }