class HashGenerator : def __init__(self): self.log = SysLog() self.moduleMap = { 'User' : 'os_user', 'UserGlobal' : 'os_userglobal', 'KernelGlobal' : 'os_kernelglobal', 'Log' : 'os_log', 'Package' : 'os_package', 'Security' : 'os_security', 'Service' : 'os_service', 'TimeSyncClient' : 'os_timesyncclient', 'Group' : 'os_user', 'AuthorizationSSH' : 'os_authorizationssh', } self.paramClass = {} def classParamCollector(self, modelList): titleList = [] for key, value in modelList.items() : param = value.generateParamClass() tempTitle = param.keys()[0] if tempTitle in titleList : self.paramClass[tempTitle].update(param[tempTitle]) continue result = self.paramClass.update(param) titleList.append(param.keys()[0]) def generateParamClass(self): raise NotImplementedError('generateParamClass Not Implemented') def generateParamParameter(self, list): raise NotImplementedError('generateParamParameter Not Implemented') def generateParamEnv(self, list): raise NotImplementedError('generateParamEnv Not Implemented') def generateYAML(self, hostname, modelList): if modelList is None or hostname is None: self.log.output('ERROR', '%s: hostname and modelList can not be None' \ % self.__class__.__name__) sys.exit(-1) self.classParamCollector(modelList) filename = hostname + '.yaml' timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S') output = { 'classes' : self.paramClass, # 'parameters' : tmp_param, # 'environments' : tmp_env, } #如果文件已存在,将原文件备份 if os.path.exists(filename) : os.rename(filename, filename+'.'+timestamp) stream = file(filename, 'a') yaml.dump(output, stream, default_flow_style=False, encoding='utf-8')
class CI(object): ''' classdocs ''' def __init__(self, attributes=None): self.log = SysLog() if attributes and type(attributes) is types.DictType: self.attributes = attributes elif attributes is None : self.attributes = {} elif type(attributes) is not types.DictType: self.log.output('ERROR', 'parameter attributes is not dict') return -1 def __setattr__(self, key, value): object.__setattr__(self, key, value) def __getattribute__(self, name): try : if name == 'attributes': return object.__getattribute__(self, name) except AttributeError : print '[ERROR] Get attribute error' raise def __getattr__(self, name): print '[ERROR] Can not find attribute %s' % name return None
class CI(object): """ classdocs """ def __init__(self, para=None, attr=None): self.log = SysLog() if para and type(para) is types.DictType: self.parameters = para elif para is None: self.parameters = {} elif type(para) is not types.DictType: self.log.output("ERROR", "parameter attributes is not dict") self.parameters = None if attr and type(attr) is types.DictType: self.attributes = attr elif attr is None: self.attributes = {} elif type(attr) is not types.DictType: self.log.output("ERROR", "parameter attributes is not dict") self.attributes = None def __setattr__(self, key, value): object.__setattr__(self, key, value) def __getattribute__(self, name): try: if name == "attributes" or name == "parameters": return object.__getattribute__(self, name) except AttributeError: print "[ERROR] Get attribute error" raise def __getattr__(self, name): print "[ERROR] Can not find attribute %s" % name return None
class RestCMDBConnector: ''' classdocs ''' def __init__(self, url='localhost', port='8080'): self.log = SysLog() self.conn = None self.url = url self.port = port ''' #函数功能:web连接初始化 #函数输入: #函数输出: #变更历史: #备注: ''' def connector(self): try: self.conn = httplib.HTTPConnection(self.url, self.port) self.log.output('INFO', 'RestCMDBConnector Initializing') except Exception as e: self.log.output('ERROR', '[%s]: WEB连接初始化失败, %s' % (self.__class__.__name__, e)) sys.exit(-1) ''' #函数功能:web连接关闭 #函数输入: #函数输出: #变更历史: #备注: ''' def close(self): try: self.conn.close() except Exception as e: self.log.output('ERROR', '[%s]: WEB连接关闭失败, %s' % (self.__class__.__name__, e)) sys.exit(-1) ''' #函数功能:输入time,获取时间戳 #函数输入:time #函数输出:vtimestamp -> 字符串形式的时间戳 #变更历史: #备注: ''' def getTimestamp(self, time): #如果time参数为空,则使用当前时间作为时间戳 if time is None : vtimestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S') else : vtimestamp = time return vtimestamp ''' #函数功能:输入uri,获取查询结果 #函数输入:uri -> 查询uri地址 #函数输出:result -> 查询结果 #变更历史: #备注: ''' def getResponse(self, uri): if self.conn is None: self.log.output('ERROR', '[%s]: HTTPConnection failed' % self.__class__.__name__) return None self.conn.request("GET", uri) data = self.conn.getresponse().read() result = json.loads(data, encoding="utf-8") if not isinstance(result, list) : self.log.output('ERROR', '[%s] : 查询结果应为list类型,实际为%s' % sys._getframe().f_code.co_name, type(result)) result = None return result ''' #函数功能:输入web uri和参数,获取查询结果 #函数输入:rootUri -> web api方法 # parameters -> 传入api的参数 #函数输出:函数getResponse的返回值 #变更历史: #备注: ''' def getResultByUri(self, rootUri, parameters): token = 0 uri = "" #检查rootUri是否符合uri格式 if rootUri is None : self.log.output('ERROR', '[%s]: 参数[rootUri]为空或不符合uri格式' % self.__class__.__name__) return None uri = rootUri #判断parameters是否为字典 if not [ parameters and type(parameters) is types.DictType ]: self.log.output('ERROR', '[%s]: 参数[paramters]为空或不是dict类型' % self.__class__.__name__) return None # for key, value in parameters.items() : # if value : # if token == 0 : # uri += "?" + key + "=" + value # token = 1 # else : # uri += "&" + key + "=" + value # else : # continue listattr = [ k+'='+v for k, v in parameters.iteritems() if not v is None ] uri += "?" + "&".join(listattr) return self.getResponse(uri) ''' #函数功能:根据CI优先级进行合并 #函数输入:cilist -> 源CI列表 # ci -> 待合并CI #函数输出:无 #变更历史: #备注: ''' def CIMerge(self, cilist, ci): status = 0 #status保存是否通过优先级合并or直接将ci追加到list中、0:追加;1:优先级合并 #判断是否存在不同优先级的ci需要合并 for index in range(0, len(cilist)) : #ci的type和name相同,且priority不相同,那么则认为这两个ci是优先级不同的两个ci,需要进行合并操作的 if ci._TYPE == cilist[index].TYPE and \ ci.PRIORITY != cilist[index].PRIORITY and \ ci.NAME == cilist[index].NAME: for key, value in ci.attributes.items(): #如果属性相同,判断优先级,如果ci的优先级高则替换cilist中的,否则不进行替换 #如果ci中的属性在cilist中不存在,那么则直接将该属性插入到cilist的ci中 if [cilist[index].attributes.has_key(key) and \ cilist[index].PRIORITY < ci.PRIORITY ] or \ [ not cilist[index].attributes.has_key(key) ]: cilist[index].attributes[key] = value status = 1 break else : continue #如果不存在优先级合并的ci,那么将该ci追加到cilist中 if status == 0: cilist.append(ci) ''' #函数功能:根据CI获取该CI所有attribute #函数输入:ciFid -> ci family ID # timestamp -> 时间戳 #函数输出:attribute -> 以字典形式保存的属性 #变更历史: #备注: ''' def getCIAttributes(self, ciFid, timestamp = None): attribute = {} vtime = self.getTimestamp(timestamp) if ciFid is None: self.log.output('ERROR', '[%s] : 参数[ciFid]不可为空' % sys._getframe().f_code.co_name) apipara = { "ci_fid" : ciFid, "time" : vtime, } uri = "/ciattr" result = self.getResultByUri(uri, apipara) if result is None : self.log.output('ERROR', '[%s] : 查询结果为None' % sys._getframe().f_code.co_name) return None for attr in result : attribute[attr["CIAT_NAME"].encode("utf-8")] = attr["VALUE"].encode("utf-8") return attribute ''' cifid就可以唯一确认出来ci,但是由于必须main函数中,根据主机名找出ci,所以需要设计这个ci的存在 #函数功能:生成CI CLASS #函数输入:ciName -> ci name # ciType -> ci type # ciFid -> ci family id # timestamp -> timestamp #函数输出:ci #变更历史: #备注: ''' def getCI(self, ciName = None, ciType = None, ciFid = None, timestamp = None): vtime = self.getTimestamp(timestamp) apipara = { "name" : ciName, "citype" : ciType, "family_id" : ciFid, "time" : timestamp, } uri = "/ci" result = self.getResultByUri(uri, apipara) if len(result) != 1: self.log.output('ERROR', '[%s] : 查询出的CI非唯一,请确认查询条件' % sys._getframe().f_code.co_name) return None resultci = result[0] attr = self.getCIAttributes(resultci["FAMILY_ID"], vtime) #将ci的name保存到attribute中。这是因为在module中,定义了NAME->name的关系 attr["NAME"] = resultci["NAME"].encode("utf-8") #新建CI para = { "NAME" : resultci["NAME"].encode("utf-8"), "CITYPE_NAME" : resultci["CITYPE_NAME"].encode("utf-8"), "PRIORITY" : resultci["PRIORITY"].encode("utf-8"), "TIME" : vtime, "FAMILY_ID" : resultci["FAMILY_ID"].encode("utf-8"), "TYPE_FID" : resultci["TYPE_FID"].encode("utf-8"), } ci = CI(para, attr) return ci ''' #函数功能:该函数找出与ci满足存在制定关系的CI。由于优先级的存在,找出的CI中,会存在多个CI属于同一种 CI TYPE,所以在本函数中,直接将找出的CI进行合并 #函数输入:sourcefid -> source ci family ID # targetfid -> target ci family ID # relation -> ci relation name:REFERENCE or COMPOSITION # sourcetype_fid -> source ci type family ID # targettype_fid -> target ci type family ID # timestamp -> timestamp # location -> 获取relation中source ci或者target ci #函数输出:cilist #变更历史: #备注: ''' def getCIByRelations(self, sourcefid = None, targetfid = None, relation = None, sourcetype_fid = None, targettype_fid = None, timestamp = None, location = "target"): vtime = self.getTimestamp(timestamp) apipara = { "source_fid" : sourcefid, "target_fid" : targetfid, "typename" : relation, "source_type_fid" : sourcetype_fid, "target_type_fid" : targettype_fid, "time" : vtime, } uri = "/cirela" result = self.getResultByUri(uri, apipara) cilist = [] for it in result : #因为getCI函数返回的为ci list,所以,在本函数中返回的ciList是[ci,ci,ci...]这种形式的 if location == "source": ci_fid = it["SOURCE_FID"] elif location == "target": ci_fid = it["TARGET_FID"] ci = self.getCI(ciFid = ci_fid.encode("utf-8"), timestamp = vtime) self.CIMerge(cilist, ci) return cilist ''' #函数功能:查询CI TYPE #函数输入:sourcefid -> source ci family ID # targetfid -> target ci family ID # relation -> ci relation name:REFERENCE or COMPOSITION # sourcetype_fid -> source ci type family ID # targettype_fid -> target ci type family ID # timestamp -> timestamp #函数输出:cilist #变更历史: #备注: ''' def getCIType(self, name = None, fid = None, timestamp = None): vtime = self.getTimestamp(timestamp) apipara = { "name" : name, "family_id" : fid, "time" : vtime, } uri = "/citype" result = self.getResultByUri(uri, apipara) return result
class PuppetModelElementFactory: def __init__(self): self.modelList = {} self.log = SysLog() def CIInitialization(self, ci): modelElement = '' CIType = ci.parameters["CITYPE_NAME"] if(CIType == 'OS_USER') : if not self.modelList.has_key(CIType) : #如果没有该类型的dict,那么则新建一个 modelElement = User() self.modelList['OS_USER'] = modelElement #无论是否第一次添加,都是通过updateattr方法实现 self.modelList['OS_USER'].updateAttr(ci) elif (CIType == 'OS_KERNEL_GLOBAL') : if not self.modelList.has_key(CIType) : modelElement = KernelGlobal() self.modelList['OS_KERNEL_GLOBAL'] = modelElement self.modelList['OS_KERNEL_GLOBAL'].updateAttr(ci) elif (CIType == 'OS_USER_GLOBAL') : if not self.modelList.has_key(CIType) : modelElement = UserGlobal() self.modelList['OS_USERGLOBAL'] = modelElement self.modelList['OS_USERGLOBAL'].updateAttr(ci) elif (CIType == 'OS_SERVICE') : if not self.modelList.has_key(CIType) : modelElement = Service() self.modelList['OS_SERVICE'] = modelElement self.modelList['OS_SERVICE'].updateAttr(ci) elif (CIType == 'OS_LOG') : if not self.modelList.has_key(CIType) : modelElement = Log() self.modelList['OS_LOG'] = modelElement self.modelList['OS_LOG'].updateAttr(ci) elif (CIType == 'OS_PACKAGE') : if not self.modelList.has_key(CIType) : modelElement = Package() self.modelList['OS_PACKAGE'] = modelElement self.modelList['OS_PACKAGE'].updateAttr(ci) elif (CIType == 'OS_SECURITY') : if not self.modelList.has_key(CIType) : modelElement = Security() self.modelList['OS_SECURITY'] = modelElement self.modelList['OS_SECURITY'].updateAttr(ci) elif (CIType == 'OS_TIME_SYNC_CLIENT') : if not self.modelList.has_key(CIType) : modelElement = TimeSyncClient() self.modelList['OS_TIME_SYNC_CLIENT'] = modelElement self.modelList['OS_TIME_SYNC_CLIENT'].updateAttr(ci) elif (CIType == 'OS_GROUP') : if not self.modelList.has_key(CIType) : modelElement = Group() self.modelList['OS_GROUP'] = modelElement self.modelList['OS_GROUP'].updateAttr(ci) # elif (CIType == 'OS_AUTHORIZATION_SSH') : # if not self.modelList.has_key(CIType) : # modelElement = AuthorizationSSH() # self.modelList['OS_AUTHORIZATION_SSH'] = modelElement # self.modelList['OS_AUTHORIZATION_SSH'].updateAttr(ci) else : self.log.output('ERROR', 'Without CI TYPE') return None def factoryTransformation(self): for key, value in self.modelList.items() : value.CITransformation()
connector = OracleCMDBConnector('cmdb', 'cmdb123', 'cffexcmdb') connector.connect() factory = PuppetModelElementFactory() modelElementList = [] hash = HashGenerator() log = SysLog() hostname = 'slave1' ciList = connector.getCI(hostname, 'HOST_OS') relationList = ['OSHASUSER', 'OSHASKERNEL', 'OSHASUSERGLOBAL', 'OSHASLOG', 'OSHASSERVICE', 'OSHASPACKAGE', 'OSHASSECURITY', 'OSHASTIMESYNCCLIENT', 'OSHASGROUP', 'OSHASAUTHORIZATION',] #relationList = ['OSHASUSER'] for eachCI in ciList : for each in relationList : CIList = connector.getCIByRelations(eachCI.attributes['FAMILY_ID'], each, eachCI.attributes['TIME']) for index in range(0, len(CIList)): factory.CIInitialization(CIList[index]) factory.factoryTransformation() hash.generateYAML(factory.modelList) log.output('INFO', 'Generate ENC Finished') connector.close()
class User(PuppetModelElement): def __init__(self): self.log = SysLog() self.attributes = [] #将CI中attributes(CI ATTR)保存在该属性中,以字典形式保存 self.parameters = [] #将CI中CMDB相关的属性值保存在该参数中,列表中以字典形式保存 self.mapping = { 'NAME' : 'name', 'UID' : 'uid', 'GID' : 'gid', 'HOME_DIR' : 'home', 'PASSWD' : 'password', 'LOGIN_SHELL' : 'shell', 'STATUS' : 'ensure', # 'KEY' : 'ssh_key', #cmdb模型修改后,将用户的公钥保存到了user ci中 # 'PROTOCOL_TYPE' : 'ssh_type', #保存ssh中的协议类型。注释不使用的原因是,都是找出本用户信任的用户的sshkey 'PROFILE_EXPORT_PS1' : 'export_PS1', 'PROFILE_UMASK' : 'umask', 'PROFILE_EXPORT_ORACLE_BASE' : 'export_ORACLE_BASE', 'PROFILE_EXPORT_LD_LIBRARY_PATH' : 'export_LD_LIBRARY_PATH', 'PROFILE_EXPORT_CLASSPATH' : 'export_CLASSPATH', 'PROFILE_EXPORT_PATH' : 'export_PATH', 'PROFILE_EXPORT_NLS_LANG' : 'export_NLS_LANG', } self.param_classes = {} self.title_group = 'users_list' self.title_ssh = 'sshkey_list' self.title = 'os_user' ''' #函数功能:CI初始化为对应的host class #函数输入:ci #函数输出:cilist #变更历史: #备注: ''' def updateAttr(self, ci): if ci is None : self.log.output('ERROR', '[%s]: 参数[ci]为空,无法添加到类实例中' % self.__class__.__name__) sys.exit(-1) #初始化attributes参数 self.attributes.append(ci.attributes) #初始化parameters参数 self.parameters.append(ci.parameters) def getAttrMapping(self, attrName): if self.mapping.has_key(attrName): return self.mapping.get(attrName) else: return None def generateParamClass(self): conn = RestCMDBConnector("192.168.1.3", "8080") conn.connector() self.param_classes[self.title] = {} self.param_classes[self.title][self.title_group] = {} #原有user的属性,attributes为list,保存了同一个CI TYPE:OS_USER的多个CI for index in range(0, len(self.attributes)): each = self.attributes[index] name = each['name'] self.param_classes[self.title][self.title_group][name] = {} export_list = [] for key, value in each.items(): if key.startswith('export'): export_list.append(re.sub('export_', '', key) + '=' + value) continue self.param_classes[self.title][self.title_group][name][key] = {} self.param_classes[self.title][self.title_group][name][key] = value if len(export_list) != 0 : self.param_classes[self.title][self.title_group][name]['profile'] = export_list #生成users中需要建立信任关系的属性,因为可能会存在多个用户,所以使用列表形式 vtime = self.parameters[index]["TIME"] #获取该HOST_CI和OS_USER的type fid。这里没有初始化为CI,所以访问的时候直接使用字典形式访问 userCIType = conn.getCIType("OS_USER", timestamp = vtime) hostCIType = conn.getCIType("HOST_OS", timestamp = vtime) if len(userCIType) != 1 or len(hostCIType) != 1: self.log.output('ERROR', '[%s]: 获取的CI TYPE[HOST_OS|OS_USER],无法唯一确定CI TYPE' % self.__class__.__name__) sys.exit(-1) targetUserCIList = conn.getCIByRelations(sourcefid = self.parameters[index]["FAMILY_ID"], targettype_fid = userCIType[0]["FAMILY_ID"] ) #此用户没有信任关系需要建立 if len(targetUserCIList) == 0: continue for eachUserCI in targetUserCIList : #获取该用户属于的主机,targetHost列表长度应为1 targetHost = conn.getCIByRelations(targetfid = eachUserCI.parameters["FAMILY_ID"], sourcetype_fid = hostCIType[0]["FAMILY_ID"], location="source") if len(targetHost) != 1: self.log.output('ERROR', '[%s]: 该用户所属的主机不唯一,异常并退出' % self.__class__.__name__) sys.exit(-1) targetHostName = conn.getCI(ciFid = targetHost[0].parameters["FAMILY_ID"], timestamp = vtime).parameters["NAME"] temp_name = eachUserCI.parameters['NAME'] temp_key = eachUserCI.attributes["KEY"] temp_type = eachUserCI.attributes["PROTOCOL_TYPE"] temp_title = targetHostName + "@" + temp_name self.param_classes[self.title][self.title_group][name][self.title_ssh] = {} self.param_classes[self.title][self.title_group][name][self.title_ssh][temp_title] = {} self.param_classes[self.title][self.title_group][name][self.title_ssh][temp_title]["key"] = {} self.param_classes[self.title][self.title_group][name][self.title_ssh][temp_title]["type"] = {} self.param_classes[self.title][self.title_group][name][self.title_ssh][temp_title]["key"] = temp_key self.param_classes[self.title][self.title_group][name][self.title_ssh][temp_title]["type"] = temp_type conn.close() return self.param_classes def getParamClass(self, CIList): return self.generateParamClass(CIList)
class OracleCMDBConnector: conn = '' cursor = '' def __init__(self, user, passwd, database) : self.log = SysLog() self.user = user self.passwd = passwd self.database = database def connect(self): try : self.log.output('INFO', 'test') self.log.output('INFO', 'DBConnector Initializing') self.conn = cx_Oracle.connect(self.user, self.passwd, self.database) self.cursor = self.conn.cursor() self.log.output('INFO', 'test') except Exception as e: print e sys.exit(-1) def getCIAttributes(self, ciFid, vtime=None): vtimestamp = '' if vtime is None : vtime = datetime.datetime.now() vtimestamp = int(time.mktime(vtime.timetuple())) else : vtimestamp = int(vtime) if ciFid is None: self.log.output('ERROR', '%s : ciFid is Null' % sys._getframe().f_code.co_name) ci = CI() #attrs = {} lCurAttr = self.cursor.var(cx_Oracle.CURSOR) results = self.cursor.callproc("pkg_cmdb.sp_get_ci_attributes", [ciFid, vtimestamp, lCurAttr])[2] for it in results: #print it[0] ci.attributes[it[0]] = it[1] #print ci.attributes[it[0]] #attrs[it[0]] = it[1] #ci.attributes = attrs return ci #找出指定CI名和CI类型的所有相关CI项 def getCI(self, ciName, ciType, vtime = None): vtimestamp = '' if vtime is None : vtime = datetime.datetime.now() vtimestamp = int(time.mktime(vtime.timetuple())) else : vtimestamp = int(vtime) if ciName is None or ciType is None: self.log.output('ERROR', '%s : ciFid is Null' % sys._getframe().f_code.co_name) ciList = [] tmpCICur = self.cursor.var(cx_Oracle.CURSOR) #该sp会返回ci_fid和time CICur = self.cursor.callproc("pkg_cmdb.sp_find_ci", [ciName, ciType, vtimestamp, tmpCICur])[3] for it in CICur : ci = self.getCIAttributes(it[0], vtimestamp) ciList.append(ci) print ciList return ciList def getCIByRelations(self, ciFid, relations, vtime = None): vtimestamp = '' if vtime is None : vtime = datetime.datetime.now() vtimestamp = int(time.mktime(vtime.timetuple())) else : vtimestamp = int(vtime) if ciFid is None or relations is None: self.log.output('ERROR', '%s : ciFid is Null' % sys._getframe().f_code.co_name) CIList = [] tmpCICur = self.cursor.var(cx_Oracle.CURSOR) #该SP返回CI list CICur = self.cursor.callproc("pkg_cmdb.sp_find_relational_ci", [ciFid, relations, vtimestamp, tmpCICur])[3] for it in CICur : ci = self.getCIAttributes(it[0], vtimestamp) CIList.append(ci) return CIList def close(self): try: self.cursor.close() self.conn.close() except Exception as e: print e sys.exit(-1)
class HashGenerator : def __init__(self): self.log = SysLog() self.moduleMap = { 'User' : 'os_user', 'UserGlobal' : 'os_userglobal', 'KernelGlobal' : 'os_kernelglobal', 'Log' : 'os_log', 'Package' : 'os_package', 'Security' : 'os_security', 'Service' : 'os_service', 'TimeSyncClient' : 'os_timesyncclient', 'Group' : 'os_user', 'AuthorizationSSH' : 'os_authorizationssh', } self.paramClass = {} def classParamCollector(self, modelList): titleList = [] for key, value in modelList.items() : param = value.generateParamClass() tempTitle = param.keys()[0] if tempTitle in titleList : self.paramClass[tempTitle].update(param[tempTitle]) continue self.paramClass.update(param) titleList.append(param.keys()[0]) def generateParamClass(self): raise NotImplementedError('generateParamClass Not Implemented') def generateParamParameter(self, list): raise NotImplementedError('generateParamParameter Not Implemented') def generateParamEnv(self, list): raise NotImplementedError('generateParamEnv Not Implemented') def generateYAML(self, modelList): if modelList is None : self.log.output('ERROR', '%s: modelList is None' % self.__class__.__name__) sys.exit(-1) self.classParamCollector(modelList) output = { 'classes' : self.paramClass, # 'parameters' : tmp_param, # 'environments' : tmp_env, } if os.path.exists('slave1.yaml') : os.remove('slave1.yaml') stream = file('slave1.yaml', 'a') yaml.dump(output, stream, default_flow_style=False)