def get_rpc_handler(self, rpc_node, msg, grpc_channel, session, capabilities): try: # Parse the request into a dictionary log.info("rpc-node", node=etree.tostring(rpc_node, pretty_print=True)) request = self.parse_xml_request(rpc_node) if not request: log.error("request-bad-format") raise ncerror.BadMsg(rpc_node) log.info("parsed-request", request=request) if not request.has_key('message_id'): log.error("request-no-message-id") raise ncerror.BadMsg(rpc_node) class_handler = self._get_rpc_handler(request['command']) if class_handler is not None: return class_handler(request, rpc_node, grpc_channel, session, capabilities) log.error("rpc-not-implemented", rpc=request['command']) except ncerror.BadMsg as err: log.info('ncerror.BadMsg') raise ncerror.BadMsg(rpc_node) except Exception as e: log.exception('exception', e=e) raise ncerror.ServerException(rpc_node, exception=e)
def _validate_parameters(self): log.info('validate-parameters', session=self.session.session_id) # Validate the GET-SCHEMA command if self.request: try: if self.request['command'] != 'get-schema' or \ not self.request.has_key('identifier') or \ not self.request.has_key('format') or \ not self.request.has_key('version'): self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(self.request_xml) return if self.request.has_key('filter'): if not self.request.has_key('class'): self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg( self.request_xml) return # Verify that the requested schema exists if not self.capabilities.is_schema_supported(self.request[ 'identifier']) \ or self.request['format'] != 'yang' : self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(self.request_xml) return except Exception as e: self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(self.request) return
def _extract_parameters(self): try: rpc_node = self.request_xml.find(''.join( [qmap(C.VOLTHA), self.request['command']])) # Parse rpc the parameters self.request['params'] = self._parse_params(rpc_node) # Remove the subclass element in the request if it is present as # it is not required for rpc calls if self.request.has_key('subclass'): self.request.pop('subclass', None) # Extract the service and method from the rpc command command = self.request['command'].split('-') if len(command) != 2: log.debug('invalid-format', command=self.request['command']) raise self.service = command[0] self.method = command[1] if self.request.has_key('metadata'): self.metadata = self.request['metadata'] except Exception as e: self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(self.request_xml) log.exception('params-parsing-error', xml=self.request_xml, e=e)
def _validate_parameters(self): log.info('validate-parameters', session=self.session.session_id) self.params = self.rpc_method.getchildren() paramslen = len(self.params) # Verify that the source parameter is present if paramslen > 2: # TODO: need to specify all elements not known self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(self.rpc_request) return self.source_param = self.rpc_method.find(C.NC_SOURCE, namespaces=C.NS_MAP) # if self.source_param is None: # self.rpc_response.is_error = True # self.rpc_response.node = ncerror.MissingElement( # self.rpc_request, elm(C.NC_SOURCE)) # return self.filter_param = None if paramslen == 2: self.filter_param = self.rpc_method.find(C.NC_FILTER, namespaces=C.NS_MAP) if self.filter_param is None: unknown_elm = self.params[0] if self.params[0] != \ self.source_param else \ self.params[1] self.rpc_response.is_error = True self.rpc_response.node = ncerror.UnknownElement( self.rpc_request, unknown_elm) self.params = [self.source_param, self.filter_param]
def _validate_parameters(self): log.info('validate-parameters', session=self.session.session_id) # Validate the GET command if self.request: try: if self.request['command'] != 'get-schemas': self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(self.request_xml) return if self.request.has_key('filter'): if not self.request.has_key('class'): self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg( self.request_xml) return except Exception as e: self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(self.request) return
def _validate_parameters(self): if self.request: try: if self.request['command'] != 'close-session': self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(self.request_xml) return except Exception as e: self.rpc_response.is_error = True self.rpc_response.node = ncerror.ServerException( self.request_xml) return
def _validate_parameters(self): log.info('validate-parameters', session=self.session.session_id) # For now just validate that the command is presenf if self.request: try: if self.request['command'] is None: self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(self.request_xml) return except Exception as e: self.rpc_response.is_error = True self.rpc_response.node = ncerror.ServerException( self.request_xml) return
def build_yang_response(self, root, request, yang_options=None, custom_rpc=False): try: self.custom_rpc = custom_rpc yang_xml = self.to_yang_xml(root, request, yang_options, custom_rpc) log.info('yang-xml', yang_xml=etree.tounicode(yang_xml, pretty_print=True)) return self.build_xml_response(request, yang_xml, custom_rpc) except Exception as e: log.exception('error-building-yang-response', request=request, xml=etree.tostring(root)) self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(request) return
def execute(self): if self.rpc_response.is_error: returnValue(self.rpc_response) log.info('get-schema-request', session=self.session.session_id, request=self.request) # Get the yang schema content # TODO: Use version as well content = yield self.capabilities.get_schema_content( self.request['identifier']) if not content: self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(self.request_xml) returnValue(self.rpc_response) self.rpc_response.node = yield self.create_xml_response(content) self.rpc_response.is_error = False returnValue(self.rpc_response)
def _validate_parameters(self): for child in self.rpc_method.getchildren(): # There cannot be parameters to a close session request self.rpc_response.is_error = True self.rpc_response.node = ncerror.BadMsg(self.rpc_request) return
def handle_request(self, msg): if not self.session.session_opened: return # Any error with XML encoding here is going to cause a session close try: tree = etree.parse(io.BytesIO(msg.encode('utf-8'))) if not tree: raise ncerror.SessionError(msg, "Invalid XML from client.") except etree.XMLSyntaxError: log.error("malformed-message", msg=msg) try: error = ncerror.BadMsg(msg) self.send_message(error.get_reply_msg()) except AttributeError: log.error("attribute-error", msg=msg) # close session self.close() return rpcs = tree.xpath(C.RPC_XPATH, namespaces=C.NS_MAP) if not rpcs: raise ncerror.SessionError(msg, "No rpc found") # A message can have multiple rpc requests rpc_factory = get_rpc_factory_instance() for rpc in rpcs: try: # Validate message id is received try: msg_id = rpc.get(C.MESSAGE_ID) log.info("Received-rpc-message-id", msg_id=msg_id) except (TypeError, ValueError): log.error('no-message-id', rpc=rpc) raise ncerror.MissingElement(msg, C.MESSAGE_ID) # Get a rpc handler rpc_handler = rpc_factory.get_rpc_handler( rpc, msg, self.grpc_client, self.session, self.capabilities) if rpc_handler: # set the parameters for this handler response = yield rpc_handler.execute() log.info('handler', rpc_handler=rpc_handler, is_error=response.is_error, custom_rpc=response.custom_rpc, response=response) if not response.is_error: if response.custom_rpc: self.send_custom_rpc_reply(response.node, rpc) else: self.send_rpc_reply(response.node, rpc) # self.send_rpc_reply(self.get_mock_volthainstance(), rpc) else: self.send_message(response.node.get_xml_reply()) if response.close_session: log.info('response-closing-session', response=response) self.close() else: log.error('no-rpc-handler', request=msg, session_id=self.session.session_id) error = ncerror.NotImpl(rpc) self.send_message(error.get_xml_reply()) except ncerror.BadMsg as err: log.info('ncerror.BadMsg') if self.new_framing: self.send_message(err.get_xml_reply()) else: # If we are 1.0 we have to simply close the connection # as we are not allowed to send this error log.error("Closing-1-0-session--malformed-message") self.close() except (ncerror.NotImpl, ncerror.MissingElement) as e: log.exception('error', e=e) self.send_message(e.get_reply_msg()) except Exception as e: log.exception('Exception', e=e) error = ncerror.ServerException(rpc, e) self.send_message(error.get_xml_reply())