pyVmomi操作VMware

2022-06-17 08:20:41 浏览数 (1)

前言

VMware,一个优秀的虚拟化平台。其拥有优秀的 Api 和稳定的性能,其也拥有完善的 SDK,但是官方的 SDK 并不好用,今天我们就用简单的例子来认识一款简单好用的 VMwarePython 库,它就是 pyVmomi

环境准备

pyVmomi 支持 Python3,我们在 Python3 的环境上直接安装 pyVmomi 即可。

代码语言:javascript复制
pip install pyvmomi

我们还需要准备 VMware 的环境信息,主要就是 vSphere 的登录 ip,端口,用户名和密码。

呆猫

连接 vSphere 获取所有虚机

这个例子可以让我们了解如何通过 pyVmomi 连接 vSphere,再通过 vim 的类型获取指定的资源。

代码语言:javascript复制
from pyVim import connect
from pyVmomi import vim
import pchelper
from pyVim.task import WaitForTask

# 根据vim的对象类型获取对象容器,本方法获取虚机容器
def Conn(host='192.168.x.x',user='user@vsphere.local',pwd='pwd@pwd',port=443):
    # 获取链接
    vm_ins = connect.SmartConnectNoSSL(host=host,user=user,port=port,pwd=pwd)
    # 获取上下文
    content = vm_ins.RetrieveContent()
    # 获取根路径容器
    container = content.rootFolder
    # 指定vim类型
    vm_type=[vim.VirtualMachine]
    recursive = True
    # 回去容器视图,这里面装的就是所有的VirtualMachine虚机
    containerView = content.viewManager.CreateContainerView(container, vm_type, recursive)
    # 将虚机容器返回
    return containerView

if __name__=='__main__':
     ds = Conn()
     for i in ds.view:
         # 打印虚机的name和电源状态
         print(i.name,i.runtime.powerState)

创建虚机

pyVmomi 创建虚机接口不支持定义启动盘和网卡等信息,所以需要创建完后单独进行挂载。 pyVmomi 创建虚机支持定义 CPU、内存、nameDataCenterDataStorehost 信息。

这个例子我们将创建一个不含启动盘和网络信息的虚机。

代码语言:javascript复制
from pyVim import connect
from pyVmomi import vim
import pchelper
from pyVim.task import WaitForTask

# 获取vm的实例
def Si(host='192.168.x.x',user='user@vsphere.local',pwd='pwd@pwd',port=443):
    vm_ins = connect.SmartConnectNoSSL(host=host,user=user,port=port,pwd=pwd)
    return vm_ins

# 初始化虚机配置
def create_config_spec(datastore_name, name, memory=4, guest="otherGuest",
                       annotation="Sample", cpus=1):
    # 获取配置对象
    config = vim.vm.ConfigSpec()
    # 为配置对象增加配置
    config.annotation = annotation
    config.memoryMB = int(memory)
    config.guestId = guest
    config.name = name
    config.numCPUs = cpus
    files = vim.vm.FileInfo()
    files.vmPathName = "[" datastore_name "]"
    config.files = files
    # 返回配置对象
    return config

# 创建虚机
def create_vm(si, vm_name, datacenter_name='Datacenter', host_ip='192.168.x.x', datastore_name='xx-LUN_SHARE01'):

    # 获取上下文
    content = si.RetrieveContent()
    destination_host = pchelper.get_obj(content, [vim.HostSystem], host_ip)
    source_pool = destination_host.parent.resourcePool
    if datastore_name is None:
        datastore_name = destination_host.datastore[0].name

    config = create_config_spec(datastore_name=datastore_name, name=vm_name)
    for child in content.rootFolder.childEntity:
        if child.name == datacenter_name:
            vm_folder = child.vmFolder  # child is a datacenter
            break
    else:
        print("Datacenter %s not found!" % datacenter_name)
        sys.exit(1)

    try:
        WaitForTask(vm_folder.CreateVm(config, pool=source_pool, host=destination_host))
        print("VM created: %s" % vm_name)
    except vim.fault.DuplicateName:
        print("VM duplicate name: %s" % vm_name, file=sys.stderr)
    except vim.fault.AlreadyExists:
        print("VM name %s already exists." % vm_name, file=sys.stderr)

if __name__=='__main__':
    create_vm(si=Si(),vm_name='Python全栈开发')

根据名称获取虚机对象

当我们需要对虚机进行操作的时候,我们需要获取虚机对象。这个例子就会告诉我们如何获取虚机对象。

代码语言:javascript复制
from pyVim import connect
from pyVmomi import vim
import pchelper
from pyVim.task import WaitForTask

# 根据vim的对象类型获取对象容器,本方法获取虚机容器
def Conn(host='192.168.x.x',user='user@vsphere.local',pwd='pwd@pwd',port=443):
    # 获取链接
    vm_ins = connect.SmartConnectNoSSL(host=host,user=user,port=port,pwd=pwd)
    # 获取上下文
    content = vm_ins.RetrieveContent()
    # 获取根路径容器
    container = content.rootFolder
    # 指定vim类型
    vm_type=[vim.VirtualMachine]
    recursive = True
    # 回去容器视图,这里面装的就是所有的VirtualMachine虚机
    containerView = content.viewManager.CreateContainerView(container, vm_type, recursive)
    # 将虚机容器返回
    return containerView

# 根据名称找虚机对象
def getVmbyName(name):
    vms = Conn()
    for i in vms.view:
        if i.name == name:
            print(i,i.name)
            return i

if __name__=='__main__':
    getVmbyName('Python全栈开发')

拿到虚机对象后,我们就可以对虚机进行很多操作了。

操作虚机

拿到虚机对象后,我们如何操作虚机呢?我们直接 dir 去获取虚机对象的属性即可。

代码语言:javascript复制
VMObj = getVmbyName('Python全栈开发')
print(dir(VMObj))

克隆虚机

因为 VMware 创建虚机流程复杂,通常我们会采用克隆的方式来创建虚机,然后再对虚机进行配置以达到创建虚机的效果。

代码语言:javascript复制
from pyVim import connect
from pyVmomi import vim
import pchelper
from pyVim.task import WaitForTask

# 根据vim的对象类型获取对象容器,本方法获取虚机容器
def Conn(host='192.168.x.x',user='user@vsphere.local',pwd='pwd@pwd',port=443):
    # 获取链接
    vm_ins = connect.SmartConnectNoSSL(host=host,user=user,port=port,pwd=pwd)
    # 获取上下文
    content = vm_ins.RetrieveContent()
    # 获取根路径容器
    container = content.rootFolder
    # 指定vim类型
    vm_type=[vim.VirtualMachine]
    recursive = True
    # 回去容器视图,这里面装的就是所有的VirtualMachine虚机
    containerView = content.viewManager.CreateContainerView(container, vm_type, recursive)
    # 将虚机容器返回
    return containerView


# 获取vm的实例
def Si(host='192.168.x.x',user='user@vsphere.local',pwd='pwd@pwd',port=443):
    vm_ins = connect.SmartConnectNoSSL(host=host,user=user,port=port,pwd=pwd)
    return vm_ins

# 根据名称找虚机对象
def getVmbyName(name):
    vms = Conn()
    for i in vms.view:
        if i.name == name:
            print(i,i.name)
            return i

# 克隆虚机
def getFloder(datacenter_name='Datacenter'):

    # 获取上下文
    content = Si().RetrieveContent()
    for child in content.rootFolder.childEntity:
        if child.name == datacenter_name:
            vm_folder = child.vmFolder  # child is a datacenter
            return vm_folder

def wait_for_task(task):
    """ wait for a vCenter task to finish """
    task_done = False
    while not task_done:
        if task.info.state == 'success':
            return task.info.result

        if task.info.state == 'error':
            print("there was an error")
            print(task.info.error)
            task_done = True


def clone_vm(
        content, template, vm_name, datacenter_name, vm_folder, datastore_name,
        cluster_name, resource_pool, power_on, datastorecluster_name):
    """
    Clone a VM from a template/VM, datacenter_name, vm_folder, datastore_name
    cluster_name, resource_pool, and power_on are all optional.
    """

    # if none git the first one
    datacenter = pchelper.get_obj(content, [vim.Datacenter], datacenter_name)

    if vm_folder:
        #destfolder = pchelper.search_for_obj(content, [vim.Folder], vm_folder)
        destfolder = datacenter.vmFolder
    else:
        destfolder = datacenter.vmFolder

    if datastore_name:
        datastore = pchelper.search_for_obj(content, [vim.Datastore], datastore_name)
    else:
        datastore = pchelper.get_obj(
            content, [vim.Datastore], template.datastore[0].info.name)

    # if None, get the first one
    cluster = pchelper.search_for_obj(content, [vim.ClusterComputeResource], cluster_name)
    if not cluster:
        clusters = pchelper.get_all_obj(content, [vim.ResourcePool])
        cluster = list(clusters)[0]

    if resource_pool:
        resource_pool = pchelper.search_for_obj(content, [vim.ResourcePool], resource_pool)
    else:
        resource_pool = cluster.resourcePool

    vmconf = vim.vm.ConfigSpec()

    if datastorecluster_name:
        podsel = vim.storageDrs.PodSelectionSpec()
        pod = pchelper.get_obj(content, [vim.StoragePod], datastorecluster_name)
        podsel.storagePod = pod

        storagespec = vim.storageDrs.StoragePlacementSpec()
        storagespec.podSelectionSpec = podsel
        storagespec.type = 'create'
        storagespec.folder = destfolder
        storagespec.resourcePool = resource_pool
        storagespec.configSpec = vmconf

        try:
            rec = content.storageResourceManager.RecommendDatastores(
                storageSpec=storagespec)
            rec_action = rec.recommendations[0].action[0]
            real_datastore_name = rec_action.destination.name
        except Exception:
            real_datastore_name = template.datastore[0].info.name

        datastore = pchelper.get_obj(content, [vim.Datastore], real_datastore_name)

    # set relospec
    relospec = vim.vm.RelocateSpec()
    relospec.datastore = datastore
    relospec.pool = resource_pool

    clonespec = vim.vm.CloneSpec()
    clonespec.location = relospec
    clonespec.powerOn = power_on

    print("cloning VM...")
    task = template.Clone(folder=destfolder, name=vm_name, spec=clonespec)
    wait_for_task(task)
    print("VM cloned.")


if __name__=='__main__':
    # 这是我们的模板,即镜像
    VMObj = getVmbyName('image_test')
    # 获取vm实例,供克隆用
    conn = Si().RetrieveContent()
    # 获取文件目录
    vm_folder=getFloder()
    # 开始克隆
    clone_vm(content=conn, template=VMObj, vm_name='newVM', datacenter_name='Datacenter', vm_folder=vm_folder, datastore_name='xx-LUN_SHARE01',cluster_name='xx_Cluster_test1', resource_pool=False, power_on=True, datastorecluster_name=None)

总结

以上就是 pyVmomi 的简单使用,虽然功能比较多,但是文档不完善,后续还有很大的进步空间。更多内容大家可以查看 VMware 的官方文档和 pyVmomisamples

代码中用到的 pchelper 就是从下面的 github 仓库/tools/中下载的。

参考:https://github.com/vmware/pyvmomi-community-samples/tree/master/samples

0 人点赞