VMmanager, управление инфраструктурой через VMmanager API и Ansible

от автора

Привет, Хабр! Статья будет посвящена любимому мной IaC. Чтобы ввести в курс дела, кратко расскажу про VMmanager и текущую реализацию продукта. Затронем варианты, как можно работать с VMmanager с подходом Infrastructure as Code, а основная часть — про развертывание платформы VMmanager и управление виртуальными машинами в ней с помощью Ansible.

О платформе VMmanager

Наверняка вы уже знаете, что такое VMmanager. Это платформа управления виртуализацией. Она имеет версии VMmanager Hosting и VMmanager Infrastructure — под разные цели использования.

Версия

Hosting

Infrastructure

Назначение

— ориентирована на потребности хостинг-провайдеров

— ориентирована на потребности владельцев IT-инфраструктур

Состав

— базовая функциональность платформы
— возможность брендирования

— базовая функциональность платформы
— дополнительные функции

Дополнительно

— регистрация в Едином реестре российских программ для электронных вычислительных машин и баз данных
— поддержка ОС Astra Linux, сертифицированной Федеральной службой по техническому и экспортному контролю (ФСТЭК России)

VMmanager — один из продуктов ISPsystem, он имеет интеграцию с другими продуктами, на схеме кратко и просто представлена их взаимосвязь.

Я буду работать с VMmanager Infrastructure.

IaC-решения

Для реализации подхода Infrastructure as Code в работе с VMmanager у нас есть сценарий развертывания платформы с помощью Ansible, примеры управления инфраструктурой через провайдер Terraform и работа с платформой с использованием VMmanager API. Все это представлено в документации.

По работе с Terraform уже была подробная статья. Поэтому сосредоточимся на Ansible. С помощью готового сценария мы развернем платформу, посмотрим, что из себя представляет сценарий (спойлер: набор плейбуков с задачами, использующими модуль ansible.builtin.uri). А для управления виртуальными машинами на платформе я погружусь в VMmanager API и напишу собственный модуль на Python.

Управление инфраструктурой через VMmanager API и Ansible

Развертывание платформы с помощью Ansible

Начнем с подготовки серверов для платформы VMmanager, понадобится Astra Linux версии 1.8.1 уровня защиты «Орел». У меня есть такой образ, его я и буду разворачивать в Yandex Cloud. Узел кластера для тестирования можно не разворачивать: в VMmanager для таких целей можно настроить кластер-заглушку, это нужно сделать уже после создания кластера.

Настройку серверов для платформы и узла кластера я не буду приводить в статье по двум причинам: во-первых, в документации очень подробно и точно описаны шаги — можно смело по ним идти, все получится; во-вторых, тема статьи о другом и будет неуместно сюда из документации репостить объемный материал. Но приведу несколько замечаний, которые при аналогичном развертывании на виртуальной машине Yandex Cloud могут быть полезны.

Примечание к настройке сервера

Из всех пунктов мне понадобилось только отредактировать /etc/apt/sources.list. Остальное я оставил по умолчанию.

Раздел «Настройка подключения к узлам кластера» можно пропустить, если настраиваем кластер-заглушку.

Переходим к развертыванию VMmanager. В документации есть step-by-step по установке VMmanager с помощью Ansible. Но, поскольку шагов не так много и это уже про IaC, я перепишу в статью все шаги, немного добавив пояснений.

Для начала стоит сказать, что для активации платформы понадобится лицензия. У меня есть триал, получил за красивые глаза, но это не обязательный навык для работы с VMmanager. 

Все продукты ISPsystem доступны для бесплатного тестирования. По запросу на сайте получите бесплатный триал или доступ к демостенду. Также можно заказать демонстрацию интересующих платформ на сайте: DCImanager, VMmanager, BILLmanager, DNSmanager.

Нас все еще интересует триал для VMmanager.

Переходим к установке платформы.

  1. Установим Ansible на ПК, с которого будет запускаться установка платформы. Порядок установки в официальной документации Ansible.

  2. На ПК с Ansible:

    Если на ПК не установлена утилита curl, установите ее: 

    dnf install curl || apt install curl

    Скачайте сценарии установки: 

    curl https://download.ispsystem.com/extras/ansible/vmmanager6_common.tar.gz

    Создайте SSH-ключ и скопируйте его на сервер платформы. Подробнее — в статье про SSH-протокол.

  3. Создадим директорию для сценариев установки: 

    mkdir vm6_ansible

  4. Распакуем в директорию архив со сценариями: 

    tar xzf vmmanager6_common.tar.gz -C vm6_ansible/

  5. Перейдем в созданную директорию:

    cd vm6_ansible

  6. Укажем параметры установки в секции vars файла vmmanager6.yml:

  vars:     vmi_first_username: "admin@example.com"     vmi_first_password: "q1w2e3r4"     vmmanager6_license_token: "..........:..................."     vmi_domain: "{{ ansible_ssh_host }}" # Поскольку я разворачивал виртуальную машину в Yandex Cloud,  # параметры сети берем по факту, в которой разворачиваем.      vmi_network: "10.177.91.0/24"     vmi_network_gateway: "10.177.91.1"     vmi_network_note: "some network notes"     vmi_pool_name: "some_pool"     vmi_pool_note: "testing pool"     vmi_cluster_name: "new_cluster"     vmi_time_zone: "UTC"     vmi_cluster_note: "some cluster note"     vmi_domain_template: ".example.com" # Я указал для check ip из настроек dns, но он нам не понадобится в рамках теста.     vmi_node_check_ip: "10.177.181.142" # Мы далее закомментируем все, что касается ssl и бэкапа, поэтому следующие # настройки можно не трогать.     vmi_certificate: "-----BEGIN CERTIFICATE-----\nMIIDkT……7s=\n-----END CERTIFICATE-----\n"     vmi_certificate_key: "-----BEGIN PRIVATE KEY-----\nMI….BlXDeTd\n-----END PRIVATE KEY-----\n"     vmi_certificate_ca: ""     vmi_backup_ip: "10.177.91.71"     vmi_backup_user: "root"     vmi_backup_password: "q1w2e3p4"     vmi_backup_path: "/backup"
  1. Мы не планируем подключать SSL-сертификат, закомментируем в файле vmmanager6.yml строку:

    #    - include_tasks: cert.yml

  2. Резервное копирование платформы мы также не планируем, закомментируем в файле vmmanager6.yml строку:

    #    - include_tasks: backup.yml

  3. Запустим установку:

    ansible-playbook -i <IP>, -u root vmmanager6.yml

    Вместо <IP> укажите ip своей виртуальной машины.

Посмотрим немного глубже в Ansible-сценарий установки VMmanager. В распакованном архиве мы видим набор плейбуков.

Основной плейбук vmmanager6.yml, в который подключаются по порядку остальные плейбуки для установки.

