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.

Reply via email to