Опыт построения Infrastructure-as-Code в VMware. Часть 1.1: Динамическая инвентаризация


image

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

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

Первым делом, что я сделал, когда обнаружил этот коммент, это побежал к нашим инфраструктурщикам с вопросом «оно мне надо, велосипед пилить?». Ребята пояснили, что Vcloud это:

  • Дорого.
  • Окупается, когда у тебя распределенные датацентры на разных континентах.
  • Овер9000 изменений в инфраструктуре и столько же виртуалок.
  • Да и вообще, мы в AWS переезжаем, зачем нам.

Зарядившись мотивацией («нам никто не поможет, кроме нас самих»), я полез в дебри изучения динамики. Не пойми меня неправильно, дорогой читатель, статичный инвентарь в Ansible штука очень удобная, да и вооружившись echo и sed в него тоже можно «писать динамически», но зачем?

Ищем нужный скрипт


На данный момент на Github в разделе contrib представлены следующие реализации динамического инвентаря: тот и этот.

На просторах интернета еще нашелся такой вариант. Я его отбросил сразу — он тупо выгребает список всех машинок (без внутренностей), работает долго, логин и пароль для соединения с варей надо хардкодить. Иными словами — здорово чтобы поиграть, но не более.

vmware.py тоже отпал, поскольку работает долго даже с кэшем (на моей машинке 30 минут без кэша, и 8 с кэшем), да и «глубина» погружения во внутренности виртуалки тоже не нравится.

Так что мой выбор пал vmware_inventory.py — он очень гибок, с кэшем работает 2 секунды и дает мне возможность группировать по параметрам машинки.

В первую очередь, большой и длинный INI файлик — конфигурация для работы с варей.

vmware_inventory.ini
# Ansible VMware external inventory script settings

[vmware]

# The resolvable hostname or ip address of the vsphere
server=virtualcenter.example.com

# The port for the vsphere API
#port=443

# The username with access to the vsphere API
username=example\vmware_reader

# The password for the vsphere API
password=supersecurepassword

# Verify the server's SSL certificate
validate_certs = False

# Specify the number of seconds to use the inventory cache before it is
# considered stale.  If not defined, defaults to 0 seconds.
cache_max_age = 86400


# Specify the directory used for storing the inventory cache.  If not defined,
# caching will be disabled.
cache_path = ~/.cache/ansible


# Max object level refers to the level of recursion the script will delve into
# the objects returned from pyvomi to find serializable facts. The default 
# level of 0 is sufficient for most tasks and will be the most performant. 
# Beware that the recursion can exceed python's limit (causing traceback),
# cause sluggish script performance and return huge blobs of facts.
# If you do not know what you are doing, leave this set to 1.
max_object_level=2


# Lower the keynames for facts to make addressing them easier.
lower_var_keys=True


# Host alias for objects in the inventory. VMWare allows duplicate VM names
# so they can not be considered unique. Use this setting to alter the alias
# returned for the hosts. Any atributes for the guest can be used to build 
# this alias. The default combines the config name and the config uuid and 
# expects that the ansible_host will be set by the host_pattern.
alias_pattern={{ config.name }}


# Host pattern is the value set for ansible_host and ansible_ssh_host, which
# needs to be a hostname or ipaddress the ansible controlhost can reach.
#host_pattern={{ guest.ipaddress }}


# Host filters are a comma separated list of jinja patterns to remove 
# non-matching hosts from the final result.
# EXAMPLES:
#   host_filters={{ config.guestid == 'rhel7_64Guest' }}
#   host_filters={{ config.cpuhotremoveenabled != False }},{{ runtime.maxmemoryusage >= 512 }}
#   host_filters={{ config.cpuhotremoveenabled != False }},{{ runtime.maxmemoryusage >= 512 }}
# The default is only gueststate of 'running'
host_filters={{ guest.gueststate == "running" }}


# Groupby patterns enable the user to create groups via any possible jinja
# expression. The resulting value will the groupname and the host will be added
# to that group. Be careful to not make expressions that simply return True/False
# because those values will become the literal group name. The patterns can be
# comma delimited to create as many groups as necessary
groupby_patterns={{ guest.guestid }},{{ 'templates' if config.template else 'guests'}}

# The script attempts to recurse into virtualmachine objects and serialize
# all available data. The serialization is comprehensive but slow. If the
# vcenter environment is large and the desired properties are known, create
# a 'properties' section in this config and make an arbitrary list of
# key=value settings where the value is a path to a specific property. If 
# If this feature is enabled, be sure to fetch every property that is used
# in the jinja expressions defined above. For performance tuning, reduce
# the number of properties to the smallest amount possible and limit the 
# use of properties that are not direct attributes of vim.VirtualMachine
#[properties]
prop01=name
prop04=config.instanceUuid
prop05=config.hardware.numCPU
prop06=config.template
prop07=config.name
prop08=guest.hostName
prop09=guest.ipAddress
prop11=guest.guestState
prop12=runtime.maxMemoryUsage


В первую очередь я рекомендую завести отдельного юзера для работы с варей. По сути нам нужен обычный пользователь, который может читать данные машинок, ресурспулов, папок и датасторов. Никаких прав на включение/выключение, создание/удаление виртуалок у него нет и не должно быть. Least privilege principle!

Допольнительно подчеркиваю:

  1. Срок жизни кэша (cache_max_age) в секундах. Я выставил на сутки, но каждый раз когда будет создаваться машинка, кэш будет обновляться (запуск скрипта с опцией --refresh-cache). Также обновление будет раз в сутки ночью (точно также)
  2. Глубину рекурсии (max_object_level). Двойка здесь самый оптимальный вариант, чтобы получить ЕЩЕ больше метаданных о машинке. Больше метаданных — больше игр с группировками и фильтрацией. Но — больше json и больше времени работы скрипта.
  3. Паттерн машинки (alias_pattern) — по умолчанию идет {{ config.name + '_' + config.uuid }}, что делает название машинки нечитабельным, так что я убрал config.uuid
  4. Паттерны группировки (groupby_patterns) — вот это самая прелесть в скрипте. Позволяет группировать машины на основе метаданных. Группировать можно по всему от слова «совсем». Ресурспул, кастомный вар в нотах, сетка, location, даже название датастора. По умолчанию группируется по гестам (читай — по установленной ОС)

Всякие очевидные вещи типа валидации сертификатов описывать не буду, но если попал в беду со скриптом — пиши в комментариях.

Пробуем запустить.

$ time ./vmware_inventory.py > fact_from_vm_py.json

real	27m59.970s
user	8m33.334s
sys	0m7.841s

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

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

Данных очень много
"edin_host": {
        "resourcepool": {
          "_moId": "resgroup-14510", 
          "name": "example-BI"
        }, 
        "customvalue": [], 
        "permission": [], 
        "storage": {
          "timestamp": {
            "hour": 7, 
            "min": {}, 
            "max": {}, 
            "month": 12, 
            "second": 20, 
            "microsecond": 859999, 
            "year": 2016, 
            "tzinfo": {}, 
            "resolution": {}, 
            "day": 22, 
            "minute": 45
          }, 
          "perdatastoreusage": []
        }, 
        "configissue": [], 
        "parentvapp": null, 
        "tag": [], 
        "recenttask": [], 
        "resourceconfig": {
          "changeversion": null, 
          "lastmodified": null, 
          "memoryallocation": {
            "overheadlimit": 63, 
            "reservation": 0, 
            "limit": -1, 
            "shares": {}, 
            "expandablereservation": false
          }, 
          "cpuallocation": {
            "overheadlimit": null, 
            "reservation": 0, 
            "limit": -1, 
            "shares": {}, 
            "expandablereservation": false
          }, 
          "entity": {
            "resourcepool": {
              "_moId": "resgroup-14510", 
              "name": "example-BI"
            }, 
            "alarmactionsenabled": true, 
            "configissue": [], 
            "tag": [], 
            "resourceconfig": {}, 
            "datastore": [], 
            "triggeredalarmstate": [], 
            "layout": {}, 
            "guest": {}, 
            "effectiverole": [], 
            "storage": {}, 
            "layoutex": {}, 
            "config": {}, 
            "customvalue": [], 
            "permission": [], 
            "parentvapp": null, 
            "recenttask": [], 
            "availablefield": [], 
            "overallstatus": "green", 
            "network": [], 
            "guestheartbeatstatus": "green", 
            "name": "edin_host", 
            "rootsnapshot": [], 
            "configstatus": "green", 
            "value": [], 
            "summary": {}, 
            "capability": {}, 
            "snapshot": null, 
            "runtime": {}
          }
        }, 
        "availablefield": [
          {
            "fieldinstanceprivileges": null, 
            "fielddefprivileges": null, 
            "name": "Service", 
            "key": 101
          }, 
          {
            "fieldinstanceprivileges": null, 
            "fielddefprivileges": null, 
            "name": "Group", 
            "key": 301
          }, 
          {
            "fieldinstanceprivileges": null, 
            "fielddefprivileges": null, 
            "name": "Role", 
            "key": 103
          }, 
          {
            "fieldinstanceprivileges": null, 
            "fielddefprivileges": null, 
            "name": "Owner", 
            "key": 104
          }, 
          {
            "fieldinstanceprivileges": null, 
            "fielddefprivileges": null, 
            "name": "Environment", 
            "key": 102
          }
        ], 
        "datastore": [
          {
            "_moId": "datastore-57683", 
            "name": "mydatastore"
          }
        ], 
        "summary": {
          "customvalue": [], 
          "guest": {
            "toolsstatus": "toolsOk", 
            "toolsversionstatus": "guestToolsUnmanaged", 
            "hostname": "edin_host.example.com", 
            "toolsrunningstatus": "guestToolsRunning", 
            "guestid": "centos64Guest", 
            "ipaddress": "192.168.1.1", 
            "toolsversionstatus2": "guestToolsUnmanaged", 
            "guestfullname": "CentOS 4/5/6/7 (64-bit)"
          }, 
          "config": {
            "memoryreservation": 0, 
            "product": null, 
            "instanceuuid": "502c6c2d-8b58-a01c-4ce0-a18e0a65ac3a", 
            "name": "edin_host", 
            "numethernetcards": 1, 
            "numcpu": 1, 
            "installbootrequired": false, 
            "guestid": "centos64Guest", 
            "memorysizemb": 2048, 
            "vmpathname": "[mydatastore] edin_host/edin_host.vmx", 
            "template": false, 
            "ftinfo": null, 
            "uuid": "422c78f0-7401-3dbc-2790-9708af08bd03", 
            "cpureservation": 0, 
            "annotation": null, 
            "numvirtualdisks": 2, 
            "guestfullname": "CentOS 4/5/6/7 (64-bit)"
          }, 
          "storage": {
            "timestamp": {}, 
            "uncommitted": 1064, 
            "unshared": 85899345920, 
            "committed": 88272314106
          }, 
          "vm": {
            "resourcepool": {
              "_moId": "resgroup-14510", 
              "name": "example-BI"
            }, 
            "alarmactionsenabled": true, 
            "configissue": [], 
            "tag": [], 
            "resourceconfig": {}, 
            "datastore": [], 
            "triggeredalarmstate": [], 
            "layout": {}, 
            "guest": {}, 
            "effectiverole": [], 
            "storage": {}, 
            "layoutex": {}, 
            "config": {}, 
            "customvalue": [], 
            "permission": [], 
            "parentvapp": null, 
            "recenttask": [], 
            "availablefield": [], 
            "overallstatus": "green", 
            "network": [], 
            "guestheartbeatstatus": "green", 
            "name": "edin_host", 
            "rootsnapshot": [], 
            "configstatus": "green", 
            "value": [], 
            "summary": {}, 
            "capability": {}, 
            "snapshot": null, 
            "runtime": {}
          }, 
          "quickstats": {
            "ftsecondarylatency": -1, 
            "privatememory": 1877, 
            "compressedmemory": 0, 
            "consumedoverheadmemory": 37, 
            "swappedmemory": 0, 
            "ftlatencystatus": "gray", 
            "uptimeseconds": 1898839, 
            "ssdswappedmemory": 0, 
            "guestheartbeatstatus": "green", 
            "distributedmemoryentitlement": 602, 
            "staticcpuentitlement": 1905, 
            "balloonedmemory": 0, 
            "guestmemoryusage": 81, 
            "overallcpuusage": 0, 
            "overallcpudemand": 0, 
            "staticmemoryentitlement": 2111, 
            "ftlogbandwidth": -1, 
            "distributedcpuentitlement": 0, 
            "sharedmemory": 47, 
            "hostmemoryusage": 1916
          }, 
          "runtime": {
            "powerstate": "poweredOn", 
            "featuremask": [], 
            "onlinestandby": false, 
            "cleanpoweroff": null, 
            "featurerequirement": [], 
            "question": null, 
            "boottime": {}, 
            "maxmemoryusage": 2048, 
            "offlinefeaturerequirement": [], 
            "minrequiredevcmodekey": "intel-sandybridge", 
            "toolsinstallermounted": false, 
            "suspendinterval": 0, 
            "memoryoverhead": null, 
            "needsecondaryreason": null, 
            "vflashcacheallocation": 0, 
            "host": {}, 
            "maxcpuusage": 1999, 
            "device": [], 
            "suspendtime": null, 
            "recordreplaystate": "inactive", 
            "consolidationneeded": false, 
            "connectionstate": "connected", 
            "dasvmprotection": {}, 
            "faulttolerancestate": "notConfigured", 
            "nummksconnections": 0
          }, 
          "overallstatus": "green"
        }, 
        "overallstatus": "green", 
        "ansible_host": "192.168.1.1", 
        "triggeredalarmstate": [], 
        "network": [
          {
            "configstatus": "green", 
            "customvalue": [], 
            "name": "bi-acceptatie", 
            "effectiverole": [], 
            "permission": [], 
            "configissue": [], 
            "alarmactionsenabled": true, 
            "vm": [], 
            "value": [], 
            "summary": {}, 
            "host": [], 
            "tag": [], 
            "recenttask": [], 
            "availablefield": [], 
            "overallstatus": "green", 
            "triggeredalarmstate": []
          }
        ], 
        "configstatus": "green", 
        "guestheartbeatstatus": "green", 
        "layout": {
          "logfile": [
            "vmware-10.log", 
            "vmware-11.log", 
            "vmware-12.log", 
            "vmware-13.log", 
            "vmware-8.log", 
            "vmware-9.log", 
            "vmware.log"
          ], 
          "configfile": [
            "edin_host.nvram", 
            "edin_host.vmsd"
          ], 
          "disk": [], 
          "snapshot": [], 
          "swapfile": "[mydatastore] edin_host/edin_host-60ee652b.vswp"
        }, 
        "guest": {
          "appheartbeatstatus": "appStatusGray", 
          "interactiveguestoperationsready": false, 
          "toolsversion": "2147483647", 
          "toolsversionstatus": "guestToolsUnmanaged", 
          "toolsrunningstatus": "guestToolsRunning", 
          "ipaddress": "192.168.1.1", 
          "screen": {
            "width": 1280, 
            "height": 768
          }, 
          "guestfamily": "linuxGuest", 
          "generationinfo": [], 
          "ipstack": [], 
          "gueststate": "running", 
          "hostname": "edin_host.example.com", 
          "guestid": "centos64Guest", 
          "toolsstatus": "toolsOk", 
          "net": [], 
          "disk": [], 
          "appstate": "none", 
          "guestoperationsready": true, 
          "toolsversionstatus2": "guestToolsUnmanaged", 
          "guestfullname": "CentOS 4/5/6/7 (64-bit)"
        }, 
        "effectiverole": [
          -2
        ], 
        "rootsnapshot": [], 
        "alarmactionsenabled": true, 
        "value": [], 
        "name": "edin_host", 
        "capability": {
          "quiescedsnapshotssupported": true, 
          "cpufeaturemasksupported": true, 
          "consolepreferencessupported": false, 
          "vpmcsupported": true, 
          "featurerequirementsupported": true, 
          "snapshotconfigsupported": true, 
          "bootoptionssupported": true, 
          "changetrackingsupported": true, 
          "vmnpivwwnupdatesupported": true, 
          "poweredonmonitortypechangesupported": true, 
          "nestedhvsupported": true, 
          "poweredoffsnapshotssupported": true, 
          "settingvideoramsizesupported": true, 
          "settingscreenresolutionsupported": false, 
          "virtualmmuusagesupported": true, 
          "sesparsedisksupported": true, 
          "s1acpimanagementsupported": true, 
          "reverttosnapshotsupported": true, 
          "disksharessupported": true, 
          "vmnpivwwndisablesupported": true, 
          "disablesnapshotssupported": false, 
          "swapplacementsupported": true, 
          "bootretryoptionssupported": true, 
          "memoryreservationlocksupported": true, 
          "recordreplaysupported": true, 
          "settingdisplaytopologysupported": false, 
          "vmnpivwwnsupported": true, 
          "npivwwnonnonrdmvmsupported": true, 
          "toolsautoupdatesupported": false, 
          "multiplecorespersocketsupported": true, 
          "guestautolocksupported": true, 
          "multiplesnapshotssupported": true, 
          "snapshotoperationssupported": true, 
          "toolssynctimesupported": true, 
          "hostbasedreplicationsupported": true, 
          "locksnapshotssupported": true, 
          "memorysnapshotssupported": true
        }, 
        "snapshot": null, 
        "ansible_uuid": "39d641a6-9b9e-4ce0-b1f8-a4e8e38c9743", 
        "layoutex": {
          "timestamp": {
            "hour": 7, 
            "min": {}, 
            "max": {}, 
            "month": 12, 
            "second": 20, 
            "microsecond": 860550, 
            "year": 2016, 
            "tzinfo": {}, 
            "resolution": {}, 
            "day": 22, 
            "minute": 45
          }, 
          "disk": [], 
          "snapshot": [], 
          "file": []
        }, 
        "runtime": {
          "powerstate": "poweredOn", 
          "featuremask": [], 
          "onlinestandby": false, 
          "cleanpoweroff": null, 
          "featurerequirement": [], 
          "question": null, 
          "boottime": {
            "hour": 9, 
            "min": {}, 
            "max": {}, 
            "month": 11, 
            "second": 31, 
            "microsecond": 402054, 
            "year": 2016, 
            "tzinfo": {}, 
            "resolution": {}, 
            "day": 30, 
            "minute": 42
          }, 
          "maxmemoryusage": 2048, 
          "offlinefeaturerequirement": [], 
          "minrequiredevcmodekey": "intel-sandybridge", 
          "toolsinstallermounted": false, 
          "suspendinterval": 0, 
          "memoryoverhead": null, 
          "needsecondaryreason": null, 
          "vflashcacheallocation": 0, 
          "host": {
            "alarmactionsenabled": true, 
            "configissue": [], 
            "vm": [], 
            "hardware": {}, 
            "tag": [], 
            "datastore": [], 
            "triggeredalarmstate": [], 
            "network": [], 
            "effectiverole": [], 
            "datastorebrowser": {}, 
            "config": {}, 
            "customvalue": [], 
            "permission": [], 
            "systemresources": {}, 
            "configmanager": {}, 
            "recenttask": [], 
            "availablefield": [], 
            "overallstatus": "green", 
            "name": "esx1.example.com", 
            "configstatus": "green", 
            "value": [], 
            "summary": {}, 
            "capability": {}, 
            "licensableresource": {}, 
            "runtime": {}
          }, 
          "maxcpuusage": 1999, 
          "device": [], 
          "suspendtime": null, 
          "recordreplaystate": "inactive", 
          "consolidationneeded": false, 
          "connectionstate": "connected", 
          "dasvmprotection": {
            "dasprotected": true
          }, 
          "faulttolerancestate": "notConfigured", 
          "nummksconnections": 0
        }, 
        "config": {
          "uuid": "422c78f0-7401-3dbc-2790-9708af08bd03", 
          "alternateguestname": "", 
          "npivonnonrdmdisks": null, 
          "instanceuuid": "502c6c2d-8b58-a01c-4ce0-a18e0a65ac3a", 
          "cpuaffinity": null, 
          "npivdesirednodewwns": null, 
          "memoryhotaddenabled": true, 
          "hardware": {
            "virtualich7mpresent": false, 
            "numcpu": 1, 
            "virtualsmcpresent": false, 
            "memorymb": 2048, 
            "device": [], 
            "numcorespersocket": 1
          }, 
          "vappconfig": null, 
          "tools": {
            "beforegueststandby": true, 
            "beforeguestreboot": null, 
            "beforeguestshutdown": true, 
            "toolsupgradepolicy": "manual", 
            "afterresume": true, 
            "afterpoweron": true, 
            "synctimewithhost": false, 
            "lastinstallinfo": {}, 
            "pendingcustomization": null, 
            "toolsversion": 2147483647
          }, 
          "guestfullname": "CentOS 4/5/6/7 (64-bit)", 
          "changeversion": "2016-11-30T09:42:11.343789Z", 
          "defaultpowerops": {
            "defaultresettype": "soft", 
            "defaultsuspendtype": "hard", 
            "suspendtype": "hard", 
            "standbyaction": "powerOnSuspend", 
            "defaultpowerofftype": "soft", 
            "resettype": "soft", 
            "powerofftype": "soft"
          }, 
          "cpuhotremoveenabled": false, 
          "vpmcenabled": false, 
          "firmware": "bios", 
          "npivworldwidenametype": null, 
          "nestedhvenabled": false, 
          "version": "vmx-11", 
          "locationid": "564da59f-ac2b-54e9-c006-84e06f757410", 
          "maxmksconnections": 40, 
          "template": false, 
          "guestid": "centos64Guest", 
          "bootoptions": {
            "enterbiossetup": false, 
            "bootorder": [], 
            "bootdelay": 0, 
            "bootretryenabled": false, 
            "bootretrydelay": 10000
          }, 
          "cpufeaturemask": [], 
          "hotplugmemorylimit": 3072, 
          "npivnodeworldwidename": [], 
          "cpuallocation": {
            "overheadlimit": null, 
            "reservation": 0, 
            "limit": -1, 
            "shares": {}, 
            "expandablereservation": false
          }, 
          "files": {
            "vmpathname": "[mydatastore] edin_host/edin_host.vmx", 
            "snapshotdirectory": "[mydatastore] edin_host/", 
            "suspenddirectory": "[mydatastore] edint_host/", 
            "logdirectory": "[mydatastore] edin_host/"
          }, 
          "memoryreservationlockedtomax": false, 
          "scheduledhardwareupgradeinfo": {
            "fault": null, 
            "upgradepolicy": "never", 
            "versionkey": null, 
            "scheduledhardwareupgradestatus": "none"
          }, 
          "initialoverhead": null, 
          "hotplugmemoryincrementsize": 128, 
          "guestautolockenabled": false, 
          "latencysensitivity": {
            "sensitivity": null, 
            "level": "normal"
          }, 
          "npivtemporarydisabled": true, 
          "memoryallocation": {
            "overheadlimit": 63, 
            "reservation": 0, 
            "limit": -1, 
            "shares": {}, 
            "expandablereservation": false
          }, 
          "ftinfo": null, 
          "npivportworldwidename": [], 
          "annotation": null, 
          "memoryaffinity": null, 
          "vassertsenabled": false, 
          "datastoreurl": [], 
          "changetrackingenabled": false, 
          "name": "edin_host", 
          "npivdesiredportwwns": null, 
          "vflashcachereservation": 0, 
          "extraconfig": [], 
          "networkshaper": null, 
          "modified": {
            "hour": 0, 
            "min": {}, 
            "max": {}, 
            "month": 1, 
            "second": 0, 
            "microsecond": 0, 
            "year": 1970, 
            "tzinfo": {}, 
            "resolution": {}, 
            "day": 1, 
            "minute": 0
          }, 
          "consolepreferences": null, 
          "swapplacement": "inherit", 
          "flags": {
            "diskuuidenabled": false, 
            "snapshotdisabled": false, 
            "recordreplayenabled": false, 
            "runwithdebuginfo": false, 
            "virtualmmuusage": "automatic", 
            "enablelogging": true, 
            "snapshotpoweroffbehavior": "powerOff", 
            "snapshotlocked": false, 
            "htsharing": "any", 
            "disableacceleration": false, 
            "monitortype": "release", 
            "virtualexecusage": "hvAuto", 
            "usetoe": false
          }, 
          "cpuhotaddenabled": true
        }, 
        "ansible_ssh_host": "192.168.1.1"

Здорово, правда? :) Как я уже сказал, количество метаданных также регулируется max_object_level, так что если данных уж слишком много — опустите до 1.

