Reformatting RO
[osm/RO.git] / RO-SDN-arista_cloudvision / osm_rosdn_arista_cloudvision / wimconn_arista.py
index e72a082..314c673 100644 (file)
 #
 # This work has been performed in the context of Arista Telefonica OSM PoC.
 ##
+
 from osm_ro_plugin.sdnconn import SdnConnectorBase, SdnConnectorError
 import re
 import socket
+
 # Required by compare function
 import difflib
+
 # Library that uses Levenshtein Distance to calculate the differences
 # between strings.
 # from fuzzywuzzy import fuzz
@@ -49,24 +52,22 @@ from osm_rosdn_arista_cloudvision.aristaTask import AristaCVPTask
 
 
 class SdnError(Enum):
-    UNREACHABLE = 'Unable to reach the WIM url, connect error.',
-    TIMEOUT = 'Unable to reach the WIM url, timeout.',
-    VLAN_INCONSISTENT = \
-        'VLAN value inconsistent between the connection points',
-    VLAN_NOT_PROVIDED = 'VLAN value not provided',
-    CONNECTION_POINTS_SIZE = \
-        'Unexpected number of connection points: 2 expected.',
-    ENCAPSULATION_TYPE = \
-        'Unexpected service_endpoint_encapsulation_type. ' \
-        'Only "dotq1" is accepted.',
-    BANDWIDTH = 'Unable to get the bandwidth.',
-    STATUS = 'Unable to get the status for the service.',
-    DELETE = 'Unable to delete service.',
-    CLEAR_ALL = 'Unable to clear all the services',
-    UNKNOWN_ACTION = 'Unknown action invoked.',
-    BACKUP = 'Unable to get the backup parameter.',
-    UNSUPPORTED_FEATURE = "Unsupported feature",
-    UNAUTHORIZED = "Failed while authenticating",
+    UNREACHABLE = "Unable to reach the WIM url, connect error."
+    TIMEOUT = "Unable to reach the WIM url, timeout."
+    VLAN_INCONSISTENT = "VLAN value inconsistent between the connection points"
+    VLAN_NOT_PROVIDED = "VLAN value not provided"
+    CONNECTION_POINTS_SIZE = "Unexpected number of connection points: 2 expected."
+    ENCAPSULATION_TYPE = (
+        'Unexpected service_endpoint_encapsulation_type. Only "dotq1" is accepted.'
+    )
+    BANDWIDTH = "Unable to get the bandwidth."
+    STATUS = "Unable to get the status for the service."
+    DELETE = "Unable to delete service."
+    CLEAR_ALL = "Unable to clear all the services"
+    UNKNOWN_ACTION = "Unknown action invoked."
+    BACKUP = "Unable to get the backup parameter."
+    UNSUPPORTED_FEATURE = "Unsupported feature"
+    UNAUTHORIZED = "Failed while authenticating"
     INTERNAL_ERROR = "Internal error"
 
 
@@ -97,14 +98,15 @@ class AristaSdnConnector(SdnConnectorBase):
     -- All created services identification is stored in a generic ConfigLet 'OSM_metadata'
        to keep track of the managed resources by OSM in the Arista deployment.
     """
+
     __supported_service_types = ["ELINE (L2)", "ELINE", "ELAN"]
     __service_types_ELAN = "ELAN"
     __service_types_ELINE = "ELINE"
     __ELINE_num_connection_points = 2
     __supported_service_types = ["ELINE", "ELAN"]
     __supported_encapsulation_types = ["dot1q"]
-    __WIM_LOGGER = 'ro.sdn.arista'
-    __SERVICE_ENDPOINT_MAPPING = 'service_endpoint_mapping'
+    __WIM_LOGGER = "ro.sdn.arista"
+    __SERVICE_ENDPOINT_MAPPING = "service_endpoint_mapping"
     __ENCAPSULATION_TYPE_PARAM = "service_endpoint_encapsulation_type"
     __ENCAPSULATION_INFO_PARAM = "service_endpoint_encapsulation_info"
     __BACKUP_PARAM = "backup"
@@ -119,16 +121,16 @@ class AristaSdnConnector(SdnConnectorBase):
     __SW_PORT_PARAM = "switch_port"
     __VLAN_PARAM = "vlan"
     __VNI_PARAM = "vni"
-    __SEPARATOR = '_'
-    __MANAGED_BY_OSM = '## Managed by OSM '
+    __SEPARATOR = "_"
+    __MANAGED_BY_OSM = "## Managed by OSM "
     __OSM_PREFIX = "osm_"
     __OSM_METADATA = "OSM_metadata"
-    __METADATA_PREFIX = '!## Service'
+    __METADATA_PREFIX = "!## Service"
     __EXC_TASK_EXEC_WAIT = 10
     __ROLLB_TASK_EXEC_WAIT = 10
     __API_REQUEST_TOUT = 60
-    __SWITCH_TAG_NAME = 'topology_type'
-    __SWITCH_TAG_VALUE = 'leaf'
+    __SWITCH_TAG_NAME = "topology_type"
+    __SWITCH_TAG_VALUE = "leaf"
     __LOOPBACK_INTF = "Loopback0"
     _VLAN = "VLAN"
     _VXLAN = "VXLAN"
@@ -159,55 +161,74 @@ class AristaSdnConnector(SdnConnectorBase):
         :param logger (logging.Logger): optional logger object. If none is passed 'ro.sdn.sdnconn' is used.
         """
         self.__regex = re.compile(
-            r'^(?:http|ftp)s?://'  # http:// or https://
-            r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'  # domain...
-            r'localhost|'  # localhost...
-            r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'  # ...or ip
-            r'(?::\d+)?', re.IGNORECASE)  # optional port
+            r"^(?:http|ftp)s?://"  # http:// or https://
+            r"(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|"  # domain...
+            r"localhost|"  # localhost...
+            r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"  # ...or ip
+            r"(?::\d+)?",
+            re.IGNORECASE,
+        )  # optional port
         self.raiseException = True
         self.logger = logger or logging.getLogger(self.__WIM_LOGGER)
         super().__init__(wim, wim_account, config, self.logger)
         self.__wim = wim
         self.__wim_account = wim_account
         self.__config = config
+
         if self.is_valid_destination(self.__wim.get("wim_url")):
             self.__wim_url = self.__wim.get("wim_url")
         else:
-            raise SdnConnectorError(message='Invalid wim_url value',
-                                    http_code=500)
+            raise SdnConnectorError(message="Invalid wim_url value", http_code=500)
+
         self.__user = wim_account.get("user")
         self.__passwd = wim_account.get("password")
         self.client = None
         self.cvp_inventory = None
         self.cvp_tags = None
-        self.logger.debug("Arista SDN plugin {}, cvprac version {}, user:{} and config:{}".
-                          format(wim, cvprac_version, self.__user,
-                                 self.delete_keys_from_dict(config, ('passwd',))))
+        self.logger.debug(
+            "Arista SDN plugin {}, cvprac version {}, user:{} and config:{}".format(
+                wim,
+                cvprac_version,
+                self.__user,
+                self.delete_keys_from_dict(config, ("passwd",)),
+            )
+        )
         self.allDeviceFacts = []
         self.taskC = None
+
         try:
             self.__load_topology()
             self.__load_switches()
         except (ConnectTimeout, Timeout) as ct:
-            raise SdnConnectorError(message=SdnError.TIMEOUT + " " + str(ct), http_code=408)
+            raise SdnConnectorError(
+                message=SdnError.TIMEOUT + " " + str(ct), http_code=408
+            )
         except ConnectionError as ce:
-            raise SdnConnectorError(message=SdnError.UNREACHABLE + " " + str(ce), http_code=404)
+            raise SdnConnectorError(
+                message=SdnError.UNREACHABLE + " " + str(ce), http_code=404
+            )
         except SdnConnectorError as sc:
             raise sc
         except CvpLoginError as le:
             raise SdnConnectorError(message=le.msg, http_code=500) from le
         except Exception as e:
-            raise SdnConnectorError(message="Unable to load switches from CVP" + " " + str(e),
-                                    http_code=500) from e
-        self.logger.debug("Using topology {} in Arista Leaf switches: {}".format(
-            self.topology,
-            self.delete_keys_from_dict(self.switches, ('passwd',))))
+            raise SdnConnectorError(
+                message="Unable to load switches from CVP " + str(e), http_code=500
+            ) from e
+
+        self.logger.debug(
+            "Using topology {} in Arista Leaf switches: {}".format(
+                self.topology, self.delete_keys_from_dict(self.switches, ("passwd",))
+            )
+        )
         self.clC = AristaSDNConfigLet(self.topology)
 
     def __load_topology(self):
         self.topology = self._VXLAN_MLAG
-        if self.__config and self.__config.get('topology'):
-            topology = self.__config.get('topology')
+
+        if self.__config and self.__config.get("topology"):
+            topology = self.__config.get("topology")
+
             if topology == "VLAN":
                 self.topology = self._VLAN
             elif topology == "VXLAN":
@@ -218,7 +239,7 @@ class AristaSdnConnector(SdnConnectorBase):
                 self.topology = self._VXLAN_MLAG
 
     def __load_switches(self):
-        """ Retrieves the switches to configure in the following order
+        """Retrieves the switches to configure in the following order
         1.  from incoming configuration:
         1.1 using port mapping
               using user and password from WIM
@@ -236,47 +257,58 @@ class AristaSdnConnector(SdnConnectorBase):
             for port in self.__config.get(self.__SERVICE_ENDPOINT_MAPPING):
                 switch_dpid = port.get(self.__SW_ID_PARAM)
                 if switch_dpid and switch_dpid not in self.switches:
-                    self.switches[switch_dpid] = {'passwd': self.__passwd,
-                                                  'ip': None,
-                                                  'usr': self.__user,
-                                                  'lo0': None,
-                                                  'AS': None,
-                                                  'serialNumber': None,
-                                                  'mlagPeerDevice': None}
-
-        if self.__config and self.__config.get('switches'):
+                    self.switches[switch_dpid] = {
+                        "passwd": self.__passwd,
+                        "ip": None,
+                        "usr": self.__user,
+                        "lo0": None,
+                        "AS": None,
+                        "serialNumber": None,
+                        "mlagPeerDevice": None,
+                    }
+
+        if self.__config and self.__config.get("switches"):
             # Not directly from json, complete one by one
