Remove contract package dependency

Change-Id: I16f8430289447575b4c22b809a7a7da6521f2db8
This commit is contained in:
LingxianKong 2015-05-05 12:10:48 +08:00
parent b135bb8e7c
commit c402b72d2f
17 changed files with 91 additions and 749 deletions

View File

@ -3,7 +3,7 @@ test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_LOG_CAPTURE=${OS_LOG_CAPTURE:-1} \ OS_LOG_CAPTURE=${OS_LOG_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-160} \ OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-160} \
${PYTHON:-python} -m subunit.run discover -t ./ ./mistral/tests/unit $LISTOPT $IDOPTION ${PYTHON:-python} -m subunit.run discover -t ./ ./terracotta/tests/unit $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE test_id_option=--load-list $IDFILE
test_list_option=--list test_list_option=--list

View File

@ -22,108 +22,71 @@ import re
import subprocess import subprocess
import time import time
from contracts import contract
from terracotta.contracts_primitive import *
from terracotta.contracts_extra import *
@contract
def build_local_vm_path(local_data_directory): def build_local_vm_path(local_data_directory):
""" Build the path to the local VM data directory. """ Build the path to the local VM data directory.
:param local_data_directory: The base local data path. :param local_data_directory: The base local data path.
:type local_data_directory: str
:return: The path to the local VM data directory. :return: The path to the local VM data directory.
:rtype: str
""" """
return os.path.join(local_data_directory, 'vms') return os.path.join(local_data_directory, 'vms')
@contract
def build_local_host_path(local_data_directory): def build_local_host_path(local_data_directory):
""" Build the path to the local host data file. """ Build the path to the local host data file.
:param local_data_directory: The base local data path. :param local_data_directory: The base local data path.
:type local_data_directory: str
:return: The path to the local host data file. :return: The path to the local host data file.
:rtype: str
""" """
return os.path.join(local_data_directory, 'host') return os.path.join(local_data_directory, 'host')
@contract
def physical_cpu_count(vir_connection): def physical_cpu_count(vir_connection):
""" Get the number of physical CPUs using libvirt. """ Get the number of physical CPUs using libvirt.
:param vir_connection: A libvirt connection object. :param vir_connection: A libvirt connection object.
:type vir_connection: virConnect
:return: The number of physical CPUs. :return: The number of physical CPUs.
:rtype: int
""" """
return vir_connection.getInfo()[2] return vir_connection.getInfo()[2]
@contract
def physical_cpu_mhz(vir_connection): def physical_cpu_mhz(vir_connection):
""" Get the CPU frequency in MHz using libvirt. """ Get the CPU frequency in MHz using libvirt.
:param vir_connection: A libvirt connection object. :param vir_connection: A libvirt connection object.
:type vir_connection: virConnect
:return: The CPU frequency in MHz. :return: The CPU frequency in MHz.
:rtype: int
""" """
return vir_connection.getInfo()[3] return vir_connection.getInfo()[3]
@contract
def physical_cpu_mhz_total(vir_connection): def physical_cpu_mhz_total(vir_connection):
""" Get the sum of the core CPU frequencies in MHz using libvirt. """ Get the sum of the core CPU frequencies in MHz using libvirt.
:param vir_connection: A libvirt connection object. :param vir_connection: A libvirt connection object.
:type vir_connection: virConnect
:return: The total CPU frequency in MHz. :return: The total CPU frequency in MHz.
:rtype: int
""" """
return physical_cpu_count(vir_connection) * \ return physical_cpu_count(vir_connection) * \
physical_cpu_mhz(vir_connection) physical_cpu_mhz(vir_connection)
@contract
def frange(start, end, step): def frange(start, end, step):
""" A range generator for floats. """ A range generator for floats.
:param start: The starting value. :param start: The starting value.
:type start: number
:param end: The end value. :param end: The end value.
:type end: number
:param step: The step. :param step: The step.
:type step: number
""" """
while start <= end: while start <= end:
yield start yield start
start += step start += step
@contract
def call_function_by_name(name, args): def call_function_by_name(name, args):
""" Call a function specified by a fully qualified name. """ Call a function specified by a fully qualified name.
:param name: A fully qualified name of a function. :param name: A fully qualified name of a function.
:type name: str
:param args: A list of positional arguments of the function. :param args: A list of positional arguments of the function.
:type args: list
:return: The return value of the function call. :return: The return value of the function call.
:rtype: *
""" """
fragments = name.split('.') fragments = name.split('.')
module = '.'.join(fragments[:-1]) module = '.'.join(fragments[:-1])
@ -133,58 +96,40 @@ def call_function_by_name(name, args):
return getattr(m, function)(*args) return getattr(m, function)(*args)
@contract
def parse_parameters(params): def parse_parameters(params):
""" Parse algorithm parameters from the config file. """ Parse algorithm parameters from the config file.
:param params: JSON encoded parameters. :param params: JSON encoded parameters.
:type params: str
:return: A dict of parameters. :return: A dict of parameters.
:rtype: dict(str: *)
""" """
return dict((str(k), v) return dict((str(k), v)
for k, v in json.loads(params).items()) for k, v in json.loads(params).items())
@contract
def parse_compute_hosts(compute_hosts): def parse_compute_hosts(compute_hosts):
""" Transform a coma-separated list of host names into a list. """ Transform a coma-separated list of host names into a list.
:param compute_hosts: A coma-separated list of host names. :param compute_hosts: A coma-separated list of host names.
:type compute_hosts: str
:return: A list of host names. :return: A list of host names.
:rtype: list(str)
""" """
return filter(None, re.split('[^a-zA-Z0-9\-_]+', compute_hosts)) return filter(None, re.split('[^a-zA-Z0-9\-_]+', compute_hosts))
@contract
def calculate_migration_time(vms, bandwidth): def calculate_migration_time(vms, bandwidth):
""" Calculate the mean migration time from VM RAM usage data. """ Calculate the mean migration time from VM RAM usage data.
:param vms: A map of VM UUIDs to the corresponding maximum RAM in MB. :param vms: A map of VM UUIDs to the corresponding maximum RAM in MB.
:type vms: dict(str: long)
:param bandwidth: The network bandwidth in MB/s. :param bandwidth: The network bandwidth in MB/s.
:type bandwidth: float,>0
:return: The mean VM migration time in seconds. :return: The mean VM migration time in seconds.
:rtype: float
""" """
return float(numpy.mean(vms.values()) / bandwidth) return float(numpy.mean(vms.values()) / bandwidth)
@contract
def execute_on_hosts(hosts, commands): def execute_on_hosts(hosts, commands):
""" Execute Shell command on hosts over SSH. """ Execute Shell command on hosts over SSH.
:param hosts: A list of host names. :param hosts: A list of host names.
:type hosts: list(str)
:param commands: A list of Shell commands. :param commands: A list of Shell commands.
:type commands: list(str)
""" """
commands_merged = '' commands_merged = ''
for command in commands: for command in commands:

View File

@ -1,4 +1,5 @@
# Copyright 2012 Anton Beloglazov # Copyright 2012 Anton Beloglazov
# Copyright 2015 Huawei Technologies Co., Ltd.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -19,26 +20,23 @@ by VMs stored in the database. This is requried to avoid excess growth
of the database size. of the database size.
""" """
from contracts import contract
from neat.contracts_primitive import *
from neat.contracts_extra import *
import datetime import datetime
import neat.common as common from oslo_config import cfg
from neat.config import * from oslo_log import log as logging
from neat.db_utils import *
import logging import terracotta.common as common
log = logging.getLogger(__name__) from terracotta.config import *
from terracotta.utils.db_utils import *
LOG = logging.getLogger(__name__)
@contract
def start(): def start():
""" Start the database cleaner loop. """ Start the database cleaner loop.
:return: The final state. :return: The final state.
:rtype: dict(str: *)
""" """
config = read_and_validate_config([DEFAULT_CONFIG_PATH, CONFIG_PATH], config = read_and_validate_config([DEFAULT_CONFIG_PATH, CONFIG_PATH],
REQUIRED_FIELDS) REQUIRED_FIELDS)
@ -49,9 +47,8 @@ def start():
int(config['log_level'])) int(config['log_level']))
interval = config['db_cleaner_interval'] interval = config['db_cleaner_interval']
if log.isEnabledFor(logging.INFO): LOG.info('Starting the database cleaner, ' +
log.info('Starting the database cleaner, ' + 'iterations every %s seconds', interval)
'iterations every %s seconds', interval)
return common.start( return common.start(
init_state, init_state,
execute, execute,
@ -59,15 +56,11 @@ def start():
int(interval)) int(interval))
@contract
def init_state(config): def init_state(config):
""" Initialize a dict for storing the state of the database cleaner. """ Initialize a dict for storing the state of the database cleaner.
:param config: A config dictionary. :param config: A config dictionary.
:type config: dict(str: *)
:return: A dictionary containing the initial state of the database cleaner. :return: A dictionary containing the initial state of the database cleaner.
:rtype: dict
""" """
return { return {
'db': init_db(config['sql_connection']), 'db': init_db(config['sql_connection']),
@ -75,33 +68,24 @@ def init_state(config):
seconds=int(config['db_cleaner_interval']))} seconds=int(config['db_cleaner_interval']))}
@contract
def execute(config, state): def execute(config, state):
""" Execute an iteration of the database cleaner. """ Execute an iteration of the database cleaner.
:param config: A config dictionary. :param config: A config dictionary.
:type config: dict(str: *)
:param state: A state dictionary. :param state: A state dictionary.
:type state: dict(str: *)
:return: The updated state dictionary. :return: The updated state dictionary.
:rtype: dict(str: *)
""" """
datetime_threshold = today() - state['time_delta'] datetime_threshold = today() - state['time_delta']
state['db'].cleanup_vm_resource_usage(datetime_threshold) state['db'].cleanup_vm_resource_usage(datetime_threshold)
state['db'].cleanup_host_resource_usage(datetime_threshold) state['db'].cleanup_host_resource_usage(datetime_threshold)
if log.isEnabledFor(logging.INFO): LOG.info('Cleaned up data older than %s',
log.info('Cleaned up data older than %s', datetime_threshold.strftime('%Y-%m-%d %H:%M:%S'))
datetime_threshold.strftime('%Y-%m-%d %H:%M:%S'))
return state return state
@contract
def today(): def today():
""" Return the today's datetime. """ Return the today's datetime.
:return: A datetime object representing current date and time. :return: A datetime object representing current date and time.
:rtype: datetime
""" """
return datetime.datetime.today() return datetime.datetime.today()

