docs: def create_vm(client, name, compute_resource, datastore, disksize, nics,
                memory, num_cpus, guest_id, host=None):
      """Create a virtual machine using the specified values.
  
      :param name: The name of the VM to create.
      :type name: str
      :param compute_resource: The name of a ComputeResource in which to \
              create the VM.
      :type compute_resource: str
      :param datastore: The name of the datastore on which to create the VM.
      :type datastore: str
      :param disksize: The size of the disk, specified in KB, MB or GB. e.g. \
              20971520KB, 20480MB, 20GB.
      :type disksize: str
      :param nics: The NICs to create, specified in a list of dict's which \
              contain a "network_name" and "type" key. e.g. \
              {"network_name": "VM Network", "type": "VirtualE1000"}
      :type nics: list of dict's
      :param memory: The amount of memory for the VM. Specified in KB, MB or \
              GB. e.g. 2097152KB, 2048MB, 2GB.
      :type memory: str
      :param num_cpus: The number of CPUs the VM will have.
      :type num_cpus: int
      :param guest_id: The vSphere string of the VM guest you are creating. \
              The list of VMs can be found at \
          http://pubs.vmware.com/vsphere-50/index.jsp?topic=/com.vmware.wssdk.apiref.doc_50/right-pane.html
      :type guest_id: str
      :param host: The name of the host (default: None), if you want to \
              provision the VM on a \ specific host.
      :type host: str
  
      """
      print("Creating VM %s" % name)
      # If the host is not set, use the ComputeResource as the target
      if host is None:
          target = client.find_entity_view("ComputeResource",
                                        filter={"name": compute_resource})
          resource_pool = target.resourcePool
      else:
          target = client.find_entity_view("HostSystem", filter={"name": host})
          resource_pool = target.parent.resourcePool
  
      disksize_pattern = re.compile("^\d+[KMG]B")
      if disksize_pattern.match(disksize) is None:
          print("Disk size %s is invalid. Try \"12G\" or similar" % disksize)
          sys.exit(1)
  
      if disksize.endswith("GB"):
          disksize_kb = int(disksize[:-2]) * 1024 * 1024
      elif disksize.endswith("MB"):
          disksize_kb = int(disksize[:-2]) * 1024
      elif disksize.endswith("KB"):
          disksize_kb = int(disksize[:-2])
      else:
          print("Disk size %s is invalid. Try \"12G\" or similar" % disksize)
  
      memory_pattern = re.compile("^\d+[KMG]B")
      if memory_pattern.match(memory) is None:
          print("Memory size %s is invalid. Try \"12G\" or similar" % memory)
          sys.exit(1)
  
      if memory.endswith("GB"):
          memory_mb = int(memory[:-2]) * 1024
      elif memory.endswith("MB"):
          memory_mb = int(memory[:-2])
      elif memory.endswith("KB"):
          memory_mb = int(memory[:-2]) / 1024
      else:
          print("Memory size %s is invalid. Try \"12G\" or similar" % memory)
  
      # A list of devices to be assigned to the VM
      vm_devices = []
  
      # Create a disk controller
      controller = create_controller(client, "VirtualLsiLogicController")
      vm_devices.append(controller)
  
      ds_to_use = None
      for ds in target.datastore:
          if ds.name == datastore:
              ds_to_use = ds
              break
  
      if ds_to_use is None:
          print("Could not find datastore on %s with name %s" %
                (target.name, datastore))
          sys.exit(1)
  
      # Ensure the datastore is accessible and has enough space
      if ds_to_use.summary.accessible is not True:
          print("Datastore (%s) exists, but is not accessible" %
                ds_to_use.summary.name)
          sys.exit(1)
      if ds_to_use.summary.freeSpace < disksize_kb * 1024:
          print("Datastore (%s) exists, but does not have sufficient"
                " free space." % ds_to_use.summary.name)
          sys.exit(1)
  
      disk = create_disk(client, datastore=ds_to_use, disksize_kb=disksize_kb)
      vm_devices.append(disk)
      
      for nic in nics:
          nic_spec = create_nic(client, target, nic)
          if nic_spec is None:
              print("Could not create spec for NIC")
              sys.exit(1)
  
          # Append the nic spec to the vm_devices list
          vm_devices.append(nic_spec)
  
      vmfi = client.create("VirtualMachineFileInfo")
      vmfi.vmPathName = "[%s]" % ds_to_use.summary.name
      vm_config_spec = client.create("VirtualMachineConfigSpec")
      vm_config_spec.name = name
      vm_config_spec.memoryMB = memory_mb
      vm_config_spec.files = vmfi
      vm_config_spec.annotation = "Auto-provisioned by psphere"
      vm_config_spec.numCPUs = num_cpus
      vm_config_spec.guestId = guest_id
      vm_config_spec.deviceChange = vm_devices
  
      # Find the datacenter of the target
      if target.__class__.__name__ == "HostSystem":
          datacenter = target.parent.parent.parent
      else:
          datacenter = target.parent.parent
  
      try:
          task = datacenter.vmFolder.CreateVM_Task(config=vm_config_spec,
                                                   pool=resource_pool)
      except VimFault as e:
          print("Failed to create %s: " % e)
          sys.exit()
  
      while task.info.state in ["queued", "running"]:
          time.sleep(5)
          task.update()
          print("Waiting 5 more seconds for VM creation")
  
      if task.info.state == "success":
          elapsed_time = task.info.completeTime - task.info.startTime
          print("Successfully created new VM %s. Server took %s seconds." %
                (name, elapsed_time.seconds))
      elif task.info.state == "error":
          print("ERROR: The task for creating the VM has finished with"
                " an error. If an error was reported it will follow.")
          try:
              print("ERROR: %s" % task.info.error.localizedMessage)
          except AttributeError:
              print("ERROR: There is no error message available.")
      else:
          print("UNKNOWN: The task reports an unknown state %s" %
                task.info.state)