乐趣区

关于python3.x:python3-pyVmomi-操作-vcenter-克隆虚拟机-实例

克隆虚拟机是依赖于虚拟机模板,在虚拟机模板失常的状况下,以上代码可能实现克隆虚拟机并指定 IP 的操作的,那么先来说一说克隆虚拟机的坑。

  • 景象 1:虚拟机克隆胜利,虚拟机主动失常开机,但没有指定上网络 IP。
    景象产生的起因:
    克隆应用的模板没有网络适配器
  • 景象 2:虚拟机克隆胜利,然而没有自动开机,并且指定网络 IP 也失败了,在 vSphere 上还报了 ident.hostName.name 异样。
    景象产生的起因:
    ①虚拟机主机名:不能够用下划线等特殊字符
    ②虚拟机主机名为空
  • 景象 3:虚拟机克隆胜利,虚拟机主动失常开机,网络指定胜利,但虚拟机网络不通,无奈失常应用网络。
    景象产生的起因:
    指定的虚拟机 IP 和虚拟机所在的网络适配器的网络段不匹配,导致网络不通。

补充:当克隆虚拟机,没有集群,层级:数据中心–> 文件夹–> 主机

vim 飘红能够疏忽

code


# -*- coding: utf-8 -*-
import time
import traceback
import logging

from pyVim.connect import SmartConnectNoSSL, Disconnect
from pyVmomi import vim


class VmManage(object):
    def __init__(self, host, user, password, port, ssl):
        self.config = None
        self.host = host
        self.user = user
        self.pwd = password
        self.port = port
        self.sslContext = ssl
        try:
            self.client = SmartConnectNoSSL(host=host,
                                            user=user,
                                            pwd=password,
                                            port=443
                                            )
            self.content = self.client.RetrieveContent()
            self.result = True
        except Exception as e:
            self.result = e

    def _get_all_objs(self, obj_type, folder=None):
        """依据对象类型获取这一类型的所有对象"""
        if folder is None:
            container = self.content.viewManager.CreateContainerView(self.content.rootFolder, obj_type, True)
        else:
            container = self.content.viewManager.CreateContainerView(folder, obj_type, True)
        return container.view

    def _get_obj(self, obj_type, name):
        obj = None
        content = self.client.RetrieveContent()
        container = content.viewManager.CreateContainerView(content.rootFolder, obj_type, True)
        for c in container.view:
            if c.name == name:
                obj = c
                break
        return obj

    def get_datacenters(self):
        """获取数据核心列表"""
        return self._get_all_objs([vim.Datacenter])

    # vcenter 执行动作期待
    def wait_for_task(self, task):
        """wait for a vCenter task to finish"""
        task_done = False

        while not task_done:
            print("task.....%s" % task.info.state)
            if task.info.state == 'success':
                return {'message': u'执行胜利', 'status': True}

            if task.info.state == 'error':
                print("there was an error")
                return {'message': task.info.error.msg, 'status': True}

    def handleTask(self, tasks=None):
        if tasks is None:
            return False
        else:
            from pyVim.task import WaitForTasks
            try:
                WaitForTasks(tasks=tasks, si=self.client)
            except Exception as e:
                traceback.print_exc()
                print(str(e))
                return False

    def get_cluster_by_name(self, name=None, datacenter=None):
        if datacenter:
            folder = datacenter.hostFolder
        else:
            folder = self.content.rootFolder

        container = self.content.viewManager.CreateContainerView(folder, [vim.ClusterComputeResource], True)
        clusters = container.view
        for cluster in clusters:
            if cluster.name == name:
                return cluster
        return None

    def get_datastore_by_name(self, name, datacenter):
        datastores = datacenter.datastore
        for datastore in datastores:
            if datastore.name == name:
                return datastore
        return None

    def get_host_by_name(self, name, datastore):
        hosts = datastore.host
        for host in hosts:
            print("##get_host_by_name host:", host.key.summary.config.name)
            if host.key.summary.config.name == name:
                return host.key
        return None

    def get_vms_by_cluster(self, vmFolder):
        content = self.client.content
        objView = content.viewManager.CreateContainerView(vmFolder, [vim.VirtualMachine], True)
        vmList = objView.view
        objView.Destroy()
        return vmList

    def get_customspec(self, vm_ip=None, vm_subnetmask=None, vm_gateway=None, vm_dns=None,
                       vm_domain=None, vm_hostname=None):
        # guest NIC settings  无关 dns 和域名的配置谬误 更改了
        adaptermaps = []

        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 = vm_ip
        guest_map.adapter.subnetMask = vm_subnetmask
        guest_map.adapter.gateway = vm_gateway
        if vm_domain:
            guest_map.adapter.dnsDomain = vm_domain
        adaptermaps.append(guest_map)

        # DNS settings
        globalip = vim.vm.customization.GlobalIPSettings()
        if vm_dns:
            globalip.dnsServerList = [vm_dns]
            globalip.dnsSuffixList = vm_domain

        # Hostname settings
        ident = vim.vm.customization.LinuxPrep()
        if vm_domain:
            ident.domain = vm_domain
        ident.hostName = vim.vm.customization.FixedName()
        if vm_hostname:
            ident.hostName.name = vm_hostname
        customspec = vim.vm.customization.Specification()
        customspec.nicSettingMap = adaptermaps
        customspec.globalIPSettings = globalip
        customspec.identity = ident
        return customspec

    def change_disk_size(self, vm_obj, vm_disk):
        """
        :param vm_obj:  虚拟机对象(模板对象也实用):param vm_disk: 硬盘大小(单位:G):return: disk_change 配置列表
        """
        virtual_disk_devices = []
        virtual_disk_device = None
        virtual_scsi_controller = None

        # Find the disk device
        for dev in vm_obj.config.hardware.device:
            if isinstance(dev, vim.vm.device.VirtualSCSIController):
                virtual_scsi_controller = dev
            if isinstance(dev, vim.vm.device.VirtualDisk):
                virtual_disk_devices.append(dev)

        for dev in virtual_disk_devices:
            if dev.controllerKey == virtual_scsi_controller.key:
                virtual_disk_device = dev

        new_disk_kb = int(vm_disk) * 1024 * 1024

        virtual_disk_spec = vim.vm.device.VirtualDeviceSpec()
        virtual_disk_spec.operation = \
            vim.vm.device.VirtualDeviceSpec.Operation.edit
        virtual_disk_spec.device = virtual_disk_device
        virtual_disk_spec.device.capacityInKB = new_disk_kb
        disk_changes = []
        disk_changes.append(virtual_disk_spec)
        return disk_changes

    def add_disk(self, vm_obj, capacity):
        spec = vim.vm.ConfigSpec()
        dev_changes = []
        # capacity 为 存储盘容量将单位改为 G
        new_disk_kb = capacity * 1024 * 1024
        unit_number = 0
        # 遍历所有的硬件设施,找适合的地位增加
        for dev in vm_obj.config.hardware.device:
            if hasattr(dev.backing, 'fileName'):
                unit_number = int(dev.unitNumber) + 1
                # unit_number 7 reserved for scsi controller
                if unit_number == 7:
                    unit_number += 1
                if unit_number >= 16:
                    logging.error('we don\'t support this many disks')
            if isinstance(dev, vim.vm.device.VirtualSCSIController):
                controller = dev

        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.FlatVer2BackingInfo()
        disk_spec.device.backing.thinProvisioned = True
        disk_spec.device.backing.diskMode = 'persistent'

        disk_spec.device.unitNumber = unit_number
        disk_spec.device.capacityInKB = new_disk_kb
        disk_spec.device.controllerKey = controller.key
        dev_changes.append(disk_spec)

        return dev_changes


    def add_disk_to_vm(self, vm_name, capacity):
        vm_obj = self._get_obj([vim.VirtualMachine], vm_name)
        spec = vim.vm.ConfigSpec()
        dev_changes = []
        # capacity 为 存储盘容量将单位改为 G
        new_disk_kb = capacity * 1024 * 1024
        unit_number = 0
        # 遍历所有的硬件设施,找适合的地位增加
        for dev in vm_obj.config.hardware.device:
            if hasattr(dev.backing, 'fileName'):
                unit_number = int(dev.unitNumber) + 1
                # unit_number 7 reserved for scsi controller
                if unit_number == 7:
                    unit_number += 1
                if unit_number >= 16:
                    logging.error('we don\'t support this many disks')
            if isinstance(dev, vim.vm.device.VirtualSCSIController):
                controller = dev

        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.FlatVer2BackingInfo()
        disk_spec.device.backing.thinProvisioned = True
        disk_spec.device.backing.diskMode = 'persistent'

        disk_spec.device.unitNumber = unit_number
        disk_spec.device.capacityInKB = new_disk_kb
        disk_spec.device.controllerKey = controller.key
        dev_changes.append(disk_spec)
        spec.deviceChange = dev_changes
        task = vm_obj.ReconfigVM_Task(spec=spec)
        result1 = self.wait_for_task(task)
        if result1['status']:
            data = {'message': u'硬盘增加胜利', 'result': True}
        else:
            data = {'message': u'硬盘增加失败: %s' % result1['message'], 'result': False}
        return data



    def edit_nic(self, vm, network_name, is_vss):
        device_change = []
        data = {'message': None, 'result': False, 'code': 1}
        for device in vm.config.hardware.device:
            if isinstance(device, vim.vm.device.VirtualEthernetCard):
                nicspec = vim.vm.device.VirtualDeviceSpec()
                nicspec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit
                nicspec.device = device
                nicspec.device.wakeOnLanEnabled = True
                if is_vss:
                    nicspec.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo()
                    nicspec.device.backing.network = self._get_obj([vim.Network], network_name)
                    nicspec.device.backing.deviceName = network_name
                else:
                    network = self._get_obj([vim.dvs.DistributedVirtualPortgroup], network_name)
                    dvs_port_connection = vim.dvs.PortConnection()
                    dvs_port_connection.portgroupKey = network.key
                    dvs_port_connection.switchUuid = network.config.distributedVirtualSwitch.uuid
                    nicspec.device.backing = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo()
                    nicspec.device.backing.port = dvs_port_connection
                nicspec.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo()
                nicspec.device.connectable.startConnected = True
                nicspec.device.connectable.allowGuestControl = True
                device_change.append(nicspec)
                nicspec.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo()
                nicspec.device.connectable.startConnected = True
                nicspec.device.connectable.allowGuestControl = True
                device_change.append(nicspec)
                break
        if device_change:
            config_spec = vim.vm.ConfigSpec(deviceChange=device_change)
            task = vm.ReconfigVM_Task(config_spec)
            result = self.wait_for_task(task)
            if result['status']:
                power_state = vm.runtime.powerState
                if power_state == 'poweredOn':
                    stop_task = vm.PowerOff()
                    stop_result = self.wait_for_task(stop_task)
                #     if stop_result['status']:
                #         start_task = vm.PowerOn()
                #         self.wait_for_task(start_task)
                # else:
                start_task = vm.PowerOn()
                self.wait_for_task(start_task)
                data["message"] = u'更改网络胜利'
                data["result"] = True
                data["code"] = 0
            else:
                data["message"] = u'更改网络失败'
        else:
            data["message"] = u'网络适配器不存在,无奈批改网络'
        return data

    def device_nic(self, vm, network_name, switch_type):
        """
        :param vm: 虚拟机模板对象
        :param network_name: 要批改的网络段名称
        :param switch_type: 网络段类型
        :return:
        """
        device_change = []
        no_vlan = False
        for device in vm.config.hardware.device:
            # 判断是否存在网络适配器
            if isinstance(device, vim.vm.device.VirtualEthernetCard):
                nicspec = vim.vm.device.VirtualDeviceSpec()
                # 肯定要是 vim.vm.device.VirtualDeviceSpec.Operation.edit  代表编辑
                nicspec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit
                nicspec.device = device
                nicspec.device.wakeOnLanEnabled = True
                if switch_type == 1:
                    # 规范交换机设置
                    nicspec.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo()
                    nicspec.device.backing.network = self._get_obj([vim.Network], network_name)
                    nicspec.device.backing.deviceName = network_name
                else:
                    # 判断网络段是否在分组交换机网络范畴
                    network = self._get_obj([vim.dvs.DistributedVirtualPortgroup], network_name)
                    if network is None:
                        logging.error(u'分组交换机没有 {0} 网段'.format(network_name))
                        no_vlan = True
                        break
                    # 分布式交换机设置
                    dvs_port_connection = vim.dvs.PortConnection()
                    dvs_port_connection.portgroupKey = network.key
                    dvs_port_connection.switchUuid = network.config.distributedVirtualSwitch.uuid
                    nicspec.device.backing = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo()
                    nicspec.device.backing.port = dvs_port_connection
                # 网络段配置设置
                nicspec.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo()
                nicspec.device.connectable.startConnected = True
                nicspec.device.connectable.allowGuestControl = True
                device_change.append(nicspec)
                logging.info('网络适配器设置')
                break
        if device_change:
            return device_change
        else:
            if not no_vlan:
                logging.error(u'网络适配器不存在,无奈批改网络')
        return device_change

    def get_vm_ip(self, vm_obj):
        """获取 VM 所有 IP 地址"""
        ips = []
        for i in vm_obj.guest.net:
            if i.network:
                for b in range(6):
                    if i.ipAddress:
                        ips.extend(i.ipAddress)
                        return ips
                    else:
                        print("VM 没有获取到 IP 地址期待 10 秒")
                        time.sleep(10)
            else:
                print('VM 未配置网卡')
        return 'VM 未获取到 IP 地址, 请检测网络状态或者 DHCP 服务器'


    def clone_cluster(self, template_name, vm_name, datacenter_name,
                      datastore_name, cluster_name, host_name=None,
                      cup_num=None, memory=None, vm_ip=None, vm_subnetmask=None,
                      vm_gateway=None, vm_dns=None, vm_domain=None,
                      vm_hostname=None):
        # 获取模版
        template = self._get_obj([vim.VirtualMachine], template_name)
        # 模版不存在
        if template is None:
            return {'message': u'克隆失败: 模版不存在', 'result': False}
        else:
            print(template.name, "模版存在 hehe")
        # 抉择克隆的虚拟机寄存地位, 通过数据中心获取对象
        datacenter = self._get_obj([vim.Datacenter], datacenter_name)
        # 数据中心不存在
        if datacenter is None:
            return {'message': u'克隆失败: 数据中心不存在', 'result': False}
        vmfolder = datacenter.vmFolder

        # 获取存储
        if datastore_name:
            datastore = self.get_datastore_by_name(datastore_name, datacenter)
            if datastore is None:
                return {'message': u'克隆失败: 该数据中心下 %s 存储不存在' % datastore_name, 'result': False}
            else:
                print(datastore.name, "数据中心存储存在")
        else:
            # 此处感觉须要批改
            datastore = self.get_datastore_by_name(template.datastore[0].info.name, datacenter)
            if datastore is None:
                return {'message': u'克隆失败: 该数据中心下 %s 模版不存在' % template_name, 'result': False}
            else:
                print(template.name, datastore, "模版存在 hehe")

        # 获取集群
        cluster = self.get_cluster_by_name(cluster_name, datacenter)
        print("##cluster:", cluster)
        if cluster is None:
            print(self.get_host_by_name(host_name, datastore))
            return {'message': u'克隆失败: cluster %s no 存在' % cluster, 'result': False}
        else:
            vms = self.get_vms_by_cluster(cluster)
            vms_name = [i.name for i in vms]
            if vm_name in vms_name:
                return {'message': u'克隆失败: 虚拟机 %s 曾经存在' % vm_name, 'result': False}
            resource_pool = cluster.resourcePool
            relospec = vim.vm.RelocateSpec()
            relospec.datastore = datastore
            relospec.pool = resource_pool

            # 获取主机
            if host_name:
                host = self.get_host_by_name(host_name, datastore)
                if host is None:
                    return {'message': u'克隆失败: 该存储下 %s 主机不存在' % host_name, 'result': False}
                else:
                    relospec.host = host

            clonespec = vim.vm.CloneSpec()
            clonespec.location = relospec
            clonespec.powerOn = True
            # 设置 cpu 和内存
            if all([vm_ip, vm_subnetmask, vm_gateway, vm_domain]):
                clonespec.customization = self.get_customspec(vm_ip, vm_subnetmask, vm_gateway, vm_domain, vm_dns,
                                                              vm_hostname)
            vmconf = vim.vm.ConfigSpec()
            if cup_num:
                vmconf.numCPUs = cup_num
            if memory:
                vmconf.memoryMB = memory
            if vmconf is not None:
                clonespec.config = vmconf
            print("cloning VM...")

            task = template.Clone(folder=vmfolder, name=vm_name, spec=clonespec)
            result = self.wait_for_task(task)
            if result['status']:
                data = {'message': u'克隆胜利', 'result': True}
            else:
                data = {'message': u'克隆失败: %s' % result['message'], 'result': False}
            return data

    def clone_host(self, template_name, vm_name, datacenter_name,
                   datastore_name, vm_exi_ip, vm_vlan=None, switch_type=None, vm_folder=None,
                   cup_num=None, memory=None, vm_disk=None, vm_add_disk=None, vm_ip=None,
                   vm_subnetmask=None, vm_gateway=None, vm_dns=None,
                   vm_domain=None, vm_hostname=None):
        # 获取模版
        template = self._get_obj([vim.VirtualMachine], template_name)
        # 模版不存在
        if template is None:
            return {'message': u'克隆失败: 模版不存在', 'result': False}
        # 抉择克隆的虚拟机寄存地位, 通过数据中心获取对象
        datacenter = self._get_obj([vim.Datacenter], datacenter_name)
        # 数据中心不存在
        if datacenter is None:
            return {'message': u'克隆失败: 数据中心不存在', 'result': False}
        # vm 创立门路
        if vm_folder:
            vmfolder = self._get_obj([vim.Folder], vm_folder)
        else:
            vmfolder = datacenter.vmFolder


        # 获取存储
        if datastore_name:
            datastore = self.get_datastore_by_name(datastore_name, datacenter)
            if datastore is None:
                return {'message': u'克隆失败: 该数据中心下 %s 存储不存在' % datastore_name, 'result': False}
        else:
            datastore = self.get_datastore_by_name(template.datastore[0].info.name, datacenter)
            if datastore is None:
                return {'message': u'克隆失败: 该数据中心下 %s 模版不存在' % template_name, 'result': False}
        # 获取宿主机
        host = self.get_host_by_name(vm_exi_ip, datastore)
        if host is None:
            return {'message': u'克隆失败: 该存储下 %s 主机不存在' % vm_exi_ip, 'result': False}
        # 获取宿主机下的 vm
        vms = host.vm
        for vm in vms:
            print("##host vm:", vm)
            config = vm.summary.config
            if vm_name == config.name:
                return {'message': u'克隆失败: 虚拟机 %s 曾经存在' % vm_name, 'result': False}
        # 获取资源池
        resourcepool = host.parent.resourcePool
        relospec = vim.vm.RelocateSpec()
        relospec.datastore = datastore
        relospec.pool = resourcepool
        relospec.host = host
        # 配置 Clone 属性
        clonespec = vim.vm.CloneSpec()
        clonespec.location = relospec
        clonespec.powerOn = True
        device_change = []
        # # 设置网卡
        # if len(template.network) == 0:
        #     logging.info(u'设置网卡')
        #     nic_change = self.add_nic('VM Network')
        #     device_change.extend(nic_change)
        # 指定网络段配置
        if vm_vlan:
            device_nic_change = self.device_nic(
                vm=template,
                network_name=vm_vlan,
                switch_type=switch_type
            )
            device_change.extend(device_nic_change)

        # 批改硬盘大小
        # vm_disk 必须比原来值大哦
        if vm_disk:
            logging.info(u'扩容硬盘')
            disk_change = self.change_disk_size(template, vm_disk)
            if type(disk_change) is list:
                device_change.extend(disk_change)
            else:
                return {'message': disk_change, 'result': False}

        # add_disk
        if vm_add_disk:
            logging.info(u'扩容硬盘')
            add_disk_change = self.add_disk(template, vm_add_disk)
            if type(add_disk_change) is list:
                device_change.extend(add_disk_change)
            else:
                return {'message': add_disk_change, 'result': False}

        # 更新配置
        vmconf = vim.vm.ConfigSpec(deviceChange=device_change)
        logging.info(u'更新网卡网卡的配置')
        # 设置 IP
        if all([vm_ip, vm_subnetmask, vm_gateway]):
            clonespec.customization = self.get_customspec(vm_ip, vm_subnetmask, vm_gateway, vm_dns, vm_domain,
                                                          vm_hostname)
            logging.info(u'设置 IP')
        # 更改 cpu 和内存
        if cup_num:
            vmconf.numCPUs = cup_num
        if memory:
            vmconf.memoryMB = memory * 1024
        if vmconf is not None:
            clonespec.config = vmconf
        # 开始克隆
        task = template.Clone(folder=vmfolder, name=vm_name, spec=clonespec)

        vm_task = {
            'task': task,
            'vm_name': vm_name,
            'vm_ip': vm_ip,
            'vm_exi_ip': vm_exi_ip
        }
        data = {'message': u'工作下发胜利', 'result': True, 'data': vm_task}
        return data


if __name__ == '__main__':
    ip = '10.31.1xx.4x'
    user = 'axxxxcal'
    password = 'Qxxxxx4'
    port = 443
    template_name = u'centos7temp'
    vm_name = u'centos7test60'
    data_center_name = u'Datacenter'
    datastore_name = u'datastore1'
    cluster_name = "10.31.1xx.x6"
    host_name = "10.31.1x.x6"
    cup_num = 2
    memory = 2
    resource_pool = None
    power_on = True
    vm_ext_disk = 50
    vm_add_disk = 20
    vm_ip = '10.31.1xx.x8'
    vm_subnetmask = '255.255.255.0'
    vm_gateway = '10.31.1xx.1'
    vm_dns = '8.8.8.8'
    vm_vlan = None
    switch_type = None
    vm_domain = 'xiaohxx.com'
    vm_hostname = 'test'
    vm = VmManage(host=ip, user=user, password=password, port=port, ssl=None)

    data = vm.clone_host(template_name=template_name, vm_name=vm_name, datacenter_name=data_center_name,
                         datastore_name=datastore_name, vm_exi_ip=host_name, vm_vlan=None, switch_type=None, vm_folder=None,
                         cup_num=4, memory=2, vm_disk=None, vm_add_disk=30, vm_ip=vm_ip,
                         vm_subnetmask=vm_subnetmask, vm_gateway=vm_gateway, vm_dns=vm_dns,
                         vm_domain=vm_domain, vm_hostname=vm_hostname)


    # 给 vm add 30G 磁盘
    #data = vm.add_disk_to_vm(vm_name=template_name, capacity=30)

    # # 虚拟机开机, 期待 x0 秒, 待虚拟机开机启动获取 IP 地址
    # vm_obj = vm._get_obj([vim.VirtualMachine], vm_name)
    # task = vm_obj.PowerOn()
    # print("启动 VM 电源")
    # print(vm.wait_for_task(task))
    # time.sleep(50)
    # print("开始获取 VM IP 地址")
    # vm_obj_ip = vm.get_vm_ip(vm_obj)

    # # 虚拟机 off
    # vm_obj = vm._get_obj([vim.VirtualMachine], template_name)
    # task = vm_obj.PowerOff()
    # print("PowerOff")
    # print(vm.wait_for_task(task))
    # time.sleep(20)

    # data = vm.clone_cluster(
    #     template_name=template_name,
    #     vm_name=vm_name,
    #     datacenter_name=data_center_name,
    #     cluster_name=cluster_name,
    #     datastore_name=datastore_name,
    #     host_name=host_name,
    #     cup_num=cup_num,
    #     memory=memory,
    #     vm_ip=vm_ip,
    #     vm_subnetmask=vm_subnetmask,
    #     vm_gateway=vm_gateway,
    #     vm_dns=vm_dns,
    #     vm_domain=vm_domain,
    #     vm_hostname=vm_hostname
    # )


    print(data)

我给各位一个忠告,装一下 vmware tools 呦

退出移动版