Commit b08d5cb7 authored by Daniele Venzano's avatar Daniele Venzano

Implement additional random and waterfill placement policies

parent 93d35c2e
......@@ -99,6 +99,7 @@ def load_configuration(test_conf=None):
# Scheduler
argparser.add_argument('--scheduler-class', help='Scheduler class to use for scheduling ZApps', choices=['ZoeElasticScheduler'], default='ZoeElasticScheduler')
argparser.add_argument('--scheduler-policy', help='Scheduler policy to use for scheduling ZApps', choices=['FIFO', 'SIZE'], default='FIFO')
argparser.add_argument('--placement-policy', help='Placement policy', choices=['waterfill', 'random', 'average'], default='average')
argparser.add_argument('--backend', choices=['Kubernetes', 'DockerEngine'], default='DockerEngine', help='Which backend to enable')
......
......@@ -173,8 +173,7 @@ class ZoeElasticScheduler:
def _requeue(self, execution: Execution):
execution.termination_lock.release()
if execution not in self.queue: # make sure the execution is in the queue
log.warning("Execution {} re-queued, but it was not in the queue".format(execution.id))
self.queue.append(execution)
log.warning("Execution {} wants to be re-queued, but it was not in the queue".format(execution.id))
@catch_exceptions_and_retry
def loop_start_th(self): # pylint: disable=too-many-locals
......
"""Classes to hold the system state and simulated container/service placements"""
import logging
import random
from typing import List
from zoe_lib.state import Execution, Service
from zoe_lib.config import get_conf
from zoe_master.stats import ClusterStats, NodeStats
from zoe_master.backends.interface import list_available_images
......@@ -109,6 +112,16 @@ class SimulatedPlatform:
if node.status == 'online':
self.nodes[node.name] = SimulatedNode(node)
def _select_node_policy(self, node_list: List[SimulatedNode]) -> SimulatedNode:
if get_conf().placement_policy == "random":
return random.choice(node_list)
elif get_conf().placement_policy == "waterfill":
node_list.sort(key=lambda n: n.container_count, reverse=True) # biggest first
return node_list[0]
elif get_conf().placement_policy == "average":
node_list.sort(key=lambda n: n.container_count) # smallest first
return node_list[0]
def allocate_essential(self, execution: Execution) -> bool:
"""Try to find an allocation for essential services"""
for service in execution.essential_services:
......@@ -122,8 +135,8 @@ class SimulatedPlatform:
self.deallocate_essential(execution)
log.info('Cannot fit essential service {} anywhere, bailing out'.format(service.id))
return False
candidate_nodes.sort(key=lambda n: n.container_count) # smallest first
candidate_nodes[0].service_add(service)
selected_node = self._select_node_policy(candidate_nodes)
selected_node.service_add(service)
return True
def deallocate_essential(self, execution: Execution):
......@@ -148,8 +161,8 @@ class SimulatedPlatform:
if len(candidate_nodes) == 0: # this service does not fit anywhere
log.info('Cannot fit elastic service {} anywhere'.format(service.id))
continue
candidate_nodes.sort(key=lambda n: n.container_count) # smallest first
candidate_nodes[0].service_add(service)
selected_node = self._select_node_policy(candidate_nodes)
selected_node.service_add(service)
service.set_runnable()
at_least_one_allocated = True
return at_least_one_allocated
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment