Esempio n. 1
0
    def rpc_get_config(self, session, rpc, source_elm, filter_or_none):  # pylint: disable=W0613
        assert source_elm is not None
        if source_elm.find("nc:running", namespaces=NSMAP) is None:
            # Really this should be a different error its a bad value for source not missing
            raise ncerror.MissingElementProtoError(rpc, ncutil.qname("nc:running"))

        data = ncutil.elm("data")
        cont = ncutil.subelm(data, "interfaces")
        listval = ncutil.subelm(cont, "interface")
        listval.append(ncutil.leaf_elm("name", "Ethernet0/0"))
        listval.append(ncutil.leaf_elm("shutdown", "true"))
        listval = ncutil.subelm(cont, "interface")
        listval.append(ncutil.leaf_elm("name", "Ethernet0/1"))
        listval.append(ncutil.leaf_elm("shutdown", "false"))
        listval = ncutil.subelm(cont, "interface")
        listval.append(ncutil.leaf_elm("name", "FastEthernet1/0"))
        listval.append(ncutil.leaf_elm("shutdown", "false"))
        listval = ncutil.subelm(cont, "interface")
        listval.append(ncutil.leaf_elm("name", "FastEthernet1/1"))
        listval.append(ncutil.leaf_elm("shutdown", "false"))
        # Missing from operational
        listval.append(ncutil.leaf_elm("name", "GigabitEthernet2/0"))
        listval.append(ncutil.leaf_elm("shutdown", "false"))

        return ncutil.filter_results(rpc, data, filter_or_none)
Esempio n. 2
0
    def rpc_get(self, unused_session, unused_rpc, filter_elm):
        data = ncutil.elm("data")

        get_data_methods = {
            ncutil.qname("j:ocm-type").text: self.device.get_device_type,
            ncutil.qname("j:oper-mode").text: self.device.get_oper_mode,
            ncutil.qname("j:ident-data").text: self.device.get_idn_string,
            ncutil.qname("j:device-info").text: self.device.get_module_info,
            ncutil.qname("j:application-version").text:
            self.device.get_app_version,
            ncutil.qname("j:temp").text: self.device.get_temp_int,
        }
        if not self.device.get_device_type().startswith("tf"):
            get_data_methods[ncutil.qname(
                "j:safe-version").text] = self.device.get_safe_version

        infonode = ncutil.elm("j:info")
        # infonode = etree.Element(ncutil.qname("j:info"), nsmap={ 'j': NSMAP['j'] })

        # Get filter children
        children = []
        if filter_elm is not None:
            children = filter_elm.getchildren(
            ) if filter_elm is not None else []

        def get_all_values():
            leaf_elms = []
            for key, valuef in get_data_methods.items():
                leaf_elms.append(ncutil.leaf_elm(key, valuef()))
            return leaf_elms

        # No filter children return info only
        if not children:
            ncutil.filter_leaf_values(None, infonode, get_all_values(), data)
            return data

        # Look for info filter.
        finfo = filter_elm.find("info") or filter_elm.find("j:info",
                                                           namespaces=NSMAP)
        if finfo is not None:
            children = finfo.getchildren()
            if not children:
                leaf_elms = get_all_values()
            else:
                leaf_elms = []
                for felm in children:
                    tag = felm.tag
                    if tag in get_data_methods:
                        leaf_elms.append(
                            ncutil.leaf_elm(tag, get_data_methods[tag]()))
                        rv = ncutil.filter_leaf_values(finfo, infonode,
                                                       leaf_elms, data)
                        # Some selector doesn't match return empty.
            if rv is False:
                logger.error("XXX returning False")
                return data

        return data
Esempio n. 3
0
    def rpc_get (self, unused_session, unused_rpc, filter_elm):
        data = ncutil.elm("data")

        get_data_methods = {
            ncutil.qname("j:ocm-type").text: self.device.get_device_type,
            ncutil.qname("j:oper-mode").text: self.device.get_oper_mode,
            ncutil.qname("j:ident-data").text: self.device.get_idn_string,
            ncutil.qname("j:device-info").text: self.device.get_module_info,
            ncutil.qname("j:application-version").text: self.device.get_app_version,
            ncutil.qname("j:temp").text: self.device.get_temp_int,
        }
        if not self.device.get_device_type().startswith("tf"):
            get_data_methods[ncutil.qname("j:safe-version").text] = self.device.get_safe_version

        infonode = ncutil.elm("j:info")
        # infonode = etree.Element(ncutil.qname("j:info"), nsmap={ 'j': NSMAP['j'] })

        # Get filter children
        children = []
        if filter_elm is not None:
            children = filter_elm.getchildren() if filter_elm is not None else []

        def get_all_values ():
            leaf_elms = []
            for key, valuef in get_data_methods.items():
                leaf_elms.append(ncutil.leaf_elm(key, valuef()))
            return leaf_elms

        # No filter children return info only
        if not children:
            ncutil.filter_leaf_values(None, infonode, get_all_values(), data)
            return data

        # Look for info filter.
        finfo = filter_elm.find("info") or filter_elm.find("j:info", namespaces=NSMAP)
        if finfo is not None:
            children = finfo.getchildren()
            if not children:
                leaf_elms = get_all_values()
            else:
                leaf_elms = []
                for felm in children:
                    tag = felm.tag
                    if tag in get_data_methods:
                        leaf_elms.append(ncutil.leaf_elm(tag, get_data_methods[tag]()))
                        rv = ncutil.filter_leaf_values(finfo, infonode, leaf_elms, data)
                        # Some selector doesn't match return empty.
            if rv is False:
                logger.error("XXX returning False")
                return data

        return data
