def xml_xpath(self, query): """ Execute an XPath query with this object standing in for the context node. The namespace mappings are taken from the root binding object. There are no variable bindings. Most XPath is supported. query - a unicode object expressing an XPath The return value depends on the XPath expression (expr) - If expr reults in an XPath string, the return value is a Python Unicode object - If expr reults in an XPath number, the return value is a Python float - If expr reults in an XPath boolean, the return value is a Python bool object - If expr reults in an XPath node set, the return value is a Python list (always a list, even if empty, or a node with just one entry) """ prefixes = self.rootNode.xmlns_prefixes if u'xml' not in prefixes: prefixes.update({u'xml': XML_NS}) ctx = Context(self, processorNss=prefixes) result = Evaluate(query, context=ctx) return result
def editConfig(self,defaultoperation,testoption,erroroption,target,confignode,targetnode=None): """ Apply a ifconfig request from the confignode to the targetnode. delete and create attributes are supported only for iface element. For example, it is not possible to delete the name or the IP address of a network interface. @type defaultoperation: MERGE_OPERATION | REPLACE_OPERATION | NONE_OPERATION @param defaultoperation : as specified in NETCONF protocol @type testoption : SET | TEST_AND_SET @param testoption : as specified in NETCONF protocol @type erroroption : STOP_ON_ERROR | IGNORE_ERROR | ROLL_BACK_ON_ERROR @param erroroption : as specified in NETCONF protocol @type target : RUNNING_TARGET | CANDIDATE_TARGET | STARTUP_TARGET @param target : as specified in NETCONF protocol @type targetnode : string @param targetnode : if the target is RUNNING_TARGET or STARTUP_TARGET it will be ignored otherwise should be the node of the CANDIDATE_TARGET that this module should procees @rtype: ModuleReply @return: It returns a success or error message. ** Relates to the netconf edit-config operation """ moduleReply = ModuleReply( error_type = ModuleReply.APPLICATION, error_tag = ModuleReply.OPERATION_FAILED, error_severity = ModuleReply.ERROR, error_message = "Sorry, edit-config is temporarily no more supported for Interfaces.") # First ,find what to change from edit-config # the interface name is the key and can not be changed NS= 'urn:ietf:params:xml:ns:netconf:base:1.0' NSS = {u'xc': NS } ctx = Context (confignode, processorNss = NSS) liste = Evaluate("//*[@xc:operation]", ctx) if len(liste)>=2: moduleReply = ModuleReply( error_type = ModuleReply.APPLICATION, error_tag = ModuleReply.OPERATION_FAILED, error_severity = ModuleReply.ERROR, error_message = "Only one operation attribute is allowed.") return moduleReply elif len(liste)==1: opNode = liste[0] #for att in liste[0].attributes.values(): for att in opNode.attributes: ns, name = att value = opNode.getAttributeNS(ns, str(name)) if name == C.OPERATION and ns == C.NETCONF_XMLNS: opValue = value else: opValue = defaultoperation opNode = confignode if (not opValue in [C.MERGE, C.REPLACE, C.CREATE, C.DELETE]): moduleReply = ModuleReply( error_type = ModuleReply.APPLICATION, error_tag = ModuleReply.OPERATION_FAILED, error_severity = ModuleReply.ERROR, error_message = "Operation value is not allowed. Must be one of (merge, replace, create, delete).") return moduleReply macrocommand = MacroCommand() # On peut optimiser en creant mergeInterface(interfaceNode) # On peut optimiser en creant replaceInterface(interfaceNode) # Chacune renvoie un tableau de commande qu'on ajouter au tableau global if opNode != None: nodeName = string.strip(str(opNode.tagName)) if (nodeName == "interfaces"): if (opValue == C.MERGE): for node in opNode.childNodes: if (node.nodeType==Node.ELEMENT_NODE): if (node.tagName == "interface"): ifname = None mtu = None netmask = None addr = None broadcast = None for n in node.childNodes: if (n.nodeType==Node.ELEMENT_NODE): if (n.tagName == "name"): ifname = string.strip(str(n.childNodes[0].nodeValue)) elif (node.tagName == "mtu"): mtu = int(string.strip(str(n.childNodes[0].nodeValue))) if ifname != None: if mtu !=None: macrocommand.add(SetMtu(ifname,mtu)) if broadcast !=None: macrocommand.add(SetBroadcast(ifname,broadcast)) if netmask !=None: macrocommand.add(SetNetmask(ifname,netmask)) if addr != None: macrocommand.add(SetAddr(ifname,addr)) #elif (opValue == C.CREATE): #elif (opValue == C.DELETE): #... elif (nodeName == "interface"): ifname = None mtu = None netmask = None addr = None broadcast = None address = None if (opValue == C.MERGE): for node in opNode.childNodes: if (node.nodeType==Node.ELEMENT_NODE): if (node.tagName == "name"): ifname = string.strip(str(node.childNodes[0].nodeValue)) elif (node.tagName == "mtu"): mtu = int(string.strip(str(node.childNodes[0].nodeValue))) elif (node.tagName == "ipv4"): for n in node.childNodes: if (n.nodeType==Node.ELEMENT_NODE): if (n.tagName == "broadcast"): broadcast = string.strip(str(n.childNodes[0].nodeValue)) elif (n.tagName == "netmask"): netmask = string.strip(str(n.childNodes[0].nodeValue)) elif (n.tagName == "address-v4"): address = string.strip(str(n.childNodes[0].nodeValue)) # ... addr v6... if ifname != None: if mtu != None: macrocommand.add(SetMtu(ifname,mtu)) if broadcast !=None: macrocommand.add(SetBroadcast(ifname,broadcast)) if netmask !=None: macrocommand.add(SetNetmask(ifname,netmask)) if address != None: macrocommand.add(SetAddr(ifname,address)) elif (nodeName == "mtu"): ifname = None mtu = None if (opValue == C.DELETE or opValue == C.CREATE): moduleReply = ModuleReply( error_type=ModuleReply.PROTOCOL, error_tag=ModuleReply.OPERATION_FAILED, error_severity=ModuleReply.ERROR, error_message="Sorry, mtu can not be deleted or created. Only interface element can.") return moduleReply elif (opValue == C.MERGE or opValue == C.REPLACE): # first find ifName for k in opNode.parent.childNodes: if (k.nodeType==Node.ELEMENT_NODE): if (k.tagName == "name"): ifname = string.strip(str(k.childNodes[0].nodeValue)) # Then get the new mtu value mtu = int(string.strip(str(opNode.childNodes[0].nodeValue))) if ifname != None: # Build the command and add it to the macro command macrocommand.add(SetMtu(ifname,mtu)) elif (nodeName == "broadcast"): ifname = None broadcast = None if (opValue == C.DELETE or opValue == C.CREATE): moduleReply = ModuleReply( error_type=ModuleReply.PROTOCOL, error_tag=ModuleReply.OPERATION_FAILED, error_severity=ModuleReply.ERROR, error_message="Sorry, broadcast can not be deleted or created. Only interface element can.") return moduleReply elif (opValue == C.MERGE or opValue == C.REPLACE): # first find ifName for k in opNode.parent.parent.childNodes: if (k.nodeType==Node.ELEMENT_NODE): if (k.tagName == "name"): ifname = string.strip(str(k.childNodes[0].nodeValue)) # Then get the new mtu value broadcast = int(string.strip(str(opNode.childNodes[0].nodeValue))) if ifname != None: # Build the command and add it to the macro command macrocommand.add(SetBroadcast(ifname,broadcast)) elif (nodeName == "netmask"): ifname = None netmask = None if (opValue == C.DELETE or opValue == C.CREATE): moduleReply = ModuleReply( error_type=ModuleReply.PROTOCOL, error_tag=ModuleReply.OPERATION_FAILED, error_severity=ModuleReply.ERROR, error_message="Sorry, netmask can not be deleted or created. Only interface element can.") return moduleReply elif (opValue == C.MERGE or opValue == C.REPLACE): # first find ifName for k in opNode.parent.parent.childNodes: if (k.nodeType==Node.ELEMENT_NODE): if (k.tagName == "name"): ifname = string.strip(str(k.childNodes[0].nodeValue)) # Then get the new mtu value netmask = int(string.strip(str(opNode.childNodes[0].nodeValue))) if ifname != None: # Build the command and add it to the macro command macrocommand.add(SetNetmask(ifname,netmask)) elif (nodeName == "address-v4"): ifname = None address = None if (opValue == C.DELETE or opValue == C.CREATE): moduleReply = ModuleReply( error_type=ModuleReply.PROTOCOL, error_tag=ModuleReply.OPERATION_FAILED, error_severity=ModuleReply.ERROR, error_message="Sorry, address-v4 can not be deleted or created. Only interface element can.") return moduleReply elif (opValue == C.MERGE or opValue == C.REPLACE): # first find ifName for k in opNode.parent.parent.childNodes: if (k.nodeType==Node.ELEMENT_NODE): if (k.tagName == "name"): ifname = string.strip(str(k.childNodes[0].nodeValue)) # Then get the new mtu value address = int(string.strip(str(opNode.childNodes[0].nodeValue))) if ifname != None: # Build the command and add it to the macro command macrocommand.add(SetAddr(ifname,address)) # elif ... # Prepare the commands that must be executed and add them to a macro command #macrocommand = MacroCommand() #macrocommand.add(SetMtu("eth0",1200)) #macrocommand.add(SetBroadcast("eth0","152.81.15.255")) #macrocommand.add(SetNetmask("eth0","255.255.240.0")) #macrocommand.add(SetAddr("eth0","152.81.8.136")) # Then, make the changes by executing the macro command try: macrocommand.execute() moduleReply = ModuleReply() except Exception,exp: moduleReply = ModuleReply( error_type=ModuleReply.PROTOCOL, error_tag=ModuleReply.OPERATION_FAILED, error_severity=ModuleReply.ERROR, error_message="Interfaces_Module.py ERROR: "+str(exp))
def xpath(node, xpath): '''Evaluate an xpath of an arbitrary node''' nodes = Evaluate(xpath, node) return nodes
def insert_math_images(file): file = os.path.abspath(file) doc = NonvalidatingReader.parseUri(file) ctxt = Context(doc, processorNss=NSS) # Check that verbatim math is used for node in Evaluate("//xhtml:span[@class='verbatimmath']/@lxir:value", context=ctxt): verbatimmath = node.value assert verbatimmath == u'true', "Need verbatim math mode for math conversion" # Check that the document class is known latexClass = None symbols = [] for node in Evaluate( "//xhtml:span[@class='ClassOrPackageUsed']/@lxir:name", context=ctxt): if latexClasses.has_key(node.value): latexClass = latexClasses[node.value] elif node.value in symbolPackages: symbols.append(node.value[:-4]) assert latexClass, "Unknown document class used" # Get All macro text macros = [] for node in Evaluate("//xhtml:span[@class='macro']//text()", context=ctxt): macros.append(node.nodeValue) gen = ImageGenerator(file, latexClass, macros, symbols) # Convert All math images for node in Evaluate("//xhtml:span[@class='formule']", context=ctxt): c = Context(node, processorNss=NSS) formula = "" for t in Evaluate("xhtml:span[@class='text']/text()", context=c): formula += t.nodeValue formula = formula.strip() if not len(formula): print "empty formula found in document" image, mathml, label = None, None, None else: if formula[0] != "$": p = node.parentNode env = p.getAttributeNS(None, 'class') assert env, "No env found for equation" if env[-5:] == "-star": env = env[:-5] + "*" formula = "\\begin{" + env + "}\n" + formula + "\n\\end{" + env + "}" image, mathml, label = gen.makeImage(formula) # remove the empty text node(s) for t in Evaluate("xhtml:span[@class='text']", context=c): t.parentNode.removeChild(t) if image: img = node.ownerDocument.createElementNS(XHTML_NAMESPACE, "img") img.setAttributeNS(XHTML_NAMESPACE, "src", image) img.setAttributeNS(XHTML_NAMESPACE, "alt", formula) node.appendChild(img) if mathml: if mathml.tagName != 'math': # here, we have the case : a$_b$ # mathml is: <span class='msub'><span class='mi'/><span>b</span></span> # original xml is : ... <span>a</span><span class="formula"> ...</span> # and node is the formula # p is <span>a</span> p = get_prev_span_node(node) newNode = node.parentNode.insertBefore(mathml.cloneNode(True), node) newNode.firstChild.appendChild(p) node.parentNode.removeChild(node) print "Formula '%s' replaced by simple form (%s)." % ( formula, newNode.tagName + '.' + newNode.getAttributeNS(None, u'class')) else: node.appendChild(node.ownerDocument.importNode(mathml, True)) if label: node.appendChild(node.ownerDocument.importNode(label, True)) base, ext = os.path.splitext(file) output = base + "_images" + ext o = open(output, "w") Print(doc, stream=o) o.close()
def _getLabel(self, context): nodes = Evaluate("//xhtml:a[@class='label']", context=context) if not nodes or len(nodes) == 0: return None return nodes[0]
if self.target in [C.RUNNING, C.CANDIDATE, C.STARTUP]: if self.target == C.CANDIDATE: self.datastoreManager.initializeAll(self.target) for module in self.moduleManager.getModules(): sourceNode = None if sourceDoc != None: currentPath = module.path # Finding the nodes (related to the current module) in the received configuration try: ctx = Context(sourceDoc, processorNss=self.moduleManager.prefixes) nodeList = Evaluate(currentPath, ctx) except Exception, exp: moduleReply = ModuleReply( error_type=ModuleReply.APPLICATION, error_tag=ModuleReply.UNKNOWN_ELEMENT, error_severity=ModuleReply.ERROR, error_message=str(exp)) self.operationReply.setError() self.operationReply.setNode( moduleReply.getXMLNodeReply()) return self.operationReply # Distributing the nodes to the current module: if len(nodeList) > 1: moduleReply = ModuleReply(
def execute(self): """ Execute the edit-config operation. """ if self.operationReply.isError(): return self.operationReply sessionId = sessionManager.getInstance().getLockOwnerSessionId( self.target) if sessionId >= 0 and sessionId != self.session.getSessionId(): # Somebody else locked the target. moduleReply = ModuleReply( error_type=ModuleReply.PROTOCOL, error_tag=ModuleReply.IN_USE, error_severity=ModuleReply.ERROR, error_message= "Operation failed, target is locked by another session.") moduleReply.addErrorInfo("session-id", sessionId) self.operationReply.setError() self.operationReply.setNode(moduleReply.getXMLNodeReply()) return self.operationReply # Check access here if self.rbacManager.isActive(): operation_allowed = self.rbacManager.checkAccessEditConfig( self.config, self.session) if (not operation_allowed): moduleReply = ModuleReply(error_type=ModuleReply.PROTOCOL, error_tag=ModuleReply.ACCESS_DENIED, error_severity=ModuleReply.ERROR, error_message="Access denied.") self.operationReply.setError() self.operationReply.setNode(moduleReply.getXMLNodeReply()) return self.operationReply # Execute edit-config #if (self.target == C.RUNNING or self.target == C.URL): if (self.target in [C.RUNNING, C.STARTUP, C.CANDIDATE, C.URL]): moduleReply = None for module in self.moduleManager.getModules(): currentPath = module.path # Finding the nodes (related to the current module) # in the received configuration ctx = Context(self.config, processorNss=self.moduleManager.getPrefixes()) nodeList = Evaluate(currentPath, ctx) # Distributing the nodes to the current module if len(nodeList) > 1: moduleReply = ModuleReply( error_type=ModuleReply.APPLICATION, error_tag=ModuleReply.UNKNOWN_ELEMENT, error_severity=ModuleReply.ERROR, error_message= "More than one node found in the received data for the same module" + module.name) self.operationReply.setError() self.operationReply.setNode(moduleReply.getXMLNodeReply()) return self.operationReply elif len(nodeList) == 1: defaultOperation = self.defaultOperation node = nodeList[0] # Search for the first parent node of 'node' having xc:operation attribute and set the default value to its value: tmpNode = node.parentNode boolean = False while tmpNode != None and tmpNode.nodeType != Node.DOCUMENT_NODE and not boolean: for att in tmpNode.attributes: ns, name = att if name == 'operation' and ns == C.NETCONF_XMLNS: # We found the first parent node having an operation attribute. # This is the new default op for this module. defaultOperation = tmpNode.getAttributeNS( ns, str(name)) # Stop the loop. boolean = True tmpNode = tmpNode.parentNode # Send the operation to the module. moduleReply = module.editConfig(defaultOperation, self.testOption, self.errorOption, self.target, node) # Update the cache according to the new config. module.resetConfigTime(self.target) if (moduleReply.isError()): if self.errorOption == C.STOP_ON_ERROR: self.operationReply.setError() self.operationReply.setNode( moduleReply.getXMLNodeReply()) return self.operationReply elif self.errorOption == C.CONTINUE_ON_ERROR: pass elif self.errorOption == C.ROLLBACK_ON_ERROR: # ROLLBACK IS EXPERIMENTAL for previousmodule in self.moduleManager.getModules( ): if previousmodule is module: moduleReply = ModuleReply( error_type=ModuleReply.APPLICATION, error_tag=ModuleReply.UNKNOWN_ELEMENT, error_severity=ModuleReply.ERROR, error_message= "%s module failed and the whole operation has been rolled back." % module.name) self.operationReply.setError() self.operationReply.setNode( moduleReply.getXMLNodeReply()) return self.operationReply else: moduleReply = previousmodule.rollBack() if moduleReply.isError(): self.operationReply.setError() self.operationReply.setNode( moduleReply.getXMLNodeReply()) return self.operationReply if (moduleReply == None): moduleReply = ModuleReply( error_type=ModuleReply.APPLICATION, error_tag=ModuleReply.UNKNOWN_ELEMENT, error_severity=ModuleReply.ERROR, error_message="Not any module matched") self.operationReply.setError() self.operationReply.setNode(moduleReply.getXMLNodeReply()) return self.operationReply
def test_query(tester, dom_object, query): tester.startTest("Starting query") result = Evaluate(query, contextNode=dom_object.documentElement) tester.testDone() return result
def execute(self): """ Execute the validate operation. """ if self.operationReply.isError(): return self.operationReply # Execute validate if (self.target in [C.CANDIDATE, C.STARTUP, C.RUNNING]): moduleReply = None for module in self.moduleManager.getModules(): moduleReply = module.validate(self.target) if moduleReply.isError(): self.operationReply.setNode(moduleReply.getXMLNodeReply()) return self.operationReply self.operationReply.setNode(moduleReply.getXMLNodeReply()) return self.operationReply elif (self.target == C.CONFIG): moduleReply = None for module in self.moduleManager.getModules(): currentPath = module.path # Finding the nodes (related to the current module) # in the received configuration ctx = Context(self.config, processorNss = self.moduleManager.getPrefixes()) nodeList = Evaluate(currentPath, ctx) # Distributing the nodes to the current module if len(nodeList)>1: moduleReply = ModuleReply( error_type = ModuleReply.APPLICATION, error_tag = ModuleReply.UNKNOWN_ELEMENT, error_severity = ModuleReply.ERROR, error_message = "More than one node found in the received data for the same module" + module.name) self.operationReply.setError() self.operationReply.setNode(moduleReply.getXMLNodeReply()) return self.operationReply elif len(nodeList)==1: #Get the configuration to validate. node = nodeList[0] # Send the operation to the module. moduleReply = module.validate(self.target, self.config) if (moduleReply.isError()): self.operationReply.setError() self.operationReply.setNode(moduleReply.getXMLNodeReply()) return self.operationReply if (moduleReply == None): moduleReply = ModuleReply( error_type = ModuleReply.APPLICATION, error_tag = ModuleReply.UNKNOWN_ELEMENT, error_severity = ModuleReply.ERROR, error_message = "Not any module matched") self.operationReply.setError() self.operationReply.setNode(moduleReply.getXMLNodeReply()) return self.operationReply #If somebody has the strange idea to try this: elif (self.target == C.URL): xmlreply = ModuleReply( error_type=ModuleReply.APPLICATION, error_tag=ModuleReply.OPERATION_NOT_SUPPORTED, error_severity=ModuleReply.ERROR, error_message="OPERATION-NOT-SUPPORTED") self.operationReply.setNode(xmlReply.getXMLNodeReply()) return self.operationReply