def connect(self, pOptions=None): if self.cfactory is None: self.cfactory = ConnectionFactory(self) if pOptions == None: pOptions = self.pOptions return self.my_connect(pOptions)
class iBaseDriver(object): def __init__(self, registry, protofactory, ipaddr, creds): self.ref = registry self.ipaddr = ipaddr self.creds = creds self.device_type = self.ref.name # Facts self.facts = {} self.facts["HandlesManyDevices"] = False self.facts["IsADevice"] = False # Protocol self.protofactory = protofactory self.cfactory = None # Add commands to this object self._make_all_methods() # Components Map self.ComponentEnum = self.ref.ComponentEnum self.components = {} for comp in self.ref.defs: self.components[comp] = {} for en in MonitorScope: self.components[comp][en] = [] mon = TypeHelper.get_name(en, MonitorScopeMap) if mon in self.ref.defs[comp]: self.components[comp][en] = self.ref.defs[comp][mon] # Entity JSON self.entityjson = {} # SNMP Entity MIB JSON self.emib_json = {} self.supports_entity_mib = False # Reset self.reset() def get_facts(self): return self.facts def reset(self): # Connection if self.cfactory: self.cfactory.disconnect() self.cfactory = None # Init Flags self.inited = False # Initialize EnityJSON self.emib_json = {} self.entityjson = {} self.entityjson["topology"] = {} self.entityjson["devices"] = {} self.entityjson["doc.prop"] = {} self.entityjson["doc.prop"]["ipaddr"] = self.ipaddr self.entityjson["doc.prop"]["creds"] = str(self.creds) self.my_reset() def my_reset(self): pass def get_doc_props(self): return self.entityjson["doc.prop"] def _request_device_features(self): self.facts["IsADevice"] = True def _request_console_features(self): self.facts["HandlesManyDevices"] = True def handles_many_devices(self): return self.facts["HandlesManyDevices"] # Connection APIs def connect(self, pOptions=None): if self.cfactory is None: self.cfactory = ConnectionFactory(self) if pOptions == None: pOptions = self.pOptions return self.my_connect(pOptions) def my_connect(self, pOptions): if not self.cfactory.connect(self.ref.name, self.ipaddr, self.creds, self.protofactory, pOptions): logger.debug("Connection failed to " + self.ipaddr) return False retval = self.cfactory.identify(self.entityjson) if 'System' in self.entityjson and len(self.entityjson['System']) > 0: if '_Type' not in self.entityjson['System'][0]: self.entityjson['System'][0]['_Type'] = self.device_type return retval def my_disconnect(self): return True def disconnect(self): if self.cfactory: self.cfactory.disconnect() self.cfactory = None def reconnect(self, pOptions=None): self.disconnect() return self.connect(pOptions) # End Connection APIs # Containment Tree APIs @property def ContainmentTree(self): return self._build_ctree(self.protofactory.ctree, self.entityjson) def _build_ctree(self, mTree, device_json): comp_tree = {} if not mTree: return comp_tree system = None system_cname = None for ctree in mTree: compname = TypeHelper.resolve(ctree) comp_tree[compname] = self._build_tree(mTree, device_json, ctree) if compname == 'System': system = comp_tree[compname] system_cname = ctree # Populate with subsystem names! self._populate_component_tree(system_cname, system, device_json) return comp_tree def _is_comp_in_subsystem(self, device_json, comp): if 'Subsystem' not in device_json: return False for cjson in device_json['Subsystem']: if cjson['Key'] == comp: return True return False def _populate_component_tree(self, compn, comp_tree, device_json): counter = 0 for comp in self.protofactory.ctree[compn]: c = TypeHelper.resolve(comp) if (comp not in self.protofactory.ctree): # comp is simple component - not container if self._is_comp_in_subsystem(device_json, c): counter += 1 if c not in comp_tree: comp_tree[c] = [] continue # comp is container, can contain multiple subcomponents toadd = {} if c in comp_tree: toadd = comp_tree[c] n = self._populate_component_tree(comp, toadd, device_json) if self._is_comp_in_subsystem(device_json, c): counter = n + 1 if counter > 0 and c not in comp_tree: comp_tree[c] = toadd return counter def _get_obj_index(self, clsName, js): retval = None if js is None: return retval if not clsName in self.ref.defs: return retval if not 'Key' in self.ref.defs[clsName] \ or len(self.ref.defs[clsName]['Key']) <= 0: return "[" + clsName + "]" retval = "" comma = "" for key in self.ref.defs[clsName]["Key"]: if key not in js or js[key] is None: js[key] = self.my_fix_obj_index(clsName, key, js) if js[key] is None: js[key] = clsName + "_" + key + "_null" retval = retval + comma + js[key] comma = "," return retval def my_fix_obj_index(self, clsName, key, js): return clsName + "_" + key + "_null" def _get_cls_presence(self, clsName): if clsName in self.ref.defs: return True return False # Must be overridden by base class def _isin(self, parentClsName, parent, childClsName, child): not_implemented def _build_tree(self, mTree, device_json, ctree, parent=None, parentClsName=None): comp_tree = {} if not ctree in mTree: return comp_tree for entry in mTree[ctree]: if isinstance(entry, str): comp_tree[entry] = self._build_tree(mTree, device_json, entry) continue # Enum enname = TypeHelper.resolve(entry) if not enname in device_json: logger.debug("Component " + enname + " is not present in device!") continue if isinstance(device_json[enname], dict): if len(device_json[enname]) <= 0: # Empty entry continue child_index = self._get_obj_index(enname, device_json[enname]) if parent == None or self._isin(parentClsName, parent, enname, device_json[enname]): if not entry in mTree: # entry is a leaf node comp_tree[enname] = child_index else: # entry is not a leaf node comp_tree[enname] = { child_index: self._build_tree(mTree, device_json, entry, device_json[enname], enname) } elif isinstance(device_json[enname], list): if len(device_json[enname]) <= 0: # Empty entry continue dict_list = {} list_list = [] for tt in device_json[enname]: child_index = self._get_obj_index(enname, tt) if parent == None or self._isin(parentClsName, parent, enname, tt): if not entry in mTree: # entry is a leaf node list_list.append(child_index) else: # entry is not a leaf node dict_list[child_index] = self._build_tree( mTree, device_json, entry, tt, enname) if len(dict_list) != 0 and len(list_list) == 0: comp_tree[enname] = dict_list elif len(dict_list) == 0 and len(list_list) != 0: comp_tree[enname] = list_list elif len(dict_list) != 0 and len(list_list) != 0: comp_tree[enname] = dict_list comp_tree[enname]["_unknown_"] = list_list else: logger.debug("Unexpected format!") return comp_tree # End Containment Tree APIs # Entity JSON APIs def _get_entries(self, json, en): comps = self.ref.convert_comp_to_enum(en, self.comp_union_spec, self.comp_merge_join_spec, self.comp_misc_join_spec, self.more_details_spec) return self.cfactory.enumerate_all(json, comps) # Consoles should override this! def my_get_entityjson(self): plist = [] for comp in self.ComponentEnum: plist.append(comp) return self.get_partial_entityjson(*plist) def get_partial_entityjson(self, *en): #Components with Sensors_* comps = self.ref.convert_comp_to_enum(en, self.comp_union_spec, self.comp_merge_join_spec, self.comp_misc_join_spec, self.more_details_spec) #Sensor_* replaced with Sensor enum ServerSensor, NumericSensor, PSNumericSensor enjson = self.cfactory.enumerate_list(self.entityjson, *comps) #json with ServerSensor, NumericSensor, PSNumericSensor self._misc_join_component(enjson, self.comp_misc_join_spec) self._merge_join_component(enjson, self.comp_merge_join_spec) self._union_component(enjson, self.comp_union_spec) #json with One Sensors replacing ServerSensor, NumericSensor, PSNumericSensor self._pivot_component(enjson, self.comp_union_spec) #call to collect more details self._get_more_details(enjson, self.more_details_spec, comps) return enjson def _get_more_details(self, entityjson, more_details_spec, comps): tempList = [] if more_details_spec is not None: for item in more_details_spec: myList = more_details_spec[item]['_components_enum'] keyComp = item for val in myList: tempList.append(TypeHelper.resolve(val)) self._call_it(keyComp, tempList) def get_partial_entityjson_str(self, *comps): return self.get_partial_entityjson(*comps) def get_entityjson(self): if self.inited == False and self.connect(): if not self.my_get_entityjson(): return False self._build_device_map() self.inited = True elif self.inited == True: logger.debug("already present") else: logger.debug("failed to connect to device!") return self.inited def _build_device_map(self): return True def print_components(self): self.ref.print_components() def _should_i_include(self, component, entry): return True def _call_it(self, more_details_spec): pass def _get_json_for_device(self, devicejson, monitorfilter=None, compScope=None): toret = devicejson if (monitorfilter is None): monitorfilter = MonitorScopeFilter_All metrics_or_health = monitorfilter.isset(MonitorScope.Metrics) or \ monitorfilter.isset(MonitorScope.Health) invconfig_attrs = monitorfilter.isset(MonitorScope.Key) or \ monitorfilter.isset(MonitorScope.Inventory) or \ monitorfilter.isset(MonitorScope.ConfigState) finalret = {} for component in devicejson: if not (compScope is None or compScope.isMatch(component)): continue toret = devicejson[component] if not component in self.components: if not component in ['topology', 'devices', 'doc.prop']: logger.debug(component + " is not defined in ref!") continue myret = [] for entry in toret: if (len(entry) <= 0): continue tgtentry = {} if not self._should_i_include(component, entry): continue for en in MonitorScope: if not monitorfilter.isset(en): continue for attr in self.components[component][en]: if (attr in entry) and (entry[attr] != None): tval = self.ref.Translate(component, attr, entry[attr]) tgtentry[attr] = tval elif not metrics_or_health: tgtentry[attr] = "Not Available" tgtentry["Key"] = entry["Key"] if '_Type' in entry: if invconfig_attrs: tgtentry["_Type"] = entry["_Type"] if not invconfig_attrs: # clean dummy entries if len(tgtentry) == 1 and 'Key' in tgtentry: # empty record continue myret.append(tgtentry) if len(myret) > 0: finalret[component] = myret # self._pivot_component(finalret, self.comp_union_spec) return finalret def _get_topology_info(self): return {} def _get_topology_influencers(self): return [] # End Entity JSON APIs # Entity JSON/Member APIs # for members with multiple instances def _union_component(self, entityjson, comp_union_spec): #Remove duplicates not considered yet if comp_union_spec: for target_comp, value in comp_union_spec.items(): tempCompGroup = [] compTypes = value['_components'] for compProfileType in compTypes: if compProfileType in entityjson: if isinstance(entityjson[compProfileType], dict): x = entityjson[compProfileType] #This renaming can be moved to func _pivot_component if '_pivot' in value: typen = value['_pivot'] if typen in value and x[typen] in value[typen]: x[typen] = value[typen][x[typen]] tempCompGroup.append(x) else: for x in entityjson[compProfileType]: # lot of 'if's required here, write your union json carefully if '_pivot' in value: typen = value['_pivot'] if typen in value and x[typen] in value[ typen]: x[typen] = value[typen][x[typen]] tempCompGroup = tempCompGroup + entityjson[ compProfileType] del entityjson[compProfileType] if tempCompGroup: entityjson[target_comp] = tempCompGroup def _pivot_component(self, entityjson, comp_union_spec): #already changed to list in union component function, so no need of dict check if comp_union_spec: for target_comp, value in comp_union_spec.items(): if target_comp in entityjson: if '_pivot' in value: classifier = value['_pivot'] classifieDict = {} for i in entityjson[target_comp]: keyBuilt = target_comp + '_' + i[classifier] if keyBuilt not in classifieDict: classifieDict[keyBuilt] = [] classifieDict[keyBuilt].append(i) entityjson.update(classifieDict) del entityjson[target_comp] def _merge_join_component(self, entityjson, comp_merge_join_spec): if comp_merge_join_spec: for key, value in comp_merge_join_spec.items(): compTypes = value['_components'] overwrite = True # overwrite = value['_overwrite'] target_comp = compTypes[0][0] target_key = compTypes[0][1] tempList = [] if target_comp in entityjson: for keylist in compTypes: temp = {} # if "FanSlot" if keylist[2] in entityjson and keylist[ 0] in entityjson: if isinstance(entityjson[keylist[2]], dict): slot = entityjson[keylist[2]] temp[slot[keylist[3]]] = slot else: for slot in entityjson[keylist[2]]: temp[slot[keylist[3]]] = slot del entityjson[keylist[2]] if temp: tempList.append(temp) # logger.debug(PrettyPrint.prettify_json(tempList)) if isinstance(entityjson[target_comp], dict): fan = entityjson[target_comp] for tmp in tempList: if fan[target_key] in tmp: if overwrite: fan.update(tmp[fan[target_key]]) else: #a bit complex logic required here fan = tmp[fan[target_key]].update(fan) else: for fan in entityjson[target_comp]: for tmp in tempList: if fan[target_key] in tmp: if overwrite: fan.update(tmp[fan[target_key]]) else: #a bit complex logic required here fan = tmp[fan[target_key]].update(fan) entityjson[key] = entityjson.pop(target_comp) def _misc_join_component(self, entityjson, comp_misc_join_spec): if comp_misc_join_spec: compDelList = [] for key, value in comp_misc_join_spec.items(): if '_createFlag' in value: if value['_createFlag'] == True: entityjson[key] = {} entityjson[key]["Key"] = key #this is to create separate the Misc profiles to new ones #Will work for single instance components like SystemString, IDRACEnumeration etc if key in entityjson: keytripletsdict = value['_complexkeys'] profs = value['_components_enum'] if isinstance(entityjson[key], dict): myDict = entityjson[key] for comp, ckeys in keytripletsdict.items(): if comp in entityjson: k = ckeys[0] attrName = ckeys[1] if isinstance(entityjson[comp], dict): attrInst = entityjson[comp] myDict[attrInst[attrName]] = attrInst[ ckeys[2]] else: for attrInst in entityjson[comp]: #This check is avoided to accomodate iDRAVcardView FQDD issue #if(myDict[k] == attrInst[k]): myDict[attrInst[attrName]] = attrInst[ ckeys[2]] #del entityjson[comp] compDelList.append(comp) else: #assuming list myList = entityjson[key] for comp, ckeys in keytripletsdict.items(): if comp in entityjson: k = ckeys[0] attrName = ckeys[1] if isinstance(entityjson[comp], dict): attrInst = entityjson[comp] for compInst in myList: if (compInst[k] == attrInst[k]): compInst[attrInst[ attrName]] = attrInst[ckeys[2]] else: for attrInst in entityjson[comp]: for compInst in myList: if (compInst[k] == attrInst[k]): compInst[attrInst[ attrName]] = attrInst[ ckeys[2]] #del entityjson[comp] compDelList.append(comp) for dlcomp in compDelList: if dlcomp in entityjson: del entityjson[dlcomp] def _get_field(self, myjson, component_en, fieldname, idx=0): compfilter = ComponentScope(component_en) compname = TypeHelper.resolve(component_en) json = self._get_json_for_device(myjson, compScope=compfilter) if (compname in json): entry = None if (isinstance(json[compname], list)): if (idx >= 0 and idx < len(json[compname])): entry = json[compname][idx] else: entry = json[compname] if entry and (fieldname in entry): return entry[fieldname] return "<not_found>" def _get_field_for_all(self, myjson, component_en, fieldname): retval = [] compfilter = ComponentScope(component_en) compname = TypeHelper.resolve(component_en) json = self._get_json_for_device(myjson, compScope=compfilter) if (compname in json): entry = None if (isinstance(json[compname], list)): for idx in json[compname]: if fieldname in idx: retval.append(idx[fieldname]) else: entry = json[compname] if fieldname in json[compname]: retval.append(json[compname][fieldname]) return retval def _get_field_from_action(self, rjson, *args): retval = rjson for arg in args: if arg in retval: retval = retval[arg] else: return None return retval # End Member APIs def _build_cmd_list(self): cmdlist = {} for proto in self.protofactory: for k in proto.cmds: if not k in cmdlist: cmdlist[k] = [] cmdlist[k].append(proto.cmds[k]) commands = [] for cmd in cmdlist: commands.append(cmd) args = {} arg_counter = 0 inited = False for proto_cmd in cmdlist[cmd]: if type(proto_cmd) == int: continue if 'Args' in proto_cmd: my_counter = 0 for arg in proto_cmd['Args']: my_counter = my_counter + 1 if not arg in args: if inited: logger.debug("ERROR: " + cmd + " has additional arg" + arg) else: arg_counter = arg_counter + 1 args[arg] = proto_cmd['Args'][arg] if arg in args and args[arg] != proto_cmd['Args'][arg]: logger.debug("ERROR: " + cmd + " different argument type") if my_counter != arg_counter: logger.debug( "ERROR: " + cmd + " different # of arguments across protocols!") inited = True return commands def _make_all_methods(self): fcmds = self._build_cmd_list() for fname in fcmds: self._make_method(fname) def _make_method(self, fname): def func1(**kwargs): myname = func1.__name__ if not hasattr(self, 'cfactory') or self.cfactory == None: logger.debug("Protocol not initialized!") return { 'Status': 'Failed', 'Message': 'Protocol not initialized' } return self.cfactory.operation(fname, **kwargs) func1.__name__ = fname setattr(self, fname, func1)