class MyInventory(): """ this is ansible inventory object. """ def __init__(self, resource, loader, variable_manager): self.resource = resource self.loader = DataLoader() self.inventory = InventoryManager(loader=self.loader, sources=['%s/conf/hostslist' %BASE_DIR]) # self.variable_manager.set_inventory(self.inventory) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) self.dynamic_inventory() def add_dynamic_group(self, hosts, groupname, groupvars=None): """add new hosts to a group""" self.inventory.add_group(groupname) my_group = Group(name=groupname) # if group variables exists, add them to group if groupvars: for key in groupvars: my_group.set_variable(key, groupvars[key]) # add hosts to group for host in hosts: # set connection variables hostname = host.get("hostname") hostip = host.get('ip', hostname) hostport = host.get("port") username = host.get("username") password = host.get("password") ssh_key = host.get("ssh_key") my_host = Host(name=hostname, port=hostport) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_host', value=hostip) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_pass', value=password) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_port', value=hostport) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_user', value=username) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_private_key_file', value=ssh_key) # my_host.set_variable('ansible_ssh_pass', password) # my_host.set_variable('ansible_ssh_private_key_file', ssh_key) # set other variables for key in host: if key not in ["hostname", "port", "username", "password"]: self.variable_manager.set_host_variable(host=my_host, varname=key, value=host[key]) # add to group self.inventory.add_host(host=hostname, group=groupname, port=hostport) #ghost = Host(name="192.168.8.119") def dynamic_inventory(self): """ add new hosts to inventory. """ if isinstance(self.resource, list): self.add_dynamic_group(self.resource, 'default_group') elif isinstance(self.resource, dict): for groupname in self.resource: self.add_dynamic_group(self.resource[groupname].get("hosts"), groupname, self.resource[groupname].get("vars"))
def add_dynamic_host(hosts_list): loader = None inventory = InventoryManager(loader=loader, sources=resource) for hosts in hosts_list: hostname = hosts.get("hostname") hostport = hosts.get("hostport") password = hosts.get("password") username = hosts.get("username") my_host = Host(name=hostname, port=hostport) variable_manager = VariableManager(loader=loader, inventory=inventory) variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_host', value=hostname) variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_pass', value=password) variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_port', value=hostport) variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_user', value=username) inventory.add_host(host=hostname, port=hostport) print() print(hosts_list)
def give_inventory_and_data_loader( ) -> Tuple[InventoryManager, dataloader.DataLoader, VariableManager]: data_loader = dataloader.DataLoader() # create the inventory, and filter it based on the subset specified (if any) inventory = InventoryManager(loader=data_loader, sources="localhost") inventory.add_group("all") inventory.add_group("ungrouped") inventory.add_host("localhost", group="ungrouped") inventory.add_host("spire_server", group="ungrouped") # create the variable manager, which will be shared throughout # the code, ensuring a consistent view of global variables var_manager = VariableManager(loader=data_loader, inventory=inventory, version_info=None) var_manager.set_host_variable("spire_server", "ansible_connection", "local") var_manager.set_host_variable("spire_server", "ansible_host", "localhost") python_path = sys.executable var_manager.set_host_variable("spire_server", "ansible_python_interpreter", python_path) var_manager.set_host_variable("localhost", "ansible_python_interpreter", python_path) return inventory, data_loader, var_manager
def _run_play(self, play_source, host_vars): host_list = play_source['hosts'] loader = dataloader.DataLoader() # FIXME(jpena): we need to behave differently if we are using # Ansible >= 2.4.0.0. Remove when only versions > 2.4 are supported if PRE_24_ANSIBLE: variable_manager = VariableManager() inventory_inst = Inventory(loader=loader, variable_manager=variable_manager, host_list=host_list) variable_manager.set_inventory(inventory_inst) else: inventory_inst = Inventory(loader=loader, sources=','.join(host_list) + ',') variable_manager = VariableManager(loader=loader, inventory=inventory_inst) for host, variables in host_vars.items(): host_inst = inventory_inst.get_host(host) for var_name, value in variables.items(): if value is not None: variable_manager.set_host_variable( host_inst, var_name, value) storage = [] callback = MyCallback(storage) tqm = task_queue_manager.TaskQueueManager( inventory=inventory_inst, variable_manager=variable_manager, loader=loader, options=self.options, passwords=self.passwords, stdout_callback=callback, ) # create play play_inst = play.Play().load(play_source, variable_manager=variable_manager, loader=loader) # actually run it try: tqm.run(play_inst) finally: tqm.cleanup() return storage
def execute(playbooks: list, context: dict): ''' ''' assert playbooks os.environ["ANSIBLE_CONDITIONAL_BARE_VARS"] = "False" # ctx._init_global_context({}) # since the API is constructed for CLI it expects certain options to always be set in the context object ctx.CLIARGS = ImmutableDict(connection='local', module_path=['./playbooks/roles'], forks=1, become=False, become_method="sudo", syntax=False, start_at_task=None, diff=False, verbosity=0) # initialize needed objects loader = DataLoader( ) # Takes care of finding and reading yaml, json and ini files # passwords = dict(become_pass="******") passwords = dict() # Instantiate our ResultCallback for handling results as they come in. Ansible expects this to be one of its main display outlets results_callback = ResultCallback() # create inventory, use path to host config file as source or hosts in a comma separated string inventory = InventoryManager(loader=loader, sources='localhost,') host = Host(name="localhost") # variable manager takes care of merging all the different sources to give you a unified view of variables available in each context variable_manager = VariableManager(loader=loader, inventory=inventory) variable_manager.set_host_variable(host, "current_directory", context.get("current_directory", "")) pbex = PlaybookExecutor(playbooks=playbooks, inventory=inventory, variable_manager=variable_manager, loader=loader, passwords=passwords) result = pbex.run() post_command = variable_manager.get_vars()["hostvars"]["localhost"].get( "mondrik_post_command") return result, post_command
class BasisAnsibleobject(object): def __init__(self, ): self.loader = DataLoader() self.options = Options(connection='smart', module_path='/path/to/mymodules', forks=100, timeout=10, remote_user='******', private_key_file='/root/.ssh/id_rsa', ask_pass=False, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None, become_user=None, ask_value_pass=False, verbosity=None, check=False, listhosts=False, listtasks=False, listtags=False, syntax=False, diff=False) self.passwords = dict(sshpass=None, becomepass=None) self.inventory = InventoryManager(loader=self.loader, sources='/etc/ansible/hosts') self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) def createplay(self, filename, hosts, taskid, username, password, sshLoginType, systemType, command): # action try: with open('/etc/ansible/{0}'.format(hosts), 'w') as f: f.writelines(hosts) except Exception as e: # logger.error("【错误】 ansible配置文件写入失败 -- mission.py line68") pass self.inventory = InventoryManager(loader=self.loader, sources='/etc/ansible/{0}'.format(hosts)) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) if sshLoginType == 'ssh_key' and systemType == 'linux': command = "iptables-save" #重启防火墙命令 remote_command = command self.variable_manager.set_host_variable(Host(hosts, '22'), 'ansible_ssh_user', username) self.variable_manager.set_host_variable(Host(hosts, '22'), 'ansible_ssh_pass', password) play_source = dict( name="Ansible Play", hosts='all', gather_facts='no', tasks=[ dict(action=dict(module="command", args=remote_command)), dict(action=dict(module="command", args=command)), dict(action=dict(module="command", args="firewall-cmd --reload")), ] ) self.play = Play.load(play_source, variable_manager=self.variable_manager, loader=self.loader) return self.play,self.variable_manager,self.inventory
def autocreate_publickey(host_list, password, jobid): C.HOST_KEY_CHECKING = False loader = DataLoader() options = Options(connection='smart', forks=5, ssh_common_args='-C -o ControlPersist=30s') passwords = dict() if len(host_list) <= 1: sources = host_list[0] + ',' else: sources = ','.join(host_list) inventory = InventoryManager(loader=loader, sources=sources) variable_manager = VariableManager(loader=loader, inventory=inventory) for host in host_list: host_info = Host(name=host, port=22) variable_manager.set_host_variable(host_info, 'ansible_ssh_user', 'root') variable_manager.set_host_variable(host_info, 'ansible_ssh_pass', password) play_source = dict( name='Generate Publickey', hosts=host_list, gather_facts='no', tasks=[ dict(action=dict( module='authorized_key', args=dict(user='******', key="{{ lookup('file','/root/.ssh/id_rsa.pub') }}"))) ]) play = Play().load(play_source, variable_manager=variable_manager, loader=loader) tqm = None callback = ResultsCollector(jobid) 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() return callback.result
class MyInventory: """ Ansible Inventory """ def __init__(self, resource, loader, variable_manager): self.resource = resource self.loader = DataLoader() self.inventory = InventoryManager(loader=self.loader, sources=['/etc/ansible/hosts']) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) self.dynamic_inventory() def add_dynamic_group(self, hosts, groupname, groupvars=None): """ add hosts to a group """ self.inventory.add_group(groupname) my_group = Group(name=groupname) # if group variables exists, add them to group if groupvars: for key, value in groupvars.iteritems(): my_group.set_variable(key, value) # add hosts to group for host in hosts: # set connection variables hostname = host.get("hostname") hostip = host.get('ip', hostname) hostport = host.get("port") my_host = Host(name=hostname, port=hostport) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_host', value=hostip) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_port', value=hostport) # set other variables for key, value in host.iteritems(): if key not in ["hostname", "port", "username", "password"]: self.variable_manager.set_host_variable(host=my_host, varname=key, value=value) # add to group self.inventory.add_host(host=hostname, group=groupname, port=hostport) def dynamic_inventory(self): """ add hosts to inventory. """ if isinstance(self.resource, list): self.add_dynamic_group(self.resource, 'default_group') elif isinstance(self.resource, dict): for groupname, hosts_and_vars in self.resource.iteritems(): self.add_dynamic_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars")) else: pass
# create inventory and pass to var manager inventory = InventoryManager(loader=loader, sources=None) #variable_manager = VariableManager(loader=loader, inventory=inventory) hostname = 'test1' hostport = 22 hostip = '127.0.0.1' password = '******' username = '******' variable_manager = VariableManager(loader=loader, inventory=inventory) my_host = Host(name=hostname, port=hostport) variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_host', value=hostip) variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_pass', value=password) variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_port', value=hostport) variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_user', value=username) # variable_manager.set_host_variable(host=my_host,varname='ansible_become_pass',value='tusbasa1') # variable_manager.set_host_variable(host=my_host,varname='ansible_become',value=True) # variable_manager.set_host_variable(host=my_host,varname='ansible_become_method',value='sudo') # variable_manager.set_host_variable(host=my_host,varname='ansible_become_user',value='root')
from ansible.parsing.dataloader import DataLoader from ansible.inventory.manager import InventoryManager from ansible.vars.manager import VariableManager loader = DataLoader() inventory = InventoryManager(loader=loader, sources='hosts') variable_manager = VariableManager(loader=loader, inventory=inventory) host = inventory.get_host('192.168.10.150') # get_vars() # 查看变量 print(variable_manager.get_vars(host=host)) # set_host_variable() # 修改指定主机的变量信息 variable_manager.set_host_variable(host=host, varname="ansible_ssh_pass", value="1111111") print(variable_manager.get_vars(host=host)) print(variable_manager.__dict__) # _extra_vars={} # 添加指定对象的扩展变量,全局有效 variable_manager._extra_vars = {'mysite': "ys.blog.com"} print(variable_manager.get_vars(host=host))
class PackageInstallerTask(): #: Name of the task. name = 'PackageInstallerTask' def __init__(self, host_dict): self.package = None self.connection_type = None self.connection_port = None self.connection_user = None self.ansible_password = None self.loader = self.get_loader() self.variable_manager = VariableManager(loader=self.loader) self.inventory = create_inventory(host_dict, self.variable_manager, self.loader, self.ansible_password) def get_loader(self, base_dir='../playbooks'): loader = DataLoader( ) # Takes care of finding and reading yml, json and ini files loader.set_basedir(base_dir) return loader def variable_manager_initialization(self, ip_address): for host in self.inventory._inventory.hosts.values(): for group in host.groups: if group.name == 'ubuntu': self.variable_manager.set_host_variable( host, 'ansible_connection', self.connection_type) self.variable_manager.set_host_variable( host, 'ansible_host', ip_address) self.variable_manager.set_host_variable( host, 'ansible_port', self.connection_port) self.variable_manager.set_host_variable( host, 'ansible_user', self.connection_user) self.variable_manager.set_host_variable( host, 'ansible_ssh_private_key_file', '/home/ansible/.ssh/id_rsa') self.variable_manager.set_host_variable( host, 'ansible_become_user', self.connection_user) self.variable_manager.set_host_variable( host, 'ansible_become', 'yes') self.variable_manager.set_host_variable( host, 'ansible_become_password', 'Mp3b27') if group.name == 'windows': self.variable_manager.set_host_variable( host, 'ansible_user', self.connection_user) self.variable_manager.set_host_variable( host, 'ansible_password', self.ansible_password) self.variable_manager.set_host_variable( host, 'ansible_port', self.connection_port) self.variable_manager.set_host_variable( host, 'ansible_username', self.connection_user) self.variable_manager.set_host_variable( host, 'ansible_connection', 'winrm') self.variable_manager.set_host_variable( host, 'ansible_winrm_transport', 'ntlm') self.variable_manager.set_host_variable( host, 'ansible_winrm_server_cert_validation', 'ignore') def _install(self, ip_address): # initialize needed objects # self.variable_manager_initialization(ip_address) host_list = [ip_address] hosts = ','.join(host_list) if len(host_list) == 1: hosts += ',' package = [self.package] # create data structure that represents our play # including tasks, this is basically what our YAML loader does internally. print(f'hosts : {ip_address} \n roles : {package}') play_source = { 'hosts': hosts, 'gather_facts': True, 'become': True, 'become_user': '******', 'become_method': 'sudo', 'roles': package } passwords = dict() results_callback = ResultsCollectorJSONCallback() tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, passwords=passwords, stdout_callback=results_callback, ) # Create play object, playbook objects use .load instead of init or new methods, # this will also automatically create the task objects from the info provided in play_source play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader, vars={'ansible_become_pass': '******'}) # Actually run it try: result = tqm.run( play ) # most interesting data for a play is actually sent to the callback's methods finally: # we always need to cleanup child procs and the structures we use to communicate with them tqm.cleanup() if self.loader: self.loader.cleanup_all_tmp_files() shutil.rmtree(C.DEFAULT_LOCAL_TMP, True) print("UP ***********") for host, result in results_callback.host_ok.items(): print('{0} >>> {1}'.format(host, result._result)) print("FAILED *******") for host, result in results_callback.host_failed.items(): print('{0} >>> {1}'.format(host, result._result['msg'])) print("DOWN *********") for host, result in results_callback.host_unreachable.items(): print('{0} >>> {1}'.format(host, result._result['msg'])) def run(self, ip_address, package, connection_type, connection_user, connection_port, ansible_password): print(f'ip: {ip_address}, connection_user: {connection_user}') self.package = package self.connection_type = connection_type self.connection_port = connection_port self.connection_user = connection_user self.ansible_password = ansible_password self._install(ip_address)
class MyInventory: """ 动态生成/etc/ansible/hosts文件 """ def __init__(self, hosts_resource): # hosts_resource = { # "Group1": { # "hosts": [{"ip": "10.0.0.62", "port": "22", "username": "******", "password": "******"}, # {"ip": "10.0.0.61", "port": "22", "username": "******", "password": "******"}], # "group_vars": {"var1": "ansible"} # }, # # "Group2": {} # } self.hosts_resource = hosts_resource self.loader = DataLoader() self.hosts_file = [""] """ sources这个我们知道这里是设置hosts文件的地方,它可以是一个列表里面包含多个文件路径且文件真实存在,在单纯的执行ad-hoc的时候这里的 文件里面必须具有有效的hosts配置,但是当通过动态生成的资产信息的时候这个文件必须存在但是它里面可以是空的,如果这里配置成None那么 它不影响资产信息动态生成但是会有一个警告 [WARNING]: No inventory was parsed, only implicit localhost is available {'all': [], 'ungrouped': [], 'Group1': ['10.0.0.62', '10.0.0.61']} """ self.inventory = InventoryManager(loader=self.loader, sources=self.hosts_file) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) self.dynamic_inventory() def add_hosts_group(self, hosts_list, group_name, group_vars=None): """ 动态添加主机到指定的主机组 完整的HOSTS文件格式 [test1] hostname ansible_ssh_host=192.168.1.111 ansible_ssh_user="******" ansible_ssh_pass="******" 但通常我们都省略hostname,端口也省略因为默认是22,这个在ansible配置文件中有,除非有非22端口的才会配置 [test1] 192.168.100.10 ansible_ssh_user="******" ansible_ssh_pass="******" ansible_python_interpreter="/usr/bin/python3" [test2] 192.168.100.10 ansible_ssh_user="******" ansible_ssh_pass="******" ansible_python_interpreter="/usr/bin/python3" [parent_group:children] test1 test2 [test2:vars] touch_file=new_file :param hosts_list: 主机列表 [{"hostname":"m01","ip": "192.168.100.10", "port": "22", "username": "******", "password": None}, {}] :param group_name: 组名称 :param group_vars: 组变量,格式为字典group_vars={"var1": "ansible"} :return: """ # 如果主机组不存在,就添加主机组,如果存在,就直接获取 if not self.inventory.groups.get(group_name): self.inventory.add_group(group_name) # 返回值是Group对象,注意这里一定要保证是同一个对象 inventory_group = self.inventory.groups.get(group_name) # 如果组变量存在,就设置组变量,可用于playbook中 if group_vars: for key, value in group_vars.items(): inventory_group.set_variable(key, value) for host in hosts_list: ip = host.get("ip", None) hostname = host.get("hostname", ip) port = host.get("port", "22") username = host.get("username") password = host.get("password", None) ssh_key = host.get("ssh_key", None) python_interpreter = host.get("python_interpreter", None) try: host_obj = Host(name=hostname, port=port) self.variable_manager.set_host_variable(host=host_obj, varname="ansible_ssh_host", value=ip) self.variable_manager.set_host_variable(host=host_obj, varname="ansible_ssh_port", value=port) self.variable_manager.set_host_variable(host=host_obj, varname="ansible_ssh_user", value=username) if password: self.variable_manager.set_host_variable(host=host_obj, varname="ansible_ssh_pass", value=password) if ssh_key: self.variable_manager.set_host_variable(host=host_obj, varname="ansible_ssh_private_key_file", value=ssh_key) if python_interpreter: self.variable_manager.set_host_variable(host=host_obj, varname="ansible_python_interpreter", value=python_interpreter) # 添加其他变量 for key, value in host.items(): if key not in ["ip", "hostname", "port", "username", "password", "ssh_key", "python_interpreter"]: self.variable_manager.set_host_variable(host=host_obj, varname=key, value=value) # 添加主机到主机组 self.inventory.add_host(host=hostname, group=group_name, port=port) except Exception as e: print(e) def dynamic_inventory(self): # 为了以后扩展,我们先把该段内容写在这里 for group_name, hosts_and_vars in self.hosts_resource.items(): self.add_hosts_group(hosts_and_vars.get("hosts"), group_name, hosts_and_vars.get("group_vars")) @property def inventory_obj(self): """ 返回inventory對象 :return: """ return self.inventory @property def variable_manager_obj(self): """ 返回variable_manager對象 :return: """ return self.variable_manager
class AnsibleConfigurer: def __init__(self, options=None): if not options: options = {} self.options = options self.loader = DataLoader() if "inventory_path" in self.options: sources = self.options["inventory_path"] else: sources = None self.inventory_manager = InventoryManager(self.loader, sources=sources) self.variable_manager = VariableManager( loader=self.loader, inventory=self.inventory_manager) # TODO load ansible configuration self.config_manager = ConfigManager() def gen_configuration(self, options=None): configuration = {} if not options: options = {} configuration["host_variables"] = dict( ansible_connection="ssh", ansible_ssh_common_args="-o HostKeyAlgorithms={}".format( ",".join(default_host_key_order)), ) if "host_variables" in options and isinstance( options["host_variables"], dict): configuration["host_variables"].update(options["host_variables"]) configuration["host_settings"] = {} if "host_settings" in options and isinstance(options["host_settings"], dict): configuration["host_settings"].update(options["host_settings"]) configuration["apply_kwargs"] = {} if "apply_kwargs" in options and isinstance(options["apply_kwargs"], dict): configuration["apply_kwargs"].update(options["apply_kwargs"]) return configuration def format_configuration(self, configuration, kwargs=None): if not kwargs: kwargs = {} host_variables_kwargs = { k: v for k, v in configuration["host_variables"].items() if isinstance(v, str) or isinstance(v, list) or isinstance(v, dict) } host_settings_kwargs = { k: v for k, v in configuration["host_settings"].items() if isinstance(v, str) or isinstance(v, list) or isinstance(v, dict) } apply_kwargs = { k: v for k, v in configuration["apply_kwargs"].items() if isinstance(v, str) or isinstance(v, list) or isinstance(v, dict) } # Format with kwargs for key, value in kwargs.items(): try: recursive_format(host_variables_kwargs, {key: value}) recursive_format(host_settings_kwargs, {key: value}) recursive_format(apply_kwargs, {key: value}) except TypeError: pass configuration["host_variables"].update(host_variables_kwargs) configuration["host_settings"].update(host_settings_kwargs) configuration["apply_kwargs"].update(apply_kwargs) return configuration def apply(self, host, configuration=None, credentials=None): if not configuration: configuration = {} if ("group" in configuration["host_settings"] and configuration["host_settings"]["group"]): self.inventory_manager.add_group( configuration["host_settings"]["group"]) if host not in self.inventory_manager.hosts: self.inventory_manager.add_host(host, **configuration["host_settings"]) for k, v in configuration["host_variables"].items(): self.variable_manager.set_host_variable(host, k, v) if "playbook_paths" not in configuration["apply_kwargs"]: return False if not isinstance(configuration["apply_kwargs"]["playbook_paths"], (list, set)): return False for playbook_path in configuration["apply_kwargs"]["playbook_paths"]: # Expand the playbook path if it is using relative paths playbook_path = os.path.expanduser(playbook_path) if not exists(playbook_path): print("The playbook_path: {} does not exist".format( playbook_path)) return False if credentials: self.variable_manager.set_host_variable( host, "ansible_ssh_private_key_file", credentials.private_key_file) playbook = Playbook.load( playbook_path, variable_manager=self.variable_manager, loader=self.loader, ) plays = playbook.get_plays() for play in plays: if not run_playbook( play, variable_manager=self.variable_manager, inventory_manager=self.inventory_manager, loader=self.loader, ): return False return True @classmethod def validate_options(cls, options): if not isinstance(options, dict): raise TypeError("options is not a dictionary")
class MyInventory(): """ 动态添加resource,中定义的主机组信息到inventory文件中和并进行相关变量操作 """ def __init__(self, resource, loader, variable_manager): self.resource = resource # 我们需要动态添加的主机信息 self.loader = DataLoader() self.inventory = InventoryManager( loader=self.loader, sources=['%s/conf/auto_hosts' % BASE_DIR]) # self.variable_manager.set_inventory(self.inventory) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) self.dynamic_inventory() def add_dynamic_group(self, hosts, groupname, groupvars=None): """ 将主机添加到对应主机组中 """ self.inventory.add_group(groupname) my_group = Group(name=groupname) # 判断是否有主机组变量 if groupvars: for key, value in groupvars.items(): my_group.set_variable(key, value) # add hosts to group for host in hosts: # set connection variables hostname = host.get("hostname") hostip = host.get('ip', hostname) hostport = host.get("port") username = host.get("username") password = host.get("password") ssh_key = host.get("ssh_key") my_host = Host(name=hostname, port=hostport) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_host', value=hostip) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_pass', value=password) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_port', value=hostport) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_user', value=username) self.variable_manager.set_host_variable( host=my_host, varname='ansible_ssh_private_key_file', value=ssh_key) # 判断是否还有除hostname,port,username,password之外的变量 for key, value in host.items(): if key not in ["hostname", "port", "username", "password"]: self.variable_manager.set_host_variable(host=my_host, varname=key, value=value) # 添加到指定主机组 self.inventory.add_host(host=hostname, group=groupname, port=hostport) def dynamic_inventory(self): """ 动态添加主机到inventory 支持列表和字典形式的添加 :return: """ if isinstance(self.resource, list): self.add_dynamic_group(self.resource, 'default_group') elif isinstance(self.resource, dict): for groupname, hosts_and_vars in self.resource.items(): self.add_dynamic_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
class ExecPlaybook(object): def __init__(self, playbooks=[], track_id=None): ResultModel().inster({"track_id": track_id, "status": "init"}) self.playbooks = playbooks self.track_id = track_id self.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', 'diff' ]) self.options = self.Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='ssh', module_path=None, forks=50, 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, diff=False) self.loader = DataLoader() self.passwords = dict(vault_pass='******') self.inventory = InventoryManager(loader=self.loader, sources='') self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) def add_host(self, host, port=None, user=None, passwd=None, private_file=None): h = Host(host, port) self.inventory.add_host(host, 'all', port) self.inventory.add_host(host, 'all', port) if user: self.variable_manager.set_host_variable(h, 'ansible_ssh_user', user) if passwd: self.variable_manager.set_host_variable(h, 'ansible_ssh_pass', passwd) if private_file: self.variable_manager.set_host_variable( h, 'ansible_ssh_private_key_file', private_file) def run(self): play = PlaybookExecutor(playbooks=self.playbooks, passwords=self.passwords, inventory=self.inventory, loader=self.loader, variable_manager=self.variable_manager, options=self.options) # play._tqm._stdout_callback = CallbackModule() play._tqm._stdout_callback = ResultCallback(track_id=self.track_id) return play.run() def add_playbook_vars(self, key, value): extra_vars = self.variable_manager.extra_vars extra_vars[key] = value self.variable_manager.extra_vars = extra_vars def get_playbook_vars(self): self.variable_manager.get_vars(play=self.playbooks)
class ANSRunner(object): """ This is a General object for parallel execute modules. """ def __init__(self, ips=None, user='******', topology=None, inventory=None, tiargs=None, passwd=None, *args, **kwargs): self.ips = ips self.list_ip_check() self.user = user self.topology = topology self.inventory = inventory self.variable_manager = None self.loader = None self.options = None self.password = passwd self.callback = None try: self.forks = tiargs.forks except AttributeError: self.forks = 5 self.results_raw = {} try: self.cluster_name = tiargs.cluster_name except AttributeError: pass try: self.private_key = tiargs.private_key except AttributeError: self.private_key = None self.__initializeData() def list_ip_check(self): if not self.ips or len(self.ips) < 1: return iplist = [] if ',' in self.ips: for ip in self.ips.split(','): if not ip or not utils.is_valid_ip(ip): continue iplist.append(ip) else: iplist.append(self.ips) ipsstr = ','.join(iplist) if len(iplist) == 1: ipsstr += ',' return ipsstr def __initializeData(self): """ 初始化ansible """ C.DEFAULT_FILTER_PLUGIN_PATH.append( '{}/tiops/ansibleapi/plugins/filter'.format(os.environ['TIUP_COMPONENT_INSTALL_DIR'])) C.HOST_KEY_CHECKING = False C.ANSIBLE_SSH_ARGS = '-C -o ControlMaster=auto -o ControlPersist=1d' C.PIPELINING = True C.CACHE_PLUGIN = 'jsonfile' C.CACHE_PLUGIN_CONNECTION = '~/.ansible/ansible_fact_cache' C.CACHE_PLUGIN_TIMEOUT = 86400 C.DEFAULT_GATHER_TIMEOUT = 120 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', 'diff']) self.options = Options(connection='smart', module_path=None, forks=self.forks, timeout=60, remote_user=self.user, ask_pass=False, private_key_file=self.private_key, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=None, become_method='sudo', become_user='******', ask_value_pass=False, verbosity=None, check=False, listhosts=False, listtasks=False, listtags=False, syntax=False, diff=True) # generate an Ansible inventory object from the topology def inventory(topology): for grp, srvs in topology.items(): if grp not in self.inventory.groups: self.inventory.add_group(grp) for srv in srvs: self.inventory.add_host( srv.get('uuid', srv['ip']), group=grp, port=srv['ssh_port']) self.variable_manager = VariableManager( loader=DataLoader(), inventory=self.inventory) for group in self.inventory.get_groups_dict().iterkeys(): for items in self.inventory.get_groups_dict()[group]: host = self.inventory.get_host(hostname=str(items)) self.variable_manager.set_host_variable( host=host, varname='ansible_user', value=self.user) for vars in topology[group]: if vars.get('uuid', vars['ip']) != items: continue for key, value in vars.items(): if key == 'uuid' or key == 'ssh_port': continue if key == 'ip': self.variable_manager.set_host_variable( host=host, varname='ansible_host', value=value) else: self.variable_manager.set_host_variable( host=host, varname=key, value=value) self.variable_manager.set_host_variable(host=host, varname='numa_node', value=vars['numa_node']) if group == 'tidb_servers': service_name = 'tidb-{}'.format(vars['port']) self.variable_manager.set_host_variable(host=host, varname='service_name', value=service_name) elif group == 'pd_servers': service_name = 'pd-{}'.format(vars['client_port']) self.variable_manager.set_host_variable(host=host, varname='service_name', value=service_name) elif group == 'tikv_servers': service_name = 'tikv-{}'.format(vars['port']) self.variable_manager.set_host_variable(host=host, varname='service_name', value=service_name) elif group == 'grafana_server': service_name = 'grafana-{}'.format(vars['port']) self.variable_manager.set_host_variable(host=host, varname='service_name', value=service_name) elif group == 'pump_servers': service_name = 'pump-{}'.format(vars['port']) self.variable_manager.set_host_variable(host=host, varname='service_name', value=service_name) elif group == 'drainer_servers': service_name = 'drainer-{}'.format(vars['port']) self.variable_manager.set_host_variable(host=host, varname='service_name', value=service_name) elif group == 'alertmanager_server': service_name = 'alertmanager-{}'.format(vars['web_port']) self.variable_manager.set_host_variable(host=host, varname='service_name', value=service_name) return inventory self.password = dict(conn_pass=self.password) self.loader = DataLoader() self.ips = self.list_ip_check() if self.ips: self.inventory = InvManager(loader=self.loader, sources=self.ips) self.variable_manager = VariableManager( loader=DataLoader(), inventory=self.inventory) else: if self.topology: self.inventory = InvManager(loader=self.loader, sources=self.inventory) inventory(self.topology) def run_model(self, module_name, module_args, become=False, register=None, with_items=None, group='*', extra_vars=None, node=None): """ run module from andible ad-hoc. module_name: ansible module_name module_args: ansible module args """ if self.topology: service_names = {'node_exporter': ['monitored_servers', 'node_exporter_port'], 'blackbox_exporter': ['monitored_servers', 'blackbox_exporter_port'], 'prometheus': ['monitoring_server', 'prometheus_port'], 'pushgateway': ['monitoring_server', 'pushgateway_port']} if extra_vars in service_names and service_names[extra_vars][0] in self.inventory.get_groups_dict(): for host in self.inventory.get_groups_dict()[service_names[extra_vars][0]]: hostname = self.inventory.get_host(hostname=host) service_name = '{}-{}'.format(extra_vars, self.variable_manager.get_vars( host=hostname)[service_names[extra_vars][1]]) self.variable_manager.set_host_variable( host=hostname, varname='service_name', value=service_name) if self.cluster_name and extra_vars: self.variable_manager.extra_vars = { 'cluster_name': self.cluster_name, 'service': extra_vars} else: self.variable_manager.extra_vars = { 'cluster_name': self.cluster_name} if register and with_items: task = [dict(action=dict(module=module_name, args=module_args), become=become, register=register, with_items=with_items)] elif register is None and with_items: task = [dict(action=dict(module=module_name, args=module_args), become=become, with_items=with_items)] elif register and with_items is None: task = [dict(action=dict(module=module_name, args=module_args), become=become, register=register)] else: task = [dict(action=dict(module=module_name, args=module_args), become=become)] if node: node_list = node.split(',') if len(node_list) == 1: node_str = '{},'.format(node) else: node_str = ','.join(node_list) play_source = dict( name="Ansible Play", hosts=self.ips if self.ips else (node_str if node else group), gather_facts='no', tasks=task ) play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader) tqm = None self.callback = ModelResultsCollector() import traceback try: tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.password, stdout_callback="minimal", ) tqm._stdout_callback = self.callback tqm.run(play) except Exception as e: term.warn(str(e)) term.debug(traceback.print_exc()) finally: if tqm is not None: tqm.cleanup() result = self.get_model_result() failed = {} unreachable = {} offline_list = [] if self.topology: for grp in ['drainer_servers', 'pump_servers', 'tikv_servers']: if not self.topology.has_key(grp) or not self.topology[grp]: continue for _node in self.topology[grp]: if _node['offline']: offline_list.append(_node['uuid']) if result['success']: for _uuid, _info in result['success'].iteritems(): _ip = _info['ansible_host'] if _info.has_key('stderr') and _info['stderr']: try: failed[_uuid][_ip].append(_info['stderr']) except: if not failed.has_key(_uuid): failed[_uuid] = {} failed[_uuid][_ip] = [_info['stderr']] if result['failed']: for _uuid, _info in result['failed'].iteritems(): _ip = _info['ansible_host'] if _info.has_key('stderr') and _info['stderr']: try: failed[_uuid][_ip].append(_info['stderr']) except: if not failed.has_key(_uuid): failed[_uuid] = {} failed[_uuid][_ip] = [_info['stderr']] if _info.has_key('stdout') and _info['stdout']: try: failed[_uuid][_ip].append(_info['stdout']) except: if not failed.has_key(_uuid): failed[_uuid] = {} failed[_uuid][_ip] = [_info['stdout']] if _info.has_key('msg') and \ _info['msg'] and \ "'full_data_dir' is undefined" not in _info['msg'] and \ not re.search(r'Could not find.*firewalld', _info['msg']): if _uuid in offline_list and re.search(r'the.*port.*is not up', _info['msg']): continue try: failed[_uuid][_ip].append(_info['msg']) except: if not failed.has_key(_uuid): failed[_uuid] = {} failed[_uuid][_ip] = [_info['msg']] if result['unreachable']: for _uuid, _info in result['unreachable'].iteritems(): _ip = _info['ansible_host'] if _info.has_key('stderr') and _info['stderr']: try: unreachable[_uuid][_ip].append(_info['stderr']) except: if not unreachable.has_key(_uuid): unreachable[_uuid] = {} unreachable[_uuid][_ip] = [_info['stderr']] if _info.has_key('stdout') and _info['stdout']: try: unreachable[_uuid][_ip].append(_info['stdout']) except: if not unreachable.has_key(_uuid): unreachable[_uuid] = {} unreachable[_uuid][_ip] = [_info['stdout']] if _info.has_key('msg') and _info['msg']: try: unreachable[_uuid][_ip].append(_info['msg']) except: if not unreachable.has_key(_uuid): unreachable[_uuid] = {} unreachable[_uuid][_ip] = [_info['msg']] if not failed and not unreachable: return result msg = {} msg['failed'] = failed msg['unreachable'] = unreachable raise exceptions.TiOPSRuntimeError(msg, result, tp='ansible') def run_playbook(self, playbook_path, extra_vars=None): """ 运行playbook """ try: self.callback = PlayBookResultsCollector() if extra_vars: 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.password, ) executor._tqm._stdout_callback = self.callback executor.run() except Exception as e: term.warn(str(e)) return False def __ansible_host(self, hostname=None): _ansible_host = self.variable_manager.get_vars(host=hostname)[ 'ansible_host'] if 'ansible_host' in self.variable_manager.get_vars(host=hostname) else \ self.variable_manager.get_vars(host=hostname)['inventory_hostname'] return _ansible_host 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 hostname = self.inventory.get_host(hostname=str(host)) self.results_raw['success'][host]['ansible_host'] = self.__ansible_host(hostname) for host, result in self.callback.host_failed.items(): self.results_raw['failed'][host] = result._result hostname = self.inventory.get_host(hostname=str(host)) self.results_raw['failed'][host]['ansible_host'] = self.__ansible_host(hostname) for host, result in self.callback.host_unreachable.items(): self.results_raw['unreachable'][host] = result._result hostname = self.inventory.get_host(hostname=str(host)) self.results_raw['unreachable'][host]['ansible_host'] = self.__ansible_host(hostname) return 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._result hostname = self.inventory.get_host(hostname=str(host)) self.results_raw['ok'][host]['ansible_host'] = self.__ansible_host(hostname) for host, result in self.callback.task_failed.items(): self.results_raw['failed'][host] = result._result hostname = self.inventory.get_host(hostname=str(host)) self.results_raw['failed'][host]['ansible_host'] = self.__ansible_host(hostname) for host, result in self.callback.task_status.items(): self.results_raw['status'][host] = result hostname = self.inventory.get_host(hostname=str(host)) self.results_raw['status'][host]['ansible_host'] = self.__ansible_host(hostname) for host, result in self.callback.task_skipped.items(): self.results_raw['skipped'][host] = result._result hostname = self.inventory.get_host(hostname=str(host)) self.results_raw['skipped'][host]['ansible_host'] = self.__ansible_host(hostname) for host, result in self.callback.task_unreachable.items(): self.results_raw['unreachable'][host] = result._result hostname = self.inventory.get_host(hostname=str(host)) self.results_raw['unreachable'][host]['ansible_host'] = self.__ansible_host(hostname) return self.results_raw
class MyInventory: def __init__(self, resource, loader, variable_manager): self.resource = resource self.loader = DataLoader() self.inventory = InventoryManager(loader=self.loader, sources=[host_list_file]) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) self.dynamic_inventory() def add_dynamic_group(self, hosts, group_name, group_vars=None): self.inventory.add_group(group_name) my_group = Group(name=group_name) if group_vars is not None: for k, v in group_vars.items(): my_group.set_variable(k, v) for host in hosts: hostname = host.get("hostname") hostip = host.get("ip", hostname) hostport = host.get("port", 22) username = host.get("username") password = host.get("password") ssh_key = host.get("ssh_key", "~/.ssh/id_rsa") my_host = Host(name=hostname, port=hostport) self.variable_manager.set_host_variable(host=my_host, varname="ansible_ssh_host", value=hostip) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_pass', value=password) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_port', value=hostport) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_user', value=username) self.variable_manager.set_host_variable( host=my_host, varname='ansible_ssh_private_key_file', value=ssh_key) for key, value in host.items(): if key not in ["hostname", "port", "username", "password"]: self.variable_manager.set_host_variable(host=my_host, varname=key, value=value) self.inventory.add_host(host=hostname, group=group_name, port=hostport) def dynamic_inventory(self): if isinstance(self.resource, list): self.add_dynamic_group(self.resource, "default_group") elif isinstance(self.resource, dict): for groupname, hosts_and_vars in self.resource.items(): self.add_dynamic_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
class AnsibleApi(object): def __init__(self, inventory_file, host_list, groupname): self.options = { 'verbosity': 0, 'ask_pass': False, 'private_key_file': None, 'remote_user': None, 'connection': 'smart', 'timeout': 10, 'ssh_common_args': '', 'sftp_extra_args': '', 'scp_extra_args': '', 'ssh_extra_args': '', 'force_handlers': False, 'flush_cache': None, 'become': False, 'become_method': 'sudo', 'become_user': None, 'become_ask_pass': False, 'tags': ['all'], 'skip_tags': [], 'check': False, 'syntax': None, 'diff': False, 'inventory': inventory_file, 'listhosts': None, 'subset': None, 'extra_vars': [], 'ask_vault_pass': False, 'vault_password_files': [], 'vault_ids': [], 'forks': 5, 'module_path': None, 'listtasks': None, 'listtags': None, 'step': None, 'start_at_task': None, 'args': ['fake'] } self.ops = Values(self.options) self.loader = DataLoader() self.passwords = dict() self.results_callback = ResultCallback() self.inventory = InventoryManager(loader=self.loader, sources=[self.options['inventory']]) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) self.result_playbook = PlayBookResultsCollector() self.results_raw = {} self.groupname = groupname self.host_list = host_list self.add_dynamic_group(self.host_list, self.groupname) def add_dynamic_group(self, hosts, groupname): self.inventory.add_group(groupname) # { # ip1: {key: value}, # ip2: {key: value}, # } for host in hosts: self.inventory.add_host(host, group=groupname) my_host = self.inventory.get_host(host) print('add {}'.format(host)) for var in hosts[host]: self.variable_manager.set_host_variable(host=my_host, varname=var, value=hosts[host][var]) print('print inventory') print(self.inventory.get_groups_dict()) def ansible_run(self, host_list, task_list): context._init_global_context(self.ops) play_source = dict(name="Ansible Play", hosts=host_list, gather_facts='no', tasks=task_list) play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader) tqm = None try: tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, # options=self.ops, passwords=self.passwords, stdout_callback=self.results_callback, run_additional_callbacks=C.DEFAULT_LOAD_CALLBACK_PLUGINS, run_tree=False, ) result = tqm.run(play) finally: if tqm is not None: tqm.cleanup() # shutil.rmtree(C.DEFAULT_LOCAL_TMP, True) results_raw = {} results_raw['success'] = {} results_raw['failed'] = {} results_raw['unreachable'] = {} for host, result in self.results_callback.host_ok.items(): results_raw['success'][host] = json.dumps(result._result) for host, result in self.results_callback.host_failed.items(): results_raw['failed'][host] = result._result['msg'] for host, result in self.results_callback.host_unreachable.items(): results_raw['unreachable'][host] = result._result['msg'] return results_raw def playbook_run(self, playbook_path): # self.variable_manager.extra_vars = {'customer': 'test', 'disabled': 'yes'} context._init_global_context(self.ops) playbook = PlaybookExecutor(playbooks=playbook_path, inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, passwords=self.passwords) playbook._tqm._stdout_callback = self.result_playbook C.HOST_KEY_CHECKING = False playbook.run() self.results_raw = { 'skipped': {}, 'failed': {}, 'ok': {}, "status": {}, 'unreachable': {}, "changed": {} } for host, result in self.result_playbook.task_ok.items(): self.results_raw['ok'][host] = json.dumps(result._result) for host, result in self.result_playbook.task_failed.items(): self.results_raw['failed'][host] = result._result['msg'] for host, result in self.result_playbook.task_status.items(): self.results_raw['status'][host] = result for host, result in self.result_playbook.task_skipped.items(): self.results_raw['skipped'][host] = result._result['msg'] for host, result in self.result_playbook.task_unreachable.items(): self.results_raw['unreachable'][host] = result._result['msg'] return self.results_raw
class MyInventory(): """ this is IOPS ansible inventory object. """ # myinvent = MyInventory(self.resource, self.loader, self.variable_manager) def __init__(self, resource, loader, variable_manager): self.resource = resource self.loader = DataLoader() self.inventory = InventoryManager(loader=self.loader, sources=['%s/conf/hosts' % BASE_DIR]) # self.variable_manager.set_inventory(self.inventory) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) # 自动执行dynamic_inventory self.dynamic_inventory() def add_dynamic_group(self, hosts, groupname, groupvars=None): """ add hosts to a group """ self.inventory.add_group(groupname) my_group = Group(name=groupname) # if group variables exists, add them to group if dict # groupvars={'var1': 'ansible', 'var2': 'saltstack'} if groupvars: for key, value in groupvars.iteritems(): my_group.set_variable(key, value) # if list hosts=resource [{"hostname": "192.168.1.111"}], if dict host=[{'username': u'root', 'ip': '192.168.1.11',}] # add hosts to group,all hosts is list for host in hosts: # set connection variables hostname = host.get("hostname") # 拿IP 没有IP就用hostname代替,没有IP一般是新增的 hostip = host.get('ip', hostname) hostport = host.get("port") username = host.get("username") password = host.get("password") ssh_key = host.get("ssh_key") my_host = Host(name=hostname, port=hostport) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_host', value=hostip) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_pass', value=password) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_port', value=hostport) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_user', value=username) self.variable_manager.set_host_variable( host=my_host, varname='ansible_ssh_private_key_file', value=ssh_key) # my_host.set_variable('ansible_ssh_pass', password) # my_host.set_variable('ansible_ssh_private_key_file', ssh_key) # set other variables for key, value in host.iteritems(): if key not in ["hostname", "port", "username", "password"]: self.variable_manager.set_host_variable(host=my_host, varname=key, value=value) # add to group self.inventory.add_host(host=hostname, group=groupname, port=hostport) ghost = Host(name="192.168.8.119") def dynamic_inventory(self): """ add hosts to inventory. """ if isinstance(self.resource, list): self.add_dynamic_group(self.resource, 'default_group') elif isinstance(self.resource, dict): for groupname, hosts_and_vars in self.resource.iteritems(): self.add_dynamic_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
class MyInventory(): ''' resource = [{'hostid': '1231', 'hostname': 'h1', 'hostip': '1.1.1.1'}, {'hostid': '2345', 'hostname': 'h2', 'hostip': '2.2.2.2'}, ] resource = {'groupname1': { 'hosts': [ {'hostid': '1231', 'hostname': 'h1', 'hostip': '1.1.1.1'}, {'hostid': '2231', 'hostname': 'h2', 'hostip': '1.1.1.2'}, ], 'groupvars': {"k1":"v1"} }, 'groupname2': {'hosts': [], 'groupvars': {}}, } ''' # edit ori code ansible/inventory/manage.pay line215 try if C.InventoryManager_PARSE_NOSOURCE:pass constants.InventoryManager_PARSE_NOSOURCE = True def __init__(self, resource): self.resource = resource self.loader = DataLoader() # self.inventory=InventoryManager(loader=self.loader,sources=['/etc/ansible/hosts']) self.inventory = InventoryManager(loader=self.loader) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) self._parse(self.resource) def _parse(self, resource): if isinstance(resource, list): self._addGroupHosts(self.resource) elif isinstance(resource, dict): # logging.info('parsing resuorce: %s'%(self.resource)) for groupname, hosts_and_groupvars in self.resource.items(): print("[1] groupname: %s |hostsandvars: %s" % (groupname, hosts_and_groupvars)) # debug [1] self._addGroupHosts(hosts_and_groupvars.get('hosts'), groupname, hosts_and_groupvars.get('groupvars')) else: logging.error('resource error ,need dict or list') def _addGroupHosts(self, hosts, groupname='default', groupvars=None): self.inventory.add_group(group=groupname) group = Group(groupname) if groupvars: for k, v in groupvars.items(): group.set_variable(k, v) # hosts=[{'hostid':'123','hostname':'h1','hostip':'192.168.188.20'} for host in hosts: hostid = host.get('hostid') hostname = host.get('hostname') hostip = host.get('hostip') username = host.get('username') password = host.get('password') port = host.get('port', 22) sshkey = host.get('sshkey') if hostname: self.inventory.add_host( host=hostname, group=groupname ) # by default, indentify by hostname and need hostobj = self.inventory.get_host( hostname=hostname) # add host= , get hostname= self.variable_manager.set_host_variable( host=hostobj, varname='ansible_ssh_host', value=hostip) self.variable_manager.set_host_variable( host=hostobj, varname='ansible_ssh_port', value=port) self.variable_manager.set_host_variable( host=hostobj, varname='ansible_ssh_user', value=username) self.variable_manager.set_host_variable( host=hostobj, varname='ansible_ssh_pass', value=password) self.variable_manager.set_host_variable( host=hostobj, varname='ansible_ssh_private_key_file', value=sshkey) # TODO: other vars such as become-method-user-pass #hostobj.set_variable('ansible_ssh_port',port) for k, v in host.items(): if k not in [ 'hostip', 'port', 'username', 'password', 'sshkey' ]: hostobj.set_variable(k, v) else: logging.warning('resource error:cant get hostname from | %s' % resource) def testcase(self): print(self.inventory.get_groups_dict()) host = self.inventory.get_host(hostname='h1') print(self.variable_manager.get_vars(host=host))
class MyInventory: """ Dynamic Creates and manages inventory By default, there are six group names """ def __init__(self, resources): self.resource = resources self.loader = DataLoader() self.inventory = InventoryManager( loader=self.loader, sources=['%s/conf/inventorys' % settings.BASE_DIR]) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) self.dynamic_inventory() def add_dynamic_group(self, hosts, groupname, groupvars=None): """ add hosts to a group """ self.inventory.add_group(groupname) my_group = Group(name=groupname) # if group variables exists, add them to group if groupvars: for key, value in groupvars.items(): my_group.set_variable(key, value) # add hosts to group for host in hosts: # set connection variables hostname = host.get("hostname", None) hostip = host.get('ip', None) if hostip is None: print("IP地址为空,跳过该元素。") continue hostport = host.get("port", 22) user = host.get("user", 'root') password = host.get("password", None) ssh_key = host.get("ssh_key", None) if hostname is None: hostname = hostip my_host = Host(name=hostname, port=hostport) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_port', value=hostport) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_host', value=hostip) self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_user', value=user) if password: self.variable_manager.set_host_variable( host=my_host, varname='ansible_ssh_pass', value=password) if ssh_key: self.variable_manager.set_host_variable( host=my_host, varname='ansible_ssh_private_key_file', value=ssh_key) # set other variables for key, value in host.items(): if key not in ["hostname", "port", "user", "password"]: self.variable_manager.set_host_variable(host=my_host, varname=key, value=value) # add to group self.inventory.add_host(host=hostname, group=groupname, port=hostport) def dynamic_inventory(self): """ add hosts to inventory. """ if isinstance(self.resource, list): self.add_dynamic_group(self.resource, 'default_group') elif isinstance(self.resource, dict): for groupname, hosts_and_vars in self.resource.items(): self.add_dynamic_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars")) elif isinstance(self.resource, str): return @property def INVENTORY(self): """ 返回资产实例 :return: """ return self.inventory @property def VARIABLE_MANAGER(self): """ 返回变量管理器实例 :return: """ return self.variable_manager
], "ungrouped":[ ], "test_group1":[ "192.168.1.80", "192.168.1.76", "192.168.1.77", "192.168.1.1" ] }, "omit":"__omit_place_holder__3909aaf2b72b39148f1cf8db39bfdb4745bec16d", "ansible_version":"Unknown" } """ variable_manager.set_host_variable(host=host, varname='ansible_ssh_pass', value='dsfnbhjkdasnfjkdsaf') print(variable_manager.get_vars(host=host)) # variable_manager.extra_vars 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', 'diff']) # 方法1 # ops = Values(Options) # context._init_global_context(ops)
class AnsibleApi(object): def __init__(self, hostinfo, taskinfo=None): self.resultinfo = [] self.taskinfo = taskinfo self.hostinfo = hostinfo self.host_list = [i.get("host", None) for i in self.hostinfo] self.sources = ",".join(self.host_list) if len(self.host_list) == 1: self.sources += "," self.passwords = dict() self.callback = None self.__initializeData() def __initializeData(self): 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", "diff" ]) self.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="sudo", become_user=None, verbosity=None, check=False, diff=False, ) self.loader = DataLoader() # 设置本次调用的host_list self.inventory = InventoryManager(loader=self.loader, sources=self.sources) # 加载之前的变量 self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) self.__set_hostinfo() def __set_hostinfo(self): # 设置调用主机认证信息 for host in self.hostinfo: self.inventory.add_host(host.get("host"), port=host.get("port")) hostname = self.inventory.get_host(hostname=host.get("host")) self.variable_manager.set_host_variable(host=hostname, varname='ansible_ssh_pass', value=host.get('password')) self.variable_manager.set_host_variable(host=hostname, varname='ansible_ssh_user', value=host.get('user')) self.variable_manager.set_host_variable(host=hostname, varname='ansible_ssh_port', value=host.get('port')) if host.get("sudo_pass"): self.variable_manager.set_host_variable( host=hostname, varname="ansible_become_user", value=host.get("sudo_user")) self.variable_manager.set_host_variable( host=hostname, varname="ansible_become_pass", value=host.get("sudo_pass")) self.variable_manager.set_host_variable( host=hostname, varname="ansible_become", value=True) if not host.get('password') or host.get('password') == "None": self.variable_manager.set_host_variable( host=hostname, varname="ansible_ssh_private_key_file", value=host.get("ansible_ssh_private_key_file")) def run_model(self): for task in self.taskinfo: play_source = dict(name="andible_api_play", hosts=self.host_list, gather_facts="no", tasks=[ dict(action=dict(module=task.get("module"), args=task.get("args"))) ]) play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader) tqm = None self.callback = ModelResultsCollector() try: tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, stdout_callback="minimal", ) tqm._stdout_callback = self.callback result = tqm.run(play) except Exception as err: import traceback print(traceback.print_exc()) finally: if tqm is not None: tqm.cleanup() @property def get_model_result(self): for host, result in self.callback.host_ok.items(): self.resultinfo.append( {host: { "message": result._result, "code": 0 }}) for host, result in self.callback.host_unreachable.items(): self.resultinfo.append( {host: { "message": result._result, "code": -1 }}) for host, result in self.callback.host_failed.items(): self.resultinfo.append( {host: { "message": result._result, "code": 1 }}) return self.resultinfo def run_playbook(self, PlayBookPath): try: self.callback = PlayBookResultsCollector() pbex = PlaybookExecutor(playbooks=[PlayBookPath], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, option=self.options, passwords=self.passwords) pbex._tqm._stdout_callback = self.callback pbex.run() except Exception as err: import traceback print(traceback.print_exc()) return False def get_playbook_result(self): for host, result in self.callback.host_ok.items(): self.resultinfo.append( {host: { "message": result._result, "code": 0 }}) for host, result in self.callback.host_unreachable.items(): self.resultinfo.append( {host: { "message": result._result, "code": -1 }}) for host, result in self.callback.host_failed.items(): self.resultinfo.append( {host: { "message": result._result, "code": 1 }}) for host, result in self.callback.task_status.items(): self.resultinfo.append( {host: { "message": result._result, "code": 2 }}) for host, result in self.callback.task_skipped.items(): self.resultinfo.append( {host: { "message": result._result, "code": 3 }}) return self.resultinfo
def run_ansible(module_name, module_args, host_list, ansible_user="******"): """ansible api""" # 负责查找和读取yaml、json和ini文件 loader = DataLoader() # 初始化需要的对象 Options = namedtuple('Options', [ 'connection', 'module_path', 'forks', 'become', 'become_method', 'private_key_file', 'become_user', 'remote_user', 'check', 'diff' ]) options = Options(connection='ssh', module_path=None, forks=5, become=True, become_method='sudo', private_key_file="/root/.ssh/id_rsa", become_user='******', remote_user=ansible_user, check=False, diff=False) passwords = dict(vault_pass='******') # 实例化ResultCallback来处理结果 callback = ResultsCollector() # 创建库存(inventory)并传递给VariableManager inventory = InventoryManager(loader=loader, sources='') for ip in host_list: inventory.add_host(host=ip, port=22) # 管理变量的类,包括主机,组,扩展等变量 variable_manager = VariableManager(loader=loader, inventory=inventory) for ip in host_list: host = inventory.get_host(hostname=ip) variable_manager.set_host_variable(host=host, varname='ansible_ssh_pass', value='lzx@2019') # 创建任务 host = ",".join(host_list) play_source = dict(name="Ansible Play", hosts=host, gather_facts='no', tasks=[ dict(action=dict(module=module_name, args=module_args), register='shell_out'), ]) play = Play().load(play_source, variable_manager=variable_manager, loader=loader) # 开始执行 tqm = None tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords, stdout_callback=callback, ) result = tqm.run(play) result_raw = {'success': {}, 'failed': {}, 'unreachable': {}} for host, result in callback.host_ok.items(): result_raw['success'][host] = result._result for host, result in callback.host_failed.items(): result_raw['failed'][host] = result._result for host, result in callback.host_unreachable.items(): result_raw['unreachable'][host] = result._result for host, result in callback.host_skipped.items(): result_raw['skipped'][host] = result._result return json.dumps(result_raw, indent=4, ensure_ascii=False)
VariableManager 实例化需要两个参数: 1. 参数一为读取yml文件的信息,需要实例化DataLoader。 2. 参数二为资产管理配置变量。 """ loader = DataLoader() inventory = InventoryManager(loader='', sources=ansible_host_sources) variable = VariableManager(loader=loader, inventory=inventory) # 获取变量 print(variable.get_vars()) host = inventory.get_host(hostname='django2.example.com') host_vars = variable.get_vars(host=host) print(host_vars) print('- ' * 80) # 设置主机变量方法,传入的host是inventory.get_host获得的主机对象 host = inventory.get_host(hostname='django2.example.com') variable.set_host_variable(host=host, varname='ansible_ssh_pass', value='12345') host_vars = variable.get_vars(host=host) print(host_vars) variable.set_host_variable(host=host, varname='ansible_ssh_pass', value='12345_again') host_vars = variable.get_vars(host=host) print(host_vars)
class Api(object): def __init__(self): # disable check the host key at ansible running C.HOST_KEY_CHECKING = False self._callback = None self._loader = DataLoader() self._inventory = InventoryManager(loader=self._loader, sources=",") self._variable_manager = VariableManager(loader=self._loader, inventory=self._inventory) self._tasks = [] def _parse_host(self, hosts): for host in hosts: hostname = host.get("hostname", None) if hostname is None: raise ValueError("error: not found hostname") port = host.get("port", 22) variables = host.get("vars", {}) self._add_host(hostname, port, variables) def _add_host(self, hostname, port, variables): self._inventory.add_host(host=hostname, port=port) host = self._inventory.get_host(hostname) for varname, value in variables.items(): self._set_variable(host, varname, value) def _set_variable(self, host, varname, value): self._variable_manager.set_host_variable(host, varname, value) def json(self): self._callback = JsonCallBack() return self def module(self, module, task_name=None, args=None, **kwargs): ''' Args: module: string, ansible模板名称 task_name: string, 此任务的名称,如果为None, 则使用模块名称 args: string, dict, 模块的参数 kwargs: dict, 任务的其它参数 Return: Api对象实例 ''' if args is not None: if isinstance(args, str) or isinstance(args, dict): self._tasks.append( dict(action=dict(module=module, args=args), name=task_name, **kwargs)) else: raise ValueError("args type is error") else: self._tasks.append( dict(action=dict(module=module), name=task_name, **kwargs)) return self def run(self, hosts, play_name="Ansible Play", gather_facts="no", callback=None, **kwargs): ''' Args: hosts: list, example: [ { "hostname": "127.0.0.1", "port": 22, "vars": { "asisble_ssh_pass": "******" } } ] play_name: string, ansible play name gather_facts: string, no/yes; 是否在运行任务前使用steup模块收集主机信息 callback: object, Ansible CallbackBase实现 kwargs: dict, 选项参数 ''' Options = namedtuple("Options", [ "connection", "module_path", "forks", "become", "become_method", "become_user", "check", "diff" ]) options = Options(connection=kwargs.get("connection", "smart"), module_path=kwargs.get("module_path", []), forks=kwargs.get("forks", 10), become=kwargs.get("become", None), become_method=kwargs.get("become_method", None), become_user=kwargs.get("become_method", None), check=kwargs.get("check", False), diff=kwargs.get("diff", False)) if self._callback is None: self._callback = callback self._parse_host(hosts) play_source = dict(name=play_name, hosts=[host["hostname"] for host in hosts], gather_facts=gather_facts, tasks=self._tasks) play = Play().load(play_source, variable_manager=self._variable_manager, loader=self._loader) tqm = None try: tqm = TaskQueueManager(inventory=self._inventory, variable_manager=self._variable_manager, loader=self._loader, options=options, passwords=dict(), stdout_callback=self._callback) tqm.run(play) finally: if tqm is not None: tqm.cleanup() shutil.rmtree(C.DEFAULT_LOCAL_TMP, True) results = getattr(self._callback, "results", None) return results