--- - name: Install VMmanager 6 playbook   hosts: all   debugger: on_failed   vars:     vmi_first_username: "admin@example.com"     vmi_first_password: "q1w2e3r4"     vmmanager6_license_token: ".............:................"     vmi_domain: "{{ ansible_ssh_host }}"     vmi_network: "10.177.91.0/24"     vmi_network_gateway: "10.177.91.1"     vmi_network_note: "some network notes"     vmi_pool_name: "some_pool"     vmi_pool_note: "testing pool"     vmi_cluster_name: "new_cluster"     vmi_time_zone: "UTC"     vmi_cluster_note: "some cluster note"     vmi_domain_template: ".example.com"     vmi_node_check_ip: "10.177.181.142"     vmi_certificate: "-----BEGIN CERTIFICATE-----\nMIIDkT……7s=\n-----END CERTIFICATE-----\n"     vmi_certificate_key: "-----BEGIN PRIVATE KEY-----\nMI….BlXDeTd\n-----END PRIVATE KEY-----\n"    vmi_certificate_ca: ""     vmi_backup_ip: "10.177.91.71"     vmi_backup_user: "root"     vmi_backup_password: "q1w2e3p4"     vmi_backup_path: "/backup"   tasks:     - include_tasks: remove_and_install.yml      - name: First time token       uri:         url: "https://{{ vmi_domain }}/auth/v4/public/token"         method: POST         body_format: json         status_code: [200,201,503]         return_content: yes         body:           email: "{{ vmi_first_username }}"           password: "{{ vmi_first_password }}"         validate_certs: no       register: first_token       retries: 3       delay: 30       until: first_token.status == 201      - name: make ses6 a fact       set_fact:         ses6: "{{ (first_token.content|from_json).token }}"      - include_tasks: first_run.yml #   - include_tasks: cert.yml     - include_tasks: setup_ip.yml     - include_tasks: cluster.yml     - include_tasks: storage.yml #   - include_tasks: backup.yml

Посмотрим на один из плейбуков cluster.yml, чтобы разобраться, что происходит при установке. Мы видим, что сценарий построен на использовании модуля ansible.builtin.uri.

--- - name: Set up cluster   uri: # В документации API можем посмотреть url для создания кластера, и другие url, # а также параметры, которые мы можем передать.     url: "https://{{ vmi_domain }}/vm/v3/cluster"     method: POST     body_format: json     status_code: [200, 401, 409, 500, 503]     headers:       Cookie: "ses6={{ ses6 }}"       x-xsrf-token: "{{ ses6 }}"     body:       name: "{{ vmi_cluster_name }}"       virtualization_type: "kvm"       time_zone: "{{ vmi_time_zone }}"       dns_servers:         - "1.1.1.1"       comment: "{{ vmi_cluster_note }}"       os:         - 1       iso_enabled: false       manage_disk_enabled: false       domain_template: "{{ vmi_domain_template }}"       domain_change_allowed: false       overselling: 1       host_per_node_limit: -1       host_distribution_policy: "spread"       host_filter: []       backup_locations: []       image_storage_path: "/image"       os_storage_path: "/share"       datacenter_type: "common"       interfaces:         - interface: 0           ippool: [ 1 ]       node_network:         gateway: "{{ vmi_node_check_ip }}"         timeout: 300       vxlan_mode: "disabled"     validate_certs: no   register: cluster   retries: 3   delay: 10   until: cluster.status == 200

С помощью переменных мы ранее задали все нужные значения, которые подтягиваются при выполнении задач. ansible.builtin.uri отправляет запросы для скачивания установочных файлов VMmanager API и инициализации установки. А далее происходит магия… Обращение к VMmanager API для создания кластера и его настройки. 

Посмотрев на все задачи из сценария, можно увидеть, что работа с VMmanager API несложная, документации соответствует, такой сценарий вполне можно составить самостоятельно.

Далее нужно создать кластер в VMmanager — в документации пошагово представлено, как это сделать через веб-интерфейс, а затем настроить заглушку для кластера. Эти шаги я тоже оставляю за пределами статьи — по тем же причинам, что и настройка серверов.

По заглушке кластера есть небольшое примечание

Команда должна быть:

update vm_cluster set virtualization_type = 'dummy' where id = <cluster_id>; 

Где ‘dummy’ в одинарных кавычках.

Управление ВМ с помощью модуля ansible.builtin.uri

У меня готова платформа VMmanager, кластер настроен и подключен, самое время попробовать в IaC — будем создавать виртуальные машины. Научимся с простого варианта — с использованием модуля ansible.builtin.uri. Поскольку VMmanager API позволяет довольно гибко работать с платформой, будет полезно отработать быстрый вариант работы с API, если захочется использовать разные возможности управления. 

