consolidation of watcher

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

View File

@@ -31,7 +31,7 @@ from watcher.tests.objects import utils as obj_utils
def post_get_test_action(**kw):
action = api_utils.action_post_data(**kw)
action_plan = db_utils.get_test_action_plan()
action['action_plan_id'] = None
del action['action_plan_id']
action['action_plan_uuid'] = kw.get('action_plan_uuid',
action_plan['uuid'])
action['next'] = None

View File

@@ -0,0 +1,63 @@
# 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
from watcher.tests.api import base as api_base
CONF = cfg.CONF
class TestListGoal(api_base.FunctionalTest):
def setUp(self):
super(TestListGoal, self).setUp()
def _assert_goal_fields(self, goal):
goal_fields = ['name', 'strategy']
for field in goal_fields:
self.assertIn(field, goal)
def test_one(self):
response = self.get_json('/goals')
self._assert_goal_fields(response['goals'][0])
def test_get_one(self):
goal_name = CONF.watcher_goals.goals.keys()[0]
response = self.get_json('/goals/%s' % goal_name)
self.assertEqual(goal_name, response['name'])
self._assert_goal_fields(response)
def test_detail(self):
goal_name = CONF.watcher_goals.goals.keys()[0]
response = self.get_json('/goals/detail')
self.assertEqual(goal_name, response['goals'][0]["name"])
self._assert_goal_fields(response['goals'][0])
def test_detail_against_single(self):
goal_name = CONF.watcher_goals.goals.keys()[0]
response = self.get_json('/goals/%s/detail' % goal_name,
expect_errors=True)
self.assertEqual(404, response.status_int)
def test_many(self):
response = self.get_json('/goals')
self.assertEqual(len(CONF.watcher_goals.goals),
len(response['goals']))
def test_collection_links(self):
response = self.get_json('/goals/?limit=2')
self.assertEqual(2, len(response['goals']))
def test_collection_links_default_limit(self):
cfg.CONF.set_override('max_limit', 3, 'api')
response = self.get_json('/goals')
self.assertEqual(3, len(response['goals']))

View File

@@ -1,65 +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
from watcher.applier.framework.default_applier import DefaultApplier
from watcher.common import utils
from watcher.decision_engine.framework.default_planner import DefaultPlanner
from watcher.decision_engine.strategies.basic_consolidation import \
BasicConsolidation
from watcher.openstack.common import log
from watcher.tests.db import base
from watcher.tests.db import utils as db_utils
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
from oslo_config import cfg
CONF = cfg.CONF
""
class TestApplier(base.DbTestCase):
default_planner = DefaultPlanner()
def create_solution(self):
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
return sercon.execute(current_state_cluster.generate_scenario_1())
def test_scheduler_w(self):
CONF.debug = True
log.setup('watcher-sercon-demo')
CONF.keystone_authtoken.auth_uri = "http://10.50.0.105:5000/v3"
CONF.keystone_authtoken.admin_user = "admin"
CONF.keystone_authtoken.admin_password = "openstacktest"
CONF.keystone_authtoken.admin_tenant_name = "test"
audit = db_utils.create_test_audit(uuid=utils.generate_uuid())
action_plan = self.default_planner.schedule(self.context,
audit.id,
self.create_solution())
applier = DefaultApplier()
applier.execute(self.context, action_plan.uuid)
"""""

View File

@@ -1,99 +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 keystoneclient import session
from keystoneclient.auth.identity import v3
import cinderclient.v2.client as ciclient
import glanceclient.v2.client as glclient
import keystoneclient.v3.client as ksclient
import neutronclient.neutron.client as netclient
import novaclient.v2.client as nvclient
from watcher.common.utils import CONF
from oslo_config import cfg
from watcher.applier.framework.command.migrate_command import MigrateCommand
from watcher.applier.framework.command.wrapper.nova_wrapper import NovaWrapper
from watcher.decision_engine.framework.default_planner import Primitives
from watcher.openstack.common import log
cfg.CONF.import_opt('auth_uri', 'keystoneclient.middleware.auth_token',
group='keystone_authtoken')
cfg.CONF.import_opt('admin_user', 'keystoneclient.middleware.auth_token',
group='keystone_authtoken')
cfg.CONF.import_opt('admin_password', 'keystoneclient.middleware.auth_token',
group='keystone_authtoken')
cfg.CONF.import_opt('admin_tenant_name',
'keystoneclient.middleware.auth_token',
group='keystone_authtoken')
cfg.CONF.keystone_authtoken.auth_uri = "http://10.50.0.105:5000/v3/"
cfg.CONF.keystone_authtoken.admin_user = "admin"
cfg.CONF.keystone_authtoken.admin_password = "openstacktest"
cfg.CONF.keystone_authtoken.admin_tenant_name = "test"
try:
cfg.CONF.debug = True
log.setup('watcher-sercon-demo')
creds = \
{'auth_url': CONF.keystone_authtoken.auth_uri,
'username': CONF.keystone_authtoken.admin_user,
'password': CONF.keystone_authtoken.admin_password,
'project_name': CONF.keystone_authtoken.admin_tenant_name,
'user_domain_name': "default",
'project_domain_name': "default"}
auth = v3.Password(auth_url=creds['auth_url'],
username=creds['username'],
password=creds['password'],
project_name=creds['project_name'],
user_domain_name=creds[
'user_domain_name'],
project_domain_name=creds[
'project_domain_name'])
sess = session.Session(auth=auth)
nova = nvclient.Client("3", session=sess)
neutron = netclient.Client('2.0', session=sess)
neutron.format = 'json'
keystone = ksclient.Client(**creds)
glance_endpoint = keystone. \
service_catalog.url_for(service_type='image',
endpoint_type='publicURL')
glance = glclient.Client(glance_endpoint,
token=keystone.auth_token)
cinder = ciclient.Client('2', session=sess)
wrapper = NovaWrapper(user=creds['username'], nova=nova,
neutron=neutron, glance=glance,
cinder=cinder)
instance = wrapper. \
create_instance(hypervisor_id='ldev-indeedsrv006',
inst_name="demo_instance_1",
keypair_name='admin',
image_id=
"2b958331-379b-4618-b2ba-fbe8a608b2bb")
cmd = MigrateCommand(instance.id, Primitives.COLD_MIGRATE,
'ldev-indeedsrv006',
'ldev-indeedsrv005')
resu = cmd.execute(cmd)
resu.result()
# wrapper.delete_instance(instance.id)
except Exception as e:
print("rollback " + unicode(e))
"""""

View File

@@ -1,6 +1,8 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -13,6 +15,7 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from mock import call
from mock import MagicMock

View File

@@ -1,6 +1,8 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

View File

@@ -1,6 +1,8 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -13,6 +15,7 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from mock import MagicMock

View File

@@ -1,6 +1,8 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

View File

@@ -1,6 +1,8 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

View File

@@ -1,6 +1,8 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

View File

@@ -1,6 +1,8 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -13,6 +15,7 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from watcher.decision_engine.framework.manager_decision_engine import \

View File

@@ -1,6 +1,8 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -13,6 +15,7 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import mock
import oslo.messaging as om
@@ -42,12 +45,6 @@ class TestApplierAPI(base.TestCase):
'check_api_version',
api_version=ApplierAPI().API_VERSION)
def test_execute_action_plan_throw_exception(self):
action_plan_uuid = "uuid"
self.assertRaises(exception.InvalidUuidOrName,
self.api.launch_action_plan,
action_plan_uuid)
def test_execute_audit_without_error(self):
with mock.patch.object(om.RPCClient, 'call') as mock_call:
action_plan_uuid = utils.generate_uuid()
@@ -56,3 +53,9 @@ class TestApplierAPI(base.TestCase):
self.context.to_dict(),
'launch_action_plan',
action_plan_uuid=action_plan_uuid)
def test_execute_action_plan_throw_exception(self):
action_plan_uuid = "uuid"
self.assertRaises(exception.InvalidUuidOrName,
self.api.launch_action_plan,
action_plan_uuid)

View File

@@ -0,0 +1,85 @@
# -*- 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.metrics_engine.api.metrics_resource_collector import \
AggregationFunction
from watcher.metrics_engine.framework.datasources.influxdb_collector import \
InfluxDBCollector
from watcher.tests import base
class TestInfluxDB(base.TestCase):
def get_databases(self):
return {'name': 'indeed'}
def test_get_measurement(self):
influx = InfluxDBCollector()
influx.get_client = mock.MagicMock()
influx.get_client.get_list_database = self.get_databases
result = influx.get_measurement("")
self.assertEqual(result, [])
def test_build_query(self):
influx = InfluxDBCollector()
influx.get_client = mock.MagicMock()
query = influx.build_query("cpu_compute")
self.assertEqual(str(query), "SELECT * FROM \"cpu_compute\" ;")
def test_build_query_aggregate(self):
influx = InfluxDBCollector()
influx.get_client = mock.MagicMock()
query = influx.build_query("cpu_compute",
aggregation_function=AggregationFunction.
COUNT)
self.assertEqual(str(query),
"SELECT count(value) FROM \"cpu_compute\" ;")
def test_build_query_aggregate_intervals(self):
influx = InfluxDBCollector()
influx.get_client = mock.MagicMock()
query = influx.build_query("cpu_compute",
aggregation_function=AggregationFunction.
COUNT,
intervals="5m")
self.assertEqual(str(query),
"SELECT count(value) FROM \"cpu_compute\" "
"group by time(5m);")
def test_build_query_aggregate_filters(self):
influx = InfluxDBCollector()
influx.get_client = mock.MagicMock()
filters = ['host=server1']
query = influx.build_query("cpu_compute",
aggregation_function=AggregationFunction.
COUNT,
intervals="5m",
filters=filters)
self.assertEqual(str(query), 'SELECT count(value) FROM'
' \"cpu_compute" WHERE'
' host = \'server1\' group by time(5m);')
def test_get_qusurement_start(self):
influx = InfluxDBCollector()
influx.get_client = mock.MagicMock()
influx.get_client.get_list_database = self.get_databases
result = influx.get_measurement("cpu_compute", start_time='now',
end_time="now")
self.assertEqual(result, [])

View File

@@ -0,0 +1,43 @@
# -*- 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.metrics_engine.framework.statedb_collector import NovaCollector
from watcher.tests import base
class TestNovaCollector(base.TestCase):
@mock.patch('keystoneclient.v3.client.Client')
def setUp(self, mock_ksclient):
super(TestNovaCollector, self).setUp()
self.wrapper = mock.MagicMock()
self.nova_collector = NovaCollector(self.wrapper)
def test_nova_collector(self):
hypervisor = mock.Mock()
hypervisor.hypervisor_hostname = "rdev-lannion.eu"
hypervisor.service = mock.MagicMock()
service = mock.Mock()
service.host = ""
self.wrapper.get_hypervisors_list.return_value = {hypervisor}
self.wrapper.nova.services.find.get.return_value = service
model = self.nova_collector.get_latest_state_cluster()
self.assertIsNotNone(model)

View File

@@ -0,0 +1,52 @@
# -*- 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.metrics_engine.framework.datasources.sql_ast.build_db_query import \
DBQuery
from watcher.tests import base
class TestDBQuery(base.TestCase):
def test_query(self):
expected = "SELECT * FROM \"cpu_compute.cpu.user.percent_gauge\" ;"
query = DBQuery("cpu_compute.cpu.user.percent_gauge")
self.assertEqual(str(query), expected)
def test_query_where(self):
expected = "SELECT * FROM" \
" \"cpu_compute.cpu.user.percent_gauge\" WHERE host=jed;"
query = DBQuery("cpu_compute.cpu.user.percent_gauge").where(
"host=jed")
self.assertEqual(str(query), expected)
def test_query_filter(self):
expected = "SELECT mean(value) FROM" \
" \"cpu_compute.cpu.user.percent_gauge\" WHERE host=jed;"
query = DBQuery("cpu_compute.cpu.user.percent_gauge").where(
"host=jed").select("mean(value)")
self.assertEqual(str(query), expected)
def test_query_groupby(self):
expected = "SELECT * FROM" \
" \"cpu_compute.cpu.user.percent_gauge\" " \
"group by time(5m);"
query = DBQuery("cpu_compute.cpu.user.percent_gauge").groupby(
"time(5m)")
self.assertEqual(str(query), expected)

View File

@@ -31,7 +31,6 @@ class TestTransportUrlBuilder(base.TestCase):
def test_transport_url_not_none(self):
url = TransportUrlBuilder().url
print(url)
self.assertIsNotNone(url, "The transport url must not be none")
def test_transport_url_valid_pattern(self):

View File

@@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from watcher.decision_engine.api.messaging.decision_engine_command import \
DecisionEngineCommand
from watcher.tests import base
class TestDecisionEngineCommand(base.TestCase):
def test_execute(self):
DEC = DecisionEngineCommand()
self.assertRaises(NotImplementedError, DEC.execute)

View File

@@ -0,0 +1,30 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from watcher.decision_engine.api.messaging.event_consumer import EventConsumer
from watcher.tests import base
class TestEventConsumer(base.TestCase):
def test_set_messaging(self):
messaging = "test message"
EC = EventConsumer()
EC.set_messaging(messaging)
self.assertEqual(EC.messaging, messaging)
def test_execute(self):
EC = EventConsumer()
self.assertRaises(NotImplementedError, EC.execute, None, None, None)

View File

@@ -0,0 +1,24 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from watcher.decision_engine.api.planner.planner import Planner
from watcher.tests import base
class TestPlanner(base.TestCase):
def test_schedule(self):
pl = Planner()
self.assertRaises(NotImplementedError, pl.schedule, None, None, None)

View File

@@ -0,0 +1,26 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
'''from watcher.decision_engine.api.solution.solution import Solution
from watcher.decision_engine.framework.model.model_root import ModelRoot
from watcher.tests import base
class TestSolution(base.TestCase):
def test_get_model(self):
sol = Solution()
current_model =
sol.set_model(current_model)
'''

View File

@@ -0,0 +1,30 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from watcher.decision_engine.api.solution.solution import Solution as sol
from watcher.decision_engine.api.solution.solution_comparator import Solution
from watcher.tests import base
class test_Solution_Comparator(base.TestCase):
def test_compare(self):
sol1 = sol()
sol2 = sol()
solution_comparator = Solution()
self.assertRaises(NotImplementedError,
solution_comparator.compare,
sol1,
sol2)

View File

@@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from watcher.decision_engine.api.solution.solution_evaluator import \
SolutionEvaluator
from watcher.tests import base
class TestSolutionEvaluator(base.TestCase):
def test_evaluate(self):
SE = SolutionEvaluator()
self.assertRaises(NotImplementedError, SE.evaluate, None)

View File

@@ -0,0 +1,30 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from watcher.decision_engine.api.strategy.meta_action import MetaAction
from watcher.tests import base
class TestMetaAction(base.TestCase):
def test_get_priority(self):
MA = MetaAction()
MA.set_priority(3)
self.assertEqual(MA.get_priority(), 3)
def test_get_level(self):
MA = MetaAction()
MA.set_level(5)
self.assertEqual(MA.get_level(), 5)

View File

@@ -0,0 +1,24 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from watcher.decision_engine.api.strategy.selector import Selector
from watcher.tests import base
class TestSelector(base.TestCase):
def test_define_from_goal(self):
Sel = Selector()
self.assertRaises(NotImplementedError, Sel.define_from_goal, None)

View File

@@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from watcher.decision_engine.api.strategy.strategy_context import \
StrategyContext
from watcher.tests import base
class TestStrategyContext(base.TestCase):
def test_execute_strategy(self):
SC = StrategyContext()
self.assertRaises(NotImplementedError, SC.execute_strategy, None)

View File

@@ -1,103 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# FIXME(jed): remove this class due jenkins build failed
# The following librairies are removed from requirement.txt :
# - numpy
# - matplotlib
# These dependencies required a server x, jenkin's server has no
# server x
# import matplotlib.pyplot as plt
# import numpy as np
from watcher.decision_engine.strategies.basic_consolidation import \
BasicConsolidation
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
class PlotConsolidationBasic(object):
def plot(self, sercon, orign_model, solution):
pass
# cluster_size = len(orign_model._hypervisors)
# labels = []
# before_score = []
# after_score = []
# for hypevisor_id in orign_model.get_all_hypervisors():
# labels.append(hypevisor_id)
# hypevisor = orign_model.get_hypervisor_from_id(hypevisor_id)
# result_before = sercon.calculate_score_node(hypevisor,
# orign_model)
# result_after = sercon.calculate_score_node(hypevisor,
# solution.get_model())
# before_score.append(float(result_before * 100))
# if result_after == 0:
# result_after = 0
# after_score.append(float(result_after * 100))
#
# ind = np.arange(cluster_size) # the x locations for the groups
# width = 0.35 # the width of the bars
#
# fig, ax = plt.subplots()
#
# rects1 = ax.bar(ind, before_score, width, color='b')
#
# rects2 = ax.bar(ind + width, after_score, width, color='r')
#
# # add some text for labels, title and axes ticks
# ax.set_ylabel(
# 'Score of each hypervisor that represent their \
# utilization level')
# ax.set_title('Watcher Basic Server consolidation (efficiency ' + str(
# sercon.get_solution().get_efficiency()) + " %)")
#
# ax.set_xticks(ind + width)
# ax.set_xticklabels(labels)
# ax.set_ylim([0, 140])
# ax.legend((rects1[0], rects2[0]),
# ('Before Consolidation', 'After Consolidation'))
# def autolabel(rects):
# # attach some text labels
# for rect in rects:
# height = rect.get_height()
# ax.text(rect.get_x() + rect.get_width() / 2., 1.05 * height,
# '%d' % int(height),
# ha='center', va='bottom')
#
# autolabel(rects1)
# autolabel(rects2)
# plt.show()
cluster = FakerStateCollector()
metrics = FakerMetricsCollector()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
# try overbooking ? :) 150 % cpu
sercon.set_threshold_cores(1)
model_cluster = cluster.generate_scenario_1()
solution = sercon.execute(model_cluster)
plot = PlotConsolidationBasic()
plot.plot(sercon, cluster.generate_scenario_1(), solution)

View File

@@ -1,45 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
import time
from watcher.decision_engine.strategies.basic_consolidation import \
BasicConsolidation
from watcher.openstack.common import log
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
LOG = log.getLogger(__name__)
cfg.CONF.debug = True
log.setup('metering-controller')
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation("basic", "Basic offline consolidation")
sercon.set_metrics_resource_collector(metrics)
start_time = time.clock()
solution = sercon.execute(current_state_cluster.generate_scenario_1())
print(time.clock() - start_time, "seconds")
print(solution)
# planner = DefaultPlanner()
# planner.schedule(solution)

View File

@@ -1,43 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
import time
from watcher.decision_engine.strategies.basic_consolidation import \
BasicConsolidation
from watcher.openstack.common import log
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
LOG = log.getLogger(__name__)
# debug on
cfg.CONF.debug = True
log.setup('metering-controller')
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
start_time = time.clock()
solution = sercon.execute(current_state_cluster.generate_scenario_1())
print("duration =" + str((time.clock() - start_time)), "seconds")
LOG.debug(solution)

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,32 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from watcher.decision_engine.framework.meta_actions.migrate import Migrate
from watcher.decision_engine.framework.model.hypervisor import Hypervisor
from watcher.decision_engine.framework.model.vm import VM
from watcher.tests import base
class TestMigtrate(base.BaseTestCase):
def test_set_get_bandwidth(self):
vm = VM()
hyp_src = Hypervisor()
hyp_dst = Hypervisor()
mig = Migrate(vm, hyp_src, hyp_dst)
mig.set_bandwidth(2)
self.assertEqual(mig.get_bandwidth(), 2)

View File

@@ -0,0 +1,33 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from watcher.decision_engine.framework.model.diskInfo import DiskInfo
from watcher.tests import base
class TestDiskInfo(base.BaseTestCase):
def test_all(self):
disk_information = DiskInfo()
disk_information.set_size(1024)
self.assertEqual(disk_information.get_size(), 1024)
disk_information.set_scheduler = "scheduler_qcq"
disk_information.set_device_name("nom_qcq")
self.assertEqual(disk_information.get_device_name(), "nom_qcq")

View File

@@ -0,0 +1,106 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import uuid
from watcher.decision_engine.framework.model.hypervisor import Hypervisor
from watcher.decision_engine.framework.model.vm_state import VMState
from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
class TestMapping(base.BaseTestCase):
def test_get_node_from_vm(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
vms = model.get_all_vms()
keys = vms.keys()
vm = vms[keys[0]]
if vm.uuid != 'VM_0':
vm = vms[keys[1]]
node = model.mapping.get_node_from_vm(vm)
self.assertEqual(node.uuid, 'Node_0')
def test_get_node_from_vm_id(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
hyps = model.mapping.get_node_vms_from_id("BLABLABLA")
self.assertEqual(hyps.__len__(), 0)
def test_get_all_vms(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
vms = model.get_all_vms()
self.assertEqual(vms.__len__(), 2)
self.assertEqual(vms['VM_0'].state, VMState.ACTIVE.value)
self.assertEqual(vms['VM_0'].uuid, 'VM_0')
self.assertEqual(vms['VM_1'].state, VMState.ACTIVE.value)
self.assertEqual(vms['VM_1'].uuid, 'VM_1')
def test_get_mapping(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
mapping_vm = model.mapping.get_mapping_vm()
self.assertEqual(mapping_vm.__len__(), 2)
self.assertEqual(mapping_vm['VM_0'], 'Node_0')
self.assertEqual(mapping_vm['VM_1'], 'Node_1')
def test_migrate_vm(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
vms = model.get_all_vms()
keys = vms.keys()
vm0 = vms[keys[0]]
hyp0 = model.mapping.get_node_from_vm_id(vm0.uuid)
vm1 = vms[keys[1]]
hyp1 = model.mapping.get_node_from_vm_id(vm1.uuid)
self.assertEqual(model.mapping.migrate_vm(vm1, hyp1, hyp1), False)
self.assertEqual(model.mapping.migrate_vm(vm1, hyp0, hyp0), False)
self.assertEqual(model.mapping.migrate_vm(vm1, hyp1, hyp0), True)
self.assertEqual(model.mapping.migrate_vm(vm1, hyp0, hyp1), True)
def test_unmap_from_id_log_warning(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
vms = model.get_all_vms()
keys = vms.keys()
vm0 = vms[keys[0]]
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.mapping.unmap_from_id(hypervisor.uuid, vm0.uuid)
# self.assertEqual(len(model.mapping.get_node_vms_from_id(
# hypervisor.uuid)), 1)
def test_unmap_from_id(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
vms = model.get_all_vms()
keys = vms.keys()
vm0 = vms[keys[0]]
hyp0 = model.mapping.get_node_from_vm_id(vm0.uuid)
model.mapping.unmap_from_id(hyp0.uuid, vm0.uuid)
self.assertEqual(len(model.mapping.get_node_vms_from_id(
hyp0.uuid)), 0)

View File

@@ -0,0 +1,139 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import uuid
from watcher.common import exception
from watcher.common.exception import IllegalArgumentException
from watcher.decision_engine.framework.model.hypervisor import Hypervisor
from watcher.decision_engine.framework.model.hypervisor_state import \
HypervisorState
from watcher.decision_engine.framework.model.model_root import ModelRoot
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests import base
class TestModel(base.BaseTestCase):
def test_model(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_1()
self.assertEqual(len(model._hypervisors), 5)
self.assertEqual(len(model._vms), 35)
self.assertEqual(len(model.get_mapping().get_mapping()), 5)
def test_add_hypervisor(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
self.assertEqual(model.get_hypervisor_from_id(id), hypervisor)
def test_delete_hypervisor(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
self.assertEqual(model.get_hypervisor_from_id(id), hypervisor)
model.remove_hypervisor(hypervisor)
self.assertRaises(exception.HypervisorNotFound,
model.get_hypervisor_from_id, id)
def test_get_all_hypervisors(self):
model = ModelRoot()
for i in range(10):
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
all_hypervisors = model.get_all_hypervisors()
for id in all_hypervisors:
hyp = model.get_hypervisor_from_id(id)
model.assert_hypervisor(hyp)
def test_set_get_state_hypervisors(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
self.assertIsInstance(hypervisor.state, HypervisorState)
hyp = model.get_hypervisor_from_id(id)
hyp.state = HypervisorState.OFFLINE
self.assertIsInstance(hyp.state, HypervisorState)
# /watcher/decision_engine/framework/model/hypervisor.py
# set_state accept any char chain.
# verification (IsInstance) should be used in the function
# hyp.set_state('blablabla')
# self.assertEqual(hyp.get_state(), 'blablabla')
# self.assertIsInstance(hyp.get_state(), HypervisorState)
# def test_get_all_vms(self):
# model = ModelRoot()
# vms = model.get_all_vms()
# self.assert(len(model._vms))
def test_hypervisor_from_id_raise(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
id2 = str(uuid.uuid4())
self.assertRaises(exception.HypervisorNotFound,
model.get_hypervisor_from_id, id2)
def test_remove_hypervisor_raise(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
id2 = str(uuid.uuid4())
hypervisor2 = Hypervisor()
hypervisor2.uuid = id2
self.assertRaises(exception.HypervisorNotFound,
model.remove_hypervisor, hypervisor2)
def test_assert_hypervisor_raise(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.uuid = id
model.add_hypervisor(hypervisor)
self.assertRaises(IllegalArgumentException,
model.assert_hypervisor, "objet_qcq")
def test_vm_from_id_raise(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_1()
self.assertRaises(exception.VMNotFound,
model.get_vm_from_id, "valeur_qcq")
def test_assert_vm_raise(self):
model = ModelRoot()
self.assertRaises(IllegalArgumentException,
model.assert_vm, "valeur_qcq")

View File

@@ -0,0 +1,32 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from watcher.decision_engine.framework.model.named_element import NamedElement
from watcher.tests import base
class TestNamedElement(base.BaseTestCase):
def test_namedelement(self):
id = NamedElement()
id.uuid = "BLABLABLA"
self.assertEqual(id.uuid, "BLABLABLA")
def test_set_get_human_id(self):
id = NamedElement()
id.human_id = "BLABLABLA"
self.assertEqual(id.human_id, "BLABLABLA")

View File

@@ -0,0 +1,30 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from watcher.decision_engine.framework.model.vm import VM
from watcher.decision_engine.framework.model.vm_state import VMState
from watcher.tests import base
class TestVm(base.BaseTestCase):
def test_namedelement(self):
vm = VM()
vm.state = VMState.ACTIVE
self.assertEqual(vm.state, VMState.ACTIVE)
vm.human_id = "human_05"
self.assertEqual(vm.human_id, "human_05")

View File

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

View File

@@ -0,0 +1,32 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from watcher.decision_engine.framework.strategy.StrategyManagerImpl import \
StrategyContextImpl
from watcher.tests import base
class FakeStrategy(object):
def __init__(self):
self.name = "BALANCE_LOAD"
class TestStrategyContextImpl(base.BaseTestCase):
def test_add_remove_strategy(self):
strategy = FakeStrategy()
strategy_context = StrategyContextImpl()
strategy_context.add_strategy(strategy)
strategy_context.remove_strategy(strategy)

View File

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

View File

@@ -0,0 +1,24 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from watcher.decision_engine.framework.default_solution import DefaultSolution
from watcher.tests import base
class TestDefaultSolution(base.BaseTestCase):
def test_default_solution(self):
solution = DefaultSolution()
solution.add_change_request("BLA")
self.assertEqual(solution.meta_actions[0], "BLA")

View File

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

View File

@@ -0,0 +1,314 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import mock
from watcher.common import exception
from watcher.decision_engine.framework.meta_actions.hypervisor_state import \
ChangeHypervisorState
from watcher.decision_engine.framework.meta_actions.power_state import \
ChangePowerState
from watcher.decision_engine.framework.meta_actions.migrate import Migrate
from watcher.decision_engine.framework.model.model_root import ModelRoot
from watcher.decision_engine.strategies.basic_consolidation import \
BasicConsolidation
from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
# from watcher.tests.decision_engine.faker_metrics_collector import \
# FakerMetricsCollectorEmptyType
class TestBasicConsolidation(base.BaseTestCase):
# fake metrics
fake_metrics = FakerMetricsCollector()
# fake cluster
fake_cluster = FakerStateCollector()
def test_cluster_size(self):
size_cluster = len(
self.fake_cluster.generate_scenario_1().get_all_hypervisors())
size_cluster_assert = 5
self.assertEqual(size_cluster, size_cluster_assert)
def test_basic_consolidation_score_hypervisor(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
node_1_score = 0.01666666666666668
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_1"),
cluster), node_1_score)
node_2_score = 0.01666666666666668
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_2"),
cluster), node_2_score)
node_0_score = 0.01666666666666668
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_0"),
cluster), node_0_score)
def test_basic_consolidation_score_vm(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
vm_0 = cluster.get_vm_from_id("VM_0")
vm_0_score = 0.0
self.assertEqual(sercon.calculate_score_vm(vm_0, cluster), vm_0_score)
vm_1 = cluster.get_vm_from_id("VM_1")
vm_1_score = 0.0
self.assertEqual(sercon.calculate_score_vm(vm_1, cluster),
vm_1_score)
vm_2 = cluster.get_vm_from_id("VM_2")
vm_2_score = 0.0
self.assertEqual(sercon.calculate_score_vm(vm_2, cluster), vm_2_score)
vm_6 = cluster.get_vm_from_id("VM_6")
vm_6_score = 0.0
self.assertEqual(sercon.calculate_score_vm(vm_6, cluster), vm_6_score)
vm_7 = cluster.get_vm_from_id("VM_7")
vm_7_score = 0.0
self.assertEqual(sercon.calculate_score_vm(vm_7, cluster), vm_7_score)
def test_basic_consolidation_weight(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
vm_0 = cluster.get_vm_from_id("VM_0")
cores = 16
# 80 Go
disk = 80
# mem 8 Go
mem = 8
vm_0_weight_assert = 3.1999999999999997
self.assertEqual(sercon.calculate_weight(cluster, vm_0, cores, disk,
mem),
vm_0_weight_assert)
def test_calculate_migration_efficiency(self):
sercon = BasicConsolidation()
sercon.calculate_migration_efficiency()
def test_exception_model(self):
sercon = BasicConsolidation()
self.assertRaises(exception.ClusteStateNotDefined, sercon.execute,
None)
def test_exception_cluster_empty(self):
sercon = BasicConsolidation()
model = ModelRoot()
self.assertRaises(exception.ClusterEmpty, sercon.execute,
model)
def test_calculate_score_vm_raise_metric_collector(self):
sercon = BasicConsolidation()
self.assertRaises(exception.MetricCollectorNotDefined,
sercon.calculate_score_vm, "VM_1", None)
def test_calculate_score_vm_raise_cluster_state_not_found(self):
metrics = FakerMetricsCollector()
metrics.empty_one_metric("CPU_COMPUTE")
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
self.assertRaises(exception.ClusteStateNotDefined,
sercon.calculate_score_vm, "VM_1", None)
def test_print_utilization_raise_cluster_state_not_found(self):
sercon = BasicConsolidation()
self.assertRaises(exception.ClusteStateNotDefined,
sercon.print_utilization, None)
def check_migration(self, array, indice, vm, src, dest):
"""Helper to check migration
:param array:
:param indice:
:param vm:
:param src:
:param dest:
:return:
"""
self.assertEqual(array[indice].get_vm().uuid, vm)
self.assertEqual(array[indice].get_source_hypervisor().uuid, src)
self.assertEqual(array[indice].get_dest_hypervisor().uuid, dest)
self.assertEqual(array[indice].get_bandwidth(), 0)
array[indice].set_bandwidth(5)
self.assertEqual(array[indice].get_bandwidth(), 5)
def test_check_migration(self):
sercon = BasicConsolidation()
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
all_vms = model.get_all_vms()
all_hyps = model.get_all_hypervisors()
vm0 = all_vms[all_vms.keys()[0]]
hyp0 = all_hyps[all_hyps.keys()[0]]
sercon.check_migration(model, hyp0, hyp0, vm0)
def test_threshold(self):
sercon = BasicConsolidation()
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
all_hyps = model.get_all_hypervisors()
hyp0 = all_hyps[all_hyps.keys()[0]]
sercon.check_threshold(model, hyp0, 1000, 1000, 1000)
threshold_cores = sercon.get_threshold_cores()
sercon.set_threshold_cores(threshold_cores + 1)
self.assertEqual(sercon.get_threshold_cores(), threshold_cores + 1)
def test_number_of(self):
sercon = BasicConsolidation()
sercon.get_number_of_released_nodes()
sercon.get_number_of_migrations()
def test_calculate_score_node_raise_1(self):
sercon = BasicConsolidation()
metrics = FakerStateCollector()
model = metrics.generate_scenario_4_with_2_hypervisors()
all_hyps = model.get_all_hypervisors()
hyp0 = all_hyps[all_hyps.keys()[0]]
self.assertRaises(exception.MetricCollectorNotDefined,
sercon.calculate_score_node, hyp0, model)
def test_calculate_score_node_raise_cpu_compute(self):
metrics = FakerMetricsCollector()
metrics.empty_one_metric("CPU_COMPUTE")
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
current_state_cluster = FakerStateCollector()
model = current_state_cluster.generate_scenario_4_with_2_hypervisors()
all_hyps = model.get_all_hypervisors()
hyp0 = all_hyps[all_hyps.keys()[0]]
self.assertRaises(exception.NoDataFound,
sercon.calculate_score_node, hyp0, model)
"""
def test_calculate_score_node_raise_memory_compute(self):
metrics = FakerMetricsCollector()
metrics.empty_one_metric("MEM_COMPUTE")
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
current_state_cluster = FakerStateCollector()
model = current_state_cluster.generate_scenario_4_with_2_hypervisors()
all_hyps = model.get_all_hypervisors()
hyp0 = all_hyps[all_hyps.keys()[0]]
self.assertRaises(exception.NoDataFound,
sercon.calculate_score_node, hyp0, model)
def test_calculate_score_node_raise_disk_compute(self):
metrics = FakerMetricsCollector()
metrics.empty_one_metric("DISK_COMPUTE")
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
current_state_cluster = FakerStateCollector()
model = current_state_cluster.generate_scenario_4_with_2_hypervisors()
all_hyps = model.get_all_hypervisors()
hyp0 = all_hyps[all_hyps.keys()[0]]
self.assertRaises(exception.NoDataFound,
sercon.calculate_score_node, hyp0, model)
"""
def test_basic_consolidation_migration(self):
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(FakerMetricsCollector())
solution = None
solution = sercon.execute(FakerStateCollector().generate_scenario_1())
count_migration = 0
change_hypervisor_state = 0
change_power_state = 0
migrate = []
for action in solution.meta_actions:
if isinstance(action, Migrate):
count_migration += 1
migrate.append(action)
if isinstance(action, ChangeHypervisorState):
change_hypervisor_state += 1
if isinstance(action, ChangePowerState):
change_power_state += 1
# self.assertEqual(change_hypervisor_state, 1)
# self.assertEqual(count_migration, 2)
def test_execute_cluster_empty(self):
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation("sercon", "Basic offline consolidation")
sercon.set_metrics_resource_collector(metrics)
model = current_state_cluster.generate_random(0, 0)
self.assertRaises(exception.ClusterEmpty, sercon.execute, model)
def test_basic_consolidation_random(self):
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation("sercon", "Basic offline consolidation")
sercon.set_metrics_resource_collector(metrics)
solution = sercon.execute(
current_state_cluster.generate_random(25, 2))
solution.__str__()
count_migration = 0
change_hypervisor_state = 0
change_power_state = 0
migrate = []
for action in solution.meta_actions:
if isinstance(action, Migrate):
count_migration += 1
migrate.append(action)
if isinstance(action, ChangeHypervisorState):
change_hypervisor_state += 1
if isinstance(action, ChangePowerState):
change_power_state += 1
# calculate_weight
def test_execute_no_workload(self):
metrics = FakerMetricsCollector()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(metrics)
current_state_cluster = FakerStateCollector()
model = current_state_cluster.\
generate_scenario_5_with_1_hypervisor_no_vm()
with mock.patch.object(BasicConsolidation, 'calculate_weight') \
as mock_score_call:
mock_score_call.return_value = 0
solution = sercon.execute(model)
self.assertEqual(solution.efficiency, 100)

View File

@@ -0,0 +1,27 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from watcher.decision_engine.strategies.dummy_strategy import DummyStrategy
from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
class TestDummyStrategy(base.TestCase):
def test_dummy_strategy(self):
tactique = DummyStrategy("basic", "Basic offline consolidation")
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors()
tactique.execute(model)

View File

@@ -1,184 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from watcher.common import exception
from watcher.decision_engine.framework.meta_actions.hypervisor_state import \
ChangeHypervisorState
from watcher.decision_engine.framework.meta_actions.power_state import \
ChangePowerState
from watcher.decision_engine.framework.meta_actions.migrate import Migrate
from watcher.decision_engine.framework.model.model_root import ModelRoot
from watcher.decision_engine.strategies.basic_consolidation import \
BasicConsolidation
from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests.decision_engine.faker_metrics_collector import \
FakerMetricsCollector
class TestBasicConsolidation(base.BaseTestCase):
# fake metrics
fake_metrics = FakerMetricsCollector()
# fake cluster
fake_cluster = FakerStateCollector()
def test_cluster_size(self):
size_cluster = len(
self.fake_cluster.generate_scenario_1().get_all_hypervisors())
size_cluster_assert = 5
self.assertEqual(size_cluster, size_cluster_assert)
def test_basic_consolidation_score_hypervisor(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
node_1_score = 0.09862626262626262
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_1"),
cluster), node_1_score)
node_2_score = 0.29989898989898994
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_2"),
cluster), node_2_score)
node_0_score = 0.13967676767676765
self.assertEqual(
sercon.calculate_score_node(
cluster.get_hypervisor_from_id("Node_0"),
cluster), node_0_score)
def test_basic_consolidation_score_vm(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
vm_0 = cluster.get_vm_from_id("VM_0")
vm_0_score = 0.6
self.assertEqual(sercon.calculate_score_vm(vm_0, cluster), vm_0_score)
vm_1 = cluster.get_vm_from_id("VM_1")
vm_1_score = 1.0999999999999999
self.assertEqual(sercon.calculate_score_vm(vm_1, cluster),
vm_1_score)
vm_2 = cluster.get_vm_from_id("VM_2")
vm_2_score = 1.2
self.assertEqual(sercon.calculate_score_vm(vm_2, cluster), vm_2_score)
def test_basic_consolidation_weight(self):
cluster = self.fake_cluster.generate_scenario_1()
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
vm_0 = cluster.get_vm_from_id("VM_0")
cores = 16
# 80 Go
disk = 80
# mem 8 Go
mem = 8
vm_0_weight_assert = 3.1999999999999997
self.assertEqual(sercon.calculate_weight(cluster, vm_0, cores, disk,
mem),
vm_0_weight_assert)
def test_basic_consolidation_efficiency(self):
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
efficient_assert = 100
solution = sercon.execute(self.fake_cluster.generate_scenario_1())
self.assertEqual(solution.get_efficiency(), efficient_assert)
def test_exception_model(self):
sercon = BasicConsolidation()
self.assertRaises(exception.ClusteStateNotDefined, sercon.execute,
None)
def test_exception_cluster_empty(self):
sercon = BasicConsolidation()
model = ModelRoot()
self.assertRaises(exception.ClusterEmpty, sercon.execute,
model)
def test_exception_metric_collector(self):
sercon = BasicConsolidation()
self.assertRaises(exception.MetricCollectorNotDefined,
sercon.calculate_score_vm, "VM_1", None)
def check_migration(self, array, indice, vm, src, dest):
"""Helper to check migration
:param array:
:param indice:
:param vm:
:param src:
:param dest:
:return:
"""
self.assertEqual(array[indice].get_vm().get_uuid(), vm)
self.assertEqual(array[indice].get_source_hypervisor().get_uuid(), src)
self.assertEqual(array[indice].get_dest_hypervisor().get_uuid(), dest)
def test_basic_consolidation_migration(self):
sercon = BasicConsolidation()
sercon.set_metrics_resource_collector(self.fake_metrics)
solution = sercon.execute(self.fake_cluster.generate_scenario_1())
count_migration = 0
change_hypervisor_state = 0
change_power_state = 0
migrate = []
for action in solution.meta_actions:
if isinstance(action, Migrate):
count_migration += 1
migrate.append(action)
if isinstance(action, ChangeHypervisorState):
change_hypervisor_state += 1
if isinstance(action, ChangePowerState):
change_power_state += 1
self.assertEqual(change_hypervisor_state, 3)
self.assertEqual(count_migration, 3)
# check migration
self.check_migration(migrate, 0, "VM_7", "Node_4", "Node_2")
self.check_migration(migrate, 1, "VM_6", "Node_3", "Node_0")
self.check_migration(migrate, 2, "VM_2", "Node_1", "Node_0")
def test_basic_consolidation_random(self):
metrics = FakerMetricsCollector()
current_state_cluster = FakerStateCollector()
sercon = BasicConsolidation("sercon", "Basic offline consolidation")
sercon.set_metrics_resource_collector(metrics)
solution = sercon.execute(
current_state_cluster.generate_random(25, 2))
count_migration = 0
change_hypervisor_state = 0
change_power_state = 0
migrate = []
for action in solution.meta_actions:
if isinstance(action, Migrate):
count_migration += 1
migrate.append(action)
if isinstance(action, ChangeHypervisorState):
change_hypervisor_state += 1
if isinstance(action, ChangePowerState):
change_power_state += 1

View File

@@ -1,11 +1,13 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,6 +15,7 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from watcher.tests import base

View File

@@ -1,54 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import uuid
from watcher.common import exception
from watcher.decision_engine.framework.model.hypervisor import Hypervisor
from watcher.decision_engine.framework.model.model_root import ModelRoot
from watcher.tests.decision_engine.faker_cluster_state import \
FakerStateCollector
from watcher.tests import base
class TestModel(base.BaseTestCase):
def test_model(self):
fake_cluster = FakerStateCollector()
model = fake_cluster.generate_scenario_1()
self.assertEqual(len(model._hypervisors), 5)
self.assertEqual(len(model._vms), 35)
self.assertEqual(len(model.get_mapping().get_mapping()), 5)
def test_add_hypervisor(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.set_uuid(id)
model.add_hypervisor(hypervisor)
self.assertEqual(model.get_hypervisor_from_id(id), hypervisor)
def test_delete_hypervisor(self):
model = ModelRoot()
id = str(uuid.uuid4())
hypervisor = Hypervisor()
hypervisor.set_uuid(id)
model.add_hypervisor(hypervisor)
self.assertEqual(model.get_hypervisor_from_id(id), hypervisor)
model.remove_hypervisor(hypervisor)
self.assertRaises(exception.HypervisorNotFound,
model.get_hypervisor_from_id, id)

View File

@@ -1,11 +1,13 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,6 +15,7 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from watcher.tests import base

View File

@@ -1,151 +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 concurrent.futures import ThreadPoolExecutor
from keystoneclient import session
from keystoneclient.auth.identity import v3
import cinderclient.v2.client as ciclient
import glanceclient.v2.client as glclient
import keystoneclient.v3.client as ksclient
import neutronclient.neutron.client as netclient
import novaclient.v2.client as nvclient
from watcher.common.utils import CONF
from oslo_config import cfg
from watcher.applier.framework.command.migrate_command import MigrateCommand
from watcher.applier.framework.command.wrapper.nova_wrapper import NovaWrapper
from watcher.decision_engine.framework.default_planner import Primitives
from watcher.openstack.common import log
import ceilometerclient.v2 as c_client
cfg.CONF.debug = True
log.setup('metering-controller')
cfg.CONF.import_opt('auth_uri', 'keystoneclient.middleware.auth_token',
group='keystone_authtoken')
cfg.CONF.import_opt('admin_user', 'keystoneclient.middleware.auth_token',
group='keystone_authtoken')
cfg.CONF.import_opt('admin_password', 'keystoneclient.middleware.auth_token',
group='keystone_authtoken')
cfg.CONF.import_opt('admin_tenant_name',
'keystoneclient.middleware.auth_token',
group='keystone_authtoken')
cfg.CONF.keystone_authtoken.auth_uri = "http://10.50.0.105:5000/v3/"
cfg.CONF.keystone_authtoken.admin_user = "watcher"
cfg.CONF.keystone_authtoken.admin_password = "watcher"
cfg.CONF.keystone_authtoken.admin_tenant_name = "services"
def make_query(user_id=None, tenant_id=None, resource_id=None,
user_ids=None, tenant_ids=None, resource_ids=None):
user_ids = user_ids or []
tenant_ids = tenant_ids or []
resource_ids = resource_ids or []
query = []
if user_id:
user_ids = [user_id]
for u_id in user_ids:
query.append({"field": "user_id", "op": "eq", "value": u_id})
if tenant_id:
tenant_ids = [tenant_id]
for t_id in tenant_ids:
query.append({"field": "project_id", "op": "eq", "value": t_id})
if resource_id:
resource_ids = [resource_id]
for r_id in resource_ids:
query.append({"field": "resource_id", "op": "eq", "value": r_id})
return query
# nova-manage service enable
--host='ldev-indeedsrv005' --service='nova-compute'
def create(wrapper, id, hypervisorid):
print("create instance VM_{0} on {1}".format(str(id), str(hypervisorid)))
try:
for image in glance.images.list(name='Cirros'):
id_image = image.id
vm = wrapper.create_instance(hypervisor_id=hypervisorid,
inst_name="VM_" + str(id),
keypair_name='admin',
image_id=id_image,
create_new_floating_ip=True,
flavor_name='m1.medium')
print(vm)
except Exception as e:
print(unicode(e))
def purge(nova, wrapper):
print("Purging the cluster")
instances = nova.servers.list()
for instance in instances:
wrapper.delete_instance(instance.id)
try:
executor = ThreadPoolExecutor(max_workers=3)
creds = \
{'auth_url': CONF.keystone_authtoken.auth_uri,
'username': CONF.keystone_authtoken.admin_user,
'password': CONF.keystone_authtoken.admin_password,
'project_name': CONF.keystone_authtoken.admin_tenant_name,
'user_domain_name': "default",
'project_domain_name': "default"}
auth = v3.Password(auth_url=creds['auth_url'],
username=creds['username'],
password=creds['password'],
project_name=creds['project_name'],
user_domain_name=creds[
'user_domain_name'],
project_domain_name=creds[
'project_domain_name'])
sess = session.Session(auth=auth)
nova = nvclient.Client("3", session=sess)
neutron = netclient.Client('2.0', session=sess)
neutron.format = 'json'
keystone = ksclient.Client(**creds)
glance_endpoint = keystone. \
service_catalog.url_for(service_type='image',
endpoint_type='publicURL')
glance = glclient.Client(glance_endpoint,
token=keystone.auth_token)
wrapper = NovaWrapper(creds, session=sess)
wrapper.live_migrate_instance(
instance_id="b2aca823-a621-4235-9d56-9f0f75955dc1",
dest_hostname="ldev-indeedsrv006", block_migration=True)
nova-manage service enable --host='ldev-indeedsrv005' \
--service='nova-compute'
nova-manage service enable --host='ldev-indeedsrv006' \
--service='nova-compute'
except Exception as e:
print("rollback " + str(e))
"""