-            config_switches = self.__config.get('switches')
+            config_switches = self.__config.get("switches")
             for cs, cs_content in config_switches.items():
                 if cs not in self.switches:
-                    self.switches[cs] = {'passwd': self.__passwd,
-                                         'ip': None,
-                                         'usr': self.__user,
-                                         'lo0': None,
-                                         'AS': None,
-                                         'serialNumber': None,
-                                         'mlagPeerDevice': None}
+                    self.switches[cs] = {
+                        "passwd": self.__passwd,
+                        "ip": None,
+                        "usr": self.__user,
+                        "lo0": None,
+                        "AS": None,
+                        "serialNumber": None,
+                        "mlagPeerDevice": None,
+                    }
+
                 if cs_content:
                     self.switches[cs].update(cs_content)
 
         # Load the rest of the data
         if self.client is None:
             self.client = self.__connect()
+
         self.__load_inventory()
+
         if not self.switches:
             self.__get_tags(self.__SWITCH_TAG_NAME, self.__SWITCH_TAG_VALUE)
+
             for device in self.allDeviceFacts:
                 # get the switches whose topology_tag is 'leaf'
-                if device['serialNumber'] in self.cvp_tags:
-                    if not self.switches.get(device['hostname']):
-                        switch_data = {'passwd': self.__passwd,
-                                       'ip': device['ipAddress'],
-                                       'usr': self.__user,
-                                       'lo0': None,
-                                       'AS': None,
-                                       'serialNumber': None,
-                                       'mlagPeerDevice': None}
-                        self.switches[device['hostname']] = switch_data
+                if device["serialNumber"] in self.cvp_tags:
+                    if not self.switches.get(device["hostname"]):
+                        switch_data = {
+                            "passwd": self.__passwd,
+                            "ip": device["ipAddress"],
+                            "usr": self.__user,
+                            "lo0": None,
+                            "AS": None,
+                            "serialNumber": None,
+                            "mlagPeerDevice": None,
+                        }
+                        self.switches[device["hostname"]] = switch_data
+
         if len(self.switches) == 0:
             self.logger.error("Unable to load Leaf switches from CVP")
             return
@@ -285,68 +317,93 @@ class AristaSdnConnector(SdnConnectorBase):
         # used to make eAPI calls by using switch.py module
         for s in self.switches:
             for device in self.allDeviceFacts:
-                if device['hostname'] == s:
-                    if not self.switches[s].get('ip'):
-                        self.switches[s]['ip'] = device['ipAddress']
-                    self.switches[s]['serialNumber'] = device['serialNumber']
+                if device["hostname"] == s:
+                    if not self.switches[s].get("ip"):
+                        self.switches[s]["ip"] = device["ipAddress"]
+                    self.switches[s]["serialNumber"] = device["serialNumber"]
                     break
 
             # Each switch has a different loopback address,
             # so it's a different configLet
-            if not self.switches[s].get('lo0'):
-                inf = self.__get_interface_ip(self.switches[s]['serialNumber'], self.__LOOPBACK_INTF)
-                self.switches[s]["lo0"] = inf.split('/')[0]
-            if not self.switches[s].get('AS'):
-                self.switches[s]["AS"] = self.__get_device_ASN(self.switches[s]['serialNumber'])
+            if not self.switches[s].get("lo0"):
+                inf = self.__get_interface_ip(
+                    self.switches[s]["serialNumber"], self.__LOOPBACK_INTF
+                )
+                self.switches[s]["lo0"] = inf.split("/")[0]
+
+            if not self.switches[s].get("AS"):
+                self.switches[s]["AS"] = self.__get_device_ASN(
+                    self.switches[s]["serialNumber"]
+                )
+
         if self.topology in (self._VXLAN_MLAG, self._VLAN_MLAG):
             for s in self.switches:
-                if not self.switches[s].get('mlagPeerDevice'):
-                    self.switches[s]['mlagPeerDevice'] = self.__get_peer_MLAG(self.switches[s]['serialNumber'])
-
-    def __check_service(self, service_type, connection_points,
-                        check_vlan=True, check_num_cp=True, kwargs=None):
-        """ Reviews the connection points elements looking for semantic errors in the incoming data
-        """
+                if not self.switches[s].get("mlagPeerDevice"):
+                    self.switches[s]["mlagPeerDevice"] = self.__get_peer_MLAG(
+                        self.switches[s]["serialNumber"]
+                    )
+
+    def __check_service(
+        self,
+        service_type,
+        connection_points,
+        check_vlan=True,
+        check_num_cp=True,
+        kwargs=None,
+    ):
+        """Reviews the connection points elements looking for semantic errors in the incoming data"""
         if service_type not in self.__supported_service_types:
-            raise Exception("The service '{}' is not supported. Only '{}' are accepted".format(
-                            service_type,
-                            self.__supported_service_types))
+            raise Exception(
+                "The service '{}' is not supported. Only '{}' are accepted".format(
+                    service_type, self.__supported_service_types
+                )
+            )
 
         if check_num_cp:
             if len(connection_points) < 2:
                 raise Exception(SdnError.CONNECTION_POINTS_SIZE)
-            if (len(connection_points) != self.__ELINE_num_connection_points and
-               service_type == self.__service_types_ELINE):
+
+            if (
+                len(connection_points) != self.__ELINE_num_connection_points
+                and service_type == self.__service_types_ELINE
+            ):
                 raise Exception(SdnError.CONNECTION_POINTS_SIZE)
 
         if check_vlan:
-            vlan_id = ''
+            vlan_id = ""
+
             for cp in connection_points:
                 enc_type = cp.get(self.__ENCAPSULATION_TYPE_PARAM)
-                if (enc_type and
-                        enc_type not in self.__supported_encapsulation_types):
+
+                if enc_type and enc_type not in self.__supported_encapsulation_types:
                     raise Exception(SdnError.ENCAPSULATION_TYPE)
+
                 encap_info = cp.get(self.__ENCAPSULATION_INFO_PARAM)
                 cp_vlan_id = str(encap_info.get(self.__VLAN_PARAM))
+
                 if cp_vlan_id:
                     if not vlan_id:
                         vlan_id = cp_vlan_id
                     elif vlan_id != cp_vlan_id:
                         raise Exception(SdnError.VLAN_INCONSISTENT)
+
             if not vlan_id:
                 raise Exception(SdnError.VLAN_NOT_PROVIDED)
+
             if vlan_id in self.__get_srvVLANs():
-                raise Exception('VLAN {} already assigned to a connectivity service'.format(vlan_id))
+                raise Exception(
+                    "VLAN {} already assigned to a connectivity service".format(vlan_id)
+                )
 
         # Commented out for as long as parameter isn't implemented
         # bandwidth = kwargs.get(self.__BANDWIDTH_PARAM)
         # if not isinstance(bandwidth, int):
-            # self.__exception(SdnError.BANDWIDTH, http_code=400)
+        #    self.__exception(SdnError.BANDWIDTH, http_code=400)
 
         # Commented out for as long as parameter isn't implemented
         # backup = kwargs.get(self.__BACKUP_PARAM)
         # if not isinstance(backup, bool):
-            # self.__exception(SdnError.BACKUP, http_code=400)
+        #    self.__exception(SdnError.BACKUP, http_code=400)
 
     def check_credentials(self):
         """Retrieves the CloudVision version information, as the easiest way
@@ -355,18 +412,23 @@ class AristaSdnConnector(SdnConnectorBase):
         try:
             if self.client is None:
                 self.client = self.__connect()
+
             result = self.client.api.get_cvp_info()
             self.logger.debug(result)
         except CvpLoginError as e:
             self.logger.info(str(e))
             self.client = None
-            raise SdnConnectorError(message=SdnError.UNAUTHORIZED + " " + str(e),
-                                    http_code=401) from e
+
+            raise SdnConnectorError(
+                message=SdnError.UNAUTHORIZED + " " + str(e), http_code=401
+            ) from e
         except Exception as ex:
             self.client = None
             self.logger.error(str(ex))
-            raise SdnConnectorError(message=SdnError.INTERNAL_ERROR + " " + str(ex),
-                                    http_code=500) from ex
+
+            raise SdnConnectorError(
+                message=SdnError.INTERNAL_ERROR + " " + str(ex), http_code=500
+            ) from ex
 
     def get_connectivity_service_status(self, service_uuid, conn_info=None):
         """Monitor the status of the connectivity service established
