svn commit: samba r16722 - in branches/SOC/bnh/perl: .

brad at samba.org brad at samba.org
Sat Jul 1 02:15:53 GMT 2006


Author: brad
Date: 2006-07-01 02:15:52 +0000 (Sat, 01 Jul 2006)
New Revision: 16722

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=16722

Log:
Fixed error handling when working with the vix perl api.

Added functionality to host_connect() function to log into windows as a user.
This allows us to copy files and run commands on the windows vm.
The initial_setup.conf parameters GUEST_ADMIN_USERNAME and GUEST_ADMIN_PASSWORD specify this account.

Added function run_on_guest() to execute programs on the guest vm as the user mentioned above.

Added function copy_to_guest() which takes a local src directory or filename and remote directory as parameters, and creates an associative list of local-remote file paths.
The function passes this list to copy_files_to_guest() to perform the actual copy to the guest vm.

With this update, these scripts can automatically setup a windows guest on vmware server with the only preconfiguration being that vmware tools is installed and the guest os has an ip address configured.

I'll put together a zip file containing the set of scripts needed to make this happen as well as a README file a little later.


Modified:
   branches/SOC/bnh/perl/initial_setup.conf
   branches/SOC/bnh/perl/vm_setup.pl


Changeset:
Modified: branches/SOC/bnh/perl/initial_setup.conf
===================================================================
--- branches/SOC/bnh/perl/initial_setup.conf	2006-07-01 01:03:27 UTC (rev 16721)
+++ branches/SOC/bnh/perl/initial_setup.conf	2006-07-01 02:15:52 UTC (rev 16722)
@@ -20,8 +20,13 @@
 # Where these scripts will be copied from on the unix host.
 # I don't know how this will work if the unix host is a different
 # system than the vmware server host.
-export LOCAL_SCRIPT_PATH="./windows-scripts"
+export LOCAL_SCRIPT_PATH="./windows-scripts/"
 
+# In order to copy files and execute programs on the guest vm,
+# we need administrator-level credentials to log in with.
+export GUEST_ADMIN_USERNAME="administrator"
+export GUEST_ADMIN_PASSWORD="adminpass"
+
 # These parameters are optional, and change the windows guest
 # hostname and workgroup if set.
 #export GUEST_HOSTNAME="tortureguest"

Modified: branches/SOC/bnh/perl/vm_setup.pl
===================================================================
--- branches/SOC/bnh/perl/vm_setup.pl	2006-07-01 01:03:27 UTC (rev 16721)
+++ branches/SOC/bnh/perl/vm_setup.pl	2006-07-01 02:15:52 UTC (rev 16722)
@@ -35,6 +35,8 @@
 	my $username;
 	my $password;
 	my $vm_cfg_path;
+	my $guest_admin_username;
+	my $guest_admin_password;
 
 	sub error {
 		my $old_err_code = $err_code;
@@ -45,7 +47,7 @@
 	}
 
 	# Power on the guest if it isn't already running.
-	# Returns 0 when the guest is already running, and 
+	# Returns 0 when the guest is already running, and
 	# if not, it waits until it is started.
 	sub start_guest {
 		my $vm_power_state = $perl_vm->get_execution_state();
@@ -58,7 +60,7 @@
 				VMware::VmPerl::VM_EXECUTION_STATE_SUSPENDED)
 		{
 			if (!$perl_vm->start()) {
-				($err_code, $err_str) = 
+				($err_code, $err_str) =
 					$perl_vm->get_last_error();
 				return ($err_code);
 			}
@@ -74,10 +76,11 @@
 		# name of the method. Called locally, this function will lose
 		# the first parameter.
 		shift @_;
-		($hostname, $port, $username, $password, $vm_cfg_path) = @_;
+		($hostname, $port, $username, $password, $vm_cfg_path,
+			$guest_admin_username, $guest_admin_password) = @_;
 
 		# Connect to host using vmperl api.
-		$perl_vm_credentials = 
+		$perl_vm_credentials =
 			VMware::VmPerl::ConnectParams::new($hostname, $port,
 				$username, $password);
 		if (!$perl_vm->connect($perl_vm_credentials, $vm_cfg_path)) {
@@ -94,7 +97,8 @@
 				$hostname, $port, $username, $password,
 				0, VMware::Vix::Simple::VIX_INVALID_HANDLE);
 		if ($err_code != VMware::Vix::Simple::VIX_OK) {
-			($err_code, $err_str) = $vix_vm_host->get_last_error();
+			$err_str =
+				VMware::Vix::Simple::GetErrorText($err_code);
 			undef $perl_vm;
 			undef $vix_vm;
 			undef $vix_vm_host;
@@ -114,15 +118,29 @@
 		}
 
 		# Open VM.
-		($err_code, $vix_vm) = 
+		($err_code, $vix_vm) =
 			VMware::Vix::Simple::VMOpen($vix_vm_host, $vm_cfg_path);
 		if ($err_code != VMware::Vix::Simple::VIX_OK) {
-			($err_code, $err_str) = $vix_vm->get_last_error();
+			$err_str =
+				VMware::Vix::Simple::GetErrorText($err_code);
 			undef $perl_vm;
 			undef $vix_vm;
 			undef $vix_vm_host;
 			return ($err_code);
 		}
+
+		# Login to $vix_vm guest OS.
+		$err_code = VMware::Vix::Simple::VMLoginInGuest($vix_vm,
+				$guest_admin_username, $guest_admin_password,
+				0);
+		if ($err_code != VMware::Vix::Simple::VIX_OK) {
+			$err_str =
+				VMware::Vix::Simple::GetErrorText($err_code);
+			undef $perl_vm;
+			undef $vix_vm;
+			undef $vix_vm_host;
+			return ($err_code);
+		}
 		return ($err_code);
 	}
 
@@ -134,7 +152,7 @@
 			$err_code = 1;
 			$err_str = "Error creating new VmPerl object";
 		}
-	
+
 		undef $vix_vm;
 		VMware::Vix::Simple::HostDisconnect($vix_vm_host);
 		VMware::Vix::Simple::ReleaseHandle($vix_vm_host);
@@ -151,7 +169,8 @@
 		}
 
 		$err_code = host_connect(NULL, $hostname, $port, $username,
-				$password, $vm_cfg_path);
+				$password, $vm_cfg_path, $guest_admin_username,
+				$guest_admin_password);
 		if ($err_code != 0) {
 			my $old_err_str = $err_str;
 			$err_str = "Re-connecting to host failed: " .
@@ -164,7 +183,7 @@
 	sub create_snapshot {
 		my $snapshot;
 
-		($err_code, $snapshot) = 
+		($err_code, $snapshot) =
 			VMware::Vix::Simple::VMCreateSnapshot($vix_vm,
 			"Snapshot", "Created by vm_setup.pl", 0,
 			VMware::Vix::Simple::VIX_INVALID_HANDLE);
@@ -172,7 +191,8 @@
 		VMware::Vix::Simple::ReleaseHandle($snapshot);
 
 		if ($err_code != VMware::Vix::Simple::VIX_OK) {
-			($err_code, $err_str) = $vix_vm->get_last_error();
+			$err_str =
+				VMware::Vix::Simple::GetErrorText($err_code);
 			return $err_code;
 		}
 
@@ -189,17 +209,18 @@
 	sub revert_snapshot {
 		my $snapshot;
 
-		# We are passing 0 to VMGetRootSnapshot because we can only 
+		# We are passing 0 to VMGetRootSnapshot because we can only
 		# have one snapshot in vmware server, and it has an id of 0.
-		($err_code, $snapshot) = 
+		($err_code, $snapshot) =
 			VMware::Vix::Simple::VMGetRootSnapshot($vix_vm, 0);
 		if ($err_code != VMware::Vix::Simple::VIX_OK) {
-			($err_code, $err_str) = $vix_vm->get_last_error();
+			$err_str =
+				VMware::Vix::Simple::GetErrorText($err_code);
 			return ($err_code);
 		}
 
 		my $job = VMware::Vix::API::VM::RevertToSnapshot($vix_vm,
-				$snapshot, 0, 
+				$snapshot, 0,
 				VMware::Vix::Simple::VIX_INVALID_HANDLE,
 				undef,0);
 
@@ -226,17 +247,103 @@
 		return ($err_code);
 	}
 
+	# $dest_path must exist. It doesn't get created.
+	sub copy_files_to_guest {
+		shift @_;
+		my (%files) = @_;
+
+		my $src_file;
+		my $dest_file;
+
+		foreach $src_file (keys(%files)) {
+			$dest_file = $files{$src_file};
+			$err_code =
+				VMware::Vix::Simple::VMCopyFileFromHostToGuest(
+					$vix_vm, $src_file, $dest_file, 0,
+					VMware::Vix::Simple::VIX_INVALID_HANDLE);
+			if ($err_code != VMware::Vix::Simple::VIX_OK) {
+				$err_str = "Copying $src_file: " .
+					VMware::Vix::Simple::GetErrorText(
+						$err_code);
+				return $err_code;
+			}
+		}
+		return $err_code;
+	}
+
 	sub copy_to_guest {
-		$err_code = -1;
-		$err_str = "Function copy_to_guest() is not yet implemented";
+		# Read parameters $src_path, $dest_path.
+		shift @_;
+		my ($src_path, $dest_dir) = @_;
 
+		my $len = length($dest_dir);
+		my $idx = rindex($dest_dir, '\\');
+		if ($idx != ($len - 1)) {
+			$err_code = -1;
+			$err_str = "Destination $dest_dir must be a " .
+					"directory path";
+			return ($err_code);
+		}
+
+		# If $src_filepath specifies a file, create it in $dest_path
+		# and keep the same name.
+		# If $src_path is a directory, create the files it contains in
+		# $dest_path, keeping the same names.
+		$len = length($src_path);
+		my %files;
+		$idx = rindex($src_path, '/');
+		if ($idx == ($len - 1)) {
+			# $src_path is a directory.
+			if (!opendir (DIR_HANDLE, $src_path)) {
+				$err_code = -1;
+				$err_str = "Error opening directory $src_path";
+				return $err_code;
+			}
+
+			foreach $file (readdir DIR_HANDLE) {
+				my $src_file = $src_path . $file;
+
+				if (!opendir(DIR_HANDLE2, $src_file)) {
+					# We aren't interested in subdirs.
+					my $dest_path = $dest_dir . $file;
+					$files{$src_file} = $dest_path;
+				} else {
+					closedir(DIR_HANDLE2);
+				}
+			}
+		} else {
+			# Strip if preceeding path from $src_path.
+			my $src_file = substr($src_path, ($idx + 1), $len);
+			my $dest_path = $dest_dir . $src_file;
+
+			# Add $src_path => $dest_path to %files.
+			$files{$src_path} = $dest_path;
+		}
+
+		$err_code = copy_files_to_guest(NULL, %files);
+		if ($err_code != 0) {
+			my $old_err_str = $err_str;
+			$err_str = "Copying files to host after " .
+				"populating %files: " . $old_err_str;
+			return ($err_code);
+		}
 		return ($err_code);
 	}
 
 	sub run_on_guest {
-		$err_code = -1;
-		$err_str = "Function run_on_guest() is not yet implemented";
+		# Read parameters $cmd, $cmd_args.
+		shift @_;
+		my ($cmd, $cmd_args) = @_;
 
+		$err_code = VMware::Vix::Simple::VMRunProgramInGuest($vix_vm,
+				$cmd, $cmd_args, 0, 
+				VMware::Vix::Simple::VIX_INVALID_HANDLE);
+		if ($err_code != VMware::Vix::Simple::VIX_OK) {
+			$err_str = VMware::Vix::Simple::GetErrorText(
+					$err_code);
+			return ($err_code);
+		}
+
 		return ($err_code);
 	}
 
@@ -286,6 +393,9 @@
 my $host_username = $ENV{'HOST_USERNAME'};
 my $host_password = $ENV{'HOST_PASSWORD'};
 
+my $guest_admin_username = $ENV{'GUEST_ADMIN_USERNAME'};
+my $guest_admin_password = $ENV{'GUEST_ADMIN_PASSWORD'};
+
 my $guest_username = $ENV{'GUEST_USERNAME'};
 my $guest_password = $ENV{'GUEST_PASSWORD'};
 my $guest_hostname = $ENV{'GUEST_HOSTNAME'};
@@ -295,7 +405,8 @@
 
 my $vm = VMHost;
 $vm->host_connect($host_server_name, $host_server_port, $host_username,
-			$host_password, $vm_cfg_path);
+			$host_password, $vm_cfg_path, $guest_admin_username,
+			$guest_admin_password);
 check_error($vm, "Error in \$vm->connect().\n");
 print "Connected successfully to VM.\n";
 
@@ -309,15 +420,26 @@
 print "Snapshot creation has started.\n";
 
 # Copy the windows setup scripts to the VM.
-$vm->copy_to_guest($local_script_path,$guest_script_path);
+$vm->copy_to_guest($local_script_path, $guest_script_path);
 check_error($vm, "Error in \$vm->copy_to_guest().\n");
 print "Windows setup scripts have been copied to the VM.\n";
 
-# Run win_setup.wsh on the VM.
-$cmd = "cscript $guest_script_path win_setup.wsf /username:$guest_username" .
-		"/password: $guest_password";
-$vm->run_on_guest($cmd);
-check_error($vm, "Error in \$vm->run_on_guest() executing " . $cmd . ".\n");
+# Run win_setup.wsf on the VM.
+$cmd = "C:\\WINDOWS\\system32\\cscript.exe ";
+$cmd_args = $guest_script_path . "win_setup.wsf /username:" .
+		$guest_username . " /password:" . $guest_password;
+
+if ($guest_hostname) {
+	$cmd_args = $cmd_args . " /hostname:" . $guest_hostname;
+}
+
+if ($guest_workgroup) {
+	$cmd_args = $cmd_args . " /workgroup:" . $guest_workgroup;
+}
+
+$vm->run_on_guest($cmd, $cmd_args);
+check_error($vm, "Error in \$vm->run_on_guest() while executing: " .
+		$cmd . $cmd_args . ".\n");
 print "Windows setup scripts have been successfully executed on the VM.\n";
 
 # Destroy the vm object and disconnect from the vm.



More information about the samba-cvs mailing list