def loadAnsibleInventory(): arr = {} loader = DataLoader() variable_manager = VariableManager() try: # Loading Ansible inventory inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=settings.ANSIBLE_HOSTS_FILE) for group in inventory.list_groups(): arr[str(group)] = [] for host in inventory.list_hosts(): for group in inventory.groups_for_host(str(host)): arr[str(group)].append(str(host)) # Removing unneeded groups arr.pop('all', None) arr.pop('ungrouped', None) except: pass res = {} #Removing empty groups for key in arr: if len(arr[key]) <> 0: res[key] = arr[key] #Sorting items by length keys = sorted(res, key=lambda k: len(res[k]), reverse=True) return [res, keys]
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)))
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