2012-09-25 15:59:45 +10:00

230 lines
7.0 KiB
Python

# Copyright 2012 Anton Beloglazov
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""" This is the main module of the MHOD algorithm.
"""
from contracts import contract
from neat.contracts_extra import *
import neat.locals.overload.mhod.multisize_estimation as estimation
import neat.locals.overload.mhod.bruteforce as bruteforce
from neat.locals.overload.mhod.l_2_states import ls
import logging
log = logging.getLogger(__name__)
@contract
def init_state(window_sizes, number_of_states):
""" Initialize the state dictionary of the MHOD algorithm.
:param window_sizes: The required window sizes.
:type window_sizes: list(int)
:param number_of_states: The number of states.
:type number_of_states: int,>0
:return: The initialization state dictionary.
:rtype: dict(str: *)
"""
state = {}
state['previous_state'] = 0
state['request_windows'] = estimation.init_request_windows(
number_of_states)
state['estimate_windows'] = estimation.init_deque_structure(
window_sizes, number_of_states)
state['variances'] = estimation.init_variances(
window_sizes, number_of_states)
state['acceptable_variances'] = estimation.init_variances(
window_sizes, number_of_states)
return state
@contract
def execute(state_config, otf, window_sizes, bruteforce_step,
time_step, migration_time, utilization, state):
""" The MHOD algorithm returning whether the host is overloaded.
:param state_config: The state configuration.
:type state_config: list(float)
:param otf: The OTF parameter.
:type otf: int,>0
:param window_sizes: A list of window sizes.
:type window_sizes: list(int)
:param bruteforce_step: The step of the bruteforce algorithm.
:type bruteforce_step: float
:param time_step: The lenght of a time frame in seconds.
:type time_step: int
:param migration_time: The VM migration time in seconds.
:type migration_time: int
:param utilization: The history of the host's CPU utilization.
:type utilization: list(float)
:param state: The state of the algorithm.
:type state: dict
:return: The updated state and decision of the algorithm.
:rtype: tuple(dict, bool)
"""
total_time = len(utilization)
max_window_size = max(window_sizes)
state_vector = build_state_vector(state_config, utilization)
state = current_state(state_vector)
selected_windows = estimation.select_window(
state['variances'],
state['acceptable_variances'],
window_sizes)
p = estimation.select_best_estimates(
state['estimate_windows'],
selected_windows)
state['request_windows'] = estimation.update_request_windows(
state['request_windows'],
max_window_size,
state['previous_state'],
state)
state['estimate_windows'] = estimation.update_estimate_windows(
state['estimate_windows'],
state['request_windows'],
state['previous_state'])
state['variances'] = estimation.update_variances(
state['variances'],
state['estimate_windows'],
state['previous_state'])
state['acceptable_variances'] = estimation.update_acceptable_variances(
state['acceptable_variances'],
state['estimate_windows'],
state['previous_state'])
state['previous_state'] = state
if len(utilization) >= 30:
state_history = utilization_to_states(state_config, utilization)
time_in_states = total_time
time_in_state_n = get_time_in_state_n(state_config, state_history)
tmp = set(p[state])
if len(tmp) != 1 or tmp[0] != 0:
policy = bruteforce.optimize(
step, 1.0, otf, (migration_time / time_step), ls,
p, state_vector, time_in_states, time_in_state_n)
return issue_command_deterministic(policy)
return false
@contract
def build_state_vector(state_config, utilization):
""" Build the current state PMF corresponding to the utilization
history and state config.
:param state_config: The state configuration.
:type state_config: list(float)
:param utilization: The history of the host's CPU utilization.
:type utilization: list(float)
:return: The current state vector.
:rtype: list(int)
"""
state = utilization_to_state(state_config, utilization[-1])
return [int(state == x) for x in range(len(state_config) + 1)]
@contract
def utilization_to_state(state_config, utilization):
""" Transform a utilization value into the corresponding state.
:param state_config: The state configuration.
:type state_config: list(float)
:param utilization: A utilization value.
:type utilization: number,>=0
:return: The state corresponding to the utilization value.
:rtype: int
"""
prev = -1
for state, threshold in enumerate(state_config):
if utilization >= prev and utilization < threshold:
return state
prev = state
return prev + 1
@contract
def current_state(state_vector):
""" Get the current state corresponding to the state probability vector.
:param state_vector: The state PMF vector.
:type state_vector: list(int)
:return: The current state.
:rtype: int,>=0
"""
return state_vector.index(1)
@contract
def utilization_to_states(state_config, utilization):
""" Get the state history corresponding to the utilization history.
Adds the 0 state to the beginning to simulate the first transition.
(map (partial utilization-to-state state-config) utilization))
:param state_config: The state configuration.
:type state_config: list(float)
:param utilization: The history of the host's CPU utilization.
:type utilization: list(float)
:return: The state history.
:rtype: list(int)
"""
return [utilization_to_state(state_config, x) for x in utilization]
@contract
def get_time_in_state_n(state_config, state_history):
""" Get the number of time steps the system has been in the state N.
:param state_config: The state configuration.
:type state_config: list(float)
:param state_history: The state history.
:type state_history: list(int)
:return: The total time the system has been in the state N.
:rtype: int
"""
return state_history.count(len(state_config))
@contract
def issue_command_deterministic(policy):
""" Issue a migration command according to the policy PMF p.
:param policy: A policy PMF.
:type policy: list(number)
:return: A migration command.
:rtype: bool
"""
return len(policy) == 0