def tasktime(): global tn time_current = time.strftime('%A %d %B %Y %H:%M:%S %z') time_elapsed = secondsToStr(time.time() - tn) time_total_elapsed = secondsToStr(time.time() - t0) display(filled('%s (%s)%s%s' % (time_current, time_elapsed, ' ' * 7, time_total_elapsed))) tn = time.time()
def playbook_on_stats(self, stats): timestamp() display(filled("", fchar="=")) print "Slowest 25 Tasks" display(filled("", fchar="=")) # Record the timing of the very last task if self.current is not None: self.stats[self.current] = time.time() - self.stats[self.current] # Sort the tasks by their running time results = sorted( self.stats.items(), key=lambda value: value[1], reverse=True, ) # Just keep the top 10 results = results[:25] # Print the timings for name, elapsed in results: print("{0:-<70}{1:->9}".format( '{0} '.format(name), ' {0:.02f}s'.format(elapsed), )) pass
def print_stats(host, smry): ok = smry['ok'] changed = smry['changed'] unreachable = smry['unreachable'] failures = smry['failures'] if unreachable > 0 or failures > 0: status = stringc("FAILED", "red") else: status = stringc("OK", "bright green") pattern = "\tPlaybook %s, %s, %s, %s, %s" display(pattern % (status, # hostcolor(host, smry, False), colorize('ok', ok, 'bright green'), colorize('changed', changed, 'yellow'), colorize('unreachable', unreachable, 'red'), colorize('failed', failures, 'red')), screen_only=True ) display(pattern % (status, # hostcolor(host, smry, False), colorize('ok', ok, None), colorize('changed', changed, None), colorize('unreachable', unreachable, None), colorize('failed', failures, None)), log_only=True )
def clear_from_cache(cache): corrupt_files = [] for key in cache: try: for host_key in cache[key].keys(): if (host_key.startswith(HLM_PREFIX) and host_key.endswith(".deleted") and cache[key].get(host_key, "False")): hlm_key = host_key.split(".deleted")[0] del cache[key][host_key] if hlm_key in cache[key]: del cache[key][hlm_key] except Exception: display( "Fact cache entry for host %s isn't valid, deleting and failing" % key) # This next bit only works for JSON fact-cache if C.CACHE_PLUGIN == "jsonfile": try: os.remove("%s/%s" % (C.CACHE_PLUGIN_CONNECTION, key)) except (OSError, IOError): display("Couldn't remove cache entry") finally: corrupt_files.append(key) if len(corrupt_files) > 0: files = ', '.join(corrupt_files) raise AnsibleError( "The JSON cache files %s were corrupt, or did not otherwise contain valid JSON data." " They have been removed, so you can re-run your command now." % files)
def clear_from_cache(cache): corrupt_files = [] for key in cache: try: for host_key in cache[key].keys(): if (host_key.startswith(HLM_PREFIX) and host_key.endswith(".deleted") and cache[key].get(host_key, "False")): hlm_key = host_key.split(".deleted")[0] del cache[key][host_key] if hlm_key in cache[key]: del cache[key][hlm_key] except Exception: display("Fact cache entry for host %s isn't valid, deleting and failing" % key) # This next bit only works for JSON fact-cache if C.CACHE_PLUGIN == "jsonfile": try: os.remove("%s/%s" % (C.CACHE_PLUGIN_CONNECTION, key)) except (OSError, IOError): display("Couldn't remove cache entry") finally: corrupt_files.append(key) if len(corrupt_files) > 0: files = ', '.join(corrupt_files) raise AnsibleError("The JSON cache files %s were corrupt, or did not otherwise contain valid JSON data." " They have been removed, so you can re-run your command now." % files)
def on_ok(self, host, res): if 'msg' in res: msg = ": %s" % res.get('msg') if 'item' in res: msg = "%s => item=%s" % (msg, res.get('item')) else: msg = '' try: if self.get_play(): display("\tTask OK: %s%s" % (self.get_name(), msg)) except AttributeError: invocation = res.get('invocation') msg = invocation['module_args'] module_name = invocation['module_name'] #TODO: move this? if module_name == 'git': args = dict() tokens = invocation['module_args'].split() for token in tokens: pair = token.split("=")[:2] args[pair[0]] = pair[1] msg = args['repo'] display("\tTask OK: %s, changed=%s %s" % (module_name, res.get('changed'), msg)) super(BattleschoolRunnerCallbacks, self).on_ok(host, res)
def run(self): stats = callbacks.AggregateStats() runner_cb = callbacks.PlaybookRunnerCallbacks( stats, verbose=utils.VERBOSITY) playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY) pb = ansible.playbook.PlayBook( playbook=self.tmp, inventory=self.conf["inventory"], remote_user=self.conf["remote_user"], callbacks=playbook_cb, runner_callbacks=runner_cb, stats=stats ) pb.run() hosts = sorted(pb.stats.processed.keys()) display(callbacks.banner("‽")) for h in hosts: t = pb.stats.summarize(h) display( "%s : %s %s %s %s" % ( h, t['ok'], t['changed'], t['unreachable'], t['failures'],), screen_only=True )
def run(self): stats = callbacks.AggregateStats() runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY) playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY) pb = ansible.playbook.PlayBook(playbook=self.tmp, inventory=self.conf["inventory"], remote_user=self.conf["remote_user"], callbacks=playbook_cb, runner_callbacks=runner_cb, stats=stats) pb.run() hosts = sorted(pb.stats.processed.keys()) display(callbacks.banner("‽")) for h in hosts: t = pb.stats.summarize(h) display("%s : %s %s %s %s" % ( h, t['ok'], t['changed'], t['unreachable'], t['failures'], ), screen_only=True)
def do_update(self, arg): """update module_args|ma|complex_args|ca ... Partially update module_args or complex_args. * To see how to update module_args, call `help update_module_args|update_ma`. * To see how to update complex_args, call `help update_complex_args|update_ca`. * Use `assign` command to totally replace module_args and/or complex_args. """ if arg is None or arg == '': display('Invalid option. See help for usage.') return arg_split = arg.split(None, 1) args_type = arg_split[0] if len(arg_split) >= 2: rest = arg_split[1] else: rest = '' if args_type == 'module_args' or args_type == 'ma': self.update_module_args(rest) elif args_type == 'complex_args' or args_type == 'ca': self.update_complex_args(rest) else: display('Invalid option. See help for usage.')
def do_assign(self, arg): """assign module_args|ma|complex_args|ca ... Replace module_args or complex_args with new values. * To see how to replace module_args, call `help assign_module_args|assign_ma`. * To see how to replace complex_args, call `help assign_complex_args|assign_ca`. * Use `update` command for partial updates of module_args and/or complex_args. """ if arg is None or arg == '': display('Invalid option. See help for usage.') return arg_split = arg.split(None, 1) args_type = arg_split[0] if len(arg_split) >= 2: rest = arg_split[1] else: rest = '' if args_type == 'module_args' or args_type == 'ma': self.assign_module_args(rest) elif args_type == 'complex_args' or args_type == 'ca': self.assign_complex_args(rest) else: display('Invalid option. See help for usage.')
def do_set(self, arg): """set module_args|complex_args key value Add or update the module's argument. If the first argument is `module_args`, *key* and *value* are added to module_args. If `complex_args`, *key* and *value* are added to complex_args. As the special case, if the *key* is `.`, the entire arguments are replaced with *value*. """ if arg is None or arg == '' or len(arg.split()) < 2: display('Invalid option. See help for usage.') return arg_split = arg.split() target = arg_split[0] key = arg_split[1] index_after_target = arg.find(target) + len(target) index_after_key = arg.find(key, index_after_target) + len(key) value = arg[index_after_key:].strip() if target == 'module_args': self.set_module_args(key, value) elif target == 'complex_args': self.set_complex_args(key, value) else: display('Invalid option. See help for usage.')
def warning(msg): new_msg = "\n[WARNING]: %s" % msg wrapped = textwrap.wrap(new_msg, 79) new_msg = "\n".join(wrapped) + "\n" if new_msg not in warns: display(new_msg, color='bright purple', stderr=True) warns[new_msg] = 1
def on_ok(self, host, res): if "msg" in res: msg = ": %s" % res["msg"] if "item" in res: msg = "%s => item=%s" % (msg, res["item"]) else: msg = "" try: if self.get_play(): display("\tTask OK: %s%s" % (self.get_name(), msg)) except AttributeError: invocation = res["invocation"] msg = invocation["module_args"] module_name = invocation["module_name"] # TODO: move this? if module_name == "git": args = dict() tokens = invocation["module_args"].split() for token in tokens: pair = token.split("=")[:2] args[pair[0]] = pair[1] msg = args["repo"] display("\tTask OK: %s, changed=%s %s" % (module_name, res["changed"], msg)) super(BattleschoolRunnerCallbacks, self).on_ok(host, res)
def print_playbook_results(self): if self.statuscode == 0: display_color = 'green' else: display_color = 'red' display("Ran playbooks {}. \n Total time was {}".format(self.playbooks, datetime.timedelta(seconds=self.runtime)), color=display_color)
def playbook_on_stats(self, stats): tasktime() display(filled("", fchar="=")) timestamp(self) # Sort the tasks by their running time results = sorted( self.stats.items(), key=lambda value: value[1], reverse=True, ) # Just keep the top 20 results = results[:20] # Print the timings for name, elapsed in results: print( "{0:-<70}{1:->9}".format( '{0} '.format(name), ' {0:.02f}s'.format(elapsed), ) ) print ''
def print_playbook_results(self): if self.statuscode == 0: display_color = 'green' else: display_color = 'red' display("Ran playbooks {}. \n Total time was {}".format( self.playbooks, datetime.timedelta(seconds=self.runtime)), color=display_color)
def timestamp(): global tn time_current = time.strftime('%Y-%m-%d %H:%M:%S %Z') time_elapsed = secondsToStr(time.time() - tn) time_total_elapsed = secondsToStr(time.time() - t0) display( filled( 'TIME: [%s | Elapsed: %s Total: %s]' % (time_current, time_elapsed, time_total_elapsed ))) tn = time.time()
def timestamp(): global tn time_current = time.strftime("%A %d %B %Y %H:%M:%S %z") time_elapsed = secondsToStr(time.time() - tn) time_total_elapsed = secondsToStr(time.time() - t0) display(filled("%s (%s)%s%s" % (time_current, time_elapsed, " " * 7, time_total_elapsed))) tn = time.time()
def timestamp(): global tn time_current = time.strftime('%A %d %B %Y %H:%M:%S %z') time_elapsed = secondsToStr(time.time() - tn) time_total_elapsed = secondsToStr(time.time() - t0) display( filled( '%s (%s)%s%s' % (time_current, time_elapsed, ' ' * 7, time_total_elapsed ))) tn = time.time()
def print_var(self, arg): try: value = self.get_value(arg) value_yaml = Interpreter.yaml_format(value) display('%s' % (value_yaml)) except Exception, ex: display('%s' % str(ex))
def assign_module_args(self, arg): """assign module_args|ma [key1=value1 key2=value2 ...] Replace module_args with new key=value pairs. * To replace key: value style arguments, use `assign complex_args`. """ self.task_info.module_args = arg display('assigned: %s' % (self.task_info.module_args))
def print_all_vars(self): for key in self.task_info.vars.iterkeys(): try: value = self.get_value(key) value_yaml = Interpreter.yaml_format(value, 2) display('%s:\n%s' % (key, value_yaml)) except Exception, ex: display('%s' % str(ex))
def timestamp(): global tn time_current = time.strftime('%Y-%m-%d %H:%M:%S %Z') time_elapsed = secondsToStr(time.time() - tn) time_total_elapsed = secondsToStr(time.time() - t0) display( filled('TIME: [%s | Elapsed: %s Total: %s]' % (time_current, time_elapsed, time_total_elapsed))) tn = time.time()
def on_unreachable(self, host, results): item = None if type(results) == dict: item = results.get('item', None) if item: msg = "\tFailed Task: %s => (item=%s) => %s" % (host, item, results) else: msg = "\tFatal Task: %s => %s" % (host, results) display(msg, color='red', runner=self.runner) super(BattleschoolRunnerCallbacks, self).on_unreachable(host, results)
def default(self, arg, forceshell=True): if arg.startswith("#"): return False if not self.options.cwd: print u'没有匹配到机器 请重新选择\n' 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 log(arg) if not self.confirm(module, module_args): callbacks.display("Command canceled by user") return self.options.module_name = module self.callbacks.options = self.options try: results = ansible.runner.Runner( pattern=self.options.cwd, module_name=module, module_args=module_args, remote_user=self.options.remote_user, timeout=self.options.timeout, private_key_file=self.options.private_key_file, forks=self.options.forks, become=self.options.become, become_user=self.options.become_user, become_pass=self.become_password, become_method=self.options.become_method, transport=self.options.connection, subset=self.options.subset, check=self.options.check, diff=self.options.check, callbacks=self.callbacks, inventory=self.ansible.inventory, vault_pass=self.vault_password, ).run() if results is None: print "No hosts found" return False except Exception as e: print unicode(e) return False
def list(args): """ Implements a command line method to list all environments that have been instantiated using `init`. """ envs = EnvironmentManager.get_envs() if len(envs) == 0: display("(none)", color="red", stderr=False) else: for env in envs: EnvironmentManagerFactory(env_name=env, cmd='info').display_basic_info()
def _check_options(self): manager = self.setting_manager if not hasattr(manager, 'serverspec_dir') or manager.serverspec_dir is None: display("[kirby] 'serverspec_dir' is not correctly defined") return False if not hasattr(manager, 'serverspec_cmd') or manager.serverspec_cmd is None: display("[kirby] 'serverspec_cmd' is not correctly defined") return False return True
def set_complex_args(self, key, value): display('WARNING: `set complex_args` is deprecated. Use `update complex_args` instead.') if key == '.': key_list = [] else: key_list = Interpreter.dot_str_to_key_list(key) if key_list is None: display('Failed to interpret the key') return try: value = json.loads(value) value = utils.json_dict_unicode_to_bytes(value) except ValueError: pass if not isinstance(value, dict) and key == '.': display('complex_args has to be dict.') return new_complex_args = copy.deepcopy(self.task_info.complex_args) parent = None curr = new_complex_args last_key = None for key, expected_type in key_list: if isinstance(curr, dict): parent = curr last_key = key try: curr = curr[key] except KeyError: curr = curr[key] = {} elif isinstance(curr, list) or isinstance(curr, str): try: curr = curr[key] except TypeError: curr = parent[last_key] = {} curr = curr[key] = {} except IndexError: display('Invalid Index: %s' % str(key)) return parent = parent[last_key] last_key = key if parent is None: new_complex_args = value else: parent[last_key] = value self.task_info.complex_args = new_complex_args display('updated: %s' % (str(self.task_info.complex_args)))
def deprecated(msg, version): ''' used to print out a deprecation message.''' if not C.DEPRECATION_WARNINGS: return new_msg = "\n[DEPRECATION WARNING]: %s. This feature will be removed in version %s." % (msg, version) new_msg = new_msg + " Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.\n\n" wrapped = textwrap.wrap(new_msg, 79) new_msg = "\n".join(wrapped) + "\n" if new_msg not in deprecations: display(new_msg, color='purple', stderr=True) deprecations[new_msg] = 1
def timestamp(type="task"): global tn, time_play_start time_elapsed = secondsToStr(time.time() - tn) time_play_elapsed = secondsToStr(time.time() - time_play_start) time_total_elapsed = secondsToStr(time.time() - t0) display( filled( 'Previous Task Duration: %s Overall Duration: %s' % (time_elapsed, time_total_elapsed ))) if type == "play": display( filled( 'Previous Play Duration: %s' % (time_play_elapsed ))) tn = time.time()
def playbook_on_start(self): if self.setting_manager.enable: result = self.runner.run() if result is None: display('[kirby] serverspec\'s settings are invalid...disable kirby', stderr=True) self.setting_manager.enable = False return self.num_tests = result[0] self.num_failed_tests = result[1] self.failed_tests = result[2] self.dirty = False
def timestamp(type="task"): global tn, time_play_start time_elapsed = secondsToStr(time.time() - tn) time_play_elapsed = secondsToStr(time.time() - time_play_start) time_total_elapsed = secondsToStr(time.time() - t0) display( filled('Previous Task Duration: %s Overall Duration: %s' % (time_elapsed, time_total_elapsed))) if type == "play": display(filled('Previous Play Duration: %s' % (time_play_elapsed))) tn = time.time()
def del_module_args(self, key): if key == '.': self.task_info.module_args = '' display('deleted') else: module_args = self.task_info.module_args try: module_args_list = utils.split_args(module_args) except Exception as ex: display('%s' % str(ex)) return deleted = False for i, arg in enumerate(module_args_list): quoted = arg.startswith('"') and arg.endswith('"') or arg.startswith("'") and arg.endswith("'") if '=' in arg and not quoted and arg.split('=', 1)[0] == key: del module_args_list[i] display('deleted') deleted = True break if not deleted: display('module_args does not contain the key %s' % (key)) return self.task_info.module_args = ' '.join(module_args_list)
def deprecated(msg, version): """ used to print out a deprecation message.""" if not C.DEPRECATION_WARNINGS: return new_msg = "\n[DEPRECATION WARNING]: %s. This feature will be removed in version %s." % (msg, version) new_msg = ( new_msg + " Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.\n\n" ) wrapped = textwrap.wrap(new_msg, 79) new_msg = "\n".join(wrapped) + "\n" if new_msg not in deprecations: display(new_msg, color="purple", stderr=True) deprecations[new_msg] = 1
def remove(args): """ Deletes all inventory files for a deployment from ~/vars/f5aws/env/<env name> This environment should already have been torn down using `teardown` """ exec_results = EnvironmentManager(args).remove() print_playbook_results(exec_results) try: # print the login information if the deployment was successful if exec_results["playbook_results"].statuscode == 0: print "" display(" The environment '{}' has been successfully removed".format(args.env_name), color="green", stderr=False) except KeyError, e: raise ExecutionError("Failed due to KeyError while removing {}".format(args.env_name))
def display_basic_info(self): inventory, resources, statuses = self.get_environment_info() color = 'green' status = 'deployed' for k, v in statuses.items(): try: if v['state'] != 'deployed': color = 'red' status = 'not deployed/error' except KeyError: color = 'red' status = 'not deployed/error' env_info = self.get_env_info(inventory) display(" - %s (%s)" % (self.options.env_name, status), color=color, stderr=False) for k in sorted(env_info, key=lambda key: key): display(" %s: %s" % (k, env_info[k]), color=color, stderr=False)
def __init__(self): config_file = os.environ.get('KIRBY_CONFIG', None) if config_file is None: config_file = os.getcwd() + '/kirby.cfg' self.setting_manager = SettingManager(config_file) if self.setting_manager.enable and not self._check_options(): display('[kirby] disable kirby...', stderr=True) self.setting_manager.enable = False if self.setting_manager.enable: self.runner = ServerspecRunner(self.setting_manager.serverspec_dir, self.setting_manager.serverspec_cmd) self.num_changed_tasks = 0 self.num_tested_tasks = 0 self.not_tested_tasks = []
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): args = {} if complex_args: args.update(complex_args) args.update(utils.parse_kv(module_args)) if 'msg' not in args: raise AnsibleError("'msg' is a required argument.") # might be handy to allow delayed formatting msg = args['msg'].format(args.get('args', {})) display(msg, args.get('color', 'normal')) result = dict( changed=False, msg=msg, ) return ReturnData(conn=conn, result=result)
def exec_command(self, *args, **kwargs): """ Wrapper around _exec_command to retry in the case of an ssh failure Will retry if: * an exception is caught * ssh returns 255 Will not retry if * remaining_tries is <2 * retries limit reached """ remaining_tries = C.get_config( C.p, 'ssh_retry', 'retries', 'ANSIBLE_SSH_RETRY_RETRIES', 3, integer=True) + 1 cmd_summary = "%s %s..." % (args[0], str(kwargs)[:200]) for attempt in xrange(remaining_tries): pause = 2 ** attempt - 1 if pause > 30: pause = 30 time.sleep(pause) try: return_tuple = super(Connection, self).exec_command(*args, **kwargs) except Exception as e: msg = ("ssh_retry: attempt: %d, caught exception(%s) from cmd " "(%s).") % (attempt, e, cmd_summary) display(msg, color='blue') if attempt == remaining_tries - 1: raise e else: continue # 0 = success # 1-254 = remote command return code # 255 = failure from the ssh command itself if return_tuple[0] != 255: break else: msg = ('ssh_retry: attempt: %d, ssh return code is 255. cmd ' '(%s).') % (attempt, cmd_summary) display(msg, color='blue') return return_tuple
def do_del(self, arg): """del module_args|ma|complex_args|ca key Delete the argument of the module. The usage is almost same as set command. """ if arg is None or arg == '' or len(arg.split()) != 2: display('Invalid option. See help for usage.') return arg_split = arg.split() target = arg_split[0] key = arg_split[1] if target == 'module_args' or target == 'ma': self.del_module_args(key) elif target == 'complex_args' or target == 'ca': self.del_complex_args(key) else: display('Invalid option. See help for usage.')
def deprecated(msg, version, removed=False): ''' used to print out a deprecation message.''' if not removed and not C.DEPRECATION_WARNINGS: return if not removed: if version: new_msg = "\n[DEPRECATION WARNING]: %s. This feature will be removed in version %s." % (msg, version) else: new_msg = "\n[DEPRECATION WARNING]: %s. This feature will be removed in a future release." % (msg) new_msg = new_msg + " Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.\n\n" else: raise errors.AnsibleError("[DEPRECATED]: %s. Please update your playbooks." % msg) wrapped = textwrap.wrap(new_msg, 79) new_msg = "\n".join(wrapped) + "\n" if new_msg not in deprecations: display(new_msg, color='purple', stderr=True) deprecations[new_msg] = 1
def playbook_on_play_start(self, name): play_vars = merge_hash(self.play.vars, getattr(self.play, 'vars_file_vars', {})) play_vars = merge_hash(play_vars, getattr(self.playbook, 'extra_vars', {})) pem = play_vars.get('creds_ssh_private_key', None) if pem is None: return key = RSAKey.from_private_key(StringIO.StringIO(pem)) hexdigest = unpack('16B', key.get_fingerprint()) hexdigest = ':'.join(['%02x' % x for x in hexdigest]) display('Loading SSH private key %s' % hexdigest) pub = '%s %s %s' % (key.get_name(), key.get_base64(), self.KEY_COMMENT) for x in self.play.tasks() + self.play.handlers(): y = getattr(x, 'module_vars', None) if y: y['creds_ssh_public_key'] = pub ssh_agent = play_vars.get('creds_ssh_agent', True) if not ssh_agent: return msg = Message() msg.add_byte(chr(self.SSH2_AGENTC_ADD_IDENTITY)) msg.add_string(key.get_name()) msg.add_mpint(key.n) msg.add_mpint(key.e) msg.add_mpint(key.d) msg.add_mpint(0) msg.add_mpint(key.p) msg.add_mpint(key.q) msg.add_string(self.KEY_COMMENT) agent = Agent() if agent._conn: agent._send_message(msg) else: warning('Failed to connect to ssh-agent') agent.close()
def playbook_on_stats(self, stats): tasktime() display(filled("", fchar="=")) timestamp(self) # Sort the tasks by their running time results = sorted( self.stats.items(), key=lambda value: value[1], reverse=True, ) # Just keep the top 20 results = results[:20] # Print the timings for name, elapsed in results: print("{0:-<70}{1:->9}".format( '{0} '.format(name), ' {0:.02f}s'.format(elapsed), )) print ''
def run_module(self, inventory, source, sshpass, sudopass): runner_cb = BattleschoolRunnerCallbacks() runner_cb.options = self.options runner_cb.options.module_name = self.module_name() module_args = self.module_args(source) #TODO: get workstation from options runner = Runner( pattern='workstation', module_name=self.module_name(), module_path=self.options.module_path, module_args=module_args, inventory=inventory, callbacks=runner_cb, timeout=self.options.timeout, transport=self.options.connection, #sudo=self.options.sudo, sudo=False, sudo_user=self.options.sudo_user, sudo_pass=sudopass, check=self.options.check, diff=self.options.diff, private_key_file=self.options.private_key_file, remote_user=self.options.remote_user, remote_pass=sshpass, forks=self.options.forks) try: results = runner.run() for result in results['contacted'].values(): if 'failed' in result or result.get('rc', 0) != 0: display("ERROR: failed source type (%s) '%s': %s" % (self.type(), module_args, result['msg']), stderr=True, color='red') sys.exit(2) if results['dark']: display("ERROR: failed source type (%s) '%s': DARK" % (self.type(), module_args), stderr=True, color='red') sys.exit(2) except errors.AnsibleError, e: # Generic handler for ansible specific errors display("ERROR: %s" % str(e), stderr=True, color='red') sys.exit(1)
def get_host_list(self): '''根据用户配置从xbox获取机器列表''' http = httplib2.Http() headers = { 'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'ansible-host-getter' } url = self.xbox_url_get_hostlist for group in self.xbox_groups: body = {'token': self.xbox_token, 'tag': group} url = self.xbox_url_get_hostlist + urllib.urlencode(body) try: response, content = http.request(url, 'GET', headers=headers) # 检查返回是否正常 if response.status != 200: raise AnsibleXboxResponseError( '%s %s' % (response.status, response.reason)) hosts = json.loads(content)['hosts'] callbacks.display( '[DEBUG] [get_host_list] url[%s] ==> hosts[%s]' % (url, len(hosts)), log_only=True) for host in hosts: self.push(self.inventory, 'all', host) # 连不上? except httplib2.HttpLib2Error, e: callbacks.display( '[ERROR] [get_host_list] Connect to xbox failed', 'red') sys.exit(1) # http返回非200? except AnsibleXboxResponseError, e: callbacks.display( '[ERROR] [get_host_list] Xbox response error, http status: %s' % e, 'red') sys.exit(1)
def on_failed(self, host, res, ignore_errors=False): if not ignore_errors: display("\tTask FAILED: %s %s" % (self.get_name(), res.get('msg')), color="red") super(BattleschoolRunnerCallbacks, self).on_failed(host, res, ignore_errors=ignore_errors)
def playbook_on_play_start(self, pattern): timestamp() display(filled("", fchar="=")) pass
def on_skipped(self, host, item=None): display("\tTask skipped: %s" % self.get_name(), color="yellow") super(BattleschoolRunnerCallbacks, self).on_skipped(host, item)
def on_error(self, host, err): display("\tTask ERROR: %s%s" % (self.get_name(), err), color="red") super(BattleschoolRunnerCallbacks, self).on_error(host, err)
def main(args): ''' run ansible-playbook operations ''' ## truiz: here I add options that will become parameters in the function ## truiz: extra vars is dict with the vars and values extra_vars = {'host': 'testing', 'vars_file': 'the_vars.yml'} print extra_vars ## truiz: this is just a list of playbooks playbooks = ['ansible/the_work.yml'] ## truiz: The file with hosts and their vars inventory_file = 'ansible/inventory' ## truiz: this could be an usefull parameter timeout = 10 # create parser for CLI options parser = utils.base_parser(constants=C, usage="%prog playbook.yml", connect_opts=True, runas_opts=True, subset_opts=True, check_opts=True, diff_opts=True) parser.add_option('--vault-password', dest="vault_password", help="password for vault encrypted files") parser.add_option( '--syntax-check', dest='syntax', action='store_true', help="perform a syntax check on the playbook, but do not execute it") parser.add_option('--list-tasks', dest='listtasks', action='store_true', help="list all tasks that would be executed") parser.add_option('--list-tags', dest='listtags', action='store_true', help="list all available tags") parser.add_option('--start-at-task', dest='start_at', help="start the playbook at the task matching this name") parser.add_option('--force-handlers', dest='force_handlers', default=C.DEFAULT_FORCE_HANDLERS, action='store_true', help="run handlers even if a task fails") parser.add_option('--flush-cache', dest='flush_cache', action='store_true', help="clear the fact cache") options, args = parser.parse_args(args) if len(args) == 0: parser.print_help(file=sys.stderr) return 1 # privlege escalation command line arguments need to be mutually exclusive # utils.check_mutually_exclusive_privilege(options, parser) # if (options.ask_vault_pass and options.vault_password_file): # parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive") sshpass = None becomepass = None vault_pass = None # options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS # if options.listhosts or options.syntax or options.listtasks or options.listtags: # (_, _, vault_pass) = utils.ask_passwords(ask_vault_pass=options.ask_vault_pass) # else: # options.ask_pass = options.ask_pass or C.DEFAULT_ASK_PASS # # Never ask for an SSH password when we run with local connection # if options.connection == "local": # options.ask_pass = False # # set pe options # utils.normalize_become_options(options) # prompt_method = utils.choose_pass_prompt(options) # (sshpass, becomepass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, # become_ask_pass=options.become_ask_pass, # ask_vault_pass=options.ask_vault_pass, # become_method=prompt_method) # read vault_pass from a file # if not options.ask_vault_pass and options.vault_password_file: # vault_pass = utils.read_vault_file(options.vault_password_file) for playbook in playbooks: print playbook if not os.path.exists(playbook): raise errors.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 errors.AnsibleError( "the playbook: %s does not appear to be a file" % playbook) ## truiz: is better to pass the inventory file inventory = ansible.inventory.Inventory(inventory_file, vault_password=vault_pass) print options.inventory print inventory # Note: slightly wrong, this is written so that implicit localhost # (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 in v2 no_hosts = False if len(inventory.list_hosts()) == 0: # Empty inventory utils.warning( "provided hosts list is empty, only localhost is available") no_hosts = True #print options.subset #inventory.subset(options.subset) if len(inventory.list_hosts()) == 0 and no_hosts is False: # Invalid limit raise errors.AnsibleError("Specified --limit does not match any hosts") print options.become print options.become_user print options.remote_user print options.timeout print becomepass for playbook in playbooks: stats = callbacks.AggregateStats() playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY) runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY) print runner_cb pb = ansible.playbook.PlayBook( playbook=playbook, # module_path=options.module_path, inventory=inventory, # forks=options.forks, # remote_user=options.remote_user, # remote_pass=sshpass, callbacks=playbook_cb, runner_callbacks=runner_cb, stats=stats, timeout=timeout, # transport=options.connection, #become=options.become, become_method='sudo', become_user=options.become_user, # become_pass=becomepass, extra_vars=extra_vars, private_key_file=options.private_key_file, # only_tags=only_tags, # skip_tags=skip_tags, check=options.check, diff=options.diff, # vault_password=vault_pass, force_handlers=options.force_handlers, ) # if options.flush_cache: # display(callbacks.banner("FLUSHING FACT CACHE")) # pb.SETUP_CACHE.flush() # if options.listhosts or options.listtasks or options.syntax or options.listtags: # print '' # print 'playbook: %s' % playbook # print '' # playnum = 0 # for (play_ds, play_basedir) in zip(pb.playbook, pb.play_basedirs): # playnum += 1 # play = ansible.playbook.Play(pb, play_ds, play_basedir, # vault_password=pb.vault_password) # label = play.name # hosts = pb.inventory.list_hosts(play.hosts) # if options.listhosts: # print ' play #%d (%s): host count=%d' % (playnum, label, len(hosts)) # for host in hosts: # print ' %s' % host # if options.listtags or options.listtasks: # print ' play #%d (%s):\tTAGS: [%s]' % (playnum, label,','.join(sorted(set(play.tags)))) # if options.listtags: # tags = [] # for task in pb.tasks_to_run_in_play(play): # tags.extend(task.tags) # print ' TASK TAGS: [%s]' % (', '.join(sorted(set(tags).difference(['untagged'])))) # if options.listtasks: # for task in pb.tasks_to_run_in_play(play): # if getattr(task, 'name', None) is not None: # # meta tasks have no names # print ' %s\tTAGS: [%s]' % (task.name, ', '.join(sorted(set(task.tags).difference(['untagged'])))) # if options.listhosts or options.listtasks or options.listtags: # print '' # continue # if options.syntax: # # if we've not exited by now then we are fine. # print 'Playbook Syntax is fine' # return 0 failed_hosts = [] unreachable_hosts = [] try: print "Before run" res = pb.run() print "After run" ## truiz: returns a resume of all work done print res hosts = sorted(pb.stats.processed.keys()) display(callbacks.banner("PLAY RECAP")) playbook_cb.on_stats(pb.stats) for h in hosts: t = pb.stats.summarize(h) if t['failures'] > 0: failed_hosts.append(h) if t['unreachable'] > 0: unreachable_hosts.append(h) retries = failed_hosts + unreachable_hosts if C.RETRY_FILES_ENABLED and len(retries) > 0: filename = pb.generate_retry_inventory(retries) if filename: display(" to retry, use: --limit @%s\n" % filename) for h in hosts: t = pb.stats.summarize(h) display("%s : %s %s %s %s" % (hostcolor(h, t), colorize('ok', t['ok'], 'green'), colorize('changed', t['changed'], 'yellow'), colorize('unreachable', t['unreachable'], 'red'), colorize('failed', t['failures'], 'red')), screen_only=True) display("%s : %s %s %s %s" % (hostcolor(h, t, False), colorize('ok', t['ok'], None), colorize('changed', t['changed'], None), colorize('unreachable', t['unreachable'], None), colorize('failed', t['failures'], None)), log_only=True) print "" if len(failed_hosts) > 0: return 2 if len(unreachable_hosts) > 0: return 3 except errors.AnsibleError, e: display("ERROR: %s" % e, color='red') return 1
(hostcolor(h, t, False), colorize('ok', t['ok'], None), colorize('changed', t['changed'], None), colorize('unreachable', t['unreachable'], None), colorize('failed', t['failures'], None)), log_only=True) print "" if len(failed_hosts) > 0: return 2 if len(unreachable_hosts) > 0: return 3 except errors.AnsibleError, e: display("ERROR: %s" % e, color='red') return 1 return 0 if __name__ == "__main__": display(" ", log_only=True) display(" ".join(sys.argv), log_only=True) display(" ", log_only=True) try: sys.exit(main(sys.argv[1:])) except errors.AnsibleError, e: display("ERROR: %s" % e, color='red', stderr=True) sys.exit(1) except KeyboardInterrupt, ke: display("ERROR: interrupted", color='red', stderr=True) sys.exit(1)
def on_no_hosts(self): display("\tTask NO HOSTS: %s" % self.get_name(), color="red") super(BattleschoolRunnerCallbacks, self).on_no_hosts()
def on_no_hosts_remaining(self): display("\tFailed playbook: %s" % self.playbook.filename, color='bright red') call_callback_module('playbook_on_no_hosts_remaining')
def on_play_start(self, pattern): display(banner("Executing playbook %s" % self.playbook.filename), color="bright blue") call_callback_module('playbook_on_play_start', pattern)