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
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
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
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])
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
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()
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"
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"
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()
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)
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)
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)
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)))
#!/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
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)
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