Как настроить автоматическую сборку образов ВМ для VMware Cloud Director — компактное руководство

от автора

Привет, Хабр! Меня зовут Роман Петров, занимаюсь разработкой продуктов для управления учетными данными в SberCloud. В рамках одного проекта мне потребовалось автоматизировать сборку виртуальных машин под VMware Cloud Director.

Можно было решить эту задачу с помощью инструментов VMware: Fusion, Workstation или Player, но они требуют покупки лицензий, а последний еще и установки не обновляемого пакета VMware VIX API в случае GNU\Linux. Я выбрал альтернативный путь и построил необходимый пайплайн на базе опенсорсного VirtualBox.

Под катом — кратко о том, как я это сделал.

Прежде чем мы начнем

Прежде чем переходить к делу, немного расскажу о том, почему вообще решил заняться этим вопросом, и познакомлю вас с программным стеком, который мы будем использовать. У меня был шаблон для Packer с операционной системой Ubuntu Server 18.04 и перечнем дополнительного ПО для предустановки. Изначально сборка этого образа проходила в среде Fusion. Для инсталляции операционной системы использовал файл ответов preseed.cfg. Он содержит сценарии ответов на все вопросы инсталлятора (для автоматизации процесса).

Я решил оставить Packer, но заменить Fusion на VirtualBox. Выбор в пользу open source решения был сделан по причине того, что оно распространяется на бесплатной основе, поддерживает большое количество хостовых ОС и экспорт образов в форматах OVF и OVA. Кроме того, VirtualBox предоставляет репозитории для GNU/Linux, позволяющие автоматически обновлять пакеты операционных систем. К слову, аналогичный репозиторий предлагают и разработчики Packer.

Начало работы

В качестве хоста для развертки окружения, в котором будет запускаться CI-пайплайн, выбрал виртуальную машину с Ubuntu Server 20.04. На неё установил утилиты Packer и VirtualBox. Не буду подробно рассказывать, как это сделать, так как все необходимые инструкции вы можете найти в официальной документации этих инструментов [раз, два].

Следующим шагом стала подготовка шаблона для Packer. Packer включает в себя сборщики для разных окружений, в том числе для VirtualBox — virtualbox-iso. Написал шаблон, запустил сборку образа ВМ. Осталось загрузить этот образ в библиотеку Cloud Director. Обнаружил, что Cloud Director отказывается его импортировать. Это основная трудность, которая заняла много времени.

В процессе поиска решения проблемы я наткнулся на статью иностранного коллеги. Он заметил, что из-за несовместимости в системных типах и поддержке аппаратного обеспечения (разная трактовка открытого стандарта), экспорт такого образа в VMware Cloud Director требует дополнительной настройки — какой именно, покажу далее.

Настраиваем шаблон Packer

В шаблон Packer внесем следующие изменения:

  • Настроим экспорт образа в формате OVF. Для этого в конфигурационном файле атрибуту format присвоим значение ovf. Эта операция позволит нам получить на выходе два отдельных файла: XML-документ с описанием ВМ и образ жесткого диска. Так, нам будет проще настраивать нашу систему в дальнейшем. Отмечу, что для своего кейса я не создаю дополнительные диски и не включаю iso-образы в состав виртуальной машины. Расширить дисковое пространство или добавить дополнительные накопители можно непосредственно при развертке виртуальной машины.

  • Укажем SCSI в качестве контроллера жестких дисков. Соответствующее значение (scsi) необходимо прописать в атрибуте hard_drive_interface. В VirtualBox будет эмулироваться контроллер LsiLogic, что является плюсом, поскольку контроллер этого типа поддерживается в Cloud Director.

  • В качестве прошивки выберем BIOS, а в качестве видеоконтроллера — vmsvga (VMware SVGA). Атрибуты, которые нам нужны, — это firmware и gfx_controller.

Финальный вариант шаблона для Packer — main.pkr.hcl — выглядит так:

