You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by jf...@apache.org on 2008/12/12 19:20:18 UTC
svn commit: r726079 [7/32] - in /incubator/vcl/tags/import: ./
managementnode/ managementnode/bin/ managementnode/etc/
managementnode/etc/vcl/ managementnode/legacy_vcl_vbs_scripts/
managementnode/lib/ managementnode/lib/VCL/ managementnode/lib/VCL/Mod...
Added: incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning/vmware.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning/vmware.pm?rev=726079&view=auto
==============================================================================
--- incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning/vmware.pm (added)
+++ incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning/vmware.pm Fri Dec 12 10:20:10 2008
@@ -0,0 +1,2400 @@
+#!/usr/bin/perl -w
+
+# 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.
+
+##############################################################################
+# $Id: vmware.pm 1953 2008-12-12 14:23:17Z arkurth $
+##############################################################################
+
+=head1 NAME
+
+VCL::Provisioning::vmware - VCL module to support the vmware provisioning engine
+
+=head1 SYNOPSIS
+
+ Needs to be written
+
+=head1 DESCRIPTION
+
+ This module provides VCL support for vmware server
+ http://www.vmware.com
+
+=cut
+
+##############################################################################
+package VCL::Module::Provisioning::vmware;
+
+# Specify the lib path using FindBin
+use FindBin;
+use lib "$FindBin::Bin/../../..";
+
+# Configure inheritance
+use base qw(VCL::Module::Provisioning);
+
+# Specify the version of this module
+our $VERSION = '2.00';
+
+# Specify the version of Perl to use
+use 5.008000;
+
+use strict;
+use warnings;
+use diagnostics;
+
+use VCL::utils;
+use Fcntl qw(:DEFAULT :flock);
+
+##############################################################################
+
+=head1 CLASS ATTRIBUTES
+
+=cut
+
+=head2 %VMWARE_CONFIG
+
+ Data type : hash
+ Description : %VMWARE_CONFIG is a hash containing the general VMWARE configuration
+ for the management node this code is running on. Since the data is
+ the same for every instance of the VMWARE class, a class attribute
+ is used and the hash is shared among all instances. This also
+ means that the data only needs to be retrieved from the database
+ once.
+
+=cut
+
+#my %VMWARE_CONFIG;
+
+# Class attributes to store VMWWARE configuration details
+# This data also resides in the %VMWARE_CONFIG hash
+# Extract hash data to scalars for ease of use
+my $IMAGE_LIB_ENABLE = $IMAGELIBENABLE;
+my $IMAGE_LIB_USER = $IMAGELIBUSER;
+my $IMAGE_LIB_KEY = $IMAGELIBKEY;
+my $IMAGE_LIB_SERVERS = $IMAGESERVERS;
+
+##############################################################################
+
+=head1 OBJECT METHODS
+
+=cut
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 initialize
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub initialize {
+ notify($ERRORS{'DEBUG'}, 0, "vmware module initialized");
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 provision
+
+ Parameters : hash
+ Returns : 1(success) or 0(failure)
+ Description : loads node with provided image
+
+=cut
+
+sub load {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+ return 0;
+ }
+
+ my $request_data = shift;
+ my ($package, $filename, $line, $sub) = caller(0);
+
+ # preform cleanup
+ if ($self->control_VM("remove")) {
+ }
+
+ # Store some hash variables into local variables
+ my $request_id = $self->data->get_request_id;
+ my $reservation_id = $self->data->get_reservation_id;
+ my $persistent = $self->data->get_request_forimaging;
+
+ my $image_id = $self->data->get_image_id;
+ my $image_os_name = $self->data->get_image_os_name;
+ my $image_identity = $self->data->get_image_identity;
+ my $image_os_type = $self->data->get_image_os_type;
+
+ my $vmclient_computerid = $self->data->get_computer_id;
+ my $computer_shortname = $self->data->get_computer_short_name;
+ my $computer_nodename = $computer_shortname;
+ my $computer_hostname = $self->data->get_computer_hostname;
+ my $computer_type = $self->data->get_computer_type;
+
+ my $vmtype_name = $self->data->get_vmhost_type_name;
+ my $vmhost_vmpath = $self->data->get_vmhost_profile_vmpath;
+ my $vmprofile_vmdisk = $self->data->get_vmhost_profile_vmdisk;
+ my $datastorepath = $self->data->get_vmhost_profile_datastore_path;
+ my $datastorepath4vmx = $self->data->get_vmhost_profile_datastorepath_4vmx;
+ my $virtualswitch0 = $self->data->get_vmhost_profile_virtualswitch0;
+ my $virtualswitch1 = $self->data->get_vmhost_profile_virtualswitch1;
+ my $vmtype = $vmtype_name;
+
+ my $requestedimagename = $self->data->get_image_name;
+ my $shortname = $computer_shortname;
+
+ my $vmhost_imagename = $self->data->get_vmhost_image_name;
+ my $vmhost_hostname = $self->data->get_vmhost_hostname;
+ my $host_type = $self->data->get_vmhost_type;
+ my $project = $self->data->get_image_project;
+ my $vmclient_eth0MAC = $self->data->get_computer_eth0_mac_address;
+ my $vmclient_eth1MAC = $self->data->get_computer_eth1_mac_address;
+ my $vmclient_imageminram = $self->data->get_image_minram;
+ my $vmhost_RAM = $self->data->get_vmhost_ram;
+ my $vmclient_drivetype = $self->data->get_computer_drive_type;
+ my $vmclient_privateIPaddress = $self->data->get_computer_ip_address;
+ my $vmclient_publicIPaddress = $self->data->get_computer_private_ip_address;
+ my $vmclient_OSname = $self->data->get_image_os_name;
+ # Assemble a consistent prefix for notify messages
+ my $notify_prefix = "req=$request_id, res=$reservation_id:";
+
+ #$VMWARErepository
+ #if (!($vm{vmhost}{ok})) {
+ #not ok to proceed
+ #do we need to provide another resource?
+ #fill in code to submit a request for another vmhost
+ #}
+ my @sshcmd;
+
+ insertloadlog($reservation_id, $vmclient_computerid, "startload", "$computer_shortname $requestedimagename");
+ my $starttime = convert_to_epoch_seconds;
+ #proceed
+ #$vm{"vmclient"}{"project"} = "vcl" if (!defined($vm{"vmclient"}{"project"}));
+
+
+ my ($hostnode, $identity);
+ if ($host_type eq "blade") {
+ $hostnode = $1 if ($vmhost_hostname =~ /([-_a-zA-Z0-9]*)(\.?)/);
+ $identity = $IDENTITY_bladerhel if ($vmhost_imagename =~ /^(rh[0-9]image|rhel[0-9]|fc[0-9]image|rhfc[0-9]|rhas[0-9]|esx[0-9]*)/);
+
+ # assign2project is only for blades - and not all blades
+ #if (VCL::Module::Provisioning::xCAT::_assign2project($hostnode, $project)) {
+ # notify($ERRORS{'OK'}, 0, "$hostnode assign2project return successful");
+ #}
+ #else {
+ # notify($ERRORS{'CRITICAL'}, 0, "$hostnode could not assign2project to $project");
+ # #return to get another machine
+ # return 0;
+ #}
+ } ## end if ($host_type eq "blade")
+ else {
+ #using FQHN
+ $hostnode = $vmhost_hostname;
+ $identity = $IDENTITY_linux_lab if ($vmhost_imagename =~ /^(realmrhel)/);
+ }
+
+ if (!(defined($identity))) {
+ notify($ERRORS{'CRITICAL'}, 0, "identity variiable not definted, setting to blade identity file vmhost variable set to $vmhost_imagename");
+ $identity = $IDENTITY_bladerhel;
+ }
+
+ notify($ERRORS{'OK'}, 0, "identity file set $identity vmhost imagename $vmhost_imagename bladekey $IDENTITY_bladerhel");
+ #setup flags
+ my $baseexists = 0;
+ my $dirstructure = 0;
+
+ #for convienence
+ my ($myimagename, $myvmx, $myvmdir, $mybasedirname, $requestedimagenamebase);
+ if ($persistent) {
+ #either in imaging mode or special use
+ $myvmdir = "$reservation_id$computer_shortname";
+ $myvmx = "$vmhost_vmpath/$reservation_id$computer_shortname/$reservation_id$computer_shortname.vmx";
+ $mybasedirname = "$reservation_id$computer_shortname";
+
+ #if GSX use requested imagename
+ $myimagename = $requestedimagename if ($vmtype =~ /(vmware|vmwareGSX)$/);
+ #if ESX use requestid+shortname
+ $myimagename = "$reservation_id$computer_shortname" if ($vmtype =~ /(vmwareESX3)/);
+
+ #base directory should not exist for image creation
+ } ## end if ($persistent)
+ else {
+ #standard use
+ $myvmdir = "$requestedimagename$computer_shortname";
+ $myvmx = "$vmhost_vmpath/$requestedimagename$computer_shortname/$requestedimagename$computer_shortname.vmx";
+ $mybasedirname = $requestedimagename;
+ $myimagename = $requestedimagename;
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "persistent= $persistent");
+ notify($ERRORS{'DEBUG'}, 0, "myvmdir= $myvmdir");
+ notify($ERRORS{'DEBUG'}, 0, "myvmx= $myvmx");
+ notify($ERRORS{'DEBUG'}, 0, "mybasedirname= $mybasedirname");
+ notify($ERRORS{'DEBUG'}, 0, "myimagename= $myimagename");
+
+ #does the requested base vmware image files already existed on the vmhost
+ notify($ERRORS{'OK'}, 0, "checking for base image $myvmdir on $hostnode ");
+ insertloadlog($reservation_id, $vmclient_computerid, "vmround1", "checking host for requested image files");
+
+ #check for lock file - another process might be copying the same image files to the same host server
+ my $tmplockfile = "/tmp/$hostnode" . "$requestedimagename" . "lock";
+ notify($ERRORS{'OK'}, 0, "trying to create exclusive lock on $tmplockfile while checking if image files exist on host");
+ if (sysopen(TMPLOCK, $tmplockfile, O_RDONLY | O_CREAT)) {
+ if (flock(TMPLOCK, LOCK_EX)) {
+ notify($ERRORS{'OK'}, 0, "owning exclusive lock on $tmplockfile");
+ notify($ERRORS{'OK'}, 0, "listing datestore $datastorepath ");
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "ls -1 $datastorepath", "root");
+ notify($ERRORS{'OK'}, 0, "@{ $sshcmd[1] }");
+ foreach my $l (@{$sshcmd[1]}) {
+ if ($l =~ /denied|No such/) {
+ notify($ERRORS{'CRITICAL'}, 0, "node $hostnode output @{ $sshcmd[1] }");
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "could not log into vmhost $hostnode @{ $sshcmd[1] }");
+ close(TMPLOCK);
+ unlink($tmplockfile);
+ return 0;
+ }
+ if ($l =~ /Warning: Permanently/) {
+ #ignore
+ }
+ if ($l =~ /(\s*?)$mybasedirname$/) {
+ notify($ERRORS{'OK'}, 0, "base image exists");
+ $baseexists = 1;
+ }
+ #For persistent images - we rename the mybasedirname
+ #If base really does exists and not inuse just rename directory for localdisk
+ if ($l =~ /(\s*?)$requestedimagename$/) {
+ notify($ERRORS{'OK'}, 0, "requestedimagenamebase image exists") if ($persistent);
+ $requestedimagenamebase = 1;
+ }
+ if ($l eq "$myvmdir") {
+ notify($ERRORS{'OK'}, 0, "directory structure $myvmdir image exists");
+ $dirstructure = 1;
+ }
+ } ## end foreach my $l (@{$sshcmd[1]})
+
+ if ($requestedimagenamebase && $persistent) {
+ notify($ERRORS{'DEBUG'}, 0, "requestedimagenamebase and persistent are both true, attempting to detect status for move of base image instead of full copy");
+ #Confirm base is not inuse then simply rename the directory to match our needs
+ my $okforMOVE = 0;
+ my @sshcmd = run_ssh_command($hostnode, $identity, "vmware-cmd -l", "root");
+ foreach my $vm (@{$sshcmd[1]}) {
+ chomp($vm);
+ next if ($vm =~ /Warning:/);
+ notify($ERRORS{'OK'}, 0, "$vm");
+ if ($vm =~ /(.*)(\/)(.*)(\/)($requestedimagename[-_a-zA-Z0-9]*.vmx)/) {
+ # do within this loop in case there is more than one
+ my $localmyvmx = "$1/$3/$5";
+ my $localmyvmdir = "$1/$3";
+ $localmyvmx =~ s/(\s+)/\\ /g;
+ $localmyvmdir =~ s/(\s+)/\\ /g;
+
+ notify($ERRORS{'OK'}, 0, "my vmx $localmyvmx");
+ my @sshcmd_1 = run_ssh_command($hostnode, $identity, "vmware-cmd $localmyvmx getstate");
+ foreach my $l (@{$sshcmd_1[1]}) {
+ if ($l =~ /= off/) {
+ #Good
+ $okforMOVE = 1;
+ }
+ elsif ($l =~ /= on/) {
+ $baseexists = 0;
+ }
+ }
+
+ } ## end if ($vm =~ /(.*)(\/)(.*)(\/)($requestedimagename[-_a-zA-Z0-9]*.vmx)/)
+ } ## end foreach my $vm (@{$sshcmd[1]})
+ if ($okforMOVE) {
+ #use the mv command to rename the directory of the base image files
+ notify($ERRORS{'DEBUG'}, 0, "simulating move of directory cmd= mv $vmhost_vmpath/$requestedimagename $myvmdir");
+
+ }
+
+ } ## end if ($requestedimagenamebase && $persistent)
+ if (!($baseexists)) {
+ #check available disk space -- clean up if needed
+ #copy vm files from local repository to vmhost
+ #this could take a few minutes
+ #get size of vmdl files
+
+ insertloadlog($reservation_id, $vmclient_computerid, "info", "image files do not exist on host server, preparing to copy");
+ my $myvmdkfilesize = 0;
+ if (open(SIZE, "du -k $VMWAREREPOSITORY/$requestedimagename 2>&1 |")) {
+ my @du = <SIZE>;
+ close(SIZE);
+ foreach my $d (@du) {
+ if ($d =~ /No such file or directory/) {
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "could not collect size of local image files");
+ notify($ERRORS{'CRITICAL'}, 0, "problem checking local vm file size on $VMWAREREPOSITORY/$requestedimagename");
+ close(TMPLOCK);
+ unlink($tmplockfile);
+ return 0;
+ }
+ if ($d =~ /^([0-9]*)/) {
+ $myvmdkfilesize += $1;
+ }
+ } ## end foreach my $d (@du)
+ } ## end if (open(SIZE, "du -k $VMWAREREPOSITORY/$requestedimagename 2>&1 |"...
+
+ notify($ERRORS{'DEBUG'}, 0, "file size $myvmdkfilesize of $requestedimagename");
+ notify($ERRORS{'OK'}, 0, "checking space on $hostnode $vmhost_vmpath");
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "df -k $vmhost_vmpath", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ next if ($l =~ /Warning: Permanently/);
+ next if ($l =~ /^Filesystem/);
+ if ($l =~ /\/dev\//) {
+ #in k blocks
+ my ($d, $s, $u, $a, $p, $m) = split(" ", $l);
+ notify($ERRORS{'OK'}, 0, "datastore space available on remote machine $a ");
+ #lets give ourselves at least double what the image needs for some buffer
+ if ($a < ($myvmdkfilesize * 1.5)) {
+ #free up space if possible only if $vm{vmhost}{vmware_disk} eq "localdisk"
+ if ($vmprofile_vmdisk eq "localdisk") {
+ notify($ERRORS{'OK'}, 0, "detected space issue on $hostnode, attempting to free up space");
+ #remove stuff
+ my %vmlist = ();
+ my @sshcmd_1 = run_ssh_command($hostnode, $identity, "vmware-cmd -l", "root");
+ my $i;
+ foreach my $r (@{$sshcmd_1[1]}) {
+ $i++;
+ next if ($r =~ /^Warning: /);
+ #if($r =~ /\/var\/lib\/vmware/){
+ if ($r =~ /.vmx/) {
+ chomp($r);
+ notify($ERRORS{'OK'}, 0, "disk cleanup - pushing $r on array");
+ $vmlist{$i}{"path"} = $r;
+ }
+ } ## end foreach my $r (@{$sshcmd_1[1]})
+
+ foreach my $v (keys %vmlist) {
+ #handle any spaces in the path
+ $vmlist{$v}{path} =~ s/(\s+)/\\\\ /g;
+ my @sshcmd_2 = run_ssh_command($hostnode, $identity, "vmware-cmd -q $vmlist{$v}{path} getstate", "root");
+ foreach $a (@{$sshcmd_2[1]}) {
+ next if ($a =~ /^Warning: /);
+ chomp($a);
+ if ($a =~ /^on/i) {
+ $vmlist{$v}{"state"} = $a;
+ }
+ }
+ } ## end foreach my $v (keys %vmlist)
+ notify($ERRORS{'OK'}, 0, "ls datastorepath $datastorepath ");
+ my @sshcmd_3 = run_ssh_command($hostnode, $identity, "ls -1 $datastorepath", "root");
+ foreach my $d (@{$sshcmd_3[1]}) {
+ next if ($d =~ /Warning: /);
+ chomp($d);
+ my $save = 0;
+ foreach my $v (%vmlist) {
+ #print "checking if $d is part of a running vm of $v\n";
+ if ($vmlist{$v}{path} =~ /$d/) {
+ if ($vmlist{$v}{state} eq "on") {
+ $save = 1;
+ }
+ elsif ($vmlist{$v}{state} eq "off") {
+ $save = 0;
+ if (defined(run_ssh_command($hostnode, $identity, "vmware-cmd -s unregister $vmlist{$v}{path}", "root"))) {
+ notify($ERRORS{'DEBUG'}, 0, "unregistered $vmlist{$v}{path}");
+ }
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "$vmlist{$v}{path} is in strange state $vmlist{$v}{state}");
+ }
+ } ## end if ($vmlist{$v}{path} =~ /$d/)
+ } ## end foreach my $v (%vmlist)
+ if ($save) {
+ notify($ERRORS{'OK'}, 0, "disk cleanup - SAVING $datastorepath/$d");
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "disk cleanup - REMOVING $datastorepath/$d");
+ if (defined(run_ssh_command($hostnode, $identity, "/bin/rm -rf $datastorepath/$d\*", "root"))) {
+ notify($ERRORS{'DEBUG'}, 0, "disk cleanup - REMOVED $datastorepath/$d\*");
+ }
+ } #else not save
+ } #foreach vmdir
+ } #locadisk,
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "detected space issues from $hostnode this management node is configured to use network storage, not removing any data");
+ return 0;
+ }
+ } #start myvmdkfilesize comparsion
+ } # start if /dev
+ } # start foreach df -k
+ if ($vmprofile_vmdisk eq "localdisk") {
+ notify($ERRORS{'OK'}, 0, "copying base image files $requestedimagename to $hostnode");
+ if (run_scp_command("$VMWAREREPOSITORY/$requestedimagename", "$hostnode:\"$datastorepath/$mybasedirname\"", $identity)) {
+ #recheck host server for files - the scp output is not being captured
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "ls -1 $datastorepath", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ if ($l =~ /denied|No such/) {
+ notify($ERRORS{'CRITICAL'}, 0, "node $hostnode output @{ $sshcmd[1] }");
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "could not log into vmhost $hostnode @{ $sshcmd[1] }");
+ close(TMPLOCK);
+ unlink($tmplockfile);
+ return 0;
+ }
+ if ($l =~ /(\s*?)$mybasedirname$/) {
+ notify($ERRORS{'OK'}, 0, "base image exists");
+ $baseexists = 1;
+ insertloadlog($reservation_id, $vmclient_computerid, "transfervm", "copying base image files");
+ }
+ } ## end foreach my $l (@{$sshcmd[1]})
+
+ } ## end if (run_scp_command("$VMWAREREPOSITORY/$requestedimagename"...
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "problems scp vm files to $hostnode $!");
+ close(TMPLOCK);
+ unlink($tmplockfile);
+ return 0;
+ }
+ } ## end if ($vmprofile_vmdisk eq "localdisk")
+ elsif ($vmprofile_vmdisk eq "networkdisk") {
+ if ($persistent) {
+ #imaging mode -
+ my $srcDisk = "$datastorepath/$requestedimagename/$requestedimagename" . ".vmdk";
+ my $dstDisk = "$datastorepath/$mybasedirname/$myimagename" . ".vmdk";
+ my $dstDir = "$datastorepath/$mybasedirname";
+
+ #create a clone -
+ if (_vmwareclone($hostnode, $identity, $srcDisk, $dstDisk, $dstDir)) {
+ $baseexists = 1;
+ insertloadlog($reservation_id, $vmclient_computerid, "transfervm", "cloning base image files");
+ }
+ else {
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "cloning base image failed");
+ notify($ERRORS{'CRITICAL'}, 0, "problem cloning failed $srcDisk to $dstDisk");
+ close(TMPLOCK);
+ unlink($tmplockfile);
+ return 0;
+ }
+ } ## end if ($persistent)
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "problems vmware disk set to network disk can not find image in $datastorepath");
+ close(TMPLOCK);
+ unlink($tmplockfile);
+ return 0;
+ }
+ } ## end elsif ($vmprofile_vmdisk eq "networkdisk") [ if ($vmprofile_vmdisk eq "localdisk")
+ notify($ERRORS{'OK'}, 0, "confirm image exist process complete removing lock on $tmplockfile");
+ close(TMPLOCK);
+ unlink($tmplockfile);
+
+ } # start if base not exists
+ else {
+ #base exists
+ notify($ERRORS{'OK'}, 0, "confirm image exist process complete removing lock on $tmplockfile");
+ close(TMPLOCK);
+ unlink($tmplockfile);
+ }
+ } #flock
+ } #sysopen
+ #ok good base vm files exist on hostnode
+ #if guest dirstructure exists check state of vm, else create sturcture and new vmx file
+ if (($dirstructure)) {
+ #clean-up
+ #make sure vm is off, it should be
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "vmware-cmd $myvmx getstate", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ if ($l =~ /= off/) {
+ #good
+ }
+ elsif ($l =~ /= on/) {
+ my @sshcmd_1 = run_ssh_command($hostnode, $identity, "vmware-cmd $myvmx stop hard", "root");
+ foreach my $a (@{$sshcmd_1[1]}) {
+ next if ($a =~ /Warning:/);
+ if ($a =~ /= 1/) {
+ #turn off or killpid -- of course it should be off by this point but kill
+ }
+ else {
+ # FIX-ME add better error checking
+ notify($ERRORS{'OK'}, 0, "@{ $sshcmd[1] }");
+ }
+ } ## end foreach my $a (@{$sshcmd_1[1]})
+ } ## end elsif ($l =~ /= on/) [ if ($l =~ /= off/)
+ } ## end foreach my $l (@{$sshcmd[1]})
+ #if registered - unregister vm
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "vmware-cmd -s unregister $myvmx", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ if ($l =~ /No such virtual machine/) {
+ #not registered
+ notify($ERRORS{'OK'}, 0, "vm $myvmx not registered");
+ }
+ if ($l =~ /= 1/) {
+ notify($ERRORS{'OK'}, 0, "vm $myvmx unregistered");
+ }
+ }
+ #delete directory -- clean slate
+ # if in persistent mode - imaging or otherwise we may not want to rm this directory
+ if (defined(run_ssh_command($hostnode, $identity, "/bin/rm -rf $vmhost_vmpath/$myvmdir", "root"))) {
+ notify($ERRORS{'OK'}, 0, "success rm -rf $vmhost_vmpath/$myvmdir on $hostnode ");
+ }
+
+ } ## end if (($dirstructure))
+
+ #setup new vmx file and directory for this request
+ #create local directory
+ #customize a vmx file
+ # copy to vmhost
+ # unlink local directory
+ if (open(MKDIR, "/bin/mkdir /tmp/$myvmdir 2>&1 |")) {
+ my @a = <MKDIR>;
+ close(MKDIR);
+ for my $l (@a) {
+ notify($ERRORS{'OK'}, 0, "possible error @a");
+ }
+ notify($ERRORS{'OK'}, 0, "created tmp directory /tmp/$myvmdir");
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "could not create tmp directory $myvmdir $!");
+ }
+
+ #check for dependent settings ethX
+ if (!(defined($vmclient_eth0MAC))) {
+ #complain
+ notify($ERRORS{'CRITICAL'}, 0, "eth0MAC is not defined for $computer_shortname can not continue");
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "eth0MAC address is not defined");
+ return 0;
+
+ }
+
+ #check for memory settings
+ my $dynamicmemvalue = "512";
+ if (defined($vmclient_imageminram)) {
+ #preform some sanity check
+ if (($dynamicmemvalue < $vmclient_imageminram) && ($vmclient_imageminram < $vmhost_RAM)) {
+ $dynamicmemvalue = $vmclient_imageminram;
+ notify($ERRORS{'OK'}, 0, "setting memory to $dynamicmemvalue");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "image memory value $vmclient_imageminram out of the expected range in host machine $vmhost_RAM setting to 512");
+ }
+ } ## end if (defined($vmclient_imageminram))
+ my $adapter = "ide";
+ # database could be out of date
+ if ($vmclient_drivetype =~ /hda/) {
+ $adapter = "ide";
+ notify($ERRORS{'OK'}, 0, "hda flag set, setting adapter to ide");
+ }
+ elsif ($vmclient_drivetype =~ /sda/) {
+ $adapter = "buslogic";
+ notify($ERRORS{'OK'}, 0, "sda flag set, setting adapter to buslogic");
+ }
+
+ my $listedadapter = 0;
+ #scan vmdk file
+ if (open(RE, "grep adapterType $VMWAREREPOSITORY/$requestedimagename/$requestedimagename.vmdk 2>&1 |")) {
+ my @LIST = <RE>;
+ close(RE);
+ foreach my $a (@LIST) {
+ if ($a =~ /(ide|buslogic|lsilogic)/) {
+ $listedadapter = $1;
+ notify($ERRORS{'OK'}, 0, "listedadapter= $1 ");
+ }
+ }
+ } ## end if (open(RE, "grep adapterType $VMWAREREPOSITORY/$requestedimagename/$requestedimagename.vmdk 2>&1 |"...
+
+ if ($listedadapter) {
+ $adapter = $listedadapter;
+ }
+
+ notify($ERRORS{'OK'}, 0, "adapter= $adapter drivetype $vmclient_drivetype");
+ my $guestOS;
+ $guestOS = "winxppro" if ($requestedimagename =~ /(winxp)/i);
+ $guestOS = "win2003" if ($requestedimagename =~ /(win2003)/i);
+ $guestOS = "ubuntu" if ($requestedimagename =~ /(ubuntu)/i);
+
+
+ my @vmxfile;
+ my $tmpfile = "/tmp/$myvmdir/$myvmdir.vmx";
+ my $tmpdir = "/tmp/$myvmdir";
+
+ push(@vmxfile, "#!/usr/bin/vmware\n");
+ push(@vmxfile, "config.version = \"8\"\n");
+ push(@vmxfile, "virtualHW.version = \"4\"\n");
+ push(@vmxfile, "memsize = \"$dynamicmemvalue\"\n");
+ push(@vmxfile, "displayName = \"$myvmdir\"\n");
+ push(@vmxfile, "guestOS = \"$guestOS\"\n");
+ push(@vmxfile, "uuid.location = \"56 4d 25 b7 07 18 f4 b6-25 d1 77 1e 10 bd 9e 99\"\n");
+ push(@vmxfile, "uuid.bios = \"56 4d a8 df fb 38 d0 c5-25 73 d4 01 16 06 4e c0\"\n");
+ push(@vmxfile, "Ethernet0.present = \"TRUE\"\n");
+ push(@vmxfile, "Ethernet1.present = \"TRUE\"\n");
+
+ if ($vmtype eq "vmwareESX3") {
+ push(@vmxfile, "Ethernet0.networkName = \"$virtualswitch0\"\n");
+ push(@vmxfile, "Ethernet1.networkName = \"$virtualswitch1\"\n");
+ push(@vmxfile, "ethernet0.wakeOnPcktRcv = \"false\"\n");
+ push(@vmxfile, "ethernet1.wakeOnPcktRcv = \"false\"\n");
+ }
+ elsif ($vmtype =~ /freeserver|gsx|vmwareGSX/) {
+ push(@vmxfile, "Ethernet1.connectionType = \"custom\"\n");
+ push(@vmxfile, "Ethernet1.vnet = \"$virtualswitch1\"\n");
+ }
+
+ push(@vmxfile, "ethernet0.address = \"$vmclient_eth0MAC\"\n");
+ push(@vmxfile, "ethernet1.address = \"$vmclient_eth1MAC\"\n");
+ push(@vmxfile, "ethernet0.addressType = \"static\"\n");
+ push(@vmxfile, "ethernet1.addressType = \"static\"\n");
+ push(@vmxfile, "gui.exitOnCLIHLT = \"FALSE\"\n");
+ push(@vmxfile, "uuid.action = \"keep\"\n");
+ push(@vmxfile, "snapshot.disabled = \"TRUE\"\n");
+ push(@vmxfile, "floppy0.present = \"FALSE\"\n");
+ push(@vmxfile, "priority.grabbed = \"normal\"\n");
+ push(@vmxfile, "priority.ungrabbed = \"normal\"\n");
+ push(@vmxfile, "checkpoint.vmState = \"\"\n");
+
+ if ($adapter eq "ide") {
+ push(@vmxfile, "scsi0.present = \"TRUE\"\n");
+ push(@vmxfile, "ide0:0.present = \"TRUE\"\n");
+ push(@vmxfile, "ide0:0.fileName =\"$datastorepath4vmx/$mybasedirname/$myimagename.vmdk\"\n");
+ push(@vmxfile, "ide0:0.mode = \"independent-nonpersistent\"\n") if (!($persistent));
+ push(@vmxfile, "ide0:0.mode = \"independent-persistent\"\n") if (($persistent));
+ push(@vmxfile, "ide0:0.redo = \"./$myvmdir.vmdk.REDO_Y7VUab\"\n");
+ push(@vmxfile, "ide1:0.autodetect = \"TRUE\"\n");
+ push(@vmxfile, "ide1:0.startConnected = \"FALSE\"\n");
+ } ## end if ($adapter eq "ide")
+ elsif ($adapter =~ /buslogic|lsilogic/) {
+ push(@vmxfile, "scsi0:0.present = \"TRUE\"\n");
+ push(@vmxfile, "scsi0.present = \"TRUE\"\n");
+ push(@vmxfile, "scsi0.sharedBus = \"none\"\n");
+ push(@vmxfile, "scsi0:0.deviceType = \"scsi-hardDisk\"\n");
+ push(@vmxfile, "scsi0.virtualDev = \"$adapter\"\n");
+ push(@vmxfile, "scsi0:0.fileName =\"$datastorepath4vmx/$mybasedirname/$myimagename.vmdk\"\n");
+ push(@vmxfile, "scsi0:0.mode = \"independent-nonpersistent\"\n") if (!($persistent));
+ push(@vmxfile, "scsi0:0.mode = \"independent-persistent\"\n") if (($persistent));
+ push(@vmxfile, "scsi0:0.redo = \"./$myvmdir.vmdk.REDO_Y7VUab\"\n");
+ } ## end elsif ($adapter =~ /buslogic|lsilogic/) [ if ($adapter eq "ide")
+
+ #write to tmpfile
+ if (open(TMP, ">$tmpfile")) {
+ print TMP @vmxfile;
+ close(TMP);
+ notify($ERRORS{'OK'}, 0, "wrote vmxarray to $tmpfile");
+ }
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "could not write vmxarray to $tmpfile");
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "could not write vmx file to local tmp file");
+ return 0;
+ }
+
+ #scp vmx file to vmdir on vmhost
+ insertloadlog($reservation_id, $vmclient_computerid, "vmconfigcopy", "transferring vmx file to $hostnode");
+ if (run_scp_command($tmpdir, "$hostnode:\"$vmhost_vmpath\"", $identity)) {
+ my $copied = 0;
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "ls -1 $vmhost_vmpath/$myvmdir;chmod 755 $myvmx", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ if ($l =~ /$myvmdir.vmx/) {
+ notify($ERRORS{'OK'}, 0, "successfully copied vmx file to $hostnode");
+ $copied = 1;
+ insertloadlog($reservation_id, $vmclient_computerid, "vmsetupconfig", "setting up vmx file");
+ }
+ }
+ if (!($copied)) {
+ #not good
+ notify($ERRORS{'CRITICAL'}, 0, "failed to copy $tmpfile to $hostnode \noutput= @{ $sshcmd[1] }");
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "failure to transfer vmx file to $hostnode");
+ return 0;
+ }
+
+ } #scp vmx tmpfile to host node
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "failed to copy $tmpfile to $hostnode ");
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "failure to transfer vmx file to $hostnode");
+ return 0;
+ }
+
+ #remove tmpfile and tmpdirectory
+ if (unlink($tmpfile)) {
+ notify($ERRORS{'OK'}, 0, "successfully removed $tmpfile");
+ notify($ERRORS{'OK'}, 0, "successfully removed tmp directory") if (rmdir("$tmpdir"));
+ }
+
+
+ #register vmx on vmhost
+ my $registered = 0;
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "vmware-cmd -s register $myvmx", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ if ($l =~ /No such virtual machine/) {
+ #not registered
+ notify($ERRORS{'CRITICAL'}, 0, "vm $myvmx vmx does not exist on $hostnode");
+ }
+ if ($l =~ /= 1/) {
+ notify($ERRORS{'OK'}, 0, "vm $myvmx registered");
+ $registered = 1;
+ }
+ if ($l =~ /Virtual machine already exists|VMControl error -999/) {
+ notify($ERRORS{'WARNING'}, 0, "vm $myvmx already registered");
+ $registered = 1;
+ }
+ } ## end foreach my $l (@{$sshcmd[1]})
+ if (!($registered)) {
+ #now what - complain
+ notify($ERRORS{'CRITICAL'}, 0, "could not register vm $myvmx on $hostnode\n @{ $sshcmd[1] }");
+ return 0;
+ }
+
+
+ #turn on vm
+ #set loop control
+ my $vmware_starts = 0;
+
+ VMWARESTART:
+
+ $vmware_starts++;
+ notify($ERRORS{'OK'}, 0, "starting vm $myvmx - pass $vmware_starts");
+ if ($vmware_starts > 2) {
+ notify($ERRORS{'CRITICAL'}, 0, "vmware starts exceeded limit vmware_starts= $vmware_starts hostnode= $hostnode vm= $computer_shortname myvmx= $myvmx");
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "could not load machine on $hostnode exceeded attempts");
+ return 0;
+ }
+
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "vmware-cmd $myvmx start", "root");
+ for my $l (@{$sshcmd[1]}) {
+ next if ($l =~ /Warning:/);
+ #if successful -- this cmd does not appear to return any ouput so anything could be a failure
+ if ($l =~ /= 1/) {
+ notify($ERRORS{'OK'}, 0, "started $myvmx on $hostnode");
+ }
+ elsif ($l =~ /VMControl error/) {
+ notify($ERRORS{'OK'}, 0, "vmware-cmd start failed \n@{ $sshcmd[1] }");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "vmware-cmd cmd gave this output when trying to start $myvmx on $hostnode \n@{ $sshcmd[1] }");
+ }
+ } ## end for my $l (@{$sshcmd[1]})
+ insertloadlog($reservation_id, $vmclient_computerid, "startvm", "started vm on $hostnode");
+
+ #start monitoring
+ # check state of vm
+ # check messages log for boot info, DHCP requests, etc.A
+ # s1 = stage1 -- vm turned on
+ # s2 = stage2 -- DHCPDISCOVER on private mac
+ # s3 = stage3 --
+ sleep 20;
+ my ($s1, $s2, $s3, $s4, $s5) = 0; #setup stage flags
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "vmware-cmd $myvmx getstate", "root");
+ notify($ERRORS{'OK'}, 0, "checking state of vm $computer_shortname");
+ for my $l (@{$sshcmd[1]}) {
+ next if ($l =~ /Warning:/);
+ if ($l =~ /= on/) {
+ #good stage 1
+ $s1 = 1;
+ insertloadlog($reservation_id, $vmclient_computerid, "vmstage1", "node has been turned on");
+ notify($ERRORS{'OK'}, 0, "stage1 completed vm $computer_shortname has been turned on");
+ notify($ERRORS{'OK'}, 0, "eth0MAC $vmclient_eth0MAC privateIPaddress $vmclient_privateIPaddress");
+ }
+ } ## end for my $l (@{$sshcmd[1]})
+ my $sloop = 0;
+ if ($s1) {
+ #stage1 complete monitor local messages log for boot up info
+ if (open(TAIL, "</var/log/messages")) {
+ seek TAIL, -1, 2; #
+ for (;;) {
+ notify($ERRORS{'OK'}, 0, "$computer_shortname ROUND 1 checks loop $sloop of 40");
+
+ # re-check state of vm
+ my @vmstate = run_ssh_command($hostnode, $identity, "vmware-cmd $myvmx getstate", "root");
+ notify($ERRORS{'OK'}, 0, "rechecking state of vm $computer_shortname $myvmx");
+ for my $l (@{$vmstate[1]}) {
+ next if ($l =~ /Warning:/);
+ if ($l =~ /= on/) {
+ #good vm still on
+ notify($ERRORS{'OK'}, 0, "vm $computer_shortname reports on");
+ }
+ elsif ($l =~ /= off/) {
+ #good vm still on
+ notify($ERRORS{'CRITICAL'}, 0, "state of vm $computer_shortname reports off after pass number $sloop attempting to restart: start attempts $vmware_starts");
+ close(TAIL);
+ goto VMWARESTART;
+ }
+ elsif ($l =~ /= stuck/) {
+ notify($ERRORS{'CRITICAL'}, 0, "vm $computer_shortname reports stuck on pass $sloop attempting to kill pid and restart: restart attempts $vmware_starts");
+ close(TAIL);
+ #kill stuck process
+ #list processes for vmx and kill pid
+ notify($ERRORS{'OK'}, 0, "vm reported in stuck state, attempting to kill process");
+ my @ssh_pid = run_ssh_command($hostnode, $identity, "vmware-cmd -q $myvmx getpid");
+ foreach my $p (@{$ssh_pid[1]}) {
+ if ($p =~ /(\D*)(\s*)([0-9]*)/) {
+ my $vmpid = $3;
+ if (defined(run_ssh_command($hostnode, $identity, "kill -9 $vmpid"))) {
+ notify($ERRORS{'OK'}, 0, "killed $vmpid $myvmx");
+ }
+ }
+ }
+ } ## end elsif ($l =~ /= stuck/) [ if ($l =~ /= on/)
+ } ## end for my $l (@{$vmstate[1]})
+
+ while (<TAIL>) {
+ if ($_ =~ /$vmclient_eth0MAC|$vmclient_privateIPaddress|$computer_shortname/) {
+ notify($ERRORS{'DEBUG'}, 0, "DEBUG output for $computer_shortname $_");
+ }
+ if (!$s2) {
+ if ($_ =~ /dhcpd: DHCPDISCOVER from $vmclient_eth0MAC/) {
+ $s2 = 1;
+ insertloadlog($reservation_id, $vmclient_computerid, "vmstage2", "detected DHCP request for node");
+ notify($ERRORS{'OK'}, 0, "$computer_shortname STAGE 2 set DHCPDISCOVER from $vmclient_eth0MAC");
+ }
+ }
+ if (!$s3) {
+ if ($_ =~ /dhcpd: DHCPACK on $vmclient_privateIPaddress to $vmclient_eth0MAC/) {
+ $s3 = 1;
+ insertloadlog($reservation_id, $vmclient_computerid, "vmstage3", "detected DHCPACK for node");
+ notify($ERRORS{'OK'}, 0, "$computer_shortname STAGE 3 set DHCPACK on $vmclient_privateIPaddress to $vmclient_eth0MAC}");
+ }
+ }
+ if (!$s4) {
+ if ($_ =~ /dhcpd: DHCPACK on $vmclient_privateIPaddress to $vmclient_eth0MAC/) {
+ $s4 = 1;
+ insertloadlog($reservation_id, $vmclient_computerid, "vmstage4", "detected 2nd DHCPACK for node");
+ notify($ERRORS{'OK'}, 0, "$computer_shortname STAGE 4 set another DHCPACK on $vmclient_privateIPaddress to $vmclient_eth0MAC");
+ }
+ }
+ if (!$s5) {
+ if ($_ =~ /$computer_shortname (.*) READY/i) {
+ $s5 = 1;
+ notify($ERRORS{'OK'}, 0, "$computer_shortname STAGE 5 set found READY flag");
+ insertloadlog($reservation_id, $vmclient_computerid, "vmstage5", "detected READY flag proceeding to post configuration");
+ #speed this up a bit
+ close(TAIL);
+ goto VMWAREROUND2;
+ }
+
+ } ## end if (!$s5)
+ if ($sloop > 20) {
+ #are we getting close
+ if ($_ =~ /DHCPACK on $vmclient_privateIPaddress to $vmclient_eth0MAC}/) {
+ #getting close -- extend it a bit
+ notify($ERRORS{'OK'}, 0, "$computer_shortname is getting close extending wait time");
+ insertloadlog($reservation_id, $vmclient_computerid, "info", "getting close node is booting");
+ $sloop = $sloop - 8;
+ }
+ if ($_ =~ /$computer_shortname sshd/) {
+ #getting close -- extend it a bit
+ notify($ERRORS{'OK'}, 0, "$computer_shortname is getting close sshd is starting extending wait time");
+ insertloadlog($reservation_id, $vmclient_computerid, "info", "getting close services are starting on node");
+ $sloop = $sloop - 5;
+ }
+
+ my $sshd_status = _sshd_status($computer_shortname, $requestedimagename);
+ if ($sshd_status eq "on") {
+ notify($ERRORS{'OK'}, 0, "$computer_shortname now has active sshd running, maybe we missed the READY flag setting STAGE5 flag");
+ $s5 = 1;
+ #speed this up a bit
+ close(TAIL);
+ goto VMWAREROUND2;
+ }
+ } ## end if ($sloop > 20)
+
+ } #while
+
+ if ($s5) {
+ #good
+ close(TAIL);
+ goto VMWAREROUND2;
+ }
+ elsif ($sloop > 65) {
+ #taken too long -- do something different or fail it
+
+ notify($ERRORS{'CRITICAL'}, 0, "could not load $myvmx on $computer_shortname on host $hostnode");
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "could not load vmx on $hostnode");
+ close(TAIL);
+ return 0;
+
+ }
+ else {
+ #keep check the log
+ $sloop++;
+ sleep 10;
+ seek TAIL, 0, 1;
+ }
+ } # for loop
+ } #if tail
+ } #if stage1
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "stage1 not confirmed, could not determine if $computer_shortname was turned on on host $hostnode");
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "could not determine if node was turned on on $hostnode");
+ return 0;
+ }
+ my $sshd_attempts = 0;
+
+ VMWAREROUND2:
+
+ #READY flag set
+ #attempt to login via ssh
+ insertloadlog($reservation_id, $vmclient_computerid, "vmround2", "waiting for ssh to become active");
+ notify($ERRORS{'OK'}, 0, "READY flag set for $myvmx, proceeding");
+ my $sshdstatus = 0;
+ my $wait_loops = 0;
+ $sshd_attempts++;
+ my $sshd_status = "off";
+ while (!$sshdstatus) {
+ my $sshd_status = _sshd_status($computer_shortname, $requestedimagename);
+ if ($sshd_status eq "on") {
+ $sshdstatus = 1;
+ notify($ERRORS{'OK'}, 0, "$computer_shortname now has active sshd running, ok to proceed to sync ssh keys");
+ }
+ else {
+ #either sshd is off or N/A, we wait
+ if ($wait_loops > 5) {
+ if ($sshd_attempts < 3) {
+ goto VMWAREROUND2;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "waited acceptable amount of time for sshd to become active, please check $computer_shortname on $hostnode");
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "waited acceptable amout of time for core services to start on $hostnode");
+ #need to check power, maybe reboot it. for now fail it
+ return 0;
+ }
+ } ## end if ($wait_loops > 5)
+ else {
+ $wait_loops++;
+ # to give post config a chance
+ notify($ERRORS{'OK'}, 0, "going to sleep 5 seconds, waiting for post config to finish");
+ sleep 5;
+ }
+ } # else
+ } #while
+
+ #clear ssh public keys from /root/.ssh/known_hosts
+ my $known_hosts = "/root/.ssh/known_hosts";
+ my $ssh_keyscan = "/usr/bin/ssh-keyscan";
+ my $port = "22";
+ my @file;
+ if (open(FILE, $known_hosts)) {
+ @file = <FILE>;
+ close FILE;
+
+ foreach my $line (@file) {
+ if ($line =~ s/$computer_shortname.*\n//) {
+ notify($ERRORS{'OK'}, 0, "removing $computer_shortname ssh public key from $known_hosts");
+ }
+ if ($line =~ s/$vmclient_privateIPaddress}.*\n//) {
+ notify($ERRORS{'OK'}, 0, "removing $vmclient_privateIPaddress ssh public key from $known_hosts");
+ }
+ }
+
+ if (open(FILE, ">$known_hosts")) {
+ print FILE @file;
+ close FILE;
+ }
+ #sync new keys
+ if (open(KEYSCAN, "$ssh_keyscan -t rsa -p $port $computer_shortname >> $known_hosts 2>&1 |")) {
+ my @ret = <KEYSCAN>;
+ close(KEYSCAN);
+ foreach my $r (@ret) {
+ notify($ERRORS{'OK'}, 0, "$r");
+ }
+ }
+ } ## end if (open(FILE, $known_hosts))
+ else {
+ notify($ERRORS{'OK'}, 0, "could not open $known_hosts for editing the $computer_shortname public ssh key");
+ }
+
+ insertloadlog($reservation_id, $vmclient_computerid, "info", "starting post configurations on node");
+ if ($vmclient_OSname =~ /vmwarewin|vmwareesxwin/) {
+ if (changewindowspasswd($computer_shortname, "root")) {
+ notify($ERRORS{'OK'}, 0, "Successfully changed password, account $computer_shortname,root");
+ }
+
+ if (changewindowspasswd($computer_shortname, "administrator")) {
+ notify($ERRORS{'OK'}, 0, "Successfully changed password, account $computer_shortname,administrator");
+ }
+ #disable remote desktop port
+ if (remotedesktopport($computer_shortname, "DISABLE")) {
+ notify($ERRORS{'OK'}, 0, "remote desktop disabled on $computer_shortname");
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "remote desktop not disable on $computer_shortname");
+ }
+
+ # set sshd to auto
+ if (_set_sshd_startmode($computer_shortname, "auto")) {
+ notify($ERRORS{'OK'}, 0, "successfully set sshd service on $computer_shortname to start auto");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to set sshd service on $computer_shortname to start auto");
+ }
+
+ #check for root logged in on console and then logoff
+ notify($ERRORS{'OK'}, 0, "checking for any console users $computer_shortname");
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($computer_shortname, $IDENTITY_wxp, "cmd /c qwinsta.exe", "root");
+ foreach my $r (@{$sshcmd[1]}) {
+ if ($r =~ /([>]?)([-a-zA-Z0-9]*)\s+([a-zA-Z0-9]*)\s+ ([0-9]*)\s+([a-zA-Z]*)/) {
+ my $state = $5;
+ my $session = $2;
+ my $user = $3;
+ if ($5 =~ /Active/) {
+ #give it sometime to finish - just in case
+ sleep 7;
+ notify($ERRORS{'OK'}, 0, "detected $user on $session still logged on $computer_shortname $r");
+ if (defined(run_ssh_command($computer_shortname, $IDENTITY_wxp, "cmd /c logoff.exe $session", "root"))) {
+ notify($ERRORS{'OK'}, 0, "logged off $user on $session on $computer_shortname $r");
+ }
+ }
+ } ## end if ($r =~ /([>]?)([-a-zA-Z0-9]*)\s+([a-zA-Z0-9]*)\s+ ([0-9]*)\s+([a-zA-Z]*)/)
+ } ## end foreach my $r (@{$sshcmd[1]})
+ } ## end if ($vmclient_OSname =~ /vmwarewin|vmwareesxwin/)
+ #ipconfiguration
+ if ($IPCONFIGURATION ne "manualDHCP") {
+ #not default setting
+ if ($IPCONFIGURATION eq "dynamicDHCP") {
+ insertloadlog($reservation_id, $vmclient_computerid, "dynamicDHCPaddress", "collecting dynamic IP address for node");
+ my $assignedIPaddress = getdynamicaddress($computer_shortname, $vmclient_OSname);
+ if ($assignedIPaddress) {
+ #update computer table
+ if (update_computer_address($vmclient_computerid, $assignedIPaddress)) {
+ notify($ERRORS{'DEBUG'}, 0, " succesfully updated IPaddress of node $computer_shortname");
+ }
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "could not update dynamic address $assignedIPaddress for $computer_shortname $requestedimagename");
+ return 0;
+ }
+ } ## end if ($assignedIPaddress)
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "could not fetch dynamic address from $computer_shortname $requestedimagename");
+ insertloadlog($reservation_id, $vmclient_computerid, "failed", "could not collect dynamic IP address for node");
+ return 0;
+ }
+ } ## end if ($IPCONFIGURATION eq "dynamicDHCP")
+ elsif ($IPCONFIGURATION eq "static") {
+ insertloadlog($reservation_id, $vmclient_computerid, "staticIPaddress", "setting static IP address for node");
+ if (setstaticaddress($computer_shortname, $vmclient_OSname, $vmclient_publicIPaddress)) {
+ # good set static address
+ }
+ }
+ } ## end if ($IPCONFIGURATION ne "manualDHCP")
+ #
+ insertloadlog($reservation_id, $vmclient_computerid, "vmwareready", "preformed post config on node");
+ return 1;
+
+} ## end sub load
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 capture
+
+ Parameters : $request_data_hash_reference
+ Returns : 1 if sucessful, 0 if failed
+ Description : Creates a new vmware image.
+
+=cut
+
+sub capture {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+ return 0;
+ }
+
+ my ($package, $filename, $line, $sub) = caller(0);
+
+ # Store some hash variables into local variables
+ # to pass to write_current_image routine
+ my $request_data = $self->data->get_request_data;
+
+ if (!$request_data) {
+ notify($ERRORS{'WARNING'}, 0, "unable to retrieve request data hash");
+ return 0;
+ }
+
+ # Store some hash variables into local variables
+ my $request_id = $self->data->get_request_id;
+ my $reservation_id = $self->data->get_reservation_id;
+
+ my $image_id = $self->data->get_image_id;
+ my $image_os_name = $self->data->get_image_os_name;
+ my $image_identity = $self->data->get_image_identity;
+ my $image_os_type = $self->data->get_image_os_type;
+ my $image_name = $self->data->get_image_name();
+
+
+ my $imagemeta_sysprep = $self->data->get_imagemeta_sysprep;
+
+ my $computer_id = $self->data->get_computer_id;
+ my $computer_shortname = $self->data->get_computer_short_name;
+ my $computer_nodename = $computer_shortname;
+ my $computer_hostname = $self->data->get_computer_hostname;
+ my $computer_type = $self->data->get_computer_type;
+
+ my $vmtype_name = $self->data->get_vmhost_type_name;
+ my $vmhost_vmpath = $self->data->get_vmhost_profile_vmpath;
+ my $vmprofile_vmdisk = $self->data->get_vmhost_profile_vmdisk;
+ my $vmprofile_datastorepath = $self->data->get_vmhost_profile_datastore_path;
+ my $vmhost_hostname = $self->data->get_vmhost_hostname;
+ my $host_type = $self->data->get_vmhost_type;
+ my $vmhost_imagename = $self->data->get_vmhost_image_name;
+
+ my ($hostIdentity, $hostnodename);
+ if ($host_type eq "blade") {
+ $hostnodename = $1 if ($vmhost_hostname =~ /([-_a-zA-Z0-9]*)(\.?)/);
+ $hostIdentity = $IDENTITY_bladerhel if ($vmhost_imagename =~ /^(rh[0-9]image|rhel[0-9]|fc[0-9]image|rhfc[0-9]|rhas[0-9]|esx[0-9]*)/);
+ }
+ else {
+ #using FQHN
+ $hostnodename = $vmhost_hostname;
+ $hostIdentity = $IDENTITY_linux_lab if ($vmhost_imagename =~ /^(realmrhel)/);
+ }
+ # Assemble a consistent prefix for notify messages
+ my $notify_prefix = "req=$request_id, res=$reservation_id:";
+
+
+ # Print some preliminary information
+ notify($ERRORS{'OK'}, 0, "$notify_prefix new name: $image_name");
+ notify($ERRORS{'OK'}, 0, "$notify_prefix computer_name: $computer_shortname");
+ notify($ERRORS{'OK'}, 0, "$notify_prefix vmhost_hostname: $vmhost_hostname");
+ notify($ERRORS{'OK'}, 0, "$notify_prefix vmtype_name: $vmtype_name");
+
+ # Modify currentimage.txt
+ if (write_currentimage_txt($self->data)) {
+ notify($ERRORS{'OK'}, 0, "$notify_prefix currentimage.txt updated on $computer_shortname");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "$notify_prefix unable to update currentimage.txt on $computer_shortname");
+ }
+
+ # Set some vm paths and names
+ my $vmx_directory = "$reservation_id$computer_shortname";
+ my $vmx_image_name = "$reservation_id$computer_shortname";
+ my $vmx_path = "$vmhost_vmpath/$vmx_directory/$vmx_image_name.vmx";
+
+ my @sshcmd;
+
+ # Check the vm type
+ if ($vmtype_name =~ /vmware|vmwareESX/) {
+
+ #if windows
+ #set sshd to mode= demand
+ # disable pagefile
+ # reboot
+ # check for and remove pagefile
+ # if sysprep-- copy sysprep files and start
+ # delay 15 secs turn vm off
+ # if not sysprep i.e. newsid
+ # copy appropriate files, execute and wait for shutdown signal
+ #
+ # is os windows
+ if ($image_name =~ /^(vmwarewinxp|vmwarewin2003|vmwareesxwin)/) {
+ #change password of root and sshd service back to default
+ # only useful on win platforms
+ # changewindowspasswd($node,$account,$passwd)
+ # needed only for sshd service on windows OS's
+ my $p = $WINDOWS_ROOT_PASSWORD;
+ if (changewindowspasswd($computer_shortname, "root", $p)) {
+ notify($ERRORS{'OK'}, 0, "$notify_prefix changed windows password $computer_shortname,root,$p");
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "$notify_prefix failed to change windows password $computer_shortname,root,$p");
+ return 0;
+ }
+
+ #defrag before removing pagefile
+ # we do this to speed up the process
+ # defraging without a page file takes a little longer
+ notify($ERRORS{'OK'}, 0, "starting defrag on $computer_nodename");
+ @sshcmd = run_ssh_command($computer_nodename, $IDENTITY_wxp, "cmd.exe /c defrag C: -f", "root");
+ my $defragged = 0;
+ foreach my $d (@{$sshcmd[1]}) {
+ if ($d =~ /Defragmentation Report/) {
+ notify($ERRORS{'OK'}, 0, "successfully defraged $computer_nodename");
+ $defragged = 1;
+ }
+ }
+ if (!$defragged) {
+ notify($ERRORS{'WARNING'}, 0, "defrag problem @{ $sshcmd[1] }");
+ }
+
+ #copy new auto_create_image.vbs and auto_prepare_for_image.vbs
+ #this moves(sometimes) the pagefile and reboots the box
+ #actually checks for a removes the pagefile.sys
+ my @scp;
+ if (run_scp_command("$TOOLS/auto_create_image.vbs", "$computer_nodename:auto_create_image.vbs", $IDENTITY_wxp)) {
+ }
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "failed to scp $TOOLS/auto_create_image.vbs to $computer_nodename");
+ return 0;
+ }
+
+ if (_set_sshd_startmode($computer_nodename, "auto")) {
+ notify($ERRORS{'OK'}, 0, "successfully set auto mode for sshd start");
+ }
+
+ my @list;
+ my $l;
+#execute the vbs script to disable the pagefil and reboot
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($computer_nodename, $IDENTITY_wxp, "cscript.exe //Nologo auto_create_image.vbs", "root");
+ #starting process
+ foreach $l (@{$sshcmd[1]}) {
+ if ($l =~ /createimage reboot|rebooting/) {
+ notify($ERRORS{'OK'}, 0, "auto_create_image.vbs initiated, $computer_nodename rebooting, sleeping 90");
+ sleep 90;
+ next;
+ }
+ elsif ($l =~ /failed error/) {
+ notify($ERRORS{'CRITICAL'}, 0, "auto_create_image.vbs failed, @{ $sshcmd[1] }");
+ return 0;
+ }
+ } ## end foreach $l (@{$sshcmd[1]})
+ #wait until the reboot process has started to shutdown services.
+ notify($ERRORS{'OK'}, 0, "$computer_nodename rebooting, waiting");
+ my $socketflag = 0;
+ REBOOTEDVMWARE:
+ my $rebooted = 1;
+ my $reboot_wait_count = 0;
+ while ($rebooted) {
+
+ if ($reboot_wait_count > 55) {
+ notify($ERRORS{'CRITICAL'}, 0, "waited $reboot_wait_count on reboot after auto_create_image on $computer_nodename");
+ return 0;
+ }
+ notify($ERRORS{'OK'}, 0, "$computer_nodename not completed reboot sleeping for 25");
+ sleep 15;
+ if (_pingnode($computer_nodename)) {
+ #it pingable check if sshd is open
+ notify($ERRORS{'OK'}, 0, "$computer_nodename is pingable, checking sshd port");
+ my $sshd = _sshd_status($computer_nodename, $image_name);
+ if ($sshd =~ /on/) {
+ $rebooted = 0;
+ notify($ERRORS{'OK'}, 0, "$computer_nodename sshd is open");
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "$computer_nodename sshd NOT open yet,sleep 5");
+ sleep 5;
+ }
+ } ## end if (_pingnode($computer_nodename))
+ $reboot_wait_count++;
+ } ## end while ($rebooted)
+ #check for recent bug
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($computer_nodename, $IDENTITY_wxp, "uname -s", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ if ($l =~ /^Warning:/) {
+ }
+ if ($l =~ /^Read from socket failed:/) {
+ if ($socketflag) {
+ notify($ERRORS{'CRITICAL'}, 0, "could not login $computer_nodename via ssh socket failure");
+ return 0;
+ }
+ notify($ERRORS{'CRITICAL'}, 0, "discovered ssh read from socket failure on $computer_nodename, attempting to repair");
+ #power cycle node
+ if (defined(run_ssh_command($computer_nodename, $image_identity, "vmware-cmd $vmx_path reset hard", "root"))) {
+ notify($ERRORS{'CRITICAL'}, 0, "$computer_nodename reset cycled going to reboot check routine");
+ sleep 30;
+ $socketflag = 1;
+ goto REBOOTEDVMWARE;
+ }
+ } ## end if ($l =~ /^Read from socket failed:/)
+ } ## end foreach my $l (@{$sshcmd[1]})
+
+ #
+ #actually remove the pagefile.sys sometimes movefile.exe does not work
+ if (defined(run_ssh_command($computer_nodename, $IDENTITY_wxp, "/usr/bin/rm -v C:\/pagefile.sys", "root"))) {
+ notify($ERRORS{'OK'}, 0, "removed pagefile.sys");
+ }
+
+ # which sysprep to use
+ #TODO - store volume license keys in database
+ my $sysprep_files;
+ if ($image_name =~ /(^vmwarewinxp|vmwareesxwinxp)/) {
+ $sysprep_files = "$SYSPREP_VMWARE";
+ }
+ elsif ($image_name =~ /(^vmwarewin2003|vmwareesxwin2003)/) {
+ $sysprep_files = "$SYSPREP_VMWARE2003";
+ }
+
+ #cp sysprep to C:
+ #chmod C:\Sysprep\*
+ if (defined(run_scp_command($sysprep_files, "$computer_nodename:\"C:\/Sysprep\"", $IDENTITY_wxp))) {
+ notify($ERRORS{'OK'}, 0, "copied Sysprep directory $sysprep_files to $computer_nodename C:");
+ if (defined(run_ssh_command($computer_nodename, $IDENTITY_wxp, "/usr/bin/chmod -R 755 C:\/Sysprep", "root"))) {
+ notify($ERRORS{'OK'}, 0, "chmoded -R C:/Sysprep/ files ");
+ }
+ }
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "could not copy $sysprep_files to $computer_nodename");
+ return 0;
+ }
+
+ #set sshd to manual
+ if (_set_sshd_startmode($computer_nodename, "manual")) {
+ notify($ERRORS{'OK'}, 0, "successfully set manual mode for sshd start");
+ }
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "failed to set manual mode for sshd on $computer_nodename");
+ return 0;
+ }
+ #start sysprep
+ #after 15 time units -- kill sysprep process
+ # in this case also stop vm using vmware-cmd
+
+ notify($ERRORS{'OK'}, 0, "starting sysprep on $computer_nodename");
+
+ my $vmisoff = 0;
+
+ if (open(SSH, "/usr/bin/ssh -x -i $IDENTITY_wxp $computer_nodename \"C:\/Sysprep\/sysprep.cmd\" & |")) {
+ my $notstop = 1;
+ my $loop = 0;
+ while ($notstop) {
+ notify($ERRORS{'DEBUG'}, 0, "$notify_prefix sysprep.cmd loop count: $loop");
+ $loop++;
+ my $l = <SSH>;
+ if ($l =~ /sysprep/) {
+ notify($ERRORS{'OK'}, 0, "sysprep started, sleep 45 before disconecting");
+ sleep 45;
+
+ notify($ERRORS{'DEBUG'}, 0, "attempting to kill sysprep");
+ if (_killsysprep($computer_nodename)) {
+ notify($ERRORS{'OK'}, 0, "killed sshd process for sysprep command");
+ }
+
+ $notstop = 0;
+ notify($ERRORS{'DEBUG'}, 0, "closing SSH filehandle");
+ close(SSH);
+ notify($ERRORS{'DEBUG'}, 0, "SSH filehandle closed");
+
+ $notstop = 0;
+ } ## end if ($l =~ /sysprep/)
+ elsif ($l =~ /sysprep.cmd: Permission denied/) {
+ notify($ERRORS{'CRITICAL'}, 0, "chmod 755 failed to correctly set execute on sysprep.cmd output $l");
+ close(SSH);
+ return 0;
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "sysprep cmd output: $l");
+
+ #avoid infinite loop
+ if ($loop > 80) {
+ notify($ERRORS{'OK'}, 0, "sysprep executed, sleep 20 before disconecting");
+ notify($ERRORS{'DEBUG'}, 0, "sysprep executed in loop control condition, exceeded limit");
+ sleep 20;
+ notify($ERRORS{'DEBUG'}, 0, "attempting to kill sysprep");
+ if (_killsysprep($computer_nodename)) {
+ notify($ERRORS{'OK'}, 0, "killed sshd process for sysprep command");
+ }
+ notify($ERRORS{'DEBUG'}, 0, "closing SSH filehandle");
+ close(SSH);
+ notify($ERRORS{'DEBUG'}, 0, "SSH filehandle closed");
+
+ $notstop = 0;
+ } ## end if ($loop > 80)
+
+ } ## end while ($notstop)
+ #stop vm
+ #ping to make sure host is offline
+ my $online = 1;
+ my $pingloop = 0;
+ notify($ERRORS{'OK'}, 0, "checking for pingable $computer_nodename");
+ while ($online) {
+ if (!(_pingnode($computer_nodename))) {
+ notify($ERRORS{'OK'}, 0, "$computer_nodename is not pingable");
+ $online = 0;
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "$computer_nodename is still pingable");
+ sleep 10;
+ $pingloop++;
+ }
+ if ($pingloop > 10) {
+ notify($ERRORS{'CRITICAL'}, 0, "failed on sysprep process for $computer_nodename");
+ return 0;
+ }
+ } ## end while ($online)
+ # we have to stop the vm due to sysprep not shutting down the machine -- even with the forceshutdown option
+ notify($ERRORS{'OK'}, 0, "stopping vm $vmx_path on $hostnodename");
+ notify($ERRORS{'DEBUG'}, 0, "stopping vm $vmx_path on hostnodename $hostnodename identity= $hostIdentity ");
+ my @vmstop = run_ssh_command($hostnodename, $hostIdentity, "vmware-cmd $vmx_path stop hard", "root");
+ foreach my $l (@{$vmstop[1]}) {
+ next if ($l =~ /Warning: Permanently/);
+ if ($l =~ /= 1/) {
+ notify($ERRORS{'OK'}, 0, "SUCCESS vmware-cmd stop worked");
+ }
+ }
+ #sleep a bit to let it shutdown
+ sleep 15;
+ #confirm
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnodename, $hostIdentity, "vmware-cmd $vmx_path getstate", "root");
+
+ foreach my $l (@{$sshcmd[1]}) {
+ if ($l =~ /= off/) {
+ #good
+ notify($ERRORS{'OK'}, 0, "SUCCESS turned off $vmx_path");
+ $vmisoff = 1;
+ }
+ }
+ if (!$vmisoff) {
+ notify($ERRORS{'CRITICAL'}, 0, "$vmx_path still reported on");
+ return 0;
+ }
+ } #start sysprep command
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "failed to start sysprep on $computer_nodename $!");
+ return 0;
+ }
+
+ } #if windows
+ #this only applies to localdisk settings
+ if ($vmprofile_vmdisk eq "localdisk") {
+ #only copy vmdk files back to management node -- into correct directory
+ if (open(MKDIR, "/bin/mkdir $VMWAREREPOSITORY/$image_name 2>&1 |")) {
+ my @a = <MKDIR>;
+ close(MKDIR);
+ for my $l (@a) {
+ notify($ERRORS{'OK'}, 0, "possible error @a");
+ }
+ notify($ERRORS{'OK'}, 0, "created tmp directory $VMWAREREPOSITORY/$image_name");
+ }
+ if (-d "$VMWAREREPOSITORY/$image_name") {
+ }
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "could not create tmp directory $VMWAREREPOSITORY/$image_name for $vmx_directory $!");
+ return 0;
+ }
+ #copy vmdk files
+ # confirm they were copied
+ notify($ERRORS{'OK'}, 0, "attemping to copy vmdk files to $VMWAREREPOSITORY");
+ if (run_scp_command("$hostnodename:\"$vmhost_vmpath/$vmx_directory/*.vmdk\"", "$VMWAREREPOSITORY/$image_name", $hostIdentity)) {
+ if (open(LISTFILES, "ls -s1 $VMWAREREPOSITORY/$image_name |")) {
+ my @list = <LISTFILES>;
+ close(LISTFILES);
+ my $numfiles = @list;
+ my $imagesize = getimagesize($image_name);
+ if ($imagesize) {
+ notify($ERRORS{'OK'}, 0, "copied $numfiles vmdk files imagesize= $imagesize");
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "vmdk files are not copied");
+ return 0;
+ }
+ #renaming local vmdk files
+ notify($ERRORS{'OK'}, 0, "begin rename local disk image files to newname");
+ my $oldname;
+ if (open(LISTFILES, "ls -1 $VMWAREREPOSITORY/$image_name 2>&1 |")) {
+ my @list = <LISTFILES>;
+ close(LISTFILES);
+ my $numfiles = @list;
+ #figure out old name
+ foreach my $a (@list) {
+ chomp($a);
+ if ($a =~ /([a-z]*)-([_0-9a-zA-Z]*)-(v[0-9]*)\.vmdk/) {
+ #print "old name $1-$2-$3\n";
+ $oldname = "$1-$2-$3";
+ notify($ERRORS{'OK'}, 0, "found previous name= $oldname");
+ }
+ }
+ foreach my $b (@list) {
+ chomp($b);
+ if ($b =~ /($oldname)-(s[0-9]*)\.vmdk/) {
+ notify($ERRORS{'OK'}, 0, "moving $b to $image_name-$2.vmdk");
+ if (open(MV, "mv $VMWAREREPOSITORY/$image_name/$b $VMWAREREPOSITORY/$image_name/$image_name-$2.vmdk 2>&1 |")) {
+ my @mv = <MV>;
+ close(MV);
+ if (@mv) {
+ notify($ERRORS{'CRITICAL'}, 0, "could not move $b to $VMWAREREPOSITORY/$image_name/$image_name-$2.vmdk \n@mv");
+ return 0;
+ }
+ }
+ notify($ERRORS{'OK'}, 0, "moved $b $VMWAREREPOSITORY/$image_name/$image_name-$2.vmdk");
+ } ## end if ($b =~ /($oldname)-(s[0-9]*)\.vmdk/)
+ } ## end foreach my $b (@list)
+
+ if (open(FILE, "$VMWAREREPOSITORY/$image_name/$oldname.vmdk")) {
+ my @file = <FILE>;
+ close(FILE);
+ for my $l (@file) {
+ #RW 4192256 SPARSE "vmwarewinxp-base10009-v1-s001.vmdk"
+ if ($l =~ /([0-9A-Z\s]*)\"$oldname-(s[0-9]*).vmdk\"/) {
+ #print "$l\n";
+ $l = "$1\"$image_name-$2.vmdk\"\n";
+ #print "$l\n";
+ }
+ }
+
+ if (open(FILE, ">$VMWAREREPOSITORY/$image_name/$oldname.vmdk")) {
+ print FILE @file;
+ close(FILE);
+ if (open(MV, "mv $VMWAREREPOSITORY/$image_name/$oldname.vmdk $VMWAREREPOSITORY/$image_name/$image_name.vmdk 2>&1 |")) {
+ my @mv = <MV>;
+ close(MV);
+ if (@mv) {
+ notify($ERRORS{'CRITICAL'}, 0, "old $oldname move to new $image_name error: @mv\n");
+ }
+ notify($ERRORS{'OK'}, 0, "moved $VMWAREREPOSITORY/$image_name/$oldname.vmdk $VMWAREREPOSITORY/$image_name/$image_name.vmdk");
+ }
+ } # write file array back to vmdk file
+ } #read main vmdk file
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "could not read $VMWAREREPOSITORY/$image_name/$oldname.vmdk $! ");
+ return 0;
+ }
+ } ## end if (open(LISTFILES, "ls -1 $VMWAREREPOSITORY/$image_name 2>&1 |"...
+ #remove dir from vmhost
+ #everything appears to have worked
+ #remove image files from vmhost
+ if (defined(run_ssh_command($hostnodename, $hostIdentity, "vmware-cmd -s unregister $vmx_path"))) {
+ notify($ERRORS{'OK'}, 0, "unregistered $vmx_path");
+ }
+
+ if (defined(run_ssh_command($hostnodename, $hostIdentity, "/bin/rm -rf $vmhost_vmpath/$vmx_directory", "root"))) {
+ notify($ERRORS{'OK'}, 0, "removed vmhost_vmpath/$vmx_directory");
+ }
+ #set file premissions on images to 644
+ # to allow for other management nodes to fetch image if neccessary
+ # useful in a large distributed framework
+ if (open(CHMOD, "/bin/chmod -R 644 $VMWAREREPOSITORY/$image_name/\*.vmdk 2>&1 |")) {
+ close(CHMOD);
+ notify($ERRORS{'DEBUG'}, 0, "$notify_prefix recursive update file permssions 644 on $VMWAREREPOSITORY/$image_name");
+ }
+
+ return 1;
+ } ## end if (open(LISTFILES, "ls -s1 $VMWAREREPOSITORY/$image_name |"...
+ } ## end if (run_scp_command("$hostnodename:\"$vmhost_vmpath/$vmx_directory/*.vmdk\""...
+ } ## end if ($vmprofile_vmdisk eq "localdisk")
+ elsif ($vmprofile_vmdisk eq "networkdisk") {
+ #rename vmdk files
+
+ #FIXME - making local directory in our repository so does_image_exists succeeds
+ # does_image_exists needs to figure out the datastores and search them
+ if (mkdir("$VMWAREREPOSITORY/$image_name")) {
+ notify($ERRORS{'OK'}, 0, "creating local dir for $image_name");
+ }
+
+
+ # create directory
+ my @mvdir = run_ssh_command($hostnodename, $hostIdentity, "/bin/mv $vmprofile_datastorepath/$vmx_directory $vmprofile_datastorepath/$image_name", "root");
+ for my $l (@{$mvdir[1]}) {
+ notify($ERRORS{'OK'}, 0, "possible error @{ $mvdir[1] }");
+ }
+ notify($ERRORS{'OK'}, 0, "renamed directory $vmx_directory to $image_name");
+ #if ESX user vmkfstools to rename the image
+ if ($vmtype_name =~ /vmwareESX/) {
+ my $cmd = "vmkfstools -E $vmprofile_datastorepath/$image_name/$vmx_directory.vmdk $vmprofile_datastorepath/$image_name/$image_name.vmdk";
+ my @retarr = run_ssh_command($hostnodename, $hostIdentity, $cmd, "root");
+ foreach my $r (@{$retarr[1]}) {
+ #if any output could mean trouble - this command provides no no response if successful
+ notify($ERRORS{'OK'}, 0, "possible problem renaming vm @{ $retarr[1] }") if ($r);
+ }
+ }
+ #success
+ #TODO add check to confirm
+ notify($ERRORS{'OK'}, 0, "looks like vm is renamed");
+ #cleanup - unregister, and remove vm dir on vmhost local disk
+ my @cleanup = run_ssh_command($hostnodename, $hostIdentity, "vmware-cmd -s unregister $vmx_path", "root");
+ foreach my $c (@{$cleanup[1]}) {
+ notify($ERRORS{'OK'}, 0, "vm successfully unregistered") if ($c =~ /1/);
+ }
+ #remove vmx directoy from our local datastore
+ if (defined(run_ssh_command($hostnodename, $hostIdentity, "/bin/rm -rf $vmhost_vmpath/$vmx_directory", "root"))) {
+ notify($ERRORS{'OK'}, 0, "success removed $vmhost_vmpath/$vmx_directory from $hostnodename");
+
+ }
+ } ## end elsif ($vmprofile_vmdisk eq "networkdisk") [ if ($vmprofile_vmdisk eq "localdisk")
+ return 1;
+
+ } #if vmware
+ elsif ($vmtype_name eq "xen") {
+
+ }
+
+} ## end sub capture
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _vmwareclone
+
+ Parameters : $hostnode, $identity, $srcDisk, $dstDisk, $dstDir
+ Returns : 1 if successful, 0 if error occurred
+ Description : using vm tools clone srcdisk to dstdisk
+ currently using builtin vmkfstools
+
+=cut
+
+sub _vmwareclone {
+ my ($hostnode, $identity, $srcDisk, $dstDisk, $dstDir) = @_;
+ my ($package, $filename, $line, $sub) = caller(0);
+
+ #TODO - add checks for VI toolkit - then use vmclone.pl instead
+ #vmclone.pl would need additional parameters
+
+ my @list = run_ssh_command($hostnode, $identity, "ls -1 $srcDisk", "root");
+ my $srcDiskexist = 0;
+
+ foreach my $l (@{$list[1]}) {
+ $srcDiskexist = 1 if ($l =~ /($srcDisk)$/);
+ $srcDiskexist = 0 if ($l =~ /No such file or directory/);
+ notify($ERRORS{'OK'}, 0, "$l");
+ }
+ my @ssh;
+ if ($srcDiskexist) {
+ #make dir for dstdisk
+ my @mkdir = run_ssh_command($hostnode, $identity, "mkdir -m 755 $dstDir", "root");
+ notify($ERRORS{'OK'}, 0, "srcDisk is exists $srcDisk ");
+ notify($ERRORS{'OK'}, 0, "starting clone process vmkfstools -d thin -i $srcDisk $dstDisk");
+ if (open(SSH, "/usr/bin/ssh -x -q -i $identity -l root $hostnode \"vmkfstools -i $srcDisk -d thin $dstDisk\" 2>&1 |")) {
+ #@ssh=<SSH>;
+ #close(SSH);
+ #foreach my $l (@ssh) {
+ # notify($ERRORS{'OK'},0,"$l");
+ #}
+ while (<SSH>) {
+ notify($ERRORS{'OK'}, 0, "started $_") if ($_ =~ /Destination/);
+ notify($ERRORS{'OK'}, 0, "started $_") if ($_ =~ /Cloning disk/);
+ notify($ERRORS{'OK'}, 0, "status $_") if ($_ =~ /Clone:/);
+ }
+ close(SSH);
+ } ## end if (open(SSH, "/usr/bin/ssh -x -q -i $identity -l root $hostnode \"vmkfstools -i $srcDisk -d thin $dstDisk\" 2>&1 |"...
+ } ## end if ($srcDiskexist)
+ else {
+ notify($ERRORS{'OK'}, 0, "srcDisk $srcDisk does not exists");
+ }
+ #confirm
+ @list = 0;
+ @list = run_ssh_command($hostnode, $identity, "ls -1 $dstDisk", "root");
+ my $dstDiskexist = 0;
+ foreach my $l (@{$list[1]}) {
+ $dstDiskexist = 1 if ($l =~ /($dstDisk)$/);
+ $dstDiskexist = 0 if ($l =~ /No such file or directory/);
+ }
+ if ($dstDiskexist) {
+ return 1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "clone process failed dstDisk $dstDisk does not exist");
+ return 0;
+ }
+} ## end sub _vmwareclone
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 vmrun_cmd
+
+ Parameters : hostnode, hostnode type,full vmx path,cmd
+ Returns : 0 or 1
+ Description : execute specific vmware-cmd cmd
+
+=cut
+
+sub _vmrun_cmd {
+ my ($hostnode, $hosttype, $hostidentity, $vmx, $cmd) = @_;
+ my ($package, $filename, $line, $sub) = caller(0);
+ notify($ERRORS{'WARNING'}, 0, "hostnode is not defined") if (!(defined($hostnode)));
+ notify($ERRORS{'WARNING'}, 0, "hosttype is not defined") if (!(defined($hosttype)));
+ notify($ERRORS{'WARNING'}, 0, "hostidentity is not defined") if (!(defined($hostidentity)));
+ notify($ERRORS{'WARNING'}, 0, "vmx is not defined") if (!(defined($vmx)));
+ notify($ERRORS{'WARNING'}, 0, "cmd is not defined") if (!(defined($cmd)));
+
+ if ($hosttype eq "blade") {
+
+ if ($cmd eq "off") {
+ notify($ERRORS{'OK'}, 0, "$hostnode,$hosttype,$hostidentity,$vmx,$cmd");
+ my @sshcmd = run_ssh_command($hostnode, $hostidentity, "vmware-cmd $vmx stop hard", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ next if ($l =~ /Warning: Permanently added/);
+ if ($l =~ /Error/) {
+ notify($ERRORS{'CRITICAL'}, 0, "$l output for $hostnode,$hosttype,$hostidentity,$vmx,$cmd");
+ return 0;
+ }
+ }
+ } ## end if ($cmd eq "off")
+ } ## end if ($hosttype eq "blade")
+ return 1;
+} ## end sub _vmrun_cmd
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 controlVM
+
+ Parameters : control command hash
+ Returns : 0 or 1
+ Description : controls VM, stop,remove, etc
+
+=cut
+
+sub control_VM {
+ my $self = shift;
+
+ # Check if subroutine was called as a class method
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'DEBUG'}, 0, "subroutine was called as a function, it must be called as a class method");
+ }
+
+ my $control = shift;
+ #my (%vm) = shift;
+ #notify($ERRORS{'CRITICAL'}, 0, "debugging", %vm);
+
+ my ($package, $filename, $line, $sub) = caller(0);
+
+ if (!(defined($control))) {
+ notify($ERRORS{'WARNING'}, 0, "control is not defined");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "control $control is defined ");
+ }
+
+ # Store hash var into local var
+
+ my $vmpath = $self->data->get_vmhost_profile_vmpath;
+ my $datastorepath = $self->data->get_vmhost_profile_datastore_path;
+ my $currentimage = $self->data->get_computer_currentimage_name;
+ my $reservation_id = $self->data->get_reservation_id;
+ my $vmtype = $self->data->get_vmhost_type_name;
+ my $persistent = $self->data->get_request_forimaging;
+ my $vmclient_shortname = $self->data->get_computer_short_name;
+ my $vmhost_fullhostname = $self->data->get_vmhost_hostname;
+ my $vmhost_shortname = $1 if ($vmhost_fullhostname =~ /([-_a-zA-Z0-9]*)(\.?)/);
+ my $vmhost_imagename = $self->data->get_vmhost_image_name;
+ my $vmhost_type = $self->data->get_vmhost_type;
+
+ my ($myvmdir, $myvmx, $mybasedirname, $myimagename);
+
+ #if persistent flag set -- special case or imaging mode
+ if ($persistent) {
+ #either in imaging mode or special use
+ $myvmdir = "$reservation_id$vmclient_shortname";
+ $myvmx = "$vmpath/$reservation_id$vmclient_shortname/$reservation_id$vmclient_shortname.vmx";
+ $mybasedirname = "$reservation_id$vmclient_shortname";
+ $myimagename = "$reservation_id$vmclient_shortname";
+ #base directory will not be used for image creation
+ }
+ else {
+ #standard use
+ $myvmdir = "$currentimage$vmclient_shortname";
+ $myvmx = "$vmpath/$currentimage$vmclient_shortname/$currentimage$vmclient_shortname.vmx";
+ $mybasedirname = $currentimage;
+ $myimagename = $currentimage;
+ }
+
+ my ($hostnode, $identity);
+ if ($vmhost_type eq "blade") {
+
+ if (defined($vmhost_shortname)) {
+ $hostnode = $vmhost_shortname;
+ }
+ else {
+ $hostnode = $1 if ($vmhost_shortname =~ /([-_a-zA-Z0-9]*)(\.?)/);
+ }
+ $identity = $IDENTITY_bladerhel if ($vmhost_imagename =~ /^(rh[0-9]image|rhel[0-9]|fc[0-9]image|rhfc[0-9]|rhas[0-9]|esx[0-9]*)/);
+ } ## end if ($vmhost_type eq "blade")
+ else {
+ #using FQHN
+ $hostnode = $vmhost_fullhostname;
+ $identity = $IDENTITY_linux_lab if ($vmhost_imagename =~ /^(realmrhel)/);
+ }
+ if (!$identity) {
+ notify($ERRORS{'WARNING'}, 0, "could not set ssh identity variable for image $vmhost_imagename type= $vmhost_type host= $vmhost_fullhostname");
+ notify($ERRORS{'OK'}, 0, "setting to default identity key");
+ $identity = $IDENTITY_bladerhel;
+ }
+ #setup flags
+ my $baseexists = 0;
+ my $dirstructure = 0;
+ my $vmison = 0;
+ my @sshcmd;
+ if ($vmtype =~ /vmware|vmwareGSX|vmwareESX/) {
+ #common checks
+ notify($ERRORS{'OK'}, 0, "checking for base image on $hostnode $datastorepath");
+ @sshcmd = run_ssh_command($hostnode, $identity, "ls -1 $datastorepath", "root");
+ notify($ERRORS{'OK'}, 0, "@{ $sshcmd[1] }");
+ foreach my $l (@{$sshcmd[1]}) {
+ if ($l =~ /denied|No such/) {
+ notify($ERRORS{'CRITICAL'}, 0, "node $hostnode output @{ $sshcmd[1] } $identity $hostnode");
+ return 0;
+ }
+ if ($l =~ /Warning: Permanently/) {
+ #ignore
+ }
+ if ($l =~ /(\s*?)$mybasedirname$/) {
+ notify($ERRORS{'OK'}, 0, "base image exists");
+ $baseexists = 1;
+ }
+ if ($l =~ /(\s*?)$myvmdir$/) {
+ notify($ERRORS{'OK'}, 0, "directory structure $myvmdir image exists");
+ $dirstructure = 1;
+ }
+ } ## end foreach my $l (@{$sshcmd[1]})
+
+ if (($dirstructure)) {
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "$myvmx directory structure for $myvmdir did not exist ");
+ }
+ if ($control =~ /off|remove/) {
+ #simply remove any vm's running on that hostname
+
+ my $l_myvmx = 0;
+ my $l_myvmdir = 0;
+
+ ##find the correct vmx file for this node -- if running
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "vmware-cmd -l", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ chomp($l);
+ next if ($l =~ /Warning:/);
+ notify($ERRORS{'OK'}, 0, "$l");
+ if ($l =~ /(.*)(\/)([-_a-zA-Z0-9]*$vmclient_shortname)(\/)([-_a-zA-Z0-9\/]*$vmclient_shortname.vmx)/) {
+ # do within this loop in case there is more than one
+ $l_myvmx = "$1/$3/$5";
+ $l_myvmdir = "$1/$3";
+ $l_myvmx =~ s/(\s+)/\\ /g;
+ $l_myvmdir =~ s/(\s+)/\\ /g;
+
+ notify($ERRORS{'OK'}, 0, "my vmx $l_myvmx");
+ my @sshcmd_1 = run_ssh_command($hostnode, $identity, "vmware-cmd $l_myvmx getstate");
+ foreach my $l (@{$sshcmd_1[1]}) {
+ if ($l =~ /= off/) {
+ #good - move on
+ }
+ elsif ($l =~ /= on/) {
+ my @sshcmd_2 = run_ssh_command($hostnode, $identity, "vmware-cmd $l_myvmx stop hard");
+ foreach my $l (@{$sshcmd_2[1]}) {
+ next if ($l =~ /Warning:/);
+ if ($l =~ /= 1/) {
+ #turn off or killpid -- of course it should be off by this point but kill
+ notify($ERRORS{'OK'}, 0, "turned off $l_myvmx");
+ }
+ else {
+ # FIX-ME add better error checking
+ notify($ERRORS{'OK'}, 0, "@{ $sshcmd_2[1] }");
+ }
+ } ## end foreach my $l (@{$sshcmd_2[1]})
+ } ## end elsif ($l =~ /= on/) [ if ($l =~ /= off/)
+ elsif ($l =~ /= stuck/) {
+ #list processes for vmx and kill pid
+ notify($ERRORS{'OK'}, 0, "vm reported in stuck state, attempting to kill process");
+ my @ssh_pid = run_ssh_command($hostnode, $identity, "vmware-cmd -q $l_myvmx getpid");
+ foreach my $p (@{$ssh_pid[1]}) {
+ if ($p =~ /(\D*)(\s*)([0-9]*)/) {
+ notify($ERRORS{'OK'}, 0, "vm pid= $3");
+ my $vmpid = $3;
+ if (defined(run_ssh_command($hostnode, $identity, "kill -9 $vmpid"))) {
+ notify($ERRORS{'OK'}, 0, "killed $vmpid $l_myvmx");
+ }
+ }
+ }
+ } ## end elsif ($l =~ /= stuck/) [ if ($l =~ /= off/)
+ else {
+ notify($ERRORS{'OK'}, 0, "@{ $sshcmd_1[1] }");
+ }
+ } ## end foreach my $l (@{$sshcmd_1[1]})
+ #unregister
+ undef @sshcmd_1;
+ @sshcmd_1 = run_ssh_command($hostnode, $identity, "vmware-cmd -s unregister $l_myvmx ");
+ foreach my $l (@{$sshcmd_1[1]}) {
+ notify($ERRORS{'OK'}, 0, "vm $l_myvmx unregistered") if ($l =~ /= 1/);
+ }
+ } ## end if ($l =~ /(.*)(\/)([-_a-zA-Z0-9]*$vmclient_shortname)(\/)([-_a-zA-Z0-9\/]*$vmclient_shortname.vmx)/)
+ } ## end foreach my $l (@{$sshcmd[1]})
+ if ($control eq "remove") {
+ #delete directory -- clean slate
+ if (defined(run_ssh_command($hostnode, $identity, "/bin/rm -rf $l_myvmdir", "root"))) {
+ notify($ERRORS{'OK'}, 0, "removed $l_myvmdir from $hostnode");
+ return 1;
+ }
+
+ }
+ } ## end if ($control =~ /off|remove/)
+ #restart
+ if ($control eq "restart") {
+ #turn vm off
+ notify($ERRORS{'OK'}, 0, "restarting $myvmx");
+ if ($vmison) {
+ notify($ERRORS{'OK'}, 0, "turning off $myvmx");
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "vmware-cmd $myvmx stop hard", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ if ($l) {
+ notify($ERRORS{'OK'}, 0, "$myvmx strange output $l");
+ }
+ }
+ #sleep a bit to let it shutdown
+ sleep 15;
+ #confirm
+ undef @sshcmd;
+ @sshcmd = run_ssh_command($hostnode, $identity, "vmware-cmd $myvmx getstate", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ if ($l =~ /= off/) {
+ #good
+ return 1;
+ }
+ }
+ } ## end if ($vmison)
+ else {
+ notify($ERRORS{'OK'}, 0, "$myvmx reported off");
+ return 1;
+ }
+ } ## end if ($control eq "restart")
+ #suspend
+ if ($control eq "suspend") {
+ #suspend machine
+ #could copy to managment node storage
+ #under different name and store for later use
+ }
+ } ## end if ($vmtype =~ /vmware|vmwareGSX|vmwareESX/)
+ return 1;
+} ## end sub control_VM
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 getimagesize
+
+ Parameters : imagename
+ Returns : 0 failure or size of image
+ Description : in size of Kilobytes
+
+=cut
+
+sub get_image_size {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+ return 0;
+ }
+
+# Either use a passed parameter as the image name or use the one stored in this object's DataStructure
+ my $image_name = shift;
+ $image_name = $self->data->get_image_name() if !$image_name;
+ if (!$image_name) {
+ notify($ERRORS{'CRITICAL'}, 0, "image name could not be determined");
+ return 0;
+ }
+ notify($ERRORS{'DEBUG'}, 0, "getting size of image: $image_name");
+
+ #my $imagename = $_[0];
+ #my ($package, $filename, $line, $sub) = caller(0);
+ #notify($ERRORS{'WARNING'}, 0, "imagename is not defined") if (!(defined($imagename)));
+
+ #if (!(defined($imagename))) {
+ # return 0;
+ #}
+ my $IMAGEREPOSITORY = "$VMWAREREPOSITORY/$image_name";
+
+ #list files in image directory, account for main .gz file and any .gz.00X files
+ if (open(FILELIST, "/bin/ls -s1 $IMAGEREPOSITORY 2>&1 |")) {
+ my @filelist = <FILELIST>;
+ close(FILELIST);
+ my $size = 0;
+ foreach my $f (@filelist) {
+ if ($f =~ /$image_name.vmdk/) {
+ my ($presize, $blah) = split(" ", $f);
+ $size += $presize;
+ }
+ }
+ if ($size == 0) {
+ #strange imagename not found
+ return 0;
+ }
+ return int($size / 1024);
+ } ## end if (open(FILELIST, "/bin/ls -s1 $IMAGEREPOSITORY 2>&1 |"...
+
+ return 0;
+} ## end sub get_image_size
+
+
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 node_status
+
+ Parameters : $nodename, $log
+ Returns : array of related status checks
+ Description : checks on ping,sshd, currentimage, OS
+
+=cut
+
+sub node_status {
+ my $self = shift;
+
+ # Check if subroutine was called as a class method
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'DEBUG'}, 0, "subroutine was called as a function, it must be called as a class method");
+ }
+
+ #my ($vmhash) = shift;
+
+ my ($package, $filename, $line, $sub) = caller(0);
+
+ # try to contact vm
+ # $self->data->get_request_data;
+ # get state of vm
+ my $vmpath = $self->data->get_vmhost_profile_vmpath;
+ my $datastorepath = $self->data->get_vmhost_profile_datastore_path;
+ my $requestedimagename = $self->data->get_image_name;
+ my $vmhost_type = $self->data->get_vmhost_type;
+ my $vmhost_hostname = $self->data->get_vmhost_hostname;
+ my $vmhost_imagename = $self->data->get_vmhost_image_name;
+ my $vmclient_shortname = $self->data->get_computer_short_name;
+
+ my ($hostnode, $identity);
+
+ # Create a hash to store status components
+ my %status;
+
+ # Initialize all hash keys here to make sure they're defined
+ $status{status} = 0;
+ $status{currentimage} = 0;
+ $status{ping} = 0;
+ $status{ssh} = 0;
+ $status{vmstate} = 0; #on or off
+ $status{image_match} = 0;
+
+ if ($vmhost_type eq "blade") {
+ $hostnode = $1 if ($vmhost_hostname =~ /([-_a-zA-Z0-9]*)(\.?)/);
+ $identity = $IDENTITY_bladerhel; #if($vm{vmhost}{imagename} =~ /^(rhel|rh3image|rh4image|fc|rhfc)/);
+ }
+ else {
+ #using FQHN
+ $hostnode = $vmhost_hostname;
+ $identity = $IDENTITY_linux_lab if ($vmhost_imagename =~ /^(realmrhel)/);
+ }
+
+ if (!$identity) {
+ notify($ERRORS{'CRITICAL'}, 0, "could not set ssh identity variable for image $vmhost_imagename type= $vmhost_type host= $vmhost_hostname");
+ }
+
+ # Check if node is pingable
+ notify($ERRORS{'DEBUG'}, 0, "checking if $vmclient_shortname is pingable");
+ if (_pingnode($vmclient_shortname)) {
+ $status{ping} = 1;
+ notify($ERRORS{'OK'}, 0, "$vmclient_shortname is pingable ($status{ping})");
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "$vmclient_shortname is not pingable ($status{ping})");
+ $status{status} = 'RELOAD';
+ return $status{status};
+ }
+
+ #
+ my $vmx_directory = "$requestedimagename$vmclient_shortname";
+ my $myvmx = "$vmpath/$requestedimagename$vmclient_shortname/$requestedimagename$vmclient_shortname.vmx";
+ my $mybasedirname = $requestedimagename;
+ my $myimagename = $requestedimagename;
+
+
+ #can I ssh into it
+ my $sshd = _sshd_status($vmclient_shortname, $requestedimagename);
+
+
+ #is it running the requested image
+ if ($sshd eq "on") {
+
+ $status{ssh} = 1;
+ $status{currentimage} = _getcurrentimage($vmclient_shortname);
+
+ if ($status{currentimage}) {
+ chomp($status{currentimage});
+ if ($status{currentimage} =~ /$requestedimagename/) {
+ $status{image_match} = 1;
+ notify($ERRORS{'OK'}, 0, "$vmclient_shortname is loaded with requestedimagename $requestedimagename");
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "$vmclient_shortname reports current image is currentimage= $status{currentimage} requestedimagename= $requestedimagename");
+ }
+ } ## end if ($status{currentimage})
+ } ## end if ($sshd eq "on")
+
+ # #vm running
+ if ($status{image_match}) {
+ my @sshcmd = run_ssh_command($hostnode, $identity, "vmware-cmd $myvmx getstate", "root");
+ foreach my $l (@{$sshcmd[1]}) {
+ notify($ERRORS{'OK'}, 0, "$l");
+ $status{vmstate} = 1 if ($l =~ /^getstate\(\) = on/);
+ $status{vmstate} = 0 if ($l =~ /= off/);
+
+ if ($l =~ /No such virtual machine/) {
+ #ok wait something is using that hostname
+ #reset $status{image_match} controlVM will detect and remove it
+ $status{image_match} = 0;
+ }
+ } ## end foreach my $l (@{$sshcmd[1]})
+ } ## end if ($status{image_match})
+
+ # Determine the overall machine status based on the individual status results
+ if ($status{ssh} && $status{image_match}) {
+ $status{status} = 'READY';
+ }
+ else {
+ $status{status} = 'RELOAD';
+ }
+
+ notify($ERRORS{'OK'}, 0, "returning node status hash reference (\$node_status->{status}=$status{status})");
+ return \%status;
+
+} ## end sub node_status
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 does_image_exist
+
+ Parameters : imagename
+ Returns : 0 or 1
+ Description : scans our image local image library for requested image
+ returns 1 if found or 0 if not
+ attempts to scp image files from peer management nodes
+
+=cut
+
+sub does_image_exist {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+ return 0;
+ }
+
+ my $image_name = $self->data->get_image_name();
+ if (!$image_name) {
+ notify($ERRORS{'CRITICAL'}, 0, "unable to determine if image exists, unable to determine image name");
+ return 0;
+ }
+
+ my $IMAGEREPOSITORY;
+
+ if ($image_name =~ /^(vmware)/) {
+ $IMAGEREPOSITORY = "$VMWAREREPOSITORY";
+ }
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "unable to determine if image exists, image name is not vmware image_name= $image_name");
+ return 0;
+ }
+
+ if (open(IMAGES, "/bin/ls -1 $IMAGEREPOSITORY 2>&1 |")) {
+ my @images = <IMAGES>;
+ close(IMAGES);
+ foreach my $i (@images) {
+ if ($i =~ /$image_name/) {
+ notify($ERRORS{'OK'}, 0, "image $image_name exists");
+ return 1;
+ }
+ }
+ } ## end if (open(IMAGES, "/bin/ls -1 $IMAGEREPOSITORY 2>&1 |"...
+
+ notify($ERRORS{'WARNING'}, 0, "image $IMAGEREPOSITORY/$image_name does NOT exists");
+ return 0;
+
+} ## end sub does_image_exist
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 retrieve_image
+
+ Parameters :
+ Returns :
+ Description : Attempts to retrieve an image from an image library partner
+
+=cut
+
+sub retrieve_image {
+ my $self = shift;
+ if (ref($self) !~ /vmware/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+ return;
+ }
+
+ # Make sure imag library functions are enabled
+ my $image_lib_enable = $self->data->get_management_node_image_lib_enable();
+ if (!$image_lib_enable) {
+ notify($ERRORS{'OK'}, 0, "image library functions are disabled");
+ return;
+ }
+
+ # Get the image name
+ my $image_name = shift;
+ $image_name = $self->data->get_image_name() if !$image_name;
+ if (!$image_name) {
+ notify($ERRORS{'WARNING'}, 0, "unable to determine image name");
+ return;
+ }
+
+ # Get the other image library variables
+ my $image_lib_user = $self->data->get_management_node_image_lib_user() || 'undefined';
+ my $image_lib_key = $self->data->get_management_node_image_lib_key() || 'undefined';
+ my $image_lib_partners = $self->data->get_management_node_image_lib_partners() || 'undefined';
+ if ("$image_lib_user $image_lib_key $image_lib_partners" =~ /undefined/) {
+ notify($ERRORS{'WARNING'}, 0, "image library configuration data is missing: user=$image_lib_user, key=$image_lib_key, partners=$image_lib_partners");
+ return;
+ }
+
+ # Get the image repository path
+ my $image_repository_path = $self->_get_image_repository_path();
+ if (!$image_repository_path) {
+ notify($ERRORS{'WARNING'}, 0, "image repository path could not be determined");
+ return;
+ }
+
+ # Attempt to copy image from other management nodes
+ notify($ERRORS{'OK'}, 0, "attempting to copy $image_name from other management nodes");
+
+ # Split up the partner list
+ my @partner_list = split(/,/, $image_lib_partners);
+ if ((scalar @partner_list) == 0) {
+ notify($ERRORS{'WARNING'}, 0, "image lib partners variable is not listed correctly or does not contain any information: $image_lib_partners");
+ return;
+ }
+
+ # Loop through the partners, attempt to copy
+ foreach my $partner (@partner_list) {
+ notify($ERRORS{'OK'}, 0, "checking if $partner has $image_name");
+
+ # Use ssh to call ls on the partner management node
+ my ($ls_exit_status, $ls_output_array_ref) = run_ssh_command($partner, $image_lib_key, "ls -1 $image_repository_path", $image_lib_user);
+
+ # Check if the ssh command failed
+ if (!$ls_output_array_ref) {
+ notify($ERRORS{'WARNING'}, 0, "unable to run ls command via ssh on $partner");
+ next;
+ }
+
+ # Convert the output array to a string
+ my $ls_output = join("\n", @{$ls_output_array_ref});
+
+ # Check the ls output for permission denied
+ if ($ls_output =~ /permission denied/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "permission denied when checking if $partner has $image_name, exit status=$ls_exit_status, output:\n$ls_output");
+ next;
+ }
+
+ # Check the ls output for the image name
+ if ($ls_output !~ /$image_name/i) {
+ notify($ERRORS{'OK'}, 0, "$image_name does not exist on $partner");
+ next;
+ }
+
+ # Image exists
+ notify($ERRORS{'OK'}, 0, "$image_name exists on $partner, attempting to copy");
+
+ #set lockfile - prevent process from loading while a copy is in progress
+
+ my $lock = "$image_repository_path/$image_name.copylock";
+ if (sysopen(SEM, $lock, O_RDONLY | O_CREAT)) {
+ if (flock(SEM, LOCK_EX)) {
+ notify($ERRORS{'OK'}, 0, "set Exclusive lock on $lock");
+ # Attempt copy
+ if (run_scp_command("$image_lib_user\@$partner:$image_repository_path/$image_name*", $image_repository_path, $image_lib_key)) {
+ notify($ERRORS{'OK'}, 0, "$image_name files copied via SCP");
+ close(SEM);
+ notify($ERRORS{'OK'}, 0, "releasing exclusive lock on $lock, proceeding");
+ unlink($lock);
+ last;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "unable to copy $image_name files via SCP");
+ close(SEM);
+ notify($ERRORS{'OK'}, 0, "releasing exclusive lock on $lock, proceeding");
+ unlink($lock);
+ next;
+ }
+ } ## end if (flock(SEM, LOCK_EX))
+ } ## end if (sysopen(SEM, $lock, O_RDONLY | O_CREAT...
+
+
+ } ## end foreach my $partner (@partner_list)
+
+ # Make sure image was copied
+ if ($self->does_image_exist($image_name)) {
+ notify($ERRORS{'OK'}, 0, "$image_name was copied to this management node");
+ return 1;
+ }
+ else {
[... 83 lines stripped ...]