| #!/usr/bin/perl -w |
| ############################################################################### |
| # $Id$ |
| ############################################################################### |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| ############################################################################### |
| |
| =head1 NAME |
| |
| VCL::Module::OS::Linux::ESXi.pm |
| |
| =head1 SYNOPSIS |
| |
| Needs to be written |
| |
| =head1 DESCRIPTION |
| |
| This module provides VCL support for the Linux-based VMware ESXi operating |
| system. |
| |
| =cut |
| |
| ############################################################################### |
| package VCL::Module::OS::Linux::ESXi; |
| |
| # Specify the lib path using FindBin |
| use FindBin; |
| use lib "$FindBin::Bin/../../../.."; |
| |
| # Configure inheritance |
| use base qw(VCL::Module::OS::Linux); |
| |
| # Specify the version of this module |
| our $VERSION = '2.5.1'; |
| |
| # Specify the version of Perl to use |
| use 5.008000; |
| |
| use strict; |
| use warnings; |
| use diagnostics; |
| |
| use VCL::utils; |
| |
| ############################################################################### |
| |
| =head1 OBJECT METHODS |
| |
| =cut |
| |
| #////////////////////////////////////////////////////////////////////////////// |
| |
| =head2 post_load |
| |
| Parameters : |
| Returns : |
| Description : |
| |
| =cut |
| |
| sub post_load { |
| 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 $computer_short_name = $self->data->get_computer_short_name(); |
| |
| # Wait for computer to respond to SSH |
| if (!$self->wait_for_response(60, 600)) { |
| notify($ERRORS{'WARNING'}, 0, "$computer_short_name never responded to SSH"); |
| return 0; |
| } |
| |
| # Create the currentimage.txt file |
| if (!$self->OS->create_currentimage_txt()) { |
| notify($ERRORS{'WARNING'}, 0, "failed to create currentimage.txt on $computer_short_name"); |
| return 0; |
| } |
| |
| return $self->SUPER::post_load(); |
| } |
| |
| #////////////////////////////////////////////////////////////////////////////// |
| |
| =head2 reserve |
| |
| Parameters : |
| Returns : |
| Description : |
| |
| =cut |
| |
| sub reserve { |
| 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; |
| } |
| notify($ERRORS{'DEBUG'}, 0, "Enterered reserve() in the ESXi OS module"); |
| |
| return 1; |
| } |
| |
| #////////////////////////////////////////////////////////////////////////////// |
| |
| =head2 grant_access |
| |
| Parameters : |
| Returns : |
| Description : this sub called when user clicks Connect button on web GUI |
| |
| =cut |
| |
| sub grant_access { |
| 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 $esxi_storage_mount_command; |
| my @commands; |
| |
| my $computer_short_name = $self->data->get_computer_short_name(); |
| my $computer_node_name = $self->data->get_computer_node_name(); |
| notify($ERRORS{'OK'}, 0, "$computer_short_name: processing with ESXi.pm::grant_access()"); |
| |
| my $username = $self->data->get_user_login_id(); |
| my $reservation_password = $self->data->get_reservation_password(); |
| my $management_node_keys = $self->data->get_management_node_keys(); |
| |
| my $vcld_config = &local_read_vcld_config("/etc/vcl/vcld.conf"); |
| my $esxi_storage_name_prefix = $vcld_config->{"ESXI_STORAGE_NAME_PREFIX"}; |
| my $esxi_storage_address = $vcld_config->{"ESXI_STORAGE_ADDRESS"}; |
| my $esxi_storage_volume = $vcld_config->{"ESXI_STORAGE_VOLUME"}; |
| |
| $esxi_storage_mount_command = "esxcfg-nas -a $esxi_storage_name_prefix-$username -o $esxi_storage_address -s $esxi_storage_volume/$username"; |
| |
| push(@commands, "chmod +w /etc/pam.d/system-auth"); |
| push(@commands, "echo s/min=8,8,8,7,6/min=8,8,8,7,6 enforce=none/g > /tmp/sed"); |
| push(@commands, "sed -f /tmp/sed -i /etc/pam.d/system-auth"); |
| push(@commands, "rm -f /tmp/sed"); |
| push(@commands, "chmod -w /etc/pam.d/system-auth"); |
| push(@commands, "useradd -M $username"); |
| push(@commands, "groupadd root $username"); |
| push(@commands, "echo $reservation_password \| passwd $username --stdin"); |
| push(@commands, "vim-cmd vimsvc/auth/entity_permission_add vim.Folder:ha-folder-root root true Admin true"); |
| push(@commands, $esxi_storage_mount_command) if ($esxi_storage_mount_command); |
| push(@commands, "sleep 3"); |
| push(@commands, "echo /uuid.action/c > /tmp/sed"); |
| push(@commands, "echo \\\$ a uuid.action = \\\"keep\\\" >> /tmp/sed"); |
| push(@commands, "find /vmfs/volumes/$esxi_storage_name_prefix-$username/ -name *.vmx -exec sed -f /tmp/sed -i {} \\;"); |
| push(@commands, "rm -rf /tmp/sed"); |
| push(@commands, "find /vmfs/volumes/$esxi_storage_name_prefix-$username/ -name *.vmx -exec vim-cmd solo/registervm {} \\;"); |
| |
| foreach my $command (@commands) { |
| my ($exit_status, $output) = run_ssh_command($computer_node_name, $management_node_keys, $command, "root"); |
| if (!defined($output)) { |
| notify($ERRORS{'WARNING'}, 0, "failed to run SSH command: $command"); |
| return; |
| } |
| } |
| return 1; |
| |
| } |
| |
| #////////////////////////////////////////////////////////////////////////////// |
| |
| =head2 sanitize |
| |
| Parameters : |
| Returns : |
| Description : does ESXi need to reload? Check if user ever clicked connect button, if never then don't reload |
| |
| =cut |
| |
| sub sanitize { |
| 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 $computer_short_name = $self->data->get_computer_short_name(); |
| my $computer_state_name = $self->data->get_computer_state_name(); |
| |
| if ($computer_state_name =~ /^(inuse)$/) { |
| notify($ERRORS{'OK'}, 0, "$computer_short_name : need to reload."); |
| return 0; |
| } else { |
| notify($ERRORS{'OK'}, 0, "$computer_short_name : user never connected. No need to reload."); |
| return 1; |
| } |
| } |
| #////////////////////////////////////////////////////////////////////////////// |
| =head2 local_read_vcld_config |
| |
| Parameters : full path to vcld.conf |
| Returns : vcld_config array with all vcld.conf values |
| Description : this is local sub to read vcld.conf file |
| |
| =cut |
| |
| sub local_read_vcld_config { |
| my ($value,$config_file,$vcld_config); |
| ($config_file) = @_; |
| open (CONFIG,$config_file) or die "cannot open vcld.conf file"; |
| while (<CONFIG>) { |
| chomp; |
| s/#.*//; |
| s/^\s+//; |
| s/\s+$//; |
| next unless length; |
| my ($var,$value) = split(/\s*=\s*/,$_, 2); |
| $vcld_config->{$var} = $value; |
| } |
| return $vcld_config; |
| } |
| |
| #////////////////////////////////////////////////////////////////////////////// |
| |
| =head2 get_public_ip_address |
| |
| Parameters : |
| Returns : public IP address (IP address on interface vmk1) |
| Description : retrive Public IP address from ESXi server. This should be vmk1 interface |
| |
| =cut |
| |
| sub get_public_ip_address { |
| 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 $public_ip_address; |
| |
| my $command = "esxcfg-vmknic -l"; |
| my ($exit_status, $output) = $self->execute($command); |
| if (!defined($output)) { |
| notify($ERRORS{'WARNING'}, 0, "failed to run command to retrieve network configuration: $command"); |
| return; |
| } |
| for my $line (@$output) { |
| if ($line =~ /vmk1/) { |
| my @vmk1 = split(/ +/,$line); |
| for my $vmk1_line (@vmk1) { |
| if ($vmk1_line =~ /(\d+)(\.\d+){3}/) { |
| $public_ip_address = $vmk1_line; |
| last; |
| } |
| } |
| } |
| } |
| |
| return $public_ip_address; |
| } |
| |
| |
| #////////////////////////////////////////////////////////////////////////////// |
| |
| =head2 enable_firewall_port |
| |
| Parameters : $protocol, $port, $scope (optional) |
| Returns : 1 if succeeded, 0 otherwise |
| Description : Enables a firewall port on the computer. The protocol and port |
| arguments are required. An optional scope argument may supplied. |
| |
| # called by OS::process_connect_methods() |
| |
| =cut |
| |
| sub enable_firewall_port { |
| |
| #TODO |
| my $self = shift; |
| if (ref($self) !~ /osx/i) { |
| notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method"); |
| return; |
| } |
| |
| return 1; |
| } |
| |
| #////////////////////////////////////////////////////////////////////////////// |
| |
| =head2 get_cpu_core_count |
| |
| Parameters : none |
| Returns : integer |
| Description : Retrieves the number of CPU cores the computer has by querying |
| the NUMBER_OF_PROCESSORS environment variable. |
| |
| # called by Provisioning::VMware:VMware.pm |
| # Windows.pm only returns value from database |
| # return $self->get_environment_variable_value('NUMBER_OF_PROCESSORS'); |
| |
| =cut |
| |
| sub get_cpu_core_count { |
| #TODO |
| my $self = shift; |
| if (ref($self) !~ /osx/i) { |
| notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method"); |
| return; |
| } |
| |
| my $computer_node_name = $self->data->get_computer_node_name(); |
| return 1; |
| } |
| |
| #////////////////////////////////////////////////////////////////////////////// |
| |
| =head2 check_connection_on_port |
| |
| Parameters : $port |
| Returns : (connected|conn_wrong_ip|timeout|failed) |
| Description : uses netstat to see if any thing is connected to the provided port |
| |
| # called by OS.pm:is_user_connected() |
| |
| =cut |
| |
| sub check_connection_on_port { |
| #TODO |
| my $self = shift; |
| if (ref($self) !~ /osx/i) { |
| notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method"); |
| return; |
| } |
| |
| my $computer_node_name = $self->data->get_computer_node_name(); |
| |
| my $remote_ip = $self->data->get_reservation_remote_ip(); |
| my $computer_public_ip_address = $self->data->get_computer_public_ip_address(); |
| |
| my $port = shift; |
| if (!$port) { |
| notify($ERRORS{'WARNING'}, 0, "port variable was not passed as an argument"); |
| return "failed"; |
| } |
| return 1; |
| } |
| |
| #////////////////////////////////////////////////////////////////////////////// |
| |
| =head2 user_exists |
| |
| Parameters : |
| Returns : |
| Description : |
| |
| =cut |
| |
| sub user_exists { |
| #TODO |
| my $self = shift; |
| if (ref($self) !~ /osx/i) { |
| notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method"); |
| return; |
| } |
| |
| my $computer_node_name = $self->data->get_computer_node_name(); |
| return 1; |
| } |
| #////////////////////////////////////////////////////////////////////////////// |
| |
| 1; |
| __END__ |
| |
| =head1 SEE ALSO |
| |
| L<http://cwiki.apache.org/VCL/> |
| |
| =cut |