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

В настоящее время я создаю шаблоны playbook изображений Ansible для AWS и VSphere, и я хотел бы иметь возможность определять несколько дополнительных дисков, но только если они определены с помощью переменных.

Пособие:

---
- hosts: localhost
  connection: local
  gather_facts: False

  tasks:

  - name: Launch Windows 2016 VM Instance
    vmware_guest:
      validate_certs: no
      datacenter: "{{ vm_datacenter }}"
      folder: "{{ vm_folder }}"
      name: "{{ vm_servername }}"
      state: poweredon
      template: "{{ vm_template }}"
      cluster: "{{ vm_cluster }}"
      disk:
       - size_gb: "{{ vm_disk_size0 | default(80) }}"
         type: "{{ vm_disk_type0 | default(thin) }}"
         datastore: "{{ vm_disk_datastore0 }}"
       - size_gb: "{{ vm_disk_size1 }}"
         type: "{{ vm_disk_type1 }}"
         datastore: "{{ vm_disk_datastore1 }}"
       - size_gb: "{{ vm_disk_size2 }}"
         type: "{{ vm_disk_type2 }}"
         datastore: "{{ vm_disk_datastore2 }}"
       - size_gb: "{{ vm_disk_size3 }}"
         type: "{{ vm_disk_type3 }}"
         datastore: "{{ vm_disk_datastore3 }}"
      hardware:
        memory_mb: "{{ vm_memory_mb | default(8192) }}"
        num_cpus: "{{ vm_num_cpus | default(4) }}"
      networks:
      - name: "{{ vm_network }}"
        start_connected: yes
        vlan: "{{ vm_network }}"
        device_type: vmxnet3
        type: dhcp
        domain: "{{ vm_domain }}"
      customization:
        hostname: "{{ vm_servername }}"
        orgname: Redacted
        password: "{{ winlocal_admin_pass }}"
        timezone: 255
      wait_for_ip_address: yes 
    register: vm  

Переменные:

vm_disk_datastore0: C6200_T2_FCP_3Days
vm_disk_size0: 80
vm_disk_type0: thin
vm_disk_datastore1: "C6200_T2_FCP_3Days"
vm_disk_size1: "50"
vm_disk_type1: "thin"
vm_disk_datastore2: "C6200_T2_FCP_3Days"
vm_disk_size2: "20"
vm_disk_type2: "thin"
vm_disk_datastore3: ""
vm_disk_size3: ""
vm_disk_type3: ""

Ошибка:

{
    "_ansible_parsed": false,
    "exception": "Traceback (most recent call last):\n  File \"/var/lib/awx/.ansible/tmp/ansible-tmp-1568948672.23-135785453591577/AnsiballZ_vmware_guest.py\", line 113, in <module>\n    _ansiballz_main()\n  File \"/var/lib/awx/.ansible/tmp/ansible-tmp-1568948672.23-135785453591577/AnsiballZ_vmware_guest.py\", line 105, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/var/lib/awx/.ansible/tmp/ansible-tmp-1568948672.23-135785453591577/AnsiballZ_vmware_guest.py\", line 48, in invoke_module\n    imp.load_module('__main__', mod, module, MOD_DESC)\n  File \"/tmp/ansible_vmware_guest_payload_6vidiw/__main__.py\", line 2396, in <module>\n  File \"/tmp/ansible_vmware_guest_payload_6vidiw/__main__.py\", line 2385, in main\n  File \"/tmp/ansible_vmware_guest_payload_6vidiw/__main__.py\", line 2008, in deploy_vm\n  File \"/tmp/ansible_vmware_guest_payload_6vidiw/__main__.py\", line 1690, in configure_disks\n  File \"/tmp/ansible_vmware_guest_payload_6vidiw/__main__.py\", line 1608, in get_configured_disk_size\nValueError: invalid literal for int() with base 10: ''\n",
    "_ansible_no_log": false,
    "module_stderr": "Traceback (most recent call last):\n  File \"/var/lib/awx/.ansible/tmp/ansible-tmp-1568948672.23-135785453591577/AnsiballZ_vmware_guest.py\", line 113, in <module>\n    _ansiballz_main()\n  File \"/var/lib/awx/.ansible/tmp/ansible-tmp-1568948672.23-135785453591577/AnsiballZ_vmware_guest.py\", line 105, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/var/lib/awx/.ansible/tmp/ansible-tmp-1568948672.23-135785453591577/AnsiballZ_vmware_guest.py\", line 48, in invoke_module\n    imp.load_module('__main__', mod, module, MOD_DESC)\n  File \"/tmp/ansible_vmware_guest_payload_6vidiw/__main__.py\", line 2396, in <module>\n  File \"/tmp/ansible_vmware_guest_payload_6vidiw/__main__.py\", line 2385, in main\n  File \"/tmp/ansible_vmware_guest_payload_6vidiw/__main__.py\", line 2008, in deploy_vm\n  File \"/tmp/ansible_vmware_guest_payload_6vidiw/__main__.py\", line 1690, in configure_disks\n  File \"/tmp/ansible_vmware_guest_payload_6vidiw/__main__.py\", line 1608, in get_configured_disk_size\nValueError: invalid literal for int() with base 10: ''\n",
    "changed": false,
    "module_stdout": "",
    "rc": 1,
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error"
}

