def listfunction(llist):
    """This function does all the work and lists groups or hosts"""
    variable_manager = VariableManager()
    loader = DataLoader()
    if not os.path.isfile(inventory_file):
        print "%s is not a file - halting. Consider using the '--inventory $path/to/ansible_inventory file' parameter" % inventory_file
        sys.exit(1)
    else:
        inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=inventory_file)

    if chosen_group and single:
        def traverse(agroup, hostset):
            """Recursive depth-first traversal"""
            for child in agroup.child_groups:
                traverse(child, hostset)
            if len(agroup.hosts) > 0:
                hostset.add(agroup.hosts[0].name.encode('utf8'))
        single_hosts = set()
        traverse(inventory.groups[chosen_group], single_hosts)
        return {chosen_group:list(single_hosts)}

    if chosen_group:
        thegroup = inventory.groups[chosen_group]
        newhosts = []
        for h in thegroup.get_hosts():
            newhosts.append(h.name.encode('utf8'))
        return {chosen_group:newhosts}
    else:
        all_groups = {}
        for g in inventory.groups:
            newhosts = []
            for h in inventory.get_group(g).get_hosts():
                newhosts.append(h.name.encode('utf8'))
            all_groups[g] = newhosts
        return all_groups
def build_inventory(loader, variable_manager, group_names, playbook_basedir):
    inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=['localhost'])

    # because we just pass in a "host list" which isn't a real inventory file,
    # we explicitly have to add all of the desired groups to the inventory. By
    # default an "all" group is created whenever a new inventory is created
    for group_name in group_names:
        if not inventory.get_group(group_name):
            inventory.add_group(Group(group_name))

    # because we are explicitly adding groups, we also need to make sure that a
    # playbook basedir is set so that `group_vars` can be loaded from the
    # correct directory.
    inventory.set_playbook_basedir(playbook_basedir)
    inventory_hosts = inventory.get_hosts()

    # for each group specified, ensure that the inventory's host (localhost) is
    # explicitly in the group.
    for group_name in group_names:
        group = inventory.get_group(group_name)
        if group.get_hosts():
            continue

        for host in inventory.get_hosts():
            group.add_host(host)

    return inventory
Esempio n. 3
0
def run_installer(user_list, package_list, sudo_password):
    """
    Runs the playbook `installer.yml` with the supplied parameters
    """

    # Create the inventory
    controller = Host(name="localhost")
    controller.set_variable('users', user_list)
    controller.set_variable('apt_packages', package_list)
    local_inventory = Inventory([])
    local_inventory.get_group('all').add_host(controller)

    # Boilerplate for callbacks setup
    utils.VERBOSITY = 0
    # Output callbacks setup
    output_callbacks = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
    # API callbacks setup
    stats = callbacks.AggregateStats()
    api_callbacks = callbacks.PlaybookRunnerCallbacks(stats,
                                                      verbose=utils.VERBOSITY)

    provision_playbook = PlayBook(playbook="installer.yml",
                                  stats=stats,
                                  callbacks=output_callbacks,
                                  runner_callbacks=api_callbacks,
                                  inventory=local_inventory,
                                  transport="local",
                                  become_pass=sudo_password)
    playbook_result = provision_playbook.run()
    return playbook_result
def build_inventory(loader, variable_manager, group_names, playbook_basedir):
    inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=['localhost'])

    # because we just pass in a "host list" which isn't a real inventory file,
    # we explicitly have to add all of the desired groups to the inventory. By
    # default an "all" group is created whenever a new inventory is created
    for group_name in group_names:
        if not inventory.get_group(group_name):
            inventory.add_group(Group(group_name))

    # because we are explicitly adding groups, we also need to make sure that a
    # playbook basedir is set so that `group_vars` can be loaded from the
    # correct directory.
    inventory.set_playbook_basedir(playbook_basedir)

    # for each group specified, ensure that the inventory's host (localhost) is
    # explicitly in the group.
    for group_name in group_names:
        group = inventory.get_group(group_name)
        if group.get_hosts():
            continue

        for host in inventory.get_hosts():
            group.add_host(host)

    return inventory
Esempio n. 5
0
def run_installer(user_list, package_list, sudo_password):
    """
    Runs the playbook `installer.yml` with the supplied parameters
    """

    # Create the inventory
    controller = Host(name="localhost")
    controller.set_variable("users", user_list)
    controller.set_variable("apt_packages", package_list)
    local_inventory = Inventory([])
    local_inventory.get_group("all").add_host(controller)

    # Boilerplate for callbacks setup
    utils.VERBOSITY = 0
    # Output callbacks setup
    output_callbacks = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
    # API callbacks setup
    stats = callbacks.AggregateStats()
    api_callbacks = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)

    provision_playbook = PlayBook(
        playbook="installer.yml",
        stats=stats,
        callbacks=output_callbacks,
        runner_callbacks=api_callbacks,
        inventory=local_inventory,
        transport="local",
        become_pass=sudo_password,
    )
    playbook_result = provision_playbook.run()
    return playbook_result
Esempio n. 6
0
class AnsibleEnvironment():
    _cache = {}

    def __init__(self):
        ansible_basedir = os.path.join(
            os.environ.get("PROJECT_ENVIRONMENT_FILES_PATH"), "ansible")

        loader = CustomLoader()
        loader.set_basedir(ansible_basedir)

        var_manager = VariableManager()

        # load the inventory, set the basic playbook directory
        self._inventory = Inventory(loader=loader,
                                    variable_manager=var_manager)
        self._inventory.set_playbook_basedir(ansible_basedir)

        group = self._inventory.get_group("all")

        # make sure we load all magic variables on top of the global variables
        self._vars = combine_vars(
            self._inventory.get_group_vars(group, return_results=True),
            var_manager._get_magic_variables(loader, False, None, None, False,
                                             False))
        self._vars['groups'] = self._inventory.get_group_dict()
        self._vars['env'] = os.environ

        hostvars = {}
        for host in self._inventory.get_hosts():
            hostvars[host.name] = host.get_vars()

        self._vars['hostvars'] = hostvars

        # create the template renderer
        self._templar = Templar(loader=loader, variables=self._vars)

        # setup some easy variables that we use a lot
        self._vars['control_ip'] = self.get_var(
            "hostvars[groups['control'][0]]['ansible_host']")
        self._vars['edge_ip'] = self.get_var(
            "hostvars[groups['edge'][0]]['ansible_host']")
        self._vars['monitor_ip'] = self.get_var(
            "hostvars[groups['monitor'][0]]['ansible_host']")

    def get_var(self, name, cache=True):
        if name not in self._cache or not cache:
            try:
                self._cache[name] = self._templar.template("{{%s}}" % name)
            except AnsibleUndefinedVariable:
                self._cache[name] = None
        return self._cache.get(name)

    def set_var(self, name, value):
        self._vars[name] = value

    def template(self, *templates):
        return '\n'.join([self._templar.template(tpl) for tpl in templates])
Esempio n. 7
0
def _get_hosts():
    """Inspect OpenStack Ansible setup for hosts and services. Returned
    dictionary has a hostname as a key, and set of services as a value.
    Here's an example::

        {
            'host-1': [
                {'name': 'nova-conductor'},
                {'name': 'nova-api'},
            ],
            'host-2': [
                {'name': 'nova-compute'},
            ],
        }

    Please note, in some case we may return extra services due to bugs
    in OpenStack Ansible dynamic inventory which may produce extra items.
    Though they won't affect upgrade procedure, they might be a little
    misleading.
    """
    rv = collections.defaultdict(list)
    inventory = Inventory(DataLoader(), VariableManager())

    for group, services in _SERVICES_BY_INVENTORY_GROUPS.items():
        group = inventory.get_group(group)

        if group is None:
            continue

        for host in group.get_hosts():
            # In case of All-in-One setup, some services might allocated few
            # times on the same host. For instance, Neutron L2 agent should
            # run on baremetal host with nova-compute as well as inside
            # Nuetron control plane containers. From Kostyor POV, we are not
            # interested in such details so we need to deduplicate service
            # entries.
            to_add = filter(
                lambda candidate: not bool(list(filter(
                    lambda service: service['name'] == candidate,
                    rv[host.get_vars()['physical_host']]
                ))),
                services)

            # TODO: Process services to be added as not of them may be
            #       applied to the current setup. E.g., Neutron may be
            #       configured to use openvswitch instead of linux bridges,
            #       while we always add both of them. It doesn't affect
            #       upgrade procedure, though, since services are used
            #       to build an upgrade order and no more.
            rv[host.get_vars()['physical_host']].extend((
                {'name': service} for service in to_add
            ))

    return rv
Esempio n. 8
0
    def _load(self):

        variable_manager = VariableManager()
        variable_manager.extra_vars = {}
        variable_manager.options_vars = {'ansible_check_mode': False}

        loader = DataLoader()
        passwords = dict(vault_pass='******')

        #display seems not to work yet :-(
        display = Display()
        display.verbosity = self.options.verbosity
        #        playbook_executor.display.verbosity = self.options.verbosity

        extra_vars = {
            'elastic_url': Configuration.elastic_url,
            'uuid': self._job.uuid
        }
        self.variable_manager.extra_vars = extra_vars

        inventory = Inventory(loader=loader,
                              variable_manager=variable_manager,
                              host_list=self.inventoryContainer.allHosts())
        for group in self.inventoryContainer.groups:
            if group.name == 'all':
                if group.vars:
                    inventory.get_group('all').vars.update(group.vars)
            else:
                group.parent_groups.append(inventory.get_group('all'))
                inventory.add_group(group)

        variable_manager.set_inventory(inventory)
        playbook = "%s/%s" % (self.pb_dir__, self.playbook__)

        pbx = PlaybookExecutor(playbooks=[playbook],
                               inventory=inventory,
                               variable_manager=variable_manager,
                               loader=loader,
                               options=self.options,
                               passwords=passwords)
        pbx.run()
Esempio n. 9
0
def staging():
    inventory = Inventory('ansible/staging')

    env.roledefs={
        "webservers": [
            "{ssh_user}@{address}".format(
                ssh_user=SSH_USER,
                address=host.name
            )
            for host in inventory.get_group('webservers').hosts
        ]
    }

    env.DJANGO_SETTINGS_MODULE = "techfugees.settings.staging"
    env.REQUIREMENTS_FILE = "staging.txt"
    env.PROVISION_ENV = "staging"
Esempio n. 10
0
def production():
    prompt(red("Are you sure you want to run on production? [y/n]"), validate=validate_yes_no)

    inventory = Inventory('ansible/production')

    env.roledefs={
        "webservers": [
            "{ssh_user}@{address}".format(
                ssh_user=SSH_USER,
                address=host.name
            )
            for host in inventory.get_group('webservers').hosts
        ]
    }

    env.DJANGO_SETTINGS_MODULE = "techfugees.settings.production"
    env.REQUIREMENTS_FILE = "production.txt"
    env.PROVISION_ENV = "production"
Esempio n. 11
0
def _main():
    global tab_size

    parser = argparse.ArgumentParser(
        description="Convert the Ansible inventory from INI to yML format", )
    parser.add_argument("-i",
                        dest="inventory_file",
                        help="Inform the Ansible Vault Password",
                        required=True)
    parser.add_argument(
        "-d",
        dest="dest_inventory_path",
        help=
        "Destination to save the inventory files (Default will be on $PWD)",
        required=False)
    parser.add_argument(
        "-g",
        dest="group",
        help="Filter by specific GROUP",
    )
    parser.add_argument(
        "-p",
        dest="vault_password",
        help="Inform the Ansible Vault Password or file with password",
    )
    parser.add_argument(
        "-t",
        dest="tab_size",
        type=int,
        help="Number of tab spaces",
        default=4,
    )

    args = parser.parse_args()
    tab_size = args.tab_size

    try:
        #  Ansible: initialize needed objects
        variable_manager = VariableManager()
        loader = DataLoader()

        if args.vault_password:
            if os.path.isfile(args.vault_password):
                with open(args.vault_password, "r") as f:
                    args.vault_password = f.readlines()[0].rstrip()
                    f.close()

            print("** Passing Vault Password: '******'") % (args.vault_password)
            loader.set_vault_password(args.vault_password)

        #  Ansible: Load inventory
        inventory = Inventory(
            loader=loader,
            variable_manager=variable_manager,
            host_list=args.inventory_file,
        )
    except Exception as e:
        print("** ERROR: Missing the '--vault-password'??\n %s\n") % str(e)
        sys.exit(-1)

    try:
        groups = {}

        if args.group:
            _group = inventory.get_group(args.group)
            if not _group:
                print("** ERROR: No such group '%s' in inventory file '%s', exiting.") % \
                    (args.group, args.inventory_file)
                sys.exit(-1)

            groups[args.group] = _group
        else:
            groups = inventory.get_groups()

        for group in groups:
            if group == "all":
                continue

            # start the file
            output = ""
            output += "###################################################################################################\n"
            output += ("# Converted from '%s[%s]'\n") % (args.inventory_file,
                                                         group)
            output += "###################################################################################################\n"
            output += ("%s:\n") % group

            group_ref = inventory.get_group(group)

            # children or hosts?
            if group_ref.child_groups:
                output += ident_as_usual(1, "children")
                for group_name in sorted(group_ref.child_groups):
                    output += ident_as_usual(2, group_name.get_name())
            else:
                group_ips = group_ref.hosts
                if not group_ips:
                    continue
                output += ""
                output += ident_as_usual(1, "hosts")
                for group_ip in sorted(group_ips):
                    if filter_vars(group_ip):
                        continue
                    output += ident_as_usual(2, group_ip.get_name())
                    _ip_host_vars = inventory.get_host_vars(
                        group_ip, return_results=True)  # group_vars/$group
                    _ip_vars = inventory.get_vars(
                        to_native(group_ip))  # host key1=var1
                    group_ip_vars = dict(_ip_host_vars.items() +
                                         _ip_vars.items())
                    if not group_ip_vars:
                        continue
                    for k, v in group_ip_vars.items():
                        if filter_vars(k):
                            continue
                        output += ident_as_the_key(3, k, v)

            # group_vars/$service
            output += "\n"
            output += ident_as_usual(1, "vars")
            group_vars = inventory.get_group_vars(group_ref,
                                                  return_results=True)
            if group_vars:
                for k, v in sorted(group_vars.items()):
                    if filter_vars(k):
                        continue
                    output += ident_as_the_key(2, k, v)
            output += "\n"
            output += ("# End for %s\n") % group

            if not args.dest_inventory_path:
                print(output)
            else:
                dest = args.dest_inventory_path + "/" + group + ".yml"
                print("Generating " + dest)

                try:
                    dest_dir = os.path.dirname(dest)
                    os.makedirs(dest_dir)
                except OSError as e:
                    if e.errno != errno.EEXIST:
                        raise

                f = file(dest, "w+")
                f.write(output)
                f.close()

        # Should save the 'group_vars/all' ?
        src = "group_vars/all"
        if args.dest_inventory_path and os.path.isfile(src):
            dest = args.dest_inventory_path + "/" + src
            print("Copying '%s' to '%s'") % (src, dest)
            try:
                dest_dir = os.path.dirname(dest)
                os.makedirs(dest_dir)
            except OSError as e:
                if e.errno != errno.EEXIST:
                    raise
            shutil.copyfile(src, dest)

    except Exception as e:
        print("** ERROR: %s\n") % str(e)
        traceback.print_exc()
Esempio n. 12
0
class InventoryCLI(CLI):
    ''' used to display or dump the configured inventory as Ansible sees it '''

    ARGUMENTS = {'host': 'The name of a host to match in the inventory, relevant when using --list',
                 'group': 'The name of a group in the inventory, relevant when using --graph', }

    def __init__(self, args):

        super(InventoryCLI, self).__init__(args)
        self.vm = None
        self.loader = None
        self.inventory = None

        self._new_api = True

    def parse(self):

        self.parser = CLI.base_parser(
            usage='usage: %prog [options] [host|group]',
            epilog='Show Ansible inventory information, by default it uses the inventory script JSON format',
            inventory_opts=True,
            vault_opts=True
        )

        # Actions
        action_group = optparse.OptionGroup(self.parser, "Actions", "One of following must be used on invocation, ONLY ONE!")
        action_group.add_option("--list", action="store_true", default=False, dest='list', help='Output all hosts info, works as inventory script')
        action_group.add_option("--host", action="store", default=None, dest='host', help='Output specific host info, works as inventory script')
        action_group.add_option("--graph", action="store_true", default=False, dest='graph',
                                help='create inventory graph, if supplying pattern it must be a valid group name')
        self.parser.add_option_group(action_group)

        # Options
        self.parser.add_option("-y", "--yaml", action="store_true", default=False, dest='yaml',
                               help='Use YAML format instead of default JSON, ignored for --graph')
        self.parser.add_option("--vars", action="store_true", default=False, dest='show_vars',
                               help='Add vars to graph display, ignored unless used with --graph')

        super(InventoryCLI, self).parse()

        display.verbosity = self.options.verbosity

        self.validate_conflicts(vault_opts=True)

        # there can be only one! and, at least, one!
        used = 0
        for opt in (self.options.list, self.options.host, self.options.graph):
            if opt:
                used += 1
        if used == 0:
            raise AnsibleOptionsError("No action selected, at least one of --host, --graph or --list needs to be specified.")
        elif used > 1:
            raise AnsibleOptionsError("Conflicting options used, only one of --host, --graph or --list can be used at the same time.")

        # set host pattern to default if not supplied
        if len(self.args) > 0:
            self.options.pattern = self.args[0]
        else:
            self.options.pattern = 'all'

    def run(self):

        results = None

        super(InventoryCLI, self).run()

        # Initialize needed objects
        if getattr(self, '_play_prereqs', False):
            self.loader, self.inventory, self.vm = self._play_prereqs(self.options)
        else:
            # fallback to pre 2.4 way of initialzing
            from ansible.vars import VariableManager
            from ansible.inventory import Inventory

            self._new_api = False
            self.loader = DataLoader()
            self.vm = VariableManager()

            # use vault if needed
            if self.options.vault_password_file:
                vault_pass = CLI.read_vault_password_file(self.options.vault_password_file, loader=self.loader)
            elif self.options.ask_vault_pass:
                vault_pass = self.ask_vault_passwords()
            else:
                vault_pass = None

            if vault_pass:
                self.loader.set_vault_password(vault_pass)
                # actually get inventory and vars

            self.inventory = Inventory(loader=self.loader, variable_manager=self.vm, host_list=self.options.inventory)
            self.vm.set_inventory(self.inventory)

        if self.options.host:
            hosts = self.inventory.get_hosts(self.options.host)
            if len(hosts) != 1:
                raise AnsibleOptionsError("You must pass a single valid host to --hosts parameter")

            myvars = self._get_host_variables(host=hosts[0])
            self._remove_internal(myvars)

            # FIXME: should we template first?
            results = self.dump(myvars)

        elif self.options.graph:
            results = self.inventory_graph()
        elif self.options.list:
            top = self._get_group('all')
            if self.options.yaml:
                results = self.yaml_inventory(top)
            else:
                results = self.json_inventory(top)
            results = self.dump(results)

        if results:
            # FIXME: pager?
            display.display(results)
            exit(0)

        exit(1)

    def dump(self, stuff):

        if self.options.yaml:
            import yaml
            from ansible.parsing.yaml.dumper import AnsibleDumper
            results = yaml.dump(stuff, Dumper=AnsibleDumper, default_flow_style=False)
        else:
            import json
            results = json.dumps(stuff, sort_keys=True, indent=4)

        return results

    def _get_host_variables(self, host):
        if self._new_api:
            hostvars = self.vm.get_vars(host=host)
        else:
            hostvars = self.vm.get_vars(self.loader, host=host)
        return hostvars

    def _get_group(self, gname):
        if self._new_api:
            group = self.inventory.groups.get(gname)
        else:
            group = self.inventory.get_group(gname)
        return group

    def _remove_internal(self, dump):

        for internal in INTERNAL_VARS:
            if internal in dump:
                del dump[internal]

    def _remove_empty(self, dump):
        # remove empty keys
        for x in ('hosts', 'vars', 'children'):
            if x in dump and not dump[x]:
                del dump[x]

    def _show_vars(self, dump, depth):
        result = []
        self._remove_internal(dump)
        if self.options.show_vars:
            for (name, val) in sorted(dump.items()):
                result.append(self._graph_name('{%s = %s}' % (name, val), depth + 1))
        return result

    def _graph_name(self, name, depth=0):
        if depth:
            name = "  |" * (depth) + "--%s" % name
        return name

    def _graph_group(self, group, depth=0):

        result = [self._graph_name('@%s:' % group.name, depth)]
        depth = depth + 1
        for kid in sorted(group.child_groups, key=attrgetter('name')):
            result.extend(self._graph_group(kid, depth))

        if group.name != 'all':
            for host in sorted(group.hosts, key=attrgetter('name')):
                result.append(self._graph_name(host.name, depth))
                result.extend(self._show_vars(host.get_vars(), depth))

        result.extend(self._show_vars(group.get_vars(), depth))

        return result

    def inventory_graph(self):

        start_at = self._get_group(self.options.pattern)
        if start_at:
            return '\n'.join(self._graph_group(start_at))
        else:
            raise AnsibleOptionsError("Pattern must be valid group name when using --graph")

    def json_inventory(self, top):

        def format_group(group):
            results = {}
            results[group.name] = {}
            if group.name != 'all':
                results[group.name]['hosts'] = [h.name for h in sorted(group.hosts, key=attrgetter('name'))]
            results[group.name]['vars'] = group.get_vars()
            results[group.name]['children'] = []
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                results[group.name]['children'].append(subgroup.name)
                results.update(format_group(subgroup))

            self._remove_empty(results[group.name])
            return results

        results = format_group(top)

        # populate meta
        results['_meta'] = {'hostvars': {}}
        hosts = self.inventory.get_hosts()
        for host in hosts:
            results['_meta']['hostvars'][host.name] = self._get_host_variables(host=host)
            self._remove_internal(results['_meta']['hostvars'][host.name])

        return results

    def yaml_inventory(self, top):

        seen = []

        def format_group(group):
            results = {}

            # initialize group + vars
            results[group.name] = {}
            results[group.name]['vars'] = group.get_vars()

            # subgroups
            results[group.name]['children'] = {}
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                if subgroup.name != 'all':
                    results[group.name]['children'].update(format_group(subgroup))

            # hosts for group
            results[group.name]['hosts'] = {}
            if group.name != 'all':
                for h in sorted(group.hosts, key=attrgetter('name')):
                    myvars = {}
                    if h.name not in seen:  # avoid defining host vars more than once
                        seen.append(h.name)
                        myvars = self._get_host_variables(host=h)
                        self._remove_internal(myvars)
                    results[group.name]['hosts'][h.name] = myvars

            self._remove_empty(results[group.name])
            return results

        return format_group(top)
Esempio n. 13
0
class InventoryCLI(CLI):
    ''' used to display or dump the configured inventory as Ansible sees it '''

    ARGUMENTS = {
        'host':
        'The name of a host to match in the inventory, relevant when using --list',
        'group':
        'The name of a group in the inventory, relevant when using --graph',
    }

    def __init__(self, args):

        super(InventoryCLI, self).__init__(args)
        self.vm = None
        self.loader = None
        self.inventory = None

        self._new_api = True

    def parse(self):

        self.parser = CLI.base_parser(
            usage='usage: %prog [options] [host|group]',
            epilog=
            'Show Ansible inventory information, by default it uses the inventory script JSON format',
            inventory_opts=True,
            vault_opts=True,
            basedir_opts=True,
        )

        # remove unused default options
        self.parser.remove_option('--limit')
        self.parser.remove_option('--list-hosts')

        # Actions
        action_group = optparse.OptionGroup(
            self.parser, "Actions",
            "One of following must be used on invocation, ONLY ONE!")
        action_group.add_option(
            "--list",
            action="store_true",
            default=False,
            dest='list',
            help='Output all hosts info, works as inventory script')
        action_group.add_option(
            "--host",
            action="store",
            default=None,
            dest='host',
            help='Output specific host info, works as inventory script')
        action_group.add_option(
            "--graph",
            action="store_true",
            default=False,
            dest='graph',
            help=
            'create inventory graph, if supplying pattern it must be a valid group name'
        )
        self.parser.add_option_group(action_group)

        # graph
        self.parser.add_option(
            "-y",
            "--yaml",
            action="store_true",
            default=False,
            dest='yaml',
            help='Use YAML format instead of default JSON, ignored for --graph'
        )
        self.parser.add_option(
            "--vars",
            action="store_true",
            default=False,
            dest='show_vars',
            help='Add vars to graph display, ignored unless used with --graph')

        # list
        self.parser.add_option(
            "--export",
            action="store_true",
            default=C.INVENTORY_EXPORT,
            dest='export',
            help=
            "When doing an --list, represent in a way that is optimized for export,"
            "not as an accurate representation of how Ansible has processed it"
        )
        # self.parser.add_option("--ignore-vars-plugins", action="store_true", default=False, dest='ignore_vars_plugins',
        #                       help="When doing an --list, skip vars data from vars plugins, by default, this would include group_vars/ and host_vars/")

        super(InventoryCLI, self).parse()

        display.verbosity = self.options.verbosity

        self.validate_conflicts(vault_opts=True)

        # there can be only one! and, at least, one!
        used = 0
        for opt in (self.options.list, self.options.host, self.options.graph):
            if opt:
                used += 1
        if used == 0:
            raise AnsibleOptionsError(
                "No action selected, at least one of --host, --graph or --list needs to be specified."
            )
        elif used > 1:
            raise AnsibleOptionsError(
                "Conflicting options used, only one of --host, --graph or --list can be used at the same time."
            )

        # set host pattern to default if not supplied
        if len(self.args) > 0:
            self.options.pattern = self.args[0]
        else:
            self.options.pattern = 'all'

    def run(self):

        results = None

        super(InventoryCLI, self).run()

        # Initialize needed objects
        if getattr(self, '_play_prereqs', False):
            self.loader, self.inventory, self.vm = self._play_prereqs(
                self.options)
        else:
            # fallback to pre 2.4 way of initialzing
            from ansible.vars import VariableManager
            from ansible.inventory import Inventory

            self._new_api = False
            self.loader = DataLoader()
            self.vm = VariableManager()

            # use vault if needed
            if self.options.vault_password_file:
                vault_pass = CLI.read_vault_password_file(
                    self.options.vault_password_file, loader=self.loader)
            elif self.options.ask_vault_pass:
                vault_pass = self.ask_vault_passwords()
            else:
                vault_pass = None

            if vault_pass:
                self.loader.set_vault_password(vault_pass)
                # actually get inventory and vars

            self.inventory = Inventory(loader=self.loader,
                                       variable_manager=self.vm,
                                       host_list=self.options.inventory)
            self.vm.set_inventory(self.inventory)

        if self.options.host:
            hosts = self.inventory.get_hosts(self.options.host)
            if len(hosts) != 1:
                raise AnsibleOptionsError(
                    "You must pass a single valid host to --hosts parameter")

            myvars = self._get_host_variables(host=hosts[0])
            self._remove_internal(myvars)

            # FIXME: should we template first?
            results = self.dump(myvars)

        elif self.options.graph:
            results = self.inventory_graph()
        elif self.options.list:
            top = self._get_group('all')
            if self.options.yaml:
                results = self.yaml_inventory(top)
            else:
                results = self.json_inventory(top)
            results = self.dump(results)

        if results:
            # FIXME: pager?
            display.display(results)
            exit(0)

        exit(1)

    def dump(self, stuff):

        if self.options.yaml:
            import yaml
            from ansible.parsing.yaml.dumper import AnsibleDumper
            results = yaml.dump(stuff,
                                Dumper=AnsibleDumper,
                                default_flow_style=False)
        else:
            import json
            from ansible.parsing.ajson import AnsibleJSONEncoder
            results = json.dumps(stuff,
                                 cls=AnsibleJSONEncoder,
                                 sort_keys=True,
                                 indent=4)

        return results

    # FIXME: refactor to use same for VM
    def get_plugin_vars(self, path, entity):

        data = {}

        def _get_plugin_vars(plugin, path, entities):
            data = {}
            try:
                data = plugin.get_vars(self.loader, path, entity)
            except AttributeError:
                try:
                    if isinstance(entity, Host):
                        data = combine_vars(data,
                                            plugin.get_host_vars(entity.name))
                    else:
                        data = combine_vars(data,
                                            plugin.get_group_vars(entity.name))
                except AttributeError:
                    if hasattr(plugin, 'run'):
                        raise AnsibleError(
                            "Cannot use v1 type vars plugin %s from %s" %
                            (plugin._load_name, plugin._original_path))
                    else:
                        raise AnsibleError(
                            "Invalid vars plugin %s from %s" %
                            (plugin._load_name, plugin._original_path))
            return data

        for plugin in vars_loader.all():
            data = combine_vars(data, _get_plugin_vars(plugin, path, entity))

        return data

    def _get_group_variables(self, group):

        # get info from inventory source
        res = group.get_vars()

        # FIXME: add switch to skip vars plugins, add vars plugin info
        for inventory_dir in self.inventory._sources:
            res = combine_vars(res, self.get_plugin_vars(inventory_dir, group))

        if group.priority != 1:
            res['ansible_group_priority'] = group.priority

        return res

    def _get_host_variables(self, host):

        if self.options.export:
            hostvars = host.get_vars()

            # FIXME: add switch to skip vars plugins
            # add vars plugin info
            for inventory_dir in self.inventory._sources:
                hostvars = combine_vars(
                    hostvars, self.get_plugin_vars(inventory_dir, host))
        else:
            if self._new_api:
                hostvars = self.vm.get_vars(host=host, include_hostvars=False)
            else:
                hostvars = self.vm.get_vars(self.loader,
                                            host=host,
                                            include_hostvars=False)

        return hostvars

    def _get_group(self, gname):
        if self._new_api:
            group = self.inventory.groups.get(gname)
        else:
            group = self.inventory.get_group(gname)
        return group

    def _remove_internal(self, dump):

        for internal in INTERNAL_VARS:
            if internal in dump:
                del dump[internal]

    def _remove_empty(self, dump):
        # remove empty keys
        for x in ('hosts', 'vars', 'children'):
            if x in dump and not dump[x]:
                del dump[x]

    def _show_vars(self, dump, depth):
        result = []
        self._remove_internal(dump)
        if self.options.show_vars:
            for (name, val) in sorted(dump.items()):
                result.append(
                    self._graph_name('{%s = %s}' % (name, val), depth))
        return result

    def _graph_name(self, name, depth=0):
        if depth:
            name = "  |" * (depth) + "--%s" % name
        return name

    def _graph_group(self, group, depth=0):

        result = [self._graph_name('@%s:' % group.name, depth)]
        depth = depth + 1
        for kid in sorted(group.child_groups, key=attrgetter('name')):
            result.extend(self._graph_group(kid, depth))

        if group.name != 'all':
            for host in sorted(group.hosts, key=attrgetter('name')):
                result.append(self._graph_name(host.name, depth))
                result.extend(self._show_vars(host.get_vars(), depth + 1))

        result.extend(self._show_vars(self._get_group_variables(group), depth))

        return result

    def inventory_graph(self):

        start_at = self._get_group(self.options.pattern)
        if start_at:
            return '\n'.join(self._graph_group(start_at))
        else:
            raise AnsibleOptionsError(
                "Pattern must be valid group name when using --graph")

    def json_inventory(self, top):
        def format_group(group):
            results = {}
            results[group.name] = {}
            if group.name != 'all':
                results[group.name]['hosts'] = [
                    h.name for h in sorted(group.hosts, key=attrgetter('name'))
                ]
            results[group.name]['children'] = []
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                results[group.name]['children'].append(subgroup.name)
                results.update(format_group(subgroup))
            if self.options.export:
                results[group.name]['vars'] = self._get_group_variables(group)

            self._remove_empty(results[group.name])

            return results

        results = format_group(top)

        # populate meta
        results['_meta'] = {'hostvars': {}}
        hosts = self.inventory.get_hosts()
        for host in hosts:
            hvars = self._get_host_variables(host)
            if hvars:
                self._remove_internal(hvars)
                results['_meta']['hostvars'][host.name] = hvars

        return results

    def yaml_inventory(self, top):

        seen = []

        def format_group(group):
            results = {}

            # initialize group + vars
            results[group.name] = {}

            # subgroups
            results[group.name]['children'] = {}
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                if subgroup.name != 'all':
                    results[group.name]['children'].update(
                        format_group(subgroup))

            # hosts for group
            results[group.name]['hosts'] = {}
            if group.name != 'all':
                for h in sorted(group.hosts, key=attrgetter('name')):
                    myvars = {}
                    if h.name not in seen:  # avoid defining host vars more than once
                        seen.append(h.name)
                        myvars = self._get_host_variables(host=h)
                        self._remove_internal(myvars)
                    results[group.name]['hosts'][h.name] = myvars

            if self.options.export:

                gvars = self._get_group_variables(group)
                if gvars:
                    results[group.name]['vars'] = gvars

            self._remove_empty(results[group.name])

            return results

        return format_group(top)
