Compare commits

..

3 Commits

Author SHA1 Message Date
OpenStack Release Bot
003b19317b Update TOX_CONSTRAINTS_FILE for stable/zed
Update the URL to the upper-constraints file to point to the redirect
rule on releases.openstack.org so that anyone working on this branch
will switch to the correct upper-constraints list automatically when
the requirements repository branches.

Until the requirements repository has as stable/zed branch, tests will
continue to use the upper-constraints list on master.

Change-Id: Ie7f17b44f0dd48a4d20f6d28c8dfa1e12f839d58
2022-09-26 12:24:32 +00:00
OpenStack Release Bot
818ce593fd Update .gitreview for stable/zed
Change-Id: I43dc66569eead390b4cdaa83c8832a93b5e5670b
2022-09-26 12:24:16 +00:00
Alfredo Moralejo
2b103c40a7 Fix compatibility with oslo.db 12.1.0
oslo.db 12.1.0 has changed the default value for the 'autocommit'
parameter of 'LegacyEngineFacade' from 'True' to 'False'. This is a
necessary step to ensure compatibility with SQLAlchemy 2.0. However, we
are currently relying on the autocommit behavior and need changes to
explicitly manage sessions. Until that happens, we need to override the
default.

This also moves the watcher queue declaration from the pipeline level
(where it is no longer valid) to the project level.

Co-Authored-By: Thierry Carrez <thierry@openstack.org>
Co-Authored-By: Stephen Finucane <stephenfin@redhat.com>
(cherry picked from commit 5d70c207cd)
Change-Id: I7db39d958d087322bfa0aad70dfbd04de9228dd7
2022-09-26 14:16:27 +02:00
25 changed files with 56 additions and 131 deletions

View File

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

View File

@@ -3,7 +3,7 @@
templates: templates:
- check-requirements - check-requirements
- openstack-cover-jobs - openstack-cover-jobs
- openstack-python3-jobs - openstack-python3-zed-jobs
- publish-openstack-docs-pti - publish-openstack-docs-pti
- release-notes-jobs-python3 - release-notes-jobs-python3
check: check:
@@ -89,7 +89,7 @@
- job: - job:
name: watcher-tempest-multinode name: watcher-tempest-multinode
parent: watcher-tempest-functional parent: watcher-tempest-functional
nodeset: openstack-two-node-jammy nodeset: openstack-two-node-focal
roles: roles:
- zuul: openstack/tempest - zuul: openstack/tempest
group-vars: group-vars:
@@ -107,7 +107,6 @@
watcher-api: false watcher-api: false
watcher-decision-engine: true watcher-decision-engine: true
watcher-applier: false watcher-applier: false
c-bak: false
ceilometer: false ceilometer: false
ceilometer-acompute: false ceilometer-acompute: false
ceilometer-acentral: false ceilometer-acentral: false

View File

@@ -372,7 +372,7 @@ You can configure and install Ceilometer by following the documentation below :
#. https://docs.openstack.org/ceilometer/latest #. https://docs.openstack.org/ceilometer/latest
The built-in strategy 'basic_consolidation' provided by watcher requires The built-in strategy 'basic_consolidation' provided by watcher requires
"**compute.node.cpu.percent**" and "**cpu**" measurements to be collected "**compute.node.cpu.percent**" and "**cpu_util**" measurements to be collected
by Ceilometer. by Ceilometer.
The measurements available depend on the hypervisors that OpenStack manages on The measurements available depend on the hypervisors that OpenStack manages on
the specific implementation. the specific implementation.

View File

@@ -300,6 +300,6 @@ Using that you can now query the values for that specific metric:
.. code-block:: py .. code-block:: py
avg_meter = self.datasource_backend.statistic_aggregation( avg_meter = self.datasource_backend.statistic_aggregation(
instance.uuid, 'instance_cpu_usage', self.periods['instance'], instance.uuid, 'cpu_util', self.periods['instance'],
self.granularity, self.granularity,
aggregation=self.aggregation_method['instance']) aggregation=self.aggregation_method['instance'])

View File

@@ -26,7 +26,8 @@ metric service name plugins comment
``compute_monitors`` option ``compute_monitors`` option
to ``cpu.virt_driver`` in to ``cpu.virt_driver`` in
the nova.conf. the nova.conf.
``cpu`` ceilometer_ none ``cpu_util`` ceilometer_ none cpu_util has been removed
since Stein.
============================ ============ ======= =========================== ============================ ============ ======= ===========================
.. _ceilometer: https://docs.openstack.org/ceilometer/latest/admin/telemetry-measurements.html#openstack-compute .. _ceilometer: https://docs.openstack.org/ceilometer/latest/admin/telemetry-measurements.html#openstack-compute

View File

@@ -89,9 +89,9 @@ step 2: Create audit to do optimization
.. code-block:: shell .. code-block:: shell
$ openstack optimize audittemplate create \ $ openstack optimize audittemplate create \
saving_energy_template1 saving_energy --strategy saving_energy at1 saving_energy --strategy saving_energy
$ openstack optimize audit create -a saving_energy_audit1 \ $ openstack optimize audit create -a at1 \
-p free_used_percent=20.0 -p free_used_percent=20.0
External Links External Links

View File

@@ -22,7 +22,8 @@ The *vm_workload_consolidation* strategy requires the following metrics:
============================ ============ ======= ========================= ============================ ============ ======= =========================
metric service name plugins comment metric service name plugins comment
============================ ============ ======= ========================= ============================ ============ ======= =========================
``cpu`` ceilometer_ none ``cpu_util`` ceilometer_ none cpu_util has been removed
since Stein.
``memory.resident`` ceilometer_ none ``memory.resident`` ceilometer_ none
``memory`` ceilometer_ none ``memory`` ceilometer_ none
``disk.root.size`` ceilometer_ none ``disk.root.size`` ceilometer_ none

View File

@@ -27,8 +27,9 @@ metric service name plugins comment
to ``cpu.virt_driver`` in the to ``cpu.virt_driver`` in the
nova.conf. nova.conf.
``hardware.memory.used`` ceilometer_ SNMP_ ``hardware.memory.used`` ceilometer_ SNMP_
``cpu`` ceilometer_ none ``cpu_util`` ceilometer_ none cpu_util has been removed
``instance_ram_usage`` ceilometer_ none since Stein.
``memory.resident`` ceilometer_ none
============================ ============ ======= ============================= ============================ ============ ======= =============================
.. _ceilometer: https://docs.openstack.org/ceilometer/latest/admin/telemetry-measurements.html#openstack-compute .. _ceilometer: https://docs.openstack.org/ceilometer/latest/admin/telemetry-measurements.html#openstack-compute
@@ -106,10 +107,10 @@ parameter type default Value description
period of all received ones. period of all received ones.
==================== ====== ===================== ============================= ==================== ====== ===================== =============================
.. |metrics| replace:: ["instance_cpu_usage", "instance_ram_usage"] .. |metrics| replace:: ["cpu_util", "memory.resident"]
.. |thresholds| replace:: {"instance_cpu_usage": 0.2, "instance_ram_usage": 0.2} .. |thresholds| replace:: {"cpu_util": 0.2, "memory.resident": 0.2}
.. |weights| replace:: {"instance_cpu_usage_weight": 1.0, "instance_ram_usage_weight": 1.0} .. |weights| replace:: {"cpu_util_weight": 1.0, "memory.resident_weight": 1.0}
.. |instance_metrics| replace:: {"instance_cpu_usage": "compute.node.cpu.percent", "instance_ram_usage": "hardware.memory.used"} .. |instance_metrics| replace:: {"cpu_util": "compute.node.cpu.percent", "memory.resident": "hardware.memory.used"}
.. |periods| replace:: {"instance": 720, "node": 600} .. |periods| replace:: {"instance": 720, "node": 600}
Efficacy Indicator Efficacy Indicator
@@ -135,8 +136,8 @@ How to use it ?
at1 workload_balancing --strategy workload_stabilization at1 workload_balancing --strategy workload_stabilization
$ openstack optimize audit create -a at1 \ $ openstack optimize audit create -a at1 \
-p thresholds='{"instance_ram_usage": 0.05}' \ -p thresholds='{"memory.resident": 0.05}' \
-p metrics='["instance_ram_usage"]' -p metrics='["memory.resident"]'
External Links External Links
-------------- --------------

View File

@@ -24,7 +24,8 @@ The *workload_balance* strategy requires the following metrics:
======================= ============ ======= ========================= ======================= ============ ======= =========================
metric service name plugins comment metric service name plugins comment
======================= ============ ======= ========================= ======================= ============ ======= =========================
``cpu`` ceilometer_ none ``cpu_util`` ceilometer_ none cpu_util has been removed
since Stein.
``memory.resident`` ceilometer_ none ``memory.resident`` ceilometer_ none
======================= ============ ======= ========================= ======================= ============ ======= =========================
@@ -64,16 +65,15 @@ Configuration
Strategy parameters are: Strategy parameters are:
============== ====== ==================== ==================================== ============== ====== ============= ====================================
parameter type default Value description parameter type default Value description
============== ====== ==================== ==================================== ============== ====== ============= ====================================
``metrics`` String 'instance_cpu_usage' Workload balance base on cpu or ram ``metrics`` String 'cpu_util' Workload balance base on cpu or ram
utilization. Choices: utilization. choice: ['cpu_util',
['instance_cpu_usage', 'memory.resident']
'instance_ram_usage'] ``threshold`` Number 25.0 Workload threshold for migration
``threshold`` Number 25.0 Workload threshold for migration ``period`` Number 300 Aggregate time period of ceilometer
``period`` Number 300 Aggregate time period of ceilometer ============== ====== ============= ====================================
============== ====== ==================== ====================================
Efficacy Indicator Efficacy Indicator
------------------ ------------------
@@ -95,7 +95,7 @@ How to use it ?
at1 workload_balancing --strategy workload_balance at1 workload_balancing --strategy workload_balance
$ openstack optimize audit create -a at1 -p threshold=26.0 \ $ openstack optimize audit create -a at1 -p threshold=26.0 \
-p period=310 -p metrics=instance_cpu_usage -p period=310 -p metrics=cpu_util
External Links External Links
-------------- --------------

View File

@@ -1,6 +0,0 @@
===========================
2023.1 Series Release Notes
===========================
.. release-notes::
:branch: stable/2023.1

View File

@@ -21,8 +21,6 @@ Contents:
:maxdepth: 1 :maxdepth: 1
unreleased unreleased
2023.1
zed
yoga yoga
xena xena
wallaby wallaby

View File

@@ -2,16 +2,15 @@
# Andi Chandler <andi@gowling.com>, 2018. #zanata # Andi Chandler <andi@gowling.com>, 2018. #zanata
# Andi Chandler <andi@gowling.com>, 2020. #zanata # Andi Chandler <andi@gowling.com>, 2020. #zanata
# Andi Chandler <andi@gowling.com>, 2022. #zanata # Andi Chandler <andi@gowling.com>, 2022. #zanata
# Andi Chandler <andi@gowling.com>, 2023. #zanata
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: python-watcher\n" "Project-Id-Version: python-watcher\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-08-14 03:05+0000\n" "POT-Creation-Date: 2022-08-29 03:02+0000\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2023-06-21 07:54+0000\n" "PO-Revision-Date: 2022-05-31 08:39+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n" "Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language-Team: English (United Kingdom)\n" "Language-Team: English (United Kingdom)\n"
"Language: en_GB\n" "Language: en_GB\n"
@@ -60,9 +59,6 @@ msgstr "1.9.0"
msgid "2.0.0" msgid "2.0.0"
msgstr "2.0.0" msgstr "2.0.0"
msgid "2023.1 Series Release Notes"
msgstr "2023.1 Series Release Notes"
msgid "3.0.0" msgid "3.0.0"
msgstr "3.0.0" msgstr "3.0.0"
@@ -973,9 +969,6 @@ msgstr "Xena Series Release Notes"
msgid "Yoga Series Release Notes" msgid "Yoga Series Release Notes"
msgstr "Yoga Series Release Notes" msgstr "Yoga Series Release Notes"
msgid "Zed Series Release Notes"
msgstr "Zed Series Release Notes"
msgid "``[watcher_datasources] datasources = gnocchi,monasca,ceilometer``" msgid "``[watcher_datasources] datasources = gnocchi,monasca,ceilometer``"
msgstr "``[watcher_datasources] datasources = gnocchi,monasca,ceilometer``" msgstr "``[watcher_datasources] datasources = gnocchi,monasca,ceilometer``"

View File

@@ -1,6 +0,0 @@
========================
Zed Series Release Notes
========================
.. release-notes::
:branch: stable/zed

View File

@@ -17,7 +17,7 @@ oslo.context>=2.21.0 # Apache-2.0
oslo.db>=4.44.0 # Apache-2.0 oslo.db>=4.44.0 # Apache-2.0
oslo.i18n>=3.20.0 # Apache-2.0 oslo.i18n>=3.20.0 # Apache-2.0
oslo.log>=3.37.0 # Apache-2.0 oslo.log>=3.37.0 # Apache-2.0
oslo.messaging>=14.1.0 # Apache-2.0 oslo.messaging>=8.1.2 # Apache-2.0
oslo.policy>=3.6.0 # Apache-2.0 oslo.policy>=3.6.0 # Apache-2.0
oslo.reports>=1.27.0 # Apache-2.0 oslo.reports>=1.27.0 # Apache-2.0
oslo.serialization>=2.25.0 # Apache-2.0 oslo.serialization>=2.25.0 # Apache-2.0

13
tox.ini
View File

@@ -1,6 +1,7 @@
[tox] [tox]
minversion = 3.18.0 minversion = 3.18.0
envlist = py3,pep8 envlist = py3,pep8
skipsdist = True
ignore_basepython_conflict = True ignore_basepython_conflict = True
[testenv] [testenv]
@@ -8,7 +9,7 @@ basepython = python3
usedevelop = True usedevelop = True
allowlist_externals = find allowlist_externals = find
rm rm
install_command = pip install -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2023.2} {opts} {packages} install_command = pip install -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/zed} {opts} {packages}
setenv = setenv =
VIRTUAL_ENV={envdir} VIRTUAL_ENV={envdir}
deps = deps =
@@ -18,19 +19,13 @@ commands =
rm -f .testrepository/times.dbm rm -f .testrepository/times.dbm
find . -type f -name "*.py[c|o]" -delete find . -type f -name "*.py[c|o]" -delete
stestr run {posargs} stestr run {posargs}
passenv = passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY
http_proxy
HTTP_PROXY
https_proxy
HTTPS_PROXY
no_proxy
NO_PROXY
[testenv:pep8] [testenv:pep8]
commands = commands =
doc8 doc/source/ CONTRIBUTING.rst HACKING.rst README.rst doc8 doc/source/ CONTRIBUTING.rst HACKING.rst README.rst
flake8 flake8
#bandit -r watcher -x watcher/tests/* -n5 -ll -s B320 bandit -r watcher -x watcher/tests/* -n5 -ll -s B320
[testenv:venv] [testenv:venv]
setenv = PYTHONHASHSEED=0 setenv = PYTHONHASHSEED=0

View File

@@ -121,7 +121,7 @@ class RequestContextSerializer(messaging.Serializer):
def get_client(target, version_cap=None, serializer=None): def get_client(target, version_cap=None, serializer=None):
assert TRANSPORT is not None assert TRANSPORT is not None
serializer = RequestContextSerializer(serializer) serializer = RequestContextSerializer(serializer)
return messaging.get_rpc_client( return messaging.RPCClient(
TRANSPORT, TRANSPORT,
target, target,
version_cap=version_cap, version_cap=version_cap,

View File

@@ -134,13 +134,7 @@ GRAFANA_CLIENT_OPTS = [
"InfluxDB this will be the retention period. " "InfluxDB this will be the retention period. "
"These queries will need to be constructed using tools " "These queries will need to be constructed using tools "
"such as Postman. Example: SELECT cpu FROM {4}." "such as Postman. Example: SELECT cpu FROM {4}."
"cpu_percent WHERE host == '{1}' AND time > now()-{2}s"), "cpu_percent WHERE host == '{1}' AND time > now()-{2}s")]
cfg.IntOpt('http_timeout',
min=0,
default=60,
mutable=True,
help='Timeout for Grafana request')
]
def register_opts(conf): def register_opts(conf):

View File

@@ -38,7 +38,7 @@ class GnocchiHelper(base.DataSourceBase):
host_inlet_temp='hardware.ipmi.node.temperature', host_inlet_temp='hardware.ipmi.node.temperature',
host_airflow='hardware.ipmi.node.airflow', host_airflow='hardware.ipmi.node.airflow',
host_power='hardware.ipmi.node.power', host_power='hardware.ipmi.node.power',
instance_cpu_usage='cpu', instance_cpu_usage='cpu_util',
instance_ram_usage='memory.resident', instance_ram_usage='memory.resident',
instance_ram_allocated='memory', instance_ram_allocated='memory',
instance_l3_cache_usage='cpu_l3_cache', instance_l3_cache_usage='cpu_l3_cache',
@@ -93,25 +93,6 @@ class GnocchiHelper(base.DataSourceBase):
resource_id = resources[0]['id'] resource_id = resources[0]['id']
if meter_name == "instance_cpu_usage":
if resource_type != "instance":
LOG.warning("Unsupported resource type for metric "
"'instance_cpu_usage': ", resource_type)
return
# The "cpu_util" gauge (percentage) metric has been removed.
# We're going to obtain the same result by using the rate of change
# aggregate operation.
if aggregate not in ("mean", "rate:mean"):
LOG.warning("Unsupported aggregate for instance_cpu_usage "
"metric: %s. "
"Supported aggregates: mean, rate:mean ",
aggregate)
return
# TODO(lpetrut): consider supporting other aggregates.
aggregate = "rate:mean"
raw_kwargs = dict( raw_kwargs = dict(
metric=meter, metric=meter,
start=start_time, start=start_time,
@@ -136,17 +117,6 @@ class GnocchiHelper(base.DataSourceBase):
# Airflow from hardware.ipmi.node.airflow is reported as # Airflow from hardware.ipmi.node.airflow is reported as
# 1/10 th of actual CFM # 1/10 th of actual CFM
return_value *= 10 return_value *= 10
if meter_name == "instance_cpu_usage":
# "rate:mean" can return negative values for migrated vms.
return_value = max(0, return_value)
# We're converting the cumulative cpu time (ns) to cpu usage
# percentage.
vcpus = resource.vcpus
if not vcpus:
LOG.warning("instance vcpu count not set, assuming 1")
vcpus = 1
return_value *= 100 / (granularity * 10e+8) / vcpus
return return_value return return_value

View File

@@ -138,8 +138,7 @@ class GrafanaHelper(base.DataSourceBase):
raise exception.DataSourceNotAvailable(self.NAME) raise exception.DataSourceNotAvailable(self.NAME)
resp = requests.get(self._base_url + str(project_id) + '/query', resp = requests.get(self._base_url + str(project_id) + '/query',
params=params, headers=self._headers, params=params, headers=self._headers)
timeout=CONF.grafana_client.http_timeout)
if resp.status_code == HTTPStatus.OK: if resp.status_code == HTTPStatus.OK:
return resp return resp
elif resp.status_code == HTTPStatus.BAD_REQUEST: elif resp.status_code == HTTPStatus.BAD_REQUEST:

View File

@@ -48,7 +48,7 @@ class NovaClusterDataModelCollector(base.BaseClusterDataModelCollector):
"type": "array", "type": "array",
"items": { "items": {
"anyOf": [ "anyOf": [
{"$ref": HOST_AGGREGATES + "host_aggr_id"}, {"$ref": HOST_AGGREGATES + "id"},
{"$ref": HOST_AGGREGATES + "name"}, {"$ref": HOST_AGGREGATES + "name"},
] ]
} }
@@ -98,8 +98,7 @@ class NovaClusterDataModelCollector(base.BaseClusterDataModelCollector):
"type": "array", "type": "array",
"items": { "items": {
"anyOf": [ "anyOf": [
{"$ref": {"$ref": HOST_AGGREGATES + "id"},
HOST_AGGREGATES + "host_aggr_id"},
{"$ref": HOST_AGGREGATES + "name"}, {"$ref": HOST_AGGREGATES + "name"},
] ]
} }
@@ -130,7 +129,7 @@ class NovaClusterDataModelCollector(base.BaseClusterDataModelCollector):
"additionalProperties": False "additionalProperties": False
}, },
"host_aggregates": { "host_aggregates": {
"host_aggr_id": { "id": {
"properties": { "properties": {
"id": { "id": {
"oneOf": [ "oneOf": [

View File

@@ -252,6 +252,9 @@ class BaseStrategy(loadable.Loadable, metaclass=abc.ABCMeta):
if not self.compute_model: if not self.compute_model:
raise exception.ClusterStateNotDefined() raise exception.ClusterStateNotDefined()
if self.compute_model.stale:
raise exception.ClusterStateStale()
LOG.debug(self.compute_model.to_string()) LOG.debug(self.compute_model.to_string())
def execute(self, audit=None): def execute(self, audit=None):

View File

@@ -206,13 +206,13 @@ class SavingEnergy(base.SavingEnergyBaseStrategy):
for node in random.sample(self.free_poweron_node_pool, for node in random.sample(self.free_poweron_node_pool,
(len_poweron - need_poweron)): (len_poweron - need_poweron)):
self.add_action_poweronoff_node(node, 'off') self.add_action_poweronoff_node(node, 'off')
LOG.info("power off %s", node.uuid) LOG.debug("power off %s", node.uuid)
elif len_poweron < need_poweron: elif len_poweron < need_poweron:
diff = need_poweron - len_poweron diff = need_poweron - len_poweron
for node in random.sample(self.free_poweroff_node_pool, for node in random.sample(self.free_poweroff_node_pool,
min(len_poweroff, diff)): min(len_poweroff, diff)):
self.add_action_poweronoff_node(node, 'on') self.add_action_poweronoff_node(node, 'on')
LOG.info("power on %s", node.uuid) LOG.debug("power on %s", node.uuid)
def pre_execute(self): def pre_execute(self):
self._pre_execute() self._pre_execute()

View File

@@ -295,7 +295,7 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy):
self.threshold) self.threshold)
return self.solution return self.solution
# choose the server with largest cpu usage # choose the server with largest cpu_util
source_nodes = sorted(source_nodes, source_nodes = sorted(source_nodes,
reverse=True, reverse=True,
key=lambda x: (x[self._meter])) key=lambda x: (x[self._meter]))

View File

@@ -80,13 +80,13 @@ class TestService(base.TestCase):
super(TestService, self).setUp() super(TestService, self).setUp()
@mock.patch.object(om.rpc.server, "RPCServer") @mock.patch.object(om.rpc.server, "RPCServer")
def _test_start(self, m_handler): def test_start(self, m_handler):
dummy_service = service.Service(DummyManager) dummy_service = service.Service(DummyManager)
dummy_service.start() dummy_service.start()
self.assertEqual(1, m_handler.call_count) self.assertEqual(1, m_handler.call_count)
@mock.patch.object(om.rpc.server, "RPCServer") @mock.patch.object(om.rpc.server, "RPCServer")
def _test_stop(self, m_handler): def test_stop(self, m_handler):
dummy_service = service.Service(DummyManager) dummy_service = service.Service(DummyManager)
dummy_service.stop() dummy_service.stop()
self.assertEqual(1, m_handler.call_count) self.assertEqual(1, m_handler.call_count)

View File

@@ -40,25 +40,17 @@ class TestGnocchiHelper(base.BaseTestCase):
self.addCleanup(stat_agg_patcher.stop) self.addCleanup(stat_agg_patcher.stop)
def test_gnocchi_statistic_aggregation(self, mock_gnocchi): def test_gnocchi_statistic_aggregation(self, mock_gnocchi):
vcpus = 2
mock_instance = mock.Mock(
id='16a86790-327a-45f9-bc82-45839f062fdc',
vcpus=vcpus)
gnocchi = mock.MagicMock() gnocchi = mock.MagicMock()
# cpu time rate of change (ns)
mock_rate_measure = 360 * 10e+8 * vcpus * 5.5 / 100
expected_result = 5.5 expected_result = 5.5
expected_measures = [ expected_measures = [["2017-02-02T09:00:00.000000", 360, 5.5]]
["2017-02-02T09:00:00.000000", 360, mock_rate_measure]]
gnocchi.metric.get_measures.return_value = expected_measures gnocchi.metric.get_measures.return_value = expected_measures
mock_gnocchi.return_value = gnocchi mock_gnocchi.return_value = gnocchi
helper = gnocchi_helper.GnocchiHelper() helper = gnocchi_helper.GnocchiHelper()
result = helper.statistic_aggregation( result = helper.statistic_aggregation(
resource=mock_instance, resource=mock.Mock(id='16a86790-327a-45f9-bc82-45839f062fdc'),
resource_type='instance', resource_type='instance',
meter_name='instance_cpu_usage', meter_name='instance_cpu_usage',
period=300, period=300,
@@ -67,14 +59,6 @@ class TestGnocchiHelper(base.BaseTestCase):
) )
self.assertEqual(expected_result, result) self.assertEqual(expected_result, result)
gnocchi.metric.get_measures.assert_called_once_with(
metric="cpu",
start=mock.ANY,
stop=mock.ANY,
resource_id=mock_instance.uuid,
granularity=360,
aggregation="rate:mean")
def test_gnocchi_statistic_series(self, mock_gnocchi): def test_gnocchi_statistic_series(self, mock_gnocchi):
gnocchi = mock.MagicMock() gnocchi = mock.MagicMock()
expected_result = { expected_result = {