Работаем со скриптом.


Пользоваться можно двумя способами: либо кладем скрипт с настройками в папку наших инвентарей, либо задаем инвентарь вручную:
ansible all -i /path/to/my/vmware_inventory.py -m setup

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

Пример номер 1


- name: example 1
  hosts: mail-scanner*
  gather_facts: False
  tasks:
  - name: say the name of the machine
    debug:
      msg: "Hello from {{ hostvars[inventory_hostname].resourcepool.name }}!"

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

Пример номер 2


---
- name: example nr2
  hosts: all
  gather_facts: False
  vars:
    resource_pool: "{{ hostvars[inventory_hostname].resourcepool._moId }}"
  tasks:
  - name: say hello, if in RP
    debug:
      msg: "Hello, fron {{ hostvars[inventory_hostname].name }}"
    when: resource_pool == "resgroup-1"

Здесь приходится применять грязный хак, поскольку квадратные скобки не хотят нормально обрабатываться в блоке when, поэтому сначала я декларирую переменную, а затем сверяюсь. Если машинка в ресурс пуле, Ansible вернет мне ее имя.

Пример номер 3


Делать подобные выкрутасы можно и в ролях.
--
- name: example nr3
  hosts: centos64Guest
  gather_facts: False
  vars:
    resource_pool: "{{ hostvars[inventory_hostname].resourcepool._moId }}"
  roles:
  - { role: myrole, when: resource_pool == "resgroup-1" }

Дорогой читатель, возможности использования метаданных ограничиваются лишь твоей фантазией!

Группируем по-своему


Здорово использовать метаданные для фильтрации в when, но это не решает проблему пробега по всем машинам — нам же хочется группировать машины на уровне скрипта. Для этого мы еще раз поиграем с настройкой groupby_patterns. К примеру, если выставить значение {{ resourcepool.name }} то группироваться будет по имени ресурс пула. Группировать еще можно по имени виртуальной сети ({{ network.name }}) или по таге ({{ tag }})

Какой способ лучше решать уже тебе, читатель.

P.S. Кстати, можно делать связку групп-родителей и групп-детей в статическом инвентаре. Подробно это описано в документации Ansible (пусть и на примере AWS).

Комментарии (0)

© Habrahabr.ru