You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by bm...@apache.org on 2009/01/30 19:42:13 UTC

svn commit: r739371 - in /incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning: esx.README esx.pm

Author: bmbouter
Date: Fri Jan 30 18:42:13 2009
New Revision: 739371

URL: http://svn.apache.org/viewvc?rev=739371&view=rev
Log:
VCL-29

An working alpha version of the esx provsioning module.  Includes instructions in the esx.README file


Added:
    incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esx.README
    incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esx.pm

Added: incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esx.README
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esx.README?rev=739371&view=auto
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esx.README (added)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esx.README Fri Jan 30 18:42:13 2009
@@ -0,0 +1,86 @@
+Pre-Installation:
+
+You need to install the VMware VI Perl toolkit installed on the VCL server
+
+Each vmware esx hypervisor requires a mounted NFS datastore named 'VCL'
+
+This same datastore needs to be mounted on the VCL server at /mnt/vcl/
+
+This NFS export needs to be exported (from the NFS server) at /mnt/export/
+
+This same datastore requires the following structure.
+
+[VCL]
+	/inuse  (required)
+	/golden  (required)
+		/imagename
+			imagename.vmdk
+			imagename-flat.vmdk
+		...
+
+Image requirements:
+	All images used by this module must have names that begin with esx3-<anything you want>
+	ssh must be set to start on boot
+	ssh keys must be setup so that VCL can ssh into it
+	The image needs two NICs (eth0 is private, eth1 is public)
+	The IP addressing of the private (eth1) interface must be set to DHCP on boot
+
+
+VCL expects the blades to have a consistant private IP address.  Go configure dhcpd.conf and in /etc/hosts manually
+
+
+Customize the module:
+
+This module expects the following three variables to be hard-coded at the top of the esx.pm file.  Remember to character escape any special characters.
+
+$vmhost_username, $vmhost_password, $datastore_ip
+
+A note about datastore_ip.  Because the module ssh's to the storage system directly instead of doing a cp over nfs, you need to set the IP of the datastore here.  The datastore machine should be setup with SSH keys from the VCL ssh keys set as IDENTITY_blade_linux in the VCL conf file.
+
+Install the module:
+
+Do these once:
+1)  Insert a row into the module table with `perlpackage` equal to 'VCL::Module::Provisioning::esx'
+2)  Insert a row into the provisioning table with `moduleid` equal to the id of the entry from step 1 in the module table
+3)  Insert a record into the 'vmprofile' table with the following guidelines
+	profilename: VMware ESX SAN
+	vmtypeid: link to anything valid ID from the vmtype table.
+	imageid: link to the "No Image" id in the image table
+	virtualswitch0: <name of your private virtual machine port group> 
+	virtualswitch1: <name of your public virtual machine port group>
+
+Make VCL aware of your ESX hosts:
+1)  For each esx hypervisor, which VCL should provisong virtual machine to, create an entry for that hypervisor by going to Manage Computers -> Edit Computer Information -> Add
+	Hostname <your ESX's hostname>
+	IP <your ESX's IP>
+	Type "blade"
+	Provisioning Engine:  This doesn't matter
+	Computer Groups:  Don't add the hypervisors to any computer groups
+
+2)  For each esx hypervisor manually create an entry in the 'vmhost' database table with the following guidelines:
+	computerid: the id of the computer created in step 1
+	vmlimit: the max number of vms to have on this hypervisor
+	vmprofileid: the id of the vmprofile entry created in the "Do these once" secion step 3
+
+Create a virtual machine placeholder for each VM you would like to concurrently run.  Do so by going to Manage Computers -> Edit Computer Information -> Add
+	Hostname: <the hostname of the vm when it is provisioned and turned on>
+	IP: <the public IP of the vm when it is provisioned and turned on>
+	Type: virtualmachine
+	Provisioning Engine: VMware ESX
+	Computer Groups:  allComputers
+
+For each virtual machine, manually update the private IP, eth0macaddress (private), and eth1macaddress (public) for the placeholder virtual machine entries created in in the computers table during step (4)
+
+Add static entries in dhcpd.conf for the eth0macaddresses (private) for all computer placeholder entries
+
+Add similar entries for each compter placeholder to the /etc/hosts file to provide VCL with name resolution on these vms
+
+Finally, once all virtual machines placeholders have been created, 'assign' them to hypervisors by using the 'Virtual Hosts' area of your web interface.
+
+Now your hypervisors and virtual machines are setup, time to add an image:
+
+1)  Create an entry in the image table.
+	name:  esx3-<what you want>-v0
+	OSid:  link to the fc9 entry on the OS table
+2)  Create an image revision table with the imageid fromt the entry created in (1) and the imagename used in (1)
+3)  Add the image revision to the allImages and allVMimages groups
\ No newline at end of file

