Fixing bug 1437
[osm/RO.git] / RO-SDN-juniper_contrail / osm_rosdn_juniper_contrail / sdn_assist_juniper_contrail.py
index 2cd9fda..a1cc3de 100644 (file)
 #
 
 import logging
-import json
 import yaml
+import random
 
-from osm_ro.wim.sdnconn import SdnConnectorBase, SdnConnectorError
-from osm_rosdn_juniper_contrail.rest_lib import ContrailHttp
-from osm_rosdn_juniper_contrail.rest_lib import NotFound
+from osm_ro_plugin.sdnconn import SdnConnectorBase, SdnConnectorError
+from osm_rosdn_juniper_contrail.rest_lib import ContrailHttp
+from osm_rosdn_juniper_contrail.rest_lib import NotFound
 from osm_rosdn_juniper_contrail.rest_lib import DuplicateFound
 from osm_rosdn_juniper_contrail.rest_lib import HttpException
-
 from osm_rosdn_juniper_contrail.sdn_api import UnderlayApi
 
 
@@ -36,10 +35,11 @@ class JuniperContrail(SdnConnectorBase):
     whose API details can be found in these links:
 
     - https://github.com/tonyliu0592/contrail/wiki/API-Configuration-REST
-    - https://www.juniper.net/documentation/en_US/contrail19/information-products/pathway-pages/api-guide-1910/tutorial_with_rest.html
+    - https://www.juniper.net/documentation/en_US/contrail19/information-products/pathway-pages/api-guide-1910/
+      tutorial_with_rest.html
     - https://github.com/tonyliu0592/contrail-toolbox/blob/master/sriov/sriov
     """
-    _WIM_LOGGER = "openmano.sdnconn.junipercontrail"
+    _WIM_LOGGER = "ro.sdn.junipercontrail"
 
     def __init__(self, wim, wim_account, config=None, logger=None):
         """
@@ -62,7 +62,7 @@ class JuniperContrail(SdnConnectorBase):
                 datacenter_id           vim_account                 vim_account
                 id: (internal, do not use)
                 wim_id: (internal, do not use)
-        :param logger (logging.Logger): optional logger object. If none is passed 'openmano.sdn.sdnconn' is used.
+        :param logger (logging.Logger): optional logger object. If none is passed 'ro.sdn.sdnconn' is used.
         """
         self.logger = logger or logging.getLogger(self._WIM_LOGGER)
         self.logger.debug('wim: {}, wim_account: {}, config: {}'.format(wim, wim_account, config))
@@ -71,7 +71,7 @@ class JuniperContrail(SdnConnectorBase):
         self.user = wim_account.get("user")
         self.password = wim_account.get("password")
 
-        url = wim.get("wim_url") # underlay url
+        url = wim.get("wim_url")  # underlay url
         auth_url = None
         self.project = None
         self.domain = None
@@ -147,20 +147,20 @@ class JuniperContrail(SdnConnectorBase):
             Returns:
                 VNI
         """
-        #find unused VLAN ID
+        # find unused VLAN ID
         for vlanID_range in self.vni_range:
             try:
-                start_vni , end_vni = map(int, vlanID_range.replace(" ", "").split("-"))
-                for vni in range(start_vni, end_vni + 1):
+                start_vni, end_vni = map(int, vlanID_range.replace(" ", "").split("-"))
+                for i in range(start_vni, end_vni + 1):
+                    vni = random.randrange(start_vni, end_vni, 1)
                     if vni not in self.used_vni:
                         return vni
             except Exception as exp:
                 raise SdnConnectorError("Exception {} occurred while searching a free VNI.".format(exp))
         else:
-            raise SdnConnectorError("Unable to create the virtual network."\
-                " All VNI in VNI range {} are in use.".format(self.vni_range))
+            raise SdnConnectorError("Unable to create the virtual network."
+                                    " All VNI in VNI range {} are in use.".format(self.vni_range))
 
-    
     # Aux functions for testing
     def get_url(self):
         return self.url