Идея в том, что если переменная не определена при запуске задания, она будет пропущена модулем vm_guest.

Это лучший метод? Может ли кто-нибудь предложить успешный путь вперед?

Обновление: вероятно, лучшим методом было бы создание экземпляра, а затем использование vm_guest_disk для добавления дополнительных дисков с помощью метода, предложенного ниже. Этот модуль доступен в версии 2.8.

Наша версия Tower - 2.7.9, поэтому я собираюсь использовать более подробный метод множественных вызовов vm_guest через переменную disk_num:

Переменные

num_disks: 0
vm_cluster: C6200_NPE_PC_ST
vm_datacenter: DC2
vm_disk_datastore0: C6200_T2_FCP_3Days
vm_disk_datastore1: ''
vm_disk_datastore2: ''
vm_disk_datastore3: ''
vm_disk_datastore4: ''
vm_disk_size0: 80
vm_disk_type0: thin
vm_disk_type1: ''
vm_disk_type2: ''
vm_disk_type3: ''
vm_disk_type4: ''
vm_domain: corp.local
vm_folder: /DC2/vm/ap-dev
vm_hostname: xyzvmserver.corp.local
vm_memory_mb: 16000
vm_network: C6200_10.110.64.0_24_VL1750
vm_num_cpus: 4
vm_servername: server05
vm_template: Windows2016_x64_AN_ESX_v1.1

Пособие:

---
- hosts: localhost
  connection: local
  gather_facts: False

  tasks:

  - name: Launch Windows 2016 VM Instance - No additional Disk
    vmware_guest:
      validate_certs: no
      datacenter: "{{ vm_datacenter }}"
      folder: "{{ vm_folder }}"
      name: "{{ vm_servername }}"
      state: poweredon
      template: "{{ vm_template }}"
      cluster: "{{ vm_cluster }}"
      disk:
      - size_gb: "{{ vm_disk_size0 }}"
        type: "{{ vm_disk_type0 }}"
        datastore: "{{ vm_disk_datastore0 }}"
      hardware:
        memory_mb: "{{ vm_memory_mb | default(8192) }}"
        num_cpus: "{{ vm_num_cpus }}"
      networks:
      - name: "{{ vm_network }}"
        start_connected: yes
        vlan: "{{ vm_network }}"
        device_type: vmxnet3
        type: dhcp
        domain: "{{ vm_domain }}"
      customization:
        hostname: "{{ vm_servername }}"
        orgname: redacted
        password: "{{ winlocal_admin_pass }}"
        timezone: 255
      wait_for_ip_address: yes 
    register: vm
    when: num_disks == 0

  - name: Launch Windows 2016 VM Instance 1 Additional Disk
    vmware_guest:
      validate_certs: no
      datacenter: "{{ vm_datacenter }}"
      folder: "{{ vm_folder }}"
      name: "{{ vm_servername }}"
      state: poweredon
      template: "{{ vm_template }}"
      cluster: "{{ vm_cluster }}"
      disk:
      - size_gb: "{{ vm_disk_size0 }}"
        type: "{{ vm_disk_type0 }}"
        datastore: "{{ vm_disk_datastore0 }}"
      - size_gb: "{{ vm_disk_size1 }}"
        type: "{{ vm_disk_type1 }}"
        datastore: "{{ vm_disk_datastore1 }}"
      hardware:
        memory_mb: "{{ vm_memory_mb | default(8192) }}"
        num_cpus: "{{ vm_num_cpus }}"
      networks:
      - name: "{{ vm_network }}"
        start_connected: yes
        vlan: "{{ vm_network }}"
        device_type: vmxnet3
        type: dhcp
        domain: "{{ vm_domain }}"
      customization:
        hostname: "{{ vm_servername }}"
        orgname: redacted
        password: "{{ winlocal_admin_pass }}"
        timezone: 255
      wait_for_ip_address: yes 
    register: vm
    when: num_disks == 1

  - name: Launch Windows 2016 VM Instance 2 Additional Disks
    vmware_guest:
      validate_certs: no
      datacenter: "{{ vm_datacenter }}"
      folder: "{{ vm_folder }}"
      name: "{{ vm_servername }}"
      state: poweredon
      template: "{{ vm_template }}"
      cluster: "{{ vm_cluster }}"
      disk:
      - size_gb: "{{ vm_disk_size0 }}"
        type: "{{ vm_disk_type0 }}"
        datastore: "{{ vm_disk_datastore0 }}"
      - size_gb: "{{ vm_disk_size1 }}"
        type: "{{ vm_disk_type1 }}"
        datastore: "{{ vm_disk_datastore1 }}"
      - size_gb: "{{ vm_disk_size2 }}"
        type: "{{ vm_disk_type2 }}"
        datastore: "{{ vm_disk_datastore2 }}"
      hardware:
        memory_mb: "{{ vm_memory_mb | default(8192) }}"
        num_cpus: "{{ vm_num_cpus }}"
      networks:
      - name: "{{ vm_network }}"
        start_connected: yes
        vlan: "{{ vm_network }}"
        device_type: vmxnet3
        type: dhcp
        domain: "{{ vm_domain }}"
      customization:
        hostname: "{{ vm_servername }}"
        orgname: redacted
        password: "{{ winlocal_admin_pass }}"
        timezone: 255
      wait_for_ip_address: yes 
    register: vm
    when: num_disks == 2

так далее


person ThePenguin    schedule 20.09.2019    source источник


Ответы (1)


Похоже, вы должны построить свою виртуальную машину с одним диском, который, как вы точно знаете, всегда будет там, когда вы запустите воспроизведение, что вы можете сделать первой переменной в этом списке:

vms:
  0:
    vm_disk_datastore: "C6200_T2_FCP_3Days"
    vm_disk_size: "80"
    vm_disk_type: "thin"
  1:
    vm_disk_datastore: "C6200_T2_FCP_3Days"
    vm_disk_size: "50"
    vm_disk_type: "thin"
  2:
    vm_disk_datastore: "C6200_T2_FCP_3Days"
    vm_disk_size: "20"
    vm_disk_type: "thin"
  3:
    vm_disk_datastore: ""
    vm_disk_size: ""
    vm_disk_type: ""

Поскольку я не знаю способа, которым вы можете перебирать аргументы подмодуля, чтобы они присутствовали или нет, создайте свою виртуальную машину с одним диском, который, как вы точно знаете, будет там. Которая упомянутая выше, для единообразия, должна быть первой в вашем списке. Или вам нужно будет перестроить логику, чтобы углубиться в список в поисках определенного значения, которое вы можете ввести с помощью фильтров jinja, таких как selectattr и map.

- name: Launch Windows 2016 VM Instance
    vmware_guest:
      validate_certs: no
      datacenter: "{{ vm_datacenter }}"
      folder: "{{ vm_folder }}"
      name: "{{ vm_servername }}"
      state: poweredon
      template: "{{ vm_template }}"
      cluster: "{{ vm_cluster }}"
      disk:
       - size_gb: "{{ vms.0.vm_disk_size }}"
         type: "{{ vms.0.vm_disk_type }}"
         datastore: "{{ vms.0.vm_disk_datastore }}"
      hardware:
        memory_mb: "{{ vm_memory_mb | default(8192) }}"
        num_cpus: "{{ vm_num_cpus | default(4) }}"
      networks:
      - name: "{{ vm_network }}"
        start_connected: yes
        vlan: "{{ vm_network }}"
        device_type: vmxnet3
        type: dhcp
        domain: "{{ vm_domain }}"
      customization:
        hostname: "{{ vm_servername }}"
        orgname: Redacted
        password: "{{ winlocal_admin_pass }}"
        timezone: 255
      wait_for_ip_address: yes 
    register: vm 

После его создания используйте этот другой модуль для детализации добавления дополнительных дисков.

- name: Add disks to virtual machine
  vmware_guest_disk:
    hostname: "{{ vm_servername }}"
    datacenter: "{{ vm_datacenter }}"
    disk:
      - size_gb: "{{ item.vm_disk_size }}"
        type: "{{ item.vm_disk_type }}"
        datastore: "{{ item.vm_disk_datastore }}"
        state: present
    loop: "{{ vms }}"
    loop_control:
      label: "Disk {{ my_idx}} - {{ item.vm_disk_datastore }}"
      index_var: my_idx
    when:
      - item.vm_disk_datastore != ""
      - item.vm_disk_size != ""
      - item.vm_disk_type != ""
      - my_idx > 0

Это будет проходить через цикл, извлекающий эту переменную из того места, где вы решили ее определить, а затем прокручивать этот список словарей, извлекая значения с правильными метками, но делая это только в том случае, если они имеют значение (если в этом list - это то, что вы планируете делать, если нет, то даже когда это не нужно). Это также позволит вам расширяться вверх, просто добавляя больше элементов в список, без необходимости расширять вашу задачу. Если вам нужно отредактировать первую задачу, потому что вы не можете полагаться на порядок в списке, но вам нужно ввести переменную, тогда вам нужно убедиться, что вы внесли изменения на диски во второй задаче, а также не использовать диск. добавлен в первую задачу.

Кроме того, в документации по этому модулю указано, что существующие диски, вызываемые с помощью этого модуля, будут скорректированы до этого размера и не могут быть уменьшены с помощью модуля, поэтому, если вы хотите избежать этого, выполните некоторые проверки данных для сравнения настроенных размер диска до того, что находится в вашей переменной, поэтому вы можете пропустить задачу, если она будет уменьшена (или если вы просто не хотите, чтобы существующая виртуальная машина изменялась).

person ebrewer    schedule 20.09.2019
comment
Большое спасибо за информацию. Я попробовал ваш метод, и он заполнил информацию о диске, как и следовало ожидать, но на самом деле диски не созданы: - person ThePenguin; 24.09.2019
comment
Похоже, что модуль vm_guest пытается перезаписать начальный диск 0 диском 1: msg: Данный размер диска меньше найденного (52428800 ‹83886080). Уменьшение количества дисков запрещено. Таким образом, в основном ваш метод работает должным образом, но для каждого дополнительного диска в dict модуль vm_guest считает, что это основной диск, и будет пытаться перезаписать вместо добавления дополнительного диска. - person ThePenguin; 24.09.2019
comment
О, хорошо, я думаю, что, поскольку он пропускает весь модуль vmware_guest через этот цикл, он берет из этого списка и пытается назначить этому vm ТОЛЬКО диск в этой итерации цикла. Позвольте мне отредактировать свой ответ выше, добавив альтернативу. - person ebrewer; 24.09.2019
comment
Это действительно хороший пример перебора списка. Я тоже начал смотреть на модуль vm_guest_disk, но он появился в версии 2.8, а последняя версия Tower - 2.7.9 :). Я вернусь и буду ссылаться на этот код при обновлении, он очень лаконичный. А пока я только что по умолчанию использовал несколько итераций модуля, вызываемых через переменную disk_number, - person ThePenguin; 26.09.2019
comment
Большое спасибо за вашу помощь, ebrewer, это мое первое реальное использование stackoverflow, и вы мне очень помогли. Это очень ценно. - person ThePenguin; 26.09.2019
comment
Без проблем! Когда вы обновитесь, вернитесь сюда и сообщите мне, сработало ли это. Я лично не использовал эти модули, поэтому мне любопытно, работает ли это так, как я думаю. - person ebrewer; 26.09.2019