Отмечу, что данный способ имеет определенный нюанс: мы не получаем контроль идемпотентности нашего Infrastructure as Code. VMmanager API обеспечивает идемпотентность только по id, что может быть удобно, когда мы не хотим иметь ограничение в именах виртуальных машин, но модуль ansible.builtin.uri это не обеспечит. В POST-запросе нельзя указать id, то есть создать виртуальную машину с конкретным id. 

С точки зрения подхода идеально, когда за идемпотентность отвечает выбранный нами инструмент, а это Ansible. В нашем случае можно выбрать между скоростью разработки инфраструктурного кода и каноничностью принципов.

Для управления виртуальными машинами нам будет достаточно переиспользовать файл с переменными и создать сценарий. Сеть и пул IP-адресов уже созданы при развертывании платформы, учетную запись рекомендую создать отличную от админской, пользователя создадим из веб-интерфейса. А далее обратимся к документации API.

Заполним основной файл сценария — с переменными, авторизацией и вызовом сценария создания виртуальной машины.

--- - name: Install VMmanager 6 playbook   hosts: all   debugger: on_failed   vars:     vmi_first_username: "vm@example.com"     vmi_first_password: "uA2sW2nT9czV"     vmi_domain: "{{ ansible_ssh_host }}"   tasks:     - name: First time token       uri:         url: "https://{{ vmi_domain }}/auth/v4/public/token"         method: POST         body_format: json         status_code: [200,201,503]         return_content: yes         body:           email: "{{ vmi_first_username }}"           password: "{{ vmi_first_password }}"         validate_certs: no       register: first_token       retries: 3       delay: 30       until: first_token.status == 201      - name: make ses6 a fact       set_fact:         ses6: "{{ (first_token.content|from_json).token }}"      - include_tasks: vm.yml

И напишем сам сценарий работы с виртуальными машинами.

– # Для начала посмотрим, какие же виртуальные машины уже развернуты,  # указанный url выдаст все, без фильтрации. - name: Get up vm   uri:     url: "https://{{ vmi_domain }}/vm/v3/host"     method: GET     body_format: json     status_code: [200, 401, 409, 500, 503]     headers:       Cookie: "ses6={{ ses6 }}"       x-xsrf-token: "{{ ses6 }}"     validate_certs: no   # Для тестирования мы передаем минимальный набор параметров. - name: Set up vm   uri:     url: "https://{{ vmi_domain }}/vm/v3/host"     method: POST     body_format: json     status_code: [200, 401, 409, 500, 503]     headers:       Cookie: "ses6={{ ses6 }}"       x-xsrf-token: "{{ ses6 }}"     body:       name: My_vm       password: vmsecret # Для cluster, ipv4_pool, os передаем id, в веб-интерфейсе все они указаны,  # можно посмотреть.        cluster: 1       os: 1       ram_mib: 512       hdd_mib: 5000       cpu_number: 1       ipv4_pool: [1]     validate_certs: no

Управление ВМ с помощью своего модуля Ansible

Настало время перейти к технически интересному варианту, полностью соответствующему подходу Infrastructure as Code. Я напишу собственный модуль на Python для создания виртуальных машин в VMmanager. Грамотно написанный модуль обеспечит на стороне Ansible идемпотентность нашего инфраструктурного кода.

Если быть точными, то мы напишем два модуля vm_info, vm и два вспомогательных модуля auth_utils и info_utils. Это будет полностью соответствовать рекомендациям Ansible, а именно выносить сбор информации, не вносящий изменения в инфраструктуру, в модуль info, общий код модулей — во вспомогательные модули.

Начнем с модуля auth_utils. Он нужен для авторизации, при вызове других модулей мы получаем токен и возвращаем его в вызвавший авторизацию модуль.

# -*- coding: utf-8 -*-  import json import time import urllib3 from ansible.module_utils.urls import open_url, SSLValidationError  urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)  def get_auth_token(base_url, email, password, retries=3, delay=30, validate_certs_param=None, module=None):     """     Получение токена авторизации через API VMI.      :param base_url: Базовый URL (например, https://vmi.example.com)     :param email: Логин пользователя     :param password: Пароль     :param retries: Количество попыток     :param delay: Задержка между попытками     :param validate_certs_param: строка 'no' или None (если не передан параметр)     :param module: ссылка на AnsibleModule для вывода ошибок     :return: токен сессии     """     url = f"{base_url}/auth/v4/public/token"     headers = {         'Content-Type': 'application/json'     }     body = json.dumps({         "email": email,         "password": password     })      last_exception = None     for attempt in range(1, retries + 1):         try:             kwargs = {                 "url": url,                 "method": "POST",                 "headers": headers,                 "data": body,             }              if validate_certs_param == "no":                 kwargs["validate_certs"] = False              response = open_url(**kwargs)              if response.getcode() in (200, 201):                 result = json.loads(response.read())                 return result.get("token")          except (SSLValidationError) as e:             last_exception = e             if module:                 module.warn(f"Попытка {attempt} не удалась: {e}")         time.sleep(delay)      if module:         module.fail_json(msg="Не удалось получить токен после нескольких попыток", exception=str(last_exception))     else:         raise Exception(f"Ошибка получения токена: {last_exception}")

Далее vm_info. Мы могли бы ограничиться только вспомогательным модулем, но будет более показательно реализовать модуль info полностью, тем более что он будет содержать минимальное количество базового кода.

#!/usr/bin/python  from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.auth_utils import get_auth_token from ansible.module_utils.info_utils import get_vmi_info  DOCUMENTATION = r''' --- module: vmi_info short_description: Получение информации о хосте по имени из VMI API description:   - Получает токен через auth_utils.get_auth_token, затем делает GET запрос через info_utils.get_vmi_info options:   vmi_domain:     description: Домен VMI без https://     required: true     type: str   vmi_first_username:     description: Email пользователя     required: true     type: str   vmi_first_password:     description: Пароль пользователя     required: true     type: str   name:     description: Имя хоста для фильтрации     required: true     type: str   validate_certs:     description:       - Отключает проверку SSL-сертификатов ('no' для отключения).     required: false     type: str '''  EXAMPLES = r''' - name: Получить информацию о хосте   vm_info:     vmi_domain: vmi.example.com     vmi_first_username: admin@example.com     vmi_first_password: secret     name: my-host     validate_certs: no   register: result '''  def main():     module = AnsibleModule(         argument_spec=dict(             vmi_domain=dict(required=True, type='str'),             vmi_first_username=dict(required=True, type='str'),             vmi_first_password=dict(required=True, type='str'),             name=dict(required=True, type='str'),             validate_certs=dict(required=False, type='str'),         )     )      base_url = f"https://{module.params['vmi_domain']}"     email = module.params['vmi_first_username']     password = module.params['vmi_first_password']     name = module.params['name']     validate_certs = module.params.get('validate_certs')      # Получаем токен     token = get_auth_token(         base_url=base_url,         email=email,         password=password,         validate_certs_param=validate_certs,         module=module     )      # Формируем endpoint     endpoint = f"/vm/v3/host?where=(name+EQ+'{name}')"      # Получаем информацию     data = get_vmi_info(base_url, token, endpoint, validate_certs, module)      module.exit_json(changed=False, finder=data.get('size', []))   if __name__ == '__main__':     main()

Теперь перейдем к вспомогательному модулю info_utils. Он нужен для реализации идемпотентности на стороне Ansible-модуля создания виртуальных машин. Через этот модуль мы будем получать информацию о текущей инфраструктуре.

