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)