@@ -214,7 +214,6 @@ class JuniperContrail(SdnConnectorBase):
             else:
                 num_vmis = len(vmi_list)
                 for vmi in vmi_list:
-                    uuid = vmi.get("uuid")
                     fqdn = vmi.get("to")
                     # check by name
                     if fqdn[2] == vmi_name:
@@ -304,7 +303,6 @@ class JuniperContrail(SdnConnectorBase):
             self.logger.error('Exception getting connectivity service info: %s', e, exc_info=True)
             return {'sdn_status': 'ERROR', 'error_msg': str(e)}
 
-
     def create_connectivity_service(self, service_type, connection_points, **kwargs):
         """
         Establish SDN/WAN connectivity between the endpoints
@@ -351,7 +349,8 @@ class JuniperContrail(SdnConnectorBase):
         #   1.3 If more than one, ERROR
         # Step 2. Modify the existing virtual network in the overlay controller
         #   2.1 Add VNI (VxLAN Network Identifier - one free from the provided range)
-        #   2.2 Add RouteTarget (RT) ('ASN:VNI', ASN = Autonomous System Number, provided as param or read from controller config)
+        #   2.2 Add RouteTarget (RT) ('ASN:VNI', ASN = Autonomous System Number, provided as param or read from
+        #   controller config)
         # Step 3. Create a virtual network in the underlay controller
         #   3.1 Create virtual network (name, VNI, RT)
         #      If the network already existed in the overlay controller, we should use the same name
@@ -367,38 +366,35 @@ class JuniperContrail(SdnConnectorBase):
             # Initialize data
             conn_info = None
 
-
             # 1 - Filter connection_points (transform cp to a dictionary with no duplicates)
             # This data will be returned even if no cp can be created if something is created
-            vlans = set()
             work_cps = {}
             for cp in connection_points:
                 switch_id = cp.get("service_endpoint_encapsulation_info").get("switch_dpid")
                 switch_port = cp.get("service_endpoint_encapsulation_info").get("switch_port")
                 service_endpoint_id = cp.get("service_endpoint_id")
-                vlans.add(cp.get("service_endpoint_encapsulation_info").get("vlan"))
                 cp_name = self.underlay_api.get_vpg_name(switch_id, switch_port)
                 add_cp = work_cps.get(cp_name)
                 if not add_cp:
-                    # add cp to dict
-                    service_endpoint_ids = []
-                    service_endpoint_ids.append(service_endpoint_id)
-                    add_cp = {"service_endpoint_ids": service_endpoint_ids,
-                              "switch_dpid": switch_id,
-                              "switch_port": switch_port}
-                    work_cps[cp_name] = add_cp
+                    # check cp has vlan
+                    vlan = cp.get("service_endpoint_encapsulation_info").get("vlan")
+                    if vlan:
+                        # add cp to dict
+                        service_endpoint_ids = []
+                        service_endpoint_ids.append(service_endpoint_id)
+                        add_cp = {"service_endpoint_ids": service_endpoint_ids,
+                                  "switch_dpid": switch_id,
+                                  "switch_port": switch_port,
+                                  "vlan": vlan}
+                        work_cps[cp_name] = add_cp
+                    else:
+                        self.logger.warning("cp service_endpoint_id : {} has no vlan, ignore".format(
+                            service_endpoint_id))
                 else:
                     # add service_endpoint_id to list
                     service_endpoint_ids = add_cp["service_endpoint_ids"]
                     service_endpoint_ids.append(service_endpoint_id)
 
-            # check vlan
-            if len(vlans) == 1:
-                vlan = vlans.pop()
-                self.logger.debug("Provided vlan: {}".format(vlan))
-            else:
-                raise SdnConnectorError("Provided more than one vlan")
-
             # 2 - Obtain free VNI
             vni = self._generate_vni()
             self.logger.debug("VNI: {}".format(vni))
@@ -424,16 +420,16 @@ class JuniperContrail(SdnConnectorBase):
             conn_info = {
                 "vnet": {
                     "uuid": vnet_id,
-                    "name": vnet_name,
-                    "vlan": vlan
+                    "name": vnet_name
                 },
-                "connection_points": work_cps # dict with port_name as key
+                "connection_points": work_cps  # dict with port_name as key
             }
 
             # 4 - Create a port for each endpoint
             for cp in work_cps.values():
                 switch_id = cp.get("switch_dpid")
                 switch_port = cp.get("switch_port")
+                vlan = cp.get("vlan")
                 vpg_id, vmi_id = self._create_port(switch_id, switch_port, vnet_name, vlan)
                 cp["vpg_id"] = vpg_id
                 cp["vmi_id"] = vmi_id
@@ -448,7 +444,6 @@ class JuniperContrail(SdnConnectorBase):
             else:
                 self.logger.error("Error creating connectivity service: {}".format(e), exc_info=True)
 
-
             # If nothing is created raise error else return what has been created and mask as error
             if not conn_info:
                 raise SdnConnectorError("Exception create connectivity service: {}".format(str(e)))
@@ -472,22 +467,21 @@ class JuniperContrail(SdnConnectorBase):
         :raises: SdnConnectorException: In case of error. The parameter http_code must be filled
         """
         self.logger.info("delete_connectivity_service vnet_name: {}, connection_points: {}".
-                          format(service_uuid, conn_info))
+                         format(service_uuid, conn_info))
 
         try:
             vnet_uuid = service_uuid