@@ -405,81 +467,112 @@ class AristaSdnConnector(SdnConnectorBase):
                 new information available for the connectivity service.
         """
         try:
-            self.logger.debug("invoked get_connectivity_service_status '{}'".format(service_uuid))
+            self.logger.debug(
+                "invoked get_connectivity_service_status '{}'".format(service_uuid)
+            )
+
             if not service_uuid:
-                raise SdnConnectorError(message='No connection service UUID',
-                                        http_code=500)
+                raise SdnConnectorError(
+                    message="No connection service UUID", http_code=500
+                )
 
             self.__get_Connection()
-            if conn_info is None:
-                raise SdnConnectorError(message='No connection information for service UUID {}'.format(service_uuid),
-                                        http_code=500)
 
-            if 'configLetPerSwitch' in conn_info.keys():
+            if conn_info is None:
+                raise SdnConnectorError(
+                    message="No connection information for service UUID {}".format(
+                        service_uuid
+                    ),
+                    http_code=500,
+                )
+
+            if "configLetPerSwitch" in conn_info.keys():
                 c_info = conn_info
             else:
                 c_info = None
-            cls_perSw = self.__get_serviceData(service_uuid,
-                                               conn_info['service_type'],
-                                               conn_info['vlan_id'],
-                                               c_info)
+
+            cls_perSw = self.__get_serviceData(
+                service_uuid, conn_info["service_type"], conn_info["vlan_id"], c_info
+            )
 
             t_isCancelled = False
             t_isFailed = False
             t_isPending = False
             failed_switches = []
+
             for s in self.switches:
                 if len(cls_perSw[s]) > 0:
                     for cl in cls_perSw[s]:
                         # Fix 1030 SDN-ARISTA Key error note when deploy a NS
                         # Added protection to check that 'note' exists and additionally
                         # verify that it is managed by OSM
-                        if (not cls_perSw[s][0]['config'] or
-                                not cl.get('note') or
-                                self.__MANAGED_BY_OSM not in cl['note']):
+                        if (
+                            not cls_perSw[s][0]["config"]
+                            or not cl.get("note")
+                            or self.__MANAGED_BY_OSM not in cl["note"]
+                        ):
                             continue
-                        note = cl['note']
+
+                        note = cl["note"]
                         t_id = note.split(self.__SEPARATOR)[1]
                         result = self.client.api.get_task_by_id(t_id)
-                        if result['workOrderUserDefinedStatus'] == 'Completed':
+
+                        if result["workOrderUserDefinedStatus"] == "Completed":
                             continue
-                        elif result['workOrderUserDefinedStatus'] == 'Cancelled':
+                        elif result["workOrderUserDefinedStatus"] == "Cancelled":
                             t_isCancelled = True
-                        elif result['workOrderUserDefinedStatus'] == 'Failed':
+                        elif result["workOrderUserDefinedStatus"] == "Failed":
                             t_isFailed = True
                         else:
                             t_isPending = True
+
                         failed_switches.append(s)
+
             if t_isCancelled:
-                error_msg = 'Some works were cancelled in switches: {}'.format(str(failed_switches))
-                sdn_status = 'DOWN'
+                error_msg = "Some works were cancelled in switches: {}".format(
+                    str(failed_switches)
+                )
+                sdn_status = "DOWN"
             elif t_isFailed:
-                error_msg = 'Some works failed in switches: {}'.format(str(failed_switches))
-                sdn_status = 'ERROR'
+                error_msg = "Some works failed in switches: {}".format(
+                    str(failed_switches)
+                )
+                sdn_status = "ERROR"
             elif t_isPending:
-                error_msg = 'Some works are still under execution in switches: {}'.format(str(failed_switches))
-                sdn_status = 'BUILD'
+                error_msg = (
+                    "Some works are still under execution in switches: {}".format(
+                        str(failed_switches)
+                    )
+                )
+                sdn_status = "BUILD"
             else:
-                error_msg = ''
-                sdn_status = 'ACTIVE'
-            sdn_info = ''
-            return {'sdn_status': sdn_status,
-                    'error_msg': error_msg,
-                    'sdn_info': sdn_info}
+                error_msg = ""
+                sdn_status = "ACTIVE"
+
+            sdn_info = ""
+
+            return {
+                "sdn_status": sdn_status,
+                "error_msg": error_msg,
+                "sdn_info": sdn_info,
+            }
         except CvpLoginError as e:
             self.logger.info(str(e))
             self.client = None
-            raise SdnConnectorError(message=SdnError.UNAUTHORIZED + " " + str(e),
-                                    http_code=401) from e
+
+            raise SdnConnectorError(
+                message=SdnError.UNAUTHORIZED + " " + str(e), http_code=401
+            ) from e
         except Exception as ex:
             self.client = None
             self.logger.error(str(ex), exc_info=True)
-            raise SdnConnectorError(message=str(ex) + " " + str(ex),
-                                    http_code=500) from ex
 
-    def create_connectivity_service(self, service_type, connection_points,
-                                    **kwargs):
-        """Stablish SDN/WAN connectivity between the endpoints
+            raise SdnConnectorError(
+                message=str(ex) + " " + str(ex), http_code=500
+            ) from ex
+
+    def create_connectivity_service(self, service_type, connection_points, **kwargs):
+        """Establish SDN/WAN connectivity between the endpoints
         :param service_type:
             (str): ``ELINE`` (L2), ``ELAN`` (L2), ``ETREE`` (L2), ``L3``.
         :param connection_points:  (list): each point corresponds to
@@ -528,24 +621,24 @@ class AristaSdnConnector(SdnConnectorBase):
             Provide the parameter http_code
         """
         try:
-            self.logger.debug("invoked create_connectivity_service '{}' ports: {}".
-                              format(service_type, connection_points))
+            self.logger.debug(
+                "invoked create_connectivity_service '{}' ports: {}".format(
+                    service_type, connection_points
+                )
+            )
             self.__get_Connection()
-            self.__check_service(service_type,
-                                 connection_points,
-                                 check_vlan=True,
-                                 kwargs=kwargs)
+            self.__check_service(
+                service_type, connection_points, check_vlan=True, kwargs=kwargs
+            )
             service_uuid = str(uuid.uuid4())
 
-            self.logger.info("Service with uuid {} created.".
-                             format(service_uuid))
+            self.logger.info("Service with uuid {} created.".format(service_uuid))
             s_uid, s_connInf = self.__processConnection(
-                service_uuid,
-                service_type,
-                connection_points,
-                kwargs)
+                service_uuid, service_type, connection_points, kwargs
+            )
+
             try:
-                self.__addMetadata(s_uid, service_type, s_connInf['vlan_id'])
+                self.__addMetadata(s_uid, service_type, s_connInf["vlan_id"])
             except Exception:
                 pass
 
@@ -553,28 +646,29 @@ class AristaSdnConnector(SdnConnectorBase):
         except CvpLoginError as e:
             self.logger.info(str(e))
             self.client = None
-            raise SdnConnectorError(message=SdnError.UNAUTHORIZED + " " + str(e),
-                                    http_code=401) from e
+
+            raise SdnConnectorError(
+                message=SdnError.UNAUTHORIZED + " " + str(e), http_code=401
+            ) from e
         except SdnConnectorError as sde:
             raise sde
         except ValueError as err:
             self.client = None
             self.logger.error(str(err), exc_info=True)
-            raise SdnConnectorError(message=str(err),
-                                    http_code=500) from err
+
+            raise SdnConnectorError(message=str(err), http_code=500) from err
         except Exception as ex:
             self.client = None
             self.logger.error(str(ex), exc_info=True)
+
             if self.raiseException:
                 raise ex
-            raise SdnConnectorError(message=str(ex),
-                                    http_code=500) from ex
 
