Support for ELAN, ETREE, and VNoD Global Service

Change-Id: Iea1ee5b5b9224404a16bc9b88bc082719f75d10f
diff --git a/xos/synchronizer/invokers/invokerfactory.py b/xos/synchronizer/invokers/invokerfactory.py
index 786f99d..b3628fe 100644
--- a/xos/synchronizer/invokers/invokerfactory.py
+++ b/xos/synchronizer/invokers/invokerfactory.py
@@ -2,6 +2,9 @@
 from synchronizers.metronetwork.invokers.networkmultipointtomultipointinvoker import NetworkMultipointToMultipointInvoker
 from synchronizers.metronetwork.invokers.networkedgetoedgepointinvoker import NetworkEdgeToEdgePointInvoker
 from synchronizers.metronetwork.invokers.networkedgetomultipointinvoker import NetworkEdgeToMultipointInvoker
+from synchronizers.metronetwork.invokers.servicespokeinvoker import ServiceSpokeInvoker
+from synchronizers.metronetwork.invokers.vnodglobalserviceinvoker import VnodGlobalServiceInvoker
+from synchronizers.metronetwork.invokers.remoteportinvoker import RemotePortInvoker
 
 
 class InvokerFactory(object):
@@ -16,5 +19,11 @@
             return NetworkEdgeToEdgePointInvoker()
         elif isinstance(obj, NetworkEdgeToMultipointConnection):
             return NetworkEdgeToMultipointInvoker()
+        elif isinstance(obj, ServiceSpoke):
+            return ServiceSpokeInvoker()
+        elif isinstance(obj, VnodGlobalService):
+            return VnodGlobalServiceInvoker()
+        elif isinstance(obj, RemotePort):
+            return RemotePortInvoker()
         else:
             return None
diff --git a/xos/synchronizer/invokers/networkedgetoedgepointinvoker.py b/xos/synchronizer/invokers/networkedgetoedgepointinvoker.py
index ebc4d12..2c30d79 100644
--- a/xos/synchronizer/invokers/networkedgetoedgepointinvoker.py
+++ b/xos/synchronizer/invokers/networkedgetoedgepointinvoker.py
@@ -17,10 +17,11 @@
     def presave(self, obj):
         # Now that the Ports are created - get a proper reference to them and update the
         # src and dst fields
-        uni1port = NetworkEdgePort.objects.get(pid=obj.uni1_createbuffer)
-        uni2port = NetworkEdgePort.objects.get(pid=obj.uni2_createbuffer)
-        obj.uni1 = uni1port
-        obj.uni2 = uni2port
+        if hasattr(obj, 'uni1_createbuffer'):
+            uni1port = NetworkEdgePort.objects.get(pid=obj.uni1_createbuffer)
+            uni2port = NetworkEdgePort.objects.get(pid=obj.uni2_createbuffer)
+            obj.uni1 = uni1port
+            obj.uni2 = uni2port
 
     # Method for handline post save semantics
     #      content here would be model specific but could include handling Many-to-Many relationship
diff --git a/xos/synchronizer/invokers/networkedgetomultipointinvoker.py b/xos/synchronizer/invokers/networkedgetomultipointinvoker.py
index a0b7ffd..9b8e88b 100644
--- a/xos/synchronizer/invokers/networkedgetomultipointinvoker.py
+++ b/xos/synchronizer/invokers/networkedgetomultipointinvoker.py
@@ -17,8 +17,9 @@
     def presave(self, obj):
         # Now that the Ports are created - get a proper reference to them and update the
         # root field
-        rootEdgePort = NetworkEdgePort.objects.get(pid=obj.root_createbuffer)
-        obj.root = rootEdgePort
+        if hasattr(obj, 'root_createbuffer'):
+            rootEdgePort = NetworkEdgePort.objects.get(pid=obj.root_createbuffer)
+            obj.root = rootEdgePort
 
 
     # Method for handline post save semantics
@@ -37,9 +38,10 @@
         # called 'eps' that just containts a reference to a bunch of NetworkEdgePorts
         #
         #
-        scratchpad = json.loads(obj.eps_createbuffer)
-        eps = scratchpad['eps']
+        if hasattr(obj, 'eps_createbuffer'):
+            scratchpad = json.loads(obj.eps_createbuffer)
+            eps = scratchpad['eps']
 
-        for ep in eps:
-            port = NetworkEdgePort.objects.get(pid=ep)
-            obj.eps.add(port)
+            for ep in eps:
+                port = NetworkEdgePort.objects.get(pid=ep)
+                obj.eps.add(port)
diff --git a/xos/synchronizer/invokers/networkmultipointtomultipointinvoker.py b/xos/synchronizer/invokers/networkmultipointtomultipointinvoker.py
index 78b617c..6b2ab42 100644
--- a/xos/synchronizer/invokers/networkmultipointtomultipointinvoker.py
+++ b/xos/synchronizer/invokers/networkmultipointtomultipointinvoker.py
@@ -34,9 +34,10 @@
         # called 'eps' that just containts a reference to a bunch of NetworkEdgePorts
         #
         #
-        scratchpad = json.loads(obj.eps_createbuffer)
-        eps = scratchpad['eps']
+        if hasattr(obj, 'eps_createbuffer'):
+            scratchpad = json.loads(obj.eps_createbuffer)
+            eps = scratchpad['eps']
 
-        for ep in eps:
-            port = NetworkEdgePort.objects.get(pid=ep)
-            obj.eps.add(port)
+            for ep in eps:
+                port = NetworkEdgePort.objects.get(pid=ep)
+                obj.eps.add(port)
diff --git a/xos/synchronizer/invokers/remoteportinvoker.py b/xos/synchronizer/invokers/remoteportinvoker.py
new file mode 100644
index 0000000..1061dc4
--- /dev/null
+++ b/xos/synchronizer/invokers/remoteportinvoker.py
@@ -0,0 +1,35 @@
+import json
+from synchronizers.metronetwork.invokers.invoker import Invoker
+from core.models import Site
+from services.metronetwork.models import NetworkEdgePort
+
+class RemotePortInvoker(Invoker):
+    def __init__(self, **args):
+        pass
+
+    # Method for handline pre save semantics
+    #      content here would be model specific but could include handling Many-to-Many relationship
+    #      creation - which must occur post save
+    #
+    # obj     - Whatever obj was just saved
+    # returns - None - this is a pure invoke() call, return type is None
+    #
+    def presave(self, obj):
+        # Now that the Site and EdgePorts are created set the foreign keys
+        if hasattr(obj, 'sitename'):
+            site = Site.objects.get(login_base=obj.sitename)
+            obj.remoteportsite = site
+
+        if hasattr(obj, 'edgeportname'):
+            edgeport = NetworkEdgePort.objects.get(pid=obj.edgeportname)
+            obj.edgeport = edgeport
+
+    # Method for handline post save semantics
+    #      content here would be model specific but could include handling Many-to-Many relationship
+    #      creation - which must occur post save
+    #
+    # obj     - Whatever obj was just saved
+    # returns - N/A - this is a pure invoke() call
+    #
+    def postsave(self, obj):
+        pass
\ No newline at end of file
diff --git a/xos/synchronizer/invokers/servicespokeinvoker.py b/xos/synchronizer/invokers/servicespokeinvoker.py
new file mode 100644
index 0000000..8470cf5
--- /dev/null
+++ b/xos/synchronizer/invokers/servicespokeinvoker.py
@@ -0,0 +1,37 @@
+import json
+from synchronizers.metronetwork.invokers.invoker import Invoker
+from core.models import Site
+from services.metronetwork.models import RemotePort
+
+
+class ServiceSpokeInvoker(Invoker):
+    def __init__(self, **args):
+        pass
+
+    # Method for handline pre save semantics
+    #      content here would be model specific but could include handling Many-to-Many relationship
+    #      creation - which must occur post save
+    #
+    # obj     - Whatever obj was just saved
+    # returns - None - this is a pure invoke() call, return type is None
+    #
+    def presave(self, obj):
+        # Now that the Ports are created - get a proper reference to them and update the
+        # src and dst fields
+        if hasattr(obj, 'sitename'):
+            site = Site.objects.get(login_base=obj.sitename)
+            obj.vnodlocalsite = site
+
+        if hasattr(obj, 'remoteportname'):
+            remoteport = RemotePort.objects.get(name=obj.remoteportname)
+            obj.vnodlocalport = remoteport
+
+    # Method for handline post save semantics
+    #      content here would be model specific but could include handling Many-to-Many relationship
+    #      creation - which must occur post save
+    #
+    # obj     - Whatever obj was just saved
+    # returns - N/A - this is a pure invoke() call
+    #
+    def postsave(self, obj):
+        pass
\ No newline at end of file
diff --git a/xos/synchronizer/invokers/vnodglobalserviceinvoker.py b/xos/synchronizer/invokers/vnodglobalserviceinvoker.py
new file mode 100644
index 0000000..a313171
--- /dev/null
+++ b/xos/synchronizer/invokers/vnodglobalserviceinvoker.py
@@ -0,0 +1,50 @@
+import json
+from synchronizers.metronetwork.invokers.invoker import Invoker
+from services.metronetwork.models import ServiceSpoke
+from services.metronetwork.models import BandwidthProfile
+from services.metronetwork.models import NetworkEdgeToEdgePointConnection
+
+class VnodGlobalServiceInvoker(Invoker):
+
+    def __init__(self, **args):
+        pass
+
+    # Method for handline pre save semantics
+    #      content here would be model specific but could include handling Many-to-Many relationship
+    #      creation - which must occur post save
+    #
+    # obj     - Whatever obj was just saved
+    # returns - None - this is a pure invoke() call, return type is None
+    #
+    def presave(self, obj):
+
+        if hasattr(obj, 'bwpname'):
+            bwprofile = BandwidthProfile.objects.get(name=obj.bwpname)
+            obj.bandwidthProfile = bwprofile
+
+        if hasattr(obj, 'pointtopointsid'):
+            connection = NetworkEdgeToEdgePointConnection.objects.get(sid=obj.pointtopointsid)
+            obj.metronetworkpointtopoint = connection
+
+    # Method for handline post save semantics
+    #      content here would be model specific but could include handling Many-to-Many relationship
+    #      creation - which must occur post save
+    #
+    # obj     - Whatever obj was just saved
+    # returns - N/A - this is a pure invoke() call
+    #
+    def postsave(self, obj):
+        #
+        # Ok - we need to handle the multipoint many-to-many relationships in here
+        #
+        # By design convnetion we will look for them in the 'backend_register' object field
+        # this is a json field that is general purpose - we will expect to find a JSON array
+        # called 'eps' that just containts a reference to a bunch of NetworkEdgePorts
+        #
+        if hasattr(obj, 'spokes_createbuffer'):
+            scratchpad = json.loads(obj.spokes_createbuffer)
+            spokes = scratchpad['spokes']
+
+            for spokeid in spokes:
+                spoke = ServiceSpoke.objects.get(name=spokeid)
+                obj.spokes.add(spoke)
diff --git a/xos/synchronizer/manifest b/xos/synchronizer/manifest
index 98cb0d9..03f1088 100644
--- a/xos/synchronizer/manifest
+++ b/xos/synchronizer/manifest
@@ -6,15 +6,18 @@
 providers/providerfactory.py
 providers/__init__.py
 providers/metronetworkprovider.py
-invokers/invoker.py
-invokers/invokerfactory.py
-invokers/networkedgetoedgepointinvoker.py
-invokers/networkedgetomultipointinvoker.py
-invokers/networkmultipointtomultipointinvoker.py
-invokers/__init__.py
 run_devel.sh
 metronetwork-synchronizer-devel.py
 manifest
 steps/sync_metronetworkservice.py
+invokers/servicespokeinvoker.py
+invokers/networkedgetoedgepointinvoker.py
+invokers/vnodglobalserviceinvoker.py
+invokers/networkmultipointtomultipointinvoker.py
+invokers/__init__.py
+invokers/invoker.py
+invokers/networkedgetomultipointinvoker.py
+invokers/invokerfactory.py
+invokers/remoteportinvoker.py
 run.sh
 metronetwork_synchronizer_config
diff --git a/xos/synchronizer/providers/metronetworkrestprovider.py b/xos/synchronizer/providers/metronetworkrestprovider.py
index 1e00a90..2cb03ab 100644
--- a/xos/synchronizer/providers/metronetworkrestprovider.py
+++ b/xos/synchronizer/providers/metronetworkrestprovider.py
@@ -55,10 +55,171 @@
         else:

             raise Exception("OnosApiError: get_network_ports()")

 

+    def get_network_ports(self):

+

+        objs = []

+

+        restCtrlUrl = self.networkdevice.restCtrlUrl

+        username = self.networkdevice.username

+        password = self.networkdevice.password

+

+        resp = requests.get("{}/mef-sca-api/SCA_ETH_FPP_UNI_N".format(restCtrlUrl),

+                            auth=HTTPBasicAuth(username, password))

+

+        if resp.status_code == 200:

+            for uni in resp.json():

+                hostname = uni['transportPort']['Hostname']

+                port = uni['transportPort']['Port']

+

+                # Default values

+                bwpCfgCbs = 0

+                bwpCfgEbs = 0

+                bwpCfgCir = 0

+                bwpCfgEir = 0

+

+                if 'interfaceCfgIngressBwp' in uni:

+                    bwpCfgCbs = uni['interfaceCfgIngressBwp']['bwpCfgCbs']

+                    bwpCfgEbs = uni['interfaceCfgIngressBwp']['bwpCfgEbs']

+                    bwpCfgCir = uni['interfaceCfgIngressBwp']['bwpCfgCir']

+                    bwpCfgEir = uni['interfaceCfgIngressBwp']['bwpCfgEir']

+

+                uniPort = NetworkEdgePort()

+                uniPort.element = self.networkdevice

+                uniPort.pid = "{}.{}/{}".format(self.networkdevice.id, hostname, port)

+                uniPort.bwpCfgCbs = bwpCfgCbs

+                uniPort.bwpCfgEbs = bwpCfgEbs

+                uniPort.bwpCfgCir = bwpCfgCir

+                uniPort.bwpCfgEir = bwpCfgEir

+

+                objs.append(uniPort)

+

+            return objs

+

+        else:

+            raise Exception("OnosApiError: get_network_ports()")

+

+    def get_network_eline_link(self, networkDevice, evc):

+

+        sid = evc['id']

+        uni1 = evc['SCA_ETH_Flow_Points'][0]

+        hostname = uni1['scaEthFppUniN']['transportPort']['Hostname']

+        port = uni1['scaEthFppUniN']['transportPort']['Port']

+

+        edgePort1 = NetworkEdgePort()

+        edgePort1.element = networkDevice

+        edgePort1.pid = "{}.{}/{}".format(networkDevice.id, hostname, port)

+

+        if 'interfaceCfgIngressBwp' in uni1['scaEthFppUniN']:

+            edgePort1.bwpCfgCbs = uni1['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCbs']

+            edgePort1.bwpCfgEbs = uni1['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEbs']

+            edgePort1.bwpCfgCir = uni1['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCir']

+            edgePort1.bwpCfgEir = uni1['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEir']

+

+        uni2 = evc['SCA_ETH_Flow_Points'][1]

+        hostname = uni2['scaEthFppUniN']['transportPort']['Hostname']

+        port = uni2['scaEthFppUniN']['transportPort']['Port']

+

+        edgePort2 = NetworkEdgePort()

+        edgePort2.element = networkDevice

+        edgePort2.pid = "{}.{}/{}".format(networkDevice.id, hostname, port)

+

+        if 'interfaceCfgIngressBwp' in uni1['scaEthFppUniN']:

+            edgePort2.bwpCfgCbs = uni2['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCbs']

+            edgePort2.bwpCfgEbs = uni2['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEbs']

+            edgePort2.bwpCfgCir = uni2['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCir']

+            edgePort2.bwpCfgEir = uni2['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEir']

+

+        edgeToEdgeConnectivity = NetworkEdgeToEdgePointConnection()

+        edgeToEdgeConnectivity.sid = sid

+        edgeToEdgeConnectivity.type = "Point_To_Point"

+        edgeToEdgeConnectivity.uni1 = edgePort1

+        edgeToEdgeConnectivity.uni2 = edgePort2

+        edgeToEdgeConnectivity.operstate = "active"

+        edgeToEdgeConnectivity.adminstate = "enabled"

+

+        return(edgeToEdgeConnectivity)

+

+    def get_network_elan_link(self, networkDevice, evc):

+

+        sid = evc['id']

+        eps = []

+

+        for ep in evc['SCA_ETH_Flow_Points']:

+            hostname = ep['scaEthFppUniN']['transportPort']['Hostname']

+            port = ep['scaEthFppUniN']['transportPort']['Port']

+

+            edgePort = NetworkEdgePort()

+            edgePort.element = networkDevice

+            edgePort.pid = "{}.{}/{}".format(networkDevice.id, hostname, port)

+

+            if 'interfaceCfgIngressBwp' in ep['scaEthFppUniN']:

+                edgePort.bwpCfgCbs = ep['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCbs']

+                edgePort.bwpCfgEbs = ep['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEbs']

+                edgePort.bwpCfgCir = ep['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCir']

+                edgePort.bwpCfgEir = ep['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEir']

+

+            eps.append(edgePort)

+

+        multipointToMultipointConnectivity = NetworkMultipointToMultipointConnection()

+        multipointToMultipointConnectivity.sid = sid

+        multipointToMultipointConnectivity.type = "Multipoint_To_Multipoint"

+        multipointToMultipointConnectivity.eps = eps

+        multipointToMultipointConnectivity.operstate = "active"

+        multipointToMultipointConnectivity.adminstate = "enabled"

+

+        return(multipointToMultipointConnectivity)

