@@ -203,10 +203,13 @@ def loadbalancer_create(self, loadbalancer):
203203 if not isinstance (loadbalancer .pools , o_datamodels .UnsetType ):
204204 for pool in loadbalancer .pools :
205205 self .pool_create (pool )
206- for member in pool .members :
207- if not member .subnet_id :
208- member .subnet_id = loadbalancer .vip_subnet_id
209- self .member_create (member )
206+ members = [
207+ member if member .subnet_id else setattr (
208+ member , "subnet_id" , loadbalancer .vip_subnet_id ) or
209+ member
210+ for member in pool .members
211+ ]
212+ self ._members_create (members )
210213
211214 def loadbalancer_delete (self , loadbalancer , cascade = False ):
212215 request_info = {'id' : loadbalancer .loadbalancer_id ,
@@ -259,8 +262,8 @@ def pool_delete(self, pool):
259262 if pool .healthmonitor :
260263 self .health_monitor_delete (pool .healthmonitor )
261264
262- for member in pool .members :
263- self .member_delete ( member )
265+ if pool .members :
266+ self ._members_delete ( pool . members )
264267
265268 request_info = {'id' : pool .pool_id ,
266269 'protocol' : pool .protocol ,
@@ -373,88 +376,108 @@ def _ip_version_differs(self, member):
373376 return vip_version != (netaddr .IPNetwork (member .address ).version )
374377
375378 def member_create (self , member ):
376- # Validate monitoring options if present
377- self ._check_member_monitor_options (member )
378- if self ._ip_version_differs (member ):
379- raise ovn_exc .IPVersionsMixingNotSupportedError ()
380- admin_state_up = member .admin_state_up
381- subnet_id = member .subnet_id
382- if (isinstance (subnet_id , o_datamodels .UnsetType ) or not subnet_id ):
383- subnet_id , subnet_cidr = self ._ovn_helper ._get_subnet_from_pool (
384- member .pool_id )
385- if not (subnet_id and
386- self ._ovn_helper ._check_ip_in_subnet (member .address ,
387- subnet_cidr )):
388- msg = _ ('Subnet is required, or Loadbalancer associated with '
389- 'Pool must have a subnet, for Member creation '
390- 'with OVN Provider Driver if it is not the same as '
391- 'LB VIP subnet' )
392- raise driver_exceptions .UnsupportedOptionError (
393- user_fault_string = msg ,
394- operator_fault_string = msg )
379+ self ._members_create ([member ])
380+
381+ def _members_create (self , members ):
382+ request_info = []
383+ request_info_dvr = []
384+ for member in members :
385+ # Validate monitoring options if present
386+ self ._check_member_monitor_options (member )
387+ if self ._ip_version_differs (member ):
388+ raise ovn_exc .IPVersionsMixingNotSupportedError ()
389+ admin_state_up = member .admin_state_up
390+ subnt_id = member .subnet_id
391+ if (isinstance (subnt_id , o_datamodels .UnsetType ) or
392+ not subnt_id ):
393+ subnt_id , subnt_cidr = self ._ovn_helper ._get_subnet_from_pool (
394+ member .pool_id )
395+
396+ if not (subnt_id and
397+ self ._ovn_helper ._check_ip_in_subnet (member .address ,
398+ subnt_cidr )):
399+ msg = _ ('Subnet is required, or Loadbalancer associated '
400+ 'with Pool must have a subnet, for Member '
401+ 'creation with OVN Provider Driver if it is not '
402+ 'the same as LB VIP subnet' )
403+ raise driver_exceptions .UnsupportedOptionError (
404+ user_fault_string = msg ,
405+ operator_fault_string = msg )
406+
407+ if isinstance (admin_state_up , o_datamodels .UnsetType ):
408+ admin_state_up = True
409+ request_info .append ({'id' : member .member_id ,
410+ 'address' : member .address ,
411+ 'protocol_port' : member .protocol_port ,
412+ 'pool_id' : member .pool_id ,
413+ 'subnet_id' : subnt_id ,
414+ 'admin_state_up' : admin_state_up })
415+
416+ # NOTE(mjozefcz): If LB has FIP on VIP
417+ # and member has FIP we need to centralize
418+ # traffic for member.
419+ request_info_dvr .append ({'id' : member .member_id ,
420+ 'address' : member .address ,
421+ 'pool_id' : member .pool_id ,
422+ 'subnet_id' : subnt_id ,
423+ 'action' : ovn_const .REQ_INFO_MEMBER_ADDED }
424+ )
395425
396- if isinstance (admin_state_up , o_datamodels .UnsetType ):
397- admin_state_up = True
398- request_info = {'id' : member .member_id ,
399- 'address' : member .address ,
400- 'protocol_port' : member .protocol_port ,
401- 'pool_id' : member .pool_id ,
402- 'subnet_id' : subnet_id ,
403- 'admin_state_up' : admin_state_up }
404426 request = {'type' : ovn_const .REQ_TYPE_MEMBER_CREATE ,
405427 'info' : request_info }
406428 self ._ovn_helper .add_request (request )
407429
408- # NOTE(mjozefcz): If LB has FIP on VIP
409- # and member has FIP we need to centralize
410- # traffic for member.
411- request_info = {'id' : member .member_id ,
412- 'address' : member .address ,
413- 'pool_id' : member .pool_id ,
414- 'subnet_id' : subnet_id ,
415- 'action' : ovn_const .REQ_INFO_MEMBER_ADDED }
416430 request = {'type' : ovn_const .REQ_TYPE_HANDLE_MEMBER_DVR ,
417- 'info' : request_info }
431+ 'info' : request_info_dvr }
418432 self ._ovn_helper .add_request (request )
419433
420434 def member_delete (self , member ):
435+ self ._members_delete ([member ])
436+
437+ def _members_delete (self , members ):
421438 # NOTE(froyo): OVN provider allow to create member without param
422439 # subnet_id, in that case the driver search it according to the
423440 # pool_id, but it is not propagated to Octavia. In this case, if
424441 # the member is deleted, Octavia send the object without subnet_id.
425- subnet_id = member .subnet_id
426- if (isinstance (subnet_id , o_datamodels .UnsetType ) or not subnet_id ):
427- subnet_id , subnet_cidr = self ._ovn_helper ._get_subnet_from_pool (
428- member .pool_id )
429- if not (subnet_id and
430- self ._ovn_helper ._check_ip_in_subnet (member .address ,
431- subnet_cidr )):
432- msg = _ ('Subnet is required, or Loadbalancer associated with '
433- 'Pool must have a subnet, for Member deletion if it is'
434- 'with OVN Provider Driver if it is not the same as '
435- 'LB VIP subnet' )
436- raise driver_exceptions .UnsupportedOptionError (
437- user_fault_string = msg ,
438- operator_fault_string = msg )
442+ request_info = []
443+ request_info_dvr = []
444+ for member in members :
445+ subnt_id = member .subnet_id
446+ if (isinstance (subnt_id , o_datamodels .UnsetType ) or not subnt_id ):
447+ subnt_id , subnt_cidr = self ._ovn_helper ._get_subnet_from_pool (
448+ member .pool_id )
449+ if not (subnt_id and
450+ self ._ovn_helper ._check_ip_in_subnet (member .address ,
451+ subnt_cidr )):
452+ msg = _ ('Subnet is required, or Loadbalancer associated '
453+ 'with Pool must have a subnet, for Member '
454+ 'deletion if it is with OVN Provider Driver if it '
455+ 'is not the same as LB VIP subnet' )
456+ raise driver_exceptions .UnsupportedOptionError (
457+ user_fault_string = msg ,
458+ operator_fault_string = msg )
459+
460+ request_info .append ({'id' : member .member_id ,
461+ 'address' : member .address ,
462+ 'protocol_port' : member .protocol_port ,
463+ 'pool_id' : member .pool_id ,
464+ 'subnet_id' : subnt_id })
465+ # NOTE(mjozefcz): If LB has FIP on VIP
466+ # and member had FIP we can decentralize
467+ # the traffic now.
468+ request_info_dvr .append (
469+ {'id' : member .member_id ,
470+ 'address' : member .address ,
471+ 'pool_id' : member .pool_id ,
472+ 'subnet_id' : subnt_id ,
473+ 'action' : ovn_const .REQ_INFO_MEMBER_DELETED })
439474
440- request_info = {'id' : member .member_id ,
441- 'address' : member .address ,
442- 'protocol_port' : member .protocol_port ,
443- 'pool_id' : member .pool_id ,
444- 'subnet_id' : subnet_id }
445475 request = {'type' : ovn_const .REQ_TYPE_MEMBER_DELETE ,
446476 'info' : request_info }
447477 self ._ovn_helper .add_request (request )
448- # NOTE(mjozefcz): If LB has FIP on VIP
449- # and member had FIP we can decentralize
450- # the traffic now.
451- request_info = {'id' : member .member_id ,
452- 'address' : member .address ,
453- 'pool_id' : member .pool_id ,
454- 'subnet_id' : subnet_id ,
455- 'action' : ovn_const .REQ_INFO_MEMBER_DELETED }
478+
456479 request = {'type' : ovn_const .REQ_TYPE_HANDLE_MEMBER_DVR ,
457- 'info' : request_info }
480+ 'info' : request_info_dvr }
458481 self ._ovn_helper .add_request (request )
459482
460483 def member_update (self , old_member , new_member ):
@@ -470,7 +493,7 @@ def member_update(self, old_member, new_member):
470493 if not isinstance (new_member .admin_state_up , o_datamodels .UnsetType ):
471494 request_info ['admin_state_up' ] = new_member .admin_state_up
472495 request = {'type' : ovn_const .REQ_TYPE_MEMBER_UPDATE ,
473- 'info' : request_info }
496+ 'info' : [ request_info ] }
474497 self ._ovn_helper .add_request (request )
475498
476499 def member_batch_update (self , pool_id , members ):
@@ -482,6 +505,10 @@ def member_batch_update(self, pool_id, members):
482505 members_to_delete = copy .copy (existing_members )
483506 pool_subnet_id = None
484507 pool_subnet_cidr = None
508+ request_info_create = []
509+ request_info_update = []
510+ request_info_delete = []
511+ request_info_dvr_delete = []
485512 for member in members :
486513 # NOTE(froyo): in order to keep sync with Octavia DB, we raise
487514 # not supporting exceptions as soon as posible, considering the
@@ -520,49 +547,65 @@ def member_batch_update(self, pool_id, members):
520547 admin_state_up = True
521548
522549 member_info = self ._ovn_helper ._get_member_info (member )
550+ request_info = {
551+ 'id' : member .member_id ,
552+ 'address' : member .address ,
553+ 'protocol_port' : member .protocol_port ,
554+ 'pool_id' : member .pool_id ,
555+ 'subnet_id' : member .subnet_id ,
556+ 'admin_state_up' : admin_state_up }
557+
523558 if member_info not in existing_members :
524- req_type = ovn_const . REQ_TYPE_MEMBER_CREATE
559+ request_info_create . append ( request_info )
525560 else :
526561 # If member exists in pool, then Update
527- req_type = ovn_const . REQ_TYPE_MEMBER_UPDATE
562+ request_info_update . append ( request_info )
528563 # Remove all updating members so only deleted ones are left
529564 members_to_delete .remove (member_info )
530565
531- request_info = {'id' : member .member_id ,
532- 'address' : member .address ,
533- 'protocol_port' : member .protocol_port ,
534- 'pool_id' : member .pool_id ,
535- 'subnet_id' : member .subnet_id ,
536- 'admin_state_up' : admin_state_up }
537- request = {'type' : req_type ,
538- 'info' : request_info }
539- request_list .append (request )
540-
541566 for member in members_to_delete :
542567 member_info = member .split ('_' )
543568 member_ip , member_port , subnet_id , member_id = (
544569 self ._ovn_helper ._extract_member_info (member )[0 ])
545- request_info = {'id' : member_info [1 ],
546- 'address' : member_ip ,
547- 'protocol_port' : member_port ,
548- 'pool_id' : pool_id }
570+ request_info = {
571+ 'id' : member_info [1 ],
572+ 'address' : member_ip ,
573+ 'protocol_port' : member_port ,
574+ 'pool_id' : pool_id }
549575 if len (member_info ) == 4 :
550576 request_info ['subnet_id' ] = subnet_id
551- request = {'type' : ovn_const .REQ_TYPE_MEMBER_DELETE ,
552- 'info' : request_info }
553- request_list .append (request )
577+ request_info_delete .append (request_info )
554578
555579 # NOTE(mjozefcz): If LB has FIP on VIP
556580 # and member had FIP we can decentralize
557581 # the traffic now.
558- request_info = {'id' : member_id ,
559- 'address' : member_ip ,
560- 'pool_id' : pool_id ,
561- 'action' : ovn_const .REQ_INFO_MEMBER_DELETED }
582+ request_info = {
583+ 'id' : member_id ,
584+ 'address' : member_ip ,
585+ 'pool_id' : pool_id ,
586+ 'action' : ovn_const .REQ_INFO_MEMBER_DELETED }
562587 if len (member_info ) == 4 :
563588 request_info ['subnet_id' ] = subnet_id
589+ request_info_dvr_delete .append (request_info )
590+
591+ if request_info_create :
592+ request = {'type' : ovn_const .REQ_TYPE_MEMBER_CREATE ,
593+ 'info' : request_info_create }
594+ request_list .append (request )
595+
596+ if request_info_update :
597+ request = {'type' : ovn_const .REQ_TYPE_MEMBER_UPDATE ,
598+ 'info' : request_info_update }
599+ request_list .append (request )
600+
601+ if request_info_delete :
602+ request = {'type' : ovn_const .REQ_TYPE_MEMBER_DELETE ,
603+ 'info' : request_info_delete }
604+ request_list .append (request )
605+
606+ if request_info_dvr_delete :
564607 request = {'type' : ovn_const .REQ_TYPE_HANDLE_MEMBER_DVR ,
565- 'info' : request_info }
608+ 'info' : request_info_dvr_delete }
566609 request_list .append (request )
567610
568611 for request in request_list :
0 commit comments