-            vnet_name = conn_info["vnet"]["name"]   # always should exist as the network is the first thing created
+            vnet_name = conn_info["vnet"]["name"]   # always should exist as the network is the first thing created
             work_cps = conn_info["connection_points"]
-            vlan = conn_info["vnet"]["vlan"]
 
             # 1: For each connection point delete vlan from vpg and it is is the
             # last one, delete vpg
             for cp in work_cps.values():
-                self._delete_port(cp.get("switch_dpid"), cp.get("switch_port"), vlan)
+                self._delete_port(cp.get("switch_dpid"), cp.get("switch_port"), cp.get("vlan"))
 
             # 2: Delete vnet
             self.underlay_api.delete_virtual_network(vnet_uuid)
-            self.logger.info("deleted connectivity_service vnet_name: {}, connection_points: {}".
+            self.logger.info("deleted connectivity_service vnet_uuid: {}, connection_points: {}".
                              format(service_uuid, conn_info))
         except SdnConnectorError:
             raise
@@ -498,20 +492,7 @@ class JuniperContrail(SdnConnectorBase):
             self.logger.error("Error deleting connectivity service: {}".format(e), exc_info=True)
             raise SdnConnectorError("Exception deleting connectivity service: {}".format(str(e)))
 
-    # Helper methods
-    @staticmethod
-    def _get_vlan(connection_points):
-        vlan = None
-        for cp in connection_points:
-            cp_vlan = cp.get("service_endpoint_encapsulation_info").get("vlan")
-            if not vlan:
-                vlan = cp_vlan
-            else:
-                if vlan != cp_vlan:
-                    raise SdnConnectorError("More that one cp provided")
-        return vlan
-
-    def edit_connectivity_service(self, service_uuid, conn_info = None, connection_points = None, **kwargs):
+    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
@@ -537,11 +518,10 @@ class JuniperContrail(SdnConnectorBase):
         # 3 - Delete unnecesary ports
         # 4 - Add new ports
         self.logger.info("edit connectivity service, service_uuid: {}, conn_info: {}, "
-                          "connection points: {} ".format(service_uuid, conn_info, connection_points))
+                         "connection points: {} ".format(service_uuid, conn_info, connection_points))
 
         # conn_info should always exist and have connection_points and vnet elements
         old_cp = conn_info.get("connection_points", {})
-        old_vlan = conn_info.get("vnet", {}).get("vlan")
 
         # Check if an element of old_cp is marked as error, in case it is delete it
         # Not return a new conn_info in this case because it is only partial information
