Retire Packaging Deb project repos

This commit is part of a series to retire the Packaging Deb
project. Step 2 is to remove all content from the project
repos, replacing it with a README notification where to find
ongoing work, and how to recover the repo if needed at some
future point (as in
https://docs.openstack.org/infra/manual/drivers.html#retiring-a-project).

Change-Id: I431ed20740926bc6101cb607a0b3d6d8b6ccdcd5
This commit is contained in:
Tony Breeds 2017-09-12 16:02:23 -06:00
parent 6b6c4843ea
commit 853d025f9b
49 changed files with 14 additions and 4797 deletions

18
.gitignore vendored
View File

@ -1,18 +0,0 @@
.coverage*
.venv
cover
*.pyc
AUTHORS
build
dist
run_tests.err.log
.tox
doc/source/api
*.egg
monclient/versioninfo
*.egg-info
*.log
.testrepository
.pydevproject
.project
.idea

View File

@ -1,4 +0,0 @@
[gerrit]
host=review.openstack.org
port=29418
project=openstack/python-monascaclient.git

View File

@ -1,9 +0,0 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-160} \
${PYTHON:-python} -m subunit.run discover -t ./ $OS_TEST_PATH $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list
group_regex=monascaclient\.tests(?:\.|_)([^_]+)

View File

@ -1,17 +0,0 @@
If you would like to contribute to the development of OpenStack, you must
follow the steps in this page:
http://docs.openstack.org/infra/manual/developers.html
If you already have a good understanding of how the system works and your
OpenStack accounts are set up, you can skip to the development workflow
section of this documentation to learn how changes to OpenStack should be
submitted for review via the Gerrit tool:
http://docs.openstack.org/infra/manual/developers.html#development-workflow
Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Launchpad, not GitHub:
https://bugs.launchpad.net/monasca

View File

@ -1,4 +0,0 @@
python-monascaclient Style Commandments
===============================================
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/

175
LICENSE
View File

@ -1,175 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

14
README Normal file
View File

@ -0,0 +1,14 @@
This project is no longer maintained.
The contents of this repository are still available in the Git
source code management system. To see the contents of this
repository before it reached its end of life, please check out the
previous commit with "git checkout HEAD^1".
For ongoing work on maintaining OpenStack packages in the Debian
distribution, please see the Debian OpenStack packaging team at
https://wiki.debian.org/OpenStack/.
For any further questions, please email
openstack-dev@lists.openstack.org or join #openstack-dev on
Freenode.

View File

@ -1,437 +0,0 @@
========================
Team and repository tags
========================
.. image:: https://governance.openstack.org/badges/python-monascaclient.svg
:target: https://governance.openstack.org/reference/tags/index.html
.. Change things from this point on
Python bindings to the Monasca API
=======================================
This is a client library for Monasca built to interface with the Monasca API. It
provides a Python API (the ``monascaclient`` module) and a command-line tool
(``monasca``).
The Monasca Client was written using the OpenStack Heat Python client as a framework.
.. contents:: Contents:
:local:
Ubuntu Install
--------------
Requires:
- pip - version >= 1.4. python get-pip.py
See versions on PYPI:
https://pypi.python.org/pypi/python-monascaclient/
Install It:
- sudo pip install python-monascaclient
Alternative Manual Install Steps:
- cd to your python-monascaclient repo
- sudo pip install -r requirements.txt
- python setup.py install
Building and Packaging
----------------------
Install the tool dependencies
sudo apt-get install python-pip python-virtualenv
In the python-monascaclient source directory
virtualenv --no-site-packages .venv
source ./.venv/bin/activate
pip install wheel
python setup.py bdist_wheel
pip install $(ls -1rt dist/*.whl | tail -1) --upgrade
Command-line API
----------------
Installing this distribution gets you a shell command, ``monasca``, that you
can use to interact with the Monitoring API server.
Usage:
monasca
monasca help
monasca help <command>
monasca -j <command>
This outputs the results in json format. Normally output is in table format.
The monascaclient CLI needs the Monasca API endpoint url and the OS_AUTH_TOKEN to pass to the
Monasca API RESTful interface. This is provided through environment or CLI
parameters.
Environmental Variables
~~~~~~~~~~~~~~~~~~~~~~~
Environmental variables can be sourced, or optionally passed in as CLI arguments.
It is easiest to source them first and then use the CLI.
When token and endpoint are known::
export OS_AUTH_TOKEN=XXX
export MONASCA_API_URL=http://192.168.10.4:8070/v2.0/
When using Keystone to obtain the token and endpoint::
export OS_USERNAME=
export OS_PASSWORD=
export OS_USER_DOMAIN_NAME=
export OS_PROJECT_NAME=
export OS_AUTH_URL=
export OS_REGION_NAME=
# Optional(specific version added to OS_AUTH_URL if (v2.0 or v3) not present already)
export OS_AUTH_VERSION=
When OS_USER_DOMAIN_NAME is not set, then 'Default' is assumed. Alternatively IDs can be used instead of names.
Although *deprecated*, but OS_TENANT_NAME and OS_TENANT_ID can be used for
OS_PROEJCT_NAME and OS_PROJECT_ID respectively.
When using Vagrant Environment with middleware disabled::
export OS_AUTH_TOKEN=82510970543135
export OS_NO_CLIENT_AUTH=1
export MONASCA_API_URL=http://192.168.10.4:8070/v2.0/
The Monasca API will treat the auth token as the tenant ID when Keystone is not enabled.
You'll find complete documentation on the shell by running
``monasca help``::
usage: monasca [-j] [--version] [-d] [-v] [-k] [--cert-file CERT_FILE]
[--key-file KEY_FILE] [--os-cacert OS_CACERT]
[--timeout TIMEOUT] [--os-username OS_USERNAME]
[--os-password OS_PASSWORD] [--os-project-id OS_PROJECT_ID]
[--os-user-domain-id OS_USER_DOMAIN_ID] [--os-user-domain-name OS_USER_DOMAIN_NAME]
[--os-project-name OS_PROJECT_NAME]
[--os-project-domain-id OS_PROJECT_DOMAIN_ID] [--os-project-domain-name OS_PROJECT_DOMAIN_NAME]
[--os-auth-url OS_AUTH_URL] [--os-auth-version OS_AUTH_VERSION] [--os-region-name OS_REGION_NAME]
[--os-auth-token OS_AUTH_TOKEN] [--os-no-client-auth]
[--monasca-api-url MONASCA_API_URL]
[--monasca-api-version MONASCA_API_VERSION]
[--os-service-type OS_SERVICE_TYPE]
[--os-endpoint-type OS_ENDPOINT_TYPE]
<subcommand> ...
Command-line interface to the monasca-client API.
positional arguments:
<subcommand>
alarm-definition-create Create an alarm definition.
alarm-definition-delete Delete the alarm definition.
alarm-definition-list List alarm definitions for this tenant.
alarm-definition-patch Patch the alarm definition.
alarm-definition-show Describe the alarm definition.
alarm-definition-update Update the alarm definition.
alarm-delete Delete the alarm.
alarm-history Alarm state history.
alarm-history-list List alarms state history.
alarm-list List alarms for this tenant.
alarm-patch Patch the alarm.
alarm-show Describe the alarm.
alarm-update Update the alarm.
dimension-name-list List names of dimensions.
dimension-value-list List the dimension values for a given dimension name.
measurement-list List measurements for the specified metric.
metric-create Create metric.
metric-create-raw Create metric from raw json body.
metric-list List metrics for this tenant.
metric-name-list List names of metrics.
metric-statistics List measurement statistics for the specified metric.
notification-create Create notification.
notification-delete Delete notification.
notification-list List notifications for this tenant.
notification-patch Patch notification.
notification-show Describe the notification.
notification-update Update notification.
bash-completion Prints all of the commands and options to stdout.
help Display help about this program or one of its
subcommands.
optional arguments:
-j, --json output raw json response
--version Shows the client version and exits.
-d, --debug Defaults to env[MONASCA_DEBUG].
-v, --verbose Print more verbose output.
-k, --insecure Explicitly allow the client to perform "insecure" SSL
(https) requests. The server's certificate will not
be verified against any certificate authorities. This
option should be used with caution.
--cert-file CERT_FILE Path of certificate file to use in SSL connection.
This file can optionally be prepended with the
private key.
--key-file KEY_FILE Path of client key to use in SSL connection.This
option is not necessary if your key is prepended to
your cert file.
--os-cacert OS_CACERT Specify a CA bundle file to use in verifying a
TLS (https) server certificate. Defaults to
env[OS_CACERT]. Without either of these, the
client looks for the default system CA
certificates.
--timeout TIMEOUT Number of seconds to wait for a response.
--os-username OS_USERNAME Defaults to env[OS_USERNAME].
--os-password OS_PASSWORD Defaults to env[OS_PASSWORD].
--os-project-id OS_PROJECT_ID
Defaults to env[OS_PROJECT_ID].
--os-project-name OS_PROJECT_NAME
Defaults to env[OS_PROJECT_NAME].
--os-domain-id OS_DOMAIN_ID
Defaults to env[OS_DOMAIN_ID].
--os-domain-name OS_DOMAIN_NAME
Defaults to env[OS_DOMAIN_NAME].
--os-auth-url OS_AUTH_URL Defaults to env[OS_AUTH_URL].
--os-auth-version OS_AUTH_VERSION
Defaults to env[OS_AUTH_VERSION].
--os-region-name OS_REGION_NAME
Defaults to env[OS_REGION_NAME].
--os-auth-token OS_AUTH_TOKEN
Defaults to env[OS_AUTH_TOKEN].
--os-no-client-auth Do not contact keystone for a token. Defaults to
env[OS_NO_CLIENT_AUTH].
--monasca-api-url MONASCA_API_URL
Defaults to env[MONASCA_API_URL].
--monasca-api-version MONASCA_API_VERSION
Defaults to env[MONASCA_API_VERSION] or 2_0
--os-service-type OS_SERVICE_TYPE
Defaults to env[OS_SERVICE_TYPE].
--os-endpoint-type OS_ENDPOINT_TYPE
Defaults to env[OS_ENDPOINT_TYPE].
See "mon help COMMAND" for help on a specific command.
Bash Completion
~~~~~~~~~~~~~~~
Basic command tab completion can be enabled by sourcing the bash completion script.
::
source /usr/local/share/monasca.bash_completion
Metrics Examples
~~~~~~~~~~~~~~~~
Note: To see complete usage: 'monasca help' and 'monasca help <command>'
metric-create::
monasca metric-create cpu1 123.40
monasca metric-create metric1 1234.56 --dimensions instance_id=123,service=ourservice
monasca metric-create metric1 2222.22 --dimensions instance_id=123,service=ourservice
monasca metric-create metric1 3333.33 --dimensions instance_id=222,service=ourservice
monasca metric-create metric1 4444.44 --dimensions instance_id=222 --value-meta rc=404
metric-list::
monasca metric-list
+---------+--------------------+
| name | dimensions |
+---------+--------------------+
| cpu1 | |
| metric1 | instance_id:123 |
| | service:ourservice |
+---------+--------------------+
measurement-list::
monasca measurement-list metric1 2014-01-01T00:00:00Z
+---------+--------------------+----------------+----------------------+--------------+-------------+
| name | dimensions | measurement_id | timestamp | value | value_meta |
+---------+--------------------+----------------+----------------------+--------------+-------------+
| metric1 | instance_id:123 | 723885 | 2014-05-08T21:46:32Z | 1234.56 | |
| | service:ourservice | 725951 | 2014-05-08T21:48:50Z | 2222.22 | |
| metric1 | instance_id:222 | 726837 | 2014-05-08T21:49:47Z | 3333.33 | |
| | service:ourservice | 726983 | 2014-05-08T21:50:27Z | 4444.44 | rc: 404 |
+---------+--------------------+----------------+----------------------+--------------+-------------+
monasca measurement-list metric1 2014-01-01T00:00:00Z --dimensions instance_id=123
+---------+--------------------+----------------+----------------------+--------------+-------------+
| name | dimensions | measurement_id | timestamp | value | value_meta |
+---------+--------------------+----------------+----------------------+--------------+-------------+
| metric1 | instance_id:123 | 723885 | 2014-05-08T21:46:32Z | 1234.56 | |
| | service:ourservice | 725951 | 2014-05-08T21:48:50Z | 2222.22 | |
+---------+--------------------+----------------+----------------------+--------------+-------------+
Notifications Examples
~~~~~~~~~~~~~~~~~~~~~~
Note: To see complete usage: 'monasca help' and 'monasca help <command>'
notification-create::
monasca notification-create cindyemail1 EMAIL cindy.employee@hp.com
monasca notification-create myapplication WEBHOOK http://localhost:5000
monasca notification-create mypagerduty PAGERDUTY nzH2LVRdMzun11HNC2oD
notification-list::
monasca notification-list
+---------------+--------------------------------------+-------+----------------------+
| name | id | type | address |
+---------------+--------------------------------------+-------+----------------------+
| cindyemail1 | 5651406c-447d-40bd-b868-b2b3e6b59e32 | EMAIL |cindy.employee@hp.com |
| myapplication | 55905ce2-91e3-41ce-b45a-de7032f8d718 | WEBHOOK |http://localhost:5000
| mypagerduty | 5720ccb5-6a3d-22ba-545g-ce467a5b41a2 | PAGERDUTY |nzH2LVRdMzun11HNC2oD
+---------------+--------------------------------------+-------+----------------------+
Alarms Examples
~~~~~~~~~~~~~~~
Note: To see complete usage: 'monasca help' and 'monasca help <command>'
alarm-definition-create::
monasca alarm-definition-create alarmPerHost "max(cpu.load_avg_1_min) > 0" --match-by hostname
alarm-definition-list::
+--------------+--------------------------------------+-----------------------------+----------+-----------------+
| name | id | expression | match_by | actions_enabled |
+--------------+--------------------------------------+-----------------------------+----------+-----------------+
| alarmPerHost | 4bf6bfc2-c5ac-4d57-b7db-cf5313b05412 | max(cpu.load_avg_1_min) > 0 | hostname | True |
+--------------+--------------------------------------+-----------------------------+----------+-----------------+
alarm-definition-show::
monasca alarm-definition-show 4bf6bfc2-c5ac-4d57-b7db-cf5313b05412
+----------------------+----------------------------------------------------------------------------------------------------+
| Property | Value |
+----------------------+----------------------------------------------------------------------------------------------------+
| actions_enabled | true |
| alarm_actions | [] |
| description | "" |
| expression | "max(cpu.load_avg_1_min) > 0" |
| id | "4bf6bfc2-c5ac-4d57-b7db-cf5313b05412" |
| links | href:http://192.168.10.4:8070/v2.0/alarm-definitions/4bf6bfc2-c5ac-4d57-b7db-cf5313b05412,rel:self |
| match_by | [ |
| | "hostname" |
| | ] |
| name | "alarmPerHost" |
| ok_actions | [] |
| severity | "LOW" |
| undetermined_actions | [] |
+----------------------+----------------------------------------------------------------------------------------------------+
alarm-definition-delete::
monasca alarm-definition-delete 4bf6bfc2-c5ac-4d57-b7db-cf5313b05412
alarm-list::
monasca alarm-list
+--------------------------------------+--------------------------------------+----------------+---------------+---------------------+----------+-------+--------------------------+--------------------------+
| id | alarm_definition_id | alarm_name | metric_name | metric_dimensions | severity | state | state_updated_timestamp | created_timestamp |
+--------------------------------------+--------------------------------------+----------------+---------------+---------------------+----------+-------+--------------------------+--------------------------+
| 11e8c15d-0263-4b71-a8b8-4ecdaeb2902c | af1f347b-cddb-46da-b7cc-924261eeecdf | High CPU usage | cpu.idle_perc | hostname: devstack | LOW | OK | 2015-03-26T21:45:15.000Z | 2015-03-26T21:41:50.000Z |
| e5797cfe-b66e-4d44-98cd-3c7fc62d4c33 | af1f347b-cddb-46da-b7cc-924261eeecdf | High CPU usage | cpu.idle_perc | hostname: mini-mon | LOW | OK | 2015-03-26T21:43:15.000Z | 2015-03-26T21:41:47.000Z |
| | | | | service: monitoring | | | | |
+--------------------------------------+--------------------------------------+----------------+---------------+---------------------+----------+-------+--------------------------+--------------------------+
alarm-history::
monasca alarm-history 9d748b72-939b-45e7-a807-c0c5ad88d3e4
+--------------------------------------+-----------+--------------+------------------------------------------------------------------------------+-------------+--------------------+---------------------+--------------------------+
| alarm_id | new_state | old_state | reason | reason_data | metric_name | metric_dimensions | timestamp |
+--------------------------------------+-----------+--------------+------------------------------------------------------------------------------+-------------+--------------------+---------------------+--------------------------+
| 9d748b72-939b-45e7-a807-c0c5ad88d3e4 | ALARM | UNDETERMINED | Thresholds were exceeded for the sub-alarms: [max(cpu.load_avg_1_min) > 0.0] | {} | cpu.load_avg_1_min | hostname: mini-mon | 2014-10-14T21:14:11.000Z |
| | | | | | | service: monitoring | |
+--------------------------------------+-----------+--------------+------------------------------------------------------------------------------+-------------+--------------------+---------------------+--------------------------+
alarm-patch::
monasca alarm-patch fda5537b-1550-435f-9d6c-262b7e05065b --state OK
Python API
----------
There's also a complete Python API.
In order to use the python api directly, you must pass in a valid auth token and
monasca api endpoint, or you can pass in the credentials required by the keystone
client and let the Python API do the authentication. The user can obtain the token
and endpoint using the keystone client api:
http://docs.openstack.org/developer/python-keystoneclient/.
The service catalog name for our API endpoint is "monasca".
Start using the monascaclient API by constructing the monascaclient client.Client class.
The Client class takes these parameters: api_version, endpoint, and token.
The Client class is used to call all monasca-api resource commands (i.e.
client.Client.metrics.create(fields)).
Long running users of the Client will receive an indication
that the keystone token has expired when they receive an HTTP response
code of 401 Unauthorized from the monasca-API. In this case, it is
up to the user to get a new token from keystone which can be passed
into the client.Client.replace_token(token) method. If you constructed
the Client with all the keystone credentials needed to authenticate,
then the API will automatically try one time to re-authenticate with
keystone whenever the token expires.
The api_version matches the version of the Monasca API. Currently it is 'v2_0'.
When calling the commands, refer to monascaclient.v2_0.shell.py 'do_<command>'
to see the required and optional fields for each command.
https://github.com/openstack/python-monascaclient/blob/master/monascaclient/v2_0/shell.py
Refer to the example in python-monascaclient/client_api_example.py for more detail::
from monascaclient import client
from monascaclient import ksclient
import monascaclient.exc as exc
import time
api_version = '2_0'
# Authenticate to Keystone
keystone_url = 'http://keystone:5000/v3'
ks = ksclient.KSClient(auth_url=keystone_url, username='user', password='password')
# construct the mon client
monasca_client = client.Client(api_version, ks.monasca_url, token=ks.token)
# call the metric-create command
dimensions = {'instance_id': '12345', 'service': 'hello'}
fields = {}
fields['name'] = 'cindy1'
fields['dimensions'] = dimensions
fields['timestamp'] = time.time() * 1000
fields['value'] = 222.333
try:
resp = monasca_client.metrics.create(**fields)
except exc.HTTPException as he:
print(he.code)
print(he.message)
else:
print(resp)
License
-------
(C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP
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.

View File

@ -1,90 +0,0 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
"""An example using monascaclient via the Python API"""
from monascaclient import client
import monascaclient.exc as exc
import time
# In order to use the python api directly, you must first obtain an
# auth token and identify which endpoint you wish to speak to.
endpoint = 'http://192.168.10.4:8070/v2.0'
# The api version of monasca-api
api_version = '2_0'
# Pass in the keystone authentication kwargs to construct a monasca client.
# The monasca_client will try to authenticate with keystone one time
# when it sees a 401 unauthorized resp, to take care of a stale token.
# In this example no token is input, so it will get a 401 when executing the
# first metrics.create request, and will authenticate and try again.
auth_kwargs = {'username': 'mini-mon',
'password': 'password',
'project_name': 'mini-mon',
'auth_url': 'http://192.168.10.5:35357/v3/'}
monasca_client = client.Client(api_version, endpoint, **auth_kwargs)
# you can reference the monascaclient.v2_0.shell.py
# do_commands for command field initialization.
# post a metric
dimensions = {'instance_id': '12345', 'service': 'nova'}
fields = {}
fields['name'] = 'metric1'
fields['dimensions'] = dimensions
# time in milliseconds
fields['timestamp'] = time.time() * 1000
fields['value'] = 222.333
try:
resp = monasca_client.metrics.create(**fields)
except exc.HTTPException as he:
print('HTTPException code=%s message=%s' % (he.code, he.message))
else:
print(resp)
print('Successfully created metric')
# post a metric with a unicode service name
dimensions = {'instance_id': '12345', 'service': u'\u76db\u5927'}
fields = {}
fields['name'] = 'metric1'
fields['dimensions'] = dimensions
fields['timestamp'] = time.time() * 1000
fields['value'] = 222.333
try:
resp = monasca_client.metrics.create(**fields)
except exc.HTTPException as he:
print('HTTPException code=%s message=%s' % (he.code, he.message))
else:
print(resp)
print('Successfully created metric')
print('Giving the DB time to update...')
time.sleep(5)
# metric-list
name = 'metric1'
dimensions = None
fields = {}
if name:
fields['name'] = name
if dimensions:
fields['dimensions'] = dimensions
try:
body = monasca_client.metrics.list(**fields)
except exc.HTTPException as he:
print('HTTPException code=%s message=%s' % (he.code, he.message))
else:
print(body)

View File

@ -1,136 +0,0 @@
#!/usr/bin/env python
#
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
#
# 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 getopt
import os
import sys
from monascaclient import client
def usage():
usage = """
Requires services.osrc variables in bash environment (OS_USERNAME etc).
check_monasca -d <dimension> -v <value>
-h --help Prints this
-d dimension Dimension to filter on
-v value Value of dimension
Examples
check_monasca -d hostname -v test-c0-m1-mgmt # Retrieve all alarms for a host
check_monasca -d service -v nova # Retrieve all nova alarms
"""
print(usage)
def get_keystone_creds():
creds = {'username': os.environ['OS_USERNAME'], 'password': os.environ['OS_PASSWORD'],
'auth_url': os.environ['OS_AUTH_URL'], 'project_name': os.environ['OS_PROJECT_NAME'],
'endpoint': os.environ['OS_MONASCA_URL'], 'os_cacert': os.environ['OS_CACERT']}
return creds
def format_alarm(alarm):
output = "%s %s ( Metric = %s)" % (
alarm['metrics'][0]['dimensions']['hostname'],
alarm['alarm_definition']['name'],
alarm['metrics'][0]['name'])
if "process." in alarm['metrics'][0]['name']:
output += "-%s," % (alarm['metrics'][0]['dimensions']['process_name'])
if "disk." in alarm['metrics'][0]['name']:
output += "-%s," % (alarm['metrics'][0]['dimensions']['mount_point'])
output += ","
return output
def main(argv):
# Initialise Variables
warns = 0
crits = 0
warns_output = ""
crits_output = ""
dimension = ""
dim_value = ""
# Test parameters
try:
opts, args = getopt.getopt(argv, "h::d:v:", ["dimension=", "value="])
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
usage()
sys.exit()
elif opt in ("-d", "--dimension"):
dimension = arg
elif opt in ("-v", "--value"):
dim_value = arg
if dimension == "" or dim_value == "":
usage()
sys.exit(2)
# Set the api version of monasca-api
api_version = '2_0'
creds = get_keystone_creds()
# Build request
dimensions = {}
dimensions[dimension] = dim_value
fields = {}
fields['metric_dimensions'] = dimensions
monasca_client = client.Client(api_version, **creds)
body = monasca_client.alarms.list(**fields)
# Process retrieved alarms
# Note Monasca has state and severity, these are mapped to Nagios values as
# State ALARM and severity = LOW or MEDIUM is Nagios Warning
# State = UNDERTERMINED is Nagios Warning
# State ALARM and severity = HIGH it Nagios Critical
for alarm in body:
if alarm['lifecycle_state'] != "RESOLVED":
if (alarm['state'] == "ALARM" and
(alarm['alarm_definition']['severity'] == "LOW" or
alarm['alarm_definition']['severity'] == "MEDIUM")):
warns += 1
warns_output += format_alarm(alarm)
if alarm['state'] == "UNDETERMINED":
warns += 1
warns_output += format_alarm(alarm)
if alarm['state'] == "ALARM" and alarm['alarm_definition']['severity'] == "HIGH":
crits += 1
crits_output += format_alarm(alarm)
if warns == 0 and crits == 0:
print("OK")
return
elif warns > 0 and crits == 0:
print(str(warns) + " WARNING - " + warns_output)
sys.exit(1)
elif crits > 0:
print(str(crits) + " CRITICAL - " + crits_output + str(warns) + " WARNING - " + warns_output)
sys.exit(2)
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -1,36 +0,0 @@
Nagios style monasca plugin
===========================
check_monasca.py is a Nagios style plugin to query a monasca endpoint based dimensions and values. It is best called via a wrapper script that will set the following environment variables.
OS_USERNAME - a keystone user
OS_PASSWORD - user password
OS_PROJECT_NAME - Default
OS_AUTH_URL - Keystone URL
OS_MONASCA_URL ( note monasca URL should be something like http://192.168.1.10:8070/v2.0 )
Then the script should be called with the relevant dimensions and values.
e.g
check_monasca.py -d service -v nova - for all nova alarms
check_monasca.py -d hostname -v server1 - for all alarms relating to server1.
License
-------
(C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP
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.

View File

@ -1,70 +0,0 @@
# Copyright 2017 FUJITSU LIMITED
#
# 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.
"""
Patches method that transforms error responses.
That is required to handle different format monasca follows.
"""
from keystoneauth1 import exceptions as exc
from keystoneauth1.exceptions import http
def mon_exc_from_response(response, method, url):
req_id = response.headers.get('x-openstack-request-id')
kwargs = {
'http_status': response.status_code,
'response': response,
'method': method,
'url': url,
'request_id': req_id,
}
if 'retry-after' in response.headers:
kwargs['retry_after'] = response.headers['retry-after']
content_type = response.headers.get('Content-Type', '')
if content_type.startswith('application/json'):
try:
body = response.json()
except ValueError:
pass
else:
if isinstance(body, dict):
if isinstance(body.get('error'), dict):
error = body['error']
kwargs['message'] = error.get('message')
kwargs['details'] = error.get('details')
elif {'description', 'title'} <= set(body):
# monasca-api error response structure
kwargs['message'] = body.get('title')
kwargs['details'] = body.get('description')
elif content_type.startswith('text/'):
kwargs['details'] = response.text
try:
cls = http._code_map[response.status_code]
except KeyError:
if 500 <= response.status_code < 600:
cls = exc.HttpServerError
elif 400 <= response.status_code < 500:
cls = exc.HTTPClientError
else:
cls = exc.HttpError
return cls(**kwargs)
exc.from_response = mon_exc_from_response

View File

@ -1,137 +0,0 @@
# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP
# Copyright 2017 Fujitsu LIMITED
#
# 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 warnings
from keystoneauth1 import identity
from keystoneauth1 import session
from monascaclient.osc import migration
from monascaclient import version
_NO_VALUE_MARKER = object()
def Client(api_version, *args, **kwargs):
handle_deprecated(args, kwargs)
auth = _get_auth_handler(kwargs)
sess = _get_session(auth, kwargs)
client = migration.make_client(
api_version=api_version,
session=sess,
endpoint=kwargs.get('endpoint'),
service_type=kwargs.get('service_type', 'monitoring')
)
return client
def handle_deprecated(args, kwargs):
"""Handles all deprecations
Method goes through passed args and kwargs
and handles all values that are invalid from POV
of current client but:
* has their counterparts
* are candidates to be dropped
"""
kwargs.update(_handle_deprecated_args(args))
_handle_deprecated_kwargs(kwargs)
def _handle_deprecated_kwargs(kwargs):
depr_map = {
'tenant_name': ('project_name', lambda x: x),
'insecure': ('verify', lambda x: not x)
}
for key, new_key_transform in depr_map.items():
val = kwargs.get(key, _NO_VALUE_MARKER)
if val != _NO_VALUE_MARKER:
new_key = new_key_transform[0]
new_handler = new_key_transform[1]
warnings.warn(
'Usage of {old_key} has been deprecated in favour '
'of {new_key}. monascaclient will place value of {old_key} '
'under {new_key}'.format(old_key=key, new_key=new_key),
DeprecationWarning
)
kwargs[new_key] = new_handler(val)
del kwargs[key]
def _handle_deprecated_args(args):
kwargs_update = {}
if args is not None and len(args) > 0:
warnings.warn(
'Usage or args is deprecated for the sake of '
'explicit configuration of the client using '
'named arguments (**kwargs). '
'That argument will be removed in future releases.',
DeprecationWarning
)
# have all permissible args set here
kwargs_update.update({
'endpoint': args[0]
})
return kwargs_update
def _get_session(auth, kwargs):
return session.Session(auth=auth,
app_name='monascaclient',
app_version=version.version_string,
cert=kwargs.get('cert', None),
timeout=kwargs.get('timeout', None),
verify=kwargs.get('verify', True))
def _get_auth_handler(kwargs):
if 'token' in kwargs:
auth = identity.Token(
auth_url=kwargs.get('auth_url', None),
token=kwargs.get('token', None),
project_id=kwargs.get('project_id', None),
project_name=kwargs.get('project_name', None),
project_domain_id=kwargs.get('project_domain_id', None),
project_domain_name=kwargs.get('project_domain_name', None)
)
elif {'username', 'password'} <= set(kwargs):
auth = identity.Password(
auth_url=kwargs.get('auth_url', None),
username=kwargs.get('username', None),
password=kwargs.get('password', None),
project_id=kwargs.get('project_id', None),
project_name=kwargs.get('project_name', None),
project_domain_id=kwargs.get('project_domain_id', None),
project_domain_name=kwargs.get('project_domain_name', None),
user_domain_id=kwargs.get('user_domain_id', None),
user_domain_name=kwargs.get('user_domain_name', None)
)
else:
raise Exception('monascaclient can be configured with either '
'"token" or "username:password" but neither of '
'them was found in passed arguments.')
return auth

View File

@ -1,65 +0,0 @@
# (C) Copyright 2014, 2015 Hewlett Packard Enterprise Development Company LP
# Copyright 2017 Fujitsu LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from six.moves.urllib import parse
class MonascaManager(object):
base_url = None
def __init__(self, client):
self.client = client
def _parse_body(self, body):
if type(body) is dict:
self.next = None
for link in body['links']:
if link['rel'] == 'next':
self.next = link['href']
return body['elements']
else:
return body
def _list(self, path, dim_key=None, **kwargs):
"""Get a list of metrics."""
url_str = self.base_url + path
if dim_key and dim_key in kwargs:
dim_str = self.get_dimensions_url_string(kwargs[dim_key])
kwargs[dim_key] = dim_str
if kwargs:
url_str += '?%s' % parse.urlencode(kwargs, True)
body = self.client.list(
path=url_str
)
return self._parse_body(body)
@staticmethod
def get_dimensions_url_string(dimensions):
dim_list = list()
for k, v in dimensions.items():
# In case user specifies a dimension multiple times
if isinstance(v, (list, tuple)):
v = v[-1]
if v:
dim_str = k + ':' + v
else:
dim_str = k
dim_list.append(dim_str)
return ','.join(dim_list)

View File

@ -1,200 +0,0 @@
# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import print_function
import numbers
import prettytable
import yaml
from osc_lib import exceptions as exc
from oslo_serialization import jsonutils
supported_formats = {
"json": lambda x: jsonutils.dumps(x, indent=2),
"yaml": yaml.safe_dump
}
# Decorator for cli-args
def arg(*args, **kwargs):
def _decorator(func):
# Because of the semantics of decorator composition if we just append
# to the options list positional options will appear to be backwards.
func.__dict__.setdefault('arguments', []).insert(0, (args, kwargs))
return func
return _decorator
def json_formatter(js):
return (jsonutils.dumps(js, indent=2, ensure_ascii=False)).encode('utf-8')
def print_list(objs, fields, field_labels=None, formatters=None, sortby=None):
if formatters is None:
formatters = {}
field_labels = field_labels or fields
pt = prettytable.PrettyTable([f for f in field_labels],
caching=False, print_empty=False)
pt.align = 'l'
for o in objs:
row = []
for field in fields:
if field in formatters:
row.append(formatters[field](o))
elif isinstance(field, int):
row.append(o[field])
else:
data = getattr(o, field, None) or ''
row.append(data)
pt.add_row(row)
if sortby is None:
print(pt.get_string().encode('utf-8'))
else:
print(pt.get_string(sortby=field_labels[sortby]).encode('utf-8'))
def print_dict(d, formatters=None):
if formatters is None:
formatters = {}
pt = prettytable.PrettyTable(['Property', 'Value'],
caching=False, print_empty=False)
pt.align = 'l'
for field in d.keys():
if field in formatters:
pt.add_row([field, formatters[field](d[field])])
else:
pt.add_row([field, d[field]])
print(pt.get_string(sortby='Property').encode('utf-8'))
def format_parameters(params):
'''Reformat parameters into dict of format expected by the API.'''
if not params:
return {}
# expect multiple invocations of --parameters but fall back
# to ; delimited if only one --parameters is specified
if len(params) == 1:
if params[0].find(';') != -1: # found
params = params[0].split(';')
else:
params = params[0].split(',')
parameters = {}
for p in params:
try:
(n, v) = p.split('=', 1)
except ValueError:
msg = '%s(%s). %s.' % ('Malformed parameter', p,
'Use the key=value format')
raise exc.CommandError(msg)
if n not in parameters:
parameters[n] = v
else:
if not isinstance(parameters[n], list):
parameters[n] = [parameters[n]]
parameters[n].append(v)
return parameters
def format_dimensions_query(dims):
if not dims:
return {}
# expect multiple invocations of --parameters but fall back
# to ; delimited if only one --parameters is specified
if len(dims) == 1:
if dims[0].find(';') != -1: # found
dims = dims[0].split(';')
else:
dims = dims[0].split(',')
dimensions = {}
for p in dims:
try:
(n, v) = p.split('=', 1)
except ValueError:
n = p
v = ""
dimensions[n] = v
return dimensions
def format_dimensions(dict):
return 'dimensions: {\n' + format_dict(dict) + '\n}'
def format_expression_data(data):
# takes an dictionary containing a dict
string_list = list()
for k, v in data.items():
if k == 'dimensions':
dim_str = format_dimensions(v)
string_list.append(dim_str)
else:
if isinstance(v, numbers.Number):
d_str = k + ': ' + str(v)
else:
d_str = k + ': ' + v
string_list.append(d_str)
return '\n'.join(string_list)
def format_dictlist(dict_list):
# takes list of dictionaries to format for output
string_list = list()
for mdict in dict_list:
kv_list = list()
for k, v in sorted(mdict.items()):
kv_str = k + ':' + str(v)
kv_list.append(kv_str)
# a string of comma separated k:v
this_dict_str = ','.join(kv_list)
string_list.append(this_dict_str)
return '\n'.join(string_list)
def format_dict(dict):
# takes a dictionary to format for output
dstring_list = list()
for k, v in dict.items():
if isinstance(v, numbers.Number):
d_str = k + ': ' + str(v)
else:
d_str = k + ': ' + v
dstring_list.append(d_str)
return '\n'.join(dstring_list)
def format_list(in_list):
string_list = list()
for k in in_list:
if isinstance(k, unicode):
key = k.encode('utf-8')
else:
key = k
string_list.append(key)
return '\n'.join(string_list)

View File

@ -1,169 +0,0 @@
# Copyright 2017 FUJITSU LIMITED
#
# 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 logging
import six
from osc_lib.command import command
from osc_lib import utils
from monascaclient import version
LOG = logging.getLogger(__name__)
# NOTE(trebskit) this will be moved to another module
# once initial migration is up
# the point is to show how many code can we spare
# in order to get the client working with minimum effort needed
VERSION_MAP = {
'2_0': 'monascaclient.v2_0.client.Client'
}
def make_client(api_version, session=None,
endpoint=None, service_type='monitoring'):
"""Returns an monitoring API client."""
client_cls = utils.get_client_class('monitoring', api_version, VERSION_MAP)
c = client_cls(
session=session,
service_type=service_type,
endpoint=endpoint,
app_name='monascaclient',
app_version=version.version_string,
)
return c
def create_command_class(name, func_module):
"""Dynamically creates subclass of MigratingCommand.
Method takes name of the function, module it is part of
and builds the subclass of :py:class:`MigratingCommand`.
Having a subclass of :py:class:`cliff.command.Command` is mandatory
for the osc-lib integration.
:param name: name of the function
:type name: basestring
:param func_module: the module function is part of
:type func_module: module
:return: command name, subclass of :py:class:`MigratingCommand`
:rtype: tuple(basestring, class)
"""
cmd_name = name[3:].replace('_', '-')
callback = getattr(func_module, name)
desc = callback.__doc__ or ''
help = desc.strip().split('\n')[0]
arguments = getattr(callback, 'arguments', [])
body = {
'_args': arguments,
'_callback': staticmethod(callback),
'_description': desc,
'_epilog': desc,
'_help': help
}
claz = type('%sCommand' % cmd_name.title().replace('-', ''),
(MigratingCommand,), body)
return cmd_name, claz
class MigratingCommandMeta(command.CommandMeta):
"""Overwrite module name based on osc_lib.CommandMeta requirements."""
def __new__(mcs, name, bases, cls_dict):
# NOTE(trebskit) little dirty, but should suffice for migration period
cls_dict['__module__'] = 'monascaclient.v2_0.shell'
return super(MigratingCommandMeta, mcs).__new__(mcs, name,
bases, cls_dict)
@six.add_metaclass(MigratingCommandMeta)
class MigratingCommand(command.Command):
"""MigratingCommand is temporary command.
MigratingCommand allows to map function defined
shell commands from :py:module:`monascaclient.v2_0.shell`
into :py:class:`command.Command` instances.
Note:
This class is temporary solution during migrating
to osc_lib and will be removed when all
shell commands are migrated to cliff commands.
"""
_help = None
_args = None
_callback = None
def __init__(self, app, app_args, cmd_name=None):
super(MigratingCommand, self).__init__(app, app_args, cmd_name)
self._client = None
self._endpoint = None
def take_action(self, parsed_args):
return self._callback(self.mon_client, parsed_args)
def get_parser(self, prog_name):
parser = super(MigratingCommand, self).get_parser(prog_name)
for (args, kwargs) in self._args:
parser.add_argument(*args, **kwargs)
parser.add_argument('-j', '--json',
action='store_true',
help='output raw json response')
return parser
@property
def mon_client(self):
if not self._client:
self.log.debug('Initializing mon-client')
self._client = make_client(api_version=self.mon_version,
endpoint=self.mon_url,
session=self.app.client_manager.session)
return self._client
@property
def mon_version(self):
return self.app_args.monasca_api_version
@property
def mon_url(self):
if self._endpoint:
return self._endpoint
app_args = self.app_args
cm = self.app.client_manager
endpoint = app_args.monasca_api_url
if not endpoint:
req_data = {
'service_type': 'monitoring',
'region_name': cm.region_name,
'interface': cm.interface,
}
LOG.debug('Discovering monasca endpoint using %s' % req_data)
endpoint = cm.get_endpoint_for_service_type(**req_data)
else:
LOG.debug('Using supplied endpoint=%s' % endpoint)
self._endpoint = endpoint
return self._endpoint

View File

@ -1,117 +0,0 @@
# (C) Copyright 2014-2015 Hewlett Packard Enterprise Development Company LP
# Copyright 2017 Fujitsu LIMITED
#
# 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.
"""
Command-line interface to the monasca-client API.
"""
import argparse
import locale
import sys
from osc_lib.api import auth
from osc_lib.cli import client_config as cloud_config
from osc_lib import shell
from osc_lib import utils as utils
from oslo_utils import importutils
import six
from monascaclient.osc import migration
from monascaclient import version as mc_version
class MonascaShell(shell.OpenStackShell):
def __init__(self):
super(MonascaShell, self).__init__(
description=__doc__.strip(),
version=mc_version.version_string
)
self.cloud_config = None
def initialize_app(self, argv):
super(MonascaShell, self).initialize_app(argv)
self.cloud_config = cloud_config.OSC_Config(
override_defaults={
'interface': None,
'auth_type': self._auth_type,
},
)
def build_option_parser(self, description, version):
parser = super(MonascaShell, self).build_option_parser(
description,
version
)
parser = auth.build_auth_plugins_option_parser(parser)
parser = self._append_monasca_args(parser)
return parser
@staticmethod
def _append_monasca_args(parser):
parser.add_argument('--monasca-api-url',
default=utils.env('MONASCA_API_URL'),
help='Defaults to env[MONASCA_API_URL].')
parser.add_argument('--monasca_api_url',
help=argparse.SUPPRESS)
parser.add_argument('--monasca-api-version',
default=utils.env(
'MONASCA_API_VERSION',
default='2_0'),
help='Defaults to env[MONASCA_API_VERSION] or 2_0')
parser.add_argument('--monasca_api_version',
help=argparse.SUPPRESS)
return parser
def _load_commands(self):
version = self.options.monasca_api_version
submodule = importutils.import_versioned_module('monascaclient',
version,
'shell')
self._find_actions(submodule)
def _find_actions(self, actions_module):
for attr in (a for a in dir(actions_module) if a.startswith('do_')):
name, clazz = migration.create_command_class(attr, actions_module)
if 'help' == name:
# help requires no auth
clazz.auth_required = False
self.command_manager.add_command(name, clazz)
def main(args=None):
try:
if args is None:
args = sys.argv[1:]
if six.PY2:
# Emulate Py3, decode argv into Unicode based on locale so that
# commands always see arguments as text instead of binary data
encoding = locale.getpreferredencoding()
if encoding:
args = map(lambda arg: arg.decode(encoding), args)
MonascaShell().run(args)
except Exception as e:
if '--debug' in args or '-d' in args:
raise
else:
print(e)
sys.exit(1)
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))

View File

@ -1,138 +0,0 @@
# (C) Copyright 2014-2017 Hewlett Packard Enterprise Development LP
# Copyright 2017 FUJITSU LIMITED
#
# 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 warnings
import mock
from oslotest import base
from monascaclient import client
class TestMonascaClient(base.BaseTestCase):
@mock.patch('monascaclient.client.migration')
@mock.patch('monascaclient.client._get_auth_handler')
@mock.patch('monascaclient.client._get_session')
def test_should_warn_when_passing_args(self, _, __, ___):
api_version = mock.Mock()
endpoint = mock.Mock()
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
client.Client(api_version, endpoint)
self.assertEqual(1, len(w))
self.assertEqual(DeprecationWarning, w[0].category)
self.assertRegex(
str(w[0].message),
'explicit configuration of the client using'
)
@mock.patch('monascaclient.client.migration')
@mock.patch('monascaclient.client._get_auth_handler')
@mock.patch('monascaclient.client._get_session')
def test_should_not_warn_when_passing_no_args(self, _, __, ___):
api_version = mock.Mock()
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
client.Client(api_version)
self.assertEqual(0, len(w))
@mock.patch('monascaclient.client.migration')
@mock.patch('monascaclient.client._get_auth_handler')
@mock.patch('monascaclient.client._get_session')
def test_should_override_endpoint_if_passed_as_arg(self, get_session,
get_auth, _):
api_version = mock.Mock()
endpoint = mock.Mock()
endpoint_fake = mock.Mock()
auth_val = mock.Mock()
get_auth.return_value = auth_val
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
client.Client(api_version, endpoint, endpoint=endpoint_fake)
self.assertEqual(1, len(w))
get_auth.assert_called_once_with({
'endpoint': endpoint
})
get_session.assert_called_once_with(auth_val, {
'endpoint': endpoint
})
@mock.patch('monascaclient.client.migration')
@mock.patch('monascaclient.client._get_auth_handler')
@mock.patch('monascaclient.client._get_session')
def test_should_override_tenant_name_with_project_name(self,
_,
get_auth,
__):
api_version = mock.Mock()
auth_val = mock.Mock()
tenant_name = mock.Mock()
project_name = tenant_name
get_auth.return_value = auth_val
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
client.Client(api_version, tenant_name=tenant_name)
self.assertEqual(1, len(w))
self.assertEqual(DeprecationWarning, w[0].category)
self.assertRegex(
str(w[0].message),
'Usage of tenant_name has been deprecated in favour '
)
get_auth.assert_called_once_with({
'project_name': project_name
})
@mock.patch('monascaclient.client.migration')
@mock.patch('monascaclient.client._get_auth_handler')
@mock.patch('monascaclient.client._get_session')
def test_should_override_insecure_with_negated_verify(self,
_,
get_auth,
__):
api_version = mock.Mock()
auth_val = mock.Mock()
get_auth.return_value = auth_val
for insecure in [True, False]:
warnings.resetwarnings()
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
client.Client(api_version, insecure=insecure)
self.assertEqual(1, len(w))
self.assertEqual(DeprecationWarning, w[0].category)
self.assertRegex(
str(w[0].message),
'Usage of insecure has been deprecated in favour of'
)
get_auth.assert_called_once_with({
'verify': not insecure
})
get_auth.reset_mock()

View File

@ -1,61 +0,0 @@
# (C) Copyright 2014-2017 Hewlett Packard Enterprise Development LP
# Copyright 2017 FUJITSU LIMITED
#
# 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 mock
from oslotest import base
from monascaclient import shell
class TestMonascaShell(base.BaseTestCase):
@mock.patch('monascaclient.shell.auth')
def test_should_use_auth_plugin_option_parser(self, auth):
auth.build_auth_plugins_option_parser = apop = mock.Mock()
shell.MonascaShell().run([])
apop.assert_called_once()
def test_should_specify_monasca_args(self):
expected_args = [
'--monasca-api-url',
'--monasca-api-version',
'--monasca_api_url',
'--monasca_api_version',
]
parser = mock.Mock()
parser.add_argument = aa = mock.Mock()
shell.MonascaShell._append_monasca_args(parser)
aa.assert_called()
for mc in aa.mock_calls:
name = mc[1][0]
self.assertIn(name, expected_args)
@mock.patch('monascaclient.shell.importutils')
def test_should_load_commands_based_on_api_version(self, iu):
iu.import_versioned_module = ivm = mock.Mock()
instance = shell.MonascaShell()
instance.options = mock.Mock()
instance.options.monasca_api_version = version = mock.Mock()
instance._find_actions = mock.Mock()
instance._load_commands()
ivm.assert_called_once_with('monascaclient', version, 'shell')

View File

@ -1,134 +0,0 @@
# Copyright 2017 FUJITSU LIMITED
#
# 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 mock
from oslotest import base
from monascaclient.osc import migration as migr
from monascaclient.v2_0 import alarm_definitions as ad
from monascaclient.v2_0 import shell
class FakeV2Client(object):
def __init__(self):
super(FakeV2Client, self).__init__()
self.alarm_definitions = mock.Mock(
spec=ad.AlarmDefinitionsManager)
class TestAlarmDefinitionShellV2(base.BaseTestCase):
@mock.patch('monascaclient.osc.migration.make_client')
def test_should_update(self, mc):
mc.return_value = c = FakeV2Client()
ad_id = '0495340b-58fd-4e1c-932b-5e6f9cc96490'
ad_name = 'alarm_name'
ad_desc = 'test_alarm_definition'
ad_expr = 'avg(Test_Metric_1)>=10'
ad_action_id = '16012650-0b62-4692-9103-2d04fe81cc93'
ad_action_enabled = 'True'
ad_match_by = 'hostname'
ad_severity = 'CRITICAL'
raw_args = [
ad_id, ad_name, ad_desc, ad_expr,
ad_action_id, ad_action_id, ad_action_id, ad_action_enabled,
ad_match_by, ad_severity
]
name, cmd_clazz = migr.create_command_class(
'do_alarm_definition_update',
shell
)
cmd = cmd_clazz(mock.Mock(), mock.Mock())
parser = cmd.get_parser(name)
parsed_args = parser.parse_args(raw_args)
cmd.run(parsed_args)
c.alarm_definitions.update.assert_called_once_with(
actions_enabled=True,
alarm_actions=[ad_action_id],
alarm_id=ad_id,
description=ad_desc,
expression=ad_expr,
match_by=[ad_match_by],
name=ad_name,
ok_actions=[ad_action_id],
severity=ad_severity,
undetermined_actions=[ad_action_id]
)
@mock.patch('monascaclient.osc.migration.make_client')
def test_should_patch_name(self, mc):
ad_id = '0495340b-58fd-4e1c-932b-5e6f9cc96490'
ad_name = 'patch_name'
raw_args = '{0} --name {1}'.format(ad_id, ad_name).split(' ')
self._patch_test(mc, raw_args, alarm_id=ad_id, name=ad_name)
@mock.patch('monascaclient.osc.migration.make_client')
def test_should_patch_actions(self, mc):
ad_id = '0495340b-58fd-4e1c-932b-5e6f9cc96490'
ad_action_id = '16012650-0b62-4692-9103-2d04fe81cc93'
actions = ['alarm-actions', 'ok-actions',
'undetermined-actions']
for action in actions:
raw_args = ('{0} --{1} {2}'.format(ad_id, action, ad_action_id)
.split(' '))
self._patch_test(mc, raw_args, **{
'alarm_id': ad_id,
action.replace('-', '_'): [ad_action_id]
})
@mock.patch('monascaclient.osc.migration.make_client')
def test_should_patch_severity(self, mc):
ad_id = '0495340b-58fd-4e1c-932b-5e6f9cc96490'
severity_types = ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']
for st in severity_types:
raw_args = ('{0} --severity {1}'.format(ad_id, st)
.split(' '))
self._patch_test(mc, raw_args, alarm_id=ad_id, severity=st)
@mock.patch('monascaclient.osc.migration.make_client')
def test_should_not_patch_unknown_severity(self, mc):
ad_id = '0495340b-58fd-4e1c-932b-5e6f9cc96490'
st = 'foo'
raw_args = ('{0} --severity {1}'.format(ad_id, st)
.split(' '))
self._patch_test(mc, raw_args, called=False)
@staticmethod
def _patch_test(mc, args, called=True, **kwargs):
mc.return_value = c = FakeV2Client()
name, cmd_clazz = migr.create_command_class(
'do_alarm_definition_patch',
shell
)
cmd = cmd_clazz(mock.Mock(), mock.Mock())
parser = cmd.get_parser(name)
parsed_args = parser.parse_args(args)
cmd.run(parsed_args)
if called:
c.alarm_definitions.patch.assert_called_once_with(**kwargs)
else:
c.alarm_definitions.patch.assert_not_called()

View File

@ -1,85 +0,0 @@
# Copyright 2017 FUJITSU LIMITED
#
# 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 mock
from oslotest import base
from monascaclient.osc import migration as migr
from monascaclient.v2_0 import metrics
from monascaclient.v2_0 import shell
class FakeV2Client(object):
def __init__(self):
super(FakeV2Client, self).__init__()
self.metrics = mock.Mock(spec=metrics.MetricsManager)
class TestMetricsShellV2(base.BaseTestCase):
def test_bad_metrics(self):
raw_args_list = [
['metric1'],
['123'],
['']
]
name, cmd_clazz = migr.create_command_class('do_metric_create',
shell)
for raw_args in raw_args_list:
cmd = cmd_clazz(mock.Mock(), mock.Mock())
parser = cmd.get_parser(name)
self.assertRaises(SystemExit, parser.parse_args, raw_args)
@mock.patch('monascaclient.osc.migration.make_client')
def test_metric_create(self, mc):
mc.return_value = c = FakeV2Client()
raw_args = 'metric1 123 --time 1395691090'.split(' ')
name, cmd_clazz = migr.create_command_class('do_metric_create',
shell)
cmd = cmd_clazz(mock.Mock(), mock.Mock())
parser = cmd.get_parser(name)
parsed_args = parser.parse_args(raw_args)
cmd.run(parsed_args)
data = {'timestamp': 1395691090,
'name': 'metric1',
'value': 123.0}
c.metrics.create.assert_called_once_with(**data)
@mock.patch('monascaclient.osc.migration.make_client')
def test_metric_create_with_project_id(self, mc):
mc.return_value = c = FakeV2Client()
project_id = 'd48e63e76a5c4e05ba26a1185f31d4aa'
raw_args = ('metric1 123 --time 1395691090 --project-id %s'
% project_id).split(' ')
name, cmd_clazz = migr.create_command_class('do_metric_create',
shell)
cmd = cmd_clazz(mock.Mock(), mock.Mock())
parser = cmd.get_parser(name)
parsed_args = parser.parse_args(raw_args)
cmd.run(parsed_args)
data = {'timestamp': 1395691090,
'name': 'metric1',
'tenant_id': project_id,
'value': 123.0}
c.metrics.create.assert_called_once_with(**data)

View File

@ -1,52 +0,0 @@
# Copyright 2017 FUJITSU LIMITED
#
# 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 mock
from oslotest import base
from monascaclient.osc import migration as migr
from monascaclient.v2_0 import notificationtypes
from monascaclient.v2_0 import shell
class FakeV2Client(object):
def __init__(self):
super(FakeV2Client, self).__init__()
self.notificationtypes = mock.Mock(
spec=notificationtypes.NotificationTypesManager)
class TestNotificationsTypesShellV2(base.BaseTestCase):
@mock.patch('monascaclient.osc.migration.make_client')
def test_notification_types_list(self, mc):
mc.return_value = c = FakeV2Client()
c.notificationtypes.list.return_value = [
{"type": "WEBHOOK"},
{"type": "EMAIL"},
{"type": "PAGERDUTY"}
]
raw_args = []
name, cmd_clazz = migr.create_command_class('do_notification_type_list',
shell)
cmd = cmd_clazz(mock.Mock(), mock.Mock())
parser = cmd.get_parser(name)
parsed_args = parser.parse_args(raw_args)
cmd.run(parsed_args)
c.notificationtypes.list.assert_called_once()

View File

@ -1,160 +0,0 @@
# Copyright 2017 FUJITSU LIMITED
#
# 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 mock
from oslotest import base
from monascaclient.osc import migration as migr
from monascaclient.v2_0 import notifications
from monascaclient.v2_0 import shell
class FakeV2Client(object):
def __init__(self):
super(FakeV2Client, self).__init__()
self.notifications = mock.Mock(spec=notifications.NotificationsManager)
class TestNotificationsShellV2(base.BaseTestCase):
@mock.patch('monascaclient.osc.migration.make_client')
def test_notification_create_email(self, mc):
mc.return_value = c = FakeV2Client()
raw_args = ['email1', 'EMAIL', 'john.doe@hp.com']
name, cmd_clazz = migr.create_command_class('do_notification_create',
shell)
cmd = cmd_clazz(mock.Mock(), mock.Mock())
parser = cmd.get_parser(name)
parsed_args = parser.parse_args(raw_args)
cmd.run(parsed_args)
data = {'name': 'email1',
'type': 'EMAIL',
'address': 'john.doe@hp.com'}
c.notifications.create.assert_called_once_with(**data)
@mock.patch('monascaclient.osc.migration.make_client')
def test_notification_create_webhook(self, mc):
mc.return_value = c = FakeV2Client()
raw_args = ['mypost', 'WEBHOOK', 'http://localhost:8080']
name, cmd_clazz = migr.create_command_class('do_notification_create',
shell)
cmd = cmd_clazz(mock.Mock(), mock.Mock())
parser = cmd.get_parser(name)
parsed_args = parser.parse_args(raw_args)
cmd.run(parsed_args)
data = {'name': 'mypost',
'type': 'WEBHOOK',
'address': 'http://localhost:8080'}
c.notifications.create.assert_called_once_with(**data)
@mock.patch('monascaclient.osc.migration.make_client')
def test_good_notifications_patch(self, mc):
args = '--type EMAIL --address john.doe@hpe.com --period 0'
data = {'type': 'EMAIL',
'address': 'john.doe@hpe.com',
'period': 0}
self._patch_test(mc, args, data)
@mock.patch('monascaclient.osc.migration.make_client')
def test_good_notifications_patch_just_name(self, mc):
name = 'fred'
args = '--name ' + name
data = {'name': name}
self._patch_test(mc, args, data)
@mock.patch('monascaclient.osc.migration.make_client')
def test_good_notifications_patch_just_address(self, mc):
address = 'fred@fl.com'
args = '--address ' + address
data = {'address': address}
self._patch_test(mc, args, data)
@mock.patch('monascaclient.osc.migration.make_client')
def test_good_notifications_patch_just_period(self, mc):
period = 0
args = '--period ' + str(period)
data = {'period': period}
self._patch_test(mc, args, data)
@mock.patch('monascaclient.osc.migration.make_client')
def test_bad_notifications_patch(self, mc):
mc.return_value = c = FakeV2Client()
id_str = '0495340b-58fd-4e1c-932b-5e6f9cc96490'
raw_args = ('{0} --type EMAIL --address john.doe@hpe.com '
'--period 60').format(id_str).split(' ')
name, cmd_clazz = migr.create_command_class('do_notification_patch',
shell)
cmd = cmd_clazz(mock.Mock(), mock.Mock())
parser = cmd.get_parser(name)
parsed_args = parser.parse_args(raw_args)
cmd.run(parsed_args)
c.notifications.patch.assert_not_called()
@mock.patch('monascaclient.osc.migration.make_client')
def test_good_notifications_update(self, mc):
mc.return_value = c = FakeV2Client()
id_str = '0495340b-58fd-4e1c-932b-5e6f9cc96491'
raw_args = ('{0} notification_updated_name '
'EMAIL john.doe@hpe.com 0').format(id_str).split(' ')
name, cmd_clazz = migr.create_command_class('do_notification_update',
shell)
cmd = cmd_clazz(mock.Mock(), mock.Mock())
parser = cmd.get_parser(name)
parsed_args = parser.parse_args(raw_args)
cmd.run(parsed_args)
data = {
'name': 'notification_updated_name',
'type': 'EMAIL',
'address': 'john.doe@hpe.com',
'period': 0,
'notification_id': id_str
}
c.notifications.update.assert_called_once_with(**data)
@staticmethod
def _patch_test(mc, args, data):
mc.return_value = c = FakeV2Client()
id_str = '0495340b-58fd-4e1c-932b-5e6f9cc96490'
raw_args = '{0} {1}'.format(id_str, args).split(' ')
name, cmd_clazz = migr.create_command_class('do_notification_patch',
shell)
cmd = cmd_clazz(mock.Mock(), mock.Mock())
parser = cmd.get_parser(name)
parsed_args = parser.parse_args(raw_args)
cmd.run(parsed_args)
# add notification_id to data
data['notification_id'] = id_str
c.notifications.patch.assert_called_once_with(**data)

View File

@ -1,18 +0,0 @@
# (C) Copyright 2014 Hewlett Packard Enterprise Development Company LP
#
# 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.
__all__ = ['Client']
from monascaclient.v2_0.client import Client

View File

@ -1,69 +0,0 @@
# (C) Copyright 2014-2015 Hewlett Packard Enterprise Development Company LP
# Copyright 2017 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from monascaclient.common import monasca_manager
class AlarmDefinitionsManager(monasca_manager.MonascaManager):
base_url = '/alarm-definitions'
def create(self, **kwargs):
"""Create an alarm definition."""
resp = self.client.create(url=self.base_url,
json=kwargs)
return resp
def get(self, **kwargs):
"""Get the details for a specific alarm definition."""
# NOTE(trebskit) should actually be find_one, but
# monasca does not support expected response format
url = '%s/%s' % (self.base_url, kwargs['alarm_id'])
resp = self.client.list(path=url)
return resp
def list(self, **kwargs):
"""Get a list of alarm definitions."""
return self._list('', 'dimensions', **kwargs)
def delete(self, **kwargs):
"""Delete a specific alarm definition."""
url_str = self.base_url + '/%s' % kwargs['alarm_id']
resp = self.client.delete(url_str)
return resp
def update(self, **kwargs):
"""Update a specific alarm definition."""
url_str = self.base_url + '/%s' % kwargs['alarm_id']
del kwargs['alarm_id']
resp = self.client.create(url=url_str,
method='PUT',
json=kwargs)
return resp
def patch(self, **kwargs):
"""Patch a specific alarm definition."""
url_str = self.base_url + '/%s' % kwargs['alarm_id']
del kwargs['alarm_id']
resp = self.client.create(url=url_str,
method='PATCH',
json=kwargs)
return resp

View File

@ -1,97 +0,0 @@
# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
# Copyright 2017 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from six.moves.urllib import parse
from monascaclient.common import monasca_manager
class AlarmsManager(monasca_manager.MonascaManager):
base_url = '/alarms'
def get(self, **kwargs):
"""Get the details for a specific alarm."""
# NOTE(trebskit) should actually be find_one, but
# monasca does not support expected response format
url = '%s/%s' % (self.base_url, kwargs['alarm_id'])
resp = self.client.list(path=url)
return resp
def list(self, **kwargs):
"""Get a list of alarms."""
return self._list('', 'metric_dimensions', **kwargs)
def delete(self, **kwargs):
"""Delete a specific alarm."""
url_str = self.base_url + '/%s' % kwargs['alarm_id']
resp = self.client.delete(url_str)
return resp
def update(self, **kwargs):
"""Update a specific alarm."""
url_str = self.base_url + '/%s' % kwargs['alarm_id']
del kwargs['alarm_id']
body = self.client.create(url=url_str,
method='PUT',
json=kwargs)
return body
def patch(self, **kwargs):
"""Patch a specific alarm."""
url_str = self.base_url + '/%s' % kwargs['alarm_id']
del kwargs['alarm_id']
resp = self.client.create(url=url_str,
method='PATCH',
json=kwargs)
return resp
def count(self, **kwargs):
url_str = self.base_url + '/count'
if 'metric_dimensions' in kwargs:
dimstr = self.get_dimensions_url_string(
kwargs['metric_dimensions'])
kwargs['metric_dimensions'] = dimstr
if kwargs:
url_str = url_str + '?%s' % parse.urlencode(kwargs, True)
body = self.client.list(url_str)
return body
def history(self, **kwargs):
"""History of a specific alarm."""
url_str = self.base_url + '/%s/state-history' % kwargs['alarm_id']
del kwargs['alarm_id']
if kwargs:
url_str = url_str + '?%s' % parse.urlencode(kwargs, True)
resp = self.client.list(url_str)
return resp['elements'] if type(resp) is dict else resp
def history_list(self, **kwargs):
"""History list of alarm state."""
url_str = self.base_url + '/state-history/'
if 'dimensions' in kwargs:
dimstr = self.get_dimensions_url_string(kwargs['dimensions'])
kwargs['dimensions'] = dimstr
if kwargs:
url_str = url_str + '?%s' % parse.urlencode(kwargs, True)
resp = self.client.list(url_str)
return resp['elements'] if type(resp) is dict else resp

View File

@ -1,40 +0,0 @@
# (C) Copyright 2014-2015 Hewlett Packard Enterprise Development Company LP
# Copyright 2017 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from osc_lib.api import api
from monascaclient.v2_0 import alarm_definitions as ad
from monascaclient.v2_0 import alarms
from monascaclient.v2_0 import metrics
from monascaclient.v2_0 import notifications
from monascaclient.v2_0 import notificationtypes as nt
class Client(object):
def __init__(self, *args, **kwargs):
"""Initialize a new http client for the monasca API."""
client = MonascaApi(*args, **kwargs)
self.metrics = metrics.MetricsManager(client)
self.notifications = notifications.NotificationsManager(client)
self.alarms = alarms.AlarmsManager(client)
self.alarm_definitions = ad.AlarmDefinitionsManager(client)
self.notificationtypes = nt.NotificationTypesManager(client)
class MonascaApi(api.BaseAPI):
SERVICE_TYPE = "monitoring"

View File

@ -1,56 +0,0 @@
# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP
# Copyright 2017 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from monascaclient.common import monasca_manager
class MetricsManager(monasca_manager.MonascaManager):
base_url = '/metrics'
def create(self, **kwargs):
"""Create a metric."""
url_str = self.base_url
if 'tenant_id' in kwargs:
url_str = url_str + '?tenant_id=%s' % kwargs['tenant_id']
del kwargs['tenant_id']
data = kwargs['jsonbody'] if 'jsonbody' in kwargs else kwargs
body = self.client.create(url=url_str, json=data)
return body
def list(self, **kwargs):
"""Get a list of metrics."""
return self._list('', 'dimensions', **kwargs)
def list_names(self, **kwargs):
"""Get a list of metric names."""
return self._list('/names', 'dimensions', **kwargs)
def list_measurements(self, **kwargs):
"""Get a list of measurements based on metric definition filters."""
return self._list('/measurements', 'dimensions', **kwargs)
def list_statistics(self, **kwargs):
"""Get a list of measurement statistics based on metric def filters."""
return self._list('/statistics', 'dimensions', **kwargs)
def list_dimension_names(self, **kwargs):
"""Get a list of metric dimension names."""
return self._list('/dimensions/names', **kwargs)
def list_dimension_values(self, **kwargs):
"""Get a list of metric dimension values."""
return self._list('/dimensions/names/values', **kwargs)

View File

@ -1,68 +0,0 @@
# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP
# Copyright 2017 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from monascaclient.common import monasca_manager
class NotificationsManager(monasca_manager.MonascaManager):
base_url = '/notification-methods'
def create(self, **kwargs):
"""Create a notification."""
body = self.client.create(url=self.base_url,
json=kwargs)
return body
def get(self, **kwargs):
"""Get the details for a specific notification."""
# NOTE(trebskit) should actually be find_one, but
# monasca does not support expected response format
url = '%s/%s' % (self.base_url, kwargs['notification_id'])
resp = self.client.list(path=url)
return resp
def list(self, **kwargs):
"""Get a list of notifications."""
return self._list('', **kwargs)
def delete(self, **kwargs):
"""Delete a notification."""
url = self.base_url + '/%s' % kwargs['notification_id']
resp = self.client.delete(url=url)
return resp
def update(self, **kwargs):
"""Update a notification."""
url_str = self.base_url + '/%s' % kwargs['notification_id']
del kwargs['notification_id']
resp = self.client.create(url=url_str,
method='PUT',
json=kwargs)
return resp
def patch(self, **kwargs):
"""Patch a notification."""
url_str = self.base_url + '/%s' % kwargs['notification_id']
del kwargs['notification_id']
resp = self.client.create(url=url_str,
method='PATCH',
json=kwargs)
return resp

View File

@ -1,25 +0,0 @@
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
# Copyright 2017 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from monascaclient.common import monasca_manager
class NotificationTypesManager(monasca_manager.MonascaManager):
base_url = '/notification-methods/types'
def list(self, **kwargs):
"""Get a list of notifications."""
return self._list('', **kwargs)

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +0,0 @@
# Copyright 2017 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from pbr import version
__all__ = ['version_info', 'version_string']
version_info = version.VersionInfo('python-monascaclient')
version_string = version_info.version_string()

View File

@ -1,16 +0,0 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
osc-lib>=1.7.0 # Apache-2.0
oslo.serialization!=2.19.1,>=1.10.0 # Apache-2.0
oslo.utils>=3.20.0 # Apache-2.0
Babel!=2.4.0,>=2.3.4 # BSD
iso8601>=0.1.11 # MIT
pbr!=2.1.0,>=2.0.0 # Apache-2.0
PrettyTable<0.8,>=0.7.1 # BSD
PyYAML>=3.10.0 # MIT
six>=1.9.0 # MIT

View File

@ -1,120 +0,0 @@
#!/bin/bash
BASE_DIR=`dirname $0`
function usage {
echo "Usage: $0 [OPTION]..."
echo "Run monascaclient test suite(s)"
echo ""
echo " -V, --virtual-env Use virtualenv. Install automatically if not present."
echo " (Default is to run tests in local environment)"
echo " -F, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added."
echo " -f, --func Functional tests have been removed."
echo " -u, --unit Run unit tests (default when nothing specified)"
echo " -p, --pep8 Run pep8 tests"
echo " --all Run pep8 and unit tests"
echo " -c, --coverage Generate coverage report"
echo " -d, --debug Run tests with testtools instead of testr. This allows you to use the debugger."
echo " -h, --help Print this usage message"
exit
}
# must not assign -a as an option, needed for selecting custom attributes
no_venv=1
function process_option {
case "$1" in
-V|--virtual-env) no_venv=0;;
-F|--force) force=1;;
-f|--func) test_func=1;;
-u|--unit) test_unit=1;;
-p|--pep8) test_pep8=1;;
--all) test_unit=1; test_pep8=1;;
-c|--coverage) coverage=1;;
-d|--debug) debug=1;;
-h|--help) usage;;
*) args="$args $1"; test_unit=1;;
esac
}
venv=.venv
with_venv=tools/with_venv.sh
wrapper=""
debug=0
function run_tests {
echo 'Running tests'
if [ $debug -eq 1 ]; then
echo "Debugging..."
if [ "$args" = "" ]; then
# Default to running all tests if specific test is not
# provided.
testrargs="discover ./monascaclient/tests"
fi
${wrapper} python -m testtools.run $args $testrargs
# Short circuit because all of the testr and coverage stuff
# below does not make sense when running testtools.run for
# debugging purposes.
return $?
fi
# Just run the test suites in current environment
if [ -n "$args" ] ; then
args="-t $args"
fi
${wrapper} python setup.py testr --slowest $args
}
function run_pep8 {
echo "Running flake8..."
bash -c "${wrapper} flake8"
}
# run unit tests with pep8 when no arguments are specified
# otherwise process CLI options
if [[ $# == 0 ]]; then
test_pep8=1
test_unit=1
else
for arg in "$@"; do
process_option $arg
done
fi
if [ "$no_venv" == 0 ]; then
# Remove the virtual environment if --force used
if [ "$force" == 1 ]; then
echo "Cleaning virtualenv..."
rm -rf ${venv}
fi
if [ -e ${venv} ]; then
wrapper="${with_venv}"
else
# Automatically install the virtualenv
python tools/install_venv.py
wrapper="${with_venv}"
fi
fi
result=0
# If functional or unit tests have been selected, run them
if [ "$test_unit" == 1 ] || [ "$debug" == 1 ] ; then
run_tests
result=$?
fi
# Run pep8 if it was selected
if [ "$test_pep8" == 1 ]; then
run_pep8
fi
# Generate coverage report
if [ "$coverage" == 1 ]; then
echo "Generating coverage report in ./cover"
${wrapper} python setup.py testr --coverage --slowest
${wrapper} python -m coverage report --show-missing
fi
exit $result

View File

@ -1,33 +0,0 @@
[metadata]
name = python-monascaclient
summary = Monasca API Client Library
description-file = README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
home-page = https://github.com/openstack/python-monascaclient
classifier =
Environment :: Console
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3.5
[files]
packages = monascaclient
data_files =
share = tools/monasca.bash_completion
[entry_points]
console_scripts =
monasca = monascaclient.shell:main
[pbr]
autodoc_index_modules = True
[wheel]
universal = 1

View File

@ -1,29 +0,0 @@
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
#
# 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 MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
# In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215
try:
import multiprocessing # noqa
except ImportError:
pass
setuptools.setup(
setup_requires=['pbr>=2.0.0'],
pbr=True)

View File

@ -1,12 +0,0 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
bandit>=1.1.0 # Apache-2.0
coverage!=4.4,>=4.0 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0
os-testr>=0.8.0 # Apache-2.0
testrepository>=0.0.18 # Apache-2.0/BSD
testscenarios>=0.4 # Apache-2.0/BSD
testtools>=1.4.0 # MIT

View File

@ -1,76 +0,0 @@
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Copyright 2010 OpenStack Foundation
# Copyright 2013 IBM Corp.
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
#
# 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 os
import sys
import install_venv_common as install_venv # flake8: noqa
from six.moves import configparser as ConfigParser
def print_help(project, venv, root):
help = """
%(project)s development environment setup is complete.
%(project)s development uses virtualenv to track and manage Python
dependencies while in development and testing.
To activate the %(project)s virtualenv for the extent of your current
shell session you can run:
$ source %(venv)s/bin/activate
Or, if you prefer, you can run commands in the virtualenv on a case by
case basis by running:
$ %(root)s/tools/with_venv.sh <your command>
"""
print(help % dict(project=project, venv=venv, root=root))
def main(argv):
root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
if os.environ.get('tools_path'):
root = os.environ['tools_path']
venv = os.path.join(root, '.venv')
if os.environ.get('venv'):
venv = os.environ['venv']
pip_requires = os.path.join(root, 'requirements.txt')
test_requires = os.path.join(root, 'test-requirements.txt')
py_version = "python%s.%s" % (sys.version_info[0], sys.version_info[1])
setup_cfg = ConfigParser.ConfigParser()
setup_cfg.read('setup.cfg')
project = setup_cfg.get('metadata', 'name')
install = install_venv.InstallVenv(
root, venv, pip_requires, test_requires, py_version, project)
options = install.parse_args(argv)
install.check_python_version()
install.check_dependencies()
install.create_virtualenv(no_site_packages=options.no_site_packages)
install.install_dependencies()
#install.post_process()
print_help(project, venv, root)
if __name__ == '__main__':
main(sys.argv)

View File

@ -1,172 +0,0 @@
# Copyright 2013 OpenStack Foundation
# Copyright 2013 IBM Corp.
#
# 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.
"""Provides methods needed by installation script for OpenStack development
virtual environments.
Since this script is used to bootstrap a virtualenv from the system's Python
environment, it should be kept strictly compatible with Python 2.6.
Synced in from openstack-common
"""
from __future__ import print_function
import optparse
import os
import subprocess
import sys
class InstallVenv(object):
def __init__(self, root, venv, requirements,
test_requirements, py_version,
project):
self.root = root
self.venv = venv
self.requirements = requirements
self.test_requirements = test_requirements
self.py_version = py_version
self.project = project
def die(self, message, *args):
print(message % args, file=sys.stderr)
sys.exit(1)
def check_python_version(self):
if sys.version_info < (2, 6):
self.die("Need Python Version >= 2.6")
def run_command_with_code(self, cmd, redirect_output=True,
check_exit_code=True):
"""Runs a command in an out-of-process shell.
Returns the output of that command. Working directory is self.root.
"""
if redirect_output:
stdout = subprocess.PIPE
else:
stdout = None
proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout)
output = proc.communicate()[0]
if check_exit_code and proc.returncode != 0:
self.die('Command "%s" failed.\n%s', ' '.join(cmd), output)
return (output, proc.returncode)
def run_command(self, cmd, redirect_output=True, check_exit_code=True):
return self.run_command_with_code(cmd, redirect_output,
check_exit_code)[0]
def get_distro(self):
if (os.path.exists('/etc/fedora-release') or
os.path.exists('/etc/redhat-release')):
return Fedora(
self.root, self.venv, self.requirements,
self.test_requirements, self.py_version, self.project)
else:
return Distro(
self.root, self.venv, self.requirements,
self.test_requirements, self.py_version, self.project)
def check_dependencies(self):
self.get_distro().install_virtualenv()
def create_virtualenv(self, no_site_packages=True):
"""Creates the virtual environment and installs PIP.
Creates the virtual environment and installs PIP only into the
virtual environment.
"""
if not os.path.isdir(self.venv):
print('Creating venv...', end=' ')
if no_site_packages:
self.run_command(['virtualenv', '-q', '--no-site-packages',
self.venv])
else:
self.run_command(['virtualenv', '-q', self.venv])
print('done.')
else:
print("venv already exists...")
pass
def pip_install(self, *args):
self.run_command(['tools/with_venv.sh',
'pip', 'install', '--upgrade'] + list(args),
redirect_output=False)
def install_dependencies(self):
print('Installing dependencies with pip (this can take a while)...')
# First things first, make sure our venv has the latest pip and
# setuptools and pbr
self.pip_install('pip>=1.4')
self.pip_install('setuptools')
self.pip_install('pbr')
self.pip_install('-r', self.requirements, '-r', self.test_requirements)
def parse_args(self, argv):
"""Parses command-line arguments."""
parser = optparse.OptionParser()
parser.add_option('-n', '--no-site-packages',
action='store_true',
help="Do not inherit packages from global Python "
"install")
return parser.parse_args(argv[1:])[0]
class Distro(InstallVenv):
def check_cmd(self, cmd):
return bool(self.run_command(['which', cmd],
check_exit_code=False).strip())
def install_virtualenv(self):
if self.check_cmd('virtualenv'):
return
if self.check_cmd('easy_install'):
print('Installing virtualenv via easy_install...', end=' ')
if self.run_command(['easy_install', 'virtualenv']):
print('Succeeded')
return
else:
print('Failed')
self.die('ERROR: virtualenv not found.\n\n%s development'
' requires virtualenv, please install it using your'
' favorite package management tool' % self.project)
class Fedora(Distro):
"""This covers all Fedora-based distributions.
Includes: Fedora, RHEL, CentOS, Scientific Linux
"""
def check_pkg(self, pkg):
return self.run_command_with_code(['rpm', '-q', pkg],
check_exit_code=False)[1] == 0
def install_virtualenv(self):
if self.check_cmd('virtualenv'):
return
if not self.check_pkg('python-virtualenv'):
self.die("Please install 'python-virtualenv'.")
super(Fedora, self).install_virtualenv()

View File

@ -1,27 +0,0 @@
# bash completion for openstack monasca
_monasca_opts="" # lazy init
_monasca_flags="" # lazy init
_monasca_opts_exp="" # lazy init
_monasca()
{
local cur prev kbc
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
if [ "x$_monasca_opts" == "x" ] ; then
kbc="`monasca bash-completion | sed -e "s/ -h / /"`"
_monasca_opts="`echo "$kbc" | sed -e "s/--[a-z0-9_-]*//g" -e "s/[ ][ ]*/ /g"`"
_monasca_flags="`echo " $kbc" | sed -e "s/ [^-][^-][a-z0-9_-]*//g" -e "s/[ ][ ]*/ /g"`"
_monasca_opts_exp="`echo $_monasca_opts | sed -e "s/[ ]/|/g"`"
fi
if [[ " ${COMP_WORDS[@]} " =~ " "($_monasca_opts_exp)" " && "$prev" != "help" ]] ; then
COMPREPLY=($(compgen -W "${_monasca_flags}" -- ${cur}))
else
COMPREPLY=($(compgen -W "${_monasca_opts}" -- ${cur}))
fi
return 0
}
complete -o default -F _monasca monasca

View File

@ -1,30 +0,0 @@
#!/bin/bash
#
# Enforce the requirement that dependencies are listed in the input
# files in alphabetical order.
# FIXME(dhellmann): This doesn't deal with URL requirements very
# well. We should probably sort those on the egg-name, rather than the
# full line.
function check_file {
typeset f=$1
# We don't care about comment lines.
grep -v '^#' $f > ${f}.unsorted
sort -i -f ${f}.unsorted > ${f}.sorted
diff -c ${f}.unsorted ${f}.sorted
rc=$?
rm -f ${f}.sorted ${f}.unsorted
return $rc
}
exit_code=0
for filename in $@; do
check_file $filename
if [ $? -ne 0 ]; then
echo "Please list requirements in $filename in alphabetical order" 1>&2
exit_code=1
fi
done
exit $exit_code

View File

@ -1,30 +0,0 @@
#!/usr/bin/env bash
# Client constraint file contains this client version pin that is in conflict
# with installing the client from source. We should remove the version pin in
# the constraints file before applying it for from-source installation.
CONSTRAINTS_FILE=$1
shift 1
set -e
# NOTE(tonyb): Place this in the tox enviroment's log dir so it will get
# published to logs.openstack.org for easy debugging.
localfile="$VIRTUAL_ENV/log/upper-constraints.txt"
if [[ $CONSTRAINTS_FILE != http* ]]; then
CONSTRAINTS_FILE=file://$CONSTRAINTS_FILE
fi
# NOTE(tonyb): need to add curl to bindep.txt if the project supports bindep
curl $CONSTRAINTS_FILE --insecure --progress-bar --output $localfile
pip install -c$localfile openstack-requirements
# This is the main purpose of the script: Allow local installation of
# the current repo. It is listed in constraints file and thus any
# install will be constrained and we need to unconstrain it.
edit-constraints $localfile -- $CLIENT_NAME
pip install -c$localfile -U $*
exit $?

View File

@ -1,10 +0,0 @@
#!/bin/bash
command -v tox > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo 'This script requires "tox" to run.'
echo 'You can install it with "pip install tox".'
exit 1;
fi
tox -evenv -- $@

82
tox.ini
View File

@ -1,82 +0,0 @@
[tox]
envlist = py{27,35},pypy,cover,pep8
minversion = 2.5
skipsdist = True
[testenv]
setenv =
VIRTUAL_ENV={envdir}
BRANCH_NAME=master
CLIENT_NAME=python-monascaclient
OS_TEST_PATH=monascaclient/tests
passenv = *_proxy
*_PROXY
usedevelop = True
install_command =
{toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
deps = -r{toxinidir}/test-requirements.txt
whitelist_externals = bash
find
rm
commands =
find . -type f -name "*.pyc" -delete
rm -Rf .testrepository/times.dbm
[testenv:py27]
basepython = python2.7
commands =
{[testenv]commands}
ostestr {posargs}
[testenv:py35]
basepython = python3.5
commands =
{[testenv]commands}
ostestr {posargs}
[testenv:pypy]
basepython = pypy
commands =
{[testenv]commands}
ostestr {posargs}
[testenv:cover]
basepython = python2.7
commands =
{[testenv]commands}
coverage erase
python setup.py test --coverage --testr-args='{posargs}' --coverage-package-name=monascaclient
coverage report
[testenv:debug]
commands =
{[testenv]commands}
oslo_debug_helper -t {env:OS_TEST_PATH} {posargs}
[testenv:pep8]
skip_install = True
usedevelop = False
commands =
{[testenv:flake8]commands}
{[testenv:bandit]commands}
[testenv:flake8]
skip_install = True
usedevelop = False
commands =
flake8 monascaclient
[testenv:bandit]
skip_install = True
usedevelop = False
commands =
bandit -r monascaclient -n5 -x {env:OS_TEST_PATH}
[testenv:venv]
commands = {posargs}
[flake8]
show-source = True
max-line-length = 120
builtins = _
exclude=.venv,.git,.tox,dist,client_api_example.py,*lib/python*,*egg,build