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
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);
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
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
It is cryptic
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.