# -*- coding: utf-8 -*-  from ansible.module_utils.urls import open_url import json  def get_vmi_info(base_url, token, endpoint, validate_certs, module):     """     Делает GET-запрос к API по endpoint с использованием токена.      :param base_url: базовый URL с https     :param token: токен авторизации ses6     :param endpoint: путь API начиная с /, например /vm/v3/host?where=(name+...     :param validate_certs: 'no' или None     :param module: объект AnsibleModule для fail_json     :return: распарсенный JSON из ответа     """     url = f"{base_url}{endpoint}"     headers = {         'Accept': 'application/json',         'Cookie': f'ses6={token}',         'x-xsrf-token': token,     }      kwargs = {         'url': url,         'method': 'GET',         'headers': headers,     }     if validate_certs == 'no':         kwargs['validate_certs'] = False      try:         response = open_url(**kwargs)         return json.loads(response.read())     except Exception as e:         module.fail_json(msg=f"Ошибка при GET-запросе к {url}", error=str(e))

Последним модулем будет vm. Запрашивая информацию о текущей инфраструктуре, мы будем сравнивать ее параметры со входными параметрами при вызове модуля и в случае совпадения текущего состояния и желаемого — не производить изменения, отдавая changed False.

#!/usr/bin/python  from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.auth_utils import get_auth_token from ansible.module_utils.info_utils import get_vmi_info from ansible.module_utils.urls import open_url import ssl import http.client import json from urllib.parse import urlparse  DOCUMENTATION = r''' --- module: vm short_description: Управление виртуальной машиной в VM description:   - Получает токен через get_auth_token.   - Проверяет наличие VM по имени через get_vmi_info.   - Создает VM если state=present и VM не существует. options:   vmi_domain:     description: Домен VMI без https://     required: true     type: str   vmi_first_username:     description: Email пользователя     required: true     type: str   vmi_first_password:     description: Пароль пользователя     required: true     type: str   state:     description: Состояние VM     required: false     default: present     choices: [present, absent]     type: str   name:     description: Имя виртуальной машины     required: true     type: str   password:     description: Пароль для VM     required: true     type: str   cluster:     description: ID кластера     required: true     type: int   os:     description: ID операционной системы     required: true     type: int   ram_mib:     description: RAM в Мибибайтах     required: true     type: int   hdd_mib:     description: HDD в Мибибайтах     required: true     type: int   cpu_number:     description: Количество CPU     required: true     type: int   ipv4_pool:     description: Список ID пулов IPv4     required: true     type: list     elements: int   validate_certs:     description:       - Отключает проверку SSL-сертификатов ('no' для отключения).     required: false     type: str '''  EXAMPLES = r''' - name: Создать VM если отсутствует   vm:     vmi_domain: vmi.example.com     vmi_first_username: admin@example.com     vmi_first_password: secret     name: My_vm     password: vmsecret     cluster: 1     os: 1     ram_mib: 512     hdd_mib: 5000     cpu_number: 1     ipv4_pool: [1]     validate_certs: no     state: present '''  def create_vm(base_url, token, vm_spec, validate_certs, module):     url = f"{base_url}/vm/v3/host"     body = json.dumps(vm_spec)     headers = {         'Content-Type': 'application/json',         'Cookie': f'ses6={token}',         'x-xsrf-token': token,     }     body = json.dumps(vm_spec)     kwargs = {         'url': url,         'method': 'POST',         'headers': headers,         'data': body,     }     if validate_certs == 'no':         kwargs['validate_certs'] = False      try:         response = open_url(**kwargs)         response_body = response.read().decode('utf-8')         if response.getcode() in (200, 201):             return json.loads(response_body)         else:             module.fail_json(msg=f"Ошибка создания VM. HTTP {response.getcode()}", response_body=response_body)     except Exception as e:         module.fail_json(msg="Ошибка при создании VM, проверьте статус узла кластера", kwargs=kwargs, error=str(e))  def run(base_url, token, state, validate_certs, module):      vm_name = module.params['name']     vm_password = module.params['password']     cluster = module.params['cluster']     os_id = module.params['os']     ram_mib = module.params['ram_mib']     hdd_mib = module.params['hdd_mib']     cpu_number = module.params['cpu_number']     ipv4_pool = module.params['ipv4_pool']      endpoint = f"/vm/v3/host?where=(name+EQ+'{vm_name}')"     vmi_info = get_vmi_info(base_url, token, endpoint, validate_certs, module).get('size', 0)      if state == 'present':         if vmi_info != 0:             # VM существует, ничего не меняем             module.exit_json(changed=False, finder=vmi_info)         else:             # Создаем VM             vm_spec = {                 "name": vm_name,                 "password": vm_password,                 "cluster": cluster,                 "os": os_id,                 "ram_mib": ram_mib,                 "hdd_mib": hdd_mib,                 "cpu_number": cpu_number,                 "ipv4_pool": ipv4_pool,             }             created_vm = create_vm(base_url, token, vm_spec, validate_certs, module)             module.exit_json(changed=True, vm=created_vm)     else:         # Поддержка state=absent можно сделать позже         module.exit_json(changed=False, msg="state=absent пока не реализован")  def main():     module = AnsibleModule(         argument_spec=dict(             vmi_domain=dict(required=True, type='str'),             vmi_first_username=dict(required=True, type='str'),             vmi_first_password=dict(required=True, type='str'),             state=dict(required=False, default='present', choices=['present', 'absent']),             name=dict(required=True, type='str'),             password=dict(required=True, type='str'),             cluster=dict(required=True, type='int'),             os=dict(required=True, type='int'),             ram_mib=dict(required=True, type='int'),             hdd_mib=dict(required=True, type='int'),             cpu_number=dict(required=True, type='int'),             ipv4_pool=dict(required=True, type='list', elements='int'),             validate_certs=dict(required=False, type='str'),         ),         supports_check_mode=False,     )      base_url = f"https://{module.params['vmi_domain']}"     email = module.params['vmi_first_username']     password_user = module.params['vmi_first_password']     state = module.params['state']     validate_certs = module.params.get('validate_certs')      # Получаем токен     token = get_auth_token(         base_url=base_url,         email=email,         password=password_user,         validate_certs_param=validate_certs,         module=module     )     # Вызов основной функции     run(base_url, token, state, validate_certs, module)  if __name__ == '__main__':     main()

