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:
parent
6caf97596e
commit
96afcd6879
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue