@@ -367,6 +367,64 @@ def _schedule_agent_and_device(self, context, loadbalancer,
367367
368368 return agent , device
369369
370+ # use separate schedule as the schedule becomes more complicated;
371+ # it may reschedule agent; but use device even if admin_state_down
372+ def _schedule_agent_and_device_4_purge (
373+ self , context , loadbalancer , device_id_passed = None
374+ ):
375+ '''Schedule agent and device only used for purge'''
376+
377+ LAB = agent_scheduler .LoadbalancerAgentBinding
378+
379+ # If LB is already hosted on an agent, return this agent and device
380+ result = self .driver .plugin .db .get_agent_hosting_loadbalancer (
381+ context , loadbalancer .id )
382+
383+ if result :
384+ agent = result ["agent" ]
385+ if not agent ["alive" ] or not agent ["admin_state_up" ]:
386+ # Agent is not alive or is disabled. Attempt to
387+ # reschedule this loadbalancer to a new agent.
388+ LOG .info ("Reschedule loadbalancer %s" , loadbalancer .id )
389+ agent = self .driver .agent_scheduler .schedule (
390+ self .driver .plugin ,
391+ context ,
392+ loadbalancer ,
393+ self .driver .env
394+ )
395+ # Update binding table
396+ with context .session .begin (subtransactions = True ):
397+ query = context .session .query (LAB )
398+ binding = query .get (loadbalancer .id )
399+ binding .agent_id = agent ["id" ]
400+ LOG .info ("Loadbalancer %s is rescheduled to agent %s" ,
401+ loadbalancer .id , agent .id )
402+
403+ # Load device info and return
404+ if device_id_passed :
405+ LOG .warn ("using passed device %s to purge" , device_id_passed ) # noqa
406+ device_id = device_id_passed
407+ else :
408+ device_id = result ["device_id" ]
409+
410+ device = self .driver .device_scheduler .load_device (
411+ context , device_id
412+ )
413+
414+ # skipped checking admin_state_up based on discussion
415+ if device :
416+ LOG .debug ("using device %s here for purge" , device_id )
417+ return agent , device
418+ else :
419+ raise device_scheduler .LbaasDeviceNotUsable (
420+ device_id = device_id
421+ )
422+ else :
423+ raise Exception (
424+ "No binding information for loadbalancer %s" ,
425+ loadbalancer .id
426+ )
427+
370428 def _create_service (self , context , loadbalancer , agent ,
371429 entity = None , ** kwargs ):
372430 '''build service--used for most managers.
@@ -644,6 +702,55 @@ def refresh(self, context, body):
644702 self ._handle_entity_error (context , loadbalancer .id )
645703 raise e
646704
705+ @log_helpers .log_method_call
706+ def purge (self , context , body ):
707+ """Purge a loadbalancer from device without touching DB data."""
708+
709+ lbext = body ["loadbalancerext" ]
710+ loadbalancer = lbext ["loadbalancer" ]
711+
712+ self ._log_entity (loadbalancer )
713+ driver = self .driver
714+
715+ device_id_passed = None
716+
717+ try :
718+ if lbext .get ("device" , None ):
719+ device_id_passed = lbext ["device" ]
720+ LOG .warning ('device passed from args. Trying to use it!' )
721+
722+ agent , device = self ._schedule_agent_and_device_4_purge (
723+ context , loadbalancer , device_id_passed = device_id_passed
724+ )
725+
726+ service = self ._create_service (context , loadbalancer , agent )
727+ service ["device" ] = device
728+
729+ agent_host = agent ['host' ]
730+ self ._allocate_acl_groups (context , service )
731+
732+ driver .agent_rpc .purge_loadbalancer (
733+ context , loadbalancer .to_api_dict (), service , agent_host
734+ )
735+
736+ except device_scheduler .LbaasDeviceNotUsable :
737+ LOG .error ("device_id for the lb is not usable" )
738+ LOG .error ("Pls check its status. Purge unsuccessful here." )
739+ # update its status to active here although it's not purged
740+ self .driver .plugin .db .update_status (
741+ context , models .LoadBalancer ,
742+ loadbalancer .id , plugin_constants .ACTIVE
743+ )
744+ raise
745+
746+ except Exception as e :
747+ LOG .error ("Exception: loadbalancer purge: %s" % e .message )
748+ self .driver .plugin .db .update_status (
749+ context , models .LoadBalancer ,
750+ loadbalancer .id , plugin_constants .ERROR
751+ )
752+ raise e
753+
647754 def _allocate_acl_groups (self , context , service ):
648755
649756 # for compatibility with pipeline test only.
0 commit comments