Esempio n. 14
0
class InventoryCLI(CLI):
    ''' used to display or dump the configured inventory as Ansible sees it '''

    ARGUMENTS = {
        'host':
        'The name of a host to match in the inventory, relevant when using --list',
        'group':
        'The name of a group in the inventory, relevant when using --graph',
    }

    def __init__(self, args):

        super(InventoryCLI, self).__init__(args)
        self.args = args
        self.vm = None
        self.loader = None
        self.inventory = None

        self._new_api = True

    def parse(self):

        self.parser = CLI.base_parser(
            usage='usage: %prog [options] [host|group]',
            epilog=
            'Show Ansible inventory information, by default it uses the inventory script JSON format',
            inventory_opts=True,
            vault_opts=True)
        self.parser.add_option(
            "--optimize",
            action="store_true",
            default=False,
            dest='optimize',
            help='Output variables on the group or host where they are defined'
        )

        # Actions
        action_group = optparse.OptionGroup(
            self.parser, "Actions",
            "One of following must be used on invocation, ONLY ONE!")
        action_group.add_option(
            "--list",
            action="store_true",
            default=False,
            dest='list',
            help='Output all hosts info, works as inventory script')
        action_group.add_option(
            "--host",
            action="store",
            default=None,
            dest='host',
            help='Output specific host info, works as inventory script')
        action_group.add_option(
            "--graph",
            action="store_true",
            default=False,
            dest='graph',
            help=
            'create inventory graph, if supplying pattern it must be a valid group name'
        )
        self.parser.add_option_group(action_group)

        # Options
        self.parser.add_option(
            "-y",
            "--yaml",
            action="store_true",
            default=False,
            dest='yaml',
            help='Use YAML format instead of default JSON, ignored for --graph'
        )
        self.parser.add_option(
            "--vars",
            action="store_true",
            default=False,
            dest='show_vars',
            help='Add vars to graph display, ignored unless used with --graph')

        try:
            super(InventoryCLI, self).parse()
        except Exception as e:
            if 'Need to implement!' not in e.args[0]:
                raise
            # --- Start of 2.3+ super(InventoryCLI, self).parse() ---
            self.options, self.args = self.parser.parse_args(self.args[1:])
            # --- End of 2.3+ super(InventoryCLI, self).parse() ---

        display.verbosity = self.options.verbosity

        self.validate_conflicts(vault_opts=True)

        # there can be only one! and, at least, one!
        used = 0
        for opt in (self.options.list, self.options.host, self.options.graph):
            if opt:
                used += 1
        if used == 0:
            raise AnsibleOptionsError(
                "No action selected, at least one of --host, --graph or --list needs to be specified."
            )
        elif used > 1:
            raise AnsibleOptionsError(
                "Conflicting options used, only one of --host, --graph or --list can be used at the same time."
            )

        # set host pattern to default if not supplied
        if len(self.args) > 0:
            self.options.pattern = self.args[0]
        else:
            self.options.pattern = 'all'

    def run(self):

        results = None

        super(InventoryCLI, self).run()

        # Initialize needed objects
        if getattr(self, '_play_prereqs', False):
            self.loader, self.inventory, self.vm = self._play_prereqs(
                self.options)
        else:
            # fallback to pre 2.4 way of initialzing
            from ansible.vars import VariableManager
            from ansible.inventory import Inventory

            self._new_api = False
            self.loader = DataLoader()
            self.vm = VariableManager()

            # use vault if needed
            if self.options.vault_password_file:
                vault_pass = CLI.read_vault_password_file(
                    self.options.vault_password_file, loader=self.loader)
            elif self.options.ask_vault_pass:
                vault_pass = self.ask_vault_passwords()
            else:
                vault_pass = None

            if vault_pass:
                self.loader.set_vault_password(vault_pass)
                # actually get inventory and vars

            self.inventory = Inventory(loader=self.loader,
                                       variable_manager=self.vm,
                                       host_list=self.options.inventory)
            self.vm.set_inventory(self.inventory)

        if self.options.host:
            hosts = self.inventory.get_hosts(self.options.host)
            if len(hosts) != 1:
                raise AnsibleOptionsError(
                    "You must pass a single valid host to --hosts parameter")

            myvars = self._get_host_variables(host=hosts[0])
            self._remove_internal(myvars)

            # FIXME: should we template first?
            results = self.dump(myvars)

        elif self.options.graph:
            results = self.inventory_graph()
        elif self.options.list:
            top = self._get_group('all')
            if self.options.yaml:
                results = self.yaml_inventory(top)
            else:
                results = self.json_inventory(top)
            results = self.dump(results)

        if results:
            # FIXME: pager?
            display.display(results)
            exit(0)

        exit(1)

    def dump(self, stuff):

        if self.options.yaml:
            import yaml
            from ansible.parsing.yaml.dumper import AnsibleDumper
            results = yaml.dump(stuff,
                                Dumper=AnsibleDumper,
                                default_flow_style=False)
        else:
            import json
            results = json.dumps(stuff, sort_keys=True, indent=4)

        return results

    def _get_host_variables(self, host):
        if self._new_api:
            hostvars = self.vm.get_vars(host=host)
        else:
            hostvars = self.vm.get_vars(self.loader, host=host)
        return hostvars

    def _get_group(self, gname):
        if self._new_api:
            group = self.inventory.groups.get(gname)
        else:
            group = self.inventory.get_group(gname)
        return group

    def _remove_internal(self, dump):

        for internal in INTERNAL_VARS:
            if internal in dump:
                del dump[internal]

    def _remove_empty(self, dump):
        # remove empty keys
        for x in ('hosts', 'vars', 'children'):
            if x in dump and not dump[x]:
                del dump[x]

    def _show_vars(self, dump, depth):
        result = []
        self._remove_internal(dump)
        if self.options.show_vars:
            for (name, val) in sorted(dump.items()):
                result.append(
                    self._graph_name('{%s = %s}' % (name, val), depth + 1))
        return result

    def _graph_name(self, name, depth=0):
        if depth:
            name = "  |" * (depth) + "--%s" % name
        return name

    def _graph_group(self, group, depth=0):

        result = [self._graph_name('@%s:' % group.name, depth)]
        depth = depth + 1
        for kid in sorted(group.child_groups, key=attrgetter('name')):
            result.extend(self._graph_group(kid, depth))

        if group.name != 'all':
            for host in sorted(group.hosts, key=attrgetter('name')):
                result.append(self._graph_name(host.name, depth))
                result.extend(self._show_vars(host.get_vars(), depth))

        result.extend(self._show_vars(group.get_vars(), depth))

        return result

    def inventory_graph(self):

        start_at = self._get_group(self.options.pattern)
        if start_at:
            return '\n'.join(self._graph_group(start_at))
        else:
            raise AnsibleOptionsError(
                "Pattern must be valid group name when using --graph")

    def json_inventory(self, top):
        def format_group(group):
            results = {}
            results[group.name] = {}
            if group.name != 'all':
                results[group.name]['hosts'] = [
                    h.name for h in sorted(group.hosts, key=attrgetter('name'))
                ]
            results[group.name]['vars'] = group.get_vars()
            results[group.name]['children'] = []
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                results[group.name]['children'].append(subgroup.name)
                results.update(format_group(subgroup))

            self._remove_empty(results[group.name])
            return results

        results = format_group(top)

        # populate meta
        results['_meta'] = {'hostvars': {}}
        hosts = self.inventory.get_hosts()
        for host in hosts:
            results['_meta']['hostvars'][host.name] = self._get_host_variables(
                host=host)
            self._remove_internal(results['_meta']['hostvars'][host.name])

        return results

    def yaml_inventory(self, top):

        seen = []

        def format_group(group):
            results = {}

            # initialize group + vars
            results[group.name] = {}
            results[group.name]['vars'] = group.get_vars()

            # subgroups
            results[group.name]['children'] = {}
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                if subgroup.name != 'all':
                    results[group.name]['children'].update(
                        format_group(subgroup))

            # hosts for group
            results[group.name]['hosts'] = {}
            if group.name != 'all':
                for h in sorted(group.hosts, key=attrgetter('name')):
                    myvars = {}
                    if h.name not in seen:  # avoid defining host vars more than once
                        seen.append(h.name)
                        myvars = self._get_host_variables(host=h)
                        self._remove_internal(myvars)
                    results[group.name]['hosts'][h.name] = myvars

            self._remove_empty(results[group.name])
            return results

        return format_group(top)
