Compare commits
261 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7a44739a6 | ||
|
|
58d86de064 | ||
|
|
8d84da307b | ||
|
|
01e865edbf | ||
|
|
b4b3856f14 | ||
|
|
67d065e02a | ||
|
|
891a351a04 | ||
|
|
f47fd9ac5e | ||
|
|
7b766680b0 | ||
|
|
75a025d2d2 | ||
|
|
590bd43a1d | ||
|
|
d2e42a835b | ||
|
|
a34e55e47a | ||
|
|
a62acbf2ab | ||
|
|
35074edaf7 | ||
|
|
dd4aac4092 | ||
|
|
bd8151e581 | ||
|
|
8585e49359 | ||
|
|
5d3af47b7d | ||
|
|
1001525664 | ||
|
|
a33f40ec21 | ||
|
|
d2a8454043 | ||
|
|
9bb1e653d8 | ||
|
|
bb536ee40d | ||
|
|
a0bf1b7d70 | ||
|
|
40f6eea637 | ||
|
|
6c5a3910a7 | ||
|
|
a4fac69d85 | ||
|
|
21994297cf | ||
|
|
8a818c9071 | ||
|
|
041fcb4ca0 | ||
|
|
a8d765bb28 | ||
|
|
2b152bf17c | ||
|
|
08e585d405 | ||
|
|
38e4255ec0 | ||
|
|
a167044cde | ||
|
|
1366f79b63 | ||
|
|
f55b9b127e | ||
|
|
1b7b467151 | ||
|
|
f40fcdc573 | ||
|
|
2d98d5e743 | ||
|
|
877230569a | ||
|
|
f842c5f601 | ||
|
|
0a899a2dc2 | ||
|
|
426232e288 | ||
|
|
778d4c6fe4 | ||
|
|
f852467d6a | ||
|
|
dcf64ed1f4 | ||
|
|
03f75202c8 | ||
|
|
0173a713c1 | ||
|
|
216f3bab29 | ||
|
|
077b806bf6 | ||
|
|
d892153b58 | ||
|
|
2efe211f36 | ||
|
|
f55ea7824e | ||
|
|
e5eb4f51be | ||
|
|
f637a368d7 | ||
|
|
2e8fb5a821 | ||
|
|
dbff4326e3 | ||
|
|
13a99b4c09 | ||
|
|
a8994bc227 | ||
|
|
c6845c0136 | ||
|
|
02c8e7d89c | ||
|
|
0db41f1862 | ||
|
|
b02cf3bea5 | ||
|
|
4eeaa0ab6b | ||
|
|
84d6d4aadd | ||
|
|
4511b36496 | ||
|
|
9a5c017a9a | ||
|
|
4690e402ce | ||
|
|
442e569686 | ||
|
|
5d948e8aa1 | ||
|
|
f83a92fc70 | ||
|
|
a06c462050 | ||
|
|
74e9349c1f | ||
|
|
7c048c761e | ||
|
|
4006b4af7a | ||
|
|
527423a5fa | ||
|
|
1d05444f67 | ||
|
|
6de94cca2d | ||
|
|
9b5d17b412 | ||
|
|
719b96f2a8 | ||
|
|
e9f83417eb | ||
|
|
a139cca260 | ||
|
|
c04d3cc5e0 | ||
|
|
e549e43e9e | ||
|
|
c1a2c79514 | ||
|
|
f79cad99cb | ||
|
|
8663c3a5c5 | ||
|
|
19d9b83665 | ||
|
|
af22899ebe | ||
|
|
fc33e181fc | ||
|
|
a3ee163480 | ||
|
|
334558f17c | ||
|
|
4642a92e78 | ||
|
|
69c53da298 | ||
|
|
49924e1915 | ||
|
|
d53abb7af5 | ||
|
|
4d3727eafb | ||
|
|
4a3c15185c | ||
|
|
2c6ab9a926 | ||
|
|
0750b93827 | ||
|
|
a2cb02a861 | ||
|
|
377889859d | ||
|
|
54f0758fc3 | ||
|
|
a644600a18 | ||
|
|
ca3d367ac7 | ||
|
|
cde60d2ead | ||
|
|
f106076d70 | ||
|
|
e75dbfd776 | ||
|
|
18aa50c58e | ||
|
|
2c2120526c | ||
|
|
9e505d3d36 | ||
|
|
54ce5f796f | ||
|
|
f605888e32 | ||
|
|
0b213a8734 | ||
|
|
38a3cbc84a | ||
|
|
eb038e4af0 | ||
|
|
b5eccceaed | ||
|
|
f7b655b712 | ||
|
|
1386ce690f | ||
|
|
38e4b48d70 | ||
|
|
56ca542bef | ||
|
|
dafe2ad04b | ||
|
|
6044b04d33 | ||
|
|
6d81ac15b8 | ||
|
|
db077e872e | ||
|
|
fd55d28d42 | ||
|
|
51bf7fedb6 | ||
|
|
bf0fd48659 | ||
|
|
ba98c88303 | ||
|
|
77b406748c | ||
|
|
d21198da8f | ||
|
|
12a7b7171b | ||
|
|
d45ab13619 | ||
|
|
e2d2fc6227 | ||
|
|
3c564ee3d8 | ||
|
|
f9ce21a9a9 | ||
|
|
03a2c0142a | ||
|
|
5afcf7a7f4 | ||
|
|
63faf4695e | ||
|
|
97800d1553 | ||
|
|
8f85169c15 | ||
|
|
68e4bc4d87 | ||
|
|
9e7f7f54f3 | ||
|
|
fceab5299b | ||
|
|
dddbb63633 | ||
|
|
b788dfab71 | ||
|
|
7824b41e12 | ||
|
|
86ded4d952 | ||
|
|
5d6e731c42 | ||
|
|
cba6713bdc | ||
|
|
24ab0469ec | ||
|
|
4d71bb112c | ||
|
|
fd374d1d30 | ||
|
|
25789c9c5a | ||
|
|
a9b3534e97 | ||
|
|
f80c0c732a | ||
|
|
0d83354c57 | ||
|
|
67d44eb118 | ||
|
|
8c1757f86d | ||
|
|
e55c73be0e | ||
|
|
04c9e0362e | ||
|
|
8ceb710b59 | ||
|
|
58711aaaec | ||
|
|
3ad5261d2a | ||
|
|
26c7726c00 | ||
|
|
5b2cdb53a8 | ||
|
|
4b5dce51dc | ||
|
|
b6a96e04aa | ||
|
|
62cb8a8d29 | ||
|
|
50e5e86c75 | ||
|
|
e3dd5c2a7e | ||
|
|
630c2cbb79 | ||
|
|
d49c6c16a6 | ||
|
|
e51e7e4317 | ||
|
|
244d28afa6 | ||
|
|
7ac1d0d048 | ||
|
|
65f9646eae | ||
|
|
52d701a56e | ||
|
|
ea1fd5967a | ||
|
|
547bf0529f | ||
|
|
659cbf3207 | ||
|
|
eb5a362287 | ||
|
|
198d827645 | ||
|
|
ecb0e218a9 | ||
|
|
4228647d15 | ||
|
|
4f1d758a40 | ||
|
|
b4433db20a | ||
|
|
e03f56e7c7 | ||
|
|
d925166a25 | ||
|
|
4a5d8cf709 | ||
|
|
e3c6db11c6 | ||
|
|
59c5adc8ad | ||
|
|
840d422b01 | ||
|
|
e9d8a2882f | ||
|
|
6e09cdb5ac | ||
|
|
edd3d219d5 | ||
|
|
d433d6b3c8 | ||
|
|
c5d4f9cb40 | ||
|
|
41f579d464 | ||
|
|
1a2fa9addf | ||
|
|
9e5ca76116 | ||
|
|
fa63b2a2b3 | ||
|
|
22cad5651e | ||
|
|
a912977336 | ||
|
|
2d7a375338 | ||
|
|
45b82e1898 | ||
|
|
926dbc8392 | ||
|
|
0e440d37ee | ||
|
|
66934f29d3 | ||
|
|
7039a9d247 | ||
|
|
bbbae0b105 | ||
|
|
1d08d2eea1 | ||
|
|
23442a4da6 | ||
|
|
ed88b436af | ||
|
|
a48a16596f | ||
|
|
8f4a856bd2 | ||
|
|
85a46ce4d4 | ||
|
|
35066dfe60 | ||
|
|
fc9eb6e995 | ||
|
|
aaf6fd7959 | ||
|
|
5e077f37ea | ||
|
|
2ec8bc10cd | ||
|
|
89cea83c85 | ||
|
|
2dd00a2037 | ||
|
|
59e13fd1f3 | ||
|
|
4235ef7c24 | ||
|
|
a015af1bd2 | ||
|
|
dad90b63fd | ||
|
|
c6e5f98008 | ||
|
|
1341c0ee02 | ||
|
|
6e99fcffc3 | ||
|
|
a57f54ab8f | ||
|
|
d1490e3fa7 | ||
|
|
1324baf9f5 | ||
|
|
0adc7d91e6 | ||
|
|
0d7ded0bb3 | ||
|
|
80dfbd6334 | ||
|
|
7d40b3d4c3 | ||
|
|
cedf70559e | ||
|
|
cc561c528f | ||
|
|
87b494d52a | ||
|
|
d0bca1f2ab | ||
|
|
068178f12a | ||
|
|
99e6c4aebb | ||
|
|
b446f8afd2 | ||
|
|
7783ebfb71 | ||
|
|
22cfc495f4 | ||
|
|
360b0119d6 | ||
|
|
48fc90d7b6 | ||
|
|
c5ff387ae9 | ||
|
|
1bc6b0e605 | ||
|
|
345083e090 | ||
|
|
1a17c4b7ac | ||
|
|
c4dfbd5855 | ||
|
|
1981f3964e | ||
|
|
d792e3cfae | ||
|
|
f66eb463ca | ||
|
|
6a323ed54f | ||
|
|
d252d47cc0 |
@@ -1,13 +1,13 @@
|
|||||||
If you would like to contribute to the development of OpenStack,
|
If you would like to contribute to the development of OpenStack,
|
||||||
you must follow the steps in this page:
|
you must follow the steps in this page:
|
||||||
|
|
||||||
http://docs.openstack.org/infra/manual/developers.html
|
https://docs.openstack.org/infra/manual/developers.html
|
||||||
|
|
||||||
Once those steps have been completed, changes to OpenStack
|
Once those steps have been completed, changes to OpenStack
|
||||||
should be submitted for review via the Gerrit tool, following
|
should be submitted for review via the Gerrit tool, following
|
||||||
the workflow documented at:
|
the workflow documented at:
|
||||||
|
|
||||||
http://docs.openstack.org/infra/manual/developers.html#development-workflow
|
https://docs.openstack.org/infra/manual/developers.html#development-workflow
|
||||||
|
|
||||||
Pull requests submitted through GitHub will be ignored.
|
Pull requests submitted through GitHub will be ignored.
|
||||||
|
|
||||||
|
|||||||
@@ -8,4 +8,4 @@
|
|||||||
watcher Style Commandments
|
watcher Style Commandments
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/
|
Read the OpenStack Style Commandments https://docs.openstack.org/developer/hacking/
|
||||||
|
|||||||
10
README.rst
10
README.rst
@@ -2,8 +2,8 @@
|
|||||||
Team and repository tags
|
Team and repository tags
|
||||||
========================
|
========================
|
||||||
|
|
||||||
.. image:: http://governance.openstack.org/badges/watcher.svg
|
.. image:: https://governance.openstack.org/badges/watcher.svg
|
||||||
:target: http://governance.openstack.org/reference/tags/index.html
|
:target: https://governance.openstack.org/reference/tags/index.html
|
||||||
|
|
||||||
.. Change things from this point on
|
.. Change things from this point on
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ operating costs, increased system performance via intelligent virtual machine
|
|||||||
migration, increased energy efficiency-and more!
|
migration, increased energy efficiency-and more!
|
||||||
|
|
||||||
* Free software: Apache license
|
* Free software: Apache license
|
||||||
* Wiki: http://wiki.openstack.org/wiki/Watcher
|
* Wiki: https://wiki.openstack.org/wiki/Watcher
|
||||||
* Source: https://github.com/openstack/watcher
|
* Source: https://github.com/openstack/watcher
|
||||||
* Bugs: http://bugs.launchpad.net/watcher
|
* Bugs: https://bugs.launchpad.net/watcher
|
||||||
* Documentation: http://docs.openstack.org/developer/watcher/
|
* Documentation: https://docs.openstack.org/developer/watcher/
|
||||||
|
|||||||
42
devstack/files/apache-watcher-api.template
Normal file
42
devstack/files/apache-watcher-api.template
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
# This is an example Apache2 configuration file for using the
|
||||||
|
# Watcher API through mod_wsgi. This version assumes you are
|
||||||
|
# running devstack to configure the software.
|
||||||
|
|
||||||
|
Listen %WATCHER_SERVICE_PORT%
|
||||||
|
|
||||||
|
<VirtualHost *:%WATCHER_SERVICE_PORT%>
|
||||||
|
WSGIDaemonProcess watcher-api user=%USER% processes=%APIWORKERS% threads=1 display-name=%{GROUP}
|
||||||
|
WSGIScriptAlias / %WATCHER_WSGI_DIR%/app.wsgi
|
||||||
|
WSGIApplicationGroup %{GLOBAL}
|
||||||
|
WSGIProcessGroup watcher-api
|
||||||
|
WSGIPassAuthorization On
|
||||||
|
|
||||||
|
ErrorLogFormat "%M"
|
||||||
|
ErrorLog /var/log/%APACHE_NAME%/watcher-api.log
|
||||||
|
CustomLog /var/log/%APACHE_NAME%/watcher-api-access.log combined
|
||||||
|
|
||||||
|
|
||||||
|
<Directory %WATCHER_WSGI_DIR%>
|
||||||
|
WSGIProcessGroup watcher-api
|
||||||
|
WSGIApplicationGroup %{GLOBAL}
|
||||||
|
<IfVersion >= 2.4>
|
||||||
|
Require all granted
|
||||||
|
</IfVersion>
|
||||||
|
<IfVersion < 2.4>
|
||||||
|
Order allow,deny
|
||||||
|
Allow from all
|
||||||
|
</IfVersion>
|
||||||
|
</Directory>
|
||||||
|
</VirtualHost>
|
||||||
@@ -44,6 +44,9 @@ WATCHER_CONF_DIR=/etc/watcher
|
|||||||
WATCHER_CONF=$WATCHER_CONF_DIR/watcher.conf
|
WATCHER_CONF=$WATCHER_CONF_DIR/watcher.conf
|
||||||
WATCHER_POLICY_JSON=$WATCHER_CONF_DIR/policy.json
|
WATCHER_POLICY_JSON=$WATCHER_CONF_DIR/policy.json
|
||||||
|
|
||||||
|
WATCHER_DEVSTACK_DIR=$WATCHER_DIR/devstack
|
||||||
|
WATCHER_DEVSTACK_FILES_DIR=$WATCHER_DEVSTACK_DIR/files
|
||||||
|
|
||||||
NOVA_CONF_DIR=/etc/nova
|
NOVA_CONF_DIR=/etc/nova
|
||||||
NOVA_CONF=$NOVA_CONF_DIR/nova.conf
|
NOVA_CONF=$NOVA_CONF_DIR/nova.conf
|
||||||
|
|
||||||
@@ -51,6 +54,13 @@ if is_ssl_enabled_service "watcher" || is_service_enabled tls-proxy; then
|
|||||||
WATCHER_SERVICE_PROTOCOL="https"
|
WATCHER_SERVICE_PROTOCOL="https"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
WATCHER_USE_MOD_WSGI=$(trueorfalse True WATCHER_USE_MOD_WSGI)
|
||||||
|
|
||||||
|
if is_suse; then
|
||||||
|
WATCHER_WSGI_DIR=${WATCHER_WSGI_DIR:-/srv/www/htdocs/watcher}
|
||||||
|
else
|
||||||
|
WATCHER_WSGI_DIR=${WATCHER_WSGI_DIR:-/var/www/watcher}
|
||||||
|
fi
|
||||||
# Public facing bits
|
# Public facing bits
|
||||||
WATCHER_SERVICE_HOST=${WATCHER_SERVICE_HOST:-$HOST_IP}
|
WATCHER_SERVICE_HOST=${WATCHER_SERVICE_HOST:-$HOST_IP}
|
||||||
WATCHER_SERVICE_PORT=${WATCHER_SERVICE_PORT:-9322}
|
WATCHER_SERVICE_PORT=${WATCHER_SERVICE_PORT:-9322}
|
||||||
@@ -74,10 +84,21 @@ function is_watcher_enabled {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#_cleanup_watcher_apache_wsgi - Remove wsgi files,
|
||||||
|
#disable and remove apache vhost file
|
||||||
|
function _cleanup_watcher_apache_wsgi {
|
||||||
|
sudo rm -rf $WATCHER_WSGI_DIR
|
||||||
|
sudo rm -f $(apache_site_config_for watcher-api)
|
||||||
|
restart_apache_server
|
||||||
|
}
|
||||||
|
|
||||||
# cleanup_watcher() - Remove residual data files, anything left over from previous
|
# cleanup_watcher() - Remove residual data files, anything left over from previous
|
||||||
# runs that a clean run would need to clean up
|
# runs that a clean run would need to clean up
|
||||||
function cleanup_watcher {
|
function cleanup_watcher {
|
||||||
sudo rm -rf $WATCHER_STATE_PATH $WATCHER_AUTH_CACHE_DIR
|
sudo rm -rf $WATCHER_STATE_PATH $WATCHER_AUTH_CACHE_DIR
|
||||||
|
if [[ "$WATCHER_USE_MOD_WSGI" == "True" ]]; then
|
||||||
|
_cleanup_watcher_apache_wsgi
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# configure_watcher() - Set config files, create data dirs, etc
|
# configure_watcher() - Set config files, create data dirs, etc
|
||||||
@@ -108,6 +129,28 @@ function create_watcher_accounts {
|
|||||||
"$WATCHER_SERVICE_PROTOCOL://$WATCHER_SERVICE_HOST:$WATCHER_SERVICE_PORT"
|
"$WATCHER_SERVICE_PROTOCOL://$WATCHER_SERVICE_HOST:$WATCHER_SERVICE_PORT"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# _config_watcher_apache_wsgi() - Set WSGI config files of watcher
|
||||||
|
function _config_watcher_apache_wsgi {
|
||||||
|
local watcher_apache_conf
|
||||||
|
if [[ "$WATCHER_USE_MOD_WSGI" == "True" ]]; then
|
||||||
|
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%|$WATCHER_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
|
||||||
|
tail_log watcher-access /var/log/$APACHE_NAME/watcher-api-access.log
|
||||||
|
tail_log watcher-api /var/log/$APACHE_NAME/watcher-api.log
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
# create_watcher_conf() - Create a new watcher.conf file
|
# create_watcher_conf() - Create a new watcher.conf file
|
||||||
function create_watcher_conf {
|
function create_watcher_conf {
|
||||||
# (Re)create ``watcher.conf``
|
# (Re)create ``watcher.conf``
|
||||||
@@ -126,9 +169,10 @@ function create_watcher_conf {
|
|||||||
iniset $WATCHER_CONF oslo_messaging_rabbit rabbit_password $RABBIT_PASSWORD
|
iniset $WATCHER_CONF oslo_messaging_rabbit rabbit_password $RABBIT_PASSWORD
|
||||||
iniset $WATCHER_CONF oslo_messaging_rabbit rabbit_host $RABBIT_HOST
|
iniset $WATCHER_CONF oslo_messaging_rabbit rabbit_host $RABBIT_HOST
|
||||||
|
|
||||||
iniset $WATCHER_CONF oslo_messaging_notifications driver "messaging"
|
iniset $WATCHER_CONF oslo_messaging_notifications driver "messagingv2"
|
||||||
|
|
||||||
iniset $NOVA_CONF oslo_messaging_notifications topics "notifications,watcher_notifications"
|
iniset $NOVA_CONF oslo_messaging_notifications topics "notifications,watcher_notifications"
|
||||||
|
iniset $NOVA_CONF notifications notify_on_state_change "vm_and_task_state"
|
||||||
|
|
||||||
configure_auth_token_middleware $WATCHER_CONF watcher $WATCHER_AUTH_CACHE_DIR
|
configure_auth_token_middleware $WATCHER_CONF watcher $WATCHER_AUTH_CACHE_DIR
|
||||||
configure_auth_token_middleware $WATCHER_CONF watcher $WATCHER_AUTH_CACHE_DIR "watcher_clients_auth"
|
configure_auth_token_middleware $WATCHER_CONF watcher $WATCHER_AUTH_CACHE_DIR "watcher_clients_auth"
|
||||||
@@ -153,9 +197,13 @@ function create_watcher_conf {
|
|||||||
setup_colorized_logging $WATCHER_CONF DEFAULT
|
setup_colorized_logging $WATCHER_CONF DEFAULT
|
||||||
else
|
else
|
||||||
# Show user_name and project_name instead of user_id and project_id
|
# Show user_name and project_name instead of user_id and project_id
|
||||||
iniset $WATCHER_CONF DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s] %(instance)s%(message)s"
|
iniset $WATCHER_CONF DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(levelname)s %(name)s [%(request_id)s %(project_domain)s %(user_name)s %(project_name)s] %(instance)s%(message)s"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#config apache files
|
||||||
|
if [[ "$WATCHER_USE_MOD_WSGI" == "True" ]]; then
|
||||||
|
_config_watcher_apache_wsgi
|
||||||
|
fi
|
||||||
# Register SSL certificates if provided
|
# Register SSL certificates if provided
|
||||||
if is_ssl_enabled_service watcher; then
|
if is_ssl_enabled_service watcher; then
|
||||||
ensure_certificates WATCHER
|
ensure_certificates WATCHER
|
||||||
@@ -187,7 +235,7 @@ function init_watcher {
|
|||||||
recreate_database watcher
|
recreate_database watcher
|
||||||
|
|
||||||
# Create watcher schema
|
# Create watcher schema
|
||||||
$WATCHER_BIN_DIR/watcher-db-manage --config-file $WATCHER_CONF create_schema
|
$WATCHER_BIN_DIR/watcher-db-manage --config-file $WATCHER_CONF upgrade head
|
||||||
fi
|
fi
|
||||||
create_watcher_cache_dir
|
create_watcher_cache_dir
|
||||||
}
|
}
|
||||||
@@ -204,19 +252,26 @@ function install_watcherclient {
|
|||||||
function install_watcher {
|
function install_watcher {
|
||||||
git_clone $WATCHER_REPO $WATCHER_DIR $WATCHER_BRANCH
|
git_clone $WATCHER_REPO $WATCHER_DIR $WATCHER_BRANCH
|
||||||
setup_develop $WATCHER_DIR
|
setup_develop $WATCHER_DIR
|
||||||
|
if [[ "$WATCHER_USE_MOD_WSGI" == "True" ]]; then
|
||||||
|
install_apache_wsgi
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# start_watcher_api() - Start the API process ahead of other things
|
# start_watcher_api() - Start the API process ahead of other things
|
||||||
function start_watcher_api {
|
function start_watcher_api {
|
||||||
# Get right service port for testing
|
# Get right service port for testing
|
||||||
|
|
||||||
local service_port=$WATCHER_SERVICE_PORT
|
local service_port=$WATCHER_SERVICE_PORT
|
||||||
local service_protocol=$WATCHER_SERVICE_PROTOCOL
|
local service_protocol=$WATCHER_SERVICE_PROTOCOL
|
||||||
if is_service_enabled tls-proxy; then
|
if is_service_enabled tls-proxy; then
|
||||||
service_port=$WATCHER_SERVICE_PORT_INT
|
service_port=$WATCHER_SERVICE_PORT_INT
|
||||||
service_protocol="http"
|
service_protocol="http"
|
||||||
fi
|
fi
|
||||||
|
if [[ "$WATCHER_USE_MOD_WSGI" == "True" ]]; then
|
||||||
run_process watcher-api "$WATCHER_BIN_DIR/watcher-api --config-file $WATCHER_CONF"
|
restart_apache_server
|
||||||
|
else
|
||||||
|
run_process watcher-api "$WATCHER_BIN_DIR/watcher-api --config-file $WATCHER_CONF"
|
||||||
|
fi
|
||||||
echo "Waiting for watcher-api to start..."
|
echo "Waiting for watcher-api to start..."
|
||||||
if ! wait_for_service $SERVICE_TIMEOUT $service_protocol://$WATCHER_SERVICE_HOST:$service_port; then
|
if ! wait_for_service $SERVICE_TIMEOUT $service_protocol://$WATCHER_SERVICE_HOST:$service_port; then
|
||||||
die $LINENO "watcher-api did not start"
|
die $LINENO "watcher-api did not start"
|
||||||
@@ -239,7 +294,12 @@ function start_watcher {
|
|||||||
|
|
||||||
# stop_watcher() - Stop running processes (non-screen)
|
# stop_watcher() - Stop running processes (non-screen)
|
||||||
function stop_watcher {
|
function stop_watcher {
|
||||||
for serv in watcher-api watcher-decision-engine watcher-applier; do
|
if [[ "$WATCHER_USE_MOD_WSGI" == "True" ]]; then
|
||||||
|
disable_apache_site watcher-api
|
||||||
|
else
|
||||||
|
stop_process watcher-api
|
||||||
|
fi
|
||||||
|
for serv in watcher-decision-engine watcher-applier; do
|
||||||
stop_process $serv
|
stop_process $serv
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ GLANCE_HOSTPORT=${SERVICE_HOST}:9292
|
|||||||
DATABASE_TYPE=mysql
|
DATABASE_TYPE=mysql
|
||||||
|
|
||||||
# Enable services (including neutron)
|
# Enable services (including neutron)
|
||||||
ENABLED_SERVICES=n-cpu,n-api-meta,c-vol,q-agt
|
ENABLED_SERVICES=n-cpu,n-api-meta,c-vol,q-agt,placement-client
|
||||||
|
|
||||||
NOVA_VNC_ENABLED=True
|
NOVA_VNC_ENABLED=True
|
||||||
NOVNCPROXY_URL="http://$SERVICE_HOST:6080/vnc_auto.html"
|
NOVNCPROXY_URL="http://$SERVICE_HOST:6080/vnc_auto.html"
|
||||||
@@ -44,3 +44,6 @@ LOGDAYS=2
|
|||||||
[[post-config|$NOVA_CONF]]
|
[[post-config|$NOVA_CONF]]
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
compute_monitors=cpu.virt_driver
|
compute_monitors=cpu.virt_driver
|
||||||
|
notify_on_state_change = vm_and_task_state
|
||||||
|
[notifications]
|
||||||
|
notify_on_state_change = vm_and_task_state
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ NETWORK_GATEWAY=10.254.1.1 # Change this for your network
|
|||||||
|
|
||||||
MULTI_HOST=1
|
MULTI_HOST=1
|
||||||
|
|
||||||
|
|
||||||
|
#Set this to FALSE if do not want to run watcher-api behind mod-wsgi
|
||||||
|
#WATCHER_USE_MOD_WSGI=TRUE
|
||||||
|
|
||||||
# This is the controller node, so disable nova-compute
|
# This is the controller node, so disable nova-compute
|
||||||
disable_service n-cpu
|
disable_service n-cpu
|
||||||
|
|
||||||
@@ -28,7 +32,7 @@ ENABLED_SERVICES+=,q-svc,q-dhcp,q-meta,q-agt,q-l3,neutron
|
|||||||
enable_service n-cauth
|
enable_service n-cauth
|
||||||
|
|
||||||
# Enable the Watcher Dashboard plugin
|
# Enable the Watcher Dashboard plugin
|
||||||
# enable_plugin watcher-dashboard git://git.openstack.org/openstack/watcher-dashboard
|
enable_plugin watcher-dashboard git://git.openstack.org/openstack/watcher-dashboard
|
||||||
|
|
||||||
# Enable the Watcher plugin
|
# Enable the Watcher plugin
|
||||||
enable_plugin watcher git://git.openstack.org/openstack/watcher
|
enable_plugin watcher git://git.openstack.org/openstack/watcher
|
||||||
@@ -38,6 +42,11 @@ enable_plugin ceilometer git://git.openstack.org/openstack/ceilometer
|
|||||||
|
|
||||||
# This is the controller node, so disable the ceilometer compute agent
|
# This is the controller node, so disable the ceilometer compute agent
|
||||||
disable_service ceilometer-acompute
|
disable_service ceilometer-acompute
|
||||||
|
# Enable the ceilometer api explicitly(bug:1667678)
|
||||||
|
enable_service ceilometer-api
|
||||||
|
|
||||||
|
# Enable the Gnocchi plugin
|
||||||
|
enable_plugin gnocchi https://git.openstack.org/openstack/gnocchi
|
||||||
|
|
||||||
LOGFILE=$DEST/logs/stack.sh.log
|
LOGFILE=$DEST/logs/stack.sh.log
|
||||||
LOGDAYS=2
|
LOGDAYS=2
|
||||||
@@ -45,3 +54,6 @@ LOGDAYS=2
|
|||||||
[[post-config|$NOVA_CONF]]
|
[[post-config|$NOVA_CONF]]
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
compute_monitors=cpu.virt_driver
|
compute_monitors=cpu.virt_driver
|
||||||
|
notify_on_state_change = vm_and_task_state
|
||||||
|
[notifications]
|
||||||
|
notify_on_state_change = vm_and_task_state
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
|
||||||
# Copyright (c) 2015 b<>com
|
# Copyright (c) 2015 b<>com
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
|||||||
40
doc/notification_samples/action-create.json
Normal file
40
doc/notification_samples/action-create.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"priority": "INFO",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "ActionCreatePayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"input_parameters": {
|
||||||
|
"param2": 2,
|
||||||
|
"param1": 1
|
||||||
|
},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "PENDING",
|
||||||
|
"action_plan": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "TerseActionPlanPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"global_efficacy": {},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "ONGOING",
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parents": [],
|
||||||
|
"action_type": "nop",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"timestamp": "2017-01-01 00:00:00.000000",
|
||||||
|
"event_type": "action.create",
|
||||||
|
"message_id": "530b409c-9b6b-459b-8f08-f93dbfeb4d41"
|
||||||
|
}
|
||||||
40
doc/notification_samples/action-delete.json
Normal file
40
doc/notification_samples/action-delete.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"priority": "INFO",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "ActionDeletePayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"input_parameters": {
|
||||||
|
"param2": 2,
|
||||||
|
"param1": 1
|
||||||
|
},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "DELETED",
|
||||||
|
"action_plan": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "TerseActionPlanPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"global_efficacy": {},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "ONGOING",
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parents": [],
|
||||||
|
"action_type": "nop",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"timestamp": "2017-01-01 00:00:00.000000",
|
||||||
|
"event_type": "action.delete",
|
||||||
|
"message_id": "530b409c-9b6b-459b-8f08-f93dbfeb4d41"
|
||||||
|
}
|
||||||
41
doc/notification_samples/action-execution-end.json
Normal file
41
doc/notification_samples/action-execution-end.json
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"priority": "INFO",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "ActionExecutionPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"input_parameters": {
|
||||||
|
"param2": 2,
|
||||||
|
"param1": 1
|
||||||
|
},
|
||||||
|
"fault": null,
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "SUCCEEDED",
|
||||||
|
"action_plan": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "TerseActionPlanPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"global_efficacy": {},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "ONGOING",
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parents": [],
|
||||||
|
"action_type": "nop",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"event_type": "action.execution.end",
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"timestamp": "2017-01-01 00:00:00.000000",
|
||||||
|
"message_id": "530b409c-9b6b-459b-8f08-f93dbfeb4d41"
|
||||||
|
}
|
||||||
51
doc/notification_samples/action-execution-error.json
Normal file
51
doc/notification_samples/action-execution-error.json
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"priority": "ERROR",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "ActionExecutionPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"input_parameters": {
|
||||||
|
"param2": 2,
|
||||||
|
"param1": 1
|
||||||
|
},
|
||||||
|
"fault": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "ExceptionPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"module_name": "watcher.tests.notifications.test_action_notification",
|
||||||
|
"exception": "WatcherException",
|
||||||
|
"exception_message": "TEST",
|
||||||
|
"function_name": "test_send_action_execution_with_error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "FAILED",
|
||||||
|
"action_plan": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "TerseActionPlanPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"global_efficacy": {},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "ONGOING",
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parents": [],
|
||||||
|
"action_type": "nop",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"event_type": "action.execution.error",
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"timestamp": "2017-01-01 00:00:00.000000",
|
||||||
|
"message_id": "530b409c-9b6b-459b-8f08-f93dbfeb4d41"
|
||||||
|
}
|
||||||
41
doc/notification_samples/action-execution-start.json
Normal file
41
doc/notification_samples/action-execution-start.json
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"priority": "INFO",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "ActionExecutionPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"input_parameters": {
|
||||||
|
"param2": 2,
|
||||||
|
"param1": 1
|
||||||
|
},
|
||||||
|
"fault": null,
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "ONGOING",
|
||||||
|
"action_plan": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "TerseActionPlanPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"global_efficacy": {},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "ONGOING",
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parents": [],
|
||||||
|
"action_type": "nop",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"event_type": "action.execution.start",
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"timestamp": "2017-01-01 00:00:00.000000",
|
||||||
|
"message_id": "530b409c-9b6b-459b-8f08-f93dbfeb4d41"
|
||||||
|
}
|
||||||
49
doc/notification_samples/action-update.json
Normal file
49
doc/notification_samples/action-update.json
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"priority": "INFO",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "ActionUpdatePayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"input_parameters": {
|
||||||
|
"param2": 2,
|
||||||
|
"param1": 1
|
||||||
|
},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state_update": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "ActionStateUpdatePayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"old_state": "PENDING",
|
||||||
|
"state": "ONGOING"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"state": "ONGOING",
|
||||||
|
"action_plan": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "TerseActionPlanPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"global_efficacy": {},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "ONGOING",
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parents": [],
|
||||||
|
"action_type": "nop",
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"event_type": "action.update",
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"timestamp": "2017-01-01 00:00:00.000000",
|
||||||
|
"message_id": "530b409c-9b6b-459b-8f08-f93dbfeb4d41"
|
||||||
|
}
|
||||||
54
doc/notification_samples/action_plan-create.json
Normal file
54
doc/notification_samples/action_plan-create.json
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"name": "TEST",
|
||||||
|
"updated_at": null,
|
||||||
|
"parameters_spec": {},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": null
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "StrategyPayload"
|
||||||
|
},
|
||||||
|
"created_at": null,
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"scope": [],
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
|
"parameters": {},
|
||||||
|
"interval": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"state": "PENDING",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "TerseAuditPayload"
|
||||||
|
},
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"global_efficacy": {},
|
||||||
|
"deleted_at": null,
|
||||||
|
"state": "RECOMMENDED",
|
||||||
|
"updated_at": null
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "ActionPlanCreatePayload"
|
||||||
|
},
|
||||||
|
"priority": "INFO",
|
||||||
|
"message_id": "5148bff1-ea06-4ad6-8e4e-8c85ca5eb629",
|
||||||
|
"event_type": "action_plan.create",
|
||||||
|
"timestamp": "2016-10-18 09:52:05.219414"
|
||||||
|
}
|
||||||
54
doc/notification_samples/action_plan-delete.json
Normal file
54
doc/notification_samples/action_plan-delete.json
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"timestamp": "2016-10-18 09:52:05.219414",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
|
"interval": null,
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"scope": [],
|
||||||
|
"updated_at": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"state": "PENDING",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"parameters": {}
|
||||||
|
},
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "TerseAuditPayload",
|
||||||
|
"watcher_object.namespace": "watcher"
|
||||||
|
},
|
||||||
|
"global_efficacy": {},
|
||||||
|
"updated_at": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"name": "TEST",
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"deleted_at": null,
|
||||||
|
"updated_at": null,
|
||||||
|
"parameters_spec": {}
|
||||||
|
},
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "StrategyPayload",
|
||||||
|
"watcher_object.namespace": "watcher"
|
||||||
|
},
|
||||||
|
"state": "DELETED"
|
||||||
|
},
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "ActionPlanDeletePayload",
|
||||||
|
"watcher_object.namespace": "watcher"
|
||||||
|
},
|
||||||
|
"event_type": "action_plan.delete",
|
||||||
|
"message_id": "3d137686-a1fd-4683-ab40-c4210aac2140",
|
||||||
|
"priority": "INFO"
|
||||||
|
}
|
||||||
55
doc/notification_samples/action_plan-execution-end.json
Normal file
55
doc/notification_samples/action_plan-execution-end.json
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"event_type": "action_plan.execution.end",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "ActionPlanActionPayload",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": null,
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "TerseAuditPayload",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": null,
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
|
"scope": [],
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"state": "SUCCEEDED",
|
||||||
|
"parameters": {},
|
||||||
|
"interval": null,
|
||||||
|
"updated_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"fault": null,
|
||||||
|
"state": "ONGOING",
|
||||||
|
"global_efficacy": {},
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "StrategyPayload",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": null,
|
||||||
|
"name": "TEST",
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"parameters_spec": {},
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"updated_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"updated_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"priority": "INFO",
|
||||||
|
"message_id": "3984dc2b-8aef-462b-a220-8ae04237a56e",
|
||||||
|
"timestamp": "2016-10-18 09:52:05.219414",
|
||||||
|
"publisher_id": "infra-optim:node0"
|
||||||
|
}
|
||||||
65
doc/notification_samples/action_plan-execution-error.json
Normal file
65
doc/notification_samples/action_plan-execution-error.json
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"event_type": "action_plan.execution.error",
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"priority": "ERROR",
|
||||||
|
"message_id": "9a45c5ae-0e21-4300-8fa0-5555d52a66d9",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "ActionPlanActionPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"fault": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "ExceptionPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"exception_message": "TEST",
|
||||||
|
"module_name": "watcher.tests.notifications.test_action_plan_notification",
|
||||||
|
"function_name": "test_send_action_plan_action_with_error",
|
||||||
|
"exception": "WatcherException"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "StrategyPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"name": "TEST",
|
||||||
|
"updated_at": null,
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"parameters_spec": {},
|
||||||
|
"deleted_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"updated_at": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "TerseAuditPayload",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"parameters": {},
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"scope": [],
|
||||||
|
"updated_at": null,
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"interval": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"state": "PENDING"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"global_efficacy": {},
|
||||||
|
"state": "ONGOING"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"timestamp": "2016-10-18 09:52:05.219414"
|
||||||
|
}
|
||||||
55
doc/notification_samples/action_plan-execution-start.json
Normal file
55
doc/notification_samples/action_plan-execution-start.json
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"event_type": "action_plan.execution.start",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "ActionPlanActionPayload",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": null,
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "TerseAuditPayload",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": null,
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
|
"scope": [],
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"state": "PENDING",
|
||||||
|
"parameters": {},
|
||||||
|
"interval": null,
|
||||||
|
"updated_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"fault": null,
|
||||||
|
"state": "ONGOING",
|
||||||
|
"global_efficacy": {},
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "StrategyPayload",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": null,
|
||||||
|
"name": "TEST",
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"parameters_spec": {},
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"updated_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"updated_at": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"priority": "INFO",
|
||||||
|
"message_id": "3984dc2b-8aef-462b-a220-8ae04237a56e",
|
||||||
|
"timestamp": "2016-10-18 09:52:05.219414",
|
||||||
|
"publisher_id": "infra-optim:node0"
|
||||||
|
}
|
||||||
63
doc/notification_samples/action_plan-update.json
Normal file
63
doc/notification_samples/action_plan-update.json
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"scope": [],
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
|
"interval": null,
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "PENDING",
|
||||||
|
"deleted_at": null,
|
||||||
|
"parameters": {}
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "TerseAuditPayload"
|
||||||
|
},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"updated_at": null,
|
||||||
|
"state_update": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"old_state": "PENDING",
|
||||||
|
"state": "ONGOING"
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "ActionPlanStateUpdatePayload"
|
||||||
|
},
|
||||||
|
"state": "ONGOING",
|
||||||
|
"deleted_at": null,
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"name": "TEST",
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"parameters_spec": {}
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "StrategyPayload"
|
||||||
|
},
|
||||||
|
"global_efficacy": {}
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "ActionPlanUpdatePayload"
|
||||||
|
},
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"priority": "INFO",
|
||||||
|
"timestamp": "2016-10-18 09:52:05.219414",
|
||||||
|
"event_type": "action_plan.update",
|
||||||
|
"message_id": "0a8a7329-fd5a-4ec6-97d7-2b776ce51a4c"
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
"state": "PENDING",
|
"state": "PENDING",
|
||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"state": "DELETED",
|
"state": "DELETED",
|
||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
"fault": null,
|
"fault": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0"
|
"watcher_object.version": "1.0"
|
||||||
},
|
},
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
"fault": null,
|
"fault": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
"fault": null,
|
"fault": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0"
|
"watcher_object.version": "1.0"
|
||||||
},
|
},
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
"fault": null,
|
"fault": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"payload": {
|
"payload": {
|
||||||
"watcher_object.name": "AuditUpdatePayload",
|
"watcher_object.name": "AuditUpdatePayload",
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.name": "StrategyPayload",
|
"watcher_object.name": "StrategyPayload",
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
"scope": [],
|
"scope": [],
|
||||||
"created_at": "2016-11-04T16:51:21Z",
|
"created_at": "2016-11-04T16:51:21Z",
|
||||||
"uuid": "f1e0d912-afd9-4bf2-91ef-c99cd08cc1ef",
|
"uuid": "f1e0d912-afd9-4bf2-91ef-c99cd08cc1ef",
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.name": "GoalPayload",
|
"watcher_object.name": "GoalPayload",
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
|
|||||||
26
doc/notification_samples/service-update.json
Normal file
26
doc/notification_samples/service-update.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.name": "ServiceUpdatePayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"status_update": {
|
||||||
|
"watcher_object.name": "ServiceStatusUpdatePayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"old_state": "ACTIVE",
|
||||||
|
"state": "FAILED"
|
||||||
|
},
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"last_seen_up": "2016-09-22T08:32:06Z",
|
||||||
|
"name": "watcher-service",
|
||||||
|
"sevice_host": "controller"
|
||||||
|
},
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"event_type": "service.update",
|
||||||
|
"priority": "INFO",
|
||||||
|
"message_id": "3984dc2b-8aef-462b-a220-8ae04237a56e",
|
||||||
|
"timestamp": "2016-10-18 09:52:05.219414",
|
||||||
|
"publisher_id": "infra-optim:node0"
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ Overview
|
|||||||
Below you will find a diagram, showing the main components of Watcher:
|
Below you will find a diagram, showing the main components of Watcher:
|
||||||
|
|
||||||
.. image:: ./images/architecture.svg
|
.. image:: ./images/architecture.svg
|
||||||
:width: 100%
|
:width: 110%
|
||||||
|
|
||||||
|
|
||||||
.. _components_definition:
|
.. _components_definition:
|
||||||
@@ -37,13 +37,12 @@ AMQP Bus
|
|||||||
The AMQP message bus handles internal asynchronous communications between the
|
The AMQP message bus handles internal asynchronous communications between the
|
||||||
different Watcher components.
|
different Watcher components.
|
||||||
|
|
||||||
.. _cluster_history_db_definition:
|
.. _cluster_datasource_definition:
|
||||||
|
|
||||||
Cluster History Database
|
Datasource
|
||||||
------------------------
|
----------
|
||||||
|
|
||||||
This component stores the data related to the
|
This component stores the metrics related to the cluster.
|
||||||
:ref:`Cluster History <cluster_history_definition>`.
|
|
||||||
|
|
||||||
It can potentially rely on any appropriate storage system (InfluxDB, OpenTSDB,
|
It can potentially rely on any appropriate storage system (InfluxDB, OpenTSDB,
|
||||||
MongoDB,...) but will probably be more performant when using
|
MongoDB,...) but will probably be more performant when using
|
||||||
@@ -51,14 +50,6 @@ MongoDB,...) but will probably be more performant when using
|
|||||||
which are optimized for handling time series data, which are arrays of numbers
|
which are optimized for handling time series data, which are arrays of numbers
|
||||||
indexed by time (a datetime or a datetime range).
|
indexed by time (a datetime or a datetime range).
|
||||||
|
|
||||||
.. _cluster_model_db_definition:
|
|
||||||
|
|
||||||
Cluster Model Database
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
This component stores the data related to the
|
|
||||||
:ref:`Cluster Data Model <cluster_data_model_definition>`.
|
|
||||||
|
|
||||||
.. _archi_watcher_api_definition:
|
.. _archi_watcher_api_definition:
|
||||||
|
|
||||||
Watcher API
|
Watcher API
|
||||||
@@ -193,8 +184,8 @@ data:
|
|||||||
:ref:`Managed resources <managed_resource_definition>` (e.g., the data stored
|
:ref:`Managed resources <managed_resource_definition>` (e.g., the data stored
|
||||||
in the Nova database). These models gives a strategy the ability to reason on
|
in the Nova database). These models gives a strategy the ability to reason on
|
||||||
the current state of a given :ref:`cluster <cluster_definition>`.
|
the current state of a given :ref:`cluster <cluster_definition>`.
|
||||||
- The data stored in the :ref:`Cluster History Database
|
- The data stored in the :ref:`Cluster Datasource
|
||||||
<cluster_history_db_definition>` which provides information about the past of
|
<cluster_datasource_definition>` which provides information about the past of
|
||||||
the :ref:`Cluster <cluster_definition>`.
|
the :ref:`Cluster <cluster_definition>`.
|
||||||
|
|
||||||
Here below is a sequence diagram showing how the Decision Engine builds and
|
Here below is a sequence diagram showing how the Decision Engine builds and
|
||||||
@@ -416,6 +407,9 @@ be one of the following:
|
|||||||
- **CANCELLED** : the :ref:`Audit <audit_definition>` was in **PENDING** or
|
- **CANCELLED** : the :ref:`Audit <audit_definition>` was in **PENDING** or
|
||||||
**ONGOING** state and was cancelled by the
|
**ONGOING** state and was cancelled by the
|
||||||
:ref:`Administrator <administrator_definition>`
|
:ref:`Administrator <administrator_definition>`
|
||||||
|
- **SUSPENDED** : the :ref:`Audit <audit_definition>` was in **ONGOING**
|
||||||
|
state and was suspended by the
|
||||||
|
:ref:`Administrator <administrator_definition>`
|
||||||
|
|
||||||
The following diagram shows the different possible states of an
|
The following diagram shows the different possible states of an
|
||||||
:ref:`Audit <audit_definition>` and what event makes the state change to a new
|
:ref:`Audit <audit_definition>` and what event makes the state change to a new
|
||||||
@@ -452,6 +446,10 @@ state may be one of the following:
|
|||||||
- **CANCELLED** : the :ref:`Action Plan <action_plan_definition>` was in
|
- **CANCELLED** : the :ref:`Action Plan <action_plan_definition>` was in
|
||||||
**RECOMMENDED**, **PENDING** or **ONGOING** state and was cancelled by the
|
**RECOMMENDED**, **PENDING** or **ONGOING** state and was cancelled by the
|
||||||
:ref:`Administrator <administrator_definition>`
|
:ref:`Administrator <administrator_definition>`
|
||||||
|
- **SUPERSEDED** : the :ref:`Action Plan <action_plan_definition>` was in
|
||||||
|
RECOMMENDED state and was automatically superseded by Watcher, due to an
|
||||||
|
expiration delay or an update of the
|
||||||
|
:ref:`Cluster data model <cluster_data_model_definition>`
|
||||||
|
|
||||||
|
|
||||||
The following diagram shows the different possible states of an
|
The following diagram shows the different possible states of an
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
|
|||||||
49
doc/source/deploy/apache-mod-wsgi.rst
Normal file
49
doc/source/deploy/apache-mod-wsgi.rst
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
..
|
||||||
|
Except where otherwise noted, this document is licensed under Creative
|
||||||
|
Commons Attribution 3.0 License. You can view the license at:
|
||||||
|
|
||||||
|
https://creativecommons.org/licenses/by/3.0/
|
||||||
|
|
||||||
|
|
||||||
|
Installing API behind mod_wsgi
|
||||||
|
==============================
|
||||||
|
|
||||||
|
#. Install the Apache Service::
|
||||||
|
|
||||||
|
Fedora 21/RHEL7/CentOS7:
|
||||||
|
sudo yum install httpd
|
||||||
|
|
||||||
|
Fedora 22 (or higher):
|
||||||
|
sudo dnf install httpd
|
||||||
|
|
||||||
|
Debian/Ubuntu:
|
||||||
|
apt-get install apache2
|
||||||
|
|
||||||
|
#. Copy ``etc/apache2/watcher.conf`` under the apache sites::
|
||||||
|
|
||||||
|
Fedora/RHEL7/CentOS7:
|
||||||
|
sudo cp etc/apache2/watcher /etc/httpd/conf.d/watcher.conf
|
||||||
|
|
||||||
|
Debian/Ubuntu:
|
||||||
|
sudo cp etc/apache2/watcher /etc/apache2/sites-available/watcher.conf
|
||||||
|
|
||||||
|
#. Edit ``<apache-configuration-dir>/watcher.conf`` according to installation
|
||||||
|
and environment.
|
||||||
|
|
||||||
|
* Modify the ``WSGIDaemonProcess`` directive to set the ``user`` and
|
||||||
|
``group`` values to appropriate user on your server.
|
||||||
|
* Modify the ``WSGIScriptAlias`` directive to point to the
|
||||||
|
watcher/api/app.wsgi script.
|
||||||
|
* Modify the ``Directory`` directive to set the path to the Watcher API
|
||||||
|
code.
|
||||||
|
* Modify the ``ErrorLog and CustomLog`` to redirect the logs to the right
|
||||||
|
directory.
|
||||||
|
|
||||||
|
#. Enable the apache watcher site and reload::
|
||||||
|
|
||||||
|
Fedora/RHEL7/CentOS7:
|
||||||
|
sudo systemctl reload httpd
|
||||||
|
|
||||||
|
Debian/Ubuntu:
|
||||||
|
sudo a2ensite watcher
|
||||||
|
sudo service apache2 reload
|
||||||
@@ -15,7 +15,7 @@ Service overview
|
|||||||
================
|
================
|
||||||
|
|
||||||
The Watcher system is a collection of services that provides support to
|
The Watcher system is a collection of services that provides support to
|
||||||
optimize your IAAS plateform. The Watcher service may, depending upon
|
optimize your IAAS platform. The Watcher service may, depending upon
|
||||||
configuration, interact with several other OpenStack services. This includes:
|
configuration, interact with several other OpenStack services. This includes:
|
||||||
|
|
||||||
- the OpenStack Identity service (`keystone`_) for request authentication and
|
- the OpenStack Identity service (`keystone`_) for request authentication and
|
||||||
@@ -37,7 +37,7 @@ The Watcher service includes the following components:
|
|||||||
- `watcher-dashboard`_: An Horizon plugin for interacting with the Watcher
|
- `watcher-dashboard`_: An Horizon plugin for interacting with the Watcher
|
||||||
service.
|
service.
|
||||||
|
|
||||||
Additionally, the Bare Metal service has certain external dependencies, which
|
Additionally, the Watcher service has certain external dependencies, which
|
||||||
are very similar to other OpenStack services:
|
are very similar to other OpenStack services:
|
||||||
|
|
||||||
- A database to store audit and action plan information and state. You can set
|
- A database to store audit and action plan information and state. You can set
|
||||||
@@ -86,7 +86,6 @@ Configure the Identity service for the Watcher service
|
|||||||
--tenant=KEYSTONE_SERVICE_PROJECT_NAME
|
--tenant=KEYSTONE_SERVICE_PROJECT_NAME
|
||||||
$ keystone user-role-add --user=watcher \
|
$ keystone user-role-add --user=watcher \
|
||||||
--tenant=KEYSTONE_SERVICE_PROJECT_NAME --role=admin
|
--tenant=KEYSTONE_SERVICE_PROJECT_NAME --role=admin
|
||||||
$ keystone user-role-add --user=watcher --tenant=admin --role=admin
|
|
||||||
|
|
||||||
or (by using python-openstackclient 1.8.0+)
|
or (by using python-openstackclient 1.8.0+)
|
||||||
|
|
||||||
@@ -97,7 +96,6 @@ Configure the Identity service for the Watcher service
|
|||||||
--project=KEYSTONE_SERVICE_PROJECT_NAME
|
--project=KEYSTONE_SERVICE_PROJECT_NAME
|
||||||
$ openstack role add --project KEYSTONE_SERVICE_PROJECT_NAME \
|
$ openstack role add --project KEYSTONE_SERVICE_PROJECT_NAME \
|
||||||
--user watcher admin
|
--user watcher admin
|
||||||
$ openstack role add --user watcher --project admin admin
|
|
||||||
|
|
||||||
|
|
||||||
#. You must register the Watcher Service with the Identity Service so that
|
#. You must register the Watcher Service with the Identity Service so that
|
||||||
@@ -169,7 +167,7 @@ these following commands::
|
|||||||
|
|
||||||
$ git clone git://git.openstack.org/openstack/watcher
|
$ git clone git://git.openstack.org/openstack/watcher
|
||||||
$ cd watcher/
|
$ cd watcher/
|
||||||
$ tox -econfig
|
$ tox -e genconfig
|
||||||
$ vi etc/watcher/watcher.conf.sample
|
$ vi etc/watcher/watcher.conf.sample
|
||||||
|
|
||||||
|
|
||||||
@@ -368,7 +366,7 @@ Configure Nova compute
|
|||||||
Please check your hypervisor configuration to correctly handle
|
Please check your hypervisor configuration to correctly handle
|
||||||
`instance migration`_.
|
`instance migration`_.
|
||||||
|
|
||||||
.. _`instance migration`: http://docs.openstack.org/admin-guide-cloud/compute-configuring-migrations.html
|
.. _`instance migration`: http://docs.openstack.org/admin-guide/compute-live-migration-usage.html
|
||||||
|
|
||||||
Configure Measurements
|
Configure Measurements
|
||||||
======================
|
======================
|
||||||
@@ -426,7 +424,7 @@ to Watcher receives Nova notifications in ``watcher_notifications`` as well.
|
|||||||
into which Nova services will publish events ::
|
into which Nova services will publish events ::
|
||||||
|
|
||||||
[oslo_messaging_notifications]
|
[oslo_messaging_notifications]
|
||||||
driver = messaging
|
driver = messagingv2
|
||||||
topics = notifications,watcher_notifications
|
topics = notifications,watcher_notifications
|
||||||
|
|
||||||
* Restart the Nova services.
|
* Restart the Nova services.
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ The source install instructions specifically avoid using platform specific
|
|||||||
packages, instead using the source for the code and the Python Package Index
|
packages, instead using the source for the code and the Python Package Index
|
||||||
(PyPi_).
|
(PyPi_).
|
||||||
|
|
||||||
.. _PyPi: http://pypi.python.org/pypi
|
.. _PyPi: https://pypi.python.org/pypi
|
||||||
|
|
||||||
It's expected that your system already has python2.7_, latest version of pip_,
|
It's expected that your system already has python2.7_, latest version of pip_,
|
||||||
and git_ available.
|
and git_ available.
|
||||||
|
|
||||||
.. _python2.7: http://www.python.org
|
.. _python2.7: https://www.python.org
|
||||||
.. _pip: http://www.pip-installer.org/en/latest/installing.html
|
.. _pip: https://pip.pypa.io/en/latest/installing/
|
||||||
.. _git: http://git-scm.com/
|
.. _git: https://git-scm.com/
|
||||||
|
|
||||||
Your system shall also have some additional system libraries:
|
Your system shall also have some additional system libraries:
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,12 @@ Detailed DevStack Instructions
|
|||||||
Note: if you want to use a specific branch, specify WATCHER_BRANCH in the
|
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.
|
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.
|
||||||
|
|
||||||
#. Start stacking from the controller node::
|
#. Start stacking from the controller node::
|
||||||
|
|
||||||
./devstack/stack.sh
|
./devstack/stack.sh
|
||||||
@@ -193,6 +199,37 @@ 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
|
every compute node's public ECDSA key needs to be in every other compute
|
||||||
node's root user's known_hosts file.
|
node's root user's known_hosts file.
|
||||||
|
|
||||||
|
Disable serial console
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Serial console needs to be disabled for live migration to work.
|
||||||
|
|
||||||
|
On both the controller and compute node, in /etc/nova/nova.conf
|
||||||
|
|
||||||
|
[serial_console]
|
||||||
|
enabled = False
|
||||||
|
|
||||||
|
Alternatively, in devstack's local.conf:
|
||||||
|
|
||||||
|
[[post-config|$NOVA_CONF]]
|
||||||
|
[serial_console]
|
||||||
|
#enabled=false
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
vncserver_listen = 0.0.0.0
|
||||||
|
|
||||||
|
Alternatively, in devstack's local.conf:
|
||||||
|
|
||||||
|
VNCSERVER_LISTEN=0.0.0.0
|
||||||
|
|
||||||
|
|
||||||
Environment final checkup
|
Environment final checkup
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ for development purposes.
|
|||||||
To install Watcher from packaging, refer instead to Watcher `User
|
To install Watcher from packaging, refer instead to Watcher `User
|
||||||
Documentation`_.
|
Documentation`_.
|
||||||
|
|
||||||
.. _`Git Repository`: http://git.openstack.org/cgit/openstack/watcher
|
.. _`Git Repository`: https://git.openstack.org/cgit/openstack/watcher
|
||||||
.. _`User Documentation`: http://docs.openstack.org/developer/watcher/
|
.. _`User Documentation`: https://docs.openstack.org/developer/watcher/
|
||||||
|
|
||||||
Prerequisites
|
Prerequisites
|
||||||
=============
|
=============
|
||||||
@@ -35,10 +35,10 @@ following tools available on your system:
|
|||||||
**Reminder**: If you're successfully using a different platform, or a
|
**Reminder**: If you're successfully using a different platform, or a
|
||||||
different version of the above, please document your configuration here!
|
different version of the above, please document your configuration here!
|
||||||
|
|
||||||
.. _Python: http://www.python.org/
|
.. _Python: https://www.python.org/
|
||||||
.. _git: http://git-scm.com/
|
.. _git: https://git-scm.com/
|
||||||
.. _setuptools: http://pypi.python.org/pypi/setuptools
|
.. _setuptools: https://pypi.python.org/pypi/setuptools
|
||||||
.. _virtualenvwrapper: https://virtualenvwrapper.readthedocs.org/en/latest/install.html
|
.. _virtualenvwrapper: https://virtualenvwrapper.readthedocs.io/en/latest/install.html
|
||||||
|
|
||||||
Getting the latest code
|
Getting the latest code
|
||||||
=======================
|
=======================
|
||||||
@@ -85,6 +85,9 @@ your platform.
|
|||||||
|
|
||||||
$ sudo yum install openssl-devel libffi-devel mysql-devel
|
$ sudo yum install openssl-devel libffi-devel mysql-devel
|
||||||
|
|
||||||
|
* CentOS 7::
|
||||||
|
|
||||||
|
$ sudo yum install gcc python-devel libxml2-devel libxslt-devel mariadb-devel
|
||||||
|
|
||||||
PyPi Packages and VirtualEnv
|
PyPi Packages and VirtualEnv
|
||||||
----------------------------
|
----------------------------
|
||||||
@@ -172,11 +175,12 @@ The HTML files are available into ``doc/build`` directory.
|
|||||||
Configure the Watcher services
|
Configure the Watcher services
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
Watcher services require a configuration file. There is a sample configuration
|
Watcher services require a configuration file. Use tox to generate
|
||||||
file that can be used to get started:
|
a sample configuration file that can be used to get started:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ tox -e genconfig
|
||||||
$ cp etc/watcher.conf.sample etc/watcher.conf
|
$ cp etc/watcher.conf.sample etc/watcher.conf
|
||||||
|
|
||||||
Most of the default configuration should be enough to get you going, but you
|
Most of the default configuration should be enough to get you going, but you
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ implement:
|
|||||||
implement. This is the first function to be called by the
|
implement. This is the first function to be called by the
|
||||||
:ref:`applier <watcher_applier_definition>` before any further processing
|
:ref:`applier <watcher_applier_definition>` before any further processing
|
||||||
and its role is to validate the input parameters that were provided to it.
|
and its role is to validate the input parameters that were provided to it.
|
||||||
- The :py:meth:`~.BaseAction.precondition` is called before the execution of
|
- The :py:meth:`~.BaseAction.pre_condition` is called before the execution of
|
||||||
an action. This method is a hook that can be used to perform some
|
an action. This method is a hook that can be used to perform some
|
||||||
initializations or to make some more advanced validation on its input
|
initializations or to make some more advanced validation on its input
|
||||||
parameters. If you wish to block the execution based on this factor, you
|
parameters. If you wish to block the execution based on this factor, you
|
||||||
simply have to ``raise`` an exception.
|
simply have to ``raise`` an exception.
|
||||||
- The :py:meth:`~.BaseAction.postcondition` is called after the execution of
|
- The :py:meth:`~.BaseAction.post_condition` is called after the execution of
|
||||||
an action. As this function is called regardless of whether an action
|
an action. As this function is called regardless of whether an action
|
||||||
succeeded or not, this can prove itself useful to perform cleanup
|
succeeded or not, this can prove itself useful to perform cleanup
|
||||||
operations.
|
operations.
|
||||||
@@ -71,11 +71,11 @@ Here is an example showing how you can write a plugin called ``DummyAction``:
|
|||||||
# Does nothing
|
# Does nothing
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def precondition(self):
|
def pre_condition(self):
|
||||||
# No pre-checks are done here
|
# No pre-checks are done here
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def postcondition(self):
|
def post_condition(self):
|
||||||
# Nothing done here
|
# Nothing done here
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -268,5 +268,5 @@ At this point, you can use your new cluster data model plugin in your
|
|||||||
# [...]
|
# [...]
|
||||||
dummy_collector = self.collector_manager.get_cluster_model_collector(
|
dummy_collector = self.collector_manager.get_cluster_model_collector(
|
||||||
"dummy") # "dummy" is the name of the entry point we declared earlier
|
"dummy") # "dummy" is the name of the entry point we declared earlier
|
||||||
dummy_model = collector.get_latest_cluster_data_model()
|
dummy_model = dummy_collector.get_latest_cluster_data_model()
|
||||||
# Do some stuff with this model
|
# Do some stuff with this model
|
||||||
|
|||||||
@@ -245,75 +245,70 @@ Querying metrics
|
|||||||
|
|
||||||
A large set of metrics, generated by OpenStack modules, can be used in your
|
A large set of metrics, generated by OpenStack modules, can be used in your
|
||||||
strategy implementation. To collect these metrics, Watcher provides a
|
strategy implementation. To collect these metrics, Watcher provides a
|
||||||
`Helper`_ to the Ceilometer API, which makes this API reusable and easier
|
`Helper`_ for two data sources which are `Ceilometer`_ and `Monasca`_. If you
|
||||||
to used.
|
wish to query metrics from a different data source, you can implement your own
|
||||||
|
and directly use it from within your new strategy. Indeed, strategies in
|
||||||
|
Watcher have the cluster data models decoupled from the data sources which
|
||||||
|
means that you may keep the former while changing the latter.
|
||||||
|
The recommended way for you to support a new data source is to implement a new
|
||||||
|
helper that would encapsulate within separate methods the queries you need to
|
||||||
|
perform. To then use it, you would just have to instantiate it within your
|
||||||
|
strategy.
|
||||||
|
|
||||||
If you want to use your own metrics database backend, please refer to the
|
If you want to use Ceilometer but with your own metrics database backend,
|
||||||
`Ceilometer developer guide`_. Indeed, Ceilometer's pluggable model allows
|
please refer to the `Ceilometer developer guide`_. The list of the available
|
||||||
for various types of backends. A list of the available backends is located
|
Ceilometer backends is located here_. The `Ceilosca`_ project is a good example
|
||||||
here_. The Ceilosca project is a good example of how to create your own
|
of how to create your own pluggable backend. Moreover, if your strategy
|
||||||
pluggable backend.
|
requires new metrics not covered by Ceilometer, you can add them through a
|
||||||
|
`Ceilometer plugin`_.
|
||||||
|
|
||||||
Finally, if your strategy requires new metrics not covered by Ceilometer, you
|
|
||||||
can add them through a Ceilometer `plugin`_.
|
|
||||||
|
|
||||||
.. _`Helper`: https://github.com/openstack/watcher/blob/master/watcher/decision_engine/cluster/history/ceilometer.py
|
.. _`Helper`: https://github.com/openstack/watcher/blob/master/watcher/decision_engine/cluster/history/ceilometer.py
|
||||||
.. _`Ceilometer developer guide`: http://docs.openstack.org/developer/ceilometer/architecture.html#storing-the-data
|
.. _`Ceilometer developer guide`: http://docs.openstack.org/developer/ceilometer/architecture.html#storing-the-data
|
||||||
|
.. _`Ceilometer`: http://docs.openstack.org/developer/ceilometer/
|
||||||
|
.. _`Monasca`: https://github.com/openstack/monasca-api/blob/master/docs/monasca-api-spec.md
|
||||||
.. _`here`: http://docs.openstack.org/developer/ceilometer/install/dbreco.html#choosing-a-database-backend
|
.. _`here`: http://docs.openstack.org/developer/ceilometer/install/dbreco.html#choosing-a-database-backend
|
||||||
.. _`plugin`: http://docs.openstack.org/developer/ceilometer/plugins.html
|
.. _`Ceilometer plugin`: http://docs.openstack.org/developer/ceilometer/plugins.html
|
||||||
.. _`Ceilosca`: https://github.com/openstack/monasca-ceilometer/blob/master/ceilosca/ceilometer/storage/impl_monasca.py
|
.. _`Ceilosca`: https://github.com/openstack/monasca-ceilometer/blob/master/ceilosca/ceilometer/storage/impl_monasca.py
|
||||||
|
|
||||||
|
Read usage metrics using the Watcher Datasource Helper
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
Read usage metrics using the Python binding
|
The following code snippet shows how to invoke a Datasource Helper class:
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
You can find the information about the Ceilometer Python binding on the
|
|
||||||
OpenStack `ceilometer client python API documentation
|
|
||||||
<http://docs.openstack.org/developer/python-ceilometerclient/api.html>`_
|
|
||||||
|
|
||||||
To facilitate the process, Watcher provides the ``osc`` attribute to every
|
|
||||||
strategy which includes clients to major OpenStack services, including
|
|
||||||
Ceilometer. So to access it within your strategy, you can do the following:
|
|
||||||
|
|
||||||
.. code-block:: py
|
.. code-block:: py
|
||||||
|
|
||||||
# Within your strategy "execute()"
|
from watcher.datasource import ceilometer as ceil
|
||||||
cclient = self.osc.ceilometer
|
from watcher.datasource import monasca as mon
|
||||||
# TODO: Do something here
|
|
||||||
|
@property
|
||||||
|
def ceilometer(self):
|
||||||
|
if self._ceilometer is None:
|
||||||
|
self._ceilometer = ceil.CeilometerHelper(osc=self.osc)
|
||||||
|
return self._ceilometer
|
||||||
|
|
||||||
|
@property
|
||||||
|
def monasca(self):
|
||||||
|
if self._monasca is None:
|
||||||
|
self._monasca = mon.MonascaHelper(osc=self.osc)
|
||||||
|
return self._monasca
|
||||||
|
|
||||||
Using that you can now query the values for that specific metric:
|
Using that you can now query the values for that specific metric:
|
||||||
|
|
||||||
.. code-block:: py
|
.. code-block:: py
|
||||||
|
|
||||||
query = None # e.g. [{'field': 'foo', 'op': 'le', 'value': 34},]
|
if self.config.datasource == "ceilometer":
|
||||||
value_cpu = cclient.samples.list(
|
resource_id = "%s_%s" % (node.uuid, node.hostname)
|
||||||
meter_name='cpu_util',
|
return self.ceilometer.statistic_aggregation(
|
||||||
limit=10, q=query)
|
resource_id=resource_id,
|
||||||
|
meter_name='compute.node.cpu.percent',
|
||||||
|
period="7200",
|
||||||
Read usage metrics using the Watcher Cluster History Helper
|
aggregate='avg',
|
||||||
-----------------------------------------------------------
|
)
|
||||||
|
elif self.config.datasource == "monasca":
|
||||||
Here below is the abstract ``BaseClusterHistory`` class of the Helper.
|
statistics = self.monasca.statistic_aggregation(
|
||||||
|
meter_name='compute.node.cpu.percent',
|
||||||
.. autoclass:: watcher.decision_engine.cluster.history.base.BaseClusterHistory
|
dimensions=dict(hostname=node.uuid),
|
||||||
:members:
|
period=7200,
|
||||||
:noindex:
|
aggregate='avg'
|
||||||
|
)
|
||||||
The following code snippet shows how to create a Cluster History class:
|
|
||||||
|
|
||||||
.. code-block:: py
|
|
||||||
|
|
||||||
from watcher.decision_engine.cluster.history import ceilometer as ceil
|
|
||||||
|
|
||||||
query_history = ceil.CeilometerClusterHistory()
|
|
||||||
|
|
||||||
Using that you can now query the values for that specific metric:
|
|
||||||
|
|
||||||
.. code-block:: py
|
|
||||||
|
|
||||||
query_history.statistic_aggregation(resource_id=compute_node.uuid,
|
|
||||||
meter_name='compute.node.cpu.percent',
|
|
||||||
period="7200",
|
|
||||||
aggregate='avg'
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Unit tests
|
|||||||
==========
|
==========
|
||||||
|
|
||||||
All unit tests should be run using `tox`_. To run the same unit tests that are
|
All unit tests should be run using `tox`_. To run the same unit tests that are
|
||||||
executing onto `Gerrit`_ which includes ``py34``, ``py27`` and ``pep8``, you
|
executing onto `Gerrit`_ which includes ``py35``, ``py27`` and ``pep8``, you
|
||||||
can issue the following command::
|
can issue the following command::
|
||||||
|
|
||||||
$ workon watcher
|
$ workon watcher
|
||||||
@@ -26,7 +26,7 @@ If you want to only run one of the aforementioned, you can then issue one of
|
|||||||
the following::
|
the following::
|
||||||
|
|
||||||
$ workon watcher
|
$ workon watcher
|
||||||
(watcher) $ tox -e py34
|
(watcher) $ tox -e py35
|
||||||
(watcher) $ tox -e py27
|
(watcher) $ tox -e py27
|
||||||
(watcher) $ tox -e pep8
|
(watcher) $ tox -e pep8
|
||||||
|
|
||||||
|
|||||||
@@ -101,12 +101,6 @@ Cluster Data Model (CDM)
|
|||||||
|
|
||||||
.. watcher-term:: watcher.decision_engine.model.collector.base
|
.. watcher-term:: watcher.decision_engine.model.collector.base
|
||||||
|
|
||||||
.. _cluster_history_definition:
|
|
||||||
|
|
||||||
Cluster History
|
|
||||||
===============
|
|
||||||
|
|
||||||
.. watcher-term:: watcher.decision_engine.cluster.history.base
|
|
||||||
|
|
||||||
.. _controller_node_definition:
|
.. _controller_node_definition:
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ FAILED --> DELETED : Administrator removes\nAction Plan
|
|||||||
SUCCEEDED --> DELETED : Administrator removes\nAction Plan
|
SUCCEEDED --> DELETED : Administrator removes\nAction Plan
|
||||||
ONGOING --> CANCELLED : Administrator cancels\nAction Plan
|
ONGOING --> CANCELLED : Administrator cancels\nAction Plan
|
||||||
RECOMMENDED --> CANCELLED : Administrator cancels\nAction Plan
|
RECOMMENDED --> CANCELLED : Administrator cancels\nAction Plan
|
||||||
|
RECOMMENDED --> SUPERSEDED : The Watcher Decision Engine supersedes\nAction Plan
|
||||||
PENDING --> CANCELLED : Administrator cancels\nAction Plan
|
PENDING --> CANCELLED : Administrator cancels\nAction Plan
|
||||||
CANCELLED --> DELETED
|
CANCELLED --> DELETED
|
||||||
|
SUPERSEDED --> DELETED
|
||||||
DELETED --> [*]
|
DELETED --> [*]
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|||||||
@@ -4,11 +4,14 @@
|
|||||||
PENDING --> ONGOING: Audit request is received\nby the Watcher Decision Engine
|
PENDING --> ONGOING: Audit request is received\nby the Watcher Decision Engine
|
||||||
ONGOING --> FAILED: Audit fails\n(no solution found, technical error, ...)
|
ONGOING --> FAILED: Audit fails\n(no solution found, technical error, ...)
|
||||||
ONGOING --> SUCCEEDED: The Watcher Decision Engine\ncould find at least one Solution
|
ONGOING --> SUCCEEDED: The Watcher Decision Engine\ncould find at least one Solution
|
||||||
|
ONGOING --> SUSPENDED: Administrator wants to\nsuspend the Audit
|
||||||
|
SUSPENDED --> ONGOING: Administrator wants to\nresume the Audit
|
||||||
FAILED --> DELETED : Administrator wants to\narchive/delete the Audit
|
FAILED --> DELETED : Administrator wants to\narchive/delete the Audit
|
||||||
SUCCEEDED --> DELETED : Administrator wants to\narchive/delete the Audit
|
SUCCEEDED --> DELETED : Administrator wants to\narchive/delete the Audit
|
||||||
PENDING --> CANCELLED : Administrator cancels\nthe Audit
|
PENDING --> CANCELLED : Administrator cancels\nthe Audit
|
||||||
ONGOING --> CANCELLED : Administrator cancels\nthe Audit
|
ONGOING --> CANCELLED : Administrator cancels\nthe Audit
|
||||||
CANCELLED --> DELETED : Administrator wants to\narchive/delete the Audit
|
CANCELLED --> DELETED : Administrator wants to\narchive/delete the Audit
|
||||||
|
SUSPENDED --> DELETED: Administrator wants to\narchive/delete the Audit
|
||||||
DELETED --> [*]
|
DELETED --> [*]
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ table(audits) {
|
|||||||
interval : Integer, nullable
|
interval : Integer, nullable
|
||||||
parameters : JSONEncodedDict, nullable
|
parameters : JSONEncodedDict, nullable
|
||||||
scope : JSONEncodedList, nullable
|
scope : JSONEncodedList, nullable
|
||||||
|
auto_trigger: Boolean
|
||||||
|
|
||||||
created_at : DateTime
|
created_at : DateTime
|
||||||
updated_at : DateTime
|
updated_at : DateTime
|
||||||
@@ -73,7 +74,6 @@ table(action_plans) {
|
|||||||
foreign_key("audit_id : Integer, nullable")
|
foreign_key("audit_id : Integer, nullable")
|
||||||
foreign_key("strategy_id : Integer")
|
foreign_key("strategy_id : Integer")
|
||||||
uuid : String[36]
|
uuid : String[36]
|
||||||
first_action_id : Integer
|
|
||||||
state : String[20], nullable
|
state : String[20], nullable
|
||||||
global_efficacy : JSONEncodedDict, nullable
|
global_efficacy : JSONEncodedDict, nullable
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ table(actions) {
|
|||||||
action_type : String[255]
|
action_type : String[255]
|
||||||
input_parameters : JSONEncodedDict, nullable
|
input_parameters : JSONEncodedDict, nullable
|
||||||
state : String[20], nullable
|
state : String[20], nullable
|
||||||
next : String[36], nullable
|
parents : JSONEncodedList, nullable
|
||||||
|
|
||||||
created_at : DateTime
|
created_at : DateTime
|
||||||
updated_at : DateTime
|
updated_at : DateTime
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 58 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 47 KiB |
@@ -56,6 +56,7 @@ Getting Started
|
|||||||
dev/devstack
|
dev/devstack
|
||||||
deploy/configuration
|
deploy/configuration
|
||||||
deploy/conf-files
|
deploy/conf-files
|
||||||
|
deploy/apache-mod-wsgi
|
||||||
dev/notifications
|
dev/notifications
|
||||||
dev/testing
|
dev/testing
|
||||||
dev/rally_link
|
dev/rally_link
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ parameter type default Value description
|
|||||||
be tried by the strategy while
|
be tried by the strategy while
|
||||||
searching for potential candidates.
|
searching for potential candidates.
|
||||||
To remove the limit, set it to 0
|
To remove the limit, set it to 0
|
||||||
|
``period`` Number 7200 The time interval in seconds
|
||||||
|
for getting statistic aggregation
|
||||||
|
from metric data source
|
||||||
====================== ====== ============= ===================================
|
====================== ====== ============= ===================================
|
||||||
|
|
||||||
Efficacy Indicator
|
Efficacy Indicator
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ Strategy parameter is:
|
|||||||
parameter type default Value description
|
parameter type default Value description
|
||||||
============== ====== ============= ====================================
|
============== ====== ============= ====================================
|
||||||
``threshold`` Number 35.0 Temperature threshold for migration
|
``threshold`` Number 35.0 Temperature threshold for migration
|
||||||
|
``period`` Number 30 The time interval in seconds for
|
||||||
|
getting statistic aggregation from
|
||||||
|
metric data source
|
||||||
============== ====== ============= ====================================
|
============== ====== ============= ====================================
|
||||||
|
|
||||||
Efficacy Indicator
|
Efficacy Indicator
|
||||||
|
|||||||
@@ -70,6 +70,20 @@ Default Watcher's planner:
|
|||||||
.. watcher-term:: watcher.decision_engine.planner.default.DefaultPlanner
|
.. watcher-term:: watcher.decision_engine.planner.default.DefaultPlanner
|
||||||
|
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Strategy parameter is:
|
||||||
|
|
||||||
|
====================== ====== ============= ===================================
|
||||||
|
parameter type default Value description
|
||||||
|
====================== ====== ============= ===================================
|
||||||
|
``period`` Number 3600 The time interval in seconds
|
||||||
|
for getting statistic aggregation
|
||||||
|
from metric data source
|
||||||
|
====================== ====== ============= ===================================
|
||||||
|
|
||||||
|
|
||||||
Efficacy Indicator
|
Efficacy Indicator
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
@@ -89,7 +103,7 @@ How to use it ?
|
|||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
$ openstack optimize audittemplate create \
|
$ openstack optimize audittemplate create \
|
||||||
at1 vm_consolidation --strategy vm_workload_consolidation
|
at1 server_consolidation --strategy vm_workload_consolidation
|
||||||
|
|
||||||
$ openstack optimize audit create -a at1
|
$ openstack optimize audit create -a at1
|
||||||
|
|
||||||
|
|||||||
33
etc/apache2/watcher
Normal file
33
etc/apache2/watcher
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
# This is an example Apache2 configuration file for using
|
||||||
|
# Watcher API through mod_wsgi
|
||||||
|
Listen 9322
|
||||||
|
|
||||||
|
<VirtualHost *:9322>
|
||||||
|
WSGIDaemonProcess watcher-api user=stack group=stack processes=2 threads=2 display-name=%{GROUP}
|
||||||
|
WSGIScriptAlias / /opt/stack/watcher/watcher/api/app.wsgi
|
||||||
|
WSGIProcessGroup watcher-api
|
||||||
|
|
||||||
|
ErrorLog /var/log/httpd/watcher_error.log
|
||||||
|
LogLevel info
|
||||||
|
CustomLog /var/log/httpd/watcher_access.log combined
|
||||||
|
|
||||||
|
<Directory /opt/stack/watcher/watcher/api>
|
||||||
|
WSGIProcessGroup watcher-api
|
||||||
|
WSGIApplicationGroup %{GLOBAL}
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
To generate the sample watcher.conf file, run the following
|
To generate the sample watcher.conf file, run the following
|
||||||
command from the top level of the watcher directory:
|
command from the top level of the watcher directory:
|
||||||
|
|
||||||
tox -econfig
|
tox -e genconfig
|
||||||
|
|||||||
71
install-guide/source/common_configure.rst
Normal file
71
install-guide/source/common_configure.rst
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
2. Edit the ``/etc/watcher/watcher.conf`` file and complete the following
|
||||||
|
actions:
|
||||||
|
|
||||||
|
* In the ``[database]`` section, configure database access:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[database]
|
||||||
|
...
|
||||||
|
connection = mysql+pymysql://watcher:WATCHER_DBPASS@controller/watcher?charset=utf8
|
||||||
|
|
||||||
|
* In the `[DEFAULT]` section, configure the transport url for RabbitMQ message broker.
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[DEFAULT]
|
||||||
|
...
|
||||||
|
control_exchange = watcher
|
||||||
|
transport_url = rabbit://openstack:RABBIT_PASS@controller
|
||||||
|
|
||||||
|
Replace the RABBIT_PASS with the password you chose for OpenStack user in RabbitMQ.
|
||||||
|
|
||||||
|
* In the `[keystone_authtoken]` section, configure Identity service access.
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[keystone_authtoken]
|
||||||
|
...
|
||||||
|
auth_uri = http://controller:5000
|
||||||
|
auth_url = http://controller:35357
|
||||||
|
memcached_servers = controller:11211
|
||||||
|
auth_type = password
|
||||||
|
project_domain_name = default
|
||||||
|
user_domain_name = default
|
||||||
|
project_name = service
|
||||||
|
username = watcher
|
||||||
|
password = WATCHER_PASS
|
||||||
|
|
||||||
|
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_client_auth]` section,
|
||||||
|
configure the identity service access to interact with other OpenStack project clients.
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[watcher_client_auth]
|
||||||
|
...
|
||||||
|
auth_type = password
|
||||||
|
auth_url = http://controller:35357
|
||||||
|
username = watcher
|
||||||
|
password = WATCHER_PASS
|
||||||
|
project_domain_name = default
|
||||||
|
user_domain_name = default
|
||||||
|
project_name = service
|
||||||
|
|
||||||
|
Replace WATCHER_PASS with the password you chose for the watcher user in the Identity service.
|
||||||
|
|
||||||
|
* In the `[oslo_messaging_notifications]` section, configure the messaging driver.
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[oslo_messaging_notifications]
|
||||||
|
...
|
||||||
|
driver = messagingv2
|
||||||
|
|
||||||
|
3. Populate watcher database:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
su -s /bin/sh -c "watcher-db-manage" watcher
|
||||||
139
install-guide/source/common_prerequisites.rst
Normal file
139
install-guide/source/common_prerequisites.rst
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
Prerequisites
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Before you install and configure the Infrastructure Optimization service,
|
||||||
|
you must create a database, service credentials, and API endpoints.
|
||||||
|
|
||||||
|
1. Create the database, complete these steps:
|
||||||
|
|
||||||
|
* Use the database access client to connect to the database
|
||||||
|
server as the ``root`` user:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ mysql -u root -p
|
||||||
|
|
||||||
|
* Create the ``watcher`` database:
|
||||||
|
|
||||||
|
.. code-block:: none
|
||||||
|
|
||||||
|
CREATE DATABASE watcher CHARACTER SET utf8;
|
||||||
|
|
||||||
|
* Grant proper access to the ``watcher`` database:
|
||||||
|
|
||||||
|
.. code-block:: none
|
||||||
|
|
||||||
|
GRANT ALL PRIVILEGES ON watcher.* TO 'watcher'@'localhost' \
|
||||||
|
IDENTIFIED BY 'WATCHER_DBPASS';
|
||||||
|
GRANT ALL PRIVILEGES ON watcher.* TO 'watcher'@'%' \
|
||||||
|
IDENTIFIED BY 'WATCHER_DBPASS';
|
||||||
|
|
||||||
|
Replace ``WATCHER_DBPASS`` with a suitable password.
|
||||||
|
|
||||||
|
* Exit the database access client.
|
||||||
|
|
||||||
|
.. code-block:: none
|
||||||
|
|
||||||
|
exit;
|
||||||
|
|
||||||
|
2. Source the ``admin`` credentials to gain access to
|
||||||
|
admin-only CLI commands:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ . admin-openrc
|
||||||
|
|
||||||
|
3. To create the service credentials, complete these steps:
|
||||||
|
|
||||||
|
* Create the ``watcher`` user:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack user create --domain default --password-prompt watcher
|
||||||
|
User Password:
|
||||||
|
Repeat User Password:
|
||||||
|
+---------------------+----------------------------------+
|
||||||
|
| Field | Value |
|
||||||
|
+---------------------+----------------------------------+
|
||||||
|
| domain_id | default |
|
||||||
|
| enabled | True |
|
||||||
|
| id | b18ee38e06034b748141beda8fc8bfad |
|
||||||
|
| name | watcher |
|
||||||
|
| options | {} |
|
||||||
|
| password_expires_at | None |
|
||||||
|
+---------------------+----------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
* Add the ``admin`` role to the ``watcher`` user:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack role add --project service --user watcher admin
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This command produces no output.
|
||||||
|
|
||||||
|
* Create the watcher service entities:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack service create --name watcher --description "Infrastructure Optimization" infra-optim
|
||||||
|
+-------------+----------------------------------+
|
||||||
|
| Field | Value |
|
||||||
|
+-------------+----------------------------------+
|
||||||
|
| description | Infrastructure Optimization |
|
||||||
|
| enabled | True |
|
||||||
|
| id | d854f6fff0a64f77bda8003c8dedfada |
|
||||||
|
| name | watcher |
|
||||||
|
| type | infra-optim |
|
||||||
|
+-------------+----------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
4. Create the Infrastructure Optimization service API endpoints:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack endpoint create --region RegionOne \
|
||||||
|
infra-optim public http://controller:9322
|
||||||
|
+-------------+----------------------------------+
|
||||||
|
| Field | Value |
|
||||||
|
+-------------+----------------------------------+
|
||||||
|
| description | Infrastructure Optimization |
|
||||||
|
| enabled | True |
|
||||||
|
| id | d854f6fff0a64f77bda8003c8dedfada |
|
||||||
|
| name | watcher |
|
||||||
|
| type | infra-optim |
|
||||||
|
+-------------+----------------------------------+
|
||||||
|
|
||||||
|
$ openstack endpoint create --region RegionOne \
|
||||||
|
infra-optim internal http://controller:9322
|
||||||
|
+--------------+----------------------------------+
|
||||||
|
| Field | Value |
|
||||||
|
+--------------+----------------------------------+
|
||||||
|
| enabled | True |
|
||||||
|
| id | 225aef8465ef4df48a341aaaf2b0a390 |
|
||||||
|
| interface | internal |
|
||||||
|
| region | RegionOne |
|
||||||
|
| region_id | RegionOne |
|
||||||
|
| service_id | d854f6fff0a64f77bda8003c8dedfada |
|
||||||
|
| service_name | watcher |
|
||||||
|
| service_type | infra-optim |
|
||||||
|
| url | http://controller:9322 |
|
||||||
|
+--------------+----------------------------------+
|
||||||
|
|
||||||
|
$ openstack endpoint create --region RegionOne \
|
||||||
|
infra-optim admin http://controller:9322
|
||||||
|
+--------------+----------------------------------+
|
||||||
|
| Field | Value |
|
||||||
|
+--------------+----------------------------------+
|
||||||
|
| enabled | True |
|
||||||
|
| id | 375eb5057fb546edbdf3ee4866179672 |
|
||||||
|
| interface | admin |
|
||||||
|
| region | RegionOne |
|
||||||
|
| region_id | RegionOne |
|
||||||
|
| service_id | d854f6fff0a64f77bda8003c8dedfada |
|
||||||
|
| service_name | watcher |
|
||||||
|
| service_type | infra-optim |
|
||||||
|
| url | http://controller:9322 |
|
||||||
|
+--------------+----------------------------------+
|
||||||
301
install-guide/source/conf.py
Normal file
301
install-guide/source/conf.py
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# This file is execfile()d with the current directory set to its
|
||||||
|
# containing dir.
|
||||||
|
#
|
||||||
|
# Note that not all possible configuration values are present in this
|
||||||
|
# autogenerated file.
|
||||||
|
#
|
||||||
|
# All configuration values have a default; values that are commented out
|
||||||
|
# serve to show the default.
|
||||||
|
|
||||||
|
import os
|
||||||
|
# import sys
|
||||||
|
|
||||||
|
|
||||||
|
import openstackdocstheme
|
||||||
|
|
||||||
|
# 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('.'))
|
||||||
|
|
||||||
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
|
# 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.
|
||||||
|
# TODO(ajaeger): enable PDF building, for example add 'rst2pdf.pdfbuilder'
|
||||||
|
# extensions =
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
# templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The suffix of source filenames.
|
||||||
|
source_suffix = '.rst'
|
||||||
|
|
||||||
|
# The encoding of source files.
|
||||||
|
# source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = u'Installation Guide for Infrastructure Optimization Service'
|
||||||
|
bug_tag = u'install-guide'
|
||||||
|
copyright = u'2016, OpenStack contributors'
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
version = '0.1'
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
release = '0.1'
|
||||||
|
|
||||||
|
# A few variables have to be set for the log-a-bug feature.
|
||||||
|
# giturl: The location of conf.py on Git. Must be set manually.
|
||||||
|
# gitsha: The SHA checksum of the bug description. Automatically extracted
|
||||||
|
# from git log.
|
||||||
|
# bug_tag: Tag for categorizing the bug. Must be set manually.
|
||||||
|
# These variables are passed to the logabug code via html_context.
|
||||||
|
giturl = u'http://git.openstack.org/cgit/openstack/watcher/tree/install-guide/source' # noqa
|
||||||
|
git_cmd = "/usr/bin/git log | head -n1 | cut -f2 -d' '"
|
||||||
|
gitsha = os.popen(git_cmd).read().strip('\n')
|
||||||
|
html_context = {"gitsha": gitsha, "bug_tag": bug_tag,
|
||||||
|
"giturl": giturl,
|
||||||
|
"bug_project": "watcher"}
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
# language = None
|
||||||
|
|
||||||
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
|
# non-false value, then it is used:
|
||||||
|
# today = ''
|
||||||
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
|
# 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 = ["common_prerequisites.rst", "common_configure.rst"]
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
|
# documents.
|
||||||
|
# default_role = None
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
|
# output. They are ignored by default.
|
||||||
|
# show_authors = False
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
# modindex_common_prefix = []
|
||||||
|
|
||||||
|
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||||
|
# keep_warnings = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
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 = {}
|
||||||
|
|
||||||
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
|
html_theme_path = [openstackdocstheme.get_html_theme_path()]
|
||||||
|
|
||||||
|
# The name for this set of Sphinx documents. If None, it defaults to
|
||||||
|
# "<project> v<release> documentation".
|
||||||
|
# html_title = None
|
||||||
|
|
||||||
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
# html_static_path = []
|
||||||
|
|
||||||
|
# Add any extra paths that contain custom files (such as robots.txt or
|
||||||
|
# .htaccess) here, relative to this directory. These files are copied
|
||||||
|
# directly to the root of the documentation.
|
||||||
|
# html_extra_path = []
|
||||||
|
|
||||||
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
|
# using the given strftime format.
|
||||||
|
# So that we can enable "log-a-bug" links from each output HTML page, this
|
||||||
|
# variable must be set to a format that includes year, month, day, hours and
|
||||||
|
# minutes.
|
||||||
|
html_last_updated_fmt = '%Y-%m-%d %H:%M'
|
||||||
|
|
||||||
|
|
||||||
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
|
# typographically correct entities.
|
||||||
|
# html_use_smartypants = True
|
||||||
|
|
||||||
|
# Custom sidebar templates, maps document names to template names.
|
||||||
|
# html_sidebars = {}
|
||||||
|
|
||||||
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
|
# template names.
|
||||||
|
# html_additional_pages = {}
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
# html_domain_indices = True
|
||||||
|
|
||||||
|
# If false, no index is generated.
|
||||||
|
html_use_index = False
|
||||||
|
|
||||||
|
# If true, the index is split into individual pages for each letter.
|
||||||
|
# html_split_index = False
|
||||||
|
|
||||||
|
# If true, links to the reST sources are added to the pages.
|
||||||
|
html_show_sourcelink = False
|
||||||
|
|
||||||
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
|
# html_show_sphinx = True
|
||||||
|
|
||||||
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is 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 = ''
|
||||||
|
|
||||||
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
|
# html_file_suffix = None
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = 'install-guide'
|
||||||
|
|
||||||
|
# If true, publish source files
|
||||||
|
html_copy_source = False
|
||||||
|
|
||||||
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
|
|
||||||
|
latex_elements = {
|
||||||
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
|
# 'papersize': 'letterpaper',
|
||||||
|
|
||||||
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
|
# 'pointsize': '10pt',
|
||||||
|
|
||||||
|
# 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, or own class]).
|
||||||
|
latex_documents = [
|
||||||
|
('index', 'InstallGuide.tex', u'Install Guide',
|
||||||
|
u'OpenStack contributors', 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
|
# the title page.
|
||||||
|
# latex_logo = None
|
||||||
|
|
||||||
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
|
# not chapters.
|
||||||
|
# latex_use_parts = False
|
||||||
|
|
||||||
|
# If true, show page references after internal links.
|
||||||
|
# latex_show_pagerefs = False
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
# latex_show_urls = False
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
# latex_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
# latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for manual page output ---------------------------------------
|
||||||
|
|
||||||
|
# One entry per manual page. List of tuples
|
||||||
|
# (source start file, name, description, authors, manual section).
|
||||||
|
man_pages = [
|
||||||
|
('index', 'installguide', u'Install Guide',
|
||||||
|
[u'OpenStack contributors'], 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
# man_show_urls = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for Texinfo output -------------------------------------------
|
||||||
|
|
||||||
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
|
# (source start file, target name, title, author,
|
||||||
|
# dir menu entry, description, category)
|
||||||
|
texinfo_documents = [
|
||||||
|
('index', 'InstallGuide', u'Install Guide',
|
||||||
|
u'OpenStack contributors', 'InstallGuide',
|
||||||
|
'This guide shows OpenStack end users how to install '
|
||||||
|
'an OpenStack cloud.', 'Miscellaneous'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
# texinfo_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
# texinfo_domain_indices = True
|
||||||
|
|
||||||
|
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||||
|
# texinfo_show_urls = 'footnote'
|
||||||
|
|
||||||
|
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||||
|
# texinfo_no_detailmenu = False
|
||||||
|
|
||||||
|
# -- Options for Internationalization output ------------------------------
|
||||||
|
locale_dirs = ['locale/']
|
||||||
|
|
||||||
|
# -- Options for PDF output --------------------------------------------------
|
||||||
|
|
||||||
|
pdf_documents = [
|
||||||
|
('index', u'InstallGuide', u'Install Guide',
|
||||||
|
u'OpenStack contributors')
|
||||||
|
]
|
||||||
27
install-guide/source/get_started.rst
Normal file
27
install-guide/source/get_started.rst
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
============================================
|
||||||
|
Infrastructure Optimization service overview
|
||||||
|
============================================
|
||||||
|
The Infrastructure Optimization service provides flexible and scalable
|
||||||
|
optimization service for multi-tenant OpenStack based clouds.
|
||||||
|
|
||||||
|
The Infrastructure Optimization service consists of the following components:
|
||||||
|
|
||||||
|
``watcher`` command-line client
|
||||||
|
A CLI to communicate with ``watcher-api`` to optimize the cloud.
|
||||||
|
|
||||||
|
``watcher-api`` service
|
||||||
|
An OpenStack-native REST API that accepts and responds to end-user calls
|
||||||
|
by processing them and forwarding to appropriate underlying watcher
|
||||||
|
services via AMQP.
|
||||||
|
|
||||||
|
``watcher-decision-engine`` service
|
||||||
|
It runs audit and return an action plan to achieve optimization goal
|
||||||
|
specified by the end-user in audit.
|
||||||
|
|
||||||
|
``watcher-applier`` service
|
||||||
|
It executes action plan built by watcher-decision-engine. It interacts with
|
||||||
|
other OpenStack components like nova to execute the given action
|
||||||
|
plan.
|
||||||
|
|
||||||
|
``watcher-dashboard``
|
||||||
|
Watcher UI implemented as a plugin for the OpenStack Dashboard.
|
||||||
39
install-guide/source/index.rst
Normal file
39
install-guide/source/index.rst
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
===================================
|
||||||
|
Infrastructure Optimization service
|
||||||
|
===================================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
get_started.rst
|
||||||
|
install.rst
|
||||||
|
verify.rst
|
||||||
|
next-steps.rst
|
||||||
|
|
||||||
|
The Infrastructure Optimization service (watcher) provides
|
||||||
|
flexible and scalable resource optimization service for
|
||||||
|
multi-tenant OpenStack-based clouds.
|
||||||
|
|
||||||
|
Watcher provides a complete optimization loop including
|
||||||
|
everything from a metrics receiver, complex event processor
|
||||||
|
and profiler, optimization processor and an action plan
|
||||||
|
applier. This provides a robust framework to realize a wide
|
||||||
|
range of cloud optimization goals, including the reduction
|
||||||
|
of data center operating costs, increased system performance
|
||||||
|
via intelligent virtual machine migration, increased energy
|
||||||
|
efficiency—and more!
|
||||||
|
|
||||||
|
watcher also supports a pluggable architecture by which custom
|
||||||
|
optimization algorithms, data metrics and data profilers can be
|
||||||
|
developed and inserted into the Watcher framework.
|
||||||
|
|
||||||
|
check the documentation for watcher optimization strategies at
|
||||||
|
https://docs.openstack.org/developer/watcher/strategies
|
||||||
|
|
||||||
|
check watcher glossary at
|
||||||
|
https://docs.openstack.org/developer/watcher/glossary.html
|
||||||
|
|
||||||
|
|
||||||
|
This chapter assumes a working setup of OpenStack following the
|
||||||
|
`OpenStack Installation Tutorial
|
||||||
|
<https://docs.openstack.org/project-install-guide/ocata/>`_.
|
||||||
34
install-guide/source/install-obs.rst
Normal file
34
install-guide/source/install-obs.rst
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
.. _install-obs:
|
||||||
|
|
||||||
|
|
||||||
|
Install and configure for openSUSE and SUSE Linux Enterprise
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
This section describes how to install and configure the Infrastructure Optimization service
|
||||||
|
for openSUSE Leap 42.1 and SUSE Linux Enterprise Server 12 SP1.
|
||||||
|
|
||||||
|
.. include:: common_prerequisites.rst
|
||||||
|
|
||||||
|
Install and configure components
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
#. Install the packages:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
# zypper --quiet --non-interactive install
|
||||||
|
|
||||||
|
.. include:: common_configure.rst
|
||||||
|
|
||||||
|
|
||||||
|
Finalize installation
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Start the Infrastructure Optimization services and configure them to start when
|
||||||
|
the system boots:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
# systemctl enable openstack-watcher-api.service
|
||||||
|
|
||||||
|
# systemctl start openstack-watcher-api.service
|
||||||
38
install-guide/source/install-rdo.rst
Normal file
38
install-guide/source/install-rdo.rst
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
.. _install-rdo:
|
||||||
|
|
||||||
|
Install and configure for Red Hat Enterprise Linux and CentOS
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
||||||
|
This section describes how to install and configure the Infrastructure Optimization service
|
||||||
|
for Red Hat Enterprise Linux 7 and CentOS 7.
|
||||||
|
|
||||||
|
.. include:: common_prerequisites.rst
|
||||||
|
|
||||||
|
Install and configure components
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
1. Install the packages:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
# sudo yum install openstack-watcher-api openstack-watcher-applier \
|
||||||
|
openstack-watcher-decision-engine
|
||||||
|
|
||||||
|
.. include:: common_configure.rst
|
||||||
|
|
||||||
|
Finalize installation
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Start the Infrastructure Optimization services and configure them to start when
|
||||||
|
the system boots:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
# systemctl enable openstack-watcher-api.service \
|
||||||
|
openstack-watcher-decision-engine.service \
|
||||||
|
openstack-watcher-applier.service
|
||||||
|
|
||||||
|
# systemctl start openstack-watcher-api.service \
|
||||||
|
openstack-watcher-decision-engine.service \
|
||||||
|
openstack-watcher-applier.service
|
||||||
34
install-guide/source/install-ubuntu.rst
Normal file
34
install-guide/source/install-ubuntu.rst
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
.. _install-ubuntu:
|
||||||
|
|
||||||
|
Install and configure for Ubuntu
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
This section describes how to install and configure the Infrastructure Optimization
|
||||||
|
service for Ubuntu 14.04 (LTS).
|
||||||
|
|
||||||
|
.. include:: common_prerequisites.rst
|
||||||
|
|
||||||
|
Install and configure components
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
1. Install the packages:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
# apt install watcher-api watcher-decision-engine \
|
||||||
|
watcher-applier
|
||||||
|
|
||||||
|
# apt install python-watcherclient
|
||||||
|
|
||||||
|
.. include:: common_configure.rst
|
||||||
|
|
||||||
|
Finalize installation
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Restart the Infrastructure Optimization services:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
# service watcher-api restart
|
||||||
|
# service watcher-decision-engine restart
|
||||||
|
# service watcher-applier restart
|
||||||
20
install-guide/source/install.rst
Normal file
20
install-guide/source/install.rst
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
.. _install:
|
||||||
|
|
||||||
|
Install and configure
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
This section describes how to install and configure the
|
||||||
|
Infrastructure Optimization service, code-named watcher, on the controller node.
|
||||||
|
|
||||||
|
This section assumes that you already have a working OpenStack
|
||||||
|
environment with at least the following components installed:
|
||||||
|
Identity Service, Compute Service, Telemetry data collection service.
|
||||||
|
|
||||||
|
Note that installation and configuration vary by distribution.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
install-obs.rst
|
||||||
|
install-rdo.rst
|
||||||
|
install-ubuntu.rst
|
||||||
9
install-guide/source/next-steps.rst
Normal file
9
install-guide/source/next-steps.rst
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
.. _next-steps:
|
||||||
|
|
||||||
|
Next steps
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
Your OpenStack environment now includes the watcher service.
|
||||||
|
|
||||||
|
To add additional services, see
|
||||||
|
https://docs.openstack.org/project-install-guide/ocata/.
|
||||||
119
install-guide/source/verify.rst
Normal file
119
install-guide/source/verify.rst
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
.. _verify:
|
||||||
|
|
||||||
|
Verify operation
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Verify operation of the Infrastructure Optimization service.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Perform these commands on the controller node.
|
||||||
|
|
||||||
|
1. Source the ``admin`` project credentials to gain access to
|
||||||
|
admin-only CLI commands:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ . admin-openrc
|
||||||
|
|
||||||
|
2. List service components to verify successful launch and registration
|
||||||
|
of each process:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack optimize service list
|
||||||
|
+----+-------------------------+------------+--------+
|
||||||
|
| ID | Name | Host | Status |
|
||||||
|
+----+-------------------------+------------+--------+
|
||||||
|
| 1 | watcher-decision-engine | controller | ACTIVE |
|
||||||
|
| 2 | watcher-applier | controller | ACTIVE |
|
||||||
|
+----+-------------------------+------------+--------+
|
||||||
|
|
||||||
|
3. List goals and strategies:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack optimize goal list
|
||||||
|
+--------------------------------------+----------------------+----------------------+
|
||||||
|
| UUID | Name | Display name |
|
||||||
|
+--------------------------------------+----------------------+----------------------+
|
||||||
|
| a8cd6d1a-008b-4ff0-8dbc-b30493fcc5b9 | dummy | Dummy goal |
|
||||||
|
| 03953f2f-02d0-42b5-9a12-7ba500a54395 | workload_balancing | Workload Balancing |
|
||||||
|
| de0f8714-984b-4d6b-add1-9cad8120fbce | server_consolidation | Server Consolidation |
|
||||||
|
| f056bc80-c6d1-40dc-b002-938ccade9385 | thermal_optimization | Thermal Optimization |
|
||||||
|
| e7062856-892e-4f0f-b84d-b828464b3fd0 | airflow_optimization | Airflow Optimization |
|
||||||
|
| 1f038da9-b36c-449f-9f04-c225bf3eb478 | unclassified | Unclassified |
|
||||||
|
+--------------------------------------+----------------------+----------------------+
|
||||||
|
|
||||||
|
$ openstack optimize strategy list
|
||||||
|
+--------------------------------------+---------------------------+---------------------------------------------+----------------------+
|
||||||
|
| UUID | Name | Display name | Goal |
|
||||||
|
+--------------------------------------+---------------------------+---------------------------------------------+----------------------+
|
||||||
|
| 98ae84c8-7c9b-4cbd-8d9c-4bd7c6b106eb | dummy | Dummy strategy | dummy |
|
||||||
|
| 02a170b6-c72e-479d-95c0-8a4fdd4cc1ef | dummy_with_scorer | Dummy Strategy using sample Scoring Engines | dummy |
|
||||||
|
| 8bf591b8-57e5-4a9e-8c7d-c37bda735a45 | outlet_temperature | Outlet temperature based strategy | thermal_optimization |
|
||||||
|
| 8a0810fb-9d9a-47b9-ab25-e442878abc54 | vm_workload_consolidation | VM Workload Consolidation Strategy | server_consolidation |
|
||||||
|
| 1718859c-3eb5-45cb-9220-9cb79fe42fa5 | basic | Basic offline consolidation | server_consolidation |
|
||||||
|
| b5e7f5f1-4824-42c7-bb52-cf50724f67bf | workload_stabilization | Workload stabilization | workload_balancing |
|
||||||
|
| f853d71e-9286-4df3-9d3e-8eaf0f598e07 | workload_balance | Workload Balance Migration Strategy | workload_balancing |
|
||||||
|
| 58bdfa89-95b5-4630-adf6-fd3af5ff1f75 | uniform_airflow | Uniform airflow migration strategy | airflow_optimization |
|
||||||
|
| 66fde55d-a612-4be9-8cb0-ea63472b420b | dummy_with_resize | Dummy strategy with resize | dummy |
|
||||||
|
+--------------------------------------+---------------------------+---------------------------------------------+----------------------+
|
||||||
|
|
||||||
|
4. Run an action plan by creating an audit with dummy goal:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack optimize audit create --goal dummy
|
||||||
|
+--------------+--------------------------------------+
|
||||||
|
| Field | Value |
|
||||||
|
+--------------+--------------------------------------+
|
||||||
|
| UUID | e94d4826-ad4e-44df-ad93-dff489fde457 |
|
||||||
|
| Created At | 2017-05-23T11:46:58.763394+00:00 |
|
||||||
|
| Updated At | None |
|
||||||
|
| Deleted At | None |
|
||||||
|
| State | PENDING |
|
||||||
|
| Audit Type | ONESHOT |
|
||||||
|
| Parameters | {} |
|
||||||
|
| Interval | None |
|
||||||
|
| Goal | dummy |
|
||||||
|
| Strategy | auto |
|
||||||
|
| Audit Scope | [] |
|
||||||
|
| Auto Trigger | False |
|
||||||
|
+--------------+--------------------------------------+
|
||||||
|
|
||||||
|
$ openstack optimize audit list
|
||||||
|
+--------------------------------------+------------+-----------+-------+----------+--------------+
|
||||||
|
| UUID | Audit Type | State | Goal | Strategy | Auto Trigger |
|
||||||
|
+--------------------------------------+------------+-----------+-------+----------+--------------+
|
||||||
|
| e94d4826-ad4e-44df-ad93-dff489fde457 | ONESHOT | SUCCEEDED | dummy | auto | False |
|
||||||
|
+--------------------------------------+------------+-----------+-------+----------+--------------+
|
||||||
|
|
||||||
|
$ openstack optimize actionplan list
|
||||||
|
+--------------------------------------+--------------------------------------+-------------+------------+-----------------+
|
||||||
|
| UUID | Audit | State | Updated At | Global efficacy |
|
||||||
|
+--------------------------------------+--------------------------------------+-------------+------------+-----------------+
|
||||||
|
| ba9ce6b3-969c-4b8e-bb61-ae24e8630f81 | e94d4826-ad4e-44df-ad93-dff489fde457 | RECOMMENDED | None | None |
|
||||||
|
+--------------------------------------+--------------------------------------+-------------+------------+-----------------+
|
||||||
|
|
||||||
|
$ openstack optimize actionplan start ba9ce6b3-969c-4b8e-bb61-ae24e8630f81
|
||||||
|
+---------------------+--------------------------------------+
|
||||||
|
| Field | Value |
|
||||||
|
+---------------------+--------------------------------------+
|
||||||
|
| UUID | ba9ce6b3-969c-4b8e-bb61-ae24e8630f81 |
|
||||||
|
| Created At | 2017-05-23T11:46:58+00:00 |
|
||||||
|
| Updated At | 2017-05-23T11:53:12+00:00 |
|
||||||
|
| Deleted At | None |
|
||||||
|
| Audit | e94d4826-ad4e-44df-ad93-dff489fde457 |
|
||||||
|
| Strategy | dummy |
|
||||||
|
| State | ONGOING |
|
||||||
|
| Efficacy indicators | [] |
|
||||||
|
| Global efficacy | {} |
|
||||||
|
+---------------------+--------------------------------------+
|
||||||
|
|
||||||
|
$ openstack optimize actionplan list
|
||||||
|
+--------------------------------------+--------------------------------------+-----------+---------------------------+-----------------+
|
||||||
|
| UUID | Audit | State | Updated At | Global efficacy |
|
||||||
|
+--------------------------------------+--------------------------------------+-----------+---------------------------+-----------------+
|
||||||
|
| ba9ce6b3-969c-4b8e-bb61-ae24e8630f81 | e94d4826-ad4e-44df-ad93-dff489fde457 | SUCCEEDED | 2017-05-23T11:53:16+00:00 | None |
|
||||||
|
+--------------------------------------+--------------------------------------+-----------+---------------------------+-----------------+
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Adds feature to cancel an action-plan.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Add notifications related to Action plan object.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Add notifications related to Audit object.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Watcher can continuously optimize the OpenStack cloud for a specific
|
||||||
|
strategy or goal by triggering an audit periodically which generates
|
||||||
|
an action plan and run it automatically.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Centralize all configuration options for Watcher.
|
||||||
3
releasenotes/notes/db-migration-e1a705a8b54ccdd2.yaml
Normal file
3
releasenotes/notes/db-migration-e1a705a8b54ccdd2.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Watcher database can now be upgraded thanks to Alembic.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Provides a generic way to define the scope of an audit. The set of audited
|
||||||
|
resources will be called "Audit scope" and will be defined in each audit
|
||||||
|
template (which contains the audit settings).
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- The graph model describes how VMs are associated to compute hosts.
|
||||||
|
This allows for seeing relationships upfront between the entities and hence
|
||||||
|
can be used to identify hot/cold spots in the data center and influence
|
||||||
|
a strategy decision.
|
||||||
4
releasenotes/notes/monasca-support-0b0486b8572ac38b.yaml
Normal file
4
releasenotes/notes/monasca-support-0b0486b8572ac38b.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Watcher supports multiple metrics backend and relies on Ceilometer and
|
||||||
|
Monasca.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Watcher can now run specific actions in parallel improving the performances
|
||||||
|
dramatically when executing an action plan.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Check the creation time of the action plan,
|
||||||
|
and set its state to SUPERSEDED if it has expired.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Added SUSPENDED audit state
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Provide a notification mechanism into Watcher that supports versioning.
|
||||||
|
Whenever a Watcher object is created, updated or deleted, a versioned
|
||||||
|
notification will, if it's relevant, be automatically sent to notify in order
|
||||||
|
to allow an event-driven style of architecture within Watcher. Moreover, it
|
||||||
|
will also give other services and/or 3rd party softwares (e.g. monitoring
|
||||||
|
solutions or rules engines) the ability to react to such events.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Add a service supervisor to watch Watcher deamons.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- all Watcher objects have been refactored to support OVO
|
||||||
|
(oslo.versionedobjects) which was a prerequisite step in order to implement
|
||||||
|
versioned notifications.
|
||||||
@@ -1,5 +1,16 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
#
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
# watcher documentation build configuration file, created by
|
# watcher documentation build configuration file, created by
|
||||||
# sphinx-quickstart on Fri Jun 3 11:37:52 2016.
|
# sphinx-quickstart on Fri Jun 3 11:37:52 2016.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,17 @@
|
|||||||
|
..
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
not use this file except in compliance with the License. You may obtain
|
||||||
|
a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
License for the specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
|
||||||
|
=================================================
|
||||||
Welcome to watcher's Release Notes documentation!
|
Welcome to watcher's Release Notes documentation!
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
@@ -7,5 +21,6 @@ Contents:
|
|||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
unreleased
|
unreleased
|
||||||
|
ocata
|
||||||
newton
|
newton
|
||||||
|
|
||||||
|
|||||||
33
releasenotes/source/locale/fr/LC_MESSAGES/releasenotes.po
Normal file
33
releasenotes/source/locale/fr/LC_MESSAGES/releasenotes.po
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Gérald LONLAS <g.lonlas@gmail.com>, 2016. #zanata
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: watcher 1.0.1.dev51\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2017-03-21 11:57+0000\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"PO-Revision-Date: 2016-10-22 06:44+0000\n"
|
||||||
|
"Last-Translator: Gérald LONLAS <g.lonlas@gmail.com>\n"
|
||||||
|
"Language-Team: French\n"
|
||||||
|
"Language: fr\n"
|
||||||
|
"X-Generator: Zanata 3.9.6\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
|
||||||
|
|
||||||
|
msgid "0.29.0"
|
||||||
|
msgstr "0.29.0"
|
||||||
|
|
||||||
|
msgid "Contents:"
|
||||||
|
msgstr "Contenu :"
|
||||||
|
|
||||||
|
msgid "Current Series Release Notes"
|
||||||
|
msgstr "Note de la release actuelle"
|
||||||
|
|
||||||
|
msgid "New Features"
|
||||||
|
msgstr "Nouvelles fonctionnalités"
|
||||||
|
|
||||||
|
msgid "Newton Series Release Notes"
|
||||||
|
msgstr "Note de release pour Newton"
|
||||||
|
|
||||||
|
msgid "Welcome to watcher's Release Notes documentation!"
|
||||||
|
msgstr "Bienvenue dans la documentation de la note de Release de Watcher"
|
||||||
6
releasenotes/source/ocata.rst
Normal file
6
releasenotes/source/ocata.rst
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
===================================
|
||||||
|
Ocata Series Release Notes
|
||||||
|
===================================
|
||||||
|
|
||||||
|
.. release-notes::
|
||||||
|
:branch: origin/stable/ocata
|
||||||
@@ -5,38 +5,43 @@
|
|||||||
apscheduler # MIT License
|
apscheduler # MIT License
|
||||||
enum34;python_version=='2.7' or python_version=='2.6' or python_version=='3.3' # BSD
|
enum34;python_version=='2.7' or python_version=='2.6' or python_version=='3.3' # BSD
|
||||||
jsonpatch>=1.1 # BSD
|
jsonpatch>=1.1 # BSD
|
||||||
keystoneauth1>=2.14.0 # Apache-2.0
|
keystoneauth1>=2.20.0 # Apache-2.0
|
||||||
keystonemiddleware!=4.5.0,>=4.2.0 # Apache-2.0
|
keystonemiddleware>=4.12.0 # Apache-2.0
|
||||||
lxml>=2.3 # BSD
|
lxml!=3.7.0,>=2.3 # BSD
|
||||||
oslo.concurrency>=3.8.0 # Apache-2.0
|
oslo.concurrency>=3.8.0 # Apache-2.0
|
||||||
oslo.cache>=1.5.0 # Apache-2.0
|
oslo.cache>=1.5.0 # Apache-2.0
|
||||||
oslo.config!=3.18.0,>=3.14.0 # Apache-2.0
|
oslo.config>=4.0.0 # Apache-2.0
|
||||||
oslo.context>=2.9.0 # Apache-2.0
|
oslo.context>=2.14.0 # Apache-2.0
|
||||||
oslo.db!=4.13.1,!=4.13.2,>=4.11.0 # Apache-2.0
|
oslo.db>=4.21.1 # Apache-2.0
|
||||||
oslo.i18n>=2.1.0 # Apache-2.0
|
oslo.i18n!=3.15.2,>=2.1.0 # Apache-2.0
|
||||||
oslo.log>=3.11.0 # Apache-2.0
|
oslo.log>=3.22.0 # Apache-2.0
|
||||||
oslo.messaging>=5.14.0 # Apache-2.0
|
oslo.messaging!=5.25.0,>=5.24.2 # Apache-2.0
|
||||||
oslo.policy>=1.17.0 # Apache-2.0
|
oslo.policy>=1.17.0 # Apache-2.0
|
||||||
oslo.reports>=0.6.0 # Apache-2.0
|
oslo.reports>=0.6.0 # Apache-2.0
|
||||||
oslo.serialization>=1.10.0 # Apache-2.0
|
oslo.serialization>=1.10.0 # Apache-2.0
|
||||||
oslo.service>=1.10.0 # Apache-2.0
|
oslo.service>=1.10.0 # Apache-2.0
|
||||||
oslo.utils>=3.18.0 # Apache-2.0
|
oslo.utils>=3.20.0 # Apache-2.0
|
||||||
oslo.versionedobjects>=1.17.0 # Apache-2.0
|
oslo.versionedobjects>=1.17.0 # Apache-2.0
|
||||||
PasteDeploy>=1.5.0 # MIT
|
PasteDeploy>=1.5.0 # MIT
|
||||||
pbr>=1.8 # Apache-2.0
|
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
||||||
pecan!=1.0.2,!=1.0.3,!=1.0.4,!=1.2,>=1.0.0 # BSD
|
pecan!=1.0.2,!=1.0.3,!=1.0.4,!=1.2,>=1.0.0 # BSD
|
||||||
PrettyTable<0.8,>=0.7.1 # BSD
|
PrettyTable<0.8,>=0.7.1 # BSD
|
||||||
voluptuous>=0.8.9 # BSD License
|
voluptuous>=0.8.9 # BSD License
|
||||||
|
gnocchiclient>=2.7.0 # Apache-2.0
|
||||||
python-ceilometerclient>=2.5.0 # Apache-2.0
|
python-ceilometerclient>=2.5.0 # Apache-2.0
|
||||||
python-cinderclient!=1.7.0,!=1.7.1,>=1.6.0 # Apache-2.0
|
python-cinderclient>=2.1.0 # Apache-2.0
|
||||||
python-glanceclient>=2.5.0 # Apache-2.0
|
python-glanceclient>=2.7.0 # Apache-2.0
|
||||||
python-keystoneclient>=3.8.0 # Apache-2.0
|
python-keystoneclient>=3.8.0 # Apache-2.0
|
||||||
python-neutronclient>=5.1.0 # Apache-2.0
|
python-monascaclient>=1.1.0 # Apache-2.0
|
||||||
python-novaclient!=2.33.0,>=2.29.0 # Apache-2.0
|
python-neutronclient>=6.3.0 # Apache-2.0
|
||||||
python-openstackclient>=3.3.0 # Apache-2.0
|
python-novaclient>=7.1.0 # Apache-2.0
|
||||||
|
python-openstackclient!=3.10.0,>=3.3.0 # Apache-2.0
|
||||||
|
python-ironicclient>=1.11.0 # Apache-2.0
|
||||||
six>=1.9.0 # MIT
|
six>=1.9.0 # MIT
|
||||||
SQLAlchemy<1.1.0,>=1.0.10 # MIT
|
SQLAlchemy!=1.1.5,!=1.1.6,!=1.1.7,!=1.1.8,>=1.0.10 # MIT
|
||||||
stevedore>=1.17.1 # Apache-2.0
|
stevedore>=1.20.0 # Apache-2.0
|
||||||
taskflow>=1.26.0 # Apache-2.0
|
taskflow>=2.7.0 # Apache-2.0
|
||||||
WebOb>=1.6.0 # MIT
|
WebOb>=1.7.1 # MIT
|
||||||
WSME>=0.8 # MIT
|
WSME>=0.8 # MIT
|
||||||
|
networkx>=1.10 # BSD
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ classifier =
|
|||||||
Programming Language :: Python :: 2
|
Programming Language :: Python :: 2
|
||||||
Programming Language :: Python :: 2.7
|
Programming Language :: Python :: 2.7
|
||||||
Programming Language :: Python :: 3
|
Programming Language :: Python :: 3
|
||||||
Programming Language :: Python :: 3.4
|
|
||||||
Programming Language :: Python :: 3.5
|
Programming Language :: Python :: 3.5
|
||||||
|
|
||||||
[files]
|
[files]
|
||||||
@@ -64,6 +63,7 @@ watcher_scoring_engine_containers =
|
|||||||
watcher_strategies =
|
watcher_strategies =
|
||||||
dummy = watcher.decision_engine.strategy.strategies.dummy_strategy:DummyStrategy
|
dummy = watcher.decision_engine.strategy.strategies.dummy_strategy:DummyStrategy
|
||||||
dummy_with_scorer = watcher.decision_engine.strategy.strategies.dummy_with_scorer:DummyWithScorer
|
dummy_with_scorer = watcher.decision_engine.strategy.strategies.dummy_with_scorer:DummyWithScorer
|
||||||
|
dummy_with_resize = watcher.decision_engine.strategy.strategies.dummy_with_resize:DummyWithResize
|
||||||
basic = watcher.decision_engine.strategy.strategies.basic_consolidation:BasicConsolidation
|
basic = watcher.decision_engine.strategy.strategies.basic_consolidation:BasicConsolidation
|
||||||
outlet_temperature = watcher.decision_engine.strategy.strategies.outlet_temp_control:OutletTempControl
|
outlet_temperature = watcher.decision_engine.strategy.strategies.outlet_temp_control:OutletTempControl
|
||||||
vm_workload_consolidation = watcher.decision_engine.strategy.strategies.vm_workload_consolidation:VMWorkloadConsolidation
|
vm_workload_consolidation = watcher.decision_engine.strategy.strategies.vm_workload_consolidation:VMWorkloadConsolidation
|
||||||
@@ -76,12 +76,14 @@ watcher_actions =
|
|||||||
nop = watcher.applier.actions.nop:Nop
|
nop = watcher.applier.actions.nop:Nop
|
||||||
sleep = watcher.applier.actions.sleep:Sleep
|
sleep = watcher.applier.actions.sleep:Sleep
|
||||||
change_nova_service_state = watcher.applier.actions.change_nova_service_state:ChangeNovaServiceState
|
change_nova_service_state = watcher.applier.actions.change_nova_service_state:ChangeNovaServiceState
|
||||||
|
resize = watcher.applier.actions.resize:Resize
|
||||||
|
|
||||||
watcher_workflow_engines =
|
watcher_workflow_engines =
|
||||||
taskflow = watcher.applier.workflow_engine.default:DefaultWorkFlowEngine
|
taskflow = watcher.applier.workflow_engine.default:DefaultWorkFlowEngine
|
||||||
|
|
||||||
watcher_planners =
|
watcher_planners =
|
||||||
default = watcher.decision_engine.planner.default:DefaultPlanner
|
weight = watcher.decision_engine.planner.weight:WeightPlanner
|
||||||
|
workload_stabilization = watcher.decision_engine.planner.workload_stabilization:WorkloadStabilizationPlanner
|
||||||
|
|
||||||
watcher_cluster_data_model_collectors =
|
watcher_cluster_data_model_collectors =
|
||||||
compute = watcher.decision_engine.model.collector.nova:NovaClusterDataModelCollector
|
compute = watcher.decision_engine.model.collector.nova:NovaClusterDataModelCollector
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -25,5 +25,5 @@ except ImportError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
setuptools.setup(
|
setuptools.setup(
|
||||||
setup_requires=['pbr>=1.8'],
|
setup_requires=['pbr>=2.0.0'],
|
||||||
pbr=True)
|
pbr=True)
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
# of appearance. Changing the order has an impact on the overall integration
|
# of appearance. Changing the order has an impact on the overall integration
|
||||||
# process, which may cause wedges in the gate later.
|
# process, which may cause wedges in the gate later.
|
||||||
|
|
||||||
coverage>=4.0 # Apache-2.0
|
coverage!=4.4,>=4.0 # Apache-2.0
|
||||||
doc8 # Apache-2.0
|
doc8 # Apache-2.0
|
||||||
freezegun>=0.3.6 # Apache-2.0
|
freezegun>=0.3.6 # Apache-2.0
|
||||||
hacking<0.11,>=0.10.2
|
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
|
||||||
mock>=2.0 # BSD
|
mock>=2.0 # BSD
|
||||||
oslotest>=1.10.0 # Apache-2.0
|
oslotest>=1.10.0 # Apache-2.0
|
||||||
os-testr>=0.8.0 # Apache-2.0
|
os-testr>=0.8.0 # Apache-2.0
|
||||||
@@ -15,12 +15,14 @@ testscenarios>=0.4 # Apache-2.0/BSD
|
|||||||
testtools>=1.4.0 # MIT
|
testtools>=1.4.0 # MIT
|
||||||
|
|
||||||
# Doc requirements
|
# Doc requirements
|
||||||
|
openstackdocstheme>=1.5.0 # Apache-2.0
|
||||||
oslosphinx>=4.7.0 # Apache-2.0
|
oslosphinx>=4.7.0 # Apache-2.0
|
||||||
sphinx!=1.3b1,<1.4,>=1.2.1 # BSD
|
sphinx!=1.6.1,>=1.5.1 # BSD
|
||||||
sphinxcontrib-pecanwsme>=0.8 # Apache-2.0
|
sphinxcontrib-pecanwsme>=0.8 # Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
# releasenotes
|
# releasenotes
|
||||||
reno>=1.8.0 # Apache-2.0
|
reno!=2.3.1,>=1.8.0 # Apache-2.0
|
||||||
|
|
||||||
# bandit
|
# bandit
|
||||||
bandit>=1.1.0 # Apache-2.0
|
bandit>=1.1.0 # Apache-2.0
|
||||||
|
|||||||
19
tox.ini
19
tox.ini
@@ -1,18 +1,18 @@
|
|||||||
[tox]
|
[tox]
|
||||||
minversion = 1.8
|
minversion = 1.8
|
||||||
envlist = py35,py34,py27,pep8
|
envlist = py35,py27,pep8
|
||||||
skipsdist = True
|
skipsdist = True
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
usedevelop = True
|
usedevelop = True
|
||||||
whitelist_externals = find
|
whitelist_externals = find
|
||||||
install_command =
|
rm
|
||||||
pip install -U --force-reinstall -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
|
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
|
||||||
|
|
||||||
setenv =
|
setenv =
|
||||||
VIRTUAL_ENV={envdir}
|
VIRTUAL_ENV={envdir}
|
||||||
deps = -r{toxinidir}/test-requirements.txt
|
deps = -r{toxinidir}/test-requirements.txt
|
||||||
commands =
|
commands =
|
||||||
|
rm -f .testrepository/times.dbm
|
||||||
find . -type f -name "*.py[c|o]" -delete
|
find . -type f -name "*.py[c|o]" -delete
|
||||||
ostestr --concurrency=6 {posargs}
|
ostestr --concurrency=6 {posargs}
|
||||||
|
|
||||||
@@ -27,7 +27,9 @@ setenv = PYTHONHASHSEED=0
|
|||||||
commands = {posargs}
|
commands = {posargs}
|
||||||
|
|
||||||
[testenv:cover]
|
[testenv:cover]
|
||||||
commands = python setup.py testr --coverage --testr-args='{posargs}'
|
commands =
|
||||||
|
python setup.py testr --coverage --testr-args='{posargs}'
|
||||||
|
coverage report
|
||||||
|
|
||||||
[testenv:docs]
|
[testenv:docs]
|
||||||
setenv = PYTHONHASHSEED=0
|
setenv = PYTHONHASHSEED=0
|
||||||
@@ -38,14 +40,14 @@ commands =
|
|||||||
[testenv:debug]
|
[testenv:debug]
|
||||||
commands = oslo_debug_helper -t watcher/tests {posargs}
|
commands = oslo_debug_helper -t watcher/tests {posargs}
|
||||||
|
|
||||||
[testenv:config]
|
[testenv:genconfig]
|
||||||
sitepackages = False
|
sitepackages = False
|
||||||
commands =
|
commands =
|
||||||
oslo-config-generator --config-file etc/watcher/watcher-config-generator.conf
|
oslo-config-generator --config-file etc/watcher/watcher-config-generator.conf
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
show-source=True
|
show-source=True
|
||||||
ignore=
|
ignore= H105,E123,E226,N320
|
||||||
builtins= _
|
builtins= _
|
||||||
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,*sqlalchemy/alembic/versions/*,demo/,releasenotes
|
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,*sqlalchemy/alembic/versions/*,demo/,releasenotes
|
||||||
|
|
||||||
@@ -67,3 +69,6 @@ commands = sphinx-build -a -W -E -d releasenotes/build/doctrees -b html releasen
|
|||||||
[testenv:bandit]
|
[testenv:bandit]
|
||||||
deps = -r{toxinidir}/test-requirements.txt
|
deps = -r{toxinidir}/test-requirements.txt
|
||||||
commands = bandit -r watcher -x tests -n5 -ll -s B320
|
commands = bandit -r watcher -x tests -n5 -ll -s B320
|
||||||
|
|
||||||
|
[testenv:install-guide]
|
||||||
|
commands = sphinx-build -a -E -W -d install-guide/build/doctrees -b html install-guide/source install-guide/build/html
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
|
|||||||
40
watcher/api/app.wsgi
Normal file
40
watcher/api/app.wsgi
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# -*- mode: python -*-
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
"""
|
||||||
|
Use this file for deploying the API service under Apache2 mod_wsgi.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
import oslo_i18n as i18n
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
|
from watcher.api import app
|
||||||
|
from watcher.common import service
|
||||||
|
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
i18n.install('watcher')
|
||||||
|
|
||||||
|
service.prepare_service(sys.argv)
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
LOG.debug("Configuration:")
|
||||||
|
CONF.log_opt_values(LOG, log.DEBUG)
|
||||||
|
|
||||||
|
application = app.VersionSelectorApplication()
|
||||||
|
|
||||||
@@ -88,7 +88,6 @@ class Action(base.APIBase):
|
|||||||
between the internal object model and the API representation of a action.
|
between the internal object model and the API representation of a action.
|
||||||
"""
|
"""
|
||||||
_action_plan_uuid = None
|
_action_plan_uuid = None
|
||||||
_next_uuid = None
|
|
||||||
|
|
||||||
def _get_action_plan_uuid(self):
|
def _get_action_plan_uuid(self):
|
||||||
return self._action_plan_uuid
|
return self._action_plan_uuid
|
||||||
@@ -105,22 +104,6 @@ class Action(base.APIBase):
|
|||||||
except exception.ActionPlanNotFound:
|
except exception.ActionPlanNotFound:
|
||||||
self._action_plan_uuid = None
|
self._action_plan_uuid = None
|
||||||
|
|
||||||
def _get_next_uuid(self):
|
|
||||||
return self._next_uuid
|
|
||||||
|
|
||||||
def _set_next_uuid(self, value):
|
|
||||||
if value == wtypes.Unset:
|
|
||||||
self._next_uuid = wtypes.Unset
|
|
||||||
elif value and self._next_uuid != value:
|
|
||||||
try:
|
|
||||||
action_next = objects.Action.get(
|
|
||||||
pecan.request.context, value)
|
|
||||||
self._next_uuid = action_next.uuid
|
|
||||||
self.next = action_next.id
|
|
||||||
except exception.ActionNotFound:
|
|
||||||
self.action_next_uuid = None
|
|
||||||
# raise e
|
|
||||||
|
|
||||||
uuid = wtypes.wsattr(types.uuid, readonly=True)
|
uuid = wtypes.wsattr(types.uuid, readonly=True)
|
||||||
"""Unique UUID for this action"""
|
"""Unique UUID for this action"""
|
||||||
|
|
||||||
@@ -138,10 +121,8 @@ class Action(base.APIBase):
|
|||||||
input_parameters = types.jsontype
|
input_parameters = types.jsontype
|
||||||
"""One or more key/value pairs """
|
"""One or more key/value pairs """
|
||||||
|
|
||||||
next_uuid = wsme.wsproperty(types.uuid, _get_next_uuid,
|
parents = wtypes.wsattr(types.jsontype, readonly=True)
|
||||||
_set_next_uuid,
|
"""UUIDs of parent actions"""
|
||||||
mandatory=True)
|
|
||||||
"""This next action UUID"""
|
|
||||||
|
|
||||||
links = wsme.wsattr([link.Link], readonly=True)
|
links = wsme.wsattr([link.Link], readonly=True)
|
||||||
"""A list containing a self link and associated action links"""
|
"""A list containing a self link and associated action links"""
|
||||||
@@ -152,7 +133,6 @@ class Action(base.APIBase):
|
|||||||
self.fields = []
|
self.fields = []
|
||||||
fields = list(objects.Action.fields)
|
fields = list(objects.Action.fields)
|
||||||
fields.append('action_plan_uuid')
|
fields.append('action_plan_uuid')
|
||||||
fields.append('next_uuid')
|
|
||||||
for field in fields:
|
for field in fields:
|
||||||
# Skip fields we do not expose.
|
# Skip fields we do not expose.
|
||||||
if not hasattr(self, field):
|
if not hasattr(self, field):
|
||||||
@@ -163,15 +143,13 @@ class Action(base.APIBase):
|
|||||||
self.fields.append('action_plan_id')
|
self.fields.append('action_plan_id')
|
||||||
setattr(self, 'action_plan_uuid', kwargs.get('action_plan_id',
|
setattr(self, 'action_plan_uuid', kwargs.get('action_plan_id',
|
||||||
wtypes.Unset))
|
wtypes.Unset))
|
||||||
setattr(self, 'next_uuid', kwargs.get('next',
|
|
||||||
wtypes.Unset))
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _convert_with_links(action, url, expand=True):
|
def _convert_with_links(action, url, expand=True):
|
||||||
if not expand:
|
if not expand:
|
||||||
action.unset_fields_except(['uuid', 'state', 'next', 'next_uuid',
|
action.unset_fields_except(['uuid', 'state', 'action_plan_uuid',
|
||||||
'action_plan_uuid', 'action_plan_id',
|
'action_plan_id', 'action_type',
|
||||||
'action_type'])
|
'parents'])
|
||||||
|
|
||||||
action.links = [link.Link.make_link('self', url,
|
action.links = [link.Link.make_link('self', url,
|
||||||
'actions', action.uuid),
|
'actions', action.uuid),
|
||||||
@@ -193,9 +171,9 @@ class Action(base.APIBase):
|
|||||||
state='PENDING',
|
state='PENDING',
|
||||||
created_at=datetime.datetime.utcnow(),
|
created_at=datetime.datetime.utcnow(),
|
||||||
deleted_at=None,
|
deleted_at=None,
|
||||||
updated_at=datetime.datetime.utcnow())
|
updated_at=datetime.datetime.utcnow(),
|
||||||
|
parents=[])
|
||||||
sample._action_plan_uuid = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae'
|
sample._action_plan_uuid = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae'
|
||||||
sample._next_uuid = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae'
|
|
||||||
return cls._convert_with_links(sample, 'http://localhost:9322', expand)
|
return cls._convert_with_links(sample, 'http://localhost:9322', expand)
|
||||||
|
|
||||||
|
|
||||||
@@ -216,17 +194,6 @@ class ActionCollection(collection.Collection):
|
|||||||
collection.actions = [Action.convert_with_links(p, expand)
|
collection.actions = [Action.convert_with_links(p, expand)
|
||||||
for p in actions]
|
for p in actions]
|
||||||
|
|
||||||
if 'sort_key' in kwargs:
|
|
||||||
reverse = False
|
|
||||||
if kwargs['sort_key'] == 'next_uuid':
|
|
||||||
if 'sort_dir' in kwargs:
|
|
||||||
reverse = True if kwargs['sort_dir'] == 'desc' else False
|
|
||||||
collection.actions = sorted(
|
|
||||||
collection.actions,
|
|
||||||
key=lambda action: action.next_uuid or '',
|
|
||||||
reverse=reverse)
|
|
||||||
|
|
||||||
collection.next = collection.get_next(limit, url=url, **kwargs)
|
|
||||||
return collection
|
return collection
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -268,10 +235,7 @@ class ActionsController(rest.RestController):
|
|||||||
if audit_uuid:
|
if audit_uuid:
|
||||||
filters['audit_uuid'] = audit_uuid
|
filters['audit_uuid'] = audit_uuid
|
||||||
|
|
||||||
if sort_key == 'next_uuid':
|
sort_db_key = sort_key
|
||||||
sort_db_key = None
|
|
||||||
else:
|
|
||||||
sort_db_key = sort_key
|
|
||||||
|
|
||||||
actions = objects.Action.list(pecan.request.context,
|
actions = objects.Action.list(pecan.request.context,
|
||||||
limit,
|
limit,
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ class ActionPlanPatchType(types.JsonPatchType):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def mandatory_attrs():
|
def mandatory_attrs():
|
||||||
return ["audit_id", "state", "first_action_id"]
|
return ["audit_id", "state"]
|
||||||
|
|
||||||
|
|
||||||
class ActionPlan(base.APIBase):
|
class ActionPlan(base.APIBase):
|
||||||
@@ -120,7 +120,6 @@ class ActionPlan(base.APIBase):
|
|||||||
_audit_uuid = None
|
_audit_uuid = None
|
||||||
_strategy_uuid = None
|
_strategy_uuid = None
|
||||||
_strategy_name = None
|
_strategy_name = None
|
||||||
_first_action_uuid = None
|
|
||||||
_efficacy_indicators = None
|
_efficacy_indicators = None
|
||||||
|
|
||||||
def _get_audit_uuid(self):
|
def _get_audit_uuid(self):
|
||||||
@@ -137,21 +136,6 @@ class ActionPlan(base.APIBase):
|
|||||||
except exception.AuditNotFound:
|
except exception.AuditNotFound:
|
||||||
self._audit_uuid = None
|
self._audit_uuid = None
|
||||||
|
|
||||||
def _get_first_action_uuid(self):
|
|
||||||
return self._first_action_uuid
|
|
||||||
|
|
||||||
def _set_first_action_uuid(self, value):
|
|
||||||
if value == wtypes.Unset:
|
|
||||||
self._first_action_uuid = wtypes.Unset
|
|
||||||
elif value and self._first_action_uuid != value:
|
|
||||||
try:
|
|
||||||
first_action = objects.Action.get(pecan.request.context,
|
|
||||||
value)
|
|
||||||
self._first_action_uuid = first_action.uuid
|
|
||||||
self.first_action_id = first_action.id
|
|
||||||
except exception.ActionNotFound:
|
|
||||||
self._first_action_uuid = None
|
|
||||||
|
|
||||||
def _get_efficacy_indicators(self):
|
def _get_efficacy_indicators(self):
|
||||||
if self._efficacy_indicators is None:
|
if self._efficacy_indicators is None:
|
||||||
self._set_efficacy_indicators(wtypes.Unset)
|
self._set_efficacy_indicators(wtypes.Unset)
|
||||||
@@ -220,11 +204,6 @@ class ActionPlan(base.APIBase):
|
|||||||
uuid = wtypes.wsattr(types.uuid, readonly=True)
|
uuid = wtypes.wsattr(types.uuid, readonly=True)
|
||||||
"""Unique UUID for this action plan"""
|
"""Unique UUID for this action plan"""
|
||||||
|
|
||||||
first_action_uuid = wsme.wsproperty(
|
|
||||||
types.uuid, _get_first_action_uuid, _set_first_action_uuid,
|
|
||||||
mandatory=True)
|
|
||||||
"""The UUID of the first action this action plans links to"""
|
|
||||||
|
|
||||||
audit_uuid = wsme.wsproperty(types.uuid, _get_audit_uuid, _set_audit_uuid,
|
audit_uuid = wsme.wsproperty(types.uuid, _get_audit_uuid, _set_audit_uuid,
|
||||||
mandatory=True)
|
mandatory=True)
|
||||||
"""The UUID of the audit this port belongs to"""
|
"""The UUID of the audit this port belongs to"""
|
||||||
@@ -263,7 +242,6 @@ class ActionPlan(base.APIBase):
|
|||||||
setattr(self, field, kwargs.get(field, wtypes.Unset))
|
setattr(self, field, kwargs.get(field, wtypes.Unset))
|
||||||
|
|
||||||
self.fields.append('audit_uuid')
|
self.fields.append('audit_uuid')
|
||||||
self.fields.append('first_action_uuid')
|
|
||||||
self.fields.append('efficacy_indicators')
|
self.fields.append('efficacy_indicators')
|
||||||
|
|
||||||
setattr(self, 'audit_uuid', kwargs.get('audit_id', wtypes.Unset))
|
setattr(self, 'audit_uuid', kwargs.get('audit_id', wtypes.Unset))
|
||||||
@@ -271,16 +249,13 @@ class ActionPlan(base.APIBase):
|
|||||||
setattr(self, 'strategy_uuid', kwargs.get('strategy_id', wtypes.Unset))
|
setattr(self, 'strategy_uuid', kwargs.get('strategy_id', wtypes.Unset))
|
||||||
fields.append('strategy_name')
|
fields.append('strategy_name')
|
||||||
setattr(self, 'strategy_name', kwargs.get('strategy_id', wtypes.Unset))
|
setattr(self, 'strategy_name', kwargs.get('strategy_id', wtypes.Unset))
|
||||||
setattr(self, 'first_action_uuid',
|
|
||||||
kwargs.get('first_action_id', wtypes.Unset))
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _convert_with_links(action_plan, url, expand=True):
|
def _convert_with_links(action_plan, url, expand=True):
|
||||||
if not expand:
|
if not expand:
|
||||||
action_plan.unset_fields_except(
|
action_plan.unset_fields_except(
|
||||||
['uuid', 'state', 'efficacy_indicators', 'global_efficacy',
|
['uuid', 'state', 'efficacy_indicators', 'global_efficacy',
|
||||||
'updated_at', 'audit_uuid', 'strategy_uuid', 'strategy_name',
|
'updated_at', 'audit_uuid', 'strategy_uuid', 'strategy_name'])
|
||||||
'first_action_uuid'])
|
|
||||||
|
|
||||||
action_plan.links = [
|
action_plan.links = [
|
||||||
link.Link.make_link(
|
link.Link.make_link(
|
||||||
@@ -305,7 +280,6 @@ class ActionPlan(base.APIBase):
|
|||||||
created_at=datetime.datetime.utcnow(),
|
created_at=datetime.datetime.utcnow(),
|
||||||
deleted_at=None,
|
deleted_at=None,
|
||||||
updated_at=datetime.datetime.utcnow())
|
updated_at=datetime.datetime.utcnow())
|
||||||
sample._first_action_uuid = '57eaf9ab-5aaa-4f7e-bdf7-9a140ac7a720'
|
|
||||||
sample._audit_uuid = 'abcee106-14d3-4515-b744-5a26885cf6f6'
|
sample._audit_uuid = 'abcee106-14d3-4515-b744-5a26885cf6f6'
|
||||||
sample._efficacy_indicators = [{'description': 'Test indicator',
|
sample._efficacy_indicators = [{'description': 'Test indicator',
|
||||||
'name': 'test_indicator',
|
'name': 'test_indicator',
|
||||||
@@ -481,7 +455,8 @@ class ActionPlansController(rest.RestController):
|
|||||||
:param action_plan_uuid: UUID of a action.
|
:param action_plan_uuid: UUID of a action.
|
||||||
"""
|
"""
|
||||||
context = pecan.request.context
|
context = pecan.request.context
|
||||||
action_plan = api_utils.get_resource('ActionPlan', action_plan_uuid)
|
action_plan = api_utils.get_resource(
|
||||||
|
'ActionPlan', action_plan_uuid, eager=True)
|
||||||
policy.enforce(context, 'action_plan:delete', action_plan,
|
policy.enforce(context, 'action_plan:delete', action_plan,
|
||||||
action='action_plan:delete')
|
action='action_plan:delete')
|
||||||
|
|
||||||
@@ -500,8 +475,8 @@ class ActionPlansController(rest.RestController):
|
|||||||
raise exception.OperationNotPermitted
|
raise exception.OperationNotPermitted
|
||||||
|
|
||||||
context = pecan.request.context
|
context = pecan.request.context
|
||||||
action_plan_to_update = api_utils.get_resource('ActionPlan',
|
action_plan_to_update = api_utils.get_resource(
|
||||||
action_plan_uuid)
|
'ActionPlan', action_plan_uuid, eager=True)
|
||||||
policy.enforce(context, 'action_plan:update', action_plan_to_update,
|
policy.enforce(context, 'action_plan:update', action_plan_to_update,
|
||||||
action='action_plan:update')
|
action='action_plan:update')
|
||||||
|
|
||||||
@@ -513,6 +488,7 @@ class ActionPlansController(rest.RestController):
|
|||||||
raise exception.PatchError(patch=patch, reason=e)
|
raise exception.PatchError(patch=patch, reason=e)
|
||||||
|
|
||||||
launch_action_plan = False
|
launch_action_plan = False
|
||||||
|
cancel_action_plan = False
|
||||||
|
|
||||||
# transitions that are allowed via PATCH
|
# transitions that are allowed via PATCH
|
||||||
allowed_patch_transitions = [
|
allowed_patch_transitions = [
|
||||||
@@ -521,7 +497,7 @@ class ActionPlansController(rest.RestController):
|
|||||||
(ap_objects.State.RECOMMENDED,
|
(ap_objects.State.RECOMMENDED,
|
||||||
ap_objects.State.CANCELLED),
|
ap_objects.State.CANCELLED),
|
||||||
(ap_objects.State.ONGOING,
|
(ap_objects.State.ONGOING,
|
||||||
ap_objects.State.CANCELLED),
|
ap_objects.State.CANCELLING),
|
||||||
(ap_objects.State.PENDING,
|
(ap_objects.State.PENDING,
|
||||||
ap_objects.State.CANCELLED),
|
ap_objects.State.CANCELLED),
|
||||||
]
|
]
|
||||||
@@ -540,6 +516,8 @@ class ActionPlansController(rest.RestController):
|
|||||||
|
|
||||||
if action_plan.state == ap_objects.State.PENDING:
|
if action_plan.state == ap_objects.State.PENDING:
|
||||||
launch_action_plan = True
|
launch_action_plan = True
|
||||||
|
if action_plan.state == ap_objects.State.CANCELLED:
|
||||||
|
cancel_action_plan = True
|
||||||
|
|
||||||
# Update only the fields that have changed
|
# Update only the fields that have changed
|
||||||
for field in objects.ActionPlan.fields:
|
for field in objects.ActionPlan.fields:
|
||||||
@@ -559,6 +537,16 @@ class ActionPlansController(rest.RestController):
|
|||||||
|
|
||||||
action_plan_to_update.save()
|
action_plan_to_update.save()
|
||||||
|
|
||||||
|
# NOTE: if action plan is cancelled from pending or recommended
|
||||||
|
# state update action state here only
|
||||||
|
if cancel_action_plan:
|
||||||
|
filters = {'action_plan_uuid': action_plan.uuid}
|
||||||
|
actions = objects.Action.list(pecan.request.context,
|
||||||
|
filters=filters, eager=True)
|
||||||
|
for a in actions:
|
||||||
|
a.state = objects.action.State.CANCELLED
|
||||||
|
a.save()
|
||||||
|
|
||||||
if launch_action_plan:
|
if launch_action_plan:
|
||||||
applier_client = rpcapi.ApplierAPI()
|
applier_client = rpcapi.ApplierAPI()
|
||||||
applier_client.launch_action_plan(pecan.request.context,
|
applier_client.launch_action_plan(pecan.request.context,
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ class AuditPostType(wtypes.Base):
|
|||||||
|
|
||||||
scope = wtypes.wsattr(types.jsontype, readonly=True)
|
scope = wtypes.wsattr(types.jsontype, readonly=True)
|
||||||
|
|
||||||
|
auto_trigger = wtypes.wsattr(bool, mandatory=False)
|
||||||
|
|
||||||
def as_audit(self, context):
|
def as_audit(self, context):
|
||||||
audit_type_values = [val.value for val in objects.audit.AuditType]
|
audit_type_values = [val.value for val in objects.audit.AuditType]
|
||||||
if self.audit_type not in audit_type_values:
|
if self.audit_type not in audit_type_values:
|
||||||
@@ -115,7 +117,8 @@ class AuditPostType(wtypes.Base):
|
|||||||
goal_id=self.goal,
|
goal_id=self.goal,
|
||||||
strategy_id=self.strategy,
|
strategy_id=self.strategy,
|
||||||
interval=self.interval,
|
interval=self.interval,
|
||||||
scope=self.scope,)
|
scope=self.scope,
|
||||||
|
auto_trigger=self.auto_trigger)
|
||||||
|
|
||||||
|
|
||||||
class AuditPatchType(types.JsonPatchType):
|
class AuditPatchType(types.JsonPatchType):
|
||||||
@@ -126,8 +129,15 @@ class AuditPatchType(types.JsonPatchType):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def validate(patch):
|
def validate(patch):
|
||||||
serialized_patch = {'path': patch.path, 'op': patch.op}
|
|
||||||
if patch.path in AuditPatchType.mandatory_attrs():
|
def is_new_state_none(p):
|
||||||
|
return p.path == '/state' and p.op == 'replace' and p.value is None
|
||||||
|
|
||||||
|
serialized_patch = {'path': patch.path,
|
||||||
|
'op': patch.op,
|
||||||
|
'value': patch.value}
|
||||||
|
if (patch.path in AuditPatchType.mandatory_attrs() or
|
||||||
|
is_new_state_none(patch)):
|
||||||
msg = _("%(field)s can't be updated.")
|
msg = _("%(field)s can't be updated.")
|
||||||
raise exception.PatchError(
|
raise exception.PatchError(
|
||||||
patch=serialized_patch,
|
patch=serialized_patch,
|
||||||
@@ -257,6 +267,9 @@ class Audit(base.APIBase):
|
|||||||
scope = wsme.wsattr(types.jsontype, mandatory=False)
|
scope = wsme.wsattr(types.jsontype, mandatory=False)
|
||||||
"""Audit Scope"""
|
"""Audit Scope"""
|
||||||
|
|
||||||
|
auto_trigger = wsme.wsattr(bool, mandatory=False, default=False)
|
||||||
|
"""Autoexecute action plan once audit is succeeded"""
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.fields = []
|
self.fields = []
|
||||||
fields = list(objects.Audit.fields)
|
fields = list(objects.Audit.fields)
|
||||||
@@ -288,7 +301,7 @@ class Audit(base.APIBase):
|
|||||||
audit.unset_fields_except(['uuid', 'audit_type', 'state',
|
audit.unset_fields_except(['uuid', 'audit_type', 'state',
|
||||||
'goal_uuid', 'interval', 'scope',
|
'goal_uuid', 'interval', 'scope',
|
||||||
'strategy_uuid', 'goal_name',
|
'strategy_uuid', 'goal_name',
|
||||||
'strategy_name'])
|
'strategy_name', 'auto_trigger'])
|
||||||
|
|
||||||
audit.links = [link.Link.make_link('self', url,
|
audit.links = [link.Link.make_link('self', url,
|
||||||
'audits', audit.uuid),
|
'audits', audit.uuid),
|
||||||
@@ -313,7 +326,8 @@ class Audit(base.APIBase):
|
|||||||
deleted_at=None,
|
deleted_at=None,
|
||||||
updated_at=datetime.datetime.utcnow(),
|
updated_at=datetime.datetime.utcnow(),
|
||||||
interval=7200,
|
interval=7200,
|
||||||
scope=[])
|
scope=[],
|
||||||
|
auto_trigger=False)
|
||||||
|
|
||||||
sample.goal_id = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae'
|
sample.goal_id = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae'
|
||||||
sample.strategy_id = '7ae81bb3-dec3-4289-8d6c-da80bd8001ff'
|
sample.strategy_id = '7ae81bb3-dec3-4289-8d6c-da80bd8001ff'
|
||||||
@@ -550,6 +564,18 @@ class AuditsController(rest.RestController):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
audit_dict = audit_to_update.as_dict()
|
audit_dict = audit_to_update.as_dict()
|
||||||
|
|
||||||
|
initial_state = audit_dict['state']
|
||||||
|
new_state = api_utils.get_patch_value(patch, 'state')
|
||||||
|
if not api_utils.check_audit_state_transition(
|
||||||
|
patch, initial_state):
|
||||||
|
error_message = _("State transition not allowed: "
|
||||||
|
"(%(initial_state)s -> %(new_state)s)")
|
||||||
|
raise exception.PatchError(
|
||||||
|
patch=patch,
|
||||||
|
reason=error_message % dict(
|
||||||
|
initial_state=initial_state, new_state=new_state))
|
||||||
|
|
||||||
audit = Audit(**api_utils.apply_jsonpatch(audit_dict, patch))
|
audit = Audit(**api_utils.apply_jsonpatch(audit_dict, patch))
|
||||||
except api_utils.JSONPATCH_EXCEPTIONS as e:
|
except api_utils.JSONPATCH_EXCEPTIONS as e:
|
||||||
raise exception.PatchError(patch=patch, reason=e)
|
raise exception.PatchError(patch=patch, reason=e)
|
||||||
|
|||||||
@@ -109,6 +109,21 @@ class AuditTemplatePostType(wtypes.Base):
|
|||||||
common_utils.Draft4Validator(
|
common_utils.Draft4Validator(
|
||||||
default.DefaultScope.DEFAULT_SCHEMA).validate(audit_template.scope)
|
default.DefaultScope.DEFAULT_SCHEMA).validate(audit_template.scope)
|
||||||
|
|
||||||
|
include_host_aggregates = False
|
||||||
|
exclude_host_aggregates = False
|
||||||
|
for rule in audit_template.scope:
|
||||||
|
if 'host_aggregates' in rule:
|
||||||
|
include_host_aggregates = True
|
||||||
|
elif 'exclude' in rule:
|
||||||
|
for resource in rule['exclude']:
|
||||||
|
if 'host_aggregates' in resource:
|
||||||
|
exclude_host_aggregates = True
|
||||||
|
if include_host_aggregates and exclude_host_aggregates:
|
||||||
|
raise exception.Invalid(
|
||||||
|
message=_(
|
||||||
|
"host_aggregates can't be "
|
||||||
|
"included and excluded together"))
|
||||||
|
|
||||||
if audit_template.strategy:
|
if audit_template.strategy:
|
||||||
available_strategies = objects.Strategy.list(
|
available_strategies = objects.Strategy.list(
|
||||||
AuditTemplatePostType._ctx)
|
AuditTemplatePostType._ctx)
|
||||||
@@ -333,6 +348,7 @@ class AuditTemplate(base.APIBase):
|
|||||||
|
|
||||||
self.fields.append('goal_id')
|
self.fields.append('goal_id')
|
||||||
self.fields.append('strategy_id')
|
self.fields.append('strategy_id')
|
||||||
|
setattr(self, 'strategy_id', kwargs.get('strategy_id', wtypes.Unset))
|
||||||
|
|
||||||
# goal_uuid & strategy_uuid are not part of
|
# goal_uuid & strategy_uuid are not part of
|
||||||
# objects.AuditTemplate.fields because they're API-only attributes.
|
# objects.AuditTemplate.fields because they're API-only attributes.
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ import wsme
|
|||||||
from wsme import types as wtypes
|
from wsme import types as wtypes
|
||||||
import wsmeext.pecan as wsme_pecan
|
import wsmeext.pecan as wsme_pecan
|
||||||
|
|
||||||
from watcher._i18n import _LW
|
|
||||||
from watcher.api.controllers import base
|
from watcher.api.controllers import base
|
||||||
from watcher.api.controllers import link
|
from watcher.api.controllers import link
|
||||||
from watcher.api.controllers.v1 import collection
|
from watcher.api.controllers.v1 import collection
|
||||||
from watcher.api.controllers.v1 import utils as api_utils
|
from watcher.api.controllers.v1 import utils as api_utils
|
||||||
|
from watcher.common import context
|
||||||
from watcher.common import exception
|
from watcher.common import exception
|
||||||
from watcher.common import policy
|
from watcher.common import policy
|
||||||
from watcher import objects
|
from watcher import objects
|
||||||
@@ -52,12 +52,13 @@ class Service(base.APIBase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
_status = None
|
_status = None
|
||||||
|
_context = context.RequestContext(is_admin=True)
|
||||||
|
|
||||||
def _get_status(self):
|
def _get_status(self):
|
||||||
return self._status
|
return self._status
|
||||||
|
|
||||||
def _set_status(self, name):
|
def _set_status(self, id):
|
||||||
service = objects.Service.get_by_name(pecan.request.context, name)
|
service = objects.Service.get(pecan.request.context, id)
|
||||||
last_heartbeat = (service.last_seen_up or service.updated_at
|
last_heartbeat = (service.last_seen_up or service.updated_at
|
||||||
or service.created_at)
|
or service.created_at)
|
||||||
if isinstance(last_heartbeat, six.string_types):
|
if isinstance(last_heartbeat, six.string_types):
|
||||||
@@ -72,9 +73,9 @@ class Service(base.APIBase):
|
|||||||
elapsed = timeutils.delta_seconds(last_heartbeat, timeutils.utcnow())
|
elapsed = timeutils.delta_seconds(last_heartbeat, timeutils.utcnow())
|
||||||
is_up = abs(elapsed) <= CONF.service_down_time
|
is_up = abs(elapsed) <= CONF.service_down_time
|
||||||
if not is_up:
|
if not is_up:
|
||||||
LOG.warning(_LW('Seems service %(name)s on host %(host)s is down. '
|
LOG.warning('Seems service %(name)s on host %(host)s is down. '
|
||||||
'Last heartbeat was %(lhb)s.'
|
'Last heartbeat was %(lhb)s.'
|
||||||
'Elapsed time is %(el)s'),
|
'Elapsed time is %(el)s',
|
||||||
{'name': service.name,
|
{'name': service.name,
|
||||||
'host': service.host,
|
'host': service.host,
|
||||||
'lhb': str(last_heartbeat), 'el': str(elapsed)})
|
'lhb': str(last_heartbeat), 'el': str(elapsed)})
|
||||||
@@ -108,7 +109,7 @@ class Service(base.APIBase):
|
|||||||
for field in fields:
|
for field in fields:
|
||||||
self.fields.append(field)
|
self.fields.append(field)
|
||||||
setattr(self, field, kwargs.get(
|
setattr(self, field, kwargs.get(
|
||||||
field if field != 'status' else 'name', wtypes.Unset))
|
field if field != 'status' else 'id', wtypes.Unset))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _convert_with_links(service, url, expand=True):
|
def _convert_with_links(service, url, expand=True):
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
#
|
|
||||||
# Copyright 2013 Red Hat, Inc.
|
# Copyright 2013 Red Hat, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
@@ -183,7 +181,7 @@ class JsonPatchType(wtypes.Base):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def mandatory_attrs():
|
def mandatory_attrs():
|
||||||
"""Retruns a list of mandatory attributes.
|
"""Returns a list of mandatory attributes.
|
||||||
|
|
||||||
Mandatory attributes can't be removed from the document. This
|
Mandatory attributes can't be removed from the document. This
|
||||||
method should be overwritten by derived class.
|
method should be overwritten by derived class.
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ def validate_sort_dir(sort_dir):
|
|||||||
|
|
||||||
|
|
||||||
def validate_search_filters(filters, allowed_fields):
|
def validate_search_filters(filters, allowed_fields):
|
||||||
# Very leightweight validation for now
|
# Very lightweight validation for now
|
||||||
# todo: improve this (e.g. https://www.parse.com/docs/rest/guide/#queries)
|
# todo: improve this (e.g. https://www.parse.com/docs/rest/guide/#queries)
|
||||||
for filter_name in filters.keys():
|
for filter_name in filters.keys():
|
||||||
if filter_name not in allowed_fields:
|
if filter_name not in allowed_fields:
|
||||||
@@ -73,6 +73,21 @@ def apply_jsonpatch(doc, patch):
|
|||||||
return jsonpatch.apply_patch(doc, jsonpatch.JsonPatch(patch))
|
return jsonpatch.apply_patch(doc, jsonpatch.JsonPatch(patch))
|
||||||
|
|
||||||
|
|
||||||
|
def get_patch_value(patch, key):
|
||||||
|
for p in patch:
|
||||||
|
if p['op'] == 'replace' and p['path'] == '/%s' % key:
|
||||||
|
return p['value']
|
||||||
|
|
||||||
|
|
||||||
|
def check_audit_state_transition(patch, initial):
|
||||||
|
is_transition_valid = True
|
||||||
|
state_value = get_patch_value(patch, "state")
|
||||||
|
if state_value is not None:
|
||||||
|
is_transition_valid = objects.audit.AuditStateTransitionManager(
|
||||||
|
).check_transition(initial, state_value)
|
||||||
|
return is_transition_valid
|
||||||
|
|
||||||
|
|
||||||
def as_filters_dict(**filters):
|
def as_filters_dict(**filters):
|
||||||
filters_dict = {}
|
filters_dict = {}
|
||||||
for filter_name, filter_value in filters.items():
|
for filter_name, filter_value in filters.items():
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ from oslo_serialization import jsonutils
|
|||||||
import six
|
import six
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
from watcher._i18n import _, _LE
|
from watcher._i18n import _
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ class ParsableErrorMiddleware(object):
|
|||||||
et.ElementTree.Element(
|
et.ElementTree.Element(
|
||||||
'error_message', text='\n'.join(app_iter)))]
|
'error_message', text='\n'.join(app_iter)))]
|
||||||
except et.ElementTree.ParseError as err:
|
except et.ElementTree.ParseError as err:
|
||||||
LOG.error(_LE('Error parsing HTTP response: %s'), err)
|
LOG.error('Error parsing HTTP response: %s', err)
|
||||||
body = ['<error_message>%s'
|
body = ['<error_message>%s'
|
||||||
'</error_message>' % state['status_code']]
|
'</error_message>' % state['status_code']]
|
||||||
state['headers'].append(('Content-Type', 'application/xml'))
|
state['headers'].append(('Content-Type', 'application/xml'))
|
||||||
|
|||||||
99
watcher/api/scheduling.py
Normal file
99
watcher/api/scheduling.py
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
# Copyright (c) 2017 Servionica
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log
|
||||||
|
from oslo_utils import timeutils
|
||||||
|
import six
|
||||||
|
|
||||||
|
from watcher._i18n import _LW
|
||||||
|
from watcher.common import context as watcher_context
|
||||||
|
from watcher.common import scheduling
|
||||||
|
from watcher import notifications
|
||||||
|
|
||||||
|
from watcher import objects
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class APISchedulingService(scheduling.BackgroundSchedulerService):
|
||||||
|
|
||||||
|
def __init__(self, gconfig=None, **options):
|
||||||
|
self.services_status = {}
|
||||||
|
gconfig = None or {}
|
||||||
|
super(APISchedulingService, self).__init__(gconfig, **options)
|
||||||
|
|
||||||
|
def get_services_status(self, context):
|
||||||
|
services = objects.service.Service.list(context)
|
||||||
|
for service in services:
|
||||||
|
result = self.get_service_status(context, service.id)
|
||||||
|
if service.id not in self.services_status.keys():
|
||||||
|
self.services_status[service.id] = result
|
||||||
|
continue
|
||||||
|
if self.services_status[service.id] != result:
|
||||||
|
self.services_status[service.id] = result
|
||||||
|
notifications.service.send_service_update(context, service,
|
||||||
|
state=result)
|
||||||
|
|
||||||
|
def get_service_status(self, context, service_id):
|
||||||
|
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, 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.
|
||||||
|
last_heartbeat = timeutils.parse_strtime(last_heartbeat)
|
||||||
|
else:
|
||||||
|
# Objects have proper UTC timezones, but the timeutils comparison
|
||||||
|
# below does not (and will fail)
|
||||||
|
last_heartbeat = last_heartbeat.replace(tzinfo=None)
|
||||||
|
elapsed = timeutils.delta_seconds(last_heartbeat, timeutils.utcnow())
|
||||||
|
is_up = abs(elapsed) <= CONF.service_down_time
|
||||||
|
if not is_up:
|
||||||
|
LOG.warning(_LW('Seems service %(name)s on host %(host)s is down. '
|
||||||
|
'Last heartbeat was %(lhb)s.'
|
||||||
|
'Elapsed time is %(el)s'),
|
||||||
|
{'name': service.name,
|
||||||
|
'host': service.host,
|
||||||
|
'lhb': str(last_heartbeat), 'el': str(elapsed)})
|
||||||
|
return objects.service.ServiceStatus.FAILED
|
||||||
|
|
||||||
|
return objects.service.ServiceStatus.ACTIVE
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
"""Start service."""
|
||||||
|
context = watcher_context.make_context(is_admin=True)
|
||||||
|
self.add_job(self.get_services_status, name='service_status',
|
||||||
|
trigger='interval', jobstore='default', args=[context],
|
||||||
|
next_run_time=datetime.datetime.now(), seconds=60)
|
||||||
|
super(APISchedulingService, self).start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""Stop service."""
|
||||||
|
self.shutdown()
|
||||||
|
|
||||||
|
def wait(self):
|
||||||
|
"""Wait for service to complete."""
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Reset service.
|
||||||
|
|
||||||
|
Called in case service running in daemon mode receives SIGHUP.
|
||||||
|
"""
|
||||||
@@ -20,32 +20,66 @@ from oslo_log import log
|
|||||||
|
|
||||||
from watcher.applier.action_plan import base
|
from watcher.applier.action_plan import base
|
||||||
from watcher.applier import default
|
from watcher.applier import default
|
||||||
|
from watcher.common import exception
|
||||||
|
from watcher import notifications
|
||||||
from watcher import objects
|
from watcher import objects
|
||||||
|
from watcher.objects import fields
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DefaultActionPlanHandler(base.BaseActionPlanHandler):
|
class DefaultActionPlanHandler(base.BaseActionPlanHandler):
|
||||||
|
|
||||||
def __init__(self, context, service, action_plan_uuid):
|
def __init__(self, context, service, action_plan_uuid):
|
||||||
super(DefaultActionPlanHandler, self).__init__()
|
super(DefaultActionPlanHandler, self).__init__()
|
||||||
self.ctx = context
|
self.ctx = context
|
||||||
self.service = service
|
self.service = service
|
||||||
self.action_plan_uuid = action_plan_uuid
|
self.action_plan_uuid = action_plan_uuid
|
||||||
|
|
||||||
def update_action_plan(self, uuid, state):
|
|
||||||
action_plan = objects.ActionPlan.get_by_uuid(self.ctx, uuid)
|
|
||||||
action_plan.state = state
|
|
||||||
action_plan.save()
|
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
try:
|
try:
|
||||||
self.update_action_plan(self.action_plan_uuid,
|
action_plan = objects.ActionPlan.get_by_uuid(
|
||||||
objects.action_plan.State.ONGOING)
|
self.ctx, self.action_plan_uuid, eager=True)
|
||||||
|
if action_plan.state == objects.action_plan.State.CANCELLED:
|
||||||
|
self._update_action_from_pending_to_cancelled()
|
||||||
|
return
|
||||||
|
action_plan.state = objects.action_plan.State.ONGOING
|
||||||
|
action_plan.save()
|
||||||
|
notifications.action_plan.send_action_notification(
|
||||||
|
self.ctx, action_plan,
|
||||||
|
action=fields.NotificationAction.EXECUTION,
|
||||||
|
phase=fields.NotificationPhase.START)
|
||||||
|
|
||||||
applier = default.DefaultApplier(self.ctx, self.service)
|
applier = default.DefaultApplier(self.ctx, self.service)
|
||||||
applier.execute(self.action_plan_uuid)
|
applier.execute(self.action_plan_uuid)
|
||||||
state = objects.action_plan.State.SUCCEEDED
|
|
||||||
|
action_plan.state = objects.action_plan.State.SUCCEEDED
|
||||||
|
notifications.action_plan.send_action_notification(
|
||||||
|
self.ctx, action_plan,
|
||||||
|
action=fields.NotificationAction.EXECUTION,
|
||||||
|
phase=fields.NotificationPhase.END)
|
||||||
|
|
||||||
|
except exception.ActionPlanCancelled as e:
|
||||||
|
LOG.exception(e)
|
||||||
|
action_plan.state = objects.action_plan.State.CANCELLED
|
||||||
|
self._update_action_from_pending_to_cancelled()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.exception(e)
|
LOG.exception(e)
|
||||||
state = objects.action_plan.State.FAILED
|
action_plan.state = objects.action_plan.State.FAILED
|
||||||
|
notifications.action_plan.send_action_notification(
|
||||||
|
self.ctx, action_plan,
|
||||||
|
action=fields.NotificationAction.EXECUTION,
|
||||||
|
priority=fields.NotificationPriority.ERROR,
|
||||||
|
phase=fields.NotificationPhase.ERROR)
|
||||||
finally:
|
finally:
|
||||||
self.update_action_plan(self.action_plan_uuid, state)
|
action_plan.save()
|
||||||
|
|
||||||
|
def _update_action_from_pending_to_cancelled(self):
|
||||||
|
filters = {'action_plan_uuid': self.action_plan_uuid,
|
||||||
|
'state': objects.action.State.PENDING}
|
||||||
|
actions = objects.Action.list(self.ctx, filters=filters, eager=True)
|
||||||
|
if actions:
|
||||||
|
for a in actions:
|
||||||
|
a.state = objects.action.State.CANCELLED
|
||||||
|
a.save()
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user