-    def __processConnection(self,
-                            service_uuid,
-                            service_type,
-                            connection_points,
-                            kwargs):
+            raise SdnConnectorError(message=str(ex), http_code=500) from ex
+
+    def __processConnection(
+        self, service_uuid, service_type, connection_points, kwargs
+    ):
         """
         Invoked from creation and edit methods
 
@@ -590,107 +684,133 @@ class AristaSdnConnector(SdnConnectorBase):
             cls_perSw = {}
             cls_cp = {}
             cl_bgp = {}
+
             for s in self.switches:
                 cls_perSw[s] = []
                 cls_cp[s] = []
+
             vlan_processed = False
-            vlan_id = ''
+            vlan_id = ""
             i = 0
             processed_connection_points = []
+
             for cp in connection_points:
                 i += 1
                 encap_info = cp.get(self.__ENCAPSULATION_INFO_PARAM)
+
                 if not vlan_processed:
                     vlan_id = str(encap_info.get(self.__VLAN_PARAM))
+
                     if not vlan_id:
                         continue
+
                     vni_id = encap_info.get(self.__VNI_PARAM)
+
                     if not vni_id:
                         vni_id = str(10000 + int(vlan_id))
 
                     if service_type == self.__service_types_ELAN:
-                        cl_vlan = self.clC.getElan_vlan(service_uuid,
-                                                        vlan_id,
-                                                        vni_id)
+                        cl_vlan = self.clC.getElan_vlan(service_uuid, vlan_id, vni_id)
                     else:
-                        cl_vlan = self.clC.getEline_vlan(service_uuid,
-                                                         vlan_id,
-                                                         vni_id)
+                        cl_vlan = self.clC.getEline_vlan(service_uuid, vlan_id, vni_id)
+
                     vlan_processed = True
 
                 encap_type = cp.get(self.__ENCAPSULATION_TYPE_PARAM)
                 switch_id = encap_info.get(self.__SW_ID_PARAM)
                 interface = encap_info.get(self.__SW_PORT_PARAM)
-                switches = [{'name': switch_id, 'interface': interface}]
+                switches = [{"name": switch_id, "interface": interface}]
 
                 # remove those connections that are equal. This happens when several sriovs are located in the same
                 # compute node interface, that is, in the same switch and interface
                 switches = [x for x in switches if x not in processed_connection_points]
+
                 if not switches:
                     continue
+
                 processed_connection_points += switches
+
                 for switch in switches:
                     if not interface:
                         raise SdnConnectorError(
-                            message="Connection point switch port empty for switch_dpid {}".format(switch_id),
-                            http_code=406)
+                            message="Connection point switch port empty for switch_dpid {}".format(
+                                switch_id
+                            ),
+                            http_code=406,
+                        )
                     # it should be only one switch where the mac is attached
-                    if encap_type == 'dot1q':
+                    if encap_type == "dot1q":
                         # SRIOV configLet for Leaf switch mac's attached to
                         if service_type == self.__service_types_ELAN:
-                            cl_encap = self.clC.getElan_sriov(service_uuid, interface, vlan_id, i)
+                            cl_encap = self.clC.getElan_sriov(
+                                service_uuid, interface, vlan_id, i
+                            )
                         else:
-                            cl_encap = self.clC.getEline_sriov(service_uuid, interface, vlan_id, i)
+                            cl_encap = self.clC.getEline_sriov(
+                                service_uuid, interface, vlan_id, i
+                            )
                     elif not encap_type:
                         # PT configLet for Leaf switch attached to the mac
                         if service_type == self.__service_types_ELAN:
-                            cl_encap = self.clC.getElan_passthrough(service_uuid,
-                                                                    interface,
-                                                                    vlan_id, i)
+                            cl_encap = self.clC.getElan_passthrough(
+                                service_uuid, interface, vlan_id, i
+                            )
                         else:
-                            cl_encap = self.clC.getEline_passthrough(service_uuid,
-                                                                     interface,
-                                                                     vlan_id, i)
-                    if cls_cp.get(switch['name']):
-                        cls_cp[switch['name']] = str(cls_cp[switch['name']]) + cl_encap
+                            cl_encap = self.clC.getEline_passthrough(
+                                service_uuid, interface, vlan_id, i
+                            )
+
+                    if cls_cp.get(switch["name"]):
+                        cls_cp[switch["name"]] = str(cls_cp[switch["name"]]) + cl_encap
                     else:
-                        cls_cp[switch['name']] = cl_encap
+                        cls_cp[switch["name"]] = cl_encap
 
             # at least 1 connection point has to be received
             if not vlan_processed:
-                raise SdnConnectorError(message=SdnError.UNSUPPORTED_FEATURE,
-                                        http_code=406)
+                raise SdnConnectorError(
+                    message=SdnError.UNSUPPORTED_FEATURE, http_code=406
+                )
 
             for s in self.switches:
                 # for cl in cp_configLets:
-                cl_name = (self.__OSM_PREFIX +
-                           s +
-                           self.__SEPARATOR + service_type + str(vlan_id) +
-                           self.__SEPARATOR + service_uuid)
-                cl_config = ''
+                cl_name = (
+                    self.__OSM_PREFIX
+                    + s
+                    + self.__SEPARATOR
+                    + service_type
+                    + str(vlan_id)
+                    + self.__SEPARATOR
+                    + service_uuid
+                )
+                cl_config = ""
+
                 # Apply BGP configuration only for VXLAN topologies
                 if self.topology in (self._VXLAN_MLAG, self._VXLAN):
                     if service_type == self.__service_types_ELAN:
-                        cl_bgp[s] = self.clC.getElan_bgp(service_uuid,
-                                                         vlan_id,
-                                                         vni_id,
-                                                         self.switches[s]['lo0'],
-                                                         self.switches[s]['AS'])
+                        cl_bgp[s] = self.clC.getElan_bgp(
+                            service_uuid,
+                            vlan_id,
+                            vni_id,
+                            self.switches[s]["lo0"],
+                            self.switches[s]["AS"],
+                        )
                     else:
-                        cl_bgp[s] = self.clC.getEline_bgp(service_uuid,
-                                                          vlan_id,
-                                                          vni_id,
-                                                          self.switches[s]['lo0'],
-                                                          self.switches[s]['AS'])
+                        cl_bgp[s] = self.clC.getEline_bgp(
+                            service_uuid,
+                            vlan_id,
+                            vni_id,
+                            self.switches[s]["lo0"],
+                            self.switches[s]["AS"],
+                        )
                 else:
-                    cl_bgp[s] = ''
+                    cl_bgp[s] = ""
 
                 if not cls_cp.get(s):
                     # Apply VLAN configuration to peer MLAG switch,
                     # only necessary when there are no connection points in the switch
                     if self.topology in (self._VXLAN_MLAG, self._VLAN_MLAG):
                         for p in self.switches:
-                            if self.switches[p]['mlagPeerDevice'] == s:
+                            if self.switches[p]["mlagPeerDevice"] == s:
                                 if cls_cp.get(p):
                                     if self.topology == self._VXLAN_MLAG:
                                         cl_config = str(cl_vlan) + str(cl_bgp[s])
@@ -699,7 +819,7 @@ class AristaSdnConnector(SdnConnectorBase):
                 else:
                     cl_config = str(cl_vlan) + str(cl_bgp[s]) + str(cls_cp[s])
 
-                cls_perSw[s] = [{'name': cl_name, 'config': cl_config}]
+                cls_perSw[s] = [{"name": cl_name, "config": cl_config}]
 
             allLeafConfigured, allLeafModified = self.__updateConnection(cls_perSw)
 
@@ -710,17 +830,19 @@ class AristaSdnConnector(SdnConnectorBase):
                 "vlan_id": vlan_id,
                 "connection_points": connection_points,
                 "configLetPerSwitch": cls_perSw,
-                'allLeafConfigured': allLeafConfigured,
-                'allLeafModified': allLeafModified}
+                "allLeafConfigured": allLeafConfigured,
+                "allLeafModified": allLeafModified,
+            }
 
             return service_uuid, conn_info
         except Exception as ex:
-            self.logger.debug("Exception processing connection {}: {}".
-                              format(service_uuid, str(ex)))
+            self.logger.debug(
+                "Exception processing connection {}: {}".format(service_uuid, str(ex))
+            )
             raise ex
 
     def __updateConnection(self, cls_perSw):
-        """ Invoked in the creation and modification
+        """Invoked in the creation and modification
 
         checks if the new connection points config is:
             - already in the Cloud Vision, the configLet is modified, and applied to the switch,
@@ -740,18 +862,21 @@ class AristaSdnConnector(SdnConnectorBase):
             for s in self.switches:
                 allLeafConfigured[s] = False
                 allLeafModified[s] = False
+
             cl_toDelete = []
+
             for s in self.switches:
                 toDelete_in_cvp = False
-                if not (cls_perSw.get(s) and cls_perSw[s][0].get('config')):
+                if not (cls_perSw.get(s) and cls_perSw[s][0].get("config")):
                     # when there is no configuration, means that there is no interface
                     # in the switch to be connected, so the configLet has to be removed from CloudVision
                     # after removing the ConfigLet from the switch if it was already there
 
                     # get config let name and key
                     cl = cls_perSw[s]
+
                     try:
-                        cvp_cl = self.client.api.get_configlet_by_name(cl[0]['name'])
+                        cvp_cl = self.client.api.get_configlet_by_name(cl[0]["name"])
                         # remove configLet
                         cl_toDelete.append(cvp_cl)
                         cl[0] = cvp_cl
@@ -765,69 +890,84 @@ class AristaSdnConnector(SdnConnectorBase):
                 else:
                     res = self.__configlet_modify(cls_perSw[s])
                     allLeafConfigured[s] = res[0]
+
                     if not allLeafConfigured[s]:
                         continue
+
                     cl = cls_perSw[s]
+
                 res = self.__device_modify(
-                    device_to_update=s,
-                    new_configlets=cl,
-                    delete=toDelete_in_cvp)
+                    device_to_update=s, new_configlets=cl, delete=toDelete_in_cvp
+                )
+
                 if "errorMessage" in str(res):
                     raise Exception(str(res))
+
                 self.logger.info("Device {} modify result {}".format(s, res))
-                for t_id in res[1]['tasks']:
+
+                for t_id in res[1]["tasks"]:
                     if not toDelete_in_cvp:
-                        note_msg = "{}{}{}{}##".format(self.__MANAGED_BY_OSM,
-                                                       self.__SEPARATOR,
-                                                       t_id,
-                                                       self.__SEPARATOR)
+                        note_msg = "{}{}{}{}##".format(
+                            self.__MANAGED_BY_OSM,
+                            self.__SEPARATOR,
+                            t_id,
+                            self.__SEPARATOR,
+                        )
                         self.client.api.add_note_to_configlet(
-                            cls_perSw[s][0]['key'],
-                            note_msg)
-                        cls_perSw[s][0]['note'] = note_msg
-                    tasks = {t_id: {'workOrderId': t_id}}
+                            cls_perSw[s][0]["key"], note_msg
+                        )
+                        cls_perSw[s][0]["note"] = note_msg
+
+                    tasks = {t_id: {"workOrderId": t_id}}
                     self.__exec_task(tasks, self.__EXC_TASK_EXEC_WAIT)
+
                 # with just one configLet assigned to a device,
                 # delete all if there are errors in next loops
                 if not toDelete_in_cvp:
                     allLeafModified[s] = True
+
             if len(cl_toDelete) > 0:
                 self.__configlet_modify(cl_toDelete, delete=True)
 
             return allLeafConfigured, allLeafModified
         except Exception as ex:
             try:
-                self.__rollbackConnection(cls_perSw,
-                                          allLeafConfigured,
-                                          allLeafModified)
+                self.__rollbackConnection(cls_perSw, allLeafConfigured, allLeafModified)
             except Exception as e:
-                self.logger.error("Exception rolling back in updating  connection: {}".
-                                  format(e), exc_info=True)
+                self.logger.error(
+                    "Exception rolling back in updating  connection: {}".format(e),
+                    exc_info=True,
+                )
+
             raise ex
 
-    def __rollbackConnection(self,
-                             cls_perSw,
-                             allLeafConfigured,
-                             allLeafModified):
-        """ Removes the given configLet from the devices and then remove the configLets
-        """
+    def __rollbackConnection(self, cls_perSw, allLeafConfigured, allLeafModified):
+        """Removes the given configLet from the devices and then remove the configLets"""
         for s in self.switches:
             if allLeafModified[s]:
                 try:
                     res = self.__device_modify(
                         device_to_update=s,
                         new_configlets=cls_perSw[s],
-                        delete=True)
+                        delete=True,
+                    )
+
                     if "errorMessage" in str(res):
                         raise Exception(str(res))
+
                     tasks = dict()
-                    for t_id in res[1]['tasks']:
-                        tasks[t_id] = {'workOrderId': t_id}
+
+                    for t_id in res[1]["tasks"]:
+                        tasks[t_id] = {"workOrderId": t_id}
+
                     self.__exec_task(tasks)
                     self.logger.info("Device {} modify result {}".format(s, res))
                 except Exception as e:
-                    self.logger.error('Error removing configlets from device {}: {}'.format(s, e))
+                    self.logger.error(
+                        "Error removing configlets from device {}: {}".format(s, e)
+                    )
                     pass
+
         for s in self.switches:
             if allLeafConfigured[s]:
                 self.__configlet_modify(cls_perSw[s], delete=True)
@@ -835,23 +975,27 @@ class AristaSdnConnector(SdnConnectorBase):
     def __exec_task(self, tasks, tout=10):
         if self.taskC is None:
             self.__connect()
+
         data = self.taskC.update_all_tasks(tasks).values()
-        self.taskC.task_action(data, tout, 'executed')
+        self.taskC.task_action(data, tout, "executed")
 
     def __device_modify(self, device_to_update, new_configlets, delete):
-        """ Updates the devices (switches) adding or removing the configLet,
+        """Updates the devices (switches) adding or removing the configLet,
         the tasks Id's associated to the change are returned
         """
-        self.logger.info('Enter in __device_modify delete: {}'.format(delete))
+        self.logger.info("Enter in __device_modify delete: {}".format(delete))
         updated = []
         changed = False
         # Task Ids that have been identified during device actions
         newTasks = []
 
-        if (len(new_configlets) == 0 or
-                device_to_update is None or
-                len(device_to_update) == 0):
-            data = {'updated': updated, 'tasks': newTasks}
+        if (
+            len(new_configlets) == 0
+            or device_to_update is None
+            or len(device_to_update) == 0
+        ):
+            data = {"updated": updated, "tasks": newTasks}
+
             return [changed, data]
 
         self.__load_inventory()
@@ -862,17 +1006,21 @@ class AristaSdnConnector(SdnConnectorBase):
         for try_device in allDeviceFacts:
             # Add Device Specific Configlets
             # self.logger.debug(device)
-            if try_device['hostname'] not in device_to_update:
+            if try_device["hostname"] not in device_to_update:
                 continue
