Ejemplo n.º 1
0
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]
Ejemplo n.º 2
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)))
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