[CORD-1324-1328-1330-1331] Models for refactored Global ECORD service

Change-Id: Ib9c02d25bd65729c7faaa48d40b54a2ce6ffffac
diff --git a/xos/synchronizer/steps/__init__.py b/xos/synchronizer/steps/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/xos/synchronizer/steps/__init__.py
diff --git a/xos/synchronizer/steps/sync_metroneteline.py b/xos/synchronizer/steps/sync_metroneteline.py
new file mode 100644
index 0000000..bd0bfef
--- /dev/null
+++ b/xos/synchronizer/steps/sync_metroneteline.py
@@ -0,0 +1,89 @@
+import os
+import sys
+import requests
+import json
+from synchronizers.new_base.syncstep import SyncStep
+from synchronizers.new_base.modelaccessor import *
+#from xos.logger import Logger, logging
+
+from requests.auth import HTTPBasicAuth
+#logger = Logger(level=logging.INFO)
+
+parentdir = os.path.join(os.path.dirname(__file__), "..")
+sys.path.insert(0, parentdir)
+
+
+class SyncMetroNetEline(SyncStep):
+    provides = [ELine]
+
+    observes = ELine
+
+    requested_interval = 0
+
+    def __init__(self, *args, **kwargs):
+        super(SyncMetroNetEline, self).__init__(*args, **kwargs)
+
+    def get_onos_global_addr(self, onos):
+        #Fetching ip and port from the Global ONOS, append the CE specif API
+
+        onos_url = "http://%s:%s/onos/" % (onos.onos_ip, onos.onos_port)
+        evc_endpoint = "carrierethernet/evc"
+        return onos_url + evc_endpoint
+
+    def get_onos_global_auth(self, onos):
+        #Fetching username and password from the Global ONOS
+
+        return HTTPBasicAuth(onos.onos_username, onos.onos_password)
+
+    def sync_record(self, evc):
+        print "POST %s " % (evc)
+        #logger.info("Syncing Edited EVC: %s" % evc.name)
+        # Fetch the bwp from the DB
+        bwp = BandwidthProfile.objects.get(name=evc.bwp)
+
+        # json to configure ONOS to start the EVC.
+        # {
+        #     "evcId": "evc1",
+        #     "evcCfgId": "evpl1",
+        #     "uniList": [
+        #         "netconf:192.168.56.10:830/0",
+        #         "netconf:192.168.56.20:830/0"
+        #     ],
+        #     "evcType": "POINT_TO_POINT",
+        #     "vlanId": 100,
+        #     "cir": "400",
+        #     "eir": "200",
+        #     "cbs": "3000",
+        #     "ebs": "2000"
+        # }
+
+        data = {}
+        data["evcId"] = evc.name
+        data["evcCfgId"] = evc.name
+        data["uniList"] = [evc.connect_point_1_id, evc.connect_point_2_id]
+        data["evcType"] = "POINT_TO_POINT"
+        data["vlanId"] = evc.vlanids.split(",")
+        data["cbs"] = bwp.cbs
+        data["ebs"] = bwp.ebs
+        data["cir"] = bwp.cir
+        data["eir"] = bwp.eir
+        print "data %s" % data
+        # assuming that the CPEs are controller by the fabric ONOS
+        onos = OnosModel.objects.get(onos_type="global")
+        onos_addr = self.get_onos_global_addr(onos)
+
+        # FIXME - hardcoded auth
+        auth = self.get_onos_global_auth(onos)
+
+        print "POST %s for app %s, data = %s" % (onos_addr, evc.name, data)
+
+        r = requests.post(onos_addr, data=json.dumps(data), auth=auth)
+        #TODO XOS might fail to connect to ONOS.
+        if (r.status_code != 200):
+            print r
+            raise Exception("Received error from EVC Installation update (%d)" % r.status_code)
+
+    def delete_record(self, evc):
+        # TODO evaluate what to in this case.
+        print "Syncing delete EVC: %s" % evc.name
+        #logger.info("Syncing delete EVC: %s" % evc.name)
diff --git a/xos/synchronizer/steps/sync_metronetworkservice.py b/xos/synchronizer/steps/sync_metronetworkservice.py
deleted file mode 100644
index 3468d2b..0000000
--- a/xos/synchronizer/steps/sync_metronetworkservice.py
+++ /dev/null
@@ -1,254 +0,0 @@
-import os, sys
-from itertools import chain
-
-from synchronizers.new_base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible #if needed
-from synchronizers.new_base.ansible_helper import run_template_ssh #if needed
-from synchronizers.new_base.modelaccessor import *
-from xos.logger import Logger, logging
-from synchronizers.metronetwork.providers.providerfactory import ProviderFactory
-from synchronizers.metronetwork.invokers.invokerfactory import InvokerFactory
-
-# metronetwork will be in steps/..
-parentdir = os.path.join(os.path.dirname(__file__), "..")
-sys.path.insert(0, parentdir)
-
-logger = Logger(level=logging.INFO)
-
-
-class SyncMetroNetworkSystem(SyncStep):
-    provides = [MetroNetworkSystem]
-    observes = MetroNetworkSystem
-    requested_interval = 0
-    initialized = False
-
-    def __init__(self, **args):
-        SyncStep.__init__(self, **args)
-
-    def fetch_pending(self, deletion=False):
-
-        # The general idea:
-        # We do one of two things in here:
-        #    1. Full Synchronization of the DBS (XOS <-> MetroONOS)
-        #    2. Look for updates between the two stores
-        # The first thing is potentially a much bigger
-        # operation and should not happen as often
-        #
-        # The Sync operation must take into account the 'deletion' flag
-
-        objs = []
-
-        # Get the NetworkSystem object - if it exists it will test us
-        # whether we should do a full sync or not - it all has our config
-        # information about the REST interface
-
-        metronetworksystem = self.get_metronetwork_system()
-        if not metronetworksystem:
-            logger.debug("No Service configured")
-            return objs
-
-        # Check to make sure the Metro Network System is enabled
-        metronetworksystem = self.get_metronetwork_system()
-        if metronetworksystem.administrativeState == 'disabled':
-            # Nothing to do
-            logger.debug("MetroService configured - state is Disabled")
-            return objs
-
-        # The Main Loop - retrieve all the NetworkDevice objects - for each of these
-        # Apply synchronization aspects
-        networkdevices = NetworkDevice.objects.all()
-
-        for dev in networkdevices:
-
-            # Set up the provider
-            provider = ProviderFactory.getprovider(dev)
-
-            # First check is for the AdminState of Disabled - do nothing
-            if dev.administrativeState == 'disabled':
-                # Nothing to do with this device
-                logger.debug("NetworkDevice %s: administrativeState set to Disabled - continuing" % dev.id)
-
-            # Now to the main options - are we syncing - deletion portion
-            elif dev.administrativeState == 'syncrequested' and deletion is True:
-
-                logger.info("NetworkDevice %s: administrativeState set to SyncRequested" % dev.id)
-
-                # Kill Links
-                networklinks = provider.get_network_links_for_deletion()
-                for link in networklinks:
-                    objs.append(link)
-
-                # Kill Ports
-                allports = provider.get_network_ports_for_deletion()
-                for port in allports:
-                    objs.append(port)
-
-                logger.info("NetworkDevice %s: Deletion part of Sync completed" % dev.id)
-                dev.administrativeState = 'syncinprogress'
-                dev.save(update_fields=['administrativeState'])
-
-            # Now to the main options - are we syncing - creation portion
-            elif dev.administrativeState == 'syncinprogress' and deletion is False:
-
-                logger.info("NetworkDevice %s: administrativeState set to SyncRequested" % dev.id)
-                # Reload objects in the reverse order of deletion
-
-                # Add Ports
-                networkports = provider.get_network_ports()
-                for port in networkports:
-                    objs.append(port)
-
-                # Add Links
-                networklinks = provider.get_network_links()
-                for link in networklinks:
-                    objs.append(link)
-
-                logger.info("NetworkDevice %s: Creation part of Sync completed" % dev.id)
-                dev.administrativeState = 'enabled'
-                dev.save(update_fields=['administrativeState'])
-
-            # If we are enabled - then check for events - in either direction and sync
-            elif dev.administrativeState == 'enabled' and deletion is False:
-                logger.debug("NetworkDevice: administrativeState set to Enabled - non deletion phase")
-
-                # This should be the 'normal running state' when we are not deleting - a few things to do in here
-
-                # Get the changed objects from the provider - deletions are handled separately
-                eventobjs = provider.get_updated_or_created_objects()
-                for eventobj in eventobjs:
-                    # Simply put in the queue for update - this will handle both new and changed objects
-                    objs.append(eventobj)
-
-                # Handle changes XOS -> ONOS
-                # Check for ConnectivityObjects that are in acticationequested state - creates to the backend
-                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_network_connectivity(activatereq)):
-                        # Everyting is OK, lets let the system handle the persist
-                        objs.append(activatereq)
-                    else:
-                        # In the case of an error we persist the state of the object directly to preserve
-                        # the error code - and because that is how the base synchronizer is designed
-                        activatereq.save()
-
-                # Check for ConnectivityObjects that are in deacticationequested state - deletes to the backend
-                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_network_connectivity(deactivatereq):
-                        # Everyting is OK, lets let the system handle the persist
-                        objs.append(deactivatereq)
-                    else:
-                        # In the case of an error we persist the state of the object directly to preserve
-                        # the error code - and because that is how the base synchronizer is designed
-                        deactivatereq.save()
-
-            # If we are enabled - and in our deletion pass then look for objects waiting for deletion
-            elif dev.administrativeState == 'enabled' and deletion is True:
-                logger.debug("NetworkDevice: administrativeState set to Enabled - deletion phase")
-
-                # Any object that is simply deleted in the model gets removed automatically - the synchronizer
-                # doesn't get involved - we just need to check for deleted objects in the domain and reflect that
-                # in the model
-                #
-                # Get the deleted objects from the provider
-                eventobjs = provider.get_deleted_objects()
-                for eventobj in eventobjs:
-                    # 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
-
-    def sync_record(self, o):
-
-        # First we call and see if there is an invoker for this object - the idea of the invoker
-        # is to wrap the save with a pre/post paradigm to handle special cases
-        # It will only exist for a subset of ojbects
-        invoker = InvokerFactory.getinvoker(o)
-
-        # Call Pre-save on the inovker (if it exists)
-        if invoker is not None:
-            invoker.presave(o)
-
-        # Simply save the record to the DB - both updates and adds are handled the same way
-        o.save()
-
-        # Call Post-save on the inovker (if it exists)
-        if invoker is not None:
-            invoker.postsave(o)
-
-    def delete_record(self, o):
-        # Overriden to customize our behaviour - the core sync step for will remove the record directly
-        # We just log and return
-        logger.debug("deleting Object %s" % str(o), extra=o.tologdict())
-
-    def get_metronetwork_system(self):
-        # We only expect to have one of these objects in the system in the curent design
-        # So get the first element from the query
-        metronetworksystem = MetroNetworkSystem.objects.all()
-        if not metronetworksystem:
-            return None
-
-        return metronetworksystem[0]