#!/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();
$anvil->Log->level({set => 2});
$anvil->Log->secure({set => 1});

### 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!#" : "&nbsp;",
	}});

	# Display the page.
	my $say_center_top_bar = "&nbsp;";
	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   => "&nbsp;",
		center_bottom_bar => "&nbsp;",
		right_bottom_bar  => "&nbsp;",
		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 => 3, 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 - There 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();
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { cookie_problem => $cookie_problem }});
		if (not $cookie_problem)
		{
			$logged_in = 1;
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, 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 OK.
	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;
				   $job_data   .= $state_uuid.",";
				$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
					state_uuid => $state_uuid,
					show_list  => $show_list, 
					job_data   => $job_data, 
				}});
			}
		}
		$job_data =~ s/,$//;
		$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_data => $job_data }});
		
		if ($job_data)
		{
			my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
				file            => $THIS_FILE, 
				line            => __LINE__, 
				job_command     => $anvil->data->{path}{exe}{'anvil-manage-keys'}, 
				job_data        => $job_data, 
				job_name        => "manage::broken_keys", 
				job_title       => "job_0056", 
				job_description => "job_0057", 
				job_progress    => 0,
				job_host_uuid   => $anvil->data->{sys}{host_uuid},
			});
			$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!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->data->{sys}{database}{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'}, 
			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->data->{sys}{database}{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'}, 
				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->data->{sys}{database}{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'}, 
				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" : "falsa";
				$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->data->{sys}{database}{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'}, 
							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);
	}
	
	# (Re)load the data.
	$anvil->Database->get_files();
	$anvil->Database->get_file_locations();

	# 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();
			$anvil->Database->get_file_locations();
			
			my $say_save_confirm  = "&nbsp;";
			my $say_purge_confirm = "&nbsp;";
			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};
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 
		bcn_count => $bcn_count, 
		sn_count  => $sn_count, 
		ifn_count => $ifn_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'}, 
				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'}, 
				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'}, 
					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", "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"; }
			$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", "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"; }
			$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 ? '<span class="available">#!string!unit_0001!#</span>' : '<span class="unavailable">#!string!unit_0002!#</span>',
			node2 => $node2_uses ? '<span class="available">#!string!unit_0001!#</span>' : '<span class="unavailable">#!string!unit_0002!#</span>',
			dr1   => $dr1_uses   ? '<span class="available">#!string!unit_0001!#</span>' : '<span class="unavailable">#!string!unit_0002!#</span>',
		}});
		$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}{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::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}{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", "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", "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}{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" : "",
			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}{bcn_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 <input type="hidden" name="'.$network_key.'" id="'.$network_key.'" value="'.$anvil->data->{cgi}{sn1_subnet}{value}.'" />',
			}});
		}
		
		# 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", "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"; }

				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", "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", "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"; }

				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
					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 }});
	
	# 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 }})."<br />";
					$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 }})."<br />";
					$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 <div> 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 }})."<br />";
							$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 }})."<br />";
							$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 => "&nbsp;", 
					}});
					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/"/&quot;/g;
							my $value      =  $anvil->data->{fence}{confirm_table}{data}{$name}{$i}{value};
							   $value      =~ s/"/&quot;/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}     = "0";
		$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'}    = "";
		
		# 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}})
			{
				# 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;
				}
				
				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/"/&quot;/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."::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 <div> 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.
		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});
		
		$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 <br /> elements.
	$agent_description =~ s/\n/<br \/>/gs;
	$agent_description =~ s/<br \/>/<br \/>\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/<br \/>//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 .= "<pre>\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 .= "</pre>\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/<br \/>//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);
	}
	
	# Pull the host's data out of the JSON file.
	$anvil->Striker->parse_all_status_json();
	
	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;
			$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { host_name => $host_name }});
			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 => 3, 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 => 3, list => { "interfaces->{".$interface."}" => $interfaces->{$interface} }});
	}
	
	# Get the interface count
	my $interface_count = keys %{$interfaces};
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { interface_count => $interface_count }});
	
	if ($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 and SN. So at this time, we'll show one BCN pair, one SN
	#       pair and N-IFN pairs.
	my $bcn_pair_count = 1;
	my $sn_pair_count  = 1;
	my $ifn_pair_count = int(($interface_count - 4) / 2);
	   $ifn_pair_count = 1 if $ifn_pair_count < 1;
	$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 
		bcn_pair_count => $bcn_pair_count,
		sn_pair_count  => $sn_pair_count,
		ifn_pair_count => $ifn_pair_count,
	}});
	
	### NOTE: The weird 'form::config_step2::<x>::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", "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 "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 .= ",<br /> &nbsp; #!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 .= ",<br /> &nbsp; #!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 ($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'}, 
				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,
				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", "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;
		}
		$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" ? 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,
		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->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}, 
			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";
		my $job_title       = "job_0009";
		my $job_description = "job_0006";
		my $say_title       = "#!string!job_0005!#";
		my $say_description = "#!string!job_0006!#";
		if ($task eq "poweroff")
		{
			$job_command     = $anvil->data->{path}{exe}{'anvil-manage-power'}." --poweroff -y";
			$job_title       = "job_0010";
			$job_description = "job_0008";
			$say_title       = "#!string!job_0007!#";
			$say_description = "#!string!job_0008!#";
		}
		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'}, 
			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} : $anvil->data->{sys}{database}{user};
		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, the 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->data->{sys}{database}{name};
		my $user     = $anvil->data->{database}{$uuid}{user}     ? $anvil->data->{database}{$uuid}{user}     : $anvil->data->{sys}{database}{user};
		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->data->{sys}{database}{name};
	my $user      = $anvil->data->{database}{$uuid}{user} ? $anvil->data->{database}{$uuid}{user} : $anvil->data->{sys}{database}{user};
	$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, 
			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 => "<input type=\"hidden\" name=\"delete\" id=\"delete\" value=\"".$uuid."\" />",
		}});
	}
	
	
	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 = $anvil->data->{sys}{database}{user};
	my $host       = $anvil->data->{cgi}{new_peer_access}{value};
	my $password   = $anvil->data->{cgi}{new_peer_password}{value};
	my $db_name    = $anvil->data->{sys}{database}{name};
	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->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;
				   $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'}, 
			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();
		$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'}});
	
	# 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

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);
}
