Author: arkurth
Date: Thu Dec 11 18:28:52 2014
New Revision: 1644715

URL: http://svn.apache.org/r1644715
Log:
VCL-174
Updated OS.pm::process_connect_methods. It was not configuring the NAT 
forwarding correctly. Reworked NAT subroutines in iptables.pm.

Renamed nathost.natIP to publicIPaddress. Added nathost.internalIPaddress.

Added subroutines to Linux.pm and corresponding subroutines to init modules:
is_service_enabled
is_service_running
enable_service
disable_service

Modified:
    vcl/trunk/managementnode/lib/VCL/DataStructure.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm
    vcl/trunk/managementnode/lib/VCL/Module/State.pm
    vcl/trunk/managementnode/lib/VCL/utils.pm

Modified: vcl/trunk/managementnode/lib/VCL/DataStructure.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=1644715&r1=1644714&r2=1644715&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/DataStructure.pm Thu Dec 11 18:28:52 2014
@@ -251,7 +251,8 @@ $SUBROUTINE_MAPPINGS{nathost_hostname} =
 $SUBROUTINE_MAPPINGS{nathost_date_deleted} = 
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{nathost}{datedeleted}';
 $SUBROUTINE_MAPPINGS{nathost_deleted} = 
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{nathost}{deleted}';
 $SUBROUTINE_MAPPINGS{nathost_id} = 
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{nathost}{id}';
-$SUBROUTINE_MAPPINGS{nathost_nat_ip} = 
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{nathost}{natIP}';
+$SUBROUTINE_MAPPINGS{nathost_public_ip_address} = 
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{nathost}{publicIPaddress}';
+$SUBROUTINE_MAPPINGS{nathost_internal_ip_address} = 
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{nathost}{internalIPaddress}';
 $SUBROUTINE_MAPPINGS{nathost_resource_id} = 
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{nathost}{resource}{id}';
 $SUBROUTINE_MAPPINGS{nathost_resource_subid} = 
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{nathost}{resource}{subid}';
 $SUBROUTINE_MAPPINGS{nathost_resourcetype_id} = 
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{nathost}{resource}{resourcetype}{id}';

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS.pm?rev=1644715&r1=1644714&r2=1644715&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Thu Dec 11 18:28:52 2014
@@ -2664,6 +2664,8 @@ sub process_connect_methods {
        my $reservation_id = $self->data->get_reservation_id();
        my $request_state = $self->data->get_request_state_name();
        my $computer_node_name = $self->data->get_computer_node_name();
+       my $nathost_hostname = $self->data->get_nathost_hostname(0);
+       my $nathost_public_ip_address = 
$self->data->get_nathost_public_ip_address(0);
        
        # Retrieve the connect method info hash
        my $connect_method_info = $self->data->get_connect_methods();
@@ -2672,25 +2674,6 @@ sub process_connect_methods {
                return;
        }
        
-       # Check if NAT is used
-       my $nathost_hostname;
-       my $computer_private_ip_address;
-       if ($self->nathost_os(0)) {
-               $nathost_hostname = $self->data->get_nathost_hostname();
-               # Call configure_nat - this adds a chain for the reservation if 
one does not already exist
-               if (!$self->nathost_os->firewall->configure_nat()) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to configure NAT 
on $nathost_hostname");
-                       return;
-               }
-               
-               # Retrieve the computer's private IP address
-               $computer_private_ip_address = $self->get_private_ip_address();
-               if (!$computer_private_ip_address) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to retrieve 
private IP address of computer $computer_node_name, unable to configure NAT 
port forwarding");
-                       return;
-               }
-       }
-       
        my $remote_ip = shift;
        if (!$remote_ip) {
                notify($ERRORS{'OK'}, 0, "reservation remote IP address is not 
defined, connect methods will be available from any IP address");
@@ -2710,6 +2693,38 @@ sub process_connect_methods {
                $overwrite = 0;
        }
        
+       # Check if NAT is used
+       my $computer_ip_address;
+       if ($nathost_hostname) {
+               if (!$self->nathost_os(0)) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to process 
connect methods, $computer_node_name is assigned to NAT host $nathost_hostname 
but NAT host OS object is not available");
+                       return;
+               }
+               elsif (!$self->nathost_os->firewall()) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to process 
connect methods, $computer_node_name is assigned to NAT host $nathost_hostname 
but NAT host OS's firewall object is not available");
+                       return;
+               }
+               
+               # Get the IP address used to communicate between the NAT host 
and computer
+               $computer_ip_address = $self->get_public_ip_address();
+               if (!$computer_ip_address) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to process 
connect methods, failed to retrieve public (internal NAT) IP address of 
computer $computer_node_name, unable to configure NAT port forwarding");
+                       return;
+               }
+               
+               # Perform general NAT configuration
+               if (!$self->nathost_os->firewall->configure_nat()) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to process 
connect methods, failed to configure NAT on $nathost_hostname");
+                       return;
+               }
+               
+               # Perform reservation-specific NAT configuration
+               if (!$self->nathost_os->firewall->configure_nat_reservation()) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to process 
connect methods, failed to configure NAT on $nathost_hostname for this 
reservation");
+                       return;
+               }
+       }
+       
        CONNECT_METHOD: for my $connect_method_id (sort keys 
%{$connect_method_info} ) {
                my $connect_method = $connect_method_info->{$connect_method_id};
                
@@ -2788,24 +2803,22 @@ sub process_connect_methods {
                                        }
                                }
                                