@@ -552,6 +532,7 @@ class JuniperContrail(SdnConnectorBase):
                 if cp.get("sdn_status") == "ERROR":
                     switch_id = cp.get("switch_dpid")
                     switch_port = cp.get("switch_port")
+                    old_vlan = cp.get("vlan")
                     self._delete_port(switch_id, switch_port, old_vlan)
                     deleted_ports.append(self.underlay_api.get_vpg_name(switch_id, switch_port))
 
@@ -559,7 +540,7 @@ class JuniperContrail(SdnConnectorBase):
                 del old_cp[port]
 
             # Delete sdn_status and sdn_info if exists (possibly marked as error)
-            if conn_info.get("vnet",{}).get("sdn_status"):
+            if conn_info.get("vnet", {}).get("sdn_status"):
                 del conn_info["vnet"]["sdn_status"]
         except HttpException as e:
             self.logger.error("Error trying to delete old ports marked as error: {}".format(e))
@@ -575,35 +556,33 @@ class JuniperContrail(SdnConnectorBase):
 
             # Check and obtain what should be added and deleted, if there is an error here raise an exception
             try:
-                vlans = set()
                 work_cps = {}
                 for cp in connection_points:
                     switch_id = cp.get("service_endpoint_encapsulation_info").get("switch_dpid")
                     switch_port = cp.get("service_endpoint_encapsulation_info").get("switch_port")
                     service_endpoint_id = cp.get("service_endpoint_id")
-                    vlans.add(cp.get("service_endpoint_encapsulation_info").get("vlan"))
                     cp_name = self.underlay_api.get_vpg_name(switch_id, switch_port)
                     add_cp = work_cps.get(cp_name)
                     if not add_cp:
                         # add cp to dict
-                        service_endpoint_ids = []
-                        service_endpoint_ids.append(service_endpoint_id)
-                        add_cp = {"service_endpoint_ids": service_endpoint_ids,
-                                  "switch_dpid": switch_id,
-                                  "switch_port": switch_port}
-                        work_cps[cp_name] = add_cp
+                        # check cp has vlan
+                        vlan = cp.get("service_endpoint_encapsulation_info").get("vlan")
+                        if vlan:
+                            service_endpoint_ids = []
+                            service_endpoint_ids.append(service_endpoint_id)
+                            add_cp = {"service_endpoint_ids": service_endpoint_ids,
+                                      "switch_dpid": switch_id,
+                                      "switch_port": switch_port,
+                                      "vlan": vlan}
+                            work_cps[cp_name] = add_cp
+                        else:
+                            self.logger.warning("cp service_endpoint_id : {} has no vlan, ignore".
+                                                format(service_endpoint_id))
                     else:
                         # add service_endpoint_id to list
                         service_endpoint_ids = add_cp["service_endpoint_ids"]
                         service_endpoint_ids.append(service_endpoint_id)
 
-                # check vlan
-                if len(vlans) == 1:
-                    vlan = vlans.pop()
-                    self.logger.debug("Provided vlan: {}".format(vlan))
-                else:
-                    raise SdnConnectorError("Provided more than one vlan")
-
                 old_port_list = list(old_cp.keys())
                 port_list = list(work_cps.keys())
                 to_delete_ports = list(set(old_port_list) - set(port_list))
@@ -637,7 +616,7 @@ class JuniperContrail(SdnConnectorBase):
                         cp = conn_info_cp[port_name]
                         switch_id = cp.get("switch_dpid")
                         switch_port = cp.get("switch_port")
-                        self.logger.debug("delete port switch_id, switch_port: {}".format(switch_id, switch_port))
+                        self.logger.debug("delete port switch_id={}, switch_port={}".format(switch_id, switch_port))
                         self._delete_port(switch_id, switch_port, vlan)
                         deleted_ports.append(port_name)
 
@@ -650,7 +629,8 @@ class JuniperContrail(SdnConnectorBase):
                     if port_name in to_add_ports:
                         switch_id = cp.get("switch_dpid")
                         switch_port = cp.get("switch_port")
-                        self.logger.debug("add port switch_id, switch_port: {}".format(switch_id, switch_port))
+                        vlan = cp.get("vlan")
+                        self.logger.debug("add port switch_id={}, switch_port={}".format(switch_id, switch_port))
                         vpg_id, vmi_id = self._create_port(switch_id, switch_port, vnet_name, vlan)
                         cp_added = cp.copy()
                         cp_added["vpg_id"] = vpg_id
@@ -700,9 +680,9 @@ if __name__ == '__main__':
     log_formatter = logging.Formatter(log_format, datefmt='%Y-%m-%dT%H:%M:%S')
     handler = logging.StreamHandler()
     handler.setFormatter(log_formatter)
-    logger = logging.getLogger('openmano.sdnconn.junipercontrail')
-    #logger.setLevel(level=logging.ERROR)
-    #logger.setLevel(level=logging.INFO)
+    logger = logging.getLogger('ro.sdn.junipercontrail')
+    # logger.setLevel(level=logging.ERROR)
+    # logger.setLevel(level=logging.INFO)
     logger.setLevel(level=logging.DEBUG)
     logger.addHandler(handler)
 
@@ -722,167 +702,76 @@ if __name__ == '__main__':
         vni = juniper_contrail._generate_vni()
         juniper_contrail.used_vni.add(vni)
     print(juniper_contrail.used_vni)
-    juniper_contrail.used_vni.remove(1000003)
+    juniper_contrail.used_vni.remove(1000003)
     print(juniper_contrail.used_vni)
     for i in range(2):
         vni = juniper_contrail._generate_vni()
         juniper_contrail.used_vni.add(vni)
     print(juniper_contrail.used_vni)
+
     # 0. Check credentials
     print('0. Check credentials')
-    juniper_contrail.check_credentials()
-
-    underlay_url = juniper_contrail.get_url()
-    overlay_url = juniper_contrail.get_overlay_url()
-    # Generate VNI
-    for i in range(5):
-        vni = juniper_contrail._generate_vni()
-        juniper_contrail.used_vni.add(vni)
-    print(juniper_contrail.used_vni)
-    juniper_contrail.used_vni.remove(1000003)
-    print(juniper_contrail.used_vni)
-    for i in range(2):
-        vni = juniper_contrail._generate_vni()
-        juniper_contrail.used_vni.add(vni)
-    print(juniper_contrail.used_vni)
-    # 1. Read virtual networks from overlay controller
-    print('1. Read virtual networks from overlay controller')
-    try:
-        vnets = juniper_contrail._get_virtual_networks(overlay_url)
-        logger.debug(yaml.safe_dump(vnets, indent=4, default_flow_style=False))
-        print('OK')
-    except Exception as e:
-        logger.error('Exception reading virtual networks from overlay controller: %s', e)
-        print('FAILED')    
-    # 2. Read virtual networks from underlay controller
-    print('2. Read virtual networks from underlay controller')
-    vnets = juniper_contrail._get_virtual_networks(underlay_url)
-    logger.debug(yaml.safe_dump(vnets, indent=4, default_flow_style=False))
-    print('OK')
-    # 3. Delete virtual networks gerardoX from underlay controller
-    print('3. Delete virtual networks gerardoX from underlay controller')
-    for vn in vnets:
-        name = vn['fq_name'][2]
-        logger.debug('Virtual network: {}'.format(name))
-    for vn in vnets:
-        name = vn['fq_name'][2]
-        if 'gerardo' in name:
-            logger.info('Virtual Network *gerardo*: {}, {}'.format(name,vn['uuid']))
-            if name != "gerardo":
-                print('Deleting Virtual Network: {}, {}'.format(name,vn['uuid']))
-                logger.info('Deleting Virtual Network: {}, {}'.format(name,vn['uuid']))
-                juniper_contrail._delete_virtual_network(underlay_url, vn['uuid'])
-                print('OK')
-    # 4. Get virtual network (gerardo) from underlay controller
-    print('4. Get virtual network (gerardo) from underlay controller')
-    vnet1_info = juniper_contrail._get_virtual_network(underlay_url, 'c5d332f7-420a-4e2b-a7b1-b56a59f20c97')
-    print(yaml.safe_dump(vnet1_info, indent=4, default_flow_style=False))
-    print('OK')
-    # 5. Create virtual network in underlay controller
-    print('5. Create virtual network in underlay controller')
-    myname = 'gerardo4'
-    myvni = 20004
-    vnet2_id, _ = juniper_contrail._create_virtual_network(underlay_url, myname, myvni)
-    vnet2_info = juniper_contrail._get_virtual_network(underlay_url, vnet2_id)
-    print(yaml.safe_dump(vnet2_info, indent=4, default_flow_style=False))
-    print('OK')
-    # 6. Delete virtual network in underlay controller
-    print('6. Delete virtual network in underlay controller')
-    juniper_contrail._delete_virtual_network(underlay_url, vnet2_id)
-    print('OK')
-    # 7. Read previously deleted virtual network in underlay controller
-    print('7. Read previously deleted virtual network in underlay controller')
-    try:
-        vnet2_info = juniper_contrail._get_virtual_network(underlay_url, vnet2_id)
-        if vnet2_info:
-            print('FAILED. Network {} exists'.format(vnet2_id))
-        else:
-            print('OK. Network {} does not exist because it has been deleted'.format(vnet2_id))
-    except Exception as e:
-        logger.info('Exception reading virtual networks from overlay controller: %s', e)
-    exit(0)
-
-    # Test CRUD:
-    net_name = "gerardo"
-    net_vni = "2000"
-    net_vlan = "501"
-    switch_1 = "LEAF-2"
-    port_1 = "xe-0/0/18"
-    switch_2 = "LEAF-1"
-    port_2 = "xe-0/0/18"
-
-    # 1 - Create a new virtual network
-    vnet2_id, vnet2_created = juniper_contrail._create_virtual_network(underlay_url, net_name, net_vni)
-    print("Created virtual network:")
-    print(vnet2_id)
-    print(yaml.safe_dump(vnet2_created, indent=4, default_flow_style=False))
-    print("Get virtual network:")
-    vnet2_info = juniper_contrail._get_virtual_network(underlay_url, vnet2_id)
-    print(json.dumps(vnet2_info, indent=4))
-    print('OK')
-
-    # 2 - Create a new virtual port group
-    vpg_id, vpg_info = juniper_contrail._create_vpg(underlay_url, switch_1, port_1, net_name, net_vlan)
-    print("Created virtual port group:")
-    print(vpg_id)
-    print(json.dumps(vpg_info, indent=4))
-
-    print("Get virtual network:")
-    vnet2_info = juniper_contrail._get_virtual_network(underlay_url, vnet2_id)
-    print(yaml.safe_dump(vnet2_info, indent=4, default_flow_style=False))
-    print('OK')
-
-    # 3 - Create a new virtual machine interface
-    vmi_id, vmi_info = juniper_contrail._create_vmi(underlay_url, switch_1, port_1, net_name, net_vlan)
-    print("Created virtual machine interface:")
-    print(vmi_id)
-    print(yaml.safe_dump(vmi_info, indent=4, default_flow_style=False))
-
-    # 4 - Create a second virtual port group
-    # 5 - Create a second virtual machine interface
-
-    ### Test rapido de modificación de requests:
-    # Ver que metodos siguen funcionando y cuales no e irlos corrigiendo
-
-    """
-    vnets = juniper_contrail._get_virtual_networks(underlay_url)
-    logger.debug("Virtual networks:")
-    logger.debug(json.dumps(vnets, indent=2))
-
-    vpgs = juniper_contrail._get_vpgs(underlay_url)
-    logger.debug("Virtual port groups:")
-    logger.debug(json.dumps(vpgs, indent=2))
-    """
-    # Get by uuid
-
-    """
-    # 3 - Get vmi
-    vmi_uuid = "dbfd2099-b895-459e-98af-882d77d968c1"
-    vmi = juniper_contrail._get_vmi(underlay_url, vmi_uuid)
-    logger.debug("Virtual machine interface:")
-    logger.debug(json.dumps(vmi, indent=2))
-
-    # Delete vmi    
-    logger.debug("Delete vmi")
-    juniper_contrail._delete_vmi(underlay_url, vmi_uuid)
-    """
-
-    """
-    # 2 - Get vpg
-    vpg_uuid = "85156474-d1a5-44c0-9d8b-8f690f39d27e"
-    vpg = juniper_contrail._get_vpg(underlay_url, vpg_uuid)
-    logger.debug("Virtual port group:")
-    logger.debug(json.dumps(vpg, indent=2))
-    # Delete vpg
-    vpg = juniper_contrail._delete_vpg(underlay_url, vpg_uuid)
-    """
-
-    # 1 - Obtain virtual network
-    """
-    vnet_uuid = "68457d61-6558-4d38-a03d-369a9de803ea"
-    vnet = juniper_contrail._get_virtual_network(underlay_url, vnet_uuid)
-    logger.debug("Virtual network:")
-    logger.debug(json.dumps(vnet, indent=2))
-    # Delete virtual network
-    juniper_contrail._delete_virtual_network(underlay_url, vnet_uuid)
-    """
+    # juniper_contrail.check_credentials()
+
+    # 1 - Create and delete connectivity service
+    conn_point_0 = {
+        "service_endpoint_id": "0000:83:11.4",
+        "service_endpoint_encapsulation_type": "dot1q",
+        "service_endpoint_encapsulation_info": {
+            "switch_dpid": "LEAF-1",
+            "switch_port": "xe-0/0/17",
+            "vlan": "501"
+        }
+    }
+    conn_point_1 = {
+        "service_endpoint_id": "0000:81:10.3",
+        "service_endpoint_encapsulation_type": "dot1q",
+        "service_endpoint_encapsulation_info": {
+            "switch_dpid": "LEAF-2",
+            "switch_port": "xe-0/0/16",
+            "vlan": "501"
+        }
+    }
+    conn_point_2 = {
+        "service_endpoint_id": "0000:08:11.7",
+        "service_endpoint_encapsulation_type": "dot1q",
+        "service_endpoint_encapsulation_info": {
+            "switch_dpid": "LEAF-2",
+            "switch_port": "xe-0/0/16",
+            "vlan": "502"
+        }
+    }
+    conn_point_3 = {
+        "service_endpoint_id": "0000:83:10.4",
+        "service_endpoint_encapsulation_type": "dot1q",
+        "service_endpoint_encapsulation_info": {
+            "switch_dpid": "LEAF-1",
+            "switch_port": "xe-0/0/17",
+            "vlan": "502"
+        }
+    }
+
+    # 1 - Define connection points
+    logger.debug("create first connection service")
+    print("Create connectivity service")
+    connection_points = [conn_point_0, conn_point_1]
+    service_id, conn_info = juniper_contrail.create_connectivity_service("ELAN", connection_points)
+    logger.info("Created connectivity service 1")
+    logger.info(service_id)
+    logger.info(yaml.safe_dump(conn_info, indent=4, default_flow_style=False))
+
+    logger.debug("create second connection service")
+    print("Create connectivity service")
+    connection_points = [conn_point_2, conn_point_3]
+    service_id2, conn_info2 = juniper_contrail.create_connectivity_service("ELAN", connection_points)
+    logger.info("Created connectivity service 2")
+    logger.info(service_id2)
+    logger.info(yaml.safe_dump(conn_info2, indent=4, default_flow_style=False))
+
+    logger.debug("Delete connectivity service 1")
+    juniper_contrail.delete_connectivity_service(service_id, conn_info)
+    logger.debug("Delete Ok")
+
+    logger.debug("Delete connectivity service 2")
+    juniper_contrail.delete_connectivity_service(service_id2, conn_info2)
+    logger.debug("Delete Ok")