blob: 97b16042e8980412df41d9f1094dc5b1ae955f6b [file] [log] [blame]
Rizwan Haider51fdb3f2016-11-09 18:29:32 -05001import os
2import sys
3
4from synchronizers.base.syncstep import SyncStep
5from synchronizers.vnodlocal.pseudowireproviders.providerfactory import ProviderFactory
6from services.vnodlocal.models import *
7
8from xos.logger import Logger, logging
9
10# vnod local will be in steps/..
11parentdir = os.path.join(os.path.dirname(__file__), "..")
12sys.path.insert(0, parentdir)
13
14logger = Logger(level=logging.INFO)
15
16
17class SyncVnodLocalPseudowireConnectorServiceSystem(SyncStep):
18 provides = [VnodLocalPseudowireConnectorService]
19 observes = VnodLocalPseudowireConnectorService
20 requested_interval = 0
21 initialized = False
22
23 def __init__(self, **args):
24 SyncStep.__init__(self, **args)
25
26 def fetch_pending(self, deletion=False):
27 logger.info("VnodLocalPseudowireConnector fetch pending called")
28
29 # Some comments to replace as we write the code
30
31 # The AdministrativeState state machine:
32 #
33 #
34 # Disabled---------DeactivationRequested
35 # \ |
36 # ActivationRequested |
37 # / / \ |
38 # / / \ |
39 # ActivationFailed Enabled -----------
40 #
41 #
42
43 # The OperationalState state machine
44 #
45 # active
46 # |
47 # inactive
48
49 objs = []
50
51
52 # The whole thing needs to be conditional on the VnodLocalSystem existing and being 'enabled'
53 # This is the 'kill switch' in the system that is the first thing to check
54 vnodlocalsystem = self.get_vnodlocal_system()
55 if not vnodlocalsystem:
56 logger.debug("No VnodLocal System Configured, skipping sync")
57 return objs
58
59 # Check to make sure the Metro Network System is enabled
60 if vnodlocalsystem.administrativeState == 'disabled':
61 # Nothing to do
62 logger.debug("VnodLocal System configured - state is Disabled, skipping sync")
63 return objs
64
65
66
67 # Handle call when deletion is False
68 if deletion is False:
69
70 # Check for admin status 'ActivationRequested'
71 activationreqs = VnodLocalPseudowireConnectorService.objects.filter(administrativeState='activationrequested')
72 for activationreq in activationreqs:
73 # Handle the case where we don't yet have a VnodLocalSerive
74 if activationreq.vnodlocal is None:
75 # Create VnodLocalService
76 # We save the changes right here in this case to avoid having to to 'pre-save' semnatics
77 # to cover the foreign key
78 vnodlocalservice = VnodLocalService()
79 vnodlocalservice.servicehandle = activationreq.servicehandle
80 vnodlocalservice.administrativeState = 'configurationrequested'
81 vnodlocalservice.save()
82 activationreq.vnodlocal = vnodlocalservice
83 activationreq.save()
84 elif activationreq.vnodlocal.administrativeState == 'configured':
85 # Once the underlying VnodLocal is configured then activated it
86 vnodlocalservice = activationreq.vnodlocal
87 # Call our underlying provider to connect the pseudo wire
88 self.activate_pseudowire(activationreq, vnodlocalsystem)
89 activationreq.administrativeState = 'enabled'
90 activationreq.operstate = 'active'
91 objs.append(activationreq)
92 vnodlocalservice.administrativeState = 'activationrequested'
93 vnodlocalservice.operstate = 'activereported'
94 objs.append(vnodlocalservice)
95
96
97 # Check for admin status 'DeactivationRequested'
98 deactivationreqs = VnodLocalPseudowireConnectorService.objects.filter(administrativeState='deactivationrequested')
99 for deactivationreq in deactivationreqs:
100 # Call the XOS Interface to de-actiavte the spoke
101 logger.debug("Attempting to de-activate VnodLocalService servicehandle: %s" % deactivationreq.servicehandle)
102 # De-activate the underlying service
103 vnodlocalservice = deactivationreq.vnodlocal
104 # Call our underlying provider to connect the pseudo wire
105 self.deactivate_pseudowire(deactivationreq)
106 deactivationreq.administrativeState = 'disabled'
107 deactivationreq.operstate = 'inactive'
108 objs.append(deactivationreq)
109 vnodlocalservice.administrativeState = 'deactivationrequested'
110 objs.append(vnodlocalservice)
111
112
113 elif deletion:
114 # Apply Deletion Semantics:
115 logger.debug("Applying Deletion Semanctics")
116 # TODO: Figure out the odd scenario of Service deletion
117 deletedobjs = VnodLocalPseudowireConnectorService.deleted_objects.all()
118
119 # Delete the underlying VnodLocalService objects
120 for deletedobj in deletedobjs:
121 # Set the VnodLocal to Deleted - its Synchronizer will take care of deletion
122 vnodlocalobj = deletedobj.vnodlocal
123 vnodlocalobj.deleted = True
124 vnodlocalobj.save()
125 # Delete the underlying pseudowire
126 self.delete_pseudowire(deletedobj)
127 # Finally - add the Service for deletion
128 objs.append(deletedobj)
129
130 # Finally just return the set of changed objects
131 return objs
132
133
134 def sync_record(self, o):
135
136 # Simply save the record to the DB - both updates and adds are handled the same way
137 o.save()
138
139
140 def delete_record(self, o):
141 # Overriden to customize our behaviour - the core sync step for will remove the record directly
142 # We just log and return
143 logger.debug("deleting Object %s" % str(o), extra=o.tologdict())
144
145 def get_vnodlocal_system(self):
146 # We only expect to have one of these objects in the system in the curent design
147 # So get the first element from the query
148 vnodlocalsystems = VnodLocalSystem.objects.all()
149 if not vnodlocalsystems:
150 return None
151
152 return vnodlocalsystems[0]
153
154 def activate_pseudowire(self, o, vnodlocalsystem):
155 # Call the underlying pseudowire provicers and call
156 logger.debug("activating pseudowire %s" % o.servicehandle)
157
158 pseudowireprovier = ProviderFactory.getprovider()
159
160 if pseudowireprovier is not None:
161 # Pass it the two ports - the internal port configured on the Pseudowire and the NNI port from
162 # the VnodLocal
163 if o.pseudowirehandle == '':
164 o.pseudowirehandle = pseudowireprovier.create(o.internalport, o.vnodlocal.portid, o.vnodlocal.vlanid, vnodlocalsystem)
165
166 # handle already exists - just connect it
167 pseudowireprovier.connect(o.pseudowirehandle)
168 else:
169 # No Provider configured - lets put a handle that reflects thsi
170 o.pseudowirehandle = 'No Pseudowire Provider configured'
171
172
173 def deactivate_pseudowire(self, o):
174 # Call the underlying pseudowire provicers and call
175 logger.debug("deactivating pseudowire %s" % o.servicehandle)
176
177 pseudowireprovier = ProviderFactory.getprovider()
178
179 if pseudowireprovier is not None:
180 # Pass it the handle
181 pseudowireprovier.disconnect(o.pseudowirehandle)
182
183
184 def delete_pseudowire(self, o):
185 # Call the underlying pseudowire provicers and call
186 logger.debug("deleting pseudowire %s" % o.servicehandle)
187
188 pseudowireprovier = ProviderFactory.getprovider()
189
190 if pseudowireprovier is not None:
191 # Pass it the handle
192 if o.pseudowirehandle != '':
193 pseudowireprovier.delete(o.pseudowirehandle)
194
195 # Either way blank out the handle name
196 o.pseudowirehandle = ''