Esempio n. 4
0
    def _reader_handle_message(self, msg):
        if not self.session_open:
            return

        msg = msg.replace('\n', '').replace('\r', '').replace('\t', '')

        # Any error with XML encoding here is going to cause a session close
        # Technically we should be able to return malformed message I think.
        try:
            tree = etree.parse(io.BytesIO(msg.encode('utf-8')))
            if not tree:
                raise ncerror.SessionError(msg, "Invalid XML from client.")
        except etree.XMLSyntaxError:
            logger.warning("Closing session due to malformed message")
            raise ncerror.SessionError(msg, "Invalid XML from client.")

        if self.debug and msg.find('message-id="-1"') == -1:
            logger.debug("%s: Recieved RPC message:\n%s", str(self),
                         str(etree.tounicode(tree, pretty_print=True)))

        rpcs = tree.xpath("/nc:rpc", namespaces=NSMAP)
        if not rpcs:
            raise ncerror.SessionError(msg, "No rpc found")

        for rpc in rpcs:
            try:
                msg_id = rpc.get('message-id')
                if self.debug:
                    logger.debug("%s: Received rpc message-id: %s", str(self),
                                 msg_id)
            except (TypeError, ValueError):
                raise ncerror.SessionError(
                    msg, "No valid message-id attribute found")

            try:
                # Get the first child of rpc as the method name
                rpc_method = rpc.getchildren()
                if len(rpc_method) != 1:
                    if self.debug:
                        logger.debug("%s: Bad Msg: msg-id: %s", str(self),
                                     msg_id)
                    raise ncerror.MalformedMessageRPCError(rpc)
                rpc_method = rpc_method[0]

                rpcname = rpc_method.tag.replace(qmap('nc'), "")
                params = rpc_method.getchildren()
                paramslen = len(params)
                lock_target = None

                if self.debug:
                    logger.debug("%s: RPC: %s: paramslen: %s", str(self),
                                 rpcname, str(paramslen))

                if rpcname == "close-session":
                    # XXX should be RPC-unlocking if need be
                    if self.debug:
                        logger.debug("%s: Received close-session msg-id: %s",
                                     str(self), msg_id)
                    self._send_rpc_reply(etree.Element("ok"), rpc)
                    self.close()
                    # XXX should we also call the user method if it exists?
                    return
                elif rpcname == "kill-session":
                    # XXX we are supposed to cleanly abort anything underway
                    if self.debug:
                        logger.debug("%s: Received kill-session msg-id: %s",
                                     str(self), msg_id)
                    self._send_rpc_reply(etree.Element("ok"), rpc)
                    self.close()
                    # XXX should we also call the user method if it exists?
                    return
                elif rpcname == "get":
                    # Validate GET parameters

                    if paramslen > 1:
                        # XXX need to specify all elements not known
                        raise ncerror.MalformedMessageRPCError(rpc)
                    if params and not util.filter_tag_match(
                            params[0], "nc:filter"):
                        raise ncerror.UnknownElementProtoError(rpc, params[0])
                    if not params:
                        params = [None]
                elif rpcname == "get-config":
                    # Validate GET-CONFIG parameters

                    if paramslen > 2:
                        # XXX Should be ncerror.UnknownElementProtoError? for each?
                        raise ncerror.MalformedMessageRPCError(rpc)
                    source_param = rpc_method.find("nc:source",
                                                   namespaces=NSMAP)
                    if source_param is None:
                        raise ncerror.MissingElementProtoError(
                            rpc, util.qname("nc:source"))
                    filter_param = None
                    if paramslen == 2:
                        filter_param = rpc_method.find("nc:filter",
                                                       namespaces=NSMAP)
                        if filter_param is None:
                            unknown_elm = params[
                                0] if params[0] != source_param else params[1]
                            raise ncerror.UnknownElementProtoError(
                                rpc, unknown_elm)
                    params = [source_param, filter_param]
                elif rpcname == "lock" or rpcname == "unlock":
                    if paramslen != 1:
                        raise ncerror.MalformedMessageRPCError(rpc)
                    target_param = rpc_method.find("nc:target",
                                                   namespaces=NSMAP)
                    if target_param is None:
                        raise ncerror.MissingElementProtoError(
                            rpc, util.qname("nc:target"))
                    elms = target_param.getchildren()
                    if len(elms) != 1:
                        raise ncerror.MissingElementProtoError(
                            rpc, util.qname("nc:target"))
                    lock_target = elms[0].tag.replace(qmap('nc'), "")
                    if lock_target not in ["running", "candidate"]:
                        raise ncerror.BadElementProtoError(
                            rpc, util.qname("nc:target"))
                    params = [lock_target]

                    if rpcname == "lock":
                        logger.error("%s: Lock Target: %s", str(self),
                                     lock_target)
                        # Try and obtain the lock.
                        locksid = self.server.lock_target(self, lock_target)
                        if locksid:
                            raise ncerror.LockDeniedProtoError(rpc, locksid)
                    elif rpcname == "unlock":
                        logger.error("%s: Unlock Target: %s", str(self),
                                     lock_target)
                        # Make sure we have the lock.
                        locksid = self.server.is_target_locked(lock_target)
                        if locksid != self.session_id:
                            # An odd error to return
                            raise ncerror.LockDeniedProtoError(rpc, locksid)

                #------------------
                # Call the method.
                #------------------

                try:
                    # Handle any namespaces or prefixes in the tag, other than
                    # "nc" which was removed above. Of course, this does not handle
                    # namespace collisions, but that seems reasonable for now.
                    rpcname = rpcname.rpartition("}")[-1]
                    method_name = "rpc_" + rpcname.replace('-', '_')
                    method = getattr(self.methods, method_name, None)

                    if method is None:
                        if rpcname in self.handled_rpc_methods:
                            self._send_rpc_reply(etree.Element("ok"), rpc)
                            method = None
                        else:
                            method = self._rpc_not_implemented

                    if method is not None:
                        if self.debug:
                            logger.debug("%s: Calling method: %s", str(self),
                                         method_name)
                        reply = method(self, rpc, *params)
                        self._send_rpc_reply(reply, rpc)
                except Exception:
                    # If user raised error unlock if this was lock
                    if rpcname == "lock" and lock_target:
                        self.server.unlock_target(self, lock_target)
                    raise

                # If this was unlock and we're OK, release the lock.
                if rpcname == "unlock":
                    self.server.unlock_target(self, lock_target)

            except ncerror.MalformedMessageRPCError as msgerr:
                if self.new_framing:
                    if self.debug:
                        logger.debug("%s: MalformedMessageRPCError: %s",
                                     str(self), str(msgerr))
                    self.send_message(msgerr.get_reply_msg())
                else:
                    # If we are 1.0 we have to simply close the connection
                    # as we are not allowed to send this error
                    logger.warning(
                        "Closing 1.0 session due to malformed message")
                    raise ncerror.SessionError(msg, "Malformed message")
            except ncerror.RPCServerError as error:
                if self.debug:
                    logger.debug("%s: RPCServerError: %s", str(self),
                                 str(error))
                self._send_rpc_reply_error(error)
            except EOFError:
                if self.debug:
                    logger.debug("%s: Got EOF in reader_handle_message",
                                 str(self))
                error = ncerror.RPCSvrException(rpc, EOFError("EOF"))
                self._send_rpc_reply_error(error)
            except Exception as exception:
                if self.debug:
                    logger.debug(
                        "%s: Got unexpected exception in reader_handle_message: %s",
                        str(self), str(exception))
                error = ncerror.RPCSvrException(rpc, exception)
                self._send_rpc_reply_error(error)
