python3 vsphere 虚拟机管理平台

python3 脚本通过pyvim 调用 vshphere,进行一些操作,可以对接自己的运维管理平台

物理机详情

虚拟机简略信息

虚拟机开机

虚拟机关机

虚拟机详情

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)

你可能感兴趣的:(python,vsphere)