summaryrefslogtreecommitdiffstats
path: root/src/vpp-api
diff options
context:
space:
mode:
authorPaul Vinciguerra <pvinci@vinciconsulting.com>2018-11-27 08:15:22 -0800
committerOle Trøan <otroan@employees.org>2018-11-29 19:18:07 +0000
commit6ccc6e91648312cc210e9b6a18e469e64f4a523f (patch)
treec80d92e7d8c1c28f90cb92d4455c39c52f3b2617 /src/vpp-api
parent039a1c2f1401ebf3b38fa9bd55dffff0713b8b98 (diff)
vpp_papi: Add custom exceptions.
This patchset adds and raises the following custom exception classes: * class VPPApiError(Exception): * class VPPNotImplementedError(NotImplementedError): * class VPPIOError(IOError): * class VPPRuntimeError(RuntimeError): * class VPPValueError(ValueError): * class VPPSerializerValueError(ValueError): * class VPPStatsIOError(IOError): * class VPPStatsClientLoadError(RuntimeError): * class VppTransportShmemIOError(IOError): * class VppTransportSocketIOError(IOError) Change-Id: Ia40900fd2dcef148d01125d6c691329fc666901e Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
Diffstat (limited to 'src/vpp-api')
-rw-r--r--src/vpp-api/python/vpp_papi/vpp_format.py15
-rw-r--r--src/vpp-api/python/vpp_papi/vpp_papi.py49
-rw-r--r--src/vpp-api/python/vpp_papi/vpp_serializer.py54
-rw-r--r--src/vpp-api/python/vpp_papi/vpp_stats.py28
-rw-r--r--src/vpp-api/python/vpp_papi/vpp_transport_shmem.py14
-rw-r--r--src/vpp-api/python/vpp_papi/vpp_transport_socket.py15
6 files changed, 121 insertions, 54 deletions
diff --git a/src/vpp-api/python/vpp_papi/vpp_format.py b/src/vpp-api/python/vpp_papi/vpp_format.py
index d020df96188..c6f9477e03f 100644
--- a/src/vpp-api/python/vpp_papi/vpp_format.py
+++ b/src/vpp-api/python/vpp_papi/vpp_format.py
@@ -14,9 +14,16 @@
#
from socket import inet_pton, inet_ntop, AF_INET6, AF_INET
+import socket
+
+
+class VPPFormatError(Exception):
+ pass
class VPPFormat(object):
+ VPPFormatError = VPPFormatError
+
@staticmethod
def format_vl_api_ip6_prefix_t(args):
prefix, len = args.split('/')
@@ -52,7 +59,7 @@ class VPPFormat(object):
try:
return {'un': {'ip6': {'address': inet_pton(AF_INET6, args)}},
'af': int(1)}
- except Exception as e:
+ except socket.error as e:
return {'un': {'ip4': {'address': inet_pton(AF_INET, args)}},
'af': int(0)}
@@ -62,7 +69,7 @@ class VPPFormat(object):
return inet_ntop(AF_INET6, arg.un.ip6.address)
if arg.af == 0:
return inet_ntop(AF_INET, arg.un.ip4.address)
- raise
+ raise VPPFormatError
@staticmethod
def format_vl_api_prefix_t(args):
@@ -80,7 +87,7 @@ class VPPFormat(object):
return "{}/{}".format(inet_ntop(AF_INET,
arg.address.un.ip4.address),
arg.address_length)
- raise
+ raise VPPFormatError
@staticmethod
def format_u8(args):
@@ -101,7 +108,7 @@ class VPPFormat(object):
def unformat_bytes(args):
try:
return args.decode('utf-8')
- except Exception as e:
+ except ValueError as e:
return args
@staticmethod
diff --git a/src/vpp-api/python/vpp_papi/vpp_papi.py b/src/vpp-api/python/vpp_papi/vpp_papi.py
index bd2682f5b8f..3c3eb706bf9 100644
--- a/src/vpp-api/python/vpp_papi/vpp_papi.py
+++ b/src/vpp-api/python/vpp_papi/vpp_papi.py
@@ -77,6 +77,26 @@ class FuncWrapper(object):
return self._func(**kwargs)
+class VPPApiError(Exception):
+ pass
+
+
+class VPPNotImplementedError(NotImplementedError):
+ pass
+
+
+class VPPIOError(IOError):
+ pass
+
+
+class VPPRuntimeError(RuntimeError):
+ pass
+
+
+class VPPValueError(ValueError):
+ pass
+
+
class VPP(object):
"""VPP interface.
@@ -89,6 +109,11 @@ class VPP(object):
provides a means to register a callback function to receive
these messages in a background thread.
"""
+ VPPApiError = VPPApiError
+ VPPRuntimeError = VPPRuntimeError
+ VPPValueError = VPPValueError
+ VPPNotImplementedError = VPPNotImplementedError
+ VPPIOError = VPPIOError
def process_json_file(self, apidef_file):
api = json.load(apidef_file)
@@ -134,15 +159,15 @@ class VPP(object):
if len(unresolved) == 0:
break
if i > 3:
- raise ValueError('Unresolved type definitions {}'
- .format(unresolved))
+ raise VPPValueError('Unresolved type definitions {}'
+ .format(unresolved))
types = unresolved
i += 1
for m in api['messages']:
try:
self.messages[m[0]] = VPPMessage(m[0], m[1:])
- except NotImplementedError:
+ except VPPNotImplementedError:
self.logger.error('Not implemented error for {}'.format(m[0]))
def __init__(self, apifiles=None, testmode=False, async_thread=True,
@@ -192,7 +217,7 @@ class VPP(object):
if testmode:
apifiles = []
else:
- raise
+ raise VPPRuntimeError
for file in apifiles:
with open(file) as apidef_file:
@@ -202,7 +227,7 @@ class VPP(object):
# Basic sanity check
if len(self.messages) == 0 and not testmode:
- raise ValueError(1, 'Missing JSON message definitions')
+ raise VPPValueError(1, 'Missing JSON message definitions')
self.transport = VppTransport(self, read_timeout=read_timeout,
server_address=server_address)
@@ -333,7 +358,7 @@ class VPP(object):
if api_dir is None:
api_dir = cls.find_api_dir()
if api_dir is None:
- raise RuntimeError("api_dir cannot be located")
+ raise VPPApiError("api_dir cannot be located")
if isinstance(patterns, list) or isinstance(patterns, tuple):
patterns = [p.strip() + '.api.json' for p in patterns]
@@ -352,7 +377,7 @@ class VPP(object):
@property
def api(self):
if not hasattr(self, "_api"):
- raise Exception("Not connected, api definitions not available")
+ raise VPPApiError("Not connected, api definitions not available")
return self._api
def make_function(self, msg, i, multipart, do_async):
@@ -393,7 +418,7 @@ class VPP(object):
rv = self.transport.connect(name.encode(), pfx, msg_handler, rx_qlen)
if rv != 0:
- raise IOError(2, 'Connect failed')
+ raise VPPIOError(2, 'Connect failed')
self.vpp_dictionary_maxid = self.transport.msg_table_max_index()
self._register_functions(do_async=do_async)
@@ -459,7 +484,7 @@ class VPP(object):
# No context -> async notification that we feed to the callback
self.message_queue.put_nowait(r)
else:
- raise IOError(2, 'RPC reply message received in event handler')
+ raise VPPIOError(2, 'RPC reply message received in event handler')
def decode_incoming_msg(self, msg):
if not msg:
@@ -474,7 +499,7 @@ class VPP(object):
#
msgobj = self.id_msgdef[i]
if not msgobj:
- raise IOError(2, 'Reply message undefined')
+ raise VPPIOError(2, 'Reply message undefined')
r, size = msgobj.unpack(msg)
return r
@@ -502,7 +527,7 @@ class VPP(object):
def validate_args(self, msg, kwargs):
d = set(kwargs.keys()) - set(msg.field_by_name.keys())
if d:
- raise ValueError('Invalid argument {} to {}'
+ raise VPPValueError('Invalid argument {} to {}'
.format(list(d), msg.name))
def _call_vpp(self, i, msg, multipart, **kwargs):
@@ -549,7 +574,7 @@ class VPP(object):
while (True):
msg = self.transport.read()
if not msg:
- raise IOError(2, 'VPP API client: read failed')
+ raise VPPIOError(2, 'VPP API client: read failed')
r = self.decode_incoming_msg(msg)
msgname = type(r).__name__
if context not in r or r.context == 0 or context != r.context:
diff --git a/src/vpp-api/python/vpp_papi/vpp_serializer.py b/src/vpp-api/python/vpp_papi/vpp_serializer.py
index a001cca565a..f78972979cd 100644
--- a/src/vpp-api/python/vpp_papi/vpp_serializer.py
+++ b/src/vpp-api/python/vpp_papi/vpp_serializer.py
@@ -55,14 +55,10 @@ class BaseTypes(object):
return self.packer.unpack_from(data, offset)[0], self.packer.size
-types = {}
-types['u8'] = BaseTypes('u8')
-types['u16'] = BaseTypes('u16')
-types['u32'] = BaseTypes('u32')
-types['i32'] = BaseTypes('i32')
-types['u64'] = BaseTypes('u64')
-types['f64'] = BaseTypes('f64')
-types['bool'] = BaseTypes('bool')
+types = {'u8': BaseTypes('u8'), 'u16': BaseTypes('u16'),
+ 'u32': BaseTypes('u32'), 'i32': BaseTypes('i32'),
+ 'u64': BaseTypes('u64'), 'f64': BaseTypes('f64'),
+ 'bool': BaseTypes('bool')}
def vpp_get_type(name):
@@ -72,6 +68,10 @@ def vpp_get_type(name):
return None
+class VPPSerializerValueError(ValueError):
+ pass
+
+
class FixedList_u8(object):
def __init__(self, name, field_type, num):
self.name = name
@@ -85,16 +85,18 @@ class FixedList_u8(object):
if not list:
return b'\x00' * self.size
if len(list) > self.num:
- raise ValueError('Fixed list length error for "{}", got: {}'
- ' expected: {}'
- .format(self.name, len(list), self.num))
+ raise VPPSerializerValueError(
+ 'Fixed list length error for "{}", got: {}'
+ ' expected: {}'
+ .format(self.name, len(list), self.num))
return self.packer.pack(list)
def unpack(self, data, offset=0, result=None):
if len(data[offset:]) < self.num:
- raise ValueError('Invalid array length for "{}" got {}'
- ' expected {}'
- .format(self.name, len(data[offset:]), self.num))
+ raise VPPSerializerValueError(
+ 'Invalid array length for "{}" got {}'
+ ' expected {}'
+ .format(self.name, len(data[offset:]), self.num))
return self.packer.unpack(data, offset)
@@ -106,8 +108,9 @@ class FixedList(object):
def pack(self, list, kwargs):
if len(list) != self.num:
- raise ValueError('Fixed list length error, got: {} expected: {}'
- .format(len(list), self.num))
+ raise VPPSerializerValueError(
+ 'Fixed list length error, got: {} expected: {}'
+ .format(len(list), self.num))
b = bytes()
for e in list:
b += self.packer.pack(e)
@@ -137,8 +140,9 @@ class VLAList(object):
if not list:
return b""
if len(list) != kwargs[self.length_field]:
- raise ValueError('Variable length error, got: {} expected: {}'
- .format(len(list), kwargs[self.length_field]))
+ raise VPPSerializerValueError(
+ 'Variable length error, got: {} expected: {}'
+ .format(len(list), kwargs[self.length_field]))
b = bytes()
# u8 array
@@ -187,7 +191,8 @@ class VLAList_legacy():
total = 0
# Return a list of arguments
if (len(data) - offset) % self.packer.size:
- raise ValueError('Legacy Variable Length Array length mismatch.')
+ raise VPPSerializerValueError(
+ 'Legacy Variable Length Array length mismatch.')
elements = int((len(data) - offset) / self.packer.size)
r = []
for e in range(elements):
@@ -241,7 +246,8 @@ class VPPUnionType(object):
f_type, f_name = f
if f_type not in types:
logger.debug('Unknown union type {}'.format(f_type))
- raise ValueError('Unknown message type {}'.format(f_type))
+ raise VPPSerializerValueError(
+ 'Unknown message type {}'.format(f_type))
fields.append(f_name)
size = types[f_type].size
self.packers[f_name] = types[f_type]
@@ -309,7 +315,8 @@ class VPPType(object):
self.fieldtypes.append(f_type)
if f_type not in types:
logger.debug('Unknown type {}'.format(f_type))
- raise ValueError('Unknown message type {}'.format(f_type))
+ raise VPPSerializerValueError(
+ 'Unknown message type {}'.format(f_type))
if len(f) == 3: # list
list_elements = f[2]
if list_elements == 0:
@@ -345,8 +352,9 @@ class VPPType(object):
# Try one of the format functions
if data and type(data) is not dict and a not in data:
- raise ValueError("Invalid argument: {} expected {}.{}".
- format(data, self.name, a))
+ raise VPPSerializerValueError(
+ "Invalid argument: {} expected {}.{}".
+ format(data, self.name, a))
# Defaulting to zero.
if not data or a not in data: # Default to 0
diff --git a/src/vpp-api/python/vpp_papi/vpp_stats.py b/src/vpp-api/python/vpp_papi/vpp_stats.py
index 8344de0c55b..bb6cdf5ffdc 100644
--- a/src/vpp-api/python/vpp_papi/vpp_stats.py
+++ b/src/vpp-api/python/vpp_papi/vpp_stats.py
@@ -138,12 +138,26 @@ def stat_entry_to_python(api, e):
return None
+class VPPStatsIOError(IOError):
+ pass
+
+
+class VPPStatsClientLoadError(RuntimeError):
+ pass
+
+
class VPPStats(object):
- def __init__(self, socketname='/var/run/stats.sock', timeout=10):
+ VPPStatsIOError = VPPStatsIOError
+
+ default_socketname = '/var/run/stats.sock'
+ sharedlib_name = 'libvppapiclient.so'
+
+ def __init__(self, socketname=default_socketname, timeout=10):
try:
- self.api = ffi.dlopen('libvppapiclient.so')
+ self.api = ffi.dlopen(VPPStats.sharedlib_name)
except Exception:
- raise RuntimeError("Could not open: libvppapiclient.so")
+ raise VPPStatsClientLoadError("Could not open: %s" %
+ VPPStats.sharedlib_name)
self.client = self.api.stat_client_get()
poll_end_time = time.time() + timeout
@@ -154,7 +168,7 @@ class VPPStats(object):
break
if rv != 0:
- raise IOError()
+ raise VPPStatsIOError()
def heartbeat(self):
return self.api.stat_segment_heartbeat_r(self.client)
@@ -169,7 +183,7 @@ class VPPStats(object):
rv = self.api.stat_segment_dump_r(counters, self.client)
# Raise exception and retry
if rv == ffi.NULL:
- raise IOError()
+ raise VPPStatsIOError()
rv_len = self.api.stat_segment_vec_len(rv)
for i in range(rv_len):
n = ffi.string(rv[i].name).decode()
@@ -184,7 +198,7 @@ class VPPStats(object):
try:
dir = self.ls(name)
return self.dump(dir).values()[0]
- except Exception as e:
+ except VPPStatsIOError as e:
if retries > 10:
return None
retries += 1
@@ -201,7 +215,7 @@ class VPPStats(object):
error_names = self.ls(['/err/'])
error_counters = self.dump(error_names)
break
- except Exception as e:
+ except VPPStatsIOError as e:
if retries > 10:
return None
retries += 1
diff --git a/src/vpp-api/python/vpp_papi/vpp_transport_shmem.py b/src/vpp-api/python/vpp_papi/vpp_transport_shmem.py
index 5920cd16dcb..53ae775069f 100644
--- a/src/vpp-api/python/vpp_papi/vpp_transport_shmem.py
+++ b/src/vpp-api/python/vpp_papi/vpp_transport_shmem.py
@@ -47,7 +47,13 @@ def vac_error_handler(arg, msg, msg_len):
vpp_object.logger.warning("VPP API client:: %s", ffi.string(msg, msg_len))
+class VppTransportShmemIOError(IOError):
+ pass
+
+
class VppTransport(object):
+ VppTransportShmemIOError = VppTransportShmemIOError
+
def __init__(self, parent, read_timeout, server_address):
self.connected = False
self.read_timeout = read_timeout
@@ -95,23 +101,23 @@ class VppTransport(object):
def _write_new_cffi(self, buf):
"""Send a binary-packed message to VPP."""
if not self.connected:
- raise IOError(1, 'Not connected')
+ raise VppTransportShmemIOError(1, 'Not connected')
return vpp_api.vac_write(ffi.from_buffer(buf), len(buf))
def _write_legacy_cffi(self, buf):
"""Send a binary-packed message to VPP."""
if not self.connected:
- raise IOError(1, 'Not connected')
+ raise VppTransportShmemIOError(1, 'Not connected')
return vpp_api.vac_write(bytes(buf), len(buf))
def read(self):
if not self.connected:
- raise IOError(1, 'Not connected')
+ raise VppTransportShmemIOError(1, 'Not connected')
mem = ffi.new("char **")
size = ffi.new("int *")
rv = vpp_api.vac_read(mem, size, self.read_timeout)
if rv:
- raise IOError(rv, 'vac_read failed')
+ raise VppTransportShmemIOError(rv, 'vac_read failed')
msg = bytes(ffi.buffer(mem[0], size[0]))
vpp_api.vac_free(mem[0])
return msg
diff --git a/src/vpp-api/python/vpp_papi/vpp_transport_socket.py b/src/vpp-api/python/vpp_papi/vpp_transport_socket.py
index 49e565980f2..393e2e9c9c1 100644
--- a/src/vpp-api/python/vpp_papi/vpp_transport_socket.py
+++ b/src/vpp-api/python/vpp_papi/vpp_transport_socket.py
@@ -13,7 +13,13 @@ except ImportError:
import logging
+class VppTransportSocketIOError(IOError):
+ pass
+
+
class VppTransport(object):
+ VppTransportSocketIOError = VppTransportSocketIOError
+
def __init__(self, parent, read_timeout, server_address):
self.connected = False
self.read_timeout = read_timeout if read_timeout > 0 else 1
@@ -59,7 +65,8 @@ class VppTransport(object):
else:
self.parent.msg_handler_async(msg)
else:
- raise IOError(2, 'Unknown response from select')
+ raise VppTransportSocketIOError(
+ 2, 'Unknown response from select')
def connect(self, name, pfx, msg_handler, rx_qlen):
@@ -87,7 +94,7 @@ class VppTransport(object):
msg = self._read()
hdr, length = self.parent.header.unpack(msg, 0)
if hdr.msgid != 16:
- raise IOError('Invalid reply message')
+ raise VppTransportSocketIOError('Invalid reply message')
r, length = sockclnt_create_reply.unpack(msg)
self.socket_index = r.index
@@ -136,7 +143,7 @@ class VppTransport(object):
def write(self, buf):
"""Send a binary-packed message to VPP."""
if not self.connected:
- raise IOError(1, 'Not connected')
+ raise VppTransportSocketIOError(1, 'Not connected')
# Send header
header = self.header.pack(0, len(buf), 0)
@@ -177,7 +184,7 @@ class VppTransport(object):
def read(self):
if not self.connected:
- raise IOError(1, 'Not connected')
+ raise VppTransportSocketIOError(1, 'Not connected')
try:
return self.q.get(True, self.read_timeout)
except queue.Empty: