blob: 7a33f695d9abd4229fbe9fab711f387eddf0d84e [file] [log] [blame]
Khen Nursimulu3869d8d2016-11-28 20:44:28 -05001# -*- coding: utf-8 -*-#
2#
3# February 19 2015, Christian Hopps <chopps@gmail.com>
4#
5# Copyright (c) 2015, Deutsche Telekom AG
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19from __future__ import absolute_import, division, unicode_literals, \
20 print_function, nested_scopes
21from lxml import etree
22from netconf import NSMAP
23
24
25class NetconfException(Exception):
26 pass
27
28
29class ChannelClosed(NetconfException):
30 pass
31
32
33class FramingError(NetconfException):
34 pass
35
36
37class SessionError(NetconfException):
38 pass
39
40
41class RPCError(NetconfException):
42 def __init__(self, output, tree, error):
43 super(RPCError, self).__init__(output)
44 self.tree = tree
45 self.error = error
46
47 def _get_error_val(self, value):
48 try:
49 return self.error.xpath("nc:" + value, namespaces=NSMAP)[0].text
50 except IndexError:
51 return None
52
53 def get_error_tag(self):
54 return self._get_error_val("error-tag")
55
56 def get_error_type(self):
57 return self._get_error_val("error-type")
58
59 def get_error_info(self):
60 return self._get_error_val("error-info")
61
62 def get_error_severity(self):
63 return self._get_error_val("error-severity")
64
65
66# RFC6241
67
68# error-type
69RPCERR_TYPE_TRANSPORT = 0
70RPCERR_TYPE_RPC = 1
71RPCERR_TYPE_PROTOCOL = 2
72RPCERR_TYPE_APPLICATION = 3
73RPCERR_TYPE_ENUM = {
74 RPCERR_TYPE_TRANSPORT: "transport",
75 RPCERR_TYPE_RPC: "rpc",
76 RPCERR_TYPE_PROTOCOL: "protocol",
77 RPCERR_TYPE_APPLICATION: "application"
78}
79
80# error-tag
81RPCERR_TAG_IN_USE = "in-use"
82RPCERR_TAG_INVALID_VALUE = "invalid-value"
83RPCERR_TAG_TOO_BIG = "too-big"
84RPCERR_TAG_MISSING_ATTRIBUTE = "missing-attribute"
85RPCERR_TAG_BAD_ATTRIBUTE = "bad-attribute"
86RPCERR_TAG_UNKNOWN_ATTRIBUTE = "unknown-attribute"
87RPCERR_TAG_MISSING_ELEMENT = "missing-element"
88RPCERR_TAG_BAD_ELEMENT = "bad-element"
89RPCERR_TAG_UNKNOWN_ELEMENT = "unknown-element"
90RPCERR_TAG_UNKNOWN_NAMESPACE = "unknown-namespace"
91RPCERR_TAG_ACCESS_DENIED = "access-denied"
92RPCERR_TAG_LOCK_DENIED = "lock-denied"
93RPCERR_TAG_RESOURCE_DENIED = "resource-denied"
94RPCERR_TAG_ROLLBACK_FAILED = "rollback-failed"
95RPCERR_TAG_DATA_EXISTS = "data-exists"
96RPCERR_TAG_DATA_MISSING = "data-missing"
97RPCERR_TAG_OPERATION_NOT_SUPPORTED = "operation-not-supported"
98RPCERR_TAG_OPERATION_FAILED = "operation-failed"
99RPCERR_TAG_MALFORMED_MESSAGE = "malformed-message"
100
101
102# error-app-tag
103# error-path # xpath associated with error.
104# error-message # human readable message describiing error
105# error-info
106
107
108class RPCServerError(NetconfException):
109 def __init__(self, origmsg, etype, tag, **kwargs):
110 # Add attrib and nsmap from original message.
111 self.reply = etree.Element("rpc-reply", attrib=origmsg.attrib,
112 nsmap=origmsg.nsmap)
113
114 rpcerr = etree.SubElement(self.reply, "rpc-error")
115
116 # We require a type, tag, and severity assuming error for severity.
117 if etype in RPCERR_TYPE_ENUM:
118 etype = RPCERR_TYPE_ENUM[etype]
119 etree.SubElement(rpcerr, "error-type").text = str(etype)
120
121 etree.SubElement(rpcerr, "error-tag").text = tag
122
123 if "severity" not in kwargs:
124 etree.SubElement(rpcerr, "error-severity").text = "error"
125
126 # Now convert any other arguments to xml
127 for key, value in kwargs.items():
128 key = key.replace('_', '-')
129 etree.SubElement(rpcerr, "error-{}".format(key)).text = str(value)
130
131 # This sort of sucks for humans
132 super(RPCServerError, self).__init__(self.get_reply_msg())
133
134 def get_reply_msg(self):
135 return etree.tounicode(self.reply)
136
137
138class RPCSvrErrBadMsg(RPCServerError):
139 """If the server raises this exception the and netconf 1.0 is in use, the session will be closed"""
140
141 def __init__(self, origmsg):
142 RPCServerError.__init__(self, origmsg, RPCERR_TYPE_RPC,
143 RPCERR_TAG_MALFORMED_MESSAGE)
144
145
146class RPCSvrInvalidValue(RPCServerError):
147 def __init__(self, origmsg, **kwargs):
148 RPCServerError.__init__(self, origmsg, RPCERR_TYPE_RPC,
149 RPCERR_TAG_INVALID_VALUE, **kwargs)
150
151
152class RPCSvrMissingElement(RPCServerError):
153 def __init__(self, origmsg, tag, **kwargs):
154 try:
155 # Old API had this as an element...
156 tag = tag.tag
157 except AttributeError:
158 pass
159 RPCServerError.__init__(self, origmsg, RPCERR_TYPE_RPC,
160 RPCERR_TAG_MISSING_ELEMENT, info=tag, **kwargs)
161
162
163class RPCSvrBadElement(RPCServerError):
164 def __init__(self, origmsg, element, **kwargs):
165 RPCServerError.__init__(self, origmsg, RPCERR_TYPE_RPC,
166 RPCERR_TAG_BAD_ELEMENT, info=element.tag,
167 **kwargs)
168
169
170class RPCSvrUnknownElement(RPCServerError):
171 def __init__(self, origmsg, element, **kwargs):
172 RPCServerError.__init__(self, origmsg, RPCERR_TYPE_RPC,
173 RPCERR_TAG_UNKNOWN_ELEMENT, info=element.tag,
174 **kwargs)
175
176
177class RPCSvrErrNotImpl(RPCServerError):
178 def __init__(self, origmsg, **kwargs):
179 RPCServerError.__init__(self, origmsg, RPCERR_TYPE_PROTOCOL,
180 RPCERR_TAG_OPERATION_NOT_SUPPORTED, **kwargs)
181
182
183class RPCSvrException(RPCServerError):
184 def __init__(self, origmsg, exception, **kwargs):
185 RPCServerError.__init__(self, origmsg, RPCERR_TYPE_PROTOCOL,
186 RPCERR_TAG_OPERATION_FAILED,
187 info=str(exception), **kwargs)
188
189
190__author__ = 'Christian Hopps'
191__date__ = 'February 19 2015'
192__version__ = '1.0'
193__docformat__ = "restructuredtext en"