def sysDetails(self): basePath = self.cmcPolicyRetarget('/rbt/sport/sysdetail/state') fields = self.fields appliance = fields.get('appliance') if appliance: # Get the data from the appliance directly. data = self.mgmt.action( '/cmc/actions/appliance/query', ('appliance', 'string', appliance), ('operation', 'string', 'iterate'), ('flags', 'string', 'subtree'), ('timeout', 'uint32', '30'), ('node', 'string', basePath)) # Pop off the basePath from the keys so we can treeify correctly. for k in data.keys(): v = data.pop(k) if k.startswith(basePath): k = k[len(basePath):] if k.startswith("/"): k = k[1:] if k: data[k] = v data = Nodes.treeifySubtree(data); else: data = Nodes.getTreeifiedSubtree(self.mgmt, basePath); # if sport is not running there won't be a 'sport' subtree so # use an empty dict instead sportModules = data.get('sport') or {} systemModules = data.get('system') or {} result = self.doc.createElement('systemDetails') # Maps to a 'status_map' enum in the backend: # products/rbt_sh/src/bin/cli/modules/python/cli_rbt_sysdetail_cmds.py prettyStatuses = ['OK', 'Warning', 'Error', 'Disabled'] # Takes in a system details data dict and adds each entry as an # attribute to the XML element in a pretty way. # moduleEl - an XML element # moduleName - the name the system module. Due to the design # of the backend, this attribute is not included # in moduleData dict. # moduleData - a data dict with entries that become XML attributes. def parseDataAndAttributizeXml(moduleEl, moduleName, moduleData): moduleEl.setAttribute('name', moduleName) # Formatting module data by replacing newlines with semicolons. # Semicolons get converted to newlines in JS. info = moduleData.get('info', '').replace('\n', ';') # Strip the last newline from info output (this fixes the bug where # an extra <br /> would show up at the end of each module info div) if info[-1:] == ';': info = info[:-1] if not info: # If no details, insert "<None>" message. info = "No details." moduleEl.setAttribute('info', info) statusMsg = prettyStatuses[int(moduleData.get('status', '2'))] moduleEl.setAttribute('status', statusMsg) moduleEl.setAttribute('statusTdClass', statusMsg.lower()) return moduleEl # Sort module names to maintain display order. sysModuleNames = systemModules.keys() sysModuleNames.sort(FormUtils.alphanumericCompare) sportModuleNames = sportModules.keys() sportModuleNames.sort(FormUtils.alphanumericCompare) sortedModuleNames = sysModuleNames + sportModuleNames for moduleName in sortedModuleNames: if moduleName in sysModuleNames: moduleData = systemModules.get(moduleName) else: moduleData = sportModules.get(moduleName) moduleEl = self.doc.createElement('module') moduleEl = parseDataAndAttributizeXml(moduleEl, moduleName, moduleData) # Display additional submodules if 'items' in moduleData: submodules = moduleData.get('items') submoduleNames = submodules.keys() submoduleNames.sort(FormUtils.alphanumericCompare) # Loop through each submodule and add each entry as a child to # the module XML node for subName in submoduleNames: subData = submodules.get(subName) submoduleEl = self.doc.createElement('module') prettyName = subData.get('name', '') submoduleEl = parseDataAndAttributizeXml(submoduleEl, prettyName, subData) moduleEl.appendChild(submoduleEl) result.appendChild(moduleEl) self.doc.documentElement.appendChild(result) self.writeXmlDoc()
def netTestDetails(self): fields = self.request().fields() base = '/rbt/nettest/state/' table = self.getXmlTable(None, tagNames=('testDetails', 'testDetail')) testId = fields.get('id', '-1') assert int(testId) in self.netTestMap.values(), 'Invalid test specified.' testBasePath = base + testId # '/rbt/nettest/state/<testId>' # get all nodes under testBasePath if isCMC: app_prod, app_sn = self.fields.get('appliance').split('_') resp = self.mgmt.action( '/cmc/actions/appliance/query', ('appliance', 'string', app_sn), ('operation', 'string', 'iterate'), ('flags', 'string', 'subtree'), ('timeout', 'uint32', '120'), ('node', 'string', testBasePath)) # take a dictionary of flat nodes and strip the base path off # the keys subtreeDict = {} for key, val in resp.iteritems(): # strip /rbt/nettest/state/<testID>/ subtreeDict[key[len(testBasePath) + 1:]] = val testSubtree = Nodes.treeifySubtree(subtreeDict) else: testSubtree = Nodes.getTreeifiedSubtree(self.mgmt, testBasePath) if 'attrib' in testSubtree: numRows = len(testSubtree['attrib']) else: numRows = 0 aggregateResultDict = {} for row in xrange(numRows): res = testSubtree['result'][str(row)] if res in aggregateResultDict: aggregateResultDict[res] += 1 else: aggregateResultDict[res] = 1 # Parse run time output. hasRun = testSubtree['has_run'] lastRun = testSubtree['last_run'] lastRunPretty = '' if ('true' == hasRun): # expected time format to parse: "1970/01/01 13:59:59" format = '%Y/%m/%d %H:%M:%S' t = time.strptime(lastRun, format) # Two formats will work well here: # '%I:%M%p on %B %d, %Y' => "1:59PM on January 01, 1970" # '%Y/%m/%d %I:%M%p' => "1970/01/01 1:59PM" prettyFormat = '%I:%M%p on %B %d, %Y' # Use the former lastRunPretty = time.strftime(prettyFormat, t) table.open(self.request(), id=testId, name=testSubtree['name'], has_run=hasRun, run_state=self.netTestResultCodes[int(testSubtree['run_state'])], last_run=lastRunPretty, num_passed=aggregateResultDict.get('2', 0), num_failed=aggregateResultDict.get('3', 0), num_error=aggregateResultDict.get('4', 0), num_undetermined=aggregateResultDict.get('5', 0)) for row in xrange(numRows): cols = testSubtree['attrib'][str(row)]['value'] # Create a list of arguments to pass to addEntry # {'attrib_0' : ../value/0, # 'attrib_1' : ../value/1, # ...} args = {} for col in cols: attribName = 'attrib_' + str(col) args[attribName] = cols[col] # Results are returned from the backend as an enum value. returnCode = int(testSubtree['result'][str(row)]) # Return the human-readable result code: 0 -> "Not Run", 3 -> "Error", etc args['result'] = self.netTestResultCodes[returnCode] # Equivalent to calling: # table.addEntry(attrib_0 = <value>, attrib_1 = <value>, ...) table.addEntry(**args) table.close()