blob: 724bb9a9161f71a87fc153b1b3906d6addd25138 [file] [log] [blame]
Rizwan Haider30b33792016-08-18 02:11:18 -04001import os
2import sys
3
4from synchronizers.base.syncstep import SyncStep
Rizwan Haidereb2cc772016-09-08 12:14:55 -04005from services.metronetwork.models import *
Rizwan Haider30b33792016-08-18 02:11:18 -04006from xos.logger import Logger, logging
7from synchronizers.metronetwork.providers.providerfactory import ProviderFactory
8
9# metronetwork will be in steps/..
10parentdir = os.path.join(os.path.dirname(__file__), "..")
11sys.path.insert(0, parentdir)
12
13logger = Logger(level=logging.INFO)
14
15
16class SyncMetroNetworkService(SyncStep):
17 provides = [MetroNetworkService]
18 observes = MetroNetworkService
19 requested_interval = 0
20 initialized = False
21
22 def __init__(self, **args):
23 SyncStep.__init__(self, **args)
24
25 def fetch_pending(self, deletion=False):
26
27 # The general idea:
28 # We do one of two things in here:
29 # 1. Full Synchronization of the DBS (XOS <-> MetroONOS)
30 # 2. Look for updates between the two stores
31 # The first thing is potentially a much bigger
32 # operation and should not happen as often
33 #
34 # The Sync operation must take into account the 'deletion' flag
35
36 objs = []
37
38 # Get the NetworkService object - if it exists it will test us
39 # whether we should do a full sync or not - it all has our config
40 # information about the REST interface
41
42 metronetworkservice = self.get_metronetwork_service()
43 if not metronetworkservice:
44 logger.debug("No Service configured")
45 return objs
46
47 # Check to make sure the Service is enabled
48 metronetworkservice = self.get_metronetwork_service()
49 if metronetworkservice.administrativeState == 'disabled':
50 # Nothing to do
51 logger.debug("MetroService configured - state is Disabled")
52 return objs
53
54 # The Main Loop - retrieve all the NetworkDevice objects - for each of these
55 # Apply synchronization aspects
56 networkdevices = NetworkDevice.objects.all()
57
58 for dev in networkdevices:
59
60 # Set up the provider
61 provider = ProviderFactory.getprovider(dev)
62
63 # First check is for the AdminState of Disabled - do nothing
64 if dev.administrativeState == 'disabled':
65 # Nothing to do with this device
66 logger.debug("NetworkDevice %s: administrativeState set to Disabled - continuing" % dev.id)
67
68 # Now to the main options - are we syncing - deletion portion
69 elif dev.administrativeState == 'syncrequested' and deletion is True:
70
71 logger.info("NetworkDevice %s: administrativeState set to SyncRequested" % dev.id)
72
73 # Kill Links
74 networklinks = provider.get_network_links_for_deletion()
75 for link in networklinks:
76 objs.append(link)
77
78 # Kill Ports
79 allports = provider.get_network_ports_for_deletion()
80 for port in allports:
81 objs.append(port)
82
83 logger.info("NetworkDevice %s: Deletion part of Sync completed" % dev.id)
84 dev.administrativeState = 'syncinprogress'
85 dev.save(update_fields=['administrativeState'])
86
87 # Now to the main options - are we syncing - creation portion
88 elif dev.administrativeState == 'syncinprogress' and deletion is False:
89
90 logger.info("NetworkDevice %s: administrativeState set to SyncRequested" % dev.id)
91 # Reload objects in the reverse order of deletion
92
93 # Add Ports
94 networkports = provider.get_network_ports()
95 for port in networkports:
96 objs.append(port)
97
98 # Add Links
99 networklinks = provider.get_network_links()
100 for link in networklinks:
101 objs.append(link)
102
103 logger.info("NetworkDevice %s: Creation part of Sync completed" % dev.id)
104 dev.administrativeState = 'enabled'
105 dev.save(update_fields=['administrativeState'])
106
107 # If we are enabled - then check for events - in either direction and sync
108 elif dev.administrativeState == 'enabled' and deletion is False:
109 logger.debug("NetworkDevice: administrativeState set to Enabled - non deletion phase")
110
111 # This should be the 'normal running state' when we are not deleting - a few things to do in here
112
113 # Get the changed objects from the provider - deletions are handled separately
114 eventobjs = provider.get_updated_or_created_objects()
115 for eventobj in eventobjs:
116 # Simply put in the queue for update - this will handle both new and changed objects
117 objs.append(eventobj)
118
119 # Handle changes XOS -> ONOS
120 # Check for ConnectivityObjects that are in acticationequested state - creates to the backend
121 activatereqs = NetworkEdgeToEdgePointConnection.objects.filter(adminstate='activationrequested')
122 for activatereq in activatereqs:
123
124 # Call the XOS Interface to create the service
125 logger.debug("Attempting to create EdgePointToEdgePointConnectivity: %s" % activatereq.id)
126 if (provider.create_point_to_point_connectivity(activatereq)):
127 # Everyting is OK, lets let the system handle the persist
128 objs.append(activatereq)
129 else:
130 # In the case of an error we persist the state of the object directly to preserve
131 # the error code - and because that is how the base synchronizer is designed
132 activatereq.save()
133
134 # Check for ConnectivityObjects that are in deacticationequested state - deletes to the backend
135 deactivatereqs = NetworkEdgeToEdgePointConnection.objects.filter(adminstate='deactivationrequested')
136 for deactivatereq in deactivatereqs:
137
138 # Call the XOS Interface to delete the service
139 logger.debug("Attempting to delete EdgePointToEdgePointConnectivity: %s" % deactivatereq.id)
140 if provider.delete_point_to_point_connectivity(deactivatereq):
141 # Everyting is OK, lets let the system handle the persist
142 objs.append(deactivatereq)
143 else:
144 # In the case of an error we persist the state of the object directly to preserve
145 # the error code - and because that is how the base synchronizer is designed
146 deactivatereq.save()
147
148 # If we are enabled - and in our deletion pass then look for objects waiting for deletion
149 elif dev.administrativeState == 'enabled' and deletion is True:
150 logger.debug("NetworkDevice: administrativeState set to Enabled - deletion phase")
151
152 # Any object that is simply deleted in the model gets removed automatically - the synchronizer
153 # doesn't get involved - we just need to check for deleted objects in the domain and reflect that
154 # in the model
155 #
156 # Get the deleted objects from the provider
157 eventobjs = provider.get_deleted_objects()
158 for eventobj in eventobjs:
159 # Simply put in the queue for update - this will handle both new and changed objects
160 objs.append(eventobj)
161
162 # In add cases return the objects we are interested in
163 return objs
164
165 def sync_record(self, o):
166 # Simply save the record to the DB - both updates and adds are handled the same way
167 o.save()
168
169 def delete_record(self, o):
170 # Overriden to customize our behaviour - the core sync step for will remove the record directly
171 # We just log and return
172 logger.debug("deleting Object %s" % str(o), extra=o.tologdict())
173
174 def get_metronetwork_service(self):
175 # We only expect to have one of these objects in the system in the curent design
176 # So get the first element from the query
177 metronetworkservices = MetroNetworkService.get_service_objects().all()
178 if not metronetworkservices:
179 return None
180
181 return metronetworkservices[0]