python3 vsphere 虚拟机管理平台


前言

随着云计算和虚拟化技术的普及,越来越多的企业开始使用vSphere来管理他们的虚拟化环境。为了提高运维团队的工作效率,我们将介绍如何使用Python 3和pyVim调用vSphere API进行自动化运维管理。本文将详细介绍如何通过编写Python脚本来对接自己的运维管理平台,实现对vSphere环境的监控和操作

安装python环境

centos安装python

安装pyVim库

pip3 install pyVim

pyVmomi库介绍

pyVmomi 是 VMware 官方提供的用于 Python 的 vSphere API 封装库,它的全称是 “Python bindings for the VMware vSphere API”。这个库允许开发人员使用 Python 与 VMware vSphere 进行交互,实现自动化管理、监控和配置虚拟化环境。

以下是 pyVmomi 库的一些关键特点和功能:

  1. 与 vSphere API 交互pyVmomi 提供了直接的 Python 接口,允许开发人员与 vSphere API 进行交互,执行各种操作,如获取虚拟机信息、管理数据存储、监控主机状态等。

  2. 高级功能支持pyVmomi 支持 vSphere API 的各种高级功能,如克隆虚拟机、创建快照、迁移虚拟机、设置资源池等,使开发人员能够灵活地管理虚拟化环境。

  3. 对象模型映射pyVmomi 将 vSphere API 中的各种对象、属性和方法映射到 Python 对象模型中,使开发人员可以像操作 Python 对象一样操作 vSphere 中的资源,降低了学习成本和开发难度。

  4. 易用性和灵活性pyVmomi 设计简洁、易于使用,提供了丰富的文档和示例代码,使开发人员能够快速上手并实现各种自动化管理任务。同时,它也提供了丰富的配置选项和扩展机制,满足不同场景下的需求。

  5. 跨平台支持pyVmomi 支持在多种操作系统平台上运行,包括 Windows、Linux、macOS 等,使开发人员能够在不同环境下使用相同的代码进行开发和部署。

  6. 活跃的社区支持:作为 VMware 官方提供的库,pyVmomi 拥有一个活跃的开发社区和用户群体,提供了丰富的技术支持、文档和示例代码,帮助开发人员解决各种问题和挑战。

脚本功能描述

用于与 VMware vSphere 服务器进行交互的脚本。它提供了一些功能,包括连接到 vSphere 服务器、获取物理机和虚拟机的信息、控制虚拟机的开关机以及删除虚拟机等。

  1. 连接到 vSphere 服务器

    • connect_vsphere 函数用于建立与 vSphere 服务器的连接。它需要提供服务器的 IP 地址、用户名、密码以及端口号。
    • 如果连接成功,将返回一个与 vSphere 服务器建立的会话实例 si
  2. 获取物理机详情

    • get_host_template 函数用于获取指定物理机的详细信息。它需要提供物理机的 DNS 名称。
    • 返回物理机的状态(开机或关机)、型号、CPU 相关信息、内存使用情况、运行时长、存储空间等信息。
  3. 获取虚拟机简略信息

    • get_vm_template 函数用于获取虚拟机的简略信息,包括名称、IP、操作系统、CPU、内存、状态以及所属物理机等。
    • 这里展示了一个虚拟机的简略信息。
  4. 虚拟机开机

    • power_on_vm 函数用于开启指定虚拟机。它需要提供虚拟机的名称。
    • 如果虚拟机已关机,则会尝试开机虚拟机。
  5. 虚拟机关机

    • power_off_vm 函数用于关闭指定虚拟机。它需要提供虚拟机的名称。
    • 如果虚拟机处于开机状态,则会尝试关闭虚拟机。
  6. 获取虚拟机详细信息

    • get_vm_details 函数用于获取指定虚拟机的详细信息。它需要提供虚拟机的名称。
    • 返回虚拟机的状态、IP、操作系统、CPU 核数、内存使用情况、关联物理机以及硬盘信息等。
  7. 虚拟机删除

    • delete_vms 函数用于删除指定虚拟机。它需要提供虚拟机的名称。
    • 如果虚拟机处于运行状态,会先尝试关闭虚拟机,然后再删除虚拟机。

完整代码

import atexit
import datetime
from itertools import count
import ssl
import time
from pyVim.connect import Disconnect, SmartConnect
from pyVmomi import vim, vmodl
import json

# 磁盘大小来显示不同的单位(例如字节、千字节、兆字节、吉字节等
def format_disk_size(bytes):
    if bytes < 1024:
        return f"{bytes} 字节"
    elif bytes < 1024 * 1024:
        kilobytes = bytes / 1024
        return f"{kilobytes:.2f} KB"
    elif bytes < 1024 * 1024 * 1024:
        megabytes = bytes / (1024 * 1024)
        return f"{megabytes:.2f} MB"
    elif bytes < 1024 * 1024 * 1024 * 1024:
        gigabytes = bytes / (1024 * 1024 * 1024)
        return f"{gigabytes:.2f} GB"
    else:
        terabytes = bytes / (1024 * 1024 * 1024 * 1024)
        return f"{terabytes:.2f} TB"
    
# 时间
def format_time(seconds):
    if seconds < 60:
        return f"{seconds}秒"
    elif seconds < 3600:
        minutes = seconds // 60
        return f"{minutes}分钟"
    elif seconds < 86400:
        hours = seconds // 3600
        return f"{hours}小时"
    else:
        days = seconds // 86400
        return f"{days}天"
    
# 根据 CPU 大小来显示不同的单位(例如赫兹、千赫兹、兆赫兹等)
def format_cpu_speed(hertz):
    if hertz < 1000:
        return f"{hertz} Hz"
    elif hertz < 1000000:
        kilohertz = hertz / 1000
        return f"{kilohertz:.2f} kHz"
    elif hertz < 1000000000:
        megahertz = hertz / 1000000
        return f"{megahertz:.2f} MHz"
    else:
        gigahertz = hertz / 1000000000
        return f"{gigahertz:.2f} GHz"
    
# 根据内存大小来显示不同的单位(例如字节、千字节、兆字节、吉字节等)
def format_memory_size(bytes):
    if bytes < 1024:
        return f"{bytes} 字节"
    elif bytes < 1024 * 1024:
        kilobytes = bytes / 1024
        return f"{kilobytes:.2f} KB"
    elif bytes < 1024 * 1024 * 1024:
        megabytes = bytes / (1024 * 1024)
        return f"{megabytes:.2f} MB"
    else:
        gigabytes = bytes / (1024 * 1024 * 1024)
        return f"{gigabytes:.2f} GB"
    
# 虚拟机开关机需要的一个方法
def WaitForTasks(service_instance, tasks):
    """
    Given the service instance si and tasks, it returns after all the
    tasks are complete
    """
    pc = service_instance.content.propertyCollector
    task_list = [str(task) for task in tasks]
    # Create filter
    obj_specs = [vmodl.query.PropertyCollector.ObjectSpec(obj=task)
                 for task in tasks]
    property_spec = vmodl.query.PropertyCollector.PropertySpec(type=vim.Task,
                                                             pathSet=[],
                                                             all=True)
    filter_spec = vmodl.query.PropertyCollector.FilterSpec()
    filter_spec.objectSet = obj_specs
    filter_spec.propSet = [property_spec]
    pcfilter = pc.CreateFilter(filter_spec, True)
    try:
        version, state = None, None
        # Loop looking for updates till the state moves to a completed state.
        while True:
            update = pc.WaitForUpdates(version)
            for filter_set in update.filterSet:
                for obj_set in filter_set.objectSet:
                    task = obj_set.obj
                    for change in obj_set.changeSet:
                        if change.name == 'info':
                            state = change.val.state
                        elif change.name == 'info.state':
                            state = change.val
                        else:
                            continue

            # Check if the state moved to a completed state.
            if state == vim.TaskInfo.State.success:
                return task.info.result
            elif state == vim.TaskInfo.State.error:
                raise task.info.error
    finally:
        if pcfilter:
            pcfilter.Destroy()


