Compare commits

..

3 Commits

Author SHA1 Message Date
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
336 changed files with 3413 additions and 6941 deletions

View File

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

View File

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

View File

@@ -1,45 +1,108 @@
- project:
queue: watcher
templates:
- check-requirements
- openstack-cover-jobs
- openstack-python3-jobs
- openstack-lower-constraints-jobs
- openstack-python3-ussuri-jobs
- publish-openstack-docs-pti
- release-notes-jobs-python3
check:
jobs:
- watcher-tempest-functional
- watcher-tempest-functional-jammy
- watcher-grenade
- watcher-tempest-strategies
- watcher-tempest-actuator
- watcherclient-tempest-functional
- watcher-tls-test
- watcher-tempest-functional-ipv6-only
- watcher-prometheus-integration
gate:
queue: watcher
jobs:
- watcher-tempest-functional
- watcher-tempest-functional-jammy
- watcher-tempest-functional-ipv6-only
- job:
name: watcher-tempest-dummy_optim
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_dummy_optim
- job:
name: watcher-tempest-actuator
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_actuator
- job:
name: watcher-tempest-basic_optim
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_basic_optim
- job:
name: watcher-tempest-vm_workload_consolidation
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_vm_workload_consolidation
devstack_local_conf:
test-config:
$WATCHER_CONFIG:
watcher_strategies.vm_workload_consolidation:
datasource: ceilometer
- job:
name: watcher-tempest-workload_balancing
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_workload_balancing
- job:
name: watcher-tempest-zone_migration
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_zone_migration
- job:
name: watcher-tempest-host_maintenance
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_host_maintenance
- job:
name: watcher-tempest-storage_balance
parent: watcher-tempest-multinode
vars:
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_storage_balance
devstack_local_conf:
test-config:
$TEMPEST_CONFIG:
volume:
backend_names: ['BACKEND_1', 'BACKEND_2']
volume-feature-enabled:
multi_backend: true
- job:
name: watcher-tempest-strategies
parent: watcher-tempest-multinode
vars:
tempest_concurrency: 1
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_strategies
tempest_exclude_regex: .*\[.*\breal_load\b.*\].*
- job:
name: watcher-tls-test
parent: watcher-tempest-multinode
group-vars:
subnode:
devstack_services:
tls-proxy: true
vars:
devstack_services:
tls-proxy: true
- job:
name: watcher-tempest-multinode
parent: watcher-tempest-functional
nodeset: openstack-two-node-noble
nodeset: openstack-two-node-bionic
roles:
- zuul: openstack/tempest
group-vars:
@@ -57,7 +120,8 @@
watcher-api: false
watcher-decision-engine: true
watcher-applier: false
c-bak: false
# We need to add TLS support for watcher plugin
tls-proxy: false
ceilometer: false
ceilometer-acompute: false
ceilometer-acentral: false
@@ -96,6 +160,7 @@
timeout: 7200
required-projects: &base_required_projects
- openstack/ceilometer
- openstack/devstack-gate
- openstack/python-openstackclient
- openstack/python-watcherclient
- openstack/watcher
@@ -105,6 +170,7 @@
devstack_plugins:
watcher: https://opendev.org/openstack/watcher
devstack_services:
tls-proxy: false
watcher-api: true
watcher-decision-engine: true
watcher-applier: true
@@ -113,24 +179,17 @@
s-container: false
s-object: false
s-proxy: false
tempest_plugins:
- watcher-tempest-plugin
devstack_localrc:
TEMPEST_PLUGINS: /opt/stack/watcher-tempest-plugin
USE_PYTHON3: true
tempest_test_regex: watcher_tempest_plugin.tests.api
tox_envlist: all
tox_environment:
# Do we really need to set this? It's cargo culted
PYTHONUNBUFFERED: 'true'
zuul_copy_output:
/etc/hosts: logs
# TODO(gmann): As per the 2025.1 testing runtime, we need to run at least
# one job on jammy. This job can be removed in the next cycle(2025.2)
- job:
name: watcher-tempest-functional-jammy
description: This is integrated job testing on Ubuntu jammy(22.04)
parent: watcher-tempest-functional
nodeset: openstack-single-node-jammy
vars:
<<: *base_vars
python_version: '3.9'
- job:
name: watcher-tempest-functional-ipv6-only
parent: devstack-tempest-ipv6
@@ -141,13 +200,11 @@
- job:
name: watcher-grenade
parent: grenade
required-projects:
- openstack/watcher
- openstack/python-watcherclient
- openstack/watcher-tempest-plugin
vars: *base_vars
irrelevant-files: &irrelevent_files
parent: legacy-dsvm-base
timeout: 10800
run: playbooks/legacy/grenade-devstack-watcher/run.yaml
post-run: playbooks/legacy/grenade-devstack-watcher/post.yaml
irrelevant-files:
- ^(test-|)requirements.txt$
- ^.*\.rst$
- ^api-ref/.*$
@@ -158,6 +215,12 @@
- ^setup.cfg$
- ^tools/.*$
- ^tox.ini$
required-projects:
- openstack/grenade
- openstack/devstack-gate
- openstack/watcher
- openstack/python-watcherclient
- openstack/watcher-tempest-plugin
- job:
# This job is used in python-watcherclient repo
@@ -167,126 +230,3 @@
vars:
tempest_concurrency: 1
tempest_test_regex: watcher_tempest_plugin.tests.client_functional
- job:
name: watcher-sg-core-tempest-base
parent: devstack-tempest
nodeset: openstack-two-node-noble
description: |
This job is for testing watcher and sg-core/prometheus installation
abstract: true
pre-run:
- playbooks/generate_prometheus_config.yml
irrelevant-files: *irrelevent_files
timeout: 7800
required-projects: &base_sg_required_projects
- openstack/aodh
- openstack/ceilometer
- openstack/tempest
- openstack-k8s-operators/sg-core
- openstack/watcher
- openstack/python-watcherclient
- openstack/watcher-tempest-plugin
- openstack/devstack-plugin-prometheus
vars:
configure_swap_size: 8192
devstack_plugins:
ceilometer: https://opendev.org/openstack/ceilometer
aodh: https://opendev.org/openstack/aodh
sg-core: https://github.com/openstack-k8s-operators/sg-core
watcher: https://opendev.org/openstack/watcher
devstack-plugin-prometheus: https://opendev.org/openstack/devstack-plugin-prometheus
devstack_services:
watcher-api: true
watcher-decision-engine: true
watcher-applier: true
tempest: true
# We do not need Swift in this job so disable it for speed
# Swift services
s-account: false
s-container: false
s-object: false
s-proxy: false
# Prometheus related service
prometheus: true
node_exporter: true
devstack_localrc:
CEILOMETER_BACKENDS: "sg-core"
CEILOMETER_PIPELINE_INTERVAL: 15
CEILOMETER_ALARM_THRESHOLD: 6000000000
PROMETHEUS_CONFIG_FILE: "/home/zuul/prometheus.yml"
# Disable sg_core prometheus config copy
PROMETHEUS_ENABLE: false
# PROMETHEUS_CONFIG_FILE var conflicts with sg_core var
# to avoid issue, set PROMETHEUS_CONF_DIR
PROMETHEUS_CONF_DIR: "/home/zuul"
devstack_local_conf:
post-config:
$WATCHER_CONF:
watcher_datasources:
datasources: prometheus
prometheus_client:
host: 127.0.0.1
port: 9090
watcher_cluster_data_model_collectors.compute:
period: 120
watcher_cluster_data_model_collectors.baremetal:
period: 120
watcher_cluster_data_model_collectors.storage:
period: 120
test-config:
$TEMPEST_CONFIG:
compute:
min_compute_nodes: 2
min_microversion: 2.56
compute-feature-enabled:
live_migration: true
block_migration_for_live_migration: true
placement:
min_microversion: 1.29
service_available:
sg_core: True
telemetry_services:
metric_backends: prometheus
telemetry:
disable_ssl_certificate_validation: True
ceilometer_polling_interval: 15
optimize:
datasource: prometheus
tempest_plugins:
- watcher-tempest-plugin
tempest_test_regex: watcher_tempest_plugin.tests.scenario.test_execute_strategies
tempest_exclude_regex: .*\[.*\breal_load\b.*\].*
tempest_concurrency: 1
tox_envlist: all
zuul_copy_output:
/etc/prometheus/prometheus.yml: logs
group-vars:
subnode:
devstack_plugins:
ceilometer: https://opendev.org/openstack/ceilometer
devstack-plugin-prometheus: https://opendev.org/openstack/devstack-plugin-prometheus
devstack_services:
ceilometer-acompute: true
sg-core: false
prometheus: false
node_exporter: true
devstack_localrc:
CEILOMETER_BACKEND: "none"
CEILOMETER_BACKENDS: "none"
# avoid collecting real host cpu metric since tests
# will inject fake metrics when needed
NODE_EXPORTER_COLLECTOR_EXCLUDE: "cpu"
devstack_local_conf:
post-config:
$WATCHER_CONF:
watcher_cluster_data_model_collectors.compute:
period: 120
watcher_cluster_data_model_collectors.baremetal:
period: 120
watcher_cluster_data_model_collectors.storage:
period: 120
- job:
name: watcher-prometheus-integration
parent: watcher-sg-core-tempest-base

View File

@@ -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

View File

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

View File

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

View File

@@ -12,7 +12,7 @@ Here are some examples of ``Goals``:
- minimize the energy consumption
- minimize the number of compute nodes (consolidation)
- balance the workload among compute nodes
- minimize the license cost (some software have a licensing model which is
- minimize the license cost (some softwares have a licensing model which is
based on the number of sockets or cores where the software is deployed)
- find the most appropriate moment for a planned maintenance on a
given group of host (which may be an entire availability zone):
@@ -123,4 +123,4 @@ Response
**Example JSON representation of a Goal:**
.. literalinclude:: samples/goal-show-response.json
:language: javascript
:language: javascript

2
babel.cfg Normal file
View File

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

View File

@@ -1,3 +1,5 @@
#!/bin/bash
#
# lib/watcher
# Functions to control the configuration and operation of the watcher services
@@ -36,6 +38,7 @@ GITBRANCH["python-watcherclient"]=${WATCHERCLIENT_BRANCH:-master}
GITDIR["python-watcherclient"]=$DEST/python-watcherclient
WATCHER_STATE_PATH=${WATCHER_STATE_PATH:=$DATA_DIR/watcher}
WATCHER_AUTH_CACHE_DIR=${WATCHER_AUTH_CACHE_DIR:-/var/cache/watcher}
WATCHER_CONF_DIR=/etc/watcher
WATCHER_CONF=$WATCHER_CONF_DIR/watcher.conf
@@ -55,7 +58,11 @@ else
WATCHER_BIN_DIR=$(get_python_exec_prefix)
fi
WATCHER_UWSGI=watcher.wsgi.api:application
# There are 2 modes, which is "uwsgi" which runs with an apache
# proxy uwsgi in front of it, or "mod_wsgi", which runs in
# apache. mod_wsgi is deprecated, don't use it.
WATCHER_USE_WSGI_MODE=${WATCHER_USE_WSGI_MODE:-$WSGI_MODE}
WATCHER_UWSGI=$WATCHER_BIN_DIR/watcher-api-wsgi
WATCHER_UWSGI_CONF=$WATCHER_CONF_DIR/watcher-uwsgi.ini
if is_suse; then
@@ -69,7 +76,11 @@ WATCHER_SERVICE_PORT=${WATCHER_SERVICE_PORT:-9322}
WATCHER_SERVICE_PORT_INT=${WATCHER_SERVICE_PORT_INT:-19322}
WATCHER_SERVICE_PROTOCOL=${WATCHER_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
WATCHER_API_URL="$WATCHER_SERVICE_PROTOCOL://$WATCHER_SERVICE_HOST/infra-optim"
if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
WATCHER_API_URL="$WATCHER_SERVICE_PROTOCOL://$WATCHER_SERVICE_HOST/infra-optim"
else
WATCHER_API_URL="$WATCHER_SERVICE_PROTOCOL://$WATCHER_SERVICE_HOST:$WATCHER_SERVICE_PORT"
fi
# Entry Points
# ------------
@@ -92,8 +103,12 @@ function _cleanup_watcher_apache_wsgi {
# cleanup_watcher() - Remove residual data files, anything left over from previous
# runs that a clean run would need to clean up
function cleanup_watcher {
sudo rm -rf $WATCHER_STATE_PATH
remove_uwsgi_config "$WATCHER_UWSGI_CONF" "$WATCHER_UWSGI"
sudo rm -rf $WATCHER_STATE_PATH $WATCHER_AUTH_CACHE_DIR
if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
remove_uwsgi_config "$WATCHER_UWSGI_CONF" "$WATCHER_UWSGI"
else
_cleanup_watcher_apache_wsgi
fi
}
# configure_watcher() - Set config files, create data dirs, etc
@@ -142,6 +157,31 @@ function create_watcher_accounts {
"$WATCHER_API_URL"
}
# _config_watcher_apache_wsgi() - Set WSGI config files of watcher
function _config_watcher_apache_wsgi {
local watcher_apache_conf
if [[ "$WATCHER_USE_WSGI_MODE" == "mod_wsgi" ]]; then
local service_port=$WATCHER_SERVICE_PORT
if is_service_enabled tls-proxy; then
service_port=$WATCHER_SERVICE_PORT_INT
service_protocol="http"
fi
sudo mkdir -p $WATCHER_WSGI_DIR
sudo cp $WATCHER_DIR/watcher/api/app.wsgi $WATCHER_WSGI_DIR/app.wsgi
watcher_apache_conf=$(apache_site_config_for watcher-api)
sudo cp $WATCHER_DEVSTACK_FILES_DIR/apache-watcher-api.template $watcher_apache_conf
sudo sed -e "
s|%WATCHER_SERVICE_PORT%|$service_port|g;
s|%WATCHER_WSGI_DIR%|$WATCHER_WSGI_DIR|g;
s|%USER%|$STACK_USER|g;
s|%APIWORKERS%|$API_WORKERS|g;
s|%APACHE_NAME%|$APACHE_NAME|g;
" -i $watcher_apache_conf
enable_apache_site watcher-api
fi
}
# create_watcher_conf() - Create a new watcher.conf file
function create_watcher_conf {
# (Re)create ``watcher.conf``
@@ -159,14 +199,19 @@ function create_watcher_conf {
iniset $WATCHER_CONF api host "$(ipv6_unquote $WATCHER_SERVICE_HOST)"
iniset $WATCHER_CONF api port "$WATCHER_SERVICE_PORT_INT"
# iniset $WATCHER_CONF api enable_ssl_api "True"
else
if [[ "$WATCHER_USE_WSGI_MODE" == "mod_wsgi" ]]; then
iniset $WATCHER_CONF api host "$(ipv6_unquote $WATCHER_SERVICE_HOST)"
iniset $WATCHER_CONF api port "$WATCHER_SERVICE_PORT"
fi
fi
iniset $WATCHER_CONF oslo_policy policy_file $WATCHER_POLICY_YAML
iniset $WATCHER_CONF oslo_messaging_notifications driver "messagingv2"
configure_keystone_authtoken_middleware $WATCHER_CONF watcher
configure_keystone_authtoken_middleware $WATCHER_CONF watcher "watcher_clients_auth"
configure_auth_token_middleware $WATCHER_CONF watcher $WATCHER_AUTH_CACHE_DIR
configure_auth_token_middleware $WATCHER_CONF watcher $WATCHER_AUTH_CACHE_DIR "watcher_clients_auth"
if is_fedora || is_suse; then
# watcher defaults to /usr/local/bin, but fedora and suse pip like to
@@ -186,8 +231,12 @@ function create_watcher_conf {
# Format logging
setup_logging $WATCHER_CONF
write_uwsgi_config "$WATCHER_UWSGI_CONF" "$WATCHER_UWSGI" "/infra-optim" "" "watcher-api"
#config apache files
if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
write_uwsgi_config "$WATCHER_UWSGI_CONF" "$WATCHER_UWSGI" "/infra-optim"
else
_config_watcher_apache_wsgi
fi
# Register SSL certificates if provided
if is_ssl_enabled_service watcher; then
ensure_certificates WATCHER
@@ -199,6 +248,13 @@ function create_watcher_conf {
fi
}
# create_watcher_cache_dir() - Part of the init_watcher() process
function create_watcher_cache_dir {
# Create cache dir
sudo install -d -o $STACK_USER $WATCHER_AUTH_CACHE_DIR
rm -rf $WATCHER_AUTH_CACHE_DIR/*
}
# init_watcher() - Initialize databases, etc.
function init_watcher {
# clean up from previous (possibly aborted) runs
@@ -210,6 +266,7 @@ function init_watcher {
# Create watcher schema
$WATCHER_BIN_DIR/watcher-db-manage --config-file $WATCHER_CONF upgrade
fi
create_watcher_cache_dir
}
# install_watcherclient() - Collect source and prepare
@@ -218,15 +275,15 @@ function install_watcherclient {
git_clone_by_name "python-watcherclient"
setup_dev_lib "python-watcherclient"
fi
if [[ "$GLOBAL_VENV" == "True" ]]; then
sudo ln -sf /opt/stack/data/venv/bin/watcher /usr/local/bin
fi
}
# install_watcher() - Collect source and prepare
function install_watcher {
git_clone $WATCHER_REPO $WATCHER_DIR $WATCHER_BRANCH
setup_develop $WATCHER_DIR
if [[ "$WATCHER_USE_WSGI_MODE" == "mod_wsgi" ]]; then
install_apache_wsgi
fi
}
# start_watcher_api() - Start the API process ahead of other things
@@ -240,10 +297,19 @@ function start_watcher_api {
service_port=$WATCHER_SERVICE_PORT_INT
service_protocol="http"
fi
run_process "watcher-api" "$(which uwsgi) --procname-prefix watcher-api --ini $WATCHER_UWSGI_CONF"
watcher_url=$service_protocol://$SERVICE_HOST/infra-optim
# TODO(sean-k-mooney): we should probably check that we can hit
# the microversion endpoint and get a valid response.
if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
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
enable_apache_site watcher-api
restart_apache_server
# Start proxies if enabled
if is_service_enabled tls-proxy; then
start_tls_proxy watcher '*' $WATCHER_SERVICE_PORT $WATCHER_SERVICE_HOST $WATCHER_SERVICE_PORT_INT
fi
fi
echo "Waiting for watcher-api to start..."
if ! wait_for_service $SERVICE_TIMEOUT $watcher_url; then
die $LINENO "watcher-api did not start"
@@ -261,25 +327,17 @@ function start_watcher {
# stop_watcher() - Stop running processes (non-screen)
function stop_watcher {
stop_process watcher-api
if [[ "$WATCHER_USE_WSGI_MODE" == "uwsgi" ]]; then
stop_process watcher-api
else
disable_apache_site watcher-api
restart_apache_server
fi
for serv in watcher-decision-engine watcher-applier; do
stop_process $serv
done
}
# configure_tempest_for_watcher() - Configure Tempest for watcher
function configure_tempest_for_watcher {
# Set default microversion for watcher-tempest-plugin
# Please make sure to update this when the microversion is updated, otherwise
# new tests may be skipped.
TEMPEST_WATCHER_MIN_MICROVERSION=${TEMPEST_WATCHER_MIN_MICROVERSION:-"1.0"}
TEMPEST_WATCHER_MAX_MICROVERSION=${TEMPEST_WATCHER_MAX_MICROVERSION:-"1.4"}
# Set microversion options in tempest.conf
iniset $TEMPEST_CONFIG optimize min_microversion $TEMPEST_WATCHER_MIN_MICROVERSION
iniset $TEMPEST_CONFIG optimize max_microversion $TEMPEST_WATCHER_MAX_MICROVERSION
}
# Restore xtrace
$_XTRACE_WATCHER

View File

@@ -1,3 +1,5 @@
#!/bin/bash
#
# plugin.sh - DevStack plugin script to install watcher
# Save trace setting
@@ -36,9 +38,6 @@ if is_service_enabled watcher-api watcher-decision-engine watcher-applier; then
# Start the watcher components
echo_summary "Starting watcher"
start_watcher
elif [[ "$1" == "stack" && "$2" == "test-config" ]]; then
echo_summary "Configuring tempest for watcher"
configure_tempest_for_watcher
fi
if [[ "$1" == "unstack" ]]; then

View File

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

View File

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

View File

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

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

View File

@@ -1,10 +1,10 @@
sphinx>=2.1.1 # BSD
sphinxcontrib-svg2pdfconverter>=0.1.0 # BSD
# 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>=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>=2.7.0 # Apache-2.0
sphinxcontrib-apidoc>=0.2.0 # BSD
# openstack
os-api-ref>=1.4.0 # Apache-2.0
openstackdocstheme>=2.2.1 # Apache-2.0
# releasenotes
reno>=3.1.0 # Apache-2.0

View File

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

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

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

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

@@ -14,6 +14,7 @@
import os
import sys
from watcher import version as watcher_version
from watcher import objects
objects.register_all()
@@ -56,8 +57,18 @@ source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
project = 'Watcher'
copyright = 'OpenStack Foundation'
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 --------------------------------------------
@@ -91,14 +102,14 @@ pygments_style = 'native'
# List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual'
man_pages = [
('man/watcher-api', 'watcher-api', 'Watcher API Server',
['OpenStack'], 1),
('man/watcher-applier', 'watcher-applier', 'Watcher Applier',
['OpenStack'], 1),
('man/watcher-api', 'watcher-api', u'Watcher API Server',
[u'OpenStack'], 1),
('man/watcher-applier', 'watcher-applier', u'Watcher Applier',
[u'OpenStack'], 1),
('man/watcher-db-manage', 'watcher-db-manage',
'Watcher Db Management Utility', ['OpenStack'], 1),
u'Watcher Db Management Utility', [u'OpenStack'], 1),
('man/watcher-decision-engine', 'watcher-decision-engine',
'Watcher Decision Engine', ['OpenStack'], 1),
u'Watcher Decision Engine', [u'OpenStack'], 1),
]
# -- Options for HTML 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 = ''
#openstackdocstheme options
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,8 +138,8 @@ openstackdocs_bug_tag = ''
latex_documents = [
('index',
'doc-watcher.tex',
'Watcher Documentation',
'OpenStack Foundation', 'manual'),
u'%s Documentation' % project,
u'OpenStack Foundation', 'manual'),
]
# If false, no module index is generated.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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,9 +0,0 @@
---
- hosts: all
tasks:
- name: Generate prometheus.yml config file
delegate_to: controller
template:
src: "templates/prometheus.yml.j2"
dest: "/home/zuul/prometheus.yml"
mode: "0644"

View File

@@ -0,0 +1,15 @@
- hosts: primary
tasks:
- name: Copy files from {{ ansible_user_dir }}/workspace/ on node
synchronize:
src: '{{ ansible_user_dir }}/workspace/'
dest: '{{ zuul.executor.log_root }}'
mode: pull
copy_links: true
verify_host: true
rsync_opts:
- --include=/logs/**
- --include=*/
- --exclude=*
- --prune-empty-dirs

View File

@@ -0,0 +1,60 @@
- hosts: all
name: legacy-grenade-dsvm-watcher
tasks:
- name: Ensure legacy workspace directory
file:
path: '{{ ansible_user_dir }}/workspace'
state: directory
- shell:
cmd: |
set -e
set -x
cat > clonemap.yaml << EOF
clonemap:
- name: openstack/devstack-gate
dest: devstack-gate
EOF
/usr/zuul-env/bin/zuul-cloner -m clonemap.yaml --cache-dir /opt/git \
https://opendev.org \
openstack/devstack-gate
executable: /bin/bash
chdir: '{{ ansible_user_dir }}/workspace'
environment: '{{ zuul | zuul_legacy_vars }}'
- shell:
cmd: |
set -e
set -x
export PYTHONUNBUFFERED=true
export PROJECTS="openstack/grenade $PROJECTS"
export PROJECTS="openstack/watcher $PROJECTS"
export PROJECTS="openstack/watcher-tempest-plugin $PROJECTS"
export PROJECTS="openstack/python-watcherclient $PROJECTS"
export DEVSTACK_PROJECT_FROM_GIT="python-watcherclient $DEVSTACK_PROJECT_FROM_GIT"
export GRENADE_PLUGINRC="enable_grenade_plugin watcher https://opendev.org/openstack/watcher"
export DEVSTACK_LOCAL_CONFIG+=$'\n'"export TEMPEST_PLUGINS='/opt/stack/new/watcher-tempest-plugin'"
export DEVSTACK_GATE_TEMPEST_NOTESTS=1
export DEVSTACK_GATE_GRENADE=pullup
export DEVSTACK_GATE_USE_PYTHON3=True
export BRANCH_OVERRIDE=default
if [ "$BRANCH_OVERRIDE" != "default" ] ; then
export OVERRIDE_ZUUL_BRANCH=$BRANCH_OVERRIDE
fi
# Add configuration values for enabling security features in local.conf
function pre_test_hook {
if [ -f /opt/stack/old/watcher-tempest-plugin/tools/pre_test_hook.sh ] ; then
. /opt/stack/old/watcher-tempest-plugin/tools/pre_test_hook.sh
fi
}
export -f pre_test_hook
cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh
./safe-devstack-vm-gate-wrap.sh
executable: /bin/bash
chdir: '{{ ansible_user_dir }}/workspace'
environment: '{{ zuul | zuul_legacy_vars }}'

View File

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

View File

@@ -1,3 +0,0 @@
[build-system]
requires = ["pbr>=6.0.0", "setuptools>=64.0.0"]
build-backend = "pbr.build"

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,30 +0,0 @@
---
features:
- |
A new module, ``watcher.wsgi``, has been added as a place to gather WSGI
``application`` objects. This is intended to ease deployment by providing
a consistent location for these objects. For example, if using uWSGI then
instead of:
.. code-block:: ini
[uwsgi]
wsgi-file = /bin/watcher-api-wsgi
You can now use:
.. code-block:: ini
[uwsgi]
module = watcher.wsgi.api:application
This also simplifies deployment with other WSGI servers that expect module
paths such as gunicorn.
deprecations:
- |
The watcher-api-wsgi console script is deprecated for removal
in a future release. This artifact is generated using a setup-tools
extension that is provide by PBR which is also deprecated.
due to the changes in python packaging this custom extensions
is planned to be removed form all OpenStack projects in a future
PBR release in favor of module based wsgi applications entry points.

View File

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

View File

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

View File

@@ -1,8 +0,0 @@
---
fixes:
- |
When using prometheus datasource and more that one target has the same value
for the ``fqdn_label``, the driver used the wrong instance label to query for host
metrics. The ``instance`` label is no longer used in the queries but the ``fqdn_label``
which identifies all the metrics for a specific compute node.
see Bug 2103451: https://bugs.launchpad.net/watcher/+bug/2103451 for more info.

View File

@@ -1,10 +0,0 @@
---
fixes:
- |
Previously, when users attempted to create a new audit without providing
a name and a goal or an audit template, the API returned error 500 and an
incorrect error message was displayed.
Now, Watcher displays a helpful message and returns HTTP error 400.
For more info see: https://bugs.launchpad.net/watcher/+bug/2110947

View File

@@ -1,47 +0,0 @@
---
security:
- |
Watchers no longer forges requests on behalf of a tenant when
swapping volumes. Prior to this release watcher had 2 implementations
of moving a volume, it could use cinders volume migrate api or its own
internal implementation that directly calls nova volume attachment update
api. The former is safe and the recommend way to move volumes between
cinder storage backend the internal implementation was insecure, fragile
due to a lack of error handling and capable of deleting user data.
Insecure: the internal volume migration operation created a new keystone
user with a weak name and password and added it to the tenants project
with the admin role. It then used that user to forge request on behalf
of the tenant with admin right to swap the volume. if the applier was
restarted during the execution of this operation it would never be cleaned
up.
Fragile: the error handling was minimal, the swap volume api is async
so watcher has to poll for completion, there was no support to resume
that if interrupted of the time out was exceeded.
Data-loss: while the internal polling logic returned success or failure
watcher did not check the result, once the function returned it
unconditionally deleted the source volume. For larger volumes this
could result in irretrievable data loss.
Finally if a volume was swapped using the internal workflow it put
the nova instance in an out of sync state. If the VM was live migrated
after the swap volume completed successfully prior to a hard reboot
then the migration would fail or succeed and break tenant isolation.
see: https://bugs.launchpad.net/nova/+bug/2112187 for details.
fixes:
- |
All code related to creating keystone user and granting roles has been
removed. The internal swap volume implementation has been removed and
replaced by cinders volume migrate api. Note as part of this change
Watcher will no longer attempt volume migrations or retypes if the
instance is in the `Verify Resize` task state. This resolves several
issues related to volume migration in the zone migration and
Storage capacity balance strategies. While efforts have been made
to maintain backward compatibility these changes are required to
address a security weakness in watcher's prior approach.
see: https://bugs.launchpad.net/nova/+bug/2112187 for more context.

View File

@@ -1,14 +0,0 @@
---
fixes:
- |
When running an audit with the `workload_stabilization` strategy with
`instance_ram_usage` metric in a deployment with prometheus datasource,
the host metric for the ram usage was wrongly reported with the incorrect
unit which lead to incorrect standard deviation and action plans due to the
application of the wrong scale factor in the algorithm.
The host ram usage metric is now properly reported in KB when using a
prometheus datasource and the strategy `workload_stabilization` calculates
the standard deviation properly.
For more details: https://launchpad.net/bugs/2113776

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

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

View File

@@ -1,10 +0,0 @@
---
fixes:
- |
Host maintenance strategy should migrate servers based on backup node if specified
or rely on nova scheduler. It was enabling disabled hosts with watcher_disabled
reason and migrating servers to those nodes. It can impact customer workload. Compute
nodes were disabled for a reason.
Host maintenance strategy is fixed now to support migrating servers only on backup
node or rely on nova scheduler if no backup node is provided.

View File

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

View File

@@ -1,13 +0,0 @@
---
fixes:
- |
Previously, if an action failed in an action plan, the state of the
action plan was reported as SUCCEEDED if the execution of the action has
finished regardless of the outcome.
Watcher will now reflect the actual state of all the actions in the plan
after the execution has finished. If any action has status FAILED, it
will set the state of the action plan as FAILED. This is the expected
behavior according to Watcher documentation.
For more info see: https://bugs.launchpad.net/watcher/+bug/2106407

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +0,0 @@
---
fixes:
- |
`Bug #2110538 <https://bugs.launchpad.net/watcher/+bug/2110538>`_:
Corrected the HTTP error code returned when watcher users try to create
audits with invalid parameters. The API now correctly returns a 400 Bad
Request error.

View File

@@ -1,4 +1,4 @@
---
features:
- Check the creation time of the action plan,
- Check the creation time of the action plan,
and set its state to SUPERSEDED if it has expired.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

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: unmaintained/victoria

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,49 +1,50 @@
# Requirements lower bounds listed here are our best effort to keep them up to
# date but we do not test them so no guarantee of having them all correct. If
# you find any incorrect lower bounds, let us know or propose a fix.
# 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
eventlet>=0.27.0 # MIT
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>=14.1.0 # Apache-2.0
oslo.policy>=4.5.0 # Apache-2.0
oslo.messaging>=8.1.2 # 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.utils>=7.0.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
python-glanceclient>=2.9.1 # Apache-2.0
python-keystoneclient>=3.15.0 # Apache-2.0
python-monascaclient>=1.12.0 # Apache-2.0
python-neutronclient>=6.7.0 # Apache-2.0
python-novaclient>=14.1.0 # Apache-2.0
python-observabilityclient>=0.3.0 # Apache-2.0
python-openstackclient>=3.14.0 # Apache-2.0
python-ironicclient>=2.5.0 # Apache-2.0
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

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

@@ -1,7 +1,16 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
coverage>=4.5.1 # Apache-2.0
doc8>=0.8.0 # Apache-2.0
freezegun>=0.3.10 # Apache-2.0
hacking>=3.0,<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
testtools>=2.3.0 # MIT
stestr>=2.0.0 # Apache-2.0
WebTest>=2.0.27 # MIT
os-api-ref>=1.4.0 # Apache-2.0
bandit>=1.6.0 # Apache-2.0

107
tox.ini
View File

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

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

View File

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

View File

@@ -32,10 +32,6 @@ states, visit :ref:`the Audit State machine <audit_state_machine>`.
import datetime
from dateutil import tz
from http import HTTPStatus
import jsonschema
from oslo_log import log
from oslo_utils import timeutils
import pecan
from pecan import rest
import wsme
@@ -43,6 +39,8 @@ from wsme import types as wtypes
from wsme import utils as wutils
import wsmeext.pecan as wsme_pecan
from oslo_log import log
from watcher._i18n import _
from watcher.api.controllers import base
from watcher.api.controllers import link
@@ -115,11 +113,6 @@ class AuditPostType(wtypes.Base):
if self.audit_type not in audit_type_values:
raise exception.AuditTypeNotFound(audit_type=self.audit_type)
if not self.audit_template_uuid and not self.goal:
message = _(
'A valid goal or audit_template_id must be provided')
raise exception.Invalid(message)
if (self.audit_type == objects.audit.AuditType.ONESHOT.value and
self.interval not in (wtypes.Unset, None)):
raise exception.AuditIntervalNotAllowed(audit_type=self.audit_type)
@@ -177,16 +170,16 @@ class AuditPostType(wtypes.Base):
strategy = _get_object_by_value(context, objects.Strategy,
self.strategy)
self.name = "%s-%s" % (strategy.name,
timeutils.utcnow().isoformat())
datetime.datetime.utcnow().isoformat())
elif self.audit_template_uuid:
audit_template = objects.AuditTemplate.get(
context, self.audit_template_uuid)
self.name = "%s-%s" % (audit_template.name,
timeutils.utcnow().isoformat())
datetime.datetime.utcnow().isoformat())
else:
goal = _get_object_by_value(context, objects.Goal, self.goal)
self.name = "%s-%s" % (goal.name,
timeutils.utcnow().isoformat())
datetime.datetime.utcnow().isoformat())
# No more than 63 characters
if len(self.name) > 63:
LOG.warning("Audit: %s length exceeds 63 characters",
@@ -430,15 +423,15 @@ class Audit(base.APIBase):
name='My Audit',
audit_type='ONESHOT',
state='PENDING',
created_at=timeutils.utcnow(),
created_at=datetime.datetime.utcnow(),
deleted_at=None,
updated_at=timeutils.utcnow(),
updated_at=datetime.datetime.utcnow(),
interval='7200',
scope=[],
auto_trigger=False,
next_run_time=timeutils.utcnow(),
start_time=timeutils.utcnow(),
end_time=timeutils.utcnow())
next_run_time=datetime.datetime.utcnow(),
start_time=datetime.datetime.utcnow(),
end_time=datetime.datetime.utcnow())
sample.goal_id = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae'
sample.strategy_id = '7ae81bb3-dec3-4289-8d6c-da80bd8001ff'
@@ -474,7 +467,6 @@ class AuditCollection(collection.Collection):
class AuditsController(rest.RestController):
"""REST controller for Audits."""
def __init__(self):
super(AuditsController, self).__init__()
self.dc_client = rpcapi.DecisionEngineAPI()
@@ -576,7 +568,7 @@ class AuditsController(rest.RestController):
context = pecan.request.context
policy.enforce(context, 'audit:detail',
action='audit:detail')
# NOTE(lucasagomes): /detail should only work against collections
# NOTE(lucasagomes): /detail should only work agaist collections
parent = pecan.request.path.split('/')[:-1][-1]
if parent != "audits":
raise exception.HTTPNotFound
@@ -603,8 +595,7 @@ class AuditsController(rest.RestController):
return Audit.convert_with_links(rpc_audit)
@wsme_pecan.wsexpose(Audit, body=AuditPostType,
status_code=HTTPStatus.CREATED)
@wsme_pecan.wsexpose(Audit, body=AuditPostType, status_code=201)
def post(self, audit_p):
"""Create a new audit.
@@ -618,6 +609,11 @@ class AuditsController(rest.RestController):
if self.from_audits:
raise exception.OperationNotPermitted
if not audit._goal_uuid:
raise exception.Invalid(
message=_('A valid goal_id or audit_template_id '
'must be provided'))
strategy_uuid = audit.strategy_uuid
no_schema = True
if strategy_uuid is not None:
@@ -628,12 +624,8 @@ class AuditsController(rest.RestController):
if schema:
# validate input parameter with default value feedback
no_schema = False
try:
utils.StrictDefaultValidatingDraft4Validator(
schema).validate(audit.parameters)
except jsonschema.exceptions.ValidationError as e:
raise exception.Invalid(
_('Invalid parameters for strategy: %s') % e)
utils.StrictDefaultValidatingDraft4Validator(schema).validate(
audit.parameters)
if no_schema and audit.parameters:
raise exception.Invalid(_('Specify parameters but no predefined '
@@ -725,7 +717,7 @@ class AuditsController(rest.RestController):
audit_to_update.save()
return Audit.convert_with_links(audit_to_update)
@wsme_pecan.wsexpose(None, wtypes.text, status_code=HTTPStatus.NO_CONTENT)
@wsme_pecan.wsexpose(None, wtypes.text, status_code=204)
def delete(self, audit):
"""Delete an audit.

View File

@@ -43,8 +43,8 @@ will be launched automatically or will need a manual confirmation from the
:ref:`Administrator <administrator_definition>`.
"""
from http import HTTPStatus
from oslo_utils import timeutils
import datetime
import pecan
from pecan import rest
import wsme
@@ -138,9 +138,6 @@ class AuditTemplatePostType(wtypes.Base):
raise exception.InvalidGoal(goal=audit_template.goal)
if audit_template.scope:
keys = [list(s)[0] for s in audit_template.scope]
if keys[0] not in ('compute', 'storage'):
audit_template.scope = [dict(compute=audit_template.scope)]
common_utils.Draft4Validator(
AuditTemplatePostType._build_schema()
).validate(audit_template.scope)
@@ -161,23 +158,18 @@ class AuditTemplatePostType(wtypes.Base):
"included and excluded together"))
if audit_template.strategy:
try:
if (common_utils.is_uuid_like(audit_template.strategy) or
common_utils.is_int_like(audit_template.strategy)):
strategy = objects.Strategy.get(
AuditTemplatePostType._ctx, audit_template.strategy)
else:
strategy = objects.Strategy.get_by_name(
AuditTemplatePostType._ctx, audit_template.strategy)
except Exception:
available_strategies = objects.Strategy.list(
AuditTemplatePostType._ctx)
available_strategies_map = {
s.uuid: s for s in available_strategies}
if audit_template.strategy not in available_strategies_map:
raise exception.InvalidStrategy(
strategy=audit_template.strategy)
strategy = available_strategies_map[audit_template.strategy]
# Check that the strategy we indicate is actually related to the
# specified goal
if strategy.goal_id != goal.id:
available_strategies = objects.Strategy.list(
AuditTemplatePostType._ctx)
choices = ["'%s' (%s)" % (s.uuid, s.name)
for s in available_strategies]
raise exception.InvalidStrategy(
@@ -439,9 +431,9 @@ class AuditTemplate(base.APIBase):
description='Description of my audit template',
goal_uuid='83e44733-b640-40e2-8d8a-7dd3be7134e6',
strategy_uuid='367d826e-b6a4-4b70-bc44-c3f6fe1c9986',
created_at=timeutils.utcnow(),
created_at=datetime.datetime.utcnow(),
deleted_at=None,
updated_at=timeutils.utcnow(),
updated_at=datetime.datetime.utcnow(),
scope=[],)
return cls._convert_with_links(sample, 'http://localhost:9322', expand)
@@ -475,7 +467,6 @@ class AuditTemplateCollection(collection.Collection):
class AuditTemplatesController(rest.RestController):
"""REST controller for AuditTemplates."""
def __init__(self):
super(AuditTemplatesController, self).__init__()
@@ -576,7 +567,7 @@ class AuditTemplatesController(rest.RestController):
policy.enforce(context, 'audit_template:detail',
action='audit_template:detail')
# NOTE(lucasagomes): /detail should only work against collections
# NOTE(lucasagomes): /detail should only work agaist collections
parent = pecan.request.path.split('/')[:-1][-1]
if parent != "audit_templates":
raise exception.HTTPNotFound
@@ -619,7 +610,7 @@ class AuditTemplatesController(rest.RestController):
@wsme.validate(types.uuid, AuditTemplatePostType)
@wsme_pecan.wsexpose(AuditTemplate, body=AuditTemplatePostType,
status_code=HTTPStatus.CREATED)
status_code=201)
def post(self, audit_template_postdata):
"""Create a new audit template.
@@ -695,7 +686,7 @@ class AuditTemplatesController(rest.RestController):
audit_template_to_update.save()
return AuditTemplate.convert_with_links(audit_template_to_update)
@wsme_pecan.wsexpose(None, wtypes.text, status_code=HTTPStatus.NO_CONTENT)
@wsme_pecan.wsexpose(None, wtypes.text, status_code=204)
def delete(self, audit_template):
"""Delete a audit template.

View File

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

View File

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

View File

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

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

View File

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

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
@@ -161,7 +162,6 @@ class MultiType(wtypes.UserType):
:param types: Variable-length list of types.
"""
def __init__(self, *types):
self.types = types

View File

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

View File

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

View File

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

View File

@@ -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

@@ -56,30 +56,12 @@ class DefaultActionPlanHandler(base.BaseActionPlanHandler):
applier = default.DefaultApplier(self.ctx, self.service)
applier.execute(self.action_plan_uuid)
# If any action has failed the action plan should be FAILED
# Define default values for successful execution
ap_state = objects.action_plan.State.SUCCEEDED
notification_kwargs = {
'phase': fields.NotificationPhase.END
}
failed_filter = {'action_plan_uuid': self.action_plan_uuid,
'state': objects.action.State.FAILED}
failed_actions = objects.Action.list(
self.ctx, filters=failed_filter, eager=True)
if failed_actions:
ap_state = objects.action_plan.State.FAILED
notification_kwargs = {
'phase': fields.NotificationPhase.ERROR,
'priority': fields.NotificationPriority.ERROR
}
action_plan.state = ap_state
action_plan.state = objects.action_plan.State.SUCCEEDED
action_plan.save()
notifications.action_plan.send_action_notification(
self.ctx, action_plan,
action=fields.NotificationAction.EXECUTION,
**notification_kwargs)
phase=fields.NotificationPhase.END)
except exception.ActionPlanCancelled as e:
LOG.exception(e)

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

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