wip: dynamic inventory

dynamic-inventory
Dustin 2025-02-07 06:23:21 -06:00
parent 143c96074e
commit ae39d2a232
2 changed files with 109 additions and 0 deletions

View File

@ -4,6 +4,7 @@
inventory = hosts
callback_plugins = plugins/callback
inventory_plugins = plugins/inventory
gathering = smart
fact_caching = jsonfile

View File

@ -0,0 +1,108 @@
import logging
from xml.etree import ElementTree as etree
import libvirt
import yaml
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
DOCUMENTATION = r'''
name: pyrocufflink
extends_documentation_fragment:
- constructed
short_description: Pyrocufflink inventory source
version_added: ''
description:
- Dynamic inventory for Pyrocufflink machines
author:
- Dustin C. Hatch <dustin@hatch.name>
options:
plugin:
description:
Token that ensures this is a source file for the 'pyrocufflink' plugin.
required: True
choices: ['pyrocufflink']
'''
log = logging.getLogger('ansible.plugins.inventory.pyrocufflink')
METADATA_XMLNS = 'http://du5t1n.me/xmlns/libvirt/metadata/'
DOMAIN_STATES = {
0: 'no state',
1: 'the domain is running',
2: 'the domain is blocked on resource',
3: 'the domain is paused by user',
4: 'the domain is being shut down',
5: 'the domain is shut off',
6: 'the domain is crashed',
7: 'the domain is suspended by guest power management',
}
# Remove the default error handler, which prints to stderr
libvirt.registerErrorHandler(lambda *_: None, None)
class InventoryModule(BaseInventoryPlugin, Constructable):
NAME = 'pyrocufflink'
def parse(self, inventory, loader, path, cache=True):
super().parse(inventory, loader, path, cache=cache)
config_data = self._read_config_data(path)
# set _options from config data
self._consume_options(config_data)
assert self.inventory
conn = libvirt.open()
for dom in conn.listAllDomains():
v = {}
name = v['name'] = dom.name()
try:
v['title'] = dom.metadata(1, None)
except libvirt.libvirtError as e:
log.debug('Could not get title for domain %s: %s', name, e)
inventory_hostname = name
else:
inventory_hostname = v['title']
self.inventory.add_host(inventory_hostname)
try:
v['description'] = dom.metadata(0, None)
except libvirt.libvirtError as e:
log.debug('Could not get description for %s: %s', name, e)
try:
metadata = dom.metadata(2, METADATA_XMLNS)
except libvirt.libvirtError as e:
log.debug(
'Could not get extended domain metadata for %s: %s',
name,
e,
)
else:
try:
v['metadata'] = parse_metadata(metadata)
except Exception as e:
log.error('Failed to parse metadata for %s: %s', name, e)
state, reason = dom.state()
v['state_code'] = state
v['state_reason_code'] = reason
try:
v['state'] = DOMAIN_STATES[state]
except KeyError:
pass
if state == 1:
try:
guest_info = dom.guestInfo()
except libvirt.libvirtError as e:
log.error('Could not get guest info for %s: %s', name, e)
else:
self.inventory.set_variable(name, 'guest_info', guest_info)
self.inventory.set_variable(inventory_hostname, 'libvirt', v)
def parse_metadata(metadata: str):
tree = etree.fromstring(metadata)
return yaml.safe_load(tree.text)