+
             dev_cvp_configlets = self.client.api.get_configlets_by_device_id(
-                try_device['systemMacAddress'])
+                try_device["systemMacAddress"]
+            )
             # self.logger.debug(dev_cvp_configlets)
-            try_device['deviceSpecificConfiglets'] = []
+            try_device["deviceSpecificConfiglets"] = []
+
             for cvp_configlet in dev_cvp_configlets:
-                if int(cvp_configlet['containerCount']) == 0:
-                    try_device['deviceSpecificConfiglets'].append(
-                        {'name': cvp_configlet['name'],
-                         'key': cvp_configlet['key']})
+                if int(cvp_configlet["containerCount"]) == 0:
+                    try_device["deviceSpecificConfiglets"].append(
+                        {"name": cvp_configlet["name"], "key": cvp_configlet["key"]}
+                    )
+
             # self.logger.debug(device)
             device = try_device
             break
@@ -884,81 +1032,95 @@ class AristaSdnConnector(SdnConnectorBase):
         update_devices = []
 
         if delete:
-            for cvp_configlet in device['deviceSpecificConfiglets']:
+            for cvp_configlet in device["deviceSpecificConfiglets"]:
                 for cl in new_configlets:
-                    if cvp_configlet['name'] == cl['name']:
+                    if cvp_configlet["name"] == cl["name"]:
                         remove_configlets.append(cvp_configlet)
                         device_update = True
         else:
             for configlet in new_configlets:
-                if configlet not in device['deviceSpecificConfiglets']:
+                if configlet not in device["deviceSpecificConfiglets"]:
                     add_configlets.append(configlet)
                     device_update = True
+
         if device_update:
-            update_devices.append({'hostname': device['hostname'],
-                                   'configlets': [add_configlets,
-                                                  remove_configlets],
-                                   'device': device})
+            update_devices.append(
+                {
+                    "hostname": device["hostname"],
+                    "configlets": [add_configlets, remove_configlets],
+                    "device": device,
+                }
+            )
+
         self.logger.info("Device to modify: {}".format(update_devices))
 
         up_device = update_devices[0]
-        cl_toAdd = up_device['configlets'][0]
-        cl_toDel = up_device['configlets'][1]
+        cl_toAdd = up_device["configlets"][0]
+        cl_toDel = up_device["configlets"][1]
+
         # Update Configlets
         try:
             if delete and len(cl_toDel) > 0:
                 r = self.client.api.remove_configlets_from_device(
-                    'OSM',
-                    up_device['device'],
-                    cl_toDel,
-                    create_task=True)
+                    "OSM", up_device["device"], cl_toDel, create_task=True
+                )
                 dev_action = r
-                self.logger.debug("remove_configlets_from_device {} {}".format(dev_action, cl_toDel))
+                self.logger.debug(
+                    "remove_configlets_from_device {} {}".format(dev_action, cl_toDel)
+                )
             elif len(cl_toAdd) > 0:
                 r = self.client.api.apply_configlets_to_device(
-                    'OSM',
-                    up_device['device'],
-                    cl_toAdd,
-                    create_task=True)
+                    "OSM", up_device["device"], cl_toAdd, create_task=True
+                )
                 dev_action = r
-                self.logger.debug("apply_configlets_to_device {} {}".format(dev_action, cl_toAdd))
-
+                self.logger.debug(
+                    "apply_configlets_to_device {} {}".format(dev_action, cl_toAdd)
+                )
         except Exception as error:
             errorMessage = str(error)
-            msg = "errorMessage: Device {} Configlets couldnot be updated: {}".format(
-                up_device['hostname'], errorMessage)
+            msg = "errorMessage: Device {} Configlets could not be updated: {}".format(
+                up_device["hostname"], errorMessage
+            )
             raise SdnConnectorError(msg) from error
         else:
             if "errorMessage" in str(dev_action):
                 m = "Device {} Configlets update fail: {}".format(
-                    up_device['name'], dev_action['errorMessage'])
+                    up_device["name"], dev_action["errorMessage"]
+                )
                 raise SdnConnectorError(m)
             else:
                 changed = True
-                if 'taskIds' in str(dev_action):
+                if "taskIds" in str(dev_action):
                     # Fix 1030 SDN-ARISTA Key error note when deploy a NS
-                    if not dev_action['data']['taskIds']:
-                        raise SdnConnectorError("No taskIds found: Device {} Configlets could not be updated".format(
-                            up_device['hostname']))
-                    for taskId in dev_action['data']['taskIds']:
-                        updated.append({
-                            up_device['hostname']: "Configlets-{}".format(taskId)})
+                    if not dev_action["data"]["taskIds"]:
+                        raise SdnConnectorError(
+                            "No taskIds found: Device {} Configlets could not be updated".format(
+                                up_device["hostname"]
+                            )
+                        )
+
+                    for taskId in dev_action["data"]["taskIds"]:
+                        updated.append(
+                            {up_device["hostname"]: "Configlets-{}".format(taskId)}
+                        )
                         newTasks.append(taskId)
                 else:
-                    updated.append({up_device['hostname']:
-                                   "Configlets-No_Specific_Tasks"})
-        data = {'updated': updated, 'tasks': newTasks}
+                    updated.append(
+                        {up_device["hostname"]: "Configlets-No_Specific_Tasks"}
+                    )
+
+        data = {"updated": updated, "tasks": newTasks}
+
         return [changed, data]
 
     def __configlet_modify(self, configletsToApply, delete=False):
-        ''' adds/update or delete the provided configLets
+        """Adds/update or delete the provided configLets
         :param configletsToApply: list of configLets to apply
         :param delete: flag to indicate if the configLets have to be deleted
                         from Cloud Vision Portal
         :return: data: dict of module actions and taskIDs
-        '''
-        self.logger.info('Enter in __configlet_modify delete:{}'.format(
-            delete))
+        """
+        self.logger.info("Enter in __configlet_modify delete:{}".format(delete))
 
         # Compare configlets against cvp_facts-configlets
         changed = False
@@ -973,10 +1135,11 @@ class AristaSdnConnector(SdnConnectorBase):
             to_update = False
             to_create = False
             to_check = False
+
             try:
-                cvp_cl = self.client.api.get_configlet_by_name(cl['name'])
-                cl['key'] = cvp_cl['key']
-                cl['note'] = cvp_cl['note']
+                cvp_cl = self.client.api.get_configlet_by_name(cl["name"])
+                cl["key"] = cvp_cl["key"]
+                cl["note"] = cvp_cl["note"]
                 found_in_cvp = True
             except CvpApiError as error:
                 if "Entity does not exist" in error.msg:
@@ -987,119 +1150,130 @@ class AristaSdnConnector(SdnConnectorBase):
             if delete:
                 if found_in_cvp:
                     to_delete = True
-                    configlet = {'name': cvp_cl['name'],
-                                 'data': cvp_cl}
+                    configlet = {"name": cvp_cl["name"], "data": cvp_cl}
             else:
                 if found_in_cvp:
-                    cl_compare = self.__compare(cl['config'],
-                                                cvp_cl['config'])
+                    cl_compare = self.__compare(cl["config"], cvp_cl["config"])
+
                     # compare function returns a floating point number
                     if cl_compare[0] != 100.0:
                         to_update = True
-                        configlet = {'name': cl['name'],
-                                     'data': cvp_cl,
-                                     'config': cl['config']}
+                        configlet = {
+                            "name": cl["name"],
+                            "data": cvp_cl,
+                            "config": cl["config"],
+                        }
                     else:
                         to_check = True
-                        configlet = {'name': cl['name'],
-                                     'key': cvp_cl['key'],
-                                     'data': cvp_cl,
-                                     'config': cl['config']}
+                        configlet = {
+                            "name": cl["name"],
+                            "key": cvp_cl["key"],
+                            "data": cvp_cl,
+                            "config": cl["config"],
+                        }
                 else:
                     to_create = True
-                    configlet = {'name': cl['name'],
-                                 'config': cl['config']}
+                    configlet = {"name": cl["name"], "config": cl["config"]}
             try:
                 if to_delete:
-                    operation = 'delete'
+                    operation = "delete"
                     resp = self.client.api.delete_configlet(
-                        configlet['data']['name'],
-                        configlet['data']['key'])
+                        configlet["data"]["name"], configlet["data"]["key"]
+                    )
                 elif to_update:
-                    operation = 'update'
+                    operation = "update"
                     resp = self.client.api.update_configlet(
-                        configlet['config'],
-                        configlet['data']['key'],
-                        configlet['data']['name'],
-                        wait_task_ids=True)
+                        configlet["config"],
+                        configlet["data"]["key"],
+                        configlet["data"]["name"],
+                        wait_task_ids=True,
+                    )
                 elif to_create:
-                    operation = 'create'
+                    operation = "create"
                     resp = self.client.api.add_configlet(
-                        configlet['name'],
-                        configlet['config'])
+                        configlet["name"], configlet["config"]
+                    )
                 else:
-                    operation = 'checked'
-                    resp = 'checked'
+                    operation = "checked"
+                    resp = "checked"
             except Exception as error:
-                errorMessage = str(error).split(':')[-1]
+                errorMessage = str(error).split(":")[-1]
                 message = "Configlet {} cannot be {}: {}".format(
-                    cl['name'], operation, errorMessage)
+                    cl["name"], operation, errorMessage
+                )
+
                 if to_delete:
-                    deleted.append({configlet['name']: message})
+                    deleted.append({configlet["name"]: message})
                 elif to_update:
-                    updated.append({configlet['name']: message})
+                    updated.append({configlet["name"]: message})
                 elif to_create:
-                    new.append({configlet['name']: message})
+                    new.append({configlet["name"]: message})
                 elif to_check:
-                    checked.append({configlet['name']: message})
-
+                    checked.append({configlet["name"]: message})
             else:
                 if "error" in str(resp).lower():
                     message = "Configlet {} cannot be deleted: {}".format(
-                        cl['name'], resp['errorMessage'])
+                        cl["name"], resp["errorMessage"]
+                    )
+
                     if to_delete:
-                        deleted.append({configlet['name']: message})
+                        deleted.append({configlet["name"]: message})
                     elif to_update:
-                        updated.append({configlet['name']: message})
+                        updated.append({configlet["name"]: message})
                     elif to_create:
-                        new.append({configlet['name']: message})
+                        new.append({configlet["name"]: message})
                     elif to_check:
-                        checked.append({configlet['name']: message})
+                        checked.append({configlet["name"]: message})
                 else:
                     if to_delete:
                         changed = True
-                        deleted.append({configlet['name']: "success"})
+                        deleted.append({configlet["name"]: "success"})
                     elif to_update:
                         changed = True
-                        updated.append({configlet['name']: "success"})
+                        updated.append({configlet["name"]: "success"})
                     elif to_create:
                         changed = True
-                        cl['key'] = resp  # This key is used in API call deviceApplyConfigLet FGA
-                        new.append({configlet['name']: "success"})
+                        # This key is used in API call deviceApplyConfigLet FGA
+                        cl["key"] = resp
+                        new.append({configlet["name"]: "success"})
                     elif to_check:
                         changed = False
-                        checked.append({configlet['name']: "success"})
+                        checked.append({configlet["name"]: "success"})
+
+        data = {"new": new, "updated": updated, "deleted": deleted, "checked": checked}
 
-        data = {'new': new, 'updated': updated, 'deleted': deleted, 'checked': checked}
         return [changed, data]
 
     def __get_configletsDevices(self, configlets):
         for s in self.switches:
             configlet = configlets[s]
+
             # Add applied Devices
             if len(configlet) > 0:
-                configlet['devices'] = []
-                applied_devices = self.client.api.get_applied_devices(
-                    configlet['name'])
-                for device in applied_devices['data']:
-                    configlet['devices'].append(device['hostName'])
+                configlet["devices"] = []
+                applied_devices = self.client.api.get_applied_devices(configlet["name"])
+
+                for device in applied_devices["data"]:
+                    configlet["devices"].append(device["hostName"])
 
     def __get_serviceData(self, service_uuid, service_type, vlan_id, conn_info=None):
         cls_perSw = {}
+
         for s in self.switches:
             cls_perSw[s] = []
+
         if not conn_info:
-            srv_cls = self.__get_serviceConfigLets(service_uuid,
-                                                   service_type,
-                                                   vlan_id)
+            srv_cls = self.__get_serviceConfigLets(service_uuid, service_type, vlan_id)
             self.__get_configletsDevices(srv_cls)
+
             for s in self.switches:
                 cl = srv_cls[s]
                 if len(cl) > 0:
-                    for dev in cl['devices']:
+                    for dev in cl["devices"]:
                         cls_perSw[dev].append(cl)
         else:
-            cls_perSw = conn_info['configLetPerSwitch']
+            cls_perSw = conn_info["configLetPerSwitch"]
+
         return cls_perSw
 
     def delete_connectivity_service(self, service_uuid, conn_info=None):
@@ -1113,59 +1287,77 @@ class AristaSdnConnector(SdnConnectorBase):
         :raises: SdnConnectorException: In case of error. The parameter http_code must be filled
         """
         try:
