class PlayBook(object): def __init__(self, inventory='/etc/ansible/hosts', extra_vars=None, private_key_file=None): """ :param playbook: playbook.yml :param inventory: inventory file or script :type param extra_vars: dict :param private_key_file: ssh private key """ self.pbex = None self.options = Options(private_key_file=private_key_file, connection='smart', forks=10, timeout=10, verbosity=0, check=False, listtasks=False, listhosts=False, syntax=False, subset=None, module_path=None, become=None, become_user=None, become_method='sudo') # initialize needed objects self.loader = DataLoader() self.variable_manager = VariableManager() self.variable_manager.extra_vars = extra_vars self.variable_manager.options_vars = {'ansible_check_mode': self.options.check} self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=inventory) self.variable_manager.set_inventory(self.inventory) # Limits inventory results to a subset of inventory that matches a given pattern self.inventory._subset = self.options.subset def run_playbook(self, playbook): self.pbex = PlaybookExecutor(playbooks=[playbook], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords={'conn_pass': None, 'become_pass': None}) self.pbex._tqm._stdout_callback = ResultCallback() return self.pbex.run() def run_play(self, play): pass
def playbook_api(self,yml_fp): loader = DataLoader() variable_manager = VariableManager() inventory = Inventory( loader=loader, variable_manager=variable_manager, host_list=self.ansible_host_list ) variable_manager.set_inventory(inventory) playbooks = ["%s" % yml_fp] pbex = PlaybookExecutor( playbooks=playbooks, inventory=inventory, variable_manager=variable_manager, loader=loader, options=self.options, passwords=self.passwords ) callback = AnsiCallBack() pbex._tqm._stdout_callback = callback pbex.run() return self.evaluate_results(callback)
def pbexe(sid,war,mode): variable_manager = VariableManager() loader = DataLoader() # inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=[]) inventory = Inventory(loader=loader, variable_manager=variable_manager) playbook_path = '/etc/ansible/yml/'+sid+'.yml' if not os.path.exists(playbook_path): print playbook_path print '[INFO] The playbook does not exist' sys.exit() Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check']) options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='ssh', module_path=None, forks=100, remote_user='******', private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True, become_method=None, become_user='******', verbosity=None, check=False) variable_manager.extra_vars = {'war': war,'mode': mode} # This can accomodate various other command line arguments.` passwords = {} #cb = ResultCallback() # cb = default.CallbackModule() pbex = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords) # pbex._tqm._stdout_callback = cb op=sys.stdout filename='/var/log/ansible/'+time.strftime('%Y%m%d%H%M%S')+'.log' opf=open(filename,'w') sys.stdout=opf results = pbex.run() sys.stdout=op opf.close print open(filename,'r').read() return filename
def pbexe(userid,serial,host,module,apppath,yaml,url=None): variable_manager = VariableManager() loader = DataLoader() hostfile = '/ansible/hosts' inventory = Inventory(loader=loader, variable_manager=variable_manager,host_list='/ansible/hosts') playbook_path = yaml if not os.path.exists(playbook_path): print playbook_path print '[INFO] The playbook does not exist' sys.exit() Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check']) options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='ssh', module_path=None, forks=100, remote_user='******', private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True, become_method=None, become_user='******', verbosity=None, check=False) variable_manager.extra_vars = { 'host': host, 'module': module, 'tomcat_root': apppath, 'url': url } # This can accomodate various other command line arguments.` passwords = {} cb = CallbackModule(serial) # cb = default.CallbackModule() pbex = PlaybookExecutor( playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords) pbex._tqm._stdout_callback = cb results = pbex.run() return results
def AnsibleTask(task_list,host_list,user): '''ansible python api 2.0''' loader = DataLoader() variable_manager = VariableManager() inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=host_list) variable_manager.set_inventory(inventory) task_dict = [] for i in task_list: task_dict.append({"action": {"module": i[0], "args": i[1] }}) variable_manager.extra_vars = {"ansible_ssh_user": user, "ansible_ssh_pass": ""} play_source = {"name" : "Ansible PlayBook Run", "hosts": host_list[0], "gather_facts": "no","tasks": task_dict} play = Play().load(play_source, variable_manager=variable_manager, loader=loader) tqm = None try: tqm = TaskQueueManager( inventory = inventory, variable_manager = variable_manager, loader = loader, options = options, passwords = None, stdout_callback = 'minimal', run_tree = False, ) result = tqm.run(play) except Exception,e: result = e
def __init__(self, **kwargs): super(Ansible_playbook, self).__init__(**kwargs) self.task_file = kwargs.get('task_file', None) self.sudo = kwargs.get('sudo', False) self.sudo_user = kwargs.get('sudo_user', False) self.sudo_password = kwargs.get('sudo_password', False) # check if parameters have been provided if self._is_parameters_ok(): variable_manager = VariableManager() loader = DataLoader() options = self._get_options() passwords = {'become_pass': self.sudo_password} inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list="localhost") variable_manager.set_inventory(inventory) playbooks = [self.task_file] executor = PlaybookExecutor( playbooks=playbooks, inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords) executor.run()
def call_ansible(yaml_file, become=False, tag=None): """Call Ansible with a playbook.""" variable_manager = VariableManager() loader = DataLoader() inventory = Inventory(loader, variable_manager) variable_manager.set_inventory(inventory) Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection', 'module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check', 'tags']) options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='', module_path='', forks=100, remote_user='', private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=become, become_method='sudo', become_user='******', verbosity=2, check=False, tags=tag) pbex = PlaybookExecutor(playbooks=[yaml_file], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords={}) logger.debug("Calling Ansible with yaml file: {}".format(yaml_file)) result = pbex.run() if result: logger.error("An error occured whilst executing the Ansible Playbook.")
def test_manager_extra_vars(self): extra_vars = dict(a=1, b=2, c=3) v = VariableManager() v.set_extra_vars(extra_vars) self.assertEqual(v.get_vars(), extra_vars) self.assertIsNot(v.extra_vars, extra_vars)
def ansible_task(playbooks): Options = namedtuple('Options', \ ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'listhosts', 'listtasks', 'listtags', 'syntax']) options = Options( connection = 'ssh', module_path = '/opt/ansible/modules', forks = 100, become = True, become_method = 'sudo', become_user = '******', check = False, listhosts = None, listtasks = None, listtags = None, syntax = None ) loader = DataLoader() variable_manager = VariableManager() inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='/opt/ansible/inventory') variable_manager.set_inventory(inventory) pb = PlaybookExecutor(playbooks=[playbooks], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=None) pb.run() stats = pb._tqm._stats ips = stats.processed.keys() return [ {ip : stats.summarize(ip)} for ip in ips ]
def execute_action(self, action, args): """ Execute the requested operation """ C.DEFAULT_ROLES_PATH = [os.path.join(ROLESDIR, str(action))] i3xfce.loggers.ROOTLOGGER.debug("Executing the %s action", action) # Get the real user behind the sudo username = os.getenv("SUDO_USER") if username is None: i3xfce.loggers.ROOTLOGGER.debug("Unable to get SUDO_USER environment variable. This means i3-xfce has not been \ started using sudo") raise Exception("This program must be ran using sudo ") i3xfce.loggers.ROOTLOGGER.debug("Creating the option tuple") options_tuple = namedtuple('Options', ['connection', 'forks', 'module_path', 'become_user', 'become', 'become_method', 'check', 'verbosity']) try: # initialize needed objects variable_manager = VariableManager() variable_manager.extra_vars = dict(action=str(action), remote_user=username) loader = DataLoader() i3xfce.loggers.ROOTLOGGER.debug("Creating option to count number of tasks to execute") options = options_tuple(connection=None, module_path=None, forks=1, become_user=None, become=None, become_method=None, verbosity=0, check=True) tasks_count_callback = TaskCountCallback() # create inventory and pass to var manager inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=None) variable_manager.set_inventory(inventory) # create play with tasks play_source = dict( name="Ansible Play", hosts='localhost', gather_facts='no', ignore_errors="yes", roles=args.parts ) CmdLine._execute_play(play_source, inventory, variable_manager, loader, options, tasks_count_callback) i3xfce.loggers.ROOTLOGGER.debug("%i tasks are going to be executed", tasks_count_callback.get_total_tasks_num()) play_source["ignore_errors"] = "no" options = options_tuple(connection=None, module_path=None, forks=1, become_user=None, become=None, become_method=None, verbosity=0, check=args.dryrun) self._results_callback = PlaybookExecutionCallback(tasks_count_callback.get_total_tasks_num(), tasks_count_callback.get_task_name_max_len()) CmdLine._execute_play(play_source, inventory, variable_manager, loader, options, self._results_callback) self._results_callback.get_progress_bar().stop() self._results_callback.get_progress_bar().join() if self._results_callback.get_task_failed() is True: raise TaskExecutionException("") except TaskExecutionException as exc: raise except Exception as exc: raise TaskExecutionException(str(exc))
def test_manager_play_vars(self): mock_play = MagicMock() mock_play.get_vars.return_value = dict(foo="bar") mock_play.get_roles.return_value = [] mock_play.get_vars_files.return_value = [] v = VariableManager() self.assertEqual(v.get_vars(play=mock_play), dict(foo="bar"))
class Runner(object): def __init__(self, playbook, display, hosts=None, options={}, passwords={}, vault_pass=None): self.options = Options() for k, v in options.iteritems(): setattr(self.options, k, v) self.display = display self.display.verbosity = self.options.verbosity # executor has its own verbosity setting playbook_executor.verbosity = self.options.verbosity # gets data from YAML/JSON files self.loader = DataLoader() if vault_pass is not None: self.loader.set_vault_password(vault_pass) elif 'VAULT_PASS' in os.environ: self.loader.set_vault_password(os.environ['VAULT_PASS']) # all the variables from all the various places self.variable_manager = VariableManager() if self.options.python_interpreter is not None: self.variable_manager.extra_vars = { 'ansible_python_interpreter': self.options.python_interpreter } # set inventory, using most of above objects self.inventory = Inventory( loader=self.loader, variable_manager=self.variable_manager, host_list=hosts) if len(self.inventory.list_hosts()) == 0: self.display.error("Provided hosts list is empty.") sys.exit(1) self.inventory.subset(self.options.subset) if len(self.inventory.list_hosts()) == 0: self.display.error("Specified limit does not match any hosts.") sys.exit(1) self.variable_manager.set_inventory(self.inventory) # setup playbook executor, but don't run until run() called self.pbex = playbook_executor.PlaybookExecutor( playbooks=[playbook], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=passwords) def run(self): # run playbook and get stats self.pbex.run() stats = self.pbex._tqm._stats return stats
def test_variable_manager_task_vars(self): fake_loader = DictDataLoader({}) mock_task = MagicMock() mock_task._role = None mock_task.get_vars.return_value = dict(foo="bar") v = VariableManager() self.assertEqual(v.get_vars(loader=fake_loader, task=mock_task, use_cache=False).get("foo"), "bar")
def main(): host_list = ['localhost', 'www.example.com', 'www.google.com'] Options = namedtuple('Options', ['connection','module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check']) # initialize needed objects variable_manager = VariableManager() loader = DataLoader() options = Options(connection='smart', module_path='/usr/share/ansible', forks=100, remote_user=None, private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None, become_user=None, verbosity=None, check=False) passwords = dict() # create inventory and pass to var manager inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=host_list) variable_manager.set_inventory(inventory) # create play with tasks play_source = dict( name = "Ansible Play", hosts = host_list, gather_facts = 'no', tasks = [ dict(action=dict(module='command', args=dict(cmd='/usr/bin/uptime'))) ] ) play = Play().load(play_source, variable_manager=variable_manager, loader=loader) # actually run it tqm = None callback = ResultsCollector() try: tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords, ) tqm._stdout_callback = callback result = tqm.run(play) finally: if tqm is not None: tqm.cleanup() print "UP ***********" for host, result in callback.host_ok.items(): print '{} >>> {}'.format(host, result._result['stdout']) print "FAILED *******" for host, result in callback.host_failed.items(): print '{} >>> {}'.format(host, result._result['msg']) print "DOWN *********" for host, result in callback.host_unreachable.items(): print '{} >>> {}'.format(host, result._result['msg'])
def get_inventory(inventory='hosts'): if HAS_ANSIBLE2: loader = DataLoader() variable_manager = VariableManager() inventory = Inventory(loader=loader, variable_manager=variable_manager) variable_manager.set_inventory(inventory) else: inventory_filename = "%s/%s" % (ANSIBLE_DIR, inventory) inventory = Inventory(host_list=inventory_filename) return inventory
def test_variable_manager_play_vars(self): fake_loader = DictDataLoader({}) mock_play = MagicMock() mock_play.get_vars.return_value = dict(foo="bar") mock_play.get_roles.return_value = [] mock_play.get_vars_files.return_value = [] v = VariableManager() self.assertEqual(v.get_vars(loader=fake_loader, play=mock_play, use_cache=False).get("foo"), "bar")
def main(args): # Options definition # Custom tuple to store playbook options Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check']) # Object initialization variable_manager = VariableManager() loader = DataLoader() options = Options(connection='ssh',module_path='library', forks=100, become=None, become_method=None, become_user=None, check=False) passwords = {} # Dinamyc inventory inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=args) # Inventory assignation variable_manager.set_inventory(inventory) # Play creation with tasks play_source = dict( name="Ansible Play", hosts=args, gather_facts='no', tasks=[ dict(action=dict(module='shell', args='hostname -f'), register='shell_out'), dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))) ] ) play = Play().load(play_source, variable_manager=variable_manager, loader=loader) # Running it tqm = None try: tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords, stdout_callback='default' ) result = tqm.run(play) finally: if tqm is not None: tqm.cleanup()
def test_basic_manager(self): fake_loader = DictDataLoader({}) v = VariableManager() vars = v.get_vars(loader=fake_loader, use_cache=False) #FIXME: not sure why we remove all and only test playbook_dir for remove in ['omit', 'vars', 'ansible_version', 'ansible_check_mode', 'ansible_playbook_python']: if remove in vars: del vars[remove] self.assertEqual(vars, dict(playbook_dir='.'))
def test_variable_manager_role_vars_dependencies(self): ''' Tests vars from role dependencies with duplicate dependencies. ''' v = VariableManager() v._fact_cache = defaultdict(dict) fake_loader = DictDataLoader({ # role common-role '/etc/ansible/roles/common-role/tasks/main.yml': """ - debug: msg="{{role_var}}" """, # We do not need allow_duplicates: yes for this role # because eliminating duplicates is done by the execution # strategy, which we do not test here. # role role1 '/etc/ansible/roles/role1/vars/main.yml': """ role_var: "role_var_from_role1" """, '/etc/ansible/roles/role1/meta/main.yml': """ dependencies: - { role: common-role } """, # role role2 '/etc/ansible/roles/role2/vars/main.yml': """ role_var: "role_var_from_role2" """, '/etc/ansible/roles/role2/meta/main.yml': """ dependencies: - { role: common-role } """, }) play1 = Play.load(dict( hosts=['all'], roles=['role1', 'role2'], ), loader=fake_loader, variable_manager=v) # The task defined by common-role exists twice because role1 # and role2 depend on common-role. Check that the tasks see # different values of role_var. blocks = play1.compile() task = blocks[1].block[0] res = v.get_vars(loader=fake_loader, play=play1, task=task) self.assertEqual(res['role_var'], 'role_var_from_role1') task = blocks[2].block[0] res = v.get_vars(loader=fake_loader, play=play1, task=task) self.assertEqual(res['role_var'], 'role_var_from_role2')
def test_basic_manager(self): fake_loader = DictDataLoader({}) v = VariableManager() vars = v.get_vars(loader=fake_loader, use_cache=False) if 'omit' in vars: del vars['omit'] if 'vars' in vars: del vars['vars'] if 'ansible_version' in vars: del vars['ansible_version'] self.assertEqual(vars, dict(playbook_dir='.'))
def test_variable_manager_extra_vars(self): fake_loader = DictDataLoader({}) extra_vars = dict(a=1, b=2, c=3) v = VariableManager() v.extra_vars = extra_vars vars = v.get_vars(loader=fake_loader, use_cache=False) for (key, val) in extra_vars.iteritems(): self.assertEqual(vars.get(key), val) self.assertIsNot(v.extra_vars, extra_vars)
class Runner(object): def __init__(self, hostnames, playbook, private_key_file, run_data, become_pass=None, verbosity=0, callback=None, subset_pattern=None): self.hostnames = hostnames self.playbook = os.path.join(playbooks_dir, playbook) self.run_data = run_data self.options = Options(subset=subset_pattern, private_key_file=private_key_file, verbosity=verbosity) self.display = Display() self.display.verbosity = verbosity playbook_executor.verbosity = verbosity passwords = {'become_pass': None} # Gets data from YAML/JSON files self.loader = DataLoader() self.loader.set_vault_password(os.environ.get('VAULT_PASS')) self.variable_manager = VariableManager() self.variable_manager.extra_vars = self.run_data self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=self.hostnames) self.variable_manager.set_inventory(self.inventory) self.pbex = playbook_executor.PlaybookExecutor( playbooks=[self.playbook], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=passwords) if callback: self.pbex._tqm._stdout_callback = callback def run(self): self.pbex.run() stats = self.pbex._tqm._stats run_success = True hosts = sorted(stats.processed.keys()) for h in hosts: t = stats.summarize(h) if t['unreachable'] > 0 or t['failures'] > 0: run_success = False return run_success
def main(argv=sys.argv[1:]): # # initialize needed objects # variable_manager = VariableManager() loader = DataLoader() # https://pymotw.com/2/collections/namedtuple.html Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection', 'module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check']) options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='local', module_path=None, forks=100, remote_user='******', private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True, become_method=None, become_user='******', verbosity=None, check=False) passwords = {} inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='./ls_hosts') variable_manager.set_inventory(inventory) playbook_path = './ls.yml' if not os.path.exists(playbook_path): print '[INFO] The playbook does not exist' sys.exit() # This can accomodate various other command line arguments.` # variable_manager.extra_vars = {'hosts': 'mywebserver'} pbex = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords) # cb = ResultAccumulator() # pbex._tqm._stdout_callback = cb results = pbex.run() if results != 0: print "ERROR"
def main(argv=sys.argv[1:]): Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check']) # initialize needed objects variable_manager = VariableManager() loader = DataLoader() options = Options(connection='local', module_path='/path/to/mymodules', forks=100, become=None, become_method=None, become_user=None, check=False) passwords = dict(vault_pass='******') # create inventory and pass to var manager inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='localhost') variable_manager.set_inventory(inventory) # create play with tasks play_source = dict(name="Ansible Play", hosts='localhost', gather_facts='no', tasks=[ dict(action=dict(module='shell', args='uname -a'), register='shell_out'), dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))) ] ) play = Play().load(play_source, variable_manager=variable_manager, loader=loader) # actually run it tqm = None try: tqm = TaskQueueManager(inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords, stdout_callback='default', ) result = tqm.run(play) print result finally: if tqm is not None: tqm.cleanup()
def test_manager_play_vars_files(self): fake_loader = DictDataLoader({ "/path/to/somefile.yml": """ foo: bar """ }) mock_play = MagicMock() mock_play.get_vars.return_value = dict() mock_play.get_roles.return_value = [] mock_play.get_vars_files.return_value = ['/path/to/somefile.yml'] v = VariableManager(loader=fake_loader) self.assertEqual(v.get_vars(play=mock_play), dict(foo="bar"))
def test_variable_manager_play_vars_files(self): fake_loader = DictDataLoader({ "/path/to/somefile.yml": """ foo: bar """ }) mock_play = MagicMock() mock_play.get_vars.return_value = dict() mock_play.get_roles.return_value = [] mock_play.get_vars_files.return_value = ['/path/to/somefile.yml'] v = VariableManager() self.assertEqual(v.get_vars(loader=fake_loader, play=mock_play, use_cache=False).get("foo"), "bar")
class AnsibleTask(object): def __init__(self, hosts='127.0.0.1', module='shell', args='ls -l', options=DEFAULT_OPTIONS, name='Ansible Play'): self.hosts = hosts self.module = module self.args = args self.options = options self.name = name self.task = dict(action=dict( module=self.module, args=self.args ), register='shell_out') self.tasks = [self.task] # initialize needed objects self.variable_manager = VariableManager() self.loader = DataLoader() self.passwords = dict() self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=[self.hosts]) self.variable_manager.set_inventory(self.inventory) self.play_source = dict( name=self.name, hosts=self.hosts, gather_facts='no', tasks=self.tasks ) self.play = Play().load(self.play_source, loader=self.loader, variable_manager=self.variable_manager) self.results_callback = ResultCallback() self.return_results = {} setattr(self.results_callback, 'task_obj', self) def ansible_play(self): # run it tqm = None try: tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, stdout_callback=self.results_callback, # stdout_callback='default', ) result = tqm.run(self.play) finally: if tqm is not None: tqm.cleanup() #self.inventory.clear_pattern_cache() if result != 0: raise ValueError('SSH Command Failed, resturn: %s' % result) return self.return_results
def test_variable_manager_host_vars_file(self): fake_loader = DictDataLoader({ "host_vars/hostname1.yml": """ foo: bar """, "other_path/host_vars/hostname1.yml": """ foo: bam baa: bat """, "host_vars/host.name.yml": """ host_with_dots: true """, }) v = VariableManager() v.add_host_vars_file("host_vars/hostname1.yml", loader=fake_loader) v.add_host_vars_file("other_path/host_vars/hostname1.yml", loader=fake_loader) self.assertIn("hostname1", v._host_vars_files) self.assertEqual(v._host_vars_files["hostname1"], [dict(foo="bar"), dict(foo="bam", baa="bat")]) mock_host = MagicMock() mock_host.get_name.return_value = "hostname1" mock_host.get_vars.return_value = dict() mock_host.get_groups.return_value = () mock_host.get_group_vars.return_value = dict() self.assertEqual(v.get_vars(loader=fake_loader, host=mock_host, use_cache=False).get("foo"), "bam") self.assertEqual(v.get_vars(loader=fake_loader, host=mock_host, use_cache=False).get("baa"), "bat") v.add_host_vars_file("host_vars/host.name", loader=fake_loader) self.assertEqual(v._host_vars_files["host.name"], [dict(host_with_dots=True)])
def test_base(self): test_inv_dir = 'test/inventory' for inv in os.listdir(test_inv_dir): print "Processing ", inv res = dynlxc.main(os.path.join(test_inv_dir, inv), '') variable_manager = VariableManager() loader = DataLoader() self.mock_rv.communicate.return_value = [ json.dumps(res), 'mocked_err'] try: inventory = Inventory( loader=loader, variable_manager=variable_manager, host_list='inventory/dynlxc.py' ) except Exception as err: raise Exception("Inventory file {0} processing result '{1}' " "failed with {2}".format(inv, res, err)) variable_manager.set_inventory(inventory) play_source = dict(name="Ansible Play", hosts='localhost', gather_facts='no') playbook = os.path.abspath(os.path.join(test_inv_dir, '../playbooks', inv)) if os.path.isfile(playbook): with open(playbook) as fh: real_playbook = yaml.load(fh)[0] play_source.update(real_playbook) play = Play().load(play_source, variable_manager=variable_manager, loader=loader) tqm = None try: tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, options=self.options, passwords=None, stdout_callback='default', ) result = tqm.run(play) assert result == 0, ("Ansible playbook exitcode " "different from 0") finally: if tqm is not None: tqm.cleanup()
def __init__(self, hosts='127.0.0.1', module='shell', args='ls -l', options=DEFAULT_OPTIONS, name='Ansible Play'): self.hosts = hosts self.module = module self.args = args self.options = options self.name = name self.task = dict(action=dict( module=self.module, args=self.args ), register='shell_out') self.tasks = [self.task] # initialize needed objects self.variable_manager = VariableManager() self.loader = DataLoader() self.passwords = dict() self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=[self.hosts]) self.variable_manager.set_inventory(self.inventory) self.play_source = dict( name=self.name, hosts=self.hosts, gather_facts='no', tasks=self.tasks ) self.play = Play().load(self.play_source, loader=self.loader, variable_manager=self.variable_manager) self.results_callback = ResultCallback() self.return_results = {} setattr(self.results_callback, 'task_obj', self)
def __init__(self, exec_mode, work_name, username, options_dict, describe, mongoclient=None): ''' ansible的基类,为adhoc、playbook等父类 :parm: exec_mode:ansible工作类型,接受adhoc、palybook等 work_name:该任务的名称,用于日志 username:执行者 options_dict:该任务的特定设置 mongoclient:初始化mongo连接类 ''' self.logger = logging.getLogger("ansible") if exec_mode in ('adhoc', 'playbook'): self.exec_mode = exec_mode else: self.logger.warn( '正在准备执行ansible任务,准备工作失败,原因:参数exec_mode必须是adhoc或者是playbook') return (False, '参数exec_mode必须是adhoc或者是playbook') if isinstance(work_name, str) and work_name: self.work_name = work_name else: self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数work_name必须是非字符串') return (False, '参数work_name必须是非字符串') if isinstance(username, str) and username: self.username = username else: self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数username必须是非字符串') return (False, '参数username必须是非字符串') if isinstance(options_dict, dict) and options_dict: self.options_dict = options_dict else: self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数options_dict必须是非空字典') return (False, '参数options_dict必须是非空字典') if mongoclient is None: self.mongoclient = Op_Mongo() else: self.mongoclient = mongoclient self.work_uuid = str(uuid.uuid4()) self.log_router = Routing_Logging() self.describe = describe if exec_mode == 'adhoc': self.log_prefix = '正在执行用户' + username + '的名为' + work_name + 'uuid为' + self.work_uuid + '的ansible临时任务,' else: self.log_prefix = '正在执行用户' + username + '的名为' + work_name + 'uuid为' + self.work_uuid + '的ansible-playbook任务,' # 下面是加载和初始化相关类 self._parse_options() self.passwords = { 'conn_pass': self.options.ask_pass, 'become_pass': self.options.become_ask_pass } # 设置passwords self.inventory_file = self.options_dict.get('inventory', '') self.loader = DataLoader() self._get_vault_pwd() self.variable_manager = VariableManager() self.variable_manager.extra_vars = load_extra_vars( loader=self.loader, options=self.options) self.variable_manager.options_vars = load_options_vars(self.options) self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=self.inventory_file) self.variable_manager.set_inventory(self.inventory) self.inventory.subset(self.options.subset)
class Base(): def __init__(self, exec_mode, work_name, username, options_dict, describe, mongoclient=None): ''' ansible的基类,为adhoc、playbook等父类 :parm: exec_mode:ansible工作类型,接受adhoc、palybook等 work_name:该任务的名称,用于日志 username:执行者 options_dict:该任务的特定设置 mongoclient:初始化mongo连接类 ''' self.logger = logging.getLogger("ansible") if exec_mode in ('adhoc', 'playbook'): self.exec_mode = exec_mode else: self.logger.warn( '正在准备执行ansible任务,准备工作失败,原因:参数exec_mode必须是adhoc或者是playbook') return (False, '参数exec_mode必须是adhoc或者是playbook') if isinstance(work_name, str) and work_name: self.work_name = work_name else: self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数work_name必须是非字符串') return (False, '参数work_name必须是非字符串') if isinstance(username, str) and username: self.username = username else: self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数username必须是非字符串') return (False, '参数username必须是非字符串') if isinstance(options_dict, dict) and options_dict: self.options_dict = options_dict else: self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数options_dict必须是非空字典') return (False, '参数options_dict必须是非空字典') if mongoclient is None: self.mongoclient = Op_Mongo() else: self.mongoclient = mongoclient self.work_uuid = str(uuid.uuid4()) self.log_router = Routing_Logging() self.describe = describe if exec_mode == 'adhoc': self.log_prefix = '正在执行用户' + username + '的名为' + work_name + 'uuid为' + self.work_uuid + '的ansible临时任务,' else: self.log_prefix = '正在执行用户' + username + '的名为' + work_name + 'uuid为' + self.work_uuid + '的ansible-playbook任务,' # 下面是加载和初始化相关类 self._parse_options() self.passwords = { 'conn_pass': self.options.ask_pass, 'become_pass': self.options.become_ask_pass } # 设置passwords self.inventory_file = self.options_dict.get('inventory', '') self.loader = DataLoader() self._get_vault_pwd() self.variable_manager = VariableManager() self.variable_manager.extra_vars = load_extra_vars( loader=self.loader, options=self.options) self.variable_manager.options_vars = load_options_vars(self.options) self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=self.inventory_file) self.variable_manager.set_inventory(self.inventory) self.inventory.subset(self.options.subset) def _get_vault_pwd(self): ''' 获取vault密码,并初始化vault密码 ''' vault_pwd_file = self.options_dict.get('vault_password_file', False) ask_vault_pass = self.options_dict.get('ask_vault_pass', False) if ask_vault_pass: vault_password = ask_vault_pass else: if vault_pwd_file: this_path = os.path.realpath( os.path.expanduser(vault_pwd_file)) if os.path.exists(this_path): mode = self.loader.is_executable(this_path) result = read_file(this_path, mode=mode, sprfmt=b'\r\n', outfmt='bytes') if result[0]: vault_password = result[1] else: vault_password = None else: vault_password = None else: vault_password = None if vault_password: b_vault_password = string2bytes(vault_password) self.loader.set_vault_password(b_vault_password) self.vault_password = vault_password else: self.vault_password = None def _parse_options(self): ''' 获取options字典 ''' keys_list = [] values_list = [] for key, value in self.options_dict.items(): keys_list.append(key) values_list.append(value) Options = namedtuple('Options', keys_list) self.options = Options._make(values_list) def _show_protectfield(self): protectfield_list = [ 'ask_pass', 'ask_su_pass', 'ask_sudo_pass', 'ask_vault_pass', 'become_ask_pass', 'new_vault_password_file', 'vault_password_file', 'private_key_file', ] log_options = {} for field in self.options_dict: if field in protectfield_list: log_options[field] = '***hidden***' else: log_options[field] = self.options_dict[field] return log_options
class YoRunner(object): Options = namedtuple("Options", [ 'connection', 'module_path', 'private_key_file', "remote_user", 'timeout', 'forks', 'become', 'become_method', 'become_user', 'check', 'extra_vars', ]) def __init__( self, hosts=C.DEFAULT_HOST_LIST, forks=C.DEFAULT_FORKS, # 5 timeout=C.DEFAULT_TIMEOUT, # SSH timeout = 10s remote_user=C.DEFAULT_REMOTE_USER, # root module_path=None, # dirs of custome modules connection_type="smart", become=None, become_method=None, become_user=None, check=False, passwords=None, extra_vars=None, private_key_file=None, gather_facts='no'): self.pattern = '' self.variable_manager = VariableManager() self.loader = DataLoader() self.gather_facts = gather_facts self.options = self.Options( connection=connection_type, timeout=timeout, module_path=module_path, forks=forks, become=become, become_method=become_method, become_user=become_user, check=check, remote_user=remote_user, extra_vars=extra_vars or [], private_key_file=private_key_file, ) # self.variable_manager.extra_vars = load_extra_vars(self.loader, # options=self.options) self.variable_manager.extra_vars = extra_vars self.variable_manager.options_vars = load_options_vars(self.options) self.passwords = passwords or {} self.inventory = YoInventory(hosts) self.variable_manager.set_inventory(self.inventory) self.tasks = [] self.play_source = None self.play = None self.runner = None self.timestamp = str(time.time()) self.filename = FILENAME % (self.timestamp, '') self.have_script = 0 def set_callback(self, callback): self.results_callback = callback @staticmethod def check_module_args(module_name, module_args=''): if module_name in C.MODULE_REQUIRE_ARGS and not module_args: err = "No argument passed to '%s' module." % module_name print(err) return False return True def task_add(self, task_tuple): for task in task_tuple: if not self.check_module_args(task.module, task.args): return if task.module == u'script': self.have_script = 1 script = Script.objects.filter(id=task.args) if os.path.exists(self.filename): os.remove(self.filename) script_name = FILENAME % (self.timestamp, '-' + str(script.get().id)) output = open(script_name, 'w') output.writelines(script.get().formatScript()) output.close() if self.have_script == 1: self.tasks.append( dict(action=dict( module=task.module, args=script_name, ))) else: self.tasks.append( dict(action=dict( module=task.module, args=task.args, ))) def run( self, task_tuple, ): # pattern='all'): """ :param task_tuple: (('shell', 'ls'), ('ping', '')) :param pattern: :param timestamp: :return: """ self.task_add(task_tuple) self.play_source = dict(name=self.timestamp, hosts='all', gather_facts=self.gather_facts, tasks=self.tasks) self.play = Play().load( self.play_source, variable_manager=self.variable_manager, loader=self.loader, ) self.runner = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, stdout_callback=self.results_callback, ) # if not self.inventory.list_hosts("all"): # raise AnsibleError("Inventory is empty.") # # if not self.inventory.list_hosts(self.pattern): # raise AnsibleError( # "pattern: %s dose not match any hosts." % self.pattern) try: self.runner.run(self.play) finally: if self.runner: self.runner.cleanup() if self.loader: self.loader.cleanup_all_tmp_files() if self.have_script: self.cleanup_script() def cleanup_script(self): # if os.path.exists(self.filename): # os.remove(self.filename) # return self.filename for name in glob.glob(self.filename + '*'): if os.path.exists(name): print(name) os.remove(name)
def __init__(self,playbooks,host_list,remote_user='******',passwords='null',group_name='all',ask_pass=False,forks=5,ext_vars=None): self.playbooks = playbooks self.host_list = host_list self.remote_user = remote_user self.passwords = dict(conn_pass=passwords) self.group_name = group_name self.ask_pass = ask_pass self.forks = forks self.connection='smart' self.ext_vars = ext_vars ## 用来加载解析yaml文件或JSON内容,并且支持vault的解密 self.loader = DataLoader() # 管理变量的类,包括主机,组,扩展等变量,之前版本是在 inventory中的 self.variable_manager = VariableManager() # 根据inventory加载对应变量 self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, group_name=self.group_name, # 项目名对应组名,区分当前执行的内容 ext_vars=self.ext_vars, host_list=self.host_list) self.variable_manager.set_inventory(self.inventory) # 初始化需要的对象1 self.Options = namedtuple('Options', ['connection', 'remote_user', 'ask_sudo_pass', 'verbosity', 'ask_pass', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'listhosts', 'listtasks', 'listtags', 'syntax', 'sudo_user', 'sudo' ]) # 初始化需要的对象2 self.options = self.Options(connection=self.connection, remote_user=self.remote_user, ask_pass=self.ask_pass, sudo_user='******', forks=self.forks, sudo='yes', ask_sudo_pass=False, verbosity=5, module_path=None, become=True, become_method='sudo', become_user='******', check=None, listhosts=None, listtasks=None, listtags=None, syntax=None ) # 初始化console输出 self.callback = ExtendCallback()
def run(self, command, *args): self._check_ansible() if HAS_ANSIBLE_1: import ansible.inventory import ansible.runner command = self.get_command(command, *args) kwargs = {} if self.ansible_inventory is not None: kwargs["host_list"] = self.ansible_inventory out = ansible.runner.Runner(pattern=self.host, module_name="shell", module_args=command, **kwargs).run()["contacted"][self.host] # Ansible return an unicode object but this is bytes ... # A simple test case is: # >>> assert File("/bin/true").content == open("/bin/true").read() stdout_bytes = b"".join((chr(ord(c)) for c in out['stdout'])) stderr_bytes = b"".join((chr(ord(c)) for c in out['stderr'])) result = base.CommandResult( self, out['rc'], stdout_bytes, stderr_bytes, command, stdout=out["stdout"], stderr=out["stderr"], ) logger.info("RUN %s", result) return result if HAS_ANSIBLE_2: from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars import VariableManager from ansible.inventory import Inventory from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager from ansible.plugins.callback import CallbackBase class SilentCallbackModule(CallbackBase): """ A callback module that does not print anything, but keeps tabs on what's happening in an Ansible play. """ def __init__(self): self.unreachable = {} self.contacted = {} def runner_on_ok(self, host, result): self.contacted[host] = {'success': True, 'result': result} def runner_on_failed(self, host, result, ignore_errors=False): self.contacted[host] = {'success': False, 'result': result} def runner_on_unreachable(self, host, result): self.unreachable[host] = result callback = SilentCallbackModule() command = self.get_command(command, *args) Options = namedtuple('Options', [ 'connection', 'module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check' ]) # initialize needed objects variable_manager = VariableManager() loader = DataLoader() options = Options(connection='smart', module_path=None, forks=100, remote_user=None, private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None, become_user=None, verbosity=None, check=False) passwords = dict() # create inventory and pass to var manager inventory = Inventory(loader, variable_manager, self.ansible_inventory) variable_manager.set_inventory(inventory) # create play with tasks play_source = dict( name="Ansible Play", hosts=self.host, gather_facts='no', tasks=[dict(action=dict(module="shell", args=command))]) play = Play().load(play_source, variable_manager=variable_manager, loader=loader) # actually run it tqm = None try: tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords, stdout_callback=callback, ) tqm.run(play) ret = base.CommandResult( self, 0 if callback.contacted[self.host][u'success'] else 1, bytes(callback.contacted[self.host][u'result'] ["stdout_lines"]), b"", command, stdout=callback.contacted[self.host][u'result']["stdout"], stderr=callback.contacted[self.host][u'result']["stdout"], ) return ret finally: if tqm is not None: tqm.cleanup()
def apply_playbook(playbook_path, hosts_inv, host_user, ssh_priv_key_file_path, variables=None, proxy_setting=None): """ Executes an Ansible playbook to the given host :param playbook_path: the (relative) path to the Ansible playbook :param hosts_inv: a list of hostnames/ip addresses to which to apply the Ansible playbook :param host_user: A user for the host instances (must be a password-less sudo user if playbook has "sudo: yes" :param ssh_priv_key_file_path: the file location of the ssh key :param variables: a dictionary containing any substitution variables needed by the Jinga 2 templates :param proxy_setting: string containing host:port of the proxy server in use :return: the results """ if not os.path.isfile(playbook_path): raise Exception('Requested playbook not found - ' + playbook_path) if not os.path.isfile(ssh_priv_key_file_path): raise Exception('Requested private SSH key not found - ' + ssh_priv_key_file_path) import ansible.constants ansible.constants.HOST_KEY_CHECKING = False variable_manager = VariableManager() if variables: variable_manager.extra_vars = variables loader = DataLoader() inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=hosts_inv) variable_manager.set_inventory(inventory) loader = DataLoader() ssh_common_args = None ssh_extra_args = None ssh_connection = 'ssh' proxy_command = None if proxy_setting: tokens = re.split(':', proxy_setting) # TODO - Need to configure the proxy settings to avoid adding entries into the host's ~/.ssh/config file options = namedtuple('Options', [ 'listtags', 'listtasks', 'listhosts', 'syntax', 'connection', 'module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check', 'host_key_checking', 'transport', 'proxy_command' ]) ansible_opts = options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection=ssh_connection, module_path=None, forks=100, remote_user=host_user, private_key_file=ssh_priv_key_file_path, ssh_common_args=ssh_common_args, ssh_extra_args=ssh_extra_args, sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None, become_user='******', verbosity=1111, check=False, host_key_checking=True, transport='paramiko', proxy_command=proxy_command) logger.debug('Setting up Ansible Playbook Executor') executor = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=ansible_opts, passwords=None) logger.debug('Executing Ansible Playbook - ' + playbook_path) retval = executor.run() if retval != 0: logger.error('Playbook application failed [' + playbook_path + '] with return value of - ' + str(retval)) raise Exception('Playbook not applied - ' + playbook_path) return retval
def test_variable_manager_precedence(self, mock_basedir): ''' Tests complex variations and combinations of get_vars() with different objects to modify the context under which variables are merged. ''' v = VariableManager() v._fact_cache = defaultdict(dict) fake_loader = DictDataLoader({ # inventory1 '/etc/ansible/inventory1': """ [group2:children] group1 [group1] host1 host_var=host_var_from_inventory_host1 [group1:vars] group_var = group_var_from_inventory_group1 [group2:vars] group_var = group_var_from_inventory_group2 """, # role defaults_only1 '/etc/ansible/roles/defaults_only1/defaults/main.yml': """ default_var: "default_var_from_defaults_only1" host_var: "host_var_from_defaults_only1" group_var: "group_var_from_defaults_only1" group_var_all: "group_var_all_from_defaults_only1" extra_var: "extra_var_from_defaults_only1" """, '/etc/ansible/roles/defaults_only1/tasks/main.yml': """ - debug: msg="here i am" """, # role defaults_only2 '/etc/ansible/roles/defaults_only2/defaults/main.yml': """ default_var: "default_var_from_defaults_only2" host_var: "host_var_from_defaults_only2" group_var: "group_var_from_defaults_only2" group_var_all: "group_var_all_from_defaults_only2" extra_var: "extra_var_from_defaults_only2" """, }) mock_basedir.return_value = './' inv1 = Inventory(loader=fake_loader, variable_manager=v, host_list='/etc/ansible/inventory1') inv1.set_playbook_basedir('./') play1 = Play.load(dict( hosts=['all'], roles=['defaults_only1', 'defaults_only2'], ), loader=fake_loader, variable_manager=v) # first we assert that the defaults as viewed as a whole are the merged results # of the defaults from each role, with the last role defined "winning" when # there is a variable naming conflict res = v.get_vars(loader=fake_loader, play=play1) self.assertEqual(res['default_var'], 'default_var_from_defaults_only2') # next, we assert that when vars are viewed from the context of a task within a # role, that task will see its own role defaults before any other role's blocks = play1.compile() task = blocks[1].block[0] res = v.get_vars(loader=fake_loader, play=play1, task=task) self.assertEqual(res['default_var'], 'default_var_from_defaults_only1') # next we assert the precendence of inventory variables v.set_inventory(inv1) h1 = inv1.get_host('host1') res = v.get_vars(loader=fake_loader, play=play1, host=h1) self.assertEqual(res['group_var'], 'group_var_from_inventory_group1') self.assertEqual(res['host_var'], 'host_var_from_inventory_host1') # next we test with group_vars/ files loaded fake_loader.push( "/etc/ansible/group_vars/all", """ group_var_all: group_var_all_from_group_vars_all """) fake_loader.push( "/etc/ansible/group_vars/group1", """ group_var: group_var_from_group_vars_group1 """) fake_loader.push( "/etc/ansible/group_vars/group3", """ # this is a dummy, which should not be used anywhere group_var: group_var_from_group_vars_group3 """) fake_loader.push( "/etc/ansible/host_vars/host1", """ host_var: host_var_from_host_vars_host1 """) v.add_group_vars_file("/etc/ansible/group_vars/all", loader=fake_loader) v.add_group_vars_file("/etc/ansible/group_vars/group1", loader=fake_loader) v.add_group_vars_file("/etc/ansible/group_vars/group2", loader=fake_loader) v.add_host_vars_file("/etc/ansible/host_vars/host1", loader=fake_loader) res = v.get_vars(loader=fake_loader, play=play1, host=h1) self.assertEqual(res['group_var'], 'group_var_from_group_vars_group1') self.assertEqual(res['group_var_all'], 'group_var_all_from_group_vars_all') self.assertEqual(res['host_var'], 'host_var_from_host_vars_host1') # add in the fact cache v._fact_cache['host1'] = dict( fact_cache_var="fact_cache_var_from_fact_cache") res = v.get_vars(loader=fake_loader, play=play1, host=h1) self.assertEqual(res['fact_cache_var'], 'fact_cache_var_from_fact_cache')
def run(self): super(PlaybookCLI, self).run() # Note: slightly wrong, this is written so that implicit localhost # Manage passwords sshpass = None becomepass = None 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 vault_pass = CLI.read_vault_password_file( self.options.vault_password_file, loader=loader) loader.set_vault_password(vault_pass) elif self.options.ask_vault_pass: vault_pass = self.ask_vault_passwords() loader.set_vault_password(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) 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) # create the playbook executor, which manages running the plays via a task queue manager pbex = PlaybookExecutor(playbooks=self.args, inventory=inventory, variable_manager=variable_manager, loader=loader, options=self.options, passwords=passwords) results = pbex.run() 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
class ANSRunner(object): """ This is a General object for parallel execute modules. """ def __init__(self, resource, redisKey=None, logId=None, *args, **kwargs): self.resource = resource self.inventory = None self.variable_manager = None self.loader = None self.options = None self.passwords = None self.callback = None self.__initializeData(kwargs) self.results_raw = {} self.redisKey = redisKey self.logId = logId def __initializeData(self, kwargs): """ 初始化ansible """ Options = namedtuple('Options', [ 'connection', 'module_path', 'forks', 'timeout', 'remote_user', 'ask_pass', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'ask_value_pass', 'verbosity', 'check', 'listhosts', 'listtasks', 'listtags', 'syntax' ]) self.variable_manager = VariableManager() self.loader = DataLoader() self.options = Options( connection='smart', module_path=None, forks=100, timeout=10, remote_user=kwargs.get('remote_user', 'root'), ask_pass=False, private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True, become_method=kwargs.get('become_method', 'sudo'), become_user=kwargs.get('become_user', 'root'), verbosity=kwargs.get('verbosity', None), check=False, listhosts=False, listtasks=False, listtags=False, syntax=False, ask_value_pass=False, ) self.passwords = dict(sshpass=None, becomepass=None) self.inventory = MyInventory(self.resource, self.loader, self.variable_manager).inventory self.variable_manager.set_inventory(self.inventory) def run_model(self, host_list, module_name, module_args): """ run module from andible ad-hoc. module_name: ansible module_name module_args: ansible module args """ play_source = dict( name="Ansible Play", hosts=host_list, gather_facts='no', tasks=[dict(action=dict(module=module_name, args=module_args))]) play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader) tqm = None if self.redisKey or self.logId: self.callback = ModelResultsCollectorToSave( self.redisKey, self.logId) else: self.callback = ModelResultsCollector() try: tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, ) tqm._stdout_callback = self.callback constants.HOST_KEY_CHECKING = False #关闭第一次使用ansible连接客户端是输入命令 tqm.run(play) except Exception as err: logger.error(msg="run model failed: {err}".format(err=str(err))) if self.redisKey: DsRedis.OpsAnsibleModel.lpush(self.redisKey, data=err) if self.logId: AnsibleSaveResult.Model.insert(self.logId, err) finally: if tqm is not None: tqm.cleanup() def run_playbook(self, host_list, playbook_path, extra_vars=dict()): """ run ansible palybook """ try: if self.redisKey or self.logId: self.callback = PlayBookResultsCollectorToSave( self.redisKey, self.logId) else: self.callback = PlayBookResultsCollector() extra_vars['host'] = ','.join(host_list) self.variable_manager.extra_vars = extra_vars executor = PlaybookExecutor( playbooks=[playbook_path], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, ) executor._tqm._stdout_callback = self.callback constants.HOST_KEY_CHECKING = False #关闭第一次使用ansible连接客户端是输入命令 constants.DEPRECATION_WARNINGS = False constants.RETRY_FILES_ENABLED = False executor.run() except Exception as err: logger.error(msg="run playbook failed: {err}".format(err=str(err))) if self.redisKey: DsRedis.OpsAnsibleModel.lpush(self.redisKey, data=err) if self.logId: AnsibleSaveResult.Model.insert(self.logId, err) return False def get_model_result(self): self.results_raw = {'success': {}, 'failed': {}, 'unreachable': {}} for host, result in self.callback.host_ok.items(): self.results_raw['success'][host] = result._result for host, result in self.callback.host_failed.items(): self.results_raw['failed'][host] = result._result for host, result in self.callback.host_unreachable.items(): self.results_raw['unreachable'][host] = result._result return json.dumps(self.results_raw) def get_playbook_result(self): self.results_raw = { 'skipped': {}, 'failed': {}, 'ok': {}, "status": {}, 'unreachable': {}, "changed": {} } for host, result in self.callback.task_ok.items(): self.results_raw['ok'][host] = result for host, result in self.callback.task_failed.items(): self.results_raw['failed'][host] = result for host, result in self.callback.task_status.items(): self.results_raw['status'][host] = result for host, result in self.callback.task_changed.items(): self.results_raw['changed'][host] = result for host, result in self.callback.task_skipped.items(): self.results_raw['skipped'][host] = result for host, result in self.callback.task_unreachable.items(): self.results_raw['unreachable'][host] = result return self.results_raw def handle_cmdb_data(self, data): '''处理setup返回结果方法''' data_list = [] for k, v in json.loads(data).items(): if k == "success": for x, y in v.items(): cmdb_data = {} data = y.get('ansible_facts') disk_size = 0 cpu = data['ansible_processor'][-1] for k, v in data['ansible_devices'].items(): if k[0:2] in ['sd', 'hd', 'ss', 'vd']: disk = int( (int(v.get('sectors')) * int(v.get('sectorsize'))) / 1024 / 1024) disk_size = disk_size + disk cmdb_data['serial'] = data['ansible_product_serial'].split( )[0] cmdb_data['ip'] = x cmdb_data['cpu'] = cpu.replace('@', '') cmdb_data['ram_total'] = int(data['ansible_memtotal_mb']) cmdb_data['disk_total'] = int(disk_size) cmdb_data[ 'system'] = data['ansible_distribution'] + ' ' + data[ 'ansible_distribution_version'] + ' ' + data[ 'ansible_userspace_bits'] cmdb_data['model'] = data['ansible_product_name'].split( ':')[0] cmdb_data['cpu_number'] = data['ansible_processor_count'] cmdb_data['vcpu_number'] = data['ansible_processor_vcpus'] cmdb_data['cpu_core'] = data['ansible_processor_cores'] cmdb_data['hostname'] = data['ansible_hostname'] cmdb_data['kernel'] = str(data['ansible_kernel']) cmdb_data['manufacturer'] = data['ansible_system_vendor'] if data['ansible_selinux']: cmdb_data['selinux'] = data['ansible_selinux'].get( 'status') else: cmdb_data['selinux'] = 'disabled' cmdb_data['swap'] = int(data['ansible_swaptotal_mb']) #获取网卡资源 nks = [] for nk in data.keys(): if re.match(r"^ansible_(eth|bind|eno|ens|em)\d+?", nk): device = data.get(nk).get('device') try: address = data.get(nk).get('ipv4').get( 'address') except: address = 'unkown' macaddress = data.get(nk).get('macaddress') module = data.get(nk).get('module') mtu = data.get(nk).get('mtu') if data.get(nk).get('active'): active = 1 else: active = 0 nks.append({ "device": device, "address": address, "macaddress": macaddress, "module": module, "mtu": mtu, "active": active }) cmdb_data['status'] = 0 cmdb_data['nks'] = nks data_list.append(cmdb_data) elif k == "unreachable": for x, y in v.items(): cmdb_data = {} cmdb_data['status'] = 1 cmdb_data['ip'] = x data_list.append(cmdb_data) if data_list: return data_list else: return False def handle_cmdb_crawHw_data(self, data): data_list = [] for k, v in json.loads(data).items(): if k == "success": for x, y in v.items(): cmdb_data = {} cmdb_data['ip'] = x data = y.get('ansible_facts') cmdb_data['mem_info'] = data.get( 'ansible_mem_detailed_info') cmdb_data['disk_info'] = data.get( 'ansible_disk_detailed_info') data_list.append(cmdb_data) if data_list: return data_list else: return False def handle_model_data(self, data, module_name, module_args=None): '''处理ANSIBLE 模块输出内容''' module_data = json.loads(data) failed = module_data.get('failed') success = module_data.get('success') unreachable = module_data.get('unreachable') data_list = [] if module_name == "raw": if failed: for x, y in failed.items(): data = {} data['ip'] = x try: data['msg'] = y.get('stdout').replace( '\t\t', '<br>').replace('\r\n', '<br>').replace('\t', '<br>') except: data['msg'] = None if y.get('rc') == 0: data['status'] = 'succeed' else: data['status'] = 'failed' data_list.append(data) elif success: for x, y in success.items(): data = {} data['ip'] = x try: data['msg'] = y.get('stdout').replace( '\t\t', '<br>').replace('\r\n', '<br>').replace('\t', '<br>') except: data['msg'] = None if y.get('rc') == 0: data['status'] = 'succeed' else: data['status'] = 'failed' data_list.append(data) elif module_name == "ping": if success: for x, y in success.items(): data = {} data['ip'] = x if y.get('ping'): data['msg'] = y.get('ping') data['status'] = 'succeed' data_list.append(data) else: if success: for x, y in success.items(): data = {} data['ip'] = x if y.get('invocation'): data['msg'] = "Ansible %s with %s execute success." % ( module_name, module_args) data['status'] = 'succeed' data_list.append(data) elif failed: for x, y in failed.items(): data = {} data['ip'] = x data['msg'] = y.get('msg') data['status'] = 'failed' data_list.append(data) if unreachable: for x, y in unreachable.items(): data = {} data['ip'] = x data['msg'] = y.get('msg') data['status'] = 'failed' data_list.append(data) if data_list: return data_list else: return False
def exec_ansible_api(self, playbooks_file): variable_manager = VariableManager() loader = DataLoader() ds = loader.load_from_file(playbooks_file) Options = namedtuple('Options', [ 'connection', 'module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check' ]) options = Options(connection='ssh', module_path=None, forks=100, remote_user='******', private_key_file='id_rsa', ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None, become_user=None, verbosity=None, check=False) # create inventory and pass to var manager inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=Global.inventory) variable_manager.set_inventory(inventory) # Currently we are limiting to one playbook play_source = ds[0] play = Play().load(play_source, variable_manager=variable_manager, loader=loader) tqm = None try: tqm = TaskQueueManager(inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=None, stdout_callback=Global.display) result = tqm.run(play) # Exit gdeploy in case of errors and user has explicitly set # not to ignore errors if result != 0 and Global.ignore_errors != 'yes': msg = "Error while executing playbook %s, exiting"\ %playbooks_file print msg Global.logger.error(msg) self.cleanup_and_quit(1) elif result != 0 and Global.ignore_errors == 'yes': msg = "Error while executing playbook %s, ignoring errors..."\ %playbooks_file Global.logger.error(msg) print msg except AnsibleError, e: print "%s" % e
def __init__(self, playbook, become_pass, verbosity=0): self.options = Options() self.options.verbosity = verbosity self.display = Display() self.display.verbosity = self.options.verbosity playbook_executor.verbosity = self.options.verbosity passwords = {'become_pass': become_pass} self.loader = DataLoader() self.loader.set_vault_password(os.environ['VAULT_PASS']) self.variable_manager = VariableManager() self.variable_manager.extra_vars = self.run_data Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check']) # initialize needed objects variable_manager = VariableManager() loader = DataLoader() options = Options(connection='local', module_path='/path/to/mymodules', forks=100, become=None, become_method=None, become_user=None, check=False) passwords = dict(vault_pass='******') # Instantiate our ResultCallback for handling results as they come in results_callback = ResultCallback()
metavar="MULTIINSTANCE_URL") (options, args) = parser.parse_args() checkRequiredArguments(options, parser) # read instance data instance_file = options.instance_file with open(instance_file, 'r') as fh: instance_data = json.load(fh) Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check']) # initialize needed objects variable_manager = VariableManager() instance_number = instance_data['number'] variables = {'openslides_secure_key': random_string(50), 'openslides_instance_db_password': random_string(12), 'openslides_instance_systemd_port': str(23232 + instance_number * 2), 'openslides_instance_port': str(23232 + (instance_number * 2 + 1)), 'postgres_host': 'localhost', 'postgres_user': '******', 'postgres_password': options.postgres_password, 'upload_dir': options.upload_dir, 'openslides_instance_file': instance_file, 'openslides_multiinstance_api_url': options.multiinstance_url} for instance_var in instance_data.keys(): variables['openslides_instance_' + instance_var] = instance_data[instance_var]
def run_playbook(self, playbook_file, playbook_variables=None, option_overrides=None): """ Run a playbook from file with the variables provided. :param playbook_file: the location of the playbook :param playbook_variables: extra variables for the playbook """ # on the first run, the playbook that initializes the # inventory will not have yet run, so we should ensure # that the directory for it exists, at the least, so # ansible doesn't complain if not exists(self.host_list): makedirs(self.host_list) variable_manager = VariableManager() data_loader = DataLoader() inventory = Inventory( loader=data_loader, variable_manager=variable_manager, host_list=self.host_list, ) variable_manager.set_inventory(inventory) variable_manager.extra_vars = playbook_variables # until Ansible's display logic is less hack-ey we need # to mutate their global in __main__ options = self.generate_playbook_options(playbook_file) display.verbosity = options.verbosity # we want to log everything so we can parse output # nicely later from files and don't miss output due # to the pretty printer, if it's on from ..oct import __file__ as root_dir callback_loader.add_directory( join(dirname(root_dir), 'ansible', 'oct', 'callback_plugins')) constants.DEFAULT_CALLBACK_WHITELIST = [ 'log_results', 'generate_junit' ] environ['ANSIBLE_LOG_ROOT_PATH'] = self.log_directory if options.verbosity == 1: # if the user has not asked for verbose output # we will use our pretty printer for progress # on the TTY constants.DEFAULT_STDOUT_CALLBACK = 'pretty_progress' # we really don't want output in std{err,out} # that we didn't put there, but some code in # Ansible calls directly to the Display, not # through a callback, so we need to ensure # that those raw calls don't go to stdout display.display = partial(display.display, log_only=True) else: # if the user asks for verbose output, we want # to give them nicer output than the default # plugin, anyway constants.DEFAULT_STDOUT_CALLBACK = 'default_with_output_lists' if option_overrides: for key in option_overrides: if hasattr(options, key): setattr(options, key, option_overrides[key]) result = PlaybookExecutor( playbooks=[playbook_file], inventory=inventory, variable_manager=variable_manager, loader=data_loader, options=options, passwords=None, ).run() if result != TaskQueueManager.RUN_OK: # TODO: this seems bad, but can we discover the thread here to join() it? sleep(0.2) raise ClickException('\nPlaybook execution failed with code ' + str(result))
class MyRunner(object): """ This is a General object for parallel execute modules. """ def __init__(self, resource, *args, **kwargs): self.resource = resource self.inventory = None self.variable_manager = None self.loader = None self.options = None self.passwords = None self.callback = None self.__initializeData() self.results_raw = {} def __initializeData(self): """ 初始化ansible """ Options = namedtuple('Options', [ 'connection', 'module_path', 'forks', 'timeout', 'remote_user', 'ask_pass', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'ask_value_pass', 'verbosity', 'check', 'listhosts', 'listtasks', 'listtags', 'syntax' ]) # initialize needed objects self.variable_manager = VariableManager() self.loader = DataLoader() self.options = Options(connection='smart', module_path='/usr/share/ansible', forks=100, timeout=10, remote_user='******', ask_pass=False, private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None, become_user='******', ask_value_pass=False, verbosity=None, check=False, listhosts=False, listtasks=False, listtags=False, syntax=False) self.passwords = dict(sshpass=None, becomepass=None) self.inventory = MyInventory(self.resource, self.loader, self.variable_manager).inventory self.variable_manager.set_inventory(self.inventory) def run( self, host_list, module_name, module_args, ): """ run module from andible ad-hoc. module_name: ansible module_name module_args: ansible module args """ # create play with tasks play_source = dict( name="Ansible Play", hosts=host_list, gather_facts='no', tasks=[dict(action=dict(module=module_name, args=module_args))]) play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader) # actually run it tqm = None self.callback = ResultsCollector() try: tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, ) tqm._stdout_callback = self.callback result = tqm.run(play) finally: if tqm is not None: tqm.cleanup() def run_playbook(self, host_list, role_name, role_uuid, temp_param): """ run ansible palybook """ try: self.callback = ResultsCollector() filenames = [BASE_DIR + '/handlers/ansible/v1_0/sudoers.yml'] logger.info('ymal file path:%s' % filenames) template_file = TEMPLATE_DIR if not os.path.exists(template_file): logger.error('%s 路径不存在 ' % template_file) sys.exit() extra_vars = {} host_list_str = ','.join([item for item in host_list]) extra_vars['host_list'] = host_list_str extra_vars['username'] = role_name extra_vars['template_dir'] = template_file extra_vars['command_list'] = temp_param.get('cmdList') extra_vars['role_uuid'] = 'role-%s' % role_uuid self.variable_manager.extra_vars = extra_vars logger.info('playbook 额外参数:%s' % self.variable_manager.extra_vars) # actually run it executor = PlaybookExecutor( playbooks=filenames, inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, ) executor._tqm._stdout_callback = self.callback executor.run() except Exception as e: logger.error("run_playbook:%s" % e) def get_result(self): self.results_raw = {'success': {}, 'failed': {}, 'unreachable': {}} for host, result in self.callback.host_ok.items(): logger.info('ansible run host_ok :%s' % result._result) self.results_raw['success'][host] = result._result for host, result in self.callback.host_failed.items(): logger.info('ansible run host_failed :%s' % result._result) if 'msg' in result._result: self.results_raw['failed'][host] = result._result['msg'] else: self.results_raw['failed'][host] = result._result['stderr'] for host, result in self.callback.host_unreachable.items(): logger.info('ansible run host_unreachable :%s' % result._result) if 'msg' in result._result: self.results_raw['unreachable'][host] = result._result['msg'] else: self.results_raw['unreachable'][host] = result._result[ 'stderr'] logger.debug("Ansible执行结果集:%s" % self.results_raw) return self.results_raw
def run_ansible(self, inv=[]): Options = namedtuple('Options', [ 'connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check' ]) # initialize needed objects variable_manager = VariableManager() loader = DataLoader() options = Options(connection='ssh', module_path='', forks=100, become=False, become_method="sudo", become_user="******", check=False) # Instantiate our ResultCallback for handling results as they come in results_callback = ResultCallback() # create inventory and pass to var manager inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=inv) variable_manager.set_inventory(inventory) # create play with tasks play_source = dict( name="Inventory Play", hosts='all', gather_facts='yes', tasks=[ dict(action=dict( module='shell', args= "/usr/sbin/dmidecode | grep -i 'UUID:' | sed 's/[\t ]*UUID: //gI'" ), become=True, register='dmidecode_out'), ]) play = Play().load(play_source, variable_manager=variable_manager, loader=loader) # actually run it tqm = None try: tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=None, stdout_callback= results_callback, # Use our custom callback instead of the ``default`` callback plugin ) result = tqm.run(play) except Exception as e: pass finally: if tqm is not None: tqm.cleanup() return result
def run(self): ''' use Runner lib to do SSH things ''' super(AdHocCLI, self).run() # only thing left should be host pattern pattern = self.args[0] # ignore connection password cause we are local if self.options.connection == "local": self.options.ask_pass = False sshpass = None becomepass = None vault_pass = None self.normalize_become_options() (sshpass, becomepass) = self.ask_passwords() passwords = {'conn_pass': sshpass, 'become_pass': becomepass} if self.options.vault_password_file: # read vault_pass from a file vault_pass = CLI.read_vault_password_file( self.options.vault_password_file) elif self.options.ask_vault_pass: vault_pass = self.ask_vault_passwords(ask_vault_pass=True, ask_new_vault_pass=False, confirm_new=False)[0] loader = DataLoader(vault_password=vault_pass) variable_manager = VariableManager() variable_manager.extra_vars = load_extra_vars(loader=loader, options=self.options) inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=self.options.inventory) variable_manager.set_inventory(inventory) hosts = inventory.list_hosts(pattern) if len(hosts) == 0: self.display.warning( "provided hosts list is empty, only localhost is available") if self.options.listhosts: for host in hosts: self.display.display(' %s' % host) return 0 if self.options.module_name in C.MODULE_REQUIRE_ARGS and not self.options.module_args: raise AnsibleOptionsError("No argument passed to %s module" % self.options.module_name) #TODO: implement async support #if self.options.seconds: # callbacks.display("background launch...\n\n", color='cyan') # results, poller = runner.run_async(self.options.seconds) # results = self.poll_while_needed(poller) #else: # results = runner.run() # create a pseudo-play to execute the specified module via a single task play_ds = self._play_ds(pattern) play = Play().load(play_ds, variable_manager=variable_manager, loader=loader) if self.options.one_line: cb = 'oneline' else: cb = 'minimal' # now create a task queue manager to execute the play self._tqm = None try: self._tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, display=self.display, options=self.options, passwords=passwords, stdout_callback=cb, ) result = self._tqm.run(play) finally: if self._tqm: self._tqm.cleanup() return result
def test_variable_manager_group_vars_file(self): fake_loader = DictDataLoader({ "group_vars/all.yml": """ foo: bar """, "group_vars/somegroup.yml": """ bam: baz """, "other_path/group_vars/somegroup.yml": """ baa: bat """, "group_vars/some.group.yml": """ group_with_dots: true """, }) v = VariableManager() v.add_group_vars_file("group_vars/all.yml", loader=fake_loader) v.add_group_vars_file("group_vars/somegroup.yml", loader=fake_loader) v.add_group_vars_file("other_path/group_vars/somegroup.yml", loader=fake_loader) self.assertIn("somegroup", v._group_vars_files) self.assertEqual(v._group_vars_files["all"], [dict(foo="bar")]) self.assertEqual(v._group_vars_files["somegroup"], [dict(bam="baz"), dict(baa="bat")]) mock_group = MagicMock() mock_group.name = "somegroup" mock_group.get_ancestors.return_value = () mock_group.get_vars.return_value = dict() mock_host = MagicMock() mock_host.get_name.return_value = "hostname1" mock_host.get_vars.return_value = dict() mock_host.get_groups.return_value = (mock_group, ) mock_host.get_group_vars.return_value = dict() vars = v.get_vars(loader=fake_loader, host=mock_host, use_cache=False) self.assertEqual(vars.get("foo"), "bar") self.assertEqual(vars.get("baa"), "bat") v.add_group_vars_file("group_vars/some.group", loader=fake_loader) self.assertEqual(v._group_vars_files["some.group"], [dict(group_with_dots=True)])
def __init__(self, resource, *args, **kwargs): self.resource = resource self.loader = DataLoader() self.variable_manager = VariableManager() self.inventory = self._set_inventory(resource) self.results_raw = {}
from ansible.vars import VariableManager from ansible.inventory import Inventory from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager from ansible.executor.playbook_executor import PlaybookExecutor from ansible.plugins import callback_loader from ansible.plugins.callback import CallbackBase #import os #import logging Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check']) options = Options(connection='smart', module_path=None, forks=10, become=None, become_method=None, become_user=None, check=False) loader = DataLoader() variable_manager = VariableManager() inventory = Inventory(loader=loader, variable_manager=variable_manager) variable_manager.set_inventory(inventory) #get result output class ResultsCollector(CallbackBase): def __init__(self, *args, **kwargs): super(ResultsCollector, self).__init__(*args, **kwargs) self.host_ok = [] self.host_unreachable = [] self.host_failed = [] def v2_runner_on_unreachable(self, result, ignore_errors=False): name = result._host.get_name() task = result._task.get_name() print "ansible unreachable, name:%s, task:%s " % (nova, task)
def run(self): super(ConsoleCLI, self).run() sshpass = None becomepass = None vault_pass = None # hosts if len(self.args) != 1: self.pattern = 'all' else: self.pattern = self.args[0] self.options.cwd = self.pattern # dynamically add modules as commands self.modules = self.list_modules() for module in self.modules: setattr( self, 'do_' + module, lambda arg, module=module: self.default(module + ' ' + arg)) setattr(self, 'help_' + module, lambda module=module: self.helpdefault(module)) self.normalize_become_options() (sshpass, becomepass) = self.ask_passwords() self.passwords = {'conn_pass': sshpass, 'become_pass': becomepass} self.loader = DataLoader() if self.options.vault_password_file: # read vault_pass from a file vault_pass = CLI.read_vault_password_file( self.options.vault_password_file, loader=self.loader) self.loader.set_vault_password(vault_pass) elif self.options.ask_vault_pass: vault_pass = self.ask_vault_passwords()[0] self.loader.set_vault_password(vault_pass) self.variable_manager = VariableManager() self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=self.options.inventory) self.variable_manager.set_inventory(self.inventory) if len(self.inventory.list_hosts(self.pattern)) == 0: # Empty inventory display.warning( "provided hosts list is empty, only localhost is available") self.inventory.subset(self.options.subset) self.groups = self.inventory.list_groups() self.hosts = [x.name for x in self.inventory.list_hosts(self.pattern)] # This hack is to work around readline issues on a mac: # http://stackoverflow.com/a/7116997/541202 if 'libedit' in readline.__doc__: readline.parse_and_bind("bind ^I rl_complete") else: readline.parse_and_bind("tab: complete") histfile = os.path.join(os.path.expanduser("~"), ".ansible-console_history") try: readline.read_history_file(histfile) except IOError: pass atexit.register(readline.write_history_file, histfile) self.set_prompt() self.cmdloop()
def __init__(self, hostnames, playbook, private_key_file, run_data, become_pass, verbosity=0): self.run_data = run_data self.options = Options() self.options.private_key_file = private_key_file self.options.verbosity = verbosity self.options.connection = 'ssh' # Need a connection type "smart" or "ssh" self.options.become = True self.options.become_method = 'sudo' self.options.become_user = '******' # Set global verbosity self.display = Display() self.display.verbosity = self.options.verbosity # Executor appears to have it's own # verbosity object/setting as well playbook_executor.verbosity = self.options.verbosity # Become Pass Needed if not logging in as user root passwords = {'become_pass': become_pass} # Gets data from YAML/JSON files self.loader = DataLoader() self.loader.set_vault_password(os.environ['VAULT_PASS']) # All the variables from all the various places self.variable_manager = VariableManager() self.variable_manager.extra_vars = self.run_data # Parse hosts, I haven't found a good way to # pass hosts in without using a parsed template :( # (Maybe you know how?) self.hosts = NamedTemporaryFile(delete=False) self.hosts.write("""[run_hosts] %s""" % hostnames) self.hosts.close() # This was my attempt to pass in hosts directly. # # Also Note: In py2.7, "isinstance(foo, str)" is valid for # latin chars only. Luckily, hostnames are # ascii-only, which overlaps latin charset ## if isinstance(hostnames, str): ## hostnames = {"customers": {"hosts": [hostnames]}} # Set inventory, using most of above objects self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=self.hosts.name) self.variable_manager.set_inventory(self.inventory) # Playbook to run. Assumes it is # local to this python file pb_dir = os.path.dirname(__file__) playbook = "%s/%s" % (pb_dir, playbook) # Setup playbook executor, but don't run until run() called self.pbex = playbook_executor.PlaybookExecutor( playbooks=[playbook], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=passwords)
class AdHocRunner(object): """ ADHoc接口 """ Options = namedtuple("Options", [ 'connection', 'module_path', 'private_key_file', "remote_user", 'timeout', 'forks', 'become', 'become_method', 'become_user', 'check', 'extra_vars', ] ) results_callback_class = AdHocResultCallback def __init__(self, hosts=c.DEFAULT_HOST_LIST, forks=c.DEFAULT_FORKS, # 5 timeout=c.DEFAULT_TIMEOUT, # SSH timeout = 10s remote_user=c.DEFAULT_REMOTE_USER, # root module_path=None, # dirs of custome modules connection_type="smart", become=None, become_method=None, become_user=None, check=False, passwords=None, extra_vars=None, private_key_file=None, gather_facts='no'): self.pattern = '' self.variable_manager = VariableManager() self.loader = DataLoader() self.gather_facts = gather_facts self.results_callback = AdHocRunner.results_callback_class() self.options = self.Options( connection=connection_type, timeout=timeout, module_path=module_path, forks=forks, become=become, become_method=become_method, become_user=become_user, check=check, remote_user=remote_user, extra_vars=extra_vars or [], private_key_file=private_key_file, ) self.variable_manager.extra_vars = load_extra_vars(self.loader, options=self.options) self.variable_manager.options_vars = load_options_vars(self.options) self.passwords = passwords or {} self.inventory = JMSInventory(hosts) self.variable_manager.set_inventory(self.inventory) self.tasks = [] self.play_source = None self.play = None self.runner = None @staticmethod def check_module_args(module_name, module_args=''): if module_name in c.MODULE_REQUIRE_ARGS and not module_args: err = "No argument passed to '%s' module." % module_name print(err) return False return True def run(self, task_tuple, pattern='all', task_name='Ansible Ad-hoc'): """ :param task_tuple: (('shell', 'ls'), ('ping', '')) :param pattern: :param task_name: :return: """ for module, args in task_tuple: if not self.check_module_args(module, args): return self.tasks.append( dict(action=dict( module=module, args=args, )) ) self.play_source = dict( name=task_name, hosts=pattern, gather_facts=self.gather_facts, tasks=self.tasks ) self.play = Play().load( self.play_source, variable_manager=self.variable_manager, loader=self.loader, ) self.runner = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, stdout_callback=self.results_callback, ) if not self.inventory.list_hosts("all"): raise AnsibleError("Inventory is empty.") if not self.inventory.list_hosts(self.pattern): raise AnsibleError( "pattern: %s dose not match any hosts." % self.pattern) try: self.runner.run(self.play) except Exception as e: logger.warning(e) else: # logger.debug(self.results_callback.result_q) return self.results_callback.result_q finally: if self.runner: self.runner.cleanup() if self.loader: self.loader.cleanup_all_tmp_files() def clean_result(self): """ :return: { "success": ['hostname',], "failed": [('hostname', 'msg'), {}], } """ result = {'success': [], 'failed': []} for host in self.results_callback.result_q['contacted']: result['success'].append(host) for host, msgs in self.results_callback.result_q['dark'].items(): msg = '\n'.join(['{} {}: {}'.format( msg.get('module_stdout', ''), msg.get('invocation', {}).get('module_name'), msg.get('msg', '')) for msg in msgs]) result['failed'].append((host, msg)) return result
# Email: [email protected] # # this is the Interface package of Ansible2 API # import json from ansible.plugins.callback import CallbackBase from ansible.parsing.dataloader import DataLoader from ansible.vars import VariableManager from ansible.inventory import Inventory from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager from ansible.executor.playbook_executor import PlaybookExecutor loader = DataLoader() # 用来加载解析yaml文件或JSON内容,并且支持vault的解密 variable_manager = VariableManager() # 管理变量的类,包括主机,组,扩展等变量,之前版本是在 inventory 中的 inventory = Inventory(loader=loader, variable_manager=variable_manager) variable_manager.set_inventory(inventory) # 根据 inventory 加载对应变量 class Options(object): ''' 这是一个公共的类,因为ad-hoc和playbook都需要一个options参数 并且所需要拥有不同的属性,但是大部分属性都可以返回None或False 因此用这样的一个类来省去初始化大一堆的空值的属性 ''' def __init__(self): self.connection = "local" self.forks = 1 self.check = False
class PlayBookRunner(object): """ 用于执行AnsiblePlaybook的接口.简化Playbook对象的使用. """ Options = namedtuple('Options', [ 'listtags', 'listtasks', 'listhosts', 'syntax', 'connection', 'module_path', 'forks', 'remote_user', 'private_key_file', 'timeout', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check', 'extra_vars']) def __init__(self, hosts=None, playbook_path=None, forks=c.DEFAULT_FORKS, listtags=False, listtasks=False, listhosts=False, syntax=False, module_path=None, remote_user='******', timeout=c.DEFAULT_TIMEOUT, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True, become_method=None, become_user="******", verbosity=None, extra_vars=None, connection_type="ssh", passwords=None, private_key_file=None, check=False): c.RETRY_FILES_ENABLED = False self.callbackmodule = PlaybookResultCallBack() if playbook_path is None or not os.path.exists(playbook_path): raise AnsibleError( "Not Found the playbook file: %s." % playbook_path) self.playbook_path = playbook_path self.loader = DataLoader() self.variable_manager = VariableManager() self.passwords = passwords or {} self.inventory = JMSInventory(hosts) self.options = self.Options( listtags=listtags, listtasks=listtasks, listhosts=listhosts, syntax=syntax, timeout=timeout, connection=connection_type, module_path=module_path, forks=forks, remote_user=remote_user, private_key_file=private_key_file, ssh_common_args=ssh_common_args or "", ssh_extra_args=ssh_extra_args or "", sftp_extra_args=sftp_extra_args, scp_extra_args=scp_extra_args, become=become, become_method=become_method, become_user=become_user, verbosity=verbosity, extra_vars=extra_vars or [], check=check ) self.variable_manager.extra_vars = load_extra_vars(loader=self.loader, options=self.options) self.variable_manager.options_vars = load_options_vars(self.options) self.variable_manager.set_inventory(self.inventory) # 初始化playbook的executor self.runner = PlaybookExecutor( playbooks=[self.playbook_path], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords) if self.runner._tqm: self.runner._tqm._stdout_callback = self.callbackmodule def run(self): if not self.inventory.list_hosts('all'): raise AnsibleError('Inventory is empty') self.runner.run() self.runner._tqm.cleanup() return self.callbackmodule.output
def launch_ansible_playbook(list_ip, playbook, extra_variable=None): """ Applies an Ansible playbook :param list_ip: the ips :param playbook: the playboos to be applied :param extra_variable: dict of the playbook variables to be applied """ if not os.path.isfile(playbook): raise Exception('Requested playbook is not found - ' + playbook) if not playbook: logger.warn('Unable to find playbook - ' + playbook) variable_manager = VariableManager() if extra_variable is not None: variable_manager.extra_vars = extra_variable logger.info(extra_variable) else: logger.info('NO EXTRA VARS') loader = DataLoader() inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=list_ip) variable_manager.set_inventory(inventory) options = namedtuple('Options', [ 'listtags', 'listtasks', 'listhosts', 'syntax', 'connection', 'module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check', 'sftp_extra_args', 'scp_extra_args' ]) ansible_opts = options(listtags=None, listtasks=None, listhosts=None, syntax=False, connection='ssh', module_path=None, forks=100, remote_user=None, private_key_file=None, ssh_common_args=None, ssh_extra_args=None, become=True, become_method='sudo', become_user=None, verbosity=11111, check=False, sftp_extra_args=None, scp_extra_args=None) logger.debug('Setting up Ansible Playbook Executor for playbook - ' + playbook) executor = PlaybookExecutor(playbooks=[playbook], inventory=inventory, variable_manager=variable_manager, loader=loader, options=ansible_opts, passwords=None) logger.debug('Executing Ansible Playbook - ' + playbook) ret = executor.run() return ret
def __init__(self, hosts=None, playbook_path=None, forks=c.DEFAULT_FORKS, listtags=False, listtasks=False, listhosts=False, syntax=False, module_path=None, remote_user='******', timeout=c.DEFAULT_TIMEOUT, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True, become_method=None, become_user="******", verbosity=None, extra_vars=None, connection_type="ssh", passwords=None, private_key_file=None, check=False): c.RETRY_FILES_ENABLED = False self.callbackmodule = PlaybookResultCallBack() if playbook_path is None or not os.path.exists(playbook_path): raise AnsibleError( "Not Found the playbook file: %s." % playbook_path) self.playbook_path = playbook_path self.loader = DataLoader() self.variable_manager = VariableManager() self.passwords = passwords or {} self.inventory = JMSInventory(hosts) self.options = self.Options( listtags=listtags, listtasks=listtasks, listhosts=listhosts, syntax=syntax, timeout=timeout, connection=connection_type, module_path=module_path, forks=forks, remote_user=remote_user, private_key_file=private_key_file, ssh_common_args=ssh_common_args or "", ssh_extra_args=ssh_extra_args or "", sftp_extra_args=sftp_extra_args, scp_extra_args=scp_extra_args, become=become, become_method=become_method, become_user=become_user, verbosity=verbosity, extra_vars=extra_vars or [], check=check ) self.variable_manager.extra_vars = load_extra_vars(loader=self.loader, options=self.options) self.variable_manager.options_vars = load_options_vars(self.options) self.variable_manager.set_inventory(self.inventory) # 初始化playbook的executor self.runner = PlaybookExecutor( playbooks=[self.playbook_path], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords) if self.runner._tqm: self.runner._tqm._stdout_callback = self.callbackmodule
class AnsibleRunner(object): def __init__(self, vault_pass='', connection='local', module_path='', forks=100, become=None, become_method=None, become_user=None, check=False): """ 初始化ansible信息 """ Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check'] ) self.options = Options(connection=connection, module_path=module_path, forks=forks, become=become, become_method=become_method, become_user=become_user, check=check ) self.variable_manager = VariableManager() self.loader = DataLoader() self.passwords = dict(vault_pass=vault_pass) def init_inventory(self, host_list='localhost'): # 创建inventory # 把inventory传递给variable_manager管理 self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=host_list ) self.variable_manager.set_inventory(self.inventory) def init_play(self, hosts='localhost', module='ping', args=''): # # 创建playbook # # create play with tasks # self.play_source = dict( name = "Ansible Play", hosts = hosts, gather_facts = 'no', tasks = [ dict(action=dict(module=module, args=args), register='task_out'), dict(action=dict(module='debug', args=dict(msg='{{task_out.stdout}}'))) ] ) self.play = Play().load(self.play_source, variable_manager=self.variable_manager, loader=self.loader ) def run_it(self): # # 结果回调类实例化 # # Instantiate our ResultCallback for handling results as they come in # results_callback = ResultCallback() # # 通过TaskQueueManager().run()执行ansible,具体语法如下 # "TaskQueueManager( # 指定inventory,loader,variable_manager, # options,passwords, stdout_callback # ).run(play)" # # actually run it # tqm = None try: tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, stdout_callback=results_callback, ) result = tqm.run(self.play) finally: if tqm is not None: tqm.cleanup() return result
class MyWSRunner(MyRunner): """ This is a General object for parallel execute modules. """ def __init__(self, resource, *args, **kwargs): self.resource = resource self.loader = DataLoader() self.variable_manager = VariableManager() self.inventory = self._set_inventory(resource) self.results_raw = {} def _set_inventory(self, resource): # initialize needed objects inventory = MyInventory(resource, self.loader, self.variable_manager).inventory self.variable_manager.set_inventory(inventory) return inventory def run( self, host_list, module_name, module_args, ): """ run module from andible ad-hoc. module_name: ansible module_name module_args: ansible module args """ self.results_raw = {'success': {}, 'failed': {}, 'unreachable': {}} Options = namedtuple('Options', [ 'connection', 'module_path', 'forks', 'timeout', 'remote_user', 'ask_pass', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'ask_value_pass', 'verbosity', 'check' ]) options = Options(connection='smart', module_path='/usr/share/ansible', forks=100, timeout=10, remote_user='******', ask_pass=False, private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None, become_user='******', ask_value_pass=False, verbosity=None, check=False) passwords = dict(sshpass=None, becomepass=None) # create play with tasks play_source = dict( name="Ansible Play", hosts=host_list, gather_facts='no', tasks=[dict(action=dict(module=module_name, args=module_args))]) play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader) # actually run it tqm = None callback = ResultsCollector() try: tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=options, passwords=passwords, ) tqm._stdout_callback = callback result = tqm.run(play) finally: if tqm is not None: tqm.cleanup() for host, result in callback.host_ok.items(): self.results_raw['success'][host] = result._result.get( 'stdout') + result._result.get('stderr') for host, result in callback.host_failed.items(): self.results_raw['failed'][host] = result._result.get( 'stdout') + result._result.get('stderr') for host, result in callback.host_unreachable.items(): self.results_raw['unreachable'][host] = result._result['msg'] logger.info(self.results_raw) return self.results_raw
class ConsoleCLI(CLI, cmd.Cmd): modules = [] def __init__(self, args): super(ConsoleCLI, self).__init__(args) self.intro = 'Welcome to the ansible console.\nType help or ? to list commands.\n' self.groups = [] self.hosts = [] self.pattern = None self.variable_manager = None self.loader = None self.passwords = dict() self.modules = None cmd.Cmd.__init__(self) def parse(self): self.parser = CLI.base_parser( usage='%prog <host-pattern> [options]', runas_opts=True, inventory_opts=True, connect_opts=True, check_opts=True, vault_opts=True, fork_opts=True, module_opts=True, ) # options unique to shell self.parser.add_option( '--step', dest='step', action='store_true', help="one-step-at-a-time: confirm each task before running") self.parser.set_defaults(cwd='*') self.options, self.args = self.parser.parse_args(self.args[1:]) display.verbosity = self.options.verbosity self.validate_conflicts(runas_opts=True, vault_opts=True, fork_opts=True) return True def get_names(self): return dir(self) def cmdloop(self): try: cmd.Cmd.cmdloop(self) except KeyboardInterrupt: self.do_exit(self) def set_prompt(self): login_user = self.options.remote_user or getpass.getuser() self.selected = self.inventory.list_hosts(self.options.cwd) prompt = "%s@%s (%d)[f:%s]" % (login_user, self.options.cwd, len(self.selected), self.options.forks) if self.options.become and self.options.become_user in [None, 'root']: prompt += "# " color = C.COLOR_ERROR else: prompt += "$ " color = C.COLOR_HIGHLIGHT self.prompt = stringc(prompt, color) def list_modules(self): modules = set() if self.options.module_path is not None: for i in self.options.module_path.split(os.pathsep): module_loader.add_directory(i) module_paths = module_loader._get_paths() for path in module_paths: if path is not None: modules.update(self._find_modules_in_path(path)) return modules def _find_modules_in_path(self, path): if os.path.isdir(path): for module in os.listdir(path): if module.startswith('.'): continue elif os.path.isdir(module): self._find_modules_in_path(module) elif module.startswith('__'): continue elif any(module.endswith(x) for x in C.BLACKLIST_EXTS): continue elif module in C.IGNORE_FILES: continue elif module.startswith('_'): fullpath = '/'.join([path, module]) if os.path.islink(fullpath): # avoids aliases continue module = module.replace('_', '', 1) module = os.path.splitext(module)[0] # removes the extension yield module def default(self, arg, forceshell=False): """ actually runs modules """ if arg.startswith("#"): return False if not self.options.cwd: display.error("No host found") return False if arg.split()[0] in self.modules: module = arg.split()[0] module_args = ' '.join(arg.split()[1:]) else: module = 'shell' module_args = arg if forceshell is True: module = 'shell' module_args = arg self.options.module_name = module result = None try: check_raw = self.options.module_name in ('command', 'shell', 'script', 'raw') play_ds = dict( name="Ansible Shell", hosts=self.options.cwd, gather_facts='no', tasks=[ dict(action=dict(module=module, args=parse_kv(module_args, check_raw=check_raw))) ]) play = Play().load(play_ds, variable_manager=self.variable_manager, loader=self.loader) except Exception as e: display.error(u"Unable to build command: %s" % to_unicode(e)) return False try: cb = 'minimal' #FIXME: make callbacks configurable # now create a task queue manager to execute the play self._tqm = None try: self._tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, stdout_callback=cb, run_additional_callbacks=C.DEFAULT_LOAD_CALLBACK_PLUGINS, run_tree=False, ) result = self._tqm.run(play) finally: if self._tqm: self._tqm.cleanup() if self.loader: self.loader.cleanup_all_tmp_files() if result is None: display.error("No hosts found") return False except KeyboardInterrupt: display.error('User interrupted execution') return False except Exception as e: display.error(to_unicode(e)) #FIXME: add traceback in very very verbose mode return False def emptyline(self): return def do_shell(self, arg): """ You can run shell commands through the shell module. eg.: shell ps uax | grep java | wc -l shell killall python shell halt -n You can use the ! to force the shell module. eg.: !ps aux | grep java | wc -l """ self.default(arg, True) def do_forks(self, arg): """Set the number of forks""" if not arg: display.display('Usage: forks <number>') return self.options.forks = int(arg) self.set_prompt() do_serial = do_forks def do_verbosity(self, arg): """Set verbosity level""" if not arg: display.display('Usage: verbosity <number>') else: display.verbosity = int(arg) display.v('verbosity level set to %s' % arg) def do_cd(self, arg): """ Change active host/group. You can use hosts patterns as well eg.: cd webservers cd webservers:dbservers cd webservers:!phoenix cd webservers:&staging cd webservers:dbservers:&staging:!phoenix """ if not arg: self.options.cwd = '*' elif arg == '..': try: self.options.cwd = self.inventory.groups_for_host( self.options.cwd)[1].name except Exception: self.options.cwd = '' elif arg in '/*': self.options.cwd = 'all' elif self.inventory.get_hosts(arg): self.options.cwd = arg else: display.display("no host matched") self.set_prompt() def do_list(self, arg): """List the hosts in the current group""" if arg == 'groups': for group in self.groups: display.display(group) else: for host in self.selected: display.display(host.name) def do_become(self, arg): """Toggle whether plays run with become""" if arg: self.options.become_user = arg display.v("become changed to %s" % self.options.become) self.set_prompt() else: display.display("Please specify become value, e.g. `become yes`") def do_remote_user(self, arg): """Given a username, set the remote user plays are run by""" if arg: self.options.remote_user = arg self.set_prompt() else: display.display( "Please specify a remote user, e.g. `remote_user root`") def do_become_user(self, arg): """Given a username, set the user that plays are run by when using become""" if arg: self.options.become_user = arg else: display.display( "Please specify a user, e.g. `become_user jenkins`") display.v("Current user is %s" % self.options.become_user) self.set_prompt() def do_become_method(self, arg): """Given a become_method, set the privilege escalation method when using become""" if arg: self.options.become_method = arg display.v("become_method changed to %s" % self.options.become_method) else: display.display( "Please specify a become_method, e.g. `become_method su`") def do_exit(self, args): """Exits from the console""" sys.stdout.write('\n') return -1 do_EOF = do_exit def helpdefault(self, module_name): if module_name in self.modules: in_path = module_loader.find_plugin(module_name) if in_path: oc, a, _ = module_docs.get_docstring(in_path) if oc: display.display(oc['short_description']) display.display('Parameters:') for opt in oc['options'].keys(): display.display(' ' + stringc(opt, C.COLOR_HIGHLIGHT) + ' ' + oc['options'][opt]['description'][0]) else: display.error('No documentation found for %s.' % module_name) else: display.error( '%s is not a valid command, use ? to list all valid commands.' % module_name) def complete_cd(self, text, line, begidx, endidx): mline = line.partition(' ')[2] offs = len(mline) - len(text) if self.options.cwd in ('all', '*', '\\'): completions = self.hosts + self.groups else: completions = [ x.name for x in self.inventory.list_hosts(self.options.cwd) ] return [ to_str(s)[offs:] for s in completions if to_str(s).startswith(to_str(mline)) ] def completedefault(self, text, line, begidx, endidx): if line.split()[0] in self.modules: mline = line.split(' ')[-1] offs = len(mline) - len(text) completions = self.module_args(line.split()[0]) return [s[offs:] + '=' for s in completions if s.startswith(mline)] def module_args(self, module_name): in_path = module_loader.find_plugin(module_name) oc, a, _ = module_docs.get_docstring(in_path) return oc['options'].keys() def run(self): super(ConsoleCLI, self).run() sshpass = None becomepass = None vault_pass = None # hosts if len(self.args) != 1: self.pattern = 'all' else: self.pattern = self.args[0] self.options.cwd = self.pattern # dynamically add modules as commands self.modules = self.list_modules() for module in self.modules: setattr( self, 'do_' + module, lambda arg, module=module: self.default(module + ' ' + arg)) setattr(self, 'help_' + module, lambda module=module: self.helpdefault(module)) self.normalize_become_options() (sshpass, becomepass) = self.ask_passwords() self.passwords = {'conn_pass': sshpass, 'become_pass': becomepass} self.loader = DataLoader() if self.options.vault_password_file: # read vault_pass from a file vault_pass = CLI.read_vault_password_file( self.options.vault_password_file, loader=self.loader) self.loader.set_vault_password(vault_pass) elif self.options.ask_vault_pass: vault_pass = self.ask_vault_passwords()[0] self.loader.set_vault_password(vault_pass) self.variable_manager = VariableManager() self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=self.options.inventory) self.variable_manager.set_inventory(self.inventory) if len(self.inventory.list_hosts(self.pattern)) == 0: # Empty inventory display.warning( "provided hosts list is empty, only localhost is available") self.inventory.subset(self.options.subset) self.groups = self.inventory.list_groups() self.hosts = [x.name for x in self.inventory.list_hosts(self.pattern)] # This hack is to work around readline issues on a mac: # http://stackoverflow.com/a/7116997/541202 if 'libedit' in readline.__doc__: readline.parse_and_bind("bind ^I rl_complete") else: readline.parse_and_bind("tab: complete") histfile = os.path.join(os.path.expanduser("~"), ".ansible-console_history") try: readline.read_history_file(histfile) except IOError: pass atexit.register(readline.write_history_file, histfile) self.set_prompt() self.cmdloop()
class Runner(object): def __init__(self, hostnames, playbook, private_key_file, run_data, become_pass, verbosity=0): self.run_data = run_data self.options = Options() self.options.private_key_file = private_key_file self.options.verbosity = verbosity self.options.connection = 'ssh' # Need a connection type "smart" or "ssh" self.options.become = True self.options.become_method = 'sudo' self.options.become_user = '******' # Set global verbosity self.display = Display() self.display.verbosity = self.options.verbosity # Executor appears to have it's own # verbosity object/setting as well playbook_executor.verbosity = self.options.verbosity # Become Pass Needed if not logging in as user root passwords = {'become_pass': become_pass} # Gets data from YAML/JSON files self.loader = DataLoader() self.loader.set_vault_password(os.environ['VAULT_PASS']) # All the variables from all the various places self.variable_manager = VariableManager() self.variable_manager.extra_vars = self.run_data # Parse hosts, I haven't found a good way to # pass hosts in without using a parsed template :( # (Maybe you know how?) self.hosts = NamedTemporaryFile(delete=False) self.hosts.write("""[run_hosts] %s""" % hostnames) self.hosts.close() # This was my attempt to pass in hosts directly. # # Also Note: In py2.7, "isinstance(foo, str)" is valid for # latin chars only. Luckily, hostnames are # ascii-only, which overlaps latin charset ## if isinstance(hostnames, str): ## hostnames = {"customers": {"hosts": [hostnames]}} # Set inventory, using most of above objects self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=self.hosts.name) self.variable_manager.set_inventory(self.inventory) # Playbook to run. Assumes it is # local to this python file pb_dir = os.path.dirname(__file__) playbook = "%s/%s" % (pb_dir, playbook) # Setup playbook executor, but don't run until run() called self.pbex = playbook_executor.PlaybookExecutor( playbooks=[playbook], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=passwords) def run(self): # Results of PlaybookExecutor self.pbex.run() stats = self.pbex._tqm._stats # Test if success for record_logs run_success = True hosts = sorted(stats.processed.keys()) for h in hosts: t = stats.summarize(h) if t['unreachable'] > 0 or t['failures'] > 0: run_success = False # Dirty hack to send callback to save logs with data we want # Note that function "record_logs" is one I created and put into # the playbook callback file self.pbex._tqm.send_callback('record_logs', user_id=self.run_data['user_id'], success=run_success) # Remove created temporary files os.remove(self.hosts.name) return stats