consolidation of watcher

Change-Id: I9c82ef4d8a81af98afdfc34f5ad496bcade4af6a
This commit is contained in:
Jean-Emile DARTOIS
2015-10-22 17:02:45 +02:00
parent 8c76c7fbef
commit 74160c5e78
140 changed files with 2991 additions and 1271 deletions

View File

@@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.api.messaging.decision_engine_command import \
DecisionEngineCommand
from watcher.tests import base
class TestDecisionEngineCommand(base.TestCase):
def test_execute(self):
DEC = DecisionEngineCommand()
self.assertRaises(NotImplementedError, DEC.execute)

View File

@@ -0,0 +1,30 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.api.messaging.event_consumer import EventConsumer
from watcher.tests import base
class TestEventConsumer(base.TestCase):
def test_set_messaging(self):
messaging = "test message"
EC = EventConsumer()
EC.set_messaging(messaging)
self.assertEqual(EC.messaging, messaging)
def test_execute(self):
EC = EventConsumer()
self.assertRaises(NotImplementedError, EC.execute, None, None, None)

View File

@@ -0,0 +1,24 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.api.planner.planner import Planner
from watcher.tests import base
class TestPlanner(base.TestCase):
def test_schedule(self):
pl = Planner()
self.assertRaises(NotImplementedError, pl.schedule, None, None, None)

View File

@@ -0,0 +1,26 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
'''from watcher.decision_engine.api.solution.solution import Solution
from watcher.decision_engine.framework.model.model_root import ModelRoot
from watcher.tests import base
class TestSolution(base.TestCase):
def test_get_model(self):
sol = Solution()
current_model =
sol.set_model(current_model)
'''

View File

@@ -0,0 +1,30 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.api.solution.solution import Solution as sol
from watcher.decision_engine.api.solution.solution_comparator import Solution
from watcher.tests import base
class test_Solution_Comparator(base.TestCase):
def test_compare(self):
sol1 = sol()
sol2 = sol()
solution_comparator = Solution()
self.assertRaises(NotImplementedError,
solution_comparator.compare,
sol1,
sol2)

View File

@@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.api.solution.solution_evaluator import \
SolutionEvaluator
from watcher.tests import base
class TestSolutionEvaluator(base.TestCase):
def test_evaluate(self):
SE = SolutionEvaluator()
self.assertRaises(NotImplementedError, SE.evaluate, None)

View File

@@ -0,0 +1,30 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.api.strategy.meta_action import MetaAction
from watcher.tests import base
class TestMetaAction(base.TestCase):
def test_get_priority(self):
MA = MetaAction()
MA.set_priority(3)
self.assertEqual(MA.get_priority(), 3)
def test_get_level(self):
MA = MetaAction()
MA.set_level(5)
self.assertEqual(MA.get_level(), 5)

View File

@@ -0,0 +1,24 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.api.strategy.selector import Selector
from watcher.tests import base
class TestSelector(base.TestCase):
def test_define_from_goal(self):
Sel = Selector()
self.assertRaises(NotImplementedError, Sel.define_from_goal, None)

View File

@@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.api.strategy.strategy_context import \
StrategyContext
from watcher.tests import base
class TestStrategyContext(base.TestCase):
def test_execute_strategy(self):
SC = StrategyContext()
self.assertRaises(NotImplementedError, SC.execute_strategy, None)

View File

@@ -1,103 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
#
# FIXME(jed): remove this class due jenkins build failed
# The following librairies are removed from requirement.txt :
# - numpy
# - matplotlib
# These dependencies required a server x, jenkin's server has no
# server x
# import matplotlib.pyplot as plt
# import numpy as np
from watcher.decision_engine.strategies.basic_consolidation import \
BasicConsolidation
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
class PlotConsolidationBasic(object):
def plot(self, sercon, orign_model, solution):
pass
# cluster_size = len(orign_model._hypervisors)
# labels = []
# before_score = []
# after_score = []
# for hypevisor_id in orign_model.get_all_hypervisors():
# labels.append(hypevisor_id)
# hypevisor = orign_model.get_hypervisor_from_id(hypevisor_id)
# result_before = sercon.calculate_score_node(hypevisor,
# orign_model)
# result_after = sercon.calculate_score_node(hypevisor,
# solution.get_model())
# before_score.append(float(result_before * 100))
# if result_after == 0:
# result_after = 0
# after_score.append(float(result_after * 100))
#
# ind = np.arange(cluster_size) # the x locations for the groups
# width = 0.35 # the width of the bars
#
# fig, ax = plt.subplots()
#
# rects1 = ax.bar(ind, before_score, width, color='b')
#
# rects2 = ax.bar(ind + width, after_score, width, color='r')
#
# # add some text for labels, title and axes ticks
# ax.set_ylabel(
# 'Score of each hypervisor that represent their \
# utilization level')
# ax.set_title('Watcher Basic Server consolidation (efficiency ' + str(
# sercon.get_solution().get_efficiency()) + " %)")
#
# ax.set_xticks(ind + width)
# ax.set_xticklabels(labels)
# ax.set_ylim([0, 140])
# ax.legend((rects1[0], rects2[0]),
# ('Before Consolidation', 'After Consolidation'))
# def autolabel(rects):
# # attach some text labels
# for rect in rects:
# height = rect.get_height()
# ax.text(rect.get_x() + rect.get_width() / 2., 1.05 * height,
# '%d' % int(height),
# ha='center', va='bottom')
#
# autolabel(rects1)
# autolabel(rects2)
# plt.show()
cluster = FakerStateCollector()
metrics = FakerMetricsCollector()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
# try overbooking ? :) 150 % cpu
sercon.set_threshold_cores(1)
model_cluster = cluster.generate_scenario_1()
solution = sercon.execute(model_cluster)
plot = PlotConsolidationBasic()
plot.plot(sercon, cluster.generate_scenario_1(), solution)

View File

