Compare commits
48 Commits
stable/new
...
ocata-eol
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
884a227b03 | ||
|
|
58128dee7e | ||
|
|
c8be166dd3 | ||
|
|
21f98cf00c | ||
| dd510d32f9 | |||
| 692d403a3e | |||
|
|
2fe71f729a | ||
|
|
c6b90fc6e6 | ||
|
|
d9aa46de34 | ||
|
|
56e6f689bb | ||
|
|
75755b2af3 | ||
|
|
40ddf6a470 | ||
|
|
287dd57185 | ||
|
|
416a717ebc | ||
|
|
efb2b0949a | ||
|
|
a567600b77 | ||
|
|
d04e5ac776 | ||
|
|
a1f45a0206 | ||
|
|
2211d48f72 | ||
|
|
e402ce676c | ||
|
|
c423ca4470 | ||
|
|
f750d31169 | ||
|
|
cdbcafd142 | ||
|
|
cffa8b8936 | ||
|
|
10f80c7d02 | ||
|
|
87cdbb1340 | ||
|
|
cede66dde6 | ||
|
|
addb3a8b33 | ||
|
|
04bf3504ee | ||
|
|
b6f7a7831f | ||
|
|
70cef21224 | ||
|
|
8fa848fb51 | ||
|
|
d70f9c778c | ||
|
|
ddf93becc1 | ||
|
|
0024760bef | ||
|
|
5d43074cc4 | ||
|
|
d82273fcd4 | ||
|
|
241d90f541 | ||
|
|
708aeff9b7 | ||
|
|
9a9399f284 | ||
|
|
a070f5b16c | ||
|
|
9a1f531155 | ||
|
|
d0f0aaf346 | ||
|
|
a93f8b04b1 | ||
|
|
e6daa3df81 | ||
|
|
7a199820d0 | ||
|
|
d4ae928048 | ||
|
|
0de831021d |
@@ -3,10 +3,7 @@ branch = True
|
||||
source = cloudkittyclient
|
||||
omit =
|
||||
cloudkittyclient/tests/*,
|
||||
cloudkittyclient/openstack/*,
|
||||
cloudkittyclient/i18n.py,
|
||||
cloudkittyclient/common/client.py,
|
||||
cloudkittyclient/common/exceptions.py
|
||||
cloudkittyclient/i18n.py
|
||||
|
||||
[report]
|
||||
ignore_errors = True
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -11,3 +11,6 @@ cover
|
||||
dist
|
||||
*.egg
|
||||
*.sw?
|
||||
.eggs
|
||||
AUTHORS
|
||||
ChangeLog
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[gerrit]
|
||||
host=review.openstack.org
|
||||
host=review.opendev.org
|
||||
port=29418
|
||||
project=openstack/python-cloudkittyclient.git
|
||||
defaultbranch=stable/ocata
|
||||
|
||||
19
.pylintrc
19
.pylintrc
@@ -1,19 +0,0 @@
|
||||
[MASTER]
|
||||
ignore=openstack,test
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
# C0111: Don't require docstrings on every method
|
||||
# W0511: TODOs in code comments are fine.
|
||||
# W0142: *args and **kwargs are fine.
|
||||
# W0622: Redefining id is fine.
|
||||
disable=C0111,W0511,W0142,W0622
|
||||
|
||||
[BASIC]
|
||||
# Don't require docstrings on tests.
|
||||
no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$
|
||||
|
||||
[Variables]
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid to define new builtins when possible.
|
||||
# _ is used by our localization
|
||||
additional-builtins=_
|
||||
8
.zuul.yaml
Normal file
8
.zuul.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
- project:
|
||||
templates:
|
||||
- openstack-python-jobs
|
||||
- openstack-python35-jobs
|
||||
- openstackclient-plugin-jobs
|
||||
post:
|
||||
jobs:
|
||||
- openstack-tox-cover
|
||||
@@ -1,3 +1,12 @@
|
||||
========================
|
||||
Team and repository tags
|
||||
========================
|
||||
|
||||
.. image:: http://governance.openstack.org/badges/python-cloudkittyclient.svg
|
||||
:target: http://governance.openstack.org/reference/tags/index.html
|
||||
|
||||
.. Change things from this point on
|
||||
|
||||
Python bindings to the CloudKitty API
|
||||
=====================================
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2015 Objectif Libre
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -37,7 +37,7 @@ import os
|
||||
import six
|
||||
from stevedore import extension
|
||||
|
||||
from cloudkittyclient.openstack.common.apiclient import exceptions
|
||||
from cloudkittyclient.apiclient import exceptions
|
||||
|
||||
|
||||
_discovered_plugins = {}
|
||||
@@ -54,7 +54,7 @@ def discover_auth_systems():
|
||||
def add_plugin(ext):
|
||||
_discovered_plugins[ext.name] = ext.plugin
|
||||
|
||||
ep_namespace = "cloudkittyclient.openstack.common.apiclient.auth"
|
||||
ep_namespace = "cloudkittyclient.apiclient.auth"
|
||||
mgr = extension.ExtensionManager(ep_namespace)
|
||||
mgr.map(add_plugin)
|
||||
|
||||
@@ -156,8 +156,7 @@ class BaseAuthPlugin(object):
|
||||
|
||||
@classmethod
|
||||
def add_opts(cls, parser):
|
||||
"""Populate the parser with the options for this plugin.
|
||||
"""
|
||||
"""Populate the parser with the options for this plugin."""
|
||||
for opt in cls.opt_names:
|
||||
# use `BaseAuthPlugin.common_opt_names` since it is never
|
||||
# changed in child classes
|
||||
@@ -166,8 +165,7 @@ class BaseAuthPlugin(object):
|
||||
|
||||
@classmethod
|
||||
def add_common_opts(cls, parser):
|
||||
"""Add options that are common for several plugins.
|
||||
"""
|
||||
"""Add options that are common for several plugins."""
|
||||
for opt in cls.common_opt_names:
|
||||
cls._parser_add_opt(parser, opt)
|
||||
|
||||
@@ -204,8 +202,7 @@ class BaseAuthPlugin(object):
|
||||
|
||||
@abc.abstractmethod
|
||||
def _do_authenticate(self, http_client):
|
||||
"""Protected method for authentication.
|
||||
"""
|
||||
"""Protected method for authentication."""
|
||||
|
||||
def sufficient_options(self):
|
||||
"""Check if all required options are present.
|
||||
@@ -44,8 +44,8 @@ from oslo_utils import strutils
|
||||
import six
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from cloudkittyclient.apiclient import exceptions
|
||||
from cloudkittyclient.i18n import _
|
||||
from cloudkittyclient.openstack.common.apiclient import exceptions
|
||||
|
||||
|
||||
def getid(obj):
|
||||
@@ -467,8 +467,7 @@ class Resource(object):
|
||||
|
||||
@property
|
||||
def human_id(self):
|
||||
"""Human-readable ID which can be used for bash completion.
|
||||
"""
|
||||
"""Human-readable ID which can be used for bash completion."""
|
||||
if self.HUMAN_ID:
|
||||
name = getattr(self, self.NAME_ATTR, None)
|
||||
if name is not None:
|
||||
@@ -523,6 +522,9 @@ class Resource(object):
|
||||
return self.id == other.id
|
||||
return self._info == other._info
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def is_loaded(self):
|
||||
return self._loaded
|
||||
|
||||
@@ -38,8 +38,9 @@ from oslo_utils import encodeutils
|
||||
from oslo_utils import importutils
|
||||
import requests
|
||||
|
||||
from cloudkittyclient.apiclient import exceptions
|
||||
from cloudkittyclient.i18n import _
|
||||
from cloudkittyclient.openstack.common.apiclient import exceptions
|
||||
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
SENSITIVE_HEADERS = ('X-Auth-Token', 'X-Subject-Token',)
|
||||
@@ -64,7 +65,7 @@ class HTTPClient(object):
|
||||
into terminal and send the same request with curl.
|
||||
"""
|
||||
|
||||
user_agent = "cloudkittyclient.openstack.common.apiclient"
|
||||
user_agent = "cloudkittyclient.apiclient"
|
||||
|
||||
def __init__(self,
|
||||
auth_plugin,
|
||||
@@ -42,8 +42,7 @@ from cloudkittyclient.i18n import _
|
||||
|
||||
|
||||
class ClientException(Exception):
|
||||
"""The base exception class for all exceptions this library raises.
|
||||
"""
|
||||
"""The base exception class for all exceptions this library raises."""
|
||||
pass
|
||||
|
||||
|
||||
@@ -118,8 +117,7 @@ class AmbiguousEndpoints(EndpointException):
|
||||
|
||||
|
||||
class HttpError(ClientException):
|
||||
"""The base exception class for all HTTP exceptions.
|
||||
"""
|
||||
"""The base exception class for all HTTP exceptions."""
|
||||
http_status = 0
|
||||
message = _("HTTP Error")
|
||||
|
||||
@@ -43,7 +43,7 @@ import requests
|
||||
import six
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from cloudkittyclient.openstack.common.apiclient import client
|
||||
from cloudkittyclient.apiclient import client
|
||||
|
||||
|
||||
def assert_has_keys(dct, required=None, optional=None):
|
||||
@@ -59,8 +59,7 @@ def assert_has_keys(dct, required=None, optional=None):
|
||||
|
||||
|
||||
class TestResponse(requests.Response):
|
||||
"""Wrap requests.Response and provide a convenient initialization.
|
||||
"""
|
||||
"""Wrap requests.Response and provide a convenient initialization."""
|
||||
|
||||
def __init__(self, data):
|
||||
super(TestResponse, self).__init__()
|
||||
@@ -88,6 +87,9 @@ class TestResponse(requests.Response):
|
||||
self.headers == other.headers and
|
||||
self._content == other._content)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
|
||||
class FakeHTTPClient(client.HTTPClient):
|
||||
|
||||
@@ -99,15 +101,14 @@ class FakeHTTPClient(client.HTTPClient):
|
||||
super(FakeHTTPClient, self).__init__(*args, **kwargs)
|
||||
|
||||
def assert_called(self, method, url, body=None, pos=-1):
|
||||
"""Assert than an API method was just called.
|
||||
"""
|
||||
"""Assert than an API method was just called."""
|
||||
expected = (method, url)
|
||||
called = self.callstack[pos][0:2]
|
||||
assert self.callstack, \
|
||||
"Expected %s %s but no calls were made." % expected
|
||||
msg = "Expected %s %s but no calls were made." % expected
|
||||
assert self.callstack, msg
|
||||
|
||||
assert expected == called, 'Expected %s %s; got %s %s' % \
|
||||
(expected + called)
|
||||
msg = 'Expected %s %s; got %s %s' % (expected + called)
|
||||
assert expected == called, msg
|
||||
|
||||
if body is not None:
|
||||
if self.callstack[pos][3] != body:
|
||||
@@ -115,12 +116,11 @@ class FakeHTTPClient(client.HTTPClient):
|
||||
(self.callstack[pos][3], body))
|
||||
|
||||
def assert_called_anytime(self, method, url, body=None):
|
||||
"""Assert than an API method was called anytime in the test.
|
||||
"""
|
||||
"""Assert than an API method was called anytime in the test."""
|
||||
expected = (method, url)
|
||||
|
||||
assert self.callstack, \
|
||||
"Expected %s %s but no calls were made." % expected
|
||||
msg = "Expected %s %s but no calls were made." % expected
|
||||
assert self.callstack, msg
|
||||
|
||||
found = False
|
||||
entry = None
|
||||
@@ -129,8 +129,8 @@ class FakeHTTPClient(client.HTTPClient):
|
||||
found = True
|
||||
break
|
||||
|
||||
assert found, 'Expected %s %s; got %s' % \
|
||||
(method, url, self.callstack)
|
||||
msg = 'Expected %s %s; got %s' % (method, url, self.callstack)
|
||||
assert found, msg
|
||||
if body is not None:
|
||||
assert entry[3] == body, "%s != %s" % (entry[3], body)
|
||||
|
||||
@@ -28,8 +28,8 @@ from oslo_utils import encodeutils
|
||||
from oslo_utils import uuidutils
|
||||
import six
|
||||
|
||||
from cloudkittyclient.apiclient import exceptions
|
||||
from cloudkittyclient.i18n import _
|
||||
from cloudkittyclient.openstack.common.apiclient import exceptions
|
||||
|
||||
|
||||
def find_resource(manager, name_or_id, **find_args):
|
||||
@@ -84,17 +84,13 @@ def find_resource(manager, name_or_id, **find_args):
|
||||
return manager.find(**kwargs)
|
||||
except exceptions.NotFound:
|
||||
msg = _("No %(name)s with a name or "
|
||||
"ID of '%(name_or_id)s' exists.") % \
|
||||
{
|
||||
"name": manager.resource_class.__name__.lower(),
|
||||
"name_or_id": name_or_id
|
||||
}
|
||||
"ID of '%(name_or_id)s' exists.") % {
|
||||
"name": manager.resource_class.__name__.lower(),
|
||||
"name_or_id": name_or_id}
|
||||
raise exceptions.CommandError(msg)
|
||||
except exceptions.NoUniqueMatch:
|
||||
msg = _("Multiple %(name)s matches found for "
|
||||
"'%(name_or_id)s', use an ID to be more specific.") % \
|
||||
{
|
||||
"name": manager.resource_class.__name__.lower(),
|
||||
"name_or_id": name_or_id
|
||||
}
|
||||
"'%(name_or_id)s', use an ID to be more specific.") % {
|
||||
"name": manager.resource_class.__name__.lower(),
|
||||
"name_or_id": name_or_id}
|
||||
raise exceptions.CommandError(msg)
|
||||
@@ -22,11 +22,11 @@ from keystoneclient import session
|
||||
from oslo_utils import strutils
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
from cloudkittyclient.apiclient import auth
|
||||
from cloudkittyclient.apiclient import client
|
||||
from cloudkittyclient.apiclient import exceptions
|
||||
from cloudkittyclient.common import utils
|
||||
from cloudkittyclient import exc
|
||||
from cloudkittyclient.openstack.common.apiclient import auth
|
||||
from cloudkittyclient.openstack.common.apiclient import client
|
||||
from cloudkittyclient.openstack.common.apiclient import exceptions
|
||||
|
||||
|
||||
def _discover_auth_versions(session, auth_url):
|
||||
@@ -306,8 +306,10 @@ def get_client(version, **kwargs):
|
||||
cli_kwargs = {
|
||||
'username': kwargs.get('os_username'),
|
||||
'password': kwargs.get('os_password'),
|
||||
'tenant_id': kwargs.get('os_tenant_id'),
|
||||
'tenant_name': kwargs.get('os_tenant_name'),
|
||||
'tenant_id': (kwargs.get('os_tenant_id')
|
||||
or kwargs.get('os_project_id')),
|
||||
'tenant_name': (kwargs.get('os_tenant_name')
|
||||
or kwargs.get('os_project_name')),
|
||||
'auth_url': kwargs.get('os_auth_url'),
|
||||
'region_name': kwargs.get('os_region_name'),
|
||||
'service_type': kwargs.get('os_service_type'),
|
||||
@@ -339,7 +341,7 @@ def get_auth_plugin(endpoint, **kwargs):
|
||||
endpoint=endpoint,
|
||||
username=kwargs.get('username'),
|
||||
password=kwargs.get('password'),
|
||||
tenant_name=kwargs.get('tenant_name'),
|
||||
tenant_name=kwargs.get('tenant_name') or kwargs.get('project_name'),
|
||||
user_domain_name=kwargs.get('user_domain_name'),
|
||||
user_domain_id=kwargs.get('user_domain_id'),
|
||||
project_domain_name=kwargs.get('project_domain_name'),
|
||||
|
||||
@@ -22,9 +22,9 @@ import copy
|
||||
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from cloudkittyclient.apiclient import base
|
||||
from cloudkittyclient import exc
|
||||
from cloudkittyclient.i18n import _
|
||||
from cloudkittyclient.openstack.common.apiclient import base
|
||||
|
||||
|
||||
def getid(obj):
|
||||
|
||||
@@ -267,5 +267,5 @@ def pretty_choice_list(l):
|
||||
|
||||
def exit(msg=''):
|
||||
if msg:
|
||||
print (msg, file=sys.stderr)
|
||||
print(msg, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
@@ -23,12 +23,20 @@ import uuid
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import encodeutils
|
||||
from oslo_utils import importutils
|
||||
from oslo_utils import timeutils
|
||||
import prettytable
|
||||
import six
|
||||
|
||||
from cloudkittyclient.common import cliutils
|
||||
from cloudkittyclient import exc
|
||||
from cloudkittyclient.i18n import _
|
||||
from cloudkittyclient.openstack.common import cliutils
|
||||
|
||||
|
||||
def iso2dt(iso_date):
|
||||
"""iso8601 format to datetime."""
|
||||
iso_dt = timeutils.parse_isotime(iso_date)
|
||||
trans_dt = timeutils.normalize_time(iso_dt)
|
||||
return trans_dt
|
||||
|
||||
|
||||
def import_versioned_module(version, submodule=None):
|
||||
|
||||
35
cloudkittyclient/osc.py
Normal file
35
cloudkittyclient/osc.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# Copyright 2014 OpenStack Foundation
|
||||
#
|
||||
# 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 cloudkittyclient import client as ckclient
|
||||
|
||||
DEFAULT_API_VERSION = '1'
|
||||
API_VERSION_OPTION = 'os_rating_api_version'
|
||||
API_NAME = "rating"
|
||||
API_VERSIONS = {
|
||||
"1": "cloudkittyclient.v1.client.Client",
|
||||
}
|
||||
|
||||
|
||||
def make_client(instance):
|
||||
"""Returns a rating service client."""
|
||||
version = instance._api_version[API_NAME]
|
||||
version = int(version)
|
||||
auth_config = instance.get_configuration()['auth']
|
||||
return ckclient.get_client(version, **auth_config)
|
||||
|
||||
|
||||
def build_option_parser(parser):
|
||||
"""Hook to add global options."""
|
||||
return parser
|
||||
@@ -28,9 +28,9 @@ from stevedore import extension
|
||||
|
||||
import cloudkittyclient
|
||||
from cloudkittyclient import client as ckclient
|
||||
from cloudkittyclient.common import cliutils
|
||||
from cloudkittyclient.common import utils
|
||||
from cloudkittyclient import exc
|
||||
from cloudkittyclient.openstack.common import cliutils
|
||||
from cloudkittyclient.v1.collector import shell as collector_shell
|
||||
from cloudkittyclient.v1.report import shell as report_shell
|
||||
from cloudkittyclient.v1.storage import shell as storage_shell
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2010-2011 OpenStack Foundation
|
||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
|
||||
@@ -132,7 +132,7 @@ class ClientTest(utils.BaseTestCase):
|
||||
'user_agent': None,
|
||||
'debug': None,
|
||||
}
|
||||
cls = 'cloudkittyclient.openstack.common.apiclient.client.HTTPClient'
|
||||
cls = 'cloudkittyclient.apiclient.client.HTTPClient'
|
||||
with mock.patch(cls) as mocked:
|
||||
self.create_client(env)
|
||||
mocked.assert_called_with(**expected)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
# 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 cloudkittyclient.openstack.common.apiclient import client
|
||||
from cloudkittyclient.openstack.common.apiclient import fake_client
|
||||
from cloudkittyclient.apiclient import client
|
||||
from cloudkittyclient.apiclient import fake_client
|
||||
from cloudkittyclient.tests import utils
|
||||
import cloudkittyclient.v1.core
|
||||
|
||||
@@ -26,10 +26,12 @@ fixtures = {
|
||||
{
|
||||
'module_id': 'hashmap',
|
||||
'enabled': True,
|
||||
'priority': 1,
|
||||
},
|
||||
{
|
||||
'module_id': 'noop',
|
||||
'enabled': False,
|
||||
'priority': 1,
|
||||
},
|
||||
]},
|
||||
),
|
||||
@@ -40,6 +42,7 @@ fixtures = {
|
||||
{
|
||||
'module_id': 'hashmap',
|
||||
'enabled': True,
|
||||
'priority': 1,
|
||||
}
|
||||
),
|
||||
'PUT': (
|
||||
@@ -47,6 +50,7 @@ fixtures = {
|
||||
{
|
||||
'module_id': 'hashmap',
|
||||
'enabled': False,
|
||||
'priority': 1,
|
||||
}
|
||||
),
|
||||
},
|
||||
@@ -56,6 +60,7 @@ fixtures = {
|
||||
{
|
||||
'module_id': 'noop',
|
||||
'enabled': False,
|
||||
'priority': 1,
|
||||
}
|
||||
),
|
||||
'PUT': (
|
||||
@@ -63,6 +68,7 @@ fixtures = {
|
||||
{
|
||||
'module_id': 'noop',
|
||||
'enabled': True,
|
||||
'priority': 1,
|
||||
}
|
||||
),
|
||||
},
|
||||
@@ -123,7 +129,8 @@ class CloudkittyModuleTest(utils.BaseTestCase):
|
||||
# body : {'enabled': True}
|
||||
expect = [
|
||||
'PUT', '/v1/rating/modules/noop', {'module_id': 'noop',
|
||||
'enabled': True},
|
||||
'enabled': True,
|
||||
'priority': 1},
|
||||
]
|
||||
self.http_client.assert_called(*expect)
|
||||
|
||||
@@ -134,6 +141,19 @@ class CloudkittyModuleTest(utils.BaseTestCase):
|
||||
# body : {'enabled': False}
|
||||
expect = [
|
||||
'PUT', '/v1/rating/modules/hashmap', {'module_id': 'hashmap',
|
||||
'enabled': False},
|
||||
'enabled': False,
|
||||
'priority': 1},
|
||||
]
|
||||
self.http_client.assert_called(*expect)
|
||||
|
||||
def test_set_priority(self):
|
||||
self.ck_module = self.mgr.get(module_id='hashmap')
|
||||
self.ck_module.set_priority(100)
|
||||
# PUT /v1/rating/modules/hashmap
|
||||
# body : {'priority': 100}
|
||||
expect = [
|
||||
'PUT', '/v1/rating/modules/hashmap', {'module_id': 'hashmap',
|
||||
'enabled': True,
|
||||
'priority': 100},
|
||||
]
|
||||
self.http_client.assert_called(*expect)
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
# 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 cloudkittyclient.openstack.common.apiclient import client
|
||||
from cloudkittyclient.openstack.common.apiclient import fake_client
|
||||
from cloudkittyclient.apiclient import client
|
||||
from cloudkittyclient.apiclient import fake_client
|
||||
from cloudkittyclient.tests import utils
|
||||
from cloudkittyclient.v1.rating import hashmap
|
||||
|
||||
|
||||
139
cloudkittyclient/tests/v1/test_report.py
Normal file
139
cloudkittyclient/tests/v1/test_report.py
Normal file
@@ -0,0 +1,139 @@
|
||||
# Copyright 2015 Objectif Libre
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 cloudkittyclient.apiclient import client
|
||||
from cloudkittyclient.apiclient import fake_client
|
||||
from cloudkittyclient.tests import utils
|
||||
import cloudkittyclient.v1.report
|
||||
|
||||
|
||||
fixtures = {
|
||||
'/v1/report/summary': {
|
||||
'GET': (
|
||||
{},
|
||||
{'summary': [
|
||||
{
|
||||
'tenant_id': 'ALL',
|
||||
'res_type': 'ALL',
|
||||
'begin': '2017-01-01T00:00:00',
|
||||
'end': '2017-02-01T00:00:00',
|
||||
'rate': '2325.29992'
|
||||
},
|
||||
]},
|
||||
),
|
||||
},
|
||||
'/v1/report/summary?tenant_id=649de47ad78a44bd8562b0aa84389b2b': {
|
||||
'GET': (
|
||||
{},
|
||||
{'summary': [
|
||||
{
|
||||
'tenant_id': '649de47ad78a44bd8562b0aa84389b2b',
|
||||
'res_type': 'ALL',
|
||||
'begin': '2017-01-01T00:00:00',
|
||||
'end': '2017-02-01T00:00:00',
|
||||
'rate': '990.14996'
|
||||
},
|
||||
]},
|
||||
),
|
||||
},
|
||||
'/v1/report/summary?service=compute': {
|
||||
'GET': (
|
||||
{},
|
||||
{'summary': [
|
||||
{
|
||||
'tenant_id': 'ALL',
|
||||
'res_type': 'compute',
|
||||
'begin': '2017-01-01T00:00:00',
|
||||
'end': '2017-02-01T00:00:00',
|
||||
'rate': '690.0'
|
||||
},
|
||||
]},
|
||||
),
|
||||
},
|
||||
'/v1/report/summary?groupby=res_type%2Ctenant_id': {
|
||||
'GET': (
|
||||
{},
|
||||
{'summary': [
|
||||
{
|
||||
'tenant_id': '3747afc360b64702a53bdd64dc1b8976',
|
||||
'res_type': 'compute',
|
||||
'begin': '2017-01-01T00:00:00',
|
||||
'end': '2017-02-01T00:00:00',
|
||||
'rate': '517.5'
|
||||
},
|
||||
{
|
||||
'tenant_id': '3747afc360b64702a53bdd64dc1b8976',
|
||||
'res_type': 'volume',
|
||||
'begin': '2017-01-01T00:00:00',
|
||||
'end': '2017-02-01T00:00:00',
|
||||
'rate': '817.64996'
|
||||
},
|
||||
{
|
||||
'tenant_id': '649de47ad78a44bd8562b0aa84389b2b',
|
||||
'res_type': 'compute',
|
||||
'begin': '2017-01-01T00:00:00',
|
||||
'end': '2017-02-01T00:00:00',
|
||||
'rate': '172.5'
|
||||
},
|
||||
{
|
||||
'tenant_id': '649de47ad78a44bd8562b0aa84389b2b',
|
||||
'res_type': 'volume',
|
||||
'begin': '2017-01-01T00:00:00',
|
||||
'end': '2017-02-01T00:00:00',
|
||||
'rate': '817.64996'
|
||||
},
|
||||
]},
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class ReportSummaryManagerTest(utils.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ReportSummaryManagerTest, self).setUp()
|
||||
self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures)
|
||||
self.api = client.BaseClient(self.http_client)
|
||||
self.mgr = cloudkittyclient.v1.report.ReportSummaryManager(self.api)
|
||||
|
||||
def test_get_summary(self):
|
||||
self.mgr.get_summary()
|
||||
expect = [
|
||||
'GET', '/v1/report/summary'
|
||||
]
|
||||
self.http_client.assert_called(*expect)
|
||||
|
||||
def test_get_summary_with_tenant(self):
|
||||
self.mgr.get_summary(tenant_id='649de47ad78a44bd8562b0aa84389b2b')
|
||||
expect = [
|
||||
'GET',
|
||||
'/v1/report/summary?tenant_id=649de47ad78a44bd8562b0aa84389b2b'
|
||||
]
|
||||
self.http_client.assert_called(*expect)
|
||||
|
||||
def test_get_summary_with_service(self):
|
||||
self.mgr.get_summary(service='compute')
|
||||
expect = [
|
||||
'GET',
|
||||
'/v1/report/summary?service=compute'
|
||||
]
|
||||
self.http_client.assert_called(*expect)
|
||||
|
||||
def test_get_summary_with_groupby(self):
|
||||
self.mgr.get_summary(groupby='res_type,tenant_id')
|
||||
expect = [
|
||||
'GET',
|
||||
'/v1/report/summary?groupby=res_type%2Ctenant_id'
|
||||
]
|
||||
self.http_client.assert_called(*expect)
|
||||
@@ -57,8 +57,11 @@ class Client(object):
|
||||
self.modules = core.CloudkittyModuleManager(self.http_client)
|
||||
self.collector = collector.CollectorManager(self.http_client)
|
||||
self.reports = report.ReportManager(self.http_client)
|
||||
self.reportsummary = report.ReportSummaryManager(self.http_client)
|
||||
self.quotations = core.QuotationManager(self.http_client)
|
||||
self.storage = storage.StorageManager(self.http_client)
|
||||
self.config = core.ConfigInfoManager(self.http_client)
|
||||
self.service_info = core.ServiceInfoManager(self.http_client)
|
||||
self._expose_submodules()
|
||||
|
||||
def _expose_submodules(self):
|
||||
|
||||
109
cloudkittyclient/v1/collector/shell_cli.py
Normal file
109
cloudkittyclient/v1/collector/shell_cli.py
Normal file
@@ -0,0 +1,109 @@
|
||||
# Copyright 2016 Objectif Libre
|
||||
#
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.command import command
|
||||
|
||||
from cloudkittyclient.v1.collector import shell
|
||||
|
||||
|
||||
class CliCollectorMappingList(command.Command):
|
||||
"""List collector mappings."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliCollectorMappingList, self).get_parser(prog_name)
|
||||
parser.add_argument('-c', '--collector',
|
||||
help='Collector name to filter on.',
|
||||
required=False,
|
||||
default=None)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_collector_mapping_list(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliCollectorMappingGet(command.Command):
|
||||
"""Show collector mapping detail."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliCollectorMappingGet, self).get_parser(prog_name)
|
||||
parser.add_argument('-s', '--service',
|
||||
help='Which service to get the mapping for.',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_collector_mapping_get(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliCollectorMappingCreate(command.Command):
|
||||
"""Create collector mappings."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliCollectorMappingCreate, self).get_parser(prog_name)
|
||||
parser.add_argument('-c', '--collector',
|
||||
help='Map a service to this collector.',
|
||||
required=True)
|
||||
parser.add_argument('-s', '--service',
|
||||
help='Map a collector to this service.',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_collector_mapping_create(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliCollectorMappingDelete(command.Command):
|
||||
"""Delete collector mappings."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliCollectorMappingDelete, self).get_parser(prog_name)
|
||||
parser.add_argument('-s', '--service',
|
||||
help='Filter on this service',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_collector_mapping_delete(ckclient, parsed_args)
|
||||
|
||||
|
||||
class BaseCliCollectorState(command.Command):
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(BaseCliCollectorState, self).get_parser(prog_name)
|
||||
parser.add_argument('-n', '--name',
|
||||
help='Name of the collector',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
|
||||
class CliCollectorStateGet(BaseCliCollectorState):
|
||||
"""Show collector state."""
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_collector_state_get(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliCollectorStateEnable(BaseCliCollectorState):
|
||||
"""Enable collector state."""
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_collector_state_enable(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliCollectorStateDisable(BaseCliCollectorState):
|
||||
"""Disable collector state."""
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_collector_state_disable(ckclient, parsed_args)
|
||||
@@ -30,6 +30,10 @@ class CloudkittyModule(base.Resource):
|
||||
self.enabled = False
|
||||
self.update()
|
||||
|
||||
def set_priority(self, value):
|
||||
self.priority = value
|
||||
self.update()
|
||||
|
||||
|
||||
class CloudkittyModuleManager(base.CrudManager):
|
||||
resource_class = CloudkittyModule
|
||||
@@ -60,3 +64,26 @@ class QuotationManager(base.Manager):
|
||||
out = self.api.post(self.base_url,
|
||||
json={'resources': resources}).json()
|
||||
return out
|
||||
|
||||
|
||||
class ServiceInfo(base.Resource):
|
||||
|
||||
key = "service"
|
||||
|
||||
def __repr__(self):
|
||||
return "<Service %s>" % self._info
|
||||
|
||||
|
||||
class ServiceInfoManager(base.CrudManager):
|
||||
resource_class = ServiceInfo
|
||||
base_url = "/v1/info"
|
||||
key = "service"
|
||||
collection_key = "services"
|
||||
|
||||
|
||||
class ConfigInfoManager(base.Manager):
|
||||
base_url = "/v1/info/config"
|
||||
|
||||
def get_config(self):
|
||||
out = self.api.get(self.base_url).json()
|
||||
return out
|
||||
|
||||
@@ -17,6 +17,7 @@ import functools
|
||||
|
||||
from oslo_utils import strutils
|
||||
|
||||
from cloudkittyclient.apiclient import exceptions
|
||||
from cloudkittyclient.common import utils
|
||||
from cloudkittyclient import exc
|
||||
|
||||
@@ -44,8 +45,8 @@ def do_hashmap_service_list(cc, args={}):
|
||||
"""List services."""
|
||||
try:
|
||||
services = cc.hashmap.services.list()
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Services not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Services not found.')
|
||||
else:
|
||||
field_labels = ['Name', 'Service id']
|
||||
fields = ['name', 'service_id']
|
||||
@@ -60,8 +61,8 @@ def do_hashmap_service_delete(cc, args={}):
|
||||
"""Delete a service."""
|
||||
try:
|
||||
cc.hashmap.services.delete(service_id=args.service_id)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Service not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Service not found: %s' % args.service_id)
|
||||
|
||||
|
||||
@utils.arg('-n', '--name',
|
||||
@@ -92,8 +93,9 @@ def do_hashmap_field_list(cc, args={}):
|
||||
"""List fields."""
|
||||
try:
|
||||
created_field = cc.hashmap.fields.list(service_id=args.service_id)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Fields not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Fields not found in service: %s'
|
||||
% args.service_id)
|
||||
else:
|
||||
field_labels = ['Name', 'Field id']
|
||||
fields = ['name', 'field_id']
|
||||
@@ -108,8 +110,8 @@ def do_hashmap_field_delete(cc, args={}):
|
||||
"""Delete a field."""
|
||||
try:
|
||||
cc.hashmap.fields.delete(field_id=args.field_id)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Field not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Field not found: %s' % args.field_id)
|
||||
|
||||
|
||||
def common_hashmap_mapping_arguments(create=False):
|
||||
@@ -179,8 +181,8 @@ def do_hashmap_mapping_update(cc, args={}):
|
||||
}
|
||||
try:
|
||||
mapping = cc.hashmap.mappings.get(mapping_id=args.mapping_id)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Modules not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Mapping not found: %s' % args.mapping_id)
|
||||
for k, v in vars(args).items():
|
||||
if k in arg_to_field_mapping:
|
||||
if v is not None:
|
||||
@@ -210,8 +212,9 @@ def do_hashmap_mapping_list(cc, args={}):
|
||||
mappings = cc.hashmap.mappings.list(service_id=args.service_id,
|
||||
field_id=args.field_id,
|
||||
group_id=args.group_id)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Mapping not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Mappings not found for field: %s'
|
||||
% args.field_id)
|
||||
else:
|
||||
field_labels = ['Mapping id', 'Value', 'Cost',
|
||||
'Type', 'Field id',
|
||||
@@ -230,7 +233,7 @@ def do_hashmap_mapping_delete(cc, args={}):
|
||||
"""Delete a mapping."""
|
||||
try:
|
||||
cc.hashmap.mappings.delete(mapping_id=args.mapping_id)
|
||||
except exc.HTTPNotFound:
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Mapping not found: %s' % args.mapping_id)
|
||||
|
||||
|
||||
@@ -255,8 +258,8 @@ def do_hashmap_group_list(cc, args={}):
|
||||
"""List groups."""
|
||||
try:
|
||||
groups = cc.hashmap.groups.list()
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Mapping not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Groups not found.')
|
||||
else:
|
||||
field_labels = ['Name',
|
||||
'Group id']
|
||||
@@ -277,7 +280,7 @@ def do_hashmap_group_delete(cc, args={}):
|
||||
try:
|
||||
cc.hashmap.groups.delete(group_id=args.group_id,
|
||||
recursive=args.recursive)
|
||||
except exc.HTTPNotFound:
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Group not found: %s' % args.group_id)
|
||||
|
||||
|
||||
@@ -348,8 +351,8 @@ def do_hashmap_threshold_update(cc, args={}):
|
||||
}
|
||||
try:
|
||||
threshold = cc.hashmap.thresholds.get(threshold_id=args.threshold_id)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Modules not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Threshold not found: %s' % args.threshold_id)
|
||||
for k, v in vars(args).items():
|
||||
if k in arg_to_field_mapping:
|
||||
if v is not None:
|
||||
@@ -384,8 +387,8 @@ def do_hashmap_threshold_list(cc, args={}):
|
||||
field_id=args.field_id,
|
||||
group_id=args.group_id,
|
||||
no_group=args.no_group)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Threshold not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Thresholds not found')
|
||||
else:
|
||||
field_labels = ['Threshold id', 'Level', 'Cost',
|
||||
'Type', 'Field id',
|
||||
@@ -403,7 +406,7 @@ def do_hashmap_threshold_delete(cc, args={}):
|
||||
"""Delete a threshold."""
|
||||
try:
|
||||
cc.hashmap.thresholds.delete(threshold_id=args.threshold_id)
|
||||
except exc.HTTPNotFound:
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Threshold not found: %s' % args.threshold_id)
|
||||
|
||||
|
||||
@@ -414,7 +417,7 @@ def do_hashmap_threshold_get(cc, args={}):
|
||||
"""Get a threshold."""
|
||||
try:
|
||||
threshold = cc.hashmap.thresholds.get(threshold_id=args.threshold_id)
|
||||
except exc.HTTPNotFound:
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Threshold not found: %s' % args.threshold_id)
|
||||
utils.print_dict(threshold.to_dict())
|
||||
|
||||
@@ -426,6 +429,6 @@ def do_hashmap_threshold_group(cc, args={}):
|
||||
"""Get a threshold group."""
|
||||
try:
|
||||
threshold = cc.hashmap.thresholds.group(threshold_id=args.threshold_id)
|
||||
except exc.HTTPNotFound:
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Threshold not found: %s' % args.threshold_id)
|
||||
utils.print_dict(threshold.to_dict())
|
||||
|
||||
355
cloudkittyclient/v1/rating/hashmap/shell_cli.py
Normal file
355
cloudkittyclient/v1/rating/hashmap/shell_cli.py
Normal file
@@ -0,0 +1,355 @@
|
||||
# Copyright 2016 Objectif Libre
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 functools
|
||||
|
||||
from osc_lib.command import command
|
||||
from oslo_utils import strutils
|
||||
|
||||
from cloudkittyclient.v1.rating.hashmap import shell
|
||||
|
||||
|
||||
_bool_strict = functools.partial(strutils.bool_from_string, strict=True)
|
||||
|
||||
|
||||
class CliHashmapServiceCreate(command.Command):
|
||||
"""Create a service."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapServiceCreate, self).get_parser(prog_name)
|
||||
parser.add_argument('-n', '--name',
|
||||
help='Service name',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_service_create(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapServiceList(command.Command):
|
||||
"""List services."""
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_service_list(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapServiceDelete(command.Command):
|
||||
"""Delete a service."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapServiceDelete, self).get_parser(prog_name)
|
||||
parser.add_argument('-s', '--service-id',
|
||||
help='Service id',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_service_delete(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapFieldCreate(command.Command):
|
||||
"""Create a field."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapFieldCreate, self).get_parser(prog_name)
|
||||
parser.add_argument('-s', '--service-id',
|
||||
help='Service id',
|
||||
required=True)
|
||||
parser.add_argument('-n', '--name',
|
||||
help='Field name',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_field_create(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapFieldList(command.Command):
|
||||
"""List fields."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapFieldList, self).get_parser(prog_name)
|
||||
parser.add_argument('-s', '--service-id',
|
||||
help='Service id',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_field_list(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapFieldDelete(command.Command):
|
||||
"""Delete a field."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapFieldDelete, self).get_parser(prog_name)
|
||||
parser.add_argument('-f', '--field-id',
|
||||
help='Field id',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_field_delete(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapMappingCommon(command.Command):
|
||||
def get_parser(self, prog_name, cost=False):
|
||||
parser = super(CliHashmapMappingCommon, self).get_parser(prog_name)
|
||||
parser.add_argument('-c', '--cost',
|
||||
help='Mapping Cost',
|
||||
required=cost)
|
||||
parser.add_argument('-v', '--value',
|
||||
help='Mapping Value',
|
||||
required=False)
|
||||
parser.add_argument('-t', '--type',
|
||||
help='Mapping type (flat, rate)',
|
||||
required=False)
|
||||
parser.add_argument('-g', '--group-id',
|
||||
help='Group id',
|
||||
required=False)
|
||||
parser.add_argument('-p', '--project-id',
|
||||
help='Project/Tenant id',
|
||||
required=False)
|
||||
return parser
|
||||
|
||||
|
||||
class CliHashmapMappingCreate(CliHashmapMappingCommon):
|
||||
"""Create a mapping."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapMappingCreate, self).get_parser(prog_name,
|
||||
cost=True)
|
||||
parser.add_argument('-s', '--service-id',
|
||||
help='Service id',
|
||||
required=False)
|
||||
parser.add_argument('-f', '--field-id',
|
||||
help='Service id',
|
||||
required=False)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_mapping_create(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapMappingUpdate(CliHashmapMappingCommon):
|
||||
"""Update a mapping."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapMappingUpdate, self).get_parser(prog_name)
|
||||
parser.add_argument('-m', '--mapping-id',
|
||||
help='Mapping id',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_mapping_update(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapMappingList(command.Command):
|
||||
"""List mappings."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapMappingList, self).get_parser(prog_name)
|
||||
parser.add_argument('-s', '--service-id',
|
||||
help='Service id',
|
||||
required=False)
|
||||
parser.add_argument('-f', '--field-id',
|
||||
help='Field id',
|
||||
required=False)
|
||||
parser.add_argument('-g', '--group-id',
|
||||
help='Group id',
|
||||
required=False)
|
||||
parser.add_argument('-p', '--project-id',
|
||||
help='Project id',
|
||||
required=False)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_mapping_list(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapMappingDelete(command.Command):
|
||||
"""Delete a mapping."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapMappingDelete, self).get_parser(prog_name)
|
||||
parser.add_argument('-m', '--mapping-id',
|
||||
help='Mapping id',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_mapping_delete(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapGroupCreate(command.Command):
|
||||
"""Create a group."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapGroupCreate, self).get_parser(prog_name)
|
||||
parser.add_argument('-n', '--name',
|
||||
help='Group name.',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_group_create(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapGroupList(command.Command):
|
||||
"""List groups."""
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_group_list(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapGroupDelete(command.Command):
|
||||
"""Delete a group."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapGroupDelete, self).get_parser(prog_name)
|
||||
parser.add_argument('-g', '--group-id',
|
||||
help='Group uuid',
|
||||
required=True)
|
||||
parser.add_argument('-r', '--recursive',
|
||||
help="""Delete the group's mappings.""",
|
||||
required=False,
|
||||
default=False)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_group_delete(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapThresholdCommon(command.Command):
|
||||
def get_parser(self, prog_name, create=False):
|
||||
parser = super(CliHashmapThresholdCommon, self).get_parser(prog_name)
|
||||
parser.add_argument('-l', '--level',
|
||||
help='Threshold level',
|
||||
required=create)
|
||||
parser.add_argument('-c', '--cost',
|
||||
help='Threshold cost',
|
||||
required=create)
|
||||
parser.add_argument('-t', '--type',
|
||||
help='Threshold type',
|
||||
required=False)
|
||||
parser.add_argument('-g', '--group-id',
|
||||
help='Group id',
|
||||
required=False)
|
||||
parser.add_argument('-p', '--project-id',
|
||||
help='Project/tenant id',
|
||||
required=False)
|
||||
return parser
|
||||
|
||||
|
||||
class CliHashmapThresholdCreate(CliHashmapThresholdCommon):
|
||||
"""Create a threshold."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapThresholdCreate, self).get_parser(prog_name,
|
||||
create=True)
|
||||
parser.add_argument('-s', '--service-id',
|
||||
help='Service id',
|
||||
required=False)
|
||||
parser.add_argument('-f', '--field-id',
|
||||
help='Field id',
|
||||
required=False)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_threshold_create(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapThresholdUpdate(CliHashmapThresholdCommon):
|
||||
"""Update a threshold."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapThresholdUpdate, self).get_parser(prog_name)
|
||||
parser.add_argument('-i', '--threshold-id',
|
||||
help='Threshold id',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_threshold_update(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapThresholdList(command.Command):
|
||||
"""List thresholds."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapThresholdList, self).get_parser(prog_name)
|
||||
parser.add_argument('-s', '--service-id',
|
||||
help='Service id',
|
||||
required=False)
|
||||
parser.add_argument('-f', '--field-id',
|
||||
help='Field id',
|
||||
required=False)
|
||||
parser.add_argument('-g', '--group-id',
|
||||
help='Group id',
|
||||
required=False)
|
||||
parser.add_argument('--no-group',
|
||||
type=_bool_strict, metavar='{True,False}',
|
||||
help='If True, list only orphaned thresholds',
|
||||
required=False)
|
||||
parser.add_argument('-p', '--project-id',
|
||||
help='Project/tenant id',
|
||||
required=False)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_threshold_list(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapThresholdDelete(command.Command):
|
||||
"""Delete a threshold."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapThresholdDelete, self).get_parser(prog_name)
|
||||
parser.add_argument('-i', '--threshold-id',
|
||||
help='Threshold uuid',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_threshold_delete(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapThresholdGet(command.Command):
|
||||
"""Get a threshold."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapThresholdGet, self).get_parser(prog_name)
|
||||
parser.add_argument('-i', '--threshold-id',
|
||||
help='Threshold uuid',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_threshold_get(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliHashmapThresholdGroup(command.Command):
|
||||
"""Get a threshold group."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliHashmapThresholdGroup, self).get_parser(prog_name)
|
||||
parser.add_argument('-i', '--threshold-id',
|
||||
help='Threshold uuid',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_hashmap_threshold_group(ckclient, parsed_args)
|
||||
@@ -17,6 +17,7 @@ import functools
|
||||
from oslo_utils import strutils
|
||||
import six
|
||||
|
||||
from cloudkittyclient.apiclient import exceptions
|
||||
from cloudkittyclient.common import utils
|
||||
from cloudkittyclient import exc
|
||||
|
||||
@@ -64,7 +65,7 @@ def do_pyscripts_script_get(cc, args={}):
|
||||
"""Get script."""
|
||||
try:
|
||||
script = cc.pyscripts.scripts.get(script_id=args.script_id)
|
||||
except exc.HTTPNotFound:
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Script not found: %s' % args.script_id)
|
||||
utils.print_dict(script.to_dict())
|
||||
|
||||
@@ -76,7 +77,7 @@ def do_pyscripts_script_get_data(cc, args={}):
|
||||
"""Get script data."""
|
||||
try:
|
||||
script = cc.pyscripts.scripts.get(script_id=args.script_id)
|
||||
except exc.HTTPNotFound:
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Script not found: %s' % args.script_id)
|
||||
six.print_(script.data)
|
||||
|
||||
@@ -88,8 +89,8 @@ def do_pyscripts_script_delete(cc, args={}):
|
||||
"""Delete a script."""
|
||||
try:
|
||||
cc.pyscripts.scripts.delete(script_id=args.script_id)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Script not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Script not found: %s' % args.script_id)
|
||||
|
||||
|
||||
@utils.arg('-s', '--script-id',
|
||||
@@ -107,7 +108,7 @@ def do_pyscripts_script_update(cc, args={}):
|
||||
content = fp.read()
|
||||
try:
|
||||
script = cc.pyscripts.scripts.get(script_id=args.script_id)
|
||||
except exc.HTTPNotFound:
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Script not found: %s' % args.script_id)
|
||||
script_dict = script.to_dict()
|
||||
for field in excluded_fields:
|
||||
|
||||
115
cloudkittyclient/v1/rating/pyscripts/shell_cli.py
Normal file
115
cloudkittyclient/v1/rating/pyscripts/shell_cli.py
Normal file
@@ -0,0 +1,115 @@
|
||||
# Copyright 2016 Objectif Libre
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 functools
|
||||
|
||||
from osc_lib.command import command
|
||||
from oslo_utils import strutils
|
||||
|
||||
from cloudkittyclient.v1.rating.pyscripts import shell
|
||||
|
||||
|
||||
_bool_strict = functools.partial(strutils.bool_from_string, strict=True)
|
||||
|
||||
|
||||
class CliPyScriptCreate(command.Command):
|
||||
"""Create a script."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliPyScriptCreate, self).get_parser(prog_name)
|
||||
parser.add_argument('-n', '--name',
|
||||
help='Script name',
|
||||
required=True)
|
||||
parser.add_argument('-f', '--file',
|
||||
help='Script file',
|
||||
required=False)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_pyscripts_script_create(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliPyScriptList(command.Command):
|
||||
"""List scripts."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliPyScriptList, self).get_parser(prog_name)
|
||||
parser.add_argument('-d', '--show-data',
|
||||
help='Show data in the listing',
|
||||
required=False,
|
||||
default=False)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_pyscripts_script_list(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliPyScriptGet(command.Command):
|
||||
"""Get script."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliPyScriptGet, self).get_parser(prog_name)
|
||||
parser.add_argument('-s', '--script-id',
|
||||
help='Script uuid',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_pyscripts_script_get(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliPyScriptGetData(command.Command):
|
||||
"""Get script data."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliPyScriptGetData, self).get_parser(prog_name)
|
||||
parser.add_argument('-s', '--script-id',
|
||||
help='Script uuid',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_pyscripts_script_get_data(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliPyScriptDelete(command.Command):
|
||||
"""Get script data."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliPyScriptDelete, self).get_parser(prog_name)
|
||||
parser.add_argument('-s', '--script-id',
|
||||
help='Script uuid',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_pyscripts_script_delete(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliPyScriptUpdate(command.Command):
|
||||
"""Update a script."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliPyScriptUpdate, self).get_parser(prog_name)
|
||||
parser.add_argument('-s', '--script-id',
|
||||
help='Script uuid',
|
||||
required=True)
|
||||
parser.add_argument('-f', '--file',
|
||||
help='Script file',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_pyscripts_script_update(ckclient, parsed_args)
|
||||
@@ -15,22 +15,31 @@
|
||||
from cloudkittyclient.common import base
|
||||
|
||||
|
||||
class ReportResult(base.Resource):
|
||||
class ReportSummary(base.Resource):
|
||||
|
||||
key = 'report'
|
||||
key = 'summary'
|
||||
|
||||
def __init(self, tenant_id=None, res_type=None, begin=None,
|
||||
end=None, rate=None):
|
||||
self.tenant_id = tenant_id
|
||||
self.res_type = res_type
|
||||
self.begin = begin
|
||||
self.end = end
|
||||
self.rate = rate
|
||||
|
||||
def __repr__(self):
|
||||
return "<Report %s>" % self._info
|
||||
return "<Summary %s" % self._info
|
||||
|
||||
|
||||
class ReportManager(base.Manager):
|
||||
class ReportManager(base.CrudManager):
|
||||
|
||||
base_url = "/v1/report"
|
||||
|
||||
def list_tenants(self):
|
||||
return self.client.get(self.base_url + "/tenants").json()
|
||||
|
||||
def get_total(self, tenant_id=None, begin=None, end=None, service=None):
|
||||
def get_total(self, tenant_id=None, begin=None, end=None,
|
||||
service=None, all_tenants=False):
|
||||
url = self.base_url + "/total"
|
||||
filters = list()
|
||||
if tenant_id:
|
||||
@@ -41,6 +50,32 @@ class ReportManager(base.Manager):
|
||||
filters.append("end=%s" % end.isoformat())
|
||||
if service:
|
||||
filters.append("service=%s" % service)
|
||||
if all_tenants:
|
||||
filters.append("all_tenants=%s" % all_tenants)
|
||||
if filters:
|
||||
url += "?%s" % ('&'.join(filters))
|
||||
return self.client.get(url).json()
|
||||
|
||||
|
||||
class ReportSummaryManager(ReportManager):
|
||||
|
||||
resource_class = ReportSummary
|
||||
key = 'summary'
|
||||
collection_key = "summary"
|
||||
|
||||
def get_summary(self, tenant_id=None, begin=None, end=None,
|
||||
service=None, groupby=None, all_tenants=False):
|
||||
kwargs = {}
|
||||
if tenant_id:
|
||||
kwargs['tenant_id'] = tenant_id
|
||||
if begin:
|
||||
kwargs['begin'] = begin.isoformat()
|
||||
if end:
|
||||
kwargs['end'] = end.isoformat()
|
||||
if service:
|
||||
kwargs['service'] = service
|
||||
if groupby:
|
||||
kwargs['groupby'] = groupby
|
||||
if all_tenants:
|
||||
kwargs['all_tenants'] = all_tenants
|
||||
return super(ReportManager, self).list(**kwargs)
|
||||
|
||||
@@ -30,6 +30,37 @@ def do_report_tenant_list(cc, args):
|
||||
help='Tenant id',
|
||||
required=False,
|
||||
dest='total_tenant_id')
|
||||
@utils.arg('-b', '--begin',
|
||||
help='Starting date/time (YYYY-MM-DDTHH:MM:SS)',
|
||||
required=False)
|
||||
@utils.arg('-e', '--end',
|
||||
help='Ending date/time (YYYY-MM-DDTHH:MM:SS)',
|
||||
required=False)
|
||||
@utils.arg('-s', '--service',
|
||||
help='Service Type',
|
||||
required=False)
|
||||
@utils.arg('-a', '--all-tenants',
|
||||
default=False,
|
||||
action="store_true",
|
||||
dest='all_tenants',
|
||||
help='Allows to get total from all tenants'
|
||||
' (admin only).')
|
||||
def do_total_get(cc, args):
|
||||
"""Get total reports."""
|
||||
begin = utils.iso2dt(args.begin) if args.begin else None
|
||||
end = utils.iso2dt(args.end) if args.end else None
|
||||
total = cc.reports.get_total(tenant_id=args.total_tenant_id,
|
||||
begin=begin,
|
||||
end=end,
|
||||
service=args.service,
|
||||
all_tenants=args.all_tenants)
|
||||
utils.print_dict({'Total': total or 0.0})
|
||||
|
||||
|
||||
@utils.arg('-t', '--tenant-id',
|
||||
help='Tenant id',
|
||||
required=False,
|
||||
dest='summary_tenant_id')
|
||||
@utils.arg('-b', '--begin',
|
||||
help='Begin timestamp',
|
||||
required=False)
|
||||
@@ -39,12 +70,27 @@ def do_report_tenant_list(cc, args):
|
||||
@utils.arg('-s', '--service',
|
||||
help='Service Type',
|
||||
required=False)
|
||||
def do_total_get(cc, args):
|
||||
"""Get total reports."""
|
||||
@utils.arg('-g', '--groupby',
|
||||
help=('Fields to groupby, separated by commas '
|
||||
'if multiple, now support res_type,tenant_id'),
|
||||
required=False)
|
||||
@utils.arg('-a', '--all-tenants',
|
||||
default=False,
|
||||
action="store_true",
|
||||
dest='all_tenants',
|
||||
help='Allows to get summary from all tenants'
|
||||
' (admin only).')
|
||||
def do_summary_get(cc, args):
|
||||
"""Get summary report."""
|
||||
begin = utils.ts2dt(args.begin) if args.begin else None
|
||||
end = utils.ts2dt(args.end) if args.end else None
|
||||
total = cc.reports.get_total(tenant_id=args.total_tenant_id,
|
||||
begin=begin,
|
||||
end=end,
|
||||
service=args.service)
|
||||
utils.print_dict({'Total': total or 0.0})
|
||||
summarys = cc.reportsummary.get_summary(tenant_id=args.summary_tenant_id,
|
||||
begin=begin,
|
||||
end=end,
|
||||
service=args.service,
|
||||
groupby=args.groupby,
|
||||
all_tenants=args.all_tenants)
|
||||
field_labels = ['Tenant ID', 'Resource Type', 'Rate',
|
||||
'Begin Time', 'End Time']
|
||||
fields = ['tenant_id', 'res_type', 'rate', 'begin', 'end']
|
||||
utils.print_list(summarys, fields, field_labels, sortby=0)
|
||||
|
||||
88
cloudkittyclient/v1/report/shell_cli.py
Normal file
88
cloudkittyclient/v1/report/shell_cli.py
Normal file
@@ -0,0 +1,88 @@
|
||||
# Copyright 2016 Objectif Libre
|
||||
#
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.command import command
|
||||
|
||||
from cloudkittyclient.v1.report import shell
|
||||
|
||||
|
||||
class CliTotalGet(command.Command):
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliTotalGet, self).get_parser(prog_name)
|
||||
parser.add_argument('-t', '--tenant-id',
|
||||
help='Tenant id',
|
||||
required=False,
|
||||
dest='total_tenant_id')
|
||||
parser.add_argument('-b', '--begin',
|
||||
help='Begin timestamp',
|
||||
required=False)
|
||||
parser.add_argument('-e', '--end',
|
||||
help='End timestamp',
|
||||
required=False)
|
||||
parser.add_argument('-s', '--service',
|
||||
help='Service Type',
|
||||
required=False)
|
||||
parser.add_argument('-a', '--all-tenants',
|
||||
default=False,
|
||||
action="store_true",
|
||||
dest='all_tenants',
|
||||
help='Allows to get total from all tenants'
|
||||
' (admin only).')
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_total_get(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliReportTenantList(command.Command):
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_report_tenant_list(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliSummaryGet(command.Command):
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliSummaryGet, self).get_parser(prog_name)
|
||||
parser.add_argument('-t', '--tenant-id',
|
||||
help='Tenant id',
|
||||
required=False,
|
||||
dest='summary_tenant_id')
|
||||
parser.add_argument('-b', '--begin',
|
||||
help='Begin timestamp',
|
||||
required=False)
|
||||
parser.add_argument('-e', '--end',
|
||||
help='End timestamp',
|
||||
required=False)
|
||||
parser.add_argument('-s', '--service',
|
||||
help='Service Type',
|
||||
required=False)
|
||||
parser.add_argument('-g', '--groupby',
|
||||
help=('Fields to groupby, separated by '
|
||||
'commas if multiple, now support '
|
||||
'res_type,tenant_id'),
|
||||
required=False)
|
||||
parser.add_argument('-a', '--all-tenants',
|
||||
default=False,
|
||||
action="store_true",
|
||||
dest='all_tenants',
|
||||
help='Allows to get summary from all tenants'
|
||||
' (admin only).')
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_summary_get(ckclient, parsed_args)
|
||||
@@ -13,6 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from cloudkittyclient.apiclient import exceptions
|
||||
from cloudkittyclient.common import utils
|
||||
from cloudkittyclient import exc
|
||||
|
||||
@@ -21,11 +22,11 @@ def do_module_list(cc, args):
|
||||
'''List the samples for this meters.'''
|
||||
try:
|
||||
modules = cc.modules.list()
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Modules not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Modules not found')
|
||||
else:
|
||||
field_labels = ['Module', 'Enabled']
|
||||
fields = ['module_id', 'enabled']
|
||||
field_labels = ['Module', 'Enabled', 'Priority']
|
||||
fields = ['module_id', 'enabled', 'priority']
|
||||
utils.print_list(modules, fields, field_labels,
|
||||
sortby=0)
|
||||
|
||||
@@ -38,11 +39,11 @@ def do_module_enable(cc, args):
|
||||
try:
|
||||
module = cc.modules.get(module_id=args.name)
|
||||
module.enable()
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Modules not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Module not found: %s' % args.name)
|
||||
else:
|
||||
field_labels = ['Module', 'Enabled']
|
||||
fields = ['module_id', 'enabled']
|
||||
field_labels = ['Module', 'Enabled', 'Priority']
|
||||
fields = ['module_id', 'enabled', 'priority']
|
||||
modules = [cc.modules.get(module_id=args.name)]
|
||||
utils.print_list(modules, fields, field_labels,
|
||||
sortby=0)
|
||||
@@ -56,11 +57,58 @@ def do_module_disable(cc, args):
|
||||
try:
|
||||
module = cc.modules.get(module_id=args.name)
|
||||
module.disable()
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Modules not found: %s' % args.counter_name)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Module not found: %s' % args.name)
|
||||
else:
|
||||
field_labels = ['Module', 'Enabled']
|
||||
fields = ['module_id', 'enabled']
|
||||
field_labels = ['Module', 'Enabled', 'Priority']
|
||||
fields = ['module_id', 'enabled', 'priority']
|
||||
modules = [cc.modules.get(module_id=args.name)]
|
||||
utils.print_list(modules, fields, field_labels,
|
||||
sortby=0)
|
||||
|
||||
|
||||
@utils.arg('-n', '--name',
|
||||
help='Module name',
|
||||
required=True)
|
||||
@utils.arg('-p', '--priority',
|
||||
help='Module priority',
|
||||
required=True)
|
||||
def do_module_set_priority(cc, args):
|
||||
'''Set module priority.'''
|
||||
try:
|
||||
module = cc.modules.get(module_id=args.name)
|
||||
module.set_priority(args.priority)
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Module not found: %s' % args.name)
|
||||
else:
|
||||
field_labels = ['Module', 'Enabled', 'Priority']
|
||||
fields = ['module_id', 'enabled', 'priority']
|
||||
modules = [cc.modules.get(module_id=args.name)]
|
||||
utils.print_list(modules, fields, field_labels,
|
||||
sortby=0)
|
||||
|
||||
|
||||
def do_info_config_get(cc, args):
|
||||
'''Get cloudkitty configuration.'''
|
||||
utils.print_dict(cc.config.get_config(), dict_property="Section")
|
||||
|
||||
|
||||
@utils.arg('-n', '--name',
|
||||
help='Service name',
|
||||
required=False)
|
||||
def do_info_service_get(cc, args):
|
||||
'''Get service info.'''
|
||||
if args.name:
|
||||
try:
|
||||
services_info = [cc.service_info.get(service_id=args.name)]
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('Service not found: %s' % args.name)
|
||||
else:
|
||||
try:
|
||||
services_info = cc.service_info.list()
|
||||
except exceptions.NotFound:
|
||||
raise exc.CommandError('ServiceInfo not found')
|
||||
|
||||
field_labels = ['Service', 'Metadata', 'Unit']
|
||||
fields = ['service_id', 'metadata', 'unit']
|
||||
utils.print_list(services_info, fields, field_labels, sortby=0)
|
||||
|
||||
91
cloudkittyclient/v1/shell_cli.py
Normal file
91
cloudkittyclient/v1/shell_cli.py
Normal file
@@ -0,0 +1,91 @@
|
||||
# Copyright 2016 Objectif Libre
|
||||
|
||||
# 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.command import command
|
||||
|
||||
from cloudkittyclient.v1 import shell
|
||||
|
||||
|
||||
class CliModuleList(command.Command):
|
||||
"""List modules."""
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_module_list(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliModuleEnable(command.Command):
|
||||
"""Enable a module."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliModuleEnable, self).get_parser(prog_name)
|
||||
parser.add_argument('-n', '--name',
|
||||
help='Module name',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_module_enable(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliModuleDisable(command.Command):
|
||||
"""Disable a module."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliModuleDisable, self).get_parser(prog_name)
|
||||
parser.add_argument('-n', '--name',
|
||||
help='Module name',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_module_disable(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliModuleSetPriority(command.Command):
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliModuleSetPriority, self).get_parser(prog_name)
|
||||
parser.add_argument('-n', '--name',
|
||||
help='Module name',
|
||||
required=True)
|
||||
parser.add_argument('-p', '--priority',
|
||||
help='Module priority',
|
||||
required=True)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_module_set_priority(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliInfoGetConfig(command.Command):
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliInfoGetConfig, self).get_parser(prog_name)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_info_config_get(ckclient, parsed_args)
|
||||
|
||||
|
||||
class CliInfoGetService(command.Command):
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliInfoGetService, self).get_parser(prog_name)
|
||||
parser.add_argument('-n', '--name',
|
||||
help='Service name',
|
||||
required=False)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_info_service_get(ckclient, parsed_args)
|
||||
@@ -17,17 +17,17 @@
|
||||
from cloudkittyclient.common import utils
|
||||
|
||||
|
||||
@utils.arg('--begin',
|
||||
help='Starting date/time (YYYY-MM-ddThh:mm:ss)',
|
||||
required=True)
|
||||
@utils.arg('--end',
|
||||
help='Ending date/time (YYYY-MM-ddThh:mm:ss)',
|
||||
required=True)
|
||||
@utils.arg('--tenant',
|
||||
@utils.arg('-b', '--begin',
|
||||
help='Starting date/time (YYYY-MM-DDTHH:MM:SS)',
|
||||
required=False)
|
||||
@utils.arg('-e', '--end',
|
||||
help='Ending date/time (YYYY-MM-DDTHH:MM:SS)',
|
||||
required=False)
|
||||
@utils.arg('-t', '--tenant',
|
||||
help='Tenant ID',
|
||||
required=False,
|
||||
default=None)
|
||||
@utils.arg('--resource-type',
|
||||
@utils.arg('-r', '--resource-type',
|
||||
help='Resource type (compute, image, ...)',
|
||||
required=False,
|
||||
default=None)
|
||||
|
||||
44
cloudkittyclient/v1/storage/shell_cli.py
Normal file
44
cloudkittyclient/v1/storage/shell_cli.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# Copyright 2016 Objectif Libre
|
||||
#
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.command import command
|
||||
|
||||
from cloudkittyclient.v1.storage import shell
|
||||
|
||||
|
||||
class CliStorageDataframeList(command.Command):
|
||||
"""List dataframes."""
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliStorageDataframeList, self).get_parser(prog_name)
|
||||
parser.add_argument('-b', '--begin',
|
||||
help='Starting date/time (YYYY-MM-ddThh:mm:ss)',
|
||||
required=False)
|
||||
parser.add_argument('-e', '--end',
|
||||
help='Ending date/time (YYYY-MM-ddThh:mm:ss)',
|
||||
required=False)
|
||||
parser.add_argument('-t', '--tenant',
|
||||
help='Tenant ID',
|
||||
required=False,
|
||||
default=None)
|
||||
parser.add_argument('-r', '--resource-type',
|
||||
help='Resource type (compute, image...)',
|
||||
required=False,
|
||||
default=None)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ckclient = self.app.client_manager.rating
|
||||
shell.do_storage_dataframe_list(ckclient, parsed_args)
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
[DEFAULT]
|
||||
|
||||
# The list of modules to copy from oslo-incubator.git
|
||||
module=apiclient
|
||||
module=cliutils
|
||||
|
||||
# The base module to hold the copy of openstack.common
|
||||
base=cloudkittyclient
|
||||
@@ -5,6 +5,7 @@
|
||||
pbr>=1.6 # Apache-2.0
|
||||
Babel>=2.3.4 # BSD
|
||||
python-keystoneclient!=1.8.0,!=2.1.0,>=1.7.0 # Apache-2.0
|
||||
python-openstackclient>=3.0.0 # Apache-2.0
|
||||
stevedore>=1.10.0 # Apache-2.0
|
||||
oslo.i18n>=2.1.0 # Apache-2.0
|
||||
oslo.serialization>=1.10.0 # Apache-2.0
|
||||
|
||||
53
setup.cfg
53
setup.cfg
@@ -30,6 +30,59 @@ cloudkitty.client.modules =
|
||||
hashmap = cloudkittyclient.v1.rating.hashmap.extension:Extension
|
||||
pyscripts = cloudkittyclient.v1.rating.pyscripts.extension:Extension
|
||||
|
||||
openstack.cli.extension =
|
||||
rating = cloudkittyclient.osc
|
||||
|
||||
openstack.rating.v1 =
|
||||
rating_module-list = cloudkittyclient.v1.shell_cli:CliModuleList
|
||||
rating_module-enable = cloudkittyclient.v1.shell_cli:CliModuleEnable
|
||||
rating_module-disable = cloudkittyclient.v1.shell_cli:CliModuleDisable
|
||||
rating_module-set-priority = cloudkittyclient.v1.shell_cli:CliModuleSetPriority
|
||||
|
||||
rating_info-config-get = cloudkittyclient.v1.shell_cli:CliInfoGetConfig
|
||||
rating_info-service-get = cloudkittyclient.v1.shell_cli:CliInfoGetService
|
||||
|
||||
rating_total-get = cloudkittyclient.v1.report.shell_cli:CliTotalGet
|
||||
rating_summary-get = cloudkittyclient.v1.report.shell_cli:CliSummaryGet
|
||||
rating_report-tenant-list = cloudkittyclient.v1.report.shell_cli:CliReportTenantList
|
||||
|
||||
rating_collector-mapping-list = cloudkittyclient.v1.collector.shell_cli:CliCollectorMappingList
|
||||
rating_collector-mapping-get = cloudkittyclient.v1.collector.shell_cli:CliCollectorMappingGet
|
||||
rating_collector-mapping-create = cloudkittyclient.v1.collector.shell_cli:CliCollectorMappingCreate
|
||||
rating_collector-mapping-delete = cloudkittyclient.v1.collector.shell_cli:CliCollectorMappingDelete
|
||||
rating_collector-state-get = cloudkittyclient.v1.collector.shell_cli:CliCollectorStateGet
|
||||
rating_collector-state-enable = cloudkittyclient.v1.collector.shell_cli:CliCollectorStateEnable
|
||||
rating_collector-state-disable = cloudkittyclient.v1.collector.shell_cli:CliCollectorStateDisable
|
||||
|
||||
rating_storage-dataframe-list = cloudkittyclient.v1.storage.shell_cli:CliStorageDataframeList
|
||||
|
||||
rating_hashmap-service-create = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapServiceCreate
|
||||
rating_hashmap-service-list = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapServiceList
|
||||
rating_hashmap-service-delete = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapServiceDelete
|
||||
rating_hashmap-field-create = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapFieldCreate
|
||||
rating_hashmap-field-list = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapFieldList
|
||||
rating_hashmap-field-delete = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapFieldDelete
|
||||
rating_hashmap-mapping-create = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapMappingCreate
|
||||
rating_hashmap-mapping-update = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapMappingUpdate
|
||||
rating_hashmap-mapping-list = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapMappingList
|
||||
rating_hashmap-mapping-delete = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapMappingDelete
|
||||
rating_hashmap-group-create = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapGroupCreate
|
||||
rating_hashmap-group-list = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapGroupList
|
||||
rating_hashmap-group-delete = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapGroupDelete
|
||||
rating_hashmap-threshold-create = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapThresholdCreate
|
||||
rating_hashmap-threshold-update = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapThresholdUpdate
|
||||
rating_hashmap-threshold-list = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapThresholdList
|
||||
rating_hashmap-threshold-delete = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapThresholdDelete
|
||||
rating_hashmap-threshold-get = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapThresholdGet
|
||||
rating_hashmap-threshold-group = cloudkittyclient.v1.rating.hashmap.shell_cli:CliHashmapThresholdGroup
|
||||
|
||||
rating_pyscripts-script-create = cloudkittyclient.v1.rating.pyscripts.shell_cli:CliPyScriptCreate
|
||||
rating_pyscripts-script-list = cloudkittyclient.v1.rating.pyscripts.shell_cli:CliPyScriptList
|
||||
rating_pyscripts-script-get = cloudkittyclient.v1.rating.pyscripts.shell_cli:CliPyScriptGet
|
||||
rating_pyscripts-script-get-data = cloudkittyclient.v1.rating.pyscripts.shell_cli:CliPyScriptGetData
|
||||
rating_pyscripts-script-delete = cloudkittyclient.v1.rating.pyscripts.shell_cli:CliPyScriptDelete
|
||||
rating_pyscripts-script-update = cloudkittyclient.v1.rating.pyscripts.shell_cli:CliPyScriptUpdate
|
||||
|
||||
[build_sphinx]
|
||||
source-dir = doc/source
|
||||
build-dir = doc/build
|
||||
|
||||
10
tox.ini
10
tox.ini
@@ -5,13 +5,16 @@ skipsdist = True
|
||||
|
||||
[testenv]
|
||||
usedevelop = True
|
||||
install_command = pip install -U {opts} {packages}
|
||||
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=stable/ocata} -U {opts} {packages}
|
||||
setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = python setup.py testr --slowest --testr-args='{posargs}'
|
||||
|
||||
[testenv:debug]
|
||||
commands = oslo_debug_helper {posargs}
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8
|
||||
|
||||
@@ -25,13 +28,12 @@ commands = python setup.py testr --coverage --testr-args='{posargs}'
|
||||
commands = python setup.py build_sphinx
|
||||
|
||||
[flake8]
|
||||
# H803 skipped on purpose per list discussion.
|
||||
# E123, E125 skipped as they are invalid PEP-8.
|
||||
|
||||
show-source = True
|
||||
ignore = E123,E125,H803
|
||||
ignore = E123,E125
|
||||
builtins = _
|
||||
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build
|
||||
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
|
||||
|
||||
[hacking]
|
||||
import_exceptions = cloudkittyclient.i18n
|
||||
|
||||
Reference in New Issue
Block a user