+

+    def get_network_etree_link(self, networkDevice, evc):

+

+        sid = evc['id']

+        eps = []

+

+        root = evc['SCA_ETH_Flow_Points'][0]

+        hostname = root['scaEthFppUniN']['transportPort']['Hostname']

+        port = root['scaEthFppUniN']['transportPort']['Port']

+

+        edgePort = NetworkEdgePort()

+        edgePort.element = networkDevice

+        edgePort.pid = "{}.{}/{}".format(networkDevice.id, hostname, port)

+

+        if 'interfaceCfgIngressBwp' in root['scaEthFppUniN']:

+            edgePort.bwpCfgCbs = root['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCbs']

+            edgePort.bwpCfgEbs = root['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEbs']

+            edgePort.bwpCfgCir = root['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCir']

+            edgePort.bwpCfgEir = root['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEir']

+

+        edgeToMultipointConnectivity = NetworkEdgeToMultipointConnection()

+        edgeToMultipointConnectivity.sid = sid

+        edgeToMultipointConnectivity.type = "Root_Multipoint"

+        edgeToMultipointConnectivity.root = edgePort

+

+        for ep in evc['SCA_ETH_Flow_Points'][1:]:

+            hostname = ep['scaEthFppUniN']['transportPort']['Hostname']

+            port = ep['scaEthFppUniN']['transportPort']['Port']

+

+            edgePort = NetworkEdgePort()

+            edgePort.element = networkDevice

+            edgePort.pid = "{}.{}/{}".format(networkDevice.id, hostname, port)

+

+            if 'interfaceCfgIngressBwp' in ep['scaEthFppUniN']:

+                edgePort.bwpCfgCbs = ep['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCbs']

+                edgePort.bwpCfgEbs = ep['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEbs']

+                edgePort.bwpCfgCir = ep['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCir']

+                edgePort.bwpCfgEir = ep['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEir']

+

+            eps.append(edgePort)

+

+        edgeToMultipointConnectivity.eps = eps

+        edgeToMultipointConnectivity.operstate = "active"

+        edgeToMultipointConnectivity.adminstate = "enabled"

+

+        return(edgeToMultipointConnectivity)

+

     def get_network_links(self):

 

         objs = []

 

+        networkDevice = self.networkdevice

         restCtrlUrl = self.networkdevice.restCtrlUrl

         username = self.networkdevice.username

         password = self.networkdevice.password

@@ -68,69 +229,24 @@
 

         if resp.status_code == 200:

             for evc in resp.json():

-                id = evc['id']

                 evcServiceType = evc['evcServiceType']

-

                 if (evcServiceType == "Point_To_Point"):

-                    uni1 = evc['SCA_ETH_Flow_Points'][0]

-                    hostname = uni1['scaEthFppUniN']['transportPort']['Hostname']

-                    port = uni1['scaEthFppUniN']['transportPort']['Port']

-

-                    if 'interfaceCfgIngressBwp' in uni1['scaEthFppUniN']:

-                        bwpCfgCbs = uni1['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCbs']

-                        bwpCfgEbs = uni1['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEbs']

-                        bwpCfgCir = uni1['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCir']

-                        bwpCfgEir = uni1['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEir']

-

-                    edgePort1 = NetworkEdgePort()

-                    edgePort1.element = self.networkdevice

-                    edgePort1.pid = "{}.{}/{}".format(self.networkdevice.id, hostname, port)

-                    edgePort1.bwpCfgCbs = bwpCfgCbs

-                    edgePort1.bwpCfgEbs = bwpCfgEbs

-                    edgePort1.bwpCfgCir = bwpCfgCir

-                    edgePort1.bwpCfgEir = bwpCfgEir

-

-                    uni2 = evc['SCA_ETH_Flow_Points'][1]

-                    hostname = uni2['scaEthFppUniN']['transportPort']['Hostname']

-                    port = uni2['scaEthFppUniN']['transportPort']['Port']

-

-                    if 'interfaceCfgIngressBwp' in uni1['scaEthFppUniN']:

-                        bwpCfgCbs = uni2['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCbs']

-                        bwpCfgEbs = uni2['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEbs']

-                        bwpCfgCir = uni2['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgCir']

-                        bwpCfgEir = uni2['scaEthFppUniN']['interfaceCfgIngressBwp']['bwpCfgEir']

-

-                    edgePort2 = NetworkEdgePort()

-                    edgePort2.element = self.networkdevice

-                    edgePort2.pid = "{}.{}/{}".format(self.networkdevice.id, hostname, port)

-                    edgePort2.bwpCfgCbs = bwpCfgCbs

-                    edgePort2.bwpCfgEbs = bwpCfgEbs

-                    edgePort2.bwpCfgCir = bwpCfgCir

-                    edgePort2.bwpCfgEir = bwpCfgEir

-

-                edgeToEdgeConnectivity = NetworkEdgeToEdgePointConnection()

-                edgeToEdgeConnectivity.sid = id

-                edgeToEdgeConnectivity.type = evcServiceType

-                edgeToEdgeConnectivity.uni1 = edgePort1

-                edgeToEdgeConnectivity.uni2 = edgePort2

-                edgeToEdgeConnectivity.operstate = "active"

-                edgeToEdgeConnectivity.adminstate = "enabled"

-

-                objs.append(edgeToEdgeConnectivity)

-

-            return objs

-

+                    objs.append(self.get_network_eline_link(networkDevice, evc))

+                elif (evcServiceType == "Multipoint_To_Multipoint"):

+                    objs.append(self.get_network_elan_link(networkDevice, evc))

+                elif (evcServiceType == "Root_Multipoint"):

+                    objs.append(self.get_network_etree_link(networkDevice, evc))

+                else:

+                    raise Exception("OnosApiError: get_network_links() - unknown link type")

         else:

             raise Exception("OnosApiError: get_network_links()")

 

-    def create_point_to_point_connectivity(self, obj):

+        return objs

 

-        restCtrlUrl = self.networkdevice.restCtrlUrl

