vmware / pyvmomi

VMware vSphere API Python Bindings
Apache License 2.0
2.21k stars 767 forks source link

How do I create NIC with static IP? #461

Open habakook opened 8 years ago

habakook commented 8 years ago

I have a VM with no NIC and it is powered off. When I execute the following code:

import atexit
import time
import ssl 
from pyVim import connect
from pyVmomi import vim, vmodl

# Disabling SSL certificate verification 
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) 
context.verify_mode = ssl.CERT_NONE 

inputs = {'vcenter_ip': '10.7.32.119',
          'vcenter_password': 'password',
          'vcenter_user': 'root',
          'vm_name' : 'myName',
          'isDHCP' : False,
          'vm_ip' : '10.7.42.91',
          'subnet' : '255.255.255.0',
          'gateway' : '10.7.42.40',
          'dns' : ['company.com', 'company.com'],
          'domain' : 'esx10g.company.com'
          }

def get_obj(content, vimtype, name):
    obj = None
    container = content.viewManager.CreateContainerView(content.rootFolder, vimtype, True)
    for c in container.view:
        if c.name == name:
            obj = c
            break
    return obj

def add_nic(vm, network):
    spec = vim.vm.ConfigSpec()

    # add Switch here
    dev_changes = []
    switch_spec                = vim.vm.device.VirtualDeviceSpec()
    switch_spec.operation      = vim.vm.device.VirtualDeviceSpec.Operation.add
    switch_spec.device         = vim.vm.device.VirtualVmxnet3()

    switch_spec.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo()
    switch_spec.device.backing.useAutoDetect = False
    switch_spec.device.backing.deviceName = network.name
    switch_spec.device.backing.network = network
    switch_spec.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo()
    switch_spec.device.connectable.startConnected = True
    switch_spec.device.connectable.connected = True

    dev_changes.append(switch_spec)

    spec.deviceChange = dev_changes
    output = vm.ReconfigVM_Task(spec=spec)
    time.sleep(2)
    print output.info

def wait_for_task(task, actionName='job', hideResult=False):
    """
    Waits and provides updates on a vSphere task
    """

    while task.info.state == vim.TaskInfo.State.running or task.info.state == vim.TaskInfo.State.queued:
        time.sleep(2)

    if task.info.state == vim.TaskInfo.State.success:
        if task.info.result is not None and not hideResult:
            out = '%s completed successfully, result: %s' % (actionName, task.info.result)
            print out
        else:
            out = '%s completed successfully.' % actionName
            print out
    else:
        out = '%s did not complete successfully: %s' % (actionName, task.info.error)
        print out
        raise task.info.error #error happens here

    return task.info.result

def ip_assign(vm):
    adaptermap = vim.vm.customization.AdapterMapping()
    globalip = vim.vm.customization.GlobalIPSettings()
    adaptermap.adapter = vim.vm.customization.IPSettings()

    """Static IP Configuration"""
    adaptermap.adapter.ip = vim.vm.customization.FixedIp()
    adaptermap.adapter.ip.ipAddress = inputs['vm_ip']
    adaptermap.adapter.subnetMask = inputs['subnet']
    adaptermap.adapter.gateway = inputs['gateway']  
    globalip.dnsServerList = inputs['dns']

    adaptermap.adapter.dnsDomain = inputs['domain']

    # Hostname settings
    ident = vim.vm.customization.LinuxPrep()
    ident.domain = inputs['domain']
    ident.hostName = vim.vm.customization.FixedName()
    ident.hostName.name = inputs['vm_name']

    customspec = vim.vm.customization.Specification()
    customspec.nicSettingMap = [adaptermap]
    customspec.globalIPSettings = globalip
    customspec.identity = ident

    print "Reconfiguring VM Networks . . ."
    task = vm.Customize(spec=customspec)

    # Wait for Network Reconfigure to complete
    wait_for_task(task, "config task") #error happens here

if __name__ == '__main__':
    service_instance = connect.SmartConnect(host=inputs['vcenter_ip'], user=inputs['vcenter_user'], pwd=inputs['vcenter_password'], sslContext=context)
    atexit.register(connect.Disconnect, service_instance)

    content = service_instance.RetrieveContent()
    vm = get_obj(content, [vim.VirtualMachine], inputs['vm_name'])
    network = get_obj(content, [vim.Network], "DMZ")

    add_nic(vm, network)
    ip_assign(vm) #error happens here

NIC gets created but on assigning IP it gets an error:

Reconfiguring VM Networks . . .
config task did not complete successfully: (vmodl.fault.NotSupported) {
   dynamicType = <unset>,
   dynamicProperty = (vmodl.DynamicProperty) [],
   msg = 'The operation is not supported on the object.',
   faultCause = <unset>,
   faultMessage = (vmodl.LocalizableMessage) []
}
Traceback (most recent call last):
  File "test2.py", line 124, in <module>
    ip_assign(vm)
  File "test2.py", line 111, in ip_assign
    wait_for_task(task, "config task")
  File "test2.py", line 77, in wait_for_task
    raise task.info.error
pyVmomi.VmomiSupport.NotSupported: (vmodl.fault.NotSupported) {
   dynamicType = <unset>,
   dynamicProperty = (vmodl.DynamicProperty) [],
   msg = 'The operation is not supported on the object.',
   faultCause = <unset>,
   faultMessage = (vmodl.LocalizableMessage) []
}

What am I missing? What am I doing wrong? How do I create a new NIC with static IP assigned?

Would much appreciate any help! @jm66 @Ctesias @rreubenur @thedeco @tianhao64 @snobear @ciorceri @sitle @bsherman @czee

OscarLopezEns commented 7 years ago

Hi, @habakook did you ever get a solution for your issue?

I am having this issue as well when creating a NIC for a Windows machine. When trying to assign a static ip, a NIC gets created but the static ip, netmask and gateway details I provide get ignored by vcenter. Any idea why static ip is not working?

Thanks!

uddyan92 commented 6 years ago

Hi guys ,i am struggling to fix that ip address issue ,any updates on the above :)

uddyan92 commented 6 years ago

@prziborowski any fix on this?

prziborowski commented 6 years ago

I haven't been able to hit this NotSupported exception. I hit a flurry of other issues, such as the dnsServerList should be IP addresses and not domain names and the hostName uses the VM name and depending on that name, it might not be valid as a hostName. (example case it is valid though). [And if the VM doesn't have tools installed, then it will get a different/confusing fault about being an UncustomizableGuest].

I didn't look into the Windows side since no sample is provided for that. When I tried the script on an ubuntu VM, after updating the dnsServerList and hostname, it worked fine and was configured as expected.

habakook commented 6 years ago

I found the solution. But I don't have it available now, because I left that company 8 months ago (they have the source code). Sorry, can't help you, but can assure you that it is doable.

reubenur-rahman commented 6 years ago
  1. Make sure vmware tools is running and up to date.
  2. Make sure guest OS is supported by vmware https://partnerweb.vmware.com/programs/guestOS/guest-os-customization-matrix.pdf
  3. For linux use vim.vm.customization.LinuxPrep()
  4. For windows use vim.vm.customization.Sysprep() and make sure you have the sysprep files. Have a look at this link https://communities.vmware.com/message/934733#934733
shubham893 commented 6 years ago

@uddyan92 @prziborowski @rreubenur I am also getting similar issue. I am doing it by connecting directly to an ESXi host instead of vcenter server. Do you think that may be the issue??

prziborowski commented 6 years ago

@shubham893 The guest customization is handled through vCenter Server, so if you try it directly to the ESXi host, I believe you'd get an error.

shubham893 commented 6 years ago

@prziborowski due to some issues i can not get vCenter server credentials, is there any other way to provide static ip address to vm? I am deploying vm by deploy_ovf.py file. But all deployed vm's have same ip address. So, is there any way to provide those vm different ip address by python script?

13052477839 commented 6 years ago

this is my solution,i hope it can help

def customeWin(customizationSpec, customeInfo):

"adapter map" no idea wtf this is

guest_map = vim.vm.customization.AdapterMapping()
guest_map.adapter = vim.vm.customization.IPSettings()
guest_map.adapter.ip = vim.vm.customization.FixedIp()
guest_map.adapter.ip.ipAddress = customeInfo.ip  # hard coded for now
guest_map.adapter.subnetMask = customeInfo.subnetMask  # ditto
guest_map.adapter.gateway = customeInfo.gateway  # ditto
guest_map.adapter.dnsServerList = customeInfo.dnsServerList  # ditto

# DNS settings
globalip = vim.vm.customization.GlobalIPSettings()
globalip.dnsServerList = customeInfo.dnsServerList

# Hostname settings
ident = vim.vm.customization.Sysprep()
ident.guiUnattended = vim.vm.customization.GuiUnattended()
ident.guiUnattended.autoLogon = True  # the machine does not auto-logon
ident.guiUnattended.password = vim.vm.customization.Password()
ident.guiUnattended.password.value = 'test@1234'
ident.guiUnattended.password.plainText = True  # the password is not encrypted
ident.guiUnattended.timeZone = 210
ident.guiUnattended.autoLogonCount = 1

ident.userData = vim.vm.customization.UserData()
ident.userData.fullName = "My Name"
ident.userData.orgName = "Company"
ident.userData.computerName = vim.vm.customization.FixedName()
ident.userData.computerName.name = 'vmtest'
ident.userData.productId = ''
# ident.userData.productId = '489J6-VHDMP-X63PK-3K798-CPX3Y'
# join domain
ident.identification = vim.vm.customization.Identification()
# ident.identification.joinWorkgroup = ''
# ident.identification.joinDomain = ''
# ident.identification.domainAdmin = ''
# ident.identification.domainAdminPassword = vim.vm.customization.Password()
# ident.identification.domainAdminPassword.value=''
# ident.identification.domainAdminPassword.plainText = True
#

# create spec to change host IP address
# customspec = vim.vm.customization.Specification()
customizationSpec.nicSettingMap = [guest_map]
customizationSpec.globalIPSettings = globalip
customizationSpec.identity = ident
sumeersinha commented 6 years ago

In addition to the above post, static ip assignment for windows works provided VMware Tools is running. Also at first the windows vm might get some random dhcp ip when powered ON and then eventually when sysprep runs, you should see the static IP on the NICs.

FraGOuT commented 6 years ago

@shubham893 Hey did you find a work around for this? Even I am connecting directly to an ESXi

Sad-polar-bear commented 5 years ago

I haven't been able to hit this NotSupported exception. I hit a flurry of other issues, such as the dnsServerList should be IP addresses and not domain names and the hostName uses the VM name and depending on that name, it might not be valid as a hostName. (example case it is valid though). [And if the VM doesn't have tools installed, then it will get a different/confusing fault about being an UncustomizableGuest].

I didn't look into the Windows side since no sample is provided for that. When I tried the script on an ubuntu VM, after updating the dnsServerList and hostname, it worked fine and was configured as expected.

I use this way in Centos 7.x,it always except not valid param spec.identity.hostName.Did you solved it? Thanks