Compare commits

...

10 Commits

Author SHA1 Message Date
Vincent Françoise
1c38637dff Fixed issue on compute nodes iteration
In this changeset, I fixed the issue with the basic server
consolidation strategy to now loop over all compute nodes
as expected instead of stopping after the first one.

Change-Id: If594f0df41e39dfb0ef8f0fce41822018490c4ec
Closes-bug: #1548874
2016-10-24 20:11:19 +00:00
Vincent Françoise
1eb2b517ef Refactored Tests to load scenarios from file
In this changeset, I simplified the logic that is used to create
cluster data model scenarios.

Change-Id: Ia6e138d9897190d3207a70485dc62ccc34087686
2016-10-21 17:32:42 +02:00
licanwei
3e030618fa 'tox -e py27' failed
cfg.CONF.debug should be set False as default,
If it's True, some unittests can't pass.

Change-Id: Ib098250af3aec48aa9d9152e20c80460f3bd641e
Closes-Bug: #1625560
2016-10-20 07:31:51 +00:00
Antoine Cabot
f823345424 Update Watcher description
This change-set update Watcher description
as it is used in the ML to announce each
new release.

Change-Id: I6318107c3e3322a3ef734e90c9e3e0176967ceaf
(cherry picked from commit 8cf233ab03)
2016-09-29 09:02:51 +00:00
Vincent Françoise
19fdd1557e Doc updates
Updated inconsistent docs.

Change-Id: I4be05f662fee6ebdf721ac93dd97611b5a686273
2016-09-28 15:29:30 +00:00
Jenkins
641989b424 Merge "Add constraint target to tox.ini and remove 1 dep" into stable/newton 2016-09-26 09:41:34 +00:00
Vincent Françoise
8814c09087 Fixed GMR configuration issue
GMR was ignoring the config because the conf wasn't passed when
starting any of the Watcher services. This changeset fixes this issue.

Change-Id: If386c5f0459c4278a2a56c8c3185fcdafce673a0
2016-09-21 13:49:39 +00:00
David TARDIVEL
eb4f46b703 Add constraint target to tox.ini and remove 1 dep
This adds a pip install command to tox.ini that is only used when the
tox env is passed with the 'constraints' factor appended onto it.
As such this will not effect developer workflows or current unit tests.

The initial use of this will be in a non-voting job, to verify that the
constrained checks with tox are stable.  DevStack is already running
constrained jobs, as such problems are no expected.

To run a tox with pip using constraints on a developer system a
developer should run the desired tox environment with -constraints.
For example: $(tox -epy27-constraints)
Pip will pull the current version of the upper-constraints.txt file down
from the git.openstack.org, however this method can be overriden to use
a local file setting the environment variable "UPPER_CONSTRAINTS_FILE"
to the local path or a different URL, it is passed directly to pip.

This is currently not enabled in the default tox run, however it is
possible to enable it as a default by adding it to 'envlist' in tox.ini

This also removes requirements.txt from tox.ini deps
This is redundant, per lifeless email:
http://lists.openstack.org/pipermail/openstack-dev/2015-July/069663.html

Change-Id: I79c0ceb46fc980840a8baf5fa4a303bb450bfbec
2016-09-21 12:03:50 +02:00
OpenStack Proposal Bot
2f33dd10c0 Updated from global requirements
Change-Id: Id918c0fd8f2a567f57d3849683282aad5c1c68f8
2016-09-20 13:17:37 +00:00
Thierry Carrez
1a197ab801 Update .gitreview for stable/newton
Change-Id: I410924887299ae8d32247ff1f798ac059f8d5dbd
2016-09-16 15:02:51 +02:00
45 changed files with 695 additions and 975 deletions

View File

@@ -2,3 +2,4 @@
host=review.openstack.org
port=29418
project=openstack/watcher.git
defaultbranch=stable/newton

View File

@@ -10,10 +10,8 @@ Watcher
OpenStack Watcher provides a flexible and scalable resource optimization
service for multi-tenant OpenStack-based clouds.
Watcher provides a complete optimization loop-including everything from a
metrics receiver, complex event processor and profiler, optimization processor
and an action plan applier. This provides a robust framework to realize a wide
range of cloud optimization goals, including the reduction of data center
Watcher provides a robust framework to realize a wide range of cloud
optimization goals, including the reduction of data center
operating costs, increased system performance via intelligent virtual machine
migration, increased energy efficiency-and more!

View File

@@ -171,12 +171,12 @@ This component is responsible for computing a set of potential optimization
:ref:`Actions <action_definition>` in order to fulfill
the :ref:`Goal <goal_definition>` of an :ref:`Audit <audit_definition>`.
It first reads the parameters of the :ref:`Audit <audit_definition>` from the
associated :ref:`Audit Template <audit_template_definition>` and knows the
:ref:`Goal <goal_definition>` to achieve.
It first reads the parameters of the :ref:`Audit <audit_definition>` to know
the :ref:`Goal <goal_definition>` to achieve.
It then selects the most appropriate :ref:`Strategy <strategy_definition>`
from the list of available strategies achieving this goal.
Unless specified, it then selects the most appropriate :ref:`strategy
<strategy_definition>` from the list of available strategies achieving this
goal.
The :ref:`Strategy <strategy_definition>` is then dynamically loaded (via
`stevedore <http://docs.openstack.org/developer/stevedore/>`_). The
@@ -290,7 +290,7 @@ the Audit parameters from the
:ref:`Watcher Database <watcher_database_definition>`. It instantiates the
appropriate :ref:`strategy <strategy_definition>` (using entry points)
given both the :ref:`goal <goal_definition>` and the strategy associated to the
parent :ref:`audit template <audit_template_definition>` of the :ref:`Audit
parent :ref:`audit template <audit_template_definition>` of the :ref:`audit
<audit_definition>`. If no strategy is associated to the audit template, the
strategy is dynamically selected by the Decision Engine.

View File

@@ -5,11 +5,12 @@
hide methods
hide stereotypes
table(goal) {
table(goals) {
primary_key(id: Integer)
uuid : String[36]
name : String[63]
display_name : String[63]
efficacy_specification : JSONEncodedList, nullable
created_at : DateTime
updated_at : DateTime
@@ -18,12 +19,13 @@ table(goal) {
}
table(strategy) {
table(strategies) {
primary_key(id: Integer)
foreign_key(goal_id : Integer)
uuid : String[36]
name : String[63]
display_name : String[63]
parameters_spec : JSONEncodedDict, nullable
created_at : DateTime
updated_at : DateTime
@@ -32,7 +34,7 @@ table(strategy) {
}
table(audit_template) {
table(audit_templates) {
primary_key(id: Integer)
foreign_key("goal_id : Integer")
foreign_key("strategy_id : Integer, nullable")
@@ -50,14 +52,17 @@ table(audit_template) {
}
table(audit) {
table(audits) {
primary_key(id: Integer)
foreign_key("audit_template_id : Integer")
foreign_key("goal_id : Integer")
foreign_key("strategy_id : Integer, nullable")
uuid : String[36]
audit_type : String[20]
state : String[20], nullable
deadline :DateTime, nullable
deadline : DateTime, nullable
interval : Integer, nullable
parameters : JSONEncodedDict, nullable
host_aggregate : Integer, nullable
created_at : DateTime
updated_at : DateTime
@@ -66,9 +71,10 @@ table(audit) {
}
table(action_plan) {
table(action_plans) {
primary_key(id: Integer)
foreign_key("audit_id : Integer, nullable")
foreign_key("strategy_id : Integer")
uuid : String[36]
first_action_id : Integer
state : String[20], nullable
@@ -81,7 +87,7 @@ table(action_plan) {
}
table(action) {
table(actions) {
primary_key(id: Integer)
foreign_key("action_plan_id : Integer")
uuid : String[36]
@@ -97,7 +103,7 @@ table(action) {
}
table(efficacy_indicator) {
table(efficacy_indicators) {
primary_key(id: Integer)
foreign_key("action_plan_id : Integer")
uuid : String[36]
@@ -112,12 +118,27 @@ table(efficacy_indicator) {
deleted : Integer
}
"goal" <.. "strategy" : Foreign Key
"goal" <.. "audit_template" : Foreign Key
"strategy" <.. "audit_template" : Foreign Key
"audit_template" <.. "audit" : Foreign Key
"action_plan" <.. "action" : Foreign Key
"action_plan" <.. "efficacy_indicator" : Foreign Key
"audit" <.. "action_plan" : Foreign Key
table(scoring_engines) {
primary_key(id: Integer)
uuid : String[36]
name : String[63]
description : String[255], nullable
metainfo : Text, nullable
created_at : DateTime
updated_at : DateTime
deleted_at : DateTime
deleted : Integer
}
"goals" <.. "strategies" : Foreign Key
"goals" <.. "audit_templates" : Foreign Key
"strategies" <.. "audit_templates" : Foreign Key
"goals" <.. "audits" : Foreign Key
"strategies" <.. "audits" : Foreign Key
"action_plans" <.. "actions" : Foreign Key
"action_plans" <.. "efficacy_indicators" : Foreign Key
"strategies" <.. "action_plans" : Foreign Key
"audits" <.. "action_plans" : Foreign Key
@enduml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -12,7 +12,7 @@ oslo.concurrency>=3.8.0 # Apache-2.0
oslo.cache>=1.5.0 # Apache-2.0
oslo.config>=3.14.0 # Apache-2.0
oslo.context>=2.9.0 # Apache-2.0
oslo.db>=4.10.0 # Apache-2.0
oslo.db!=4.13.1,!=4.13.2,>=4.10.0 # Apache-2.0
oslo.i18n>=2.1.0 # Apache-2.0
oslo.log>=1.14.0 # Apache-2.0
oslo.messaging>=5.2.0 # Apache-2.0

View File

@@ -1,6 +1,6 @@
[metadata]
name = python-watcher
summary = Watcher takes advantage of CEP and ML algorithms/metaheuristics to improve physical resources usage through better VM placement. Watcher can improve your cloud optimization by reducing energy footprint and increasing profits.
summary = OpenStack Watcher provides a flexible and scalable resource optimization service for multi-tenant OpenStack-based clouds.
description-file =
README.rst
author = OpenStack

13
tox.ini
View File

@@ -1,16 +1,17 @@
[tox]
minversion = 1.6
minversion = 1.8
envlist = py35,py34,py27,pep8
skipsdist = True
[testenv]
usedevelop = True
whitelist_externals = find
install_command = pip install -U {opts} {packages}
install_command =
constraints: pip install -U --force-reinstall -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=stable/newton} {opts} {packages}
pip install -U {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
deps = -r{toxinidir}/test-requirements.txt
commands =
find . -type f -name "*.pyc" -delete
find . -type d -name "__pycache__" -delete
@@ -20,7 +21,7 @@ commands =
commands =
doc8 doc/source/ CONTRIBUTING.rst HACKING.rst README.rst
flake8
bandit -r watcher -x tests -n5 -ll
bandit -r watcher -x tests -n5 -ll -s B320
[testenv:venv]
setenv = PYTHONHASHSEED=0
@@ -66,4 +67,4 @@ commands = sphinx-build -a -W -E -d releasenotes/build/doctrees -b html releasen
[testenv:bandit]
deps = -r{toxinidir}/test-requirements.txt
commands = bandit -r watcher -x tests -n5 -ll
commands = bandit -r watcher -x tests -n5 -ll -s B320

View File

@@ -272,4 +272,4 @@ def prepare_service(argv=(), conf=cfg.CONF):
conf.log_opt_values(LOG, logging.DEBUG)
gmr.TextGuruMeditation.register_section(_('Plugins'), opts.show_plugins)
gmr.TextGuruMeditation.setup_autorun(version)
gmr.TextGuruMeditation.setup_autorun(version, conf=conf)

View File

@@ -223,3 +223,53 @@ class ModelRoot(object):
root.append(self._build_instance_element(instance))
return etree.tostring(root, pretty_print=True).decode('utf-8')
@classmethod
def from_xml(cls, data):
model = cls()
root = etree.fromstring(data)
mem = element.Resource(element.ResourceType.memory)
num_cores = element.Resource(element.ResourceType.cpu_cores)
disk = element.Resource(element.ResourceType.disk)
disk_capacity = element.Resource(element.ResourceType.disk_capacity)
model.create_resource(mem)
model.create_resource(num_cores)
model.create_resource(disk)
model.create_resource(disk_capacity)
for cn in root.findall('.//ComputeNode'):
node = element.ComputeNode(cn.get('id'))
node.uuid = cn.get('uuid')
node.hostname = cn.get('hostname')
# set capacity
mem.set_capacity(node, int(cn.get(str(mem.name))))
disk.set_capacity(node, int(cn.get(str(disk.name))))
disk_capacity.set_capacity(
node, int(cn.get(str(disk_capacity.name))))
num_cores.set_capacity(node, int(cn.get(str(num_cores.name))))
node.state = cn.get('state')
node.status = cn.get('status')
model.add_node(node)
for inst in root.findall('.//Instance'):
instance = element.Instance()
instance.uuid = inst.get('uuid')
instance.state = inst.get('state')
mem.set_capacity(instance, int(inst.get(str(mem.name))))
disk.set_capacity(instance, int(inst.get(str(disk.name))))
disk_capacity.set_capacity(
instance, int(inst.get(str(disk_capacity.name))))
num_cores.set_capacity(
instance, int(inst.get(str(num_cores.name))))
parent = inst.getparent()
if parent.tag == 'ComputeNode':
node = model.get_node_by_uuid(parent.get('uuid'))
model.map_instance(instance, node)
else:
model.add_instance(instance)
return model

View File

@@ -81,8 +81,6 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy):
self.number_of_released_nodes = 0
# set default value for the number of migrations
self.number_of_migrations = 0
# set default value for number of allowed migration attempts
self.migration_attempts = 0
# set default value for the efficacy
self.efficacy = 100
@@ -94,21 +92,14 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy):
self.threshold_disk = 1
self.threshold_cores = 1
# TODO(jed): target efficacy
self.target_efficacy = 60
# TODO(jed): weight
self.weight_cpu = 1
self.weight_mem = 1
self.weight_disk = 1
# TODO(jed): bound migration attempts (80 %)
self.bound_migration = 0.80
@classmethod
def get_name(cls):
return "basic"
@property
def migration_attempts(self):
return self.input_parameters.get('migration_attempts', 0)
@classmethod
def get_display_name(cls):
return _("Basic offline consolidation")
@@ -117,6 +108,22 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy):
def get_translatable_display_name(cls):
return "Basic offline consolidation"
@classmethod
def get_schema(cls):
# Mandatory default setting for each element
return {
"properties": {
"migration_attempts": {
"description": "Maximum number of combinations to be "
"tried by the strategy while searching "
"for potential candidates. To remove the "
"limit, set it to 0 (by default)",
"type": "number",
"default": 0
},
},
}
@property
def ceilometer(self):
if self._ceilometer is None:
@@ -127,13 +134,6 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy):
def ceilometer(self, ceilometer):
self._ceilometer = ceilometer
def compute_attempts(self, size_cluster):
"""Upper bound of the number of migration
:param size_cluster: The size of the cluster
"""
self.migration_attempts = size_cluster * self.bound_migration
def check_migration(self, source_node, destination_node,
instance_to_migrate):
"""Check if the migration is possible
@@ -199,16 +199,6 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy):
disk_capacity >= total_disk * self.threshold_disk and
memory_capacity >= total_mem * self.threshold_mem)
def get_allowed_migration_attempts(self):
"""Allowed migration
Maximum allowed number of migrations this allows us to fix
the upper bound of the number of migrations.
:return:
"""
return self.migration_attempts
def calculate_weight(self, compute_resource, total_cores_used,
total_disk_used, total_memory_used):
"""Calculate weight of every resource
@@ -331,8 +321,9 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy):
resource_id=resource_id,
input_parameters=parameters)
def score_of_nodes(self, score):
def compute_score_of_nodes(self):
"""Calculate score of nodes based on load by VMs"""
score = []
for node in self.compute_model.get_all_compute_nodes().values():
count = self.compute_model.mapping.get_node_instances(node)
if len(count) > 0:
@@ -344,9 +335,9 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy):
score.append((node.uuid, result))
return score
def node_and_instance_score(self, sorted_score, score):
def node_and_instance_score(self, sorted_scores):
"""Get List of VMs from node"""
node_to_release = sorted_score[len(score) - 1][0]
node_to_release = sorted_scores[len(sorted_scores) - 1][0]
instances_to_migrate = self.compute_model.mapping.get_node_instances(
self.compute_model.get_node_by_uuid(node_to_release))
@@ -409,20 +400,14 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy):
if not self.compute_model:
raise exception.ClusterStateNotDefined()
if len(self.compute_model.get_all_compute_nodes()) == 0:
raise exception.ClusterEmpty()
LOG.debug(self.compute_model.to_string())
def do_execute(self):
# todo(jed) clone model
self.efficacy = 100
unsuccessful_migration = 0
first_migration = True
size_cluster = len(self.compute_model.get_all_compute_nodes())
if size_cluster == 0:
raise exception.ClusterEmpty()
self.compute_attempts(size_cluster)
for node_uuid, node in self.compute_model.get_all_compute_nodes(
).items():
node_instances = self.compute_model.mapping.get_node_instances(
@@ -432,44 +417,44 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy):
self.add_change_service_state(
node_uuid, element.ServiceState.DISABLED.value)
while self.get_allowed_migration_attempts() >= unsuccessful_migration:
if not first_migration:
self.efficacy = self.calculate_migration_efficacy()
if self.efficacy < float(self.target_efficacy):
break
first_migration = False
score = []
score = self.score_of_nodes(score)
# Sort compute nodes by Score decreasing
sorted_score = sorted(score, reverse=True, key=lambda x: (x[1]))
LOG.debug("Compute node(s) BFD %s", sorted_score)
# Get Node to be released
if len(score) == 0:
LOG.warning(_LW(
"The workloads of the compute nodes"
" of the cluster is zero"))
break
scores = self.compute_score_of_nodes()
# Sort compute nodes by Score decreasing
sorted_scores = sorted(scores, reverse=True, key=lambda x: (x[1]))
LOG.debug("Compute node(s) BFD %s", sorted_scores)
# Get Node to be released
if len(scores) == 0:
LOG.warning(_LW(
"The workloads of the compute nodes"
" of the cluster is zero"))
return
while sorted_scores and (
not self.migration_attempts or
self.migration_attempts >= unsuccessful_migration):
node_to_release, instance_score = self.node_and_instance_score(
sorted_score, score)
sorted_scores)
# Sort instances by Score
sorted_instances = sorted(
instance_score, reverse=True, key=lambda x: (x[1]))
# BFD: Best Fit Decrease
LOG.debug("VM(s) BFD %s", sorted_instances)
LOG.debug("Instance(s) BFD %s", sorted_instances)
migrations = self.calculate_num_migrations(
sorted_instances, node_to_release, sorted_score)
sorted_instances, node_to_release, sorted_scores)
unsuccessful_migration = self.unsuccessful_migration_actualization(
migrations, unsuccessful_migration)
if not migrations:
# We don't have any possible migrations to perform on this node
# so we discard the node so we can try to migrate instances
# from the next one in the list
sorted_scores.pop()
infos = {
"number_of_migrations": self.number_of_migrations,
"number_of_nodes_released": self.number_of_released_nodes,
"released_compute_nodes_count": self.number_of_released_nodes,
"instance_migrations_count": self.number_of_migrations,
"efficacy": self.efficacy
}
LOG.debug(infos)

View File

@@ -120,6 +120,7 @@ class TestNoExceptionTracebackHook(base.FunctionalTest):
p = mock.patch.object(root.Root, 'convert')
self.root_convert_mock = p.start()
self.addCleanup(p.stop)
cfg.CONF.set_override('debug', False, enforce_type=True)
def test_hook_exception_success(self):
self.root_convert_mock.side_effect = Exception(self.MSG_WITH_TRACE)

View File

@@ -25,8 +25,7 @@ from watcher.decision_engine.messaging import events
from watcher.decision_engine.model.collector import manager
from watcher.objects import audit as audit_objects
from watcher.tests.db import base
from watcher.tests.decision_engine.strategy.strategies import \
faker_cluster_state as faker
from watcher.tests.decision_engine.model import faker_cluster_state as faker
from watcher.tests.objects import utils as obj_utils

View File

@@ -23,8 +23,7 @@ from watcher.common import exception
from watcher.decision_engine.loading import default as default_loading
from watcher.tests import base
from watcher.tests import conf_fixture
from watcher.tests.decision_engine.strategy.strategies import \
faker_cluster_state
from watcher.tests.decision_engine.model import faker_cluster_state
class TestClusterDataModelCollectorLoader(base.TestCase):

View File

@@ -20,8 +20,7 @@ from watcher.decision_engine.audit import oneshot as oneshot_handler
from watcher.decision_engine.messaging import audit_endpoint
from watcher.decision_engine.model.collector import manager
from watcher.tests.db import base
from watcher.tests.decision_engine.strategy.strategies \
import faker_cluster_state
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.objects import utils as obj_utils

View File

@@ -0,0 +1,47 @@
<ModelRoot>
<ComputeNode human_id="" uuid="Node_0" status="enabled" state="up" id="0" hostname="hostname_0" ResourceType.cpu_cores="40" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="132">
<Instance state="active" human_id="" uuid="INSTANCE_0" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_1" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode human_id="" uuid="Node_1" status="enabled" state="up" id="1" hostname="hostname_1" ResourceType.cpu_cores="40" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="132">
<Instance state="active" human_id="" uuid="INSTANCE_2" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode human_id="" uuid="Node_2" status="enabled" state="up" id="2" hostname="hostname_2" ResourceType.cpu_cores="40" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="132">
<Instance state="active" human_id="" uuid="INSTANCE_3" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_4" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_5" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode human_id="" uuid="Node_3" status="enabled" state="up" id="3" hostname="hostname_3" ResourceType.cpu_cores="40" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="132">
<Instance state="active" human_id="" uuid="INSTANCE_6" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode human_id="" uuid="Node_4" status="enabled" state="up" id="4" hostname="hostname_4" ResourceType.cpu_cores="40" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="132">
<Instance state="active" human_id="" uuid="INSTANCE_7" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<Instance state="active" human_id="" uuid="INSTANCE_10" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_11" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_12" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_13" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_14" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_15" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_16" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_17" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_18" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_19" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_20" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_21" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_22" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_23" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_24" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_25" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_26" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_27" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_28" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_29" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_30" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_31" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_32" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_33" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_34" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_8" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_9" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ModelRoot>

View File

@@ -0,0 +1,8 @@
<ModelRoot>
<ComputeNode hostname="hostname_0" uuid="Node_0" id="0" state="enabled" human_id="" status="enabled" ResourceType.cpu_cores="40" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_0" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode hostname="hostname_1" uuid="Node_1" id="1" state="enabled" human_id="" status="enabled" ResourceType.cpu_cores="40" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_1" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
</ModelRoot>

View File

@@ -0,0 +1,13 @@
<ModelRoot>
<ComputeNode hostname="hostname_0" uuid="Node_0" id="0" state="up" human_id="" status="enabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_0" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_1" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_2" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_3" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_4" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_5" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode hostname="hostname_1" uuid="Node_1" id="1" state="up" human_id="" status="enabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64"/>
<ComputeNode hostname="hostname_2" uuid="Node_2" id="2" state="up" human_id="" status="enabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64"/>
<ComputeNode hostname="hostname_3" uuid="Node_3" id="3" state="up" human_id="" status="enabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64"/>
</ModelRoot>

View File

@@ -0,0 +1,8 @@
<ModelRoot>
<ComputeNode human_id="" uuid="Node_0" status="enabled" state="up" id="0" hostname="hostname_0" ResourceType.cpu_cores="40" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="132">
<Instance state="active" human_id="" uuid="73b09e16-35b7-4922-804e-e8f5d9b740fc" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode human_id="" uuid="Node_1" status="enabled" state="up" id="1" hostname="hostname_1" ResourceType.cpu_cores="40" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="132">
<Instance state="active" human_id="" uuid="a4cab39b-9828-413a-bf88-f76921bf1517" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
</ModelRoot>

View File

@@ -0,0 +1,9 @@
<ModelRoot>
<ComputeNode hostname="hostname_0" uuid="Node_0" id="0" state="up" human_id="" status="enabled" ResourceType.cpu_cores="10" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_6" ResourceType.cpu_cores="1" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_7" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_8" ResourceType.cpu_cores="4" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_9" ResourceType.cpu_cores="8" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode hostname="hostname_1" uuid="Node_1" id="1" state="up" human_id="" status="enabled" ResourceType.cpu_cores="10" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64"/>
</ModelRoot>

View File

@@ -0,0 +1,3 @@
<ModelRoot>
<ComputeNode human_id="" uuid="Node_0" status="enabled" state="up" id="0" hostname="hostname_0" ResourceType.cpu_cores="1" ResourceType.disk="1" ResourceType.disk_capacity="1" ResourceType.memory="1"/>
</ModelRoot>

View File

@@ -0,0 +1,5 @@
<ModelRoot>
<ComputeNode human_id="" uuid="Node_0" status="enabled" state="up" id="0" hostname="hostname_0" ResourceType.cpu_cores="4" ResourceType.disk="4" ResourceType.disk_capacity="4" ResourceType.memory="4">
<Instance state="active" human_id="" uuid="INSTANCE_0" hostname="" ResourceType.cpu_cores="4" ResourceType.disk="0" ResourceType.disk_capacity="0" ResourceType.memory="2"/>
</ComputeNode>
</ModelRoot>

View File

@@ -0,0 +1,10 @@
<ModelRoot>
<ComputeNode human_id="" uuid="Node_0" status="enabled" state="up" id="0" hostname="hostname_0" ResourceType.cpu_cores="40" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="132">
<Instance state="active" human_id="" uuid="73b09e16-35b7-4922-804e-e8f5d9b740fc" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_1" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode human_id="" uuid="Node_1" status="enabled" state="up" id="1" hostname="hostname_1" ResourceType.cpu_cores="40" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="132">
<Instance state="active" human_id="" uuid="INSTANCE_3" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_4" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
</ModelRoot>

View File

@@ -0,0 +1,10 @@
<ModelRoot>
<ComputeNode human_id="" uuid="Node_0" status="enabled" state="up" id="0" hostname="hostname_0" ResourceType.cpu_cores="50" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="132">
<Instance state="active" human_id="" uuid="73b09e16-35b7-4922-804e-e8f5d9b740fc" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="cae81432-1631-4d4e-b29c-6f3acdcde906" hostname="" ResourceType.cpu_cores="15" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode human_id="" uuid="Node_1" status="enabled" state="up" id="1" hostname="hostname_1" ResourceType.cpu_cores="50" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="132">
<Instance state="active" human_id="" uuid="INSTANCE_3" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance state="active" human_id="" uuid="INSTANCE_4" hostname="" ResourceType.cpu_cores="10" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
</ModelRoot>

View File

@@ -0,0 +1,16 @@
<ModelRoot>
<ComputeNode hostname="hostname_0" uuid="Node_0" id="0" state="up" human_id="" status="enabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_0" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_1" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_2" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode hostname="hostname_1" uuid="Node_1" id="1" state="up" human_id="" status="enabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_3" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode hostname="hostname_2" uuid="Node_2" id="2" state="up" human_id="" status="enabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_4" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode hostname="hostname_3" uuid="Node_3" id="3" state="up" human_id="" status="enabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_5" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
</ModelRoot>

View File

@@ -0,0 +1,16 @@
<ModelRoot>
<ComputeNode hostname="hostname_0" uuid="Node_0" id="0" state="up" human_id="" status="enabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_0" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_1" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_2" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode hostname="hostname_1" uuid="Node_1" id="1" state="up" human_id="" status="enabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_3" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode hostname="hostname_2" uuid="Node_2" id="2" state="up" human_id="" status="enabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_4" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
<ComputeNode hostname="hostname_3" uuid="Node_3" id="3" state="up" human_id="" status="disabled" ResourceType.cpu_cores="16" ResourceType.disk="250" ResourceType.disk_capacity="250" ResourceType.memory="64">
<Instance hostname="" human_id="" state="active" uuid="INSTANCE_5" ResourceType.cpu_cores="2" ResourceType.disk="20" ResourceType.disk_capacity="20" ResourceType.memory="2"/>
</ComputeNode>
</ModelRoot>

View File

@@ -0,0 +1,161 @@
# -*- encoding: utf-8 -*-
#
# Authors: Vojtech CIMA <cima@zhaw.ch>
# Bruno GRAZIOLI <gaea@zhaw.ch>
# Sean MURPHY <murp@zhaw.ch>
#
# 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 os
import mock
from watcher.decision_engine.model.collector import base
from watcher.decision_engine.model import element
from watcher.decision_engine.model import model_root as modelroot
class FakerModelCollector(base.BaseClusterDataModelCollector):
def __init__(self, config=None, osc=None):
if config is None:
config = mock.Mock()
super(FakerModelCollector, self).__init__(config)
@property
def notification_endpoints(self):
return []
def execute(self):
return self.generate_scenario_1()
def load_data(self, filename):
cwd = os.path.abspath(os.path.dirname(__file__))
data_folder = os.path.join(cwd, "data")
with open(os.path.join(data_folder, filename), 'rb') as xml_file:
xml_data = xml_file.read()
return xml_data
def load_model(self, filename):
return modelroot.ModelRoot.from_xml(self.load_data(filename))
def generate_scenario_1(self):
"""Simulates cluster with 2 nodes and 2 instances using 1:1 mapping"""
return self.load_model('scenario_1_with_metrics.xml')
def generate_scenario_2(self):
"""Simulates a cluster
With 4 nodes and 6 instances all mapped to a single node
"""
return self.load_model('scenario_2_with_metrics.xml')
def generate_scenario_3(self):
"""Simulates a cluster
With 4 nodes and 6 instances all mapped to one node
"""
return self.load_model('scenario_3_with_metrics.xml')
def generate_scenario_4(self):
"""Simulates a cluster
With 4 nodes and 6 instances spread on all nodes
"""
return self.load_model('scenario_4_with_metrics.xml')
class FakeCeilometerMetrics(object):
def __init__(self, model):
self.model = model
def mock_get_statistics(self, resource_id, meter_name, period=3600,
aggregate='avg'):
if meter_name == "compute.node.cpu.percent":
return self.get_node_cpu_util(resource_id)
elif meter_name == "cpu_util":
return self.get_instance_cpu_util(resource_id)
elif meter_name == "memory.usage":
return self.get_instance_ram_util(resource_id)
elif meter_name == "disk.root.size":
return self.get_instance_disk_root_size(resource_id)
def get_node_cpu_util(self, r_id):
"""Calculates node utilization dynamicaly.
node CPU utilization should consider
and corelate with actual instance-node mappings
provided within a cluster model.
Returns relative node CPU utilization <0, 100>.
:param r_id: resource id
"""
id = '%s_%s' % (r_id.split('_')[0], r_id.split('_')[1])
instances = self.model.get_mapping().get_node_instances_by_uuid(id)
util_sum = 0.0
node_cpu_cores = self.model.get_resource_by_uuid(
element.ResourceType.cpu_cores).get_capacity_by_uuid(id)
for instance_uuid in instances:
instance_cpu_cores = self.model.get_resource_by_uuid(
element.ResourceType.cpu_cores).\
get_capacity(self.model.get_instance_by_uuid(instance_uuid))
total_cpu_util = instance_cpu_cores * self.get_instance_cpu_util(
instance_uuid)
util_sum += total_cpu_util / 100.0
util_sum /= node_cpu_cores
return util_sum * 100.0
def get_instance_cpu_util(self, r_id):
instance_cpu_util = dict()
instance_cpu_util['INSTANCE_0'] = 10
instance_cpu_util['INSTANCE_1'] = 30
instance_cpu_util['INSTANCE_2'] = 60
instance_cpu_util['INSTANCE_3'] = 20
instance_cpu_util['INSTANCE_4'] = 40
instance_cpu_util['INSTANCE_5'] = 50
instance_cpu_util['INSTANCE_6'] = 100
instance_cpu_util['INSTANCE_7'] = 100
instance_cpu_util['INSTANCE_8'] = 100
instance_cpu_util['INSTANCE_9'] = 100
return instance_cpu_util[str(r_id)]
def get_instance_ram_util(self, r_id):
instance_ram_util = dict()
instance_ram_util['INSTANCE_0'] = 1
instance_ram_util['INSTANCE_1'] = 2
instance_ram_util['INSTANCE_2'] = 4
instance_ram_util['INSTANCE_3'] = 8
instance_ram_util['INSTANCE_4'] = 3
instance_ram_util['INSTANCE_5'] = 2
instance_ram_util['INSTANCE_6'] = 1
instance_ram_util['INSTANCE_7'] = 2
instance_ram_util['INSTANCE_8'] = 4
instance_ram_util['INSTANCE_9'] = 8
return instance_ram_util[str(r_id)]
def get_instance_disk_root_size(self, r_id):
instance_disk_util = dict()
instance_disk_util['INSTANCE_0'] = 10
instance_disk_util['INSTANCE_1'] = 15
instance_disk_util['INSTANCE_2'] = 30
instance_disk_util['INSTANCE_3'] = 35
instance_disk_util['INSTANCE_4'] = 20
instance_disk_util['INSTANCE_5'] = 25
instance_disk_util['INSTANCE_6'] = 25
instance_disk_util['INSTANCE_7'] = 25
instance_disk_util['INSTANCE_8'] = 25
instance_disk_util['INSTANCE_9'] = 25
return instance_disk_util[str(r_id)]

View File

@@ -0,0 +1,157 @@
# -*- 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 os
import mock
from watcher.decision_engine.model.collector import base
from watcher.decision_engine.model import element
from watcher.decision_engine.model import model_root as modelroot
class FakerModelCollector(base.BaseClusterDataModelCollector):
def __init__(self, config=None, osc=None):
if config is None:
config = mock.Mock(period=777)
super(FakerModelCollector, self).__init__(config)
@property
def notification_endpoints(self):
return []
def load_data(self, filename):
cwd = os.path.abspath(os.path.dirname(__file__))
data_folder = os.path.join(cwd, "data")
with open(os.path.join(data_folder, filename), 'rb') as xml_file:
xml_data = xml_file.read()
return xml_data
def load_model(self, filename):
return modelroot.ModelRoot.from_xml(self.load_data(filename))
def execute(self):
return self._cluster_data_model or self.build_scenario_1()
def build_scenario_1(self):
instances = []
current_state_cluster = modelroot.ModelRoot()
# number of nodes
node_count = 5
# number max of instance per node
node_instance_count = 7
# total number of virtual machine
instance_count = (node_count * node_instance_count)
# define ressouce ( CPU, MEM disk, ... )
mem = element.Resource(element.ResourceType.memory)
# 2199.954 Mhz
num_cores = element.Resource(element.ResourceType.cpu_cores)
disk = element.Resource(element.ResourceType.disk)
disk_capacity = element.Resource(element.ResourceType.disk_capacity)
current_state_cluster.create_resource(mem)
current_state_cluster.create_resource(num_cores)
current_state_cluster.create_resource(disk)
current_state_cluster.create_resource(disk_capacity)
for id_ in range(0, node_count):
node_uuid = "Node_{0}".format(id_)
node = element.ComputeNode(id_)
node.uuid = node_uuid
node.hostname = "hostname_{0}".format(id_)
mem.set_capacity(node, 132)
disk.set_capacity(node, 250)
disk_capacity.set_capacity(node, 250)
num_cores.set_capacity(node, 40)
current_state_cluster.add_node(node)
for i in range(0, instance_count):
instance_uuid = "INSTANCE_{0}".format(i)
instance = element.Instance()
instance.uuid = instance_uuid
mem.set_capacity(instance, 2)
disk.set_capacity(instance, 20)
disk_capacity.set_capacity(instance, 20)
num_cores.set_capacity(instance, 10)
instances.append(instance)
current_state_cluster.add_instance(instance)
current_state_cluster.mapping.map(
current_state_cluster.get_node_by_uuid("Node_0"),
current_state_cluster.get_instance_by_uuid("INSTANCE_0"))
current_state_cluster.mapping.map(
current_state_cluster.get_node_by_uuid("Node_0"),
current_state_cluster.get_instance_by_uuid("INSTANCE_1"))
current_state_cluster.mapping.map(
current_state_cluster.get_node_by_uuid("Node_1"),
current_state_cluster.get_instance_by_uuid("INSTANCE_2"))
current_state_cluster.mapping.map(
current_state_cluster.get_node_by_uuid("Node_2"),
current_state_cluster.get_instance_by_uuid("INSTANCE_3"))
current_state_cluster.mapping.map(
current_state_cluster.get_node_by_uuid("Node_2"),
current_state_cluster.get_instance_by_uuid("INSTANCE_4"))
current_state_cluster.mapping.map(
current_state_cluster.get_node_by_uuid("Node_2"),
current_state_cluster.get_instance_by_uuid("INSTANCE_5"))
current_state_cluster.mapping.map(
current_state_cluster.get_node_by_uuid("Node_3"),
current_state_cluster.get_instance_by_uuid("INSTANCE_6"))
current_state_cluster.mapping.map(
current_state_cluster.get_node_by_uuid("Node_4"),
current_state_cluster.get_instance_by_uuid("INSTANCE_7"))
return current_state_cluster
def generate_scenario_1(self):
return self.load_model('scenario_1.xml')
def generate_scenario_3_with_2_nodes(self):
return self.load_model('scenario_3_with_2_nodes.xml')
def generate_scenario_4_with_1_node_no_instance(self):
return self.load_model('scenario_4_with_1_node_no_instance.xml')
def generate_scenario_5_with_instance_disk_0(self):
return self.load_model('scenario_5_with_instance_disk_0.xml')
def generate_scenario_6_with_2_nodes(self):
return self.load_model('scenario_6_with_2_nodes.xml')
def generate_scenario_7_with_2_nodes(self):
return self.load_model('scenario_7_with_2_nodes.xml')
def generate_scenario_8_with_4_nodes(self):
return self.load_model('scenario_8_with_4_nodes.xml')
def generate_scenario_9_with_3_active_plus_1_disabled_nodes(self):
return self.load_model(
'scenario_9_with_3_active_plus_1_disabled_nodes.xml')

View File

@@ -250,9 +250,3 @@ class FakerMetricsCollector(object):
def get_virtual_machine_capacity(self, instance_uuid):
return random.randint(1, 4)
def get_average_network_incomming(self, node):
pass
def get_average_network_outcomming(self, node):
pass

View File

@@ -17,8 +17,7 @@
# limitations under the License.
from watcher.decision_engine.model.notification import nova as novanotification
from watcher.tests.decision_engine.strategy.strategies \
import faker_cluster_state
from watcher.tests.decision_engine.model import faker_cluster_state
class FakeManager(object):

View File

@@ -29,9 +29,8 @@ from watcher.decision_engine.model import element
from watcher.decision_engine.model import model_root
from watcher.decision_engine.model.notification import nova as novanotification
from watcher.tests import base as base_test
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model.notification import fake_managers
from watcher.tests.decision_engine.strategy.strategies \
import faker_cluster_state
class NotificationTestCase(base_test.TestCase):

View File

@@ -20,8 +20,7 @@ import uuid
from watcher.decision_engine.model import element
from watcher.tests import base
from watcher.tests.decision_engine.strategy.strategies import \
faker_cluster_state
from watcher.tests.decision_engine.model import faker_cluster_state
class TestMapping(base.TestCase):

View File

@@ -16,6 +16,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os
from lxml import etree
from oslo_utils import uuidutils
import six
@@ -24,154 +26,32 @@ from watcher.common import exception
from watcher.decision_engine.model import element
from watcher.decision_engine.model import model_root
from watcher.tests import base
from watcher.tests.decision_engine.strategy.strategies \
import faker_cluster_state
from watcher.tests.decision_engine.model import faker_cluster_state
class TestModel(base.TestCase):
def load_data(self, filename):
cwd = os.path.abspath(os.path.dirname(__file__))
data_folder = os.path.join(cwd, "data")
with open(os.path.join(data_folder, filename), 'rb') as xml_file:
xml_data = xml_file.read()
return xml_data
def load_model(self, filename):
return model_root.ModelRoot.from_xml(self.load_data(filename))
def test_model_structure(self):
fake_cluster = faker_cluster_state.FakerModelCollector()
model = fake_cluster.generate_scenario_1()
model = fake_cluster.build_scenario_1()
self.assertEqual(5, len(model._nodes))
self.assertEqual(35, len(model._instances))
self.assertEqual(5, len(model.mapping.get_mapping()))
expected_struct_str = """
<ModelRoot>
<ComputeNode ResourceType.cpu_cores="40" ResourceType.disk="250"
ResourceType.disk_capacity="250" ResourceType.memory="132"
hostname="hostname_0" human_id="" id="0" state="up"
status="enabled" uuid="Node_0">
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_0"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_1"/>
</ComputeNode>
<ComputeNode ResourceType.cpu_cores="40" ResourceType.disk="250"
ResourceType.disk_capacity="250" ResourceType.memory="132"
hostname="hostname_1" human_id="" id="1" state="up"
status="enabled" uuid="Node_1">
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_2"/>
</ComputeNode>
<ComputeNode ResourceType.cpu_cores="40" ResourceType.disk="250"
ResourceType.disk_capacity="250" ResourceType.memory="132"
hostname="hostname_2" human_id="" id="2" state="up"
status="enabled" uuid="Node_2">
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_3"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_4"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_5"/>
</ComputeNode>
<ComputeNode ResourceType.cpu_cores="40" ResourceType.disk="250"
ResourceType.disk_capacity="250" ResourceType.memory="132"
hostname="hostname_3" human_id="" id="3" state="up"
status="enabled" uuid="Node_3">
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_6"/>
</ComputeNode>
<ComputeNode ResourceType.cpu_cores="40" ResourceType.disk="250"
ResourceType.disk_capacity="250" ResourceType.memory="132"
hostname="hostname_4" human_id="" id="4" state="up"
status="enabled" uuid="Node_4">
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_7"/>
</ComputeNode>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_10"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_11"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_12"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_13"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_14"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_15"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_16"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_17"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_18"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_19"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_20"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_21"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_22"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_23"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_24"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_25"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_26"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_27"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_28"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_29"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_30"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_31"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_32"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_33"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_34"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_8"/>
<Instance ResourceType.cpu_cores="10" ResourceType.disk="20"
ResourceType.disk_capacity="20" ResourceType.memory="2"
hostname="" human_id="" state="active" uuid="INSTANCE_9"/>
</ModelRoot>
"""
expected_struct_str = self.load_data('scenario_1.xml')
parser = etree.XMLParser(remove_blank_text=True)
expected_struct = etree.fromstring(expected_struct_str, parser)
model_structure = etree.fromstring(model.to_string(), parser)
@@ -186,6 +66,15 @@ class TestModel(base.TestCase):
self.assertEqual(normalized_expected_struct, normalized_model_struct)
def test_build_model_from_xml(self):
fake_cluster = faker_cluster_state.FakerModelCollector()
expected_model = fake_cluster.generate_scenario_1()
struct_str = self.load_data('scenario_1.xml')
model = model_root.ModelRoot.from_xml(struct_str)
self.assertEqual(expected_model.to_string(), model.to_string())
def test_add_node(self):
model = model_root.ModelRoot()
uuid_ = "{0}".format(uuidutils.generate_uuid())

View File

@@ -24,10 +24,8 @@ from watcher.decision_engine.strategy import strategies
from watcher import objects
from watcher.tests.db import base
from watcher.tests.db import utils as db_utils
from watcher.tests.decision_engine.strategy.strategies \
import faker_cluster_state
from watcher.tests.decision_engine.strategy.strategies \
import faker_metrics_collector as fake
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import faker_metrics_collector as fake
from watcher.tests.objects import utils as obj_utils

View File

@@ -1,270 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Authors: Vojtech CIMA <cima@zhaw.ch>
# Bruno GRAZIOLI <gaea@zhaw.ch>
# Sean MURPHY <murp@zhaw.ch>
#
# 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.decision_engine.model.collector import base
from watcher.decision_engine.model import element
from watcher.decision_engine.model import model_root as modelroot
class FakerModelCollector(base.BaseClusterDataModelCollector):
def __init__(self, config=None, osc=None):
if config is None:
config = mock.Mock()
super(FakerModelCollector, self).__init__(config)
@property
def notification_endpoints(self):
return []
def execute(self):
return self.generate_scenario_1()
def generate_scenario_1(self):
"""Simulates cluster with 2 nodes and 2 instances using 1:1 mapping"""
current_state_cluster = modelroot.ModelRoot()
count_node = 2
count_instance = 2
mem = element.Resource(element.ResourceType.memory)
num_cores = element.Resource(element.ResourceType.cpu_cores)
disk = element.Resource(element.ResourceType.disk)
disk_capacity =\
element.Resource(element.ResourceType.disk_capacity)
current_state_cluster.create_resource(mem)
current_state_cluster.create_resource(num_cores)
current_state_cluster.create_resource(disk)
current_state_cluster.create_resource(disk_capacity)
for id_ in range(0, count_node):
node_uuid = "Node_{0}".format(id_)
node = element.ComputeNode(id_)
node.uuid = node_uuid
node.hostname = "hostname_{0}".format(id_)
node.state = 'enabled'
mem.set_capacity(node, 64)
disk_capacity.set_capacity(node, 250)
num_cores.set_capacity(node, 40)
current_state_cluster.add_node(node)
for i in range(0, count_instance):
instance_uuid = "INSTANCE_{0}".format(i)
instance = element.Instance()
instance.uuid = instance_uuid
instance.state = element.InstanceState.ACTIVE.value
mem.set_capacity(instance, 2)
disk.set_capacity(instance, 20)
num_cores.set_capacity(instance, 10)
current_state_cluster.add_instance(instance)
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_0"),
current_state_cluster.get_instance_by_uuid("INSTANCE_0"))
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_1"),
current_state_cluster.get_instance_by_uuid("INSTANCE_1"))
return current_state_cluster
def generate_scenario_2(self):
"""Simulates a cluster
With 4 nodes and 6 instances all mapped to a single node
"""
current_state_cluster = modelroot.ModelRoot()
count_node = 4
count_instance = 6
mem = element.Resource(element.ResourceType.memory)
num_cores = element.Resource(element.ResourceType.cpu_cores)
disk = element.Resource(element.ResourceType.disk)
disk_capacity =\
element.Resource(element.ResourceType.disk_capacity)
current_state_cluster.create_resource(mem)
current_state_cluster.create_resource(num_cores)
current_state_cluster.create_resource(disk)
current_state_cluster.create_resource(disk_capacity)
for id_ in range(0, count_node):
node_uuid = "Node_{0}".format(id_)
node = element.ComputeNode(id_)
node.uuid = node_uuid
node.hostname = "hostname_{0}".format(id_)
node.state = 'up'
mem.set_capacity(node, 64)
disk_capacity.set_capacity(node, 250)
num_cores.set_capacity(node, 16)
current_state_cluster.add_node(node)
for i in range(0, count_instance):
instance_uuid = "INSTANCE_{0}".format(i)
instance = element.Instance()
instance.uuid = instance_uuid
instance.state = element.InstanceState.ACTIVE.value
mem.set_capacity(instance, 2)
disk.set_capacity(instance, 20)
num_cores.set_capacity(instance, 10)
current_state_cluster.add_instance(instance)
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_0"),
current_state_cluster.get_instance_by_uuid("INSTANCE_%s" % i))
return current_state_cluster
def generate_scenario_3(self):
"""Simulates a cluster
With 4 nodes and 6 instances all mapped to one node
"""
current_state_cluster = modelroot.ModelRoot()
count_node = 2
count_instance = 4
mem = element.Resource(element.ResourceType.memory)
num_cores = element.Resource(element.ResourceType.cpu_cores)
disk = element.Resource(element.ResourceType.disk)
disk_capacity =\
element.Resource(element.ResourceType.disk_capacity)
current_state_cluster.create_resource(mem)
current_state_cluster.create_resource(num_cores)
current_state_cluster.create_resource(disk)
current_state_cluster.create_resource(disk_capacity)
for id_ in range(0, count_node):
node_uuid = "Node_{0}".format(id_)
node = element.ComputeNode(id_)
node.uuid = node_uuid
node.hostname = "hostname_{0}".format(id_)
node.state = 'up'
mem.set_capacity(node, 64)
disk_capacity.set_capacity(node, 250)
num_cores.set_capacity(node, 10)
current_state_cluster.add_node(node)
for i in range(6, 6 + count_instance):
instance_uuid = "INSTANCE_{0}".format(i)
instance = element.Instance()
instance.uuid = instance_uuid
instance.state = element.InstanceState.ACTIVE.value
mem.set_capacity(instance, 2)
disk.set_capacity(instance, 20)
num_cores.set_capacity(instance, 2 ** (i - 6))
current_state_cluster.add_instance(instance)
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_0"),
current_state_cluster.get_instance_by_uuid("INSTANCE_%s" % i))
return current_state_cluster
class FakeCeilometerMetrics(object):
def __init__(self, model):
self.model = model
def mock_get_statistics(self, resource_id, meter_name, period=3600,
aggregate='avg'):
if meter_name == "compute.node.cpu.percent":
return self.get_node_cpu_util(resource_id)
elif meter_name == "cpu_util":
return self.get_instance_cpu_util(resource_id)
elif meter_name == "memory.usage":
return self.get_instance_ram_util(resource_id)
elif meter_name == "disk.root.size":
return self.get_instance_disk_root_size(resource_id)
def get_node_cpu_util(self, r_id):
"""Calculates node utilization dynamicaly.
node CPU utilization should consider
and corelate with actual instance-node mappings
provided within a cluster model.
Returns relative node CPU utilization <0, 100>.
:param r_id: resource id
"""
id = '%s_%s' % (r_id.split('_')[0], r_id.split('_')[1])
instances = self.model.get_mapping().get_node_instances_by_uuid(id)
util_sum = 0.0
node_cpu_cores = self.model.get_resource_by_uuid(
element.ResourceType.cpu_cores).get_capacity_by_uuid(id)
for instance_uuid in instances:
instance_cpu_cores = self.model.get_resource_by_uuid(
element.ResourceType.cpu_cores).\
get_capacity(self.model.get_instance_by_uuid(instance_uuid))
total_cpu_util = instance_cpu_cores * self.get_instance_cpu_util(
instance_uuid)
util_sum += total_cpu_util / 100.0
util_sum /= node_cpu_cores
return util_sum * 100.0
def get_instance_cpu_util(self, r_id):
instance_cpu_util = dict()
instance_cpu_util['INSTANCE_0'] = 10
instance_cpu_util['INSTANCE_1'] = 30
instance_cpu_util['INSTANCE_2'] = 60
instance_cpu_util['INSTANCE_3'] = 20
instance_cpu_util['INSTANCE_4'] = 40
instance_cpu_util['INSTANCE_5'] = 50
instance_cpu_util['INSTANCE_6'] = 100
instance_cpu_util['INSTANCE_7'] = 100
instance_cpu_util['INSTANCE_8'] = 100
instance_cpu_util['INSTANCE_9'] = 100
return instance_cpu_util[str(r_id)]
def get_instance_ram_util(self, r_id):
instance_ram_util = dict()
instance_ram_util['INSTANCE_0'] = 1
instance_ram_util['INSTANCE_1'] = 2
instance_ram_util['INSTANCE_2'] = 4
instance_ram_util['INSTANCE_3'] = 8
instance_ram_util['INSTANCE_4'] = 3
instance_ram_util['INSTANCE_5'] = 2
instance_ram_util['INSTANCE_6'] = 1
instance_ram_util['INSTANCE_7'] = 2
instance_ram_util['INSTANCE_8'] = 4
instance_ram_util['INSTANCE_9'] = 8
return instance_ram_util[str(r_id)]
def get_instance_disk_root_size(self, r_id):
instance_disk_util = dict()
instance_disk_util['INSTANCE_0'] = 10
instance_disk_util['INSTANCE_1'] = 15
instance_disk_util['INSTANCE_2'] = 30
instance_disk_util['INSTANCE_3'] = 35
instance_disk_util['INSTANCE_4'] = 20
instance_disk_util['INSTANCE_5'] = 25
instance_disk_util['INSTANCE_6'] = 25
instance_disk_util['INSTANCE_7'] = 25
instance_disk_util['INSTANCE_8'] = 25
instance_disk_util['INSTANCE_9'] = 25
return instance_disk_util[str(r_id)]

View File

@@ -1,414 +0,0 @@
# -*- 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.decision_engine.model.collector import base
from watcher.decision_engine.model import element
from watcher.decision_engine.model import model_root as modelroot
class FakerModelCollector(base.BaseClusterDataModelCollector):
def __init__(self, config=None, osc=None):
if config is None:
config = mock.Mock(period=777)
super(FakerModelCollector, self).__init__(config)
@property
def notification_endpoints(self):
return []
def execute(self):
return self._cluster_data_model or self.generate_scenario_1()
def generate_scenario_1(self):
instances = []
current_state_cluster = modelroot.ModelRoot()
# number of nodes
node_count = 5
# number max of instance per node
node_instance_count = 7
# total number of virtual machine
instance_count = (node_count * node_instance_count)
# define ressouce ( CPU, MEM disk, ... )
mem = element.Resource(element.ResourceType.memory)
# 2199.954 Mhz
num_cores = element.Resource(element.ResourceType.cpu_cores)
disk = element.Resource(element.ResourceType.disk)
disk_capacity = element.Resource(element.ResourceType.disk_capacity)
current_state_cluster.create_resource(mem)
current_state_cluster.create_resource(num_cores)
current_state_cluster.create_resource(disk)
current_state_cluster.create_resource(disk_capacity)
for id_ in range(0, node_count):
node_uuid = "Node_{0}".format(id_)
node = element.ComputeNode(id_)
node.uuid = node_uuid
node.hostname = "hostname_{0}".format(id_)
mem.set_capacity(node, 132)
disk.set_capacity(node, 250)
disk_capacity.set_capacity(node, 250)
num_cores.set_capacity(node, 40)
current_state_cluster.add_node(node)
for i in range(0, instance_count):
instance_uuid = "INSTANCE_{0}".format(i)
instance = element.Instance()
instance.uuid = instance_uuid
mem.set_capacity(instance, 2)
disk.set_capacity(instance, 20)
disk_capacity.set_capacity(instance, 20)
num_cores.set_capacity(instance, 10)
instances.append(instance)
current_state_cluster.add_instance(instance)
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_0"),
current_state_cluster.get_instance_by_uuid("INSTANCE_0"))
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_0"),
current_state_cluster.get_instance_by_uuid("INSTANCE_1"))
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_1"),
current_state_cluster.get_instance_by_uuid("INSTANCE_2"))
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_2"),
current_state_cluster.get_instance_by_uuid("INSTANCE_3"))
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_2"),
current_state_cluster.get_instance_by_uuid("INSTANCE_4"))
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_2"),
current_state_cluster.get_instance_by_uuid("INSTANCE_5"))
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_3"),
current_state_cluster.get_instance_by_uuid("INSTANCE_6"))
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_4"),
current_state_cluster.get_instance_by_uuid("INSTANCE_7"))
return current_state_cluster
def map(self, model, h_id, instance_id):
model.get_mapping().map(
model.get_node_by_uuid(h_id),
model.get_instance_by_uuid(instance_id))
def generate_scenario_3_with_2_nodes(self):
instances = []
root = modelroot.ModelRoot()
# number of nodes
node_count = 2
# define ressouce ( CPU, MEM disk, ... )
mem = element.Resource(element.ResourceType.memory)
# 2199.954 Mhz
num_cores = element.Resource(element.ResourceType.cpu_cores)
disk = element.Resource(element.ResourceType.disk)
disk_capacity = element.Resource(element.ResourceType.disk_capacity)
root.create_resource(mem)
root.create_resource(num_cores)
root.create_resource(disk)
root.create_resource(disk_capacity)
for id_ in range(0, node_count):
node_uuid = "Node_{0}".format(id_)
node = element.ComputeNode(id_)
node.uuid = node_uuid
node.hostname = "hostname_{0}".format(id_)
mem.set_capacity(node, 132)
disk.set_capacity(node, 250)
disk_capacity.set_capacity(node, 250)
num_cores.set_capacity(node, 40)
root.add_node(node)
instance1 = element.Instance()
instance1.uuid = "73b09e16-35b7-4922-804e-e8f5d9b740fc"
mem.set_capacity(instance1, 2)
disk.set_capacity(instance1, 20)
disk_capacity.set_capacity(instance1, 20)
num_cores.set_capacity(instance1, 10)
instances.append(instance1)
root.add_instance(instance1)
instance2 = element.Instance()
instance2.uuid = "a4cab39b-9828-413a-bf88-f76921bf1517"
mem.set_capacity(instance2, 2)
disk.set_capacity(instance2, 20)
disk_capacity.set_capacity(instance2, 20)
num_cores.set_capacity(instance2, 10)
instances.append(instance2)
root.add_instance(instance2)
root.get_mapping().map(root.get_node_by_uuid("Node_0"),
root.get_instance_by_uuid(str(instance1.uuid)))
root.get_mapping().map(root.get_node_by_uuid("Node_1"),
root.get_instance_by_uuid(str(instance2.uuid)))
return root
def generate_scenario_4_with_1_node_no_instance(self):
current_state_cluster = modelroot.ModelRoot()
# number of nodes
node_count = 1
# define ressouce ( CPU, MEM disk, ... )
mem = element.Resource(element.ResourceType.memory)
# 2199.954 Mhz
num_cores = element.Resource(element.ResourceType.cpu_cores)
disk = element.Resource(element.ResourceType.disk)
disk_capacity = element.Resource(element.ResourceType.disk_capacity)
current_state_cluster.create_resource(mem)
current_state_cluster.create_resource(num_cores)
current_state_cluster.create_resource(disk)
current_state_cluster.create_resource(disk_capacity)
for id_ in range(0, node_count):
node_uuid = "Node_{0}".format(id_)
node = element.ComputeNode(id_)
node.uuid = node_uuid
node.hostname = "hostname_{0}".format(id_)
mem.set_capacity(node, 1)
disk.set_capacity(node, 1)
disk_capacity.set_capacity(node, 1)
num_cores.set_capacity(node, 1)
current_state_cluster.add_node(node)
return current_state_cluster
def generate_scenario_5_with_instance_disk_0(self):
instances = []
current_state_cluster = modelroot.ModelRoot()
# number of nodes
node_count = 1
# number of instances
instance_count = 1
# define ressouce ( CPU, MEM disk, ... )
mem = element.Resource(element.ResourceType.memory)
# 2199.954 Mhz
num_cores = element.Resource(element.ResourceType.cpu_cores)
disk = element.Resource(element.ResourceType.disk)
disk_capacity = element.Resource(element.ResourceType.disk_capacity)
current_state_cluster.create_resource(mem)
current_state_cluster.create_resource(num_cores)
current_state_cluster.create_resource(disk)
current_state_cluster.create_resource(disk_capacity)
for id_ in range(0, node_count):
node_uuid = "Node_{0}".format(id_)
node = element.ComputeNode(id_)
node.uuid = node_uuid
node.hostname = "hostname_{0}".format(id_)
mem.set_capacity(node, 4)
disk.set_capacity(node, 4)
disk_capacity.set_capacity(node, 4)
num_cores.set_capacity(node, 4)
current_state_cluster.add_node(node)
for i in range(0, instance_count):
instance_uuid = "INSTANCE_{0}".format(i)
instance = element.Instance()
instance.uuid = instance_uuid
mem.set_capacity(instance, 2)
disk.set_capacity(instance, 0)
disk_capacity.set_capacity(instance, 0)
num_cores.set_capacity(instance, 4)
instances.append(instance)
current_state_cluster.add_instance(instance)
current_state_cluster.get_mapping().map(
current_state_cluster.get_node_by_uuid("Node_0"),
current_state_cluster.get_instance_by_uuid("INSTANCE_0"))
return current_state_cluster
def generate_scenario_6_with_2_nodes(self):
instances = []
root = modelroot.ModelRoot()
# number of nodes
node_count = 2
# define ressouce ( CPU, MEM disk, ... )
mem = element.Resource(element.ResourceType.memory)
# 2199.954 Mhz
num_cores = element.Resource(element.ResourceType.cpu_cores)
disk = element.Resource(element.ResourceType.disk)
disk_capacity = element.Resource(element.ResourceType.disk_capacity)
root.create_resource(mem)
root.create_resource(num_cores)
root.create_resource(disk)
root.create_resource(disk_capacity)
for id_ in range(0, node_count):
node_uuid = "Node_{0}".format(id_)
node = element.ComputeNode(id_)
node.uuid = node_uuid
node.hostname = "hostname_{0}".format(id_)
mem.set_capacity(node, 132)
disk.set_capacity(node, 250)
disk_capacity.set_capacity(node, 250)
num_cores.set_capacity(node, 40)
root.add_node(node)
instance1 = element.Instance()
instance1.uuid = "INSTANCE_1"
mem.set_capacity(instance1, 2)
disk.set_capacity(instance1, 20)
disk_capacity.set_capacity(instance1, 20)
num_cores.set_capacity(instance1, 10)
instances.append(instance1)
root.add_instance(instance1)
instance11 = element.Instance()
instance11.uuid = "73b09e16-35b7-4922-804e-e8f5d9b740fc"
mem.set_capacity(instance11, 2)
disk.set_capacity(instance11, 20)
disk_capacity.set_capacity(instance11, 20)
num_cores.set_capacity(instance11, 10)
instances.append(instance11)
root.add_instance(instance11)
instance2 = element.Instance()
instance2.uuid = "INSTANCE_3"
mem.set_capacity(instance2, 2)
disk.set_capacity(instance2, 20)
disk_capacity.set_capacity(instance2, 20)
num_cores.set_capacity(instance2, 10)
instances.append(instance2)
root.add_instance(instance2)
instance21 = element.Instance()
instance21.uuid = "INSTANCE_4"
mem.set_capacity(instance21, 2)
disk.set_capacity(instance21, 20)
disk_capacity.set_capacity(instance21, 20)
num_cores.set_capacity(instance21, 10)
instances.append(instance21)
root.add_instance(instance21)
root.get_mapping().map(root.get_node_by_uuid("Node_0"),
root.get_instance_by_uuid(str(instance1.uuid)))
root.get_mapping().map(root.get_node_by_uuid("Node_0"),
root.get_instance_by_uuid(str(instance11.uuid)))
root.get_mapping().map(root.get_node_by_uuid("Node_1"),
root.get_instance_by_uuid(str(instance2.uuid)))
root.get_mapping().map(root.get_node_by_uuid("Node_1"),
root.get_instance_by_uuid(str(instance21.uuid)))
return root
def generate_scenario_7_with_2_nodes(self):
instances = []
root = modelroot.ModelRoot()
# number of nodes
count_node = 2
# define ressouce ( CPU, MEM disk, ... )
mem = element.Resource(element.ResourceType.memory)
# 2199.954 Mhz
num_cores = element.Resource(element.ResourceType.cpu_cores)
disk = element.Resource(element.ResourceType.disk)
disk_capacity = element.Resource(element.ResourceType.disk_capacity)
root.create_resource(mem)
root.create_resource(num_cores)
root.create_resource(disk)
root.create_resource(disk_capacity)
for id_ in range(0, count_node):
node_uuid = "Node_{0}".format(id_)
node = element.ComputeNode(id_)
node.uuid = node_uuid
node.hostname = "hostname_{0}".format(id_)
mem.set_capacity(node, 132)
disk.set_capacity(node, 250)
disk_capacity.set_capacity(node, 250)
num_cores.set_capacity(node, 50)
root.add_node(node)
instance1 = element.Instance()
instance1.uuid = "cae81432-1631-4d4e-b29c-6f3acdcde906"
mem.set_capacity(instance1, 2)
disk.set_capacity(instance1, 20)
disk_capacity.set_capacity(instance1, 20)
num_cores.set_capacity(instance1, 15)
instances.append(instance1)
root.add_instance(instance1)
instance11 = element.Instance()
instance11.uuid = "73b09e16-35b7-4922-804e-e8f5d9b740fc"
mem.set_capacity(instance11, 2)
disk.set_capacity(instance11, 20)
disk_capacity.set_capacity(instance11, 20)
num_cores.set_capacity(instance11, 10)
instances.append(instance11)
root.add_instance(instance11)
instance2 = element.Instance()
instance2.uuid = "INSTANCE_3"
mem.set_capacity(instance2, 2)
disk.set_capacity(instance2, 20)
disk_capacity.set_capacity(instance2, 20)
num_cores.set_capacity(instance2, 10)
instances.append(instance2)
root.add_instance(instance2)
instance21 = element.Instance()
instance21.uuid = "INSTANCE_4"
mem.set_capacity(instance21, 2)
disk.set_capacity(instance21, 20)
disk_capacity.set_capacity(instance21, 20)
num_cores.set_capacity(instance21, 10)
instances.append(instance21)
root.add_instance(instance21)
root.get_mapping().map(root.get_node_by_uuid("Node_0"),
root.get_instance_by_uuid(str(instance1.uuid)))
root.get_mapping().map(root.get_node_by_uuid("Node_0"),
root.get_instance_by_uuid(str(instance11.uuid)))
root.get_mapping().map(root.get_node_by_uuid("Node_1"),
root.get_instance_by_uuid(str(instance2.uuid)))
root.get_mapping().map(root.get_node_by_uuid("Node_1"),
root.get_instance_by_uuid(str(instance21.uuid)))
return root

View File

@@ -26,10 +26,8 @@ from watcher.decision_engine.model.collector import nova
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 \
import faker_cluster_state
from watcher.tests.decision_engine.strategy.strategies \
import faker_metrics_collector
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import faker_metrics_collector
class TestBasicConsolidation(base.TestCase):
@@ -186,14 +184,37 @@ class TestBasicConsolidation(base.TestCase):
[action.get('action_type') for action in solution.actions])
expected_num_migrations = 1
expected_power_state = 0
expected_power_state = 1
num_migrations = actions_counter.get("migrate", 0)
num_node_state_change = actions_counter.get(
"change_node_state", 0)
"change_nova_service_state", 0)
self.assertEqual(expected_num_migrations, num_migrations)
self.assertEqual(expected_power_state, num_node_state_change)
def test_basic_consolidation_execute_scenario_8_with_4_nodes(self):
model = self.fake_cluster.generate_scenario_8_with_4_nodes()
self.m_model.return_value = model
solution = self.strategy.execute()
actions_counter = collections.Counter(
[action.get('action_type') for action in solution.actions])
expected_num_migrations = 5
expected_power_state = 3
expected_global_efficacy = 60
num_migrations = actions_counter.get("migrate", 0)
num_node_state_change = actions_counter.get(
"change_nova_service_state", 0)
global_efficacy_value = solution.global_efficacy.get("value", 0)
self.assertEqual(expected_num_migrations, num_migrations)
self.assertEqual(expected_power_state, num_node_state_change)
self.assertEqual(expected_global_efficacy, global_efficacy_value)
def test_exception_stale_cdm(self):
self.fake_cluster.set_cluster_data_model_as_stale()
self.m_model.return_value = self.fake_cluster.cluster_data_model

View File

@@ -21,8 +21,7 @@ from watcher.common import utils
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 import \
faker_cluster_state
from watcher.tests.decision_engine.model import faker_cluster_state
class TestDummyStrategy(base.TestCase):

View File

@@ -21,8 +21,7 @@ from watcher.common import utils
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 import \
faker_cluster_state
from watcher.tests.decision_engine.model import faker_cluster_state
class TestDummyWithScorer(base.TestCase):

View File

@@ -26,10 +26,8 @@ from watcher.decision_engine.model import element
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 \
import faker_cluster_state
from watcher.tests.decision_engine.strategy.strategies \
import faker_metrics_collector
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import faker_metrics_collector
class TestOutletTempControl(base.TestCase):

View File

@@ -26,10 +26,8 @@ from watcher.decision_engine.model import element
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 \
import faker_cluster_state
from watcher.tests.decision_engine.strategy.strategies \
import faker_metrics_collector
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import faker_metrics_collector
class TestUniformAirflow(base.TestCase):

View File

@@ -24,8 +24,7 @@ from watcher.common import exception
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 \
import faker_cluster_and_metrics
from watcher.tests.decision_engine.model import faker_cluster_and_metrics
class TestVMWorkloadConsolidation(base.TestCase):

View File

@@ -26,10 +26,8 @@ from watcher.decision_engine.model import element
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 \
import faker_cluster_state
from watcher.tests.decision_engine.strategy.strategies \
import faker_metrics_collector
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import faker_metrics_collector
class TestWorkloadBalance(base.TestCase):

View File

@@ -23,10 +23,8 @@ from watcher.common import utils
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 \
import faker_cluster_state
from watcher.tests.decision_engine.strategy.strategies \
import faker_metrics_collector
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import faker_metrics_collector
class TestWorkloadStabilization(base.TestCase):

View File

@@ -24,8 +24,7 @@ import mock
from watcher.decision_engine.loading import default as default_loading
from watcher.decision_engine import scheduling
from watcher.tests import base
from watcher.tests.decision_engine.strategy.strategies import \
faker_cluster_state
from watcher.tests.decision_engine.model import faker_cluster_state
class TestDecisionEngineSchedulingService(base.TestCase):