Added: incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esx.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esx.pm?rev=739371&view=auto
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esx.pm (added)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esx.pm Fri Jan 30 18:42:13 2009
@@ -0,0 +1,592 @@
+#!/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::esx - VCL module to support the vmware esx 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::esx;
+
+# Include File Copying for Perl
+use File::Copy;
+
+# 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 = '1.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 ESX module initialized");
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 provision
+
+ Parameters  : hash
+ Returns     : 1(success) or 0(failure)
+ Description : loads virtual machine with requested image
+
+=cut
+
+sub load {
+	my $self = shift;
+
+	#check to make sure this call is for the esx module
+	if (ref($self) !~ /esx/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);
+	notify($ERRORS{'DEBUG'}, 0, "****************************************************");
+
+	# get various useful vars from the database
+	my $request_id     = $self->data->get_request_id;
+	my $reservation_id = $self->data->get_reservation_id;
+	my $vmhost_hostname           = $self->data->get_vmhost_hostname;
+	my $image_name     = $self->data->get_image_name;
+	my $computer_shortname  = $self->data->get_computer_short_name;
+	my $vmclient_computerid = $self->data->get_computer_id;
+	my $vmclient_imageminram      = $self->data->get_image_minram;
+	my $image_os_name  = $self->data->get_image_os_name;
+	my $image_identity = $self->data->get_image_identity;
+
+	my $virtualswitch0    = $self->data->get_vmhost_profile_virtualswitch0;
+	my $virtualswitch1    = $self->data->get_vmhost_profile_virtualswitch1;
+	my $vmclient_eth0MAC          = $self->data->get_computer_eth0_mac_address;
+	my $vmclient_eth1MAC          = $self->data->get_computer_eth1_mac_address;
+	my $vmclient_OSname           = $self->data->get_image_os_name;
+
+	#eventually get these from a config file or database
+	my $vmhost_username = "";
+	my $vmhost_password = "";
+	my $datastore_ip = "";
+
+	notify($ERRORS{'OK'}, 0, "Entered ESX module, loading $image_name on $computer_shortname (on $vmhost_hostname) for reservation $reservation_id");
+
+	my $datastorepath4vmx = "/mnt/vcl/inuse/$computer_shortname";
+
+	# query the host to see if the vm currently exists
+	my $vminfo_command = "/usr/lib/vmware-viperl/apps/vm/vminfo.pl";
+	$vminfo_command .= " --server '$vmhost_hostname'";
+	$vminfo_command .= " --vmname $computer_shortname";
+	$vminfo_command .= " --username $vmhost_username";
+	$vminfo_command .= " --password '$vmhost_password'";
+	notify($ERRORS{'DEBUG'},0,"VM info command: $vminfo_command");
+	my $vminfo_output;
+	$vminfo_output = `$vminfo_command`;
+	notify($ERRORS{'DEBUG'},0,"VM info output: $vminfo_output");
+
+	# parse the results from the host and determine if we need to remove an old vm
+	if ($vminfo_output =~ /^Information of Virtual Machine $computer_shortname/m) {
+		# Turn new vm on
+		my $poweroff_command = "/usr/lib/vmware-viperl/apps/vm/vmcontrol.pl";
+		$poweroff_command .= " --server '$vmhost_hostname'";
+		$poweroff_command .= " --vmname $computer_shortname";
+		$poweroff_command .= " --operation poweroff";
+		$poweroff_command .= " --username $vmhost_username";
+		$poweroff_command .= " --password '$vmhost_password'";
+		notify($ERRORS{'DEBUG'},0,"Power off command: $poweroff_command");
+		my $poweroff_output;
+		$poweroff_output = `$poweroff_command`;
+		notify($ERRORS{'DEBUG'},0,"Powered off: $poweroff_output");
+
+		# unregister old vm from host
+		my $unregister_command = "/usr/lib/vmware-viperl/apps/vm/vmregister.pl";
+		$unregister_command .= " --server '$vmhost_hostname'";
+		$unregister_command .= " --username $vmhost_username";
+		$unregister_command .= " --password '$vmhost_password'";
+		$unregister_command .= " --vmxpath '[VCL]/inuse/$computer_shortname/$image_name.vmx'";
+		$unregister_command .= " --operation unregister";
+		$unregister_command .= " --vmname $computer_shortname";
+		$unregister_command .= " --pool Resources";
+		$unregister_command .= " --hostname '$vmhost_hostname'";
+		$unregister_command .= " --datacenter 'ha-datacenter'";
+		my $unregister_output;
+		$unregister_output = `$unregister_command`;
+		notify($ERRORS{'DEBUG'}, 0, "Un-Registered: $unregister_output");
+
+		my $remove_vm_output = `rm -rf $datastorepath4vmx`;
+		notify($ERRORS{'DEBUG'}, 0, "Output from remove command is: $remove_vm_output");
+	}
+
+	# copy appropriate vmdk file
+	my $newdir = $datastorepath4vmx;
+	if (!mkdir($newdir)) {
+		notify($ERRORS{'CRITICAL'}, 0, "Could not create new directory: $!");
+		return 0;
+	}
+	my $from = "/mnt/vcl/golden/$image_name/$image_name.vmdk";
+	my $to = "$datastorepath4vmx/$image_name.vmdk";
+	if (!copy($from, $to)) {
+		notify($ERRORS{'CRITICAL'}, 0, "Could not copy VMDK file! $!");
+		# insert load log here perhaps
+		return 0;
+	}
+	notify($ERRORS{'DEBUG'}, 0, "COPIED VMDK SUCCESSFULLY");
+
+
+	# Copy the (large) -flat.vmdk file
+	# This uses ssh to do the copy locally on the nfs server.
+	$from = "/mnt/export/golden/$image_name/$image_name-flat.vmdk";
+	$to = "/mnt/export/inuse/$computer_shortname/$image_name-flat.vmdk";
+	my @copy_command = ("ssh", $datastore_ip, "-i", $image_identity, "-o", "BatchMode yes", "cp $from $to");
+	notify($ERRORS{'OK'}, 0, "SSHing to copy vmdk-flat file");
+	if (system(@copy_command) >> 8) {
+		notify($ERRORS{'CRITICAL'}, 0, "Could not copy VMDK-flat file! $!");
+		# insert load log here perhaps
+		return 0;
+	}
+
+	# Author new VMX file
+	my @vmxfile;
+	my $vmxpath = "$datastorepath4vmx/$image_name.vmx";
+
+	my $guestOS = "other";
+	$guestOS = "linux"   if ($image_os_name =~ /(fc|centos)/i);
+	# FIXME Should add some more entries here
+
+	# determine adapter type by looking at vmdk file
+	my $adapter = "lsilogic"; # default
+	if (open(RE, "grep adapterType $datastorepath4vmx/$image_name.vmdk 2>&1 |")) {
+		my @LIST = <RE>;
+		close(RE);
+		foreach my $a (@LIST) {
+			if ($a =~ /(ide|buslogic|lsilogic)/) {
+				$adapter = $1;
+				notify($ERRORS{'OK'}, 0, "adapter= $1 ");
+			}
+		}
+	} ## end if (open(RE, "grep adapterType $VMWAREREPOSITORY/$image_name/$image_name.vmdk 2>&1 |"...
+
+	push(@vmxfile, "#!/usr/bin/vmware\n");
+	push(@vmxfile, "config.version = \"8\"\n");
+	push(@vmxfile, "virtualHW.version = \"4\"\n");
+	push(@vmxfile, "memsize = \"$vmclient_imageminram\"\n");
+	push(@vmxfile, "displayName = \"$computer_shortname\"\n");
+	push(@vmxfile, "guestOS = \"$guestOS\"\n");
+	push(@vmxfile, "uuid.action = \"create\"\n");
+	push(@vmxfile, "Ethernet0.present = \"TRUE\"\n");
+	push(@vmxfile, "Ethernet1.present = \"TRUE\"\n");
+
+	push(@vmxfile, "Ethernet0.networkName = \"$virtualswitch0\"\n");
+	push(@vmxfile, "Ethernet1.networkName = \"$virtualswitch1\"\n");
+	push(@vmxfile, "ethernet0.wakeOnPcktRcv = \"false\"\n");
+	push(@vmxfile, "ethernet1.wakeOnPcktRcv = \"false\"\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 = \"generated\"\n");
+	push(@vmxfile, "gui.exitOnCLIHLT = \"FALSE\"\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");
+
+	push(@vmxfile, "scsi0.present = \"TRUE\"\n");
+	push(@vmxfile, "scsi0.sharedBus = \"none\"\n");
+	push(@vmxfile, "scsi0.virtualDev = \"$adapter\"\n");
+	push(@vmxfile, "scsi0:0.present = \"TRUE\"\n");
+	push(@vmxfile, "scsi0:0.deviceType = \"scsi-hardDisk\"\n");
+	push(@vmxfile, "scsi0:0.fileName =\"$image_name.vmdk\"\n");
+
+	#write to tmpfile
+	if (open(TMP, ">$vmxpath")) {
+		print TMP @vmxfile;
+		close(TMP);
+		notify($ERRORS{'OK'}, 0, "wrote vmxarray to $vmxpath");
+	}
+	else {
+		notify($ERRORS{'CRITICAL'}, 0, "could not write vmxarray to $vmxpath");
+		insertloadlog($reservation_id, $vmclient_computerid, "failed", "could not write vmx file to local tmp file");
+		return 0;
+	}
+
+	# Register new vm on host
+	my $register_command = "/usr/lib/vmware-viperl/apps/vm/vmregister.pl";
+	$register_command .= " --server '$vmhost_hostname'";
+	$register_command .= " --username $vmhost_username";
+	$register_command .= " --password '$vmhost_password'";
+	$register_command .= " --vmxpath '[VCL]/inuse/$computer_shortname/$image_name.vmx'";
+	$register_command .= " --operation register";
+	$register_command .= " --vmname $computer_shortname";
+	$register_command .= " --pool Resources";
+	$register_command .= " --hostname '$vmhost_hostname'";
+	$register_command .= " --datacenter 'ha-datacenter'";
+	my $register_output;
+	$register_output = `$register_command`;
+	notify($ERRORS{'DEBUG'}, 0, "Registered: $register_output");
+
+	# Turn new vm on
+	my $poweron_command = "/usr/lib/vmware-viperl/apps/vm/vmcontrol.pl";
+	$poweron_command .= " --server '$vmhost_hostname'";
+	$poweron_command .= " --vmname $computer_shortname";
+	$poweron_command .= " --operation poweron";
+	$poweron_command .= " --username $vmhost_username";
+	$poweron_command .= " --password '$vmhost_password'";
+	notify($ERRORS{'DEBUG'},0,"Power on command: $poweron_command");
+	my $poweron_output;
+	$poweron_output = `$poweron_command`;
+	notify($ERRORS{'DEBUG'},0,"Powered on: $poweron_output");
+
+
+	# Start waiting for SSH to come up
+	
+
+	my $sshdstatus = 0;
+	my $wait_loops = 0;
+	my $sshd_status = "off";
+	notify($ERRORS{'DEBUG'}, 0, "Waiting for ssh to come up on $computer_shortname");
+	while (!$sshdstatus) {
+		my $sshd_status = _sshd_status($computer_shortname, $image_name);
+		if ($sshd_status eq "on") {
+			$sshdstatus = 1;
+			notify($ERRORS{'OK'}, 0, "$computer_shortname now has active sshd running");
+		}
+		else {
+			#either sshd is off or N/A, we wait
+			if ($wait_loops > 24) {
+					notify($ERRORS{'CRITICAL'}, 0, "waited acceptable amount of time for sshd to become active, please check $computer_shortname on $vmhost_hostname");
+					#need to check power, maybe reboot it. for now fail it
+					return 0;
+			}
+			else {
+				$wait_loops++;
+				# to give post config a chance
+				notify($ERRORS{'OK'}, 0, "going to sleep 5 seconds, waiting for post config to finish. Try $wait_loops");
+				sleep 5;
+			}
+		}    # else
+	}    #while
+
+	# Set IP info
+	if ($IPCONFIGURATION ne "manualDHCP") {
+		#not default setting
+		if ($IPCONFIGURATION eq "dynamicDHCP") {
+			insertloadlog($reservation_id, $vmclient_computerid, "dynamicDHCPaddress", "collecting dynamic IP address for node");
+			notify($ERRORS{'DEBUG'}, 0, "Attempting to query vmclient for its public IP...");
+			my $assignedIPaddress = getdynamicaddress($computer_shortname, $vmclient_OSname);
+			if ($assignedIPaddress) {
+				#update computer table
+				notify($ERRORS{'DEBUG'}, 0, " Got dynamic address from vmclient, attempting to update database");
+				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 $image_name");
+					return 0;
+				}
+			} ## end if ($assignedIPaddress)
+			else {
+				notify($ERRORS{'CRITICAL'}, 0, "could not fetch dynamic address from $computer_shortname $image_name");
+				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") {
+			notify($ERRORS{'CRITICAL'}, 0, "STATIC ASSIGNMENT NOT SUPPORTED. See vcld.conf");
+			return 0;
+			#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")
+	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 {
+	notify($ERRORS{'OK'}, 0, "Hello world, I am capturing an image now");
+	return 1;
+} ## end sub capture
+
+
+#/////////////////////////////////////////////////////////////////////////
+=head2 node_status
+
+ Parameters  : $nodename, $log
+ Returns     : array of related status checks
+ Description : checks on sshd, currentimage
+
+=cut
+
+sub node_status {
+	my $self = shift;
+
+	# Check if subroutine was called as a class method
+	if (ref($self) !~ /esx/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return 0;
+	}
+
+	#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 $request_forimaging              = $self->data->get_request_forimaging();
+
+	notify($ERRORS{'OK'}, 0, "Entering node_status, checking status of $vmclient_shortname");
+	notify($ERRORS{'DEBUG'}, 0, "request_for_imaging: $request_forimaging");
+	notify($ERRORS{'DEBUG'}, 0, "requeseted image name: $requestedimagename");
+
+	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;
+
+	notify($ERRORS{'DEBUG'}, 0, "Trying to ssh...");
+
+	#can I ssh into it
+	my $sshd = _sshd_status($vmclient_shortname, $requestedimagename);
+
+
+	#is it running the requested image
+	if ($sshd eq "on") {
+
+		notify($ERRORS{'DEBUG'}, 0, "SSH good, trying to query image name");
+
+		$status{ssh}          = 1;
+		my $identity = $IDENTITY_bladerhel;
+		my @sshcmd = run_ssh_command($vmclient_shortname, $identity, "cat currentimage.txt");
+		$status{currentimage} = $sshcmd[1][0];
+
+		notify($ERRORS{'DEBUG'}, 0, "Image name: $status{currentimage}");
+
+		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")
+
+	# 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{'DEBUG'}, 0, "status set to $status{status}");
+
+
+	if($request_forimaging){
+		$status{status} = 'RELOAD';
+		notify($ERRORS{'OK'}, 0, "request_forimaging set, setting status to RELOAD");
+	}
+
+	notify($ERRORS{'DEBUG'}, 0, "returning node status hash reference (\$node_status->{status}=$status{status})");
+	return \%status;
+
+} ## end sub node_status
+
+sub does_image_exist {
+	my $self = shift;
+	if (ref($self) !~ /esx/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 = "/mnt/vcl/golden";
+
+	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
+
+initialize();
+1;
+__END__
+
+=head1 BUGS and LIMITATIONS
+
+ There are no known bugs in this module.
+ Please report problems to the VCL team (vcl_help@ncsu.edu).
+
+=head1 AUTHOR
+
+ Andrew Brown <am...@ncsu.edu>
+ Brian Bouterse <bm...@ncsu.edu>
+
+=head1 SEE ALSO
+
+L<http://vcl.ncsu.edu>
+
+=cut