Add a new lbaas agent Scheduler, LeastPoolAgentScheduler

LeastPoolAgentScheduler assigns a pool to an lbaas-agent
with the least number of pools. When there are multiple
lbaas-agents on multiple nodes, pools will be evenly
distributed over the agents. Thus this scheduler helps
the scalability of lbaas-agents serving large number of pools.
At the moment only available lbaas-agent scheduler is ChanceScheduler.

Co-Authored-By: Adam Harwell <flux.adam@gmail.com>
Change-Id: I0b920a8bb5b2918dd5f47ef2a81d3009896af47d
This commit is contained in:
Sungjin Yook 2015-05-08 19:42:13 -05:00 committed by Brandon Logan
parent 6caf97596e
commit 96afcd6879
4 changed files with 51 additions and 4 deletions

View File

@ -1,6 +1,7 @@
[DEFAULT]
# =========== items for agent scheduler extension =============
# loadbalancer_pool_scheduler_driver = neutron.services.loadbalancer.agent_scheduler.ChanceScheduler
# loadbalancer_pool_scheduler_driver = neutron.services.loadbalancer.agent_scheduler.LeastPoolAgentScheduler
# loadbalancer_scheduler_driver = neutron.agent_scheduler.ChanceScheduler
[quotas]

View File

@ -14,6 +14,7 @@
# under the License.
import random
import sys
from neutron.common import constants
from neutron.db import agents_db
@ -26,6 +27,7 @@ import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.orm import joinedload
from abc import abstractmethod
from neutron_lbaas.extensions import lbaas_agentscheduler
LOG = logging.getLogger(__name__)
@ -80,6 +82,11 @@ class LbaasAgentSchedulerDbMixin(agentschedulers_db.AgentSchedulerDbMixin,
else:
return {'pools': []}
def num_of_pools_on_lbaas_agent(self, context, id):
query = context.session.query(PoolLoadbalancerAgentBinding.pool_id)
query = query.filter_by(agent_id=id)
return query.count()
def get_lbaas_agent_candidates(self, device_driver, active_agents):
candidates = []
for agent in active_agents:
@ -89,8 +96,7 @@ class LbaasAgentSchedulerDbMixin(agentschedulers_db.AgentSchedulerDbMixin,
return candidates
class ChanceScheduler(object):
"""Allocate a loadbalancer agent for a vip in a random way."""
class SchedulerBase(object):
def schedule(self, plugin, context, pool, device_driver):
"""Schedule the pool to an active loadbalancer agent if there
@ -118,7 +124,8 @@ class ChanceScheduler(object):
device_driver)
return
chosen_agent = random.choice(candidates)
chosen_agent = self._schedule(candidates, plugin, context)
binding = PoolLoadbalancerAgentBinding()
binding.agent = chosen_agent
binding.pool_id = pool['id']
@ -128,3 +135,29 @@ class ChanceScheduler(object):
{'pool_id': pool['id'],
'agent_id': chosen_agent['id']})
return chosen_agent
@abstractmethod
def _schedule(self, candidates, plugin, context):
pass
class ChanceScheduler(SchedulerBase):
def _schedule(self, candidates, plugin, context):
"""Allocate a loadbalancer agent for a vip in a random way."""
return random.choice(candidates)
class LeastPoolAgentScheduler(SchedulerBase):
def _schedule(self, candidates, plugin, context):
"""Pick an agent with least number of pools from candidates"""
current_min_pool_num = sys.maxint
# SchedulerBase.schedule() already checks for empty candidates
for tmp_agent in candidates:
tmp_pool_num = plugin.num_of_pools_on_lbaas_agent(
context, tmp_agent['id'])
if current_min_pool_num > tmp_pool_num:
current_min_pool_num = tmp_pool_num
chosen_agent = tmp_agent
return chosen_agent

View File

@ -73,7 +73,7 @@ class LBaaSAgentSchedulerTestCase(test_agent.AgentDBTestMixIn,
service_plugins = {
'lb_plugin_name': test_db_loadbalancer.DB_LB_PLUGIN_KLASS}
#default provider should support agent scheduling
# default provider should support agent scheduling
cfg.CONF.set_override(
'service_provider',
[('LOADBALANCER:lbaas:neutron_lbaas.services.'
@ -217,3 +217,15 @@ class LBaaSAgentSchedulerTestCase(test_agent.AgentDBTestMixIn,
'fake_id',
expected_code=exc.HTTPForbidden.code,
admin_context=False)
class LeastPoolAgentSchedulerTestCase(LBaaSAgentSchedulerTestCase):
def setUp(self):
# Setting LeastPoolAgentScheduler as scheduler
cfg.CONF.set_override(
'loadbalancer_pool_scheduler_driver',
'neutron_lbaas.services.loadbalancer.'
'agent_scheduler.LeastPoolAgentScheduler')
super(LeastPoolAgentSchedulerTestCase, self).setUp()

View File

@ -48,6 +48,7 @@ loadbalancer_schedulers =
neutron_lbaas.agent_scheduler.ChanceScheduler = neutron_lbaas.agent_scheduler:ChanceScheduler
pool_schedulers =
neutron.services.loadbalancer.agent_scheduler.ChanceScheduler = neutron_lbaas.services.loadbalancer.agent_scheduler:ChanceScheduler
neutron.services.loadbalancer.agent_scheduler.LeastPoolAgentScheduler = neutron_lbaas.services.loadbalancer.agent_scheduler:LeastPoolAgentScheduler
[build_sphinx]
all_files = 1