consolidation of watcher
Change-Id: I9c82ef4d8a81af98afdfc34f5ad496bcade4af6a
This commit is contained in:
25
watcher/tests/decision_engine/api/messaging/test_decision_engine_command.py
Executable file
25
watcher/tests/decision_engine/api/messaging/test_decision_engine_command.py
Executable 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)
|
||||
@@ -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)
|
||||
0
watcher/tests/decision_engine/api/planner/__init__.py
Executable file
0
watcher/tests/decision_engine/api/planner/__init__.py
Executable file
24
watcher/tests/decision_engine/api/planner/test_planner.py
Executable file
24
watcher/tests/decision_engine/api/planner/test_planner.py
Executable 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)
|
||||
26
watcher/tests/decision_engine/api/solution/test_solution.py
Normal file
26
watcher/tests/decision_engine/api/solution/test_solution.py
Normal 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)
|
||||
'''
|
||||
30
watcher/tests/decision_engine/api/solution/test_solution_comparator.py
Executable file
30
watcher/tests/decision_engine/api/solution/test_solution_comparator.py
Executable 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)
|
||||
25
watcher/tests/decision_engine/api/solution/test_solution_evaluator.py
Executable file
25
watcher/tests/decision_engine/api/solution/test_solution_evaluator.py
Executable 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)
|
||||
@@ -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)
|
||||
24
watcher/tests/decision_engine/api/strategy/test_selector.py
Executable file
24
watcher/tests/decision_engine/api/strategy/test_selector.py
Executable 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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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)]
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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")
|
||||
106
watcher/tests/decision_engine/framework/model/test_mapping.py
Normal file
106
watcher/tests/decision_engine/framework/model/test_mapping.py
Normal 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)
|
||||
139
watcher/tests/decision_engine/framework/model/test_model.py
Normal file
139
watcher/tests/decision_engine/framework/model/test_model.py
Normal 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")
|
||||
@@ -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")
|
||||
30
watcher/tests/decision_engine/framework/model/test_vm.py
Normal file
30
watcher/tests/decision_engine/framework/model/test_vm.py
Normal 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")
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
1
watcher/tests/decision_engine/strategies/__init__.py
Normal file
1
watcher/tests/decision_engine/strategies/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
__author__ = 'Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>'
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user