@@ -1,45 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from oslo_config import cfg
import time
from watcher.decision_engine.strategies.basic_consolidation import \
BasicConsolidation
from watcher.openstack.common import log
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
LOG = log.getLogger(__name__)
cfg.CONF.debug = True
log.setup('metering-controller')
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation("basic", "Basic offline consolidation")
sercon.set_metrics_resource_collector(metrics)
start_time = time.clock()
solution = sercon.execute(current_state_cluster.generate_scenario_1())
print(time.clock() - start_time, "seconds")
print(solution)
# planner = DefaultPlanner()
# planner.schedule(solution)

View File

@@ -1,43 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from oslo_config import cfg
import time
from watcher.decision_engine.strategies.basic_consolidation import \
BasicConsolidation
from watcher.openstack.common import log
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
LOG = log.getLogger(__name__)
# debug on
cfg.CONF.debug = True
log.setup('metering-controller')
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
start_time = time.clock()
solution = sercon.execute(current_state_cluster.generate_scenario_1())
print("duration =" + str((time.clock() - start_time)), "seconds")
LOG.debug(solution)

View File

@@ -1,6 +1,8 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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
@@ -13,16 +15,17 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import random
from watcher.decision_engine.api.collector.cluster_state_collector import \
ClusterStateCollector
from watcher.decision_engine.framework.model.hypervisor import Hypervisor
from watcher.decision_engine.framework.model.model_root import ModelRoot
from watcher.decision_engine.framework.model.resource import Resource
from watcher.decision_engine.framework.model.resource import ResourceType
from watcher.decision_engine.framework.model.vm import VM
from watcher.metrics_engine.api.cluster_state_collector import \
ClusterStateCollector
class FakerStateCollector(ClusterStateCollector):
@@ -56,7 +59,7 @@ class FakerStateCollector(ClusterStateCollector):
for i in range(0, count_node):
node_uuid = "Node_" + str(i)
hypervisor = Hypervisor()
hypervisor.set_uuid(node_uuid)
hypervisor.uuid = node_uuid
mem.set_capacity(hypervisor, 132)
disk.set_capacity(hypervisor, 250)
num_cores.set_capacity(hypervisor, 40)
@@ -66,7 +69,7 @@ class FakerStateCollector(ClusterStateCollector):
for i in range(0, count_vm):
vm_uuid = "VM_" + str(i)
vm = VM()
vm.set_uuid(vm_uuid)
vm.uuid = vm_uuid
# print("create "+str(vm))
mem.set_capacity(vm, 8)
disk.set_capacity(vm, 10)
@@ -107,7 +110,7 @@ class FakerStateCollector(ClusterStateCollector):
for i in range(0, count_node):
node_uuid = "Node_" + str(i)
node = Hypervisor()
node.set_uuid(node_uuid)
node.uuid = node_uuid
mem.set_capacity(node, 132)
disk.set_capacity(node, 250)
@@ -118,7 +121,7 @@ class FakerStateCollector(ClusterStateCollector):
for i in range(0, count_vm):
vm_uuid = "VM_" + str(i)
vm = VM()
vm.set_uuid(vm_uuid)
vm.uuid = vm_uuid
# print("create "+str(vm))
mem.set_capacity(vm, 2)
disk.set_capacity(vm, 20)
@@ -178,7 +181,7 @@ class FakerStateCollector(ClusterStateCollector):
for i in range(0, count_node):
node_uuid = "Node_" + str(i)
node = Hypervisor()
node.set_uuid(node_uuid)
node.uuid = node_uuid
mem.set_capacity(node, 132)
disk.set_capacity(node, 250)
num_cores.set_capacity(node, 40)
@@ -215,7 +218,7 @@ class FakerStateCollector(ClusterStateCollector):
for i in range(0, count_node):
node_uuid = "Node_" + str(i)
node = Hypervisor()
node.set_uuid(node_uuid)
node.uuid = node_uuid
mem.set_capacity(node, 132)
disk.set_capacity(node, 250)
num_cores.set_capacity(node, 40)
@@ -225,14 +228,13 @@ class FakerStateCollector(ClusterStateCollector):
for i in range(0, count_vm):
vm_uuid = "VM_" + str(i)
vm = VM()
vm.set_uuid(vm_uuid)
vm.uuid = vm_uuid
# print("create "+str(vm))
mem.set_capacity(vm, 10)
disk.set_capacity(vm, 25)
num_cores.set_capacity(vm, 16)
vms.append(vm)
current_state_cluster.add_vm(vm)
print(count_vm)
indice = 0
for j in range(0, 2):
node_uuid = "Node_" + str(j)
@@ -253,3 +255,84 @@ class FakerStateCollector(ClusterStateCollector):
self.map(current_state_cluster, node_uuid, vm_uuid)
return current_state_cluster
def generate_scenario_4_with_2_hypervisors(self):
vms = []
current_state_cluster = ModelRoot()
# number of nodes
count_node = 2
# number max of vm per node
node_count_vm = 1
# total number of virtual machine
count_vm = (count_node * node_count_vm)
# define ressouce ( CPU, MEM disk, ... )
mem = Resource(ResourceType.memory)
# 2199.954 Mhz
num_cores = Resource(ResourceType.cpu_cores)
disk = Resource(ResourceType.disk)
current_state_cluster.create_resource(mem)
current_state_cluster.create_resource(num_cores)
current_state_cluster.create_resource(disk)
for i in range(0, count_node):
node_uuid = "Node_" + str(i)
node = Hypervisor()
node.uuid = node_uuid
mem.set_capacity(node, 132)
disk.set_capacity(node, 250)
num_cores.set_capacity(node, 40)
# print("create "+str(node))
current_state_cluster.add_hypervisor(node)
for i in range(0, count_vm):
vm_uuid = "VM_" + str(i)
vm = VM()
vm.uuid = vm_uuid
# print("create "+str(vm))
mem.set_capacity(vm, 2)
disk.set_capacity(vm, 20)
num_cores.set_capacity(vm, 10)
vms.append(vm)
current_state_cluster.add_vm(vm)
current_state_cluster.get_mapping().map(
current_state_cluster.get_hypervisor_from_id("Node_0"),
current_state_cluster.get_vm_from_id("VM_0"))
current_state_cluster.get_mapping().map(
current_state_cluster.get_hypervisor_from_id("Node_1"),
current_state_cluster.get_vm_from_id("VM_1"))
return current_state_cluster
def generate_scenario_5_with_1_hypervisor_no_vm(self):
current_state_cluster = ModelRoot()
# number of nodes
count_node = 1
# define ressouce ( CPU, MEM disk, ... )
mem = Resource(ResourceType.memory)
# 2199.954 Mhz
num_cores = Resource(ResourceType.cpu_cores)
disk = Resource(ResourceType.disk)
current_state_cluster.create_resource(mem)
current_state_cluster.create_resource(num_cores)
current_state_cluster.create_resource(disk)
for i in range(0, count_node):
node_uuid = "Node_" + str(i)
node = Hypervisor()
node.uuid = node_uuid
mem.set_capacity(node, 1)
disk.set_capacity(node, 1)
num_cores.set_capacity(node, 1)
# print("create "+str(node))
current_state_cluster.add_hypervisor(node)
return current_state_cluster

View File

@@ -1,6 +1,8 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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
@@ -13,15 +15,130 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import random
from watcher.decision_engine.api.collector.metrics_resource_collector import \
from watcher.metrics_engine.api.metrics_resource_collector import Measure
from watcher.metrics_engine.api.metrics_resource_collector import \
MetricsResourceCollector
class FakerMetricsCollector(MetricsResourceCollector):
def __init__(self):
pass
self.emptytype = ""
def empty_one_metric(self, emptytype):
self.emptytype = emptytype
def get_measurement(self,
metric,
callback=None,
start_time=None,
end_time=None,
filters=None,
aggregation_function=None,
intervals=None):
results = []
if metric == "compute_cpu_user_percent_gauge":
if self.emptytype == "CPU_COMPUTE":
pass
else:
results.append(Measure(0, 5))
elif metric == "instance_cpu_percent_gauge":
results.append(
self.get_average_usage_vm_cpu(filters[0].split('=')[1]))
elif metric == "instance_memory_resident_used_bytes_gauge":
results.append(
self.get_average_usage_vm_memory(filters[0].split('=')[1]))
elif metric == "instance_disk_used_bytes_gauge":
if self.emptytype == "DISK_COMPUTE":
pass
else:
results.append(
self.get_average_usage_vm_disk(filters[0].split('=')[1]))
elif metric == "compute_memory_used_bytes_gauge":
if self.emptytype == "MEM_COMPUTE":
pass
else:
results.append(self.get_usage_node_cpu(
filters[0].split('=')[1]))
elif metric == "compute_disk_size_used_bytes_gauge":
if self.emptytype == "DISK_COMPUTE":
pass
else:
results.append(self.get_usage_node_disk(
filters[0].split('=')[1]))
else:
results.append(Measure(0, 0))
return results
def get_usage_node_disk(self, uuid):
"""The last VM CPU usage values to average
:param uuid:00
:return:
"""
# query influxdb stream
# compute in stream
# Normalize
mock = {}
# node 0
mock['Node_0'] = Measure(0, 7)
mock['Node_1'] = Measure(0, 100)
# node 1
mock['Node_2'] = Measure(0, 10)
# node 2
mock['Node_3'] = Measure(0, 5)
mock['Node_4'] = Measure(0, 5)
mock['Node_5'] = Measure(0, 10)
# node 3
mock['Node_6'] = Measure(0, 8)
# node 4
mock['VM_7'] = Measure(0, 4)
if uuid not in mock.keys():
# mock[uuid] = random.randint(1, 4)
mock[uuid] = Measure(0, 8)
return mock[str(uuid)]
def get_usage_node_cpu(self, uuid):
"""The last VM CPU usage values to average
:param uuid:00
:return:
"""
# query influxdb stream
# compute in stream
# Normalize
mock = {}
# node 0
mock['Node_0'] = Measure(0, 7)
mock['Node_1'] = Measure(0, 7)
# node 1
mock['Node_2'] = Measure(0, 80)
# node 2
mock['Node_3'] = Measure(0, 5)
mock['Node_4'] = Measure(0, 5)
mock['Node_5'] = Measure(0, 10)
# node 3
mock['Node_6'] = Measure(0, 8)
# node 4
mock['VM_7'] = Measure(0, 4)
if uuid not in mock.keys():
# mock[uuid] = random.randint(1, 4)
mock[uuid] = Measure(0, 8)
return mock[str(uuid)]
def get_average_usage_vm_cpu(self, uuid):
"""The last VM CPU usage values to average
@@ -36,70 +153,70 @@ class FakerMetricsCollector(MetricsResourceCollector):
# Normalize
mock = {}
# node 0
mock['VM_0'] = 7
mock['VM_1'] = 7
mock['VM_0'] = Measure(0, 7)
mock['VM_1'] = Measure(0, 7)
# node 1
mock['VM_2'] = 10
mock['VM_2'] = Measure(0, 10)
# node 2
mock['VM_3'] = 5
mock['VM_4'] = 5
mock['VM_5'] = 10
mock['VM_3'] = Measure(0, 5)
mock['VM_4'] = Measure(0, 5)
mock['VM_5'] = Measure(0, 10)
# node 3
mock['VM_6'] = 8
mock['VM_6'] = Measure(0, 8)
# node 4
mock['VM_7'] = 4
mock['VM_7'] = Measure(0, 4)
if uuid not in mock.keys():
# mock[uuid] = random.randint(1, 4)
mock[uuid] = 8
mock[uuid] = Measure(0, 8)
return mock[str(uuid)]
def get_average_usage_vm_memory(self, uuid):
mock = {}
# node 0
mock['VM_0'] = 2
mock['VM_1'] = 5
mock['VM_0'] = Measure(0, 2)
mock['VM_1'] = Measure(0, 5)
# node 1
mock['VM_2'] = 5
mock['VM_2'] = Measure(0, 5)
# node 2
mock['VM_3'] = 8
mock['VM_4'] = 5
mock['VM_5'] = 16
mock['VM_3'] = Measure(0, 8)
mock['VM_4'] = Measure(0, 5)
mock['VM_5'] = Measure(0, 16)
# node 3
mock['VM_6'] = 8
mock['VM_6'] = Measure(0, 8)
# node 4
mock['VM_7'] = 4
mock['VM_7'] = Measure(0, 4)
if uuid not in mock.keys():
# mock[uuid] = random.randint(1, 4)
mock[uuid] = 10
mock[uuid] = Measure(0, 10)
return mock[str(uuid)]
def get_average_usage_vm_disk(self, uuid):
mock = {}
# node 0
mock['VM_0'] = 2
mock['VM_1'] = 2
mock['VM_0'] = Measure(0, 2)
mock['VM_1'] = Measure(0, 2)
# node 1
mock['VM_2'] = 2
mock['VM_2'] = Measure(0, 2)
# node 2
mock['VM_3'] = 10
mock['VM_4'] = 15
mock['VM_5'] = 20
mock['VM_3'] = Measure(0, 10)
mock['VM_4'] = Measure(0, 15)
mock['VM_5'] = Measure(0, 20)
# node 3
mock['VM_6'] = 8
mock['VM_6'] = Measure(0, 8)
# node 4
mock['VM_7'] = 4
mock['VM_7'] = Measure(0, 4)
if uuid not in mock.keys():
# mock[uuid] = random.randint(1, 4)
mock[uuid] = 4
mock[uuid] = Measure(0, 4)
return mock[str(uuid)]

View File

@@ -39,14 +39,21 @@ class TestTriggerAuditCommand(DbTestCase):
self.context,
audit_template_id=self.audit_template.id)
def test_trigger_audit_wihout_errors(self):
def test_trigger_audit_without_errors(self):
try:
statedb = FakerStateCollector()
ressourcedb = FakerMetricsCollector()
command = TriggerAuditCommand(MagicMock(), statedb, ressourcedb)
command.execute(self.audit.uuid, self.context)
except Exception:
self.fail("The audit should be trigged wihtour error")
self.fail("The audit should be trigged without error")
def test_trigger_audit_with_errors(self):
try:
command = TriggerAuditCommand(MagicMock(), 0, 0)
command.execute(self.audit.uuid, self.context)
except Exception:
self.fail("The audit should be trigged with error")
def test_trigger_audit_state_succes(self):
statedb = FakerStateCollector()

View File

@@ -13,7 +13,6 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
import mock
from mock import MagicMock
from watcher.common import utils
@@ -21,22 +20,54 @@ from watcher.decision_engine.framework.command.trigger_audit_command import \
TriggerAuditCommand
from watcher.decision_engine.framework.messaging.audit_endpoint import \
AuditEndpoint
from watcher.metrics_engine.framework.collector_manager import CollectorManager
from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
class TriggerAuditCommandWithExecutor(TriggerAuditCommand):
def setUp(self):
super(TriggerAuditCommand, self).setUp()
def executor(self):
pass
class TestAuditEndpoint(base.TestCase):
def setUp(self):
super(TestAuditEndpoint, self).setUp()
self.endpoint = AuditEndpoint(MagicMock())
def test_do_trigger_audit(self):
audit_uuid = utils.generate_uuid()
statedb = FakerStateCollector()
ressourcedb = FakerMetricsCollector()
command = TriggerAuditCommand(MagicMock(), statedb, ressourcedb)
endpoint = AuditEndpoint(command)
with mock.patch.object(CollectorManager, 'get_statedb_collector') \
as mock_call2:
mock_call2.return_value = 0
with mock.patch.object(TriggerAuditCommand, 'execute') \
as mock_call:
mock_call.return_value = 0
endpoint.do_trigger_audit(command, audit_uuid)
# mock_call.assert_called_once_with()
mock_call2.assert_called_once_with()
def test_trigger_audit(self):
audit_uuid = utils.generate_uuid()
# todo() add
statedb = FakerStateCollector()
ressourcedb = FakerMetricsCollector()
command = TriggerAuditCommandWithExecutor(MagicMock(),
statedb, ressourcedb)
endpoint = AuditEndpoint(command)
with mock.patch.object(TriggerAuditCommand, 'execute') as mock_call:
expected_uuid = self.endpoint.trigger_audit(
self.context, audit_uuid)
self.assertEqual(audit_uuid, expected_uuid)
mock_call.assert_called_once_with(audit_uuid, self.context)
"""
with mock.patch.object(TriggerAuditCommandWithExecutor, 'executor') \
as mock_call:
mock_call.return_value = 0
endpoint.trigger_audit(command, audit_uuid)

