Fix Bug 1030 checking that task and note exists
[osm/RO.git] / RO-SDN-arista / osm_rosdn_arista / wimconn_arista.py
index b0e5b13..67db739 100644 (file)
@@ -38,6 +38,7 @@ import difflib
 import logging
 import uuid
 from enum import Enum
+from requests import RequestException
 
 from cvprac.cvp_client import CvpClient
 from cvprac.cvp_client_errors import CvpLoginError,  CvpSessionLogOutError, CvpApiError
@@ -117,6 +118,7 @@ class AristaSdnConnector(SdnConnectorBase):
     __VLAN_PARAM = "vlan"
     __VNI_PARAM = "vni"
     __SEPARATOR = '_'
+    __MANAGED_BY_OSM = '## Managed by OSM '
     __OSM_PREFIX = "osm_"
     __OSM_METADATA = "OSM_metadata"
     __METADATA_PREFIX = '!## Service'
@@ -405,7 +407,12 @@ class AristaSdnConnector(SdnConnectorBase):
             for s in self.s_api:
                 if (len(cls_perSw[s]) > 0):
                     for cl in cls_perSw[s]:
-                        if len(cls_perSw[s][0]['config']) == 0:
+                        # 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']):
                             continue
                         note = cl['note']
                         t_id = note.split(self.__SEPARATOR)[1]
@@ -497,6 +504,8 @@ class AristaSdnConnector(SdnConnectorBase):
             Provide the parameter http_code
         """
         try:
+            self.logger.debug("invoked create_connectivity_service '{}' ports: {}".
+                              format(service_type, connection_points))
             self.__get_Connection()
             self.__check_service(service_type,
                                  connection_points,
@@ -558,6 +567,7 @@ class AristaSdnConnector(SdnConnectorBase):
             vlan_processed = False
             vlan_id = ''
             i = 0
+            processed_connection_points = []
             for cp in connection_points:
                 i += 1
                 encap_info = cp.get(self.__ENCAPSULATION_INFO_PARAM)
@@ -584,26 +594,33 @@ class AristaSdnConnector(SdnConnectorBase):
                 if not switch_id:
                     point_mac = encap_info.get(self.__MAC_PARAM)
                     switches = self.__lldp_find_neighbor("chassisId", point_mac)
-
-                    if len(switches) == 0:
-                        raise SdnConnectorError(message="Connection point MAC address {} not found in the switches".format(point_mac),
-                                                http_code=406)
                     self.logger.debug("Found connection point for MAC {}: {}".
                                       format(point_mac, switches))
-                    port_channel = self.__get_switch_po(switch['name'],
-                                                        switch['interface'])
-                    if len(port_channel) > 0:
-                        interface = port_channel[0]
-                    else:
-                        interface = switch['interface']
                 else:
                     interface = encap_info.get(self.__SW_PORT_PARAM)
                     switches = [{'name': switch_id, 'interface': interface}]
 
+                if len(switches) == 0:
+                    raise SdnConnectorError(message="Connection point MAC address {} not found in the switches".format(point_mac),
+                                            http_code=406)
+
+                # 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 switch_id:
+                        port_channel = self.__get_switch_po(switch['name'],
+                                                            switch['interface'])
+                        if len(port_channel) > 0:
+                            interface = port_channel[0]
+                        else:
+                            interface = switch['interface']
                     if not interface:
                         raise SdnConnectorError(message="Connection point switch port empty for switch_dpid {}".format(switch_id),
                                                 http_code=406)
-                for switch in switches:
                     # it should be only one switch where the mac is attached
                     if encap_type == 'dot1q':
                         # SRIOV configLet for Leaf switch mac's attached to
@@ -736,9 +753,10 @@ class AristaSdnConnector(SdnConnectorBase):
                 for t_id in res[1]['tasks']:
                     tasks[t_id] = {'workOrderId': t_id}
                     if not toDelete_in_cvp:
-                        note_msg = "## Managed by OSM {}{}{}##".format(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)
@@ -897,6 +915,10 @@ class AristaSdnConnector(SdnConnectorBase):
             else:
                 changed = True
                 if 'taskIds' in str(dev_action):
+                    # Fix 1030 SDN-ARISTA Key error note when deploy a NS
+                    if not dev_action['data']['taskIds']:
+                        raise Exception("No taskIds found: Device {} Configlets couldnot be updated".format(
+                                        up_device['hostname']))
                     for taskId in dev_action['data']['taskIds']:
                         updated.append({up_device['hostname']:
                                         "Configlets-{}".format(
@@ -1200,7 +1222,8 @@ class AristaSdnConnector(SdnConnectorBase):
             SdnConnectorError: In case of error.
         """
         try:
-            self.logger.debug('invoked edit_connectivity_service for service {}'.format(service_uuid))
+            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',
@@ -1408,7 +1431,8 @@ class AristaSdnConnector(SdnConnectorBase):
             if self.client is None:
                 self.client = self.__connect()
             self.client.api.get_cvp_info()
-        except CvpSessionLogOutError:
+        except (CvpSessionLogOutError, RequestException) as e:
+            self.logger.debug("Connection error '{}'. Reconnecting".format(e))
             self.client = self.__connect()
             self.client.api.get_cvp_info()
 
@@ -1426,7 +1450,7 @@ class AristaSdnConnector(SdnConnectorBase):
         else:
             port = 443
 
-        client.connect([host],        
+        client.connect([host],
                        self.__user,
                        self.__passwd,
                        protocol=protocol or "https",