Esempio n. 15
0
class AnsibleInventoryManager():
    """Class to handle the ansible inventory file.
    This class will allow you to add groups/hosts and remove them from the inventory file"""
    #FROM http://www.ansibleworks.com/docs/patterns.html
    ALLOWED_VARIABLES = ['ansible_ssh_host',
                         'ansible_ssh_port',
                         'ansible_ssh_user',
                         'ansible_ssh_pass',
                         'ansible_connection',
                         'ansible_ssh_private_key_file',
                         'ansible_syslog_facility',
                         'ansible_python_interpreter',
                         ]
    # NOTE:Works for anything such as ruby or perl and works just like
    # ansible_python_interpreter.
    # This replaces shebang of modules which will run on that host.

    def __init__(self, inventory_file="/etc/ansible/hosts"):
        self.__inventory_file = inventory_file
        self.__dirty = False
        if not os.path.exists(self.__inventory_file):
            raise AnsibleInventoryManagerFileNotFound("File: %s Not found or not accessible" % self.__inventory_file)
        self.__inventory = Inventory(inventory_file)

    def get_hosts(self):
        """return the list of hosts
        Returns a list host ips"""
        host_list = [host.name for host in self.__inventory.get_hosts()]
        return host_list

    def get_groups(self):
        """return the groups
        Returns a list of objects: ansible.inventory.group.Group"""
        return self.__inventory.get_groups()

    def get_groups_for_host(self,host):
        """return the groups list where the given host appears"""
        return self.__inventory.groups_for_host(host)

    def get_group(self, groupname):
        """Returns the given group"""
        return self.__inventory.get_group(groupname)

    def delete_host(self,host_ip,group=""):
        """Removes a host from a given group
        if group is empty, removes the host from all the groups
        """
        self.__dirty = True
        groups = []
        if group == "":
            groups = [group.name for group in self.get_groups_for_host(host_ip)]
        else:
            groups.append(group)
        for group in groups:
            grp = self.__inventory.get_group(group)
            new_host_list = [host for host in grp.get_hosts() if host.name != host_ip]
            grp.hosts = new_host_list

    def add_host(self, host_ip, add_to_root=True, group_list=[], var_list={}):
        """Add a host ip to the ansible host file
        This is a simple function to add hosts to
        add_to_root = Adds the host to the root group (unnamed)
        groups_list: List of groupnames where the host should appears.
        var_list: Variable list. see allowed_variables."""
        #root group in unnamed, but in the inventory object
        # is the 'ungrouped' group
        self.__dirty = True
        new_host = Host(host_ip)
        for key,value in var_list.iteritems():
            if self.is_allowed_variable(key):
                new_host.set_variable(key,value)
        if add_to_root:
            if 'ungrouped' not in group_list:
                group_list.append('ungrouped')

        #Check groups. The ansible inventory should contain each of the groups.
        for group in group_list:
            if not self.__inventory.get_group(group):
                new_group= Group(group)
                self.__inventory.add_group(new_group)
            grp = self.__inventory.get_group(group)
            host_names = [host.name for host in grp.get_hosts()]
            if new_host.name not in host_names:
                grp.add_host(new_host)

    def is_dirty(self):
        return self.__dirty

    def is_allowed_variable(self, variable):
        """Checks if the given variable is an allowed variable"""
        if variable in self.ALLOWED_VARIABLES:
            return True
        elif re.match("ansible_(.+)_interpreter", variable):
            return True
        return False

    def save_inventory(self, backup_file=""):
        """Saves the inventory file. If a backup_file is given,
        a backup will be done before re-write the file"""

        try:
            if backup_file != "":
                copyfile(self.__inventory_file, backup_file)
            data = ""
            for group in self.__inventory.get_groups():
                ingroup = False
                if group.name == "all":
                    continue
                elif group.name != "ungrouped":
                    data += "[%s]\n" % group.name
                    ingroup = True
                strvars = ""
                for host in group.get_hosts():
                    for key, value in host.get_variables().iteritems():
                        if key in AnsibleInventoryManager.ALLOWED_VARIABLES:
                            strvars += "%s=%s    " % (key, value)
                    if ingroup:
                        data += "\t%s\t%s\n" % (host.name, strvars)
                    else:
                        data += "%s\t%s\n" % (host.name, strvars)
            ansiblehostfile = open(self.__inventory_file, "w")
            ansiblehostfile.write(data)
            ansiblehostfile.close()
        except Exception, e:
            error("Error doing the %s backup: %s" % (self.__inventory_file, str(e)))
Esempio n. 16
0
#!/usr/bin/env python
#  Ansible: initialize needed objects

from ansible.inventory import Inventory
from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager

variable_manager = VariableManager()
loader = DataLoader()

#  Ansible: Load inventory
inventory = Inventory(
    loader=loader,
    variable_manager=variable_manager,
    host_list='./ansible/inventory',  # Substitute your filename here
)

data = dict()
max = 0
for group in inventory.get_groups():
    for host in inventory.get_group(group).hosts:
        if not host.name in data:
            max =  max if max > len(host.name) else len(host.name)
            data[host.name]=host

print "%s   %s  %s" % ( 'host'.ljust(max) , 'private'.ljust(15),'private'.ljust(15) )
print '-' * 80
for host in data:
    print "%s   %s  %s" % ( data[host].name.ljust(max) , data[host].vars['ansible_ssh_host'].ljust(15),data[host].vars['private_ip'].ljust(15))

    def run(self):

        sshpass = None
        becomepass = None
        b_vault_pass = None
        passwords = {}

        # initial error check, to make sure all specified playbooks are accessible
        # before we start running anything through the playbook executor
        for playbook in self.args:
            if not os.path.exists(playbook):
                raise AnsibleError("the playbook: %s could not be found" %
                                   playbook)
            if not (os.path.isfile(playbook)
                    or stat.S_ISFIFO(os.stat(playbook).st_mode)):
                raise AnsibleError(
                    "the playbook: %s does not appear to be a file" % playbook)

        # don't deal with privilege escalation or passwords when we don't need to
        if not self.options.listhosts and not self.options.listtasks and not self.options.listtags and not self.options.syntax:
            self.normalize_become_options()
            (sshpass, becomepass) = self.ask_passwords()
            passwords = {'conn_pass': sshpass, 'become_pass': becomepass}

        loader = DataLoader()

        if self.options.vault_password_file:
            # read vault_pass from a file
            b_vault_pass = CLI.read_vault_password_file(
                self.options.vault_password_file, loader=loader)
            loader.set_vault_password(b_vault_pass)
        elif self.options.ask_vault_pass:
            b_vault_pass = self.ask_vault_passwords()
            loader.set_vault_password(b_vault_pass)

        # create the variable manager, which will be shared throughout
        # the code, ensuring a consistent view of global variables
        variable_manager = VariableManager()
        variable_manager.extra_vars = load_extra_vars(loader=loader,
                                                      options=self.options)

        #        extra_vars = {'elastic_url':Configuration.elastic_url,
        #                      'uuid':self._job.uuid }

        variable_manager.options_vars = load_options_vars(self.options)

        # create the inventory, and filter it based on the subset specified (if any)
        inventory = Inventory(loader=loader,
                              variable_manager=variable_manager,
                              host_list=self.options.inventory)

        # added by [email protected]
        inventory.host_list = []
        inventory.host_list = self.options.inventory
        for group in self.inventoryContainer.groups:
            if group.name == 'all':
                if group.vars:
                    inventory.get_group('all').vars.update(group.vars)
            else:
                group.parent_groups.append(inventory.get_group('all'))
                inventory.get_group('all').child_groups.append(group)
                #                inventory.get_group('all').hosts.extend(group.hosts)
                #                inventory.get_group('all').vars.update(group.vars)

                inventory.add_group(group)

        variable_manager.set_inventory(inventory)

        # (which is not returned in list_hosts()) is taken into account for
        # warning if inventory is empty.  But it can't be taken into account for
        # checking if limit doesn't match any hosts.  Instead we don't worry about
        # limit if only implicit localhost was in inventory to start with.
        #
        # Fix this when we rewrite inventory by making localhost a real host (and thus show up in list_hosts())
        no_hosts = False
        #        if len(inventory.list_hosts()) == 0:
        # Empty inventory
        #            display.warning("provided hosts list is empty, only localhost is available")
        #            no_hosts = True
        inventory.subset(self.options.subset)
        #        if len(inventory.list_hosts()) == 0 and no_hosts is False:
        # Invalid limit
        #            raise AnsibleError("Specified --limit does not match any hosts")

        # flush fact cache if requested
        if self.options.flush_cache:
            self._flush_cache(inventory, variable_manager)

        # create the playbook executor, which manages running the plays via a task queue manager
        self.pbex = PlaybookExecutor(playbooks=[playbook],
                                     inventory=inventory,
                                     variable_manager=variable_manager,
                                     loader=loader,
                                     options=self.options,
                                     passwords=passwords)

        results = self.pbex.run()
        self.apijob.stats = self.pbex._tqm._stats
        self.apijob.finished()

        if isinstance(results, list):
            for p in self.results:

                display.display('\nplaybook: %s' % p['playbook'])
                for idx, play in enumerate(p['plays']):
                    if play._included_path is not None:
                        loader.set_basedir(play._included_path)
                    else:
                        pb_dir = os.path.realpath(
                            os.path.dirname(p['playbook']))
                        loader.set_basedir(pb_dir)

                    msg = "\n  play #%d (%s): %s" % (idx + 1, ','.join(
                        play.hosts), play.name)
                    mytags = set(play.tags)
                    msg += '\tTAGS: [%s]' % (','.join(mytags))

                    if self.options.listhosts:
                        playhosts = set(inventory.get_hosts(play.hosts))
                        msg += "\n    pattern: %s\n    hosts (%d):" % (
                            play.hosts, len(playhosts))
                        for host in playhosts:
                            msg += "\n      %s" % host

                    display.display(msg)

                    all_tags = set()
                    if self.options.listtags or self.options.listtasks:
                        taskmsg = ''
                        if self.options.listtasks:
                            taskmsg = '    tasks:\n'

                        def _process_block(b):
                            taskmsg = ''
                            for task in b.block:
                                if isinstance(task, Block):
                                    taskmsg += _process_block(task)
                                else:
                                    if task.action == 'meta':
                                        continue

                                    all_tags.update(task.tags)
                                    if self.options.listtasks:
                                        cur_tags = list(
                                            mytags.union(set(task.tags)))
                                        cur_tags.sort()
                                        if task.name:
                                            taskmsg += "      %s" % task.get_name(
                                            )
                                        else:
                                            taskmsg += "      %s" % task.action
                                        taskmsg += "\tTAGS: [%s]\n" % ', '.join(
                                            cur_tags)

                            return taskmsg

                        all_vars = variable_manager.get_vars(loader=loader,
                                                             play=play)
                        play_context = PlayContext(play=play,
                                                   options=self.options)
                        for block in play.compile():
                            block = block.filter_tagged_tasks(
                                play_context, all_vars)
                            if not block.has_tasks():
                                continue
                            taskmsg += _process_block(block)

                        if self.options.listtags:
                            cur_tags = list(mytags.union(all_tags))
                            cur_tags.sort()
                            taskmsg += "      TASK TAGS: [%s]\n" % ', '.join(
                                cur_tags)

                        display.display(taskmsg)

            return 0
        else:
            return results
def listfunction(llist):
    """This function does all the work and lists groups or hosts"""
    llist = llist
    variable_manager = VariableManager()
    loader = DataLoader()
    if not os.path.isfile(inventory_file):
        print "%s is not a file - halting. Consider using the '--inventory $path/to/ansible_inventory file' parameter" % inventory_file
        sys.exit(1)
    else:
        inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=inventory_file)

    groups = inventory.groups
    for group in groups:
        dogroup = inventory.get_group(group)
        if dogroup.child_groups:
            list_of_hosts = dogroup.child_groups
            # we need to quote the items in the list because JSON
            list_of_hosts2 = ','.join("'{0}'".format(x) for x in list_of_hosts)
            list_of_hosts3 = list_of_hosts2.replace('["', '[')
            list_of_hosts4 = list_of_hosts3.replace('"]', ']')
            # the three lists
            dict_groups2[group] = list_of_hosts # used with --single
            dict_groups[group] = [list_of_hosts4] # used with --list and --group
            dict_hosts[group] = inventory.list_hosts(group) # used with --single

