51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

使用Python SDK操作VMware进行虚拟机创建和配置变更

前言 {#前言}

最近在搞虚拟机变更自动化的对接,支持了两个平台,分别是 SmartX 和 VMware 平台。这篇文章记录一下使用 Python SDK 进行 VMware 虚拟机操作的一些实战场景,主要包括快照创建、快照删除、计算资源变更、磁盘扩容等操作。
💩 感慨

VMware 的使用和 Python SDK 使用已经不是第一次了,之前就因为 CMDB 进行过全资源采集,而 SmartX 则是第一次对接,看了 SmartX 的接口文档才真的见识了什么叫好的接口文档,真的是清晰明了,完全是可以边看边调,相比之下 VMware 的接口文档就是负作用,看了只会浪费自己时间和让自己摸不着头脑,还不如直接让 ChatGPT 写。

SDK 封装代码 {#sdk-封装代码}

先来一个自己封装好的 VMware 连接和基本操作的管理类代码,这个类提供了一些常用的函数,比如支持 with 语法的连接和断开连接操作、获取单个资源实例和全部资源实例的函数、使用不同方式获取虚拟机实例的、开关机、资源变更操作等。利用这些提供好的函数,基本就可以支持常见资源变更场景了。

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

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


FORMAT = '[%(asctime)s (line:%(lineno)d) %(levelname)s] %(message)s'
logging.basicConfig(level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S', format=FORMAT)
logger = logging.getLogger(name)


class VMwareManager:
def init(self, host, user, password, port=443):
self.host = host
self.user = user
self.password = password
self.port = port
self.si = None
self.content = None


    <span class="k">def</span> <span class="fm">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
        <span class="k">return</span> <span class="bp">self</span>

    <span class="k">def</span> <span class="fm">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">,</span> <span class="n">exc_val</span><span class="p">,</span> <span class="n">exc_tb</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">disconnect</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">connect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'Connect vmware start ...'</span><span class="p">)</span>
        <span class="n">context</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">SSLContext</span><span class="p">(</span><span class="n">ssl</span><span class="o">.</span><span class="n">PROTOCOL_TLSv1_2</span><span class="p">)</span>
        <span class="n">context</span><span class="o">.</span><span class="n">verify_mode</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">CERT_NONE</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">si</span> <span class="o">=</span> <span class="n">SmartConnect</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="n">user</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">user</span><span class="p">,</span> <span class="n">pwd</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">password</span><span class="p">,</span>
                               <span class="n">port</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">,</span> <span class="n">sslContext</span><span class="o">=</span><span class="n">context</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">content</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">si</span><span class="o">.</span><span class="n">RetrieveContent</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">disconnect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">si</span><span class="p">:</span>
            <span class="n">Disconnect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">si</span><span class="p">)</span>
        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'Disconnect vmware done.'</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">_get_obj</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj_type</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">_moId</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>




        """通过名称或者_moId获取实例,获取不到就报错"""
container = self.content.viewManager.CreateContainerView(self.content.rootFolder,
obj_type, True)
if name:
for c in container.view:
if c.name == name:
return c
if _moId:
for c in container.view:
if c._moId == _moId:
return c
raise Exception('Get obj {} by name or _moId failed'.format(obj_type))


    <span class="k">def</span> <span class="nf">_get_all_objs</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj_type</span><span class="p">,</span> <span class="n">folder</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>




        """批量获取实例"""
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


    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">_wait_for_task</span><span class="p">(</span><span class="n">task</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">120</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span>




        """任务在queued和running都需要等待,成功时返回结果,失败或执行超时都报异常"""
start_time = time.time()
task_desc = task.info.descriptionId
while task.info.state in [vim.TaskInfo.State.running, vim.TaskInfo.State.queued]:
exec_time = int(time.time() - start_time)
if exec_time > timeout:
raise Exception("Task {} timed out.".format(task_desc))
time.sleep(interval)
logger.info('Task {} is running {}/{} ...'.format(task_desc, exec_time, timeout))
if task.info.state == vim.TaskInfo.State.success:
print("Task {} completed successfully.".format(task_desc))
return task.info.result
else:
raise Exception("Task failed: {}".format(task.info))


    <span class="k">def</span> <span class="nf">get_vm_by_uuid</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">uuid</span><span class="p">):</span>




        """通过uuid获取虚拟机"""
objs = self._get_all_objs([vim.VirtualMachine])
for obj in objs:
if obj.config.uuid == uuid:
return obj
raise Exception('Get vm by uuid {} failed.'.format(uuid))


    <span class="k">def</span> <span class="nf">vm_power_off</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">vm</span><span class="o">.</span><span class="n">runtime</span><span class="o">.</span><span class="n">powerState</span> <span class="o">==</span> <span class="n">vim</span><span class="o">.</span><span class="n">VirtualMachinePowerState</span><span class="o">.</span><span class="n">poweredOff</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机 </span><span class="si">{}</span><span class="s1"> 已关机,无需执行关机操作'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机 </span><span class="si">{}</span><span class="s1"> 执行关机 ...'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>
            <span class="n">task</span> <span class="o">=</span> <span class="n">vm</span><span class="o">.</span><span class="n">PowerOffVM_Task</span><span class="p">()</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_wait_for_task</span><span class="p">(</span><span class="n">task</span><span class="p">,</span> <span class="mi">30</span><span class="p">)</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机 </span><span class="si">{}</span><span class="s1"> 关机完成'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">vm_power_on</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">vm</span><span class="o">.</span><span class="n">runtime</span><span class="o">.</span><span class="n">powerState</span> <span class="o">==</span> <span class="n">vim</span><span class="o">.</span><span class="n">VirtualMachinePowerState</span><span class="o">.</span><span class="n">poweredOn</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机 </span><span class="si">{}</span><span class="s1"> 已开机,无需执行开机操作'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机 </span><span class="si">{}</span><span class="s1"> 执行开机 ...'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>
            <span class="n">task</span> <span class="o">=</span> <span class="n">vm</span><span class="o">.</span><span class="n">PowerOnVM_Task</span><span class="p">()</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_wait_for_task</span><span class="p">(</span><span class="n">task</span><span class="p">,</span> <span class="mi">30</span><span class="p">)</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机 </span><span class="si">{}</span><span class="s1"> 开机完成'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">check_vm_is_power_off</span><span class="p">(</span><span class="n">vm</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">vm</span><span class="o">.</span><span class="n">runtime</span><span class="o">.</span><span class="n">powerState</span> <span class="o">!=</span> <span class="n">vim</span><span class="o">.</span><span class="n">VirtualMachinePowerState</span><span class="o">.</span><span class="n">poweredOff</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s1">'虚拟机未处理关机状态,无法执行变更!!!'</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机已经关机,可执行变更操作。'</span><span class="p">)</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">print_cpu_and_memory</span><span class="p">(</span><span class="n">vm</span><span class="p">):</span>
        <span class="n">cpu</span><span class="p">,</span> <span class="n">memory</span> <span class="o">=</span> <span class="n">vm</span><span class="o">.</span><span class="n">summary</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">numCpu</span><span class="p">,</span> <span class="n">vm</span><span class="o">.</span><span class="n">summary</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">memorySizeMB</span> <span class="o">//</span> <span class="mi">1024</span>
        <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机 </span><span class="si">{}</span><span class="s1"> 当前CPU:</span><span class="si">{}</span><span class="s1">,内存:</span><span class="si">{}</span><span class="s1">GB'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">cpu</span><span class="p">,</span> <span class="n">memory</span><span class="p">))</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">print_power_state</span><span class="p">(</span><span class="n">vm</span><span class="p">):</span>
        <span class="n">power_state</span> <span class="o">=</span> <span class="n">vm</span><span class="o">.</span><span class="n">runtime</span><span class="o">.</span><span class="n">powerState</span>
        <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机 </span><span class="si">{}</span><span class="s1"> 当前电源状态:</span><span class="si">{}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">power_state</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">print_disks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">):</span>
        <span class="n">disks</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_vm_disks</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>
        <span class="n">size_info</span> <span class="o">=</span> <span class="p">{</span><span class="n">disk</span><span class="o">.</span><span class="n">unitNumber</span><span class="p">:</span> <span class="n">disk</span><span class="o">.</span><span class="n">capacityInKB</span> <span class="o">//</span> <span class="mi">1024</span> <span class="o">//</span> <span class="mi">1024</span> <span class="k">for</span> <span class="n">disk</span> <span class="ow">in</span> <span class="n">disks</span><span class="p">}</span>
        <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机 </span><span class="si">{}</span><span class="s1"> 磁盘信息(GB):</span><span class="si">{}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">size_info</span><span class="p">))</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">get_vm_disks</span><span class="p">(</span><span class="n">vm</span><span class="p">):</span>




        """返回虚拟机磁盘"""
disks = []
for device in vm.config.hardware.device:
if isinstance(device, vim.vm.device.VirtualDisk):
disks.append(device)
return disks


    <span class="k">def</span> <span class="nf">get_disk_by_check_disk_size</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">,</span> <span class="n">check_size_kb</span><span class="p">):</span>




        """
        利用磁盘大小找到虚拟机的磁盘,比如已知Windows的D盘是100G,则可以通过这个找到具体磁盘
        注意:对于多个磁盘相差很接近的,这个方法不适合,比如D盘和E盘都是100G,此时找到的不准
        """
check_dict = {}
disks = self.get_vm_disks(vm)
for disk in disks:
disk_size_kb = disk.capacityInKB
abs_size = abs(disk_size_kb - check_size_kb)
check_dict[abs_size] = disk
print('磁盘差值KB: {}'.format(check_dict.keys()))
min_size = min(check_dict.keys())
get_disk = check_dict[min_size]
print('磁盘差值最小值为 {}MB,磁盘编号:{}'.format(min_size // 1024, get_disk.unitNumber))
return get_disk


    <span class="k">def</span> <span class="nf">vm_resize</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">,</span> <span class="n">new_cpu</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">new_memory_gb</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>




        """计算资源变更,CPU内存都可以变更,需要在关机情况下执行(除非支持热更新)"""
spec = vim.vm.ConfigSpec()
if new_cpu:
spec.numCPUs = new_cpu
if new_memory_gb:
spec.memoryMB = new_memory_gb * 1024


        <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机 </span><span class="si">{}</span><span class="s1"> 开始执行计算资源变更 ...'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>
        <span class="n">task</span> <span class="o">=</span> <span class="n">vm</span><span class="o">.</span><span class="n">ReconfigVM_Task</span><span class="p">(</span><span class="n">spec</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_wait_for_task</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
        <span class="nb">print</span><span class="p">(</span><span class="s1">'虚拟机 </span><span class="si">{}</span><span class="s1"> 计算资源变更完成'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">expand_disk_by_add_size</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">,</span> <span class="n">disk</span><span class="p">,</span> <span class="n">add_size_gb</span><span class="p">):</span>




        """
        扩容指定磁盘
        前置条件:
            1.支持热扩容的可以直接扩容,否则需要关机后扩容
            2.不能有快照存在,因此需要先清理快照
        """
old_size_kb = disk.capacityInKB
add_size_kb = add_size_gb 1024 1024
new_size_kb = old_size_kb + add_size_kb
print('准备将磁盘 {} 从 {} GB扩容到 {} GB'.format(disk.unitNumber,
old_size_kb // 1024 // 1024,
new_size_kb // 1024 // 1024))


        <span class="c1"># 设置扩容磁盘配置</span>
        <span class="n">disk_spec</span> <span class="o">=</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">VirtualDeviceSpec</span><span class="p">()</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">operation</span> <span class="o">=</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">VirtualDeviceSpec</span><span class="o">.</span><span class="n">Operation</span><span class="o">.</span><span class="n">edit</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">device</span> <span class="o">=</span> <span class="n">disk</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">capacityInKB</span> <span class="o">=</span> <span class="n">new_size_kb</span>

        <span class="c1"># 应用配置到虚拟机</span>
        <span class="n">vm_spec</span> <span class="o">=</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">ConfigSpec</span><span class="p">()</span>
        <span class="n">vm_spec</span><span class="o">.</span><span class="n">deviceChange</span> <span class="o">=</span> <span class="p">[</span><span class="n">disk_spec</span><span class="p">]</span>

        <span class="n">task</span> <span class="o">=</span> <span class="n">vm</span><span class="o">.</span><span class="n">ReconfigVM_Task</span><span class="p">(</span><span class="n">spec</span><span class="o">=</span><span class="n">vm_spec</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_wait_for_task</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'磁盘</span><span class="si">{}</span><span class="s1">扩容完成!!!'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">disk</span><span class="o">.</span><span class="n">unitNumber</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">add_disk</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">,</span> <span class="n">size_gb</span><span class="p">,</span> <span class="n">thin</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>




        """
        新增磁盘,thin=True表示精简置备
        前置条件:
            1.支持热扩容的可以直接扩容,否则需要关机后扩容
            2.不能有快照存在,因此需要先清理快照
        """
logger.info('准备新增磁盘 {} GB'.format(size_gb))
size_kb = size_gb 1024 1024


        <span class="n">controller</span> <span class="o">=</span> <span class="kc">None</span>
        <span class="k">for</span> <span class="n">device</span> <span class="ow">in</span> <span class="n">vm</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">hardware</span><span class="o">.</span><span class="n">device</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">device</span><span class="p">,</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">VirtualSCSIController</span><span class="p">):</span>
                <span class="n">controller</span> <span class="o">=</span> <span class="n">device</span>
                <span class="k">break</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">controller</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s1">'No SCSI controller found in the VM </span><span class="si">{}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">vm</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>
        <span class="n">unit_number</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">controller</span><span class="o">.</span><span class="n">device</span><span class="p">)</span>  <span class="c1"># 磁盘序号,从0开始,自动生成就行</span>
        <span class="nb">print</span><span class="p">(</span><span class="s1">'新增磁盘序号: </span><span class="si">{}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">unit_number</span><span class="p">))</span>

        <span class="c1"># 新增磁盘spec</span>
        <span class="n">disk_spec</span> <span class="o">=</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">VirtualDeviceSpec</span><span class="p">()</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">fileOperation</span> <span class="o">=</span> <span class="s1">'create'</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">operation</span> <span class="o">=</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">VirtualDeviceSpec</span><span class="o">.</span><span class="n">Operation</span><span class="o">.</span><span class="n">add</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">device</span> <span class="o">=</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">VirtualDisk</span><span class="p">()</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">backing</span> <span class="o">=</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">VirtualDisk</span><span class="o">.</span><span class="n">FlatVer2BackingInfo</span><span class="p">()</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">backing</span><span class="o">.</span><span class="n">thinProvisioned</span> <span class="o">=</span> <span class="n">thin</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">backing</span><span class="o">.</span><span class="n">diskMode</span> <span class="o">=</span> <span class="s1">'persistent'</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">unitNumber</span> <span class="o">=</span> <span class="n">unit_number</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">capacityInKB</span> <span class="o">=</span> <span class="n">size_kb</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">controllerKey</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">key</span>
        <span class="c1"># print(disk_spec)</span>

        <span class="c1"># 应用到虚拟机</span>
        <span class="n">vm_spec</span> <span class="o">=</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">ConfigSpec</span><span class="p">()</span>
        <span class="n">vm_spec</span><span class="o">.</span><span class="n">deviceChange</span> <span class="o">=</span> <span class="p">[</span><span class="n">disk_spec</span><span class="p">]</span>

        <span class="n">task</span> <span class="o">=</span> <span class="n">vm</span><span class="o">.</span><span class="n">ReconfigVM_Task</span><span class="p">(</span><span class="n">spec</span><span class="o">=</span><span class="n">vm_spec</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_wait_for_task</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'新增磁盘完成!!!'</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">remove_disk</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">,</span> <span class="n">disk</span><span class="p">):</span>
        <span class="nb">print</span><span class="p">(</span><span class="s1">'准备删除磁盘编号:</span><span class="si">{}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">disk</span><span class="o">.</span><span class="n">unitNumber</span><span class="p">))</span>
        <span class="n">disk_spec</span> <span class="o">=</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">VirtualDeviceSpec</span><span class="p">()</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">operation</span> <span class="o">=</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">device</span><span class="o">.</span><span class="n">VirtualDeviceSpec</span><span class="o">.</span><span class="n">Operation</span><span class="o">.</span><span class="n">remove</span>
        <span class="n">disk_spec</span><span class="o">.</span><span class="n">device</span> <span class="o">=</span> <span class="n">disk</span>

        <span class="c1"># 应用到虚拟机</span>
        <span class="n">vm_spec</span> <span class="o">=</span> <span class="n">vim</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">ConfigSpec</span><span class="p">()</span>
        <span class="n">vm_spec</span><span class="o">.</span><span class="n">deviceChange</span> <span class="o">=</span> <span class="p">[</span><span class="n">disk_spec</span><span class="p">]</span>

        <span class="n">task</span> <span class="o">=</span> <span class="n">vm</span><span class="o">.</span><span class="n">ReconfigVM_Task</span><span class="p">(</span><span class="n">spec</span><span class="o">=</span><span class="n">vm_spec</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_wait_for_task</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'删除磁盘完成!!!'</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">_list_snapshots_recursively</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">snapshots</span><span class="p">):</span>




        """递归查询快照"""
snapshot_list = []
for snapshot in snapshots:
snapshot_list.append(snapshot)
snapshot_list.extend(self._list_snapshots_recursively(snapshot.childSnapshotList))
return snapshot_list


    <span class="k">def</span> <span class="nf">get_snapshots</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">):</span>




        """返回虚拟机快照列表"""
snapshots = vm.snapshot.rootSnapshotList if vm.snapshot else []
snapshot_list = self._list_snapshots_recursively(snapshots)
return snapshot_list


    <span class="k">def</span> <span class="nf">create_snapshot</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">,</span> <span class="n">snapshot_name</span><span class="p">,</span> <span class="n">snapshot_desc</span><span class="o">=</span><span class="s1">''</span><span class="p">,</span> <span class="n">memory</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">quiesce</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>




        """
        创建快照
        :param vm: 虚拟机对象
        :param snapshot_name: 快照名称
        :param snapshot_desc: 快照描述
        :param memory: 是否包含虚拟机内存状态,建议True
        :param quiesce: 是否保持磁盘状态,建议False
        :return:
        """
task = vm.CreateSnapshot_Task(
name=snapshot_name,
description=snapshot_desc,
memory=memory,
quiesce=quiesce
)
self._wait_for_task(task)
logger.info('创建快照 {} 完成!!!'.format(snapshot_name))


    <span class="k">def</span> <span class="nf">delete_snapshot</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">,</span> <span class="n">snapshot_id</span><span class="p">,</span> <span class="n">remove_children</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="n">snapshot_item</span> <span class="o">=</span> <span class="kc">None</span>
        <span class="n">snapshot_list</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_snapshots</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">snapshot</span> <span class="ow">in</span> <span class="n">snapshot_list</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">str</span><span class="p">(</span><span class="n">snapshot</span><span class="o">.</span><span class="n">id</span><span class="p">)</span> <span class="o">==</span> <span class="nb">str</span><span class="p">(</span><span class="n">snapshot_id</span><span class="p">):</span>
                <span class="n">snapshot_item</span> <span class="o">=</span> <span class="n">snapshot</span>
                <span class="k">break</span>
        <span class="k">if</span> <span class="n">snapshot_item</span><span class="p">:</span>
            <span class="n">task</span> <span class="o">=</span> <span class="n">snapshot_item</span><span class="o">.</span><span class="n">snapshot</span><span class="o">.</span><span class="n">RemoveSnapshot_Task</span><span class="p">(</span><span class="n">removeChildren</span><span class="o">=</span><span class="n">remove_children</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_wait_for_task</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
            <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'删除快照 id=</span><span class="si">{}</span><span class="s1"> 完成'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">snapshot_id</span><span class="p">))</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">'快照id=</span><span class="si">{}</span><span class="s1">不存在,不需要删除'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">snapshot_id</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">delete_all_snatshots</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vm</span><span class="p">):</span>
        <span class="n">snapshot_list</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_snapshots</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">snapshot_list</span><span class="p">:</span>
            <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'开始清理快照'</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">snapshot</span> <span class="ow">in</span> <span class="n">snapshot_list</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">delete_snapshot</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="n">snapshot</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
            <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'快照清理完成'</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'没有快照,无需清理'</span><span class="p">)</span>




def main():
with VMwareManager(VMWARE_HOST, VMWARE_USERNAME, VMWARE_PASSWORD, VMWARE_PORT) as vm_manager:
# vm_list = vm_manager._get_all_objs([vim.VirtualMachine])
# for vm in vm_list:
#     # print(dir(vm))
#     print(vm._moId, vm.name)
# vm = vm_manager._get_obj([vim.VirtualMachine], _moId='15')
vm = vm_manager.get_vm_by_uuid('564da6fb-8ed5-f765-da86-238c1dfbe934')
vm_manager.print_power_state(vm)
vm_manager.print_cpu_and_memory(vm)
vm_manager.print_disks(vm)
# disk = vm_manager.get_disk_by_check_disk_size(vm, 100 * 1024 * 1024)
# vm_manager.expand_disk_by_add_size(vm, disk, 100)
# 
# vm_manager.add_disk(vm, 100, False)
# vm_manager.remove_disk(vm, disk)
# 
# snapshots = vm_manager.get_snapshots(vm)
# print(snapshots)
# vm_manager.create_snapshot(vm, 'test-01')
# vm_manager.delete_all_snatshots(vm)


if name == 'main':
VMWARE_HOST = '192.168.0.254'
VMWARE_PORT = 443
VMWARE_USERNAME = 'root'
VMWARE_PASSWORD = 'admin@!9876'


    <span class="n">main</span><span class="p">()</span>




虚拟机自动化变更场景 {#虚拟机自动化变更场景}

虚拟机的自动化场景我这里主要实现了常用资源变更,虚拟机创建的场景就没实现了,如果要实现,一定是通过模板创建虚拟机而不是直接去创建,不过我这里没试过,但是大致了解了一下是比较麻烦的。查到了一篇文章有进行过虚拟机通过模板创建的过程,可以参考一下:vSphere通 python API接口创建虚拟机及修改配置

计算资源(CPU和内存)变更 {#计算资源cpu和内存变更}

计算资源的变更支持单独变更CPU或内存,也可以同时变更,可以库容也可以缩容,代码演示:

def resize_cpu_memory():
    """
    CPU和内存变更,一般情况下需要关机变更,除非支持热更新,则可以直接扩容,但不能缩容
    :return:
    """
    vm_uuid = '564da6fb-8ed5-f765-da86-238c1dfbe934'
    cpu = 8
    memory = 32

    <span class="k">with</span> <span class="n">VMwareManager</span><span class="p">(</span><span class="n">VMWARE_HOST</span><span class="p">,</span> <span class="n">VMWARE_USERNAME</span><span class="p">,</span> <span class="n">VMWARE_PASSWORD</span><span class="p">,</span> <span class="n">VMWARE_PORT</span><span class="p">)</span> <span class="k">as</span> <span class="n">vm_manager</span><span class="p">:</span>
        <span class="n">vm</span> <span class="o">=</span> <span class="n">vm_manager</span><span class="o">.</span><span class="n">get_vm_by_uuid</span><span class="p">(</span><span class="n">vm_uuid</span><span class="p">)</span>

        <span class="c1"># 变更前检查是否关机,必须关机变更</span>
        <span class="c1"># 可以手动关机也可以自动关机,一般在ITSM流程中需要用户手动关机,减少变更带了的业务风险</span>
        <span class="c1"># vm_manager.vm_power_off(vm)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">check_vm_is_power_off</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>

        <span class="c1"># 变更前查询当前资源和状态</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_power_state</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_cpu_and_memory</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>

        <span class="c1"># 执行变更</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">vm_resize</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="n">new_cpu</span><span class="o">=</span><span class="n">cpu</span><span class="p">,</span> <span class="n">new_memory_gb</span><span class="o">=</span><span class="n">memory</span><span class="p">)</span>

        <span class="c1"># 开机</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">vm_power_on</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>

        <span class="c1"># 变更后查询当前资源和状态</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_cpu_and_memory</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_power_state</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>




注意事项:

  • 计算资源变更可以单独变更CPU或内存,也可以一起变更,并且扩容和缩容都支持
  • 一般情况计算资源变更需要停机操作,虽然有的机器支持热更新可以不停机,但是由于支持缩容,所以停机是比较稳妥的
  • 虽然可以使用脚本直接关机,但是安全起见,停机操作由主机管理员执行,而不是自动化脚本去执行,这样是为了保证主机上运行的服务可控的停掉

新增快照 {#新增快照}

快照的创建比较简单,只需要选定虚拟机,传入快照名称和描述即可。

def create_snapshot():
    """
    为指定的虚拟机创建快照
    :return:
    """
    vm_uuid = '564da6fb-8ed5-f765-da86-238c1dfbe934'
    snapshot_name = "snapshot-test01"
    snapshot_desc = "快照描述"

    <span class="k">with</span> <span class="n">VMwareManager</span><span class="p">(</span><span class="n">VMWARE_HOST</span><span class="p">,</span> <span class="n">VMWARE_USERNAME</span><span class="p">,</span> <span class="n">VMWARE_PASSWORD</span><span class="p">,</span> <span class="n">VMWARE_PORT</span><span class="p">)</span> <span class="k">as</span> <span class="n">vm_manager</span><span class="p">:</span>
        <span class="n">vm</span> <span class="o">=</span> <span class="n">vm_manager</span><span class="o">.</span><span class="n">get_vm_by_uuid</span><span class="p">(</span><span class="n">vm_uuid</span><span class="p">)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">create_snapshot</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="n">snapshot_name</span><span class="o">=</span><span class="n">snapshot_name</span><span class="p">,</span> <span class="n">snapshot_desc</span><span class="o">=</span><span class="n">snapshot_desc</span><span class="p">)</span>




删除快照 {#删除快照}

删除快照可以通过名称来删除也可以通过快照ID,取决于查询快照的方式,还可以一次性删除某个虚拟机的所有快照。

def delete_snapshot():
    """
    为指定的虚拟机删除快照
    :return:
    """
    vm_uuid = '564da6fb-8ed5-f765-da86-238c1dfbe934'
    snapshot_id = '1'

    <span class="k">with</span> <span class="n">VMwareManager</span><span class="p">(</span><span class="n">VMWARE_HOST</span><span class="p">,</span> <span class="n">VMWARE_USERNAME</span><span class="p">,</span> <span class="n">VMWARE_PASSWORD</span><span class="p">,</span> <span class="n">VMWARE_PORT</span><span class="p">)</span> <span class="k">as</span> <span class="n">vm_manager</span><span class="p">:</span>
        <span class="n">vm</span> <span class="o">=</span> <span class="n">vm_manager</span><span class="o">.</span><span class="n">get_vm_by_uuid</span><span class="p">(</span><span class="n">vm_uuid</span><span class="p">)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">delete_snapshot</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="n">snapshot_id</span><span class="o">=</span><span class="n">snapshot_id</span><span class="p">,</span> <span class="n">remove_children</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>




新增磁盘 {#新增磁盘}

演示代码:

def add_disk():
    """
    新增磁盘场景,只是服务器概念的磁盘增加,后续还要进行分区操作,属于系统层面的操作
    :return:
    """
    vm_uuid = '564da6fb-8ed5-f765-da86-238c1dfbe934'
    disk_size = 500

    <span class="k">with</span> <span class="n">VMwareManager</span><span class="p">(</span><span class="n">VMWARE_HOST</span><span class="p">,</span> <span class="n">VMWARE_USERNAME</span><span class="p">,</span> <span class="n">VMWARE_PASSWORD</span><span class="p">,</span> <span class="n">VMWARE_PORT</span><span class="p">)</span> <span class="k">as</span> <span class="n">vm_manager</span><span class="p">:</span>
        <span class="n">vm</span> <span class="o">=</span> <span class="n">vm_manager</span><span class="o">.</span><span class="n">get_vm_by_uuid</span><span class="p">(</span><span class="n">vm_uuid</span><span class="p">)</span>

        <span class="c1"># 磁盘新增很多时候是不需要关机的,这个看实际支持情况</span>
        <span class="c1"># 可以手动关机也可以自动关机,一般在ITSM流程中需要用户手动关机,减少变更带了的业务风险</span>
        <span class="c1"># vm_manager.vm_power_off(vm)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">check_vm_is_power_off</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>

        <span class="c1"># 变更前查询当前资源和状态</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_power_state</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_disks</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>

        <span class="c1"># 清理全部快照</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">delete_all_snatshots</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>

        <span class="c1"># 新增磁盘</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">add_disk</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="n">size_gb</span><span class="o">=</span><span class="n">disk_size</span><span class="p">,</span> <span class="n">thin</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>

        <span class="c1"># 开机</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">vm_power_on</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>

        <span class="c1"># 变更后查询当前资源和状态</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_disks</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_power_state</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>




注意事项:

  • 新增磁盘前需要删除虚拟机所有快照
  • 新增磁盘之后,在系统层面还需要进行分区操作,才可以把新增的磁盘分给具体分区
  • 新增磁盘有一些属性可选,比如 thinProvisioned 属性,最好是参考一下原有磁盘的属性,跟原有磁盘保持一致

扩容磁盘 {#扩容磁盘}

扩容磁盘的关键在于如何找到需要扩容的磁盘,比如用户只会告诉你他要扩容的分区,比如 Windows中的 D 盘或 Linux 中的 /data 盘,此时怎么获取到这个分区对应的磁盘?

我这里有一个基于实际情况约定的规则:

  1. 实际情况是无论 Windows 还是 Linux 系统,不会有两个分区的大小相差接近,基本都是 100 G 以上的差别
  2. 默认的系统每个分区对应单独的磁盘,不存在一个磁盘分给多个分区的情况
  3. 基于前两点的实际情况,给出任意一个分区的大小,便可以找到一个大小跟这个分区很接近的磁盘,比如 /data 分区已知 289 GB,此时可以查到一个分区是 300 GB,另一个分区是 100 GB,则可以通过差值判断是 300 GB 那个磁盘
  4. 特殊情况的处理:为了避免某些特殊的分区的确相差很解决,可以规定的一个原则,如果发现两个分区大小相差小于 100 GB 则报错不要库容,避免扩容错磁盘。
def expand_disk():
    """
    扩容磁盘,选择一个磁盘进行扩容
    这里的关键是怎么选中磁盘,有一个思路是获取当前的分区,拿着分区大小去跟磁盘大小对比,一般磁盘大小会比分区稍微
    大一些,但是比较接近,这样就可以对应上,但是如果多个分区大小一致就不能使用这个方式,比如win里面D盘和E盘都是200G
    则无法匹配到实际的磁盘
    :return:
    """
    vm_uuid = '564da6fb-8ed5-f765-da86-238c1dfbe934'
    partition_size_kb = 200 * 1024 * 1024
    add_size_gb = 300

    <span class="k">with</span> <span class="n">VMwareManager</span><span class="p">(</span><span class="n">VMWARE_HOST</span><span class="p">,</span> <span class="n">VMWARE_USERNAME</span><span class="p">,</span> <span class="n">VMWARE_PASSWORD</span><span class="p">,</span> <span class="n">VMWARE_PORT</span><span class="p">)</span> <span class="k">as</span> <span class="n">vm_manager</span><span class="p">:</span>
        <span class="n">vm</span> <span class="o">=</span> <span class="n">vm_manager</span><span class="o">.</span><span class="n">get_vm_by_uuid</span><span class="p">(</span><span class="n">vm_uuid</span><span class="p">)</span>

        <span class="c1"># 磁盘扩容一般要关机进行</span>
        <span class="c1"># 可以手动关机也可以自动关机,一般在ITSM流程中需要用户手动关机,减少变更带了的业务风险</span>
        <span class="c1"># vm_manager.vm_power_off(vm)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">check_vm_is_power_off</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>

        <span class="c1"># 变更前查询当前资源和状态</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_power_state</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_disks</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>

        <span class="c1"># 清理全部快照</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">delete_all_snatshots</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>

        <span class="c1"># 扩容磁盘,先使用一定条件查询到要扩容的磁盘</span>
        <span class="n">disk</span> <span class="o">=</span> <span class="n">vm_manager</span><span class="o">.</span><span class="n">get_disk_by_check_disk_size</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="n">check_size_kb</span><span class="o">=</span><span class="n">partition_size_kb</span><span class="p">)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">expand_disk_by_add_size</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="n">disk</span><span class="p">,</span> <span class="n">add_size_gb</span><span class="o">=</span><span class="n">add_size_gb</span><span class="p">)</span>

        <span class="c1"># 开机</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">vm_power_on</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>

        <span class="c1"># 变更后查询当前资源和状态</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_disks</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>
        <span class="n">vm_manager</span><span class="o">.</span><span class="n">print_power_state</span><span class="p">(</span><span class="n">vm</span><span class="p">)</span>




注意事项:

  • 磁盘扩容前需要删除虚拟机所有快照
  • 在未知具体磁盘的情况下,如何准确找到要扩容的磁盘是关键点

向 ChatGPT 提问 {#向-chatgpt-提问}

使用 Python 操作 VMware 最简单的做法是向 ChatGPT 提问,让它写代码,你去调试,基本可以满足大部分需求,而且代码有效率极高。

赞(1)
未经允许不得转载:工具盒子 » 使用Python SDK操作VMware进行虚拟机创建和配置变更