View File

@ -1,4 +1,5 @@
# Copyright 2012 Anton Beloglazov # Copyright 2012 Anton Beloglazov
# Copyright 2015 Huawei Technologies Co., Ltd.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -15,29 +16,19 @@
""" Bin Packing based VM placement algorithms. """ Bin Packing based VM placement algorithms.
""" """
from contracts import contract from oslo_log import log as logging
from neat.contracts_primitive import *
from neat.contracts_extra import *
LOG = logging.getLogger(__name__)
import logging
log = logging.getLogger(__name__)
@contract
def best_fit_decreasing_factory(time_step, migration_time, params): def best_fit_decreasing_factory(time_step, migration_time, params):
""" Creates the Best Fit Decreasing (BFD) heuristic for VM placement. """ Creates the Best Fit Decreasing (BFD) heuristic for VM placement.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the BFD algorithm. :return: A function implementing the BFD algorithm.
:rtype: function
""" """
return lambda hosts_cpu_usage, hosts_cpu_total, \ return lambda hosts_cpu_usage, hosts_cpu_total, \
hosts_ram_usage, hosts_ram_total, \ hosts_ram_usage, hosts_ram_total, \
@ -60,64 +51,39 @@ def best_fit_decreasing_factory(time_step, migration_time, params):
{}) {})
@contract
def get_available_resources(threshold, usage, total): def get_available_resources(threshold, usage, total):
""" Get a map of the available resource capacity. """ Get a map of the available resource capacity.
:param threshold: A threshold on the maximum allowed resource usage. :param threshold: A threshold on the maximum allowed resource usage.
:type threshold: float,>=0
:param usage: A map of hosts to the resource usage. :param usage: A map of hosts to the resource usage.
:type usage: dict(str: number)
:param total: A map of hosts to the total resource capacity. :param total: A map of hosts to the total resource capacity.
:type total: dict(str: number)
:return: A map of hosts to the available resource capacity. :return: A map of hosts to the available resource capacity.
:rtype: dict(str: int)
""" """
return dict((host, int(threshold * total[host] - resource)) return dict((host, int(threshold * total[host] - resource))
for host, resource in usage.items()) for host, resource in usage.items())
@contract
def best_fit_decreasing(last_n_vm_cpu, hosts_cpu, hosts_ram, def best_fit_decreasing(last_n_vm_cpu, hosts_cpu, hosts_ram,
inactive_hosts_cpu, inactive_hosts_ram, inactive_hosts_cpu, inactive_hosts_ram,
vms_cpu, vms_ram): vms_cpu, vms_ram):
""" The Best Fit Decreasing (BFD) heuristic for placing VMs on hosts. """ The Best Fit Decreasing (BFD) heuristic for placing VMs on hosts.
:param last_n_vm_cpu: The last n VM CPU usage values to average. :param last_n_vm_cpu: The last n VM CPU usage values to average.
:type last_n_vm_cpu: int
:param hosts_cpu: A map of host names and their available CPU in MHz. :param hosts_cpu: A map of host names and their available CPU in MHz.
:type hosts_cpu: dict(str: int)
:param hosts_ram: A map of host names and their available RAM in MB. :param hosts_ram: A map of host names and their available RAM in MB.
:type hosts_ram: dict(str: int)
:param inactive_hosts_cpu: A map of inactive hosts and available CPU MHz. :param inactive_hosts_cpu: A map of inactive hosts and available CPU MHz.
:type inactive_hosts_cpu: dict(str: int)
:param inactive_hosts_ram: A map of inactive hosts and available RAM MB. :param inactive_hosts_ram: A map of inactive hosts and available RAM MB.
:type inactive_hosts_ram: dict(str: int)
:param vms_cpu: A map of VM UUID and their CPU utilization in MHz. :param vms_cpu: A map of VM UUID and their CPU utilization in MHz.
:type vms_cpu: dict(str: list(int))
:param vms_ram: A map of VM UUID and their RAM usage in MB. :param vms_ram: A map of VM UUID and their RAM usage in MB.
:type vms_ram: dict(str: int)
:return: A map of VM UUIDs to host names, or {} if cannot be solved. :return: A map of VM UUIDs to host names, or {} if cannot be solved.
:rtype: dict(str: str)
""" """
if log.isEnabledFor(logging.DEBUG): LOG.debug('last_n_vm_cpu: %s', str(last_n_vm_cpu))
log.debug('last_n_vm_cpu: %s', str(last_n_vm_cpu)) LOG.debug('hosts_cpu: %s', str(hosts_cpu))
log.debug('hosts_cpu: %s', str(hosts_cpu)) LOG.debug('hosts_ram: %s', str(hosts_ram))
log.debug('hosts_ram: %s', str(hosts_ram)) LOG.debug('inactive_hosts_cpu: %s', str(inactive_hosts_cpu))
log.debug('inactive_hosts_cpu: %s', str(inactive_hosts_cpu)) LOG.debug('inactive_hosts_ram: %s', str(inactive_hosts_ram))
log.debug('inactive_hosts_ram: %s', str(inactive_hosts_ram)) LOG.debug('vms_cpu: %s', str(vms_cpu))
log.debug('vms_cpu: %s', str(vms_cpu)) LOG.debug('vms_ram: %s', str(vms_ram))
log.debug('vms_ram: %s', str(vms_ram))
vms_tmp = [] vms_tmp = []
for vm, cpu in vms_cpu.items(): for vm, cpu in vms_cpu.items():
if cpu: if cpu:
@ -126,7 +92,7 @@ def best_fit_decreasing(last_n_vm_cpu, hosts_cpu, hosts_ram,
vms_ram[vm], vms_ram[vm],
vm)) vm))
else: else:
log.warning('No CPU data for VM: %s - skipping', vm) LOG.warning('No CPU data for VM: %s - skipping', vm)
vms = sorted(vms_tmp, reverse=True) vms = sorted(vms_tmp, reverse=True)
hosts = sorted(((v, hosts_ram[k], k) hosts = sorted(((v, hosts_ram[k], k)

View File

@ -1,4 +1,5 @@
# Copyright 2012 Anton Beloglazov # Copyright 2012 Anton Beloglazov
# Copyright 2015 Huawei Technologies Co., Ltd.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -15,35 +16,18 @@
""" Functions for solving NLP problems using the bruteforce method. """ Functions for solving NLP problems using the bruteforce method.
""" """
from contracts import contract
from neat.contracts_primitive import *
from neat.contracts_extra import *
import nlp import nlp
from neat.common import frange from terracotta.common import frange
import logging
log = logging.getLogger(__name__)
@contract
def solve2(objective, constraint, step, limit): def solve2(objective, constraint, step, limit):
""" Solve a maximization problem for 2 states. """ Solve a maximization problem for 2 states.
:param objective: The objective function. :param objective: The objective function.
:type objective: function
:param constraint: A tuple representing the constraint. :param constraint: A tuple representing the constraint.
:type constraint: tuple(function, function, number)
:param step: The step size. :param step: The step size.
:type step: number,>0
:param limit: The maximum value of the variables. :param limit: The maximum value of the variables.
:type limit: number,>0
:return: The problem solution. :return: The problem solution.
:rtype: list(number)
""" """
res_best = 0 res_best = 0
solution = [] solution = []
@ -52,48 +36,28 @@ def solve2(objective, constraint, step, limit):
try: try:
res = objective(x, y) res = objective(x, y)
if res > res_best and \ if res > res_best and \
constraint[1](constraint[0](x, y), constraint[2]): constraint[1](constraint[0](x, y), constraint[2]):
res_best = res res_best = res
solution = [x, y] solution = [x, y]
except ZeroDivisionError: except ZeroDivisionError:
pass pass
return solution return solution
@contract
def optimize(step, limit, otf, migration_time, ls, p, state_vector, def optimize(step, limit, otf, migration_time, ls, p, state_vector,
time_in_states, time_in_state_n): time_in_states, time_in_state_n):
""" Solve a MHOD optimization problem. """ Solve a MHOD optimization problem.
:param step: The step size for the bruteforce algorithm. :param step: The step size for the bruteforce algorithm.
:type step: number,>0
:param limit: The maximum value of the variables. :param limit: The maximum value of the variables.
:type limit: number,>0
:param otf: The OTF parameter. :param otf: The OTF parameter.
:type otf: number,>=0,<=1
:param migration_time: The VM migration time in time steps. :param migration_time: The VM migration time in time steps.
:type migration_time: float,>=0
:param ls: L functions. :param ls: L functions.
:type ls: list(function)
:param p: A matrix of transition probabilities. :param p: A matrix of transition probabilities.
:type p: list(list(number))
:param state_vector: A state vector. :param state_vector: A state vector.
:type state_vector: list(int)
:param time_in_states: The total time in all the states in time steps. :param time_in_states: The total time in all the states in time steps.
:type time_in_states: number,>=0
:param time_in_state_n: The total time in the state N in time steps. :param time_in_state_n: The total time in the state N in time steps.
:type time_in_state_n: number,>=0
:return: The solution of the problem. :return: The solution of the problem.
:rtype: list(number)
""" """
objective = nlp.build_objective(ls, state_vector, p) objective = nlp.build_objective(ls, state_vector, p)
constraint = nlp.build_constraint(otf, migration_time, ls, state_vector, constraint = nlp.build_constraint(otf, migration_time, ls, state_vector,

View File

@ -1,4 +1,5 @@
# Copyright 2012 Anton Beloglazov # Copyright 2012 Anton Beloglazov
# Copyright 2015 Huawei Technologies Co., Ltd.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -15,34 +16,25 @@
""" This is the main module of the MHOD algorithm. """ This is the main module of the MHOD algorithm.
""" """
from contracts import contract from oslo_log import log as logging
from neat.contracts_primitive import *
from neat.contracts_extra import *
import neat.locals.overload.mhod.multisize_estimation as estimation import terracotta.locals.overload.mhod.multisize_estimation as estimation
import neat.locals.overload.mhod.bruteforce as bruteforce import terracotta.locals.overload.mhod.bruteforce as bruteforce
from neat.locals.overload.mhod.l_2_states import ls from terracotta.locals.overload.mhod.l_2_states import ls
import logging
log = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@contract
def mhod_factory(time_step, migration_time, params): def mhod_factory(time_step, migration_time, params):
""" Creates the MHOD algorithm. """ Creates the MHOD algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the MHOD algorithm. :return: A function implementing the MHOD algorithm.
:rtype: function
""" """
def mhod_wrapper(utilization, state=None): def mhod_wrapper(utilization, state=None):
if not state: if not state:
state = init_state(params['history_size'], state = init_state(params['history_size'],
@ -57,24 +49,17 @@ def mhod_factory(time_step, migration_time, params):
migration_time, migration_time,
utilization, utilization,
state) state)
return mhod_wrapper return mhod_wrapper
@contract
def init_state(history_size, window_sizes, number_of_states): def init_state(history_size, window_sizes, number_of_states):
""" Initialize the state dictionary of the MHOD algorithm. """ Initialize the state dictionary of the MHOD algorithm.
:param history_size: The number of last system states to store. :param history_size: The number of last system states to store.
:type history_size: int,>0
:param window_sizes: The required window sizes. :param window_sizes: The required window sizes.
:type window_sizes: list(int)
:param number_of_states: The number of states. :param number_of_states: The number of states.
:type number_of_states: int,>0
:return: The initialization state dictionary. :return: The initialization state dictionary.
:rtype: dict(str: *)
""" """
return { return {
'previous_state': 0, 'previous_state': 0,
@ -91,47 +76,29 @@ def init_state(history_size, window_sizes, number_of_states):
window_sizes, number_of_states)} window_sizes, number_of_states)}
@contract
def mhod(state_config, otf, window_sizes, bruteforce_step, learning_steps, def mhod(state_config, otf, window_sizes, bruteforce_step, learning_steps,
time_step, migration_time, utilization, state): time_step, migration_time, utilization, state):
""" The MHOD algorithm returning whether the host is overloaded. """ The MHOD algorithm returning whether the host is overloaded.
:param state_config: The state configuration. :param state_config: The state configuration.
:type state_config: list(float)
:param otf: The OTF parameter. :param otf: The OTF parameter.
:type otf: float,>0
:param window_sizes: A list of window sizes. :param window_sizes: A list of window sizes.
:type window_sizes: list(int)
:param bruteforce_step: The step of the bruteforce algorithm. :param bruteforce_step: The step of the bruteforce algorithm.
:type bruteforce_step: float
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param utilization: The history of the host's CPU utilization. :param utilization: The history of the host's CPU utilization.
:type utilization: list(float)
:param state: The state of the algorithm. :param state: The state of the algorithm.
:type state: dict
:return: The updated state and decision of the algorithm. :return: The updated state and decision of the algorithm.
:rtype: tuple(bool, dict)
""" """
utilization_length = len(utilization) utilization_length = len(utilization)
# if utilization_length == state['time_in_states'] and \ # if utilization_length == state['time_in_states'] and \
# utilization == state['previous_utilization']: # utilization == state['previous_utilization']:
# # No new utilization values # # No new utilization values
# return False, state # return False, state
number_of_states = len(state_config) + 1 number_of_states = len(state_config) + 1
previous_state = 0 previous_state = 0
# state['previous_utilization'] = utilization # state['previous_utilization'] = utilization
state['request_windows'] = estimation.init_request_windows( state['request_windows'] = estimation.init_request_windows(
number_of_states, max(window_sizes)) number_of_states, max(window_sizes))
state['estimate_windows'] = estimation.init_deque_structure( state['estimate_windows'] = estimation.init_deque_structure(
@ -141,7 +108,8 @@ def mhod(state_config, otf, window_sizes, bruteforce_step, learning_steps,
state['acceptable_variances'] = estimation.init_variances( state['acceptable_variances'] = estimation.init_variances(
window_sizes, number_of_states) window_sizes, number_of_states)
for i, current_state in enumerate(utilization_to_states(state_config, utilization)): for i, current_state in enumerate(
utilization_to_states(state_config, utilization)):
state['request_windows'] = estimation.update_request_windows( state['request_windows'] = estimation.update_request_windows(
state['request_windows'], state['request_windows'],
previous_state, previous_state,
@ -176,73 +144,59 @@ def mhod(state_config, otf, window_sizes, bruteforce_step, learning_steps,
state['previous_state'] = current_state state['previous_state'] = current_state
state_n = len(state_config) state_n = len(state_config)
# if utilization_length > state['time_in_states'] + 1: # if utilization_length > state['time_in_states'] + 1:
# for s in utilization_to_states( # for s in utilization_to_states(
# state_config, # state_config,
# utilization[-(utilization_length - state['time_in_states']):]): # utilization[-(utilization_length - state['time_in_states']):]):
# state['time_in_states'] += 1 # state['time_in_states'] += 1
# if s == state_n: # if s == state_n:
# state['time_in_state_n'] += 1 # state['time_in_state_n'] += 1
# else: # else:
state['time_in_states'] += 1 state['time_in_states'] += 1
if current_state == state_n: if current_state == state_n:
state['time_in_state_n'] += 1 state['time_in_state_n'] += 1
if log.isEnabledFor(logging.DEBUG): LOG.debug('MHOD utilization:' + str(utilization))
log.debug('MHOD utilization:' + str(utilization)) LOG.debug('MHOD time_in_states:' + str(state['time_in_states']))
log.debug('MHOD time_in_states:' + str(state['time_in_states'])) LOG.debug('MHOD time_in_state_n:' + str(state['time_in_state_n']))
log.debug('MHOD time_in_state_n:' + str(state['time_in_state_n'])) LOG.debug('MHOD p:' + str(p))
log.debug('MHOD p:' + str(p)) LOG.debug('MHOD current_state:' + str(current_state))
log.debug('MHOD current_state:' + str(current_state)) LOG.debug('MHOD p[current_state]:' + str(p[current_state]))
log.debug('MHOD p[current_state]:' + str(p[current_state]))
if utilization_length >= learning_steps: if utilization_length >= learning_steps:
if current_state == state_n and p[state_n][state_n] > 0: if current_state == state_n and p[state_n][state_n] > 0:
# if p[current_state][state_n] > 0: # if p[current_state][state_n] > 0:
policy = bruteforce.optimize( policy = bruteforce.optimize(
bruteforce_step, 1.0, otf, (migration_time / time_step), ls, p, bruteforce_step, 1.0, otf, (migration_time / time_step), ls, p,
state_vector, state['time_in_states'], state['time_in_state_n']) state_vector, state['time_in_states'],
state['time_in_state_n'])
# This is saved for testing purposes # This is saved for testing purposes
state['policy'] = policy state['policy'] = policy
if log.isEnabledFor(logging.DEBUG): LOG.debug('MHOD policy:' + str(policy))
log.debug('MHOD policy:' + str(policy))
command = issue_command_deterministic(policy) command = issue_command_deterministic(policy)
if log.isEnabledFor(logging.DEBUG): LOG.debug('MHOD command:' + str(command))
log.debug('MHOD command:' + str(command))
return command, state return command, state
return False, state return False, state
@contract
def build_state_vector(state_config, utilization): def build_state_vector(state_config, utilization):
""" Build the current state PMF corresponding to the utilization """ Build the current state PMF corresponding to the utilization
history and state config. history and state config.
:param state_config: The state configuration. :param state_config: The state configuration.
:type state_config: list(float)
:param utilization: The history of the host's CPU utilization. :param utilization: The history of the host's CPU utilization.
:type utilization: list(float)
:return: The current state vector. :return: The current state vector.
:rtype: list(int)
""" """
state = utilization_to_state(state_config, utilization[-1]) state = utilization_to_state(state_config, utilization[-1])
return [int(state == x) for x in range(len(state_config) + 1)] return [int(state == x) for x in range(len(state_config) + 1)]
@contract
def utilization_to_state(state_config, utilization): def utilization_to_state(state_config, utilization):
""" Transform a utilization value into the corresponding state. """ Transform a utilization value into the corresponding state.
:param state_config: The state configuration. :param state_config: The state configuration.
:type state_config: list(float)
:param utilization: A utilization value. :param utilization: A utilization value.
:type utilization: number,>=0
:return: The state corresponding to the utilization value. :return: The state corresponding to the utilization value.
:rtype: int
""" """
prev = -1 prev = -1
for state, threshold in enumerate(state_config): for state, threshold in enumerate(state_config):
@ -252,20 +206,15 @@ def utilization_to_state(state_config, utilization):
return prev + 1 return prev + 1
@contract
def get_current_state(state_vector): def get_current_state(state_vector):
""" Get the current state corresponding to the state probability vector. """ Get the current state corresponding to the state probability vector.
:param state_vector: The state PMF vector. :param state_vector: The state PMF vector.
:type state_vector: list(int)
:return: The current state. :return: The current state.
:rtype: int,>=0
""" """
return state_vector.index(1) return state_vector.index(1)
@contract
def utilization_to_states(state_config, utilization): def utilization_to_states(state_config, utilization):
""" Get the state history corresponding to the utilization history. """ Get the state history corresponding to the utilization history.
@ -274,25 +223,16 @@ def utilization_to_states(state_config, utilization):
(map (partial utilization-to-state state-config) utilization)) (map (partial utilization-to-state state-config) utilization))
:param state_config: The state configuration. :param state_config: The state configuration.
:type state_config: list(float)
:param utilization: The history of the host's CPU utilization. :param utilization: The history of the host's CPU utilization.
:type utilization: list(float)
:return: The state history. :return: The state history.
:rtype: list(int)
""" """
return [utilization_to_state(state_config, x) for x in utilization] return [utilization_to_state(state_config, x) for x in utilization]
@contract
def issue_command_deterministic(policy): def issue_command_deterministic(policy):
""" Issue a migration command according to the policy PMF p. """ Issue a migration command according to the policy PMF p.
:param policy: A policy PMF. :param policy: A policy PMF.
:type policy: list(number)
:return: A migration command. :return: A migration command.
:rtype: bool
""" """
return len(policy) == 0 return len(policy) == 0

View File

@ -1,4 +1,5 @@
# Copyright 2012 Anton Beloglazov # Copyright 2012 Anton Beloglazov
# Copyright 2015 Huawei Technologies Co., Ltd.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -15,29 +16,14 @@
""" L functions for the 2 state configuration of the MHOD algorithm. """ L functions for the 2 state configuration of the MHOD algorithm.
""" """
from contracts import contract
from neat.contracts_primitive import *
from neat.contracts_extra import *
import logging
log = logging.getLogger(__name__)
@contract
def l0(p_initial, p_matrix, m): def l0(p_initial, p_matrix, m):
""" Compute the L0 function. """ Compute the L0 function.
:param p_initial: The initial state distribution. :param p_initial: The initial state distribution.
:type p_initial: list(number)
:param p_matrix: A matrix of transition probabilities. :param p_matrix: A matrix of transition probabilities.
:type p_matrix: list(list(number))
:param m: The m values. :param m: The m values.
:type m: list(number)
:return: The value of the L0 function. :return: The value of the L0 function.
:rtype: number
""" """
p0 = p_initial[0] p0 = p_initial[0]
p1 = p_initial[1] p1 = p_initial[1]
@ -53,21 +39,13 @@ def l0(p_initial, p_matrix, m):
p10 - 1)) p10 - 1))
@contract
def l1(p_initial, p_matrix, m): def l1(p_initial, p_matrix, m):
""" Compute the L1 function. """ Compute the L1 function.
:param p_initial: The initial state distribution. :param p_initial: The initial state distribution.
:type p_initial: list(number)
:param p_matrix: A matrix of transition probabilities. :param p_matrix: A matrix of transition probabilities.
:type p_matrix: list(list(number))
:param m: The m values. :param m: The m values.
:type m: list(number)
:return: The value of the L1 function. :return: The value of the L1 function.
:rtype: number
""" """
p0 = p_initial[0] p0 = p_initial[0]
p1 = p_initial[1] p1 = p_initial[1]

View File

@ -15,121 +15,72 @@
""" Multisize sliding window workload estimation functions. """ Multisize sliding window workload estimation functions.
""" """
from contracts import contract
from neat.contracts_primitive import *
from neat.contracts_extra import *
from itertools import islice from itertools import islice
from collections import deque from collections import deque
import logging
log = logging.getLogger(__name__)
@contract
def mean(data, window_size): def mean(data, window_size):
""" Get the data mean according to the window size. """ Get the data mean according to the window size.
:param data: A list of values. :param data: A list of values.
:type data: list(number)
:param window_size: A window size. :param window_size: A window size.
:type window_size: int,>0
:return: The mean value. :return: The mean value.
:rtype: float
""" """
return float(sum(data)) / window_size return float(sum(data)) / window_size
@contract
def variance(data, window_size): def variance(data, window_size):
""" Get the data variance according to the window size. """ Get the data variance according to the window size.
:param data: A list of values. :param data: A list of values.
:type data: list(number)
:param window_size: A window size. :param window_size: A window size.
:type window_size: int,>0
:return: The variance value. :return: The variance value.
:rtype: float
""" """
m = mean(data, window_size) m = mean(data, window_size)
return float(sum((x - m) ** 2 for x in data)) / (window_size - 1) return float(sum((x - m) ** 2 for x in data)) / (window_size - 1)
@contract
def acceptable_variance(probability, window_size): def acceptable_variance(probability, window_size):
""" Get the acceptable variance. """ Get the acceptable variance.
:param probability: The probability to use. :param probability: The probability to use.
:type probability: number,>=0,<=1
:param window_size: A window size. :param window_size: A window size.
:type window_size: int,>0
:return: The acceptable variance. :return: The acceptable variance.
:rtype: float
""" """
return float(probability * (1 - probability)) / window_size return float(probability * (1 - probability)) / window_size
@contract
def estimate_probability(data, window_size, state): def estimate_probability(data, window_size, state):
""" Get the estimated probability. """ Get the estimated probability.
:param data: A list of data values. :param data: A list of data values.
:type data: list(number)
:param window_size: The window size. :param window_size: The window size.
:type window_size: int,>0
:param state: The current state. :param state: The current state.
:type state: int,>=0
:return: The estimated probability. :return: The estimated probability.
:rtype: float,>=0
""" """
return float(data.count(state)) / window_size return float(data.count(state)) / window_size
@contract
def update_request_windows(request_windows, previous_state, current_state): def update_request_windows(request_windows, previous_state, current_state):
""" Update and return the updated request windows. """ Update and return the updated request windows.
:param request_windows: The previous request windows. :param request_windows: The previous request windows.
:type request_windows: list(deque)
:param previous_state: The previous state. :param previous_state: The previous state.
:type previous_state: int,>=0
:param current_state: The current state. :param current_state: The current state.
:type current_state: int,>=0
:return: The updated request windows. :return: The updated request windows.
:rtype: list(deque)
""" """
request_windows[previous_state].append(current_state) request_windows[previous_state].append(current_state)
return request_windows return request_windows
@contract
def update_estimate_windows(estimate_windows, request_windows, def update_estimate_windows(estimate_windows, request_windows,
previous_state): previous_state):
""" Update and return the updated estimate windows. """ Update and return the updated estimate windows.
:param estimate_windows: The previous estimate windows. :param estimate_windows: The previous estimate windows.
:type estimate_windows: list(list(dict))
:param request_windows: The current request windows. :param request_windows: The current request windows.
:type request_windows: list(deque)
:param previous_state: The previous state. :param previous_state: The previous state.
:type previous_state: int,>=0
:return: The updated estimate windows. :return: The updated estimate windows.
:rtype: list(list(dict))
""" """
request_window = request_windows[previous_state] request_window = request_windows[previous_state]
state_estimate_windows = estimate_windows[previous_state] state_estimate_windows = estimate_windows[previous_state]
@ -145,21 +96,13 @@ def update_estimate_windows(estimate_windows, request_windows,
return estimate_windows return estimate_windows
@contract
def update_variances(variances, estimate_windows, previous_state): def update_variances(variances, estimate_windows, previous_state):
""" Updated and return the updated variances. """ Updated and return the updated variances.
:param variances: The previous variances. :param variances: The previous variances.
:type variances: list(list(dict))
:param estimate_windows: The current estimate windows. :param estimate_windows: The current estimate windows.
:type estimate_windows: list(list(dict))
:param previous_state: The previous state. :param previous_state: The previous state.
:type previous_state: int,>=0
:return: The updated variances. :return: The updated variances.
:rtype: list(list(dict))
""" """
estimate_window = estimate_windows[previous_state] estimate_window = estimate_windows[previous_state]
for state, variance_map in enumerate(variances[previous_state]): for state, variance_map in enumerate(variances[previous_state]):
@ -173,21 +116,14 @@ def update_variances(variances, estimate_windows, previous_state):
return variances return variances
@contract def update_acceptable_variances(acceptable_variances, estimate_windows,
def update_acceptable_variances(acceptable_variances, estimate_windows, previous_state): previous_state):
""" Update and return the updated acceptable variances. """ Update and return the updated acceptable variances.
:param acceptable_variances: The previous acceptable variances. :param acceptable_variances: The previous acceptable variances.
:type acceptable_variances: list(list(dict))
:param estimate_windows: The current estimate windows. :param estimate_windows: The current estimate windows.
:type estimate_windows: list(list(dict))
:param previous_state: The previous state. :param previous_state: The previous state.
:type previous_state: int,>=0
:return: The updated acceptable variances. :return: The updated acceptable variances.
:rtype: list(list(dict))
""" """
estimate_window = estimate_windows[previous_state] estimate_window = estimate_windows[previous_state]
state_acc_variances = acceptable_variances[previous_state] state_acc_variances = acceptable_variances[previous_state]
@ -199,21 +135,13 @@ def update_acceptable_variances(acceptable_variances, estimate_windows, previous
return acceptable_variances return acceptable_variances
@contract
def select_window(variances, acceptable_variances, window_sizes): def select_window(variances, acceptable_variances, window_sizes):
""" Select window sizes according to the acceptable variances. """ Select window sizes according to the acceptable variances.
:param variances: The variances. :param variances: The variances.
:type variances: list(list(dict))
:param acceptable_variances: The acceptable variances. :param acceptable_variances: The acceptable variances.
:type acceptable_variances: list(list(dict))
:param window_sizes: The available window sizes. :param window_sizes: The available window sizes.
:type window_sizes: list(int)
:return: The selected window sizes. :return: The selected window sizes.
:rtype: list(list(int))
""" """
n = len(variances) n = len(variances)
selected_windows = [] selected_windows = []
@ -223,25 +151,19 @@ def select_window(variances, acceptable_variances, window_sizes):
selected_size = window_sizes[0] selected_size = window_sizes[0]
for window_size in window_sizes: for window_size in window_sizes:
if variances[i][j][window_size] > \ if variances[i][j][window_size] > \
acceptable_variances[i][j][window_size]: acceptable_variances[i][j][window_size]:
break break
selected_size = window_size selected_size = window_size
selected_windows[i].append(selected_size) selected_windows[i].append(selected_size)
return selected_windows return selected_windows
@contract
def select_best_estimates(estimate_windows, selected_windows): def select_best_estimates(estimate_windows, selected_windows):
""" Select the best estimates according to the selected windows. """ Select the best estimates according to the selected windows.
:param estimate_windows: The estimate windows. :param estimate_windows: The estimate windows.
:type estimate_windows: list(list(dict))
:param selected_windows: The selected window sizes. :param selected_windows: The selected window sizes.
:type selected_windows: list(list(int))
:return: The selected best estimates. :return: The selected best estimates.
:rtype: list(list(number))
""" """
n = len(estimate_windows) n = len(estimate_windows)
selected_estimates = [] selected_estimates = []
@ -256,35 +178,23 @@ def select_best_estimates(estimate_windows, selected_windows):
return selected_estimates return selected_estimates
@contract
def init_request_windows(number_of_states, max_window_size): def init_request_windows(number_of_states, max_window_size):
""" Initialize a request window data structure. """ Initialize a request window data structure.
:param number_of_states: The number of states. :param number_of_states: The number of states.
:type number_of_states: int,>0
:param max_window_size: The max size of the request windows. :param max_window_size: The max size of the request windows.
:type max_window_size: int,>0
:return: The initialized request windows data structure. :return: The initialized request windows data structure.
:rtype: list(deque)
""" """
return [deque([], max_window_size) return [deque([], max_window_size)
for _ in range(number_of_states)] for _ in range(number_of_states)]
@contract
def init_variances(window_sizes, number_of_states): def init_variances(window_sizes, number_of_states):
""" Initialize a variances data structure. """ Initialize a variances data structure.
:param window_sizes: The required window sizes. :param window_sizes: The required window sizes.
:type window_sizes: list(int)
:param number_of_states: The number of states. :param number_of_states: The number of states.
:type number_of_states: int,>0
:return: The initialized variances data structure. :return: The initialized variances data structure.
:rtype: list(list(dict))
""" """
variances = [] variances = []
for i in range(number_of_states): for i in range(number_of_states):
@ -295,18 +205,12 @@ def init_variances(window_sizes, number_of_states):
return variances return variances
@contract
def init_deque_structure(window_sizes, number_of_states): def init_deque_structure(window_sizes, number_of_states):
""" Initialize a 3 level deque data structure. """ Initialize a 3 level deque data structure.
:param window_sizes: The required window sizes. :param window_sizes: The required window sizes.
:type window_sizes: list(int)
:param number_of_states: The number of states. :param number_of_states: The number of states.
:type number_of_states: int,>0
:return: The initialized 3 level deque data structure. :return: The initialized 3 level deque data structure.
:rtype: list(list(dict))
""" """
structure = [] structure = []
for i in range(number_of_states): for i in range(number_of_states):
@ -317,18 +221,12 @@ def init_deque_structure(window_sizes, number_of_states):
return structure return structure
@contract
def init_selected_window_sizes(window_sizes, number_of_states): def init_selected_window_sizes(window_sizes, number_of_states):
""" Initialize a selected window sizes data structure. """ Initialize a selected window sizes data structure.
:param window_sizes: The required window sizes. :param window_sizes: The required window sizes.
:type window_sizes: list(int)
:param number_of_states: The number of states. :param number_of_states: The number of states.
:type number_of_states: int,>0
:return: The initialized selected window sizes data structure. :return: The initialized selected window sizes data structure.
:rtype: list(list(int))
""" """
structure = [] structure = []
for i in range(number_of_states): for i in range(number_of_states):

View File

@ -15,31 +15,16 @@
""" Functions for defing the NLP problem of the MHOD algorithm. """ Functions for defing the NLP problem of the MHOD algorithm.
""" """
from contracts import contract
from neat.contracts_primitive import *
from neat.contracts_extra import *
import operator import operator
import logging
log = logging.getLogger(__name__)
@contract
def build_objective(ls, state_vector, p): def build_objective(ls, state_vector, p):
""" Creates an objective function, which is a sum of the L functions. """ Creates an objective function, which is a sum of the L functions.
:param ls: A list of L functions. :param ls: A list of L functions.
:type ls: list(function)
:param state-vector: A state vector. :param state-vector: A state vector.
:type state-vector: list(int)
:param p: A matrix of transition probabilities. :param p: A matrix of transition probabilities.
:type p: list(list(number))
:return: An objective function. :return: An objective function.
:rtype: function
""" """
def objective(*m): def objective(*m):
return sum(l(state_vector, p, list(m)) for l in ls) return sum(l(state_vector, p, list(m)) for l in ls)
@ -52,28 +37,13 @@ def build_constraint(otf, migration_time, ls, state_vector,
""" Creates an optimization constraint from the L functions. """ Creates an optimization constraint from the L functions.
:param otf: The OTF parameter. :param otf: The OTF parameter.
:type otf: float
:param migration_time: The VM migration time in time steps. :param migration_time: The VM migration time in time steps.
:type migration_time: float,>=0
:param ls: A list of L functions. :param ls: A list of L functions.
:type ls: list(function)
:param state-vector: A state vector. :param state-vector: A state vector.
:type state-vector: list(int)
:param p: A matrix of transition probabilities. :param p: A matrix of transition probabilities.
:type p: list(list(number))
:param time_in_states: The total time in all the states in time steps. :param time_in_states: The total time in all the states in time steps.
:type time_in_states: number,>=0
:param time_in_state_n: The total time in the state N in time steps. :param time_in_state_n: The total time in the state N in time steps.
:type time_in_state_n: number,>=0
:return: The created constraint. :return: The created constraint.
:rtype: tuple(function, function, number)
""" """
def constraint(*m): def constraint(*m):
m_list = list(m) m_list = list(m)

View File

@ -15,29 +15,19 @@
""" OTF threshold based algorithms. """ OTF threshold based algorithms.
""" """
from contracts import contract from oslo_log import log as logging
from neat.contracts_primitive import *
from neat.contracts_extra import *
LOG = logging.getLogger(__name__)
import logging
log = logging.getLogger(__name__)
@contract
def otf_factory(time_step, migration_time, params): def otf_factory(time_step, migration_time, params):
""" Creates the OTF algorithm with limiting and migration time. """ Creates the OTF algorithm with limiting and migration time.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the OTF algorithm. :return: A function implementing the OTF algorithm.
:rtype: function
""" """
migration_time_normalized = float(migration_time) / time_step migration_time_normalized = float(migration_time) / time_step
def otf_wrapper(utilization, state=None): def otf_wrapper(utilization, state=None):
@ -54,48 +44,33 @@ def otf_factory(time_step, migration_time, params):
return otf_wrapper return otf_wrapper
@contract
def otf(otf, threshold, limit, migration_time, utilization, state): def otf(otf, threshold, limit, migration_time, utilization, state):
""" The OTF threshold algorithm with limiting and migration time. """ The OTF threshold algorithm with limiting and migration time.
:param otf: The threshold on the OTF value. :param otf: The threshold on the OTF value.
:type otf: float,>=0
:param threshold: The utilization overload threshold. :param threshold: The utilization overload threshold.
:type threshold: float,>=0
:param limit: The minimum number of values in the utilization history. :param limit: The minimum number of values in the utilization history.
:type limit: int,>=0
:param migration_time: The VM migration time in time steps. :param migration_time: The VM migration time in time steps.
:type migration_time: float,>=0
:param utilization: The history of the host's CPU utilization. :param utilization: The history of the host's CPU utilization.
:type utilization: list(float)
:param state: The state dictionary. :param state: The state dictionary.
:type state: dict(str: *)
:return: The decision of the algorithm and updated state. :return: The decision of the algorithm and updated state.
:rtype: tuple(bool, dict(*: *))
""" """
state['total'] += 1 state['total'] += 1
overload = (utilization[-1] >= threshold) overload = (utilization[-1] >= threshold)
if overload: if overload:
state['overload'] += 1 state['overload'] += 1
if log.isEnabledFor(logging.DEBUG): LOG.debug('OTF overload:' + str(overload))
log.debug('OTF overload:' + str(overload)) LOG.debug('OTF overload steps:' + str(state['overload']))
log.debug('OTF overload steps:' + str(state['overload'])) LOG.debug('OTF total steps:' + str(state['total']))
log.debug('OTF total steps:' + str(state['total'])) LOG.debug('OTF:' + str(float(state['overload']) / state['total']))
log.debug('OTF:' + str(float(state['overload']) / state['total'])) LOG.debug('OTF migration time:' + str(migration_time))
log.debug('OTF migration time:' + str(migration_time)) LOG.debug('OTF + migration time:' +
log.debug('OTF + migration time:' + str((migration_time + state['overload']) / \
str((migration_time + state['overload']) / \ (migration_time + state['total'])))
(migration_time + state['total']))) LOG.debug('OTF decision:' +
log.debug('OTF decision:' + str(overload and (migration_time + state['overload']) / \
str(overload and (migration_time + state['overload']) / \ (migration_time + state['total']) >= otf))
(migration_time + state['total']) >= otf))
if not overload or len(utilization) < limit: if not overload or len(utilization) < limit:
decision = False decision = False

View File

@ -15,33 +15,18 @@
""" Statistics based overload detection algorithms. """ Statistics based overload detection algorithms.
""" """
from contracts import contract
from neat.contracts_primitive import *
from neat.contracts_extra import *
from numpy import median from numpy import median
from scipy.optimize import leastsq from scipy.optimize import leastsq
import numpy as np import numpy as np
import logging
log = logging.getLogger(__name__)
@contract
def loess_factory(time_step, migration_time, params): def loess_factory(time_step, migration_time, params):
""" Creates the Loess based overload detection algorithm. """ Creates the Loess based overload detection algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the OTF algorithm. :return: A function implementing the OTF algorithm.
:rtype: function
""" """
migration_time_normalized = float(migration_time) / time_step migration_time_normalized = float(migration_time) / time_step
return lambda utilization, state=None: \ return lambda utilization, state=None: \
@ -53,21 +38,13 @@ def loess_factory(time_step, migration_time, params):
{}) {})
@contract
def loess_robust_factory(time_step, migration_time, params): def loess_robust_factory(time_step, migration_time, params):
""" Creates the robust Loess based overload detection algorithm. """ Creates the robust Loess based overload detection algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the OTF algorithm. :return: A function implementing the OTF algorithm.
:rtype: function
""" """
migration_time_normalized = float(migration_time) / time_step migration_time_normalized = float(migration_time) / time_step
return lambda utilization, state=None: \ return lambda utilization, state=None: \
@ -79,21 +56,13 @@ def loess_robust_factory(time_step, migration_time, params):
{}) {})
@contract
def mad_threshold_factory(time_step, migration_time, params): def mad_threshold_factory(time_step, migration_time, params):
""" Creates the MAD based utilization threshold algorithm. """ Creates the MAD based utilization threshold algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the static threshold algorithm. :return: A function implementing the static threshold algorithm.
:rtype: function
""" """
return lambda utilization, state=None: \ return lambda utilization, state=None: \
(mad_threshold(params['threshold'], (mad_threshold(params['threshold'],
@ -102,21 +71,13 @@ def mad_threshold_factory(time_step, migration_time, params):
{}) {})
@contract
def iqr_threshold_factory(time_step, migration_time, params): def iqr_threshold_factory(time_step, migration_time, params):
""" Creates the IQR based utilization threshold algorithm. """ Creates the IQR based utilization threshold algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the static threshold algorithm. :return: A function implementing the static threshold algorithm.
:rtype: function
""" """
return lambda utilization, state=None: \ return lambda utilization, state=None: \
(iqr_threshold(params['threshold'], (iqr_threshold(params['threshold'],
@ -125,27 +86,15 @@ def iqr_threshold_factory(time_step, migration_time, params):
{}) {})
@contract
def loess(threshold, param, length, migration_time, utilization): def loess(threshold, param, length, migration_time, utilization):
""" The Loess based overload detection algorithm. """ The Loess based overload detection algorithm.
:param threshold: The CPU utilization threshold. :param threshold: The CPU utilization threshold.
:type threshold: float
:param param: The safety parameter. :param param: The safety parameter.
:type param: float
:param length: The required length of the utilization history. :param length: The required length of the utilization history.
:type length: int
:param migration_time: The VM migration time in time steps. :param migration_time: The VM migration time in time steps.
:type migration_time: float
:param utilization: The utilization history to analize. :param utilization: The utilization history to analize.
:type utilization: list(float)
:return: A decision of whether the host is overloaded. :return: A decision of whether the host is overloaded.
:rtype: bool
""" """
return loess_abstract(loess_parameter_estimates, return loess_abstract(loess_parameter_estimates,
threshold, threshold,
@ -155,27 +104,15 @@ def loess(threshold, param, length, migration_time, utilization):
utilization) utilization)
@contract
def loess_robust(threshold, param, length, migration_time, utilization): def loess_robust(threshold, param, length, migration_time, utilization):
""" The robust Loess based overload detection algorithm. """ The robust Loess based overload detection algorithm.
:param threshold: The CPU utilization threshold. :param threshold: The CPU utilization threshold.
:type threshold: float
:param param: The safety parameter. :param param: The safety parameter.
:type param: float
:param length: The required length of the utilization history. :param length: The required length of the utilization history.
:type length: int
:param migration_time: The VM migration time in time steps. :param migration_time: The VM migration time in time steps.
:type migration_time: float
:param utilization: The utilization history to analize. :param utilization: The utilization history to analize.
:type utilization: list(float)
:return: A decision of whether the host is overloaded. :return: A decision of whether the host is overloaded.
:rtype: bool
""" """
return loess_abstract(loess_robust_parameter_estimates, return loess_abstract(loess_robust_parameter_estimates,
threshold, threshold,
@ -185,30 +122,16 @@ def loess_robust(threshold, param, length, migration_time, utilization):
utilization) utilization)
@contract
def loess_abstract(estimator, threshold, param, length, migration_time, utilization): def loess_abstract(estimator, threshold, param, length, migration_time, utilization):
""" The abstract Loess algorithm. """ The abstract Loess algorithm.
:param estimator: A parameter estimation function. :param estimator: A parameter estimation function.
:type estimator: function
:param threshold: The CPU utilization threshold. :param threshold: The CPU utilization threshold.
:type threshold: float
:param param: The safety parameter. :param param: The safety parameter.
:type param: float
:param length: The required length of the utilization history. :param length: The required length of the utilization history.
:type length: int
:param migration_time: The VM migration time in time steps. :param migration_time: The VM migration time in time steps.
:type migration_time: float
:param utilization: The utilization history to analize. :param utilization: The utilization history to analize.
:type utilization: list(float)
:return: A decision of whether the host is overloaded. :return: A decision of whether the host is overloaded.
:rtype: bool
""" """
if len(utilization) < length: if len(utilization) < length:
return False return False
@ -217,92 +140,60 @@ def loess_abstract(estimator, threshold, param, length, migration_time, utilizat
return param * prediction >= threshold return param * prediction >= threshold
@contract
def mad_threshold(param, limit, utilization): def mad_threshold(param, limit, utilization):
""" The MAD based threshold algorithm. """ The MAD based threshold algorithm.
:param param: The safety parameter. :param param: The safety parameter.
:type param: float
:param limit: The minimum allowed length of the utilization history. :param limit: The minimum allowed length of the utilization history.
:type limit: int
:param utilization: The utilization history to analize. :param utilization: The utilization history to analize.
:type utilization: list(float)
:return: A decision of whether the host is overloaded. :return: A decision of whether the host is overloaded.
:rtype: bool
""" """
return utilization_threshold_abstract(lambda x: 1 - param * mad(x), return utilization_threshold_abstract(lambda x: 1 - param * mad(x),
limit, limit,
utilization) utilization)
@contract
def iqr_threshold(param, limit, utilization): def iqr_threshold(param, limit, utilization):
""" The IQR based threshold algorithm. """ The IQR based threshold algorithm.
:param param: The safety parameter. :param param: The safety parameter.
:type param: float
:param limit: The minimum allowed length of the utilization history. :param limit: The minimum allowed length of the utilization history.
:type limit: int
:param utilization: The utilization history to analize. :param utilization: The utilization history to analize.
:type utilization: list(float)
:return: A decision of whether the host is overloaded. :return: A decision of whether the host is overloaded.
:rtype: bool
""" """
return utilization_threshold_abstract(lambda x: 1 - param * iqr(x), return utilization_threshold_abstract(lambda x: 1 - param * iqr(x),
limit, limit,
utilization) utilization)
@contract
def utilization_threshold_abstract(f, limit, utilization): def utilization_threshold_abstract(f, limit, utilization):
""" The abstract utilization threshold algorithm. """ The abstract utilization threshold algorithm.
:param f: A function to calculate the utilization threshold. :param f: A function to calculate the utilization threshold.
:type f: function
:param limit: The minimum allowed length of the utilization history. :param limit: The minimum allowed length of the utilization history.
:type limit: int
:param utilization: The utilization history to analize. :param utilization: The utilization history to analize.
:type utilization: list(float)
:return: A decision of whether the host is overloaded. :return: A decision of whether the host is overloaded.
:rtype: bool
""" """
if (len(utilization) < limit): if (len(utilization) < limit):
return False return False
return f(utilization) <= utilization[-1] return f(utilization) <= utilization[-1]
@contract
def mad(data): def mad(data):
""" Calculate the Median Absolute Deviation from the data. """ Calculate the Median Absolute Deviation from the data.
:param data: The data to analyze. :param data: The data to analyze.
:type data: list(number)
:return: The calculated MAD. :return: The calculated MAD.
:rtype: float
""" """
data_median = median(data) data_median = median(data)
return float(median([abs(data_median - x) for x in data])) return float(median([abs(data_median - x) for x in data]))
@contract
def iqr(data): def iqr(data):
""" Calculate the Interquartile Range from the data. """ Calculate the Interquartile Range from the data.
:param data: The data to analyze. :param data: The data to analyze.
:type data: list(number)
:return: The calculated IQR. :return: The calculated IQR.
:rtype: float
""" """
sorted_data = sorted(data) sorted_data = sorted(data)
n = len(data) + 1 n = len(data) + 1
@ -311,15 +202,11 @@ def iqr(data):
return float(sorted_data[q3] - sorted_data[q1]) return float(sorted_data[q3] - sorted_data[q1])
@contract
def loess_parameter_estimates(data): def loess_parameter_estimates(data):
""" Calculate Loess parameter estimates. """ Calculate Loess parameter estimates.
:param data: A data set. :param data: A data set.
:type data: list(float)
:return: The parameter estimates. :return: The parameter estimates.
:rtype: list(float)
""" """
def f(p, x, y, weights): def f(p, x, y, weights):
return weights * (y - (p[0] + p[1] * x)) return weights * (y - (p[0] + p[1] * x))
@ -333,15 +220,11 @@ def loess_parameter_estimates(data):
return estimates.tolist() return estimates.tolist()
@contract
def loess_robust_parameter_estimates(data): def loess_robust_parameter_estimates(data):
""" Calculate Loess robust parameter estimates. """ Calculate Loess robust parameter estimates.
:param data: A data set. :param data: A data set.
:type data: list(float)
:return: The parameter estimates. :return: The parameter estimates.
:rtype: list(float)
""" """
def f(p, x, y, weights): def f(p, x, y, weights):
return weights * (y - (p[0] + p[1] * x)) return weights * (y - (p[0] + p[1] * x))
@ -361,15 +244,11 @@ def loess_robust_parameter_estimates(data):
return estimates2.tolist() return estimates2.tolist()
@contract
def tricube_weights(n): def tricube_weights(n):
""" Generates a list of weights according to the tricube function. """ Generates a list of weights according to the tricube function.
:param n: The number of weights to generate. :param n: The number of weights to generate.
:type n: int
:return: A list of generated weights. :return: A list of generated weights.
:rtype: list(float)
""" """
spread = top = float(n - 1) spread = top = float(n - 1)
weights = [] weights = []
@ -378,15 +257,11 @@ def tricube_weights(n):
return [weights[0], weights[0]] + weights return [weights[0], weights[0]] + weights
@contract
def tricube_bisquare_weights(data): def tricube_bisquare_weights(data):
""" Generates a weights according to the tricube bisquare function. """ Generates a weights according to the tricube bisquare function.
:param data: The input data. :param data: The input data.
:type data: list(float)
:return: A list of generated weights. :return: A list of generated weights.
:rtype: list(float)
""" """
n = len(data) n = len(data)
s6 = 6 * median(map(abs, data)) s6 = 6 * median(map(abs, data))

View File

@ -15,69 +15,38 @@
""" Trivial overload detection algorithms. """ Trivial overload detection algorithms.
""" """
from contracts import contract
from neat.contracts_primitive import *
from neat.contracts_extra import *
import logging
log = logging.getLogger(__name__)
@contract
def never_overloaded_factory(time_step, migration_time, params): def never_overloaded_factory(time_step, migration_time, params):
""" Creates an algorithm that never considers the host overloaded. """ Creates an algorithm that never considers the host overloaded.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the algorithm. :return: A function implementing the algorithm.
:rtype: function
""" """
return lambda utilization, state=None: (False, {}) return lambda utilization, state=None: (False, {})
@contract
def threshold_factory(time_step, migration_time, params): def threshold_factory(time_step, migration_time, params):
""" Creates the static CPU utilization threshold algorithm. """ Creates the static CPU utilization threshold algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the static threshold algorithm. :return: A function implementing the static threshold algorithm.
:rtype: function
""" """
return lambda utilization, state=None: (threshold(params['threshold'], return lambda utilization, state=None: (threshold(params['threshold'],
utilization), utilization),
{}) {})
@contract
def last_n_average_threshold_factory(time_step, migration_time, params): def last_n_average_threshold_factory(time_step, migration_time, params):
""" Creates the averaging CPU utilization threshold algorithm. """ Creates the averaging CPU utilization threshold algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the averaging threshold algorithm. :return: A function implementing the averaging threshold algorithm.
:rtype: function
""" """
return lambda utilization, state=None: ( return lambda utilization, state=None: (
last_n_average_threshold(params['threshold'], last_n_average_threshold(params['threshold'],
@ -86,39 +55,25 @@ def last_n_average_threshold_factory(time_step, migration_time, params):
{}) {})
@contract
def threshold(threshold, utilization): def threshold(threshold, utilization):
""" The static CPU utilization threshold algorithm. """ The static CPU utilization threshold algorithm.
:param threshold: The threshold on the CPU utilization. :param threshold: The threshold on the CPU utilization.
:type threshold: float,>=0
:param utilization: The history of the host's CPU utilization. :param utilization: The history of the host's CPU utilization.
:type utilization: list(float)
:return: The decision of the algorithm. :return: The decision of the algorithm.
:rtype: bool
""" """
if utilization: if utilization:
return utilization[-1] > threshold return utilization[-1] > threshold
return False return False
@contract
def last_n_average_threshold(threshold, n, utilization): def last_n_average_threshold(threshold, n, utilization):
""" The averaging CPU utilization threshold algorithm. """ The averaging CPU utilization threshold algorithm.
:param threshold: The threshold on the CPU utilization. :param threshold: The threshold on the CPU utilization.
:type threshold: float,>=0
:param n: The number of last CPU utilization values to average. :param n: The number of last CPU utilization values to average.
:type n: int,>0
:param utilization: The history of the host's CPU utilization. :param utilization: The history of the host's CPU utilization.
:type utilization: list(float)
:return: The decision of the algorithm. :return: The decision of the algorithm.
:rtype: bool
""" """
if utilization: if utilization:
utilization = utilization[-n:] utilization = utilization[-n:]

View File

@ -15,68 +15,37 @@
""" Trivial underload detection algorithms. """ Trivial underload detection algorithms.
""" """
from contracts import contract
from neat.contracts_primitive import *
from neat.contracts_extra import *
import logging
log = logging.getLogger(__name__)
@contract
def always_underloaded_factory(time_step, migration_time, params): def always_underloaded_factory(time_step, migration_time, params):
""" Creates an algorithm that always considers the host underloaded. """ Creates an algorithm that always considers the host underloaded.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the algorithm. :return: A function implementing the algorithm.
:rtype: function
""" """
return lambda utilization, state=None: (True, {}) return lambda utilization, state=None: (True, {})
@contract
def threshold_factory(time_step, migration_time, params): def threshold_factory(time_step, migration_time, params):
""" Creates the threshold underload detection algorithm. """ Creates the threshold underload detection algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the OTF algorithm. :return: A function implementing the OTF algorithm.
:rtype: function
""" """
return lambda utilization, state=None: (threshold(params['threshold'], return lambda utilization, state=None: (threshold(params['threshold'],
utilization), utilization),
{}) {})
@contract
def last_n_average_threshold_factory(time_step, migration_time, params): def last_n_average_threshold_factory(time_step, migration_time, params):
""" Creates the averaging threshold underload detection algorithm. """ Creates the averaging threshold underload detection algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the averaging underload detection. :return: A function implementing the averaging underload detection.
:rtype: function
""" """
return lambda utilization, state=None: ( return lambda utilization, state=None: (
last_n_average_threshold(params['threshold'], last_n_average_threshold(params['threshold'],
@ -85,7 +54,6 @@ def last_n_average_threshold_factory(time_step, migration_time, params):
{}) {})
@contract
def threshold(threshold, utilization): def threshold(threshold, utilization):
""" Static threshold-based underload detection algorithm. """ Static threshold-based underload detection algorithm.
@ -93,20 +61,14 @@ def threshold(threshold, utilization):
CPU utilization is lower than the specified threshold. CPU utilization is lower than the specified threshold.
:param threshold: The static underload CPU utilization threshold. :param threshold: The static underload CPU utilization threshold.
:type threshold: float,>=0,<=1
:param utilization: The history of the host's CPU utilization. :param utilization: The history of the host's CPU utilization.
:type utilization: list(float)
:return: A decision of whether the host is underloaded. :return: A decision of whether the host is underloaded.
:rtype: bool
""" """
if utilization: if utilization:
return utilization[-1] <= threshold return utilization[-1] <= threshold
return False return False
@contract
def last_n_average_threshold(threshold, n, utilization): def last_n_average_threshold(threshold, n, utilization):
""" Averaging static threshold-based underload detection algorithm. """ Averaging static threshold-based underload detection algorithm.
@ -114,16 +76,9 @@ def last_n_average_threshold(threshold, n, utilization):
the host's CPU utilization is lower than the specified threshold. the host's CPU utilization is lower than the specified threshold.
:param threshold: The static underload CPU utilization threshold. :param threshold: The static underload CPU utilization threshold.
:type threshold: float,>=0,<=1
:param n: The number of last values to average. :param n: The number of last values to average.
:type n: int,>0
:param utilization: The history of the host's CPU utilization. :param utilization: The history of the host's CPU utilization.
:type utilization: list(float)
:return: A decision of whether the host is underloaded. :return: A decision of whether the host is underloaded.
:rtype: bool
""" """
if utilization: if utilization:
utilization = utilization[-n:] utilization = utilization[-n:]

View File

@ -15,91 +15,52 @@
""" VM selection algorithms. """ VM selection algorithms.
""" """
from contracts import contract
from neat.contracts_primitive import *
from neat.contracts_extra import *
from random import choice from random import choice
import operator import operator
import logging
log = logging.getLogger(__name__)
@contract
def random_factory(time_step, migration_time, params): def random_factory(time_step, migration_time, params):
""" Creates the random VM selection algorithm. """ Creates the random VM selection algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the random VM selection algorithm. :return: A function implementing the random VM selection algorithm.
:rtype: function
""" """
return lambda vms_cpu, vms_ram, state=None: ([random(vms_cpu)], {}) return lambda vms_cpu, vms_ram, state=None: ([random(vms_cpu)], {})
@contract
def minimum_utilization_factory(time_step, migration_time, params): def minimum_utilization_factory(time_step, migration_time, params):
""" Creates the minimum utilization VM selection algorithm. """ Creates the minimum utilization VM selection algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the minimum utilization VM selection. :return: A function implementing the minimum utilization VM selection.
:rtype: function
""" """
return lambda vms_cpu, vms_ram, state=None: \ return lambda vms_cpu, vms_ram, state=None: \
([minimum_utilization(vms_cpu)], {}) ([minimum_utilization(vms_cpu)], {})
@contract
def minimum_migration_time_factory(time_step, migration_time, params): def minimum_migration_time_factory(time_step, migration_time, params):
""" Creates the minimum migration time VM selection algorithm. """ Creates the minimum migration time VM selection algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the minimum migration time VM selection. :return: A function implementing the minimum migration time VM selection.
:rtype: function
""" """
return lambda vms_cpu, vms_ram, state=None: \ return lambda vms_cpu, vms_ram, state=None: \
([minimum_migration_time(vms_ram)], {}) ([minimum_migration_time(vms_ram)], {})
@contract
def minimum_migration_time_max_cpu_factory(time_step, migration_time, params): def minimum_migration_time_max_cpu_factory(time_step, migration_time, params):
""" Creates the minimum migration time / max CPU usage VM selection algorithm. """ Creates the minimum migration time / max CPU usage VM selection algorithm.
:param time_step: The length of the simulation time step in seconds. :param time_step: The length of the simulation time step in seconds.
:type time_step: int,>=0
:param migration_time: The VM migration time in time seconds. :param migration_time: The VM migration time in time seconds.
:type migration_time: float,>=0
:param params: A dictionary containing the algorithm's parameters. :param params: A dictionary containing the algorithm's parameters.
:type params: dict(str: *)
:return: A function implementing the minimum migration time / max CPU VM selection. :return: A function implementing the minimum migration time / max CPU VM selection.
:rtype: function
""" """
return lambda vms_cpu, vms_ram, state=None: \ return lambda vms_cpu, vms_ram, state=None: \
([minimum_migration_time_max_cpu(params['last_n'], ([minimum_migration_time_max_cpu(params['last_n'],
@ -107,30 +68,22 @@ def minimum_migration_time_max_cpu_factory(time_step, migration_time, params):
vms_ram)], {}) vms_ram)], {})
@contract
def minimum_migration_time(vms_ram): def minimum_migration_time(vms_ram):
""" Selects the VM with the minimum RAM usage. """ Selects the VM with the minimum RAM usage.
:param vms_ram: A map of VM UUID and their RAM usage data. :param vms_ram: A map of VM UUID and their RAM usage data.
:type vms_ram: dict(str: number)
:return: A VM to migrate from the host. :return: A VM to migrate from the host.
:rtype: str
""" """
min_index, min_value = min(enumerate(vms_ram.values()), min_index, min_value = min(enumerate(vms_ram.values()),
key=operator.itemgetter(1)) key=operator.itemgetter(1))
return vms_ram.keys()[min_index] return vms_ram.keys()[min_index]
@contract
def minimum_utilization(vms_cpu): def minimum_utilization(vms_cpu):
""" Selects the VM with the minimum CPU utilization. """ Selects the VM with the minimum CPU utilization.
:param vms_cpu: A map of VM UUID and their CPU utilization histories. :param vms_cpu: A map of VM UUID and their CPU utilization histories.
:type vms_cpu: dict(str: list)
:return: A VM to migrate from the host. :return: A VM to migrate from the host.
:rtype: str
""" """
last_utilization = [x[-1] for x in vms_cpu.values()] last_utilization = [x[-1] for x in vms_cpu.values()]
min_index, min_value = min(enumerate(last_utilization), min_index, min_value = min(enumerate(last_utilization),
@ -138,34 +91,22 @@ def minimum_utilization(vms_cpu):
return vms_cpu.keys()[min_index] return vms_cpu.keys()[min_index]
@contract
def random(vms_cpu): def random(vms_cpu):
""" Selects a random VM. """ Selects a random VM.
:param vms_cpu: A map of VM UUID and their CPU utilization histories. :param vms_cpu: A map of VM UUID and their CPU utilization histories.
:type vms_cpu: dict(str: list)
:return: A VM to migrate from the host. :return: A VM to migrate from the host.
:rtype: str
""" """
return choice(vms_cpu.keys()) return choice(vms_cpu.keys())
@contract
def minimum_migration_time_max_cpu(last_n, vms_cpu, vms_ram): def minimum_migration_time_max_cpu(last_n, vms_cpu, vms_ram):
""" Selects the VM with the minimum RAM and maximum CPU usage. """ Selects the VM with the minimum RAM and maximum CPU usage.
:param last_n: The number of last CPU utilization values to average. :param last_n: The number of last CPU utilization values to average.
:type last_n: int,>0
:param vms_cpu: A map of VM UUID and their CPU utilization histories. :param vms_cpu: A map of VM UUID and their CPU utilization histories.
:type vms_cpu: dict(str: list)
:param vms_ram: A map of VM UUID and their RAM usage data. :param vms_ram: A map of VM UUID and their RAM usage data.
:type vms_ram: dict(str: number)
:return: A VM to migrate from the host. :return: A VM to migrate from the host.
:rtype: str
""" """
min_ram = min(vms_ram.values()) min_ram = min(vms_ram.values())
max_cpu = 0 max_cpu = 0

View File

@ -12,21 +12,17 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from oslo.config import cfg from oslo_config import cfg
from oslo import messaging from oslo_log import log as logging
from oslo_messaging.rpc import client from oslo_messaging.rpc import client
from mistral import context as auth_ctx from terracotta import context as auth_ctx
from mistral.engine import base from terracotta import exceptions as exc
from mistral import exceptions as exc
from mistral.openstack.common import log as logging
from mistral.workflow import utils as wf_utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
_TRANSPORT = None _TRANSPORT = None
_ENGINE_CLIENT = None _ENGINE_CLIENT = None
_EXECUTOR_CLIENT = None _EXECUTOR_CLIENT = None

View File

View File