def __init__(self, mongoclient=None, redisclient=None): ''' 这是用户管理部分的MVC中的C ''' self.logger = logging.getLogger("devops") self.userinfo_mongocollect = 'user.login.info' self.userinfo_rediskey = 'devops:userinfo' self.privacy_mongocollect = 'user.privacy' if mongoclient is None : self.mongoclient = Op_Mongo() self.logger.warn('无法继承,需要初始化mongodb连接') else : self.mongoclient = mongoclient if redisclient is None : self.redisclient = Op_Redis() self.logger.warn('无法继承,需要初始化redis连接') else : self.redisclient = redisclient self.password_api = Manager_Password() self.expiretime = 60 * 60 * 24 self.rediskey_prefix = 'devops:'
def __init__(self): ''' 该class用于写日志到mongodb服务器中 __init__()用于初始化mongo ''' from library.connecter.database.mongo import Op_Mongo self.mongoclient = Op_Mongo(dest='log') self.default_log_dict = log_category_dict['default']
def __init__(self, mongoclient=None, redisclient=None): self.logger = logging.getLogger("weboper") if mongoclient is None: self.mongoclient = Op_Mongo() self.logger.warn('无法继承,需要初始化mongodb连接') else: self.mongoclient = mongoclient if redisclient is None: self.redisclient = Op_Redis() self.logger.warn('无法继承,需要初始化redis连接') else: self.redisclient = redisclient self.usermanager_api = Manager_User(mongoclient=self.mongoclient, redisclient=self.redisclient) self.privacy_api = Manager_Privacy(mongoclient=self.mongoclient, redisclient=self.redisclient) self.ansible_report_api = Manager_Report(mongoclient=self.mongoclient, redisclient=self.redisclient) self.ansible_option_api = Manager_Option(mongoclient=self.mongoclient, redisclient=self.redisclient) self.uri_api = Manager_Uri(mongoclient=self.mongoclient, redisclient=self.redisclient) self.inventory_api = Manager_Inventory(mongoclient=self.mongoclient, redisclient=self.redisclient)
def __init__(self, username, vault_passwd=None, mongoclient=None): self.logger = logging.getLogger("ansible") self.yaml_mongocollect = username + '.ansible.yaml' self.temp_basedir = '/dev/shm/devops/ansible/yaml/' self.username = username self.vault_passwd = vault_passwd if mongoclient is None : self.mongoclient = Op_Mongo() self.logger.warn('无法继承,需要初始化mongodb连接') else : self.mongoclient = mongoclient if vault_passwd is None or not vault_passwd : self.this_cipher = None # self.logger.warn('没有提供vault密码,不加载加解密模块') else : self.logger.warn('提供vault密码,加载加解密模块') self.this_cipher = Using_AES256(vault_passwd, vault_header) self.vault_header = vault_header
def __init__(self, oper, log_router=False, mongoclient=None): ''' 根据condition_dict读取所有的callback日志 :parm condition_dict:查询条件 ''' self.logger = logging.getLogger("ansible") if mongoclient is None: self.mongoclient = Op_Mongo() else: self.mongoclient = mongoclient if not log_router: from library.storage.logging import Routing_Logging log_router = Routing_Logging() self.log_router = log_router self.collect = oper + '.ansible.callback' self.log_dict = { 'level': 'info', 'dest': 'mongo', 'mongo': self.collect, }
from django.conf.urls import url # from django.contrib import admin from library.connecter.database.mongo import Op_Mongo from library.connecter.database.redis_api import Op_Redis # from lykops import settings from lykops.ansible.execute import Exec from lykops.ansible.options import Options from lykops.ansible.report import Report from lykops.ansible.yaml import Yaml from lykops.sysadmin.inventory import Inventory # from lykops.sysadmin.privacy import Privacy from lykops.sysadmin.user import User from lykops.views import Login mongoclient = Op_Mongo() redisclient = Op_Redis() urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^$', User(mongoclient=mongoclient, redisclient=redisclient).summary, name='index'), url(r'^login.html', Login(mongoclient=mongoclient, redisclient=redisclient).login, name='login'), url(r'^logout.html', Login(mongoclient=mongoclient, redisclient=redisclient).logout, name='logout'), url(r'^user/create_admin', Login(mongoclient=mongoclient, redisclient=redisclient).create_admin,
class Base(): def __init__(self, mongoclient=None, redisclient=None): ''' 这是用户管理部分的MVC中的C ''' self.logger = logging.getLogger("lykops") self.userinfo_mongocollect = 'user.login.info' self.userinfo_rediskey = 'lykops:userinfo' self.privacy_mongocollect = 'user.privacy' if mongoclient is None: self.mongoclient = Op_Mongo() self.logger.warn('无法继承,需要初始化mongodb连接') else: self.mongoclient = mongoclient if redisclient is None: self.redisclient = Op_Redis() self.logger.warn('无法继承,需要初始化redis连接') else: self.redisclient = redisclient self.password_api = Manager_Password() self.expiretime = 60 * 60 * 24 self.rediskey_prefix = 'lykops:' def get_userinfo(self, force=False, username=None): ''' 获取userinfo数据 ''' if force: self.logger.warn('强制删除用户信息缓存') self.redisclient.delete(self.userinfo_rediskey) result = self.redisclient.get(self.userinfo_rediskey, fmt='obj') if result[0] and (result[1] is not None or result[1]): userinfo = result[1] else: result = self.mongoclient.find(self.userinfo_mongocollect) if result[0]: userinfo = result[1] set_dict = { 'name': self.userinfo_rediskey, 'value': userinfo, 'ex': self.expiretime } self.redisclient.set(set_dict, fmt='obj') else: userinfo = {} if username is None: return userinfo else: try: for u_dict in userinfo: if username == u_dict['username']: us = u_dict else: continue except: us = {} try: return us except: return {} def verify_vaultpassword(self, username, vault_password): ''' 验证用户的vault密码是否正确 :parm username:用户名 vault_password:vault密码 ''' user_dict = self.get_userinfo(username=username) if not user_dict: content = '用户' + username + '不存在' self.logger.error(content) return (False, content) try: cipher_pwd = user_dict['vault_password'] except: content = '从数据库中没有查询到用户' + username + '的vault密码' self.logger.error(content) return (False, content) result = self.password_api.verify(vault_password, cipher_pwd) if not result: content = '用户' + username + '输入的vault密码与数据库中vault密码不匹配' self.logger.error(content) return (False, content) else: content = '用户' + username + '输入的vault密码与数据库中vault密码匹配成功' # self.logger.info(content) return (True, content) def get_data(self, username, redis_key, mongo_collect, force=False, mongoshare=True): ''' 获取用户数据 :parm username:用户名 redis_key:redis缓存key名 mongo_collect:mongo的集合名 force:强制刷新 ''' if force: self.logger.warn('强制删除指定缓存') self.redisclient.delete(redis_key) result = self.redisclient.get(redis_key, fmt='obj') if not result[0] or (result[0] and not result[1]): if mongoshare: result = self.mongoclient.find( mongo_collect, condition_dict={'username': username}) else: result = self.mongoclient.find(mongo_collect) if result[0]: data_dict = result[1] self.write_cache(redis_key, data_dict) else: self.logger.error('从数据库中查询数据失败,原因:' + result[1]) return result else: data_dict = result[1] try: del data_dict['username'] except: pass return (True, data_dict) def encryp_dict(self, username, vault_password, data, vault_list, isverify=True): ''' 对用户的数据字典中的某些字段进行加密 ''' encryp_api = Using_AES256(vault_password, vault_header) if isverify: vault_result = self.verify_vaultpassword(username, vault_password) if not vault_result[0]: self.logger.error('加密用户' + username + '的指定数据时失败,原因:输入的vault密码与数据库中vault密码不匹配') return (False, '输入的vault密码与数据库中vault密码不匹配') if not vault_list: vault_list = data.keys() encryp_dict = {} for key, value in data.items(): if not value: encryp_dict[key] = value if key in vault_list: result = encryp_api.encrypt(value) if result[0]: encryp_dict[key] = result[1] else: self.logger.error('加密用户' + username + '的指定数据时失败,键名' + key + '的值加密失败,原因:' + result[1]) return (False, '加密用户' + username + '的指定数据时失败,键名' + key + '的值加密失败,' + result[1]) else: if value == 'False': value = False if value == 'True': value = True isdigit = True if isinstance(value, str): for t in value: if t not in '0123456789': isdigit = False if isdigit: try: value = int(value) except: pass encryp_dict[key] = value # content = '加密用户' + username + '的指定数据成功' # self.logger.info(content) return (True, encryp_dict) def decryp_dict(self, username, vault_password, data, vault_list, isverify=True): ''' 对用户的数据字典中的某些字段进行解密 ''' encryp_api = Using_AES256(vault_password, vault_header) if isverify: vault_result = self.verify_vaultpassword(username, vault_password) if not vault_result[0]: self.logger.error('解密用户' + username + '的指定数据时失败,原因:输入的vault密码与数据库中vault密码不匹配') return (False, '输入的vault密码与数据库中vault密码不匹配') if not vault_list: vault_list = data.keys() decryp_dict = {} for key, value in data.items(): if not value: decryp_dict[key] = value if key in vault_list: result = encryp_api.decrypt(value) if result[0]: decryp_dict[key] = result[1] else: self.logger.error('解密用户' + username + '的指定数据时失败,键名' + key + '的值加密失败,原因:' + result[1]) return (False, '解密用户' + username + '的指定数据时失败,键名' + key + '的值加密失败,' + result[1]) else: if value == 'False': value = False if value == 'True': value = True decryp_dict[key] = value # content = '解密用户' + username + '的指定数据成功' # self.logger.info(content) return (True, decryp_dict) def encryp_string(self, username, vault_password, data, isverify=True): ''' 对用户的数据进行加密 ''' encryp_api = Using_AES256(vault_password, vault_header) if isverify: vault_result = self.verify_vaultpassword(username, vault_password) if not vault_result[0]: self.logger.error('加密用户' + username + '数据时失败,原因:输入的vault密码与数据库中vault密码不匹配') return (False, '加密用户' + username + '数据时失败,输入的vault密码与数据库中vault密码不匹配') result = encryp_api.encrypt(data) if result[0]: # content = '加密用户' + username + '数据成功' # self.logger.info(content) return (True, result[1]) else: self.logger.error('加密用户' + username + '数据失败,原因:' + result[1]) return (False, '加密用户' + username + '数据失败,' + result[1]) def decryp_string(self, username, vault_password, data, isverify=True): ''' 对用户的数据进行解密 ''' decryp_api = Using_AES256(vault_password, vault_header) if isverify: vault_result = self.verify_vaultpassword(username, vault_password) if not vault_result[0]: self.logger.error('解密用户' + username + '数据时失败,原因:输入的vault密码与数据库中vault密码不匹配') return (False, '解密用户' + username + '数据时失败,输入的vault密码与数据库中vault密码不匹配') result = decryp_api.decrypt(data) if result[0]: # content = '解密用户' + username + '数据成功' # self.logger.info(content) return (True, result[1]) else: self.logger.error('解密用户' + username + '数据失败,原因:' + result[1]) return (False, result[1]) def change_vltpwd_dict(self, username, old_pwd, new_pwd, vault_dict, vault_list, isverify=False): ''' 修改用户的vault数据(字典)的vault密码 ''' try: del vault_dict['add_time'] except: pass if not vault_list: vault_list = vault_dict.keys() # 不要使用encryp_dict和decryp_dict来更换密码,否则无法修改密码 new_data = {} for key, value in vault_dict.items(): if key in vault_list: result = self.decryp_string(username, old_pwd, value, isverify=isverify) if not result[0]: self.logger.error('更改用户' + username + '的vault密码时失败,解密数据时出错,原因:' + result[1]) return (False, '更改用户' + username + '的vault密码时失败,解密数据时出错,' + result[1]) new_value = result[1] result = self.encryp_string(username, new_pwd, new_value, isverify=isverify) if not result[0]: self.logger.error('更改用户' + username + '的vault密码时失败,解密后再次加密数据时出错,原因:' + result[1]) return (False, '更改用户' + username + '的vault密码时失败,解密后再次加密数据时出错,' + result[1]) new_data[key] = result[1] else: new_data[key] = value # content = '更改用户' + username + '的vault密码成功' # self.logger.info(content) return (True, new_data) def write_cache(self, redis_key, data, expire=60 * 60, ftm='obj'): try: self.logger.warn('强制删除缓存') self.redisclient.delete(redis_key) except: pass set_dict = {'name': redis_key, 'value': data, 'ex': expire} result = self.redisclient.set(set_dict, fmt=ftm) if result[0]: content = '写缓存成功' # self.logger.info(content) return (True, content) else: self.logger.info('写缓存失败,原因:' + result[1]) return (False, '写缓存失败,' + result[1])
class Yaml_Base(): def __init__(self, username, vault_passwd=None, mongoclient=None): self.logger = logging.getLogger("ansible") self.yaml_mongocollect = username + '.ansible.yaml' self.temp_basedir = '/dev/shm/devops/ansible/yaml/' self.username = username self.vault_passwd = vault_passwd if mongoclient is None : self.mongoclient = Op_Mongo() self.logger.warn('无法继承,需要初始化mongodb连接') else : self.mongoclient = mongoclient if vault_passwd is None or not vault_passwd : self.this_cipher = None # self.logger.warn('没有提供vault密码,不加载加解密模块') else : self.logger.warn('提供vault密码,加载加解密模块') self.this_cipher = Using_AES256(vault_passwd, vault_header) self.vault_header = vault_header def check_main(self, yaml_data): includefile_dict = {} roles_list = [] log_prefix = '校验类型为main或者是full_roles的ansible yaml语法规则,' for data in yaml_data : if not isinstance(data, dict) : self.logger.error(log_prefix + '未通过语法检测,原因:可能不是ansible格式的yaml文件') return (False, '可能不是ansible格式的yaml文件') key_list = data.keys() # if not ('hosts' in key_list and ('tasks' in key_list or 'roles' in key_list)) and 'include' not in key_list: if not ('hosts' in key_list and ('tasks' in key_list or 'roles' in key_list)): self.logger.error(log_prefix + '未通过ansible原生语法检测,原因:缺少hosts、tasks或者roles等必要的字段') return (False, '未通过ansible原生语法检测,缺少hosts、tasks或者roles等必要的字段') for key, value in data.items() : if key == 'include' : self.logger.error(log_prefix + '未通过本系统特定语法检测,原因:本系统禁止在入口文件中含有"- include:"字段。注:虽然原生ansible支持这样写') return (False, '未通过本系统特定的语法检测,本系统禁止在入口文件中含有"- include:"字段') if key == 'tasks' : if not isinstance(value, (list, tuple)) : self.logger.error(log_prefix + '未通过ansible原生语法检测,原因:tasks部分为空。') return (False, '未通过ansible原生语法检测,tasks部分为空。') for v in value : if not isinstance(v, dict) : self.logger.error(log_prefix + '未通过ansible原生语法检测,原因:tasks部分异常。') return (False, '未通过ansible原生语法检测,tasks部分异常。') for name , task in v.items() : if name == 'include' : result = self._isinclude(task) if not result[0] : return result includefile_dict[task] = 'tasks' ''' for file in task : result = self._isinclude(file) if not result[0] : return result includefile_dict[file] = 'tasks' ''' if key == 'roles' : if not isinstance(value, (list, tuple)) : self.logger.error(log_prefix + '未通过ansible原生语法检测,原因:roles部分为空。') return (False, '未通过ansible原生语法检测,roles部分为空。') for v in value : if not isinstance(v, dict) : self.logger.error(log_prefix + '未通过ansible原生语法检测,原因:roles部分异常。') return (False, '未通过ansible原生语法检测,roles部分异常。') kv = list(v.keys()) if not (len(kv) == 1 and 'role' in kv) : self.logger.error(log_prefix + '未通过ansible原生语法检测,原因:roles部分缺少role。') return (False, '未通过ansible原生语法检测,roles部分缺少role。') try : roles_name = v['role'] if not self._isrolesname(roles_name): self.logger.error(log_prefix + '未通过本系统特定语法检测,原因:roles名不符合本系统要求的,本系统要求roles只能是大小写、数字以及:。注:虽然原生ansible支持这样写。') return (False, '未通过本系统特定语法检测,roles名不符合本系统要求的,本系统要求roles只能是大小写、数字以及:。') roles_list.append(roles_name) except : self.logger.error(log_prefix + '未通过语法检测,原因:roles部分异常。') return (False, '未通过语法检测,roles部分异常。') self.logger.info(log_prefix + '通过语法检测') return (True, roles_list, includefile_dict) def check_include(self, yaml_data, file_type='main'): log_prefix = '校验类型为include的ansible yaml语法规则,' if file_type == 'main' : self.logger.error(log_prefix + '未通过本系统特定语法检测,原因:本系统禁止在入口文件中含有"- include:"字段。注:虽然原生ansible支持这样写。') return (False, '未通过本系统特定语法检测,本系统禁止在入口文件中含有"- include:"字段') if file_type == 'var' : if not isinstance(yaml_data, dict) : self.logger.error(log_prefix + '未通过ansible原生语法检测,原因:变量文件格式必须是键值对') return (False, '未通过ansible原生语法检测,变量文件格式必须是键值对') else : self.logger.info(log_prefix + '通过语法检测') return (True, '') for data in yaml_data : if not isinstance(data, dict) : self.logger.error(log_prefix + '未通过ansible原生语法检测,原因:语法错误') return (False, '未通过ansible原生语法检测,语法错误') if file_type != 'main' : deny_list = ('hosts', 'tasks', 'roles') key_list = data.keys() for deny in deny_list : if deny in key_list : self.logger.error(log_prefix + '未通过ansible原生语法检测,原因:含有非法字段' + deny) return (False, '未通过ansible原生语法检测,含有非法字段' + deny) for key in data : if key == 'include' : self.logger.error(log_prefix + '未通过本系统特定语法检测,原因:本系统不允许嵌套使用include。注:虽然原生ansible支持这样写。') return (False, '未通过本系统特定语法检测,本系统不允许嵌套使用include') self.logger.info(log_prefix + '通过语法检测') return (True, '') def check_roles(self, content_dict): ''' 检测roles语法是否正确 ''' log_prefix = '校验类型为roles的ansible yaml语法规则,' if 'tasks' not in content_dict : self.logger.error(log_prefix + '未通过ansible原生语法检测,原因:tasks/main.yaml不存在') return (False, '未通过ansible原生语法检测,tasks/main.yaml不存在') include_dict = {} for this_dir , content in content_dict.items() : result = self.yaml_loader(content, data_type='data') if result[0] : yaml_data = result[-1] else : self.logger.error(log_prefix + this_dir + '/main.yaml转化成yaml数据时失败,原因:' + result[1]) return (False, this_dir + '/main.yaml转化成yaml数据时失败,' + result[1]) result = self.check_roles_singlefile(yaml_data, this_dir) if result[0] : include_dict.update(result[1]) else : self.logger.error(log_prefix + this_dir + '/main.yaml未通过语法检测,原因:' + result[1]) return (False, this_dir + '/main.yaml未通过语法检测,' + result[1]) self.logger.info(log_prefix + '通过语法检测') return (True, include_dict) def check_roles_singlefile(self, yaml_data, this_dir): ''' 解析roles的每个文件 :parm yaml_data:yaml数据 this_dir:roles下的标准目录名 ''' include_dict = {} log_prefix = '校验' + this_dir + '/main.yaml语法规则,' if this_dir in ('handlers', 'tasks') : file_type = 'tasks' else : file_type = 'var' if this_dir == 'templates' : self.logger.info(log_prefix + '通过语法检测') return (True, include_dict) if file_type == 'var' : if isinstance(yaml_data, (list, tuple)) : return (False, '在role中' + this_dir + '文件不能含有键值对') else : self.logger.info(log_prefix + '通过语法检测') return (True, include_dict) if not isinstance(yaml_data, (list, tuple)) : return (False, '在role中' + this_dir + '文件语法错误') for data in yaml_data : if not isinstance(data, dict) : return (False, '在role中该文件不能含有键值对') for key, value in data.items() : if key == 'hosts' or key == 'tasks' or key == 'roles' : return (False, '在role中' + this_dir + '/main.yaml文件不能含有' + key + '关键字') if key == 'include': if this_dir == 'handlers' : return (False, '在role中' + this_dir + '/main.yaml文件不能含有' + key + '关键字') else : result = self._isinclude(value) if not result[0] : return result include_dict[value] = 'tasks' self.logger.info(log_prefix + '通过语法检测') return (True, include_dict) def yaml_loader(self, data, data_type='file'): ''' 将文件或者原始数据解析成yaml数据,如果是vault数据,将在这里解密 :parm data:路径或者原始数据 data_type:指定类型,文件或者原始数据 ''' if data_type == 'file' : log_prefix = '将yaml文件' + data + '的内容(必须为原始数据)解析为yaml格式的数据,' result = check_fileaccessible(data) if result[0] : filename = result[1] else : self.logger.error(log_prefix + '读取文件时失败,原因:' + result[1]) return (False, '读取文件时失败,' + result[1]) result = read_file(filename) if result[0] : content = result[1] else : self.logger.error(log_prefix + '读取文件时失败,原因:' + result[1]) return (False, '读取文件时失败,' + result[1]) else : log_prefix = '将原始yaml数据解析为yaml格式的数据,' content = data filename = '' # 是否写入文件中 result = yaml_loader(content, data_type='data') if result[0] : yaml_data = result[1] else : self.logger.error(log_prefix + '解析失败,原因:' + result[1]) return (False, '解析成yaml失败,' + result[1]) if not isinstance(yaml_data, (dict, list, tuple)) : self.logger.error(log_prefix + '解析失败,原因:该文件内容不是ansible支持的yaml数据') return (False, '解析成yaml失败,该文件内容不是ansible支持的yaml数据') self.logger.info(log_prefix + '解析成功') return (True, filename, content, yaml_data) def write2db(self, name, content, yaml_type, describe=''): # def write2db(self, this_path, content, yaml_type, describe='', name=''): ''' 把yaml原始数据写入数据库中 :parm this_path:通用该yaml(方式为roles或者include)的文件中写入的实际路径 content:yaml文件原始数据(可能是字典,也可能为字符串) yaml_type:yaml类型 name:yaml文件内容写入数据的名称 describe:yaml文件内容写入数据的描述 zhname:yaml文件内容写入数据的中文名称,很简短说明 ''' if not isinstance(name, str) : self.logger.error('将yaml原始数据写入数据库失败,原因:参数name必须为字符串') return (False, '参数name必须为字符串') log_prefix = '将名为' + name + '的yaml原始数据写入数据库,' result = self.get_name_list() if not result[0] : return result else : nametype_dict = result[1] if nametype_dict : try : if name in nametype_dict[yaml_type] : self.logger.error(log_prefix + '解析失败,原因:名称重复') return (False, '名称重复,请修改名称在保存,谢谢') except : pass insert_data = { 'name' : name, 'uuid' : str(uuid.uuid4()), # UUID不能作为roles或include名,只能用于查找标识 'content' : content, 'type' : yaml_type, 'describe' :describe, 'lastedit_ts' : 0 } insert_dict = { 'collect' : self.yaml_mongocollect, 'data' : insert_data } result = self.mongoclient.insert(insert_dict, addtime=True) self.logger.info('将名为' + name + '的yaml原始数据写入数据库成功') return result def edit2db(self, uuid_str, content, describe='', name=''): ''' 把修改后的yaml原始数据写入数据库中 :parm uuid_str:需要修改的UUID content:yaml文件原始数据(可能是字典,也可能为字符串) name:yaml文件内容写入数据的名称 describe:yaml文件内容写入数据的描述 zhname:yaml文件内容写入数据的中文名称,很简短说明 ''' log_prefix = '编辑数据库中uuid为' + uuid_str + '的yaml数据,' if not isinstance(name, str) : self.logger.error('编辑数据库中uuid为' + uuid_str + '的yaml数据失败,原因:参数name必须为字符串') return (False, '参数name必须为字符串') if not re.search('^[a-z|A-Z|0-9]{8}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{12}$', uuid_str) : self.logger.error(log_prefix + '参数提供错误,原因:参数uuid不是一个标准的UUID,标准的UUID格式为^[a-z|A-Z|0-9]{8}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{12}$') return (False, '参数uuid不是一个标准的UUID,标准的UUID格式为^[a-z|A-Z|0-9]{8}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{12}$') update_data = {'content' : content} result = self.read2db(uuid_str, word_field='uuid') if result[0] : try : yaml_type = result[1]['type'] old_name = result[1]['name'] except : return (False, '从数据库读取时出错') else : return result if name and old_name != name : result = self.get_name_list() if not result[0] : return result else : nametype_dict = result[1] if nametype_dict : if name in nametype_dict[yaml_type] : self.logger.error(log_prefix + '解析失败,原因:名称重复') return (False, '名称重复,请修改名称在保存,谢谢') update_data['name'] = name if describe and isinstance(describe, str): update_data['describe'] = describe update_data['lastedit_ts'] = time.time() update_dict = { 'collect' : self.yaml_mongocollect, 'data' : {"$set": update_data} } result = self.mongoclient.update({'uuid':uuid_str}, update_dict, addtime=False) self.logger.info(log_prefix + '写入数据库成功') return result def _write2file(self, content, filename): ''' 写入文件,如果处理加密数据等,应该放在这里 :parm content:写入的内容 filename:指定文件名 ''' if not isinstance(content, str) : self.logger.error('将yaml原始数据写入文件' + filename + '失败,原因:参数错误,content必须为字符串') return (False, '参数错误,content必须为字符串') result = write_file(filename , 'w' , content, force=True) if result[0] : self.logger.error('将yaml原始数据写入文件' + filename + '成功') return (True, filename) else : self.logger.error('将yaml原始数据写入文件' + filename + '失败,原因:' + result[1]) return (False, '写入文件失败,' + result[1]) def _isrolesname(self, roles_name): ''' 判断传入字符串是否符合本系统要求的roles名 :param word: 待判断字符串 :return: True:包含 False:不包含 ''' word_list = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789:' if not isinstance(roles_name, str) : return False for s in roles_name : if s not in word_list : return False return True def _isinclude(self,filename): ''' 判断传入字符串是否符合本系统要求的include :param word: 待判断字符串 :return: True:包含 False:不包含 ''' if re.search('^/', filename) : self.logger.error('检测include文件名是否符合本系统要求,' + filename + '不符合,原因:include文件不能为绝对路径') return (False, 'include文件不能为绝对路径') if re.search('^main\.', os.path.basename(filename)) : self.logger.error('检测include文件名是否符合本系统要求,' + filename + '不符合,原因:include文件名不能含有"main."字符') return (False, 'include文件名不能含有"main."字符') return (True, '') def get_abs(self): ''' 获取摘要信息 ''' get_field_list = ['name', 'uuid' , 'type' , 'describe'] result = self.mongoclient.find(self.yaml_mongocollect, get_field=get_field_list) return result def get_name_list(self): ''' 获取DB中的所有name和yaml_type ''' get_field_list = ['name', 'type'] result = self.mongoclient.find(self.yaml_mongocollect, get_field=get_field_list) if not result[0] : self.logger.error('从数据库中获取所有yaml数据的name和yaml_type时发生错误,原因:' + result[1]) return (False, '从数据库中获取所有yaml数据的name和yaml_type时发生错误,原因:' + result[1]) name_type_dict = {} name_list = result[1] for name_dict in name_list : name = name_dict['name'] yaml_type = name_dict['type'] if yaml_type not in name_type_dict : name_type_dict[yaml_type] = [] name_type_dict[yaml_type].append(name) else : name_type_dict[yaml_type].append(name) return (True, name_type_dict) def read2db(self, word, word_field='name'): ''' 从数据库读取 :parm word:关键字 word_field:根据那个字段(name或者UUID)作为关键字查找 ''' if word is None or not word or not isinstance(word, str) : self.logger.error('从数据库通过关键字查找的yaml数据失败,原因:参数word必须为不为空字符串') return (False, '参数word必须为不为空字符串') if re.search('^[a-z|A-Z|0-9]{8}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{4}-[a-z|A-Z|0-9]{12}$', word) : word_field = 'uuid' if word_field == 'uuid' : result = self.mongoclient.find(self.yaml_mongocollect, condition_dict={word_field:word}) elif word_field in ('name') : result = self.mongoclient.find(self.yaml_mongocollect, limits=1, condition_dict={word_field:word}, sort_dict={'add_time':-1}) else : result = self.mongoclient.find(self.yaml_mongocollect, limits=1, condition_dict={word_field:word}, sort_dict={'add_time':-1}) if not result[0] : self.logger.error('从数据库查找关键字类型为' + word_field + ',关键字为' + word + '的yaml数据失败,原因:' + str(result[1])) return (False, '查询失败,' + str(result[1])) try : get_dict = result[1][0] return (True, get_dict) except : if not result[1] : self.logger.error('从数据库查找关键字类型为' + word_field + ',关键字为' + word + '的yaml数据失败,原因:查询结果为空') return (False, '查询结果为空') else : self.logger.error('从数据库查找关键字类型为' + word_field + ',关键字为' + word + '的yaml数据失败,原因:查询结果数据类型异常') return (False, '查询结果数据类型异常') def data2file(self, content, this_path='', yaml_type='main', name='main'): ''' 写入临时文件 :parm content:yaml的原始内容 this_path:写入的目录,如果提供按照指定目录写入,如果不指定随机目录 yaml_type:yaml类型。main、include、roles、full_roles四种 name:用于确认include和roles的文件名 ''' if not this_path or not re.search('^/', this_path): this_path = self.temp_basedir + '/' + random_str() + str(int(time.time())) + '/' def type_roles(content_dict, roles_name): ''' 专用于类型为roles的数据写入 ''' for this_dir in content_dict : # roles_path = this_path + '/roles/' + os.path.basename(roles_name) + '/' + this_dir roles_path = this_path + '/roles/' + roles_name + '/' + this_dir if this_dir == 'templates' : for temp_file , temp_content in content_dict[this_dir].items() : filename = roles_path + '/' + temp_file result = self._write2file(temp_content, filename) if not result[0] : self.logger.error('将roles名为' + roles_name + '中的文件名为' + this_dir + '/' + temp_file + 'yaml数据内容写入文件' + filename + '失败,' + result[1]) return (False, '将roles名为' + roles_name + '中的文件名为' + this_dir + '/' + temp_file + 'yaml数据内容写入文件' + filename + '失败,' + result[1]) else : self.logger.info('将roles名为' + roles_name + '中的文件名为' + this_dir + '/' + temp_file + 'yaml数据内容写入文件' + filename + '成功') else : filename = roles_path + '/main.yaml' result = self._write2file(content_dict[this_dir], filename) if not result[0] : self.logger.error('将roles名为' + roles_name + '中的文件名为' + this_dir + '/main.yaml数据内容写入文件' + filename + '失败,' + result[1]) return (False, '将roles名为' + roles_name + '中的文件名为' + this_dir + '/main.yaml数据内容写入文件' + filename + '失败,' + result[1]) else : self.logger.info('将roles名为' + roles_name + '中的文件名为' + this_dir + '/main.yaml数据内容写入文件' + filename + '成功') return (True, this_path) log_prefix = '将yaml数据内容写入文件' if isinstance(content, str) : filename = this_path + name + '.yaml' result = self._write2file(content, filename) return result if not isinstance(content, dict) : self.logger.error(log_prefix + '失败,原因:数据写入数据库时出现错误') return (False, '数据写入数据库时出现错误') if yaml_type == 'roles' : result = type_roles(content, name) else : try : roles_dict = content['roles'] for roles_name in roles_dict : roles_content_dict = roles_dict[roles_name] result = type_roles(roles_content_dict, roles_name) except Exception as e : print(e) roles_dict = {} try : include_dict = content['include'] for incluce_file , incluce_content in include_dict.items() : filename = this_path + '/' + incluce_file result = self._write2file(incluce_content, filename) if not result[0] : self.logger.error(log_prefix + '失败,路径为' + filename + ',原因:' + str(result[1])) return (False, log_prefix + '失败,路径为' + filename + ',' + str(result[1])) except Exception as e : print(e) include_dict = {} try : main_content = content['main'] filename = this_path + '/main.yaml' result = self._write2file(main_content, filename) if not result[0] : self.logger.error(log_prefix + '失败,路径为' + filename + ',原因:' + str(result[1])) return (False, log_prefix + '失败,路径为' + filename + ',原因:' + str(result[1])) except Exception as e : print(e) main_content = '' self.logger.info(log_prefix + '成功,路径为' + this_path) return (True, this_path)
class Parse_Cblog(): def __init__(self, oper, log_router=False, mongoclient=None): ''' 根据condition_dict读取所有的callback日志 :parm condition_dict:查询条件 ''' self.logger = logging.getLogger("ansible") if mongoclient is None: self.mongoclient = Op_Mongo() else: self.mongoclient = mongoclient if not log_router: from library.storage.logging import Routing_Logging log_router = Routing_Logging() self.log_router = log_router self.collect = oper + '.ansible.callback' self.log_dict = { 'level': 'info', 'dest': 'mongo', 'mongo': self.collect, } def parse(self, uuid_str): ''' 根据uuid_str读取callback日志 ''' log_prefix = '查询uuid为' + uuid_str + '的ansible任务执行报表' result = self.log_router.read(condition_dict={'uuid': uuid_str}, log_dict=self.log_dict, limit=0, lastest_field=False) self.readlog_list = result[1] if not result[0]: self.logger.error(log_prefix + '失败,原因:' + result[1]) return (False, log_prefix + '失败,' + result[1]) try: name = self.readlog_list[0]['name'] exec_mode = self.readlog_list[0]['mode'] describe = self.readlog_list[0]['describe'] options = self.readlog_list[0]['options'] # create_time = self.readlog_list[0]['create_time'] create_date = self.readlog_list[0]['create_date'] inventory_content = self.readlog_list[0]['inventory_content'] create_ts = self.readlog_list[0]['add_time'] finish_ts = self.readlog_list[-1]['add_time'] except Exception as e: self.logger.error(log_prefix + '失败,原因:该任务还没有开始执行或者数据错误,' + str(e)) return (False, '该任务还没有开始执行或者数据错误') pattern = self.readlog_list[0].get('pattern', None) module_name = self.readlog_list[0].get('module_name', None) module_args = self.readlog_list[0].get('module_args', None) yaml_content = self.readlog_list[0].get('yaml_content', None) play = self.readlog_list[0].get('play', {}) task = self.readlog_list[0].get('task', {}) newlog_dict = { 'name': name, 'mode': exec_mode, 'describe': describe, 'create_time': timestamp2datetime(create_ts), 'create_date': create_date, 'options': options, 'uuid': uuid_str, 'inventory_content': inventory_content, 'end_time': timestamp2datetime(finish_ts), 'duration': round((finish_ts - create_ts), 3), } if exec_mode == 'adhoc': newlog_dict['pattern'] = pattern newlog_dict['module_name'] = module_name newlog_dict['module_args'] = module_args else: newlog_dict['yaml_content'] = yaml_content get_field_list = ['uuid', 'play_id', 'task_id'] result = self.mongoclient.group_by(self.collect, get_field_list) if not result[0]: self.logger.error(log_prefix + '失败,原因:该任务还没有开始执行或者数据错误,' + result[1]) return (False, '该任务还没有开始执行或者数据错误') tempplay_dict = {} for playid in result[1]: if playid['uuid'] == uuid_str: play_id = playid['play_id'] task_id = playid.get('task_id', '') if task_id == '': continue else: continue if play_id not in tempplay_dict: tempplay_dict[play_id] = [] taskid_list = tempplay_dict[play_id] taskid_list.append(task_id) taskid_list = tempplay_dict[play_id] taskid_list = list(set(taskid_list)) taskid_list = sorted(taskid_list) # 对taskid执行先后顺序排序 tempplay_dict[play_id] = taskid_list playid_dict = {} for play_id in sorted(tempplay_dict): playid_dict[play_id] = tempplay_dict[play_id] # 对play执行先后顺序排序 play_dict = {} # 下面这个循环用于:根据play_id获取下面所有的task_id,并获取的每个task_id的最后日志和执行结果信息 for playid, taskid_list in playid_dict.items(): play_dict[playid] = {} for taskid in taskid_list: task_list = [] for line in self.readlog_list: if line['play_id'] == playid and line.get('task_id', '') == taskid: summary = line.get('summary', {}) if not summary: task_list.append(line) last_log = task_list[-1] # 求这个任务执行的最后一条日志 play_dict[playid]['play'] = last_log.get('play', {}) play_dict[playid]['summary'] = summary task_dict = { 'task': last_log.get('task', {}), 'detail': last_log.get('detail', {}), } try: play_dict[playid]['task'][taskid] = task_dict except: play_dict[playid]['task'] = {} play_dict[playid]['task'][taskid] = task_dict if not play_dict or not isinstance(play_dict, dict): self.logger.error(log_prefix + '失败,原因:该任务还没有开始执行或者查询条件错误,' + result[1]) return (False, {'result': '该任务还没有开始执行或者查询条件错误'}) result_dict = {} for play_uuid, logline in play_dict.items(): result_dict[play_uuid] = {} summary = logline.get('summary', {}) task_dict = logline.get('task', {}) if 'tasks' not in result_dict[play_uuid]: result_dict[play_uuid]['tasks'] = {} play = logline.get('play', {}) pattern = play.get('name', {}) for task_id, line in task_dict.items(): task = line.get('task', {}) task_name = task.get('name', '') taskmodule = task.get('module', '') # task_args = task.get('args', {}) if exec_mode == 'playbook' and task_name not in result_dict[ play_uuid]['tasks']: result_dict[play_uuid]['tasks'][task_name] = {} new_task = { 'module': task['module'], } result_dict[play_uuid]['tasks'][task_name][ 'tasks'] = new_task detail = line.get('detail', {}) if not isinstance(detail, dict) or not detail: continue for host, value in detail.items(): end_ts = value['end_ts'] start_ts = value['start_ts'] duration = end_ts - start_ts duration = round(duration, 2) ''' if taskmodule == 'yum' and 'invocation' in value : # 在yum模块中,在没有使用循环的情况下,value也含有results的key results = [value] else : results = value.get('results', {}) if results : data_list = results else : data_list = [value] # data_list = [value] ''' data_list = [value] for data in data_list: from library.connecter.ansible.callback.module import Parse_Result parse_module = Parse_Result() if taskmodule == 'command': result = parse_module.command(data, task) elif taskmodule == 'yum': if 'invocation' in data: result = parse_module.yum(data, task) else: try: temp_dict = data['results'][0] del data['results'] data.update(temp_dict) result = parse_module.yum(data, task) except: self.logger.error(data) result = parse_module.common_module( data, task, {}) elif taskmodule == 'service' or taskmodule == 'systemd': result = parse_module.service(data, task) elif taskmodule == 'script': result = parse_module.script(data, task) elif taskmodule == 'cron': result = parse_module.cron(data, task) elif taskmodule == 'user': result = parse_module.user(data, task) elif taskmodule == 'copy': result = parse_module.copy(data, task) elif taskmodule == 'get_url': result = parse_module.get_url(data, task) elif taskmodule == 'raw': result = parse_module.command(data, task) else: result = parse_module.common_module(data, task, {}) if taskmodule == '': print(result) if exec_mode == 'playbook': try: del result['模块名'] except: pass if 'detail' not in result_dict[play_uuid]['tasks'][ task_name]: result_dict[play_uuid]['tasks'][task_name][ 'detail'] = {} result_dict[play_uuid]['tasks'][task_name][ 'detail'][host] = result result_dict[play_uuid]['pattern'] = pattern else: try: del result['模块名'] del result_dict[play_uuid] except: pass result_dict[host] = result if exec_mode == 'playbook': result_dict[play_uuid]['summary'] = {} if isinstance(summary, dict): for host in summary: ok = summary[host].get('ok', 0) failures = summary[host].get('failures', 0) unreachable = summary[host].get('unreachable', 0) changed = summary[host].get('changed', 0) skipped = summary[host].get('skipped', 0) if ok == 0: if unreachable == 1: summary_str = '该任务在该主机上执行失败,无法连接远程主机' else: summary_str = '该任务在该主机上执行失败,失败数为' + str( failures) + ',跳过数为' + str( skipped) + ',可能产生变化数为' + str(changed) else: summary_str = '该任务在该主机上执行部分或者全部成功,成功数为' + str( ok) + ',失败数为' + str(failures) + ',跳过数为' + str( skipped) + ',可能产生变化数为' + str(changed) ''' result_dict[play_uuid]['summary'][host] = summary[host] 原文输出 ''' result_dict[play_uuid]['summary'][host] = summary_str if not result_dict[play_uuid]['summary']: result_dict[play_uuid]['summary'] = '该任务还没有执行完成' newlog_dict['exec_result'] = result_dict self.logger.info(log_prefix + '成功') return (True, newlog_dict) def get_abs(self): ''' 获取该用户下所有的执行任务的摘要 ''' get_field_list = [ 'name', 'uuid', 'mode', 'create_time', 'describe', 'create_date' ] result = self.mongoclient.group_by(self.collect, get_field_list) if not result[0]: self.logger.error('ansible任务执行报表清单查询失败,原因:' + result[1]) return result work_list = result[1] if len(work_list) == 0: self.logger.warn('ansible任务执行报表清单为空') return (True, []) date_list = [] for work in work_list: create_date = work['create_time'] if create_date not in date_list: date_list.append(create_date) date_list = sorted(date_list) date_list.reverse() new_list = [] for date_str in date_list: for work_dict in work_list: if date_str == work_dict['create_time']: new_list.append(work_dict) return (True, new_list)
class Logging_Mongo(): def __init__(self): ''' 该class用于写日志到mongodb服务器中 __init__()用于初始化mongo ''' from library.connecter.database.mongo import Op_Mongo self.mongoclient = Op_Mongo(dest='log') self.default_log_dict = log_category_dict['default'] def write(self, content, oper, log_dict={}): ''' 写入mongo数据库 :参数 log_dict : 存储信息 oper : 操作者 content : 日志内容 isdubug:是否为debug日志 :返回 一个元组,(False,原因)或者(True, 结果) ''' if not log_dict or not isinstance(log_dict, dict): log_dict = self.default_log_dict try: dest = log_dict['dest'] if dest != 'mongo': level = self.default_log_dict['level'] collect = self.default_log_dict['mongo'] else: level = log_dict['level'] if level not in level_list: level = self.default_log_dict['level'] collect = log_dict['mongo'] except Exception as e: return (False, str(e)) if not oper: oper = 'unknown' if not content: return (False, '日志内容为空!!!!') msg_dict = {} if isinstance(content, dict): msg_dict.update(content) else: msg_dict['content'] = content insert_dict = {'collect': collect, 'data': msg_dict} result = self.mongoclient.insert(insert_dict, addtime=True) return result def read(self, get_field=[], condition_dict={}, log_dict={}, limit=0, lastest_field=False): ''' 读取mongo数据库的日志 :参数 log_dict : 日志存储信息 condition_dict : 查询条件 get_field_list : 获取字段列表 limit : 限制获取多少条数据 lastest_field : 获取该字段最新一条数据 ''' if log_dict == {} or not log_dict or not isinstance(log_dict, dict): return (False, '参数log_dict配置错误,必须是一个不为空的字典') if condition_dict == {} or not condition_dict or not isinstance( condition_dict, dict): return (False, '参数condition_dict必须是一个不为空的字典,查询条件') if not isinstance(get_field, (list, tuple, dict)): get_field = [] try: collect = log_dict['mongo'] except Exception as e: return (False, '参数log_dict配置错误,提供的内容为' + str(log_dict) + ',失败原因为' + str(e)) try: limit = int(limit) except: limit = 0 if lastest_field: limit = 0 result = self.mongoclient.find(collect, get_field=get_field, condition_dict=condition_dict, limits=limit, sort_dict={'add_time': 1}) if not result[0]: return result content_list = result[1] content_len = len(content_list) if content_len == 0: return (True, []) elif content_len == 1: return (True, [content_list[0]]) else: if not lastest_field: return (True, content_list) results = '' lastest_time = 0.0 for line in content_list: if lastest_field in line: addtime = line[lastest_field] try: addtime = float(addtime) except: addtime = str(addtime) from library.utils.time_conv import datetime2timestamp addtime = datetime2timestamp(addtime) if not addtime: addtime = 0.0 else: addtime = float(addtime) if addtime >= lastest_time: lastest_time = addtime results = line if results == '': return (True, [content_list[-1]]) return (True, [results])
def __init__(self, mongoclient=None, redisclient=None): self.logger = logging.getLogger("devops") if mongoclient is None : self.mongoclient = Op_Mongo() self.logger.warn('无法继承,需要初始化mongodb连接') else : self.mongoclient = mongoclient if redisclient is None : self.redisclient = Op_Redis() self.logger.warn('无法继承,需要初始化redis连接') else : self.redisclient = redisclient self.redis_key_prefix = 'devops:' self.expiretime = 60 * 60 * 24 self.uridict = { '/':{'name':'首页', 'nav':False, 'referer' : True, 'level':0, 'user_level':0,'parent':'/'}, '/login.html':{'name':'登陆', 'nav':False, 'referer' : False, 'level':1, 'user_level':0,'parent':'/'}, '/logout.html':{'name':'退出', 'nav':False, 'referer' : False, 'level':1, 'user_level':0,'parent':'/'}, '/user/':{'name':'用户管理', 'nav':True, 'referer' : True, 'level':1, 'user_level':2,'parent':'/'}, '/user/create_admin':{'name':'创建管理员', 'nav':False, 'referer' : True, 'level':2, 'user_level':2,'parent':'/user/'}, '/user/detail':{'name':'用户信息', 'nav':False, 'referer' : True, 'level':2, 'user_level':2,'parent':'/user/'}, '/user/list':{'name':'用户列表', 'nav':False, 'referer' : True, 'level':2, 'user_level':2,'parent':'user/'}, '/user/add':{'name':'新增用户', 'nav':False, 'referer' : True, 'level':2, 'user_level':2,'parent':'/user/'}, '/user/edit':{'name':'编辑用户', 'nav':False, 'referer' : True, 'level':2, 'user_level':2,'parent':'/user/'}, '/user/chgpwd':{'name':'修改用户登陆密码', 'nav':False, 'referer' : True, 'level':2, 'user_level':2,'parent':'/user/'}, '/user/chgpvltwd':{'name':'修改用户机密密码 ', 'nav':False, 'referer' : True, 'level':2, 'user_level':2,'parent':'/user/'}, '/user/del':{'name':'删除用户', 'nav':False, 'referer' : False, 'level':2, 'user_level':2,'parent':'/user/'}, '/user/disable':{'name':'禁用用户', 'nav':False, 'referer' : False, 'level':2, 'user_level':2,'parent':'/user/'}, '/user/enable':{'name':'启用用户', 'nav':False, 'referer' : False, 'level':2, 'user_level':2,'parent':'/user/'}, # '/privacy/' :{'name':'隐私数据管理', 'nav':True, 'referer' : True, 'level':1, 'parent':'/'}, # '/privacy/detail' :{'name':'查看隐私数据', 'nav':False, 'referer' : True, 'level':2, 'parent':'/privacy/'}, # '/privacy/edit' :{'name':'编辑隐私数据', 'nav':False, 'referer' : True, 'level':2, 'parent':'/privacy/'}, '/inventory/' :{'name':' 主机管理', 'nav':True, 'referer' : True, 'level':1, 'user_level':0,'parent':'/'}, '/inventory/list' :{'name':' 主机管理', 'nav':False, 'referer' : True, 'level':2, 'user_level':0,'parent':'/inventory/'}, '/inventory/add' :{'name':' 增加主机', 'nav':False, 'referer' : True, 'level':2, 'user_level':0,'parent':'/inventory/'}, '/inventory/edit' :{'name':' 编辑主机', 'nav':False, 'referer' : True, 'level':2, 'user_level':0,'parent':'/inventory/'}, '/inventory/detail' :{'name':' 主机详细信息', 'nav':False, 'referer' : True, 'level':2, 'user_level':0,'parent':'/inventory/'}, '/ansible/' :{'name':'ansible', 'nav':True, 'referer' : True, 'level':1, 'user_level':0,'parent':'/'}, '/ansible/exec/adhoc' :{'name':'执行临时任务', 'nav':True, 'referer' : True, 'level':2, 'user_level':0,'parent':'/ansible/'}, '/ansible/exec/playbook' :{'name':'执行playbook任务', 'nav':True, 'referer' : True, 'level':2, 'user_level':1,'parent':'/ansible/'}, '/ansible/option/' :{'name':'查看配置', 'nav':True, 'referer' : True, 'level':2, 'user_level':0,'parent':'/ansible/'}, '/ansible/option/detail' :{'name':'查看配置', 'nav':True, 'referer' : True, 'level':3, 'user_level':0,'parent':'/ansible/option/'}, '/ansible/option/edit' :{'name':'编辑配置', 'nav':False, 'referer' : True, 'level':3, 'user_level':0,'parent':'/ansible/option/'}, '/ansible/yaml/' :{'name':'yaml数据列表', 'nav':True, 'referer' : True, 'level':2, 'user_level':1,'parent':'/ansible/'}, '/ansible/yaml/list' :{'name':'yaml数据列表', 'nav':False, 'referer' : True, 'level':3, 'user_level':1,'parent':'/ansible/yaml/'}, '/ansible/yaml/add' :{'name':'新增yaml数据', 'nav':False, 'referer' : False, 'level':3, 'user_level':1,'parent':'/ansible/yaml/'}, '/ansible/yaml/edit' :{'name':'编辑yaml数据', 'nav':False, 'referer' : True, 'level':3, 'user_level':1,'parent':'/ansible/yaml/'}, '/ansible/yaml/detail' :{'name':'查看yaml数据', 'nav':False, 'referer' : True, 'level':3, 'user_level':1,'parent':'/ansible/yaml/'}, '/ansible/yaml/import' :{'name':'导入yaml数据', 'nav':False, 'referer' : True, 'level':3, 'user_level':1,'parent':'/ansible/yaml/'}, '/ansible/report/' :{'name':'报告', 'nav':True, 'referer' : True, 'level':2, 'user_level':0,'parent':'/ansible/'}, '/ansible/report/list' :{'name':'报告列表', 'nav':False, 'referer' : True, 'level':3, 'user_level':0,'parent':'/ansible/report/'}, '/ansible/report/detail' :{'name':'单个报告详细信息', 'nav':False, 'referer' : True, 'level':3, 'user_level':0,'parent':'/ansible/report/'}, }
def __init__(self, exec_mode, work_name, username, options_dict, describe, mongoclient=None): ''' ansible的基类,为adhoc、playbook等父类 :parm: exec_mode:ansible工作类型,接受adhoc、palybook等 work_name:该任务的名称,用于日志 username:执行者 options_dict:该任务的特定设置 mongoclient:初始化mongo连接类 ''' self.logger = logging.getLogger("ansible") if exec_mode in ('adhoc', 'playbook'): self.exec_mode = exec_mode else: self.logger.warn( '正在准备执行ansible任务,准备工作失败,原因:参数exec_mode必须是adhoc或者是playbook') return (False, '参数exec_mode必须是adhoc或者是playbook') if isinstance(work_name, str) and work_name: self.work_name = work_name else: self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数work_name必须是非字符串') return (False, '参数work_name必须是非字符串') if isinstance(username, str) and username: self.username = username else: self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数username必须是非字符串') return (False, '参数username必须是非字符串') if isinstance(options_dict, dict) and options_dict: self.options_dict = options_dict else: self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数options_dict必须是非空字典') return (False, '参数options_dict必须是非空字典') if mongoclient is None: self.mongoclient = Op_Mongo() else: self.mongoclient = mongoclient self.work_uuid = str(uuid.uuid4()) self.log_router = Routing_Logging() self.describe = describe if exec_mode == 'adhoc': self.log_prefix = '正在执行用户' + username + '的名为' + work_name + 'uuid为' + self.work_uuid + '的ansible临时任务,' else: self.log_prefix = '正在执行用户' + username + '的名为' + work_name + 'uuid为' + self.work_uuid + '的ansible-playbook任务,' # 下面是加载和初始化相关类 self._parse_options() self.passwords = { 'conn_pass': self.options.ask_pass, 'become_pass': self.options.become_ask_pass } # 设置passwords self.inventory_file = self.options_dict.get('inventory', '') self.loader = DataLoader() self._get_vault_pwd() self.variable_manager = VariableManager() self.variable_manager.extra_vars = load_extra_vars( loader=self.loader, options=self.options) self.variable_manager.options_vars = load_options_vars(self.options) self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=self.inventory_file) self.variable_manager.set_inventory(self.inventory) self.inventory.subset(self.options.subset)