## Nested child groups
# To make this work with optionally nested groups (example up top) we need to after the group is populated, look in dict_groups if there are any double-nested groups.
    if chosen_group and single:
        for group in dict_groups2[chosen_group]:
            try:
                dict_groups2[str(group)]
                child_child_groups.append(str(group))
            except KeyError:
                # this group does not have a child group!
                continue


      # here we loop through child_child groups and list the hosts of those groups and then add the last in each group to the dict_single_hosts
    if child_child_groups != []:
        for child in child_child_groups:
            for child_child in dict_groups2[child]:
                child_host = inventory.get_hosts(str(child_child))[-1]
                dict_single_hosts[child_child] = [child_host]

##   End of this child of mine

#   make a dict that only has one host per child group
    if chosen_group:
        for host in dict_hosts[chosen_group]:
            groups_for_host = inventory.groups_for_host(str(host))
#           if debug: print "groups_for_host: %s" % groups_for_host

            for group in groups_for_host:
                if group in dict_groups2[chosen_group]:
                #this host is in one of the child groups of the chosen_group
                    if len(dict_single_hosts[chosen_group]) == 0:
                        dict_single_hosts[group] = [host]

#   here we populate dict_single_hosts so that the chosen_group key only has a list of hosts that are in separate child groups
    for group in dict_single_hosts:
        if chosen_group == group:
            continue
        if len(dict_single_hosts[chosen_group]) < (len(dict_single_hosts) - 1):
            # -1 because the chosen_group is also in the same dict
            for host in dict_single_hosts[group]:
              # and we first check if it's already in there, that might have been added by the child_child hosts
                if host not in dict_single_hosts[chosen_group]:
                    dict_single_hosts[chosen_group].append(host)

#   here we quote the entries in dict_of_single_hosts (because JSON)
    if single:
        list_of_single_hosts = dict_single_hosts[chosen_group]
        list_of_single_hosts2 = ','.join("'{0}'".format(x) for x in list_of_single_hosts)
        dict_single_hosts[chosen_group] = []
        dict_single_hosts[chosen_group] = [list_of_single_hosts2]
##  ########

#   Some arguments checking - this could probably be done with argparse settings
    if chosen_group:
        if single:
            return dict_single_hosts[chosen_group]
        else:
            return dict_groups[chosen_group]
    else:
        return dict_groups
Esempio n. 19
0
class ResourceBase(object):
    """
    generate inventory

    :param resource: inventory resource, format:
        {
            "hosts" : {
                "host1": {"port": "22", "username": "******", "password": "******"},
                "host2": {"port": "22", "username": "******", "password": "******"},
            },
            "groups": {
                "group1": {"hosts": ["host1", "host2",...], "vars": {'var1':'xxxx', 'var2':'yyy',...} },
                "group2": {"hosts": ["host1", "host2",...], "child": ["group1"], "vars": {'var1':'xxxx', 'var2':'yyy',...} },
            }
        }
    """
    def __init__(self, resource=None):
        host_list = not resource and ANS_CONS.DEFAULT_HOST_LIST or []
        self.loader = DataLoader()
        self.variable_manager = VariableManager()
        self.resource = resource
        self.inventory = Inventory(loader=self.loader,
                                   variable_manager=self.variable_manager,
                                   host_list=host_list)
        #resource and self.gen_inventory()
        self.gen_inventory()

    @staticmethod
    def gen_host(host_name=None, host_vars=None):
        """
        Generate ansible Host object
        :param host_name: <string> ansible inventory hostname
        :param host_vars: <dict> host variables
        :return: Host object
        """
        if host_vars is None:
            host_vars = {}
        ssh_host = host_vars.get('ip', host_name)
        ssh_port = host_vars.get('port', ANS_CONS.DEFAULT_REMOTE_PORT)
        ssh_user = host_vars.get('username')
        ssh_pass = host_vars.get('password')
        ssh_fkey = host_vars.get('ssh_key')
        # init Host
        host = Host(name=host_name, port=ssh_port)
        host.set_variable('ansible_ssh_host', ssh_host)
        # shortcut variables
        ssh_user and host.set_variable('ansible_ssh_user', ssh_user)
        ssh_pass and host.set_variable('ansible_ssh_pass', ssh_pass)
        ssh_fkey and host.set_variable('ansible_private_key_file', ssh_fkey)
        # extra variables
        for key, value in host_vars.items():
            if key not in ['ip', 'port', 'username', 'password', 'ssh_key']:
                host.set_variable(key, value)
        # return Host object
        return host

    @staticmethod
    def gen_group(group_name=None, group_vars=None):
        """
        Generate ansible Group object
        :param group_name: <string> Group Name
        :param group_vars: <dict> Group Variables
        :return: ansible Group object
        """
        if group_vars is None:
            group_vars = {}
        group = Group(name=group_name)
        for key, value in group_vars.items():
            group.set_variable(key, value)
        return group

    def gen_inventory(self):
        """
        :return: None
        """
        # set hosts
        if 'hosts' in self.resource.keys():
            for host, info in self.resource['hosts'].items():
                obj_host = self.gen_host(host, info)
                self.inventory.get_group('all').add_host(obj_host)
        # add group
        if 'groups' in self.resource.keys():
            for group, detail in self.resource['groups'].items():
                obj_group = self.gen_group(group, detail.get('vars', {}))
                for host in detail.get('hosts', []):
                    obj_group.add_host(self.inventory.get_host(host))
                if 'child' in detail.get('child', []):
                    for child in detail.get('child', []):
                        obj_group.add_child_group(
                            self.inventory.get_group(child))
                self.inventory.add_group(obj_group)

    def get_lists(self):
        print("Host: ")
        print("=================")
        for host in self.inventory.list_hosts():
            print(host)
        print("Group: ")
        print("=================")
        for group in self.inventory.list_groups():
            print(group)
Esempio n. 20
0
class Inventory:
    def __init__(self, source):

        self._source = source

        self._loader = DataLoader()

        self._variables = VariableManager()

        self._inventory = AnsibleInventory(loader=self._loader,
                                           variable_manager=self._variables,
                                           host_list=self._source)

        self._groups = dict()

        self._hosts = dict()

    def __getitem__(self, name):

        return self.get(name)

    def get(self, name):

        result = None

        host = self.get_host(name)

        if host != None:

            result = host

        else:

            group = self.get_group(name)

            if group != None:

                result = group

            else:

                group_all = self._inventory.get_group('all')

                if group_all != None:

                    var = group_all.get_vars()[name]

                    if var != None:

                        result = var

        return result

    def get_group(self, group_name):

        result = None

        if self._groups.has_key(group_name):

            result = self._groups[group_name]

        elif self._inventory.get_group(group_name) != None:

            result = Group(group_name, self)

            self._groups[group_name] = result

        return result

    def get_group_vars(self, group_name):

        result = None

        group = self._inventory.get_group(group_name)

        if group != None:

            result = group.get_vars()

        return result

    def get_host(self, host_name):

        result = None

        if self._hosts.has_key(host_name):

            result = self._hosts[host_name]

        elif self._inventory.get_host(host_name) != None:

            result = Host(host_name, self)

            self._hosts[host_name] = result

        return result

    def get_host_vars(self, host_name):

        result = None

        host = self._inventory.get_host(host_name)

        if host != None:

            result = self._variables.get_vars(self._loader, host=host)

        return result