On Thu, Jul 12, 2018 at 05:19:21PM +0200, Andrea Bolognani wrote: > We use an actual YAML parser this time around, and bring > the behavior more in line with what Ansible is doing, so > interoperability should be more solid overall. > > New in this implementation is more flexibility in defining > host lists, including support for explicit lists as well > as glob patterns. > > Signed-off-by: Andrea Bolognani <abologna@xxxxxxxxxx> > --- > guests/lcitool | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 91 insertions(+) > > diff --git a/guests/lcitool b/guests/lcitool > index e03b388..e90a33b 100755 > --- a/guests/lcitool > +++ b/guests/lcitool > @@ -19,11 +19,13 @@ > > import argparse > import crypt > +import fnmatch > import os > import random > import string > import sys > import textwrap > +import yaml Since you have to install yaml to actually use it, I suggest at this point to create a requirements.txt file for this script, so that users don't have to go over the code to check the dependencies. > > # This is necessary to maintain Python 2.7 compatibility > try: > @@ -44,6 +46,32 @@ class Util: > salt = "".join(random.choice(alphabeth) for x in range(0, 16)) > return "$6${}$".format(salt) > > + @staticmethod > + def expand_pattern(pattern, source, name): > + if pattern == None: > + raise Error("Missing {} list".format(name)) > + > + if pattern == "all": > + pattern = "*" > + > + # This works correctly for single items as well as more complex > + # cases such as explicit lists, glob patterns and any combination > + # of the above > + matches = [] > + for partial_pattern in pattern.split(","): > + > + partial_matches = [] > + for item in source: > + if fnmatch.fnmatch(item, partial_pattern): > + partial_matches += [item] > + > + if len(partial_matches) == 0: > + raise Error("Invalid {} list '{}'".format(name, pattern)) > + > + matches += partial_matches > + > + return sorted(set(matches)) > + > class Config: > > def _get_config_file(self, name): > @@ -142,10 +170,73 @@ class Config: > > return root_hash_file > > +class Inventory: > + > + def __init__(self): > + try: > + parser = configparser.SafeConfigParser() > + parser.read("./ansible.cfg") > + inventory_path = parser.get("defaults", "inventory") > + except: > + raise Error("Can't find inventory location in ansible.cfg") > + > + self._facts = {} > + try: > + # We can only deal with trivial inventories, but that's > + # all we need right now and we can expand support further > + # later on if necessary > + with open(inventory_path, "r") as f: > + for line in f: > + host = line.strip() > + self._facts[host] = {} > + except: > + raise Error( > + "Missing or invalid inventory ({})".format( > + inventory_path, > + ) > + ) > + > + for host in self._facts: > + try: > + self._facts[host] = self._read_all_facts(host) > + self._facts[host]["inventory_hostname"] = host > + except: > + raise Error("Can't load facts for '{}'".format(host)) > + > + def _add_facts_from_file(self, facts, yaml_path): > + with open(yaml_path, "r") as f: > + some_facts = yaml.load(f) > + for fact in some_facts: > + facts[fact] = some_facts[fact] > + > + def _read_all_facts(self, host): > + facts = {} > + > + # We load from group_vars/ first and host_vars/ second, sorting > + # files alphabetically; doing so should result in our view of > + # the facts matching Ansible's > + for source in ["./group_vars/all/", "./host_vars/{}/".format(host)]: > + for item in sorted(os.listdir(source)): > + yaml_path = os.path.join(source, item) > + if not os.path.isfile(yaml_path): > + continue > + if not yaml_path.endswith(".yml"): > + continue > + self._add_facts_from_file(facts, yaml_path) > + > + return facts > + > + def expand_pattern(self, pattern): > + return Util.expand_pattern(pattern, self._facts, "host") > + > + def get_facts(self, host): > + return self._facts[host] > + > class Application: > > def __init__(self): > self._config = Config() > + self._inventory = Inventory() > > self._parser = argparse.ArgumentParser( > conflict_handler = "resolve", > -- > 2.17.1 > > -- > libvir-list mailing list > libvir-list@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list
Attachment:
signature.asc
Description: PGP signature
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list