@@ -60,7 +60,7 @@ def _dealloc_ae_id(cls, prouter_name, ae_id, vpg_name):
6060 return dealloc_dict
6161
6262 @classmethod
63- def _process_alloc_ae_id (cls , obj_dict , db_obj_dict , vpg_name ):
63+ def _process_alloc_ae_id (cls , db_obj_dict , vpg_name , obj_dict = None ):
6464 attr_dict = None
6565 alloc_dealloc_dict = {'allocated_ae_id' : [], 'deallocated_ae_id' : []}
6666 alloc_list = []
@@ -70,7 +70,9 @@ def _process_alloc_ae_id(cls, obj_dict, db_obj_dict, vpg_name):
7070 db_pi_dict = {}
7171 db_pr_dict = {}
7272 extra_deallocate_dict = {}
73- vpg_uuid = obj_dict ['uuid' ]
73+ vpg_uuid = db_obj_dict ['uuid' ]
74+ if not obj_dict :
75+ obj_dict = {}
7476
7577 # process incoming PIs
7678 for ref in obj_dict .get ('physical_interface_refs' ) or []:
@@ -95,7 +97,7 @@ def _process_alloc_ae_id(cls, obj_dict, db_obj_dict, vpg_name):
9597 return True , (attr_dict , alloc_dealloc_dict )
9698
9799 # nothing to delete, because rest of PIs shares same PR
98- if (len (create_pi_uuids ) == 0 and len (delete_pi_uuids ) > = 1 and
100+ if (len (create_pi_uuids ) == 0 and len (delete_pi_uuids ) = = 1 and
99101 len (db_pr_dict .keys ()) == 1 and len (db_pi_dict .keys ()) > 2 ):
100102 return True , (attr_dict , alloc_dealloc_dict )
101103
@@ -108,42 +110,86 @@ def _process_alloc_ae_id(cls, obj_dict, db_obj_dict, vpg_name):
108110 # allocate
109111 attr_dict , _alloc_dict = cls ._alloc_ae_id (pi_pr , vpg_name )
110112 alloc_dealloc_dict ['allocated_ae_id' ].append (_alloc_dict )
113+ msg = "Allocating AE-ID(%s) for PI(%s) at VPG(%s)/PR(%s)" % (
114+ attr_dict , pi_uuid , vpg_name , pi_pr )
115+ cls .db_conn .config_log (msg , level = SandeshLevel .SYS_INFO )
111116 else :
112117 attr_dict = pi_ae
113118
114119 # re-allocate existing single PI if any
115120 if (len (db_pi_dict .keys ()) == 1 and len (create_pi_uuids ) == 1 ):
116121 db_pi_uuid = db_pi_dict .keys ()[0 ]
117- if (db_pi_dict .values ()[0 ] != curr_pi_dict .values () [0 ]):
122+ if (db_pi_dict .values ()[0 ] != curr_pi_dict .get ( create_pi_uuids [0 ]) ):
118123 # allocate a new ae-id as it belongs to different PR
119124 db_pr = db_pi_dict .values ()[0 ]
120- attr_dict , _alloc_dict = cls ._alloc_ae_id (db_pr , vpg_name )
125+ attr_dict_leftover_pi , _alloc_dict = cls ._alloc_ae_id (db_pr , vpg_name )
121126 alloc_dealloc_dict ['allocated_ae_id' ].append (_alloc_dict )
127+ msg = "Allocating AE-ID(%s) for PI(%s) at VPG(%s)/PR(%s)" % (
128+ attr_dict_leftover_pi , db_pi_uuid , vpg_name , db_pr )
129+ cls .db_conn .config_log (msg , level = SandeshLevel .SYS_INFO )
130+ else :
131+ attr_dict_leftover_pi = attr_dict
132+ msg = "Re-using AE-ID(%s) for PI(%s) at VPG(%s)/PR(%s)" % (
133+ attr_dict_leftover_pi , db_pi_uuid , vpg_name , pi_pr )
134+ cls .db_conn .config_log (msg , level = SandeshLevel .SYS_INFO )
122135 (ok , result ) = cls .db_conn .ref_update (
123136 'virtual_port_group' ,
124137 vpg_uuid ,
125138 'physical_interface' ,
126139 db_pi_uuid ,
127- {'attr' : attr_dict },
140+ {'attr' : attr_dict_leftover_pi },
128141 'ADD' ,
129142 db_obj_dict .get ('id_perms' ),
130143 attr_to_publish = None ,
131144 relax_ref_for_delete = True )
145+ msg = "Updated AE-ID(%s) in PI(%s) ref to VPG(%s)" % (
146+ attr_dict_leftover_pi , db_pi_uuid , vpg_name )
147+ cls .db_conn .config_log (msg , level = SandeshLevel .SYS_INFO )
132148
133149 # deallocate case
150+ _in_dealloc_list = []
134151 for pi_uuid in delete_pi_uuids :
135152 pi_pr = db_pi_dict .get (pi_uuid )
136153 pi_ae = db_pr_dict .get (pi_pr )
137- if pi_ae is not None :
154+ db_pi_prs = db_pi_dict .values ().count (pi_pr )
155+ # PR/VPG is already considered for deallocation, so no need
156+ # to dealloc again
157+ if '%s:%s' % (pi_pr , vpg_name ) in _in_dealloc_list :
158+ continue
159+ if (pi_ae is not None and (db_pi_prs < 2 or
160+ len (delete_pi_uuids ) > 1 )):
138161 ae_id = pi_ae .get ('ae_num' )
139162 # de-allocate
140163 _dealloc_dict = cls ._dealloc_ae_id (pi_pr , ae_id , vpg_name )
141164 alloc_dealloc_dict ['deallocated_ae_id' ].append (_dealloc_dict )
165+ # record deallocated pr/vpg
166+ _in_dealloc_list .append ('%s:%s' % (pi_pr , vpg_name ))
167+ msg = "Deallocated AE-ID(%s) for PI(%s) at VPG(%s)/PR(%s)" % (
168+ ae_id , pi_uuid , vpg_name , pi_pr )
169+ cls .db_conn .config_log (msg , level = SandeshLevel .SYS_INFO )
142170
143171 # de-allocate leftover single PI, if any
172+ # in delete case, whatever comes in curr_pi_dict are the
173+ # leftovers because for delete refs, ref to be deleted
174+ # will not be coming in payload
144175 if (len (curr_pi_dict .keys ()) == 1 and
145176 len (db_pi_dict .keys ()) == len (delete_pi_uuids ) + 1 ):
146177 pi_uuid = curr_pi_dict .keys ()[0 ]
178+ pi_pr = curr_pi_dict .get (pi_uuid )
179+ pi_ae = curr_pr_dict .get (pi_pr )
180+ if '%s:%s' % (pi_pr , vpg_name ) not in _in_dealloc_list :
181+ if pi_ae is not None :
182+ ae_id = pi_ae .get ('ae_num' )
183+ _dealloc_dict = cls ._dealloc_ae_id (pi_pr , ae_id , vpg_name )
184+ alloc_dealloc_dict ['deallocated_ae_id' ].append (
185+ _dealloc_dict )
186+ # record deallocated pr/vpg
187+ _in_dealloc_list .append ('%s:%s' % (pi_pr , vpg_name ))
188+ msg = ("Deallocated AE-ID(%s) from leftover PI(%s) at "
189+ "VPG(%s)/PR(%s)" % (
190+ ae_id , pi_uuid , vpg_name , pi_pr ))
191+ cls .db_conn .config_log (msg , level = SandeshLevel .SYS_INFO )
192+ pi_ae = db_pr_dict .get (pi_pr )
147193 (ok , result ) = cls .db_conn .ref_update (
148194 'virtual_port_group' ,
149195 vpg_uuid ,
@@ -253,13 +299,24 @@ def update_physical_intf_type(cls, obj_dict=None,
253299
254300 @classmethod
255301 def pre_dbe_create (cls , tenant_name , obj_dict , db_conn ):
302+ ret_val = ''
256303 if ('vpg-internal' in obj_dict ['fq_name' ][2 ] and
257304 obj_dict .get ('virtual_port_group_user_created' , True )):
258305 msg = "Virtual port group(%s) with name vpg-internal as prefix " \
259306 "can only be created internally" \
260307 % (obj_dict ['uuid' ])
261308 return False , (400 , msg )
262309
310+ # when PI refs are added to VPG object during create VPG.
311+ # stateful_create do not allow us to allocate AE-ID and
312+ # update them in PI object refs
313+ if obj_dict .get ('physical_interface_refs' ):
314+ msg = ("API Infra do not support allocating AE-ID when "
315+ "Physical Interface refs are sent in VPG create request. "
316+ "Workaround: Create VPG first, then add Physical "
317+ "Interface to VPG" )
318+ return False , (400 , msg )
319+
263320 if obj_dict .get ('virtual_port_group_trunk_port_id' ):
264321 primary_vmi_id = obj_dict .get ('virtual_port_group_trunk_port_id' )
265322 ok , result = db_conn .dbe_read (
@@ -282,7 +339,7 @@ def pre_dbe_create(cls, tenant_name, obj_dict, db_conn):
282339 if not ok :
283340 return ok , result
284341
285- return True , ''
342+ return True , ret_val
286343
287344 @classmethod
288345 def pre_dbe_update (cls , id , fq_name , obj_dict , db_conn , ** kwargs ):
@@ -302,21 +359,19 @@ def pre_dbe_update(cls, id, fq_name, obj_dict, db_conn, **kwargs):
302359 ok , res = cls .update_physical_intf_type (obj_dict , db_obj_dict )
303360 if not ok :
304361 return ok , res
305-
306- ok , res = cls ._process_alloc_ae_id (obj_dict , db_obj_dict , fq_name [- 1 ])
362+ ok , res = cls ._process_alloc_ae_id (db_obj_dict , fq_name [- 1 ], obj_dict )
307363 if not ok :
308364 return ok , res
309- else :
310- obj_dict .update (res [1 ])
311- if res [0 ] and kwargs .get ('ref_args' ):
312- kwargs ['ref_args' ]['data' ]['attr' ] = res [0 ]
313- ret_val = obj_dict
365+ if res [0 ] and kwargs .get ('ref_args' ):
366+ kwargs ['ref_args' ]['data' ]['attr' ] = res [0 ]
367+ ret_val = res [1 ]
314368
315369 return True , ret_val
316370 # end pre_dbe_update
317371
318372 @classmethod
319373 def pre_dbe_delete (cls , id , obj_dict , db_conn ):
374+ ret_val = ''
320375 # If the user deletes VPG, make sure that all the referring
321376 # VMIs are deleted.
322377 if obj_dict .get ('virtual_machine_interface_refs' ):
@@ -329,7 +384,15 @@ def pre_dbe_delete(cls, id, obj_dict, db_conn):
329384 if not ok :
330385 return (False , result , None )
331386
332- return True , '' , None
387+ if obj_dict .get ('physical_interface_refs' ):
388+ # release ae-ids associated with PIs attached to this VPG
389+ fq_name = obj_dict .get ('fq_name' )
390+ ok , res = cls ._process_alloc_ae_id (obj_dict , fq_name [- 1 ])
391+ if not ok :
392+ return (ok , res , None )
393+ ret_val = res [1 ]
394+
395+ return True , ret_val , None
333396
334397 @classmethod
335398 def post_dbe_delete (cls , id , obj_dict , db_conn ):
0 commit comments