growdisk.pl -- A perl sample script that combines vixPerl (VIX API perl) with vSphere Perl SDK (VI Perl SDK)

Version 1

     

     

     

     

    The following script uses the vSphere SDK for Perl (VI Perl SDK) to change the size of a virtual disk for a virtual machine, then it uses vixPerl (VIX API in Perl) to go into the Guest Operating System run a script there to perform Disk Adminstrator operations for resizing the OS partition and making the guest OS recognize the new disk space.

     

     

    The script was written assuming a Win2k guest in the VM with VMware tools installed.

     

     

    -


     

     

     

    #!/usr/bin/perl -w

     

    use strict;

    use warnings;

    use VMware::VIRuntime;

    use VMware::Vix::Simple;

     

    1. all constants are exported

    use VMware::Vix::API::Constants;

     

    $Util::script_version = "1.0";

     

    my %opts = (

       'vmname' => {

       type => "=s",

       help => "The name of the virtual machine",

       required => 1,

       },

    );

     

    Opts::add_options(%opts);

    1. read/validate options and connect to the server

    Opts::parse();

    Opts::validate();

    Util::connect();

     

    my $extendMB = 20;

     

    my $vms = Vim::find_entity_views(view_type => 'VirtualMachine', filter => { 'guest.guestState' => 'running',

                                                                           'config.name' => Opts::get_option('vmname') } );

     

      1. Getting for matching VMs that have VMware Tools running the diskinfo from the Second Disk

      2. (growing a system disk is much harder)

     

    foreach (@$vms) {

      my $vm = $_;

       

    1. verify VMware Tools are ok in guest.  This test isn't working at the moment.

      if ( $vm->guest->toolsRunningStatus ne "guestToolsRunning" ) { die "VMware Tools must be running!  Current status is: " . $vm->guest->toolsRunningStatus . "\n"; }

      my $devices = $vm->config->hardware->device;

      foreach (@$devices) {

      if ($_->deviceInfo->label eq "Hard disk 2" ) {

         my $device = $_;

         my $capKB = $device->capacityInKB;

         print "Data disk information for VM before vmdk grow '" . $vm->name . "'\n";

         my $dfree = $vm->guest->disk->[1]->freeSpace / 1024;

         my $dcap = $vm->guest->disk->[1]->capacity / 1024;

         my $dper = int ((100 * $dfree) / $dcap);

         my $dltr = $vm->guest->disk->[1]->diskPath;

         ($dltr) = split (/:/, $dltr,2);

         print "   Disk capacity KB: $dcap\n";

         print "   Disk free KB: $dfree\n";

         print "   Disk free percentage: $dper\n";

         my $newCap = $capKB + ($extendMB * 1024);

     

         my $changeDevice = VirtualDisk->new(capacityInKB => $newCap,

                                        backing => $device->backing,

                        deviceInfo => $device->deviceInfo,

                        controllerKey => $device->controllerKey,

                        key => $device->key,

                        unitNumber => $device->unitNumber);

     

         my $spec = VirtualMachineConfigSpec->new(

                changeVersion => $vm->config->changeVersion,

                deviceChange => [

                   VirtualDeviceConfigSpec->new(

                        operation => VirtualDeviceConfigSpecOperation->new("edit"),

                        device => $changeDevice )

                ]

         );

         eval {

            print "Adding $extendMB MB...\n";

            $vm->ReconfigVM(spec => $spec);

                Util::trace(0,"\nVirtual machine '" . $vm->name . "' is reconfigured successfully.\n");

            };

     

         if ($@)

              elsif (ref($@->detail) eq 'InvalidDeviceSpec')

              elsif (ref($@->detail) eq 'FileAlreadyExists')

              else

           }

           else

         }

         print "Now refresh the disk management view to show the unallocated space.\nPress enter when ready to continue: ";

         my $go = <>;

     

          

    1. now start the VIX stuff to run diskpart.exe and extend the partition and the NTTFS volume.

         my $err;

         my $handle;

         my $vmpath = $vm->config->files->vmPathName;

     

         ($err, $handle) = HostConnect(VIX_API_VERSION,

                                       VIX_SERVICEPROVIDER_VMWARE_VI_SERVER,

                                       "https://" . Opts::get_option('server') . "/sdk",  

                                       0,

                                       Opts::get_option('username'),

                                       Opts::get_option('password'),

                                       0,

                                       VIX_INVALID_HANDLE);

     

         if ( $err != VIX_OK ) { die "Could not connect to vCenter Server: ", GetErrorText($err), "($err)\n" ;}

         my $vmHandle;

         ($err, $vmHandle) = VMOpen($handle, $vmpath);

         if ( $err != VIX_OK ) { die "Could not open $vmpath: ", GetErrorText($err), "($err)\n" ;}

     

          

    1. create extendvol.bat script locally

         open (DP, ">", "extendvol.bat");

         my $script = "\@echo off\

    echo select disk=1 >> diskpart.txt\

    echo select volume $dltr >> diskpart.txt\

    echo extend >> diskpart.txt\

    diskpart /s diskpart.txt  > C:
    vixdir
    output.txt\

    del diskpart.txt";

         print DP $script;

         close DP;

     

          

    1. login to the guest

         $err = VMLoginInGuest($vmHandle,                    # VM handle

                               Opts::get_option('username'), # guest username

                               Opts::get_option('password'), # guest password

                               0);                           # options

     

         if ( $err != VIX_OK ) { die "Could not open $vmpath: ", GetErrorText($err), "($err)\n" ;}

         print "Guest login success!\n";

     

          

    1. copy the script to C:\vixdir

         $err = VMCopyFileFromHostToGuest($vmHandle,                   # VM handle

                                          "extendvol.bat",             # source file

                                          "C:
    vixdir
    extendvol.bat", # destination file

                                          0,                           # options

                                          VIX_INVALID_HANDLE);         # property list

     

         if ( $err != VIX_OK ) { die "Could not copy extendvol.bat to guest: ", GetErrorText($err), "($err)\n" ;}

     

         print "Copy extendvol.bat to guest success!\n";

     

          

    1. execute diskpart /s C:\vixdir\diskpart.txt > C:\vixdir\output.txt

         $err = VMRunScriptInGuest($vmHandle,                    # VM handle

                                   "",                           # shell interpreter  (cmd.exe for Windows)

                                   "C:
    vixdir
    extendvol.bat",  # command

                                   0,                            # options

                                   VIX_INVALID_HANDLE);          # property list

     

         if ( $err != VIX_OK ) { die "Could not run extendvol.bat in guest: ", GetErrorText($err), "($err)\n" ;}

     

         print "diskpart.exe script execute success!\n";

     

          

    1. retrieve the output.txt

         $err = VMCopyFileFromGuestToHost($vmHandle,                 # VM handle

                                          "C:
    vixdir
    output.txt",  # guest file (full path)

                                          "output.txt",              # host file (full path)

                                          0,                         # options

                                          VIX_INVALID_HANDLE);       # property list

     

         if ( $err != VIX_OK ) { die "Could not retrieve ouptut.txt from guest: ", GetErrorText($err), "($err)\n" ;}

     

         print "output.txt retrieve success!\n";

          

    1. display it

         open (IN, 'output.txt');

         while (<IN>) { print $_; }

         close IN;

     

          

    1. delete C:\vixdir files

         $err = VMRunScriptInGuest($vmHandle,                        # VM handle

                                   "",                               # shell interpreter  (cmd.exe for Windows)

                                   "del /Q C:
    vixdir
    .",         # command

                                   0,                                # options

                                   VIX_INVALID_HANDLE);              # property list

     

         if ( $err != VIX_OK ) { die "Could not delete output.txt in guest: ", GetErrorText($err), "($err)\n" ;}

     

          

    1. this may not be needed?

         ReleaseHandle($vmHandle);

         HostDisconnect($handle);

        }

      }

     

    }

     

    1. disconnect from the server

    Util::disconnect();