3

I've found pyvmomi examples on how to add a disk to an already existing VM, but I would like to customize the VM template and then clone. Setting the CPUs and memory are pretty straight forward, but the adding of one or more disks to an existing template, asides from the boot disk, eludes me.

# Add an additional 200 GB disk
new_disk_kb = int(20) * 1024 * 1024
disk_spec = vim.vm.device.VirtualDeviceSpec()
disk_spec.fileOperation = "create"
disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
disk_spec.device = vim.vm.device.VirtualDisk()
disk_spec.device.backing = vim.vm.device.VirtualDisk.RawDiskMappingVer1BackingInfo()
disk_spec.device.backing.diskMode = 'persistent'
disk_spec.device.unitNumber = 3
disk_spec.device.capacityInKB = new_disk_kb

# vm configuration
vmconf = vim.vm.ConfigSpec()
vmconf.numCPUs = 8            # change the template's cpus from 4 to 8
vmconf.memoryMB = 16 * 1024   # change the template's memory from 4 GB to 16 GB
# change the template's disks from
#    1 250 GB boot, 1 x 200 GB disk
# to 
#    1 250 gB boot, 2 x 200 GB disks
vmconf.deviceChange = [ disk_spec ]  # something is not right
                               
clonespec = vim.vm.CloneSpec()
clonespec.location = relospec
clonespec.powerOn = True
clonespec.config = vmconf
clonespec.customization = customspec
task = template.Clone(folder = destfolder, name = vmname, spec = clonespec)

The code works without the vmconf.deviceChange. Once I try to add a disk I see the error

Invalid configuration for device '0'.

or

Incompatible device backing specified for device '0'.
snakecharmerb
  • 47,570
  • 11
  • 100
  • 153
user2569618
  • 517
  • 3
  • 16
  • 42
  • What does this mean? `The code works without the vmconf.deviceChange. Once I try to add a disk I see the error`. How does it work? – Life is complex Aug 18 '21 at 01:01
  • If you remove/comment out the vmconf.deviceChange line, the code will add the cpus and mem without an error. Try to add the disk, the code fails with the aforementioned error. – user2569618 Aug 18 '21 at 20:36

5 Answers5

3

This question has multiple moving parts including creating a template, modifying a template and cloning the VM.

Let's tackle the easiest issue first. This part of your code is incorrect:

new_disk_kb = int(20) * 1024 * 1024
disk_spec = vim.vm.device.VirtualDeviceSpec()
disk_spec.fileOperation = "create"
disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
disk_spec.device = vim.vm.device.VirtualDisk()
disk_spec.device.backing = vim.vm.device.VirtualDisk.RawDiskMappingVer1BackingInfo()
disk_spec.device.backing.diskMode = 'persistent'
disk_spec.device.unitNumber = 3
disk_spec.device.capacityInKB = new_disk_kb

After reviewing multiple pyvmomi samples scripts I can see that you're not setting the unitNumber correctly. Based on these scripts you need to determine the number of disks and assign the next unitNumber available, which I would assume in your case is 2 and not 3.

The code below was extracted from the add raw disk to vm pyvmomi script.

spec = vim.vm.ConfigSpec()
# get all disks on a VM, set unit_number to the next available
unit_number = 0
controller = None
for device in vm.config.hardware.device:
    if hasattr(device.backing, 'fileName'):
        unit_number = int(device.unitNumber) + 1
        # unit_number 7 reserved for scsi controller
        if unit_number == 7:
            unit_number += 1
        if unit_number >= 16:
            print("we don't support this many disks")
            return -1
    if isinstance(device, vim.vm.device.VirtualSCSIController):
        controller = device
if controller is None:
    print("Disk SCSI controller not found!")
    return -1
disk_spec = vim.vm.device.VirtualDeviceSpec()
disk_spec.fileOperation = "create"
disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
disk_spec.device = vim.vm.device.VirtualDisk()
rdm_info = vim.vm.device.VirtualDisk.RawDiskMappingVer1BackingInfo()
disk_spec.device.backing = rdm_info
disk_spec.device.backing.compatibilityMode = disk_compatibility_mode
disk_spec.device.backing.diskMode = disk_mode
# The device_name will look something like
#     /vmfs/devices/disks/naa.41412340757396001d7710df0fdd22a9
disk_spec.device.backing.deviceName = device_name
disk_spec.device.unitNumber = unit_number
disk_spec.device.controllerKey = controller.key
spec.deviceChange = [disk_spec]

Concerning the other problems that you want to tackle. There are several pyvmomi script that could be useful. One in particular is Clone VM, which provides details on cloning a VM from a template, which you're trying to create.

I'm not sure how useful that script would be, because it seems that you're looking for a complete solution to solve your use case.

I would recommend looking at this old Github project, which has lots of useful code for creating a template, modifying a template and cloning a VM.

Concerning your comments about using an existing template that already has one disk (boot disk) and adding a secondary disk during the cloning process.

Based on my interpretation on the VM Documentation I currently don't think this is possible and where is why:

  1. A VM template is a master copy image of a virtual machine that includes VM disks, virtual devices, and settings. This template can be use in the VM cloning process. This template is static and should be considered a configuration baseline.

  2. This template cannot be modify during the cloning process. If this static template needs to be modified for any reason than it needs to be recreated with the new additions. This means that the original template needs to be converted into a VM, this VM needs to be edited, and then convert back into a new template.

If this isn't possible you can clone the baseline template on a new VM and use one of the pyvmomi add disks scripts to enable a new disk on your VM.

I don't know your exact use case, but I think recreating the template is the logical choice, but your use case might work better with creating the new disk after cloning.

