Ejemplo n.º 1
0
class AnsibleHelper(object):

    Options = namedtuple('Options',
                         ['connection', 'module_path', 'forks', 'become_user',
                          'become', 'become_method', 'check', 'extra_vars',
                          'listhosts', 'listtasks', 'listtags', 'syntax',
                         ])

    def __init__(self, inventory_file):
        self.variable_manager = vm = VariableManager()
        self.loader = DataLoader()
        self.inventory = Inventory(loader=self.loader,
                                   variable_manager=vm,
                                   host_list=inventory_file)
        vm.set_inventory(self.inventory)
        self.options_args = dict(connection='smart',
                                 module_path=None,
                                 forks=100,
                                 become=None,
                                 become_method=None,
                                 become_user=None,
                                 check=False,
                                 listhosts=False,
                                 listtasks=False,
                                 listtags=False,
                                 syntax=False,
                                 extra_vars={})
        self._run_vars = None

    def run_playbook(self, playbook):
        options = self.Options(**self.options_args)
        vm = self.variable_manager
        vm.extra_vars = load_extra_vars(loader=self.loader, options=options)
        pbe = PlaybookExecutor(
            playbooks=[playbook],
            inventory=self.inventory,
            variable_manager=vm,
            loader=self.loader,
            options=options,
            passwords=dict(conn_pass='******'),
        )
        res = pbe.run()
        self._run_vars = vm.get_vars(self.loader)
        return res

    def get_vars(self, *args, **kwargs):
        self.inventory.get_vars(*args, **kwargs)

    def get_hosts(self, *args, **kwargs):
        self.inventory.ger_hosts(*args, **kwargs)

    def get_groups(self, *args, **kwargs):
        self.inventory.get_groups(*args, **kwargs)

    @property
    def run_vars(self):
        return self._run_vars
Ejemplo n.º 2
0
class AnsibleInventory(object):
    def __init__(self, inventory_generator):
        """
        :type inventory_generator: ops.inventory.generator.InventoryGenerator
        """

        self.inventory_generator = inventory_generator
        self.generated_path, self.ssh_config_path = inventory_generator.generate(
        )

        # clean up variables cache for tests
        ansible_vars.VARIABLE_CACHE = dict()
        ansible_vars.HOSTVARS_CACHE = dict()
        ansible_inventory.HOSTS_PATTERNS_CACHE = dict()

        self.variable_manager = VariableManager()
        loader = DataLoader()
        self.inventory = Inventory(loader=loader,
                                   variable_manager=self.variable_manager,
                                   host_list=self.generated_path)
        self.variable_manager.set_inventory(self.inventory)
        self.inventory.set_playbook_basedir(self.generated_path)

    def get_hosts(self, limit):
        return self.inventory.get_hosts(limit)

    def get_host(self, host):
        return self.inventory.get_host(unicode(host))

    def get_vars(self, host):
        return self.inventory.get_vars(unicode(host))

    def get_ssh_config(self):
        return self.ssh_config_path
Ejemplo n.º 3
0
def find_host_in_inventory(base, host_name):
  loader = DataLoader()
  var_manager = VariableManager()
  host_vars = None
  host_info = []

  for i in get_inventory_files(base):
    try:
      inv = Inventory(host_list='%s/%s' %(base, i), loader=loader, variable_manager=var_manager)
      host_vars = inv.get_vars(host_name)
    except AnsibleError as err:
#      print '%s in inventory %s' %(err, i)
      inv.host_list = None
      inv.refresh_inventory()
      continue

  if host_vars:
    ssh_host = host_vars.get('ansible_ssh_host', None)
    ssh_user = host_vars.get('ansible_ssh_user', None)
    ssh_key  = host_vars.get('ansible_ssh_private_key_file', None)
    ssh_port = host_vars.get('ansible_ssh_port', 22)
  else:
    raise Exception('Host %s is not present in any inventory %s' %(host_name, ' '.join(get_inventory_files(base))))

  if not ssh_host or not ssh_user:
    raise Exception('ansible_ssh_host and ansible_ssh_user required.')

  host_info.append(str('%s@%s' %(ssh_user, ssh_host)))

  if ssh_key:
    ssh_key = os.path.expanduser(ssh_key)

    if not os.path.isabs(ssh_key):
      ssh_key = os.path.abspath(ssh_key)

    if os.path.exists(ssh_key):
      host_info += ['-i', str(ssh_key)]
    else:
      print ("SSH key %s doesn't exists please check path." %(ssh_key))

  if ssh_port:
    if not int(ssh_port) == min(max(int(ssh_port), 0), 65535):
      raise Exception('Incorrect port number given')
    host_info += ['-p', str(ssh_port)]

  return host_info
Ejemplo n.º 4
0
    def run(self):

        # Note: slightly wrong, this is written so that implicit localhost
        # Manage passwords
        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.playbooks:
            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)
        elif 'VAULT_PASS' in os.environ:
            loader.set_vault_password(os.environ['VAULT_PASS'])

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

        # Subspace injection
        option_extra_vars = load_extra_vars(loader=loader,
                                            options=self.options)
        option_extra_vars.update(self.extra_vars)
        variable_manager.extra_vars = option_extra_vars
        # End Subspace injection

        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)
        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)

        hosts = inventory.get_hosts()
        if self.options.subset and not hosts:
            raise NoValidHosts(
                "The limit <%s> is not included in the inventory: %s" %
                (self.options.subset, inventory.host_list))

    # create the playbook executor, which manages running the plays via a task queue manager
    # Subspace injection
        pbex = PlaybookExecutor(playbooks=self.playbooks,
                                inventory=inventory,
                                variable_manager=variable_manager,
                                loader=loader,
                                options=self.options,
                                passwords=passwords)
        playbook_map = self._get_playbook_map()
        pbex._tqm._stats = SubspaceAggregateStats(playbook_map)
        pbex._tqm.load_callbacks()
        pbex._tqm.send_callback(
            'start_logging',
            logger=self.options.logger,
            username=self.extra_vars.get('ATMOUSERNAME', "No-User"),
        )
        for host in inventory._subset:
            variables = inventory.get_vars(host)
            self.options.logger.info("Vars found for hostname %s: %s" %
                                     (host, variables))
        # End Subspace injection

        results = pbex.run()
        # Subspace injection
        stats = pbex._tqm._stats
        self.stats = stats
        # Nonpersistent fact cache stores 'register' variables. We would like
        # to get access to stdout/stderr for specific commands and relay
        # some of that information back to the end user.
        self.results = dict(pbex._variable_manager._nonpersistent_fact_cache)
        # End Subspace injection

        if isinstance(results, list):
            for p in 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
Ejemplo n.º 5
0
def _main():
    global tab_size

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

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

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

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

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

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

    try:
        groups = {}

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

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

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

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

            group_ref = inventory.get_group(group)

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

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

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

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

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

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

    except Exception as e:
        print("** ERROR: %s\n") % str(e)
        traceback.print_exc()