-        username = self.networkdevice.username

-        password = self.networkdevice.password

+    def create_point_to_point_connectivity_json_data(self, obj):

 

-        evcServiceType = obj.type

-        # evcServiceType = "Point_To_Point"

+        p2p_json_data = {}

+        p2p_json_data["evcServiceType"] = "Point_To_Point"

 

         uni1 = obj.uni1

         uni1Id = uni1.pid

@@ -142,6 +258,19 @@
         uni1BwpCfgCir = uni1.bwpCfgCir

         uni1BwpCfgEir = uni1.bwpCfgEir

 

+        uni1_json_data = {}

+        uni1_json_data['scaEthFppUniN'] = {}

+        uni1_json_data['scaEthFppUniN']['ceVlanId'] = obj.vlanid

+        uni1_json_data['scaEthFppUniN']["transportPort"] = {}

+        uni1_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"] = {}

+

+        uni1_json_data['scaEthFppUniN']["transportPort"]["Hostname"] = uni1Hostname

+        uni1_json_data['scaEthFppUniN']["transportPort"]["Port"] = uni1Port

+        uni1_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgCbs"] = uni1BwpCfgCbs

+        uni1_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgEbs"] = uni1BwpCfgEbs

+        uni1_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgCir"] = uni1BwpCfgCir

+        uni1_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgEir"] = uni1BwpCfgEir

+

         uni2 = obj.uni2

         uni2Id = uni2.pid

         uni2IdToken = (uni2Id.split('.', 1))[1].split('/', 1)

@@ -152,27 +281,137 @@
         uni2BwpCfgCir = uni2.bwpCfgCir

         uni2BwpCfgEir = uni2.bwpCfgEir

 

-        data = {

-            "evcServiceType": evcServiceType,

-            "SCA_ETH_Flow_Points": [

-                {

-                    "scaEthFppUniN": {"transportPort": {"Hostname": uni1Hostname, "Port": uni1Port},

-                                      "interfaceCfgIngressBwp": {"bwpCfgCbs": uni1BwpCfgCbs,

-                                                                 "bwpCfgEbs": uni1BwpCfgEbs,

-                                                                 "bwpCfgCir": uni1BwpCfgCir,

-                                                                 "bwpCfgEir": uni1BwpCfgEir}}},

-                {

-                    "scaEthFppUniN": {"transportPort": {"Hostname": uni2Hostname, "Port": uni2Port},

-                                      "interfaceCfgIngressBwp": {"bwpCfgCbs": uni2BwpCfgCbs,

-                                                                 "bwpCfgEbs": uni2BwpCfgEbs,

-                                                                 "bwpCfgCir": uni2BwpCfgCir,

-                                                                 "bwpCfgEir": uni2BwpCfgEir}}}]

-        }

+        uni2_json_data = {}

+        uni2_json_data['scaEthFppUniN'] = {}

+        uni2_json_data['scaEthFppUniN']['ceVlanId'] = obj.vlanid

+        uni2_json_data['scaEthFppUniN']["transportPort"] = {}

+        uni2_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"] = {}

+

+        uni2_json_data['scaEthFppUniN']["transportPort"]["Hostname"] = uni2Hostname

+        uni2_json_data['scaEthFppUniN']["transportPort"]["Port"] = uni2Port

+        uni2_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgCbs"] = uni2BwpCfgCbs

+        uni2_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgEbs"] = uni2BwpCfgEbs

+        uni2_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgCir"] = uni2BwpCfgCir

+        uni2_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgEir"] = uni2BwpCfgEir

+

+        p2p_json_data["SCA_ETH_Flow_Points"] = []

+        p2p_json_data["SCA_ETH_Flow_Points"].append(uni1_json_data)

+        p2p_json_data["SCA_ETH_Flow_Points"].append(uni2_json_data)

+

+        return p2p_json_data

+

+    # nchoi: create elan service json data

+    def create_multipoint_to_multipoint_connectivity_json_data(self, obj):

+

+        mp2mp_json_data = {}

+        mp2mp_json_data["evcServiceType"] = "Multipoint_To_Multipoint"

+        mp2mp_json_data["SCA_ETH_Flow_Points"] = []

+

+        for ep in obj.eps.all():

+            uniId = ep.pid

+            uniIdToken = (uniId.split('.', 1))[1].split('/', 1)

+            uniHostname = uniIdToken[0]

+            uniPort = uniIdToken[1]

+            uniBwpCfgCbs = ep.bwpCfgCbs

+            uniBwpCfgEbs = ep.bwpCfgEbs

+            uniBwpCfgCir = ep.bwpCfgCir

+            uniBwpCfgEir = ep.bwpCfgEir

+

+            uni_json_data = {}

+            uni_json_data['scaEthFppUniN'] = {}

+            uni_json_data['scaEthFppUniN']['ceVlanId'] = obj.vlanid

+            uni_json_data['scaEthFppUniN']["transportPort"] = {}

+            uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"] = {}

+

+            uni_json_data['scaEthFppUniN']["transportPort"]["Hostname"] = uniHostname

+            uni_json_data['scaEthFppUniN']["transportPort"]["Port"] = uniPort

+            uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgCbs"] = uniBwpCfgCbs

+            uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgEbs"] = uniBwpCfgEbs

+            uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgCir"] = uniBwpCfgCir

+            uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgEir"] = uniBwpCfgEir

+

+            mp2mp_json_data["SCA_ETH_Flow_Points"].append(uni_json_data)

+

+        return mp2mp_json_data

+

+    # nchoi: create etree service json data

+    def create_root_multipoint_connectivity_json_data(self, obj):

+

+        r2mp_json_data = {}

+        r2mp_json_data["evcServiceType"] = "Root_Multipoint"

+        r2mp_json_data["SCA_ETH_Flow_Points"] = []

+

+        root = obj.root

+        uniId = root.pid

+        uniIdToken = (uniId.split('.', 1))[1].split('/', 1)

+        uniHostname = uniIdToken[0]

+        uniPort = uniIdToken[1]

+        uniBwpCfgCbs = root.bwpCfgCbs

