vmware / pyvmomi-community-samples

A place for community contributed samples for the pyVmomi library.
Apache License 2.0
1.01k stars 922 forks source link

vApp properties set during OVA deployment are not applied #691

Open adan-zuniga opened 2 years ago

adan-zuniga commented 2 years ago

Describe the bug

I'm deploying a Cisco Expressway appliance from OVA. The ova allows to configure IP, Hostname, NTP, etc settings via vApp Settings. I've tried to set those settings in two different ways, but when I power the VM on, I notice that the settings have not been applied. I tried deploying the VM manually on ESXi, and the settings do get applied.

How do I properly set those settings and have them applied to the guest VM?

def parse_descriptor():
    # p = ovf_manager.ParseDescriptor(ovf_handle.get_descriptor(), vim.OvfManager.ParseDescriptorParams(locale='en-US'))
    pars = ovf_manager.ParseDescriptor(ovf_handle.get_descriptor(), vim.OvfManager.ParseDescriptorParams(locale='en-US'))
    properties = []
    for p in pars.property:
        match p.id:
            case 'ip4.address':
                v = '10.0.1.200'
            case 'ip4.netmask':
                v = '255.255.255.0'
            case 'ip4.gateway':
                v = '10.0.1.1'
            case 'system.hostname':
                v = args.vm_name
            case 'domain.name':
                v = 'args.domainname'
            case 'ntp.servers':
                v = '10.0.1.20'
            case 'default.dns':
                v = '10.0.1.20'
            case 'system.timezone':
                v = 'America/Chicago'
            case _:
                continue
        properties.append(vim.KeyValue(key=p.id, value=v))

    return properties

if __name__ == '__main__':

    args = ESXi()
    si = service_instance.connect(args)
    dc = get_dc(args, si)
    rp = get_resource_pool(args, si, dc)
    data_store = get_data_store(args, dc)
    network = get_net_mappings(args, dc)
    ovf_handle = OvfHandler(args.ova_path)
    interface = get_net_ints(ovf_handle.get_descriptor())
    ovf_manager = si.content.ovfManager
    prop = parse_descriptor()
    cisp = vim.OvfManager.CreateImportSpecParams(
        diskProvisioning=args.disk_provision,  # diskProvisioning (thin/thick/sparse/etc)
        entityName=args.vm_name,
        # hostSystem='',
        networkMapping=[vim.OvfManager.NetworkMapping(name=interface, network=network)],
        deploymentOption=args.deployment,
        propertyMapping=prop,
    )
    cisr = ovf_manager.CreateImportSpec(
        ovfDescriptor=ovf_handle.get_descriptor(),
        resourcePool=rp,
        datastore=data_store,
        cisp=cisp
    )

    vm_import_spec = cisr.importSpec
    vm_config_spec = vm_import_spec.configSpec
    vap_config = vm_config_spec.vAppConfig

    new_configSpec = vim.vApp.VmConfigSpec()

    for config in vap_config.property:
        # print(config.info.id)
        operation = 'add'
        match config.info.id:
            case 'ip4.address':
                propSpec = vim.vApp.PropertySpec()
                propSpec.operation = operation
                propSpec.info = config.info
                propSpec.info.value = '10.0.1.200'
                new_configSpec.property.append(propSpec)
                config.info.value = '10.0.1.200'
            case 'ip4.netmask':
                propSpec = vim.vApp.PropertySpec()
                propSpec.operation = operation
                propSpec.info = config.info
                propSpec.info.value = '255.255.255.0'
                new_configSpec.property.append(propSpec)
                config.info.value = '255.255.255.0'
            case 'ip4.gateway':
                propSpec = vim.vApp.PropertySpec()
                propSpec.operation = operation
                propSpec.info = config.info
                propSpec.info.value = '10.0.1.1'
                new_configSpec.property.append(propSpec)
                config.info.value = '10.0.1.1'
            case 'system.hostname':
                propSpec = vim.vApp.PropertySpec()
                propSpec.operation = operation
                propSpec.info = config.info
                propSpec.info.value = args.vm_name
                new_configSpec.property.append(propSpec)
                config.info.value = args.vm_name
            case 'domain.name':
                propSpec = vim.vApp.PropertySpec()
                propSpec.operation = operation
                propSpec.info = config.info
                propSpec.info.value = 'args.domainname'
                new_configSpec.property.append(propSpec)
                config.info.value = 'args.domainname'
            case 'ntp.servers':
                propSpec = vim.vApp.PropertySpec()
                propSpec.operation = operation
                propSpec.info = config.info
                propSpec.info.value = '10.0.1.20'
                new_configSpec.property.append(propSpec)
                config.info.value = '10.0.1.20'
            case 'default.dns':
                propSpec = vim.vApp.PropertySpec()
                propSpec.operation = operation
                propSpec.info = config.info
                propSpec.info.value = '10.0.1.20'
                new_configSpec.property.append(propSpec)
                config.info.value = '10.0.1.20'
            case 'system.timezone':
                propSpec = vim.vApp.PropertySpec()
                propSpec.operation = operation
                propSpec.info = config.info
                propSpec.info.value = 'America/Chicago'
                new_configSpec.property.append(propSpec)
                config.info.value = 'America/Chicago'
            case _:
                propSpec = vim.vApp.PropertySpec()
                propSpec.operation = operation
                propSpec.info = config.info
                new_configSpec.property.append(propSpec)

    # cisr.importSpec.configSpec.vAppConfig = new_configSpec
    if cisr.error:
        print("The following errors will prevent import of this OVA:")
        for error in cisr.error:
            print(f'{error}')
            exit()
    else:
        ovf_handle.set_spec(cisr)
        lease = rp.ImportVApp(spec=cisr.importSpec, folder=dc.vmFolder)
        deploy_to_vmware(vmware_lease=lease, ovf__handle=ovf_handle)

Reproduction steps

Running the above code.

Expected behavior

When The VM is powered on, the console should prompt for root and admin password, not the IP settings.

Additional context

No response

mcondon3 commented 2 years ago

This seems to be the same issue I asked about recently. Hopefully we can get a response!