Esempio n. 5
0
    def _reader_handle_message(self, msg):
        if not self.session_open:
            return

        # Any error with XML encoding here is going to cause a session close
        # Technically we should be able to return malformed message I think.
        try:
            tree = etree.parse(io.BytesIO(msg.encode('utf-8')))
            if not tree:
                raise ncerror.SessionError(msg, "Invalid XML from client.")
        except etree.XMLSyntaxError:
            logger.warning("Closing session due to malformed message")
            raise ncerror.SessionError(msg, "Invalid XML from client.")

        rpcs = tree.xpath("/nc:rpc", namespaces=NSMAP)
        if not rpcs:
            raise ncerror.SessionError(msg, "No rpc found")

        for rpc in rpcs:
            try:
                msg_id = rpc.get('message-id')
                if self.debug:
                    logger.debug("%s: Received rpc message-id: %s", str(self),
                                 msg_id)
            except (TypeError, ValueError):
                raise ncerror.SessionError(
                    msg, "No valid message-id attribute found")

            try:
                # Get the first child of rpc as the method name
                rpc_method = rpc.getchildren()
                if len(rpc_method) != 1:
                    if self.debug:
                        logger.debug("%s: Bad Msg: msg-id: %s", str(self),
                                     msg_id)
                    raise ncerror.MalformedMessageRPCError(rpc)
                rpc_method = rpc_method[0]

                rpcname = rpc_method.tag.replace(qmap('nc'), "")
                params = rpc_method.getchildren()
                paramslen = len(params)

                if self.debug:
                    logger.debug("%s: RPC: %s: paramslen: %s", str(self),
                                 rpcname, str(paramslen))

                if rpcname == "close-session":
                    # XXX should be RPC-unlocking if need be
                    if self.debug:
                        logger.debug("%s: Received close-session msg-id: %s",
                                     str(self), msg_id)
                    self._send_rpc_reply(etree.Element("ok"), rpc)
                    self.close()
                    # XXX should we also call the user method if it exists?
                    return
                elif rpcname == "kill-session":
                    # XXX we are supposed to cleanly abort anything underway
                    if self.debug:
                        logger.debug("%s: Received kill-session msg-id: %s",
                                     str(self), msg_id)
                    self._send_rpc_reply(etree.Element("ok"), rpc)
                    self.close()
                    # XXX should we also call the user method if it exists?
                    return
                elif rpcname == "get":
                    # Validate GET parameters

                    if paramslen > 1:
                        # XXX need to specify all elements not known
                        raise ncerror.MalformedMessageRPCError(rpc)
                    if params and not util.filter_tag_match(
                            params[0], "nc:filter"):
                        raise ncerror.UnknownElementProtoError(rpc, params[0])
                    if not params:
                        params = [None]
                elif rpcname == "get-config":
                    # Validate GET-CONFIG parameters

                    if paramslen > 2:
                        # XXX Should be ncerror.UnknownElementProtoError? for each?
                        raise ncerror.MalformedMessageRPCError(rpc)
                    source_param = rpc_method.find("nc:source",
                                                   namespaces=NSMAP)
                    if source_param is None:
                        raise ncerror.MissingElementProtoError(
                            rpc, util.qname("nc:source"))
                    filter_param = None
                    if paramslen == 2:
                        filter_param = rpc_method.find("nc:filter",
                                                       namespaces=NSMAP)
                        if filter_param is None:
                            unknown_elm = params[
                                0] if params[0] != source_param else params[1]
                            raise ncerror.UnknownElementProtoError(
                                rpc, unknown_elm)
                    params = [source_param, filter_param]

                #------------------
                # Call the method.
                #------------------

                try:
                    # Handle any namespaces or prefixes in the tag, other than
                    # "nc" which was removed above. Of course, this does not handle
                    # namespace collisions, but that seems reasonable for now.
                    rpcname = rpcname.rpartition("}")[-1]
                    method_name = "rpc_" + rpcname.replace('-', '_')
                    method = getattr(self.methods, method_name,
                                     self._rpc_not_implemented)
                    if self.debug:
                        logger.debug("%s: Calling method: %s", str(self),
                                     method_name)
                    reply = method(self, rpc, *params)
                    self._send_rpc_reply(reply, rpc)
                except NotImplementedError:
                    raise ncerror.OperationNotSupportedProtoError(rpc)
            except ncerror.MalformedMessageRPCError as msgerr:
                if self.new_framing:
                    if self.debug:
                        logger.debug("%s: MalformedMessageRPCError: %s",
                                     str(self), str(msgerr))
                    self.send_message(msgerr.get_reply_msg())
                else:
                    # If we are 1.0 we have to simply close the connection
                    # as we are not allowed to send this error
                    logger.warning(
                        "Closing 1.0 session due to malformed message")
                    raise ncerror.SessionError(msg, "Malformed message")
            except ncerror.RPCServerError as error:
                if self.debug:
                    logger.debug("%s: RPCServerError: %s", str(self),
                                 str(error))
                self._send_rpc_reply_error(error)
            except EOFError:
                if self.debug:
                    logger.debug("%s: Got EOF in reader_handle_message",
                                 str(self))
                error = ncerror.RPCSvrException(rpc, EOFError("EOF"))
                self._send_rpc_reply_error(error)
            except Exception as exception:
                if self.debug:
                    logger.debug(
                        "%s: Got unexpected exception in reader_handle_message: %s",
                        str(self), str(exception))
                error = ncerror.RPCSvrException(rpc, exception)
                self._send_rpc_reply_error(error)