-                               my $nat_public_port = 
$connect_method->{connectmethodport}{$connect_method_port_id}{natport}{publicport};
-                               if ($nat_public_port) {
-                                       if (!$self->nathost_os(0)) {
-                                               notify($ERRORS{'WARNING'}, 0, 
"connect method info contains NAT port information but NAT OS object is not 
available to control $nathost_hostname");
+                               # Configure NAT port forwarding if NAT is being 
used
+                               if ($nathost_hostname) {
+                                       my $nat_public_port = 
$connect_method->{connectmethodport}{$connect_method_port_id}{natport}{publicport};
+                                       if (!defined($nat_public_port)) {
+                                               notify($ERRORS{'WARNING'}, 0, 
"$computer_node_name is assigned to NAT host $nathost_hostname but connect 
method info does not contain NAT port information:\n" . 
format_data($connect_method));
                                                return;
                                        }
-                                       if 
($self->nathost_os->firewall->add_nat_port_forward($protocol, $nat_public_port, 
$computer_private_ip_address, $port, $reservation_id)) {
-                                               notify($ERRORS{'OK'}, 0, 
"configured forwarded NAT port on $nathost_hostname: $protocol/$nat_public_port 
--> $computer_private_ip_address:$port");
+                                       
+                                       if 
($self->nathost_os->firewall->add_nat_port_forward($protocol, $nat_public_port, 
$computer_ip_address, $port, $reservation_id)) {
+                                               notify($ERRORS{'OK'}, 0, "NAT 
port forwarding configured on $nathost_hostname for '$name' connect method: 
$nat_public_port --> $computer_ip_address:$port ($protocol)");
                                        }
                                        else {
-                                               notify($ERRORS{'WARNING'}, 0, 
"failed to process '$name' connect method, unable to configure forwarded NAT 
port on $nathost_hostname: $protocol/$nat_public_port --> 
$computer_private_ip_address:$port");
+                                               notify($ERRORS{'WARNING'}, 0, 
"failed to configure NAT port forwarding on $nathost_hostname for '$name' 
connect method: $nathost_public_ip_address:$nat_public_port --> 
$computer_ip_address:$port ($protocol)");
                                                return;
                                        }
                                }
-                               elsif ($self->nathost_os(0)) {
-                                       notify($ERRORS{'WARNING'}, 0, "NAT OS 
object is not available but connect method info does not contain NAT port 
information:\n" . format_data($connect_method_info));
-                                       return;
-                               }
                        }
                }
        }

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm?rev=1644715&r1=1644714&r2=1644715&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Thu Dec 11 18:28:52 2014
@@ -269,7 +269,7 @@ sub firewall {
                # Attempt to create the object
                my $firewall_object;
                eval {
-                       $firewall_object = 
($firewall_perl_package)->new({data_structure => $self->data, base_package => 
ref($self)})
+                       $firewall_object = 
($firewall_perl_package)->new({data_structure => $self->data, base_package => 
ref($self), os => $self->os})
                };
                
                if ($EVAL_ERROR) {
@@ -3118,6 +3118,163 @@ sub service_exists {
 }
 
 #/////////////////////////////////////////////////////////////////////////////
+
+=head2 is_service_enabled
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Determines if a service is enabled on the computer.
+
+=cut
+
+sub is_service_enabled {
+       my $self = shift;
+       if (ref($self) !~ /linux/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
+               return;
+       }
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my ($init_module_index) = $self->service_exists($service_name);
+       if (!defined($init_module_index)) {
+               notify($ERRORS{'WARNING'}, 0, "unable to determine if 
'$service_name' service is enabled, it does not exist on $computer_node_name");
+               return;
+       }
+       
+       my $init_module = ($self->get_init_modules())[$init_module_index];
+       if (!$init_module->can('service_enabled')) {
+               notify($ERRORS{'WARNING'}, 0, "unable to determine if 
'$service_name' service is enabled on $computer_node_name, " . 
ref($init_module) . " module does not implement a 'service_running' 
subroutine");
+               return;
+       }
+       return $init_module->service_enabled($service_name);
+}
+
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 is_service_running
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Determines if a service is running on the computer.
+
+=cut
+
+sub is_service_running {
+       my $self = shift;
+       if (ref($self) !~ /linux/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
+               return;
+       }
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my ($init_module_index) = $self->service_exists($service_name);
+       if (!defined($init_module_index)) {
+               notify($ERRORS{'WARNING'}, 0, "unable to determine if 
'$service_name' service is running, it does not exist on $computer_node_name");
+               return;
+       }
+       
+       my $init_module = ($self->get_init_modules())[$init_module_index];
+       if (!$init_module->can('service_running')) {
+               notify($ERRORS{'WARNING'}, 0, "unable to determine if 
'$service_name' service is running on $computer_node_name, " . 
ref($init_module) . " module does not implement a 'service_running' 
subroutine");
+               return;
+       }
+       return $init_module->service_running($service_name);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 enable_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Enables a service on the computer.
+
+=cut
+
+sub enable_service {
+       my $self = shift;
+       if (ref($self) !~ /linux/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
+               return;
+       }
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my ($init_module_index) = $self->service_exists($service_name);
+       if (!defined($init_module_index)) {
+               notify($ERRORS{'WARNING'}, 0, "unable to enable '$service_name' 
service, it does not exist on $computer_node_name");
+               return;
+       }
+       
+       my $init_module = ($self->get_init_modules())[$init_module_index];
+       if (!$init_module->can('_enable_service')) {
+               notify($ERRORS{'WARNING'}, 0, "unable to enable '$service_name' 
service on $computer_node_name, " . ref($init_module) . " module does not 
implement an '_enable_service' subroutine");
+               return;
+       }
+       return $init_module->_enable_service($service_name);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 disable_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : disables a service on the computer.
+
+=cut
+
+sub disable_service {
+       my $self = shift;
+       if (ref($self) !~ /linux/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
+               return;
+       }
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my ($init_module_index) = $self->service_exists($service_name);
+       if (!defined($init_module_index)) {
+               notify($ERRORS{'WARNING'}, 0, "unable to disable 
'$service_name' service, it does not exist on $computer_node_name");
+               return;
+       }
+       
+       my $init_module = ($self->get_init_modules())[$init_module_index];
+       if (!$init_module->can('_disable_service')) {
+               notify($ERRORS{'WARNING'}, 0, "unable to disable 
'$service_name' service on $computer_node_name, " . ref($init_module) . " 
module does not implement an '_disable_service' subroutine");
+               return;
+       }
+       return $init_module->_disable_service($service_name);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
 
 =head2 start_service
 

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm?rev=1644715&r1=1644714&r2=1644715&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm 
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm Thu 
Dec 11 18:28:52 2014
@@ -144,6 +144,11 @@ sub insert_rule {
        # Add the parameters to the command
        for my $parameter (sort keys %{$arguments->{parameters}}) {
                my $value = $arguments->{parameters}{$parameter};
+               
+               if ($parameter =~ /^\!/) {
+                       $command .= " !";
+                       $parameter =~ s/^\!//;
+               }
                $command .= " --$parameter $value";
        }
        
@@ -596,202 +601,238 @@ sub configure_nat {
                return 0;
        }
        
-       my $reservation_id = $self->data->get_reservation_id();
        my $computer_name = $self->data->get_computer_hostname();
        
-       my $table_info = $self->get_table_info('nat');
-       if (!$table_info) {
+       my $public_ip_address = 
$self->os->data->get_nathost_public_ip_address();
+       my $internal_ip_address = 
$self->os->data->get_nathost_internal_ip_address(0);
+       if (!$internal_ip_address) {
+               notify($ERRORS{'DEBUG'}, 0, "unable to automatically configure 
NAT, nathost.internalIPaddress is not set");
+               return 1;
+       }
+       
+       # Enable IP port forwarding
+       if (!$self->enable_ip_forwarding()) {
+               notify($ERRORS{'WARNING'}, 0, "unable to configure NAT host 
$computer_name, failed to enable IP forwarding");
+               return;
+       }
+       
+       my $nat_table_info = $self->get_table_info('nat');
+       if (!$nat_table_info) {
                notify($ERRORS{'WARNING'}, 0, "failed to configure NAT on 
$computer_name, nat table info could not be retrieved");
                return;
        }
-       elsif (!defined($table_info->{PREROUTING})) {
-               notify($ERRORS{'WARNING'}, 0, "unable to configure NAT on 
$computer_name, nat table does not contain a PREROUTING chain:\n" . 
format_data($table_info));
+       elsif (!defined($nat_table_info->{PREROUTING})) {
+               notify($ERRORS{'WARNING'}, 0, "unable to configure NAT on 
$computer_name, nat table does not contain a PREROUTING chain:\n" . 
format_data($nat_table_info));
                return;
        }
-       elsif (!defined($table_info->{POSTROUTING})) {
-               notify($ERRORS{'WARNING'}, 0, "unable to configure NAT on 
$computer_name, nat table does not contain a POSTROUTING chain:\n" . 
format_data($table_info));
+       elsif (!defined($nat_table_info->{POSTROUTING})) {
+               notify($ERRORS{'WARNING'}, 0, "unable to configure NAT on 
$computer_name, nat table does not contain a POSTROUTING chain:\n" . 
format_data($nat_table_info));
                return;
        }
        
        # Check if NAT has previously been configured
-       my $nat_previously_configured = 0;
-       for my $rule_specification (@{$table_info->{POSTROUTING}{rules}}) {
+       for my $rule_specification (@{$nat_table_info->{POSTROUTING}{rules}}) {
                if ($rule_specification =~ /MASQUERADE/) {
-                       $nat_previously_configured = 1;
                        notify($ERRORS{'DEBUG'}, 0, "POSTROUTING chain in nat 
table contains a MASQUERADE rule, assuming NAT has already been configured: 
$rule_specification");
-                       last;
+                       return 1;
                }
        }
-       if (!$nat_previously_configured) {
-               my $private_interface_name = 
$self->get_private_interface_name();
-               my $private_ip_address = $self->get_private_ip_address();
-               my $public_interface_name = $self->get_public_interface_name();
-               my $public_ip_address = $self->get_public_ip_address();
+       
+       # Figure out the public and internal interface names
+       my $public_interface_name;
+       my $internal_interface_name;
+       my $network_configuration = $self->get_network_configuration();
+       for my $interface_name (keys %$network_configuration) {
+               my @ip_addresses = keys 
%{$network_configuration->{$interface_name}{ip_address}};
                
-               my $natport_ranges_variable = get_variable('natport_ranges') || 
'49152-65535';
-               my $destination_ports = '';
-               for my $natport_range (split(/[,;]+/, 
$natport_ranges_variable)) {
-                       my ($start_port, $end_port) = $natport_range =~ 
/(\d+)-(\d+)/g;
-                       if (!defined($start_port)) {
-                               notify($ERRORS{'WARNING'}, 0, "unable to parse 
NAT port range: '$natport_range'");
-                               next;
-                       }
-                       $destination_ports .= "," if ($destination_ports);
-                       $destination_ports .= "$start_port:$end_port";
+               # Check if the interface is assigned the nathost.publicIPaddress
+               if (grep { $_ eq $public_ip_address } @ip_addresses) {
+                       $public_interface_name = $interface_name;
                }
                
-               
-               if (!$self->insert_rule({
-                       'table' => 'nat',
-                       'chain' => 'POSTROUTING',
-                       'parameters' => {
-                               'out-interface' => $private_interface_name,
-                               'jump' => 'MASQUERADE',
+               # If nathost.internalIPaddress is set, check if interface is 
assigned matching IP address
+               if (grep { $_ eq $internal_ip_address } @ip_addresses) {
+                       $internal_interface_name = $interface_name;
+               }
+       }
+       if (!$public_interface_name) {
+               notify($ERRORS{'WARNING'}, 0, "failed to configure NAT host 
$computer_name, no interface is assigned the public IP address configured in 
the nathost table: $public_ip_address\n" . format_data($network_configuration));
+               return;
+       }
+       if (!$internal_interface_name) {
+               notify($ERRORS{'WARNING'}, 0, "failed to configure NAT host 
$computer_name, no interface is assigned the internal IP address configured in 
the nathost table: $internal_ip_address\n" . 
format_data($network_configuration));
+               return;
+       }
+       
+       
+       my $natport_ranges_variable = get_variable('natport_ranges') || 
'49152-65535';
+       my $destination_ports = '';
+       for my $natport_range (split(/[,;]+/, $natport_ranges_variable)) {
+               my ($start_port, $end_port) = $natport_range =~ /(\d+)-(\d+)/g;
+               if (!defined($start_port)) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to parse NAT port 
range: '$natport_range'");
+                       next;
+               }
+               $destination_ports .= "," if ($destination_ports);
+               $destination_ports .= "$start_port:$end_port";
+       }
+       
+       
+       if (!$self->insert_rule({
+               'table' => 'nat',
+               'chain' => 'POSTROUTING',
+               'parameters' => {
+                       'out-interface' => $public_interface_name,
+                       'jump' => 'MASQUERADE',
+               },
+               'match_extensions' => {
+                       'comment' => {
+                               'comment' => "change IP of outbound 
$public_interface_name packets to NAT host IP address $public_ip_address",
                        },
-                       'match_extensions' => {
-                               'comment' => {
-                                       'comment' => "change IP of outbound 
private $private_interface_name packets to NAT host private IP address 
$private_interface_name",
-                               },
+               },
+       })) {
+               return;
+       }
+       
+       if (!$self->insert_rule({
+               'chain' => 'INPUT',
+               'parameters' => {
+                       'in-interface' => $public_interface_name,
+                       'destination' => $public_ip_address,
+                       'jump' => 'ACCEPT',
+                       'protocol' => 'tcp',
+               },
+               'match_extensions' => {
+                       'state' => {
+                               'state' => 'RELATED,ESTABLISHED',
                        },
-               })) {
-                       return;
-               }
-               
-               if (!$self->insert_rule({
-                       'chain' => 'INPUT',
-                       'parameters' => {
-                               'in-interface' => $public_interface_name,
-                               'destination' => $public_ip_address,
-                               'jump' => 'ACCEPT',
-                               'protocol' => 'tcp',
+                       'multiport' => {
+                               'destination-ports' => $destination_ports,
                        },
-                       'match_extensions' => {
-                               'state' => {
-                                       'state' => 'RELATED,ESTABLISHED',
-                               },
-                               'multiport' => {
-                                       'destination-ports' => 
$destination_ports,
-                               },
+               },
+       })) {
+               return;
+       }
+       
+       if (!$self->insert_rule({
+               'chain' => 'INPUT',
+               'parameters' => {
+                       'in-interface' => $public_interface_name,
+                       'destination' => $public_ip_address,
+                       'jump' => 'ACCEPT',
+                       'protocol' => 'udp',
+               },
+               'match_extensions' => {
+                       'state' => {
+                               'state' => 'RELATED,ESTABLISHED',
                        },
-               })) {
-                       return;
-               }
-               
-               if (!$self->insert_rule({
-                       'chain' => 'INPUT',
-                       'parameters' => {
-                               'in-interface' => $public_interface_name,
-                               'destination' => $public_ip_address,
-                               'jump' => 'ACCEPT',
-                               'protocol' => 'udp',
+                       'multiport' => {
+                               'destination-ports' => $destination_ports,
                        },
-                       'match_extensions' => {
-                               'state' => {
-                                       'state' => 'RELATED,ESTABLISHED',
-                               },
-                               'multiport' => {
-                                       'destination-ports' => 
$destination_ports,
-                               },
+               },
+       })) {
+               return;
+       }
+       
+       if (!$self->insert_rule({
+               'chain' => 'FORWARD',
+               'parameters' => {
+                       'in-interface' => $public_interface_name,
+                       'out-interface' => $internal_interface_name,
+                       'jump' => 'ACCEPT',
+               },
+               'match_extensions' => {
+                       'state' => {
+                               'state' => 'NEW,RELATED,ESTABLISHED',
                        },
-               })) {
-                       return;
-               }
-               
-               if (!$self->insert_rule({
-                       'chain' => 'FORWARD',
-                       'parameters' => {
-                               'in-interface' => $public_interface_name,
-                               'out-interface' => $private_interface_name,
-                               'jump' => 'ACCEPT',
+                       'comment' => {
+                               'comment' => "forward inbound packets from 
public $public_interface_name to internal $internal_interface_name",
                        },
-                       'match_extensions' => {
-                               'state' => {
-                                       'state' => 'NEW,RELATED,ESTABLISHED',
-                               },
-                               'comment' => {
-                                       'comment' => "forward inbound packets 
from public $public_interface_name to private $private_interface_name",
-                               },
-                       },      
-               })) {
-                       return;
-               }
-               
-               if (!$self->insert_rule({
-                       'chain' => 'FORWARD',
-                       'parameters' => {
-                               'in-interface' => $private_interface_name,
-                               'out-interface' => $public_interface_name,
-                               'jump' => 'ACCEPT',
+               },      
+       })) {
+               return;
+       }
+       
+       if (!$self->insert_rule({
+               'chain' => 'FORWARD',
+               'parameters' => {
+                       'in-interface' => $internal_interface_name,
+                       'out-interface' => $public_interface_name,
+                       'jump' => 'ACCEPT',
+               },
+               'match_extensions' => {
+                       'state' => {
+                               'state' => 'NEW,RELATED,ESTABLISHED',
                        },
-                       'match_extensions' => {
-                               'comment' => {
-                                       'comment' => "forward outbound packets 
from private $private_interface_name to public $public_interface_name",
-                               },
+                       'comment' => {
+                               'comment' => "forward outbound packets from 
internal $internal_interface_name to public $public_interface_name",
                        },
-               })) {
-                       return;
-               }
-               
-               #if (!$self->insert_rule({
-               #       'chain' => 'INPUT',
-               #       'parameters' => {
-               #               'in-interface' => $public_interface_name,
-               #       },
-               #       'target_extensions' => {
-               #               'REJECT' => {
-               #                       'reject-with' => "icmp-host-prohibited",
-               #               },
-               #       },
-               #})) {
-               #       return;
-               #}
-               #
-               #if (!$self->insert_rule({
-               #       'chain' => 'FORWARD',
-               #       'target_extensions' => {
-               #               'REJECT' => {
-               #                       'reject-with' => "icmp-host-prohibited",
-               #               },
-               #       },
-               #})) {
-               #       return;
-               #}
+               },
+       })) {
+               return;
+       }
+       
+       notify($ERRORS{'DEBUG'}, 0, "successfully configured NAT on 
$computer_name");
+       return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 configure_nat_reservation
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Adds a chain named after the reservation ID to the nat table.
+               Adds a rule to the PREROUTING table to jump to the reservation
+               chain.
+
+=cut
+
+sub configure_nat_reservation {
+       my $self = shift;
+       if (ref($self) !~ /VCL::Module/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return 0;
+       }
+       
+       my $reservation_id = $self->data->get_reservation_id();
+       my $computer_name = $self->data->get_computer_hostname();
+       
+       my $nat_table_info = $self->get_table_info('nat');
+       if (!$nat_table_info) {
+               notify($ERRORS{'WARNING'}, 0, "failed to configure NAT host 
$computer_name for reservation, nat table information could not be retrieved");
+               return;
        }
        
        # Check if chain for reservation has already been created
-       if (defined($table_info->{$reservation_id})) {
-               notify($ERRORS{'DEBUG'}, 0, "'$reservation_id' chain already 
exists in nat table on $computer_name for this reservation");
+       if (defined($nat_table_info->{$reservation_id})) {
+               notify($ERRORS{'DEBUG'}, 0, "'$reservation_id' chain already 
exists in nat table on $computer_name");
        }
-       else {
-               if (!$self->create_chain('nat', $reservation_id)) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to configure NAT 
on $computer_name, '$reservation_id' chain could not be created in nat table 
for this reservation");
-                       return;
-               }
+       elsif (!$self->create_chain('nat', $reservation_id)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to configure NAT host 
$computer_name for reservation, failed to add '$reservation_id' chain to nat 
table");
+               return;
        }
        
        # Check if rule to jump to reservation's chain already exists in the 
PREROUTING table
-       my $jump_previously_configured = 0;
-       for my $rule_specification (@{$table_info->{PREROUTING}{rules}}) {
+       for my $rule_specification (@{$nat_table_info->{PREROUTING}{rules}}) {
                if ($rule_specification =~ /-j $reservation_id(\s|$)/) {
-                       $jump_previously_configured = 1;
                        notify($ERRORS{'DEBUG'}, 0, "PREROUTING chain in nat 
table on $computer_name already contains a rule to jump to '$reservation_id' 
chain: $rule_specification");
-                       last;
+                       return 1;;
                }
        }
-       if (!$jump_previously_configured) {
-               if (!$self->insert_rule({
-                       'table' => 'nat',
-                       'chain' => 'PREROUTING',
-                       'parameters' => {
-                               'jump' => $reservation_id,
-                       },
-               })) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to configure NAT 
on $computer_name, failed to create rule in PREROUTING chain in nat table to 
jump to '$reservation_id' chain");
-                       return;
-               }
+       
+       # Add a rule to the nat PREROUTING chain
+       if (!$self->insert_rule({
+               'table' => 'nat',
+               'chain' => 'PREROUTING',
+               'parameters' => {
+                       'jump' => $reservation_id,
+               },
+       })) {
+               notify($ERRORS{'WARNING'}, 0, "failed to configure NAT host 
$computer_name for reservation, failed to create rule in PREROUTING chain in 
nat table to jump to '$reservation_id' chain");
+               return;
        }
        
-       notify($ERRORS{'DEBUG'}, 0, "successfully configured NAT on 
$computer_name for reservation");
        return 1;
 }
 
@@ -845,11 +886,11 @@ sub add_nat_port_forward {
                'parameters' => {
                        'protocol' => $protocol,
                        'in-interface' => $public_interface_name,
-                       'destination' => $public_ip_address,
+                       #'destination' => $public_ip_address,
                },
                'match_extensions' => {
                        'comment' => {
-                               'comment' => "change destination address: 
$public_ip_address:$source_port --> $destination_ip_address:$destination_port 
($protocol)",
+                               'comment' => "forward: 
$public_ip_address:$source_port --> $destination_ip_address:$destination_port 
($protocol)",
                        },
                        $protocol => {
                                'destination-port' => $source_port,

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm?rev=1644715&r1=1644714&r2=1644715&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm Thu Dec 11 
18:28:52 2014
@@ -132,7 +132,7 @@ sub get_service_names {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 enable_service
+=head2 _enable_service
 
  Parameters  : $service_name
  Returns     : boolean
@@ -141,7 +141,7 @@ sub get_service_names {
 
 =cut
 
-sub enable_service {
+sub _enable_service {
        my $self = shift;
        if (ref($self) !~ /VCL::Module/i) {
                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
@@ -181,7 +181,7 @@ sub enable_service {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 disable_service
+=head2 _disable_service
 
  Parameters  : $service_name
  Returns     : boolean
@@ -190,7 +190,7 @@ sub enable_service {
 
 =cut
 
-sub disable_service {
+sub _disable_service {
        my $self = shift;
        if (ref($self) !~ /VCL::Module/i) {
                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
@@ -230,6 +230,113 @@ sub disable_service {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 service_enabled
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'chkconfig --list <$service_name>' to determine if a
+               service is enabled.
+
+=cut
+
+sub service_enabled {
+       my $self = shift;
+       if (ref($self) !~ /VCL::Module/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return 0;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name argument was not 
supplied");
+               return;
+       }
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my $command = "chkconfig --list $service_name";
+       my ($exit_status, $output) = $self->execute($command, 0);
+       if (!defined($output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if '$service_name' service is enabled on $computer_node_name: 
$command");
+               return;
+       }
+       elsif (grep(/(error reading information|No such file)/i, @$output)) {
+               # Output if the service does not exist: 'error reading 
information on service httpdx: No such file or directory'
+               notify($ERRORS{'WARNING'}, 0, "'$service_name' service does not 
exist on $computer_node_name");
+               return;
+       }
+       elsif (grep(/^$service_name\s+.*3:on/i, @$output)) {
+               # Output if the service is enabled: '<service name>    0:off   
1:off   2:on    3:on    4:on    5:on    6:off'
+               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service is enabled 
on $computer_node_name");
+               return 1;
+       }
+       elsif (grep(/^$service_name\s+.*3:off/i, @$output)) {
+               # Output if the service is disabled: '<service name>    0:off   
1:off   2:off   3:off   4:off   5:off   6:off'
+               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service is not 
enabled on $computer_node_name");
+               return 0;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to determine if 
'$service_name' service is enabled on $computer_node_name, exit status: 
$exit_status, output:\n" . join("\n", @$output));
+               return;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 service_running
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'service <$service_name> status' to determine if a
+               service is running.
+
+=cut
+
+sub service_running {
+       my $self = shift;
+       if (ref($self) !~ /VCL::Module/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return 0;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name argument was not 
supplied");
+               return;
+       }
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       # Enable the service
+       my $command = "service $service_name status";
+       my ($exit_status, $output) = $self->execute($command, 0);
+       if (!defined($output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if '$service_name' service is running on $computer_node_name: 
$command");
+               return;
+       }
+       elsif (grep(/(error reading information|No such file)/i, @$output)) {
+               # Output if the service does not exist: 'error reading 
information on service httpdx: No such file or directory'
+               notify($ERRORS{'WARNING'}, 0, "'$service_name' service does not 
exist on $computer_node_name");
+               return;
+       }
+       elsif (grep(/is running/i, @$output)) {
+               # Output if the service is running: '<service name> is running'
+               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service is running 
on $computer_node_name");
+               return 1;
+       }
+       elsif (grep(/is not running/i, @$output)) {
+               # Output if the service is not running: '<service name> is not 
running'
+               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service is not 
running on $computer_node_name");
+               return 0;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to determine if 
'$service_name' service is running on $computer_node_name, exit status: 
$exit_status, output:\n" . join("\n", @$output));
+               return;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 add_service
 
  Parameters  : $service_name
@@ -559,7 +666,7 @@ sub add_ext_sshd_service {
        # Add the service
        return unless $self->add_service('ext_sshd');
        
-       return $self->enable_service('ext_sshd');
+       return $self->_enable_service('ext_sshd');
 }
 
 #/////////////////////////////////////////////////////////////////////////////

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm?rev=1644715&r1=1644714&r2=1644715&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm Thu Dec 11 
18:28:52 2014
@@ -236,7 +236,7 @@ sub start_service {
                notify($ERRORS{'DEBUG'}, 0, "'$service_name' is already running 
on $computer_node_name");
                return 1;
        }
-       elsif (grep(/process \d+/i, @$output)) {
+       elsif (grep(/running/i, @$output)) {
                # Output if the service was started: '<service name> 
start/running, process <PID>'
                notify($ERRORS{'DEBUG'}, 0, "started '$service_name' service on 
$computer_node_name");
                return 1;
@@ -422,6 +422,211 @@ sub add_ext_sshd_service {
 }
 
 #/////////////////////////////////////////////////////////////////////////////
+
+=head2 service_running
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'initctl status <$service_name>' to determine if the
+               service is running.
+
+=cut
+
+sub service_running {
+       my $self = shift;
+       if (ref($self) !~ /linux/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name argument was not 
supplied");
+               return;
+       }
+       $service_name = $SERVICE_NAME_MAPPINGS->{$service_name} || 
$service_name;
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my $command = "initctl status $service_name";
+       my ($exit_status, $output) = $self->execute($command);
+       if (!defined($output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if '$service_name' service is enabled on $computer_node_name");
+               return;
+       }
+       elsif (grep(/Unknown job/i, @$output)) {
+               # Output if the service doesn't exist: 'initctl: Unknown job: 
<service name>'
+               notify($ERRORS{'WARNING'}, 0, "'$service_name' service does not 
exist on $computer_node_name");
+               return;
+       }
+       elsif (grep(/running/i, @$output)) {
+               # Output if the service is running: '<service name> 
start/running, process <PID>'
+               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service is running 
on $computer_node_name");
+               return 1;
+       }
+       elsif (grep(/stop/i, @$output)) {
+               # Output if the service is not running: '<service 
name>stop/waiting'
+               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service is not 
running $computer_node_name");
+               return 1;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "unable to determine if 
'$service_name' service is running on $computer_node_name, exit status: 
$exit_status, command: '$command', output:\n" . join("\n", @$output));
+               return;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 service_enabled
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'initctl show-config <$service_name>' to determine if the
+               service is enabled.
+
+=cut
+
+sub service_enabled {
+       my $self = shift;
+       if (ref($self) !~ /linux/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name argument was not 
supplied");
+               return;
+       }
+       $service_name = $SERVICE_NAME_MAPPINGS->{$service_name} || 
$service_name;
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       # Check if an override file exists and contains 'manual'
+       my $service_override_file_path = "/etc/init/$service_name.override";
+       if ($self->file_exists($service_override_file_path)) {
+               my @override_file_contents = 
$self->get_file_contents($service_override_file_path);
+               if (!@override_file_contents) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to retrieve 
contents of $service_override_file_path from $computer_node_name");
+               }
+               else {
+                       if (grep(/manual/i, @override_file_contents)) {
+                               notify($ERRORS{'DEBUG'}, 0, "'$service_name' 
service is not enabled on $computer_node_name, $service_override_file_path 
exists and contains 'manual'");
+                               return 0;
+                       }
+               }
+       }
+       
+       my $command = "initctl show-config $service_name";
+       my ($exit_status, $output) = $self->execute($command);
+       if (!defined($output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if '$service_name' service is enabled on $computer_node_name");
+               return;
+       }
+       elsif (grep(/Unknown job/i, @$output)) {
+               # Output if the service doesn't exist: 'initctl: Unknown job: 
<service name>'
+               notify($ERRORS{'WARNING'}, 0, "'$service_name' service does not 
exist on $computer_node_name");
+               return;
+       }
+       elsif (grep(/start on/i, @$output)) {
+               # Output if the service is enabled:
+               # <service name>
+               #   start on (filesystem or runlevel [2345])
+               #   stop on runlevel [!2345]
+               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service is enabled 
on $computer_node_name");
+               return 1;
+       }
+       elsif (!grep(/^initctl:/, @$output)) {
+               # Output if the service is not enabled:
+               # <service name>
+               #   stop on runlevel [06]
+               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service is not 
enabled $computer_node_name");
+               return 1;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "unable to determine if 
'$service_name' service is enabled on $computer_node_name, exit status: 
$exit_status, command: '$command', output:\n" . join("\n", @$output));
+               return;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _enable_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub _enable_service {
+       my $self = shift;
+       if (ref($self) !~ /linux/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return 0;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name argument was not 
supplied");
+               return;
+       }
+       $service_name = $SERVICE_NAME_MAPPINGS->{$service_name} || 
$service_name;
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my $service_override_file_path = "/etc/init/$service_name.override";
+       
+       if (!$self->file_exists($service_override_file_path)) {
+               return 1;
+       }
+       if ($self->delete_file($service_override_file_path)) {
+               return 1;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "unable to enable '$service_name' 
service, unable to delete override file: $service_override_file_path");
+               return;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _disable_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub _disable_service {
+       my $self = shift;
+       if (ref($self) !~ /linux/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return 0;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name argument was not 
supplied");
+               return;
+       }
+       $service_name = $SERVICE_NAME_MAPPINGS->{$service_name} || 
$service_name;
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my $service_override_file_path = "/etc/init/$service_name.override";
+       
+       if ($self->create_text_file($service_override_file_path, "manual\n")) {
+               return 1;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "unable to disable 
'$service_name' service, failed to create override file: 
$service_override_file_path");
+               return;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
 
 1;
 __END__

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm?rev=1644715&r1=1644714&r2=1644715&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm Thu Dec 11 
18:28:52 2014
@@ -130,7 +130,103 @@ sub get_service_names {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 enable_service
+=head2 service_running
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'systemctl is-active' to determines if a service is
+               running.
+
+=cut
+
+sub service_running {
+       my $self = shift;
+       if (ref($self) !~ /linux/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name argument was not 
supplied");
+               return;
+       }
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my $command = "systemctl is-active $service_name.service";
+       my ($exit_status, $output) = $self->execute($command, 0);
+       if (!defined($output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if $service_name service is running on $computer_node_name");
+               return;
+       }
+       
+       # Output should either be 'active' or 'inactive
+       if (grep(/inactive/, @$output)) {
+               notify($ERRORS{'DEBUG'}, 0, "$service_name service is not 
running on $computer_node_name");
+               return 0;
+       }
+       elsif (grep(/active/, @$output)) {
+               notify($ERRORS{'DEBUG'}, 0, "$service_name service is running 
on $computer_node_name");
+               return 1;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to determine if 
$service_name service is running on $computer_node_name, output does not 
contain 'active' or 'inactive':\n" . join("\n", @$output));
+               return;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 service_enabled
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'systemctl is-enabled' to determines if a service is
+               enabled.
+
+=cut
+
+sub service_enabled {
+       my $self = shift;
+       if (ref($self) !~ /linux/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name argument was not 
supplied");
+               return;
+       }
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my $command = "systemctl is-enabled $service_name.service";
+       my ($exit_status, $output) = $self->execute($command, 0);
+       if (!defined($output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if $service_name service is running on $computer_node_name");
+               return;
+       }
+       
+       # Output should either be 'enabled' or 'disabled
+       if (grep(/disabled/, @$output)) {
+               notify($ERRORS{'DEBUG'}, 0, "$service_name service is disabled 
on $computer_node_name");
+               return 0;
+       }
+       elsif (grep(/enabled/, @$output)) {
+               notify($ERRORS{'DEBUG'}, 0, "$service_name service is enabled 
on $computer_node_name");
+               return 1;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to determine if 
$service_name service is enabled on $computer_node_name, output does not 
contain 'enabled' or 'disabled':\n" . join("\n", @$output));
+               return;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _enable_service
 
  Parameters  : $service_name
  Returns     : boolean
@@ -139,7 +235,7 @@ sub get_service_names {
 
 =cut
 
-sub enable_service {
+sub _enable_service {
        my $self = shift;
        if (ref($self) !~ /VCL::Module/i) {
                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
@@ -179,7 +275,7 @@ sub enable_service {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 disable_service
+=head2 _disable_service
 
  Parameters  : $service_name
  Returns     : boolean
@@ -188,7 +284,7 @@ sub enable_service {
 
 =cut
 
-sub disable_service {
+sub _disable_service {
        my $self = shift;
        if (ref($self) !~ /VCL::Module/i) {
                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
@@ -254,7 +350,7 @@ sub delete_service {
        # Disable the service before deleting it
        if ($self->service_exists($service_name)) {
                $self->stop_service($service_name) || return;
-               $self->disable_service($service_name) || return;
+               $self->_disable_service($service_name) || return;
        }
        
        # Delete the service configuration file
@@ -478,7 +574,7 @@ sub add_ext_sshd_service {
        
        $self->_daemon_reload();
        
-       return $self->enable_service('ext_sshd');
+       return $self->_enable_service('ext_sshd');
 }
 
 #/////////////////////////////////////////////////////////////////////////////

Modified: vcl/trunk/managementnode/lib/VCL/Module/State.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/State.pm?rev=1644715&r1=1644714&r2=1644715&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/State.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/State.pm Thu Dec 11 18:28:52 2014
@@ -151,6 +151,10 @@ sub initialize {
                # Allow the OS object to access the nathost_os object
                # This is necessary to allow the OS code to call the 
subroutines to forward ports
                $self->os->set_nathost_os($self->nathost_os());
+               
+               # Allow the NAT host OS object to access the OS object
+               # This allows the NAT host OS object to retrieve info about the 
computer being loaded
+               $nathost_os->set_os($self->os());
        }
        
        # Create a provisioning object

Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1644715&r1=1644714&r2=1644715&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Thu Dec 11 18:28:52 2014
@@ -182,6 +182,7 @@ our @EXPORT = qw(
        hash_to_xml_string
        help
        hostname_to_ip_address
+       insert_nathost
        insert_reload_request
        insert_request
        insertloadlog
@@ -6838,6 +6839,8 @@ sub get_computer_info {
                'module',
                'schedule',
                'platform',
+               'resource',
+               'resourcetype',
        );
        
        # Construct the select statement
@@ -6877,6 +6880,15 @@ ON (
 )
 LEFT JOIN (schedule) ON (schedule.id = computer.scheduleid)
 LEFT JOIN (module AS predictivemodule) ON (predictivemodule.id = 
computer.predictivemoduleid)
+LEFT JOIN (
+   resource,
+       resourcetype
+)
+ON (
+   resource.subid = computer.id
+       AND resource.resourcetypeid = resourcetype.id
+       AND resourcetype.name = 'computer'
+)
 
 WHERE
 computer.deleted != '1'
@@ -6929,6 +6941,9 @@ EOF
                elsif ($table eq 'predictivemodule' ) {
                        $computer_info->{predictive}{module}{$column} = $value;
                }
+               elsif ($table eq 'resourcetype') {
+                       $computer_info->{resource}{$table}{$column} = $value;
+               }
                else {
                        $computer_info->{$table}{$column} = $value;
                }
@@ -7018,7 +7033,8 @@ EOF
                  "datedeleted" => undef,
                  "deleted" => 0,
                  "id" => 2,
-                 "natIP" => "x.x.x.x",
+                 "publicIPaddress" => "x.x.x.x",
+                 "internalIPaddress" => "x.x.x.x",
                  "nathostcomputermap" => {
                    "computerid" => 3591,
                    "nathostid" => 2
@@ -7218,7 +7234,7 @@ sub populate_reservation_natport {
        my $nathost_info = 
$request_info->{reservation}{$reservation_id}{computer}{nathost};
        my $nathost_id = $nathost_info->{id};
        my $nathost_hostname = $nathost_info->{HOSTNAME};
-       my $nathost_public_ip_address = $nathost_info->{natIP};
+       my $nathost_public_ip_address = $nathost_info->{publicIPaddress};
        
        # Make sure the nathost info is defined
        if (!defined($nathost_id)) {
@@ -7392,7 +7408,80 @@ EOF
                return 0;
        }
 }
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 insert_nathost
+
+ Parameters  : $resource_type, $resource_identifier
+ Returns     : boolean
+ Description : Inserts an entry into the nathost table. The $resource_type
+               argument must either be 'computer' or 'managementnode'.
+
+=cut
+
+sub insert_nathost {
+       my ($resource_type, $resource_identifier) = @_;
+       if (!defined($resource_type)) {
+               notify($ERRORS{'WARNING'}, 0, "resource type argument was not 
supplied");
+               return;
+       }
+       elsif ($resource_type !~ /^(computer|managementnode)$/) {
+               notify($ERRORS{'WARNING'}, 0, "resource type argument is not 
valid: '$resource_type', it must either be 'computer' or 'managementnode'");
+               return;
+       }
+       elsif (!defined($resource_identifier)) {
+               notify($ERRORS{'WARNING'}, 0, "resource identifier argument was 
not supplied");
+               return;
+       }
        
+       my $resource_id;
+       my $public_ip_address;
+       if ($resource_type eq 'computer') {
+               my $computer_info = get_computer_info($resource_identifier);
+               if (!$computer_info) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to insert 
nathost, info could not be retrieved for computer '$resource_identifier'");
+                       return;
+               }
+               $resource_id = $computer_info->{resource}{id};
+               $public_ip_address = $computer_info->{IPaddress};
+       }
+       elsif ($resource_type eq 'managementnode') {
+               my $management_node_info = 
get_management_node_info($resource_identifier);
+               if (!$management_node_info) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to insert 
nathost, info could not be retrieved for management node 
'$resource_identifier'");
+                       return;
+               }
+               $resource_id = $management_node_info->{resource_id};
+               $public_ip_address = $management_node_info->{IPaddress};
+       }
+       
+       my $insert_statement = <<EOF;
+INSERT IGNORE INTO
+nathost
+(
+   resourceid,
+   publicIPaddress
+)
+VALUES
+(
+   '$resource_id',
+       '$public_ip_address'
+)
+ON DUPLICATE KEY UPDATE
+resourceid=VALUES(resourceid),
+publicIPaddress='$public_ip_address'
+EOF
+
+       if (database_execute($insert_statement)) {
+               notify($ERRORS{'DEBUG'}, 0, "inserted entry into nathost table 
for $resource_type, resource ID: $resource_id, NAT host public IP address: 
$public_ip_address");
+               return 1;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to insert entry into 
nathost table for $resource_type, resource ID: $resource_id, NAT host public IP 
address: $public_ip_address");
+               return 0;
+       }
+}
 
 #/////////////////////////////////////////////////////////////////////////////
 
@@ -10179,7 +10268,7 @@ EOF
                $connect_method_info->{$connectmethod_id}{RETRIEVAL_TIME} = 
$timestamp;
        }
 
-       notify($ERRORS{'DEBUG'}, 0, "retrieved connect method info:\n" . 
format_data($connect_method_info));
+       #notify($ERRORS{'DEBUG'}, 0, "retrieved connect method info:\n" . 
format_data($connect_method_info));
        $ENV{connect_method_info}{$imagerevision_id} = $connect_method_info;
        return $ENV{connect_method_info}{$imagerevision_id};
 }


Reply via email to