Compare commits

...

42 Commits

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

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

Change-Id: I733663a069ea2887ee8f63c56673e3960f8d1a0f
2023-02-28 13:31:06 +00:00
OpenStack Release Bot
c5bf3a56cf Update .gitreview for stable/2023.1
Change-Id: I9e154b95bf1363709d3dfee18d3dd60a661ccbbe
2023-02-28 13:31:04 +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
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
52 changed files with 391 additions and 492 deletions

View File

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

View File

@@ -1,8 +1,9 @@
- project: - project:
queue: watcher
templates: templates:
- check-requirements - check-requirements
- openstack-cover-jobs - openstack-cover-jobs
- openstack-python3-wallaby-jobs - openstack-python3-jobs
- publish-openstack-docs-pti - publish-openstack-docs-pti
- release-notes-jobs-python3 - release-notes-jobs-python3
check: check:
@@ -12,10 +13,8 @@
- watcher-tempest-strategies - watcher-tempest-strategies
- watcher-tempest-actuator - watcher-tempest-actuator
- watcherclient-tempest-functional - watcherclient-tempest-functional
- watcher-tls-test
- watcher-tempest-functional-ipv6-only - watcher-tempest-functional-ipv6-only
gate: gate:
queue: watcher
jobs: jobs:
- watcher-tempest-functional - watcher-tempest-functional
- watcher-tempest-functional-ipv6-only - watcher-tempest-functional-ipv6-only
@@ -87,17 +86,6 @@
tempest_concurrency: 1 tempest_concurrency: 1
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_strategies 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: - job:
name: watcher-tempest-multinode name: watcher-tempest-multinode
parent: watcher-tempest-functional parent: watcher-tempest-functional
@@ -119,8 +107,6 @@
watcher-api: false watcher-api: false
watcher-decision-engine: true watcher-decision-engine: true
watcher-applier: false watcher-applier: false
# We need to add TLS support for watcher plugin
tls-proxy: false
ceilometer: false ceilometer: false
ceilometer-acompute: false ceilometer-acompute: false
ceilometer-acentral: false ceilometer-acentral: false
@@ -168,7 +154,6 @@
devstack_plugins: devstack_plugins:
watcher: https://opendev.org/openstack/watcher watcher: https://opendev.org/openstack/watcher
devstack_services: devstack_services:
tls-proxy: false
watcher-api: true watcher-api: true
watcher-decision-engine: true watcher-decision-engine: true
watcher-applier: true watcher-applier: true

View File

@@ -56,8 +56,8 @@ source_suffix = '.rst'
master_doc = 'index' master_doc = 'index'
# General information about the project. # General information about the project.
project = u'Watcher' project = 'Watcher'
copyright = u'OpenStack Foundation' copyright = 'OpenStack Foundation'
# A list of ignored prefixes for module index sorting. # A list of ignored prefixes for module index sorting.
modindex_common_prefix = ['watcher.'] modindex_common_prefix = ['watcher.']
@@ -91,14 +91,14 @@ pygments_style = 'native'
# List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual' # List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual'
man_pages = [ man_pages = [
('man/watcher-api', 'watcher-api', u'Watcher API Server', ('man/watcher-api', 'watcher-api', 'Watcher API Server',
[u'OpenStack'], 1), ['OpenStack'], 1),
('man/watcher-applier', 'watcher-applier', u'Watcher Applier', ('man/watcher-applier', 'watcher-applier', 'Watcher Applier',
[u'OpenStack'], 1), ['OpenStack'], 1),
('man/watcher-db-manage', 'watcher-db-manage', ('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', ('man/watcher-decision-engine', 'watcher-decision-engine',
u'Watcher Decision Engine', [u'OpenStack'], 1), 'Watcher Decision Engine', ['OpenStack'], 1),
] ]
# -- Options for HTML output -------------------------------------------------- # -- Options for HTML output --------------------------------------------------
@@ -128,8 +128,8 @@ openstackdocs_bug_tag = ''
latex_documents = [ latex_documents = [
('index', ('index',
'doc-watcher.tex', 'doc-watcher.tex',
u'Watcher Documentation', 'Watcher Documentation',
u'OpenStack Foundation', 'manual'), 'OpenStack Foundation', 'manual'),
] ]
# If false, no module index is generated. # If false, no module index is generated.

View File

@@ -47,6 +47,8 @@ unavailable as well as `instance_l3_cpu_cache`::
[[local|localrc]] [[local|localrc]]
enable_plugin watcher https://opendev.org/openstack/watcher 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 ceilometer https://opendev.org/openstack/ceilometer.git
CEILOMETER_BACKEND=gnocchi CEILOMETER_BACKEND=gnocchi

View File

@@ -89,9 +89,9 @@ step 2: Create audit to do optimization
.. code-block:: shell .. code-block:: shell
$ openstack optimize audittemplate create \ $ openstack optimize audittemplate create \
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 -p free_used_percent=20.0
External Links External Links

View File

@@ -53,7 +53,7 @@ source_suffix = '.rst'
master_doc = 'index' master_doc = 'index'
# General information about the project. # General information about the project.
copyright = u'2016, Watcher developers' copyright = '2016, Watcher developers'
# Release notes are version independent # Release notes are version independent
# The short X.Y version. # The short X.Y version.
@@ -196,8 +196,8 @@ latex_elements = {
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]) # (source start file, target name, title, author, documentclass [howto/manual])
latex_documents = [ latex_documents = [
('index', 'watcher.tex', u'Watcher Documentation', ('index', 'watcher.tex', 'Watcher Documentation',
u'Watcher developers', 'manual'), 'Watcher developers', 'manual'),
] ]
# The name of an image file (relative to this directory) to place at the top of # The name of an image file (relative to this directory) to place at the top of
@@ -226,8 +226,8 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
('index', 'watcher', u'Watcher Documentation', ('index', 'watcher', 'Watcher Documentation',
[u'Watcher developers'], 1) ['Watcher developers'], 1)
] ]
# If true, show URL addresses after external links. # If true, show URL addresses after external links.
@@ -240,8 +240,8 @@ man_pages = [
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
('index', 'watcher', u'Watcher Documentation', ('index', 'watcher', 'Watcher Documentation',
u'Watcher developers', 'watcher', 'One line description of project.', 'Watcher developers', 'watcher', 'One line description of project.',
'Miscellaneous'), 'Miscellaneous'),
] ]

View File

@@ -21,6 +21,10 @@ Contents:
:maxdepth: 1 :maxdepth: 1
unreleased unreleased
zed
yoga
xena
wallaby
victoria victoria
ussuri ussuri
train train

View File

@@ -1,15 +1,16 @@
# Andi Chandler <andi@gowling.com>, 2017. #zanata # Andi Chandler <andi@gowling.com>, 2017. #zanata
# Andi Chandler <andi@gowling.com>, 2018. #zanata # Andi Chandler <andi@gowling.com>, 2018. #zanata
# Andi Chandler <andi@gowling.com>, 2020. #zanata # Andi Chandler <andi@gowling.com>, 2020. #zanata
# Andi Chandler <andi@gowling.com>, 2022. #zanata
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: python-watcher\n" "Project-Id-Version: python-watcher\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-10-27 04:13+0000\n" "POT-Creation-Date: 2022-08-29 03:02+0000\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2020-10-28 11:13+0000\n" "PO-Revision-Date: 2022-05-31 08:39+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n" "Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language-Team: English (United Kingdom)\n" "Language-Team: English (United Kingdom)\n"
"Language: en_GB\n" "Language: en_GB\n"
@@ -64,6 +65,9 @@ msgstr "3.0.0"
msgid "4.0.0" msgid "4.0.0"
msgstr "4.0.0" msgstr "4.0.0"
msgid "6.0.0"
msgstr "6.0.0"
msgid "A ``watcher-status upgrade check`` has been added for this." msgid "A ``watcher-status upgrade check`` has been added for this."
msgstr "A ``watcher-status upgrade check`` has been added for this." msgstr "A ``watcher-status upgrade check`` has been added for this."
@@ -744,6 +748,23 @@ msgstr ""
"The configuration options for query retries in `[gnocchi_client]` are " "The configuration options for query retries in `[gnocchi_client]` are "
"deprecated and the option in `[watcher_datasources]` should now be used." "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 "" msgid ""
"The graph model describes how VMs are associated to compute hosts. This " "The graph model describes how VMs are associated to compute hosts. This "
"allows for seeing relationships upfront between the entities and hence can " "allows for seeing relationships upfront between the entities and hence can "
@@ -799,6 +820,21 @@ msgstr "Train Series Release Notes"
msgid "Upgrade Notes" msgid "Upgrade Notes"
msgstr "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 "" msgid ""
"Using ``watcher/api/app.wsgi`` script is deprecated and it will be removed " "Using ``watcher/api/app.wsgi`` script is deprecated and it will be removed "
"in U release. Please switch to automatically generated ``watcher-api-wsgi`` " "in U release. Please switch to automatically generated ``watcher-api-wsgi`` "
@@ -814,6 +850,9 @@ msgstr "Ussuri Series Release Notes"
msgid "Victoria Series Release Notes" msgid "Victoria Series Release Notes"
msgstr "Victoria Series Release Notes" msgstr "Victoria Series Release Notes"
msgid "Wallaby Series Release Notes"
msgstr "Wallaby Series Release Notes"
msgid "" msgid ""
"Watcher can continuously optimize the OpenStack cloud for a specific " "Watcher can continuously optimize the OpenStack cloud for a specific "
"strategy or goal by triggering an audit periodically which generates an " "strategy or goal by triggering an audit periodically which generates an "
@@ -924,6 +963,12 @@ msgstr "We also add some new properties:"
msgid "Welcome to watcher's Release Notes documentation!" msgid "Welcome to watcher's Release Notes documentation!"
msgstr "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 "``[watcher_datasources] datasources = gnocchi,monasca,ceilometer``" msgid "``[watcher_datasources] datasources = gnocchi,monasca,ceilometer``"
msgstr "``[watcher_datasources] datasources = gnocchi,monasca,ceilometer``" msgstr "``[watcher_datasources] datasources = gnocchi,monasca,ceilometer``"

View File

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

View File

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

View File

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

View File

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

View File

@@ -30,7 +30,6 @@ pbr>=3.1.1 # Apache-2.0
pecan>=1.3.2 # BSD pecan>=1.3.2 # BSD
PrettyTable>=0.7.2 # BSD PrettyTable>=0.7.2 # BSD
gnocchiclient>=7.0.1 # Apache-2.0 gnocchiclient>=7.0.1 # Apache-2.0
python-ceilometerclient>=2.9.0 # Apache-2.0
python-cinderclient>=3.5.0 # Apache-2.0 python-cinderclient>=3.5.0 # Apache-2.0
python-glanceclient>=2.9.1 # Apache-2.0 python-glanceclient>=2.9.1 # Apache-2.0
python-keystoneclient>=3.15.0 # Apache-2.0 python-keystoneclient>=3.15.0 # Apache-2.0

View File

@@ -1,12 +1,12 @@
[metadata] [metadata]
name = python-watcher name = python-watcher
summary = OpenStack Watcher provides a flexible and scalable resource optimization service for multi-tenant OpenStack-based clouds. summary = OpenStack Watcher provides a flexible and scalable resource optimization service for multi-tenant OpenStack-based clouds.
description-file = description_file =
README.rst README.rst
author = OpenStack author = OpenStack
author-email = openstack-discuss@lists.openstack.org author_email = openstack-discuss@lists.openstack.org
home-page = https://docs.openstack.org/watcher/latest/ home_page = https://docs.openstack.org/watcher/latest/
python-requires = >=3.6 python_requires = >=3.6
classifier = classifier =
Environment :: OpenStack Environment :: OpenStack
Intended Audience :: Information Technology Intended Audience :: Information Technology

View File

@@ -7,9 +7,9 @@ doc8>=0.8.0 # Apache-2.0
freezegun>=0.3.10 # Apache-2.0 freezegun>=0.3.10 # Apache-2.0
hacking>=3.0.1,<3.1.0 # Apache-2.0 hacking>=3.0.1,<3.1.0 # Apache-2.0
oslotest>=3.3.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 testscenarios>=0.5.0 # Apache-2.0/BSD
testtools>=2.3.0 # MIT testtools>=2.3.0 # MIT
stestr>=2.0.0 # Apache-2.0 stestr>=2.0.0 # Apache-2.0
os-api-ref>=1.4.0 # Apache-2.0 os-api-ref>=1.4.0 # Apache-2.0
bandit>=1.6.0 # Apache-2.0 bandit>=1.6.0 # Apache-2.0
WebTest>=2.0.27 # MIT

69
tox.ini
View File

@@ -1,26 +1,30 @@
[tox] [tox]
minversion = 2.0 minversion = 3.18.0
envlist = py38,pep8 envlist = py3,pep8
skipsdist = True
ignore_basepython_conflict = True ignore_basepython_conflict = True
[testenv] [testenv]
basepython = python3 basepython = python3
usedevelop = True usedevelop = True
whitelist_externals = find allowlist_externals = find
rm rm
install_command = pip install {opts} {packages} install_command = pip install -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2023.1} {opts} {packages}
setenv = setenv =
VIRTUAL_ENV={envdir} VIRTUAL_ENV={envdir}
deps = deps =
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt -r{toxinidir}/requirements.txt
commands = commands =
rm -f .testrepository/times.dbm rm -f .testrepository/times.dbm
find . -type f -name "*.py[c|o]" -delete find . -type f -name "*.py[c|o]" -delete
stestr run {posargs} stestr run {posargs}
passenv = 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
[testenv:pep8] [testenv:pep8]
commands = commands =
@@ -31,7 +35,6 @@ commands =
[testenv:venv] [testenv:venv]
setenv = PYTHONHASHSEED=0 setenv = PYTHONHASHSEED=0
deps = deps =
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/doc/requirements.txt -r{toxinidir}/doc/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt -r{toxinidir}/requirements.txt
@@ -49,14 +52,15 @@ commands =
[testenv:docs] [testenv:docs]
setenv = PYTHONHASHSEED=0 setenv = PYTHONHASHSEED=0
deps = -r{toxinidir}/doc/requirements.txt deps =
-r{toxinidir}/doc/requirements.txt
commands = commands =
rm -fr doc/build doc/source/api/ .autogenerated rm -fr doc/build doc/source/api/ .autogenerated
sphinx-build -W --keep-going -b html doc/source doc/build/html sphinx-build -W --keep-going -b html doc/source doc/build/html
[testenv:api-ref] [testenv:api-ref]
deps = -r{toxinidir}/doc/requirements.txt deps = -r{toxinidir}/doc/requirements.txt
whitelist_externals = bash allowlist_externals = bash
commands = commands =
bash -c 'rm -rf api-ref/build' 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 sphinx-build -W --keep-going -b html -d api-ref/build/doctrees api-ref/source api-ref/build/html
@@ -73,6 +77,28 @@ commands =
commands = commands =
oslopolicy-sample-generator --config-file etc/watcher/oslo-policy-generator/watcher-policy-generator.conf 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]
envdir = {toxworkdir}/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]
deps = -r{toxinidir}/test-requirements.txt
commands = bandit -r watcher -x watcher/tests/* -n5 -ll -s B320
[flake8] [flake8]
filename = *.py,app.wsgi filename = *.py,app.wsgi
show-source=True show-source=True
@@ -82,9 +108,6 @@ builtins= _
enable-extensions = H106,H203,H904 enable-extensions = H106,H203,H904
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,*sqlalchemy/alembic/versions/*,demo/,releasenotes exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,*sqlalchemy/alembic/versions/*,demo/,releasenotes
[testenv:wheel]
commands = python setup.py bdist_wheel
[hacking] [hacking]
import_exceptions = watcher._i18n import_exceptions = watcher._i18n
@@ -108,27 +131,7 @@ extension =
N366 = checks:import_stock_mock N366 = checks:import_stock_mock
paths = ./watcher/hacking paths = ./watcher/hacking
[doc8] [doc8]
extension=.rst extension=.rst
# todo: stop ignoring doc/source/man when https://bugs.launchpad.net/doc8/+bug/1502391 is fixed # 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 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

@@ -57,6 +57,7 @@ are dynamically loaded by Watcher at launch time.
import datetime import datetime
from http import HTTPStatus
import pecan import pecan
from pecan import rest from pecan import rest
import wsme import wsme
@@ -362,7 +363,7 @@ class ActionsController(rest.RestController):
return Action.convert_with_links(action) 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): def post(self, action):
"""Create a new action(forbidden). """Create a new action(forbidden).
@@ -422,7 +423,7 @@ class ActionsController(rest.RestController):
action_to_update.save() action_to_update.save()
return Action.convert_with_links(action_to_update) 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): def delete(self, action_uuid):
"""Delete a action(forbidden). """Delete a action(forbidden).

View File

@@ -56,6 +56,7 @@ state machine <action_plan_state_machine>`.
import datetime import datetime
from http import HTTPStatus
from oslo_log import log from oslo_log import log
import pecan import pecan
from pecan import rest from pecan import rest
@@ -460,7 +461,7 @@ class ActionPlansController(rest.RestController):
return ActionPlan.convert_with_links(action_plan) 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): def delete(self, action_plan_uuid):
"""Delete an action plan. """Delete an action plan.

View File

@@ -32,6 +32,7 @@ states, visit :ref:`the Audit State machine <audit_state_machine>`.
import datetime import datetime
from dateutil import tz from dateutil import tz
from http import HTTPStatus
import pecan import pecan
from pecan import rest from pecan import rest
import wsme import wsme
@@ -595,7 +596,8 @@ class AuditsController(rest.RestController):
return Audit.convert_with_links(rpc_audit) 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): def post(self, audit_p):
"""Create a new audit. """Create a new audit.
@@ -717,7 +719,7 @@ class AuditsController(rest.RestController):
audit_to_update.save() audit_to_update.save()
return Audit.convert_with_links(audit_to_update) 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): def delete(self, audit):
"""Delete an audit. """Delete an audit.

View File

@@ -45,6 +45,7 @@ will be launched automatically or will need a manual confirmation from the
import datetime import datetime
from http import HTTPStatus
import pecan import pecan
from pecan import rest from pecan import rest
import wsme import wsme
@@ -618,7 +619,7 @@ class AuditTemplatesController(rest.RestController):
@wsme.validate(types.uuid, AuditTemplatePostType) @wsme.validate(types.uuid, AuditTemplatePostType)
@wsme_pecan.wsexpose(AuditTemplate, body=AuditTemplatePostType, @wsme_pecan.wsexpose(AuditTemplate, body=AuditTemplatePostType,
status_code=201) status_code=HTTPStatus.CREATED)
def post(self, audit_template_postdata): def post(self, audit_template_postdata):
"""Create a new audit template. """Create a new audit template.
@@ -694,7 +695,7 @@ class AuditTemplatesController(rest.RestController):
audit_template_to_update.save() audit_template_to_update.save()
return AuditTemplate.convert_with_links(audit_template_to_update) 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): def delete(self, audit_template):
"""Delete a audit template. """Delete a audit template.

View File

@@ -14,6 +14,7 @@
Webhook endpoint for Watcher v1 REST API. Webhook endpoint for Watcher v1 REST API.
""" """
from http import HTTPStatus
from oslo_log import log from oslo_log import log
import pecan import pecan
from pecan import rest from pecan import rest
@@ -36,7 +37,7 @@ class WebhookController(rest.RestController):
self.dc_client = rpcapi.DecisionEngineAPI() self.dc_client = rpcapi.DecisionEngineAPI()
@wsme_pecan.wsexpose(None, wtypes.text, body=types.jsontype, @wsme_pecan.wsexpose(None, wtypes.text, body=types.jsontype,
status_code=202) status_code=HTTPStatus.ACCEPTED)
def post(self, audit_ident, body): def post(self, audit_ident, body):
"""Trigger the given audit. """Trigger the given audit.

View File

@@ -15,7 +15,7 @@
# under the License. # under the License.
from http import client as http_client from http import HTTPStatus
from oslo_config import cfg from oslo_config import cfg
from pecan import hooks from pecan import hooks
@@ -91,8 +91,8 @@ class NoExceptionTracebackHook(hooks.PecanHook):
# Do nothing if there is no error. # Do nothing if there is no error.
# Status codes in the range 200 (OK) to 399 (400 = BAD_REQUEST) are not # Status codes in the range 200 (OK) to 399 (400 = BAD_REQUEST) are not
# an error. # an error.
if (http_client.OK <= state.response.status_int < if (HTTPStatus.OK <= state.response.status_int <
http_client.BAD_REQUEST): HTTPStatus.BAD_REQUEST):
return return
json_body = state.response.json json_body = state.response.json

View File

@@ -17,7 +17,7 @@ import time
from oslo_log import log from oslo_log import log
from cinderclient import exceptions as cinder_exception 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._i18n import _
from watcher.common import clients from watcher.common import clients
from watcher.common import exception from watcher.common import exception

View File

@@ -25,6 +25,7 @@ SHOULD include dedicated exception logging.
import functools import functools
import sys import sys
from http import HTTPStatus
from keystoneclient import exceptions as keystone_exceptions from keystoneclient import exceptions as keystone_exceptions
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log from oslo_log import log
@@ -62,7 +63,7 @@ class WatcherException(Exception):
""" """
msg_fmt = _("An unknown exception occurred") msg_fmt = _("An unknown exception occurred")
code = 500 code = HTTPStatus.INTERNAL_SERVER_ERROR
headers = {} headers = {}
safe = False safe = False
@@ -114,12 +115,12 @@ class UnsupportedError(WatcherException):
class NotAuthorized(WatcherException): class NotAuthorized(WatcherException):
msg_fmt = _("Not authorized") msg_fmt = _("Not authorized")
code = 403 code = HTTPStatus.FORBIDDEN
class NotAcceptable(WatcherException): class NotAcceptable(WatcherException):
msg_fmt = _("Request not acceptable.") msg_fmt = _("Request not acceptable.")
code = 406 code = HTTPStatus.NOT_ACCEPTABLE
class PolicyNotAuthorized(NotAuthorized): class PolicyNotAuthorized(NotAuthorized):
@@ -132,7 +133,7 @@ class OperationNotPermitted(NotAuthorized):
class Invalid(WatcherException, ValueError): class Invalid(WatcherException, ValueError):
msg_fmt = _("Unacceptable parameters") msg_fmt = _("Unacceptable parameters")
code = 400 code = HTTPStatus.BAD_REQUEST
class ObjectNotFound(WatcherException): class ObjectNotFound(WatcherException):
@@ -141,12 +142,12 @@ class ObjectNotFound(WatcherException):
class Conflict(WatcherException): class Conflict(WatcherException):
msg_fmt = _('Conflict') msg_fmt = _('Conflict')
code = 409 code = HTTPStatus.CONFLICT
class ResourceNotFound(ObjectNotFound): class ResourceNotFound(ObjectNotFound):
msg_fmt = _("The %(name)s resource %(id)s could not be found") msg_fmt = _("The %(name)s resource %(id)s could not be found")
code = 404 code = HTTPStatus.NOT_FOUND
class InvalidParameter(Invalid): class InvalidParameter(Invalid):

View File

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

View File

@@ -6,6 +6,7 @@ Create Date: 2017-03-24 11:21:29.036532
""" """
from alembic import op from alembic import op
from sqlalchemy import inspect
import sqlalchemy as sa import sqlalchemy as sa
from watcher.db.sqlalchemy import models from watcher.db.sqlalchemy import models
@@ -14,8 +15,17 @@ from watcher.db.sqlalchemy import models
revision = '0f6042416884' revision = '0f6042416884'
down_revision = '001' down_revision = '001'
def _table_exists(table_name):
bind = op.get_context().bind
insp = inspect(bind)
names = insp.get_table_names()
return any(t == table_name for t in names)
def upgrade(): def upgrade():
if _table_exists('apscheduler_jobs'):
return
op.create_table( op.create_table(
'apscheduler_jobs', 'apscheduler_jobs',
sa.Column('id', sa.Unicode(191, _warn_on_bytestring=False), sa.Column('id', sa.Unicode(191, _warn_on_bytestring=False),

View File

@@ -44,7 +44,11 @@ _FACADE = None
def _create_facade_lazily(): def _create_facade_lazily():
global _FACADE global _FACADE
if _FACADE is None: if _FACADE is None:
_FACADE = db_session.EngineFacade.from_config(CONF) # FIXME(amoralej): Remove autocommit=True (and ideally use of
# LegacyEngineFacade) asap since it's not compatible with SQLAlchemy
# 2.0.
_FACADE = db_session.EngineFacade.from_config(CONF,
autocommit=True)
return _FACADE return _FACADE
@@ -278,7 +282,7 @@ class Connection(api.BaseConnection):
query = model_query(model, session=session) query = model_query(model, session=session)
query = add_identity_filter(query, id_) query = add_identity_filter(query, id_)
try: try:
ref = query.with_lockmode('update').one() ref = query.with_for_update().one()
except exc.NoResultFound: except exc.NoResultFound:
raise exception.ResourceNotFound(name=model.__name__, id=id_) raise exception.ResourceNotFound(name=model.__name__, id=id_)
@@ -815,7 +819,7 @@ class Connection(api.BaseConnection):
query = model_query(models.Action, session=session) query = model_query(models.Action, session=session)
query = add_identity_filter(query, action_id) query = add_identity_filter(query, action_id)
try: try:
ref = query.with_lockmode('update').one() ref = query.with_for_update().one()
except exc.NoResultFound: except exc.NoResultFound:
raise exception.ActionNotFound(action=action_id) raise exception.ActionNotFound(action=action_id)
@@ -900,7 +904,7 @@ class Connection(api.BaseConnection):
query = model_query(models.ActionPlan, session=session) query = model_query(models.ActionPlan, session=session)
query = add_identity_filter(query, action_plan_id) query = add_identity_filter(query, action_plan_id)
try: try:
ref = query.with_lockmode('update').one() ref = query.with_for_update().one()
except exc.NoResultFound: except exc.NoResultFound:
raise exception.ActionPlanNotFound(action_plan=action_plan_id) raise exception.ActionPlanNotFound(action_plan=action_plan_id)

View File

@@ -18,6 +18,7 @@
from urllib import parse as urlparse from urllib import parse as urlparse
from http import HTTPStatus
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log from oslo_log import log
@@ -138,11 +139,11 @@ class GrafanaHelper(base.DataSourceBase):
resp = requests.get(self._base_url + str(project_id) + '/query', resp = requests.get(self._base_url + str(project_id) + '/query',
params=params, headers=self._headers) params=params, headers=self._headers)
if resp.status_code == 200: if resp.status_code == HTTPStatus.OK:
return resp return resp
elif resp.status_code == 400: elif resp.status_code == HTTPStatus.BAD_REQUEST:
LOG.error("Query for metric is invalid") LOG.error("Query for metric is invalid")
elif resp.status_code == 401: elif resp.status_code == HTTPStatus.UNAUTHORIZED:
LOG.error("Authorization token is invalid") LOG.error("Authorization token is invalid")
raise exception.DataSourceNotAvailable(self.NAME) raise exception.DataSourceNotAvailable(self.NAME)

View File

@@ -205,7 +205,7 @@ class CinderModelBuilder(base.BaseModelBuilder):
"""Build a storage node from a Cinder storage node """Build a storage node from a Cinder storage node
:param node: A storage node :param node: A storage node
:type node: :py:class:`~cinderclient.v2.services.Service` :type node: :py:class:`~cinderclient.v3.services.Service`
""" """
# node.host is formatted as host@backendname since ocata, # node.host is formatted as host@backendname since ocata,
# or may be only host as of ocata # or may be only host as of ocata
@@ -233,7 +233,7 @@ class CinderModelBuilder(base.BaseModelBuilder):
"""Build a storage pool from a Cinder storage pool """Build a storage pool from a Cinder storage pool
:param pool: A storage pool :param pool: A storage pool
:type pool: :py:class:`~cinderclient.v2.pools.Pool` :type pool: :py:class:`~cinderclient.v3.pools.Pool`
:raises: exception.InvalidPoolAttributeValue :raises: exception.InvalidPoolAttributeValue
""" """
# build up the storage pool. # build up the storage pool.

View File

@@ -197,22 +197,22 @@ class SavingEnergy(base.SavingEnergyBaseStrategy):
def save_energy(self): def save_energy(self):
need_poweron = max( need_poweron = int(max(
(len(self.with_vms_node_pool) * self.free_used_percent / 100), ( (len(self.with_vms_node_pool) * self.free_used_percent / 100), (
self.min_free_hosts_num)) self.min_free_hosts_num)))
len_poweron = len(self.free_poweron_node_pool) len_poweron = len(self.free_poweron_node_pool)
len_poweroff = len(self.free_poweroff_node_pool) len_poweroff = len(self.free_poweroff_node_pool)
if len_poweron > need_poweron: if len_poweron > need_poweron:
for node in random.sample(self.free_poweron_node_pool, for node in random.sample(self.free_poweron_node_pool,
(len_poweron - need_poweron)): (len_poweron - need_poweron)):
self.add_action_poweronoff_node(node, 'off') self.add_action_poweronoff_node(node, 'off')
LOG.debug("power off %s", node.uuid) LOG.info("power off %s", node.uuid)
elif len_poweron < need_poweron: elif len_poweron < need_poweron:
diff = need_poweron - len_poweron diff = need_poweron - len_poweron
for node in random.sample(self.free_poweroff_node_pool, for node in random.sample(self.free_poweroff_node_pool,
min(len_poweroff, diff)): min(len_poweroff, diff)):
self.add_action_poweronoff_node(node, 'on') self.add_action_poweronoff_node(node, 'on')
LOG.debug("power on %s", node.uuid) LOG.info("power on %s", node.uuid)
def pre_execute(self): def pre_execute(self):
self._pre_execute() self._pre_execute()

View File

@@ -16,7 +16,7 @@ from dateutil.parser import parse
from oslo_log import log from oslo_log import log
from cinderclient.v2.volumes import Volume from cinderclient.v3.volumes import Volume
from novaclient.v2.servers import Server from novaclient.v2.servers import Server
from watcher._i18n import _ from watcher._i18n import _
from watcher.common import cinder_helper from watcher.common import cinder_helper

View File

@@ -1,15 +1,16 @@
# Andi Chandler <andi@gowling.com>, 2017. #zanata # Andi Chandler <andi@gowling.com>, 2017. #zanata
# Andi Chandler <andi@gowling.com>, 2018. #zanata # Andi Chandler <andi@gowling.com>, 2018. #zanata
# Andi Chandler <andi@gowling.com>, 2020. #zanata # Andi Chandler <andi@gowling.com>, 2020. #zanata
# Andi Chandler <andi@gowling.com>, 2022. #zanata
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: watcher VERSION\n" "Project-Id-Version: watcher VERSION\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2020-10-27 04:14+0000\n" "POT-Creation-Date: 2022-08-29 03:03+0000\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2020-10-28 11:02+0000\n" "PO-Revision-Date: 2022-05-31 08:38+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n" "Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language-Team: English (United Kingdom)\n" "Language-Team: English (United Kingdom)\n"
"Language: en_GB\n" "Language: en_GB\n"
@@ -507,6 +508,9 @@ msgstr ""
msgid "Plugins" msgid "Plugins"
msgstr "Plugins" msgstr "Plugins"
msgid "Policy File JSON to YAML Migration"
msgstr "Policy File JSON to YAML Migration"
#, python-format #, python-format
msgid "Policy doesn't allow %(action)s to be performed." msgid "Policy doesn't allow %(action)s to be performed."
msgstr "Policy doesn't allow %(action)s to be performed." msgstr "Policy doesn't allow %(action)s to be performed."

View File

@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from http import HTTPStatus
from watcher.tests.api import base from watcher.tests.api import base
@@ -25,6 +27,6 @@ class TestBase(base.FunctionalTest):
response = self.get_json('/bad/path', response = self.get_json('/bad/path',
expect_errors=True, expect_errors=True,
headers={"Accept": "application/json"}) headers={"Accept": "application/json"})
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual("application/json", response.content_type) self.assertEqual("application/json", response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])

View File

@@ -14,6 +14,7 @@ import datetime
import itertools import itertools
from unittest import mock from unittest import mock
from http import HTTPStatus
from oslo_config import cfg from oslo_config import cfg
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from wsme import types as wtypes from wsme import types as wtypes
@@ -102,7 +103,7 @@ class TestListAction(api_base.FunctionalTest):
response = self.get_json('/actions/%s' % action['uuid'], response = self.get_json('/actions/%s' % action['uuid'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_detail(self): def test_detail(self):
action = obj_utils.create_test_action(self.context, parents=None) action = obj_utils.create_test_action(self.context, parents=None)
@@ -125,7 +126,7 @@ class TestListAction(api_base.FunctionalTest):
action = obj_utils.create_test_action(self.context, parents=None) action = obj_utils.create_test_action(self.context, parents=None)
response = self.get_json('/actions/%s/detail' % action['uuid'], response = self.get_json('/actions/%s/detail' % action['uuid'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_many(self): def test_many(self):
action_list = [] action_list = []
@@ -266,7 +267,7 @@ class TestListAction(api_base.FunctionalTest):
url = '/actions?action_plan_uuid=%s&audit_uuid=%s' % ( url = '/actions?action_plan_uuid=%s&audit_uuid=%s' % (
action_plan.uuid, self.audit.uuid) action_plan.uuid, self.audit.uuid)
response = self.get_json(url, expect_errors=True) response = self.get_json(url, expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
def test_many_with_sort_key_uuid(self): def test_many_with_sort_key_uuid(self):
action_plan = obj_utils.create_test_action_plan( action_plan = obj_utils.create_test_action_plan(
@@ -327,7 +328,7 @@ class TestListAction(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/actions?sort_key=%s' % 'bad_name', '/actions?sort_key=%s' % 'bad_name',
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
def test_many_with_soft_deleted_action_plan_uuid(self): def test_many_with_soft_deleted_action_plan_uuid(self):
action_plan1 = obj_utils.create_test_action_plan( action_plan1 = obj_utils.create_test_action_plan(
@@ -488,7 +489,7 @@ class TestPatch(api_base.FunctionalTest):
[{'path': '/state', 'value': new_state, 'op': 'replace'}], [{'path': '/state', 'value': new_state, 'op': 'replace'}],
expect_errors=True) expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(403, response.status_int) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_int)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -516,7 +517,7 @@ class TestDelete(api_base.FunctionalTest):
mock_utcnow.return_value = test_time mock_utcnow.return_value = test_time
response = self.delete('/actions/%s' % self.action.uuid, response = self.delete('/actions/%s' % self.action.uuid,
expect_errors=True) expect_errors=True)
self.assertEqual(403, response.status_int) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -536,7 +537,7 @@ class TestActionPolicyEnforcement(api_base.FunctionalTest):
"default": "rule:admin_api", "default": "rule:admin_api",
rule: "rule:defaut"}) rule: "rule:defaut"})
response = func(*arg, **kwarg) response = func(*arg, **kwarg)
self.assertEqual(403, response.status_int) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue( self.assertTrue(
"Policy doesn't allow %s to be performed." % rule, "Policy doesn't allow %s to be performed." % rule,

View File

@@ -14,6 +14,7 @@ import datetime
import itertools import itertools
from unittest import mock from unittest import mock
from http import HTTPStatus
from oslo_config import cfg from oslo_config import cfg
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
@@ -87,7 +88,7 @@ class TestListActionPlan(api_base.FunctionalTest):
response = self.get_json('/action_plans/%s' % action_plan['uuid'], response = self.get_json('/action_plans/%s' % action_plan['uuid'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_detail(self): def test_detail(self):
action_plan = obj_utils.create_test_action_plan(self.context) action_plan = obj_utils.create_test_action_plan(self.context)
@@ -113,7 +114,7 @@ class TestListActionPlan(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/action_plan/%s/detail' % action_plan['uuid'], '/action_plan/%s/detail' % action_plan['uuid'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_many(self): def test_many(self):
action_plan_list = [] action_plan_list = []
@@ -260,7 +261,7 @@ class TestListActionPlan(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/action_plans?sort_key=%s' % 'bad_name', '/action_plans?sort_key=%s' % 'bad_name',
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
def test_links(self): def test_links(self):
uuid = utils.generate_uuid() uuid = utils.generate_uuid()
@@ -317,7 +318,7 @@ class TestDelete(api_base.FunctionalTest):
def test_delete_action_plan_without_action(self): def test_delete_action_plan_without_action(self):
response = self.delete('/action_plans/%s' % self.action_plan.uuid, response = self.delete('/action_plans/%s' % self.action_plan.uuid,
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
self.action_plan.state = objects.action_plan.State.SUCCEEDED self.action_plan.state = objects.action_plan.State.SUCCEEDED
@@ -325,7 +326,7 @@ class TestDelete(api_base.FunctionalTest):
self.delete('/action_plans/%s' % self.action_plan.uuid) self.delete('/action_plans/%s' % self.action_plan.uuid)
response = self.get_json('/action_plans/%s' % self.action_plan.uuid, response = self.get_json('/action_plans/%s' % self.action_plan.uuid,
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -345,20 +346,20 @@ class TestDelete(api_base.FunctionalTest):
expect_errors=True) expect_errors=True)
# The action plan does not exist anymore # The action plan does not exist anymore
self.assertEqual(404, ap_response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, ap_response.status_int)
self.assertEqual('application/json', ap_response.content_type) self.assertEqual('application/json', ap_response.content_type)
self.assertTrue(ap_response.json['error_message']) self.assertTrue(ap_response.json['error_message'])
# Nor does the action # Nor does the action
self.assertEqual(0, len(acts_response['actions'])) self.assertEqual(0, len(acts_response['actions']))
self.assertEqual(404, act_response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, act_response.status_int)
self.assertEqual('application/json', act_response.content_type) self.assertEqual('application/json', act_response.content_type)
self.assertTrue(act_response.json['error_message']) self.assertTrue(act_response.json['error_message'])
def test_delete_action_plan_not_found(self): def test_delete_action_plan_not_found(self):
uuid = utils.generate_uuid() uuid = utils.generate_uuid()
response = self.delete('/action_plans/%s' % uuid, expect_errors=True) response = self.delete('/action_plans/%s' % uuid, expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -388,7 +389,7 @@ class TestStart(api_base.FunctionalTest):
uuid = utils.generate_uuid() uuid = utils.generate_uuid()
response = self.post('/v1/action_plans/%s/%s' % response = self.post('/v1/action_plans/%s/%s' %
(uuid, 'start'), expect_errors=True) (uuid, 'start'), expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -401,11 +402,11 @@ class TestStart(api_base.FunctionalTest):
response = self.post('/v1/action_plans/%s/%s/' response = self.post('/v1/action_plans/%s/%s/'
% (self.action_plan.uuid, 'start'), % (self.action_plan.uuid, 'start'),
expect_errors=True) expect_errors=True)
self.assertEqual(200, response.status_int) self.assertEqual(HTTPStatus.OK, response.status_int)
act_response = self.get_json( act_response = self.get_json(
'/actions/%s' % action.uuid, '/actions/%s' % action.uuid,
expect_errors=True) expect_errors=True)
self.assertEqual(200, act_response.status_int) self.assertEqual(HTTPStatus.OK, act_response.status_int)
self.assertEqual('PENDING', act_response.json['state']) self.assertEqual('PENDING', act_response.json['state'])
self.assertEqual('application/json', act_response.content_type) self.assertEqual('application/json', act_response.content_type)
@@ -445,7 +446,7 @@ class TestPatch(api_base.FunctionalTest):
expect_errors=True) expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
def test_replace_non_existent_action_plan_denied(self): def test_replace_non_existent_action_plan_denied(self):
@@ -455,7 +456,7 @@ class TestPatch(api_base.FunctionalTest):
'value': objects.action_plan.State.PENDING, 'value': objects.action_plan.State.PENDING,
'op': 'replace'}], 'op': 'replace'}],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -465,7 +466,7 @@ class TestPatch(api_base.FunctionalTest):
[{'path': '/foo', 'value': 'bar', 'op': 'add'}], [{'path': '/foo', 'value': 'bar', 'op': 'add'}],
expect_errors=True) expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
def test_remove_denied(self): def test_remove_denied(self):
@@ -480,7 +481,7 @@ class TestPatch(api_base.FunctionalTest):
expect_errors=True) expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
def test_remove_uuid_denied(self): def test_remove_uuid_denied(self):
@@ -488,7 +489,7 @@ class TestPatch(api_base.FunctionalTest):
'/action_plans/%s' % self.action_plan.uuid, '/action_plans/%s' % self.action_plan.uuid,
[{'path': '/uuid', 'op': 'remove'}], [{'path': '/uuid', 'op': 'remove'}],
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -497,7 +498,7 @@ class TestPatch(api_base.FunctionalTest):
'/action_plans/%s' % self.action_plan.uuid, '/action_plans/%s' % self.action_plan.uuid,
[{'path': '/non-existent', 'op': 'remove'}], [{'path': '/non-existent', 'op': 'remove'}],
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_code) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_code)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -512,7 +513,7 @@ class TestPatch(api_base.FunctionalTest):
[{'path': '/state', 'value': new_state, [{'path': '/state', 'value': new_state,
'op': 'replace'}]) 'op': 'replace'}])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_code) self.assertEqual(HTTPStatus.OK, response.status_code)
applier_mock.assert_called_once_with(mock.ANY, applier_mock.assert_called_once_with(mock.ANY,
self.action_plan.uuid) self.action_plan.uuid)
@@ -579,7 +580,7 @@ class TestPatchStateTransitionDenied(api_base.FunctionalTest):
self.assertNotEqual(self.new_state, initial_ap['state']) self.assertNotEqual(self.new_state, initial_ap['state'])
self.assertEqual(self.original_state, updated_ap['state']) self.assertEqual(self.original_state, updated_ap['state'])
self.assertEqual(400, response.status_code) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_code)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -618,7 +619,7 @@ class TestPatchStateTransitionOk(api_base.FunctionalTest):
self.assertNotEqual(self.new_state, initial_ap['state']) self.assertNotEqual(self.new_state, initial_ap['state'])
self.assertEqual(self.new_state, updated_ap['state']) self.assertEqual(self.new_state, updated_ap['state'])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_code) self.assertEqual(HTTPStatus.OK, response.status_code)
class TestActionPlanPolicyEnforcement(api_base.FunctionalTest): class TestActionPlanPolicyEnforcement(api_base.FunctionalTest):
@@ -635,7 +636,7 @@ class TestActionPlanPolicyEnforcement(api_base.FunctionalTest):
"default": "rule:admin_api", "default": "rule:admin_api",
rule: "rule:defaut"}) rule: "rule:defaut"})
response = func(*arg, **kwarg) response = func(*arg, **kwarg)
self.assertEqual(403, response.status_int) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue( self.assertTrue(
"Policy doesn't allow %s to be performed." % rule, "Policy doesn't allow %s to be performed." % rule,

View File

@@ -15,6 +15,7 @@ import itertools
from unittest import mock from unittest import mock
from urllib import parse as urlparse from urllib import parse as urlparse
from http import HTTPStatus
from oslo_config import cfg from oslo_config import cfg
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from oslo_utils import timeutils from oslo_utils import timeutils
@@ -126,7 +127,7 @@ class TestListAuditTemplate(FunctionalTestWithSetup):
response = self.get_json( response = self.get_json(
'/audit_templates/%s' % audit_template['uuid'], '/audit_templates/%s' % audit_template['uuid'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_detail(self): def test_detail(self):
audit_template = obj_utils.create_test_audit_template(self.context) audit_template = obj_utils.create_test_audit_template(self.context)
@@ -152,7 +153,7 @@ class TestListAuditTemplate(FunctionalTestWithSetup):
response = self.get_json( response = self.get_json(
'/audit_templates/%s/detail' % audit_template['uuid'], '/audit_templates/%s/detail' % audit_template['uuid'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_many(self): def test_many(self):
audit_template_list = [] audit_template_list = []
@@ -336,7 +337,7 @@ class TestListAuditTemplate(FunctionalTestWithSetup):
response = self.get_json( response = self.get_json(
'/audit_templates?sort_key=%s' % 'goal_bad_name', '/audit_templates?sort_key=%s' % 'goal_bad_name',
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
class TestPatch(FunctionalTestWithSetup): class TestPatch(FunctionalTestWithSetup):
@@ -362,7 +363,7 @@ class TestPatch(FunctionalTestWithSetup):
[{'path': '/goal', 'value': new_goal_uuid, [{'path': '/goal', 'value': new_goal_uuid,
'op': 'replace'}]) 'op': 'replace'}])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_code) self.assertEqual(HTTPStatus.OK, response.status_code)
response = self.get_json( response = self.get_json(
'/audit_templates/%s' % self.audit_template.uuid) '/audit_templates/%s' % self.audit_template.uuid)
@@ -386,7 +387,7 @@ class TestPatch(FunctionalTestWithSetup):
[{'path': '/goal', 'value': new_goal_uuid, [{'path': '/goal', 'value': new_goal_uuid,
'op': 'replace'}]) 'op': 'replace'}])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_code) self.assertEqual(HTTPStatus.OK, response.status_code)
response = self.get_json( response = self.get_json(
'/audit_templates/%s' % self.audit_template.name) '/audit_templates/%s' % self.audit_template.name)
@@ -401,7 +402,7 @@ class TestPatch(FunctionalTestWithSetup):
[{'path': '/goal', 'value': self.fake_goal1.uuid, [{'path': '/goal', 'value': self.fake_goal1.uuid,
'op': 'replace'}], 'op': 'replace'}],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -416,7 +417,7 @@ class TestPatch(FunctionalTestWithSetup):
[{'path': '/goal', 'value': utils.generate_uuid(), [{'path': '/goal', 'value': utils.generate_uuid(),
'op': 'replace'}], 'op': 'replace'}],
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
assert not cn_mock.called assert not cn_mock.called
def test_add_goal_uuid(self): def test_add_goal_uuid(self):
@@ -426,7 +427,7 @@ class TestPatch(FunctionalTestWithSetup):
'value': self.fake_goal2.uuid, 'value': self.fake_goal2.uuid,
'op': 'add'}]) 'op': 'add'}])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_int) self.assertEqual(HTTPStatus.OK, response.status_int)
response = self.get_json( response = self.get_json(
'/audit_templates/%s' % self.audit_template.uuid) '/audit_templates/%s' % self.audit_template.uuid)
@@ -439,7 +440,7 @@ class TestPatch(FunctionalTestWithSetup):
'value': self.fake_strategy1.uuid, 'value': self.fake_strategy1.uuid,
'op': 'add'}]) 'op': 'add'}])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_int) self.assertEqual(HTTPStatus.OK, response.status_int)
response = self.get_json( response = self.get_json(
'/audit_templates/%s' % self.audit_template.uuid) '/audit_templates/%s' % self.audit_template.uuid)
@@ -452,7 +453,7 @@ class TestPatch(FunctionalTestWithSetup):
'value': self.fake_strategy2['uuid'], 'value': self.fake_strategy2['uuid'],
'op': 'replace'}]) 'op': 'replace'}])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_int) self.assertEqual(HTTPStatus.OK, response.status_int)
response = self.get_json( response = self.get_json(
'/audit_templates/%s' % self.audit_template.uuid) '/audit_templates/%s' % self.audit_template.uuid)
@@ -466,7 +467,7 @@ class TestPatch(FunctionalTestWithSetup):
'value': utils.generate_uuid(), # Does not exist 'value': utils.generate_uuid(), # Does not exist
'op': 'replace'}], expect_errors=True) 'op': 'replace'}], expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
def test_add_non_existent_property(self): def test_add_non_existent_property(self):
@@ -475,7 +476,7 @@ class TestPatch(FunctionalTestWithSetup):
[{'path': '/foo', 'value': 'bar', 'op': 'add'}], [{'path': '/foo', 'value': 'bar', 'op': 'add'}],
expect_errors=True) expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
def test_remove_strategy(self): def test_remove_strategy(self):
@@ -492,7 +493,7 @@ class TestPatch(FunctionalTestWithSetup):
'/audit_templates/%s' % self.audit_template.uuid, '/audit_templates/%s' % self.audit_template.uuid,
[{'path': '/strategy', 'op': 'remove'}]) [{'path': '/strategy', 'op': 'remove'}])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_code) self.assertEqual(HTTPStatus.OK, response.status_code)
def test_remove_goal(self): def test_remove_goal(self):
response = self.get_json( response = self.get_json(
@@ -503,7 +504,7 @@ class TestPatch(FunctionalTestWithSetup):
'/audit_templates/%s' % self.audit_template.uuid, '/audit_templates/%s' % self.audit_template.uuid,
[{'path': '/goal', 'op': 'remove'}], [{'path': '/goal', 'op': 'remove'}],
expect_errors=True) expect_errors=True)
self.assertEqual(403, response.status_code) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_code)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -512,7 +513,7 @@ class TestPatch(FunctionalTestWithSetup):
'/audit_templates/%s' % self.audit_template.uuid, '/audit_templates/%s' % self.audit_template.uuid,
[{'path': '/uuid', 'op': 'remove'}], [{'path': '/uuid', 'op': 'remove'}],
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -521,7 +522,7 @@ class TestPatch(FunctionalTestWithSetup):
'/audit_templates/%s' % self.audit_template.uuid, '/audit_templates/%s' % self.audit_template.uuid,
[{'path': '/non-existent', 'op': 'remove'}], [{'path': '/non-existent', 'op': 'remove'}],
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_code) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_code)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -538,7 +539,7 @@ class TestPost(FunctionalTestWithSetup):
response = self.post_json('/audit_templates', audit_template_dict) response = self.post_json('/audit_templates', audit_template_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
# Check location header # Check location header
self.assertIsNotNone(response.location) self.assertIsNotNone(response.location)
expected_location = \ expected_location = \
@@ -565,7 +566,7 @@ class TestPost(FunctionalTestWithSetup):
response = self.post_json('/audit_templates', audit_template_dict) response = self.post_json('/audit_templates', audit_template_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
# Check location header # Check location header
self.assertIsNotNone(response.location) self.assertIsNotNone(response.location)
expected_location = \ expected_location = \
@@ -613,7 +614,8 @@ class TestPost(FunctionalTestWithSetup):
strategy=self.fake_strategy1.uuid, scope=scope) strategy=self.fake_strategy1.uuid, scope=scope)
response = self.post_json('/audit_templates', response = self.post_json('/audit_templates',
audit_template_dict, expect_errors=True) audit_template_dict, expect_errors=True)
self.assertEqual(500, response.status_int) self.assertEqual(HTTPStatus.INTERNAL_SERVER_ERROR,
response.status_int)
def test_create_audit_template_does_autogenerate_id(self): def test_create_audit_template_does_autogenerate_id(self):
audit_template_dict = post_get_test_audit_template( audit_template_dict = post_get_test_audit_template(
@@ -635,7 +637,7 @@ class TestPost(FunctionalTestWithSetup):
response = self.post_json('/audit_templates', audit_template_dict) response = self.post_json('/audit_templates', audit_template_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertTrue(utils.is_uuid_like(response.json['uuid'])) self.assertTrue(utils.is_uuid_like(response.json['uuid']))
def test_create_audit_template_with_invalid_goal(self): def test_create_audit_template_with_invalid_goal(self):
@@ -648,7 +650,7 @@ class TestPost(FunctionalTestWithSetup):
goal_uuid=utils.generate_uuid()) goal_uuid=utils.generate_uuid())
response = self.post_json('/audit_templates', response = self.post_json('/audit_templates',
audit_template_dict, expect_errors=True) audit_template_dict, expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
assert not cn_mock.called assert not cn_mock.called
def test_create_audit_template_with_invalid_strategy(self): def test_create_audit_template_with_invalid_strategy(self):
@@ -662,7 +664,7 @@ class TestPost(FunctionalTestWithSetup):
strategy_uuid=utils.generate_uuid()) strategy_uuid=utils.generate_uuid())
response = self.post_json('/audit_templates', response = self.post_json('/audit_templates',
audit_template_dict, expect_errors=True) audit_template_dict, expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
assert not cn_mock.called assert not cn_mock.called
def test_create_audit_template_with_unrelated_strategy(self): def test_create_audit_template_with_unrelated_strategy(self):
@@ -676,7 +678,7 @@ class TestPost(FunctionalTestWithSetup):
strategy=self.fake_strategy2['uuid']) strategy=self.fake_strategy2['uuid'])
response = self.post_json('/audit_templates', response = self.post_json('/audit_templates',
audit_template_dict, expect_errors=True) audit_template_dict, expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
assert not cn_mock.called assert not cn_mock.called
def test_create_audit_template_with_uuid(self): def test_create_audit_template_with_uuid(self):
@@ -689,7 +691,7 @@ class TestPost(FunctionalTestWithSetup):
response = self.post_json('/audit_templates', audit_template_dict, response = self.post_json('/audit_templates', audit_template_dict,
expect_errors=True) expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
assert not cn_mock.called assert not cn_mock.called
def test_create_audit_template_with_old_scope(self): def test_create_audit_template_with_old_scope(self):
@@ -710,7 +712,7 @@ class TestPost(FunctionalTestWithSetup):
strategy=self.fake_strategy1.uuid, scope=scope) strategy=self.fake_strategy1.uuid, scope=scope)
response = self.post_json('/audit_templates', response = self.post_json('/audit_templates',
audit_template_dict) audit_template_dict)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
class TestDelete(api_base.FunctionalTest): class TestDelete(api_base.FunctionalTest):
@@ -730,7 +732,7 @@ class TestDelete(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
urlparse.quote('/audit_templates/%s' % self.audit_template.uuid), urlparse.quote('/audit_templates/%s' % self.audit_template.uuid),
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -753,7 +755,7 @@ class TestDelete(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
urlparse.quote('/audit_templates/%s' % self.audit_template.name), urlparse.quote('/audit_templates/%s' % self.audit_template.name),
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -771,7 +773,7 @@ class TestDelete(api_base.FunctionalTest):
uuid = utils.generate_uuid() uuid = utils.generate_uuid()
response = self.delete( response = self.delete(
'/audit_templates/%s' % uuid, expect_errors=True) '/audit_templates/%s' % uuid, expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -784,7 +786,7 @@ class TestAuditTemplatePolicyEnforcement(api_base.FunctionalTest):
"default": "rule:admin_api", "default": "rule:admin_api",
rule: "rule:defaut"}) rule: "rule:defaut"})
response = func(*arg, **kwarg) response = func(*arg, **kwarg)
self.assertEqual(403, response.status_int) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue( self.assertTrue(
"Policy doesn't allow %s to be performed." % rule, "Policy doesn't allow %s to be performed." % rule,

View File

@@ -16,6 +16,7 @@ import itertools
from unittest import mock from unittest import mock
from urllib import parse as urlparse from urllib import parse as urlparse
from http import HTTPStatus
from oslo_config import cfg from oslo_config import cfg
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from oslo_utils import timeutils from oslo_utils import timeutils
@@ -130,7 +131,7 @@ class TestListAudit(api_base.FunctionalTest):
response = self.get_json('/audits/%s' % audit['uuid'], response = self.get_json('/audits/%s' % audit['uuid'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_detail(self): def test_detail(self):
audit = obj_utils.create_test_audit(self.context) audit = obj_utils.create_test_audit(self.context)
@@ -153,7 +154,7 @@ class TestListAudit(api_base.FunctionalTest):
audit = obj_utils.create_test_audit(self.context) audit = obj_utils.create_test_audit(self.context)
response = self.get_json('/audits/%s/detail' % audit['uuid'], response = self.get_json('/audits/%s/detail' % audit['uuid'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_many(self): def test_many(self):
audit_list = [] audit_list = []
@@ -225,7 +226,7 @@ class TestListAudit(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/audits?sort_key=%s' % 'bad_name', '/audits?sort_key=%s' % 'bad_name',
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
def test_links(self): def test_links(self):
uuid = utils.generate_uuid() uuid = utils.generate_uuid()
@@ -295,7 +296,7 @@ class TestPatch(api_base.FunctionalTest):
[{'path': '/state', 'value': new_state, [{'path': '/state', 'value': new_state,
'op': 'replace'}]) 'op': 'replace'}])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_code) self.assertEqual(HTTPStatus.OK, response.status_code)
response = self.get_json('/audits/%s' % self.audit.uuid) response = self.get_json('/audits/%s' % self.audit.uuid)
self.assertEqual(new_state, response['state']) self.assertEqual(new_state, response['state'])
@@ -308,7 +309,7 @@ class TestPatch(api_base.FunctionalTest):
'/audits/%s' % utils.generate_uuid(), '/audits/%s' % utils.generate_uuid(),
[{'path': '/state', 'value': objects.audit.State.SUCCEEDED, [{'path': '/state', 'value': objects.audit.State.SUCCEEDED,
'op': 'replace'}], expect_errors=True) 'op': 'replace'}], expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -318,7 +319,7 @@ class TestPatch(api_base.FunctionalTest):
'/audits/%s' % self.audit.uuid, '/audits/%s' % self.audit.uuid,
[{'path': '/state', 'value': new_state, 'op': 'add'}]) [{'path': '/state', 'value': new_state, 'op': 'add'}])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_int) self.assertEqual(HTTPStatus.OK, response.status_int)
response = self.get_json('/audits/%s' % self.audit.uuid) response = self.get_json('/audits/%s' % self.audit.uuid)
self.assertEqual(new_state, response['state']) self.assertEqual(new_state, response['state'])
@@ -329,7 +330,7 @@ class TestPatch(api_base.FunctionalTest):
[{'path': '/foo', 'value': 'bar', 'op': 'add'}], [{'path': '/foo', 'value': 'bar', 'op': 'add'}],
expect_errors=True) expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
def test_remove_ok(self): def test_remove_ok(self):
@@ -339,7 +340,7 @@ class TestPatch(api_base.FunctionalTest):
response = self.patch_json('/audits/%s' % self.audit.uuid, response = self.patch_json('/audits/%s' % self.audit.uuid,
[{'path': '/interval', 'op': 'remove'}]) [{'path': '/interval', 'op': 'remove'}])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_code) self.assertEqual(HTTPStatus.OK, response.status_code)
response = self.get_json('/audits/%s' % self.audit.uuid) response = self.get_json('/audits/%s' % self.audit.uuid)
self.assertIsNone(response['interval']) self.assertIsNone(response['interval'])
@@ -348,7 +349,7 @@ class TestPatch(api_base.FunctionalTest):
response = self.patch_json('/audits/%s' % self.audit.uuid, response = self.patch_json('/audits/%s' % self.audit.uuid,
[{'path': '/uuid', 'op': 'remove'}], [{'path': '/uuid', 'op': 'remove'}],
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -357,7 +358,7 @@ class TestPatch(api_base.FunctionalTest):
'/audits/%s' % self.audit.uuid, '/audits/%s' % self.audit.uuid,
[{'path': '/non-existent', 'op': 'remove'}], [{'path': '/non-existent', 'op': 'remove'}],
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_code) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_code)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -415,7 +416,7 @@ class TestPatchStateTransitionDenied(api_base.FunctionalTest):
'op': 'replace'}], 'op': 'replace'}],
expect_errors=True) expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(400, response.status_code) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_code)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
response = self.get_json('/audits/%s' % self.audit.uuid) response = self.get_json('/audits/%s' % self.audit.uuid)
@@ -462,7 +463,7 @@ class TestPatchStateTransitionOk(api_base.FunctionalTest):
[{'path': '/state', 'value': self.new_state, [{'path': '/state', 'value': self.new_state,
'op': 'replace'}]) 'op': 'replace'}])
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(200, response.status_code) self.assertEqual(HTTPStatus.OK, response.status_code)
response = self.get_json('/audits/%s' % self.audit.uuid) response = self.get_json('/audits/%s' % self.audit.uuid)
self.assertEqual(self.new_state, response['state']) self.assertEqual(self.new_state, response['state'])
@@ -502,7 +503,7 @@ class TestPost(api_base.FunctionalTest):
response = self.post_json('/audits', audit_dict) response = self.post_json('/audits', audit_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
# Check location header # Check location header
self.assertIsNotNone(response.location) self.assertIsNotNone(response.location)
expected_location = '/v1/audits/%s' % response.json['uuid'] expected_location = '/v1/audits/%s' % response.json['uuid']
@@ -527,7 +528,7 @@ class TestPost(api_base.FunctionalTest):
audit_dict = post_get_test_audit(state=objects.audit.State.SUCCEEDED) audit_dict = post_get_test_audit(state=objects.audit.State.SUCCEEDED)
response = self.post_json('/audits', audit_dict, expect_errors=True) response = self.post_json('/audits', audit_dict, expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -542,7 +543,7 @@ class TestPost(api_base.FunctionalTest):
'next_run_time', 'hostname']) 'next_run_time', 'hostname'])
response = self.post_json('/audits', audit_dict, expect_errors=True) response = self.post_json('/audits', audit_dict, expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -557,7 +558,7 @@ class TestPost(api_base.FunctionalTest):
response = self.post_json('/audits', audit_dict) response = self.post_json('/audits', audit_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertEqual(objects.audit.State.PENDING, self.assertEqual(objects.audit.State.PENDING,
response.json['state']) response.json['state'])
self.assertTrue(utils.is_uuid_like(response.json['uuid'])) self.assertTrue(utils.is_uuid_like(response.json['uuid']))
@@ -573,7 +574,7 @@ class TestPost(api_base.FunctionalTest):
response = self.post_json('/audits', audit_dict) response = self.post_json('/audits', audit_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertEqual(objects.audit.State.PENDING, self.assertEqual(objects.audit.State.PENDING,
response.json['state']) response.json['state'])
self.assertTrue(utils.is_uuid_like(response.json['uuid'])) self.assertTrue(utils.is_uuid_like(response.json['uuid']))
@@ -590,7 +591,7 @@ class TestPost(api_base.FunctionalTest):
response = self.post_json('/audits', audit_dict) response = self.post_json('/audits', audit_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertEqual(objects.audit.State.PENDING, self.assertEqual(objects.audit.State.PENDING,
response.json['state']) response.json['state'])
self.assertTrue(utils.is_uuid_like(response.json['uuid'])) self.assertTrue(utils.is_uuid_like(response.json['uuid']))
@@ -608,7 +609,7 @@ class TestPost(api_base.FunctionalTest):
'01234567-8910-1112-1314-151617181920') '01234567-8910-1112-1314-151617181920')
response = self.post_json('/audits', audit_dict, expect_errors=True) response = self.post_json('/audits', audit_dict, expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual("application/json", response.content_type) self.assertEqual("application/json", response.content_type)
expected_error_msg = ('The audit template UUID or name specified is ' expected_error_msg = ('The audit template UUID or name specified is '
'invalid') 'invalid')
@@ -643,7 +644,7 @@ class TestPost(api_base.FunctionalTest):
response = self.post_json('/audits', audit_dict) response = self.post_json('/audits', audit_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertEqual(objects.audit.State.PENDING, self.assertEqual(objects.audit.State.PENDING,
response.json['state']) response.json['state'])
self.assertTrue(utils.is_uuid_like(response.json['uuid'])) self.assertTrue(utils.is_uuid_like(response.json['uuid']))
@@ -660,7 +661,7 @@ class TestPost(api_base.FunctionalTest):
response = self.post_json('/audits', audit_dict) response = self.post_json('/audits', audit_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertEqual(objects.audit.State.PENDING, self.assertEqual(objects.audit.State.PENDING,
response.json['state']) response.json['state'])
self.assertEqual(audit_dict['interval'], response.json['interval']) self.assertEqual(audit_dict['interval'], response.json['interval'])
@@ -679,7 +680,7 @@ class TestPost(api_base.FunctionalTest):
response = self.post_json('/audits', audit_dict) response = self.post_json('/audits', audit_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertEqual(objects.audit.State.PENDING, self.assertEqual(objects.audit.State.PENDING,
response.json['state']) response.json['state'])
self.assertEqual(audit_dict['interval'], response.json['interval']) self.assertEqual(audit_dict['interval'], response.json['interval'])
@@ -698,9 +699,9 @@ class TestPost(api_base.FunctionalTest):
response = self.post_json('/audits', audit_dict, expect_errors=True) response = self.post_json('/audits', audit_dict, expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(500, response.status_int) self.assertEqual(HTTPStatus.INTERNAL_SERVER_ERROR, response.status_int)
expected_error_msg = ('Exactly 5 or 6 columns has to be ' expected_error_msg = ('Exactly 5 or 6 columns has to be '
'specified for iteratorexpression.') 'specified for iterator expression.')
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
self.assertIn(expected_error_msg, response.json['error_message']) self.assertIn(expected_error_msg, response.json['error_message'])
@@ -714,7 +715,7 @@ class TestPost(api_base.FunctionalTest):
audit_dict['audit_type'] = objects.audit.AuditType.CONTINUOUS.value audit_dict['audit_type'] = objects.audit.AuditType.CONTINUOUS.value
response = self.post_json('/audits', audit_dict, expect_errors=True) response = self.post_json('/audits', audit_dict, expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
expected_error_msg = ('Interval of audit must be specified ' expected_error_msg = ('Interval of audit must be specified '
'for CONTINUOUS.') 'for CONTINUOUS.')
@@ -731,7 +732,7 @@ class TestPost(api_base.FunctionalTest):
audit_dict['audit_type'] = objects.audit.AuditType.ONESHOT.value audit_dict['audit_type'] = objects.audit.AuditType.ONESHOT.value
response = self.post_json('/audits', audit_dict, expect_errors=True) response = self.post_json('/audits', audit_dict, expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
expected_error_msg = 'Interval of audit must not be set for ONESHOT.' expected_error_msg = 'Interval of audit must not be set for ONESHOT.'
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -755,7 +756,7 @@ class TestPost(api_base.FunctionalTest):
del audit_dict['scope'] del audit_dict['scope']
response = self.post_json('/audits', audit_dict, expect_errors=True) response = self.post_json('/audits', audit_dict, expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
assert not mock_trigger_audit.called assert not mock_trigger_audit.called
@mock.patch.object(deapi.DecisionEngineAPI, 'trigger_audit') @mock.patch.object(deapi.DecisionEngineAPI, 'trigger_audit')
@@ -769,7 +770,7 @@ class TestPost(api_base.FunctionalTest):
response = self.post_json('/audits', audit_dict, expect_errors=True) response = self.post_json('/audits', audit_dict, expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
expected_error_msg = ('Specify parameters but no predefined ' expected_error_msg = ('Specify parameters but no predefined '
'strategy for audit, or no ' 'strategy for audit, or no '
'parameter spec in predefined strategy') 'parameter spec in predefined strategy')
@@ -792,7 +793,7 @@ class TestPost(api_base.FunctionalTest):
response = self.post_json('/audits', audit_dict, expect_errors=True) response = self.post_json('/audits', audit_dict, expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
expected_error_msg = ('Specify parameters but no predefined ' expected_error_msg = ('Specify parameters but no predefined '
'strategy for audit, or no ' 'strategy for audit, or no '
'parameter spec in predefined strategy') 'parameter spec in predefined strategy')
@@ -816,7 +817,7 @@ class TestPost(api_base.FunctionalTest):
del audit_dict[k] del audit_dict[k]
response = self.post_json('/audits', audit_dict, expect_errors=True) response = self.post_json('/audits', audit_dict, expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual("application/json", response.content_type) self.assertEqual("application/json", response.content_type)
expected_error_msg = 'Audit parameter fake2 are not allowed' expected_error_msg = 'Audit parameter fake2 are not allowed'
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -875,13 +876,13 @@ class TestPost(api_base.FunctionalTest):
audit_dict['name'] = normal_name audit_dict['name'] = normal_name
response = self.post_json('/audits', audit_dict) response = self.post_json('/audits', audit_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertEqual(normal_name, response.json['name']) self.assertEqual(normal_name, response.json['name'])
audit_dict['name'] = long_name audit_dict['name'] = long_name
response = self.post_json('/audits', audit_dict) response = self.post_json('/audits', audit_dict)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertNotEqual(long_name, response.json['name']) self.assertNotEqual(long_name, response.json['name'])
@mock.patch.object(deapi.DecisionEngineAPI, 'trigger_audit') @mock.patch.object(deapi.DecisionEngineAPI, 'trigger_audit')
@@ -905,7 +906,7 @@ class TestPost(api_base.FunctionalTest):
audit_dict, audit_dict,
headers={'OpenStack-API-Version': 'infra-optim 1.1'}) headers={'OpenStack-API-Version': 'infra-optim 1.1'})
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertEqual(objects.audit.State.PENDING, self.assertEqual(objects.audit.State.PENDING,
response.json['state']) response.json['state'])
self.assertEqual(audit_dict['interval'], response.json['interval']) self.assertEqual(audit_dict['interval'], response.json['interval'])
@@ -944,7 +945,7 @@ class TestPost(api_base.FunctionalTest):
headers={'OpenStack-API-Version': 'infra-optim 1.0'}, headers={'OpenStack-API-Version': 'infra-optim 1.0'},
expect_errors=True) expect_errors=True)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(406, response.status_int) self.assertEqual(HTTPStatus.NOT_ACCEPTABLE, response.status_int)
expected_error_msg = 'Request not acceptable.' expected_error_msg = 'Request not acceptable.'
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
self.assertIn(expected_error_msg, response.json['error_message']) self.assertIn(expected_error_msg, response.json['error_message'])
@@ -963,7 +964,7 @@ class TestPost(api_base.FunctionalTest):
audit_dict, audit_dict,
headers={'OpenStack-API-Version': 'infra-optim 1.2'}) headers={'OpenStack-API-Version': 'infra-optim 1.2'})
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertFalse(response.json['force']) self.assertFalse(response.json['force'])
@mock.patch.object(deapi.DecisionEngineAPI, 'trigger_audit') @mock.patch.object(deapi.DecisionEngineAPI, 'trigger_audit')
@@ -980,7 +981,7 @@ class TestPost(api_base.FunctionalTest):
audit_dict, audit_dict,
headers={'OpenStack-API-Version': 'infra-optim 1.2'}) headers={'OpenStack-API-Version': 'infra-optim 1.2'})
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int) self.assertEqual(HTTPStatus.CREATED, response.status_int)
self.assertTrue(response.json['force']) self.assertTrue(response.json['force'])
@@ -1013,7 +1014,7 @@ class TestDelete(api_base.FunctionalTest):
'op': 'replace'}]) 'op': 'replace'}])
response = self.delete('/audits/%s' % self.audit.uuid, response = self.delete('/audits/%s' % self.audit.uuid,
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -1025,7 +1026,7 @@ class TestDelete(api_base.FunctionalTest):
self.delete('/audits/%s' % self.audit.uuid) self.delete('/audits/%s' % self.audit.uuid)
response = self.get_json('/audits/%s' % self.audit.uuid, response = self.get_json('/audits/%s' % self.audit.uuid,
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -1041,7 +1042,7 @@ class TestDelete(api_base.FunctionalTest):
def test_delete_audit_not_found(self): def test_delete_audit_not_found(self):
uuid = utils.generate_uuid() uuid = utils.generate_uuid()
response = self.delete('/audits/%s' % uuid, expect_errors=True) response = self.delete('/audits/%s' % uuid, expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -1058,7 +1059,7 @@ class TestAuditPolicyEnforcement(api_base.FunctionalTest):
"default": "rule:admin_api", "default": "rule:admin_api",
rule: "rule:defaut"}) rule: "rule:defaut"})
response = func(*arg, **kwarg) response = func(*arg, **kwarg)
self.assertEqual(403, response.status_int) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue( self.assertTrue(
"Policy doesn't allow %s to be performed." % rule, "Policy doesn't allow %s to be performed." % rule,

View File

@@ -15,6 +15,7 @@
from unittest import mock from unittest import mock
from http import HTTPStatus
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from watcher.decision_engine import rpcapi as deapi from watcher.decision_engine import rpcapi as deapi
@@ -42,7 +43,7 @@ class TestListDataModel(api_base.FunctionalTest):
'/data_model/?data_model_type=compute', '/data_model/?data_model_type=compute',
headers={'OpenStack-API-Version': 'infra-optim 1.2'}, headers={'OpenStack-API-Version': 'infra-optim 1.2'},
expect_errors=True) expect_errors=True)
self.assertEqual(406, response.status_int) self.assertEqual(HTTPStatus.NOT_ACCEPTABLE, response.status_int)
class TestDataModelPolicyEnforcement(api_base.FunctionalTest): class TestDataModelPolicyEnforcement(api_base.FunctionalTest):
@@ -59,7 +60,7 @@ class TestDataModelPolicyEnforcement(api_base.FunctionalTest):
"default": "rule:admin_api", "default": "rule:admin_api",
rule: "rule:defaut"}) rule: "rule:defaut"})
response = func(*arg, **kwarg) response = func(*arg, **kwarg)
self.assertEqual(403, response.status_int) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue( self.assertTrue(
"Policy doesn't allow %s to be performed." % rule, "Policy doesn't allow %s to be performed." % rule,

View File

@@ -10,6 +10,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from http import HTTPStatus
from oslo_config import cfg from oslo_config import cfg
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from urllib import parse as urlparse from urllib import parse as urlparse
@@ -59,7 +60,7 @@ class TestListGoal(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/goals/%s' % goal['uuid'], '/goals/%s' % goal['uuid'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_detail(self): def test_detail(self):
goal = obj_utils.create_test_goal(self.context) goal = obj_utils.create_test_goal(self.context)
@@ -71,7 +72,7 @@ class TestListGoal(api_base.FunctionalTest):
goal = obj_utils.create_test_goal(self.context) goal = obj_utils.create_test_goal(self.context)
response = self.get_json('/goals/%s/detail' % goal.uuid, response = self.get_json('/goals/%s/detail' % goal.uuid,
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_many(self): def test_many(self):
goal_list = [] goal_list = []
@@ -139,7 +140,7 @@ class TestListGoal(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/goals?sort_key=%s' % 'bad_name', '/goals?sort_key=%s' % 'bad_name',
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
class TestGoalPolicyEnforcement(api_base.FunctionalTest): class TestGoalPolicyEnforcement(api_base.FunctionalTest):
@@ -150,7 +151,7 @@ class TestGoalPolicyEnforcement(api_base.FunctionalTest):
"default": "rule:admin_api", "default": "rule:admin_api",
rule: "rule:default"}) rule: "rule:default"})
response = func(*arg, **kwarg) response = func(*arg, **kwarg)
self.assertEqual(403, response.status_int) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue( self.assertTrue(
"Policy doesn't allow %s to be performed." % rule, "Policy doesn't allow %s to be performed." % rule,

View File

@@ -10,6 +10,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from http import HTTPStatus
from watcher.api.controllers.v1 import versions from watcher.api.controllers.v1 import versions
from watcher.tests.api import base as api_base from watcher.tests.api import base as api_base
@@ -38,7 +40,7 @@ class TestMicroversions(api_base.FunctionalTest):
'10'])}, '10'])},
expect_errors=True, return_json=False) expect_errors=True, return_json=False)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertEqual(406, response.status_int) self.assertEqual(HTTPStatus.NOT_ACCEPTABLE, response.status_int)
expected_error_msg = ('Invalid value for' expected_error_msg = ('Invalid value for'
' OpenStack-API-Version header') ' OpenStack-API-Version header')
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -98,7 +100,7 @@ class TestMicroversions(api_base.FunctionalTest):
headers={'OpenStack-API-Version': ' '.join([SERVICE_TYPE, headers={'OpenStack-API-Version': ' '.join([SERVICE_TYPE,
'1.999'])}, '1.999'])},
expect_errors=True) expect_errors=True)
self.assertEqual(406, response.status_int) self.assertEqual(HTTPStatus.NOT_ACCEPTABLE, response.status_int)
self.assertEqual(response.headers[H_MIN_VER], MIN_VER) self.assertEqual(response.headers[H_MIN_VER], MIN_VER)
self.assertEqual(response.headers[H_MAX_VER], MAX_VER) self.assertEqual(response.headers[H_MAX_VER], MAX_VER)
expected_error_msg = ('Version 1.999 was requested but the minor ' expected_error_msg = ('Version 1.999 was requested but the minor '

View File

@@ -10,6 +10,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from http import HTTPStatus
from oslo_config import cfg from oslo_config import cfg
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from watcher.common import utils from watcher.common import utils
@@ -44,7 +45,7 @@ class TestListScoringEngine(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/scoring_engines/%s' % scoring_engine['name'], '/scoring_engines/%s' % scoring_engine['name'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_detail(self): def test_detail(self):
obj_utils.create_test_goal(self.context) obj_utils.create_test_goal(self.context)
@@ -63,7 +64,7 @@ class TestListScoringEngine(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/scoring_engines/%s/detail' % scoring_engine.id, '/scoring_engines/%s/detail' % scoring_engine.id,
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_many(self): def test_many(self):
scoring_engine_list = [] scoring_engine_list = []
@@ -131,7 +132,7 @@ class TestListScoringEngine(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/goals?sort_key=%s' % 'bad_name', '/goals?sort_key=%s' % 'bad_name',
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
class TestScoringEnginePolicyEnforcement(api_base.FunctionalTest): class TestScoringEnginePolicyEnforcement(api_base.FunctionalTest):
@@ -142,7 +143,7 @@ class TestScoringEnginePolicyEnforcement(api_base.FunctionalTest):
"default": "rule:admin_api", "default": "rule:admin_api",
rule: "rule:default"}) rule: "rule:default"})
response = func(*arg, **kwarg) response = func(*arg, **kwarg)
self.assertEqual(403, response.status_int) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue( self.assertTrue(
"Policy doesn't allow %s to be performed." % rule, "Policy doesn't allow %s to be performed." % rule,

View File

@@ -10,6 +10,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from http import HTTPStatus
from oslo_config import cfg from oslo_config import cfg
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from urllib import parse as urlparse from urllib import parse as urlparse
@@ -57,7 +58,7 @@ class TestListService(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/services/%s' % service['id'], '/services/%s' % service['id'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_detail(self): def test_detail(self):
service = obj_utils.create_test_service(self.context) service = obj_utils.create_test_service(self.context)
@@ -74,7 +75,7 @@ class TestListService(api_base.FunctionalTest):
service = obj_utils.create_test_service(self.context) service = obj_utils.create_test_service(self.context)
response = self.get_json('/services/%s/detail' % service.id, response = self.get_json('/services/%s/detail' % service.id,
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_many(self): def test_many(self):
service_list = [] service_list = []
@@ -149,7 +150,7 @@ class TestListService(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/services?sort_key=%s' % 'bad_name', '/services?sort_key=%s' % 'bad_name',
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
class TestServicePolicyEnforcement(api_base.FunctionalTest): class TestServicePolicyEnforcement(api_base.FunctionalTest):
@@ -160,7 +161,7 @@ class TestServicePolicyEnforcement(api_base.FunctionalTest):
"default": "rule:admin_api", "default": "rule:admin_api",
rule: "rule:default"}) rule: "rule:default"})
response = func(*arg, **kwarg) response = func(*arg, **kwarg)
self.assertEqual(403, response.status_int) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue( self.assertTrue(
"Policy doesn't allow %s to be performed." % rule, "Policy doesn't allow %s to be performed." % rule,

View File

@@ -13,6 +13,7 @@
from unittest import mock from unittest import mock
from urllib import parse as urlparse from urllib import parse as urlparse
from http import HTTPStatus
from oslo_config import cfg from oslo_config import cfg
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
@@ -88,7 +89,7 @@ class TestListStrategy(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/strategies/%s' % strategy['uuid'], '/strategies/%s' % strategy['uuid'],
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_detail(self): def test_detail(self):
strategy = obj_utils.create_test_strategy(self.context) strategy = obj_utils.create_test_strategy(self.context)
@@ -104,7 +105,7 @@ class TestListStrategy(api_base.FunctionalTest):
strategy = obj_utils.create_test_strategy(self.context) strategy = obj_utils.create_test_strategy(self.context)
response = self.get_json('/strategies/%s/detail' % strategy.uuid, response = self.get_json('/strategies/%s/detail' % strategy.uuid,
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
def test_many(self): def test_many(self):
strategy_list = [] strategy_list = []
@@ -240,7 +241,7 @@ class TestListStrategy(api_base.FunctionalTest):
response = self.get_json( response = self.get_json(
'/strategies?sort_key=%s' % 'bad_name', '/strategies?sort_key=%s' % 'bad_name',
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
class TestStrategyPolicyEnforcement(api_base.FunctionalTest): class TestStrategyPolicyEnforcement(api_base.FunctionalTest):
@@ -256,7 +257,7 @@ class TestStrategyPolicyEnforcement(api_base.FunctionalTest):
"default": "rule:admin_api", "default": "rule:admin_api",
rule: "rule:defaut"}) rule: "rule:defaut"})
response = func(*arg, **kwarg) response = func(*arg, **kwarg)
self.assertEqual(403, response.status_int) self.assertEqual(HTTPStatus.FORBIDDEN, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue( self.assertTrue(
"Policy doesn't allow %s to be performed." % rule, "Policy doesn't allow %s to be performed." % rule,

View File

@@ -18,6 +18,8 @@ import webtest
import wsme import wsme
from wsme import types as wtypes from wsme import types as wtypes
from http import HTTPStatus
from watcher.api.controllers.v1 import types from watcher.api.controllers.v1 import types
from watcher.common import exception from watcher.common import exception
from watcher.common import utils from watcher.common import utils
@@ -120,68 +122,68 @@ class TestJsonPatchType(base.TestCase):
{'path': '/dict', 'op': 'add', {'path': '/dict', 'op': 'add',
'value': {'cat': 'meow'}}] 'value': {'cat': 'meow'}}]
ret = self._patch_json(valid_patches, False) ret = self._patch_json(valid_patches, False)
self.assertEqual(200, ret.status_int) self.assertEqual(HTTPStatus.OK, ret.status_int)
self.assertEqual(valid_patches, ret.json) self.assertEqual(valid_patches, ret.json)
def test_cannot_update_internal_attr(self): def test_cannot_update_internal_attr(self):
patch = [{'path': '/internal', 'op': 'replace', 'value': 'foo'}] patch = [{'path': '/internal', 'op': 'replace', 'value': 'foo'}]
ret = self._patch_json(patch, True) ret = self._patch_json(patch, True)
self.assertEqual(400, ret.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, ret.status_int)
self.assertTrue(ret.json['faultstring']) self.assertTrue(ret.json['faultstring'])
def test_cannot_update_internal_dict_attr(self): def test_cannot_update_internal_dict_attr(self):
patch = [{'path': '/internal', 'op': 'replace', patch = [{'path': '/internal', 'op': 'replace',
'value': 'foo'}] 'value': 'foo'}]
ret = self._patch_json(patch, True) ret = self._patch_json(patch, True)
self.assertEqual(400, ret.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, ret.status_int)
self.assertTrue(ret.json['faultstring']) self.assertTrue(ret.json['faultstring'])
def test_mandatory_attr(self): def test_mandatory_attr(self):
patch = [{'op': 'replace', 'path': '/mandatory', 'value': 'foo'}] patch = [{'op': 'replace', 'path': '/mandatory', 'value': 'foo'}]
ret = self._patch_json(patch, False) ret = self._patch_json(patch, False)
self.assertEqual(200, ret.status_int) self.assertEqual(HTTPStatus.OK, ret.status_int)
self.assertEqual(patch, ret.json) self.assertEqual(patch, ret.json)
def test_cannot_remove_mandatory_attr(self): def test_cannot_remove_mandatory_attr(self):
patch = [{'op': 'remove', 'path': '/mandatory'}] patch = [{'op': 'remove', 'path': '/mandatory'}]
ret = self._patch_json(patch, True) ret = self._patch_json(patch, True)
self.assertEqual(400, ret.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, ret.status_int)
self.assertTrue(ret.json['faultstring']) self.assertTrue(ret.json['faultstring'])
def test_missing_required_fields_path(self): def test_missing_required_fields_path(self):
missing_path = [{'op': 'remove'}] missing_path = [{'op': 'remove'}]
ret = self._patch_json(missing_path, True) ret = self._patch_json(missing_path, True)
self.assertEqual(400, ret.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, ret.status_int)
self.assertTrue(ret.json['faultstring']) self.assertTrue(ret.json['faultstring'])
def test_missing_required_fields_op(self): def test_missing_required_fields_op(self):
missing_op = [{'path': '/foo'}] missing_op = [{'path': '/foo'}]
ret = self._patch_json(missing_op, True) ret = self._patch_json(missing_op, True)
self.assertEqual(400, ret.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, ret.status_int)
self.assertTrue(ret.json['faultstring']) self.assertTrue(ret.json['faultstring'])
def test_invalid_op(self): def test_invalid_op(self):
patch = [{'path': '/foo', 'op': 'invalid'}] patch = [{'path': '/foo', 'op': 'invalid'}]
ret = self._patch_json(patch, True) ret = self._patch_json(patch, True)
self.assertEqual(400, ret.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, ret.status_int)
self.assertTrue(ret.json['faultstring']) self.assertTrue(ret.json['faultstring'])
def test_invalid_path(self): def test_invalid_path(self):
patch = [{'path': 'invalid-path', 'op': 'remove'}] patch = [{'path': 'invalid-path', 'op': 'remove'}]
ret = self._patch_json(patch, True) ret = self._patch_json(patch, True)
self.assertEqual(400, ret.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, ret.status_int)
self.assertTrue(ret.json['faultstring']) self.assertTrue(ret.json['faultstring'])
def test_cannot_add_with_no_value(self): def test_cannot_add_with_no_value(self):
patch = [{'path': '/extra/foo', 'op': 'add'}] patch = [{'path': '/extra/foo', 'op': 'add'}]
ret = self._patch_json(patch, True) ret = self._patch_json(patch, True)
self.assertEqual(400, ret.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, ret.status_int)
self.assertTrue(ret.json['faultstring']) self.assertTrue(ret.json['faultstring'])
def test_cannot_replace_with_no_value(self): def test_cannot_replace_with_no_value(self):
patch = [{'path': '/foo', 'op': 'replace'}] patch = [{'path': '/foo', 'op': 'replace'}]
ret = self._patch_json(patch, True) ret = self._patch_json(patch, True)
self.assertEqual(400, ret.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, ret.status_int)
self.assertTrue(ret.json['faultstring']) self.assertTrue(ret.json['faultstring'])

View File

@@ -12,6 +12,8 @@
from unittest import mock from unittest import mock
from http import HTTPStatus
from watcher.decision_engine import rpcapi as deapi from watcher.decision_engine import rpcapi as deapi
from watcher import objects from watcher import objects
from watcher.tests.api import base as api_base from watcher.tests.api import base as api_base
@@ -34,7 +36,7 @@ class TestPost(api_base.FunctionalTest):
response = self.post_json( response = self.post_json(
'/webhooks/%s' % audit['uuid'], {}, '/webhooks/%s' % audit['uuid'], {},
headers={'OpenStack-API-Version': 'infra-optim 1.4'}) headers={'OpenStack-API-Version': 'infra-optim 1.4'})
self.assertEqual(202, response.status_int) self.assertEqual(HTTPStatus.ACCEPTED, response.status_int)
mock_trigger_audit.assert_called_once_with( mock_trigger_audit.assert_called_once_with(
mock.ANY, audit['uuid']) mock.ANY, audit['uuid'])
@@ -43,7 +45,7 @@ class TestPost(api_base.FunctionalTest):
'/webhooks/no-audit', {}, '/webhooks/no-audit', {},
headers={'OpenStack-API-Version': 'infra-optim 1.4'}, headers={'OpenStack-API-Version': 'infra-optim 1.4'},
expect_errors=True) expect_errors=True)
self.assertEqual(404, response.status_int) self.assertEqual(HTTPStatus.NOT_FOUND, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -53,7 +55,7 @@ class TestPost(api_base.FunctionalTest):
'/webhooks/%s' % audit['uuid'], {}, '/webhooks/%s' % audit['uuid'], {},
headers={'OpenStack-API-Version': 'infra-optim 1.4'}, headers={'OpenStack-API-Version': 'infra-optim 1.4'},
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
@@ -66,6 +68,6 @@ class TestPost(api_base.FunctionalTest):
'/webhooks/%s' % audit['uuid'], {}, '/webhooks/%s' % audit['uuid'], {},
headers={'OpenStack-API-Version': 'infra-optim 1.4'}, headers={'OpenStack-API-Version': 'infra-optim 1.4'},
expect_errors=True) expect_errors=True)
self.assertEqual(400, response.status_int) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])

View File

@@ -13,9 +13,11 @@
# limitations under the License. # limitations under the License.
# #
import time
from unittest import mock from unittest import mock
from http import HTTPStatus
import time
from cinderclient import exceptions as cinder_exception from cinderclient import exceptions as cinder_exception
from watcher.common import cinder_helper from watcher.common import cinder_helper
@@ -291,7 +293,8 @@ class TestCinderHelper(base.TestCase):
volume = self.fake_volume() volume = self.fake_volume()
cinder_util.get_volume = mock.MagicMock() cinder_util.get_volume = mock.MagicMock()
cinder_util.get_volume.side_effect = cinder_exception.NotFound(404) cinder_util.get_volume.side_effect =\
cinder_exception.NotFound(HTTPStatus.NOT_FOUND)
result = cinder_util._can_get_volume(volume.id) result = cinder_util._can_get_volume(volume.id)
self.assertFalse(result) self.assertFalse(result)
@@ -339,7 +342,7 @@ class TestCinderHelper(base.TestCase):
cinder_util = cinder_helper.CinderHelper() cinder_util = cinder_helper.CinderHelper()
volume = self.fake_volume() volume = self.fake_volume()
side_effect = cinder_exception.NotFound(404) side_effect = cinder_exception.NotFound(HTTPStatus.NOT_FOUND)
cinder_util.cinder.volumes.get.side_effect = side_effect cinder_util.cinder.volumes.get.side_effect = side_effect
cinder_util.cinder.volumes.find.return_value = False cinder_util.cinder.volumes.find.return_value = False
result = cinder_util.get_volume(volume) result = cinder_util.get_volume(volume)

View File

@@ -10,8 +10,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from ceilometerclient import client as ceclient
import ceilometerclient.v2.client as ceclient_v2
from unittest import mock from unittest import mock
from cinderclient import client as ciclient from cinderclient import client as ciclient
@@ -270,56 +268,6 @@ class TestClients(base.TestCase):
cinder_cached = osc.cinder() cinder_cached = osc.cinder()
self.assertEqual(cinder, cinder_cached) self.assertEqual(cinder, cinder_cached)
@mock.patch.object(ceclient, 'Client')
@mock.patch.object(clients.OpenStackClients, 'session')
def test_clients_ceilometer(self, mock_session, mock_call):
osc = clients.OpenStackClients()
osc._ceilometer = None
osc.ceilometer()
mock_call.assert_called_once_with(
CONF.ceilometer_client.api_version,
None,
endpoint_type=CONF.ceilometer_client.endpoint_type,
region_name=CONF.ceilometer_client.region_name,
session=mock_session)
@mock.patch.object(clients.OpenStackClients, 'session')
@mock.patch.object(ceclient_v2.Client, '_get_redirect_client')
def test_clients_ceilometer_diff_vers(self, mock_get_redirect_client,
mock_session):
'''ceilometerclient currently only has one version (v2)'''
mock_get_redirect_client.return_value = [mock.Mock(), mock.Mock()]
CONF.set_override('api_version', '2',
group='ceilometer_client')
osc = clients.OpenStackClients()
osc._ceilometer = None
osc.ceilometer()
self.assertEqual(ceclient_v2.Client,
type(osc.ceilometer()))
@mock.patch.object(clients.OpenStackClients, 'session')
@mock.patch.object(ceclient_v2.Client, '_get_redirect_client')
def test_clients_ceilometer_diff_endpoint(self, mock_get_redirect_client,
mock_session):
mock_get_redirect_client.return_value = [mock.Mock(), mock.Mock()]
CONF.set_override('endpoint_type', 'publicURL',
group='ceilometer_client')
osc = clients.OpenStackClients()
osc._ceilometer = None
osc.ceilometer()
self.assertEqual('publicURL', osc.ceilometer().http_client.interface)
@mock.patch.object(clients.OpenStackClients, 'session')
@mock.patch.object(ceclient_v2.Client, '_get_redirect_client')
def test_clients_ceilometer_cached(self, mock_get_redirect_client,
mock_session):
mock_get_redirect_client.return_value = [mock.Mock(), mock.Mock()]
osc = clients.OpenStackClients()
osc._ceilometer = None
ceilometer = osc.ceilometer()
ceilometer_cached = osc.ceilometer()
self.assertEqual(ceilometer, ceilometer_cached)
@mock.patch.object(netclient, 'Client') @mock.patch.object(netclient, 'Client')
@mock.patch.object(clients.OpenStackClients, 'session') @mock.patch.object(clients.OpenStackClients, 'session')
def test_clients_neutron(self, mock_session, mock_call): def test_clients_neutron(self, mock_session, mock_call):

View File

@@ -11,6 +11,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from http import HTTPStatus
from unittest import mock from unittest import mock
from watcher.common import placement_helper from watcher.common import placement_helper
@@ -55,10 +56,10 @@ class TestPlacementHelper(base.TestCase):
kss_req.assert_called_once_with(url, method, **kwargs) kss_req.assert_called_once_with(url, method, **kwargs)
def test_get(self, kss_req): def test_get(self, kss_req):
kss_req.return_value = fake_requests.FakeResponse(200) kss_req.return_value = fake_requests.FakeResponse(HTTPStatus.OK)
url = '/resource_providers' url = '/resource_providers'
resp = self.client.get(url) resp = self.client.get(url)
self.assertEqual(200, resp.status_code) self.assertEqual(HTTPStatus.OK, resp.status_code)
self._assert_keystone_called_once(kss_req, url, 'GET') self._assert_keystone_called_once(kss_req, url, 'GET')
def test_get_resource_providers_OK(self, kss_req): def test_get_resource_providers_OK(self, kss_req):
@@ -76,7 +77,7 @@ class TestPlacementHelper(base.TestCase):
} }
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
200, content=jsonutils.dump_as_bytes(mock_json_data)) HTTPStatus.OK, content=jsonutils.dump_as_bytes(mock_json_data))
result = self.client.get_resource_providers(rp_name) result = self.client.get_resource_providers(rp_name)
@@ -99,7 +100,7 @@ class TestPlacementHelper(base.TestCase):
} }
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
200, content=jsonutils.dump_as_bytes(mock_json_data)) HTTPStatus.OK, content=jsonutils.dump_as_bytes(mock_json_data))
result = self.client.get_resource_providers(rp_name) result = self.client.get_resource_providers(rp_name)
@@ -110,7 +111,8 @@ class TestPlacementHelper(base.TestCase):
def test_get_resource_providers_fail(self, kss_req): def test_get_resource_providers_fail(self, kss_req):
rp_name = 'compute' rp_name = 'compute'
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
400, content=jsonutils.dump_as_bytes(self.fake_err_msg)) HTTPStatus.BAD_REQUEST,
content=jsonutils.dump_as_bytes(self.fake_err_msg))
result = self.client.get_resource_providers(rp_name) result = self.client.get_resource_providers(rp_name)
self.assertIsNone(result) self.assertIsNone(result)
@@ -149,7 +151,7 @@ class TestPlacementHelper(base.TestCase):
} }
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
200, content=jsonutils.dump_as_bytes(mock_json_data)) HTTPStatus.OK, content=jsonutils.dump_as_bytes(mock_json_data))
result = self.client.get_inventories(rp_uuid) result = self.client.get_inventories(rp_uuid)
@@ -160,7 +162,8 @@ class TestPlacementHelper(base.TestCase):
def test_get_inventories_fail(self, kss_req): def test_get_inventories_fail(self, kss_req):
rp_uuid = uuidutils.generate_uuid() rp_uuid = uuidutils.generate_uuid()
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
404, content=jsonutils.dump_as_bytes(self.fake_err_msg)) HTTPStatus.NOT_FOUND,
content=jsonutils.dump_as_bytes(self.fake_err_msg))
result = self.client.get_inventories(rp_uuid) result = self.client.get_inventories(rp_uuid)
self.assertIsNone(result) self.assertIsNone(result)
@@ -175,7 +178,7 @@ class TestPlacementHelper(base.TestCase):
} }
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
200, content=jsonutils.dump_as_bytes(mock_json_data)) HTTPStatus.OK, content=jsonutils.dump_as_bytes(mock_json_data))
result = self.client.get_provider_traits(rp_uuid) result = self.client.get_provider_traits(rp_uuid)
@@ -186,7 +189,8 @@ class TestPlacementHelper(base.TestCase):
def test_get_provider_traits_fail(self, kss_req): def test_get_provider_traits_fail(self, kss_req):
rp_uuid = uuidutils.generate_uuid() rp_uuid = uuidutils.generate_uuid()
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
404, content=jsonutils.dump_as_bytes(self.fake_err_msg)) HTTPStatus.NOT_FOUND,
content=jsonutils.dump_as_bytes(self.fake_err_msg))
result = self.client.get_provider_traits(rp_uuid) result = self.client.get_provider_traits(rp_uuid)
self.assertIsNone(result) self.assertIsNone(result)
@@ -216,7 +220,7 @@ class TestPlacementHelper(base.TestCase):
} }
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
200, content=jsonutils.dump_as_bytes(mock_json_data)) HTTPStatus.OK, content=jsonutils.dump_as_bytes(mock_json_data))
result = self.client.get_allocations_for_consumer(c_uuid) result = self.client.get_allocations_for_consumer(c_uuid)
@@ -227,7 +231,8 @@ class TestPlacementHelper(base.TestCase):
def test_get_allocations_for_consumer_fail(self, kss_req): def test_get_allocations_for_consumer_fail(self, kss_req):
c_uuid = uuidutils.generate_uuid() c_uuid = uuidutils.generate_uuid()
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
404, content=jsonutils.dump_as_bytes(self.fake_err_msg)) HTTPStatus.NOT_FOUND,
content=jsonutils.dump_as_bytes(self.fake_err_msg))
result = self.client.get_allocations_for_consumer(c_uuid) result = self.client.get_allocations_for_consumer(c_uuid)
self.assertIsNone(result) self.assertIsNone(result)
@@ -245,7 +250,7 @@ class TestPlacementHelper(base.TestCase):
} }
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
200, content=jsonutils.dump_as_bytes(mock_json_data)) HTTPStatus.OK, content=jsonutils.dump_as_bytes(mock_json_data))
result = self.client.get_usages_for_resource_provider(rp_uuid) result = self.client.get_usages_for_resource_provider(rp_uuid)
@@ -256,7 +261,8 @@ class TestPlacementHelper(base.TestCase):
def test_get_usages_for_resource_provider_fail(self, kss_req): def test_get_usages_for_resource_provider_fail(self, kss_req):
rp_uuid = uuidutils.generate_uuid() rp_uuid = uuidutils.generate_uuid()
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
404, content=jsonutils.dump_as_bytes(self.fake_err_msg)) HTTPStatus.NOT_FOUND,
content=jsonutils.dump_as_bytes(self.fake_err_msg))
result = self.client.get_usages_for_resource_provider(rp_uuid) result = self.client.get_usages_for_resource_provider(rp_uuid)
self.assertIsNone(result) self.assertIsNone(result)
@@ -296,7 +302,7 @@ class TestPlacementHelper(base.TestCase):
} }
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
200, content=jsonutils.dump_as_bytes(mock_json_data)) HTTPStatus.OK, content=jsonutils.dump_as_bytes(mock_json_data))
result = self.client.get_candidate_providers(resources) result = self.client.get_candidate_providers(resources)
@@ -307,6 +313,7 @@ class TestPlacementHelper(base.TestCase):
def test_get_candidate_providers_fail(self, kss_req): def test_get_candidate_providers_fail(self, kss_req):
rp_uuid = uuidutils.generate_uuid() rp_uuid = uuidutils.generate_uuid()
kss_req.return_value = fake_requests.FakeResponse( kss_req.return_value = fake_requests.FakeResponse(
404, content=jsonutils.dump_as_bytes(self.fake_err_msg)) HTTPStatus.NOT_FOUND,
content=jsonutils.dump_as_bytes(self.fake_err_msg))
result = self.client.get_candidate_providers(rp_uuid) result = self.client.get_candidate_providers(rp_uuid)
self.assertIsNone(result) self.assertIsNone(result)

View File

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

View File

@@ -1,168 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from unittest import mock
from watcher.common import clients
from watcher.common import exception
from watcher.decision_engine.datasources import ceilometer as ceilometer_helper
from watcher.tests import base
@mock.patch.object(clients.OpenStackClients, 'ceilometer')
class TestCeilometerHelper(base.BaseTestCase):
def setUp(self):
super(TestCeilometerHelper, self).setUp()
self.osc_mock = mock.Mock()
self.helper = ceilometer_helper.CeilometerHelper(osc=self.osc_mock)
stat_agg_patcher = mock.patch.object(
self.helper, 'statistic_aggregation',
spec=ceilometer_helper.CeilometerHelper.statistic_aggregation)
self.mock_aggregation = stat_agg_patcher.start()
self.addCleanup(stat_agg_patcher.stop)
def test_build_query(self, mock_ceilometer):
mock_ceilometer.return_value = mock.MagicMock()
cm = ceilometer_helper.CeilometerHelper()
expected = [{'field': 'user_id', 'op': 'eq', 'value': u'user_id'},
{'field': 'project_id', 'op': 'eq', 'value': u'tenant_id'},
{'field': 'resource_id', 'op': 'eq',
'value': u'resource_id'}]
query = cm.build_query(user_id="user_id",
tenant_id="tenant_id",
resource_id="resource_id",
user_ids=["user_ids"],
tenant_ids=["tenant_ids"],
resource_ids=["resource_ids"])
self.assertEqual(expected, query)
def test_statistic_aggregation(self, mock_ceilometer):
ceilometer = mock.MagicMock()
statistic = mock.MagicMock()
expected_result = 100
statistic[-1]._info = {'aggregate': {'avg': expected_result}}
ceilometer.statistics.list.return_value = statistic
mock_ceilometer.return_value = ceilometer
cm = ceilometer_helper.CeilometerHelper()
val = cm.statistic_aggregation(
resource=mock.Mock(id="INSTANCE_ID"),
resource_type='instance',
meter_name="instance_cpu_usage",
period="7300",
granularity=None
)
self.assertEqual(expected_result, val)
def test_statistic_aggregation_metric_unavailable(self, mock_ceilometer):
helper = ceilometer_helper.CeilometerHelper()
# invalidate instance_cpu_usage in metric map
original_metric_value = helper.METRIC_MAP.get('instance_cpu_usage')
helper.METRIC_MAP.update(
instance_cpu_usage=None
)
self.assertRaises(
exception.MetricNotAvailable,
helper.statistic_aggregation, resource=mock.Mock(id="INSTANCE_ID"),
resource_type='instance', meter_name="instance_cpu_usage",
period="7300",
granularity=None
)
# restore the metric map as it is a static attribute that does not get
# restored between unit tests!
helper.METRIC_MAP.update(
instance_cpu_usage=original_metric_value
)
def test_get_host_cpu_usage(self, mock_ceilometer):
self.helper.get_host_cpu_usage('compute1', 600, 'mean')
self.mock_aggregation.assert_called_once_with(
'compute1', 'compute_node', 'host_cpu_usage', 600, 'mean', None)
def test_get_host_ram_usage(self, mock_ceilometer):
self.helper.get_host_ram_usage('compute1', 600, 'mean')
self.mock_aggregation.assert_called_once_with(
'compute1', 'compute_node', 'host_ram_usage', 600, 'mean', None)
def test_get_host_outlet_temp(self, mock_ceilometer):
self.helper.get_host_outlet_temp('compute1', 600, 'mean')
self.mock_aggregation.assert_called_once_with(
'compute1', 'compute_node', 'host_outlet_temp', 600, 'mean', None)
def test_get_host_inlet_temp(self, mock_ceilometer):
self.helper.get_host_inlet_temp('compute1', 600, 'mean')
self.mock_aggregation.assert_called_once_with(
'compute1', 'compute_node', 'host_inlet_temp', 600, 'mean', None)
def test_get_host_airflow(self, mock_ceilometer):
self.helper.get_host_airflow('compute1', 600, 'mean')
self.mock_aggregation.assert_called_once_with(
'compute1', 'compute_node', 'host_airflow', 600, 'mean', None)
def test_get_host_power(self, mock_ceilometer):
self.helper.get_host_power('compute1', 600, 'mean')
self.mock_aggregation.assert_called_once_with(
'compute1', 'compute_node', 'host_power', 600, 'mean', None)
def test_get_instance_cpu_usage(self, mock_ceilometer):
self.helper.get_instance_cpu_usage('compute1', 600, 'mean')
self.mock_aggregation.assert_called_once_with(
'compute1', 'instance', 'instance_cpu_usage', 600, 'mean',
None)
def test_get_instance_ram_usage(self, mock_ceilometer):
self.helper.get_instance_ram_usage('compute1', 600, 'mean')
self.mock_aggregation.assert_called_once_with(
'compute1', 'instance', 'instance_ram_usage', 600, 'mean',
None)
def test_get_instance_ram_allocated(self, mock_ceilometer):
self.helper.get_instance_ram_allocated('compute1', 600, 'mean')
self.mock_aggregation.assert_called_once_with(
'compute1', 'instance', 'instance_ram_allocated', 600, 'mean',
None)
def test_get_instance_l3_cache_usage(self, mock_ceilometer):
self.helper.get_instance_l3_cache_usage('compute1', 600, 'mean')
self.mock_aggregation.assert_called_once_with(
'compute1', 'instance', 'instance_l3_cache_usage', 600, 'mean',
None)
def test_get_instance_root_disk_size(self, mock_ceilometer):
self.helper.get_instance_root_disk_size('compute1', 600, 'mean')
self.mock_aggregation.assert_called_once_with(
'compute1', 'instance', 'instance_root_disk_size', 600, 'mean',
None)
def test_check_availability(self, mock_ceilometer):
ceilometer = mock.MagicMock()
ceilometer.resources.list.return_value = True
mock_ceilometer.return_value = ceilometer
helper = ceilometer_helper.CeilometerHelper()
result = helper.check_availability()
self.assertEqual('available', result)
def test_check_availability_with_failure(self, mock_ceilometer):
ceilometer = mock.MagicMock()
ceilometer.resources.list.side_effect = Exception()
mock_ceilometer.return_value = ceilometer
helper = ceilometer_helper.CeilometerHelper()
self.assertEqual('not available', helper.check_availability())

View File

@@ -26,6 +26,7 @@ from watcher.common import exception
from watcher.decision_engine.datasources import grafana from watcher.decision_engine.datasources import grafana
from watcher.tests import base from watcher.tests import base
from http import HTTPStatus
import requests import requests
CONF = cfg.CONF CONF = cfg.CONF
@@ -128,7 +129,7 @@ class TestGrafana(base.BaseTestCase):
problems. problems.
""" """
m_request.return_value = mock.Mock(status_code=404) m_request.return_value = mock.Mock(status_code=HTTPStatus.NOT_FOUND)
t_grafana = grafana.GrafanaHelper(osc=mock.Mock()) t_grafana = grafana.GrafanaHelper(osc=mock.Mock())

View File

@@ -144,7 +144,7 @@ class TestZoneMigration(TestBaseStrategy):
@staticmethod @staticmethod
def fake_volume(**kwargs): def fake_volume(**kwargs):
volume = mock.MagicMock(spec=cinderclient.v2.volumes.Volume) volume = mock.MagicMock(spec=cinderclient.v3.volumes.Volume)
volume.id = kwargs.get('id', utils.generate_uuid()) volume.id = kwargs.get('id', utils.generate_uuid())
volume.name = kwargs.get('name', 'fake_name') volume.name = kwargs.get('name', 'fake_name')
volume.status = kwargs.get('status', 'available') volume.status = kwargs.get('status', 'available')