ipsec: IPSec protection for multi-point tunnel interfaces
[vpp.git] / test / vpp_object.py
1 """ abstract vpp object and object registry """
2
3 import abc
4 import six
5
6 from six import moves
7
8
9 @six.add_metaclass(abc.ABCMeta)
10 class VppObject(object):
11     """ Abstract vpp object """
12
13     @abc.abstractmethod
14     def add_vpp_config(self):
15         """ Add the configuration for this object to vpp. """
16         pass
17
18     @abc.abstractmethod
19     def query_vpp_config(self):
20         """Query the vpp configuration.
21
22         :return: True if the object is configured"""
23         pass
24
25     @abc.abstractmethod
26     def remove_vpp_config(self):
27         """ Remove the configuration for this object from vpp. """
28         pass
29
30     def object_id(self):
31         """ Return a unique string representing this object. """
32         return "Undefined. for <%s %s>" % (self.__class__.__name__, id(self))
33
34     def __str__(self):
35         return self.object_id()
36
37     def __repr__(self):
38         return '<%s>' % self.object_id()
39
40     def __hash__(self):
41         return hash(self.object_id())
42
43     def __eq__(self, other):
44         if not isinstance(other, self.__class__):
45             return NotImplemented
46         if other.object_id() == self.object_id():
47             return True
48         return False
49
50     # This can be removed when python2 support is dropped.
51     def __ne__(self, other):
52         return not self.__eq__(other)
53
54
55 class VppObjectRegistry(object):
56     """ Class which handles automatic configuration cleanup. """
57     _shared_state = {}
58
59     def __init__(self):
60         self.__dict__ = self._shared_state
61         if not hasattr(self, "_object_registry"):
62             self._object_registry = []
63         if not hasattr(self, "_object_dict"):
64             self._object_dict = dict()
65
66     def register(self, obj, logger):
67         """ Register an object in the registry. """
68         if obj.object_id() not in self._object_dict:
69             self._object_registry.append(obj)
70             self._object_dict[obj.object_id()] = obj
71             logger.debug("REG: registering %s" % obj)
72         else:
73             logger.debug("REG: duplicate add, ignoring (%s)" % obj)
74
75     def unregister_all(self, logger):
76         """ Remove all object registrations from registry. """
77         logger.debug("REG: removing all object registrations")
78         self._object_registry = []
79         self._object_dict = dict()
80
81     def remove_vpp_config(self, logger):
82         """
83         Remove configuration (if present) from vpp and then remove all objects
84         from the registry.
85         """
86         if not self._object_registry:
87             logger.info("REG: No objects registered for auto-cleanup.")
88             return
89         logger.info("REG: Removing VPP configuration for registered objects")
90         # remove the config in reverse order as there might be dependencies
91         failed = []
92         for obj in reversed(self._object_registry):
93             if obj.query_vpp_config():
94                 logger.info("REG: Removing configuration for %s" % obj)
95                 obj.remove_vpp_config()
96                 if obj.query_vpp_config():
97                     failed.append(obj)
98             else:
99                 logger.info(
100                     "REG: Skipping removal for %s, configuration not present" %
101                     obj)
102         self.unregister_all(logger)
103         if failed:
104             logger.error("REG: Couldn't remove configuration for object(s):")
105             for obj in failed:
106                 logger.error(repr(obj))
107             raise Exception("Couldn't remove configuration for object(s): %s" %
108                             (", ".join(str(x) for x in failed)))