View File

@@ -0,0 +1,32 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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.
#
from watcher.decision_engine.framework.meta_actions.migrate import Migrate
from watcher.decision_engine.framework.model.hypervisor import Hypervisor
from watcher.decision_engine.framework.model.vm import VM
from watcher.tests import base
class TestMigtrate(base.BaseTestCase):
def test_set_get_bandwidth(self):
vm = VM()
hyp_src = Hypervisor()
hyp_dst = Hypervisor()
mig = Migrate(vm, hyp_src, hyp_dst)
mig.set_bandwidth(2)
self.assertEqual(mig.get_bandwidth(), 2)

View File

@@ -0,0 +1,33 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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.
#
from watcher.decision_engine.framework.model.diskInfo import DiskInfo
from watcher.tests import base
class TestDiskInfo(base.BaseTestCase):
def test_all(self):
disk_information = DiskInfo()
disk_information.set_size(1024)
self.assertEqual(disk_information.get_size(), 1024)
disk_information.set_scheduler = "scheduler_qcq"
disk_information.set_device_name("nom_qcq")
self.assertEqual(disk_information.get_device_name(), "nom_qcq")

View File

@@ -0,0 +1,106 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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.
#
import uuid
from watcher.decision_engine.framework.model.hypervisor import Hypervisor
from watcher.decision_engine.framework.model.vm_state import VMState
from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
class TestMapping(base.BaseTestCase):
def test_get_node_from_vm(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
vms = model.get_all_vms()
keys = vms.keys()
vm = vms[keys[0]]
if vm.uuid != 'VM_0':
vm = vms[keys[1]]
node = model.mapping.get_node_from_vm(vm)
self.assertEqual(node.uuid, 'Node_0')
def test_get_node_from_vm_id(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
hyps = model.mapping.get_node_vms_from_id("BLABLABLA")
self.assertEqual(hyps.__len__(), 0)
def test_get_all_vms(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
vms = model.get_all_vms()
self.assertEqual(vms.__len__(), 2)
self.assertEqual(vms['VM_0'].state, VMState.ACTIVE.value)
self.assertEqual(vms['VM_0'].uuid, 'VM_0')
self.assertEqual(vms['VM_1'].state, VMState.ACTIVE.value)
self.assertEqual(vms['VM_1'].uuid, 'VM_1')
def test_get_mapping(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
mapping_vm = model.mapping.get_mapping_vm()
self.assertEqual(mapping_vm.__len__(), 2)
self.assertEqual(mapping_vm['VM_0'], 'Node_0')
self.assertEqual(mapping_vm['VM_1'], 'Node_1')
def test_migrate_vm(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
vms = model.get_all_vms()
keys = vms.keys()
vm0 = vms[keys[0]]
hyp0 = model.mapping.get_node_from_vm_id(vm0.uuid)
vm1 = vms[keys[1]]
hyp1 = model.mapping.get_node_from_vm_id(vm1.uuid)
self.assertEqual(model.mapping.migrate_vm(vm1, hyp1, hyp1), False)
self.assertEqual(model.mapping.migrate_vm(vm1, hyp0, hyp0), False)
self.assertEqual(model.mapping.migrate_vm(vm1, hyp1, hyp0), True)
self.assertEqual(model.mapping.migrate_vm(vm1, hyp0, hyp1), True)
def test_unmap_from_id_log_warning(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
vms = model.get_all_vms()
keys = vms.keys()
vm0 = vms[keys[0]]
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.mapping.unmap_from_id(hypervisor.uuid, vm0.uuid)
# self.assertEqual(len(model.mapping.get_node_vms_from_id(
# hypervisor.uuid)), 1)
def test_unmap_from_id(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
vms = model.get_all_vms()
keys = vms.keys()
vm0 = vms[keys[0]]
hyp0 = model.mapping.get_node_from_vm_id(vm0.uuid)
model.mapping.unmap_from_id(hyp0.uuid, vm0.uuid)
self.assertEqual(len(model.mapping.get_node_vms_from_id(
hyp0.uuid)), 0)

View File

@@ -0,0 +1,139 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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.
#
import uuid
from watcher.common import exception
from watcher.common.exception import IllegalArgumentException
from watcher.decision_engine.framework.model.hypervisor import Hypervisor
from watcher.decision_engine.framework.model.hypervisor_state import \
HypervisorState
from watcher.decision_engine.framework.model.model_root import ModelRoot
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests import base
class TestModel(base.BaseTestCase):
def test_model(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_1()
self.assertEqual(len(model._hypervisors), 5)
self.assertEqual(len(model._vms), 35)
self.assertEqual(len(model.get_mapping().get_mapping()), 5)
def test_add_hypervisor(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
self.assertEqual(model.get_hypervisor_from_id(id), hypervisor)
def test_delete_hypervisor(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
self.assertEqual(model.get_hypervisor_from_id(id), hypervisor)
model.remove_hypervisor(hypervisor)
self.assertRaises(exception.HypervisorNotFound,
model.get_hypervisor_from_id, id)
def test_get_all_hypervisors(self):
model = ModelRoot()
for i in range(10):
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
all_hypervisors = model.get_all_hypervisors()
for id in all_hypervisors:
hyp = model.get_hypervisor_from_id(id)
model.assert_hypervisor(hyp)
def test_set_get_state_hypervisors(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
self.assertIsInstance(hypervisor.state, HypervisorState)
hyp = model.get_hypervisor_from_id(id)
hyp.state = HypervisorState.OFFLINE
self.assertIsInstance(hyp.state, HypervisorState)
# /watcher/decision_engine/framework/model/hypervisor.py
# set_state accept any char chain.
# verification (IsInstance) should be used in the function
# hyp.set_state('blablabla')
# self.assertEqual(hyp.get_state(), 'blablabla')
# self.assertIsInstance(hyp.get_state(), HypervisorState)
# def test_get_all_vms(self):
# model = ModelRoot()
# vms = model.get_all_vms()
# self.assert(len(model._vms))
def test_hypervisor_from_id_raise(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
id2 = str(uuid.uuid4())
self.assertRaises(exception.HypervisorNotFound,
model.get_hypervisor_from_id, id2)
def test_remove_hypervisor_raise(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
id2 = str(uuid.uuid4())
hypervisor2 = Hypervisor()
hypervisor2.uuid = id2
self.assertRaises(exception.HypervisorNotFound,
model.remove_hypervisor, hypervisor2)
def test_assert_hypervisor_raise(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
self.assertRaises(IllegalArgumentException,
model.assert_hypervisor, "objet_qcq")
def test_vm_from_id_raise(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_1()
self.assertRaises(exception.VMNotFound,
model.get_vm_from_id, "valeur_qcq")
def test_assert_vm_raise(self):
model = ModelRoot()
self.assertRaises(IllegalArgumentException,
model.assert_vm, "valeur_qcq")

View File

@@ -0,0 +1,32 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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.
#
from watcher.decision_engine.framework.model.named_element import NamedElement
from watcher.tests import base
class TestNamedElement(base.BaseTestCase):
def test_namedelement(self):
id = NamedElement()
id.uuid = "BLABLABLA"
self.assertEqual(id.uuid, "BLABLABLA")
def test_set_get_human_id(self):
id = NamedElement()
id.human_id = "BLABLABLA"
self.assertEqual(id.human_id, "BLABLABLA")

View File

@@ -0,0 +1,30 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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.
#
from watcher.decision_engine.framework.model.vm import VM
from watcher.decision_engine.framework.model.vm_state import VMState
from watcher.tests import base
class TestVm(base.BaseTestCase):
def test_namedelement(self):
vm = VM()
vm.state = VMState.ACTIVE
self.assertEqual(vm.state, VMState.ACTIVE)
vm.human_id = "human_05"
self.assertEqual(vm.human_id, "human_05")

View File

@@ -34,3 +34,7 @@ class TestStrategySelector(base.BaseTestCase):
selected_strategy.get_name(),
exptected_strategy,
'The default strategy should be basic')
def test_load_driver(self):
algo = self.strategy_loader.load_driver("basic")
self.assertEqual(algo._names[0], "basic")

View File

@@ -0,0 +1,32 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.framework.strategy.StrategyManagerImpl import \
StrategyContextImpl
from watcher.tests import base
class FakeStrategy(object):
def __init__(self):
self.name = "BALANCE_LOAD"
class TestStrategyContextImpl(base.BaseTestCase):
def test_add_remove_strategy(self):
strategy = FakeStrategy()
strategy_context = StrategyContextImpl()
strategy_context.add_strategy(strategy)
strategy_context.remove_strategy(strategy)

View File

@@ -15,6 +15,7 @@
# limitations under the License.
import mock
from watcher.common.exception import MetaActionNotFound
from watcher.common import utils
from watcher.db import api as db_api
from watcher.decision_engine.framework.default_planner import DefaultPlanner
@@ -39,6 +40,17 @@ class SolutionFaker(object):
return sercon.execute(current_state_cluster.generate_scenario_1())
class SolutionFakerSingleHyp(object):
@staticmethod
def build():
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation("basic", "Basic offline consolidation")
sercon.set_metrics_resource_collector(metrics)
return sercon.execute(
current_state_cluster.generate_scenario_4_with_2_hypervisors())
class TestDefaultPlanner(base.DbTestCase):
default_planner = DefaultPlanner()
@@ -71,5 +83,25 @@ class TestDefaultPlanner(base.DbTestCase):
fake_solution = SolutionFaker.build()
action_plan = self.default_planner.schedule(self.context,
audit.id, fake_solution)
self.assertIsNotNone(action_plan.uuid)
def test_schedule_raise(self):
audit = db_utils.create_test_audit(uuid=utils.generate_uuid())
fake_solution = SolutionFaker.build()
fake_solution._meta_actions[0] = "valeur_qcq"
self.assertRaises(MetaActionNotFound, self.default_planner.schedule,
self.context, audit.id, fake_solution)
def test_schedule_scheduled_empty(self):
audit = db_utils.create_test_audit(uuid=utils.generate_uuid())
fake_solution = SolutionFakerSingleHyp.build()
action_plan = self.default_planner.schedule(self.context,
audit.id, fake_solution)
self.assertIsNotNone(action_plan.uuid)
def test_scheduler_warning_empty_action_plan(self):
audit = db_utils.create_test_audit(uuid=utils.generate_uuid())
fake_solution = SolutionFaker.build()
action_plan = self.default_planner.schedule(self.context,
audit.id, fake_solution)
self.assertIsNotNone(action_plan.uuid)

View File

@@ -0,0 +1,24 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.framework.default_solution import DefaultSolution
from watcher.tests import base
class TestDefaultSolution(base.BaseTestCase):
def test_default_solution(self):
solution = DefaultSolution()
solution.add_change_request("BLA")
self.assertEqual(solution.meta_actions[0], "BLA")

View File

@@ -0,0 +1 @@
__author__ = 'Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>'

View File

@@ -0,0 +1,314 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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.
#
import mock
from watcher.common import exception
from watcher.decision_engine.framework.meta_actions.hypervisor_state import \
ChangeHypervisorState
from watcher.decision_engine.framework.meta_actions.power_state import \
ChangePowerState
from watcher.decision_engine.framework.meta_actions.migrate import Migrate
from watcher.decision_engine.framework.model.model_root import ModelRoot
from watcher.decision_engine.strategies.basic_consolidation import \
BasicConsolidation
from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
# from watcher.tests.decision_engine.faker_metrics_collector import \
# FakerMetricsCollectorEmptyType
class TestBasicConsolidation(base.BaseTestCase):
# fake metrics
fake_metrics = FakerMetricsCollector()
# fake cluster
fake_cluster = FakerStateCollector()
def test_cluster_size(self):
size_cluster = len(
self.fake_cluster.generate_scenario_1().get_all_hypervisors())
size_cluster_assert = 5
self.assertEqual(size_cluster, size_cluster_assert)
def test_basic_consolidation_score_hypervisor(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
node_1_score = 0.01666666666666668
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_1"),
cluster), node_1_score)
node_2_score = 0.01666666666666668
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_2"),
cluster), node_2_score)
node_0_score = 0.01666666666666668
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_0"),
cluster), node_0_score)
def test_basic_consolidation_score_vm(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
vm_0 = cluster.get_vm_from_id("VM_0")
vm_0_score = 0.0
self.assertEqual(sercon.calculate_score_vm(vm_0, cluster), vm_0_score)
vm_1 = cluster.get_vm_from_id("VM_1")
vm_1_score = 0.0
self.assertEqual(sercon.calculate_score_vm(vm_1, cluster),
vm_1_score)
vm_2 = cluster.get_vm_from_id("VM_2")
vm_2_score = 0.0
self.assertEqual(sercon.calculate_score_vm(vm_2, cluster), vm_2_score)
vm_6 = cluster.get_vm_from_id("VM_6")
vm_6_score = 0.0
self.assertEqual(sercon.calculate_score_vm(vm_6, cluster), vm_6_score)
vm_7 = cluster.get_vm_from_id("VM_7")
vm_7_score = 0.0
self.assertEqual(sercon.calculate_score_vm(vm_7, cluster), vm_7_score)
def test_basic_consolidation_weight(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
vm_0 = cluster.get_vm_from_id("VM_0")
cores = 16
# 80 Go
disk = 80
# mem 8 Go
mem = 8
vm_0_weight_assert = 3.1999999999999997
self.assertEqual(sercon.calculate_weight(cluster, vm_0, cores, disk,
mem),
vm_0_weight_assert)
def test_calculate_migration_efficiency(self):
sercon = BasicConsolidation()
sercon.calculate_migration_efficiency()
def test_exception_model(self):
sercon = BasicConsolidation()
self.assertRaises(exception.ClusteStateNotDefined, sercon.execute,
None)
def test_exception_cluster_empty(self):
sercon = BasicConsolidation()
model = ModelRoot()
self.assertRaises(exception.ClusterEmpty, sercon.execute,
model)
def test_calculate_score_vm_raise_metric_collector(self):
sercon = BasicConsolidation()
self.assertRaises(exception.MetricCollectorNotDefined,
sercon.calculate_score_vm, "VM_1", None)
def test_calculate_score_vm_raise_cluster_state_not_found(self):
metrics = FakerMetricsCollector()
metrics.empty_one_metric("CPU_COMPUTE")
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
self.assertRaises(exception.ClusteStateNotDefined,
sercon.calculate_score_vm, "VM_1", None)
def test_print_utilization_raise_cluster_state_not_found(self):
sercon = BasicConsolidation()
self.assertRaises(exception.ClusteStateNotDefined,
sercon.print_utilization, None)
def check_migration(self, array, indice, vm, src, dest):
"""Helper to check migration
:param array:
:param indice:
:param vm:
:param src:
:param dest:
:return:
"""
self.assertEqual(array[indice].get_vm().uuid, vm)
self.assertEqual(array[indice].get_source_hypervisor().uuid, src)
self.assertEqual(array[indice].get_dest_hypervisor().uuid, dest)
self.assertEqual(array[indice].get_bandwidth(), 0)
array[indice].set_bandwidth(5)
self.assertEqual(array[indice].get_bandwidth(), 5)
def test_check_migration(self):
sercon = BasicConsolidation()
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
all_vms = model.get_all_vms()
all_hyps = model.get_all_hypervisors()
vm0 = all_vms[all_vms.keys()[0]]
hyp0 = all_hyps[all_hyps.keys()[0]]
sercon.check_migration(model, hyp0, hyp0, vm0)
def test_threshold(self):
sercon = BasicConsolidation()
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
all_hyps = model.get_all_hypervisors()
hyp0 = all_hyps[all_hyps.keys()[0]]
sercon.check_threshold(model, hyp0, 1000, 1000, 1000)
threshold_cores = sercon.get_threshold_cores()
sercon.set_threshold_cores(threshold_cores + 1)
self.assertEqual(sercon.get_threshold_cores(), threshold_cores + 1)
def test_number_of(self):
sercon = BasicConsolidation()
sercon.get_number_of_released_nodes()
sercon.get_number_of_migrations()
def test_calculate_score_node_raise_1(self):
sercon = BasicConsolidation()
metrics = FakerStateCollector()
model = metrics.generate_scenario_4_with_2_hypervisors()
all_hyps = model.get_all_hypervisors()
hyp0 = all_hyps[all_hyps.keys()[0]]
self.assertRaises(exception.MetricCollectorNotDefined,
sercon.calculate_score_node, hyp0, model)
def test_calculate_score_node_raise_cpu_compute(self):
metrics = FakerMetricsCollector()
metrics.empty_one_metric("CPU_COMPUTE")
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
current_state_cluster = FakerStateCollector()
model = current_state_cluster.generate_scenario_4_with_2_hypervisors()
all_hyps = model.get_all_hypervisors()
hyp0 = all_hyps[all_hyps.keys()[0]]
self.assertRaises(exception.NoDataFound,
sercon.calculate_score_node, hyp0, model)
"""
def test_calculate_score_node_raise_memory_compute(self):
metrics = FakerMetricsCollector()
metrics.empty_one_metric("MEM_COMPUTE")
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
current_state_cluster = FakerStateCollector()
model = current_state_cluster.generate_scenario_4_with_2_hypervisors()
all_hyps = model.get_all_hypervisors()
hyp0 = all_hyps[all_hyps.keys()[0]]
self.assertRaises(exception.NoDataFound,
sercon.calculate_score_node, hyp0, model)
def test_calculate_score_node_raise_disk_compute(self):
metrics = FakerMetricsCollector()
metrics.empty_one_metric("DISK_COMPUTE")
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
current_state_cluster = FakerStateCollector()
model = current_state_cluster.generate_scenario_4_with_2_hypervisors()
all_hyps = model.get_all_hypervisors()
hyp0 = all_hyps[all_hyps.keys()[0]]
self.assertRaises(exception.NoDataFound,
sercon.calculate_score_node, hyp0, model)
"""
def test_basic_consolidation_migration(self):
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(FakerMetricsCollector())
solution = None
solution = sercon.execute(FakerStateCollector().generate_scenario_1())
count_migration = 0
change_hypervisor_state = 0
change_power_state = 0
migrate = []
for action in solution.meta_actions:
if isinstance(action, Migrate):
count_migration += 1
migrate.append(action)
if isinstance(action, ChangeHypervisorState):
change_hypervisor_state += 1
if isinstance(action, ChangePowerState):
change_power_state += 1
# self.assertEqual(change_hypervisor_state, 1)
# self.assertEqual(count_migration, 2)
def test_execute_cluster_empty(self):
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation("sercon", "Basic offline consolidation")
sercon.set_metrics_resource_collector(metrics)
model = current_state_cluster.generate_random(0, 0)
self.assertRaises(exception.ClusterEmpty, sercon.execute, model)
def test_basic_consolidation_random(self):
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation("sercon", "Basic offline consolidation")
sercon.set_metrics_resource_collector(metrics)
solution = sercon.execute(
current_state_cluster.generate_random(25, 2))
solution.__str__()
count_migration = 0
change_hypervisor_state = 0
change_power_state = 0
migrate = []
for action in solution.meta_actions:
if isinstance(action, Migrate):
count_migration += 1
migrate.append(action)
if isinstance(action, ChangeHypervisorState):
change_hypervisor_state += 1
if isinstance(action, ChangePowerState):
change_power_state += 1
# calculate_weight
def test_execute_no_workload(self):
metrics = FakerMetricsCollector()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
current_state_cluster = FakerStateCollector()
model = current_state_cluster.\
generate_scenario_5_with_1_hypervisor_no_vm()
with mock.patch.object(BasicConsolidation, 'calculate_weight') \
as mock_score_call:
mock_score_call.return_value = 0
solution = sercon.execute(model)
self.assertEqual(solution.efficiency, 100)

View File

@@ -0,0 +1,27 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.strategies.dummy_strategy import DummyStrategy
from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
class TestDummyStrategy(base.TestCase):
def test_dummy_strategy(self):
tactique = DummyStrategy("basic", "Basic offline consolidation")
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
tactique.execute(model)

View File

@@ -1,184 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
#
from watcher.common import exception
from watcher.decision_engine.framework.meta_actions.hypervisor_state import \
ChangeHypervisorState
from watcher.decision_engine.framework.meta_actions.power_state import \
ChangePowerState
from watcher.decision_engine.framework.meta_actions.migrate import Migrate
from watcher.decision_engine.framework.model.model_root import ModelRoot
from watcher.decision_engine.strategies.basic_consolidation import \
BasicConsolidation
from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
class TestBasicConsolidation(base.BaseTestCase):
# fake metrics
fake_metrics = FakerMetricsCollector()
# fake cluster
fake_cluster = FakerStateCollector()
def test_cluster_size(self):
size_cluster = len(
self.fake_cluster.generate_scenario_1().get_all_hypervisors())
size_cluster_assert = 5
self.assertEqual(size_cluster, size_cluster_assert)
def test_basic_consolidation_score_hypervisor(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
node_1_score = 0.09862626262626262
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_1"),
cluster), node_1_score)
node_2_score = 0.29989898989898994
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_2"),
cluster), node_2_score)
node_0_score = 0.13967676767676765
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_0"),
cluster), node_0_score)
def test_basic_consolidation_score_vm(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
vm_0 = cluster.get_vm_from_id("VM_0")
vm_0_score = 0.6
self.assertEqual(sercon.calculate_score_vm(vm_0, cluster), vm_0_score)
vm_1 = cluster.get_vm_from_id("VM_1")
vm_1_score = 1.0999999999999999
self.assertEqual(sercon.calculate_score_vm(vm_1, cluster),
vm_1_score)
vm_2 = cluster.get_vm_from_id("VM_2")
vm_2_score = 1.2
self.assertEqual(sercon.calculate_score_vm(vm_2, cluster), vm_2_score)
def test_basic_consolidation_weight(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
vm_0 = cluster.get_vm_from_id("VM_0")
cores = 16
# 80 Go
disk = 80
# mem 8 Go
mem = 8
vm_0_weight_assert = 3.1999999999999997
self.assertEqual(sercon.calculate_weight(cluster, vm_0, cores, disk,
mem),
vm_0_weight_assert)
def test_basic_consolidation_efficiency(self):
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
efficient_assert = 100
solution = sercon.execute(self.fake_cluster.generate_scenario_1())
self.assertEqual(solution.get_efficiency(), efficient_assert)
def test_exception_model(self):
sercon = BasicConsolidation()
self.assertRaises(exception.ClusteStateNotDefined, sercon.execute,
None)
def test_exception_cluster_empty(self):
sercon = BasicConsolidation()
model = ModelRoot()
self.assertRaises(exception.ClusterEmpty, sercon.execute,
model)
def test_exception_metric_collector(self):
sercon = BasicConsolidation()
self.assertRaises(exception.MetricCollectorNotDefined,
sercon.calculate_score_vm, "VM_1", None)
def check_migration(self, array, indice, vm, src, dest):
"""Helper to check migration
:param array:
:param indice:
:param vm:
:param src:
:param dest:
:return:
"""
self.assertEqual(array[indice].get_vm().get_uuid(), vm)
self.assertEqual(array[indice].get_source_hypervisor().get_uuid(), src)
self.assertEqual(array[indice].get_dest_hypervisor().get_uuid(), dest)
def test_basic_consolidation_migration(self):
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
solution = sercon.execute(self.fake_cluster.generate_scenario_1())
count_migration = 0
change_hypervisor_state = 0
change_power_state = 0
migrate = []
for action in solution.meta_actions:
if isinstance(action, Migrate):
count_migration += 1
migrate.append(action)
if isinstance(action, ChangeHypervisorState):
change_hypervisor_state += 1
if isinstance(action, ChangePowerState):
change_power_state += 1
self.assertEqual(change_hypervisor_state, 3)
self.assertEqual(count_migration, 3)
# check migration
self.check_migration(migrate, 0, "VM_7", "Node_4", "Node_2")
self.check_migration(migrate, 1, "VM_6", "Node_3", "Node_0")
self.check_migration(migrate, 2, "VM_2", "Node_1", "Node_0")
def test_basic_consolidation_random(self):
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation("sercon", "Basic offline consolidation")
sercon.set_metrics_resource_collector(metrics)
solution = sercon.execute(
current_state_cluster.generate_random(25, 2))
count_migration = 0
change_hypervisor_state = 0
change_power_state = 0
migrate = []
for action in solution.meta_actions:
if isinstance(action, Migrate):
count_migration += 1
migrate.append(action)
if isinstance(action, ChangeHypervisorState):
change_hypervisor_state += 1
if isinstance(action, ChangePowerState):
change_power_state += 1

View File

@@ -1,11 +1,13 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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
# 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,
@@ -13,6 +15,7 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from watcher.tests import base

View File

@@ -1,54 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
import uuid
from watcher.common import exception
from watcher.decision_engine.framework.model.hypervisor import Hypervisor
from watcher.decision_engine.framework.model.model_root import ModelRoot
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests import base
class TestModel(base.BaseTestCase):
def test_model(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_1()
self.assertEqual(len(model._hypervisors), 5)
self.assertEqual(len(model._vms), 35)
self.assertEqual(len(model.get_mapping().get_mapping()), 5)
def test_add_hypervisor(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.set_uuid(id)
model.add_hypervisor(hypervisor)
self.assertEqual(model.get_hypervisor_from_id(id), hypervisor)
def test_delete_hypervisor(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.set_uuid(id)
model.add_hypervisor(hypervisor)
self.assertEqual(model.get_hypervisor_from_id(id), hypervisor)
model.remove_hypervisor(hypervisor)
self.assertRaises(exception.HypervisorNotFound,
model.get_hypervisor_from_id, id)

View File

@@ -1,11 +1,13 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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
# 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,
@@ -13,6 +15,7 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from watcher.tests import base