source "virtualbox-iso" "ubuntu-18_04-amd64" {   vm_name                  = "ubuntu-18.04-amd64"   guest_os_type            = "Ubuntu_64"   nested_virt              = false   headless                 = true   keep_registered          = false   guest_additions_mode     = "disable"   cpus                     = 2   memory                   = 4096   chipset                  = "piix3"   firmware                 = "bios"   rtc_time_base            = "UTC"   disk_size                = 32768   hard_drive_interface     = "scsi"   hard_drive_discard       = true   hard_drive_nonrotational = true   nic_type                 = "82540EM"   gfx_controller           = "vmsvga"   gfx_vram_size            = "16"   gfx_accelerate_3d        = false   sound                    = "none"   iso_url                  = "http://cdimage.ubuntu.com/ubuntu/releases/18.04/release/ubuntu-18.04.5-server-amd64.iso"   iso_checksum             = "sha256:8c5fc24894394035402f66f3824beb7234b757dd2b5531379cb310cedfdf0996"   boot_command             = ["<esc><wait>",                               "<esc><wait>",                               "<enter><wait>",                               "/install/vmlinuz auto=true priority=critical fb=false initrd=/install/initrd.gz grub-installer/bootdev=/dev/sda preseed/file=/floppy/preseed.cfg -- <enter>"]   floppy_files             = ["./preseed/preseed.cfg"]   shutdown_command         = "echo '${var.password}' | sudo -S shutdown -P now"   post_shutdown_delay      = "1m"   output_directory         = "./output"   format                   = "ovf"   bundle_iso               = false   communicator             = "ssh"   ssh_username             = var.username   ssh_password             = var.password   ssh_timeout              = "20m" }    build {   sources = ["sources.virtualbox-iso.ubuntu-18_04-amd64"]    # ssh   provisioner "shell" {     inline           = ["sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config",                         "sudo systemctl stop sshd",                         "sudo rm /etc/ssh/ssh_host_*"]   }    # ./packer-manifest.json   post-processor "manifest" {       output = "packer-manifest.json"   } }

Более подробно о том, для чего нужны остальные атрибуты, вы можете узнать в документации на сборщик virtualbox-iso. Здесь я дополнительно хочу выделить лишь один из них — headless, отвечающий за сборку в фоновом режиме. Этот флажок стоит установить в состояние false, чтобы включить графический интерфейс. Это упростит отладку.

Теперь, если мы запустим Packer с нашими настройками, он сгенерирует три файла:

  • Образ жесткого диска: ubuntu-18.04-amd64-disk001.vmdk;

  • XML-файл с описанием виртуальной машины: ubuntu-18.04-amd64.ovf;

  • JSON-файл со списком созданных артефактов: packer-manifest.json.

Последний файл записан благодаря блоку:

# ./packer-manifest.json post-processor "manifest" {     output = "packer-manifest.json" }

Файл packer-manifest.json будет иметь следующее содержимое:

{   "builds": [     {       "name": "ubuntu-18_04-amd64",       "builder_type": "virtualbox-iso",       "build_time": 1629043596,       "files": [         {           "name": "output/ubuntu-18.04-amd64-disk001.vmdk",           "size": 916132352         },         {           "name": "output/ubuntu-18.04-amd64.ovf",           "size": 6771         }       ],       "artifact_id": "VM",       "packer_run_uuid": "b5fbae2b-59e7-fd6f-4154-cae16befd459",       "custom_data": null     }   ],   "last_run_uuid": "b5fbae2b-59e7-fd6f-4154-cae16befd459" }

Этот файл поможет нам найти результат сборки образа ВМ (ubuntu-18.04-amd64-disk001.vmdk и ubuntu-18.04-amd64.ovf).

Редактируем .ovf

На предыдущем этапе мы настроили экспорт образа ВМ в Open Virtualization Format. Следующим шагом будет редактировать файл *.ovf.

Я написал специальный скрипт на Python 3.8 (он включен в дистрибутив Ubuntu Server 20.04) и «распарсил» packer-manifest.json, чтобы извлечь путь до файла .ovf. Вот часть, решающая эту задачу:

import json  with open("packer-manifest.json", "r") as json_file:     data = json.load(json_file)     for i in data["builds"]:         for j in i["files"]:             if ".ovf" in j["name"]:                 ovf_in = j["name"]                 ovf_out = ovf_in.replace(".ovf", "-vmware.ovf") 

Переменная ovf_in хранит путь до файла .ovf, а ovf_out — путь до нового файла .ovf, в котором мы сохраним изменения. Чтобы эти изменения внести, использую модуль xml.etree.ElementTree.

При редактировании XML очень помогла утилита XMLStarlet. Она покажет, какие элементы дерева входят в состав файла .ovf.

Вывод утилиты XMLStarlet
> xmlstarlet el ./output/ubuntu-18.04-amd64.ovf Envelope Envelope/References Envelope/References/File Envelope/DiskSection Envelope/DiskSection/Info Envelope/DiskSection/Disk Envelope/NetworkSection Envelope/NetworkSection/Info Envelope/NetworkSection/Network Envelope/NetworkSection/Network/Description Envelope/VirtualSystem Envelope/VirtualSystem/Info Envelope/VirtualSystem/OperatingSystemSection Envelope/VirtualSystem/OperatingSystemSection/Info Envelope/VirtualSystem/OperatingSystemSection/Description Envelope/VirtualSystem/OperatingSystemSection/vbox:OSType Envelope/VirtualSystem/VirtualHardwareSection Envelope/VirtualSystem/VirtualHardwareSection/Info Envelope/VirtualSystem/VirtualHardwareSection/System Envelope/VirtualSystem/VirtualHardwareSection/System/vssd:ElementName Envelope/VirtualSystem/VirtualHardwareSection/System/vssd:InstanceID Envelope/VirtualSystem/VirtualHardwareSection/System/vssd:VirtualSystemIdentifier Envelope/VirtualSystem/VirtualHardwareSection/System/vssd:VirtualSystemType Envelope/VirtualSystem/VirtualHardwareSection/Item Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Caption Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Description Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ElementName Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:InstanceID Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ResourceType Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:VirtualQuantity Envelope/VirtualSystem/VirtualHardwareSection/Item Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:AllocationUnits Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Caption Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Description Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ElementName Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:InstanceID Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ResourceType Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:VirtualQuantity Envelope/VirtualSystem/VirtualHardwareSection/Item Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Address Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Caption Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Description Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ElementName Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:InstanceID Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ResourceSubType Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ResourceType Envelope/VirtualSystem/VirtualHardwareSection/Item Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Address Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Caption Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Description Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ElementName Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:InstanceID Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ResourceSubType Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ResourceType Envelope/VirtualSystem/VirtualHardwareSection/Item Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Address Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Caption Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Description Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ElementName Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:InstanceID Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ResourceSubType Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ResourceType Envelope/VirtualSystem/VirtualHardwareSection/Item Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:AddressOnParent Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Caption Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Description Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ElementName Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:HostResource Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:InstanceID Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Parent Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ResourceType Envelope/VirtualSystem/VirtualHardwareSection/Item Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:AutomaticAllocation Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Caption Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:Connection Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ElementName Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:InstanceID Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ResourceSubType Envelope/VirtualSystem/VirtualHardwareSection/Item/rasd:ResourceType Envelope/VirtualSystem/vbox:Machine Envelope/VirtualSystem/vbox:Machine/ovf:Info Envelope/VirtualSystem/vbox:Machine/Hardware Envelope/VirtualSystem/vbox:Machine/Hardware/CPU Envelope/VirtualSystem/vbox:Machine/Hardware/CPU/PAE Envelope/VirtualSystem/vbox:Machine/Hardware/CPU/LongMode Envelope/VirtualSystem/vbox:Machine/Hardware/CPU/X2APIC Envelope/VirtualSystem/vbox:Machine/Hardware/CPU/HardwareVirtExLargePages Envelope/VirtualSystem/vbox:Machine/Hardware/Memory Envelope/VirtualSystem/vbox:Machine/Hardware/Boot Envelope/VirtualSystem/vbox:Machine/Hardware/Boot/Order Envelope/VirtualSystem/vbox:Machine/Hardware/Boot/Order Envelope/VirtualSystem/vbox:Machine/Hardware/Boot/Order Envelope/VirtualSystem/vbox:Machine/Hardware/Boot/Order Envelope/VirtualSystem/vbox:Machine/Hardware/Display Envelope/VirtualSystem/vbox:Machine/Hardware/VideoCapture Envelope/VirtualSystem/vbox:Machine/Hardware/RemoteDisplay Envelope/VirtualSystem/vbox:Machine/Hardware/RemoteDisplay/VRDEProperties Envelope/VirtualSystem/vbox:Machine/Hardware/RemoteDisplay/VRDEProperties/Property Envelope/VirtualSystem/vbox:Machine/Hardware/RemoteDisplay/VRDEProperties/Property Envelope/VirtualSystem/vbox:Machine/Hardware/BIOS Envelope/VirtualSystem/vbox:Machine/Hardware/BIOS/IOAPIC Envelope/VirtualSystem/vbox:Machine/Hardware/BIOS/SmbiosUuidLittleEndian Envelope/VirtualSystem/vbox:Machine/Hardware/Network Envelope/VirtualSystem/vbox:Machine/Hardware/Network/Adapter Envelope/VirtualSystem/vbox:Machine/Hardware/Network/Adapter/NAT Envelope/VirtualSystem/vbox:Machine/Hardware/AudioAdapter Envelope/VirtualSystem/vbox:Machine/Hardware/RTC Envelope/VirtualSystem/vbox:Machine/Hardware/Clipboard Envelope/VirtualSystem/vbox:Machine/StorageControllers Envelope/VirtualSystem/vbox:Machine/StorageControllers/StorageController Envelope/VirtualSystem/vbox:Machine/StorageControllers/StorageController Envelope/VirtualSystem/vbox:Machine/StorageControllers/StorageController/AttachedDevice Envelope/VirtualSystem/vbox:Machine/StorageControllers/StorageController/AttachedDevice/Image

Вывод утилиты XMLStarlet представлен на языке XPath. Как вы можете заметить, пространство имен определено не для каждого элемента — в их названии отсутствует часть перед символом двоеточия. Важно помнить, что при работе с XML в Python это приведет к неоднозначной трактовке атрибутов.

Строки, которые мы будем править, пропишу ниже в синтаксисе XPath с указанием пространства имен.

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

ovf:Envelope/ovf:NetworkSection ovf:Envelope/ovf:VirtualSystem/vbox:Machine/ovf:Hardware/ovf:Network

Из элементов ниже я удалил только те, в значении которых содержат слово Ethernet:

ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item/rasd:Caption

Исключаем элементы с упоминанием IDE-контроллеров. IDE нам не нужно, так как мы будем работать со SCSI. В первом случае удаляем значения, где упоминается ideController, а во втором — только строки с атрибутом name=»IDE Controller».

ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item/rasd:Caption ovf:Envelope/ovf:VirtualSystem/vbox:Machine/ovf:StorageControllers/ovf:StorageController

Удаляем аудиоконтроллер. Он нам также не понадобится, так как практически никогда не используется на серверах.

ovf:Envelope/ovf:VirtualSystem/vbox:Machine/ovf:Hardware/ovf:AudioAdapter

Для оперативной памяти заменяем единицы измерения. Меняем их с MegaBytes на byte*2^20. Этот нюанс связан с тем, что разные производители программного обеспечения порой трактуют Open Virtualization Format по-разному:

ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item/rasd:AllocationUnits

Меняем тип системы. Вместо virtualbox-2.2 прописываем vmx-16, то есть меняем систему виртуализации с VirtualBox на VMware.

ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:System/vssd:VirtualSystemType.

Здесь дополнительно отмечу, что для работы с модулем xml.etree.ElementTree необходимо зарегистрировать используемые пространства имен функцией xml.etree.ElementTree.register_namespace. Их можно найти в исходном файле .ova по значению атрибутов xmlns.

import xml.etree.ElementTree as ET  ET.register_namespace('', "http://schemas.dmtf.org/ovf/envelope/1") ET.register_namespace('ovf', "http://schemas.dmtf.org/ovf/envelope/1") ET.register_namespace('rasd', "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData") ET.register_namespace('vssd', "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData") ET.register_namespace('xsi', "http://www.w3.org/2001/XMLSchema-instance") ET.register_namespace('vbox', "http://www.virtualbox.org/ovf/machine")

По итогу мы получаем финальный скрипт ovf-patch.py:

#!/usr/bin/python3  import json import xml.etree.ElementTree as ET  ET.register_namespace('', "http://schemas.dmtf.org/ovf/envelope/1") ET.register_namespace('ovf', "http://schemas.dmtf.org/ovf/envelope/1") ET.register_namespace('rasd', "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData") ET.register_namespace('vssd', "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData") ET.register_namespace('xsi', "http://www.w3.org/2001/XMLSchema-instance") ET.register_namespace('vbox', "http://www.virtualbox.org/ovf/machine")  with open("packer-manifest.json", "r") as json_file:     data = json.load(json_file)     for i in data["builds"]:         for j in i["files"]:             if ".ovf" in j["name"]:                 ovf_in = j["name"]                 ovf_out = ovf_in.replace(".ovf", "-vmware.ovf")      tree = ET.parse(ovf_in)     root = tree.getroot()      # ovf:Envelope/ovf:NetworkSection     for i in root.findall("./{*}NetworkSection"):         root.remove(i)      # ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection     for i in root.findall("./{*}VirtualSystem/{*}VirtualHardwareSection"):         # ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item         for i_i in i.findall("./{*}Item"):             # ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item/rasd:AllocationUnits             for i_i_i in i_i.findall("./{*}AllocationUnits"):                 if i_i_i.text == "MegaBytes":                     i_i_i.text = "byte * 2^20"             # ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item/rasd:Caption             for i_i_i in i_i.findall("./{*}Caption"):                 if "ideController" in i_i_i.text:                     i.remove(i_i)                 if "Ethernet" in i_i_i.text:                     i.remove(i_i)         # ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:System/vssd:VirtualSystemType         for i_i in i.findall("{*}System/{*}VirtualSystemType"):             i_i.text = "vmx-16"      # ovf:Envelope/ovf:VirtualSystem/vbox:Machine/ovf:Hardware     for i in root.findall("./{*}VirtualSystem/{*}Machine/{*}Hardware"):         # ovf:Envelope/ovf:VirtualSystem/vbox:Machine/ovf:Hardware/ovf:AudioAdapter         for i_i in i.findall("./{*}AudioAdapter"):             i.remove(i_i)         # ovf:Envelope/ovf:VirtualSystem/vbox:Machine/ovf:Hardware/ovf:Network         for i_i in i.findall("./{*}Network"):             i.remove(i_i)      # ovf:Envelope/ovf:VirtualSystem/vbox:Machine/ovf:StorageControllers     for i in root.findall("./{*}VirtualSystem/{*}Machine/{*}StorageControllers"):         # ovf:Envelope/ovf:VirtualSystem/vbox:Machine/ovf:StorageControllers/ovf:StorageController         for i_i in i.findall("./{*}StorageController[@name='IDE Controller']"):             i.remove(i_i)      tree.write(ovf_out)     print(ovf_out)

После запуска скрипта в выходном каталоге появятся файлы:

  • Образ жесткого диска: ubuntu-18.04-amd64-disk001.vmdk;

  • XML-файл с описанием ВМ: ubuntu-18.04-amd64.ovf;

  • XML-файл с описанием ВМ, готовый к импорту в Cloud Director: ubuntu-18.04-amd64-vmware.ovf.

В качестве примера привожу исходный файл ubuntu-18.04-amd64.ovf:

ubuntu-18.04-amd64.ovf
<?xml version="1.0"?> <Envelope ovf:version="1.0" xml:lang="en-US" xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:vbox="http://www.virtualbox.org/ovf/machine">   <References>     <File ovf:id="file1" ovf:href="ubuntu-18.04-amd64-disk001.vmdk"/>   </References>   <DiskSection>     <Info>List of the virtual disks used in the package</Info>     <Disk ovf:capacity="34359738368" ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" vbox:uuid="a5659548-990a-4853-a8ab-bb9a168df0fc"/>   </DiskSection>   <NetworkSection>     <Info>Logical networks used in the package</Info>     <Network ovf:name="NAT">       <Description>Logical network used by this appliance.</Description>     </Network>   </NetworkSection>   <VirtualSystem ovf:id="ubuntu-18.04-amd64">     <Info>A virtual machine</Info>     <OperatingSystemSection ovf:id="94">       <Info>The kind of installed guest operating system</Info>       <Description>Ubuntu_64</Description>       <vbox:OSType ovf:required="false">Ubuntu_64</vbox:OSType>     </OperatingSystemSection>     <VirtualHardwareSection>       <Info>Virtual hardware requirements for a virtual machine</Info>       <System>         <vssd:ElementName>Virtual Hardware Family</vssd:ElementName>         <vssd:InstanceID>0</vssd:InstanceID>         <vssd:VirtualSystemIdentifier>ubuntu-18.04-amd64</vssd:VirtualSystemIdentifier>         <vssd:VirtualSystemType>virtualbox-2.2</vssd:VirtualSystemType>       </System>       <Item>         <rasd:Caption>2 virtual CPU</rasd:Caption>         <rasd:Description>Number of virtual CPUs</rasd:Description>         <rasd:ElementName>2 virtual CPU</rasd:ElementName>         <rasd:InstanceID>1</rasd:InstanceID>         <rasd:ResourceType>3</rasd:ResourceType>         <rasd:VirtualQuantity>2</rasd:VirtualQuantity>       </Item>       <Item>         <rasd:AllocationUnits>MegaBytes</rasd:AllocationUnits>         <rasd:Caption>4096 MB of memory</rasd:Caption>         <rasd:Description>Memory Size</rasd:Description>         <rasd:ElementName>4096 MB of memory</rasd:ElementName>         <rasd:InstanceID>2</rasd:InstanceID>         <rasd:ResourceType>4</rasd:ResourceType>         <rasd:VirtualQuantity>4096</rasd:VirtualQuantity>       </Item>       <Item>         <rasd:Address>0</rasd:Address>         <rasd:Caption>ideController0</rasd:Caption>         <rasd:Description>IDE Controller</rasd:Description>         <rasd:ElementName>ideController0</rasd:ElementName>         <rasd:InstanceID>3</rasd:InstanceID>         <rasd:ResourceSubType>PIIX4</rasd:ResourceSubType>         <rasd:ResourceType>5</rasd:ResourceType>       </Item>       <Item>         <rasd:Address>1</rasd:Address>         <rasd:Caption>ideController1</rasd:Caption>         <rasd:Description>IDE Controller</rasd:Description>         <rasd:ElementName>ideController1</rasd:ElementName>         <rasd:InstanceID>4</rasd:InstanceID>         <rasd:ResourceSubType>PIIX4</rasd:ResourceSubType>         <rasd:ResourceType>5</rasd:ResourceType>       </Item>       <Item>         <rasd:Address>0</rasd:Address>         <rasd:Caption>scsiController0</rasd:Caption>         <rasd:Description>SCSI Controller</rasd:Description>         <rasd:ElementName>scsiController0</rasd:ElementName>         <rasd:InstanceID>5</rasd:InstanceID>         <rasd:ResourceSubType>lsilogic</rasd:ResourceSubType>         <rasd:ResourceType>6</rasd:ResourceType>       </Item>       <Item>         <rasd:AddressOnParent>0</rasd:AddressOnParent>         <rasd:Caption>disk1</rasd:Caption>         <rasd:Description>Disk Image</rasd:Description>         <rasd:ElementName>disk1</rasd:ElementName>         <rasd:HostResource>/disk/vmdisk1</rasd:HostResource>         <rasd:InstanceID>6</rasd:InstanceID>         <rasd:Parent>5</rasd:Parent>         <rasd:ResourceType>17</rasd:ResourceType>       </Item>       <Item>         <rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>         <rasd:Caption>Ethernet adapter on 'NAT'</rasd:Caption>         <rasd:Connection>NAT</rasd:Connection>         <rasd:ElementName>Ethernet adapter on 'NAT'</rasd:ElementName>         <rasd:InstanceID>7</rasd:InstanceID>         <rasd:ResourceSubType>E1000</rasd:ResourceSubType>         <rasd:ResourceType>10</rasd:ResourceType>       </Item>     </VirtualHardwareSection>     <vbox:Machine ovf:required="false" version="1.16-linux" uuid="{37db6186-f653-47f2-ba71-1b325b4aa806}" name="ubuntu-18.04-amd64" OSType="Ubuntu_64" snapshotFolder="Snapshots" lastStateChange="2021-08-15T18:03:51Z">       <ovf:Info>Complete VirtualBox machine configuration in VirtualBox format</ovf:Info>       <Hardware>         <CPU count="2">           <PAE enabled="true"/>           <LongMode enabled="true"/>           <X2APIC enabled="true"/>           <HardwareVirtExLargePages enabled="false"/>         </CPU>         <Memory RAMSize="4096"/>         <Boot>           <Order position="1" device="HardDisk"/>           <Order position="2" device="DVD"/>           <Order position="3" device="None"/>           <Order position="4" device="None"/>         </Boot>         <Display controller="VMSVGA" VRAMSize="16"/>         <VideoCapture screens="1" file="." fps="25"/>         <RemoteDisplay enabled="true">           <VRDEProperties>             <Property name="TCP/Address" value="127.0.0.1"/>             <Property name="TCP/Ports" value="5968"/>           </VRDEProperties>         </RemoteDisplay>         <BIOS>           <IOAPIC enabled="true"/>           <SmbiosUuidLittleEndian enabled="true"/>         </BIOS>         <Network>           <Adapter slot="0" enabled="true" MACAddress="0800272C8B78" type="82540EM">             <NAT/>           </Adapter>         </Network>         <AudioAdapter driver="Pulse" enabledIn="false" enabledOut="false"/>         <RTC localOrUTC="UTC"/>         <Clipboard/>       </Hardware>       <StorageControllers>         <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true"/>         <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true">           <AttachedDevice nonrotational="true" discard="true" type="HardDisk" hotpluggable="false" port="0" device="0">             <Image uuid="{a5659548-990a-4853-a8ab-bb9a168df0fc}"/>           </AttachedDevice>         </StorageController>       </StorageControllers>     </vbox:Machine>   </VirtualSystem> </Envelope>

И файл с внесенными изменениями ubuntu-18.04-amd64-vmware.ovf:

ubuntu-18.04-amd64-vmware.ovf
<ovf:Envelope xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" xmlns:vbox="http://www.virtualbox.org/ovf/machine" xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" ovf:version="1.0" xml:lang="en-US">   <ovf:References>     <ovf:File ovf:id="file1" ovf:href="ubuntu-18.04-amd64-disk001.vmdk" />   </ovf:References>   <ovf:DiskSection>     <ovf:Info>List of the virtual disks used in the package</ovf:Info>     <ovf:Disk ovf:capacity="34359738368" ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" vbox:uuid="a5659548-990a-4853-a8ab-bb9a168df0fc" />   </ovf:DiskSection>   <ovf:VirtualSystem ovf:id="ubuntu-18.04-amd64">     <ovf:Info>A virtual machine</ovf:Info>     <ovf:OperatingSystemSection ovf:id="94">       <ovf:Info>The kind of installed guest operating system</ovf:Info>       <ovf:Description>Ubuntu_64</ovf:Description>       <vbox:OSType ovf:required="false">Ubuntu_64</vbox:OSType>     </ovf:OperatingSystemSection>     <ovf:VirtualHardwareSection>       <ovf:Info>Virtual hardware requirements for a virtual machine</ovf:Info>       <ovf:System>         <vssd:ElementName>Virtual Hardware Family</vssd:ElementName>         <vssd:InstanceID>0</vssd:InstanceID>         <vssd:VirtualSystemIdentifier>ubuntu-18.04-amd64</vssd:VirtualSystemIdentifier>         <vssd:VirtualSystemType>vmx-16</vssd:VirtualSystemType>       </ovf:System>       <ovf:Item>         <rasd:Caption>2 virtual CPU</rasd:Caption>         <rasd:Description>Number of virtual CPUs</rasd:Description>         <rasd:ElementName>2 virtual CPU</rasd:ElementName>         <rasd:InstanceID>1</rasd:InstanceID>         <rasd:ResourceType>3</rasd:ResourceType>         <rasd:VirtualQuantity>2</rasd:VirtualQuantity>       </ovf:Item>       <ovf:Item>         <rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>         <rasd:Caption>4096 MB of memory</rasd:Caption>         <rasd:Description>Memory Size</rasd:Description>         <rasd:ElementName>4096 MB of memory</rasd:ElementName>         <rasd:InstanceID>2</rasd:InstanceID>         <rasd:ResourceType>4</rasd:ResourceType>         <rasd:VirtualQuantity>4096</rasd:VirtualQuantity>       </ovf:Item>       <ovf:Item>         <rasd:Address>0</rasd:Address>         <rasd:Caption>scsiController0</rasd:Caption>         <rasd:Description>SCSI Controller</rasd:Description>         <rasd:ElementName>scsiController0</rasd:ElementName>         <rasd:InstanceID>5</rasd:InstanceID>         <rasd:ResourceSubType>lsilogic</rasd:ResourceSubType>         <rasd:ResourceType>6</rasd:ResourceType>       </ovf:Item>       <ovf:Item>         <rasd:AddressOnParent>0</rasd:AddressOnParent>         <rasd:Caption>disk1</rasd:Caption>         <rasd:Description>Disk Image</rasd:Description>         <rasd:ElementName>disk1</rasd:ElementName>         <rasd:HostResource>/disk/vmdisk1</rasd:HostResource>         <rasd:InstanceID>6</rasd:InstanceID>         <rasd:Parent>5</rasd:Parent>         <rasd:ResourceType>17</rasd:ResourceType>       </ovf:Item>       </ovf:VirtualHardwareSection>     <vbox:Machine ovf:required="false" version="1.16-linux" uuid="{37db6186-f653-47f2-ba71-1b325b4aa806}" name="ubuntu-18.04-amd64" OSType="Ubuntu_64" snapshotFolder="Snapshots" lastStateChange="2021-08-15T18:03:51Z">       <ovf:Info>Complete VirtualBox machine configuration in VirtualBox format</ovf:Info>       <ovf:Hardware>         <ovf:CPU count="2">           <ovf:PAE enabled="true" />           <ovf:LongMode enabled="true" />           <ovf:X2APIC enabled="true" />           <ovf:HardwareVirtExLargePages enabled="false" />         </ovf:CPU>         <ovf:Memory RAMSize="4096" />         <ovf:Boot>           <ovf:Order position="1" device="HardDisk" />           <ovf:Order position="2" device="DVD" />           <ovf:Order position="3" device="None" />           <ovf:Order position="4" device="None" />         </ovf:Boot>         <ovf:Display controller="VMSVGA" VRAMSize="16" />         <ovf:VideoCapture screens="1" file="." fps="25" />         <ovf:RemoteDisplay enabled="true">           <ovf:VRDEProperties>             <ovf:Property name="TCP/Address" value="127.0.0.1" />             <ovf:Property name="TCP/Ports" value="5968" />           </ovf:VRDEProperties>         </ovf:RemoteDisplay>         <ovf:BIOS>           <ovf:IOAPIC enabled="true" />           <ovf:SmbiosUuidLittleEndian enabled="true" />         </ovf:BIOS>         <ovf:RTC localOrUTC="UTC" />         <ovf:Clipboard />       </ovf:Hardware>       <ovf:StorageControllers>         <ovf:StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true">           <ovf:AttachedDevice nonrotational="true" discard="true" type="HardDisk" hotpluggable="false" port="0" device="0">             <ovf:Image uuid="{a5659548-990a-4853-a8ab-bb9a168df0fc}" />           </ovf:AttachedDevice>         </ovf:StorageController>       </ovf:StorageControllers>     </vbox:Machine>   </ovf:VirtualSystem> </ovf:Envelope>

Импортируем образ

Для импорта образа ВМ в библиотеку можно воспользоваться инструментами OVF Tool или vcd-cli. Это — инструменты, разработанные VMware. Они хорошо документированы и работают стабильно. В дальнейшем из библиотеки Cloud Director можно разворачивать ВМ из созданного шаблона вручную или с инструментами автоматизации (например, Terraform), добавив по требованию сетевые контроллеры, дополнительные диски и так далее.

Таким образом, мне удалось подготовить образ VirtualBox к загрузке в VMware Cloud Director. Описал шаги для реализации полноценного CI-пайплайна.

Если хотите использовать виртуальный ЦОД на базе VMware, вы можете оставить заявку на подключение и бесплатную консультацию.


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


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *