В данной статье будут приведены примеры взаимодействия в рамках задач администрирования с помощью Python.
Для Python есть библиотека под названием pyVmomi от самой VMware.
Подготовка
В папке проекта создадим конфигурационный файл config.txt следующего содержания:
[VSphere] host=10.10.1.2 user=admin@domain pwd=password
Для его чтения используем модуль configparser.
config = configparser.ConfigParser() config.read("config.txt")
Чтобы подключиться к сфере, используются методы pyVim.connect.SmartConnect и pyVim.connect.SmartConnectNoSSL. Второй применяется для самоподписанных сертификатов.
from pyVim.connect import SmartConnectNoSSL connection = SmartConnectNoSSL(**config["VSphere"])
Список машин по месту на датасторах
Предположим, на датасторах закончилось место. Эту проблему мы сейчас будем решать. Цель — получить список виртуальных машин, отсортированный по убыванию размера занятого места на датасторах. Также выведем максимальный размер файла, до которого может вырасти диск виртуальной машины, и количество места, занятого в гостевой системе.
Получить список виртуальных машин можно следующим образом:
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]
Как можно было заметить, возвращается список объектов класса VirtualMachine. Сейчас его и реализуем:
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)
Вывод данных уже зависит от необходимости. Самое простое — вывести в консоль:
for virtual_machine in sorted(get_all_vms(), key=lambda vm: vm.usage_storage, reverse=True): print(virtual_machine)
Размеры и количество снапшотов
С размерами виртуальных машин разобрались. Предположим, мы хотим узнать, сколько снапшотов имеет каждая виртуальная машина, и сколько места они занимают.
Логика предыдущего примера сохраняется, только теперь наш класс VirtualMachine будет выглядеть так:
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('0000dd', 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)
И вывод будет отсортирован уже по размеру или по количеству:
for virtual_machine in sorted(get_all_vms(), key=lambda vm: vm.snapshot_size, reverse=True): print(virtual_machine)
Восстановление снапшота
Раз пошла речь про снапшоты, то поговорим об их восстановлении.
Гипотетическая задача — восстановить последние созданные снапшоты, в названии которых присутствует строка infra.
Для восстановления снапшота необходимо создать задачу RevertToSnapshot_Task().
Сперва получим необходимый список машин:
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]
Для получения последнего созданного снапшота вернем последний элемент списка vm.snapshot.rootSnapshotList, отсортированного по полю createTime:
def get_last_snapshot(vm): try: return sorted(vm.snapshot.rootSnapshotList, key=lambda snap: snap.createTime)[-1] except AttributeError: return None
Теперь же можем восстановить этот снапшот:
def restore_snapshot(snaphot_obj): task = snaphot_obj.snapshot.RevertToSnapshot_Task() WaitForTask(task, connection)
Теперь все объединим:
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)
Включение/выключение по списку
Для выключения виртуальной машины необходимо создать задачу PowerOffVM_Task().
Напишем функцию выключения машины, если она включена:
def poweroff_if_enabled(vm): if vm.runtime.powerState == vim.VirtualMachinePowerState.poweredOn: vm.PowerOffVM_Task()
Итоговый скрипт:
part_of_name = "infra" for vm in get_vms(part_of_name): poweroff_if_enabled(vm)
Такое выключение машины будет принудительным. Гораздо правильнее будет вызвать задачу ShutdownGuest():
def shutdown_guest(vm): if vm.runtime.powerState == vim.VirtualMachinePowerState.poweredOn: vm.ShutdownGuest()
В конце хотелось бы привести еще несколько полезных ссылок:
- pyvmomi samples — примеры от самой VMware
- pyvmomi community samples — репозиторий с примерами использования библиотеки, написанными сообществом
- govmomi — пакет для языка goland. Его использует kubernetes
- rbvmomi — ruby-интерфейс для vSphere API
Если тема вызовет интерес, мы готовы ее продолжить и рассказать, как автоматизировать развертывание приложения от пуша в Git до создания виртуальной машины с работающим инстансом.