class test(object):
    # 与vsphere建立连接
    def connect_vsphere(host,user,password,port):
        context = None
        # 建立与vSphere的连接
        if hasattr(ssl, '_create_unverified_context'):
            context = ssl._create_unverified_context()
        si = SmartConnect(host=host,user=user,pwd=password,port=port,sslContext=context)
        if not si:
            print("帐号密码有问题")
        # else:
        #     print('成功')
        atexit.register(Disconnect, si)
        return si
        
    # 获取物理机详情
    def get_host_template(si):
        content = si.RetrieveContent()
        # 物理机名称
        host_name = "10.252.100.100"
        # 使用 content.searchIndex 执行查找
        search_index = content.searchIndex
        host = search_index.FindByDnsName(dnsName=host_name, vmSearch=False)
        host_information = {}

        if host:
            # 获取物理机电源状态
            power_state = host.runtime.powerState
            if power_state == "poweredOn":
                host_information['status'] = "开机"

                # 获取物理机信息
                cpu_usage = host.summary.quickStats.overallCpuUsage
                total_cpu_resource = host.summary.hardware.numCpuCores * host.summary.hardware.cpuMhz
                total_memory = host.hardware.memorySize
                memory_usage = host.summary.quickStats.overallMemoryUsage 
                uptime = host.summary.quickStats.uptime
                # 获取存储信息
                total_storage_size = 0
                # 获取存储已用信息
                used_storage_size = 0
                for datastore in host.datastore:
                    total_storage_size += datastore.summary.capacity
                    # 检查每个存储设备的已用容量
                    used_storage_size += datastore.summary.capacity - datastore.summary.freeSpace
                # 转换存储大小为 GB 或 TB,视情况而定
                total_storage_size_in_gb = total_storage_size  # 转换为 GB
                used_storage_size_in_gb = used_storage_size  # 转换为 TB
                # 内存可用
                memAvailable = total_memory - (memory_usage * 1024 * 1024)
                # print(format_memory_size(memAvailable))
                # 磁盘可用
                storageAvailable = total_storage_size_in_gb - used_storage_size_in_gb
                # cpu可用
                cpuAvailable = total_cpu_resource - cpu_usage

                host_information.update({
                    "name": host.name,
                    "hardware_model": host.hardware.systemInfo.model,
                    "cpu_model": host.hardware.cpuPkg[0].description,
                    "cpu_cores": host.hardware.cpuInfo.numCpuCores,
                    "cpu_sockets": host.hardware.cpuInfo.numCpuPackages,
                    "cpu_available":format_cpu_speed(cpuAvailable * 1000000),
                    "物理机逻辑处理器数量": host.summary.hardware.numCpuThreads,
                    "物理机 CPU 使用情况": format_cpu_speed(cpu_usage * 1000000 ),
                    "物理机总 CPU 资源": format_cpu_speed(total_cpu_resource * 1000000 ),
                    "物理机总内存": format_memory_size(total_memory),
                    "物理机内存使用情况": format_memory_size(memory_usage * (1024 * 1024) ),
                    "mem_available":format_memory_size(memAvailable),
                    "物理机总运行时长": format_time(uptime),
                    "物理机总存储空间大小": format_disk_size(total_storage_size_in_gb),
                    "物理机存储已用大小": format_disk_size(used_storage_size_in_gb),
                    "storage_available":format_disk_size(storageAvailable),
                })
            else:
                host_information['status'] = "关机"
                # return {
                #     "name": host.name,
                #     "hardware_model":host.hardware.systemInfo.model,
                #     "cpu_model":host.hardware.cpuPkg[0].description,
                #     "cpu_cores":host.hardware.cpuInfo.numCpuCores,
                #     "cpu_sockets":host.hardware.cpuInfo.numCpuPackages,
                #     "物理机逻辑处理器数量":host.summary.hardware.numCpuThreads,
                #     "物理机 CPU 使用情况":cpu_usage,
                #     "物理机总 CPU 资源":total_cpu_resource,
                #     "物理机总内存":format_memory_size(total_memory),
                #     "物理机内存使用情况":format_memory_size(memory_usage),
                #     "物理机总运行时长":format_time(uptime),
                #     "物理机总存储空间大小":format_disk_size(total_storage_size_in_gb),
                #     "物理机存储已用大小":format_disk_size(used_storage_size_in_gb),
                # }
        return host_information

    # 虚拟机简略信息
    def get_vm_template(si):
        # 名称
        # IP
        # 操作系统
        # CPU
        # 内存
        # 状态
        # 所属物理机
        content = si.RetrieveContent()
        container = content.viewManager.CreateContainerView(content.rootFolder, [vim.VirtualMachine], True)
        vms = container.view
        for vm in vms:
            if vm.name == "Pro_10.252.100.102_2022-05-06_文件转码服务器":
                print('VMname:', vm.name)
                print('IP :{}'.format(vm.guest.ipAddress))
                # print('操作系统:{}'.format(vm.guest.guestFullName))
                # print("CPU:{}".format(vm.config.hardware.numCPU))
                # print("内存大小: {:.0f} GB".format(vm.config.hardware.memoryMB / (1024)))
                # print('虚拟机状态:{}'.format(vm.runtime.powerState))
                # "poweredOn": 虚拟机已经开机并正在运行。"poweredOff": 虚拟机已经关机。"suspended": 虚拟机处于挂起状态
                print('关联物理机:{}'.format(vm.runtime.host.name))

    # 虚拟机开机
    def power_on_vm(si,vm_name):
        # 从已建立的连接中获取内容
        content = si.RetrieveContent()
        
        # 查找虚拟机
        vm = None
        container = content.viewManager.CreateContainerView(content.rootFolder, [vim.VirtualMachine], True)
        vms = container.view
        for v in vms:
            if v.name == vm_name:
                vm = v
                break
        if vm:
            # 检查虚拟机当前状态
            if vm.runtime.powerState == "poweredOff":
            # if vm.runtime.powerState == "poweredOn":
                # 开机虚拟机
                task = vm.PowerOnVM_Task()
                # task = vm.PowerOffVM_Task()
                # 等待操作完成
                WaitForTasks(si, [task])
                return f"虚拟机 '{vm_name}' 已开机"
            else:
                return f"虚拟机 '{vm_name}' 已处于开机状态"
        else:
            return f"找不到虚拟机 '{vm_name}'"

    # 虚拟机关机
    def power_off_vm(si,vm_name):
        # 从已建立的连接中获取内容
        content = si.RetrieveContent()
        
        # 查找虚拟机
        vm = None
        container = content.viewManager.CreateContainerView(content.rootFolder, [vim.VirtualMachine], True)
        vms = container.view
        for v in vms:
            if v.name == vm_name:
                vm = v
                break
        if vm:
            # 检查虚拟机当前状态
            if vm.runtime.powerState == "poweredOn":
                # 开机虚拟机
                task = vm.PowerOffVM_Task()
                # 等待操作完成
                WaitForTasks(si, [task])
                return f"虚拟机 '{vm_name}' 已开机"
            else:
                return f"虚拟机 '{vm_name}' 已处于开机状态"
        else:
            return f"找不到虚拟机 '{vm_name}'"

    # 虚拟机详细信息
    def get_vm_details(si, vm_name):
        content = si.RetrieveContent()
        container = content.viewManager.CreateContainerView(content.rootFolder, [vim.VirtualMachine], True)
        vms = container.view

        total_disk_capacity_gb = 0
        total_disk_free_gb = 0
        disk_block = 0

        vm_information = {}
        disk_data = {}
        disk_data2 = []
        for vm in vms:
            if vm.name == vm_name:
                vm_state = vm.runtime.powerState
                if vm_state == "poweredOn":
                    vm_information['status'] = "开机"
                else:
                    vm_information['status'] = "关机"
                vm_information.update({
                    "name" : vm.name,
                    "IP" : vm.guest.ipAddress,
                    "system" : vm.config.guestFullName,
                    "cpu核数" : vm.config.hardware.numCPU,
                    "mem": format_memory_size(vm.config.hardware.memoryMB * 1024 * 1024),
                    "host":vm.runtime.host.name,
                    "cpu 使用":format_cpu_speed(vm.summary.quickStats.overallCpuUsage * 1000000),
                    "mem使用": format_memory_size(vm.summary.quickStats.guestMemoryUsage * 1024 * 1024 ),
                })
                # 磁盘类型
                for device in vm.config.hardware.device:
                    if isinstance(device, vim.vm.device.VirtualDisk):
                        disk_capacity_kb = device.capacityInKB
                        total_disk_capacity_gb += disk_capacity_kb
                        # 硬盘块数统计
                        disk_block += 1
                        vm_information['硬盘块'] = disk_block
                        vm_information['总储存'] = format_disk_size(total_disk_capacity_gb * 1024)

                        # 硬盘详细情况                        
                        if isinstance(device.backing, vim.vm.device.VirtualDisk.FlatVer2BackingInfo):
                            if device.backing.thinProvisioned == True:
                                disk_data2.append({"disk名称" : device.deviceInfo.label,'disk大小':format_disk_size(disk_capacity_kb * 1024),"disk类型": "精简置备"})
                            else:
                                if device.backing.eagerlyScrub == None:
                                    disk_data2.append({"disk名称" : device.deviceInfo.label,'disk大小':format_disk_size(disk_capacity_kb * 1024),"disk类型": "厚置备延迟置零"})
                                elif device.backing.eagerlyScrub == True:
                                    disk_data2.append({"disk名称" : device.deviceInfo.label,'disk大小':format_disk_size(disk_capacity_kb * 1024),"disk类型": "厚置备快速置零"})
                vm_information['disk'] = disk_data2

        return vm_information
    # 虚拟机删除
    def delete_vms(si, vm_name):
        content = si.RetrieveContent()
        container = content.viewManager.CreateContainerView(content.rootFolder, [vim.VirtualMachine], True)
        vms = container.view
        for vm in vms:
            if vm.name == vm_name:
                try:
                    if vm.runtime.powerState == "poweredOn":
                        # 如果虚拟机正在运行,首先关闭它
                        task = vm.PowerOff()
                        task_info = task.info
                        task_info.state = vim.TaskInfo.State.success
                        task_info.result = None
                        # print(f"等待虚拟机 {vm_name} 关机...")
                        WaitForTasks(si, [task])
                    
                    # 删除虚拟机
                    task = vm.Destroy()
                    task_info = task.info
                    task_info.state = vim.TaskInfo.State.success
                    task_info.result = None

                    start_time = time.time()
                    while task_info.state != vim.TaskInfo.State.success:
                        if time.time() - start_time > 300:  # 设置超时时间,单位秒
                            # raise Exception(f"删除虚拟机 {vm_name} 超时")
                            print({'code': 404, 'message': '虚拟机 %s 已超时5分钟' %vm_name})
                        time.sleep(5)  # 每5秒检查一次任务状态
                        task_info = task.info
                    print({'code': 200, 'message': '虚拟机 %s 已成功删除' %vm_name})
                except Exception as e:
                    print({'code': 404, 'message': ' %s' %e}) 

if __name__ == "__main__":
    host='192.168.1.1'
    user='administrator'
    password='password'
    port=443

    si=test.connect_vsphere(host,user,password,port)
    
    # 物理机详情
    # print(test.get_host_template(si))

    # 虚拟机简略信息
    # print(test.get_vm_template(si))

    # 虚拟机开机
    # print(test.power_on_vm(si=si,vm_name="test-2"))

    # 虚拟机关机
    # print(test.power_off_vm(si=si,vm_name="test-2"))
 
    # 虚拟机详细信息
    # print(test.get_vm_details(si,'test-2'))
    
    # 虚拟机删除
    print(test.delete_vms(si,'test-2'))
    # 断开与vCenter服务器的连接
    Disconnect(si)
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XMYX-0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值