def __init__(self, host_list=C.DEFAULT_HOST_LIST): # the host file file, or script path, or list of hosts # if a list, inventory data will NOT be loaded self.host_list = host_list # caching to avoid repeated calculations, particularly with # external inventory scripts. self._vars_per_host = {} self._vars_per_group = {} self._hosts_cache = {} self._groups_list = {} # to be set by calling set_playbook_basedir by ansible-playbook self._playbook_basedir = None # the inventory object holds a list of groups self.groups = [] # a list of host(names) to contain current inquiries to self._restriction = None self._also_restriction = None self._subset = None if isinstance(host_list, basestring): if "," in host_list: host_list = host_list.split(",") host_list = [h for h in host_list if h and h.strip()] if isinstance(host_list, list): self.parser = None all = Group('all') self.groups = [all] for x in host_list: if ":" in x: tokens = x.split(":", 1) all.add_host(Host(tokens[0], tokens[1])) else: all.add_host(Host(x)) elif os.path.exists(host_list): if os.path.isdir(host_list): # Ensure basedir is inside the directory self.host_list = os.path.join(self.host_list, "") self.parser = InventoryDirectory(filename=host_list) self.groups = self.parser.groups.values() elif utils.is_executable(host_list): self.parser = InventoryScript(filename=host_list) self.groups = self.parser.groups.values() else: self.parser = InventoryParser(filename=host_list) self.groups = self.parser.groups.values() utils.plugins.vars_loader.add_directory(self.basedir(), with_subdir=True) else: raise errors.AnsibleError( "Unable to find an inventory file, specify one with -i ?") self._vars_plugins = [x for x in utils.plugins.vars_loader.all(self)]
def __init__(self, runner, host, port, *args, **kwargs): self.chroot = host self.has_pipelining = False if os.geteuid() != 0: raise errors.AnsibleError( "chroot connection requires running as root") # we're running as root on the local system so do some # trivial checks for ensuring 'host' is actually a chroot'able dir if not os.path.isdir(self.chroot): raise errors.AnsibleError("%s is not a directory" % self.chroot) chrootsh = os.path.join(self.chroot, 'bin/sh') if not utils.is_executable(chrootsh): raise errors.AnsibleError( "%s does not look like a chrootable dir (/bin/sh missing)" % self.chroot) self.chroot_cmd = distutils.spawn.find_executable('chroot') if not self.chroot_cmd: raise errors.AnsibleError("chroot command not found in PATH") self.runner = runner self.host = host # port is unused, since this is local self.port = port
def __init__(self, runner, host, port, *args, **kwargs): self.chroot = host self.has_pipelining = False self.become_methods_supported=C.BECOME_METHODS if os.geteuid() != 0: raise errors.AnsibleError("chroot connection requires running as root") # we're running as root on the local system so do some # trivial checks for ensuring 'host' is actually a chroot'able dir if not os.path.isdir(self.chroot): raise errors.AnsibleError("%s is not a directory" % self.chroot) chrootsh = os.path.join(self.chroot, 'bin/sh') if not utils.is_executable(chrootsh): raise errors.AnsibleError("%s does not look like a chrootable dir (/bin/sh missing)" % self.chroot) self.chroot_cmd = distutils.spawn.find_executable('chroot') if not self.chroot_cmd: raise errors.AnsibleError("chroot command not found in PATH") self.runner = runner self.host = host # port is unused, since this is local self.port = port
def __init__(self, host_list=C.DEFAULT_HOST_LIST): # the host file file, or script path, or list of hosts # if a list, inventory data will NOT be loaded self.host_list = host_list # caching to avoid repeated calculations, particularly with # external inventory scripts. self._vars_per_host = {} self._vars_per_group = {} self._hosts_cache = {} self._groups_list = {} # the inventory object holds a list of groups self.groups = [] # a list of host(names) to contain current inquiries to self._restriction = None self._also_restriction = None self._subset = None if type(host_list) in [ str, unicode ]: if host_list.find(",") != -1: host_list = host_list.split(",") host_list = [ h for h in host_list if h and h.strip() ] if type(host_list) == list: self.parser = None all = Group('all') self.groups = [ all ] for x in host_list: if x.find(":") != -1: tokens = x.split(":",1) all.add_host(Host(tokens[0], tokens[1])) else: all.add_host(Host(x)) elif os.path.exists(host_list): if os.path.isdir(host_list): # Ensure basedir is inside the directory self.host_list = os.path.join(self.host_list, "") self.parser = InventoryDirectory(filename=host_list) self.groups = self.parser.groups.values() elif utils.is_executable(host_list): self.parser = InventoryScript(filename=host_list) self.groups = self.parser.groups.values() else: data = file(host_list).read() if not data.startswith("---"): self.parser = InventoryParser(filename=host_list) self.groups = self.parser.groups.values() else: raise errors.AnsibleError("YAML inventory support is deprecated in 0.6 and removed in 0.7, see the migration script in examples/scripts in the git checkout") utils.plugins.vars_loader.add_directory(self.basedir(), with_subdir=True) else: raise errors.AnsibleError("Unable to find an inventory file, specify one with -i ?") self._vars_plugins = [ x for x in utils.plugins.vars_loader.all(self) ]
def __init__(self, filename=C.DEFAULT_HOST_LIST): self.names = os.listdir(filename) self.names.sort() self.directory = filename self.parsers = [] self.hosts = {} self.groups = {} for i in self.names: if i.endswith("~") or i.endswith(".orig") or i.endswith(".bak"): continue if i.endswith(".ini"): # configuration file for an inventory script continue if i.endswith(".retry"): # this file is generated on a failed playbook and should only be # used when run specifically continue # Skip hidden files if i.startswith('.') and not i.startswith('./'): continue # These are things inside of an inventory basedir if i in ("host_vars", "group_vars", "vars_plugins"): continue fullpath = os.path.join(self.directory, i) if os.path.isdir(fullpath): parser = InventoryDirectory(filename=fullpath) elif utils.is_executable(fullpath): parser = InventoryScript(filename=fullpath) else: parser = InventoryParser(filename=fullpath) self.parsers.append(parser) # This takes a lot of code because we can't directly use any of the objects, as they have to blend for name, group in parser.groups.iteritems(): if name not in self.groups: self.groups[name] = group else: # group is already there, copy variables # note: depth numbers on duplicates may be bogus for k, v in group.get_variables().iteritems(): self.groups[name].set_variable(k, v) for host in group.get_hosts(): if host.name not in self.hosts: self.hosts[host.name] = host else: # host is already there, copy variables # note: depth numbers on duplicates may be bogus for k, v in host.vars.iteritems(): self.hosts[host.name].set_variable(k, v) self.groups[name].add_host(self.hosts[host.name]) # This needs to be a second loop to ensure all the parent groups exist for name, group in parser.groups.iteritems(): for ancestor in group.get_ancestors(): self.groups[ancestor.name].add_child_group( self.groups[name])
def __init__(self, filename=C.DEFAULT_HOST_LIST): self.names = os.listdir(filename) self.names.sort() self.directory = filename self.parsers = [] self.hosts = {} self.groups = {} for i in self.names: if i.endswith("~") or i.endswith(".orig") or i.endswith(".bak"): continue if i.endswith(".ini"): # configuration file for an inventory script continue if i.endswith(".retry"): # this file is generated on a failed playbook and should only be # used when run specifically continue # Skip hidden files if i.startswith('.') and not i.startswith('./'): continue # These are things inside of an inventory basedir if i in ("host_vars", "group_vars", "vars_plugins"): continue fullpath = os.path.join(self.directory, i) if os.path.isdir(fullpath): parser = InventoryDirectory(filename=fullpath) elif utils.is_executable(fullpath): parser = InventoryScript(filename=fullpath) else: parser = InventoryParser(filename=fullpath) self.parsers.append(parser) # This takes a lot of code because we can't directly use any of the objects, as they have to blend for name, group in parser.groups.iteritems(): if name not in self.groups: self.groups[name] = group else: # group is already there, copy variables # note: depth numbers on duplicates may be bogus for k, v in group.get_variables().iteritems(): self.groups[name].set_variable(k, v) for host in group.get_hosts(): if host.name not in self.hosts: self.hosts[host.name] = host else: # host is already there, copy variables # note: depth numbers on duplicates may be bogus for k, v in host.vars.iteritems(): self.hosts[host.name].set_variable(k, v) self.groups[name].add_host(self.hosts[host.name]) # This needs to be a second loop to ensure all the parent groups exist for name, group in parser.groups.iteritems(): for ancestor in group.get_ancestors(): self.groups[ancestor.name].add_child_group(self.groups[name])
def __init__(self, host_list=C.DEFAULT_HOST_LIST): # the host file file, or script path, or list of hosts # if a list, inventory data will NOT be loaded self.host_list = host_list # caching to avoid repeated calculations, particularly with # external inventory scripts. self._vars_per_host = {} self._vars_per_group = {} self._hosts_cache = {} self._groups_list = {} # the inventory object holds a list of groups self.groups = [] # a list of host(names) to contain current inquiries to self._restriction = None self._also_restriction = None self._subset = None # whether the inventory file is a script self._is_script = False if type(host_list) in [ str, unicode ]: if host_list.find(",") != -1: host_list = host_list.split(",") host_list = [ h for h in host_list if h and h.strip() ] else: utils.plugins.vars_loader.add_directory(self.basedir()) if type(host_list) == list: all = Group('all') self.groups = [ all ] for x in host_list: if x.find(":") != -1: tokens = x.split(":",1) all.add_host(Host(tokens[0], tokens[1])) else: all.add_host(Host(x)) elif utils.is_executable(host_list): self._is_script = True self.parser = InventoryScript(filename=host_list) self.groups = self.parser.groups.values() else: data = file(host_list).read() if not data.startswith("---"): self.parser = InventoryParser(filename=host_list) self.groups = self.parser.groups.values() else: raise errors.AnsibleError("YAML inventory support is deprecated in 0.6 and removed in 0.7, see the migration script in examples/scripts in the git checkout")
def __init__(self, *args, **kwargs): super(Connection, self).__init__(*args, **kwargs) self.chroot = self._play_context.remote_addr if os.geteuid() != 0: raise AnsibleError("chroot connection requires running as root") # we're running as root on the local system so do some # trivial checks for ensuring 'host' is actually a chroot'able dir if not os.path.isdir(self.chroot): raise AnsibleError("%s is not a directory" % self.chroot) chrootsh = os.path.join(self.chroot, 'bin/sh') if not utils.is_executable(chrootsh): raise AnsibleError( "%s does not look like a chrootable dir (/bin/sh missing)" % self.chroot) self.chroot_cmd = distutils.spawn.find_executable('chroot') if not self.chroot_cmd: raise AnsibleError("chroot command not found in PATH")
def __init__(self, filename=C.DEFAULT_HOST_LIST): self.names = os.listdir(filename) self.names.sort() self.directory = filename self.parsers = [] self.hosts = {} self.groups = {} for i in self.names: if i.endswith("~") or i.endswith(".orig") or i.endswith(".bak"): continue # These are things inside of an inventory basedir if i in ("host_vars", "group_vars", "vars_plugins"): continue fullpath = os.path.join(self.directory, i) if os.path.isdir(fullpath): parser = InventoryDirectory(filename=fullpath) elif utils.is_executable(fullpath): parser = InventoryScript(filename=fullpath) else: parser = InventoryParser(filename=fullpath) self.parsers.append(parser) # This takes a lot of code because we can't directly use any of the objects, as they have to blend for name, group in parser.groups.iteritems(): if name not in self.groups: self.groups[name] = Group(name) for k, v in group.get_variables().iteritems(): self.groups[name].set_variable(k, v) for host in group.get_hosts(): if host.name not in self.hosts: self.hosts[host.name] = Host(host.name) for k, v in host.vars.iteritems(): self.hosts[host.name].set_variable(k, v) self.groups[name].add_host(self.hosts[host.name]) # This needs to be a second loop to ensure all the parent groups exist for name, group in parser.groups.iteritems(): for ancestor in group.get_ancestors(): self.groups[ancestor.name].add_child_group(self.groups[name])
def __init__(self, host_list=C.DEFAULT_HOST_LIST, vault_password=None): # the host file file, or script path, or list of hosts # if a list, inventory data will NOT be loaded self.host_list = host_list self._vault_password = vault_password # caching to avoid repeated calculations, particularly with # external inventory scripts. self._vars_per_host = {} self._vars_per_group = {} self._hosts_cache = {} self._groups_list = {} self._pattern_cache = {} # to be set by calling set_playbook_basedir by playbook code self._playbook_basedir = None # the inventory object holds a list of groups self.groups = [] # a list of host(names) to contain current inquiries to self._restriction = None self._also_restriction = None self._subset = None if isinstance(host_list, basestring): if "," in host_list: host_list = host_list.split(",") host_list = [h for h in host_list if h and h.strip()] if host_list is None: self.parser = None elif isinstance(host_list, list): self.parser = None all = Group('all') self.groups = [all] ipv6_re = re.compile('\[([a-f:A-F0-9]*[%[0-z]+]?)\](?::(\d+))?') for x in host_list: m = ipv6_re.match(x) if m: all.add_host(Host(m.groups()[0], m.groups()[1])) else: if ":" in x: tokens = x.rsplit(":", 1) # if there is ':' in the address, then this is a ipv6 if ':' in tokens[0]: all.add_host(Host(x)) else: all.add_host(Host(tokens[0], tokens[1])) else: all.add_host(Host(x)) elif os.path.exists(host_list): if os.path.isdir(host_list): # Ensure basedir is inside the directory self.host_list = os.path.join(self.host_list, "") self.parser = InventoryDirectory(filename=host_list) self.groups = self.parser.groups.values() else: # check to see if the specified file starts with a # shebang (#!/), so if an error is raised by the parser # class we can show a more apropos error shebang_present = False try: inv_file = open(host_list) first_line = inv_file.readlines()[0] inv_file.close() if first_line.startswith('#!'): shebang_present = True except: pass if utils.is_executable(host_list): try: self.parser = InventoryScript(filename=host_list) self.groups = self.parser.groups.values() except: if not shebang_present: raise errors.AnsibleError("The file %s is marked as executable, but failed to execute correctly. " % host_list + \ "If this is not supposed to be an executable script, correct this with `chmod -x %s`." % host_list) else: raise else: try: self.parser = InventoryParser(filename=host_list) self.groups = self.parser.groups.values() except: if shebang_present: raise errors.AnsibleError("The file %s looks like it should be an executable inventory script, but is not marked executable. " % host_list + \ "Perhaps you want to correct this with `chmod +x %s`?" % host_list) else: raise utils.plugins.vars_loader.add_directory(self.basedir(), with_subdir=True) else: raise errors.AnsibleError( "Unable to find an inventory file, specify one with -i ?") self._vars_plugins = [x for x in utils.plugins.vars_loader.all(self)] # get group vars from group_vars/ files and vars plugins for group in self.groups: group.vars = utils.combine_vars( group.vars, self.get_group_variables(group.name, vault_password=self._vault_password)) # get host vars from host_vars/ files and vars plugins for host in self.get_hosts(): host.vars = utils.combine_vars( host.vars, self.get_variables(host.name, vault_password=self._vault_password))
def __init__(self, host_list=C.DEFAULT_HOST_LIST): # the host file file, or script path, or list of hosts # if a list, inventory data will NOT be loaded self.host_list = host_list # caching to avoid repeated calculations, particularly with # external inventory scripts. self._vars_per_host = {} self._vars_per_group = {} self._hosts_cache = {} self._groups_list = {} self._pattern_cache = {} # to be set by calling set_playbook_basedir by ansible-playbook self._playbook_basedir = None # the inventory object holds a list of groups self.groups = [] # a list of host(names) to contain current inquiries to self._restriction = None self._also_restriction = None self._subset = None if isinstance(host_list, basestring): if "," in host_list: host_list = host_list.split(",") host_list = [ h for h in host_list if h and h.strip() ] if host_list is None: self.parser = None elif isinstance(host_list, list): self.parser = None all = Group('all') self.groups = [ all ] ipv6_re = re.compile('\[([a-f:A-F0-9]*[%[0-z]+]?)\](?::(\d+))?') for x in host_list: m = ipv6_re.match(x) if m: all.add_host(Host(m.groups()[0], m.groups()[1])) else: if ":" in x: tokens = x.rsplit(":", 1) # if there is ':' in the address, then this is a ipv6 if ':' in tokens[0]: all.add_host(Host(x)) else: all.add_host(Host(tokens[0], tokens[1])) else: all.add_host(Host(x)) elif os.path.exists(host_list): if os.path.isdir(host_list): # Ensure basedir is inside the directory self.host_list = os.path.join(self.host_list, "") self.parser = InventoryDirectory(filename=host_list) self.groups = self.parser.groups.values() elif utils.is_executable(host_list): self.parser = InventoryScript(filename=host_list) self.groups = self.parser.groups.values() else: self.parser = InventoryParser(filename=host_list) self.groups = self.parser.groups.values() utils.plugins.vars_loader.add_directory(self.basedir(), with_subdir=True) else: raise errors.AnsibleError("Unable to find an inventory file, specify one with -i ?") self._vars_plugins = [ x for x in utils.plugins.vars_loader.all(self) ]
def __init__(self, filename=C.DEFAULT_HOST_LIST): self.names = os.listdir(filename) self.names.sort() self.directory = filename self.parsers = [] self.hosts = {} self.groups = {} for i in self.names: if i.endswith("~") or i.endswith(".orig") or i.endswith(".bak"): continue if i.endswith(".ini"): # configuration file for an inventory script continue if i.endswith(".retry"): # this file is generated on a failed playbook and should only be # used when run specifically continue # Skip hidden files if i.startswith('.') and not i.startswith('./'): continue # These are things inside of an inventory basedir if i in ("host_vars", "group_vars", "vars_plugins"): continue fullpath = os.path.join(self.directory, i) if os.path.isdir(fullpath): parser = InventoryDirectory(filename=fullpath) elif utils.is_executable(fullpath): parser = InventoryScript(filename=fullpath) else: parser = InventoryParser(filename=fullpath) self.parsers.append(parser) # retrieve all groups and hosts form the parser and add them to # self, don't look at group lists yet, to avoid # recursion trouble, but just make sure all objects exist in self newgroups = parser.groups.values() for group in newgroups: for host in group.hosts: self._add_host(host) for group in newgroups: self._add_group(group) # now check the objects lists so they contain only objects from # self; membership data in groups is already fine (except all & # ungrouped, see later), but might still reference objects not in self for group in self.groups.values(): # iterate on a copy of the lists, as those lists get changed in # the loop # list with group's child group objects: for child in group.child_groups[:]: if child != self.groups[child.name]: group.child_groups.remove(child) group.child_groups.append(self.groups[child.name]) # list with group's parent group objects: for parent in group.parent_groups[:]: if parent != self.groups[parent.name]: group.parent_groups.remove(parent) group.parent_groups.append(self.groups[parent.name]) # list with group's host objects: for host in group.hosts[:]: if host != self.hosts[host.name]: group.hosts.remove(host) group.hosts.append(self.hosts[host.name]) # also check here that the group that contains host, is # also contained in the host's group list if group not in self.hosts[host.name].groups: self.hosts[host.name].groups.append(group) # extra checks on special groups all and ungrouped # remove hosts from 'ungrouped' if they became member of other groups if 'ungrouped' in self.groups: ungrouped = self.groups['ungrouped'] # loop on a copy of ungrouped hosts, as we want to change that list for host in ungrouped.hosts[:]: if len(host.groups) > 1: host.groups.remove(ungrouped) ungrouped.hosts.remove(host) # remove hosts from 'all' if they became member of other groups # all should only contain direct children, not grandchildren # direct children should have dept == 1 if 'all' in self.groups: allgroup = self.groups['all'] # loop on a copy of all's child groups, as we want to change that list for group in allgroup.child_groups[:]: # groups might once have beeen added to all, and later be added # to another group: we need to remove the link wit all then if len(group.parent_groups) > 1: # real children of all have just 1 parent, all # this one has more, so not a direct child of all anymore group.parent_groups.remove(allgroup) allgroup.child_groups.remove(group) elif allgroup not in group.parent_groups: # this group was once added to all, but doesn't list it as # a parent any more; the info in the group is the correct # info allgroup.child_groups.remove(group)
def __init__(self, host_list=C.DEFAULT_HOST_LIST, vault_password=None): # the host file file, or script path, or list of hosts # if a list, inventory data will NOT be loaded self.host_list = host_list self._vault_password=vault_password # caching to avoid repeated calculations, particularly with # external inventory scripts. self._vars_per_host = {} self._vars_per_group = {} self._hosts_cache = {} self._groups_list = {} self._pattern_cache = {} # to be set by calling set_playbook_basedir by playbook code self._playbook_basedir = None # the inventory object holds a list of groups self.groups = [] # a list of host(names) to contain current inquiries to self._restriction = None self._also_restriction = None self._subset = None if isinstance(host_list, basestring): if "," in host_list: host_list = host_list.split(",") host_list = [ h for h in host_list if h and h.strip() ] if host_list is None: self.parser = None elif isinstance(host_list, list): self.parser = None all = Group('all') self.groups = [ all ] ipv6_re = re.compile('\[([a-f:A-F0-9]*[%[0-z]+]?)\](?::(\d+))?') for x in host_list: m = ipv6_re.match(x) if m: all.add_host(Host(m.groups()[0], m.groups()[1])) else: if ":" in x: tokens = x.rsplit(":", 1) # if there is ':' in the address, then this is an ipv6 if ':' in tokens[0]: all.add_host(Host(x)) else: all.add_host(Host(tokens[0], tokens[1])) else: all.add_host(Host(x)) elif os.path.exists(host_list): if os.path.isdir(host_list): # Ensure basedir is inside the directory self.host_list = os.path.join(self.host_list, "") self.parser = InventoryDirectory(filename=host_list) self.groups = self.parser.groups.values() else: # check to see if the specified file starts with a # shebang (#!/), so if an error is raised by the parser # class we can show a more apropos error shebang_present = False try: inv_file = open(host_list) first_line = inv_file.readlines()[0] inv_file.close() if first_line.startswith('#!'): shebang_present = True except: pass if utils.is_executable(host_list): try: self.parser = InventoryScript(filename=host_list) self.groups = self.parser.groups.values() except: if not shebang_present: raise errors.AnsibleError("The file %s is marked as executable, but failed to execute correctly. " % host_list + \ "If this is not supposed to be an executable script, correct this with `chmod -x %s`." % host_list) else: raise else: try: self.parser = InventoryParser(filename=host_list) self.groups = self.parser.groups.values() except: if shebang_present: raise errors.AnsibleError("The file %s looks like it should be an executable inventory script, but is not marked executable. " % host_list + \ "Perhaps you want to correct this with `chmod +x %s`?" % host_list) else: raise utils.plugins.vars_loader.add_directory(self.basedir(), with_subdir=True) else: raise errors.AnsibleError("Unable to find an inventory file, specify one with -i ?") self._vars_plugins = [ x for x in utils.plugins.vars_loader.all(self) ] # get group vars from group_vars/ files and vars plugins for group in self.groups: group.vars = utils.combine_vars(group.vars, self.get_group_variables(group.name, vault_password=self._vault_password)) # get host vars from host_vars/ files and vars plugins for host in self.get_hosts(): host.vars = utils.combine_vars(host.vars, self.get_host_variables(host.name, vault_password=self._vault_password))
def __init__(self, filename=C.DEFAULT_HOST_LIST): self.names = os.listdir(filename) self.names.sort() self.directory = filename self.parsers = [] self.hosts = {} self.groups = {} for i in self.names: # Skip files that end with certain extensions or characters if any(i.endswith(ext) for ext in ("~", ".orig", ".bak", ".ini", ".retry", ".pyc", ".pyo")): continue # Skip hidden files if i.startswith('.') and not i.startswith('./'): continue # These are things inside of an inventory basedir if i in ("host_vars", "group_vars", "vars_plugins"): continue fullpath = os.path.join(self.directory, i) if os.path.isdir(fullpath): parser = InventoryDirectory(filename=fullpath) elif utils.is_executable(fullpath): parser = InventoryScript(filename=fullpath) else: parser = InventoryParser(filename=fullpath) self.parsers.append(parser) # retrieve all groups and hosts form the parser and add them to # self, don't look at group lists yet, to avoid # recursion trouble, but just make sure all objects exist in self newgroups = parser.groups.values() for group in newgroups: for host in group.hosts: self._add_host(host) for group in newgroups: self._add_group(group) # now check the objects lists so they contain only objects from # self; membership data in groups is already fine (except all & # ungrouped, see later), but might still reference objects not in self for group in self.groups.values(): # iterate on a copy of the lists, as those lists get changed in # the loop # list with group's child group objects: for child in group.child_groups[:]: if child != self.groups[child.name]: group.child_groups.remove(child) group.child_groups.append(self.groups[child.name]) # list with group's parent group objects: for parent in group.parent_groups[:]: if parent != self.groups[parent.name]: group.parent_groups.remove(parent) group.parent_groups.append(self.groups[parent.name]) # list with group's host objects: for host in group.hosts[:]: if host != self.hosts[host.name]: group.hosts.remove(host) group.hosts.append(self.hosts[host.name]) # also check here that the group that contains host, is # also contained in the host's group list if group not in self.hosts[host.name].groups: self.hosts[host.name].groups.append(group) # extra checks on special groups all and ungrouped # remove hosts from 'ungrouped' if they became member of other groups if 'ungrouped' in self.groups: ungrouped = self.groups['ungrouped'] # loop on a copy of ungrouped hosts, as we want to change that list for host in ungrouped.hosts[:]: if len(host.groups) > 1: host.groups.remove(ungrouped) ungrouped.hosts.remove(host) # remove hosts from 'all' if they became member of other groups # all should only contain direct children, not grandchildren # direct children should have dept == 1 if 'all' in self.groups: allgroup = self.groups['all' ] # loop on a copy of all's child groups, as we want to change that list for group in allgroup.child_groups[:]: # groups might once have beeen added to all, and later be added # to another group: we need to remove the link wit all then if len(group.parent_groups) > 1 and allgroup in group.parent_groups: # real children of all have just 1 parent, all # this one has more, so not a direct child of all anymore group.parent_groups.remove(allgroup) allgroup.child_groups.remove(group) elif allgroup not in group.parent_groups: # this group was once added to all, but doesn't list it as # a parent any more; the info in the group is the correct # info allgroup.child_groups.remove(group)
def __init__(self, filename=C.DEFAULT_HOST_LIST): ''' InventoryDirectory基类,包含以下属性: names,当前目录下的文件名称列表 directory, 目录名 parsers,解析器列表,每一个文件解析成一个parser hosts,主机对象字典 groups,组对象字典 ''' # os.listdir函数用来列出当前目录下的所有文件 self.names = os.listdir(filename) self.names.sort() self.directory = filename self.parsers = [] self.hosts = {} self.groups = {} for i in self.names: # 变量该目录下所有文件 # Skip files that end with certain extensions or characters # 跳过带有特定扩展名或字符结尾的文件 if any(i.endswith(ext) for ext in ("~", ".orig", ".bak", ".ini", ".retry", ".pyc", ".pyo")): continue # Skip hidden files # 跳过隐藏文件 if i.startswith('.') and not i.startswith('./'): continue # These are things inside of an inventory basedir # 跳过可能包含变量值的文件 if i in ("host_vars", "group_vars", "vars_plugins"): continue fullpath = os.path.join(self.directory, i) if os.path.isdir(fullpath): # 如果该文件仍然是一个目录,则生成一个当前类对象的Parser(嵌套处理) parser = InventoryDirectory(filename=fullpath) elif utils.is_executable(fullpath): # 如果文件是一个可执行文件,则创建一个InventoryScript类的Parser parser = InventoryScript(filename=fullpath) else: parser = InventoryParser(filename=fullpath) # 如果文件是一个普通文件,则使用InventoryParser类的parser self.parsers.append(parser) # 将parser加入self.parsers的列表中 # retrieve all groups and hosts form the parser and add them to # self, don't look at group lists yet, to avoid # recursion trouble, but just make sure all objects exist in self newgroups = parser.groups.values() # 获取当前parser的groups列表 for group in newgroups: for host in group.hosts: # 遍历每个group对象的hosts对象列表,将host对象添加到self.hosts字典中。 self._add_host(host) # 添加host可能出现在多个文件返回结果中具有相同hostname的情况,需要进行合并。 for group in newgroups: # 将groups列表中的group加到self.groups字典中,为什么不在上一个循环中一次性搞定。。。 self._add_group(group) # 添加group,可能出现group重复的情况,需要进行合并 # now check the objects lists so they contain only objects from # self; membership data in groups is already fine (except all & # ungrouped, see later), but might still reference objects not in self # 所有group都添加完成后还要做一些检测,包括子组,父组,host # 如果self.groups和self.hosts中的group对象和host对象出现名称相同,但对象不同的,都需要以self.groups和self.hosts中为准 for group in self.groups.values(): # iterate on a copy of the lists, as those lists get changed in # the loop # list with group's child group objects: for child in group.child_groups[:]: # a和a[:]有什么区别,干嘛多写3个字符 if child != self.groups[child.name]: group.child_groups.remove(child) group.child_groups.append(self.groups[child.name]) # list with group's parent group objects: for parent in group.parent_groups[:]: if parent != self.groups[parent.name]: group.parent_groups.remove(parent) group.parent_groups.append(self.groups[parent.name]) # list with group's host objects: for host in group.hosts[:]: if host != self.hosts[host.name]: group.hosts.remove(host) group.hosts.append(self.hosts[host.name]) # also check here that the group that contains host, is # also contained in the host's group list if group not in self.hosts[host.name].groups: self.hosts[host.name].groups.append(group) # extra checks on special groups all and ungrouped # remove hosts from 'ungrouped' if they became member of other groups # 检测ungrouped组 if 'ungrouped' in self.groups: ungrouped = self.groups['ungrouped'] # loop on a copy of ungrouped hosts, as we want to change that list for host in ungrouped.hosts[:]: if len(host.groups) > 1: host.groups.remove(ungrouped) ungrouped.hosts.remove(host) # remove hosts from 'all' if they became member of other groups # all should only contain direct children, not grandchildren # direct children should have dept == 1 # 对all组的检测 if 'all' in self.groups: allgroup = self.groups['all' ] # loop on a copy of all's child groups, as we want to change that list for group in allgroup.child_groups[:]: # 遍历allgroup中的所有group对象 # groups might once have beeen added to all, and later be added # to another group: we need to remove the link wit all then if len(group.parent_groups) > 1 and allgroup in group.parent_groups: # 如果当前group的父组数量大于1,并且allgroup是他的父组,则表名该组不是allgroup的子组 # all group的子组必须只有all一个父组 # real children of all have just 1 parent, all # this one has more, so not a direct child of all anymore group.parent_groups.remove(allgroup) allgroup.child_groups.remove(group) elif allgroup not in group.parent_groups: # 以group的父组信息为准进行数据清理 # this group was once added to all, but doesn't list it as # a parent any more; the info in the group is the correct # info allgroup.child_groups.remove(group)
continue if i.endswith(".retry"): # this file is generated on a failed playbook and should only be # used when run specifically >>>>>>> remote continue # Skip hidden files if i.startswith('.') and not i.startswith('./'): continue # These are things inside of an inventory basedir if i in ("host_vars", "group_vars", "vars_plugins"): continue fullpath = os.path.join(self.directory, i) if os.path.isdir(fullpath): parser = InventoryDirectory(filename=fullpath) elif utils.is_executable(fullpath): parser = InventoryScript(filename=fullpath) else: parser = InventoryParser(filename=fullpath) self.parsers.append(parser) # retrieve all groups and hosts form the parser and add them to # self, don't look at group lists yet, to avoid # recursion trouble, but just make sure all objects exist in self newgroups = parser.groups.values() for group in newgroups: for host in group.hosts: self._add_host(host) for group in newgroups: self._add_group(group)