-            self.logger.debug('invoked delete_connectivity_service {}'.
-                              format(service_uuid))
+            self.logger.debug(
+                "invoked delete_connectivity_service {}".format(service_uuid)
+            )
+
             if not service_uuid:
-                raise SdnConnectorError(message='No connection service UUID',
-                                        http_code=500)
+                raise SdnConnectorError(
+                    message="No connection service UUID", http_code=500
+                )
 
             self.__get_Connection()
+
             if conn_info is None:
-                raise SdnConnectorError(message='No connection information for service UUID {}'.format(service_uuid),
-                                        http_code=500)
+                raise SdnConnectorError(
+                    message="No connection information for service UUID {}".format(
+                        service_uuid
+                    ),
+                    http_code=500,
+                )
+
             c_info = None
-            cls_perSw = self.__get_serviceData(service_uuid,
-                                               conn_info['service_type'],
-                                               conn_info['vlan_id'],
-                                               c_info)
+            cls_perSw = self.__get_serviceData(
+                service_uuid, conn_info["service_type"], conn_info["vlan_id"], c_info
+            )
             allLeafConfigured = {}
             allLeafModified = {}
+
             for s in self.switches:
                 allLeafConfigured[s] = True
                 allLeafModified[s] = True
+
             found_in_cvp = False
+
             for s in self.switches:
                 if cls_perSw[s]:
                     found_in_cvp = True
+
             if found_in_cvp:
-                self.__rollbackConnection(cls_perSw,
-                                          allLeafConfigured,
-                                          allLeafModified)
+                self.__rollbackConnection(cls_perSw, allLeafConfigured, allLeafModified)
             else:
                 # if the service is not defined in Cloud Vision, return a 404 - NotFound error
-                raise SdnConnectorError(message='Service {} was not found in Arista Cloud Vision {}'.
-                                        format(service_uuid, self.__wim_url),
-                                        http_code=404)
+                raise SdnConnectorError(
+                    message="Service {} was not found in Arista Cloud Vision {}".format(
+                        service_uuid, self.__wim_url
+                    ),
+                    http_code=404,
+                )
+
             self.__removeMetadata(service_uuid)
         except CvpLoginError as e:
             self.logger.info(str(e))
             self.client = None
-            raise SdnConnectorError(message=SdnError.UNAUTHORIZED + " " + str(e),
-                                    http_code=401) from e
+            raise SdnConnectorError(
+                message=SdnError.UNAUTHORIZED + " " + str(e), http_code=401
+            ) from e
         except SdnConnectorError as sde:
             raise sde
         except Exception as ex:
             self.client = None
             self.logger.error(ex)
+
             if self.raiseException:
                 raise ex
-            raise SdnConnectorError(message=SdnError.INTERNAL_ERROR + " " + str(ex),
-                                    http_code=500) from ex
+
+            raise SdnConnectorError(
+                message=SdnError.INTERNAL_ERROR + " " + str(ex), http_code=500
+            ) from ex
 
     def __addMetadata(self, service_uuid, service_type, vlan_id):
-        """ Adds the connectivity service from 'OSM_metadata' configLet
-        """
+        """Adds the connectivity service from 'OSM_metadata' configLet"""
         found_in_cvp = False
+
         try:
             cvp_cl = self.client.api.get_configlet_by_name(self.__OSM_METADATA)
             found_in_cvp = True
@@ -1174,24 +1366,31 @@ class AristaSdnConnector(SdnConnectorBase):
                 pass
             else:
                 raise error
+
         try:
-            new_serv = '{} {} {} {}\n'.format(self.__METADATA_PREFIX, service_type, vlan_id, service_uuid)
+            new_serv = "{} {} {} {}\n".format(
+                self.__METADATA_PREFIX, service_type, vlan_id, service_uuid
+            )
 
             if found_in_cvp:
-                cl_config = cvp_cl['config'] + new_serv
+                cl_config = cvp_cl["config"] + new_serv
             else:
                 cl_config = new_serv
-            cl_meta = [{'name': self.__OSM_METADATA, 'config': cl_config}]
+
+            cl_meta = [{"name": self.__OSM_METADATA, "config": cl_config}]
             self.__configlet_modify(cl_meta)
         except Exception as e:
-            self.logger.error('Error in setting metadata in CloudVision from OSM for service {}: {}'.
-                              format(service_uuid, str(e)))
+            self.logger.error(
+                "Error in setting metadata in CloudVision from OSM for service {}: {}".format(
+                    service_uuid, str(e)
+                )
+            )
             pass
 
     def __removeMetadata(self, service_uuid):
-        """ Removes the connectivity service from 'OSM_metadata' configLet
-        """
+        """Removes the connectivity service from 'OSM_metadata' configLet"""
         found_in_cvp = False
+
         try:
             cvp_cl = self.client.api.get_configlet_by_name(self.__OSM_METADATA)
             found_in_cvp = True
@@ -1200,28 +1399,32 @@ class AristaSdnConnector(SdnConnectorBase):
                 pass
             else:
                 raise error
+
         try:
             if found_in_cvp:
-                if service_uuid in cvp_cl['config']:
-                    cl_config = ''
-                    for line in cvp_cl['config'].split('\n'):
+                if service_uuid in cvp_cl["config"]:
+                    cl_config = ""
+
+                    for line in cvp_cl["config"].split("\n"):
                         if service_uuid in line:
                             continue
                         else:
                             cl_config = cl_config + line
-                    cl_meta = [{'name': self.__OSM_METADATA, 'config': cl_config}]
+
+                    cl_meta = [{"name": self.__OSM_METADATA, "config": cl_config}]
                     self.__configlet_modify(cl_meta)
         except Exception as e:
-            self.logger.error('Error in removing metadata in CloudVision from OSM for service {}: {}'.
-                              format(service_uuid, str(e)))
+            self.logger.error(
+                "Error in removing metadata in CloudVision from OSM for service {}: {}".format(
+                    service_uuid, str(e)
+                )
+            )
             pass
 
-    def edit_connectivity_service(self,
-                                  service_uuid,
-                                  conn_info=None,
-                                  connection_points=None,
-                                  **kwargs):
-        """ Change an existing connectivity service.
+    def edit_connectivity_service(
+        self, service_uuid, conn_info=None, connection_points=None, **kwargs
+    ):
+        """Change an existing connectivity service.
 
         This method's arguments and return value follow the same convention as
         :meth:`~.create_connectivity_service`.
