Automating VMware vSphere API Administration Tasks Using Python

image

Our company is actively using the virtualization platform VMware vSphere. In it live product test environments, demonstration stands, emulators of various customer infrastructures and other equally important “virtual machines”. Despite the sufficient capacity of our infrastructure, a large number of people have access to manage virtual machines constantly leads to conflicts and reduced farm productivity. The separation of pools between departments (engineers, testers, sales and developers) does not completely solve the problem, therefore, it is periodically necessary to figure out who bothers everyone and who ate all the resources. With the number of virtual machines far over a hundred, doing this manually is sometimes problematic, so we learned how to use the API. VMware vSphere has a rather rich API, which is undeservedly poorly covered on Habré, although the application is quite wide.

This article will give examples of interactions in admin tasks using Python.

For Python, there is a library called pyVmomi from VMware itself.

  • Github
  • VMware vSphere API Reference

Training

In the project folder, create a configuration file config.txt the following content:

[VSphere]

host = 10.10.1.2
user = admin @ domain
pwd = password

To read it, use the module configparser.

config = configparser.ConfigParser ()
config.read ("config.txt")

To connect to the sphere, methods are used pyVim.connect.SmartConnect and pyVim.connect.SmartConnectNoSSL. The second is for self-signed certificates.

from pyVim.connect import SmartConnectNoSSL
connection = SmartConnectNoSSL (** config["VSphere"])

List of machines locally on datastores

Suppose the datastore runs out of space. We will solve this problem now. The goal is to get a list of virtual machines sorted in descending order of occupied space on the datastores. Also print the maximum file size to which the virtual machine disk can grow, and the amount of space used in the guest system.

You can get a list of virtual machines as follows:

from pyVmomi import vim

def get_all_vms ():
    content = connection.content
    container = content.viewManager.CreateContainerView (content.rootFolder, [vim.VirtualMachine], True)
    return [VirtualMachine(managed_object_ref) for managed_object_ref in container.view]

As you can see, a list of class objects is returned Virtualmachine. Now we are implementing it:

class VirtualMachine:
    def __init __ (self, machine_object):
        self.vm = machine_object

    @property
    def name (self):
        return self.vm.name

    @property
    def provisioned_space (self):
        return int (self.vm.summary.storage.committed + self.vm.summary.storage.uncommitted) / 1024 ** 3

    @property
    def guest_disk_usage (self):
        return sum ([int(i.capacity - i.freeSpace) for i in self.по размеру снапшотаvm.summary.vm.guest.disk]) / 1024 ** 3

    @property
    def usage_storage (self):
        return int (self.vm.summary.storage.committed) / 1024 ** 3

    def __repr __ (self):
        return "{} {: .2f} {: .2f} {: .2f}". format (self.name, self.provisioned_space,
                                                   self.guest_disk_usage, self.usage_storage)

Data output already depends on the need. The simplest thing is to output to the console:

for virtual_machine in sorted (get_all_vms (), key = lambda vm: vm.usage_storage, reverse = True):
    print (virtual_machine)

Sizes and number of snapshots

Sized the size of virtual machines. Suppose we want to know how many snapshots each virtual machine has and how much space they take.

The logic of the previous example is preserved, only now our class Virtualmachine will look like this:

class VirtualMachine:
    def __init __ (self, machine_object):
        self.vm = machine_object
        self.snapshot_count, self.snapshot_size = self._snapshot_info ()

    @property
    def name (self):
        return self.vm.name

    def _snapshot_info (self):
        disk_list = self.vm.layoutEx.file
        size = 0
        count = 0
        for disk in disk_list:
            if disk.type == 'snapshotData':
                size + = disk.size
                count + = 1
            ss_disk = re.search ('0000  d  d', disk.name)
            if ss_disk:
                size + = disk.size
        return count, size / 1024 ** 3

    def __repr __ (self):
        return "{} {: .2f} {}". format (self.name, self.snapshot_size, self.snapshot_count)

And the output will be sorted by size or quantity:

for virtual_machine in sorted (get_all_vms (), key = lambda vm: vm.snapshot_size, reverse = True):
    print (virtual_machine)

Snapshot Recovery

Since we are talking about snapshots, we’ll talk about their recovery.

The hypothetical task is to restore the last created snapshots, in the name of which there is a line infra.

To restore snapshot, you need to create a task RevertToSnapshot_Task ().

First we get the necessary list of cars:

def get_vms (part_of_name):
    content = connection.content
    container = content.viewManager.CreateContainerView (content.rootFolder, [vim.VirtualMachine], True)
    return [managed_object_ref for managed_object_ref in container.view if part_of_name in managed_object_ref.name]

To get the last snapshot created, return the last element of the list vm.snapshot.rootSnapshotListsorted by field createTime:

def get_last_snapshot (vm):
    try:
        return sorted (vm.snapshot.rootSnapshotList, key = lambda snap: snap.createTime)[-1]
    except AttributeError:
        return none

Now we can restore this snapshot:

def restore_snapshot (snaphot_obj):
    task = snaphot_obj.snapshot.RevertToSnapshot_Task ()
    WaitForTask (task, connection)

Now combine everything:

part_of_name = "infra"
for vm in get_vms (part_of_name):
    last_snapshot = get_last_snapshot (vm)
    if last_snapshot:
        restore_snapshot (last_snapshot)

List on / off

To shut down the virtual machine, you must create a task PowerOffVM_Task ().

We write the function to turn off the machine, if it is turned on:

def poweroff_if_enabled (vm):
    if vm.runtime.powerState == vim.VirtualMachinePowerState.poweredOn:
        vm.PowerOffVM_Task ()

The resulting script:

part_of_name = "infra"
for vm in get_vms (part_of_name):
    poweroff_if_enabled (vm)

This shutdown of the machine will be forced. It would be much more correct to call the task ShutdownGuest ():

def shutdown_guest (vm):
    if vm.runtime.powerState == vim.VirtualMachinePowerState.poweredOn:
        vm.ShutdownGuest ()

In the end, I would like to give some more useful links:

  • pyvmomi samples – examples from VMware itself

  • pyvmomi community samples – a repository with community usage examples of the library

  • govmomi is a package for the goland language. Kubernetes uses it

  • rbvmomi – ruby ​​interface for vSphere API

If the topic is of interest, we are ready to continue it and tell you how to automate the deployment of the application from pushing to Git to creating a virtual machine with a working instance.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *