Compare commits

...

144 Commits

Author SHA1 Message Date
Zuul
f2ee231f14 Merge "pre-commit: Integrate bandit" 2025-03-11 09:58:29 +00:00
Zuul
3861701f4a Merge "Replace deprecated abc.abstractproperty" 2025-03-11 09:47:31 +00:00
Zuul
d167134265 Merge "Drop implicit test dependency on iso8601" 2025-03-11 09:47:30 +00:00
Sean Mooney
bbf5c41cab Add epoxy prelude
This change added the prelude for the 2025.1 Expoxy release cycle.

Change-Id: I8223842a57491a91c565e47bd1819db4d142e628
2025-03-05 17:57:55 +00:00
Takashi Kajinami
df3d67a4ed Replace deprecated abc.abstractproperty
It was deprecated in Python 3.3 [1].

[1] https://docs.python.org/3.13/whatsnew/3.3.html#abc

Change-Id: Ibd98cb93f697a6da6a6bc5a5030640a262c7a66b
2025-03-02 15:36:48 +09:00
Takashi Kajinami
82f1c720dd Drop implicit test dependency on iso8601
The library has been missing from the test requirements although it is
directly used. Replace it by the built-in datetime module to get rid
of the unmaintained direct dependency.

Change-Id: I1d08b38862b54fee4c7c26161f59264fb3f2ce51
2025-03-01 15:23:15 +09:00
Zuul
77a30ef281 Merge "Enable prometheus datasource in watcher-prometheus-integration job" 2025-02-28 13:26:10 +00:00
Zuul
383751904c Merge "Further database refactoring" 2025-02-27 11:52:59 +00:00
Zuul
6a1f19d314 Merge "Deprecate Monasca data source" 2025-02-27 11:45:15 +00:00
Douglas Viroel
342fe8882a Enable prometheus datasource in watcher-prometheus-integration job
Enable prometheus as datasouce in tempest configuration,
to enable metric generation needed to run some scenario
tests. It is enabled on the watcher-prometheus-integration
job

Depends-On: https://review.opendev.org/c/openstack/watcher-tempest-plugin/+/942141
Depends-On: https://review.opendev.org/c/openstack/watcher-tempest-plugin/+/942308

Change-Id: I2b657782aedf61d89766fcd18bb453b62c0b0e3b
2025-02-22 10:46:01 -03:00
Chandan Kumar (raukadah)
7fcca0cc46 Enable prometheus and node_exporter from devstack-plugin-prometheus
https://opendev.org/openstack/devstack-plugin-prometheus is the new
devstack plugin providing functionality to install/configure
prometheus/node_exporter.

It will replace sg_core devstack plugin in future.

Depends-On: https://review.opendev.org/c/openstack/watcher/+/938893
Depends-On: https://review.opendev.org/c/openstack/devstack-plugin-prometheus/+/940426

Change-Id: Ia75e6597275b36c04cde653c16f7d45ed23bc261
Signed-off-by: Chandan Kumar (raukadah) <chkumar@redhat.com>
2025-02-19 08:49:53 -03:00
Takashi Kajinami
977f014cba Deprecate Monasca data source
The Monasca project was marked inactive during 2023.1. Although we have
seen multiple people showing interest to keep the project, we haven't
seen any real progress.

Because the project is likely retired soon, let's deprecate the feature
dependent on Monasca so that we can remove it in a future release.

Change-Id: Ifd64f5ba59bbac238ff62302ec36a3e36954d6d0
2025-02-16 18:45:31 +09:00
James Page
753c44b0c4 Further database refactoring
More refactoring of the SQLAlchemy database layer to improve
compatility with eventlet on newer Pythons.

Inspired by 0ce2c41404

Related-Bug: 2067815
Change-Id: Ib5e9aa288232cc1b766bbf2a8ce2113d5a8e2f7d
2025-02-14 11:42:47 +00:00
Takashi Kajinami
dd0082c343 pre-commit: Integrate bandit
Run bandit check from per-commit so that the check is executed in pep8
job.

Also remove requirements installed automatically by pre-commit from
test-requirements.

Change-Id: I45af8c47afb262882ebbee74ae52446fed741e26
2025-02-10 22:50:34 +09:00
Takashi Kajinami
5f6fbaea56 Remove unused os-api-ref from test requirements
It is used when building API reference but is not used in any testing.

Change-Id: I6af7c7b110b338acad10eccf42344a338afbc915
2025-02-09 08:14:17 +09:00
Takashi Kajinami
6b81b34b27 Drop import fallback for Python 2
cPickle no longer exists in Python 3 and pickle should be used always.

Change-Id: I5ddedb3e996d9a0679bab38ea94263886274ece4
2025-02-09 08:04:36 +09:00
Zuul
961bbb9460 Merge "Update master for stable/2024.2" 2025-02-06 08:07:22 +00:00
Zuul
d56e8ee65a Merge "X-Project-Name key in test code was duplicated" 2025-02-03 18:29:23 +00:00
Zuul
4527f89d8d Merge "Add support for instance metrics to prometheus datasource" 2025-02-03 13:22:28 +00:00
Zuul
e535177bc0 Merge "Remove ceilometer datasource" 2025-01-29 13:22:46 +00:00
Zuul
022d150d20 Merge "Add prometheus data source for watcher decision engine" 2025-01-24 13:46:32 +00:00
Alfredo Moralejo
136e5d927c Add support for instance metrics to prometheus datasource
In order to support vm_workload_consolidation, workload_balance and
workload_stabilization strategis some instance metrics are required.
This patch is adding support for them.

Implementation is based on a prometheus store populated using sg-core
from ceilometer metrics with Pollster source.

- instance_ram_usage: rely on ceilometer_memory_usage metrics created from
  ceilometer memory.usage meter.
- instance_ram_allocated: rely on the memory value provided by the
  inventory created from nova and placement APIs.
- instance_cpu_usage: rely on ceilometer_cpu metric created from
  ceilometer cpu meter. A max value of 100 is set in the query.
- instance_root_disk_size: rely on the `disk` value provided by the
  inventory created from nova and placement APIs.

A new parameterer `instance_uuid_label` has been added to the prometheus
datasource configuration to identify the label used to store the value of the
OpenStack instance uuid for eache instance metric in prometheus. Default
value is `resource`.

Change-Id: I2f2b56aa002014e511a5e48398ef1da43fc4f5e2
2025-01-23 13:23:04 +01:00
Chandan Kumar (raukadah)
1968334b29 Drop bandit B320 profile to fix tox -e bandit interface
e4da0b351f
drops B320 profile from blacklist. Bandit no longer identify this
profile leading to tox -e bandit failure.

This profile is not listed here
https://bandit.readthedocs.io/en/latest/plugins/index.html#complete-test-plugin-listing.
so dropping it fixes the issue.

Closes-Bug: #2094789

Change-Id: I8543a507757a22b69d9b8fda500910d2246028c4
Signed-off-by: Chandan Kumar (raukadah) <chkumar@redhat.com>
2025-01-14 16:05:19 +05:30
Zuul
0b78f31e3a Merge "Add Tempest test for Prometheus integration" 2025-01-10 17:04:02 +00:00
Ronelle Landy
56b8c1211a Add Tempest test for Prometheus integration
This review adds a base job to test Watcher,
via devstack/tempest installation) and the
intreraction with the newly added
Prometheus data source.

Related change:
https://review.opendev.org/c/openstack/watcher/+/934423

Change-Id: Id9d7d2ded1aae160a97a5f0aa0f7048a9c38e87d
2025-01-10 08:50:04 -05:00
m
3f26dc47f2 Add prometheus data source for watcher decision engine
This adds a new data source for the Watcher decision engine that
implements the watcher.decision_engine.datasources.DataSourceBase.

related spec was merged at [1].

Implements: blueprint prometheus-datasource

[1] https://review.opendev.org/c/openstack/watcher-specs/+/933300

Change-Id: I6a70c4acc70a864c418cf347f5f6951cb92ec906
2025-01-10 15:20:37 +02:00
OpenStack Proposal Bot
1b6f723cc3 Imported Translations from Zanata
For more information about this automatic import see:
https://docs.openstack.org/i18n/latest/reviewing-translation-import.html

Change-Id: I2f92bde2f6eb0d479d0b56742c530a747fa64a70
2025-01-10 04:28:40 +00:00
Zuul
d6cb38289e Merge "reno: Update master for unmaintained/2023.1" 2025-01-10 00:25:12 +00:00
Zuul
406be36c45 Merge "reno: Update master for unmaintained/zed" 2025-01-10 00:25:11 +00:00
Zuul
6bb761a803 Merge "reno: Update master for unmaintained/yoga" 2025-01-10 00:25:09 +00:00
Zuul
a169d42b1f Merge "reno: Update master for unmaintained/xena" 2025-01-10 00:25:08 +00:00
Zuul
4827d6e766 Merge "reno: Update master for unmaintained/victoria" 2025-01-10 00:25:07 +00:00
Zuul
2a2db362e3 Merge "Replace deprecated LegacyEngineFacade" 2025-01-10 00:19:56 +00:00
Zuul
32756dc7b4 Merge "Replace deprecated configure_auth_token_middleware" 2025-01-10 00:06:14 +00:00
Zuul
ee447a2281 Merge "Remove default override for config options policy_file" 2025-01-09 23:35:04 +00:00
Zuul
4d8bb57c8d Merge "tox: Drop envdir" 2025-01-09 23:32:26 +00:00
Zuul
70ba13ca6d Merge "Update python versions, drop py3.8" 2024-12-21 01:58:27 +00:00
Takashi Kajinami
da23fdc621 Remove ceilometer datasource
This datasource requires Ceilometer API which was already removed some
years ago. The implementation should have been removed when dependency
on ceilometerclient was removed by [1].

Also remove some job definitions which are not actually used.

[1] 01d74d0a87

Change-Id: I29c3865dc1207f1bbbb266e4217cf8888afebfb6
2024-12-16 23:51:27 +09:00
Jiri Podivin
2ab27c0dfe X-Project-Name key in test code was duplicated
Change-Id: Ie4938edd4b606c7b84c09c191508b72b8bc8fa52
Signed-off-by: Jiri Podivin <jpodivin@redhat.com>
2024-12-04 14:05:12 +01:00
Zuul
811a704f80 Merge "Update gate jobs as per the 2025.1 cycle testing runtime" 2024-12-02 19:52:04 +00:00
Zuul
99fea33fac Merge "Fix incompatiablity between apscheduler and eventlet" 2024-12-02 19:13:24 +00:00
Zuul
9d37d705e4 Merge "[pre-commit] enforce pre-commit checks in ci" 2024-12-02 18:37:40 +00:00
Douglas Viroel
fbb290b223 Fix create_continuous_audit_with_wrong_interval test assert
"test_create_continuous_audit_with_wrong_interval" is failing
to validate the expected error message when creating a continuous
audit with a wrong interval. The error message is now slightly
different, since "croniter" was bumped to latest version in openstack
requirements[1].

Closes-Bug: #2089866

[1] 868e0ae644

Change-Id: I33029d224577bd1d5124947f1e6150fe2dbc9456
2024-11-29 10:09:14 -03:00
Ghanshyam Mann
c80c940a4f Update gate jobs as per the 2025.1 cycle testing runtime
As per 2025.1 testing runtime[1], we need to test on Ubuntu
Noble (which will be taken care by depends-on tempest and devstack
patches to move base jobs to Noble) and at least single job to run on
Ubuntu Jammy (for smooth upgrade from previous releases).

This commit adds a new job to run on Jammy which can be removed
in future cycle when testing runtime test next version of Ubuntu
as default.

Depends-On: https://review.opendev.org/c/openstack/tempest/+/932156
Depends-On: https://review.opendev.org/c/openstack/watcher/+/933062

[1] https://governance.openstack.org/tc/reference/runtimes/2025.1.html

Change-Id: I1bc11633f4739bc87c7741496a2972ab99c9b08b
2024-11-25 18:27:25 +00:00
Sean Mooney
f07694ba6c Fix incompatiablity between apscheduler and eventlet
The apscheduler background scheduler spawns a native thread
which is not monkey patched which interacts with shared module
level objects like the module level LOG instances and sqlachmey
engine facades.

This is unsafe and leads to mixing patched and unpatched
code in the same thread.

This manifests in 2 ways:
1.) https://paste.opendev.org/show/bGPgfURx1cZYOsgmtDyw/
sqlalchmey calls can fail due to a time.sleep(0) in oslo.db being invoked
using the unpatched time modules in an eventlet greenthrad.
2.) https://paste.opendev.org/show/b5C2Zz4A4BFIGbKLKrQU/
over time that caused the sqlalchmy connection queuepool to fill up preventing
backgound tasks form running like reconsiling audits.

This change adresses this by overloading the background scheduler _main_loop
to monkey patch the main loop if the calling thread was monkey patched.

Closes-Bug: #2086710
Change-Id: I672c183274b0a17cb40d7b5ab8c313197760b5a0
2024-11-25 18:27:18 +00:00
Sean Mooney
9abec18c8b [pre-commit] enforce pre-commit checks in ci
This change moves all style checks to be run via pre-commit.

To enable this in existing ci and preserve the standard developer flow
the tox pep8 target is updated to run all checks via pre-commit.

developers can optionally install pre-commit and/or the pre-commit
commit hook to automatically or manually run the precommit hooks.

Change-Id: I6ee6ed853dbf60339e7bf3da66b2e5914c218f76
2024-11-19 00:43:39 +00:00
Sean Mooney
1f8d06e075 [docs] apply sphinx-lint to docs
This change corrects the detected sphinx-linit issue in the existing
docs and updates the contributor devstack guide to call out
required and advanced.

mostly the changes were simple fixes like replacing the configurable
default rule with explict literal syntax `term` -> ``term``

some inline Note: comments have been promoted to .. note:: blocks
and literal blocks ::  have been promoted to .. code-block:: <language>
directives.

Change-Id: I6320c313d22bf542ad407169e6538dc6acf79901
2024-11-19 00:43:36 +00:00
Takashi Kajinami
29c94c102b Replace deprecated configure_auth_token_middleware
It was deprecated some years ago by [1].

[1] https://review.opendev.org/628651

Change-Id: Id5bb081a745a0698ce0d297c098394bfd1ad6788
2024-11-15 17:36:18 +09:00
OpenStack Release Bot
3f3e660367 reno: Update master for unmaintained/2023.1
Update the 2023.1 release notes configuration to build from
unmaintained/2023.1.

Change-Id: I99964d16a09d6b24505eda8444f074a38ce4a2d7
2024-11-12 16:44:04 +00:00
Ghanshyam Mann
2eefaeed14 Remove default override for config options policy_file
olso.policy 4.5.0[1] changed the config options policy_file
default value to 'policy.yaml', which means it is changed
for all the OpenStack services and they do not need to
override the default anymore.

NOTE: There is no change in behaviour here, oslo.policy provides
the same configuration that services have overridden till now.

[1] https://review.opendev.org/c/openstack/releases/+/934012
[2] https://review.opendev.org/c/openstack/requirements/+/934295

Change-Id: I46cc9e05fbc8f6c95c0b2d50093ecfb070a4170f
2024-11-10 21:36:55 -08:00
Sean Mooney
5fadd0de57 [pre-commit] Fix execute and shebang lines
This commit removes the execute bit from several files
and remove the shebang lines from the devstack plugin.

While the devstack plugin is written in bash, it is not an executable
script. The devstack plugin is sourced by devstack as needed,
as such it is not executed in a subshell and the #!/bin/bash
lines are not used even when present.

Change-Id: I82ca22b7a47bf267fe6cf11f3e3519510108c146
2024-11-07 20:12:59 +00:00
Sean Mooney
c5edad2246 [eventlet] Ensure unit tests are monkey patched
This change refactors how watcher manages monkey_patching
modules to achieve 2 goals.

First, we want to ensure the watcher code is tested as it is used
in production. While many tests can run without eventlet,
the existing unit tests depend on eventlet monkey patching
indirectly by importing watcher code that uses eventlet.spawn and
greenthread executors. While that mostly functions today it has
incorrect and inconsistent behaviour on Python 3.9 vs Python 3.12.

Second, the unit tests that test the cmd module were indirectly
monkey patching the test executor during the execution of the tests
as a side effect of importing watcher.cmd. As such the order the tests
execute in and how they are distributed across test workers changed
if the test was monkey-patched or not.

This change makes all tests run with monkey_patching by adding
monkey patching in the watcher/tests/__init__.py
This change also splits the monkey patching from the import
in preparation for an eventual removal of eventlet in a future
release.

Change-Id: I967f3469bd66e69c00863d553bc859343afbb3ff
2024-11-07 19:50:59 +00:00
Sean Mooney
405bb93030 [tox] update tox.ini to enable debugging
This change adds supprot for OS_DEBUG and also configures
default testing timeouts and log capture.

Change-Id: I685fee4081cdee82c508b6d25c534483f2caf09b
2024-11-07 19:50:33 +00:00
Sean Mooney
5f79ab87c7 [pre-commit] fix typos and configure codespell
This chanage enabled codespell in precommit and
fixes the existing typos.

A followup commit will enable this in tox and ci.

Change-Id: I0a11bcd5a88247a48d3437525fc8a3cb3cdd4e58
2024-11-07 19:50:21 +00:00
Zuul
4d5022ab94 Merge "reno: Update master for unmaintained/wallaby" 2024-11-07 18:08:05 +00:00
Martin Kopec
6adaedf696 Update python versions, drop py3.8
The current testing runtime [1] states testing from py3.9
to 3.12. The patch updates setup.cfg to reflect the correct
python versions.

The patch also drops python 3.8 support following [2].

[1] https://governance.openstack.org/tc/reference/runtimes/2025.1.html
[2] https://lists.openstack.org/archives/list/openstack-discuss@lists.openstack.org/thread/FOWV4UQZTH4DPDA67QDEROAESYU5Z3LE/

Change-Id: I2d13409c9bfffc866e31af52611a26f6037021cc
2024-11-06 16:00:11 +01:00
OpenStack Release Bot
f3ff65f233 Update master for stable/2024.2
Add file to the reno documentation build to show release notes for
stable/2024.2.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/2024.2.

Sem-Ver: feature
Change-Id: I84f9b0b1aa9749fee8ac174ae6d15c62a934d641
2024-11-01 13:48:05 +01:00
Takashi Kajinami
b5e45b43b9 Drop unnecessary 'x' bit from doc config file
This file is not actually executable.

Trivial-Fix

Change-Id: I64352c3c5c6bfd5d08aa4cee873016e02d736a2e
2024-10-28 13:13:24 +00:00
Zuul
61afdd3df7 Merge "Update master for stable/2024.1" 2024-10-28 01:16:55 +00:00
Zuul
e8f9e31541 Merge "[pre-commit] Add initial pre-commit config" 2024-10-24 04:23:49 +00:00
Ghanshyam Mann
38288dd9c8 Run watcher-db-manage in grenade testing from venv
grenade install and run everything from virtual env

- https://review.opendev.org/c/openstack/grenade/+/930507

watcher-db-manage in watcher grenade job needs to be run accordingly
and not from system level. Otherwise it will fail with below error
- https://zuul.opendev.org/t/openstack/build/02c3bd4814ea4d0580f7dfd346416425/log/controller/logs/grenade.sh_log.txt

Depends-On: https://review.opendev.org/c/openstack/watcher/+/933062

Change-Id: I73e94222c89c6a12a6006d42637cd194a09005ac
2024-10-23 18:34:43 +00:00
Sean Mooney
9d8b990fd1 [pre-commit] Add initial pre-commit config
This change adds configuration for the pre-commit tool,
follow-up changes will address the remaining issues in a phased
approach to make the reviews simpler.

This is based on the pre-commit config used in nova
with some additional hooks.

Follow-up changes will address the FIXME comments
related to sphinx-lint and codespell, as well as update tox
to enforce these checks in ci.

Change-Id: I87681a19f7fa88366c2b0d310c8b3153aa6a137b
2024-10-22 20:12:53 +01:00
Zuul
0f96f99404 Merge "Convert CRLF to LF" 2024-10-17 03:11:48 +00:00
Zuul
57177aebb2 Merge "Replace deprecated datetime.utcnow()" 2024-10-17 02:40:39 +00:00
Takashi Kajinami
2c4fb7a990 tox: Drop envdir
tox now always recreates an env although the env is shared using envdir
options.
~~~
$ tox -e genpolicy
genpolicy: recreate env because env type changed from
{'name': 'genconfig', 'type': 'VirtualEnvRunner'} to
{'name': 'genpolicy', 'type': 'VirtualEnvRunner'}
~~~

According to the maintainer of tox, this functionality is not intended
to be supported.
https://github.com/tox-dev/tox/issues/425#issuecomment-1011944293

Change-Id: I9c1f574c6d45a7be808a023f01dee13c3ac2c72e
2024-10-13 01:31:25 +09:00
Takashi Natsume
61a7dd85ca Replace deprecated datetime.utcnow()
The datetime.utcnow() is deprecated in Python 3.12.
Replace datetime.utcnow() with oslo_utils.timeutils.utcnow().
This bumps oslo.utils to 7.0.0.

Change-Id: Icccbb0549add686a744a72b354932471cbf91c92
Signed-off-by: Takashi Natsume <takanattie@gmail.com>
2024-10-02 22:24:47 +09:00
Takashi Kajinami
a7dd51390c Remove workaround for eventlet < 0.27.0
This code worked around a bug in eventlet[1] that has been fixed in
115103d5608cbe8f15df10e27eba1644f5364e95. The fix has been available in
every eventlet release since v0.27.0.

[1] https://github.com/eventlet/eventlet/issues/592

Co-Authored-By: Cyril Roelandt <cyril@redhat.com>
Change-Id: Ifc0b9c1d7f022db54c34c48c903a1719f9404d04
2024-09-28 14:53:04 +09:00
Takashi Kajinami
a47cedecfa Convert CRLF to LF
LF is commonly used as newline code.

Change-Id: I9b40461bdb67ba3e650c694da3c3bc9ac0335dd7
2024-09-28 00:30:14 +09:00
Takashi Kajinami
566a830f64 Bump hacking
hacking 3.0.x is quite old. Bump it to the current latest version.

Change-Id: I8d87fed6afe5988678c64090af261266d1ca20e6
2024-09-22 23:54:36 +09:00
Tobias Urdin
5c627a3aa3 Replace deprecated LegacyEngineFacade
LegacyEngineFacade was deprecated in oslo.db 1.12.0 which was released
in 2015.

Change-Id: I5570698262617eae3f48cf29aacf2e23ad541e5f
2024-08-27 16:45:15 +02:00
OpenStack Proposal Bot
a9dc3794a6 Imported Translations from Zanata
For more information about this automatic import see:
https://docs.openstack.org/i18n/latest/reviewing-translation-import.html

Change-Id: I2b2afb0c0e590b737871bf4c43293df2ed88e534
2024-06-01 02:47:52 +00:00
Takashi Kajinami
d6f169197e SQLAlchemy 2.0: Omnibus fixes patch
This was originally five patches, but they are all needed to pass
any of the test jobs now, so they have been squashed into one:

Co-Authored-By: Dan Smith (dms@danplanet.com)

First:

The autoload argument was removed[1] in SQLAlchemy and only
the autoload_with argument should be passed.

The autoload argument is set according to the autoload_with argument
automatically even in SQLAlchemy 1.x[2] so is not at all needed.

[1] c932123bac
[2] ad8f921e96

Second:

Remove _warn_on_bytestring for newer SA, AFAICT, this flag has been
removed from SQLAlchemy and that is why watcher-db-manage fails to
initialize the DB for me on jammy. This migration was passing the
default value (=False) anyway, so I assume this is the right "fix".

Third:

Fix joinedload passing string attribute names

Fourth:

Fix engine.select pattern to use begin() per the migration guide.

Fifth:

Override the apscheduler get_next_run_time() which appears to be
trivially not compatible with SQLAlchemy 2.0 because of a return type
from scalar().

Change-Id: I000e5e78f97f82ed4ea64d42f1c38354c3252e08
2024-05-29 06:49:32 -07:00
OpenStack Release Bot
2bc49149b3 reno: Update master for unmaintained/zed
Update the zed release notes configuration to build from
unmaintained/zed.

Change-Id: Ie3eac64cc4cf48aa761a4f7c9d7ba06fbab28686
2024-05-08 11:00:31 +00:00
James Page
bc5922c684 Fix oslo.db >= 15.0.0 compatibility
Minimal refactor of SQLAlchemy api module to be compatible with
oslo.db >= 15.0.0 where autocommit behaviour was dropped.

Closes-Bug: #2056181
Change-Id: I33be53f647faae2aad30a43c10980df950d5d7c2
2024-03-27 09:41:23 +00:00
OpenStack Release Bot
f0935fb3e1 Update master for stable/2024.1
Add file to the reno documentation build to show release notes for
stable/2024.1.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/2024.1.

Sem-Ver: feature
Change-Id: I9eb6462199bedb3bbc24ba853ebf52ac7d93353f
2024-03-15 14:16:10 +00:00
OpenStack Release Bot
762686e99e reno: Update master for unmaintained/xena
Update the xena release notes configuration to build from
unmaintained/xena.

Change-Id: I87f52f55d6997be166dd307df327ae38b9049791
2024-03-05 20:13:43 +00:00
OpenStack Release Bot
0f0527abc1 reno: Update master for unmaintained/wallaby
Update the wallaby release notes configuration to build from
unmaintained/wallaby.

Change-Id: I4ad95adf3f67786c97c0dbe562df3ae2a85fa1c8
2024-03-05 20:13:20 +00:00
OpenStack Release Bot
6e26e41519 reno: Update master for unmaintained/victoria
Update the victoria release notes configuration to build from
unmaintained/victoria.

Change-Id: Ib81d05e74ff5514a9abf0c68ac8c0494bcb93bc9
2024-03-05 20:12:57 +00:00
OpenStack Release Bot
954fc282ee reno: Update master for unmaintained/yoga
Update the yoga release notes configuration to build from
unmaintained/yoga.

Change-Id: Ic586db766f6af33c2e70c3f6fd2fd313b44a6ab8
2024-02-05 16:00:40 +00:00
Ghanshyam Mann
9d58a6d457 Update python classifier in setup.cfg
As per the current release tested runtime, we test
python version from 3.8 to 3.11 so updating the
same in python classifier in setup.cfg

Change-Id: Ie010eea38eb0861699b60f16dfd3e2e95ae33709
2024-01-09 19:22:04 -08:00
Lucian Petrut
c95ce4ec17 Add MAAS support
At the moment, Watcher can use a single bare metal provisioning
service: Openstack Ironic.

We're now adding support for Canonical's MAAS service [1], which
is commonly used along with Juju [2] to deploy Openstack.

In order to do so, we're building a metal client abstraction, with
concrete implementations for Ironic and MAAS. We'll pick the MAAS
client if the MAAS url is provided, otherwise defaulting to Ironic.

For now, we aren't updating the baremetal model collector since it
doesn't seem to be used by any of the existing Watcher strategy
implementations.

[1] https://maas.io/docs
[2] https://juju.is/docs

Implements: blueprint maas-support

Change-Id: I6861995598f6c542fa9c006131f10203f358e0a6
2023-12-11 10:21:33 +00:00
Zuul
9492c2190e Merge "vm workload consolidation: use actual host metrics" 2023-12-01 01:51:39 +00:00
Lucian Petrut
808f1bcee3 Update action json schema
Power-off actions created by the energy saving strategy include
a resource name property, which currently isn't part of the
action json schema. For this reason, json schema validation fails.

  Additional properties are not allowed ('resource_name' was unexpected)

We'll update the json schema, including the resource name property.

Change-Id: I924d36732a917c0be98b08c2f4128e9136356215
2023-11-15 01:11:56 +00:00
Lucian Petrut
3b224b5629 Fix object tests
A couple of object tests are failing, probably after a dependency
bump.

watcher.objects.base.objects is mocked, so the registered object
version isn't properly retrieved, leading to a type error:

    File "/mnt/data/workspace/watcher/watcher/tests/objects/test_objects.py",
    line 535, in test_hook_chooses_newer_properly
      reg.registration_hook(MyObj, 0)
    File "/mnt/data/workspace/watcher/watcher/objects/base.py",
    line 46, in registration_hook
      cur_version = versionutils.convert_version_to_tuple(
    File "/home/ubuntu/openstack_venv/lib/python3.10/site-packages/oslo_utils/versionutils.py",
    line 91, in convert_version_to_tuple
      version_str = re.sub(r'(\d+)(a|alpha|b|beta|rc)\d+$', '\\1', version_str)
    File "/usr/lib/python3.10/re.py", line 209, in sub
      return _compile(pattern, flags).sub(repl, string, count)
  TypeError: expected string or bytes-like object

We'll solve the issue by setting the VERSION attribute against
the mock object.

Change-Id: Ifeb38b98f1d702908531de5fc5c846bd1c53de4b
2023-11-14 10:38:40 +00:00
Lucian Petrut
424e9a76af vm workload consolidation: use actual host metrics
The "vm workload consolidation" strategy is summing up instance
usage in order to estimate host usage.

The problem is that some infrastructure services (e.g. OVS or Ceph
clients) may also use a significant amount of resources, which
would be ignored. This can impact Watcher's ability to detect
overloaded nodes and correctly rebalance the workload.

This commit will use the host metrics, if available. The proposed
implementation uses the maximum value between the host metric
and the sum of the instance metrics.

Note that we're holding a dict of host metric deltas in order to
account for planned migrations.

Change-Id: I82f474ee613f6c9a7c0a9d24a05cba41d2f68edb
2023-10-27 21:54:42 +03:00
Zuul
40e93407c7 Merge "Handle deprecated "cpu_util" metric" 2023-10-27 09:47:38 +00:00
Zuul
721aec1cb6 Merge "vm workload consolidation: allow cold migrations" 2023-10-27 09:47:36 +00:00
Zuul
8a3ee8f931 Merge "Improve vm_consolidation logging" 2023-10-27 09:20:13 +00:00
Lucian Petrut
00fea975e2 Handle deprecated "cpu_util" metric
The "cpu_util" metric has been deprecated a few years ago.
We'll obtain the same result by converting the cumulative cpu
time to a percentage, leveraging the rate of change aggregation.

Change-Id: I18fe0de6f74c785e674faceea0c48f44055818fe
2023-10-24 10:47:23 +00:00
Lucian Petrut
fd6562382e Avoid performing retries in case of missing resources
There may be no available metrics for instances that are stopped
or were recently spawned. This makes retries unnecessary and time
consuming.

For this reason, we'll ignore gnocchi MetricNotFound errors.

Change-Id: I79cd03bf04db634b931d6dfd32d5150f58e82044
2023-10-23 14:14:21 +00:00
Lucian Petrut
ec90891636 Improve vm_consolidation logging
We're adding a few info log messages in order to trace the
"vm consolidation" strategy more easily.

Change-Id: I8ce1a9dd173733f1b801839d3ad0c1269c4306bb
2023-10-23 14:10:02 +00:00
Lucian Petrut
7336a48057 vm workload consolidation: allow cold migrations
Although Watcher supports cold migrations, the vm workload
consolidation workflow only allows live migrations to be
performed.

We'll remove this unnecessary limitation so that stopped instances
could be cold migrated.

Change-Id: I4b41550f2255560febf8586722a0e02045c3a486
2023-10-23 13:03:18 +00:00
Lucian Petrut
922478fbda Unblock the CI gate
The Nova collector json schema validation started [1][2] failing after
the jsonschema upper constraint was bumped from 4.17.3 to 4.19.1 [3].

The reason is that jsonschema v4.18.0a1 switched to a reference
resolving library [4], which treats the aggregate "id" as a jsonschema
id and expects it to be a string [5]. For this reason, we're now getting
AttributeError exceptions.

As a workaround, we'll rename the "id" ref element as "host_aggr_id".

Also, the watcher-tempest-multinode job is configured to use Focal,
which is no longer supported by Devstack [6]. That being considered,
we'll switch to Ubuntu Jammy (22.04).

While at it, we're disabling Cinder Backup, which isn't used while
testing Watched. It currently causes Devstack failures since it
uses the Swift backend by default, which is disabled.

[1] https://paste.opendev.org/raw/bjQ1uIdbDMnmA1UEhxLL/
[2] https://paste.opendev.org/raw/bNgxqulBwBLYB7tNhrU4/
[3] ab0dcbdda2
[4] https://github.com/python-jsonschema/jsonschema/releases/tag/v4.18.0a1
[5] c23a5dc1c9/referencing/jsonschema.py (L54-L55C18)
[6] https://paste.openstack.org/raw/bSoSyXgbtmq6d9768HQn/

Change-Id: I300620c2ec4857b1e0d402a9b57a637f576eeb24
2023-10-23 09:21:55 +03:00
OpenStack Release Bot
9f0eca2343 Update master for stable/2023.2
Add file to the reno documentation build to show release notes for
stable/2023.2.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/2023.2.

Sem-Ver: feature
Change-Id: I8a0c75ce5a4e5ae5cccd8eb1cb0325747a619122
2023-09-14 01:24:43 +00:00
Zuul
1e11c490a7 Merge "Add timeout option for Grafana request" 2023-08-29 11:21:46 +00:00
Zuul
8a7a8db661 Merge "Imported Translations from Zanata" 2023-08-28 06:21:40 +00:00
BubaVV
0610070e59 Add timeout option for Grafana request
Implemented config option to setup Grafana API request timeout

Change-Id: I8cbf8ce22f199fe22c0b162ba1f419169881f193
2023-08-23 17:46:19 +03:00
OpenStack Proposal Bot
a0997a0423 Imported Translations from Zanata
For more information about this automatic import see:
https://docs.openstack.org/i18n/latest/reviewing-translation-import.html

Change-Id: I37201577bd8d9c53db8ce6700f47d911359da6d2
2023-08-14 04:24:29 +00:00
chenker
4ea3eada3e Fix watcher comment
Change-Id: I4512cf1032e08934886d5e3ca858b3e05c3da76c
2023-08-13 00:00:12 +00:00
Zuul
cd1c0f3054 Merge "Imported Translations from Zanata" 2023-03-08 07:04:33 +00:00
OpenStack Proposal Bot
684350977d Imported Translations from Zanata
For more information about this automatic import see:
https://docs.openstack.org/i18n/latest/reviewing-translation-import.html

Change-Id: I4ee251e6d37a1b955c22dc6fdc04c1a08c9ae9b8
2023-03-02 03:28:31 +00:00
OpenStack Release Bot
d28630b759 Update master for stable/2023.1
Add file to the reno documentation build to show release notes for
stable/2023.1.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/2023.1.

Sem-Ver: feature
Change-Id: Ia585893e7fef42e9991a2b81f604d1ff28c0a5ad
2023-02-28 13:31:08 +00:00
Zuul
f7fbaf46a2 Merge "Use new get_rpc_client API from oslo.messaging" 2023-02-09 01:25:15 +00:00
Zuul
e7cda537e7 Merge "Modify saving_energy log info" 2023-02-07 12:18:58 +00:00
chenker
c7be34fbaa update saving_energy docs
Change-Id: I3b0c86911a8d32912c2de2e2392af9539b8d9be0
2023-02-07 10:27:54 +00:00
chenker
52da088011 Modify saving_energy log info
Change-Id: I84879a453aa3ff78917d1136c62978b9d0e606de
2023-02-07 10:20:04 +00:00
Tobias Urdin
6ac3a6febf Fix passenv in tox.ini
Change-Id: If1ddb1d48eeb96191bcbfadd1a5e14f4350a02e4
2023-02-07 08:02:20 +00:00
Tobias Urdin
e36b77ad6d Use new get_rpc_client API from oslo.messaging
Use the new API that is consistent with
the existing API instead of instantiating the client
class directly.

This was introduced in release 14.1.0 here [1] and
added into oslo.messaging here [2]

[1] https://review.opendev.org/c/openstack/requirements/+/869340
[2] https://review.opendev.org/c/openstack/oslo.messaging/+/862419

Change-Id: I43c399a0c68473e40b8b71e9617c8334a439e675
2023-01-19 20:50:26 +00:00
Thierry Carrez
6003322711 Move queue declaration to project level
This moves the watcher queue declaration from the pipeline level
(where it is no longer valid) to the project level.

https: //lists.openstack.org/pipermail/openstack-discuss/2022-May/028603.html
Change-Id: I06923abb00f7eecd59587f44cd1f6a069e88a9fc
2022-09-26 14:19:58 +02:00
Zuul
f4ffca01b8 Merge "Switch to 2023.1 Python3 unit tests and generic template name" 2022-09-16 06:36:21 +00:00
Alfredo Moralejo
5d70c207cd 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.

Co-Authored-By: Stephen Finucane <stephenfin@redhat.com>
Change-Id: I7db39d958d087322bfa0aad70dfbd04de9228dd7
2022-09-15 16:52:41 +02:00
OpenStack Release Bot
0b2e641d00 Switch to 2023.1 Python3 unit tests and generic template name
This is an automatically generated patch to ensure unit testing
is in place for all the of the tested runtimes for antelope. Also,
updating the template name to generic one.

See also the PTI in governance [1].

[1]: https://governance.openstack.org/tc/reference/project-testing-interface.html

Change-Id: Ide6c6c398f8e6cdd590c6620a752ad802a1f5cf8
2022-09-13 12:30:33 +00:00
OpenStack Release Bot
ff84b052a5 Update master for stable/zed
Add file to the reno documentation build to show release notes for
stable/zed.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/zed.

Sem-Ver: feature
Change-Id: I1726e33a14038712dbb9fd5e5c0cddf8ad872e69
2022-09-13 12:30:32 +00:00
Zuul
a43b040ebc Merge "Imported Translations from Zanata" 2022-08-30 10:44:52 +00:00
Zuul
749fa2507a Merge "Tests: fix requirements for unit tests" 2022-08-30 08:15:05 +00:00
OpenStack Proposal Bot
76d61362ee Imported Translations from Zanata
For more information about this automatic import see:
https://docs.openstack.org/i18n/latest/reviewing-translation-import.html

Change-Id: I95133dece6fdaf931dfed64015806430ba8d04f0
2022-08-29 04:12:15 +00:00
wangjiaqi07
c55143bc21 remove unicode from code
Change-Id: I747445d482a2fb40c2f39139c5fd2a0cb26c27bc
2022-08-19 14:17:10 +08:00
suzhengwei
7609df3370 Tests: fix requirements for unit tests
Add WebTest to test-requirements which used to be imported as a
transitive requirement via pecan, but the latest release of
pecan dropped this dependency. So make this requirement explicit.

Related-Bug: #1982110
Change-Id: I4852be23b489257aaa56d3fa22d27f72bcabf919
2022-07-28 16:14:13 +08:00
chenker
b57eac12cb Watcher DB upgrde compatibility consideration for add_apscheduler_jobs
Change-Id: I8896ff5731bb8c1bf88a5d7b926bd2a884100ea8
2022-04-28 02:21:06 +00:00
OpenStack Release Bot
ac6911d3c4 Add Python3 zed unit tests
This is an automatically generated patch to ensure unit testing
is in place for all the of the tested runtimes for zed.

See also the PTI in governance [1].

[1]: https://governance.openstack.org/tc/reference/project-testing-interface.html

Change-Id: I5cf874842550de18ff777b909fd28e2c32e6d530
2022-03-10 12:14:06 +00:00
OpenStack Release Bot
23c2010681 Update master for stable/yoga
Add file to the reno documentation build to show release notes for
stable/yoga.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/yoga.

Sem-Ver: feature
Change-Id: Ic7c275b38fef9afc29577f81fe92546bb94b2930
2022-03-10 12:14:04 +00:00
zhurong
01d74d0a87 Remove ceilometerclient dependecy
Change-Id: Ifa0f2493aa8414a29dc2722b6636a33bc5808be6
2022-01-07 05:48:22 +00:00
OpenStack Release Bot
e4fab0ce7f Add Python3 yoga unit tests
This is an automatically generated patch to ensure unit testing
is in place for all the of the tested runtimes for yoga.

See also the PTI in governance [1].

[1]: https://governance.openstack.org/tc/reference/project-testing-interface.html

Change-Id: I328b3ccb76153fa0dbb4d174dd976412be049200
2021-09-15 17:14:09 +00:00
OpenStack Release Bot
76ecaaeb3a Update master for stable/xena
Add file to the reno documentation build to show release notes for
stable/xena.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/xena.

Sem-Ver: feature
Change-Id: If1c02305a153575c6a550844b0c6f45b74ea5ef3
2021-09-15 17:14:07 +00:00
chenker
6dd2f2a9c1 BugFix: Prevent float type variables from being passed to random
>>> random.sample([5,10], 1.3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python3.6/random.py", line 321, in sample
    result = [None] * k
TypeError: can't multiply sequence by non-int of type 'float'

Change-Id: Ifa5dca06f07220512579e4fe3c5c741aeffc71cc
2021-08-23 01:58:52 +00:00
Takashi Kajinami
a993849928 Use Block Storage API v3 instead of API v2
Block Storage API v2 was deprecated during Pike cycle and is being
removed during Xena cycle, and current v3 API should be used instead.

Change-Id: Ia5247742b31f5f07186ef908588f0972d3ac609f
2021-07-27 11:04:16 +09:00
Zuul
6dbac1f6ae Merge "Add watcher dashboard to devstack documentation" 2021-07-13 14:31:16 +00:00
sue
c28756c48b use HTTPStatus instead of direct code
Python introduced http.HTTPStatus since version 3.5,
and Wallaby has targeted a minimum version of python 3.6.

Change-Id: I45f732f0f59b8fae831bb6c07f4fdd98cdd7409a
2021-07-09 11:02:36 +02:00
Dantali0n
2414f66e38 Add watcher dashboard to devstack documentation
Since installing watcher dashboard is fixed in devstack deployments
we can update documentation so it recommends to install dashboard
plugin.

Change-Id: I284a1ec31536ea258cc1979ffd46b22d3e1ac18b
2021-07-09 10:37:28 +02:00
Dantali0n
546b730c9b Changed minversion in tox to 3.18.0
The patch bumps min version of tox to 3.18.0 in order to
replace tox's whitelist_externals by allowlist_externals option:
https://github.com/tox-dev/tox/blob/master/docs/changelog.rst#v3180-2020-07-23

Change-Id: I00b6af1560c84d0b99b6044078c1d65d22b206b0
2021-07-06 12:48:55 +02:00
Zuul
75be54aa89 Merge "Manage constraints with testenv install_command" 2021-07-06 07:25:03 +00:00
Zuul
4e9e75f4a0 Merge "Enable tls-proxy as default in test jobs" 2021-07-05 14:17:37 +00:00
Dantali0n
e0779175cf Manage constraints with testenv install_command
This prevents having to duplicate the -c{} deps argument
across all environments in tox.ini

Change-Id: I621b581417f6967271b3a93385d592098689ae9e
2021-07-02 10:43:44 +00:00
songwenping
1235153b4c Use py3 as the default runtime for tox
Moving on py3 as the default runtime for tox to avoid to update this at
each new cycle.

Wallaby support officially the following runtimes [1]:
- Python 3.6
- Python 3.8

During Victoria Python 3.7 was used as the default runtime [2] however this
version isn't longer officially supported.

[1] https://governance.openstack.org/tc/reference/runtimes/wallaby.html#python-runtimes-for-wallaby
[2] https://governance.openstack.org/tc/reference/runtimes/victoria.html#python-runtimes-for-victoria

Change-Id: Id4b5cb679c60fda4132a10f684ed5128c0965230
2021-07-01 09:37:08 +00:00
Zuul
bf5ce9aa3f Merge "setup.cfg: Replace dashes with underscores" 2021-07-01 09:06:01 +00:00
ricolin
204992ff6f Enable tls-proxy as default in test jobs
Change-Id: Idbc8850269d84d0a3041c17f4453b00452c9dab8
2021-07-01 08:25:12 +00:00
Zuul
386e288543 Merge "Add Python3 xena unit tests" 2021-07-01 07:59:41 +00:00
maaoyu
6f668133ad setup.cfg: Replace dashes with underscores
Setuptools v54.1.0 introduces a warning that the use of dash-separated
options in 'setup.cfg' will not be supported in a future version [1].
Get ahead of the issue by replacing the dashes with underscores. Without
this, we see 'UserWarning' messages like the following on new enough
versions of setuptools:

  UserWarning: Usage of dash-separated 'description-file' will not be
  supported in future versions. Please use the underscore name
  'description_file' instead

[1] https://github.com/pypa/setuptools/commit/a2e9ae4cb

Change-Id: Ide4d650a78829a6bc16d86b620e6b3fbed0bba06
2021-07-01 07:19:01 +00:00
Zuul
fb625bfa56 Merge "Update master for stable/wallaby" 2021-06-30 15:27:12 +00:00
Zuul
32cb132712 Merge "requirements: Drop os-testr" 2021-06-30 11:48:43 +00:00
ericxiett
9ca44fa3ab Replace deprecated with_lockmode with with_for_update
The Query.with_lockmode() method is deprecated since version 0.9.0
and will be removed in a future release. [1]
This patch replaces it with Query.with_for_update().
The 'faultstring' was been modified to 'Exactly 5 or 6 columns has to be
specified for iterator expression', so adds one space between "iterator"
and "expression" for 'expected_error_msg'.

Also use upper-constraints in doc build to avoid issues in pdf build.

[1]
https://docs.sqlalchemy.org/en/13/orm/query.html#sqlalchemy.orm.query.Query.with_lockmode

Closes-Bug: #1933226
Change-Id: I0ad514da647bb08790259fd27e56a41f6dbbbaa0
2021-06-30 09:18:54 +00:00
OpenStack Release Bot
2205f4e4e3 Add Python3 xena unit tests
This is an automatically generated patch to ensure unit testing
is in place for all the of the tested runtimes for xena.

See also the PTI in governance [1].

[1]: https://governance.openstack.org/tc/reference/project-testing-interface.html

Change-Id: Ib957dae35926bf4c18e5a0c126904bbc67939f21
2021-03-22 10:01:44 +00:00
OpenStack Release Bot
7cd4373707 Update master for stable/wallaby
Add file to the reno documentation build to show release notes for
stable/wallaby.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/wallaby.

Sem-Ver: feature
Change-Id: Ic38b5071799ca733545381e79b956d7f82db2a87
2021-03-22 10:01:40 +00:00
wangzihao
a2123088bf requirements: Drop os-testr
Drop os-testr switched to stestr

Change-Id: I116f6028641ab38a611c8085b145a2ef796aea8e
2021-03-12 15:08:43 +08:00
214 changed files with 4544 additions and 2417 deletions

62
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,62 @@
---
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
# whitespace
- id: trailing-whitespace
- id: mixed-line-ending
args: ['--fix', 'lf']
exclude: '.*\.(svg)$'
- id: check-byte-order-marker
# file format and permissions
- id: check-ast
- id: debug-statements
- id: check-json
files: .*\.json$
- id: check-yaml
files: .*\.(yaml|yml)$
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
# git
- id: check-added-large-files
- id: check-case-conflict
- id: detect-private-key
- id: check-merge-conflict
- repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.5.5
hooks:
- id: remove-tabs
exclude: '.*\.(svg)$'
- repo: https://opendev.org/openstack/hacking
rev: 7.0.0
hooks:
- id: hacking
additional_dependencies: []
exclude: '^(doc|releasenotes|tools)/.*$'
- repo: https://github.com/PyCQA/bandit
rev: 1.7.6
hooks:
- id: bandit
args: ['-x', 'tests', '-s', 'B101,B311,B320']
- repo: https://github.com/hhatto/autopep8
rev: v2.3.1
hooks:
- id: autopep8
files: '^.*\.py$'
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
hooks:
- id: codespell
args: ['--ignore-words=doc/dictionary.txt']
- repo: https://github.com/sphinx-contrib/sphinx-lint
rev: v1.0.0
hooks:
- id: sphinx-lint
args: [--enable=default-role]
files: ^doc/|releasenotes|api-guide
types: [rst]
- repo: https://github.com/PyCQA/doc8
rev: v1.1.2
hooks:
- id: doc8

View File

@@ -1,85 +1,33 @@
- project:
queue: watcher
templates:
- check-requirements
- openstack-cover-jobs
- openstack-python3-wallaby-jobs
- openstack-python3-jobs
- publish-openstack-docs-pti
- release-notes-jobs-python3
check:
jobs:
- watcher-tempest-functional
- watcher-tempest-functional-jammy
- watcher-grenade
- watcher-tempest-strategies
- watcher-tempest-actuator
- watcherclient-tempest-functional
- watcher-tls-test
- watcher-tempest-functional-ipv6-only
- watcher-prometheus-integration
gate:
queue: watcher
jobs:
- watcher-tempest-functional
- watcher-tempest-functional-jammy
- watcher-tempest-functional-ipv6-only
- job:
name: watcher-tempest-dummy_optim
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_dummy_optim
- job:
name: watcher-tempest-actuator
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_actuator
- job:
name: watcher-tempest-basic_optim
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_basic_optim
- job:
name: watcher-tempest-vm_workload_consolidation
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_vm_workload_consolidation
devstack_local_conf:
test-config:
$WATCHER_CONFIG:
watcher_strategies.vm_workload_consolidation:
datasource: ceilometer
- job:
name: watcher-tempest-workload_balancing
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_workload_balancing
- job:
name: watcher-tempest-zone_migration
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_zone_migration
- job:
name: watcher-tempest-host_maintenance
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_host_maintenance
- job:
name: watcher-tempest-storage_balance
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_storage_balance
devstack_local_conf:
test-config:
$TEMPEST_CONFIG:
volume:
backend_names: ['BACKEND_1', 'BACKEND_2']
volume-feature-enabled:
multi_backend: true
- job:
name: watcher-tempest-strategies
parent: watcher-tempest-multinode
@@ -87,21 +35,10 @@
tempest_concurrency: 1
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_strategies
- job:
name: watcher-tls-test
parent: watcher-tempest-multinode
group-vars:
subnode:
devstack_services:
tls-proxy: true
vars:
devstack_services:
tls-proxy: true
- job:
name: watcher-tempest-multinode
parent: watcher-tempest-functional
nodeset: openstack-two-node-focal
nodeset: openstack-two-node-noble
roles:
- zuul: openstack/tempest
group-vars:
@@ -119,8 +56,7 @@
watcher-api: false
watcher-decision-engine: true
watcher-applier: false
# We need to add TLS support for watcher plugin
tls-proxy: false
c-bak: false
ceilometer: false
ceilometer-acompute: false
ceilometer-acentral: false
@@ -168,7 +104,6 @@
devstack_plugins:
watcher: https://opendev.org/openstack/watcher
devstack_services:
tls-proxy: false
watcher-api: true
watcher-decision-engine: true
watcher-applier: true
@@ -184,6 +119,17 @@
zuul_copy_output:
/etc/hosts: logs
# TODO(gmann): As per the 2025.1 testing runtime, we need to run at least
# one job on jammy. This job can be removed in the next cycle(2025.2)
- job:
name: watcher-tempest-functional-jammy
description: This is integrated job testing on Ubuntu jammy(22.04)
parent: watcher-tempest-functional
nodeset: openstack-single-node-jammy
vars:
<<: *base_vars
python_version: '3.9'
- job:
name: watcher-tempest-functional-ipv6-only
parent: devstack-tempest-ipv6
@@ -200,7 +146,7 @@
- openstack/python-watcherclient
- openstack/watcher-tempest-plugin
vars: *base_vars
irrelevant-files:
irrelevant-files: &irrelevent_files
- ^(test-|)requirements.txt$
- ^.*\.rst$
- ^api-ref/.*$
@@ -220,3 +166,124 @@
vars:
tempest_concurrency: 1
tempest_test_regex: watcher_tempest_plugin.tests.client_functional
- job:
name: watcher-sg-core-tempest-base
parent: devstack-tempest
nodeset: openstack-two-node-noble
description: |
This job is for testing watcher and sg-core/prometheus installation
abstract: true
pre-run:
- playbooks/generate_prometheus_config.yml
irrelevant-files: *irrelevent_files
timeout: 7800
required-projects: &base_sg_required_projects
- openstack/aodh
- openstack/ceilometer
- openstack/tempest
- openstack-k8s-operators/sg-core
- openstack/watcher
- openstack/python-watcherclient
- openstack/watcher-tempest-plugin
- openstack/devstack-plugin-prometheus
vars:
configure_swap_size: 8192
devstack_plugins:
ceilometer: https://opendev.org/openstack/ceilometer
aodh: https://opendev.org/openstack/aodh
sg-core: https://github.com/openstack-k8s-operators/sg-core
watcher: https://opendev.org/openstack/watcher
devstack-plugin-prometheus: https://opendev.org/openstack/devstack-plugin-prometheus
devstack_services:
watcher-api: true
watcher-decision-engine: true
watcher-applier: true
tempest: true
# We do not need Swift in this job so disable it for speed
# Swift services
s-account: false
s-container: false
s-object: false
s-proxy: false
# Prometheus related service
prometheus: true
node_exporter: true
devstack_localrc:
CEILOMETER_BACKENDS: "sg-core"
CEILOMETER_PIPELINE_INTERVAL: 15
CEILOMETER_ALARM_THRESHOLD: 6000000000
NODE_EXPORTER_ENABLE: false
PROMETHEUS_ENABLE: false
PROMETHEUS_SERVICE_SCRAPE_TARGETS: "sg-core,node-exporter"
PROMETHEUS_CONFIG_FILE: "/home/zuul/prometheus.yml"
devstack_local_conf:
post-config:
$WATCHER_CONF:
watcher_datasources:
datasources: prometheus
prometheus_client:
host: 127.0.0.1
port: 9090
watcher_cluster_data_model_collectors.compute:
period: 120
watcher_cluster_data_model_collectors.baremetal:
period: 120
watcher_cluster_data_model_collectors.storage:
period: 120
test-config:
$TEMPEST_CONFIG:
compute:
min_compute_nodes: 2
min_microversion: 2.56
compute-feature-enabled:
live_migration: true
block_migration_for_live_migration: true
placement:
min_microversion: 1.29
service_available:
sg_core: True
telemetry_services:
metric_backends: prometheus
telemetry:
disable_ssl_certificate_validation: True
ceilometer_polling_interval: 15
optimize:
datasource: prometheus
tempest_plugins:
- watcher-tempest-plugin
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_strategies
tempest_concurrency: 1
tox_envlist: all
zuul_copy_output:
/etc/prometheus/prometheus.yml: logs
group-vars:
subnode:
devstack_plugins:
ceilometer: https://opendev.org/openstack/ceilometer
sg-core: https://github.com/openstack-k8s-operators/sg-core
devstack-plugin-prometheus: https://opendev.org/openstack/devstack-plugin-prometheus
devstack_services:
ceilometer-acompute: true
sg-core: false
prometheus: false
node_exporter: true
devstack_localrc:
CEILOMETER_BACKEND: "none"
CEILOMETER_BACKENDS: "none"
# sg_core related var
NODE_EXPORTER_ENABLE: false
PROMETHEUS_ENABLE: false
devstack_local_conf:
post-config:
$WATCHER_CONF:
watcher_cluster_data_model_collectors.compute:
period: 120
watcher_cluster_data_model_collectors.baremetal:
period: 120
watcher_cluster_data_model_collectors.storage:
period: 120
- job:
name: watcher-prometheus-integration
parent: watcher-sg-core-tempest-base

View File

@@ -30,7 +30,7 @@
}
},
"auto_trigger": false,
"force": false,
"force": false,
"uuid": "65a5da84-5819-4aea-8278-a28d2b489028",
"goal_name": "workload_balancing",
"scope": [],

View File

@@ -13,9 +13,9 @@
"node_vcpu_ratio": "16.0",
"node_memory": "16383",
"node_memory_ratio": "1.5",
"node_disk": "37"
"node_disk": "37",
"node_disk_ratio": "1.0",
"node_state": "up",
"node_state": "up"
},
{
"server_uuid": "e2cb5f6f-fa1d-4ba2-be1e-0bf02fa86ba4",
@@ -30,9 +30,9 @@
"node_vcpu_ratio": "16.0",
"node_memory": "16383",
"node_memory_ratio": "1.5",
"node_disk": "37"
"node_disk": "37",
"node_disk_ratio": "1.0",
"node_state": "up",
"node_state": "up"
}
]
}

View File

@@ -12,7 +12,7 @@ Here are some examples of ``Goals``:
- minimize the energy consumption
- minimize the number of compute nodes (consolidation)
- balance the workload among compute nodes
- minimize the license cost (some softwares have a licensing model which is
- minimize the license cost (some software have a licensing model which is
based on the number of sockets or cores where the software is deployed)
- find the most appropriate moment for a planned maintenance on a
given group of host (which may be an entire availability zone):

View File

@@ -1,5 +1,3 @@
#!/bin/bash
#
# lib/watcher
# Functions to control the configuration and operation of the watcher services
@@ -38,7 +36,6 @@ GITBRANCH["python-watcherclient"]=${WATCHERCLIENT_BRANCH:-master}
GITDIR["python-watcherclient"]=$DEST/python-watcherclient
WATCHER_STATE_PATH=${WATCHER_STATE_PATH:=$DATA_DIR/watcher}
WATCHER_AUTH_CACHE_DIR=${WATCHER_AUTH_CACHE_DIR:-/var/cache/watcher}
WATCHER_CONF_DIR=/etc/watcher
WATCHER_CONF=$WATCHER_CONF_DIR/watcher.conf
@@ -103,7 +100,7 @@ function _cleanup_watcher_apache_wsgi {
# cleanup_watcher() - Remove residual data files, anything left over from previous
# runs that a clean run would need to clean up
function cleanup_watcher {
sudo rm -rf $WATCHER_STATE_PATH $WATCHER_AUTH_CACHE_DIR
sudo rm -rf $WATCHER_STATE_PATH
if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
remove_uwsgi_config "$WATCHER_UWSGI_CONF" "$WATCHER_UWSGI"
else
@@ -210,8 +207,8 @@ function create_watcher_conf {
iniset $WATCHER_CONF oslo_messaging_notifications driver "messagingv2"
configure_auth_token_middleware $WATCHER_CONF watcher $WATCHER_AUTH_CACHE_DIR
configure_auth_token_middleware $WATCHER_CONF watcher $WATCHER_AUTH_CACHE_DIR "watcher_clients_auth"
configure_keystone_authtoken_middleware $WATCHER_CONF watcher
configure_keystone_authtoken_middleware $WATCHER_CONF watcher "watcher_clients_auth"
if is_fedora || is_suse; then
# watcher defaults to /usr/local/bin, but fedora and suse pip like to
@@ -248,13 +245,6 @@ function create_watcher_conf {
fi
}
# create_watcher_cache_dir() - Part of the init_watcher() process
function create_watcher_cache_dir {
# Create cache dir
sudo install -d -o $STACK_USER $WATCHER_AUTH_CACHE_DIR
rm -rf $WATCHER_AUTH_CACHE_DIR/*
}
# init_watcher() - Initialize databases, etc.
function init_watcher {
# clean up from previous (possibly aborted) runs
@@ -266,7 +256,6 @@ function init_watcher {
# Create watcher schema
$WATCHER_BIN_DIR/watcher-db-manage --config-file $WATCHER_CONF upgrade
fi
create_watcher_cache_dir
}
# install_watcherclient() - Collect source and prepare
@@ -275,6 +264,9 @@ function install_watcherclient {
git_clone_by_name "python-watcherclient"
setup_dev_lib "python-watcherclient"
fi
if [[ "$GLOBAL_VENV" == "True" ]]; then
sudo ln -sf /opt/stack/data/venv/bin/watcher /usr/local/bin
fi
}
# install_watcher() - Collect source and prepare

View File

@@ -1,5 +1,3 @@
#!/bin/bash
#
# plugin.sh - DevStack plugin script to install watcher
# Save trace setting

View File

@@ -1,5 +1,3 @@
#!/usr/bin/env bash
# ``upgrade-watcher``
function configure_watcher_upgrade {

View File

@@ -70,7 +70,7 @@ then write_uwsgi_config "$WATCHER_UWSGI_CONF" "$WATCHER_UWSGI" "/infra-optim"
fi
# Migrate the database
watcher-db-manage upgrade || die $LINO "DB migration error"
$WATCHER_BIN_DIR/watcher-db-manage upgrade || die $LINO "DB migration error"
start_watcher

4
doc/dictionary.txt Normal file
View File

@@ -0,0 +1,4 @@
thirdparty
assertin
notin

View File

@@ -52,7 +52,7 @@ class BaseWatcherDirective(rst.Directive):
obj_raw_docstring = obj.__init__.__doc__
if not obj_raw_docstring:
# Raise a warning to make the tests fail wit doc8
# Raise a warning to make the tests fail with doc8
raise self.error("No docstring available for %s!" % obj)
obj_docstring = inspect.cleandoc(obj_raw_docstring)

View File

@@ -1,10 +1,10 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
openstackdocstheme>=2.2.1 # Apache-2.0
sphinx>=2.0.0,!=2.1.0 # BSD
sphinxcontrib-pecanwsme>=0.8.0 # Apache-2.0
sphinx>=2.1.1 # BSD
sphinxcontrib-svg2pdfconverter>=0.1.0 # BSD
reno>=3.1.0 # Apache-2.0
sphinxcontrib-pecanwsme>=0.8.0 # Apache-2.0
sphinxcontrib-apidoc>=0.2.0 # BSD
# openstack
os-api-ref>=1.4.0 # Apache-2.0
openstackdocstheme>=2.2.1 # Apache-2.0
# releasenotes
reno>=3.1.0 # Apache-2.0

View File

@@ -34,7 +34,7 @@ own sections. However, the base *GMR* consists of several sections:
Package
Shows information about the package to which this process belongs, including
version informations.
version information.
Threads
Shows stack traces and thread ids for each of the threads within this

View File

@@ -285,7 +285,7 @@ Audit and interval (in case of CONTINUOUS type). There is three types of Audit:
ONESHOT, CONTINUOUS and EVENT. ONESHOT Audit is launched once and if it
succeeded executed new action plan list will be provided; CONTINUOUS Audit
creates action plans with specified interval (in seconds or cron format, cron
inteval can be used like: `*/5 * * * *`), if action plan
interval can be used like: ``*/5 * * * *``), if action plan
has been created, all previous action plans get CANCELLED state;
EVENT audit is launched when receiving webhooks API.

22
doc/source/conf.py Executable file → Normal file
View File

@@ -56,8 +56,8 @@ source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
project = u'Watcher'
copyright = u'OpenStack Foundation'
project = 'Watcher'
copyright = 'OpenStack Foundation'
# A list of ignored prefixes for module index sorting.
modindex_common_prefix = ['watcher.']
@@ -91,14 +91,14 @@ pygments_style = 'native'
# List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual'
man_pages = [
('man/watcher-api', 'watcher-api', u'Watcher API Server',
[u'OpenStack'], 1),
('man/watcher-applier', 'watcher-applier', u'Watcher Applier',
[u'OpenStack'], 1),
('man/watcher-api', 'watcher-api', 'Watcher API Server',
['OpenStack'], 1),
('man/watcher-applier', 'watcher-applier', 'Watcher Applier',
['OpenStack'], 1),
('man/watcher-db-manage', 'watcher-db-manage',
u'Watcher Db Management Utility', [u'OpenStack'], 1),
'Watcher Db Management Utility', ['OpenStack'], 1),
('man/watcher-decision-engine', 'watcher-decision-engine',
u'Watcher Decision Engine', [u'OpenStack'], 1),
'Watcher Decision Engine', ['OpenStack'], 1),
]
# -- Options for HTML output --------------------------------------------------
@@ -115,7 +115,7 @@ html_theme = 'openstackdocs'
htmlhelp_basename = '%sdoc' % project
#openstackdocstheme options
# openstackdocstheme options
openstackdocs_repo_name = 'openstack/watcher'
openstackdocs_pdf_link = True
openstackdocs_auto_name = False
@@ -128,8 +128,8 @@ openstackdocs_bug_tag = ''
latex_documents = [
('index',
'doc-watcher.tex',
u'Watcher Documentation',
u'OpenStack Foundation', 'manual'),
'Watcher Documentation',
'OpenStack Foundation', 'manual'),
]
# If false, no module index is generated.

View File

@@ -194,11 +194,14 @@ The configuration file is organized into the following sections:
* ``[watcher_applier]`` - Watcher Applier module configuration
* ``[watcher_decision_engine]`` - Watcher Decision Engine module configuration
* ``[oslo_messaging_rabbit]`` - Oslo Messaging RabbitMQ driver configuration
* ``[ceilometer_client]`` - Ceilometer client configuration
* ``[cinder_client]`` - Cinder client configuration
* ``[glance_client]`` - Glance client configuration
* ``[gnocchi_client]`` - Gnocchi client configuration
* ``[ironic_client]`` - Ironic client configuration
* ``[keystone_client]`` - Keystone client configuration
* ``[nova_client]`` - Nova client configuration
* ``[neutron_client]`` - Neutron client configuration
* ``[placement_client]`` - Placement client configuration
The Watcher configuration file is expected to be named
``watcher.conf``. When starting Watcher, you can specify a different
@@ -372,7 +375,7 @@ You can configure and install Ceilometer by following the documentation below :
#. https://docs.openstack.org/ceilometer/latest
The built-in strategy 'basic_consolidation' provided by watcher requires
"**compute.node.cpu.percent**" and "**cpu_util**" measurements to be collected
"**compute.node.cpu.percent**" and "**cpu**" measurements to be collected
by Ceilometer.
The measurements available depend on the hypervisors that OpenStack manages on
the specific implementation.

View File

@@ -221,7 +221,7 @@ workflow engine can halt or take other actions while the action plan is being
executed based on the success or failure of individual actions. However, the
base workflow engine simply uses these notifies to store the result of
individual actions in the database. Additionally, since taskflow uses a graph
flow if any of the tasks would fail all childs of this tasks not be executed
flow if any of the tasks would fail all children of this tasks not be executed
while ``do_revert`` will be triggered for all parents.
.. code-block:: python

View File

@@ -16,7 +16,7 @@ multinode environment to use.
You can set up the Watcher services quickly and easily using a Watcher
DevStack plugin. See `PluginModelDocs`_ for information on DevStack's plugin
model. To enable the Watcher plugin with DevStack, add the following to the
`[[local|localrc]]` section of your controller's `local.conf` to enable the
``[[local|localrc]]`` section of your controller's ``local.conf`` to enable the
Watcher plugin::
enable_plugin watcher https://opendev.org/openstack/watcher
@@ -32,7 +32,7 @@ Quick Devstack Instructions with Datasources
Watcher requires a datasource to collect metrics from compute nodes and
instances in order to execute most strategies. To enable this a
`[[local|localrc]]` to setup DevStack for some of the supported datasources
``[[local|localrc]]`` to setup DevStack for some of the supported datasources
is provided. These examples specify the minimal configuration parameters to
get both Watcher and the datasource working but can be expanded is desired.
@@ -41,52 +41,60 @@ Gnocchi
With the Gnocchi datasource most of the metrics for compute nodes and
instances will work with the provided configuration but metrics that
require Ironic such as `host_airflow and` `host_power` will still be
unavailable as well as `instance_l3_cpu_cache`::
require Ironic such as ``host_airflow and`` ``host_power`` will still be
unavailable as well as ``instance_l3_cpu_cache``
[[local|localrc]]
enable_plugin watcher https://opendev.org/openstack/watcher
.. code-block:: ini
enable_plugin ceilometer https://opendev.org/openstack/ceilometer.git
CEILOMETER_BACKEND=gnocchi
[[local|localrc]]
enable_plugin aodh https://opendev.org/openstack/aodh
enable_plugin panko https://opendev.org/openstack/panko
enable_plugin watcher https://opendev.org/openstack/watcher
enable_plugin watcher-dashboard https://opendev.org/openstack/watcher-dashboard
enable_plugin ceilometer https://opendev.org/openstack/ceilometer.git
enable_plugin aodh https://opendev.org/openstack/aodh
enable_plugin panko https://opendev.org/openstack/panko
[[post-config|$NOVA_CONF]]
[DEFAULT]
compute_monitors=cpu.virt_driver
CEILOMETER_BACKEND=gnocchi
[[post-config|$NOVA_CONF]]
[DEFAULT]
compute_monitors=cpu.virt_driver
Detailed DevStack Instructions
==============================
#. Obtain N (where N >= 1) servers (virtual machines preferred for DevStack).
One of these servers will be the controller node while the others will be
compute nodes. N is preferably >= 3 so that you have at least 2 compute
nodes, but in order to stand up the Watcher services only 1 server is
needed (i.e., no computes are needed if you want to just experiment with
the Watcher services). These servers can be VMs running on your local
machine via VirtualBox if you prefer. DevStack currently recommends that
you use Ubuntu 16.04 LTS. The servers should also have connections to the
same network such that they are all able to communicate with one another.
#. Obtain N (where N >= 1) servers (virtual machines preferred for DevStack).
One of these servers will be the controller node while the others will be
compute nodes. N is preferably >= 3 so that you have at least 2 compute
nodes, but in order to stand up the Watcher services only 1 server is
needed (i.e., no computes are needed if you want to just experiment with
the Watcher services). These servers can be VMs running on your local
machine via VirtualBox if you prefer. DevStack currently recommends that
you use Ubuntu 16.04 LTS. The servers should also have connections to the
same network such that they are all able to communicate with one another.
#. For each server, clone the DevStack repository and create the stack user::
#. For each server, clone the DevStack repository and create the stack user
sudo apt-get update
sudo apt-get install git
git clone https://opendev.org/openstack/devstack.git
sudo ./devstack/tools/create-stack-user.sh
.. code-block:: bash
sudo apt-get update
sudo apt-get install git
git clone https://opendev.org/openstack/devstack.git
sudo ./devstack/tools/create-stack-user.sh
Now you have a stack user that is used to run the DevStack processes. You
may want to give your stack user a password to allow SSH via a password::
may want to give your stack user a password to allow SSH via a password
sudo passwd stack
.. code-block:: bash
#. Switch to the stack user and clone the DevStack repo again::
sudo passwd stack
sudo su stack
cd ~
git clone https://opendev.org/openstack/devstack.git
#. Switch to the stack user and clone the DevStack repo again
.. code-block:: bash
sudo su stack
cd ~
git clone https://opendev.org/openstack/devstack.git
#. For each compute node, copy the provided `local.conf.compute`_ example file
to the compute node's system at ~/devstack/local.conf. Make sure the
@@ -109,24 +117,30 @@ Detailed DevStack Instructions
the HOST_IP value is changed appropriately - i.e., HOST_IP is set to the IP
address of the controller node.
Note: if you want to use another Watcher git repository (such as a local
one), then change the enable plugin line::
.. NOTE::
if you want to use another Watcher git repository (such as a local
one), then change the enable plugin line
.. code-block:: bash
enable_plugin watcher <your_local_git_repo> [optional_branch]
enable_plugin watcher <your_local_git_repo> [optional_branch]
If you do this, then the Watcher DevStack plugin will try to pull the
python-watcherclient repo from <your_local_git_repo>/../, so either make
sure that is also available or specify WATCHERCLIENT_REPO in the local.conf
python-watcherclient repo from ``<your_local_git_repo>/../``, so either make
sure that is also available or specify WATCHERCLIENT_REPO in the ``local.conf``
file.
Note: if you want to use a specific branch, specify WATCHER_BRANCH in the
local.conf file. By default it will use the master branch.
.. NOTE::
if you want to use a specific branch, specify WATCHER_BRANCH in the
local.conf file. By default it will use the master branch.
Note: watcher-api will default run under apache/httpd, set the variable
WATCHER_USE_MOD_WSGI=FALSE if you do not wish to run under apache/httpd.
For development environment it is suggested to set WATHCER_USE_MOD_WSGI
to FALSE. For Production environment it is suggested to keep it at the
default TRUE value.
.. Note::
watcher-api will default run under apache/httpd, set the variable
WATCHER_USE_MOD_WSGI=FALSE if you do not wish to run under apache/httpd.
For development environment it is suggested to set WATHCER_USE_MOD_WSGI
to FALSE. For Production environment it is suggested to keep it at the
default TRUE value.
#. Start stacking from the controller node::
@@ -134,8 +148,9 @@ Detailed DevStack Instructions
#. Start stacking on each of the compute nodes using the same command.
#. Configure the environment for live migration via NFS. See the
`Multi-Node DevStack Environment`_ section for more details.
.. seealso::
Configure the environment for live migration via NFS. See the
`Multi-Node DevStack Environment`_ section for more details.
.. _local.conf.controller: https://github.com/openstack/watcher/tree/master/devstack/local.conf.controller
.. _local.conf.compute: https://github.com/openstack/watcher/tree/master/devstack/local.conf.compute
@@ -147,60 +162,19 @@ Since deploying Watcher with only a single compute node is not very useful, a
few tips are given here for enabling a multi-node environment with live
migration.
Configuring NFS Server
----------------------
.. NOTE::
If you would like to use live migration for shared storage, then the controller
can serve as the NFS server if needed::
Nova supports live migration with local block storage so by default NFS
is not required and is considered an advance configuration.
The minimum requirements for live migration are:
sudo apt-get install nfs-kernel-server
sudo mkdir -p /nfs/instances
sudo chown stack:stack /nfs/instances
- all hostnames are resolvable on each host
- all hosts have a passwordless ssh key that is trusted by the other hosts
- all hosts have a known_hosts file that lists each hosts
Add an entry to `/etc/exports` with the appropriate gateway and netmask
information::
/nfs/instances <gateway>/<netmask>(rw,fsid=0,insecure,no_subtree_check,async,no_root_squash)
Export the NFS directories::
sudo exportfs -ra
Make sure the NFS server is running::
sudo service nfs-kernel-server status
If the server is not running, then start it::
sudo service nfs-kernel-server start
Configuring NFS on Compute Node
-------------------------------
Each compute node needs to use the NFS server to hold the instance data::
sudo apt-get install rpcbind nfs-common
mkdir -p /opt/stack/data/instances
sudo mount <nfs-server-ip>:/nfs/instances /opt/stack/data/instances
If you would like to have the NFS directory automatically mounted on reboot,
then add the following to `/etc/fstab`::
<nfs-server-ip>:/nfs/instances /opt/stack/data/instances nfs auto 0 0
Edit `/etc/libvirt/libvirtd.conf` to make sure the following values are set::
listen_tls = 0
listen_tcp = 1
auth_tcp = "none"
Edit `/etc/default/libvirt-bin`::
libvirtd_opts="-d -l"
Restart the libvirt service::
sudo service libvirt-bin restart
If these requirements are met live migration will be possible.
Shared storage such as ceph, booting form cinder volume or nfs are recommend
when testing evacuate if you want to preserve vm data.
Setting up SSH keys between compute nodes to enable live migration
------------------------------------------------------------------
@@ -229,22 +203,91 @@ must exist in every other compute node's stack user's authorized_keys file and
every compute node's public ECDSA key needs to be in every other compute
node's root user's known_hosts file.
Disable serial console
----------------------
Configuring NFS Server (ADVANCED)
---------------------------------
Serial console needs to be disabled for live migration to work.
If you would like to use live migration for shared storage, then the controller
can serve as the NFS server if needed
On both the controller and compute node, in /etc/nova/nova.conf
.. code-block:: bash
[serial_console]
enabled = False
sudo apt-get install nfs-kernel-server
sudo mkdir -p /nfs/instances
sudo chown stack:stack /nfs/instances
Alternatively, in devstack's local.conf:
Add an entry to ``/etc/exports`` with the appropriate gateway and netmask
information
[[post-config|$NOVA_CONF]]
[serial_console]
#enabled=false
.. code-block:: bash
/nfs/instances <gateway>/<netmask>(rw,fsid=0,insecure,no_subtree_check,async,no_root_squash)
Export the NFS directories
.. code-block:: bash
sudo exportfs -ra
Make sure the NFS server is running
.. code-block:: bash
sudo service nfs-kernel-server status
If the server is not running, then start it
.. code-block:: bash
sudo service nfs-kernel-server start
Configuring NFS on Compute Node (ADVANCED)
------------------------------------------
Each compute node needs to use the NFS server to hold the instance data
.. code-block:: bash
sudo apt-get install rpcbind nfs-common
mkdir -p /opt/stack/data/instances
sudo mount <nfs-server-ip>:/nfs/instances /opt/stack/data/instances
If you would like to have the NFS directory automatically mounted on reboot,
then add the following to ``/etc/fstab``
.. code-block:: bash
<nfs-server-ip>:/nfs/instances /opt/stack/data/instances nfs auto 0 0
Configuring libvirt to listen on tcp (ADVANCED)
-----------------------------------------------
.. NOTE::
By default nova will use ssh as a transport for live migration
if you have a low bandwidth connection you can use tcp instead
however this is generally not recommended.
Edit ``/etc/libvirt/libvirtd.conf`` to make sure the following values are set
.. code-block:: ini
listen_tls = 0
listen_tcp = 1
auth_tcp = "none"
Edit ``/etc/default/libvirt-bin``
.. code-block:: ini
libvirtd_opts="-d -l"
Restart the libvirt service
.. code-block:: bash
sudo service libvirt-bin restart
VNC server configuration
------------------------
@@ -252,13 +295,18 @@ VNC server configuration
The VNC server listening parameter needs to be set to any address so
that the server can accept connections from all of the compute nodes.
On both the controller and compute node, in /etc/nova/nova.conf
On both the controller and compute node, in ``/etc/nova/nova.conf``
vncserver_listen = 0.0.0.0
.. code-block:: ini
Alternatively, in devstack's local.conf:
[vnc]
server_listen = "0.0.0.0"
VNCSERVER_LISTEN=0.0.0.0
Alternatively, in devstack's ``local.conf``:
.. code-block:: bash
VNCSERVER_LISTEN="0.0.0.0"
Environment final checkup

View File

@@ -43,7 +43,7 @@ different version of the above, please document your configuration here!
Getting the latest code
=======================
Make a clone of the code from our `Git repository`:
Make a clone of the code from our ``Git repository``:
.. code-block:: bash
@@ -72,9 +72,9 @@ These dependencies can be installed from PyPi_ using the Python tool pip_.
.. _PyPi: https://pypi.org/
.. _pip: https://pypi.org/project/pip
However, your system *may* need additional dependencies that `pip` (and by
However, your system *may* need additional dependencies that ``pip`` (and by
extension, PyPi) cannot satisfy. These dependencies should be installed
prior to using `pip`, and the installation method may vary depending on
prior to using ``pip``, and the installation method may vary depending on
your platform.
* Ubuntu 16.04::
@@ -141,7 +141,7 @@ forget to activate it:
$ workon watcher
You should then be able to `import watcher` using Python without issue:
You should then be able to ``import watcher`` using Python without issue:
.. code-block:: bash

View File

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

View File

@@ -90,15 +90,15 @@ parameter will need to specify the type of http protocol and the use of
plain text http is strongly discouraged due to the transmission of the access
token. Additionally the path to the proxy interface needs to be supplied as
well in case Grafana is placed in a sub directory of the web server. An example
would be: `https://mygrafana.org/api/datasource/proxy/` were
`/api/datasource/proxy` is the default path without any subdirectories.
would be: ``https://mygrafana.org/api/datasource/proxy/`` were
``/api/datasource/proxy`` is the default path without any subdirectories.
Likewise, this parameter can not be placed in the yaml.
To prevent many errors from occurring and potentially filing the logs files it
is advised to specify the desired datasource in the configuration as it would
prevent the datasource manager from having to iterate and try possible
datasources with the launch of each audit. To do this specify `datasources` in
the `[watcher_datasources]` group.
datasources with the launch of each audit. To do this specify
``datasources`` in the ``[watcher_datasources]`` group.
The current configuration that is required to be placed in the traditional
configuration file would look like the following:
@@ -120,7 +120,7 @@ traditional configuration file or in the yaml, however, it is not advised to
mix and match but in the case it does occur the yaml would override the
settings from the traditional configuration file. All five of these parameters
are dictionaries mapping specific metrics to a configuration parameter. For
instance the `project_id_map` will specify the specific project id in Grafana
instance the ``project_id_map`` will specify the specific project id in Grafana
to be used. The parameters are named as follow:
* project_id_map
@@ -149,10 +149,10 @@ project_id
The project id's can only be determined by someone with the admin role in
Grafana as that role is required to open the list of projects. The list of
projects can be found on `/datasources` in the web interface but
projects can be found on ``/datasources`` in the web interface but
unfortunately it does not immediately display the project id. To display
the id one can best hover the mouse over the projects and the url will show the
project id's for example `/datasources/edit/7563`. Alternatively the entire
project id's for example ``/datasources/edit/7563``. Alternatively the entire
list of projects can be retrieved using the `REST api`_. To easily make
requests to the REST api a tool such as Postman can be used.
@@ -239,18 +239,24 @@ conversion from bytes to megabytes.
SELECT value/1000000 FROM memory...
Queries will be formatted using the .format string method within Python. This
format will currently have give attributes exposed to it labeled `{0}` to
`{4}`. Every occurrence of these characters within the string will be replaced
Queries will be formatted using the .format string method within Python.
This format will currently have give attributes exposed to it labeled
``{0}`` through ``{4}``.
Every occurrence of these characters within the string will be replaced
with the specific attribute.
- {0} is the aggregate typically `mean`, `min`, `max` but `count` is also
supported.
- {1} is the attribute as specified in the attribute parameter.
- {2} is the period of time to aggregate data over in seconds.
- {3} is the granularity or the interval between data points in seconds.
- {4} is translator specific and in the case of InfluxDB it will be used for
retention_periods.
{0}
is the aggregate typically ``mean``, ``min``, ``max`` but ``count``
is also supported.
{1}
is the attribute as specified in the attribute parameter.
{2}
is the period of time to aggregate data over in seconds.
{3}
is the granularity or the interval between data points in seconds.
{4}
is translator specific and in the case of InfluxDB it will be used for
retention_periods.
**InfluxDB**

View File

@@ -0,0 +1,140 @@
=====================
Prometheus datasource
=====================
Synopsis
--------
The Prometheus datasource allows Watcher to use a Prometheus server as the
source for collected metrics used by the Watcher decision engine. At minimum
deployers must configure the ``host`` and ``port`` at which the Prometheus
server is listening.
Requirements
-------------
It is required that Prometheus metrics contain a label to identify the hostname
of the exporter from which the metric was collected. This is used to match
against the Watcher cluster model ``ComputeNode.hostname``. The default for
this label is ``fqdn`` and in the prometheus scrape configs would look like:
.. code-block::
scrape_configs:
- job_name: node
static_configs:
- targets: ['10.1.2.3:9100']
labels:
fqdn: "testbox.controlplane.domain"
This default can be overridden when a deployer uses a different label to
identify the exporter host (for example ``hostname`` or ``host``, or any other
label, as long as it identifies the host).
Internally this label is used in creating a ``fqdn_instance_map``, mapping
the fqdn with the Prometheus instance label associated with each exporter.
The keys of the resulting fqdn_instance_map are expected to match the
``ComputeNode.hostname`` used in the Watcher decision engine cluster model.
An example ``fqdn_instance_map`` is the following:
.. code-block::
{
'ena.controlplane.domain': '10.1.2.1:9100',
'dio.controlplane.domain': '10.1.2.2:9100',
'tria.controlplane.domain': '10.1.2.3:9100'
}
For instance metrics, it is required that Prometheus contains a label
with the uuid of the OpenStack instance in each relevant metric. By default,
the datasource will look for the label ``resource``. The
``instance_uuid_label`` config option in watcher.conf allows deployers to
override this default to any other label name that stores the ``uuid``.
Limitations
-----------
The current implementation doesn't support the ``statistic_series`` function of
the Watcher ``class DataSourceBase``. It is expected that the
``statistic_aggregation`` function (which is implemented) is sufficient in
providing the **current** state of the managed resources in the cluster.
The ``statistic_aggregation`` function defaults to querying back 300 seconds,
starting from the present time (the time period is a function parameter and
can be set to a value as required). Implementing the ``statistic_series`` can
always be re-visited if the requisite interest and work cycles are volunteered
by the interested parties.
One further note about a limitation in the implemented
``statistic_aggregation`` function. This function is defined with a
``granularity`` parameter, to be used when querying whichever of the Watcher
``DataSourceBase`` metrics providers. In the case of Prometheus, we do not
fetch and then process individual metrics across the specified time period.
Instead we use the PromQL querying operators and functions, so that the
server itself will process the request across the specified parameters and
then return the result. So ``granularity`` parameter is redundant and remains
unused for the Prometheus implementation of ``statistic_aggregation``. The
granularity of the data fetched by Prometheus server is specified in
configuration as the server ``scrape_interval`` (current default 15 seconds).
Configuration
-------------
A deployer must set the ``datasources`` parameter to include ``prometheus``
under the watcher_datasources section of watcher.conf (or add ``prometheus`` in
datasources for a specific strategy if preferred eg. under the
``[watcher_strategies.workload_stabilization]`` section).
The watcher.conf configuration file is also used to set the parameter values
required by the Watcher Prometheus data source. The configuration can be
added under the ``[prometheus_client]`` section and the available options are
duplicated below from the code as they are self documenting:
.. code-block::
cfg.StrOpt('host',
help="The hostname or IP address for the prometheus server."),
cfg.StrOpt('port',
help="The port number used by the prometheus server."),
cfg.StrOpt('fqdn_label',
default="fqdn",
help="The label that Prometheus uses to store the fqdn of "
"exporters. Defaults to 'fqdn'."),
cfg.StrOpt('instance_uuid_label',
default="resource",
help="The label that Prometheus uses to store the uuid of "
"OpenStack instances. Defaults to 'resource'."),
cfg.StrOpt('username',
help="The basic_auth username to use to authenticate with the "
"Prometheus server."),
cfg.StrOpt('password',
secret=True,
help="The basic_auth password to use to authenticate with the "
"Prometheus server."),
cfg.StrOpt('cafile',
help="Path to the CA certificate for establishing a TLS "
"connection with the Prometheus server."),
cfg.StrOpt('certfile',
help="Path to the client certificate for establishing a TLS "
"connection with the Prometheus server."),
cfg.StrOpt('keyfile',
help="Path to the client key for establishing a TLS "
"connection with the Prometheus server."),
The ``host`` and ``port`` are **required** configuration options which have
no set default. These specify the hostname (or IP) and port for at which
the Prometheus server is listening. The ``fqdn_label`` allows deployers to
override the required metric label used to match Prometheus node exporters
against the Watcher ComputeNodes in the Watcher decision engine cluster data
model. The default is ``fqdn`` and deployers can specify any other value
(e.g. if they have an equivalent but different label such as ``host``).
So a sample watcher.conf configured to use the Prometheus server at
``10.2.3.4:9090`` would look like the following:
.. code-block::
[watcher_datasources]
datasources = prometheus
[prometheus_client]
host = 10.2.3.4
port = 9090
fqdn_label = fqdn

View File

@@ -9,7 +9,7 @@
...
connection = mysql+pymysql://watcher:WATCHER_DBPASS@controller/watcher?charset=utf8
* In the `[DEFAULT]` section, configure the transport url for RabbitMQ message broker.
* In the ``[DEFAULT]`` section, configure the transport url for RabbitMQ message broker.
.. code-block:: ini
@@ -20,7 +20,7 @@
Replace the RABBIT_PASS with the password you chose for OpenStack user in RabbitMQ.
* In the `[keystone_authtoken]` section, configure Identity service access.
* In the ``[keystone_authtoken]`` section, configure Identity service access.
.. code-block:: ini
@@ -39,7 +39,7 @@
Replace WATCHER_PASS with the password you chose for the watcher user in the Identity service.
* Watcher interacts with other OpenStack projects via project clients, in order to instantiate these
clients, Watcher requests new session from Identity service. In the `[watcher_clients_auth]` section,
clients, Watcher requests new session from Identity service. In the ``[watcher_clients_auth]`` section,
configure the identity service access to interact with other OpenStack project clients.
.. code-block:: ini
@@ -56,7 +56,7 @@
Replace WATCHER_PASS with the password you chose for the watcher user in the Identity service.
* In the `[api]` section, configure host option.
* In the ``[api]`` section, configure host option.
.. code-block:: ini
@@ -66,7 +66,7 @@
Replace controller with the IP address of the management network interface on your controller node, typically 10.0.0.11 for the first node in the example architecture.
* In the `[oslo_messaging_notifications]` section, configure the messaging driver.
* In the ``[oslo_messaging_notifications]`` section, configure the messaging driver.
.. code-block:: ini

View File

@@ -48,7 +48,7 @@
logging configuration to any other existing logging
options. Please see the Python logging module documentation
for details on logging configuration files. The log-config
name for this option is depcrecated.
name for this option is deprecated.
**--log-format FORMAT**
A logging.Formatter log message format string which may use any

View File

@@ -26,8 +26,7 @@ metric service name plugins comment
``compute_monitors`` option
to ``cpu.virt_driver`` in
the nova.conf.
``cpu_util`` ceilometer_ none cpu_util has been removed
since Stein.
``cpu`` ceilometer_ none
============================ ============ ======= ===========================
.. _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
$ openstack optimize audittemplate create \
at1 saving_energy --strategy saving_energy
saving_energy_template1 saving_energy --strategy saving_energy
$ openstack optimize audit create -a at1 \
$ openstack optimize audit create -a saving_energy_audit1 \
-p free_used_percent=20.0
External Links

View File

@@ -22,14 +22,19 @@ The *vm_workload_consolidation* strategy requires the following metrics:
============================ ============ ======= =========================
metric service name plugins comment
============================ ============ ======= =========================
``cpu_util`` ceilometer_ none cpu_util has been removed
since Stein.
``cpu`` ceilometer_ none
``memory.resident`` ceilometer_ none
``memory`` ceilometer_ none
``disk.root.size`` ceilometer_ none
``compute.node.cpu.percent`` ceilometer_ none (optional) need to set the
``compute_monitors`` option
to ``cpu.virt_driver`` in the
nova.conf.
``hardware.memory.used`` ceilometer_ SNMP_ (optional)
============================ ============ ======= =========================
.. _ceilometer: https://docs.openstack.org/ceilometer/latest/admin/telemetry-measurements.html#openstack-compute
.. _SNMP: https://docs.openstack.org/ceilometer/latest/admin/telemetry-measurements.html#snmp-based-meters
Cluster data model
******************

View File

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

View File

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

View File

@@ -132,8 +132,8 @@ audit) that you want to use.
$ openstack optimize audit create -a <your_audit_template>
If your_audit_template was created by --strategy <your_strategy>, and it
defines some parameters (command `watcher strategy show` to check parameters
format), your can append `-p` to input required parameters:
defines some parameters (command ``watcher strategy show`` to check parameters
format), your can append ``-p`` to input required parameters:
.. code:: bash

View File

@@ -0,0 +1,9 @@
---
- hosts: all
tasks:
- name: Generate prometheus.yml config file
delegate_to: controller
template:
src: "templates/prometheus.yml.j2"
dest: "/home/zuul/prometheus.yml"
mode: "0644"

View File

@@ -0,0 +1,13 @@
global:
scrape_interval: 10s
scrape_configs:
- job_name: "node"
static_configs:
- targets: ["localhost:3000"]
{% if 'compute' in groups %}
{% for host in groups['compute'] %}
- targets: ["{{ hostvars[host]['ansible_fqdn'] }}:9100"]
labels:
fqdn: "{{ hostvars[host]['ansible_fqdn'] }}"
{% endfor %}
{% endif %}

View File

@@ -1,7 +1,8 @@
Rally job
=========
We provide, with Watcher, a Rally plugin you can use to benchmark the optimization service.
We provide, with Watcher, a Rally plugin you can use to benchmark
the optimization service.
To launch this task with configured Rally you just need to run:

View File

@@ -0,0 +1,33 @@
---
prelude: |
The ``Openstack 2025.1`` (``Watcher 14.0.0``) includes several new features,
deprecations, and removals. After a period of inactivity, the Watcher
project moved to the Distributed leadership model in ``2025.1`` with
several new contributors working to modernize the code base.
Activity this cycle was mainly focused on paying down technical debt
related to supporting newer testing runtimes. With this release,
``ubuntu 24.04`` is now officially tested and supported.
``Ubuntu 24.04`` brings a new default Python runtime ``3.12`` and with it
improvements to eventlet and SQLAlchemy 2.0 compatibility where required.
``2025.1`` is the last release to officially support and test with ``Ubuntu 22.04``.
``2025.1`` is the second official skip-level upgrade release supporting
upgrades from either ``2024.1`` or ``2024.2``
Another area of focus in this cycle was the data sources supported by Watcher.
The long obsolete `Ceilometer` API data source has been removed, and the untested
`Monasca` data source has been deprecated and a new `Prometheus` data source
has been added.
https://specs.openstack.org/openstack/watcher-specs/specs/2025.1/approved/prometheus-datasource.html
fixes:
- https://bugs.launchpad.net/watcher/+bug/2086710 watcher compatibility between
eventlet, apscheduler, and python 3.12
- https://bugs.launchpad.net/watcher/+bug/2067815 refactoring of the SQLAlchemy
database layer to improve compatibility with eventlet on newer Pythons
- A number of linting issues were addressed with the introduction
of pre-commit. The issues include but are not limited to, spelling and grammar
fixes across all documentation and code, numerous sphinx documentation build warnings
, and incorrect file permission such as files having the execute bit set when not required.
While none of these changes should affect the runtime behavior of Watcher, they
generally improve the maintainability and quality of the codebase.

View File

@@ -0,0 +1,6 @@
---
features:
- |
Support for instance metrics has been added to the prometheus data source.
The included metrics are `instance_cpu_usage`, `instance_ram_usage`,
`instance_ram_allocated` and `instance_root_disk_size`.

View File

@@ -4,4 +4,4 @@ features:
will standardize interactions with scoring engines
through the common API. It is possible to use the
scoring engine by different Strategies, which
improve the code and data model re-use.
improve the code and data model reuse.

View File

@@ -5,5 +5,5 @@ features:
failure. The amount of failures allowed before giving up and the time before
reattempting are configurable. The `api_call_retries` and
`api_query_timeout` parameters in the `[collector]` group can be used to
adjust these paremeters. 10 retries with a 1 second time in between
adjust these parameters. 10 retries with a 1 second time in between
reattempts is the default.

View File

@@ -3,6 +3,6 @@ features:
Watcher starts to support API microversions since Stein cycle. From now
onwards all API changes should be made with saving backward compatibility.
To specify API version operator should use OpenStack-API-Version
HTTP header. If operator wants to know the mininum and maximum supported
HTTP header. If operator wants to know the minimum and maximum supported
versions by API, he/she can access /v1 resource and Watcher API will
return appropriate headers in response.

View File

@@ -0,0 +1,5 @@
---
deprecations:
- |
Monasca Data Source is deprecated and will be removed in the future, due
to inactivity of Monasca project.

View File

@@ -0,0 +1,6 @@
---
upgrade:
- |
Python 3.8 support has been dropped. Last release of watcher
supporting python 3.8 is 13.0.0.
The minimum version of Python now supported is Python 3.9.

View File

@@ -7,7 +7,7 @@ prelude: >
features:
- |
A new threadpool for the decision engine that contributors can use to
improve the performance of many operations, primarily I/O bound onces.
improve the performance of many operations, primarily I/O bound ones.
The amount of workers used by the decision engine threadpool can be
configured to scale according to the available infrastructure using
the `watcher_decision_engine.max_general_workers` config option.

View File

@@ -13,7 +13,7 @@ features:
* disk_gb_reserved: The amount of disk a node has reserved for its own use.
* disk_ratio: Disk allocation ratio.
We also add some new propeties:
We also add some new properties:
* vcpu_capacity: The amount of vcpu, take allocation ratio into account,
but do not include reserved.

View File

@@ -0,0 +1,8 @@
---
features:
- |
A new Prometheus data source is added. This allows the watcher decision
engine to collect metrics from Prometheus server. For more information
about the Prometheus data source, including limitations and configuration
options see
https://docs.openstack.org/watcher/latest/datasources/prometheus.html

View File

@@ -0,0 +1,6 @@
---
upgrade:
- |
Ceilometer datasource has been completely removed. The datasource requires
ceilometer API which was already removed from Ceilometer. Use the other
datasources such as Gnocchi.

View File

@@ -4,5 +4,5 @@ features:
Whenever a Watcher object is created, updated or deleted, a versioned
notification will, if it's relevant, be automatically sent to notify in order
to allow an event-driven style of architecture within Watcher. Moreover, it
will also give other services and/or 3rd party softwares (e.g. monitoring
will also give other services and/or 3rd party software (e.g. monitoring
solutions or rules engines) the ability to react to such events.

View File

@@ -1,3 +1,3 @@
---
features:
- Add a service supervisor to watch Watcher deamons.
- Add a service supervisor to watch Watcher daemons.

View File

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

View File

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

View File

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

View File

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

View File

@@ -28,12 +28,12 @@ import sys
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
@@ -47,13 +47,13 @@ templates_path = ['_templates']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
copyright = u'2016, Watcher developers'
copyright = '2016, Watcher developers'
# Release notes are version independent
# The short X.Y version.
@@ -63,37 +63,37 @@ release = ''
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents
#default_role = None
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'native'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# modindex_common_prefix = []
# openstackdocstheme options
openstackdocs_repo_name = 'openstack/watcher'
@@ -109,26 +109,26 @@ html_theme = 'openstackdocs'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
@@ -137,44 +137,44 @@ html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'watcherdoc'
@@ -183,42 +183,42 @@ htmlhelp_basename = 'watcherdoc'
# -- Options for LaTeX output -------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The paper size ('letterpaper' or 'a4paper').
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# The font size ('10pt', '11pt' or '12pt').
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Additional stuff for the LaTeX preamble.
# 'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual])
latex_documents = [
('index', 'watcher.tex', u'Watcher Documentation',
u'Watcher developers', 'manual'),
('index', 'watcher.tex', 'Watcher Documentation',
'Watcher developers', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# latex_domain_indices = True
# -- Options for manual page output -------------------------------------------
@@ -226,12 +226,12 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'watcher', u'Watcher Documentation',
[u'Watcher developers'], 1)
('index', 'watcher', 'Watcher Documentation',
['Watcher developers'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# man_show_urls = False
# -- Options for Texinfo output -----------------------------------------------
@@ -240,19 +240,19 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'watcher', u'Watcher Documentation',
u'Watcher developers', 'watcher', 'One line description of project.',
'Miscellaneous'),
('index', 'watcher', 'Watcher Documentation',
'Watcher developers', 'watcher', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# texinfo_show_urls = 'footnote'
# -- Options for Internationalization output ------------------------------
locale_dirs = ['locale/']

View File

@@ -21,6 +21,14 @@ Contents:
:maxdepth: 1
unreleased
2024.2
2024.1
2023.2
2023.1
zed
yoga
xena
wallaby
victoria
ussuri
train

View File

@@ -1,15 +1,18 @@
# Andi Chandler <andi@gowling.com>, 2017. #zanata
# Andi Chandler <andi@gowling.com>, 2018. #zanata
# Andi Chandler <andi@gowling.com>, 2020. #zanata
# Andi Chandler <andi@gowling.com>, 2022. #zanata
# Andi Chandler <andi@gowling.com>, 2023. #zanata
# Andi Chandler <andi@gowling.com>, 2024. #zanata
msgid ""
msgstr ""
"Project-Id-Version: python-watcher\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-10-27 04:13+0000\n"
"POT-Creation-Date: 2025-01-10 00:32+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2020-10-28 11:13+0000\n"
"PO-Revision-Date: 2024-04-18 12:21+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language-Team: English (United Kingdom)\n"
"Language: en_GB\n"
@@ -58,12 +61,27 @@ msgstr "1.9.0"
msgid "2.0.0"
msgstr "2.0.0"
msgid "2023.1 Series Release Notes"
msgstr "2023.1 Series Release Notes"
msgid "2023.2 Series Release Notes"
msgstr "2023.2 Series Release Notes"
msgid "3.0.0"
msgstr "3.0.0"
msgid "3.0.0.0rc1"
msgstr "3.0.0.0rc1"
msgid "4.0.0"
msgstr "4.0.0"
msgid "4.0.0.0rc1"
msgstr "4.0.0.0rc1"
msgid "6.0.0"
msgstr "6.0.0"
msgid "A ``watcher-status upgrade check`` has been added for this."
msgstr "A ``watcher-status upgrade check`` has been added for this."
@@ -202,6 +220,17 @@ msgstr ""
msgid "Added SUSPENDED audit state"
msgstr "Added SUSPENDED audit state"
msgid ""
"Added a generic scoring engine module, which will standardize interactions "
"with scoring engines through the common API. It is possible to use the "
"scoring engine by different Strategies, which improve the code and data "
"model re-use."
msgstr ""
"Added a generic scoring engine module, which will standardize interactions "
"with scoring engines through the common API. It is possible to use the "
"scoring engine by different Strategies, which improve the code and data "
"model re-use."
msgid ""
"Added a generic scoring engine module, which will standarize interactions "
"with scoring engines through the common API. It is possible to use the "
@@ -321,6 +350,13 @@ msgstr ""
"Added a way to create periodic audit to be able to continuously optimise the "
"cloud infrastructure."
msgid ""
"Added a way to return the of available goals depending on which strategies "
"have been deployed on the node where the decision engine is running."
msgstr ""
"Added a way to return the of available goals depending on which strategies "
"have been deployed on the node where the decision engine is running."
msgid ""
"Added a way to return the of available goals depending on which strategies "
"have been deployed on the node where the decison engine is running."
@@ -397,6 +433,15 @@ msgstr ""
"that negatively affects performance of a high priority VM by over utilising "
"Last Level Cache."
msgid ""
"Added strategy to identify and migrate a Noisy Neighbor - a low priority VM "
"that negatively affects performance of a high priority VM by over utilizing "
"Last Level Cache."
msgstr ""
"Added strategy to identify and migrate a Noisy Neighbour - a low-priority VM "
"that negatively affects the performance of a high-priority VM by over "
"utilising Last Level Cache."
msgid ""
"Added the functionality to filter out instances which have metadata field "
"'optimize' set to False. For now, this is only available for the "
@@ -503,6 +548,13 @@ msgstr ""
msgid "Centralize all configuration options for Watcher."
msgstr "Centralise all configuration options for Watcher."
msgid ""
"Check the creation time of the action plan, and set its state to SUPERSEDED "
"if it has expired."
msgstr ""
"Check the creation time of the action plan, and set its state to SUPERSEDED "
"if it has expired."
msgid "Contents:"
msgstr "Contents:"
@@ -744,6 +796,23 @@ msgstr ""
"The configuration options for query retries in `[gnocchi_client]` are "
"deprecated and the option in `[watcher_datasources]` should now be used."
msgid ""
"The default value of ``[oslo_policy] policy_file`` config option has been "
"changed from ``policy.json`` to ``policy.yaml``. Operators who are utilizing "
"customized or previously generated static policy JSON files (which are not "
"needed by default), should generate new policy files or convert them in YAML "
"format. Use the `oslopolicy-convert-json-to-yaml <https://docs.openstack.org/"
"oslo.policy/latest/cli/oslopolicy-convert-json-to-yaml.html>`_ tool to "
"convert a JSON to YAML formatted policy file in backward compatible way."
msgstr ""
"The default value of ``[oslo_policy] policy_file`` config option has been "
"changed from ``policy.json`` to ``policy.yaml``. Operators who are utilizing "
"customized or previously generated static policy JSON files (which are not "
"needed by default), should generate new policy files or convert them in YAML "
"format. Use the `oslopolicy-convert-json-to-yaml <https://docs.openstack.org/"
"oslo.policy/latest/cli/oslopolicy-convert-json-to-yaml.html>`_ tool to "
"convert a JSON to YAML formatted policy file in backward compatible way."
msgid ""
"The graph model describes how VMs are associated to compute hosts. This "
"allows for seeing relationships upfront between the entities and hence can "
@@ -799,6 +868,21 @@ msgstr "Train Series Release Notes"
msgid "Upgrade Notes"
msgstr "Upgrade Notes"
msgid ""
"Use of JSON policy files was deprecated by the ``oslo.policy`` library "
"during the Victoria development cycle. As a result, this deprecation is "
"being noted in the Wallaby cycle with an anticipated future removal of "
"support by ``oslo.policy``. As such operators will need to convert to YAML "
"policy files. Please see the upgrade notes for details on migration of any "
"custom policy files."
msgstr ""
"Use of JSON policy files was deprecated by the ``oslo.policy`` library "
"during the Victoria development cycle. As a result, this deprecation is "
"being noted in the Wallaby cycle with an anticipated future removal of "
"support by ``oslo.policy``. As such operators will need to convert to YAML "
"policy files. Please see the upgrade notes for details on migration of any "
"custom policy files."
msgid ""
"Using ``watcher/api/app.wsgi`` script is deprecated and it will be removed "
"in U release. Please switch to automatically generated ``watcher-api-wsgi`` "
@@ -814,6 +898,9 @@ msgstr "Ussuri Series Release Notes"
msgid "Victoria Series Release Notes"
msgstr "Victoria Series Release Notes"
msgid "Wallaby Series Release Notes"
msgstr "Wallaby Series Release Notes"
msgid ""
"Watcher can continuously optimize the OpenStack cloud for a specific "
"strategy or goal by triggering an audit periodically which generates an "
@@ -924,6 +1011,15 @@ msgstr "We also add some new properties:"
msgid "Welcome to watcher's Release Notes documentation!"
msgstr "Welcome to watcher's Release Notes documentation!"
msgid "Xena Series Release Notes"
msgstr "Xena Series Release Notes"
msgid "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``"
msgstr "``[watcher_datasources] datasources = gnocchi,monasca,ceilometer``"

View File

@@ -1,33 +0,0 @@
# Gérald LONLAS <g.lonlas@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: python-watcher\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-03-22 02:21+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2016-10-22 06:44+0000\n"
"Last-Translator: Gérald LONLAS <g.lonlas@gmail.com>\n"
"Language-Team: French\n"
"Language: fr\n"
"X-Generator: Zanata 4.3.3\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
msgid "0.29.0"
msgstr "0.29.0"
msgid "Contents:"
msgstr "Contenu :"
msgid "Current Series Release Notes"
msgstr "Note de la release actuelle"
msgid "New Features"
msgstr "Nouvelles fonctionnalités"
msgid "Newton Series Release Notes"
msgstr "Note de release pour Newton"
msgid "Welcome to watcher's Release Notes documentation!"
msgstr "Bienvenue dans la documentation de la note de Release de Watcher"

View File

@@ -3,4 +3,4 @@ Victoria Series Release Notes
=============================
.. release-notes::
:branch: stable/victoria
:branch: unmaintained/victoria

View File

@@ -0,0 +1,6 @@
============================
Wallaby Series Release Notes
============================
.. release-notes::
:branch: unmaintained/wallaby

View File

@@ -0,0 +1,6 @@
=========================
Xena Series Release Notes
=========================
.. release-notes::
:branch: unmaintained/xena

View File

@@ -0,0 +1,6 @@
=========================
Yoga Series Release Notes
=========================
.. release-notes::
:branch: unmaintained/yoga

View File

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

View File

@@ -1,8 +1,8 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
# Requirements lower bounds listed here are our best effort to keep them up to
# date but we do not test them so no guarantee of having them all correct. If
# you find any incorrect lower bounds, let us know or propose a fix.
apscheduler>=3.5.1 # MIT License
eventlet>=0.27.0 # MIT
jsonpatch>=1.21 # BSD
keystoneauth1>=3.4.0 # Apache-2.0
jsonschema>=3.2.0 # MIT
@@ -17,26 +17,26 @@ oslo.context>=2.21.0 # Apache-2.0
oslo.db>=4.44.0 # Apache-2.0
oslo.i18n>=3.20.0 # Apache-2.0
oslo.log>=3.37.0 # Apache-2.0
oslo.messaging>=8.1.2 # Apache-2.0
oslo.policy>=3.6.0 # Apache-2.0
oslo.messaging>=14.1.0 # Apache-2.0
oslo.policy>=4.5.0 # Apache-2.0
oslo.reports>=1.27.0 # Apache-2.0
oslo.serialization>=2.25.0 # Apache-2.0
oslo.service>=1.30.0 # Apache-2.0
oslo.upgradecheck>=1.3.0 # Apache-2.0
oslo.utils>=3.36.0 # Apache-2.0
oslo.utils>=7.0.0 # Apache-2.0
oslo.versionedobjects>=1.32.0 # Apache-2.0
PasteDeploy>=1.5.2 # MIT
pbr>=3.1.1 # Apache-2.0
pecan>=1.3.2 # BSD
PrettyTable>=0.7.2 # BSD
gnocchiclient>=7.0.1 # Apache-2.0
python-ceilometerclient>=2.9.0 # Apache-2.0
python-cinderclient>=3.5.0 # Apache-2.0
python-glanceclient>=2.9.1 # Apache-2.0
python-keystoneclient>=3.15.0 # Apache-2.0
python-monascaclient>=1.12.0 # Apache-2.0
python-neutronclient>=6.7.0 # Apache-2.0
python-novaclient>=14.1.0 # Apache-2.0
python-observabilityclient>=0.3.0 # Apache-2.0
python-openstackclient>=3.14.0 # Apache-2.0
python-ironicclient>=2.5.0 # Apache-2.0
SQLAlchemy>=1.2.5 # MIT

View File

@@ -1,12 +1,12 @@
[metadata]
name = python-watcher
summary = OpenStack Watcher provides a flexible and scalable resource optimization service for multi-tenant OpenStack-based clouds.
description-file =
description_file =
README.rst
author = OpenStack
author-email = openstack-discuss@lists.openstack.org
home-page = https://docs.openstack.org/watcher/latest/
python-requires = >=3.6
author_email = openstack-discuss@lists.openstack.org
home_page = https://docs.openstack.org/watcher/latest/
python_requires = >=3.9
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
@@ -17,9 +17,10 @@ classifier =
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
[files]
packages =
@@ -108,3 +109,8 @@ watcher_cluster_data_model_collectors =
compute = watcher.decision_engine.model.collector.nova:NovaClusterDataModelCollector
storage = watcher.decision_engine.model.collector.cinder:CinderClusterDataModelCollector
baremetal = watcher.decision_engine.model.collector.ironic:BaremetalClusterDataModelCollector
[codespell]
skip = *.po,*.js,*.css,*.html,*.svg,HACKING.py,*hacking*,*build*,*_static*,doc/dictionary.txt,*.pyc,*.inv,*.gz,*.jpg,*.png,*.vsd,*.graffle,*.json
count =
quiet-level = 4

View File

@@ -1,15 +1,7 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
coverage>=4.5.1 # Apache-2.0
doc8>=0.8.0 # Apache-2.0
freezegun>=0.3.10 # Apache-2.0
hacking>=3.0.1,<3.1.0 # Apache-2.0
oslotest>=3.3.0 # Apache-2.0
os-testr>=1.0.0 # Apache-2.0
testscenarios>=0.5.0 # Apache-2.0/BSD
testtools>=2.3.0 # MIT
stestr>=2.0.0 # Apache-2.0
os-api-ref>=1.4.0 # Apache-2.0
bandit>=1.6.0 # Apache-2.0
WebTest>=2.0.27 # MIT

93
tox.ini
View File

@@ -1,37 +1,55 @@
[tox]
minversion = 2.0
envlist = py38,pep8
skipsdist = True
minversion = 3.18.0
envlist = py3,pep8
ignore_basepython_conflict = True
[testenv]
basepython = python3
usedevelop = True
whitelist_externals = find
allowlist_externals = find
rm
install_command = pip install {opts} {packages}
install_command = pip install -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}
VIRTUAL_ENV={envdir}
OS_STDOUT_CAPTURE=1
OS_STDERR_CAPTURE=1
OS_TEST_TIMEOUT=30
PYTHONDONTWRITEBYTECODE=1
deps =
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt
python-libmaas>=0.6.8
commands =
rm -f .testrepository/times.dbm
find . -type f -name "*.py[c|o]" -delete
stestr run {posargs}
passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY
passenv =
http_proxy
HTTP_PROXY
https_proxy
HTTPS_PROXY
no_proxy
NO_PROXY
OS_DEBUG
# NOTE(sean-k-mooney) optimization is enabled by default and when enabled
# asserts are complied out. Disable optimization to allow asserts in
# nova to fire in unit and functional tests. This can be useful for
# debugging issue with fixtures and mocks.
PYTHONOPTIMIZE
[testenv:pep8]
description =
Run style checks.
skip_install = true
deps =
pre-commit
commands =
doc8 doc/source/ CONTRIBUTING.rst HACKING.rst README.rst
flake8
bandit -r watcher -x watcher/tests/* -n5 -ll -s B320
pre-commit run --all-files --show-diff-on-failure
[testenv:venv]
setenv = PYTHONHASHSEED=0
deps =
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/doc/requirements.txt
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt
@@ -49,14 +67,15 @@ commands =
[testenv:docs]
setenv = PYTHONHASHSEED=0
deps = -r{toxinidir}/doc/requirements.txt
deps =
-r{toxinidir}/doc/requirements.txt
commands =
rm -fr doc/build doc/source/api/ .autogenerated
sphinx-build -W --keep-going -b html doc/source doc/build/html
[testenv:api-ref]
deps = -r{toxinidir}/doc/requirements.txt
whitelist_externals = bash
allowlist_externals = bash
commands =
bash -c 'rm -rf api-ref/build'
sphinx-build -W --keep-going -b html -d api-ref/build/doctrees api-ref/source api-ref/build/html
@@ -73,6 +92,29 @@ commands =
commands =
oslopolicy-sample-generator --config-file etc/watcher/oslo-policy-generator/watcher-policy-generator.conf
[testenv:wheel]
commands = python setup.py bdist_wheel
[testenv:pdf-docs]
deps = {[testenv:docs]deps}
allowlist_externals =
rm
make
commands =
rm -rf doc/build/pdf
sphinx-build -W --keep-going -b latex doc/source doc/build/pdf
make -C doc/build/pdf
[testenv:releasenotes]
deps = -r{toxinidir}/doc/requirements.txt
commands = sphinx-build -a -W -E -d releasenotes/build/doctrees --keep-going -b html releasenotes/source releasenotes/build/html
[testenv:bandit]
skip_install = true
deps = {[testenv:pep8]deps}
commands =
pre-commit run --all-files --show-diff-on-failure bandit
[flake8]
filename = *.py,app.wsgi
show-source=True
@@ -82,9 +124,6 @@ builtins= _
enable-extensions = H106,H203,H904
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,*sqlalchemy/alembic/versions/*,demo/,releasenotes
[testenv:wheel]
commands = python setup.py bdist_wheel
[hacking]
import_exceptions = watcher._i18n
@@ -108,27 +147,7 @@ extension =
N366 = checks:import_stock_mock
paths = ./watcher/hacking
[doc8]
extension=.rst
# todo: stop ignoring doc/source/man when https://bugs.launchpad.net/doc8/+bug/1502391 is fixed
ignore-path=doc/source/image_src,doc/source/man,doc/source/api
[testenv:pdf-docs]
envdir = {toxworkdir}/docs
deps = {[testenv:docs]deps}
whitelist_externals =
rm
make
commands =
rm -rf doc/build/pdf
sphinx-build -W --keep-going -b latex doc/source doc/build/pdf
make -C doc/build/pdf
[testenv:releasenotes]
deps = -r{toxinidir}/doc/requirements.txt
commands = sphinx-build -a -W -E -d releasenotes/build/doctrees --keep-going -b html releasenotes/source releasenotes/build/html
[testenv:bandit]
deps = -r{toxinidir}/test-requirements.txt
commands = bandit -r watcher -x watcher/tests/* -n5 -ll -s B320

View File

@@ -55,8 +55,8 @@ possible to :ref:`develop new implementations <implement_action_plugin>` which
are dynamically loaded by Watcher at launch time.
"""
import datetime
from http import HTTPStatus
from oslo_utils import timeutils
import pecan
from pecan import rest
import wsme
@@ -193,9 +193,9 @@ class Action(base.APIBase):
sample = cls(uuid='27e3153e-d5bf-4b7e-b517-fb518e17f34c',
description='action description',
state='PENDING',
created_at=datetime.datetime.utcnow(),
created_at=timeutils.utcnow(),
deleted_at=None,
updated_at=datetime.datetime.utcnow(),
updated_at=timeutils.utcnow(),
parents=[])
sample._action_plan_uuid = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae'
return cls._convert_with_links(sample, 'http://localhost:9322', expand)
@@ -229,6 +229,7 @@ class ActionCollection(collection.Collection):
class ActionsController(rest.RestController):
"""REST controller for Actions."""
def __init__(self):
super(ActionsController, self).__init__()
@@ -333,7 +334,7 @@ class ActionsController(rest.RestController):
policy.enforce(context, 'action:detail',
action='action:detail')
# NOTE(lucasagomes): /detail should only work agaist collections
# NOTE(lucasagomes): /detail should only work against collections
parent = pecan.request.path.split('/')[:-1][-1]
if parent != "actions":
raise exception.HTTPNotFound
@@ -362,7 +363,7 @@ class ActionsController(rest.RestController):
return Action.convert_with_links(action)
@wsme_pecan.wsexpose(Action, body=Action, status_code=201)
@wsme_pecan.wsexpose(Action, body=Action, status_code=HTTPStatus.CREATED)
def post(self, action):
"""Create a new action(forbidden).
@@ -422,7 +423,7 @@ class ActionsController(rest.RestController):
action_to_update.save()
return Action.convert_with_links(action_to_update)
@wsme_pecan.wsexpose(None, types.uuid, status_code=204)
@wsme_pecan.wsexpose(None, types.uuid, status_code=HTTPStatus.NO_CONTENT)
def delete(self, action_uuid):
"""Delete a action(forbidden).

View File

@@ -54,9 +54,9 @@ To see the life-cycle and description of
state machine <action_plan_state_machine>`.
"""
import datetime
from http import HTTPStatus
from oslo_log import log
from oslo_utils import timeutils
import pecan
from pecan import rest
import wsme
@@ -292,9 +292,9 @@ class ActionPlan(base.APIBase):
def sample(cls, expand=True):
sample = cls(uuid='9ef4d84c-41e8-4418-9220-ce55be0436af',
state='ONGOING',
created_at=datetime.datetime.utcnow(),
created_at=timeutils.utcnow(),
deleted_at=None,
updated_at=datetime.datetime.utcnow())
updated_at=timeutils.utcnow())
sample._audit_uuid = 'abcee106-14d3-4515-b744-5a26885cf6f6'
sample._efficacy_indicators = [{'description': 'Test indicator',
'name': 'test_indicator',
@@ -433,7 +433,7 @@ class ActionPlansController(rest.RestController):
policy.enforce(context, 'action_plan:detail',
action='action_plan:detail')
# NOTE(lucasagomes): /detail should only work agaist collections
# NOTE(lucasagomes): /detail should only work against collections
parent = pecan.request.path.split('/')[:-1][-1]
if parent != "action_plans":
raise exception.HTTPNotFound
@@ -460,7 +460,7 @@ class ActionPlansController(rest.RestController):
return ActionPlan.convert_with_links(action_plan)
@wsme_pecan.wsexpose(None, types.uuid, status_code=204)
@wsme_pecan.wsexpose(None, types.uuid, status_code=HTTPStatus.NO_CONTENT)
def delete(self, action_plan_uuid):
"""Delete an action plan.

View File

@@ -32,6 +32,9 @@ states, visit :ref:`the Audit State machine <audit_state_machine>`.
import datetime
from dateutil import tz
from http import HTTPStatus
from oslo_log import log
from oslo_utils import timeutils
import pecan
from pecan import rest
import wsme
@@ -39,8 +42,6 @@ from wsme import types as wtypes
from wsme import utils as wutils
import wsmeext.pecan as wsme_pecan
from oslo_log import log
from watcher._i18n import _
from watcher.api.controllers import base
from watcher.api.controllers import link
@@ -170,16 +171,16 @@ class AuditPostType(wtypes.Base):
strategy = _get_object_by_value(context, objects.Strategy,
self.strategy)
self.name = "%s-%s" % (strategy.name,
datetime.datetime.utcnow().isoformat())
timeutils.utcnow().isoformat())
elif self.audit_template_uuid:
audit_template = objects.AuditTemplate.get(
context, self.audit_template_uuid)
self.name = "%s-%s" % (audit_template.name,
datetime.datetime.utcnow().isoformat())
timeutils.utcnow().isoformat())
else:
goal = _get_object_by_value(context, objects.Goal, self.goal)
self.name = "%s-%s" % (goal.name,
datetime.datetime.utcnow().isoformat())
timeutils.utcnow().isoformat())
# No more than 63 characters
if len(self.name) > 63:
LOG.warning("Audit: %s length exceeds 63 characters",
@@ -423,15 +424,15 @@ class Audit(base.APIBase):
name='My Audit',
audit_type='ONESHOT',
state='PENDING',
created_at=datetime.datetime.utcnow(),
created_at=timeutils.utcnow(),
deleted_at=None,
updated_at=datetime.datetime.utcnow(),
updated_at=timeutils.utcnow(),
interval='7200',
scope=[],
auto_trigger=False,
next_run_time=datetime.datetime.utcnow(),
start_time=datetime.datetime.utcnow(),
end_time=datetime.datetime.utcnow())
next_run_time=timeutils.utcnow(),
start_time=timeutils.utcnow(),
end_time=timeutils.utcnow())
sample.goal_id = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae'
sample.strategy_id = '7ae81bb3-dec3-4289-8d6c-da80bd8001ff'
@@ -467,6 +468,7 @@ class AuditCollection(collection.Collection):
class AuditsController(rest.RestController):
"""REST controller for Audits."""
def __init__(self):
super(AuditsController, self).__init__()
self.dc_client = rpcapi.DecisionEngineAPI()
@@ -568,7 +570,7 @@ class AuditsController(rest.RestController):
context = pecan.request.context
policy.enforce(context, 'audit:detail',
action='audit:detail')
# NOTE(lucasagomes): /detail should only work agaist collections
# NOTE(lucasagomes): /detail should only work against collections
parent = pecan.request.path.split('/')[:-1][-1]
if parent != "audits":
raise exception.HTTPNotFound
@@ -595,7 +597,8 @@ class AuditsController(rest.RestController):
return Audit.convert_with_links(rpc_audit)
@wsme_pecan.wsexpose(Audit, body=AuditPostType, status_code=201)
@wsme_pecan.wsexpose(Audit, body=AuditPostType,
status_code=HTTPStatus.CREATED)
def post(self, audit_p):
"""Create a new audit.
@@ -717,7 +720,7 @@ class AuditsController(rest.RestController):
audit_to_update.save()
return Audit.convert_with_links(audit_to_update)
@wsme_pecan.wsexpose(None, wtypes.text, status_code=204)
@wsme_pecan.wsexpose(None, wtypes.text, status_code=HTTPStatus.NO_CONTENT)
def delete(self, audit):
"""Delete an audit.

View File

@@ -43,8 +43,8 @@ will be launched automatically or will need a manual confirmation from the
:ref:`Administrator <administrator_definition>`.
"""
import datetime
from http import HTTPStatus
from oslo_utils import timeutils
import pecan
from pecan import rest
import wsme
@@ -439,9 +439,9 @@ class AuditTemplate(base.APIBase):
description='Description of my audit template',
goal_uuid='83e44733-b640-40e2-8d8a-7dd3be7134e6',
strategy_uuid='367d826e-b6a4-4b70-bc44-c3f6fe1c9986',
created_at=datetime.datetime.utcnow(),
created_at=timeutils.utcnow(),
deleted_at=None,
updated_at=datetime.datetime.utcnow(),
updated_at=timeutils.utcnow(),
scope=[],)
return cls._convert_with_links(sample, 'http://localhost:9322', expand)
@@ -475,6 +475,7 @@ class AuditTemplateCollection(collection.Collection):
class AuditTemplatesController(rest.RestController):
"""REST controller for AuditTemplates."""
def __init__(self):
super(AuditTemplatesController, self).__init__()
@@ -575,7 +576,7 @@ class AuditTemplatesController(rest.RestController):
policy.enforce(context, 'audit_template:detail',
action='audit_template:detail')
# NOTE(lucasagomes): /detail should only work agaist collections
# NOTE(lucasagomes): /detail should only work against collections
parent = pecan.request.path.split('/')[:-1][-1]
if parent != "audit_templates":
raise exception.HTTPNotFound
@@ -618,7 +619,7 @@ class AuditTemplatesController(rest.RestController):
@wsme.validate(types.uuid, AuditTemplatePostType)
@wsme_pecan.wsexpose(AuditTemplate, body=AuditTemplatePostType,
status_code=201)
status_code=HTTPStatus.CREATED)
def post(self, audit_template_postdata):
"""Create a new audit template.
@@ -694,7 +695,7 @@ class AuditTemplatesController(rest.RestController):
audit_template_to_update.save()
return AuditTemplate.convert_with_links(audit_template_to_update)
@wsme_pecan.wsexpose(None, wtypes.text, status_code=204)
@wsme_pecan.wsexpose(None, wtypes.text, status_code=HTTPStatus.NO_CONTENT)
def delete(self, audit_template):
"""Delete a audit template.

View File

@@ -32,6 +32,7 @@ from watcher.decision_engine import rpcapi
class DataModelController(rest.RestController):
"""REST controller for data model"""
def __init__(self):
super(DataModelController, self).__init__()

View File

@@ -24,7 +24,7 @@ Here are some examples of :ref:`Goals <goal_definition>`:
- minimize the energy consumption
- minimize the number of compute nodes (consolidation)
- balance the workload among compute nodes
- minimize the license cost (some softwares have a licensing model which is
- minimize the license cost (some software have a licensing model which is
based on the number of sockets or cores where the software is deployed)
- find the most appropriate moment for a planned maintenance on a
given group of host (which may be an entire availability zone):
@@ -153,6 +153,7 @@ class GoalCollection(collection.Collection):
class GoalsController(rest.RestController):
"""REST controller for Goals."""
def __init__(self):
super(GoalsController, self).__init__()
@@ -216,7 +217,7 @@ class GoalsController(rest.RestController):
context = pecan.request.context
policy.enforce(context, 'goal:detail',
action='goal:detail')
# NOTE(lucasagomes): /detail should only work agaist collections
# NOTE(lucasagomes): /detail should only work against collections
parent = pecan.request.path.split('/')[:-1][-1]
if parent != "goals":
raise exception.HTTPNotFound

View File

@@ -145,6 +145,7 @@ class ScoringEngineCollection(collection.Collection):
class ScoringEngineController(rest.RestController):
"""REST controller for Scoring Engines."""
def __init__(self):
super(ScoringEngineController, self).__init__()

View File

@@ -175,6 +175,7 @@ class ServiceCollection(collection.Collection):
class ServicesController(rest.RestController):
"""REST controller for Services."""
def __init__(self):
super(ServicesController, self).__init__()
@@ -236,7 +237,7 @@ class ServicesController(rest.RestController):
context = pecan.request.context
policy.enforce(context, 'service:detail',
action='service:detail')
# NOTE(lucasagomes): /detail should only work agaist collections
# NOTE(lucasagomes): /detail should only work against collections
parent = pecan.request.path.split('/')[:-1][-1]
if parent != "services":
raise exception.HTTPNotFound

View File

@@ -196,6 +196,7 @@ class StrategyCollection(collection.Collection):
class StrategiesController(rest.RestController):
"""REST controller for Strategies."""
def __init__(self):
super(StrategiesController, self).__init__()
@@ -283,7 +284,7 @@ class StrategiesController(rest.RestController):
context = pecan.request.context
policy.enforce(context, 'strategy:detail',
action='strategy:detail')
# NOTE(lucasagomes): /detail should only work agaist collections
# NOTE(lucasagomes): /detail should only work against collections
parent = pecan.request.path.split('/')[:-1][-1]
if parent != "strategies":
raise exception.HTTPNotFound

View File

@@ -161,6 +161,7 @@ class MultiType(wtypes.UserType):
:param types: Variable-length list of types.
"""
def __init__(self, *types):
self.types = types

View File

@@ -14,6 +14,7 @@
Webhook endpoint for Watcher v1 REST API.
"""
from http import HTTPStatus
from oslo_log import log
import pecan
from pecan import rest
@@ -31,12 +32,13 @@ LOG = log.getLogger(__name__)
class WebhookController(rest.RestController):
"""REST controller for webhooks resource."""
def __init__(self):
super(WebhookController, self).__init__()
self.dc_client = rpcapi.DecisionEngineAPI()
@wsme_pecan.wsexpose(None, wtypes.text, body=types.jsontype,
status_code=202)
status_code=HTTPStatus.ACCEPTED)
def post(self, audit_ident, body):
"""Trigger the given audit.

View File

@@ -15,7 +15,7 @@
# under the License.
from http import client as http_client
from http import HTTPStatus
from oslo_config import cfg
from pecan import hooks
@@ -83,6 +83,7 @@ class NoExceptionTracebackHook(hooks.PecanHook):
# 'on_error' never fired for wsme+pecan pair. wsme @wsexpose decorator
# catches and handles all the errors, so 'on_error' dedicated for unhandled
# exceptions never fired.
def after(self, state):
# Omit empty body. Some errors may not have body at this level yet.
if not state.response.body:
@@ -91,8 +92,8 @@ class NoExceptionTracebackHook(hooks.PecanHook):
# Do nothing if there is no error.
# Status codes in the range 200 (OK) to 399 (400 = BAD_REQUEST) are not
# an error.
if (http_client.OK <= state.response.status_int <
http_client.BAD_REQUEST):
if (HTTPStatus.OK <= state.response.status_int <
HTTPStatus.BAD_REQUEST):
return
json_body = state.response.json

View File

@@ -33,6 +33,7 @@ class AuthTokenMiddleware(auth_token.AuthProtocol):
for public routes in the API.
"""
def __init__(self, app, conf, public_api_routes=()):
route_pattern_tpl = r'%s(\.json|\.xml)?$'

View File

@@ -118,7 +118,8 @@ class BaseAction(loadable.Loadable, metaclass=abc.ABCMeta):
"""
raise NotImplementedError()
@abc.abstractproperty
@property
@abc.abstractmethod
def schema(self):
"""Defines a Schema that the input parameters shall comply to

View File

@@ -17,17 +17,17 @@
# limitations under the License.
#
import enum
import time
from oslo_log import log
from watcher._i18n import _
from watcher.applier.actions import base
from watcher.common import exception
from watcher.common.metal_helper import constants as metal_constants
from watcher.common.metal_helper import factory as metal_helper_factory
class NodeState(enum.Enum):
POWERON = 'on'
POWEROFF = 'off'
LOG = log.getLogger(__name__)
class ChangeNodePowerState(base.BaseAction):
@@ -43,8 +43,8 @@ class ChangeNodePowerState(base.BaseAction):
'state': str,
})
The `resource_id` references a ironic node id (list of available
ironic node is returned by this command: ``ironic node-list``).
The `resource_id` references a baremetal node id (list of available
ironic nodes is returned by this command: ``ironic node-list``).
The `state` value should either be `on` or `off`.
"""
@@ -59,10 +59,14 @@ class ChangeNodePowerState(base.BaseAction):
'type': 'string',
"minlength": 1
},
'resource_name': {
'type': 'string',
"minlength": 1
},
'state': {
'type': 'string',
'enum': [NodeState.POWERON.value,
NodeState.POWEROFF.value]
'enum': [metal_constants.PowerState.ON.value,
metal_constants.PowerState.OFF.value]
}
},
'required': ['resource_id', 'state'],
@@ -82,10 +86,10 @@ class ChangeNodePowerState(base.BaseAction):
return self._node_manage_power(target_state)
def revert(self):
if self.state == NodeState.POWERON.value:
target_state = NodeState.POWEROFF.value
elif self.state == NodeState.POWEROFF.value:
target_state = NodeState.POWERON.value
if self.state == metal_constants.PowerState.ON.value:
target_state = metal_constants.PowerState.OFF.value
elif self.state == metal_constants.PowerState.OFF.value:
target_state = metal_constants.PowerState.ON.value
return self._node_manage_power(target_state)
def _node_manage_power(self, state, retry=60):
@@ -93,30 +97,32 @@ class ChangeNodePowerState(base.BaseAction):
raise exception.IllegalArgumentException(
message=_("The target state is not defined"))
ironic_client = self.osc.ironic()
nova_client = self.osc.nova()
current_state = ironic_client.node.get(self.node_uuid).power_state
# power state: 'power on' or 'power off', if current node state
# is the same as state, just return True
if state in current_state:
metal_helper = metal_helper_factory.get_helper(self.osc)
node = metal_helper.get_node(self.node_uuid)
current_state = node.get_power_state()
if state == current_state.value:
return True
if state == NodeState.POWEROFF.value:
node_info = ironic_client.node.get(self.node_uuid).to_dict()
compute_node_id = node_info['extra']['compute_node_id']
compute_node = nova_client.hypervisors.get(compute_node_id)
compute_node = compute_node.to_dict()
if state == metal_constants.PowerState.OFF.value:
compute_node = node.get_hypervisor_node().to_dict()
if (compute_node['running_vms'] == 0):
ironic_client.node.set_power_state(
self.node_uuid, state)
node.set_power_state(state)
else:
LOG.warning(
"Compute node %s has %s running vms and will "
"NOT be shut off.",
compute_node["hypervisor_hostname"],
compute_node['running_vms'])
return False
else:
ironic_client.node.set_power_state(self.node_uuid, state)
node.set_power_state(state)
ironic_node = ironic_client.node.get(self.node_uuid)
while ironic_node.power_state == current_state and retry:
node = metal_helper.get_node(self.node_uuid)
while node.get_power_state() == current_state and retry:
time.sleep(10)
retry -= 1
ironic_node = ironic_client.node.get(self.node_uuid)
node = metal_helper.get_node(self.node_uuid)
if retry > 0:
return True
else:
@@ -130,4 +136,4 @@ class ChangeNodePowerState(base.BaseAction):
def get_description(self):
"""Description of the action"""
return ("Compute node power on/off through ironic.")
return ("Compute node power on/off through Ironic or MaaS.")

0
watcher/applier/default.py Executable file → Normal file
View File

View File

@@ -199,5 +199,6 @@ class TaskFlowNop(flow_task.Task):
We need at least two atoms to create a link.
"""
def execute(self):
pass

View File

@@ -15,13 +15,15 @@
# common/service.py. This allows the API service to run without monkey
# patching under Apache (which uses its own concurrency model). Mixing
# concurrency models can cause undefined behavior and potentially API timeouts.
import eventlet
eventlet.monkey_patch()
# Monkey patch the original current_thread to use the up-to-date _active
# global variable. See https://bugs.launchpad.net/bugs/1863021 and
# https://github.com/eventlet/eventlet/issues/592
import __original_module_threading as orig_threading # noqa
import threading # noqa
orig_threading.current_thread.__globals__['_active'] = threading._active
# NOTE(sean-k-mooney) while ^ is true, since that was written asyncio was added
# to the code base in addition to apscheduler which provides native threads.
# As such we have a lot of technical debt to fix with regards to watchers
# concurrency model as we are mixing up to 3 models the same process.
# apscheduler does not technically support eventlet but it has mostly worked
# until now, apscheduler is used to provide a job schedulers which mixes
# monkey patched and non monkey patched code in the same process.
# That is problematic and can lead to errors on python 3.12+.
# The maas support added asyncio to the codebase which is unsafe to mix
# with eventlets by default.
from watcher import eventlet
eventlet.patch()

View File

@@ -17,7 +17,7 @@ import time
from oslo_log import log
from cinderclient import exceptions as cinder_exception
from cinderclient.v2.volumes import Volume
from cinderclient.v3.volumes import Volume
from watcher._i18n import _
from watcher.common import clients
from watcher.common import exception
@@ -153,7 +153,7 @@ class CinderHelper(object):
final_status = ('success', 'error')
while getattr(volume, 'migration_status') not in final_status:
volume = self.get_volume(volume.id)
LOG.debug('Waiting the migration of {0}'.format(volume))
LOG.debug('Waiting the migration of %s', volume)
time.sleep(retry_interval)
if getattr(volume, 'migration_status') == 'error':
host_name = getattr(volume, 'os-vol-host-attr:host')
@@ -230,7 +230,7 @@ class CinderHelper(object):
availability_zone=getattr(volume, 'availability_zone'))
while getattr(new_volume, 'status') != 'available' and retry:
new_volume = cinder.volumes.get(new_volume.id)
LOG.debug('Waiting volume creation of {0}'.format(new_volume))
LOG.debug('Waiting volume creation of %s', new_volume)
time.sleep(retry_interval)
retry -= 1
LOG.debug("retry count: %s", retry)

44
watcher/common/clients.py Executable file → Normal file
View File

@@ -25,12 +25,13 @@ from novaclient import api_versions as nova_api_versions
from novaclient import client as nvclient
from watcher.common import exception
from watcher.common import utils
try:
from ceilometerclient import client as ceclient
HAS_CEILCLIENT = True
from maas import client as maas_client
except ImportError:
HAS_CEILCLIENT = False
maas_client = None
CONF = cfg.CONF
@@ -70,10 +71,10 @@ class OpenStackClients(object):
self._glance = None
self._gnocchi = None
self._cinder = None
self._ceilometer = None
self._monasca = None
self._neutron = None
self._ironic = None
self._maas = None
self._placement = None
def _get_keystone_session(self):
@@ -180,24 +181,6 @@ class OpenStackClients(object):
session=self.session)
return self._cinder
@exception.wrap_keystone_exception
def ceilometer(self):
if self._ceilometer:
return self._ceilometer
ceilometerclient_version = self._get_client_option('ceilometer',
'api_version')
ceilometer_endpoint_type = self._get_client_option('ceilometer',
'endpoint_type')
ceilometer_region_name = self._get_client_option('ceilometer',
'region_name')
self._ceilometer = ceclient.get_client(
ceilometerclient_version,
endpoint_type=ceilometer_endpoint_type,
region_name=ceilometer_region_name,
session=self.session)
return self._ceilometer
@exception.wrap_keystone_exception
def monasca(self):
if self._monasca:
@@ -265,6 +248,23 @@ class OpenStackClients(object):
session=self.session)
return self._ironic
def maas(self):
if self._maas:
return self._maas
if not maas_client:
raise exception.UnsupportedError(
"MAAS client unavailable. Please install python-libmaas.")
url = self._get_client_option('maas', 'url')
api_key = self._get_client_option('maas', 'api_key')
timeout = self._get_client_option('maas', 'timeout')
self._maas = utils.async_compat_call(
maas_client.connect,
url, apikey=api_key,
timeout=timeout)
return self._maas
@exception.wrap_keystone_exception
def placement(self):
if self._placement:

View File

@@ -11,12 +11,15 @@
# under the License.
from oslo_context import context
from oslo_db.sqlalchemy import enginefacade
from oslo_log import log
from oslo_utils import timeutils
LOG = log.getLogger(__name__)
@enginefacade.transaction_context_provider
class RequestContext(context.RequestContext):
"""Extends security contexts from the OpenStack common library."""

View File

@@ -25,6 +25,7 @@ SHOULD include dedicated exception logging.
import functools
import sys
from http import HTTPStatus
from keystoneclient import exceptions as keystone_exceptions
from oslo_config import cfg
from oslo_log import log
@@ -62,7 +63,7 @@ class WatcherException(Exception):
"""
msg_fmt = _("An unknown exception occurred")
code = 500
code = HTTPStatus.INTERNAL_SERVER_ERROR
headers = {}
safe = False
@@ -114,12 +115,12 @@ class UnsupportedError(WatcherException):
class NotAuthorized(WatcherException):
msg_fmt = _("Not authorized")
code = 403
code = HTTPStatus.FORBIDDEN
class NotAcceptable(WatcherException):
msg_fmt = _("Request not acceptable.")
code = 406
code = HTTPStatus.NOT_ACCEPTABLE
class PolicyNotAuthorized(NotAuthorized):
@@ -132,7 +133,7 @@ class OperationNotPermitted(NotAuthorized):
class Invalid(WatcherException, ValueError):
msg_fmt = _("Unacceptable parameters")
code = 400
code = HTTPStatus.BAD_REQUEST
class ObjectNotFound(WatcherException):
@@ -141,18 +142,22 @@ class ObjectNotFound(WatcherException):
class Conflict(WatcherException):
msg_fmt = _('Conflict')
code = 409
code = HTTPStatus.CONFLICT
class ResourceNotFound(ObjectNotFound):
msg_fmt = _("The %(name)s resource %(id)s could not be found")
code = 404
code = HTTPStatus.NOT_FOUND
class InvalidParameter(Invalid):
msg_fmt = _("%(parameter)s has to be of type %(parameter_type)s")
class MissingParameter(Invalid):
msg_fmt = _("%(parameter)s is required but missing. Check watcher.conf")
class InvalidIdentity(Invalid):
msg_fmt = _("Expected a uuid or int but received %(identity)s")

View File

@@ -72,8 +72,8 @@ class KeystoneHelper(object):
message=(_("Project not Found: %s") % name_or_id))
if len(projects) > 1:
raise exception.Invalid(
messsage=(_("Project name seems ambiguous: %s") %
name_or_id))
message=(_("Project name seems ambiguous: %s") %
name_or_id))
return projects[0]
def get_domain(self, name_or_id):

View File

View File

@@ -0,0 +1,81 @@
# Copyright 2023 Cloudbase Solutions
# All Rights Reserved.
#
# 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 abc
from watcher.common import exception
from watcher.common.metal_helper import constants as metal_constants
class BaseMetalNode(abc.ABC):
hv_up_when_powered_off = False
def __init__(self, nova_node=None):
self._nova_node = nova_node
def get_hypervisor_node(self):
if not self._nova_node:
raise exception.Invalid(message="No associated hypervisor.")
return self._nova_node
def get_hypervisor_hostname(self):
return self.get_hypervisor_node().hypervisor_hostname
@abc.abstractmethod
def get_power_state(self):
# TODO(lpetrut): document the following methods
pass
@abc.abstractmethod
def get_id(self):
"""Return the node id provided by the bare metal service."""
pass
@abc.abstractmethod
def power_on(self):
pass
@abc.abstractmethod
def power_off(self):
pass
def set_power_state(self, state):
state = metal_constants.PowerState(state)
if state == metal_constants.PowerState.ON:
self.power_on()
elif state == metal_constants.PowerState.OFF:
self.power_off()
else:
raise exception.UnsupportedActionType(
"Cannot set power state: %s" % state)
class BaseMetalHelper(abc.ABC):
def __init__(self, osc):
self._osc = osc
@property
def nova_client(self):
if not getattr(self, "_nova_client", None):
self._nova_client = self._osc.nova()
return self._nova_client
@abc.abstractmethod
def list_compute_nodes(self):
pass
@abc.abstractmethod
def get_node(self, node_id):
pass

View File

@@ -0,0 +1,23 @@
# Copyright 2023 Cloudbase Solutions
# All Rights Reserved.
#
# 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 enum
class PowerState(str, enum.Enum):
ON = "on"
OFF = "off"
UNKNOWN = "unknown"
ERROR = "error"

View File

@@ -0,0 +1,33 @@
# Copyright 2023 Cloudbase Solutions
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from watcher.common import clients
from watcher.common.metal_helper import ironic
from watcher.common.metal_helper import maas
CONF = cfg.CONF
def get_helper(osc=None):
# TODO(lpetrut): consider caching this client.
if not osc:
osc = clients.OpenStackClients()
if CONF.maas_client.url:
return maas.MaasHelper(osc)
else:
return ironic.IronicHelper(osc)

View File

@@ -0,0 +1,94 @@
# Copyright 2023 Cloudbase Solutions
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log
from watcher.common.metal_helper import base
from watcher.common.metal_helper import constants as metal_constants
LOG = log.getLogger(__name__)
POWER_STATES_MAP = {
'power on': metal_constants.PowerState.ON,
'power off': metal_constants.PowerState.OFF,
# For now, we only use ON/OFF states
'rebooting': metal_constants.PowerState.ON,
'soft power off': metal_constants.PowerState.OFF,
'soft reboot': metal_constants.PowerState.ON,
}
class IronicNode(base.BaseMetalNode):
hv_up_when_powered_off = True
def __init__(self, ironic_node, nova_node, ironic_client):
super().__init__(nova_node)
self._ironic_client = ironic_client
self._ironic_node = ironic_node
def get_power_state(self):
return POWER_STATES_MAP.get(self._ironic_node.power_state,
metal_constants.PowerState.UNKNOWN)
def get_id(self):
return self._ironic_node.uuid
def power_on(self):
self._ironic_client.node.set_power_state(self.get_id(), "on")
def power_off(self):
self._ironic_client.node.set_power_state(self.get_id(), "off")
class IronicHelper(base.BaseMetalHelper):
@property
def _client(self):
if not getattr(self, "_cached_client", None):
self._cached_client = self._osc.ironic()
return self._cached_client
def list_compute_nodes(self):
out_list = []
# TODO(lpetrut): consider using "detailed=True" instead of making
# an additional GET request per node
node_list = self._client.node.list()
for node in node_list:
node_info = self._client.node.get(node.uuid)
hypervisor_id = node_info.extra.get('compute_node_id', None)
if hypervisor_id is None:
LOG.warning('Cannot find compute_node_id in extra '
'of ironic node %s', node.uuid)
continue
hypervisor_node = self.nova_client.hypervisors.get(hypervisor_id)
if hypervisor_node is None:
LOG.warning('Cannot find hypervisor %s', hypervisor_id)
continue
out_node = IronicNode(node, hypervisor_node, self._client)
out_list.append(out_node)
return out_list
def get_node(self, node_id):
ironic_node = self._client.node.get(node_id)
compute_node_id = ironic_node.extra.get('compute_node_id')
if compute_node_id:
compute_node = self.nova_client.hypervisors.get(compute_node_id)
else:
compute_node = None
return IronicNode(ironic_node, compute_node, self._client)

View File

@@ -0,0 +1,125 @@
# Copyright 2023 Cloudbase Solutions
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from oslo_log import log
from watcher.common import exception
from watcher.common.metal_helper import base
from watcher.common.metal_helper import constants as metal_constants
from watcher.common import utils
CONF = cfg.CONF
LOG = log.getLogger(__name__)
try:
from maas.client import enum as maas_enum
except ImportError:
maas_enum = None
class MaasNode(base.BaseMetalNode):
hv_up_when_powered_off = False
def __init__(self, maas_node, nova_node, maas_client):
super().__init__(nova_node)
self._maas_client = maas_client
self._maas_node = maas_node
def get_power_state(self):
maas_state = utils.async_compat_call(
self._maas_node.query_power_state,
timeout=CONF.maas_client.timeout)
# python-libmaas may not be available, so we'll avoid a global
# variable.
power_states_map = {
maas_enum.PowerState.ON: metal_constants.PowerState.ON,
maas_enum.PowerState.OFF: metal_constants.PowerState.OFF,
maas_enum.PowerState.ERROR: metal_constants.PowerState.ERROR,
maas_enum.PowerState.UNKNOWN: metal_constants.PowerState.UNKNOWN,
}
return power_states_map.get(maas_state,
metal_constants.PowerState.UNKNOWN)
def get_id(self):
return self._maas_node.system_id
def power_on(self):
LOG.info("Powering on MAAS node: %s %s",
self._maas_node.fqdn,
self._maas_node.system_id)
utils.async_compat_call(
self._maas_node.power_on,
timeout=CONF.maas_client.timeout)
def power_off(self):
LOG.info("Powering off MAAS node: %s %s",
self._maas_node.fqdn,
self._maas_node.system_id)
utils.async_compat_call(
self._maas_node.power_off,
timeout=CONF.maas_client.timeout)
class MaasHelper(base.BaseMetalHelper):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not maas_enum:
raise exception.UnsupportedError(
"MAAS client unavailable. Please install python-libmaas.")
@property
def _client(self):
if not getattr(self, "_cached_client", None):
self._cached_client = self._osc.maas()
return self._cached_client
def list_compute_nodes(self):
out_list = []
node_list = utils.async_compat_call(
self._client.machines.list,
timeout=CONF.maas_client.timeout)
compute_nodes = self.nova_client.hypervisors.list()
compute_node_map = dict()
for compute_node in compute_nodes:
compute_node_map[compute_node.hypervisor_hostname] = compute_node
for node in node_list:
hypervisor_node = compute_node_map.get(node.fqdn)
if not hypervisor_node:
LOG.info('Cannot find hypervisor %s', node.fqdn)
continue
out_node = MaasNode(node, hypervisor_node, self._client)
out_list.append(out_node)
return out_list
def _get_compute_node_by_hostname(self, hostname):
compute_nodes = self.nova_client.hypervisors.search(
hostname, detailed=True)
for compute_node in compute_nodes:
if compute_node.hypervisor_hostname == hostname:
return compute_node
def get_node(self, node_id):
maas_node = utils.async_compat_call(
self._client.machines.get, node_id,
timeout=CONF.maas_client.timeout)
compute_node = self._get_compute_node_by_hostname(maas_node.fqdn)
return MaasNode(maas_node, compute_node, self._client)

View File

@@ -292,9 +292,7 @@ class NovaHelper(object):
'OS-EXT-STS:vm_state') != 'resized' \
and retry:
instance = self.nova.servers.get(instance.id)
LOG.debug(
'Waiting the resize of {0} to {1}'.format(
instance, flavor_id))
LOG.debug('Waiting the resize of %s to %s', instance, flavor_id)
time.sleep(1)
retry -= 1
@@ -349,8 +347,7 @@ class NovaHelper(object):
if dest_hostname is None:
while (instance.status not in ['ACTIVE', 'ERROR'] and retry):
instance = self.nova.servers.get(instance.id)
LOG.debug(
'Waiting the migration of {0}'.format(instance.id))
LOG.debug('Waiting the migration of %s', instance.id)
time.sleep(1)
retry -= 1
new_hostname = getattr(instance, 'OS-EXT-SRV-ATTR:host')
@@ -371,11 +368,9 @@ class NovaHelper(object):
if not getattr(instance, 'OS-EXT-STS:task_state'):
LOG.debug("Instance task state: %s is null", instance_id)
break
LOG.debug(
'Waiting the migration of {0} to {1}'.format(
instance,
getattr(instance,
'OS-EXT-SRV-ATTR:host')))
LOG.debug('Waiting the migration of %s to %s',
instance,
getattr(instance, 'OS-EXT-SRV-ATTR:host'))
time.sleep(1)
retry -= 1
@@ -725,7 +720,7 @@ class NovaHelper(object):
instance_id, old_volume.id, new_volume.id)
while getattr(new_volume, 'status') != 'in-use' and retry:
new_volume = self.cinder.volumes.get(new_volume.id)
LOG.debug('Waiting volume update to {0}'.format(new_volume))
LOG.debug('Waiting volume update to %s', new_volume)
time.sleep(retry_interval)
retry -= 1
LOG.debug("retry count: %s", retry)

View File

@@ -11,6 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from http import HTTPStatus
from oslo_config import cfg
from oslo_log import log as logging
@@ -53,7 +54,7 @@ class PlacementHelper(object):
if rp_name:
url += '?name=%s' % rp_name
resp = self.get(url)
if resp.status_code == 200:
if resp.status_code == HTTPStatus.OK:
json_resp = resp.json()
return json_resp['resource_providers']
@@ -77,7 +78,7 @@ class PlacementHelper(object):
"""
url = '/resource_providers/%s/inventories' % rp_uuid
resp = self.get(url)
if resp.status_code == 200:
if resp.status_code == HTTPStatus.OK:
json = resp.json()
return json['inventories']
msg = ("Failed to get resource provider %(rp_uuid)s inventories. "
@@ -97,7 +98,7 @@ class PlacementHelper(object):
"""
resp = self.get("/resource_providers/%s/traits" % rp_uuid)
if resp.status_code == 200:
if resp.status_code == HTTPStatus.OK:
json = resp.json()
return json['traits']
msg = ("Failed to get resource provider %(rp_uuid)s traits. "
@@ -118,7 +119,7 @@ class PlacementHelper(object):
"""
url = '/allocations/%s' % consumer_uuid
resp = self.get(url)
if resp.status_code == 200:
if resp.status_code == HTTPStatus.OK:
json = resp.json()
return json['allocations']
msg = ("Failed to get allocations for consumer %(c_uuid). "
@@ -139,7 +140,7 @@ class PlacementHelper(object):
"""
url = '/resource_providers/%s/usages' % rp_uuid
resp = self.get(url)
if resp.status_code == 200:
if resp.status_code == HTTPStatus.OK:
json = resp.json()
return json['usages']
msg = ("Failed to get resource provider %(rp_uuid)s usages. "
@@ -164,7 +165,7 @@ class PlacementHelper(object):
"""
url = "/allocation_candidates?%s" % resources
resp = self.get(url)
if resp.status_code == 200:
if resp.status_code == HTTPStatus.OK:
data = resp.json()
return data['provider_summaries']

View File

@@ -18,7 +18,6 @@
import sys
from oslo_config import cfg
from oslo_policy import opts
from oslo_policy import policy
from watcher.common import exception
@@ -27,12 +26,6 @@ from watcher.common import policies
_ENFORCER = None
CONF = cfg.CONF
# TODO(gmann): Remove setting the default value of config policy_file
# once oslo_policy change the default value to 'policy.yaml'.
# https://github.com/openstack/oslo.policy/blob/a626ad12fe5a3abd49d70e3e5b95589d279ab578/oslo_policy/opts.py#L49
DEFAULT_POLICY_FILE = 'policy.yaml'
opts.set_defaults(CONF, DEFAULT_POLICY_FILE)
# we can get a policy enforcer by this init.
# oslo policy support change policy rule dynamically.
@@ -71,7 +64,6 @@ def init(policy_file=None, rules=None,
def enforce(context, rule=None, target=None,
do_raise=True, exc=None, *args, **kwargs):
"""Checks authorization of a rule against the target and credentials.
:param dict context: As much information about the user performing the

View File

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

View File

@@ -16,16 +16,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import eventlet
from apscheduler import events
from apscheduler.executors.pool import BasePoolExecutor
from apscheduler.executors import pool as pool_executor
from apscheduler.schedulers import background
import futurist
from oslo_service import service
from watcher import eventlet as eventlet_helper
job_events = events
class GreenThreadPoolExecutor(BasePoolExecutor):
class GreenThreadPoolExecutor(pool_executor.BasePoolExecutor):
"""Green thread pool
An executor that runs jobs in a green thread pool.
@@ -43,16 +49,25 @@ executors = {
}
class BackgroundSchedulerService(service.ServiceBase,
background.BackgroundScheduler):
def __init__(self, gconfig={}, **options):
class BackgroundSchedulerService(
service.ServiceBase, background.BackgroundScheduler):
def __init__(self, gconfig=None, **options):
self.should_patch = eventlet_helper.is_patched()
if options is None:
options = {'executors': executors}
else:
if 'executors' not in options.keys():
options['executors'] = executors
super(BackgroundSchedulerService, self).__init__(
gconfig, **options)
super().__init__(gconfig or {}, **options)
def _main_loop(self):
if self.should_patch:
# NOTE(sean-k-mooney): is_patched and monkey_patch form
# watcher.eventlet check a non thread local variable to early out
# as we do not use eventlet_helper.patch() here to ensure
# eventlet.monkey_patch() is actually called.
eventlet.monkey_patch()
super()._main_loop()
def start(self):
"""Start service."""

View File

@@ -26,6 +26,7 @@ from oslo_reports import guru_meditation_report as gmr
from oslo_reports import opts as gmr_opts
from oslo_service import service
from oslo_service import wsgi
from oslo_utils import timeutils
from watcher._i18n import _
from watcher.api import app
@@ -120,7 +121,7 @@ class ServiceHeartbeat(scheduling.BackgroundSchedulerService):
'host': host})
if watcher_list:
watcher_service = watcher_list[0]
watcher_service.last_seen_up = datetime.datetime.utcnow()
watcher_service.last_seen_up = timeutils.utcnow()
watcher_service.save()
else:
watcher_service = objects.Service(self.context)

View File

@@ -19,30 +19,37 @@ import abc
class ServiceManager(object, metaclass=abc.ABCMeta):
@abc.abstractproperty
@property
@abc.abstractmethod
def service_name(self):
raise NotImplementedError()
@abc.abstractproperty
@property
@abc.abstractmethod
def api_version(self):
raise NotImplementedError()
@abc.abstractproperty
@property
@abc.abstractmethod
def publisher_id(self):
raise NotImplementedError()
@abc.abstractproperty
@property
@abc.abstractmethod
def conductor_topic(self):
raise NotImplementedError()
@abc.abstractproperty
@property
@abc.abstractmethod
def notification_topics(self):
raise NotImplementedError()
@abc.abstractproperty
@property
@abc.abstractmethod
def conductor_endpoints(self):
raise NotImplementedError()
@abc.abstractproperty
@property
@abc.abstractmethod
def notification_endpoints(self):
raise NotImplementedError()

View File

@@ -16,12 +16,16 @@
"""Utilities and helper functions."""
import asyncio
import datetime
import inspect
import random
import re
import string
from croniter import croniter
import eventlet
from eventlet import tpool
from jsonschema import validators
from oslo_config import cfg
@@ -162,3 +166,37 @@ Draft4Validator = validators.Draft4Validator
def random_string(n):
return ''.join([random.choice(
string.ascii_letters + string.digits) for i in range(n)])
# Some clients (e.g. MAAS) use asyncio, which isn't compatible with Eventlet.
# As a workaround, we're delegating such calls to a native thread.
def async_compat_call(f, *args, **kwargs):
timeout = kwargs.pop('timeout', None)
async def async_wrapper():
ret = f(*args, **kwargs)
if inspect.isawaitable(ret):
return await asyncio.wait_for(ret, timeout)
return ret
def tpool_wrapper():
# This will run in a separate native thread. Ideally, there should be
# a single thread permanently running an asyncio loop, but for
# convenience we'll use eventlet.tpool, which leverages a thread pool.
#
# That being considered, we're setting up a temporary asyncio loop to
# handle this call.
loop = asyncio.new_event_loop()
try:
asyncio.set_event_loop(loop)
return loop.run_until_complete(async_wrapper())
finally:
loop.close()
# We'll use eventlet timeouts as an extra precaution and asyncio timeouts
# to avoid lingering threads. For consistency, we'll convert eventlet
# timeout exceptions to asyncio timeout errors.
with eventlet.timeout.Timeout(
seconds=timeout,
exception=asyncio.TimeoutError("Timeout: %ss" % timeout)):
return tpool.execute(tpool_wrapper)

Some files were not shown because too many files have changed in this diff Show More