+        uniBwpCfgEbs = root.bwpCfgEbs

+        uniBwpCfgCir = root.bwpCfgCir

+        uniBwpCfgEir = root.bwpCfgEir

+

+        uni_json_data = {}

+        uni_json_data['scaEthFppUniN'] = {}

+        uni_json_data['scaEthFppUniN']['ceVlanId'] = obj.vlanid

+        uni_json_data['scaEthFppUniN']["transportPort"] = {}

+        uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"] = {}

+

+        uni_json_data['scaEthFppUniN']["transportPort"]["Hostname"] = uniHostname

+        uni_json_data['scaEthFppUniN']["transportPort"]["Port"] = uniPort

+        uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgCbs"] = uniBwpCfgCbs

+        uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgEbs"] = uniBwpCfgEbs

+        uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgCir"] = uniBwpCfgCir

+        uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgEir"] = uniBwpCfgEir

+

+        r2mp_json_data["SCA_ETH_Flow_Points"].append(uni_json_data)

+

+        for ep in obj.eps.all():

+            uniId = ep.pid

+            uniIdToken = (uniId.split('.', 1))[1].split('/', 1)

+            uniHostname = uniIdToken[0]

+            uniPort = uniIdToken[1]

+            uniBwpCfgCbs = ep.bwpCfgCbs

+            uniBwpCfgEbs = ep.bwpCfgEbs

+            uniBwpCfgCir = ep.bwpCfgCir

+            uniBwpCfgEir = ep.bwpCfgEir

+

+            uni_json_data = {}

+            uni_json_data['scaEthFppUniN'] = {}

+            uni_json_data['scaEthFppUniN']['ceVlanId'] = obj.vlanid

+            uni_json_data['scaEthFppUniN']["transportPort"] = {}

+            uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"] = {}

+

+            uni_json_data['scaEthFppUniN']["transportPort"]["Hostname"] = uniHostname

+            uni_json_data['scaEthFppUniN']["transportPort"]["Port"] = uniPort

+            uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgCbs"] = uniBwpCfgCbs

+            uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgEbs"] = uniBwpCfgEbs

+            uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgCir"] = uniBwpCfgCir

+            uni_json_data['scaEthFppUniN']["interfaceCfgIngressBwp"]["bwpCfgEir"] = uniBwpCfgEir

+

+            r2mp_json_data["SCA_ETH_Flow_Points"].append(uni_json_data)

+

+        return r2mp_json_data

+

+    def create_network_connectivity(self, obj):

+

+        restCtrlUrl = self.networkdevice.restCtrlUrl

+        username = self.networkdevice.username

+        password = self.networkdevice.password

+

+        evcServiceType = obj.type

+        if (evcServiceType == "Point_To_Point"):

+            network_connectivity_json_data = self.create_point_to_point_connectivity_json_data(obj)

+        elif (evcServiceType == "Multipoint_To_Multipoint"):

+            network_connectivity_json_data = self.create_multipoint_to_multipoint_connectivity_json_data(obj)

+        elif (evcServiceType == "Root_Multipoint"):

+            network_connectivity_json_data = self.create_root_multipoint_connectivity_json_data(obj)

+        else:

+            raise Exception("OnosApiError: get_network_links() - unknown link type")

 

         headers = {'Content-Type': 'application/json'}

-

         resp = requests.post('{}/mef-sca-api/SCA_ETH_FDFr_EC'.format(restCtrlUrl),

-                             data=json.dumps(data), headers=headers, auth=HTTPBasicAuth(username, password))

+                             data=json.dumps(network_connectivity_json_data), headers=headers, auth=HTTPBasicAuth(username, password))

 

         if resp.status_code == 201:

             result = resp.json()

@@ -192,6 +431,7 @@
             obj.adminstate = "invalid"  # what's the meaning?

             obj.operstate = "inactive"

             obj.backend_status = '204 - No network resource'

+

             return False

 

         elif resp.status_code == 500:

@@ -201,9 +441,9 @@
             return False

 

         else:

-            raise Exception("OnosApiError: create_point_to_point_connectivity()")

+            raise Exception("OnosApiError: create_network_connectivity()")

 

-    def delete_point_to_point_connectivity(self, obj):

+    def delete_network_connectivity(self, obj):

 

         restCtrlUrl = self.networkdevice.restCtrlUrl

         username = self.networkdevice.username

@@ -229,4 +469,4 @@
             return False

 

         else:

-            raise Exception("OnosApiError: delete_point_to_point_connectivity()")

+            raise Exception("OnosApiError: delete_network_connectivity()")

diff --git a/xos/synchronizer/providers/metronetworktestprovider.py b/xos/synchronizer/providers/metronetworktestprovider.py
index 3c3f179..3bcbb92 100644
--- a/xos/synchronizer/providers/metronetworktestprovider.py
+++ b/xos/synchronizer/providers/metronetworktestprovider.py
@@ -3,6 +3,7 @@
 
 from xos.logger import Logger, logging
 from services.metronetwork.models import *
+from core.models import Site
 from synchronizers.metronetwork.providers.metronetworkprovider import MetroNetworkProvider
 
 logger = Logger(level=logging.INFO)
@@ -15,40 +16,18 @@
     # Method for retrieving all network ports from the backend system
     def get_network_ports(self):
         #
-        # Our Test Network Consists of three NetworkDevices (which correspond to ONOS instances):
+        # Our Test Network Consists of one NetworkDevice (which correspond to ONOS instance):
         #
-        #                    ONOS1-CORDPOD1
-        #                    ONOS2-MetroNetwork
-        #                    ONOW3-CORDPOD2
+        #  8 Ports
+        #  1 Eline (2 ports)
+        #  1 Etree (3 ports)
+        #  1 Elan (3 ports)
         #
-        #
-        #    Uni-NetworkEdgePort3--
-        #    Uni-NetworkEdgePort11-
-        #    Uni-NetworkEdgePort5--ONOS1-CORDPOD1-NetworkPort6
-        #            NetworkPort4--                     |
-        #                                        NetworkPort1-ONOS2-MetroNetwork
-        #                                        NetworkPort2-
-        #                                             |
-        #    Uni-NetworkEdgePort7--ONOS3-CORDPOD2-NetworkPort10
-        #    Uni-NetworkEdgePort9--
-        #    Uni-NetworkEdgePort12-
-        #        NetworkPort8--
-        #
-        #  Note: NetworkPorts can be endpoints of Interlinks and NetworkPointToPointConnections
-        #              they can be seem as a simple port.
-        #        NetworkEdgePorts are UNIs in the network, so are specicially user facing.
-        #
-        #
-        # InterLinks - Port1 - Port6
-        #              Port2 - Port10
-        #
-        # NetworkPointToPointConnections: Port1 - Port2
-        #                                 Port4 - Port6
-        #                                 Port8 - Port10
-        #
-        # NetworkEdgeToEdgePointConnections: Port3 - Port7
-        #
-        # NetworkMultipointConnection: Port11 - Port5 - Port9 - Port12
+        #  2 Sites - Representing Two R-CORD Pods
+        #  2 Ports, One-per-site
+        #  1 Bandwidth Profile
+        #  2 Service Spokes
+        #  1 VnodGlobalService
 
         objs = []
 
@@ -56,14 +35,9 @@
         if self.networkdevice.id != 'TestMetroNet':
             return objs
 
-        # Ok - in the test class we cheat and create one NetworkDevice with 8 NetworkEdgePorts
+        # Set the parent device id to just be the Test NetworkDevice
         device1 = NetworkDevice()
-        device1.id = 'TestCORDNet'
-        device1.administrativeState = 'enabled'
-        device1.restCtrlUrl = 'testCordPod1.onlab.net:8000'
-        device1.username = 'karaf'
-        device1.password = 'karaf'
-        objs.append(device1)
+        device1.id = self.networkdevice.id
 
         port1 = NetworkEdgePort()
         port1.element = device1
@@ -176,11 +150,6 @@
         for port in allports:
             objs.append(port)
 
-        # Ok - in the test class we cheat and take down the adjunct Fake NetworkDevices Devices
-        device1 = NetworkDevice()
-        device1.id = 'TestCORDNet'
-        objs.append(device1)
-
         return objs
 
     def get_network_links(self):
@@ -189,7 +158,7 @@
 
         # Connectivity object - Point to Point
         cordpod1device = NetworkDevice()
-        cordpod1device.id = 'TestCORDNet'
+        cordpod1device.id = self.networkdevice.id
 
         # Edge to Edge Point Connectivity Objects
         edgetoedgeconnectivity = NetworkEdgeToEdgePointConnection()
@@ -239,6 +208,81 @@
         edge2multipointconnectivity.eps_createbuffer = json.dumps(myjsonstr)
         objs.append(edge2multipointconnectivity)
 
+        # Create Objects for VnodGlobal Sort of Testing
+
+        # Bandwidth Profile
+
+        bwprofile = BandwidthProfile()
+        bwprofile.bwpcfgcbs  = 0
+        bwprofile.bwpcfgcir = 0
+        bwprofile.bwpcfgebs = 0
+        bwprofile.bwpcfgeir = 0
+        bwprofile.name = 'TestBWP'
+        objs.append(bwprofile)
+
+        # Two Sites
+        site1 = Site()
+        site1.name = 'CORDPod1'
+        site1.login_base = 'CordPod1'
+        site1.site_url = 'http://1.2.3.4:8080/VnodLocalApi'
+        objs.append(site1)
+
+        site2 = Site()
+        site2.name = 'CORDPod2'
+        site2.login_base = 'CordPod2'
+        site2.site_url = 'http://10.11.12.13:8080/VnodLocalApi'
+        objs.append(site2)
+
+        # Two Ports - one per Site
+
+        remoteport1 = RemotePort()
+        remoteport1.name = "CORDPOD1:Port1"
+        remoteport1.sitename = 'CordPod1'
+        remoteport1.edgeportname = cordpod1device.id + "." + "of:000000001/1"
+        objs.append(remoteport1)
+
+        remoteport2 = RemotePort()
+        remoteport2.name = "CORDPOD2:Port1"
+        remoteport2.sitename = 'CordPod2'
+        remoteport2.edgeportname = cordpod1device.id + "." + "of:000000001/2"
+        objs.append(remoteport2)
+
+        # One Spoke/Site
+        spoke1 = ServiceSpoke()
+        spoke1.name = 'TestSpoke1'
+        spoke1.remoteportname = "CORDPOD1:Port1"
+        spoke1.remotevnodid = 'CORDPod1:VnodLocal:1'
+        spoke1.operstate = 'inactive'
+        spoke1.adminstate = 'enabled'
+        spoke1.sitename = 'CordPod1'
+        objs.append(spoke1)
+
+        spoke2 = ServiceSpoke()
+        spoke2.name = 'TestSpoke2'
+        spoke2.remoteportname = "CORDPOD2:Port1"
+        spoke2.remotevnodid = 'CORDPod2:VnodLocal:1'
+        spoke2.operstate = 'active'
+        spoke2.adminstate = 'enabled'
+        spoke2.sitename = 'CordPod2'
+        objs.append(spoke2)
+
+        # One VnodGlobal Service
+        vnodglobal = VnodGlobalService()
+        vnodglobal.name = 'VnodGlobalPtToPtTest1'
+        vnodglobal.type = 'eline'
+        vnodglobal.vlanid = '100'
+        vnodglobal.operstate = 'active'
+        vnodglobal.adminstate = 'enabled'
+        vnodglobal.servicehandle = 'testhandle1'
+        vnodglobal.pointtopointsid = 'onos_eline_id'
+        vnodglobal.bwpname = 'TestBWP'
+
+        # Create JSON array for post-save behaviour
+        #
+        spokes = ['TestSpoke1', 'TestSpoke2']
+        myjsonstr = {'spokes': spokes}
+        vnodglobal.spokes_createbuffer = json.dumps(myjsonstr)
+        objs.append(vnodglobal)
 
         return objs
 
diff --git a/xos/synchronizer/steps/sync_metronetworkservice.py b/xos/synchronizer/steps/sync_metronetworkservice.py
index 5c3fe70..56fd5d5 100644
--- a/xos/synchronizer/steps/sync_metronetworkservice.py
+++ b/xos/synchronizer/steps/sync_metronetworkservice.py
@@ -1,5 +1,5 @@
-import os
-import sys
+import os, sys
+from itertools import chain
 
 from synchronizers.base.syncstep import SyncStep
 from services.metronetwork.models import *
@@ -119,12 +119,15 @@
 
                 # Handle changes XOS -> ONOS
                 # Check for ConnectivityObjects that are in acticationequested state - creates to the backend
-                activatereqs = NetworkEdgeToEdgePointConnection.objects.filter(adminstate='activationrequested')
+                p2pactivatereqs = NetworkEdgeToEdgePointConnection.objects.filter(adminstate='activationrequested')
+                mp2mpactivatereqs = NetworkMultipointToMultipointConnection.objects.filter(adminstate='activationrequested')
+                r2mpactivatereqs = NetworkEdgeToMultipointConnection.objects.filter(adminstate='activationrequested')
+                activatereqs = list(chain(p2pactivatereqs, mp2mpactivatereqs, r2mpactivatereqs))
                 for activatereq in activatereqs:
 
                     # Call the XOS Interface to create the service
                     logger.debug("Attempting to create EdgePointToEdgePointConnectivity: %s" % activatereq.id)
-                    if (provider.create_point_to_point_connectivity(activatereq)):
+                    if (provider.create_network_connectivity(activatereq)):
                         # Everyting is OK, lets let the system handle the persist
                         objs.append(activatereq)
                     else:
@@ -133,12 +136,15 @@
                         activatereq.save()
 
                 # Check for ConnectivityObjects that are in deacticationequested state - deletes to the backend
-                deactivatereqs = NetworkEdgeToEdgePointConnection.objects.filter(adminstate='deactivationrequested')
+                p2pdeactivatereqs = NetworkEdgeToEdgePointConnection.objects.filter(adminstate='deactivationrequested')
+                mp2mpdeactivatereqs = NetworkMultipointToMultipointConnection.objects.filter(adminstate='deactivationrequested')
+                r2mpdeactivatereqs = NetworkEdgeToMultipointConnection.objects.filter(adminstate='deactivationrequested')
+                deactivatereqs = list(chain(p2pdeactivatereqs, mp2mpdeactivatereqs, r2mpdeactivatereqs))
                 for deactivatereq in deactivatereqs:
 
                     # Call the XOS Interface to delete the service
                     logger.debug("Attempting to delete EdgePointToEdgePointConnectivity: %s" % deactivatereq.id)
-                    if provider.delete_point_to_point_connectivity(deactivatereq):
+                    if provider.delete_network_connectivity(deactivatereq):
                         # Everyting is OK, lets let the system handle the persist
                         objs.append(deactivatereq)
                     else:
@@ -160,6 +166,57 @@
                     # Simply put in the queue for update - this will handle both new and changed objects
                     objs.append(eventobj)
 
+                # Handle the case where we have deleted Eline Services from our side - if the Service is in
+                # enabled state then we call the provider, otherwise just queue it for deletion
+                elinedeletedobjs = NetworkEdgeToEdgePointConnection.deleted_objects.all()
+                for elinedeletedobj in elinedeletedobjs:
+                    if elinedeletedobj.adminstate == 'enabled':
+                        provider.delete_network_connectivity(elinedeletedobj)
+                    # Either way queue it for deletion
+                    objs.append(elinedeletedobj)
+
+                # Handle the case where we have deleted Etree Services from our side - if the Service is in
+                # enabled state then we call the provider, otherwise just queue it for deletion
+                etreedeletedobjs = NetworkEdgeToMultipointConnection.deleted_objects.all()
+                for etreedeletedobj in etreedeletedobjs:
+                    # TODO: Handle the case where its connected, we need to disconnect first
+                    if etreedeletedobj.adminstate == 'enabled':
+                        provider.delete_network_connectivity(etreedeletedobj)
+                    # Either way queue it for deletion
+                    objs.append(etreedeletedobj)
+
+                # Handle the case where we have deleted Elan Services from our side - if the Service is in
+                # enabled state then we call the provider, otherwise just queue it for deletion
+                elandeletedobjs = NetworkMultipointToMultipointConnection.deleted_objects.all()
+                for elandeletedobj in elandeletedobjs:
+                    # TODO: Handle the case where its connected, we need to disconnect first
+                    if elandeletedobj.adminstate == 'enabled':
+                        provider.delete_network_connectivity(elandeletedobj)
+                    # Either way queue it for deletion
+                    objs.append(elandeletedobj)
+
+                # Handle the case where we have deleted VnodGlobal Services from our side - if there is
+                # an attached Eline/Etree/Elan we set that to deleted
+                vnodbloaldeletedobjs = VnodGlobalService.deleted_objects.all()
+                for vnodbloaldeletedobj in vnodbloaldeletedobjs:
+                    # Check for dependent eline service
+                    if vnodbloaldeletedobj.metronetworkpointtopoint is not None:
+                        elineobj = vnodbloaldeletedobj.metronetworkpointtopoint
+                        elineobj.deleted = True
+                        objs.append(elineobj)
+                    # Check for dependent elan service
+                    if vnodbloaldeletedobj.metronetworkmultipoint is not None:
+                        elanobj = vnodbloaldeletedobj.metronetworkmultipoint
+                        elanobj.deleted = True
+                        objs.append(elanobj)
+                    # Check for dependent etree service
+                    if vnodbloaldeletedobj.metronetworkroottomultipoint is not None:
+                        etreeobj = vnodbloaldeletedobj.metronetworkroottomultipoint
+                        etreeobj.deleted = True
+                        objs.append(etreeobj)
+
+                    objs.append(vnodbloaldeletedobj)
+
         # In add cases return the objects we are interested in
         return objs