@@ -1243,43 +1446,52 @@ class AristaSdnConnector(SdnConnectorBase):
             SdnConnectorError: In case of error.
         """
         try:
-            self.logger.debug('invoked edit_connectivity_service for service {}. ports: {}'.format(service_uuid,
-                                                                                                   connection_points))
+            self.logger.debug(
+                "invoked edit_connectivity_service for service {}. ports: {}".format(
+                    service_uuid, connection_points
+                )
+            )
 
             if not service_uuid:
-                raise SdnConnectorError(message='Unable to perform operation, missing or empty uuid',
-                                        http_code=500)
+                raise SdnConnectorError(
+                    message="Unable to perform operation, missing or empty uuid",
+                    http_code=500,
+                )
+
             if not conn_info:
-                raise SdnConnectorError(message='Unable to perform operation, missing or empty connection information',
-                                        http_code=500)
+                raise SdnConnectorError(
+                    message="Unable to perform operation, missing or empty connection information",
+                    http_code=500,
+                )
 
             if connection_points is None:
                 return None
 
             self.__get_Connection()
 
-            cls_currentPerSw = conn_info['configLetPerSwitch']
-            service_type = conn_info['service_type']
-
-            self.__check_service(service_type,
-                                 connection_points,
-                                 check_vlan=False,
-                                 check_num_cp=False,
-                                 kwargs=kwargs)
+            cls_currentPerSw = conn_info["configLetPerSwitch"]
+            service_type = conn_info["service_type"]
 
-            s_uid, s_connInf = self.__processConnection(
-                service_uuid,
+            self.__check_service(
                 service_type,
                 connection_points,
-                kwargs)
-            self.logger.info("Service with uuid {} configuration updated".
-                             format(s_uid))
+                check_vlan=False,
+                check_num_cp=False,
+                kwargs=kwargs,
+            )
+
+            s_uid, s_connInf = self.__processConnection(
+                service_uuid, service_type, connection_points, kwargs
+            )
+            self.logger.info("Service with uuid {} configuration updated".format(s_uid))
+
             return s_connInf
         except CvpLoginError as e:
             self.logger.info(str(e))
             self.client = None
-            raise SdnConnectorError(message=SdnError.UNAUTHORIZED + " " + str(e),
-                                    http_code=401) from e
+            raise SdnConnectorError(
+                message=SdnError.UNAUTHORIZED + " " + str(e), http_code=401
+            ) from e
         except SdnConnectorError as sde:
             raise sde
         except Exception as ex:
@@ -1288,92 +1500,113 @@ class AristaSdnConnector(SdnConnectorBase):
                 # TODO check if there are pending task, and cancel them before restoring
                 self.__updateConnection(cls_currentPerSw)
             except Exception as e:
-                self.logger.error("Unable to restore configuration in service {} after an error in the configuration"
-                                  " updated: {}".format(service_uuid, str(e)))
+                self.logger.error(
+                    "Unable to restore configuration in service {} after an error in the configuration"
+                    " updated: {}".format(service_uuid, str(e))
+                )
+
             if self.raiseException:
                 raise ex
-            raise SdnConnectorError(message=str(ex),
-                                    http_code=500) from ex
+
+            raise SdnConnectorError(message=str(ex), http_code=500) from ex
 
     def clear_all_connectivity_services(self):
-        """ Removes all connectivity services from Arista CloudVision with two steps:
-        - retrives all the services from Arista CloudVision
+        """Removes all connectivity services from Arista CloudVision with two steps:
+        - retrieves all the services from Arista CloudVision
         - removes each service
         """
         try:
-            self.logger.debug('invoked AristaImpl ' +
-                              'clear_all_connectivity_services')
+            self.logger.debug("invoked AristaImpl clear_all_connectivity_services")
             self.__get_Connection()
             s_list = self.__get_srvUUIDs()
+
             for serv in s_list:
                 conn_info = {}
-                conn_info['service_type'] = serv['type']
-                conn_info['vlan_id'] = serv['vlan']
-
-                self.delete_connectivity_service(serv['uuid'], conn_info)
+                conn_info["service_type"] = serv["type"]
+                conn_info["vlan_id"] = serv["vlan"]
+                self.delete_connectivity_service(serv["uuid"], conn_info)
         except CvpLoginError as e:
             self.logger.info(str(e))
             self.client = None
-            raise SdnConnectorError(message=SdnError.UNAUTHORIZED + " " + str(e),
-                                    http_code=401) from e
+
+            raise SdnConnectorError(
+                message=SdnError.UNAUTHORIZED + " " + str(e), http_code=401
+            ) from e
         except SdnConnectorError as sde:
             raise sde
         except Exception as ex:
             self.client = None
             self.logger.error(ex)
+
             if self.raiseException:
                 raise ex
-            raise SdnConnectorError(message=SdnError.INTERNAL_ERROR + " " + str(ex),
-                                    http_code=500) from ex
+
+            raise SdnConnectorError(
+                message=SdnError.INTERNAL_ERROR + " " + str(ex), http_code=500
+            ) from ex
 
     def get_all_active_connectivity_services(self):
-        """ Return the uuid of all the active connectivity services with two steps:
+        """Return the uuid of all the active connectivity services with two steps:
         - retrives all the services from Arista CloudVision
         - retrives the status of each server
         """
         try:
-            self.logger.debug('invoked AristaImpl {}'.format(
-                              'get_all_active_connectivity_services'))
+            self.logger.debug(
+                "invoked AristaImpl {}".format("get_all_active_connectivity_services")
+            )
             self.__get_Connection()
             s_list = self.__get_srvUUIDs()
             result = []
+
             for serv in s_list:
                 conn_info = {}
-                conn_info['service_type'] = serv['type']
-                conn_info['vlan_id'] = serv['vlan']
+                conn_info["service_type"] = serv["type"]
+                conn_info["vlan_id"] = serv["vlan"]
+                status = self.get_connectivity_service_status(serv["uuid"], conn_info)
+
+                if status["sdn_status"] == "ACTIVE":
+                    result.append(serv["uuid"])
 
-                status = self.get_connectivity_service_status(serv['uuid'], conn_info)
-                if status['sdn_status'] == 'ACTIVE':
-                    result.append(serv['uuid'])
             return result
         except CvpLoginError as e:
             self.logger.info(str(e))
             self.client = None
-            raise SdnConnectorError(message=SdnError.UNAUTHORIZED + " " + str(e),
-                                    http_code=401) from e
+            raise SdnConnectorError(
+                message=SdnError.UNAUTHORIZED + " " + str(e), http_code=401
+            ) from e
         except SdnConnectorError as sde:
             raise sde
         except Exception as ex:
             self.client = None
             self.logger.error(ex)
+
             if self.raiseException:
                 raise ex
-            raise SdnConnectorError(message=SdnError.INTERNAL_ERROR,
-                                    http_code=500) from ex
+
+            raise SdnConnectorError(
+                message=SdnError.INTERNAL_ERROR, http_code=500
+            ) from ex
 
     def __get_serviceConfigLets(self, service_uuid, service_type, vlan_id):
-        """ Return the configLet's associated with a connectivity service,
+        """Return the configLet's associated with a connectivity service,
         There should be one, as maximum, per device (switch) for a given
         connectivity service
         """
         srv_cls = {}
+
         for s in self.switches:
             srv_cls[s] = []
             found_in_cvp = False
-            name = (self.__OSM_PREFIX +
-                    s +
-                    self.__SEPARATOR + service_type + str(vlan_id) +
-                    self.__SEPARATOR + service_uuid)
+            name = (
+                self.__OSM_PREFIX
+                + s
+                + self.__SEPARATOR
+                + service_type
+                + str(vlan_id)
+                + self.__SEPARATOR
+                + service_uuid
+            )
+
             try:
                 cvp_cl = self.client.api.get_configlet_by_name(name)
                 found_in_cvp = True
@@ -1382,16 +1615,19 @@ class AristaSdnConnector(SdnConnectorBase):
                     pass
                 else:
                     raise error
+
             if found_in_cvp:
                 srv_cls[s] = cvp_cl
+
         return srv_cls
 
     def __get_srvVLANs(self):
-        """ Returns a list with all the VLAN id's used in the connectivity services managed
+        """Returns a list with all the VLAN id's used in the connectivity services managed
         in tha Arista CloudVision by checking the 'OSM_metadata' configLet where this
         information is stored
         """
         found_in_cvp = False
+
         try:
             cvp_cl = self.client.api.get_configlet_by_name(self.__OSM_METADATA)
             found_in_cvp = True
@@ -1400,26 +1636,28 @@ class AristaSdnConnector(SdnConnectorBase):
                 pass
             else:
                 raise error
+
         s_vlan_list = []
         if found_in_cvp:
-            lines = cvp_cl['config'].split('\n')
+            lines = cvp_cl["config"].split("\n")
+
             for line in lines:
                 if self.__METADATA_PREFIX in line:
-                    s_vlan = line.split(' ')[3]
+                    s_vlan = line.split(" ")[3]
                 else:
                     continue
-                if (s_vlan is not None and
-                        len(s_vlan) > 0 and
-                        s_vlan not in s_vlan_list):
+
+                if s_vlan is not None and len(s_vlan) > 0 and s_vlan not in s_vlan_list:
                     s_vlan_list.append(s_vlan)
 
         return s_vlan_list
 
     def __get_srvUUIDs(self):
-        """ Retrieves all the connectivity services, managed in tha Arista CloudVision
+        """Retrieves all the connectivity services, managed in tha Arista CloudVision
         by checking the 'OSM_metadata' configLet where this information is stored
         """
         found_in_cvp = False
+
         try:
             cvp_cl = self.client.api.get_configlet_by_name(self.__OSM_METADATA)
             found_in_cvp = True
@@ -1428,29 +1666,31 @@ class AristaSdnConnector(SdnConnectorBase):
                 pass
             else:
                 raise error
+
         serv_list = []
         if found_in_cvp:
-            lines = cvp_cl['config'].split('\n')
+            lines = cvp_cl["config"].split("\n")
+
             for line in lines:
                 if self.__METADATA_PREFIX in line:
-                    line = line.split(' ')
-                    serv = {'uuid': line[4], 'type': line[2], 'vlan': line[3]}
+                    line = line.split(" ")
+                    serv = {"uuid": line[4], "type": line[2], "vlan": line[3]}
                 else:
                     continue
-                if (serv is not None and
-                        len(serv) > 0 and
-                        serv not in serv_list):
+
+                if serv is not None and len(serv) > 0 and serv not in serv_list:
                     serv_list.append(serv)
 
         return serv_list
 
     def __get_Connection(self):
-        """ Open a connection with Arista CloudVision,
-            invoking the version retrival as test
+        """Open a connection with Arista CloudVision,
+        invoking the version retrival as test
         """
         try:
             if self.client is None:
                 self.client = self.__connect()
+
             self.client.api.get_cvp_info()
         except (CvpSessionLogOutError, RequestException) as e:
             self.logger.debug("Connection error '{}'. Reconnecting".format(e))
@@ -1458,12 +1698,13 @@ class AristaSdnConnector(SdnConnectorBase):
             self.client.api.get_cvp_info()
 
     def __connect(self):
-        ''' Connects to CVP device using user provided credentials from initialization.
+        """Connects to CVP device using user provided credentials from initialization.
         :return: CvpClient object with connection instantiated.
