This asumes that your VM's in your libvirt network, have functioning DNS, using dnsmasq provided by libvirt and your host.
Created
December 31, 2019 05:40
-
-
Save sferich888/ec5517f7b88818e84175d33a83e8b5a4 to your computer and use it in GitHub Desktop.
libvirt dynamic inventory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import libvirt, json | |
from sys import stderr, argv | |
from xml.dom import minidom | |
### Default (Globals) | |
# We want this to run on the local system only. | |
host_domain = 'qemu:///system' | |
# Initialize the dictionary. May be a horrible way to deal with it, but deal with it. | |
inventory = {} | |
inventory['_meta'] = {} | |
inventory['_meta']['hostvars'] = {} | |
inventory['all'] = {} | |
inventory['all']['children'] = ['active', 'inactive'] | |
inventory['active'] = {} | |
inventory['inactive'] = {} | |
def get_doms_network(dom_list): | |
dom_networks = [] | |
for dom in dom_list: | |
raw_xml = dom.XMLDesc(0) | |
xml = minidom.parseString(raw_xml) | |
interfaceTypes = xml.getElementsByTagName('interface') | |
for interfaceType in interfaceTypes: | |
interfaceNodes = interfaceType.childNodes | |
for interfaceNode in interfaceNodes: | |
if interfaceNode.nodeName[0:1] != "#": | |
try: | |
dom_networks.append({'domain': dom.name(), | |
'network': interfaceNode.attributes['network'].value}) | |
except: | |
# the interfaceNode, does not have the attribute 'network' | |
# hasattr(interfaceNode, 'network') | |
# gennerally this can be ignored, thus pass. | |
pass | |
return dom_networks | |
def get_dom_domain(network_name): | |
raw_xml = virthost.networkLookupByName(network_name).XMLDesc(0) | |
xml = minidom.parseString(raw_xml) | |
return xml.getElementsByTagName('domain')[0].getAttribute('name') | |
def populate_inventory(): | |
if virthost == None: | |
print('Failed to open connection to {}'.format(host_domain), file=stderr) | |
exit(1) | |
activedomains = virthost.listAllDomains(libvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE) | |
inactivedomains = virthost.listAllDomains(libvirt.VIR_CONNECT_LIST_DOMAINS_INACTIVE) | |
for dom_list in [(activedomains, 'active'), (inactivedomains, 'inactive')]: | |
host_list = [] | |
for d in get_doms_network(dom_list[0]): | |
host_list.append("{}.{}".format(d['domain'], get_dom_domain(d['network']))) | |
if host_list: | |
inventory[dom_list[1]]['hosts'] = host_list | |
inventory[dom_list[1]]['vars'] = {} | |
if __name__ == '__main__': | |
if len(argv) == 2 and argv[1] == '--list': | |
virthost = libvirt.open(host_domain) | |
populate_inventory() | |
virthost.close() | |
print(json.dumps(inventory, indent=4, sort_keys=True)) | |
elif len(argv) == 3 and argv[1] == '--host': | |
# 1: Host var's are 'empty'; from this script | |
# 2: We don't do anything to set these! | |
# TODO: Look a pulling this from domain metadata? | |
# - https://libvirt.org/formatdomain.html#elementsMetadata | |
# 3: Ansible docs say return an empty dict '{}' | |
# - https://docs.ansible.com/ansible/latest/dev_guide/developing_inventory.html | |
print(json.dumps({})) | |
else: | |
print("Need an argument, either --list or --host <host>", file=stderr) | |
exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment