Compare commits

..

9 Commits

Author SHA1 Message Date
Luigi Toscano
2e033d7b96 Native Zuul v3 watcher-grenade job + some cleanup
Create a native Zuul v3 grenade job. It matches the existing job,
even though it doesn't call any local hook as the current legacy
job does (because no local hook exists and it should be rewritten
as zuul configuration if it did).

The new job reuses the variable definition of the devstack watcher
job, so clean up that job as well:
- do not depend on devstack-gate, which is not needed and will be
  deprecated soon anyway;
- use the new way (tempest_plugins) to define which tempest plugin
  should be installed;
- remove the definition of USE_PYTHON3: true and simply inherit
  the value set by devstack;
- remove the definition of PYTHONUNBUFFERED, not really set
  anywhere else and only useful back in the days in Jenkins.

Change-Id: Ib0ed3c0f395e1b85b8f25f6e438c414165baab32
(cherry picked from commit ed59145354)
2020-08-06 10:32:17 +02:00
limin0801
0543ccfe74 Watcher API supports strategy name when creating audit template
when directly using the `curl` command to create audit template,
strategy name can be accepted.

Closes-Bug: #1884174

Change-Id: I7c0ca760a7fa414faca03c5293df34a84aad6fac
(cherry picked from commit 3f7a508a2e)
2020-07-10 01:15:40 +00:00
Zuul
ec62bbe5bd Merge "Compatible with old scope format" into stable/ussuri 2020-06-19 07:53:38 +00:00
licanwei
cbb06e6765 Check if scope is None
if scope is None, don't create data model

Change-Id: Icf611966c9b0a3882615d778ee6c72a8da73841d
Closed-Bug: #1881920
(cherry picked from commit 9f0138e1cf)
2020-06-19 01:46:15 +00:00
licanwei
6e1be3cca4 Compatible with old scope format
Scope format changed from old to new after bp cdm-scoping.

old format:
  - availability_zones:
    - name: nova
  - host_aggregates:
    - id: 1
    - name: agg
  - exclude:
    - compute_nodes:
      - name: w012

new format:
- compute:
  - availability_zones:
    - name: nova
  - host_aggregates:
    - id: 1
    - name: agg
  - exclude:
    - compute_nodes:
      - name: w012

Change-Id: I2b5cd4d1cee19f5588e4d2185eb074343fff1187
Closed-Bug: #1882049
(cherry picked from commit 4a1915bec4)
2020-06-11 02:15:25 +00:00
Chris MacNaughton
043ebb71c6 Monkey patch original current_thread _active
Monkey patch the original current_thread to use the up-to-date _active
global variable. This solution is based on that documented at:
https://github.com/eventlet/eventlet/issues/592

Change-Id: I194eedd505d45137963eb40d1b1d5da2309caeac
Closes-Bug: #1863021
(cherry picked from commit 0b4c4f1de6)
2020-05-15 09:25:40 +00:00
OpenStack Proposal Bot
870e6d75e0 Imported Translations from Zanata
For more information about this automatic import see:
https://docs.openstack.org/i18n/latest/reviewing-translation-import.html

Change-Id: Ie708859051162cc7a68cfdf289398f6df1abe6c8
2020-04-26 09:05:18 +00:00
OpenStack Release Bot
3069f83731 Update TOX_CONSTRAINTS_FILE for stable/ussuri
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/ussuri branch, tests will
continue to use the upper-constraints list on master.

Change-Id: I80ec47827b91977dde874246fb94dbbeeeb7ef14
2020-04-23 09:48:50 +00:00
OpenStack Release Bot
d7d534f5d1 Update .gitreview for stable/ussuri
Change-Id: I72fffb815f040dd4f1b13a73455276f70bd10aaf
2020-04-23 09:48:48 +00:00
206 changed files with 682 additions and 1828 deletions

View File

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

View File

@@ -2,7 +2,8 @@
templates:
- check-requirements
- openstack-cover-jobs
- openstack-python3-wallaby-jobs
- openstack-lower-constraints-jobs
- openstack-python3-ussuri-jobs
- publish-openstack-docs-pti
- release-notes-jobs-python3
check:
@@ -101,7 +102,7 @@
- job:
name: watcher-tempest-multinode
parent: watcher-tempest-functional
nodeset: openstack-two-node-focal
nodeset: openstack-two-node-bionic
roles:
- zuul: openstack/tempest
group-vars:

View File