That GitHub project that I previously mentioned is using a baseline template for cloning a VM and it also has an addDisks function. The latter is used to add a new disk to the VM that was created during the cloning process.

Here is an older pyvmomi issue where someone wanted to modify a disk related to a template being cloned. It was recommended that the OP perform this task in the post-clone process.

That GitHub project shows how to use a baseline template and modify the VMs configuration as needed. From the code it seems that it is using CloneSpec() to modify the VM during the cloning process and not the post-clone process.

Life is complex
  • 15,374
  • 5
  • 29
  • 58
  • I do have a template. I am using the Clone VM. I can configure the cpu and the mem during the clone. I can add a disk after the VM is in the connected state courtesy of the pymomi add_disk script. What I trying to do is add a disk during the clone. – user2569618 Aug 23 '21 at 23:11
  • So you want to add a disk during the clone process. I don't that this is possible, but let me confirm that for you. – Life is complex Aug 23 '21 at 23:52
  • 1
    Assume the template already has one disk, the boot disk. – user2569618 Aug 23 '21 at 23:53
  • After looking at this issue again this morning, I think that your best course of action is to follow the code in that GitHub project. It seems to be doing what you are trying to accomplish. – Life is complex Aug 24 '21 at 14:55
  • Which is adding the disk(s) after the VM has been cloned. There should be a way to change the configuration (e.g. add disks) while the template is being cloned. The code appears to be there. I just haven't figured out the right incantation. Hence, the request for help. – user2569618 Aug 24 '21 at 16:54
1

I just ran into this exact issue adding RDM disks to a vm.

The problem is:

disk_spec.device.backing = vim.vm.device.VirtualDisk.RawDiskMappingVer1BackingInfo()

You need to provide backing.deviceName and backing.lunUuid to your spec. After that it'll work. I am confident because I saw the exact same error message and it fixed it for me.

You get the lun uuid and deviceName from host.config.storageDevice.scsiLun for the lun you're interested in.

  • This does not really answer the question. If you have a different question, you can ask it by clicking [Ask Question](https://stackoverflow.com/questions/ask). To get notified when this question gets new answers, you can [follow this question](https://meta.stackexchange.com/q/345661). Once you have enough [reputation](https://stackoverflow.com/help/whats-reputation), you can also [add a bounty](https://stackoverflow.com/help/privileges/set-bounties) to draw more attention to this question. – Cyril Jouve Aug 28 '21 at 10:15
  • 1
    It does answer the question, because I had the exact same issue with the exact same error message and i've been using pyvmomi for years. This answer is also available on the pyvmomi project page. – GuestyGuesskins Sep 02 '21 at 23:04
  • This is the correct answer. If you take the defaults you'll get the described error message. See this: https://github.com/vmware/pyvmomi/issues/542 – calvin Sep 02 '21 at 23:13
0

The errors which you're getting seem to indicate that you need to fix the unit_number. Keep in mind that 7 is reserved for the scsi controller and 16 is the maximum supported number of disks by VMWare (view sample code).

micmalti
  • 561
  • 3
  • 16
0

I am not familiar with the pyvmomi tool, but it seems to me that the disk ought to be attached to a controller. The UnitNumber makes no sense if there is no controller to supply the unit.

When associating virtual devices with default devices, the controllerKey property should be reset with the key property of the controller [ here ]

Can you try the above association? (Sorry, I am not quite sure if you should use vmconf or clonespec.config)

controller = next( \
 (device for device in vmconf.hardware.device \
     if isinstance(device, vim.vm.device.VirtualSCSIController) \
 ), None)
disk_spec.device.controllerKey = controller.key
LSerni
  • 55,617
  • 10
  • 65
  • 107
0

The problem seem to be in the following part of the code:

# Add an additional 200 GB disk
new_disk_kb = int(20) * 1024 * 1024
disk_spec = vim.vm.device.VirtualDeviceSpec()
disk_spec.fileOperation = "create"
disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
disk_spec.device = vim.vm.device.VirtualDisk()
disk_spec.device.backing = vim.vm.device.VirtualDisk.RawDiskMappingVer1BackingInfo()
disk_spec.device.backing.diskMode = 'persistent'
disk_spec.device.unitNumber = 2
disk_spec.device.capacityInKB = new_disk_kb

If the VM already has a disk, the boot disk, then the unitNumber should start at 2.

user2569618
  • 517
  • 3
  • 16
  • 42
  • That is exactly what I stated in my answer. ref: "Based on these scripts you need to determine the number of disks and assign the next unitNumber available, which I would assume in your case is 2 and not 3." – Life is complex Aug 24 '21 at 17:00
  • There something else going on that I'm not seeing. Regardless if the unit number is set to 0, 1, 2, or 3, the error is basically the same. – user2569618 Aug 24 '21 at 21:53
  • See actual answer below this one. – calvin Aug 28 '21 at 07:31
  • That answer is for after the VM has been cloned. I'm looking for how to add disks while the template is being cloned. – user2569618 Aug 30 '21 at 16:08
  • @user2569618 As I previously stated in my answer. The GitHub project is doing exactly what you are asking to do. The clone function code between lines 176 and 446 within the script `ezmomi.py` couldn't be more clearly in what it's doing. I'm still confused on why my answer didn't solve your issue. – Life is complex Aug 31 '21 at 16:58
  • Also you need to share more of your code, because you only provided a snippet. The problem in the snippet share was solved by my answer. – Life is complex Aug 31 '21 at 17:05
  • Here's the answer: https://github.com/vmware/pyvmomi/issues/542. You can't take the defaults for backingInfo despite what the docs say. – calvin Sep 02 '21 at 23:16