Add Voluptuous to validate the action parameters
We want a simplest way to validate the input parameters of an Action through a schema. APIImpact DocImpact Partially implements: blueprint watcher-add-actions-via-conf Change-Id: I139775f467fe7778c7354b0cfacf796fc27ffcb2
This commit is contained in:
committed by
Vincent Françoise
parent
33ee575936
commit
e3198d25a5
@@ -0,0 +1,54 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 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 voluptuous
|
||||
|
||||
from watcher.applier.actions import base as baction
|
||||
from watcher.applier.actions import change_nova_service_state
|
||||
from watcher.decision_engine.model import hypervisor_state as hstate
|
||||
from watcher.tests import base
|
||||
|
||||
|
||||
class TestChangeNovaServiceState(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestChangeNovaServiceState, self).setUp()
|
||||
self.a = change_nova_service_state.ChangeNovaServiceState()
|
||||
|
||||
def test_parameters_down(self):
|
||||
self.a.input_parameters = {
|
||||
baction.BaseAction.RESOURCE_ID: "compute-1",
|
||||
self.a.STATE: hstate.HypervisorState.OFFLINE.value}
|
||||
self.assertEqual(True, self.a.validate_parameters())
|
||||
|
||||
def test_parameters_up(self):
|
||||
self.a.input_parameters = {
|
||||
baction.BaseAction.RESOURCE_ID: "compute-1",
|
||||
self.a.STATE: hstate.HypervisorState.ONLINE.value}
|
||||
self.assertEqual(True, self.a.validate_parameters())
|
||||
|
||||
def test_parameters_exception_wrong_state(self):
|
||||
self.a.input_parameters = {
|
||||
baction.BaseAction.RESOURCE_ID: "compute-1",
|
||||
self.a.STATE: 'error'}
|
||||
self.assertRaises(voluptuous.Invalid, self.a.validate_parameters)
|
||||
|
||||
def test_parameters_resource_id_empty(self):
|
||||
self.a.input_parameters = {
|
||||
self.a.STATE: None}
|
||||
self.assertRaises(voluptuous.Invalid, self.a.validate_parameters)
|
||||
|
||||
def test_parameters_applies_add_extra(self):
|
||||
self.a.input_parameters = {"extra": "failed"}
|
||||
self.assertRaises(voluptuous.Invalid, self.a.validate_parameters)
|
||||
78
watcher/tests/applier/actions/test_migration.py
Normal file
78
watcher/tests/applier/actions/test_migration.py
Normal file
@@ -0,0 +1,78 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 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 voluptuous
|
||||
|
||||
from watcher.applier.actions import base as baction
|
||||
from watcher.applier.actions import migration
|
||||
from watcher.tests import base
|
||||
|
||||
|
||||
class TestMigration(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestMigration, self).setUp()
|
||||
self.mig = migration.Migrate()
|
||||
|
||||
def test_parameters(self):
|
||||
params = {baction.BaseAction.RESOURCE_ID:
|
||||
"45a37aeb-95ab-4ddb-a305-7d9f62c2f5ba",
|
||||
self.mig.MIGRATION_TYPE: 'live',
|
||||
self.mig.DST_HYPERVISOR: 'compute-2',
|
||||
self.mig.SRC_HYPERVISOR: 'compute3'}
|
||||
self.mig.input_parameters = params
|
||||
self.assertEqual(True, self.mig.validate_parameters())
|
||||
|
||||
def test_parameters_exception_resource_id(self):
|
||||
parameters = {baction.BaseAction.RESOURCE_ID: "EFEF",
|
||||
'migration_type': 'live',
|
||||
'src_hypervisor': 'compute-2',
|
||||
'dst_hypervisor': 'compute3'}
|
||||
self.mig.input_parameters = parameters
|
||||
self.assertRaises(voluptuous.Invalid, self.mig.validate_parameters)
|
||||
|
||||
def test_parameters_exception_migration_type(self):
|
||||
parameters = {baction.BaseAction.RESOURCE_ID:
|
||||
"45a37aeb-95ab-4ddb-a305-7d9f62c2f5ba",
|
||||
'migration_type': 'cold',
|
||||
'src_hypervisor': 'compute-2',
|
||||
'dst_hypervisor': 'compute3'}
|
||||
self.mig.input_parameters = parameters
|
||||
self.assertRaises(voluptuous.Invalid, self.mig.validate_parameters)
|
||||
|
||||
def test_parameters_exception_src_hypervisor(self):
|
||||
parameters = {baction.BaseAction.RESOURCE_ID:
|
||||
"45a37aeb-95ab-4ddb-a305-7d9f62c2f5ba",
|
||||
'migration_type': 'cold',
|
||||
'src_hypervisor': None,
|
||||
'dst_hypervisor': 'compute3'}
|
||||
self.mig.input_parameters = parameters
|
||||
self.assertRaises(voluptuous.Invalid, self.mig.validate_parameters)
|
||||
|
||||
def test_parameters_exception_dst_hypervisor(self):
|
||||
parameters = {baction.BaseAction.RESOURCE_ID:
|
||||
"45a37aeb-95ab-4ddb-a305-7d9f62c2f5ba",
|
||||
'migration_type': 'cold',
|
||||
'src_hypervisor': 'compute-1',
|
||||
'dst_hypervisor': None}
|
||||
self.mig.input_parameters = parameters
|
||||
self.assertRaises(voluptuous.Invalid, self.mig.validate_parameters)
|
||||
|
||||
def test_parameters_exception_empty_fields(self):
|
||||
parameters = {baction.BaseAction.RESOURCE_ID: None,
|
||||
'migration_type': None,
|
||||
'src_hypervisor': None,
|
||||
'dst_hypervisor': None}
|
||||
self.mig.input_parameters = parameters
|
||||
self.assertRaises(voluptuous.Invalid, self.mig.validate_parameters)
|
||||
42
watcher/tests/applier/actions/test_sleep.py
Normal file
42
watcher/tests/applier/actions/test_sleep.py
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 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 voluptuous
|
||||
|
||||
from watcher.applier.actions import sleep
|
||||
from watcher.tests import base
|
||||
|
||||
|
||||
class TestSleep(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestSleep, self).setUp()
|
||||
self.s = sleep.Sleep()
|
||||
|
||||
def test_parameters_duration(self):
|
||||
self.s.input_parameters = {self.s.DURATION: 1.0}
|
||||
self.assertEqual(True, self.s.validate_parameters())
|
||||
|
||||
def test_parameters_duration_empty(self):
|
||||
self.s.input_parameters = {self.s.DURATION: None}
|
||||
self.assertRaises(voluptuous.Invalid, self.s.validate_parameters)
|
||||
|
||||
def test_parameters_wrong_parameter(self):
|
||||
self.s.input_parameters = {self.s.DURATION: "ef"}
|
||||
self.assertRaises(voluptuous.Invalid, self.s.validate_parameters)
|
||||
|
||||
def test_parameters_add_field(self):
|
||||
self.s.input_parameters = {self.s.DURATION: 1.0, "not_required": "nop"}
|
||||
self.assertRaises(voluptuous.Invalid, self.s.validate_parameters)
|
||||
@@ -32,6 +32,12 @@ from watcher.tests.db import base
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class FakeAction(abase.BaseAction):
|
||||
def schema(self):
|
||||
pass
|
||||
|
||||
def postcondition(self):
|
||||
pass
|
||||
|
||||
def precondition(self):
|
||||
pass
|
||||
|
||||
@@ -62,12 +68,11 @@ class TestDefaultWorkFlowEngine(base.DbTestCase):
|
||||
result = self.engine.execute(actions)
|
||||
self.assertEqual(result, True)
|
||||
|
||||
def create_action(self, action_type, applies_to, parameters, next):
|
||||
def create_action(self, action_type, parameters, next):
|
||||
action = {
|
||||
'uuid': utils.generate_uuid(),
|
||||
'action_plan_id': 0,
|
||||
'action_type': action_type,
|
||||
'applies_to': applies_to,
|
||||
'input_parameters': parameters,
|
||||
'state': objects.action.State.PENDING,
|
||||
'alarm': None,
|
||||
@@ -92,15 +97,15 @@ class TestDefaultWorkFlowEngine(base.DbTestCase):
|
||||
self.assertEqual(result, True)
|
||||
|
||||
def test_execute_with_one_action(self):
|
||||
actions = [self.create_action("nop", "", {'message': 'test'}, None)]
|
||||
actions = [self.create_action("nop", {'message': 'test'}, None)]
|
||||
result = self.engine.execute(actions)
|
||||
self.assertEqual(result, True)
|
||||
self.check_actions_state(actions, objects.action.State.SUCCEEDED)
|
||||
|
||||
def test_execute_with_two_actions(self):
|
||||
actions = []
|
||||
next = self.create_action("sleep", "", {'duration': '0'}, None)
|
||||
first = self.create_action("nop", "", {'message': 'test'}, next.id)
|
||||
next = self.create_action("sleep", {'duration': 0.0}, None)
|
||||
first = self.create_action("nop", {'message': 'test'}, next.id)
|
||||
|
||||
actions.append(first)
|
||||
actions.append(next)
|
||||
@@ -111,9 +116,9 @@ class TestDefaultWorkFlowEngine(base.DbTestCase):
|
||||
|
||||
def test_execute_with_three_actions(self):
|
||||
actions = []
|
||||
next2 = self.create_action("nop", "vm1", {'message': 'next'}, None)
|
||||
next = self.create_action("sleep", "vm1", {'duration': '0'}, next2.id)
|
||||
first = self.create_action("nop", "vm1", {'message': 'hello'}, next.id)
|
||||
next2 = self.create_action("nop", {'message': 'next'}, None)
|
||||
next = self.create_action("sleep", {'duration': 0.0}, next2.id)
|
||||
first = self.create_action("nop", {'message': 'hello'}, next.id)
|
||||
self.check_action_state(first, objects.action.State.PENDING)
|
||||
self.check_action_state(next, objects.action.State.PENDING)
|
||||
self.check_action_state(next2, objects.action.State.PENDING)
|
||||
@@ -128,12 +133,9 @@ class TestDefaultWorkFlowEngine(base.DbTestCase):
|
||||
|
||||
def test_execute_with_exception(self):
|
||||
actions = []
|
||||
next2 = self.create_action("no_exist",
|
||||
"vm1", {'message': 'next'}, None)
|
||||
next = self.create_action("sleep", "vm1",
|
||||
{'duration': '0'}, next2.id)
|
||||
first = self.create_action("nop", "vm1",
|
||||
{'message': 'hello'}, next.id)
|
||||
next2 = self.create_action("no_exist", {'message': 'next'}, None)
|
||||
next = self.create_action("sleep", {'duration': 0.0}, next2.id)
|
||||
first = self.create_action("nop", {'message': 'hello'}, next.id)
|
||||
|
||||
self.check_action_state(first, objects.action.State.PENDING)
|
||||
self.check_action_state(next, objects.action.State.PENDING)
|
||||
@@ -158,7 +160,7 @@ class TestDefaultWorkFlowEngine(base.DbTestCase):
|
||||
plugin=FakeAction,
|
||||
obj=None),
|
||||
namespace=FakeAction.namespace())
|
||||
actions = [self.create_action("dontcare", "vm1", {}, None)]
|
||||
actions = [self.create_action("dontcare", {}, None)]
|
||||
result = self.engine.execute(actions)
|
||||
self.assertEqual(result, False)
|
||||
self.check_action_state(actions[0], objects.action.State.FAILED)
|
||||
|
||||
@@ -84,10 +84,12 @@ def get_test_action(**kwargs):
|
||||
'uuid': kwargs.get('uuid', '10a47dd1-4874-4298-91cf-eff046dbdb8d'),
|
||||
'action_plan_id': kwargs.get('action_plan_id', 1),
|
||||
'action_type': kwargs.get('action_type', 'nop'),
|
||||
'applies_to': kwargs.get('applies_to',
|
||||
'10a47dd1-4874-4298-91cf-eff046dbdb8d'),
|
||||
'input_parameters': kwargs.get('input_parameters', {'key1': 'val1',
|
||||
'key2': 'val2'}),
|
||||
'input_parameters':
|
||||
kwargs.get('input_parameters',
|
||||
{'key1': 'val1',
|
||||
'key2': 'val2',
|
||||
'resource_id':
|
||||
'10a47dd1-4874-4298-91cf-eff046dbdb8d'}),
|
||||
'state': kwargs.get('state', 'PENDING'),
|
||||
'alarm': kwargs.get('alarm', None),
|
||||
'next': kwargs.get('next', 2),
|
||||
|
||||
@@ -18,55 +18,60 @@
|
||||
#
|
||||
import uuid
|
||||
|
||||
from watcher.decision_engine.model.hypervisor import Hypervisor
|
||||
from watcher.decision_engine.model.vm_state import VMState
|
||||
from watcher.decision_engine.model import hypervisor as modelhyp
|
||||
from watcher.decision_engine.model import vm_state
|
||||
from watcher.tests import base
|
||||
from watcher.tests.decision_engine.strategy.strategies.faker_cluster_state import \
|
||||
FakerModelCollector
|
||||
from watcher.tests.decision_engine.strategy.strategies import \
|
||||
faker_cluster_state
|
||||
|
||||
|
||||
class TestMapping(base.BaseTestCase):
|
||||
|
||||
VM1_UUID = "73b09e16-35b7-4922-804e-e8f5d9b740fc"
|
||||
VM2_UUID = "a4cab39b-9828-413a-bf88-f76921bf1517"
|
||||
|
||||
def test_get_node_from_vm(self):
|
||||
fake_cluster = FakerModelCollector()
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
|
||||
vms = model.get_all_vms()
|
||||
keys = list(vms.keys())
|
||||
vm = vms[keys[0]]
|
||||
if vm.uuid != 'VM_0':
|
||||
if vm.uuid != self.VM1_UUID:
|
||||
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 = FakerModelCollector()
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = fake_cluster.generate_scenario_3_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 = FakerModelCollector()
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = fake_cluster.generate_scenario_3_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')
|
||||
self.assertEqual(vms[self.VM1_UUID].state,
|
||||
vm_state.VMState.ACTIVE.value)
|
||||
self.assertEqual(vms[self.VM1_UUID].uuid, self.VM1_UUID)
|
||||
self.assertEqual(vms[self.VM2_UUID].state,
|
||||
vm_state.VMState.ACTIVE.value)
|
||||
self.assertEqual(vms[self.VM2_UUID].uuid, self.VM2_UUID)
|
||||
|
||||
def test_get_mapping(self):
|
||||
fake_cluster = FakerModelCollector()
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = fake_cluster.generate_scenario_3_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')
|
||||
self.assertEqual(mapping_vm[self.VM1_UUID], 'Node_0')
|
||||
self.assertEqual(mapping_vm[self.VM2_UUID], 'Node_1')
|
||||
|
||||
def test_migrate_vm(self):
|
||||
fake_cluster = FakerModelCollector()
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
vms = model.get_all_vms()
|
||||
keys = list(vms.keys())
|
||||
@@ -81,13 +86,13 @@ class TestMapping(base.BaseTestCase):
|
||||
self.assertEqual(model.mapping.migrate_vm(vm1, hyp0, hyp1), True)
|
||||
|
||||
def test_unmap_from_id_log_warning(self):
|
||||
fake_cluster = FakerModelCollector()
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
vms = model.get_all_vms()
|
||||
keys = list(vms.keys())
|
||||
vm0 = vms[keys[0]]
|
||||
id = "{0}".format(uuid.uuid4())
|
||||
hypervisor = Hypervisor()
|
||||
hypervisor = modelhyp.Hypervisor()
|
||||
hypervisor.uuid = id
|
||||
|
||||
model.mapping.unmap_from_id(hypervisor.uuid, vm0.uuid)
|
||||
@@ -95,7 +100,7 @@ class TestMapping(base.BaseTestCase):
|
||||
# hypervisor.uuid)), 1)
|
||||
|
||||
def test_unmap_from_id(self):
|
||||
fake_cluster = FakerModelCollector()
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
vms = model.get_all_vms()
|
||||
keys = list(vms.keys())
|
||||
|
||||
@@ -68,7 +68,7 @@ class TestActionScheduling(base.DbTestCase):
|
||||
"dst_uuid_hypervisor": "server2",
|
||||
}
|
||||
solution.add_action(action_type="migrate",
|
||||
applies_to="b199db0c-1408-4d52-b5a5-5ca14de0ff36",
|
||||
resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36",
|
||||
input_parameters=parameters)
|
||||
|
||||
with mock.patch.object(
|
||||
@@ -94,11 +94,11 @@ class TestActionScheduling(base.DbTestCase):
|
||||
"dst_uuid_hypervisor": "server2",
|
||||
}
|
||||
solution.add_action(action_type="migrate",
|
||||
applies_to="b199db0c-1408-4d52-b5a5-5ca14de0ff36",
|
||||
resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36",
|
||||
input_parameters=parameters)
|
||||
|
||||
solution.add_action(action_type="nop",
|
||||
applies_to="",
|
||||
resource_id="",
|
||||
input_parameters={})
|
||||
|
||||
with mock.patch.object(
|
||||
|
||||
@@ -13,27 +13,29 @@
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from watcher.decision_engine.solution.default import DefaultSolution
|
||||
|
||||
from watcher.decision_engine.solution import default
|
||||
from watcher.tests import base
|
||||
|
||||
|
||||
class TestDefaultSolution(base.BaseTestCase):
|
||||
def test_default_solution(self):
|
||||
solution = DefaultSolution()
|
||||
solution = default.DefaultSolution()
|
||||
parameters = {
|
||||
"src_uuid_hypervisor": "server1",
|
||||
"dst_uuid_hypervisor": "server2",
|
||||
}
|
||||
solution.add_action(action_type="nop",
|
||||
applies_to="b199db0c-1408-4d52-b5a5-5ca14de0ff36",
|
||||
resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36",
|
||||
input_parameters=parameters)
|
||||
self.assertEqual(len(solution.actions), 1)
|
||||
expected_action_type = "nop"
|
||||
expected_applies_to = "b199db0c-1408-4d52-b5a5-5ca14de0ff36"
|
||||
expected_parameters = parameters
|
||||
expected_parameters = {
|
||||
"src_uuid_hypervisor": "server1",
|
||||
"dst_uuid_hypervisor": "server2",
|
||||
"resource_id": "b199db0c-1408-4d52-b5a5-5ca14de0ff36"
|
||||
}
|
||||
self.assertEqual(solution.actions[0].get('action_type'),
|
||||
expected_action_type)
|
||||
self.assertEqual(solution.actions[0].get('applies_to'),
|
||||
expected_applies_to)
|
||||
self.assertEqual(solution.actions[0].get('input_parameters'),
|
||||
expected_parameters)
|
||||
|
||||
@@ -16,81 +16,24 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
import random
|
||||
|
||||
from watcher.decision_engine.model.hypervisor import Hypervisor
|
||||
from watcher.decision_engine.model.model_root import ModelRoot
|
||||
from watcher.decision_engine.model.resource import Resource
|
||||
from watcher.decision_engine.model.resource import ResourceType
|
||||
from watcher.decision_engine.model.vm import VM
|
||||
from watcher.metrics_engine.cluster_model_collector.api import \
|
||||
BaseClusterModelCollector
|
||||
from watcher.decision_engine.model import hypervisor
|
||||
from watcher.decision_engine.model import model_root as modelroot
|
||||
from watcher.decision_engine.model import resource
|
||||
from watcher.decision_engine.model import vm as modelvm
|
||||
from watcher.metrics_engine.cluster_model_collector import api
|
||||
|
||||
|
||||
class FakerModelCollector(BaseClusterModelCollector):
|
||||
class FakerModelCollector(api.BaseClusterModelCollector):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def get_latest_cluster_data_model(self):
|
||||
return self.generate_scenario_1()
|
||||
|
||||
def generate_random(self, count_nodes, number_of_vm_per_node):
|
||||
vms = []
|
||||
|
||||
current_state_cluster = ModelRoot()
|
||||
# number of nodes
|
||||
count_node = count_nodes
|
||||
# number max of vm per hypervisor
|
||||
node_count_vm = number_of_vm_per_node
|
||||
# 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_{0}".format(i)
|
||||
|
||||
hypervisor = Hypervisor()
|
||||
hypervisor.uuid = node_uuid
|
||||
hypervisor.hostname = "host_{0}".format(i)
|
||||
|
||||
mem.set_capacity(hypervisor, 132)
|
||||
disk.set_capacity(hypervisor, 250)
|
||||
num_cores.set_capacity(hypervisor, 40)
|
||||
current_state_cluster.add_hypervisor(hypervisor)
|
||||
|
||||
for i in range(0, count_vm):
|
||||
vm_uuid = "VM_{0}".format(i)
|
||||
vm = VM()
|
||||
vm.uuid = vm_uuid
|
||||
mem.set_capacity(vm, 8)
|
||||
disk.set_capacity(vm, 10)
|
||||
num_cores.set_capacity(vm, 10)
|
||||
vms.append(vm)
|
||||
current_state_cluster.add_vm(vm)
|
||||
j = 0
|
||||
for node_id in current_state_cluster.get_all_hypervisors():
|
||||
for i in range(0, random.randint(0, node_count_vm)):
|
||||
# todo(jed) check if enough capacity
|
||||
current_state_cluster.get_mapping().map(
|
||||
current_state_cluster.get_hypervisor_from_id(node_id),
|
||||
vms[j])
|
||||
j += 1
|
||||
return current_state_cluster
|
||||
|
||||
def generate_scenario_1(self):
|
||||
vms = []
|
||||
|
||||
current_state_cluster = ModelRoot()
|
||||
current_state_cluster = modelroot.ModelRoot()
|
||||
# number of nodes
|
||||
count_node = 5
|
||||
# number max of vm per node
|
||||
@@ -99,10 +42,10 @@ class FakerModelCollector(BaseClusterModelCollector):
|
||||
count_vm = (count_node * node_count_vm)
|
||||
|
||||
# define ressouce ( CPU, MEM disk, ... )
|
||||
mem = Resource(ResourceType.memory)
|
||||
mem = resource.Resource(resource.ResourceType.memory)
|
||||
# 2199.954 Mhz
|
||||
num_cores = Resource(ResourceType.cpu_cores)
|
||||
disk = Resource(ResourceType.disk)
|
||||
num_cores = resource.Resource(resource.ResourceType.cpu_cores)
|
||||
disk = resource.Resource(resource.ResourceType.disk)
|
||||
|
||||
current_state_cluster.create_resource(mem)
|
||||
current_state_cluster.create_resource(num_cores)
|
||||
@@ -110,7 +53,7 @@ class FakerModelCollector(BaseClusterModelCollector):
|
||||
|
||||
for i in range(0, count_node):
|
||||
node_uuid = "Node_{0}".format(i)
|
||||
node = Hypervisor()
|
||||
node = hypervisor.Hypervisor()
|
||||
node.uuid = node_uuid
|
||||
node.hostname = "hostname_{0}".format(i)
|
||||
|
||||
@@ -121,7 +64,7 @@ class FakerModelCollector(BaseClusterModelCollector):
|
||||
|
||||
for i in range(0, count_vm):
|
||||
vm_uuid = "VM_{0}".format(i)
|
||||
vm = VM()
|
||||
vm = modelvm.VM()
|
||||
vm.uuid = vm_uuid
|
||||
mem.set_capacity(vm, 2)
|
||||
disk.set_capacity(vm, 20)
|
||||
@@ -168,130 +111,68 @@ class FakerModelCollector(BaseClusterModelCollector):
|
||||
model.get_hypervisor_from_id(h_id),
|
||||
model.get_vm_from_id(vm_id))
|
||||
|
||||
def generate_scenario_2(self):
|
||||
vms = []
|
||||
|
||||
current_state_cluster = ModelRoot()
|
||||
# number of nodes
|
||||
count_node = 10
|
||||
# number max of vm per node
|
||||
node_count_vm = 7
|
||||
# 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_{0}".format(i)
|
||||
node = Hypervisor()
|
||||
node.uuid = node_uuid
|
||||
node.hostname = "hostname_{0}".format(i)
|
||||
|
||||
mem.set_capacity(node, 132)
|
||||
disk.set_capacity(node, 250)
|
||||
num_cores.set_capacity(node, 40)
|
||||
current_state_cluster.add_hypervisor(node)
|
||||
|
||||
for i in range(0, count_vm):
|
||||
vm_uuid = "VM_{0}".format(i)
|
||||
vm = VM()
|
||||
vm.uuid = vm_uuid
|
||||
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)
|
||||
indice = 0
|
||||
for j in range(0, 2):
|
||||
node_uuid = "Node_{0}".format(j)
|
||||
for i in range(indice, 3):
|
||||
vm_uuid = "VM_{0}".format(i)
|
||||
self.map(current_state_cluster, node_uuid, vm_uuid)
|
||||
|
||||
for j in range(2, 5):
|
||||
node_uuid = "Node_{0}".format(j)
|
||||
for i in range(indice, 4):
|
||||
vm_uuid = "VM_{0}".format(i)
|
||||
self.map(current_state_cluster, node_uuid, vm_uuid)
|
||||
|
||||
for j in range(5, 10):
|
||||
node_uuid = "Node_{0}".format(j)
|
||||
for i in range(indice, 4):
|
||||
vm_uuid = "VM_{0}".format(i)
|
||||
self.map(current_state_cluster, node_uuid, vm_uuid)
|
||||
|
||||
return current_state_cluster
|
||||
|
||||
def generate_scenario_3_with_2_hypervisors(self):
|
||||
vms = []
|
||||
|
||||
current_state_cluster = ModelRoot()
|
||||
root = modelroot.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)
|
||||
mem = resource.Resource(resource.ResourceType.memory)
|
||||
# 2199.954 Mhz
|
||||
num_cores = Resource(ResourceType.cpu_cores)
|
||||
disk = Resource(ResourceType.disk)
|
||||
num_cores = resource.Resource(resource.ResourceType.cpu_cores)
|
||||
disk = resource.Resource(resource.ResourceType.disk)
|
||||
|
||||
current_state_cluster.create_resource(mem)
|
||||
current_state_cluster.create_resource(num_cores)
|
||||
current_state_cluster.create_resource(disk)
|
||||
root.create_resource(mem)
|
||||
root.create_resource(num_cores)
|
||||
root.create_resource(disk)
|
||||
|
||||
for i in range(0, count_node):
|
||||
node_uuid = "Node_{0}".format(i)
|
||||
node = Hypervisor()
|
||||
node = hypervisor.Hypervisor()
|
||||
node.uuid = node_uuid
|
||||
node.hostname = "hostname_{0}".format(i)
|
||||
|
||||
mem.set_capacity(node, 132)
|
||||
disk.set_capacity(node, 250)
|
||||
num_cores.set_capacity(node, 40)
|
||||
current_state_cluster.add_hypervisor(node)
|
||||
root.add_hypervisor(node)
|
||||
|
||||
for i in range(0, count_vm):
|
||||
vm_uuid = "VM_{0}".format(i)
|
||||
vm = VM()
|
||||
vm.uuid = vm_uuid
|
||||
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)
|
||||
vm1 = modelvm.VM()
|
||||
vm1.uuid = "73b09e16-35b7-4922-804e-e8f5d9b740fc"
|
||||
mem.set_capacity(vm1, 2)
|
||||
disk.set_capacity(vm1, 20)
|
||||
num_cores.set_capacity(vm1, 10)
|
||||
vms.append(vm1)
|
||||
root.add_vm(vm1)
|
||||
|
||||
current_state_cluster.get_mapping().map(
|
||||
current_state_cluster.get_hypervisor_from_id("Node_0"),
|
||||
current_state_cluster.get_vm_from_id("VM_0"))
|
||||
vm2 = modelvm.VM()
|
||||
vm2.uuid = "a4cab39b-9828-413a-bf88-f76921bf1517"
|
||||
mem.set_capacity(vm2, 2)
|
||||
disk.set_capacity(vm2, 20)
|
||||
num_cores.set_capacity(vm2, 10)
|
||||
vms.append(vm2)
|
||||
root.add_vm(vm2)
|
||||
|
||||
current_state_cluster.get_mapping().map(
|
||||
current_state_cluster.get_hypervisor_from_id("Node_1"),
|
||||
current_state_cluster.get_vm_from_id("VM_1"))
|
||||
root.get_mapping().map(root.get_hypervisor_from_id("Node_0"),
|
||||
root.get_vm_from_id(str(vm1.uuid)))
|
||||
|
||||
return current_state_cluster
|
||||
root.get_mapping().map(root.get_hypervisor_from_id("Node_1"),
|
||||
root.get_vm_from_id(str(vm2.uuid)))
|
||||
|
||||
return root
|
||||
|
||||
def generate_scenario_4_with_1_hypervisor_no_vm(self):
|
||||
current_state_cluster = ModelRoot()
|
||||
current_state_cluster = modelroot.ModelRoot()
|
||||
# number of nodes
|
||||
count_node = 1
|
||||
|
||||
# define ressouce ( CPU, MEM disk, ... )
|
||||
mem = Resource(ResourceType.memory)
|
||||
mem = resource.Resource(resource.ResourceType.memory)
|
||||
# 2199.954 Mhz
|
||||
num_cores = Resource(ResourceType.cpu_cores)
|
||||
disk = Resource(ResourceType.disk)
|
||||
num_cores = resource.Resource(resource.ResourceType.cpu_cores)
|
||||
disk = resource.Resource(resource.ResourceType.disk)
|
||||
|
||||
current_state_cluster.create_resource(mem)
|
||||
current_state_cluster.create_resource(num_cores)
|
||||
@@ -299,7 +180,7 @@ class FakerModelCollector(BaseClusterModelCollector):
|
||||
|
||||
for i in range(0, count_node):
|
||||
node_uuid = "Node_{0}".format(i)
|
||||
node = Hypervisor()
|
||||
node = hypervisor.Hypervisor()
|
||||
node.uuid = node_uuid
|
||||
node.hostname = "hostname_{0}".format(i)
|
||||
|
||||
@@ -312,17 +193,17 @@ class FakerModelCollector(BaseClusterModelCollector):
|
||||
|
||||
def generate_scenario_5_with_vm_disk_0(self):
|
||||
vms = []
|
||||
current_state_cluster = ModelRoot()
|
||||
current_state_cluster = modelroot.ModelRoot()
|
||||
# number of nodes
|
||||
count_node = 1
|
||||
# number of vms
|
||||
count_vm = 1
|
||||
|
||||
# define ressouce ( CPU, MEM disk, ... )
|
||||
mem = Resource(ResourceType.memory)
|
||||
mem = resource.Resource(resource.ResourceType.memory)
|
||||
# 2199.954 Mhz
|
||||
num_cores = Resource(ResourceType.cpu_cores)
|
||||
disk = Resource(ResourceType.disk)
|
||||
num_cores = resource.Resource(resource.ResourceType.cpu_cores)
|
||||
disk = resource.Resource(resource.ResourceType.disk)
|
||||
|
||||
current_state_cluster.create_resource(mem)
|
||||
current_state_cluster.create_resource(num_cores)
|
||||
@@ -330,7 +211,7 @@ class FakerModelCollector(BaseClusterModelCollector):
|
||||
|
||||
for i in range(0, count_node):
|
||||
node_uuid = "Node_{0}".format(i)
|
||||
node = Hypervisor()
|
||||
node = hypervisor.Hypervisor()
|
||||
node.uuid = node_uuid
|
||||
node.hostname = "hostname_{0}".format(i)
|
||||
|
||||
@@ -341,7 +222,7 @@ class FakerModelCollector(BaseClusterModelCollector):
|
||||
|
||||
for i in range(0, count_vm):
|
||||
vm_uuid = "VM_{0}".format(i)
|
||||
vm = VM()
|
||||
vm = modelvm.VM()
|
||||
vm.uuid = vm_uuid
|
||||
mem.set_capacity(vm, 2)
|
||||
disk.set_capacity(vm, 0)
|
||||
|
||||
@@ -16,26 +16,26 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
from collections import Counter
|
||||
import collections
|
||||
import mock
|
||||
|
||||
from watcher.applier.actions.loading import default
|
||||
from watcher.common import exception
|
||||
from watcher.decision_engine.model.model_root import ModelRoot
|
||||
from watcher.decision_engine.strategy.strategies.basic_consolidation import \
|
||||
BasicConsolidation
|
||||
from watcher.decision_engine.model import model_root
|
||||
from watcher.decision_engine.strategy import strategies
|
||||
from watcher.tests import base
|
||||
from watcher.tests.decision_engine.strategy.strategies.faker_cluster_state \
|
||||
import FakerModelCollector
|
||||
from watcher.tests.decision_engine.strategy.strategies.faker_metrics_collector\
|
||||
import FakerMetricsCollector
|
||||
from watcher.tests.decision_engine.strategy.strategies \
|
||||
import faker_cluster_state
|
||||
from watcher.tests.decision_engine.strategy.strategies \
|
||||
import faker_metrics_collector
|
||||
|
||||
|
||||
class TestBasicConsolidation(base.BaseTestCase):
|
||||
# fake metrics
|
||||
fake_metrics = FakerMetricsCollector()
|
||||
fake_metrics = faker_metrics_collector.FakerMetricsCollector()
|
||||
|
||||
# fake cluster
|
||||
fake_cluster = FakerModelCollector()
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
|
||||
def test_cluster_size(self):
|
||||
size_cluster = len(
|
||||
@@ -45,7 +45,7 @@ class TestBasicConsolidation(base.BaseTestCase):
|
||||
|
||||
def test_basic_consolidation_score_hypervisor(self):
|
||||
cluster = self.fake_cluster.generate_scenario_1()
|
||||
sercon = BasicConsolidation()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
sercon.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
|
||||
@@ -67,7 +67,7 @@ class TestBasicConsolidation(base.BaseTestCase):
|
||||
|
||||
def test_basic_consolidation_score_vm(self):
|
||||
cluster = self.fake_cluster.generate_scenario_1()
|
||||
sercon = BasicConsolidation()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
sercon.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
vm_0 = cluster.get_vm_from_id("VM_0")
|
||||
@@ -90,7 +90,7 @@ class TestBasicConsolidation(base.BaseTestCase):
|
||||
|
||||
def test_basic_consolidation_score_vm_disk(self):
|
||||
cluster = self.fake_cluster.generate_scenario_5_with_vm_disk_0()
|
||||
sercon = BasicConsolidation()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
sercon.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
vm_0 = cluster.get_vm_from_id("VM_0")
|
||||
@@ -99,7 +99,7 @@ class TestBasicConsolidation(base.BaseTestCase):
|
||||
|
||||
def test_basic_consolidation_weight(self):
|
||||
cluster = self.fake_cluster.generate_scenario_1()
|
||||
sercon = BasicConsolidation()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
sercon.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
vm_0 = cluster.get_vm_from_id("VM_0")
|
||||
@@ -114,24 +114,24 @@ class TestBasicConsolidation(base.BaseTestCase):
|
||||
vm_0_weight_assert)
|
||||
|
||||
def test_calculate_migration_efficacy(self):
|
||||
sercon = BasicConsolidation()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
sercon.calculate_migration_efficacy()
|
||||
|
||||
def test_exception_model(self):
|
||||
sercon = BasicConsolidation()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
self.assertRaises(exception.ClusterStateNotDefined, sercon.execute,
|
||||
None)
|
||||
|
||||
def test_exception_cluster_empty(self):
|
||||
sercon = BasicConsolidation()
|
||||
model = ModelRoot()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
model = model_root.ModelRoot()
|
||||
self.assertRaises(exception.ClusterEmpty, sercon.execute,
|
||||
model)
|
||||
|
||||
def test_calculate_score_vm_raise_cluster_state_not_found(self):
|
||||
metrics = FakerMetricsCollector()
|
||||
metrics = faker_metrics_collector.FakerMetricsCollector()
|
||||
metrics.empty_one_metric("CPU_COMPUTE")
|
||||
sercon = BasicConsolidation()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
sercon.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
|
||||
@@ -139,8 +139,8 @@ class TestBasicConsolidation(base.BaseTestCase):
|
||||
sercon.calculate_score_vm, "VM_1", None)
|
||||
|
||||
def test_check_migration(self):
|
||||
sercon = BasicConsolidation()
|
||||
fake_cluster = FakerModelCollector()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
|
||||
all_vms = model.get_all_vms()
|
||||
@@ -151,8 +151,8 @@ class TestBasicConsolidation(base.BaseTestCase):
|
||||
sercon.check_migration(model, hyp0, hyp0, vm0)
|
||||
|
||||
def test_threshold(self):
|
||||
sercon = BasicConsolidation()
|
||||
fake_cluster = FakerModelCollector()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
|
||||
all_hyps = model.get_all_hypervisors()
|
||||
@@ -165,19 +165,19 @@ class TestBasicConsolidation(base.BaseTestCase):
|
||||
self.assertEqual(sercon.get_threshold_cores(), threshold_cores + 1)
|
||||
|
||||
def test_number_of(self):
|
||||
sercon = BasicConsolidation()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
sercon.get_number_of_released_nodes()
|
||||
sercon.get_number_of_migrations()
|
||||
|
||||
def test_basic_consolidation_migration(self):
|
||||
sercon = BasicConsolidation()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
sercon.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
|
||||
solution = sercon.execute(
|
||||
self.fake_cluster.generate_scenario_3_with_2_hypervisors())
|
||||
|
||||
actions_counter = Counter(
|
||||
actions_counter = collections.Counter(
|
||||
[action.get('action_type') for action in solution.actions])
|
||||
|
||||
expected_num_migrations = 1
|
||||
@@ -189,26 +189,31 @@ class TestBasicConsolidation(base.BaseTestCase):
|
||||
self.assertEqual(num_migrations, expected_num_migrations)
|
||||
self.assertEqual(num_hypervisor_state_change, expected_power_state)
|
||||
|
||||
def test_execute_cluster_empty(self):
|
||||
current_state_cluster = FakerModelCollector()
|
||||
sercon = BasicConsolidation("sercon", "Basic offline consolidation")
|
||||
sercon.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
model = current_state_cluster.generate_random(0, 0)
|
||||
self.assertRaises(exception.ClusterEmpty, sercon.execute, model)
|
||||
|
||||
# calculate_weight
|
||||
def test_execute_no_workload(self):
|
||||
sercon = BasicConsolidation()
|
||||
sercon = strategies.BasicConsolidation()
|
||||
sercon.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
|
||||
current_state_cluster = FakerModelCollector()
|
||||
current_state_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = current_state_cluster. \
|
||||
generate_scenario_4_with_1_hypervisor_no_vm()
|
||||
|
||||
with mock.patch.object(BasicConsolidation, 'calculate_weight') \
|
||||
with mock.patch.object(strategies.BasicConsolidation,
|
||||
'calculate_weight') \
|
||||
as mock_score_call:
|
||||
mock_score_call.return_value = 0
|
||||
solution = sercon.execute(model)
|
||||
self.assertEqual(solution.efficacy, 100)
|
||||
|
||||
def test_check_parameters(self):
|
||||
sercon = strategies.BasicConsolidation()
|
||||
sercon.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
solution = sercon.execute(
|
||||
self.fake_cluster.generate_scenario_3_with_2_hypervisors())
|
||||
loader = default.DefaultActionLoader()
|
||||
for action in solution.actions:
|
||||
loaded_action = loader.load(action['action_type'])
|
||||
loaded_action.input_parameters = action['input_parameters']
|
||||
loaded_action.validate_parameters()
|
||||
|
||||
@@ -13,16 +13,29 @@
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from watcher.decision_engine.strategy.strategies.dummy_strategy import \
|
||||
DummyStrategy
|
||||
|
||||
from watcher.applier.actions.loading import default
|
||||
from watcher.decision_engine.strategy import strategies
|
||||
from watcher.tests import base
|
||||
from watcher.tests.decision_engine.strategy.strategies.faker_cluster_state\
|
||||
import FakerModelCollector
|
||||
from watcher.tests.decision_engine.strategy.strategies import \
|
||||
faker_cluster_state
|
||||
|
||||
|
||||
class TestDummyStrategy(base.TestCase):
|
||||
def test_dummy_strategy(self):
|
||||
tactique = DummyStrategy("basic", "Basic offline consolidation")
|
||||
fake_cluster = FakerModelCollector()
|
||||
dummy = strategies.DummyStrategy("dummy", "Dummy strategy")
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
tactique.execute(model)
|
||||
solution = dummy.execute(model)
|
||||
self.assertEqual(3, len(solution.actions))
|
||||
|
||||
def test_check_parameters(self):
|
||||
dummy = strategies.DummyStrategy("dummy", "Dummy strategy")
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
solution = dummy.execute(model)
|
||||
loader = default.DefaultActionLoader()
|
||||
for action in solution.actions:
|
||||
loaded_action = loader.load(action['action_type'])
|
||||
loaded_action.input_parameters = action['input_parameters']
|
||||
loaded_action.validate_parameters()
|
||||
|
||||
@@ -16,35 +16,35 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
from collections import Counter
|
||||
import collections
|
||||
import mock
|
||||
|
||||
from watcher.applier.actions.loading import default
|
||||
from watcher.common import exception
|
||||
from watcher.decision_engine.model.model_root import ModelRoot
|
||||
from watcher.decision_engine.model.resource import ResourceType
|
||||
from watcher.decision_engine.strategy.strategies.outlet_temp_control import \
|
||||
OutletTempControl
|
||||
from watcher.decision_engine.model import model_root
|
||||
from watcher.decision_engine.model import resource
|
||||
from watcher.decision_engine.strategy import strategies
|
||||
from watcher.tests import base
|
||||
from watcher.tests.decision_engine.strategy.strategies.faker_cluster_state \
|
||||
import FakerModelCollector
|
||||
from watcher.tests.decision_engine.strategy.strategies.faker_metrics_collector\
|
||||
import FakerMetricsCollector
|
||||
from watcher.tests.decision_engine.strategy.strategies \
|
||||
import faker_cluster_state
|
||||
from watcher.tests.decision_engine.strategy.strategies \
|
||||
import faker_metrics_collector
|
||||
|
||||
|
||||
class TestOutletTempControl(base.BaseTestCase):
|
||||
# fake metrics
|
||||
fake_metrics = FakerMetricsCollector()
|
||||
fake_metrics = faker_metrics_collector.FakerMetricsCollector()
|
||||
|
||||
# fake cluster
|
||||
fake_cluster = FakerModelCollector()
|
||||
fake_cluster = faker_cluster_state.FakerModelCollector()
|
||||
|
||||
def test_calc_used_res(self):
|
||||
model = self.fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
strategy = OutletTempControl()
|
||||
strategy = strategies.OutletTempControl()
|
||||
hypervisor = model.get_hypervisor_from_id('Node_0')
|
||||
cap_cores = model.get_resource_from_id(ResourceType.cpu_cores)
|
||||
cap_mem = model.get_resource_from_id(ResourceType.memory)
|
||||
cap_disk = model.get_resource_from_id(ResourceType.disk)
|
||||
cap_cores = model.get_resource_from_id(resource.ResourceType.cpu_cores)
|
||||
cap_mem = model.get_resource_from_id(resource.ResourceType.memory)
|
||||
cap_disk = model.get_resource_from_id(resource.ResourceType.disk)
|
||||
cores_used, mem_used, disk_used = strategy.calc_used_res(model,
|
||||
hypervisor,
|
||||
cap_cores,
|
||||
@@ -55,7 +55,7 @@ class TestOutletTempControl(base.BaseTestCase):
|
||||
|
||||
def test_group_hosts_by_outlet_temp(self):
|
||||
model = self.fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
strategy = OutletTempControl()
|
||||
strategy = strategies.OutletTempControl()
|
||||
strategy.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
h1, h2 = strategy.group_hosts_by_outlet_temp(model)
|
||||
@@ -64,17 +64,18 @@ class TestOutletTempControl(base.BaseTestCase):
|
||||
|
||||
def test_choose_vm_to_migrate(self):
|
||||
model = self.fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
strategy = OutletTempControl()
|
||||
strategy = strategies.OutletTempControl()
|
||||
strategy.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
h1, h2 = strategy.group_hosts_by_outlet_temp(model)
|
||||
vm_to_mig = strategy.choose_vm_to_migrate(model, h1)
|
||||
self.assertEqual(vm_to_mig[0].uuid, 'Node_1')
|
||||
self.assertEqual(vm_to_mig[1].uuid, 'VM_1')
|
||||
self.assertEqual(vm_to_mig[1].uuid,
|
||||
"a4cab39b-9828-413a-bf88-f76921bf1517")
|
||||
|
||||
def test_filter_dest_servers(self):
|
||||
model = self.fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
strategy = OutletTempControl()
|
||||
strategy = strategies.OutletTempControl()
|
||||
strategy.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
h1, h2 = strategy.group_hosts_by_outlet_temp(model)
|
||||
@@ -84,29 +85,28 @@ class TestOutletTempControl(base.BaseTestCase):
|
||||
self.assertEqual(dest_hosts[0]['hv'].uuid, 'Node_0')
|
||||
|
||||
def test_exception_model(self):
|
||||
strategy = OutletTempControl()
|
||||
strategy = strategies.OutletTempControl()
|
||||
self.assertRaises(exception.ClusterStateNotDefined, strategy.execute,
|
||||
None)
|
||||
|
||||
def test_exception_cluster_empty(self):
|
||||
strategy = OutletTempControl()
|
||||
model = ModelRoot()
|
||||
strategy = strategies.OutletTempControl()
|
||||
model = model_root.ModelRoot()
|
||||
self.assertRaises(exception.ClusterEmpty, strategy.execute, model)
|
||||
|
||||
def test_execute_cluster_empty(self):
|
||||
current_state_cluster = FakerModelCollector()
|
||||
strategy = OutletTempControl()
|
||||
strategy = strategies.OutletTempControl()
|
||||
strategy.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
model = current_state_cluster.generate_random(0, 0)
|
||||
model = model_root.ModelRoot()
|
||||
self.assertRaises(exception.ClusterEmpty, strategy.execute, model)
|
||||
|
||||
def test_execute_no_workload(self):
|
||||
strategy = OutletTempControl()
|
||||
strategy = strategies.OutletTempControl()
|
||||
strategy.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
|
||||
current_state_cluster = FakerModelCollector()
|
||||
current_state_cluster = faker_cluster_state.FakerModelCollector()
|
||||
model = current_state_cluster. \
|
||||
generate_scenario_4_with_1_hypervisor_no_vm()
|
||||
|
||||
@@ -114,13 +114,25 @@ class TestOutletTempControl(base.BaseTestCase):
|
||||
self.assertEqual(solution.actions, [])
|
||||
|
||||
def test_execute(self):
|
||||
strategy = OutletTempControl()
|
||||
strategy = strategies.OutletTempControl()
|
||||
strategy.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
model = self.fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
solution = strategy.execute(model)
|
||||
actions_counter = Counter(
|
||||
actions_counter = collections.Counter(
|
||||
[action.get('action_type') for action in solution.actions])
|
||||
|
||||
num_migrations = actions_counter.get("migrate", 0)
|
||||
self.assertEqual(num_migrations, 1)
|
||||
|
||||
def test_check_parameters(self):
|
||||
outlet = strategies.OutletTempControl()
|
||||
outlet.ceilometer = mock.MagicMock(
|
||||
statistic_aggregation=self.fake_metrics.mock_get_statistics)
|
||||
model = self.fake_cluster.generate_scenario_3_with_2_hypervisors()
|
||||
solution = outlet.execute(model)
|
||||
loader = default.DefaultActionLoader()
|
||||
for action in solution.actions:
|
||||
loaded_action = loader.load(action['action_type'])
|
||||
loaded_action.input_parameters = action['input_parameters']
|
||||
loaded_action.validate_parameters()
|
||||
|
||||
Reference in New Issue
Block a user