109 lines
3.4 KiB
Python
109 lines
3.4 KiB
Python
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)
|