Завершаем работу переработкой созданного ранее сценария управления виртуальными машинами vm.yml, заменим ansible.builtin.uri на свой модуль. Прошу не ругать за FQCN: все-таки модули мы не упаковывали в коллекцию и подгрузим их через указанные пути в переменных.

--- - name: Install VMmanager 6 playbook   hosts: all   debugger: on_failed   tasks:     - name: Get up vm       vm_info:         vmi_domain: "{{ ansible_ssh_host }}"         vmi_first_username: vm@example.com         vmi_first_password: uA2sW2nT9czV         name: My_vm         validate_certs: no      - name: Создать VM если отсутствует       vm:         vmi_domain: "{{ ansible_ssh_host }}"         vmi_first_username: vm@example.com         vmi_first_password: uA2sW2nT9czV         name: My_vm         password: vmsecret         cluster: 1         os: 1         ram_mib: 512         hdd_mib: 5000         cpu_number: 1         ipv4_pool: [1]         validate_certs: no         state: present

Для использования локальных модулей добавим пути через переменные:

export ANSIBLE_LIBRARY=/home/my_user/vm6_ansible/plugins/modules export ANSIBLE_MODULE_UTILS=/home/my_user/vm6_ansible/plugins/module_utils

И протестируем — запустим сценарий дважды, чтобы убедиться, что модуль действительно идемпотентен. Запускаем с помощью команды:

ansible-playbook --private-key /root/.ssh/private_key -i IP, -u root vm.yml

Смотрим результат:

В веб-интерфейсе платформы проверяем — действительно, модуль идемпотентен, создана одна виртуальная машина.

На этом наша работа с Infrastructure as Code, знакомство с платформой VMmanager и VMmanager API завершены. Желаю успехов в экспериментах, а также освоении новых инструментов и технологий.


ссылка на оригинал статьи https://habr.com/ru/articles/916884/