@@ -22,6 +22,9 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
from watcher import version as watcher_version
extensions = [
'openstackdocstheme',
'os_api_ref',
@@ -43,13 +46,21 @@ project = u'Infrastructure Optimization API Reference'
copyright = u'2010-present, OpenStack Foundation'
# openstackdocstheme options
openstackdocs_repo_name = 'openstack/watcher'
openstackdocs_auto_name = False
openstackdocs_bug_project = 'watcher'
openstackdocs_bug_tag = ''
repository_name = 'openstack/watcher'
bug_project = 'watcher'
bug_tag = ''
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The full version, including alpha/beta/rc tags.
release = watcher_version.version_info.release_string()
# The short X.Y version.
version = watcher_version.version_string
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'native'
pygments_style = 'sphinx'
# -- Options for HTML output --------------------------------------------------
@@ -64,6 +75,10 @@ html_theme_options = {
"sidebar_mode": "toc",
}
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = '%Y-%m-%d %H:%M'
# -- Options for LaTeX output -------------------------------------------------
# Grouping the document tree into LaTeX files. List of tuples

2
babel.cfg Normal file
View File

@@ -0,0 +1,2 @@
[python: **.py]

View File

@@ -298,7 +298,7 @@ function start_watcher_api {
service_protocol="http"
fi
if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
run_process "watcher-api" "$(which uwsgi) --procname-prefix watcher-api --ini $WATCHER_UWSGI_CONF"
run_process "watcher-api" "$WATCHER_BIN_DIR/uwsgi --procname-prefix watcher-api --ini $WATCHER_UWSGI_CONF"
watcher_url=$service_protocol://$SERVICE_HOST/infra-optim
else
watcher_url=$service_protocol://$SERVICE_HOST:$service_port

View File

@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import unicode_literals
import importlib
import inspect

View File

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

View File

@@ -17,14 +17,6 @@
Policies
========
.. warning::
JSON formatted policy file is deprecated since Watcher 6.0.0 (Wallaby).
This `oslopolicy-convert-json-to-yaml`__ tool will migrate your existing
JSON-formatted policy file to YAML in a backward-compatible way.
.. __: https://docs.openstack.org/oslo.policy/latest/cli/oslopolicy-convert-json-to-yaml.html
Watcher's public API calls may be restricted to certain sets of users using a
policy configuration file. This document explains exactly how policies are
configured and what they apply to.

View File

@@ -14,6 +14,7 @@
import os
import sys
from watcher import version as watcher_version
from watcher import objects
objects.register_all()
@@ -59,6 +60,16 @@ master_doc = 'index'
project = u'Watcher'
copyright = u'OpenStack Foundation'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
# The full version, including alpha/beta/rc tags.
release = watcher_version.version_info.release_string()
# The short X.Y version.
version = watcher_version.version_string
# A list of ignored prefixes for module index sorting.
modindex_common_prefix = ['watcher.']
@@ -83,7 +94,7 @@ add_module_names = True
suppress_warnings = ['app.add_directive']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'native'
pygments_style = 'sphinx'
# -- Options for man page output --------------------------------------------
@@ -114,13 +125,12 @@ html_theme = 'openstackdocs'
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
html_last_updated_fmt = '%Y-%m-%d %H:%M'
#openstackdocstheme options
openstackdocs_repo_name = 'openstack/watcher'
openstackdocs_pdf_link = True
openstackdocs_auto_name = False
openstackdocs_bug_project = 'watcher'
openstackdocs_bug_tag = ''
repository_name = 'openstack/watcher'
bug_project = 'watcher'
bug_tag = ''
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
@@ -128,7 +138,7 @@ openstackdocs_bug_tag = ''
latex_documents = [
('index',
'doc-watcher.tex',
u'Watcher Documentation',
u'%s Documentation' % project,
u'OpenStack Foundation', 'manual'),
]

View File

@@ -56,6 +56,9 @@ Here is an example showing how you can write a plugin called ``NewStrategy``:
# filepath: thirdparty/new.py
# import path: thirdparty.new
import abc
import six
from watcher._i18n import _
from watcher.decision_engine.strategy.strategies import base

161
lower-constraints.txt Normal file
View File

@@ -0,0 +1,161 @@
alabaster==0.7.10
alembic==0.9.8
amqp==2.2.2
appdirs==1.4.3
APScheduler==3.5.1
asn1crypto==0.24.0
automaton==1.14.0
Babel==2.5.3
beautifulsoup4==4.6.0
cachetools==2.0.1
certifi==2018.1.18
cffi==1.11.5
chardet==3.0.4
cliff==2.11.0
cmd2==0.8.1
contextlib2==0.5.5
coverage==4.5.1
croniter==0.3.20
cryptography==2.1.4
debtcollector==1.19.0
decorator==4.2.1
deprecation==2.0
doc8==0.8.0
docutils==0.14
dogpile.cache==0.6.5
dulwich==0.19.0
enum34==1.1.6
enum-compat==0.0.2
eventlet==0.20.0
extras==1.0.0
fasteners==0.14.1
fixtures==3.0.0
freezegun==0.3.10
future==0.16.0
futurist==1.8.0
gitdb2==2.0.3
GitPython==2.1.8
gnocchiclient==7.0.1
greenlet==0.4.13
idna==2.6
imagesize==1.0.0
iso8601==0.1.12
Jinja2==2.10
jmespath==0.9.3
jsonpatch==1.21
jsonpointer==2.0
jsonschema==2.6.0
keystoneauth1==3.4.0
keystonemiddleware==4.21.0
kombu==4.1.0
linecache2==1.0.0
logutils==0.3.5
lxml==4.1.1
Mako==1.0.7
MarkupSafe==1.0
mccabe==0.2.1
microversion_parse==0.2.1
mock==2.0.0
monotonic==1.4
mox3==0.25.0
msgpack==0.5.6
munch==2.2.0
netaddr==0.7.19
netifaces==0.10.6
networkx==2.2
openstackdocstheme==1.20.0
openstacksdk==0.12.0
os-api-ref===1.4.0
os-client-config==1.29.0
os-service-types==1.2.0
os-testr==1.0.0
osc-lib==1.10.0
os-resource-classes==0.4.0
oslo.cache==1.29.0
oslo.concurrency==3.26.0
oslo.config==5.2.0
oslo.context==2.21.0
oslo.db==4.35.0
oslo.i18n==3.20.0
oslo.log==3.37.0
oslo.messaging==8.1.2
oslo.middleware==3.35.0
oslo.policy==1.34.0
oslo.reports==1.27.0
oslo.serialization==2.25.0
oslo.service==1.30.0
oslo.upgradecheck==0.1.0
oslo.utils==3.36.0
oslo.versionedobjects==1.32.0
oslotest==3.3.0
packaging==17.1
Paste==2.0.3
PasteDeploy==1.5.2
pbr==3.1.1
pecan==1.3.2
pika==0.10.0
pika-pool==0.1.3
prettytable==0.7.2
psutil==5.4.3
pycadf==2.7.0
pycparser==2.18
Pygments==2.2.0
pyinotify==0.9.6
pyOpenSSL==17.5.0
pyparsing==2.2.0
pyperclip==1.6.0
python-ceilometerclient==2.9.0
python-cinderclient==3.5.0
python-dateutil==2.7.0
python-editor==1.0.3
python-glanceclient==2.9.1
python-ironicclient==2.5.0
python-keystoneclient==3.15.0
python-mimeparse==1.6.0
python-monascaclient==1.12.0
python-neutronclient==6.7.0
python-novaclient==14.1.0
python-openstackclient==3.14.0
python-subunit==1.2.0
pytz==2018.3
PyYAML==3.12
reno==2.7.0
repoze.lru==0.7
requests==2.18.4
requestsexceptions==1.4.0
restructuredtext-lint==1.1.3
rfc3986==1.1.0
Routes==2.4.1
simplegeneric==0.8.1
simplejson==3.13.2
six==1.11.0
smmap2==2.0.3
snowballstemmer==1.2.1
Sphinx==1.6.5
sphinxcontrib-httpdomain==1.6.1
sphinxcontrib-pecanwsme==0.8.0
sphinxcontrib-websupport==1.0.1
SQLAlchemy==1.2.5
sqlalchemy-migrate==0.11.0
sqlparse==0.2.4
statsd==3.2.2
stestr==2.0.0
stevedore==1.28.0
taskflow==3.7.1
Tempita==0.5.2
tenacity==4.9.0
testresources==2.0.1
testscenarios==0.5.0
testtools==2.3.0
traceback2==1.4.0
tzlocal==1.5.1
ujson==1.35
unittest2==1.1.0
urllib3==1.22
vine==1.1.4
waitress==1.1.0
warlock==1.3.0
WebOb==1.8.5
WebTest==2.0.29
wrapt==1.10.11
WSME==0.9.2

View File

@@ -1,20 +0,0 @@
---
upgrade:
- |
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.
deprecations:
- |
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.

View File

@@ -53,6 +53,7 @@ source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
project = u'watcher'
copyright = u'2016, Watcher developers'
# Release notes are version independent
@@ -90,15 +91,11 @@ exclude_patterns = ['_build']
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'native'
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# openstackdocstheme options
openstackdocs_repo_name = 'openstack/watcher'
openstackdocs_bug_project = 'watcher'
openstackdocs_bug_tag = ''
# -- Options for HTML output --------------------------------------------------

View File

@@ -21,8 +21,6 @@ Contents:
:maxdepth: 1
unreleased
victoria
ussuri
train
stein
rocky

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@@ -1,34 +1,34 @@
# The order of packages is significant, because pip processes them in the order
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
apscheduler>=3.5.1 # MIT License
jsonpatch>=1.21 # BSD
keystoneauth1>=3.4.0 # Apache-2.0
jsonschema>=3.2.0 # MIT
jsonschema>=2.6.0 # MIT
keystonemiddleware>=4.21.0 # Apache-2.0
lxml>=4.5.1 # BSD
lxml>=4.1.1 # BSD
croniter>=0.3.20 # MIT License
os-resource-classes>=0.4.0
oslo.concurrency>=3.26.0 # Apache-2.0
oslo.cache>=1.29.0 # Apache-2.0
oslo.config>=6.8.0 # Apache-2.0
oslo.config>=5.2.0 # Apache-2.0
oslo.context>=2.21.0 # Apache-2.0
oslo.db>=4.44.0 # Apache-2.0
oslo.db>=4.35.0 # Apache-2.0
oslo.i18n>=3.20.0 # Apache-2.0
oslo.log>=3.37.0 # Apache-2.0
oslo.messaging>=8.1.2 # Apache-2.0
oslo.policy>=3.6.0 # Apache-2.0
oslo.policy>=1.34.0 # Apache-2.0
oslo.reports>=1.27.0 # Apache-2.0
oslo.serialization>=2.25.0 # Apache-2.0
oslo.service>=1.30.0 # Apache-2.0
oslo.upgradecheck>=1.3.0 # Apache-2.0
oslo.upgradecheck>=0.1.0 # Apache-2.0
oslo.utils>=3.36.0 # Apache-2.0
oslo.versionedobjects>=1.32.0 # Apache-2.0
PasteDeploy>=1.5.2 # MIT
pbr>=3.1.1 # Apache-2.0
pecan>=1.3.2 # BSD
PrettyTable>=0.7.2 # BSD
PrettyTable<0.8,>=0.7.2 # BSD
gnocchiclient>=7.0.1 # Apache-2.0
python-ceilometerclient>=2.9.0 # Apache-2.0
python-cinderclient>=3.5.0 # Apache-2.0
@@ -39,11 +39,12 @@ python-neutronclient>=6.7.0 # Apache-2.0
python-novaclient>=14.1.0 # Apache-2.0
python-openstackclient>=3.14.0 # Apache-2.0
python-ironicclient>=2.5.0 # Apache-2.0
six>=1.11.0 # MIT
SQLAlchemy>=1.2.5 # MIT
stevedore>=1.28.0 # Apache-2.0
taskflow>=3.8.0 # Apache-2.0
taskflow>=3.7.1 # Apache-2.0
WebOb>=1.8.5 # MIT
WSME>=0.9.2 # MIT
networkx>=2.4 # BSD
networkx>=2.2;python_version>='3.4' # BSD
microversion_parse>=0.2.1 # Apache-2.0
futurist>=1.8.0 # Apache-2.0

View File

@@ -19,7 +19,6 @@ classifier =
Programming Language :: Python :: 3
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
[files]
packages =
@@ -108,3 +107,18 @@ watcher_cluster_data_model_collectors =
compute = watcher.decision_engine.model.collector.nova:NovaClusterDataModelCollector
storage = watcher.decision_engine.model.collector.cinder:CinderClusterDataModelCollector
baremetal = watcher.decision_engine.model.collector.ironic:BaremetalClusterDataModelCollector
[compile_catalog]
directory = watcher/locale
domain = watcher
[update_catalog]
domain = watcher
output_dir = watcher/locale
input_file = watcher/locale/watcher.pot
[extract_messages]
keywords = _ gettext ngettext l_ lazy_gettext _LI _LW _LE _LC
mapping_file = babel.cfg
output_file = watcher/locale/watcher.pot

View File

@@ -5,7 +5,8 @@
coverage>=4.5.1 # Apache-2.0
doc8>=0.8.0 # Apache-2.0
freezegun>=0.3.10 # Apache-2.0
hacking>=3.0.1,<3.1.0 # Apache-2.0
hacking>=3.0,<3.1.0 # Apache-2.0
mock>=2.0.0 # BSD
oslotest>=3.3.0 # Apache-2.0
os-testr>=1.0.0 # Apache-2.0
testscenarios>=0.5.0 # Apache-2.0/BSD

13
tox.ini
View File

@@ -1,6 +1,6 @@
[tox]
minversion = 2.0
envlist = py38,pep8
envlist = py36,py37,pep8
skipsdist = True
ignore_basepython_conflict = True
@@ -13,7 +13,7 @@ install_command = pip install {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}
deps =
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/ussuri}
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt
commands =
@@ -31,7 +31,7 @@ commands =
[testenv:venv]
setenv = PYTHONHASHSEED=0
deps =
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/ussuri}
-r{toxinidir}/doc/requirements.txt
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt
@@ -105,7 +105,6 @@ extension =
N340 = checks:check_oslo_i18n_wrapper
N341 = checks:check_builtins_gettext
N342 = checks:no_redundant_import_alias
N366 = checks:import_stock_mock
paths = ./watcher/hacking
@@ -132,3 +131,9 @@ commands = sphinx-build -a -W -E -d releasenotes/build/doctrees --keep-going -b
[testenv:bandit]
deps = -r{toxinidir}/test-requirements.txt
commands = bandit -r watcher -x watcher/tests/* -n5 -ll -s B320
[testenv:lower-constraints]
deps =
-c{toxinidir}/lower-constraints.txt
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt

View File

@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import unicode_literals
from oslo_config import cfg
from watcher.api import hooks

View File

@@ -19,6 +19,8 @@ Service mechanism provides ability to monitor Watcher services state.
"""
import datetime
import six
from oslo_config import cfg
from oslo_log import log
from oslo_utils import timeutils
@@ -68,7 +70,7 @@ class Service(base.APIBase):
service = objects.Service.get(pecan.request.context, id)
last_heartbeat = (service.last_seen_up or service.updated_at or
service.created_at)
if isinstance(last_heartbeat, str):
if isinstance(last_heartbeat, six.string_types):
# NOTE(russellb) If this service came in over rpc via
# conductor, then the timestamp will be a string and needs to be
# converted back to a datetime.

View File

@@ -15,6 +15,7 @@
from oslo_serialization import jsonutils
from oslo_utils import strutils
import six
import wsme
from wsme import types as wtypes
@@ -131,7 +132,7 @@ class JsonType(wtypes.UserType):
def __str__(self):
# These are the json serializable native types
return ' | '.join(map(str, (wtypes.text, int, float,
return ' | '.join(map(str, (wtypes.text, six.integer_types, float,
BooleanType, list, dict, None)))
@staticmethod

View File

@@ -15,9 +15,9 @@
# under the License.
from http import client as http_client
from oslo_config import cfg
from pecan import hooks
from six.moves import http_client
from watcher.common import context

View File

@@ -24,6 +24,7 @@ from xml import etree as et
from oslo_log import log
from oslo_serialization import jsonutils
import six
import webob
from watcher._i18n import _
@@ -83,10 +84,12 @@ class ParsableErrorMiddleware(object):
'</error_message>' % state['status_code']]
state['headers'].append(('Content-Type', 'application/xml'))
else:
app_iter = [i.decode('utf-8') for i in app_iter]
if six.PY3:
app_iter = [i.decode('utf-8') for i in app_iter]
body = [jsonutils.dumps(
{'error_message': '\n'.join(app_iter)})]
body = [item.encode('utf-8') for item in body]
if six.PY3:
body = [item.encode('utf-8') for item in body]
state['headers'].append(('Content-Type', 'application/json'))
state['headers'].append(('Content-Length', str(len(body[0]))))
else:

View File

@@ -20,6 +20,7 @@ import itertools
from oslo_config import cfg
from oslo_log import log
from oslo_utils import timeutils
import six
from watcher.common import context as watcher_context
from watcher.common import scheduling
@@ -82,7 +83,7 @@ class APISchedulingService(scheduling.BackgroundSchedulerService):
service = objects.Service.get(context, service_id)
last_heartbeat = (service.last_seen_up or service.updated_at or
service.created_at)
if isinstance(last_heartbeat, str):
if isinstance(last_heartbeat, six.string_types):
# NOTE(russellb) If this service came in over rpc via
# conductor, then the timestamp will be a string and needs to be
# converted back to a datetime.

View File

@@ -18,9 +18,11 @@
#
import abc
import six
class BaseActionPlanHandler(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseActionPlanHandler(object):
@abc.abstractmethod
def execute(self):
raise NotImplementedError()

View File

@@ -19,12 +19,14 @@
import abc
import jsonschema
import six
from watcher.common import clients
from watcher.common.loader import loadable
class BaseAction(loadable.Loadable, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseAction(loadable.Loadable):
# NOTE(jed): by convention we decided
# that the attribute "resource_id" is the unique id of
# the resource to which the Action applies to allow us to use it in the

View File

@@ -15,6 +15,8 @@
# limitations under the License.
#
from __future__ import unicode_literals
from oslo_log import log
from watcher.applier.loading import default

View File

@@ -186,7 +186,7 @@ class Migrate(base.BaseAction):
return self.migrate(destination=self.destination_node)
def revert(self):
return self.migrate(destination=self.source_node)
LOG.info('Migrate action do not revert!')
def abort(self):
nova = nova_helper.NovaHelper(osc=self.osc)

View File

@@ -95,7 +95,7 @@ class Resize(base.BaseAction):
return self.resize()
def revert(self):
LOG.warning("revert not supported")
return self.migrate(destination=self.source_node)
def pre_condition(self):
# TODO(jed): check if the instance exists / check if the instance is on

View File

@@ -26,9 +26,11 @@ See: :doc:`../architecture` for more details on this component.
"""
import abc
import six
class BaseApplier(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseApplier(object):
@abc.abstractmethod
def execute(self, action_plan_uuid):
raise NotImplementedError()

View File

@@ -11,6 +11,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import unicode_literals
from watcher.common.loader import default

View File

@@ -17,6 +17,7 @@
#
import abc
import six
import time
import eventlet
@@ -39,7 +40,8 @@ CANCEL_STATE = [objects.action_plan.State.CANCELLING,
objects.action_plan.State.CANCELLED]
class BaseWorkFlowEngine(loadable.Loadable, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseWorkFlowEngine(loadable.Loadable):
def __init__(self, config, context=None, applier_manager=None):
"""Constructor

View File

@@ -25,11 +25,8 @@ from taskflow import task as flow_task
from watcher.applier.workflow_engine import base
from watcher.common import exception
from watcher import conf
from watcher import objects
CONF = conf.CONF
LOG = log.getLogger(__name__)
@@ -130,11 +127,9 @@ class DefaultWorkFlowEngine(base.BaseWorkFlowEngine):
class TaskFlowActionContainer(base.BaseTaskFlowActionContainer):
def __init__(self, db_action, engine):
self.name = "action_type:{0} uuid:{1}".format(db_action.action_type,
db_action.uuid)
super(TaskFlowActionContainer, self).__init__(self.name,
db_action,
engine)
name = "action_type:{0} uuid:{1}".format(db_action.action_type,
db_action.uuid)
super(TaskFlowActionContainer, self).__init__(name, db_action, engine)
def do_pre_execute(self):
db_action = self.engine.notify(self._db_action,
@@ -163,12 +158,6 @@ class TaskFlowActionContainer(base.BaseTaskFlowActionContainer):
self.action.post_condition()
def do_revert(self, *args, **kwargs):
# NOTE: Not rollback action plan
if not CONF.watcher_applier.rollback_when_actionplan_failed:
LOG.info("Failed actionplan rollback option is turned off, and "
"the following action will be skipped: %s", self.name)
return
LOG.warning("Revert action: %s", self.name)
try:
# TODO(jed): do we need to update the states in case of failure?

View File

@@ -14,7 +14,6 @@
import sys
from oslo_upgradecheck import common_checks
from oslo_upgradecheck import upgradecheck
from watcher._i18n import _
@@ -44,10 +43,6 @@ class Checks(upgradecheck.UpgradeCommands):
_upgrade_checks = (
# Added in Train.
(_('Minimum Nova API Version'), _minimum_nova_api_version),
# Added in Wallaby.
(_("Policy File JSON to YAML Migration"),
(common_checks.check_policy_json, {'conf': CONF})),
)

View File

@@ -13,6 +13,7 @@
from oslo_context import context
from oslo_log import log
from oslo_utils import timeutils
import six
LOG = log.getLogger(__name__)
@@ -68,7 +69,7 @@ class RequestContext(context.RequestContext):
self.project_id = project_id
if not timestamp:
timestamp = timeutils.utcnow()
if isinstance(timestamp, str):
if isinstance(timestamp, six.string_types):
timestamp = timeutils.parse_isotime(timestamp)
self.timestamp = timestamp
self.user_name = user_name

View File

@@ -14,10 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import unicode_literals
import abc
import six
class BaseLoader(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseLoader(object):
@abc.abstractmethod
def list_available(self):

View File

@@ -14,6 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import unicode_literals
from oslo_config import cfg
from oslo_log import log
from stevedore import driver as drivermanager

View File

@@ -16,10 +16,13 @@
import abc
import six
from watcher.common import service
class Loadable(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class Loadable(object):
"""Generic interface for dynamically loading a driver/entry point.
This defines the contract in order to let the loader manager inject
@@ -45,7 +48,8 @@ LoadableSingletonMeta = type(
"LoadableSingletonMeta", (abc.ABCMeta, service.Singleton), {})
class LoadableSingleton(object, metaclass=LoadableSingletonMeta):
@six.add_metaclass(LoadableSingletonMeta)
class LoadableSingleton(object):
"""Generic interface for dynamically loading a driver as a singleton.
This defines the contract in order to let the loader manager inject

View File

@@ -18,7 +18,6 @@
import sys
from oslo_config import cfg
from oslo_policy import opts
from oslo_policy import policy
from watcher.common import exception
@@ -27,12 +26,6 @@ from watcher.common import policies
_ENFORCER = None
CONF = cfg.CONF
# TODO(gmann): Remove setting the default value of config policy_file
# once oslo_policy change the default value to 'policy.yaml'.
# https://github.com/openstack/oslo.policy/blob/a626ad12fe5a3abd49d70e3e5b95589d279ab578/oslo_policy/opts.py#L49
DEFAULT_POLICY_FILE = 'policy.yaml'
opts.set_defaults(CONF, DEFAULT_POLICY_FILE)
# we can get a policy enforcer by this init.
# oslo policy support change policy rule dynamically.

View File

@@ -121,40 +121,22 @@ class RequestContextSerializer(messaging.Serializer):
def get_client(target, version_cap=None, serializer=None):
assert TRANSPORT is not None
serializer = RequestContextSerializer(serializer)
return messaging.RPCClient(
TRANSPORT,
target,
version_cap=version_cap,
serializer=serializer
)
return messaging.RPCClient(TRANSPORT,
target,
version_cap=version_cap,
serializer=serializer)
def get_server(target, endpoints, serializer=None):
assert TRANSPORT is not None
access_policy = dispatcher.DefaultRPCAccessPolicy
serializer = RequestContextSerializer(serializer)
return messaging.get_rpc_server(
TRANSPORT,
target,
endpoints,
executor='eventlet',
serializer=serializer,
access_policy=access_policy
)
def get_notification_listener(targets, endpoints, serializer=None, pool=None):
assert NOTIFICATION_TRANSPORT is not None
serializer = RequestContextSerializer(serializer)
return messaging.get_notification_listener(
NOTIFICATION_TRANSPORT,
targets,
endpoints,
allow_requeue=False,
executor='eventlet',
pool=pool,
serializer=serializer
)
return messaging.get_rpc_server(TRANSPORT,
target,
endpoints,
executor='eventlet',
serializer=serializer,
access_policy=access_policy)
def get_notifier(publisher_id):

View File

@@ -21,12 +21,14 @@ from oslo_concurrency import processutils
from oslo_config import cfg
from oslo_log import _options
from oslo_log import log
import oslo_messaging as messaging
import oslo_messaging as om
from oslo_reports import guru_meditation_report as gmr
from oslo_reports import opts as gmr_opts
from oslo_service import service
from oslo_service import wsgi
from oslo_messaging.rpc import dispatcher
from watcher._i18n import _
from watcher.api import app
from watcher.common import config
@@ -181,6 +183,11 @@ class Service(service.ServiceBase):
]
self.notification_endpoints = self.manager.notification_endpoints
self.serializer = rpc.RequestContextSerializer(
base.WatcherObjectSerializer())
self._transport = None
self._notification_transport = None
self._conductor_client = None
self.conductor_topic_handler = None
@@ -194,17 +201,27 @@ class Service(service.ServiceBase):
self.notification_topics, self.notification_endpoints
)
@property
def transport(self):
if self._transport is None:
self._transport = om.get_rpc_transport(CONF)
return self._transport
@property
def notification_transport(self):
if self._notification_transport is None:
self._notification_transport = om.get_notification_transport(CONF)
return self._notification_transport
@property
def conductor_client(self):
if self._conductor_client is None:
target = messaging.Target(
target = om.Target(
topic=self.conductor_topic,
version=self.API_VERSION,
)
self._conductor_client = rpc.get_client(
target,
serializer=base.WatcherObjectSerializer()
)
self._conductor_client = om.RPCClient(
self.transport, target, serializer=self.serializer)
return self._conductor_client
@conductor_client.setter
@@ -212,18 +229,21 @@ class Service(service.ServiceBase):
self.conductor_client = c
def build_topic_handler(self, topic_name, endpoints=()):
target = messaging.Target(
access_policy = dispatcher.DefaultRPCAccessPolicy
serializer = rpc.RequestContextSerializer(rpc.JsonPayloadSerializer())
target = om.Target(
topic=topic_name,
# For compatibility, we can override it with 'host' opt
server=CONF.host or socket.gethostname(),
version=self.api_version,
)
return rpc.get_server(
target, endpoints,
serializer=rpc.JsonPayloadSerializer()
)
return om.get_rpc_server(
self.transport, target, endpoints,
executor='eventlet', serializer=serializer,
access_policy=access_policy)
def build_notification_handler(self, topic_names, endpoints=()):
serializer = rpc.RequestContextSerializer(rpc.JsonPayloadSerializer())
targets = []
for topic in topic_names:
kwargs = {}
@@ -231,13 +251,11 @@ class Service(service.ServiceBase):
exchange, topic = topic.split('.')
kwargs['exchange'] = exchange
kwargs['topic'] = topic
targets.append(messaging.Target(**kwargs))
return rpc.get_notification_listener(
targets, endpoints,
serializer=rpc.JsonPayloadSerializer(),
pool=CONF.host
)
targets.append(om.Target(**kwargs))
return om.get_notification_listener(
self.notification_transport, targets, endpoints,
executor='eventlet', serializer=serializer,
allow_requeue=False, pool=CONF.host)
def start(self):
LOG.debug("Connecting to '%s'", CONF.transport_url)

View File

@@ -15,9 +15,11 @@
# under the License.
import abc
import six
class ServiceManager(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class ServiceManager(object):
@abc.abstractproperty
def service_name(self):

View File

@@ -28,6 +28,7 @@ from oslo_config import cfg
from oslo_log import log
from oslo_utils import strutils
from oslo_utils import uuidutils
import six
from watcher.common import exception
@@ -81,7 +82,7 @@ def safe_rstrip(value, chars=None):
:return: Stripped value.
"""
if not isinstance(value, str):
if not isinstance(value, six.string_types):
LOG.warning(
"Failed to remove trailing character. Returning original object."
"Supplied object is not a string: %s,", value)
@@ -103,7 +104,7 @@ def is_hostname_safe(hostname):
"""
m = r'^[a-z0-9]([a-z0-9\-]{0,61}[a-z0-9])?$'
return (isinstance(hostname, str) and
return (isinstance(hostname, six.string_types) and
(re.match(m, hostname) is not None))

View File

@@ -43,20 +43,11 @@ APPLIER_MANAGER_OPTS = [
help='Select the engine to use to execute the workflow'),
]
APPLIER_OPTS = [
cfg.BoolOpt('rollback_when_actionplan_failed',
default=False,
help='If set True, the failed actionplan will rollback '
'when executing. Defaule value is False.'),
]
def register_opts(conf):
conf.register_group(watcher_applier)
conf.register_opts(APPLIER_MANAGER_OPTS, group=watcher_applier)
conf.register_opts(APPLIER_OPTS, group=watcher_applier)
def list_opts():
return [(watcher_applier, APPLIER_MANAGER_OPTS),
(watcher_applier, APPLIER_OPTS)]
return [(watcher_applier, APPLIER_MANAGER_OPTS)]

View File

@@ -18,6 +18,7 @@ Base classes for storage engines
import abc
from oslo_config import cfg
from oslo_db import api as db_api
import six
_BACKEND_MAPPING = {'sqlalchemy': 'watcher.db.sqlalchemy.api'}
IMPL = db_api.DBAPI.from_config(cfg.CONF, backend_mapping=_BACKEND_MAPPING,
@@ -29,7 +30,8 @@ def get_instance():
return IMPL
class BaseConnection(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseConnection(object):
"""Base class for storage system connections."""
@abc.abstractmethod

View File

@@ -15,6 +15,8 @@
# limitations under the License.
#
from __future__ import print_function
import collections
import datetime
import itertools
@@ -23,6 +25,7 @@ import sys
from oslo_log import log
from oslo_utils import strutils
import prettytable as ptable
from six.moves import input
from watcher._i18n import _
from watcher._i18n import lazy_translation_enabled

View File

@@ -18,6 +18,7 @@ SQLAlchemy models for watcher service
from oslo_db.sqlalchemy import models
from oslo_serialization import jsonutils
import six.moves.urllib.parse as urlparse
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import DateTime
@@ -32,7 +33,7 @@ from sqlalchemy import String
from sqlalchemy import Text
from sqlalchemy.types import TypeDecorator, TEXT
from sqlalchemy import UniqueConstraint
import urllib.parse as urlparse
from watcher import conf
CONF = conf.CONF

View File

@@ -18,6 +18,7 @@
# limitations under the License.
#
import abc
import six
from oslo_config import cfg
from oslo_log import log
@@ -35,11 +36,9 @@ CONF = cfg.CONF
LOG = log.getLogger(__name__)
class BaseMetaClass(service.Singleton, abc.ABCMeta):
pass
class BaseAuditHandler(object, metaclass=BaseMetaClass):
@six.add_metaclass(abc.ABCMeta)
@six.add_metaclass(service.Singleton)
class BaseAuditHandler(object):
@abc.abstractmethod
def execute(self, audit, request_context):
@@ -58,7 +57,8 @@ class BaseAuditHandler(object, metaclass=BaseMetaClass):
raise NotImplementedError()
class AuditHandler(BaseAuditHandler, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class AuditHandler(BaseAuditHandler):
def __init__(self):
super(AuditHandler, self).__init__()

View File

@@ -19,8 +19,6 @@ import time
from oslo_config import cfg
from oslo_log import log
from watcher.common import exception
CONF = cfg.CONF
LOG = log.getLogger(__name__)
@@ -56,13 +54,6 @@ class DataSourceBase(object):
instance_root_disk_size=None,
)
def _get_meter(self, meter_name):
"""Retrieve the meter from the metric map or raise error"""
meter = self.METRIC_MAP.get(meter_name)
if meter is None:
raise exception.MetricNotAvailable(metric=meter_name)
return meter
def query_retry(self, f, *args, **kwargs):
"""Attempts to retrieve metrics from the external service
@@ -131,30 +122,6 @@ class DataSourceBase(object):
pass
@abc.abstractmethod
def statistic_series(self, resource=None, resource_type=None,
meter_name=None, start_time=None, end_time=None,
granularity=300):
"""Retrieves metrics based on the specified parameters over a period
:param resource: Resource object as defined in watcher models such as
ComputeNode and Instance
:param resource_type: Indicates which type of object is supplied
to the resource parameter
:param meter_name: The desired metric to retrieve as key from
METRIC_MAP
:param start_time: The datetime to start retrieving metrics for
:type start_time: datetime.datetime
:param end_time: The datetime to limit the retrieval of metrics to
:type end_time: datetime.datetime
:param granularity: Interval between samples in measurements in
seconds
:return: Dictionary of key value pairs with timestamps and metric
values
"""
pass
@abc.abstractmethod
def get_host_cpu_usage(self, resource, period, aggregate,
granularity=None):

View File

@@ -161,7 +161,9 @@ class CeilometerHelper(base.DataSourceBase):
end_time = datetime.datetime.utcnow()
start_time = end_time - datetime.timedelta(seconds=int(period))
meter = self._get_meter(meter_name)
meter = self.METRIC_MAP.get(meter_name)
if meter is None:
raise exception.MetricNotAvailable(metric=meter_name)
if aggregate == 'mean':
aggregate = 'avg'
@@ -192,12 +194,6 @@ class CeilometerHelper(base.DataSourceBase):
item_value *= 10
return item_value
def statistic_series(self, resource=None, resource_type=None,
meter_name=None, start_time=None, end_time=None,
granularity=300):
raise NotImplementedError(
_('Ceilometer helper does not support statistic series method'))
def get_host_cpu_usage(self, resource, period,
aggregate, granularity=None):

View File

@@ -23,6 +23,7 @@ from oslo_config import cfg
from oslo_log import log
from watcher.common import clients
from watcher.common import exception
from watcher.decision_engine.datasources import base
CONF = cfg.CONF
@@ -71,7 +72,9 @@ class GnocchiHelper(base.DataSourceBase):
stop_time = datetime.utcnow()
start_time = stop_time - timedelta(seconds=(int(period)))
meter = self._get_meter(meter_name)
meter = self.METRIC_MAP.get(meter_name)
if meter is None:
raise exception.MetricNotAvailable(metric=meter_name)
if aggregate == 'count':
aggregate = 'mean'
@@ -120,52 +123,6 @@ class GnocchiHelper(base.DataSourceBase):
return return_value
def statistic_series(self, resource=None, resource_type=None,
meter_name=None, start_time=None, end_time=None,
granularity=300):
meter = self._get_meter(meter_name)
resource_id = resource.uuid
if resource_type == 'compute_node':
resource_id = "%s_%s" % (resource.hostname, resource.hostname)
kwargs = dict(query={"=": {"original_resource_id": resource_id}},
limit=1)
resources = self.query_retry(
f=self.gnocchi.resource.search, **kwargs)
if not resources:
LOG.warning("The {0} resource {1} could not be "
"found".format(self.NAME, resource_id))
return
resource_id = resources[0]['id']
raw_kwargs = dict(
metric=meter,
start=start_time,
stop=end_time,
resource_id=resource_id,
granularity=granularity,
)
kwargs = {k: v for k, v in raw_kwargs.items() if k and v}
statistics = self.query_retry(
f=self.gnocchi.metric.get_measures, **kwargs)
return_value = None
if statistics:
# measure has structure [time, granularity, value]
if meter_name == 'host_airflow':
# Airflow from hardware.ipmi.node.airflow is reported as
# 1/10 th of actual CFM
return_value = {s[0]: s[2]*10 for s in statistics}
else:
return_value = {s[0]: s[2] for s in statistics}
return return_value
def get_host_cpu_usage(self, resource, period, aggregate,
granularity=300):

View File

@@ -16,12 +16,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from urllib import parse as urlparse
from oslo_config import cfg
from oslo_log import log
import six.moves.urllib.parse as urlparse
from watcher._i18n import _
from watcher.common import clients
from watcher.common import exception
from watcher.decision_engine.datasources import base
@@ -189,12 +187,6 @@ class GrafanaHelper(base.DataSourceBase):
return result
def statistic_series(self, resource=None, resource_type=None,
meter_name=None, start_time=None, end_time=None,
granularity=300):
raise NotImplementedError(
_('Grafana helper does not support statistic series method'))
def get_host_cpu_usage(self, resource, period=300,
aggregate="mean", granularity=None):
return self.statistic_aggregation(

View File

@@ -21,6 +21,7 @@ import datetime
from monascaclient import exc
from watcher.common import clients
from watcher.common import exception
from watcher.decision_engine.datasources import base
@@ -89,7 +90,9 @@ class MonascaHelper(base.DataSourceBase):
stop_time = datetime.datetime.utcnow()
start_time = stop_time - datetime.timedelta(seconds=(int(period)))
meter = self._get_meter(meter_name)
meter = self.METRIC_MAP.get(meter_name)
if meter is None:
raise exception.MetricNotAvailable(metric=meter_name)
if aggregate == 'mean':
aggregate = 'avg'
@@ -118,34 +121,6 @@ class MonascaHelper(base.DataSourceBase):
return cpu_usage
def statistic_series(self, resource=None, resource_type=None,
meter_name=None, start_time=None, end_time=None,
granularity=300):
meter = self._get_meter(meter_name)
raw_kwargs = dict(
name=meter,
start_time=start_time.isoformat(),
end_time=end_time.isoformat(),
dimensions={'hostname': resource.uuid},
statistics='avg',
group_by='*',
)
kwargs = {k: v for k, v in raw_kwargs.items() if k and v}
statistics = self.query_retry(
f=self.monasca.metrics.list_statistics, **kwargs)
result = {}
for stat in statistics:
v_index = stat['columns'].index('avg')
t_index = stat['columns'].index('timestamp')
result.update({r[t_index]: r[v_index] for r in stat['statistics']})
return result
def get_host_cpu_usage(self, resource, period,
aggregate, granularity=None):
return self.statistic_aggregation(

View File

@@ -15,11 +15,13 @@
# limitations under the License.
import abc
import six
from watcher.common.loader import loadable
class Goal(loadable.Loadable, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class Goal(loadable.Loadable):
def __init__(self, config):
super(Goal, self).__init__(config)

View File

@@ -27,8 +27,11 @@ import abc
import jsonschema
from oslo_serialization import jsonutils
import six
class EfficacySpecification(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class EfficacySpecification(object):
def __init__(self):
self._indicators_specs = self.get_indicators_specifications()

View File

@@ -18,6 +18,7 @@ import abc
import jsonschema
from jsonschema import SchemaError
from jsonschema import ValidationError
import six
from oslo_log import log
from oslo_serialization import jsonutils
@@ -28,7 +29,8 @@ from watcher.common import exception
LOG = log.getLogger(__name__)
class IndicatorSpecification(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class IndicatorSpecification(object):
def __init__(self, name=None, description=None, unit=None, required=True):
self.name = name

View File

@@ -19,6 +19,9 @@
# limitations under the License.
#
from __future__ import unicode_literals
from watcher.common.loader import default

View File

@@ -25,9 +25,11 @@ See: :doc:`../architecture` for more details on this component.
"""
import abc
import six
class Model(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class Model(object):
@abc.abstractmethod
def to_string(self):

View File

@@ -110,6 +110,7 @@ import time
from oslo_config import cfg
from oslo_log import log
import six
from watcher.common import clients
from watcher.common.loader import loadable
@@ -119,8 +120,8 @@ LOG = log.getLogger(__name__)
CONF = cfg.CONF
class BaseClusterDataModelCollector(loadable.LoadableSingleton,
metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseClusterDataModelCollector(loadable.LoadableSingleton):
STALE_MODEL = model_root.ModelRoot(stale=True)

View File

@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import six
from oslo_log import log
from watcher.common import cinder_helper
@@ -287,7 +289,7 @@ class CinderModelBuilder(base.BaseModelBuilder):
:param instance: Cinder Volume object.
:return: A volume node for the graph.
"""
attachments = [{k: v for k, v in iter(d.items()) if k in (
attachments = [{k: v for k, v in six.iteritems(d) if k in (
'server_id', 'attachment_id')} for d in volume.attachments]
volume_attributes = {

View File

@@ -16,12 +16,14 @@
import abc
import six
from watcher.decision_engine.model.element import base
from watcher.objects import fields as wfields
class BaremetalResource(base.Element, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaremetalResource(base.Element):
VERSION = '1.0'

View File

@@ -21,6 +21,7 @@ import collections
from lxml import etree
from oslo_log import log
import six
from watcher.objects import base
from watcher.objects import fields as wfields
@@ -28,8 +29,9 @@ from watcher.objects import fields as wfields
LOG = log.getLogger(__name__)
@six.add_metaclass(abc.ABCMeta)
class Element(base.WatcherObject, base.WatcherObjectDictCompat,
base.WatcherComparableObject, metaclass=abc.ABCMeta):
base.WatcherComparableObject):
# Initial version
VERSION = '1.0'

View File

@@ -16,12 +16,14 @@
import abc
import six
from watcher.decision_engine.model.element import base
from watcher.objects import fields as wfields
class ComputeResource(base.Element, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class ComputeResource(base.Element):
VERSION = '1.0'

View File

@@ -16,12 +16,14 @@
import abc
import six
from watcher.decision_engine.model.element import base
from watcher.objects import fields as wfields
class StorageResource(base.Element, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class StorageResource(base.Element):
VERSION = '1.0'

View File

@@ -21,6 +21,7 @@ from lxml import etree
import networkx as nx
from oslo_concurrency import lockutils
from oslo_log import log
import six
from watcher._i18n import _
from watcher.common import exception
@@ -92,9 +93,9 @@ class ModelRoot(nx.DiGraph, base.Model):
:param node: :py:class:`~.node.ComputeNode` object or node UUID
:type node: str or :py:class:`~.instance.Instance`
"""
if isinstance(instance, str):
if isinstance(instance, six.string_types):
instance = self.get_instance_by_uuid(instance)
if isinstance(node, str):
if isinstance(node, six.string_types):
node = self.get_node_by_uuid(node)
self.assert_node(node)
self.assert_instance(instance)
@@ -103,9 +104,9 @@ class ModelRoot(nx.DiGraph, base.Model):
@lockutils.synchronized("model_root")
def unmap_instance(self, instance, node):
if isinstance(instance, str):
if isinstance(instance, six.string_types):
instance = self.get_instance_by_uuid(instance)
if isinstance(node, str):
if isinstance(node, six.string_types):
node = self.get_node_by_uuid(node)
self.remove_edge(instance.uuid, node.uuid)
@@ -366,9 +367,9 @@ class StorageModelRoot(nx.DiGraph, base.Model):
:param pool: :py:class:`~.node.Pool` object or pool name
:param node: :py:class:`~.node.StorageNode` object or node host
"""
if isinstance(pool, str):
if isinstance(pool, six.string_types):
pool = self.get_pool_by_pool_name(pool)
if isinstance(node, str):
if isinstance(node, six.string_types):
node = self.get_node_by_name(node)
self.assert_node(node)
self.assert_pool(pool)
@@ -382,9 +383,9 @@ class StorageModelRoot(nx.DiGraph, base.Model):
:param pool: :py:class:`~.node.Pool` object or pool name
:param node: :py:class:`~.node.StorageNode` object or node name
"""
if isinstance(pool, str):
if isinstance(pool, six.string_types):
pool = self.get_pool_by_pool_name(pool)
if isinstance(node, str):
if isinstance(node, six.string_types):
node = self.get_node_by_name(node)
self.remove_edge(pool.name, node.host)
@@ -410,9 +411,9 @@ class StorageModelRoot(nx.DiGraph, base.Model):
:param volume: :py:class:`~.volume.Volume` object or volume UUID
:param pool: :py:class:`~.node.Pool` object or pool name
"""
if isinstance(volume, str):
if isinstance(volume, six.string_types):
volume = self.get_volume_by_uuid(volume)
if isinstance(pool, str):
if isinstance(pool, six.string_types):
pool = self.get_pool_by_pool_name(pool)
self.assert_pool(pool)
self.assert_volume(volume)
@@ -426,9 +427,9 @@ class StorageModelRoot(nx.DiGraph, base.Model):
:param volume: :py:class:`~.volume.Volume` object or volume UUID
:param pool: :py:class:`~.node.Pool` object or pool name
"""
if isinstance(volume, str):
if isinstance(volume, six.string_types):
volume = self.get_volume_by_uuid(volume)
if isinstance(pool, str):
if isinstance(pool, six.string_types):
pool = self.get_pool_by_pool_name(pool)
self.remove_edge(volume.uuid, pool.name)
@@ -631,7 +632,7 @@ class BaremetalModelRoot(nx.DiGraph, base.Model):
super(BaremetalModelRoot, self).remove_node(node.uuid)
except nx.NetworkXError as exc:
LOG.exception(exc)
raise exception.IronicNodeNotFound(uuid=node.uuid)
raise exception.IronicNodeNotFound(name=node.uuid)
@lockutils.synchronized("baremetal_model")
def get_all_ironic_nodes(self):
@@ -643,7 +644,7 @@ class BaremetalModelRoot(nx.DiGraph, base.Model):
try:
return self._get_by_uuid(uuid)
except exception.BaremetalResourceNotFound:
raise exception.IronicNodeNotFound(uuid=uuid)
raise exception.IronicNodeNotFound(name=uuid)
def _get_by_uuid(self, uuid):
try:

View File

@@ -17,9 +17,11 @@
# limitations under the License.
import abc
import six
class NotificationEndpoint(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class NotificationEndpoint(object):
def __init__(self, collector):
super(NotificationEndpoint, self).__init__()

View File

@@ -14,6 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import six
from oslo_log import log
from watcher.common import cinder_helper
from watcher.common import exception
@@ -159,7 +161,7 @@ class CinderNotification(base.NotificationEndpoint):
return 'attachment_id'
attachments = [
{_keyReplace(k): v for k, v in iter(d.items())
{_keyReplace(k): v for k, v in six.iteritems(d)
if k in ('instance_uuid', 'id')}
for d in data['volume_attachment']
]

View File

@@ -19,6 +19,7 @@
import re
import oslo_messaging as om
import six
class NotificationFilter(om.NotificationFilter):
@@ -80,7 +81,7 @@ class NotificationFilter(om.NotificationFilter):
elif regex is not None and data is None:
return True
elif (regex is not None and
isinstance(data, str) and
isinstance(data, six.string_types) and
not regex.match(data)):
return True

View File

@@ -45,11 +45,13 @@ See :doc:`../architecture` for more details on this component.
"""
import abc
import six
from watcher.common.loader import loadable
class BasePlanner(loadable.Loadable, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BasePlanner(loadable.Loadable):
@classmethod
def get_config_opts(cls):

View File

@@ -16,11 +16,13 @@
#
import abc
import six
from watcher.common import context
class BaseScope(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseScope(object):
"""A base class for Scope mechanism
Child of this class is called when audit launches strategy. This strategy

View File

@@ -17,11 +17,13 @@
# limitations under the License.
import abc
import six
from watcher.common.loader import loadable
class ScoringEngine(loadable.Loadable, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class ScoringEngine(loadable.Loadable):
"""A base class for all the Scoring Engines.
A Scoring Engine is an instance of a data model, to which the learning
@@ -95,7 +97,8 @@ class ScoringEngine(loadable.Loadable, metaclass=abc.ABCMeta):
return []
class ScoringEngineContainer(loadable.Loadable, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class ScoringEngineContainer(loadable.Loadable):
"""A base class for all the Scoring Engines Containers.
A Scoring Engine Container is an abstraction which allows to plugin

View File

@@ -56,11 +56,13 @@ Two approaches to dealing with this can be envisaged:
"""
import abc
import six
from watcher.decision_engine.solution import efficacy
class BaseSolution(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseSolution(object):
def __init__(self, goal, strategy):
"""Base Solution constructor

View File

@@ -17,9 +17,11 @@
# limitations under the License.
#
import abc
import six
class BaseSolutionComparator(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseSolutionComparator(object):
@abc.abstractmethod
def compare(self, sol1, sol2):
raise NotImplementedError()

View File

@@ -17,9 +17,11 @@
# limitations under the License.
#
import abc
import six
class BaseSolutionEvaluator(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseSolutionEvaluator(object):
@abc.abstractmethod
def evaluate(self, solution):
raise NotImplementedError()

View File

@@ -18,12 +18,14 @@
# limitations under the License.
import abc
import six
from watcher import notifications
from watcher.objects import fields
class StrategyContext(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class StrategyContext(object):
def execute_strategy(self, audit, request_context):
"""Execute the strategy for the given an audit

View File

@@ -17,9 +17,11 @@
# limitations under the License.
#
import abc
import six
class BaseSelector(object, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseSelector(object):
@abc.abstractmethod
def select(self):

View File

@@ -37,6 +37,7 @@ which are dynamically loaded by Watcher at launch time.
"""
import abc
import six
from oslo_config import cfg
from oslo_log import log
@@ -120,7 +121,8 @@ class StrategyEndpoint(object):
return [available_datasource, available_metrics, available_cdm]
class BaseStrategy(loadable.Loadable, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class BaseStrategy(loadable.Loadable):
"""A base class for all the strategies
A Strategy is an algorithm implementation which is able to find a
@@ -469,7 +471,8 @@ class BaseStrategy(loadable.Loadable, metaclass=abc.ABCMeta):
input_parameters=parameters)
class DummyBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class DummyBaseStrategy(BaseStrategy):
@classmethod
def get_goal_name(cls):
@@ -482,7 +485,8 @@ class DummyBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
return []
class UnclassifiedStrategy(BaseStrategy, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class UnclassifiedStrategy(BaseStrategy):
"""This base class is used to ease the development of new strategies
The goal defined within this strategy can be used to simplify the
@@ -496,7 +500,8 @@ class UnclassifiedStrategy(BaseStrategy, metaclass=abc.ABCMeta):
return "unclassified"
class ServerConsolidationBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class ServerConsolidationBaseStrategy(BaseStrategy):
REASON_FOR_DISABLE = 'watcher_disabled'
@@ -505,14 +510,16 @@ class ServerConsolidationBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
return "server_consolidation"
class ThermalOptimizationBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class ThermalOptimizationBaseStrategy(BaseStrategy):
@classmethod
def get_goal_name(cls):
return "thermal_optimization"
class WorkloadStabilizationBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class WorkloadStabilizationBaseStrategy(BaseStrategy):
def __init__(self, *args, **kwargs):
super(WorkloadStabilizationBaseStrategy, self
@@ -524,14 +531,16 @@ class WorkloadStabilizationBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
return "workload_balancing"
class NoisyNeighborBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class NoisyNeighborBaseStrategy(BaseStrategy):
@classmethod
def get_goal_name(cls):
return "noisy_neighbor"
class SavingEnergyBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class SavingEnergyBaseStrategy(BaseStrategy):
@classmethod
def get_goal_name(cls):
@@ -544,7 +553,8 @@ class SavingEnergyBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
return []
class ZoneMigrationBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class ZoneMigrationBaseStrategy(BaseStrategy):
@classmethod
def get_goal_name(cls):
@@ -557,7 +567,8 @@ class ZoneMigrationBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
return []
class HostMaintenanceBaseStrategy(BaseStrategy, metaclass=abc.ABCMeta):
@six.add_metaclass(abc.ABCMeta)
class HostMaintenanceBaseStrategy(BaseStrategy):
REASON_FOR_MAINTAINING = 'watcher_maintaining'

View File

@@ -18,6 +18,8 @@
#
from oslo_log import log
import six
from watcher._i18n import _
from watcher.common import exception
from watcher.decision_engine.model import element
@@ -101,7 +103,7 @@ class HostMaintenance(base.HostMaintenanceBaseStrategy):
def get_instance_state_str(self, instance):
"""Get instance state in string format"""
if isinstance(instance.state, str):
if isinstance(instance.state, six.string_types):
return instance.state
elif isinstance(instance.state, element.InstanceState):
return instance.state.value
@@ -114,7 +116,7 @@ class HostMaintenance(base.HostMaintenanceBaseStrategy):
def get_node_status_str(self, node):
"""Get node status in string format"""
if isinstance(node.status, str):
if isinstance(node.status, six.string_types):
return node.status
elif isinstance(node.status, element.ServiceState):
return node.status.value

View File

@@ -19,6 +19,7 @@
#
from oslo_log import log
import six
from watcher._i18n import _
from watcher.common import exception
@@ -131,7 +132,7 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy):
:param instance:
"""
if isinstance(instance.state, str):
if isinstance(instance.state, six.string_types):
return instance.state
elif isinstance(instance.state, element.InstanceState):
return instance.state.value
@@ -147,7 +148,7 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy):
:param node:
"""
if isinstance(node.status, str):
if isinstance(node.status, six.string_types):
return node.status
elif isinstance(node.status, element.ServiceState):
return node.status.value

View File

@@ -17,6 +17,8 @@
# limitations under the License.
#
from __future__ import division
from oslo_log import log
from watcher._i18n import _

View File

@@ -13,6 +13,7 @@
#
from dateutil.parser import parse
import six
from oslo_log import log
@@ -281,7 +282,7 @@ class ZoneMigration(base.ZoneMigrationBaseStrategy):
action_counter = ActionCounter(total_limit,
per_pool_limit, per_node_limit)
for k, targets in iter(filtered_targets.items()):
for k, targets in six.iteritems(filtered_targets):
if k == VOLUME:
self.volumes_migration(targets, action_counter)
elif k == INSTANCE:
@@ -350,7 +351,7 @@ class ZoneMigration(base.ZoneMigrationBaseStrategy):
def is_in_use(self, volume):
return getattr(volume, 'status') == IN_USE
def instances_no_attached(self, instances):
def instances_no_attached(instances):
return [i for i in instances
if not getattr(i, "os-extended-volumes:volumes_attached")]
@@ -579,7 +580,7 @@ class ZoneMigration(base.ZoneMigrationBaseStrategy):
filter_list = []
priority_filter_map = self.get_priority_filter_map()
for k, v in iter(self.priority.items()):
for k, v in six.iteritems(self.priority):
if k in priority_filter_map:
filter_list.append(priority_filter_map[k](v))
@@ -709,7 +710,7 @@ class BaseFilter(object):
return {}
for cond in list(reversed(self.condition)):
for k, v in iter(targets.items()):
for k, v in six.iteritems(targets):
if not self.is_allowed(k):
continue
LOG.debug("filter:%s with the key: %s", cond, k)

View File

@@ -19,6 +19,7 @@
import copy
import futurist
from futurist import waiters
import six
from oslo_config import cfg
from oslo_log import log
@@ -28,7 +29,8 @@ CONF = cfg.CONF
LOG = log.getLogger(__name__)
class DecisionEngineThreadPool(object, metaclass=service.Singleton):
@six.add_metaclass(service.Singleton)
class DecisionEngineThreadPool(object):
"""Singleton threadpool to submit general tasks to"""
def __init__(self):

View File

@@ -128,20 +128,22 @@ def check_assert_called_once_with(logical_line, filename):
@flake8ext
def check_python3_xrange(logical_line):
if re.search(r"\bxrange\s*\(", logical_line):
yield(0, "N325: Do not use xrange. Use range for large loops.")
yield(0, "N325: Do not use xrange. Use range, or six.moves.range for "
"large loops.")
@flake8ext
def check_no_basestring(logical_line):
if re.search(r"\bbasestring\b", logical_line):
msg = ("N326: basestring is not Python3-compatible, use str instead.")
msg = ("N326: basestring is not Python3-compatible, use "
"six.string_types instead.")
yield(0, msg)
@flake8ext
def check_python3_no_iteritems(logical_line):
if re.search(r".*\.iteritems\(\)", logical_line):
msg = ("N327: Use dict.items() instead of dict.iteritems().")
msg = ("N327: Use six.iteritems() instead of dict.iteritems().")
yield(0, msg)
@@ -283,31 +285,3 @@ def no_redundant_import_alias(logical_line):
"""
if re.match(re_redundant_import_alias, logical_line):
yield(0, "N342: No redundant import alias.")
@flake8ext
def import_stock_mock(logical_line):
"""Use python's mock, not the mock library.
Since we `dropped support for python 2`__, we no longer need to use the
mock library, which existed to backport py3 functionality into py2.
Which must be done by saying::
from unittest import mock
...because if you say::
import mock
...you definitely will not be getting the standard library mock. That will
always import the third party mock library. This check can be removed in
the future (and we can start saying ``import mock`` again) if we manage to
purge these transitive dependencies.
.. __: https://review.opendev.org/#/c/717540
N366
"""
if logical_line == 'import mock':
yield (0, "N366: You must explicitly import python's mock: "
"``from unittest import mock``")

View File

@@ -4,7 +4,7 @@ msgid ""
msgstr ""
"Project-Id-Version: watcher VERSION\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2020-04-26 02:09+0000\n"
"POT-Creation-Date: 2020-04-26 01:47+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@@ -1,15 +1,14 @@
# Andi Chandler <andi@gowling.com>, 2017. #zanata
# Andi Chandler <andi@gowling.com>, 2018. #zanata
# Andi Chandler <andi@gowling.com>, 2020. #zanata
msgid ""
msgstr ""
"Project-Id-Version: watcher VERSION\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: 2020-04-26 01:47+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2020-10-28 11:02+0000\n"
"PO-Revision-Date: 2018-11-07 06:14+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language-Team: English (United Kingdom)\n"
"Language: en_GB\n"
@@ -188,18 +187,10 @@ msgstr "Audit Templates"
msgid "Audit parameter %(parameter)s are not allowed"
msgstr "Audit parameter %(parameter)s are not allowed"
#, python-format
msgid "Audit state %(state)s is disallowed."
msgstr "Audit state %(state)s is disallowed."
#, python-format
msgid "Audit type %(audit_type)s could not be found"
msgstr "Audit type %(audit_type)s could not be found"
#, python-format
msgid "Audit type %(audit_type)s is disallowed."
msgstr "Audit type %(audit_type)s is disallowed."
#, python-format
msgid "AuditTemplate %(audit_template)s could not be found"
msgstr "AuditTemplate %(audit_template)s could not be found"
@@ -252,9 +243,6 @@ msgstr "Cannot overwrite UUID for an existing efficacy indicator."
msgid "Cannot remove 'goal' attribute from an audit template"
msgstr "Cannot remove 'goal' attribute from an audit template"
msgid "Ceilometer helper does not support statistic series method"
msgstr "Ceilometer helper does not support statistic series method"
msgid "Cluster Maintaining"
msgstr "Cluster Maintaining"
@@ -381,9 +369,6 @@ msgstr "Goal %(goal)s is invalid"
msgid "Goals"
msgstr "Goals"
msgid "Grafana helper does not support statistic series method"
msgstr "Grafana helper does not support statistic series method"
msgid "Hardware Maintenance"
msgstr "Hardware Maintenance"
@@ -449,17 +434,10 @@ msgstr "Limit should be positive"
msgid "Maximum time since last check-in for up service."
msgstr "Maximum time since last check-in for up service."
#, python-format
msgid "Metric: %(metric)s not available"
msgstr "Metric: %(metric)s not available"
#, python-format
msgid "Migration of type '%(migration_type)s' is not supported."
msgstr "Migration of type '%(migration_type)s' is not supported."
msgid "Minimum Nova API Version"
msgstr "Minimum Nova API Version"
msgid ""
"Name of this node. This can be an opaque identifier. It is not necessarily a "
"hostname, FQDN, or IP address. However, the node name must be valid within "
@@ -473,16 +451,10 @@ msgstr ""
msgid "No %(metric)s metric for %(host)s found."
msgstr "No %(metric)s metric for %(host)s found."
msgid "No datasources available"
msgstr "No datasources available"
#, python-format
msgid "No strategy could be found to achieve the '%(goal)s' goal."
msgstr "No strategy could be found to achieve the '%(goal)s' goal."
msgid "Node Resource Consolidation strategy"
msgstr "Node Resource Consolidation strategy"
msgid "Noisy Neighbor"
msgstr "Noisy Neighbour"
@@ -634,10 +606,6 @@ msgstr "Strategy %(strategy)s could not be found"
msgid "Strategy %(strategy)s is invalid"
msgstr "Strategy %(strategy)s is invalid"
#, python-format
msgid "The %(data_model_type)s data model could not be found"
msgstr "The %(data_model_type)s data model could not be found"
#, python-format
msgid "The %(name)s %(id)s could not be found"
msgstr "The %(name)s %(id)s could not be found"
@@ -707,13 +675,6 @@ msgstr "The instance '%(name)s' could not be found"
msgid "The ironic node %(uuid)s could not be found"
msgstr "The Ironic node %(uuid)s could not be found"
#, python-format
msgid "The mapped compute node for instance '%(uuid)s' could not be found."
msgstr "The mapped compute node for instance '%(uuid)s' could not be found."
msgid "The node status is not defined"
msgstr "The node status is not defined"
msgid "The number of VM migrations to be performed."
msgstr "The number of VM migrations to be performed."
@@ -777,10 +738,6 @@ msgstr "The total number of audited instances in strategy."
msgid "The total number of enabled compute nodes."
msgstr "The total number of enabled compute nodes."
#, python-format
msgid "The value %(value)s for parameter %(parameter)s is invalid"
msgstr "The value %(value)s for parameter %(parameter)s is invalid"
msgid "The value of original standard deviation."
msgstr "The value of original standard deviation."

View File

@@ -15,6 +15,7 @@
"""Utility methods for objects"""
import ast
import six
from oslo_serialization import jsonutils
from oslo_versionedobjects import fields
@@ -66,7 +67,7 @@ class ListOfUUIDsField(fields.AutoTypedField):
class FlexibleDict(fields.FieldType):
@staticmethod
def coerce(obj, attr, value):
if isinstance(value, str):
if isinstance(value, six.string_types):
value = ast.literal_eval(value)
return dict(value)
@@ -86,7 +87,7 @@ class FlexibleDictField(fields.AutoTypedField):
class FlexibleListOfDict(fields.FieldType):
@staticmethod
def coerce(obj, attr, value):
if isinstance(value, str):
if isinstance(value, six.string_types):
value = ast.literal_eval(value)
return list(value)
@@ -105,7 +106,7 @@ class FlexibleListOfDictField(fields.AutoTypedField):
class Json(fields.FieldType):
def coerce(self, obj, attr, value):
if isinstance(value, str):
if isinstance(value, six.string_types):
loaded = jsonutils.loads(value)
return loaded
return value

View File

@@ -23,12 +23,12 @@
# NOTE(deva): import auth_token so we can override a config option
import copy
from unittest import mock
from urllib import parse as urlparse
import mock
from oslo_config import cfg
import pecan
import pecan.testing
from six.moves.urllib import parse as urlparse
from watcher.api import hooks
from watcher.common import context as watcher_context

View File

@@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import importlib
import imp
from oslo_config import cfg
from watcher.api import config as api_config
from watcher.tests.api import base
@@ -23,13 +23,13 @@ class TestRoot(base.FunctionalTest):
def test_config_enable_webhooks_auth(self):
acl_public_routes = ['/']
cfg.CONF.set_override('enable_webhooks_auth', True, 'api')
importlib.reload(api_config)
imp.reload(api_config)
self.assertEqual(acl_public_routes,
api_config.app['acl_public_routes'])
def test_config_disable_webhooks_auth(self):
acl_public_routes = ['/', '/v1/webhooks/.*']
cfg.CONF.set_override('enable_webhooks_auth', False, 'api')
importlib.reload(api_config)
imp.reload(api_config)
self.assertEqual(acl_public_routes,
api_config.app['acl_public_routes'])

View File

@@ -14,11 +14,15 @@
"""Tests for the Pecan API hooks."""
from http import client as http_client
from __future__ import unicode_literals
import mock
from oslo_config import cfg
import oslo_messaging as messaging
from oslo_serialization import jsonutils
from unittest import mock
import six
from six.moves import http_client
from watcher.api.controllers import root
from watcher.api import hooks
from watcher.common import context
@@ -141,7 +145,7 @@ class TestNoExceptionTracebackHook(base.FunctionalTest):
# we don't care about this garbage.
expected_msg = ("Remote error: %s %s"
% (test_exc_type, self.MSG_WITHOUT_TRACE) +
"\n['")
("\n[u'" if six.PY2 else "\n['"))
actual_msg = jsonutils.loads(
response.json['error_message'])['faultstring']
self.assertEqual(expected_msg, actual_msg)

View File

@@ -15,7 +15,7 @@
from apscheduler.schedulers import background
import datetime
import freezegun
from unittest import mock
import mock
from watcher.api import scheduling
from watcher.notifications import service

View File

@@ -14,6 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import unicode_literals
from oslo_config import cfg
import wsme

View File

@@ -12,7 +12,7 @@
import datetime
import itertools
from unittest import mock
import mock
from oslo_config import cfg
from oslo_serialization import jsonutils

View File

@@ -12,7 +12,7 @@
import datetime
import itertools
from unittest import mock
import mock
from oslo_config import cfg
from oslo_serialization import jsonutils

View File

@@ -12,13 +12,13 @@
import datetime
import itertools
from unittest import mock
from urllib import parse as urlparse
import mock
from webtest.app import AppError
from oslo_config import cfg
from oslo_serialization import jsonutils
from oslo_utils import timeutils
import webtest.app as webtest_app
from six.moves.urllib import parse as urlparse
from wsme import types as wtypes
from watcher.api.controllers.v1 import audit_template as api_audit_template
@@ -603,7 +603,7 @@ class TestPost(FunctionalTestWithSetup):
audit_template_dict = post_get_test_audit_template(
goal=self.fake_goal1.uuid,
strategy=self.fake_strategy1.uuid, scope=scope)
with self.assertRaisesRegex(webtest_app.AppError,
with self.assertRaisesRegex(AppError,
"be included and excluded together"):
self.post_json('/audit_templates', audit_template_dict)

View File

@@ -13,14 +13,14 @@
import datetime
from dateutil import tz
import itertools
from unittest import mock
from urllib import parse as urlparse
import mock
from oslo_config import cfg
from oslo_serialization import jsonutils
from oslo_utils import timeutils
from wsme import types as wtypes
from six.moves.urllib import parse as urlparse
from watcher.api.controllers.v1 import audit as api_audit
from watcher.common import utils
from watcher.db import api as db_api

View File

@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from unittest import mock
import mock
from oslo_serialization import jsonutils

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