VMware {code} Community
eslatts11
Contributor
Contributor

Trying to create a script that will reconfigure RDM's and IP's of a VM running RHEL

Hello,

In my current solution, for disaster recovery I SRDF our VM's  datastore's to my offsite location. Before the VM's can boot up the raw device mapping's need to be re-mapped (somehow the RDM's do not carry over through SRDF and are not recognized as RDM's but as Virtual Disk), then they need to be re-IP'd to match the network at the offsite location. I was able to manage this task within the PowerCLI plugin for PowerShell (only windows), however I would like to be able to run this on a Linux server. vShpere SDK for Perl seemed to be the best option. I've been able to run many of the basic scripts that come with the installation; however, my Perl coding abilities are far limited and was wondering if someone could help me write a script that would configure both the RDM's and re-IP'ing.

Thanks,

eslatts

4 Replies
eslatts11
Contributor
Contributor

To shed some light on this topic, I will post some of the Perl coding that should work in theory, but keeps throwing a "InvalidDeviceBacking":

# Using sub-script VMUtil

use AppUtil::VMUtil;

#Task being accomplished

Util::connect();

create_virtualdisk();

Util::disconnect();

# Snapshot of the creat_virtualdisk sub-script

sub create_virtualdisk {

   my %filter_hash = create_hash(Opts::get_option('ipaddress'),

                                 Opts::get_option('powerstatus'),

                                 Opts::get_option('guestos'));

   my $vm_views = VMUtils::get_vms ('VirtualMachine',

                                    Opts::get_option ('vmname'),

                                    Opts::get_option ('datacenter'),

                                    Opts::get_option ('folder'),

                                    Opts::get_option ('pool'),

                                    Opts::get_option ('host'),

                                    %filter_hash);

   # bug 418090

   if ((defined $vm_views) && (@$vm_views > 1)) {

      my $vm = Opts::get_option ('vmname');

      Util::trace(0, "\nVirtual machine <$vm> not uniquely identified.\n");

      return;

   }

   foreach (@$vm_views) {

      my $hostname;

      if(defined $_->runtime->host) {

         my $host_view = Vim::get_view(mo_ref => $_->runtime->host);

         $hostname = $host_view->name;

      }

      # bug 418095

      my $controller = VMUtils::find_scsi_controller_device(vm => $_);

      my $controllerKey = $controller->key;

      my $unitNumber = $#{$controller->device} + 1;

     

      my $size = Opts::get_option ('disksize') * 1024;

      my $diskMode = VMUtils::get_diskmode(nopersist => Opts::get_option ('nopersist'),

                                  independent => Opts::get_option ('independent'));

      my $fileName = VMUtils::generate_filename(vm => $_,

                                       filename => Opts::get_option ('filename'));

      Util::trace(0,"\nAdding Virtual Disk on Virtual machine " . $_->name

                    . " in the host " . $hostname ."\n");

# Calls sub-script get_vdisk_spec inside of VMUtil

      my $devspec = VMUtils::get_vdisk_spec(vm => $_,

                             backingtype => Opts::get_option ('backingtype'),

                             diskMode => $diskMode,

                             fileName => $fileName,

                             controllerKey => $controllerKey,

                             unitNumber => $unitNumber,

                             size => $size);

                            

# This calls the add_virtualdisk from VMUtil

      VMUtils::add_virtualdisk(vm => $_,

                               devspec => $devspec);

   }

}

#Snapshot of get_vdisk_spec sub-script

sub get_vdisk_spec {

   my %args = @_;

   my $vm = $args{vm};

   my $diskMode = $args{diskMode};

   my $fileName = $args{fileName};

   my $controllerKey = $args{controllerKey};

   my $unitNumber = $args{unitNumber};

   my $size = $args{size};

   my $backingtype = $args{backingtype};

   my $disk_backing_info;

   if($backingtype eq "regular") {

      $disk_backing_info = VirtualDiskFlatVer2BackingInfo->new(diskMode => $diskMode,

                                                               fileName => $fileName);

   }

   #Require a non-ESX physical disk

   elsif($backingtype eq "rdm") {

      my $host_view;

      if(defined $vm->runtime->host) {

         $host_view = Vim::get_view(mo_ref => $vm->runtime->host);

      }

      else {

         Util::trace(0,"No host found for the virtual machine");

         return;

      }     

      my $host_storage_system = $host_view->config;

      my $lunId = $host_storage_system->storageDevice->scsiLun->[0]->uuid; 

      my $deviceName = $host_storage_system->storageDevice->scsiLun->[0]->deviceName;

# This is where device path, lun id, and the file name get passed in

      $disk_backing_info = VirtualDiskRawDiskMappingVer1BackingInfo->new(compatibilityMode => "physical",

                                                                         deviceName => $deviceName,

                                                                         lunUuid => $lunId,

                                                                         fileName => $fileName);

   }

   else {

      Util::trace(0,"Invalid Disk Backing Info Specified");

      return;

   }

   my $disk = VirtualDisk->new(controllerKey => $controllerKey,

                               unitNumber => $unitNumber,

                               key => -1,

                               backing => $disk_backing_info,

                               capacityInKB => $size);

   my $devspec = VirtualDeviceConfigSpec->new(operation => VirtualDeviceConfigSpecOperation->new('add'),

                                              device => $disk,

                                              fileOperation => VirtualDeviceConfigSpecFileOperation->new('create'));

   return $devspec;

}

# add_vitural disk - grabs the specs out of $devspec and tried to create the VM

# This is where im getting the "InvalidDeviceBacking" error which Returns the elsif "Incompatible device backing specified for device" shown below

sub add_virtualdisk {

   my %args = @_;

   my $vm = $args{vm};

   my $devspec = $args{devspec};

  

   my $vmspec = VirtualMachineConfigSpec->new(deviceChange => [$devspec] );

   eval {

#When I comment out these next two lines I do not receive the error

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

      Util::trace(0,"Virtual Disk created.\n");

   };

   if ($@) {

      if (ref($@) eq 'SoapFault') {

         if (ref($@->detail) eq 'FileAlreadyExists') {

            Util::trace(0,"Operation failed because file already exists.");

         }

         elsif (ref($@->detail) eq 'InvalidName') {

            Util::trace(0,"If the specified name is invalid.");

         }

         elsif (ref($@->detail) eq 'InvalidDeviceBacking') {

            Util::trace(0,"Incompatible device backing specified for device.");

         }

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

            Util::trace(0,"Invalid backing info spec.");

         } 

         elsif (ref($@->detail) eq 'InvalidPowerState') {

            Util::trace(0,"Attempted operation cannot be performed on the current state.");

         }

         elsif (ref($@->detail) eq 'GenericVmConfigFault') {

            Util::trace(0,"Unable to configure virtual device.");

         }

         elsif (ref($@->detail) eq 'NoDiskSpace') {

            Util::trace(0,"Insufficient disk space on datastore.");

         }

         else {

            Util::trace(0,"Falut : " . $@);

         }

      }

      else {

         Util::trace(0,"Falut : " . $@);

      }

   }

}

-What I am guessing is what ever data gets passed into $devspec is the incorrect format which is why I am getting the error. I've tried specifying the $devicename and $LunUuid but nothing works.

Thanks,

eslatts

Reply
0 Kudos
stumpr
Virtuoso
Virtuoso

Interesting, I had a project identical to this a while back but was required to use PowerCLI instead of Perl.  I found several bugs around RDMs with the PowerCLI cmdlets that required using the more low level API access to fix.

The invalid backing errors can be cryptic.  Can you look at your vpxd.log file on your vCenter server?  You can usually get more detail (usually the specific property that's causing the error).

If not, add --verbose to the command line options of your script and save the XML output.  If you post it up here, I can review it to see if anything sticks out.

- Reuben

Reuben Stump | http://www.virtuin.com | @ReubenStump
eslatts11
Contributor
Contributor

Hi Reuben,

Ran the command with verbose and attached is the ouput.txt. I changed hostnames/IPs/usraccs/pws for sake of privacy.

Creating RDM's through any CLI is incredibly cryptic.

Thanks,

eslatts

Reply
0 Kudos
stumpr
Virtuoso
Virtuoso

It is cryptic Smiley Happy

I looked through the XML, nothing sticks out (but it's hard to pick out non-obvious errors).  Were you able to look at the vpxd.log file on the vC server?  That usually reports in more detail which specific property is causing the error.

Reuben Stump | http://www.virtuin.com | @ReubenStump
Reply
0 Kudos