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