-        '''
+        """
         client = CvpClient()
         protocol, _, rest_url = self.__wim_url.rpartition("://")
         host, _, port = rest_url.partition(":")
+
         if port and port.endswith("/"):
             port = int(port[:-1])
         elif port:
@@ -1471,18 +1712,21 @@ class AristaSdnConnector(SdnConnectorBase):
         else:
             port = 443
 
-        client.connect([host],
-                       self.__user,
-                       self.__passwd,
-                       protocol=protocol or "https",
-                       port=port,
-                       connect_timeout=2)
+        client.connect(
+            [host],
+            self.__user,
+            self.__passwd,
+            protocol=protocol or "https",
+            port=port,
+            connect_timeout=2,
+        )
         client.api = CvpApi(client, request_timeout=self.__API_REQUEST_TOUT)
         self.taskC = AristaCVPTask(client.api)
+
         return client
 
     def __compare(self, fromText, toText, lines=10):
-        """ Compare text string in 'fromText' with 'toText' and produce
+        """Compare text string in 'fromText' with 'toText' and produce
         diffRatio - a score as a float in the range [0, 1] 2.0*M / T
           T is the total number of elements in both sequences,
           M is the number of matches.
@@ -1499,108 +1743,162 @@ class AristaSdnConnector(SdnConnectorBase):
         tolines = toText.splitlines(1)
         diff = list(difflib.unified_diff(fromlines, tolines, n=lines))
         textComp = difflib.SequenceMatcher(None, fromText, toText)
-        diffRatio = round(textComp.quick_ratio()*100, 2)
+        diffRatio = round(textComp.quick_ratio() * 100, 2)
+
         return [diffRatio, diff]
 
     def __load_inventory(self):
-        """ Get Inventory Data for All Devices (aka switches) from the Arista CloudVision
-        """
+        """Get Inventory Data for All Devices (aka switches) from the Arista CloudVision"""
         if not self.cvp_inventory:
             self.cvp_inventory = self.client.api.get_inventory()
+
         self.allDeviceFacts = []
+
         for device in self.cvp_inventory:
             self.allDeviceFacts.append(device)
 
     def __get_tags(self, name, value):
         if not self.cvp_tags:
             self.cvp_tags = []
-            url = '/api/v1/rest/analytics/tags/labels/devices/{}/value/{}/elements'.format(name, value)
-            self.logger.debug('get_tags: URL {}'.format(url))
+            url = "/api/v1/rest/analytics/tags/labels/devices/{}/value/{}/elements".format(
+                name, value
+            )
+            self.logger.debug("get_tags: URL {}".format(url))
             data = self.client.get(url, timeout=self.__API_REQUEST_TOUT)
-            for dev in data['notifications']:
-                for elem in dev['updates']:
+
+            for dev in data["notifications"]:
+                for elem in dev["updates"]:
                     self.cvp_tags.append(elem)
-        self.logger.debug('Available devices with tag_name {} - value {}: {} '.format(name, value, self.cvp_tags))
+
+        self.logger.debug(
+            "Available devices with tag_name {} - value {}: {}".format(
+                name, value, self.cvp_tags
+            )
+        )
 
     def __get_interface_ip(self, device_id, interface):
-        url = '/api/v1/rest/{}/Sysdb/ip/config/ipIntfConfig/{}/'.format(device_id, interface)
-        self.logger.debug('get_interface_ip: URL {}'.format(url))
+        url = "/api/v1/rest/{}/Sysdb/ip/config/ipIntfConfig/{}/".format(
+            device_id, interface
+        )
+        self.logger.debug("get_interface_ip: URL {}".format(url))
         data = None
+
         try:
             data = self.client.get(url, timeout=self.__API_REQUEST_TOUT)
-            if data['notifications']:
-                for notification in data['notifications']:
-                    for update in notification['updates']:
-                        if update == 'addrWithMask':
-                            return notification['updates'][update]['value']
+
+            if data["notifications"]:
+                for notification in data["notifications"]:
+                    for update in notification["updates"]:
+                        if update == "addrWithMask":
+                            return notification["updates"][update]["value"]
         except Exception as e:
-            raise SdnConnectorError("Invalid response from url {}: data {} - {}".format(url, data, str(e)))
-        raise SdnConnectorError("Unable to get ip for interface {} in device {}, data {}".
-                                format(interface, device_id, data))
+            raise SdnConnectorError(
+                "Invalid response from url {}: data {} - {}".format(url, data, str(e))
+            )
+
+        raise SdnConnectorError(
+            "Unable to get ip for interface {} in device {}, data {}".format(
+                interface, device_id, data
+            )
+        )
 
     def __get_device_ASN(self, device_id):
-        url = '/api/v1/rest/{}/Sysdb/routing/bgp/config/'.format(device_id)
-        self.logger.debug('get_device_ASN: URL {}'.format(url))
+        url = "/api/v1/rest/{}/Sysdb/routing/bgp/config/".format(device_id)
+        self.logger.debug("get_device_ASN: URL {}".format(url))
         data = None
+
         try:
             data = self.client.get(url, timeout=self.__API_REQUEST_TOUT)
-            if data['notifications']:
-                for notification in data['notifications']:
-                    for update in notification['updates']:
-                        if update == 'asNumber':
-                            return notification['updates'][update]['value']['value']['int']
+            if data["notifications"]:
+                for notification in data["notifications"]:
+                    for update in notification["updates"]:
+                        if update == "asNumber":
+                            return notification["updates"][update]["value"]["value"][
+                                "int"
+                            ]
         except Exception as e:
-            raise SdnConnectorError("Invalid response from url {}: data {} - {}".format(url, data, str(e)))
-        raise SdnConnectorError("Unable to get AS in device {}, data {}".format(device_id, data))
+            raise SdnConnectorError(
+                "Invalid response from url {}: data {} - {}".format(url, data, str(e))
+            )
+
+        raise SdnConnectorError(
+            "Unable to get AS in device {}, data {}".format(device_id, data)
+        )
 
     def __get_peer_MLAG(self, device_id):
         peer = None
-        url = '/api/v1/rest/{}/Sysdb/mlag/status/'.format(device_id)
-        self.logger.debug('get_MLAG_status: URL {}'.format(url))
+        url = "/api/v1/rest/{}/Sysdb/mlag/status/".format(device_id)
+        self.logger.debug("get_MLAG_status: URL {}".format(url))
+
         try:
             data = self.client.get(url, timeout=self.__API_REQUEST_TOUT)
-            if data['notifications']:
+
+            if data["notifications"]:
                 found = False
-                for notification in data['notifications']:
-                    for update in notification['updates']:
-                        if update == 'systemId':
-                            mlagSystemId = notification['updates'][update]['value']
+
+                for notification in data["notifications"]:
+                    for update in notification["updates"]:
+                        if update == "systemId":
+                            mlagSystemId = notification["updates"][update]["value"]
                             found = True
                             break
+
                     if found:
                         break
+
                 # search the MLAG System Id
                 if found:
                     for s in self.switches:
-                        if self.switches[s]['serialNumber'] == device_id:
+                        if self.switches[s]["serialNumber"] == device_id:
                             continue
-                        url = '/api/v1/rest/{}/Sysdb/mlag/status/'.format(self.switches[s]['serialNumber'])
-                        self.logger.debug('Searching for MLAG system id {} in switch {}'.format(mlagSystemId, s))
+
+                        url = "/api/v1/rest/{}/Sysdb/mlag/status/".format(
+                            self.switches[s]["serialNumber"]
+                        )
+                        self.logger.debug(
+                            "Searching for MLAG system id {} in switch {}".format(
+                                mlagSystemId, s
+                            )
+                        )
                         data = self.client.get(url, timeout=self.__API_REQUEST_TOUT)
                         found = False
-                        for notification in data['notifications']:
-                            for update in notification['updates']:
-                                if update == 'systemId':
-                                    if mlagSystemId == notification['updates'][update]['value']:
+
+                        for notification in data["notifications"]:
+                            for update in notification["updates"]:
+                                if update == "systemId":
+                                    if (
+                                        mlagSystemId
+                                        == notification["updates"][update]["value"]
+                                    ):
                                         peer = s
                                         found = True
                                         break
+
                             if found:
                                 break
+
                         if found:
                             break
+
             if peer is None:
-                self.logger.error('No Peer device found for device {} with MLAG address {}'.format(device_id,
-                                                                                                   mlagSystemId))
+                self.logger.error(
+                    "No Peer device found for device {} with MLAG address {}".format(
+                        device_id, mlagSystemId
+                    )
+                )
             else:
-                self.logger.debug('Peer MLAG for device {} - value {}'.format(device_id, peer))
+                self.logger.debug(
+                    "Peer MLAG for device {} - value {}".format(device_id, peer)
+                )
+
             return peer
         except Exception:
-            raise SdnConnectorError("Invalid response from url {}: data {}".format(url, data))
+            raise SdnConnectorError(
+                "Invalid response from url {}: data {}".format(url, data)
+            )
 
     def is_valid_destination(self, url):
-        """ Check that the provided WIM URL is correct
-        """
+        """Check that the provided WIM URL is correct"""
         if re.match(self.__regex, url):
             return True
         elif self.is_valid_ipv4_address(url):
@@ -1609,8 +1907,7 @@ class AristaSdnConnector(SdnConnectorBase):
             return self.is_valid_ipv6_address(url)
 
     def is_valid_ipv4_address(self, address):
-        """ Checks that the given IP is IPv4 valid
-        """
+        """Checks that the given IP is IPv4 valid"""
         try:
             socket.inet_pton(socket.AF_INET, address)
         except AttributeError:  # no inet_pton here, sorry
@@ -1618,25 +1915,30 @@ class AristaSdnConnector(SdnConnectorBase):
                 socket.inet_aton(address)
             except socket.error:
                 return False
-            return address.count('.') == 3
+
+            return address.count(".") == 3
         except socket.error:  # not a valid address
             return False
+
         return True
 
     def is_valid_ipv6_address(self, address):
-        """ Checks that the given IP is IPv6 valid
-        """
+        """Checks that the given IP is IPv6 valid"""
         try:
             socket.inet_pton(socket.AF_INET6, address)
         except socket.error:  # not a valid address
             return False
+
         return True
 
     def delete_keys_from_dict(self, dict_del, lst_keys):
         if dict_del is None:
             return dict_del
+
         dict_copy = {k: v for k, v in dict_del.items() if k not in lst_keys}
+
         for k, v in dict_copy.items():
             if isinstance(v, dict):
                 dict_copy[k] = self.delete_keys_from_dict(v, lst_keys)
+
         return dict_copy