@@ -212,6 +212,113 @@ def update_health(self, health):
212212 LOG .error (_LE ("Load balancer %s is not in DB" ), lb_id )
213213
214214
215+ class UpdateDistributorHealthDb (object ):
216+ def __init__ (self ):
217+ super (UpdateDistributorHealthDb , self ).__init__ ()
218+ self .event_streamer = stevedore_driver .DriverManager (
219+ namespace = 'octavia.controller.queues' ,
220+ name = cfg .CONF .health_manager .event_streamer_driver ,
221+ invoke_on_load = True ).driver
222+ self .loadbalancer_repo = repo .LoadBalancerRepository ()
223+ self .distributor_repo = repo .DistributorRepository ()
224+
225+ def emit (self , info_type , info_id , info_obj ):
226+ cnt = update_serializer .InfoContainer (info_type , info_id , info_obj )
227+ self .event_streamer .emit (cnt )
228+
229+ def update_distributor_health (self , health ):
230+ """This function is to update db info based on amphora status
231+
232+ :type health: dict
233+ :param health: map object that contains distributor, amphora info
234+
235+ The input health data structure is shown as below:
236+
237+ health = {
238+ "distributor-id": self.FAKE_UUID_1,
239+ "provisioning-state": {
240+ "state": service provisioning status,
241+ "reason": str
242+ }
243+ "loadbalancers": {
244+ "lb-id-1": {
245+ "status": instance provisioning status
246+ "size": int
247+ "registered": int
248+ }
249+ }
250+ }
251+
252+ """
253+ session = db_api .get_session ()
254+ distributor_id = health ['distributor_id' ]
255+ distributor_state = health ['provisioning_state' ]['state' ]
256+ if distributor_state == constants .DISTRIBUTOR_BOOTING :
257+ LOG .debug ("Distributor %s is still booting -- skipping"
258+ " health message." , distributor_id )
259+ # nothing to report
260+ return
261+ elif distributor_state == constants .DISTRIBUTOR_FULL :
262+ # @TODO handle FULL state -- eg, set quota limit
263+ LOG .warning (_LW ("Distributor %s is unavailable for new"
264+ " requests." ),
265+ distributor_id )
266+ elif distributor_state == constants .DISTRIBUTOR_ERROR :
267+ LOG .warning (_LW ("Distributor %s is in error state" ),
268+ distributor_id )
269+ # @TODO set state of distributor so it is recycled
270+
271+ expected_lbs = self .distributor_repo .get_all_lbs_on_distributor (
272+ session , distributor_id )
273+ reported_lbs = health .get ('loadbalancers' , {})
274+
275+ if any (lb not in expected_lbs for lb in reported_lbs ):
276+ LOG .warning (_LW ("Distributor %s reported unexpected"
277+ " loadbalancer ids" ), distributor_id )
278+ # @TODO something is wrong here we should recycle
279+
280+ # NO_MONITOR for all missing lbs
281+ reported_lbs .update (
282+ (lb , {'status' : constants .NO_MONITOR })
283+ for lb in expected_lbs if lb not in reported_lbs )
284+
285+ # do actual update per lb
286+ for lb_id , lb in six .iteritems (reported_lbs ):
287+ try :
288+ lb_in_db = self .loadbalancer_repo .get (session , id = lb_id )
289+ except sqlalchemy .orm .exc .NoResultFound :
290+ LOG .error (_LE ("Load balancer %s is not in DB" ), lb_id )
291+ continue
292+
293+ reported_lb_op_status = lb ['status' ]
294+ if (reported_lb_op_status == constants .ERROR or
295+ distributor_state == constants .DISTRIBUTOR_ERROR ):
296+ # Distributor error currently sets all LBs to error too.
297+ # This is conservative. Could try to recycle Distributor
298+ # without recycling the LBs
299+ new_lb_op_status = constants .ERROR
300+ elif (reported_lb_op_status == constants .DEGRADED and
301+ lb_in_db .operating_status == constants .ONLINE ):
302+ new_lb_op_status = constants .DEGRADED
303+ elif (reported_lb_op_status == constants .NO_MONITOR and
304+ lb_in_db .operating_status == constants .ONLINE ):
305+ # @TODO Ignoring for now. Should we do anything here?
306+ new_lb_op_status = None
307+ else :
308+ new_lb_op_status = None
309+ # @TODO verify size and registered
310+ if new_lb_op_status :
311+ LOG .debug ("%s %s status has changed from %s to "
312+ "%s. Updating db and sending event." ,
313+ constants .LOADBALANCER , lb_id ,
314+ lb_in_db .operating_status ,
315+ new_lb_op_status )
316+ self .loadbalancer_repo .update (
317+ session , lb_id , operating_status = new_lb_op_status )
318+ self .emit (constants .LOADBALANCER , lb_id ,
319+ {constants .OPERATING_STATUS : new_lb_op_status })
320+
321+
215322class UpdateStatsDb (stats .StatsMixin ):
216323
217324 def __init__ (self ):
0 commit comments