[libvirt] [jenkins-ci PATCH v2 04/12] lcitool: Add inventory handling
Katerina Koukiou
kkoukiou at redhat.com
Tue Jul 17 09:57:32 UTC 2018
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 at redhat.com>
> ---
> 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 at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20180717/9ffdc3ca/attachment-0001.sig>
More information about the libvir-list
mailing list