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.





Training



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



[VSphere] host=10.10.1.2 user=admin@domain pwd=password
      
      





To read it, use the configparser module.



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





To connect to the sphere, the pyVim.connect.SmartConnect and pyVim.connect.SmartConnectNoSSL methods are used. 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, the list of objects of the VirtualMachine class is returned . 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 VirtualMachine class 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 already by size or by 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 an infra line.



To restore snapshot, you need to create the RevertToSnapshot_Task () 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 vm.snapshot.rootSnapshotList list, sorted by the createTime field:



 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 need to create the PowerOffVM_Task () 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 ShutdownGuest () task:



 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:





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.



All Articles