Compare commits

..

1 Commits

Author SHA1 Message Date
Thierry Carrez
bcab489385 Update .gitreview for stable/mitaka
Change-Id: Idb73a4b508786a8843e63e8832c641d779d0613f
2016-03-28 14:40:38 +02:00
50 changed files with 277 additions and 1603 deletions

View File

@@ -3,7 +3,10 @@ branch = True
source = cloudkittyclient
omit =
cloudkittyclient/tests/*,
cloudkittyclient/i18n.py
cloudkittyclient/openstack/*,
cloudkittyclient/i18n.py,
cloudkittyclient/common/client.py,
cloudkittyclient/common/exceptions.py
[report]
ignore_errors = True

3
.gitignore vendored
View File

@@ -11,6 +11,3 @@ cover
dist
*.egg
*.sw?
.eggs
AUTHORS
ChangeLog

View File

@@ -2,3 +2,4 @@
host=review.openstack.org
port=29418
project=openstack/python-cloudkittyclient.git
defaultbranch=stable/mitaka

19
.pylintrc Normal file
View File

@@ -0,0 +1,19 @@
[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=_

6
MANIFEST.in Normal file
View File

@@ -0,0 +1,6 @@
include AUTHORS
include ChangeLog
exclude .gitignore
exclude .gitreview
global-exclude *.pyc

View File

@@ -1,12 +1,3 @@
========================
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
=====================================

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Objectif Libre
# Licensed under the Apache License, Version 2.0 (the "License"); you may

View File

@@ -10,10 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import contextlib
import time
from keystoneclient import adapter
from keystoneclient.auth.identity import v2 as v2_auth
from keystoneclient.auth.identity import v3 as v3_auth
from keystoneclient import discover
@@ -22,11 +18,10 @@ 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 exceptions
def _discover_auth_versions(session, auth_url):
@@ -208,13 +203,8 @@ class AuthPlugin(auth.BaseAuthPlugin):
"""
has_token = self.opts.get('token') or self.opts.get('auth_token')
no_auth = has_token and self.opts.get('endpoint')
has_project = (self.opts.get('project_id')
or (self.opts.get('project_name')
and (self.opts.get('user_domain_name')
or self.opts.get('user_domain_id'))))
has_tenant = self.opts.get('tenant_id') or self.opts.get('tenant_name')
has_credential = (self.opts.get('username')
and (has_project or has_tenant)
has_credential = (self.opts.get('username') and has_tenant
and self.opts.get('password')
and self.opts.get('auth_url'))
missing = not (no_auth or has_credential)
@@ -263,28 +253,9 @@ def get_client(version, **kwargs):
:param api_version: the API version to use ('1')
:param kwargs: keyword args containing credentials, either:
* session: a keystoneauth/keystoneclient session object
* service_type: The default service_type for URL discovery
* service_name: The default service_name for URL discovery
* interface: The default interface for URL discovery
(Default: public)
* region_name: The default region_name for URL discovery
* endpoint_override: Always use this endpoint URL for requests
for this cloudkittyclient
* auth: An auth plugin to use instead of the session one
* user_agent: The User-Agent string to set
(Default is python-cloudkittyclient)
* connect_retries: the maximum number of retries that should be
attempted for connection errors
* logger: A logging object
or (DEPRECATED):
* os_token: pre-existing token to re-use
* os_endpoint: Cloudkitty API endpoint
or (DEPRECATED):
or:
* os_username: name of user
* os_password: user's password
* os_user_id: user's id
@@ -306,10 +277,8 @@ def get_client(version, **kwargs):
cli_kwargs = {
'username': kwargs.get('os_username'),
'password': kwargs.get('os_password'),
'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')),
'tenant_id': kwargs.get('os_tenant_id'),
'tenant_name': kwargs.get('os_tenant_name'),
'auth_url': kwargs.get('os_auth_url'),
'region_name': kwargs.get('os_region_name'),
'service_type': kwargs.get('os_service_type'),
@@ -341,94 +310,10 @@ def get_auth_plugin(endpoint, **kwargs):
endpoint=endpoint,
username=kwargs.get('username'),
password=kwargs.get('password'),
tenant_name=kwargs.get('tenant_name') or kwargs.get('project_name'),
tenant_name=kwargs.get('tenant_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'),
project_domain_id=kwargs.get('project_domain_id')
)
return auth_plugin
LEGACY_OPTS = ('auth_plugin', 'auth_url', 'token', 'insecure', 'cacert',
'tenant_id', 'project_id', 'username', 'password',
'project_name', 'tenant_name',
'user_domain_name', 'user_domain_id',
'project_domain_name', 'project_domain_id',
'key_file', 'cert_file', 'verify', 'timeout', 'cert')
def construct_http_client(**kwargs):
kwargs = kwargs.copy()
if kwargs.get('session') is not None:
# Drop legacy options
for opt in LEGACY_OPTS:
kwargs.pop(opt, None)
return SessionClient(
session=kwargs.pop('session'),
service_type=kwargs.pop('service_type', 'rating') or 'rating',
interface=kwargs.pop('interface', kwargs.pop('endpoint_type',
'publicURL')),
region_name=kwargs.pop('region_name', None),
user_agent=kwargs.pop('user_agent', 'python-cloudkittyclient'),
auth=kwargs.get('auth', None),
timings=kwargs.pop('timings', None),
**kwargs)
else:
return client.BaseClient(client.HTTPClient(
auth_plugin=kwargs.get('auth_plugin'),
region_name=kwargs.get('region_name'),
endpoint_type=kwargs.get('endpoint_type'),
original_ip=kwargs.get('original_ip'),
verify=kwargs.get('verify'),
cert=kwargs.get('cert'),
timeout=kwargs.get('timeout'),
timings=kwargs.get('timings'),
keyring_saver=kwargs.get('keyring_saver'),
debug=kwargs.get('debug'),
user_agent=kwargs.get('user_agent'),
http=kwargs.get('http')
))
@contextlib.contextmanager
def record_time(times, enabled, *args):
"""Record the time of a specific action.
:param times: A list of tuples holds time data.
:type times: list
:param enabled: Whether timing is enabled.
:type enabled: bool
:param args: Other data to be stored besides time data, these args
will be joined to a string.
"""
if not enabled:
yield
else:
start = time.time()
yield
end = time.time()
times.append((' '.join(args), start, end))
class SessionClient(adapter.LegacyJsonAdapter):
def __init__(self, *args, **kwargs):
self.times = []
self.timings = kwargs.pop('timings', False)
super(SessionClient, self).__init__(*args, **kwargs)
def request(self, url, method, **kwargs):
kwargs.setdefault('headers', kwargs.get('headers', {}))
# NOTE(sileht): The standard call raises errors from
# keystoneauth, where we need to raise the cloudkittyclient errors.
raise_exc = kwargs.pop('raise_exc', True)
with record_time(self.times, self.timings, method, url):
resp, body = super(SessionClient, self).request(url,
method,
raise_exc=False,
**kwargs)
if raise_exc and resp.status_code >= 400:
raise exc.from_response(resp, body)
return resp

View File

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

View File

@@ -23,20 +23,12 @@ 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 _
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
from cloudkittyclient.openstack.common import cliutils
def import_versioned_module(version, submodule=None):

View File

@@ -37,7 +37,7 @@ import os
import six
from stevedore import extension
from cloudkittyclient.apiclient import exceptions
from cloudkittyclient.openstack.common.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.apiclient.auth"
ep_namespace = "cloudkittyclient.openstack.common.apiclient.auth"
mgr = extension.ExtensionManager(ep_namespace)
mgr.map(add_plugin)
@@ -156,7 +156,8 @@ 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
@@ -165,7 +166,8 @@ 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)
@@ -202,7 +204,8 @@ 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.

View File

@@ -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,7 +467,8 @@ 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:
@@ -522,9 +523,6 @@ 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

View File

@@ -38,9 +38,8 @@ 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',)
@@ -65,7 +64,7 @@ class HTTPClient(object):
into terminal and send the same request with curl.
"""
user_agent = "cloudkittyclient.apiclient"
user_agent = "cloudkittyclient.openstack.common.apiclient"
def __init__(self,
auth_plugin,

View File

@@ -42,7 +42,8 @@ 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
@@ -117,7 +118,8 @@ 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")

View File

@@ -43,7 +43,7 @@ import requests
import six
from six.moves.urllib import parse
from cloudkittyclient.apiclient import client
from cloudkittyclient.openstack.common.apiclient import client
def assert_has_keys(dct, required=None, optional=None):
@@ -59,7 +59,8 @@ 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__()
@@ -87,9 +88,6 @@ 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):
@@ -101,14 +99,15 @@ 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]
msg = "Expected %s %s but no calls were made." % expected
assert self.callstack, msg
assert self.callstack, \
"Expected %s %s but no calls were made." % expected
msg = 'Expected %s %s; got %s %s' % (expected + called)
assert expected == called, msg
assert expected == called, 'Expected %s %s; got %s %s' % \
(expected + called)
if body is not None:
if self.callstack[pos][3] != body:
@@ -116,11 +115,12 @@ 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)
msg = "Expected %s %s but no calls were made." % expected
assert self.callstack, msg
assert self.callstack, \
"Expected %s %s but no calls were made." % expected
found = False
entry = None
@@ -129,8 +129,8 @@ class FakeHTTPClient(client.HTTPClient):
found = True
break
msg = 'Expected %s %s; got %s' % (method, url, self.callstack)
assert found, msg
assert found, 'Expected %s %s; got %s' % \
(method, url, self.callstack)
if body is not None:
assert entry[3] == body, "%s != %s" % (entry[3], body)

View File

@@ -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,13 +84,17 @@ 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)

View File

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

View File

@@ -1,35 +0,0 @@
# 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

View File

@@ -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
@@ -198,11 +198,12 @@ class CloudkittyShell(object):
@staticmethod
def no_project_and_domain_set(args):
return not (((args.os_project_id or (args.os_project_name and
(args.os_project_domain_name or
args.os_project_domain_id)))
and (args.os_user_domain_name or args.os_user_domain_id))
or (args.os_tenant_id or args.os_tenant_name))
if not (args.os_project_id or (args.os_project_name and
(args.os_user_domain_name or args.os_user_domain_id)) or
(args.os_tenant_id or args.os_tenant_name)):
return True
else:
return False
def main(self, argv):
parsed = self.parse_args(argv)
@@ -241,24 +242,20 @@ class CloudkittyShell(object):
"env[OS_USER_DOMAIN_NAME] or "
"a domain_id via either "
"--os-user-domain-id or via "
"env[OS_USER_DOMAIN_ID]\n\n"
"As an alternative to project_id, "
"you can provide a project_name via "
"either --os-project-name or via "
"env[OS_PROJECT_NAME] and "
"a project_domain_name via either "
"--os-project-domain-name or via "
"env[OS_PROJECT_DOMAIN_NAME] or "
"a project_domain_id via either "
"--os-project-domain-id or via "
"env[OS_PROJECT_DOMAIN_ID]")
"env[OS_USER_DOMAIN_ID]")
if not (self.auth_plugin.opts['tenant_id']
or self.auth_plugin.opts['tenant_name']):
raise exc.CommandError("You must provide a tenant_id via "
"either --os-tenant-id or via "
"env[OS_TENANT_ID]")
if not self.auth_plugin.opts['auth_url']:
raise exc.CommandError("You must provide an auth url via "
"either --os-auth-url or via "
"env[OS_AUTH_URL]")
client_kwargs = {}
client_kwargs = vars(args)
client_kwargs.update(self.auth_plugin.opts)
client_kwargs['auth_plugin'] = self.auth_plugin
client = ckclient.get_client(api_version, **client_kwargs)

View File

@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2010-2011 OpenStack Foundation
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
#

View File

@@ -45,16 +45,6 @@ class ClientTest(utils.BaseTestCase):
def setUp(self):
super(ClientTest, self).setUp()
def test_client_v1_with_session(self):
resp = mock.Mock(status_code=200, text=b'')
resp.json.return_value = {"modules": []}
session = mock.Mock()
session.request.return_value = resp
c = client.get_client(1, session=session)
c.modules.list()
self.assertTrue(session.request.called)
self.assertTrue(resp.json.called)
def test_client_version(self):
c1 = self.create_client(env=FAKE_ENV, api_version=1)
self.assertIsInstance(c1, v1client.Client)
@@ -132,7 +122,7 @@ class ClientTest(utils.BaseTestCase):
'user_agent': None,
'debug': None,
}
cls = 'cloudkittyclient.apiclient.client.HTTPClient'
cls = 'cloudkittyclient.openstack.common.apiclient.client.HTTPClient'
with mock.patch(cls) as mocked:
self.create_client(env)
mocked.assert_called_with(**expected)
@@ -147,8 +137,7 @@ class ClientTest(utils.BaseTestCase):
env = FAKE_ENV.copy()
env['cacert'] = '/path/to/cacert'
client = self.create_client(env)
self.assertEqual('/path/to/cacert',
client.http_client.http_client.verify)
self.assertEqual('/path/to/cacert', client.client.verify)
def test_v1_client_certfile_and_keyfile(self):
env = FAKE_ENV.copy()
@@ -156,4 +145,4 @@ class ClientTest(utils.BaseTestCase):
env['key_file'] = '/path/to/keycert'
client = self.create_client(env)
self.assertEqual(('/path/to/cert', '/path/to/keycert'),
client.http_client.http_client.cert)
client.client.cert)

View File

@@ -1,3 +1,5 @@
# -*- 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

View File

@@ -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.apiclient import client
from cloudkittyclient.apiclient import fake_client
from cloudkittyclient.openstack.common.apiclient import client
from cloudkittyclient.openstack.common.apiclient import fake_client
from cloudkittyclient.tests import utils
import cloudkittyclient.v1.core
@@ -26,12 +26,10 @@ fixtures = {
{
'module_id': 'hashmap',
'enabled': True,
'priority': 1,
},
{
'module_id': 'noop',
'enabled': False,
'priority': 1,
},
]},
),
@@ -42,7 +40,6 @@ fixtures = {
{
'module_id': 'hashmap',
'enabled': True,
'priority': 1,
}
),
'PUT': (
@@ -50,7 +47,6 @@ fixtures = {
{
'module_id': 'hashmap',
'enabled': False,
'priority': 1,
}
),
},
@@ -60,7 +56,6 @@ fixtures = {
{
'module_id': 'noop',
'enabled': False,
'priority': 1,
}
),
'PUT': (
@@ -68,7 +63,6 @@ fixtures = {
{
'module_id': 'noop',
'enabled': True,
'priority': 1,
}
),
},
@@ -129,8 +123,7 @@ class CloudkittyModuleTest(utils.BaseTestCase):
# body : {'enabled': True}
expect = [
'PUT', '/v1/rating/modules/noop', {'module_id': 'noop',
'enabled': True,
'priority': 1},
'enabled': True},
]
self.http_client.assert_called(*expect)
@@ -141,19 +134,6 @@ class CloudkittyModuleTest(utils.BaseTestCase):
# body : {'enabled': False}
expect = [
'PUT', '/v1/rating/modules/hashmap', {'module_id': 'hashmap',
'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},
'enabled': False},
]
self.http_client.assert_called(*expect)

View File

@@ -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.apiclient import client
from cloudkittyclient.apiclient import fake_client
from cloudkittyclient.openstack.common.apiclient import client
from cloudkittyclient.openstack.common.apiclient import fake_client
from cloudkittyclient.tests import utils
from cloudkittyclient.v1.rating import hashmap
@@ -622,21 +622,6 @@ class MappingManagerTest(utils.BaseTestCase):
self.api = client.BaseClient(self.http_client)
self.mgr = hashmap.MappingManager(self.api)
def test_get_mappings_by_group(self):
mappings = self.mgr.findall(group_id=GROUP2['group_id'])
expect = [
'GET', ('/v1/rating/module_config/hashmap/mappings?group_id=' +
GROUP2['group_id'])]
self.http_client.assert_called(*expect)
self.assertEqual(1, len(mappings))
mapping = mappings[0]
self.assertEqual(FIELD1['field_id'], mapping.field_id)
self.assertEqual(FIELD_MAPPING1['group_id'], mapping.group_id)
self.assertEqual(FIELD_MAPPING1['mapping_id'], mapping.mapping_id)
self.assertEqual(FIELD_MAPPING1['value'], mapping.value)
self.assertEqual(FIELD_MAPPING1['cost'], mapping.cost)
self.assertEqual(FIELD_MAPPING1['type'], mapping.type)
def test_get_a_mapping(self):
resource = self.mgr.get(mapping_id=FIELD_MAPPING1['mapping_id'])
expect = [
@@ -715,27 +700,6 @@ class ThresholdManagerTest(utils.BaseTestCase):
self.api = client.BaseClient(self.http_client)
self.mgr = hashmap.ThresholdManager(self.api)
def test_get_thresholds_by_group(self):
mappings = self.mgr.findall(group_id=GROUP3['group_id'])
expect = [
'GET', ('/v1/rating/module_config/hashmap/thresholds?group_id=' +
GROUP3['group_id'])]
self.http_client.assert_called(*expect)
self.assertEqual(1, len(mappings))
mapping = mappings[0]
self.assertEqual(SERVICE_THRESHOLD1['threshold_id'],
mapping.threshold_id)
self.assertEqual(SERVICE_THRESHOLD1['service_id'],
mapping.service_id)
self.assertEqual(SERVICE_THRESHOLD1['group_id'],
mapping.group_id)
self.assertEqual(SERVICE_THRESHOLD1['level'],
mapping.level)
self.assertEqual(SERVICE_THRESHOLD1['cost'],
mapping.cost)
self.assertEqual(SERVICE_THRESHOLD1['map_type'],
mapping.map_type)
def test_get_a_threshold(self):
resource = self.mgr.get(
threshold_id=SERVICE_THRESHOLD1['threshold_id'])

View File

@@ -1,139 +0,0 @@
# 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)

View File

@@ -16,6 +16,7 @@
from stevedore import extension
from cloudkittyclient import client as ckclient
from cloudkittyclient.openstack.common.apiclient import client
from cloudkittyclient.v1 import collector
from cloudkittyclient.v1 import core
from cloudkittyclient.v1 import report
@@ -27,41 +28,38 @@ SUBMODULES_NAMESPACE = 'cloudkitty.client.modules'
class Client(object):
"""Client for the Cloudkitty v1 API.
:param session: a keystoneauth/keystoneclient session object
:type session: keystoneclient.session.Session
:param str service_type: The default service_type for URL discovery
:param str service_name: The default service_name for URL discovery
:param str interface: The default interface for URL discovery
(Default: public)
:param str region_name: The default region_name for URL discovery
:param str endpoint_override: Always use this endpoint URL for requests
for this cloudkittyclient
:param auth: An auth plugin to use instead of the session one
:type auth: keystoneclient.auth.base.BaseAuthPlugin
:param str user_agent: The User-Agent string to set
(Default is python-cloudkittyclient)
:param int connect_retries: the maximum number of retries that should be
attempted for connection errors
:param logger: A logging object
:type logger: logging.Logger
:param string endpoint: A user-supplied endpoint URL for the cloudkitty
service.
:param function token: Provides token for authentication.
:param integer timeout: Allows customization of the timeout for client
http requests. (optional)
"""
def __init__(self, *args, **kwargs):
"""Initialize a new client for the Cloudkitty v1 API."""
self.auth_plugin = (kwargs.get('auth_plugin')
or ckclient.get_auth_plugin(*args, **kwargs))
self.client = client.HTTPClient(
auth_plugin=self.auth_plugin,
region_name=kwargs.get('region_name'),
endpoint_type=kwargs.get('endpoint_type'),
original_ip=kwargs.get('original_ip'),
verify=kwargs.get('verify'),
cert=kwargs.get('cert'),
timeout=kwargs.get('timeout'),
timings=kwargs.get('timings'),
keyring_saver=kwargs.get('keyring_saver'),
debug=kwargs.get('debug'),
user_agent=kwargs.get('user_agent'),
http=kwargs.get('http')
)
if not kwargs.get('auth_plugin'):
kwargs['auth_plugin'] = ckclient.get_auth_plugin(*args, **kwargs)
self.auth_plugin = kwargs.get('auth_plugin')
self.http_client = ckclient.construct_http_client(**kwargs)
self.http_client = client.BaseClient(self.client)
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):

View File

@@ -17,7 +17,7 @@
from cloudkittyclient.common import utils
@utils.arg('-c', '--collector',
@utils.arg('--collector',
help='Collector name to filter on.',
required=False,
default=None)
@@ -29,7 +29,7 @@ def do_collector_mapping_list(cc, args):
utils.print_list(data, fields, fields_labels, sortby=0)
@utils.arg('-s', '--service',
@utils.arg('--service',
help='Which service to get the mapping for.',
required=True)
def do_collector_mapping_get(cc, args):
@@ -38,10 +38,10 @@ def do_collector_mapping_get(cc, args):
utils.print_dict(data.to_dict())
@utils.arg('-c', '--collector',
@utils.arg('--collector',
help='Map a service to this collector.',
required=True)
@utils.arg('-s', '--service',
@utils.arg('--service',
help='Map a collector to this service.',
required=True)
def do_collector_mapping_create(cc, args):
@@ -51,7 +51,7 @@ def do_collector_mapping_create(cc, args):
utils.print_dict(out.to_dict())
@utils.arg('-s', '--service',
@utils.arg('--service',
help='Filter on this service.',
required=True)
def do_collector_mapping_delete(cc, args):
@@ -60,7 +60,7 @@ def do_collector_mapping_delete(cc, args):
cc.collector.mappings.delete(mapping_id=args.service)
@utils.arg('-n', '--name',
@utils.arg('--name',
help='Name of the collector.',
required=True)
def do_collector_state_get(cc, args):
@@ -69,7 +69,7 @@ def do_collector_state_get(cc, args):
utils.print_dict(data.to_dict())
@utils.arg('-n', '--name',
@utils.arg('--name',
help='Name of the collector.',
required=True)
def do_collector_state_enable(cc, args):
@@ -78,7 +78,7 @@ def do_collector_state_enable(cc, args):
utils.print_dict(new_state.to_dict())
@utils.arg('-n', '--name',
@utils.arg('--name',
help='Name of the collector.',
required=True)
def do_collector_state_disable(cc, args):

View File

@@ -1,109 +0,0 @@
# 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)

View File

@@ -30,10 +30,6 @@ 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
@@ -64,26 +60,3 @@ 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

View File

@@ -17,7 +17,6 @@ import functools
from oslo_utils import strutils
from cloudkittyclient.apiclient import exceptions
from cloudkittyclient.common import utils
from cloudkittyclient import exc
@@ -45,8 +44,8 @@ def do_hashmap_service_list(cc, args={}):
"""List services."""
try:
services = cc.hashmap.services.list()
except exceptions.NotFound:
raise exc.CommandError('Services not found.')
except exc.HTTPNotFound:
raise exc.CommandError('Services not found: %s' % args.counter_name)
else:
field_labels = ['Name', 'Service id']
fields = ['name', 'service_id']
@@ -61,8 +60,8 @@ def do_hashmap_service_delete(cc, args={}):
"""Delete a service."""
try:
cc.hashmap.services.delete(service_id=args.service_id)
except exceptions.NotFound:
raise exc.CommandError('Service not found: %s' % args.service_id)
except exc.HTTPNotFound:
raise exc.CommandError('Service not found: %s' % args.counter_name)
@utils.arg('-n', '--name',
@@ -93,9 +92,8 @@ def do_hashmap_field_list(cc, args={}):
"""List fields."""
try:
created_field = cc.hashmap.fields.list(service_id=args.service_id)
except exceptions.NotFound:
raise exc.CommandError('Fields not found in service: %s'
% args.service_id)
except exc.HTTPNotFound:
raise exc.CommandError('Fields not found: %s' % args.counter_name)
else:
field_labels = ['Name', 'Field id']
fields = ['name', 'field_id']
@@ -110,8 +108,8 @@ def do_hashmap_field_delete(cc, args={}):
"""Delete a field."""
try:
cc.hashmap.fields.delete(field_id=args.field_id)
except exceptions.NotFound:
raise exc.CommandError('Field not found: %s' % args.field_id)
except exc.HTTPNotFound:
raise exc.CommandError('Field not found: %s' % args.counter_name)
def common_hashmap_mapping_arguments(create=False):
@@ -128,9 +126,6 @@ def common_hashmap_mapping_arguments(create=False):
@utils.arg('-g', '--group-id',
help='Group id',
required=False)
@utils.arg('-p', '--project-id',
help='Project/tenant id',
required=False)
@functools.wraps(func)
def _wrapped(*args, **kwargs):
return func(*args, **kwargs)
@@ -154,7 +149,6 @@ def do_hashmap_mapping_create(cc, args={}):
'service_id': 'service_id',
'field_id': 'field_id',
'group_id': 'group_id',
'project_id': 'tenant_id',
}
fields = {}
for k, v in vars(args).items():
@@ -177,12 +171,11 @@ def do_hashmap_mapping_update(cc, args={}):
'value': 'value',
'type': 'type',
'group_id': 'group_id',
'project_id': 'tenant_id',
}
try:
mapping = cc.hashmap.mappings.get(mapping_id=args.mapping_id)
except exceptions.NotFound:
raise exc.CommandError('Mapping not found: %s' % args.mapping_id)
except exc.HTTPNotFound:
raise exc.CommandError('Modules not found: %s' % args.counter_name)
for k, v in vars(args).items():
if k in arg_to_field_mapping:
if v is not None:
@@ -199,29 +192,23 @@ def do_hashmap_mapping_update(cc, args={}):
@utils.arg('-g', '--group-id',
help='Group id',
required=False)
@utils.arg('-p', '--project-id',
help='Project/tenant id',
required=False)
def do_hashmap_mapping_list(cc, args={}):
"""List mappings."""
if (args.group_id is None and
args.service_id is None and args.field_id is None):
raise exc.CommandError("Provide either group-id, service-id or "
"field-id")
if args.service_id is None and args.field_id is None:
raise exc.CommandError("Provide either service-id or field-id")
try:
mappings = cc.hashmap.mappings.list(service_id=args.service_id,
field_id=args.field_id,
group_id=args.group_id)
except exceptions.NotFound:
raise exc.CommandError('Mappings not found for field: %s'
% args.field_id)
except exc.HTTPNotFound:
raise exc.CommandError('Mapping not found: %s' % args.counter_name)
else:
field_labels = ['Mapping id', 'Value', 'Cost',
'Type', 'Field id',
'Service id', 'Group id', 'Tenant id']
'Service id', 'Group id']
fields = ['mapping_id', 'value', 'cost',
'type', 'field_id',
'service_id', 'group_id', 'tenant_id']
'service_id', 'group_id']
utils.print_list(mappings, fields, field_labels,
sortby=0)
@@ -233,7 +220,7 @@ def do_hashmap_mapping_delete(cc, args={}):
"""Delete a mapping."""
try:
cc.hashmap.mappings.delete(mapping_id=args.mapping_id)
except exceptions.NotFound:
except exc.HTTPNotFound:
raise exc.CommandError('Mapping not found: %s' % args.mapping_id)
@@ -258,8 +245,8 @@ def do_hashmap_group_list(cc, args={}):
"""List groups."""
try:
groups = cc.hashmap.groups.list()
except exceptions.NotFound:
raise exc.CommandError('Groups not found.')
except exc.HTTPNotFound:
raise exc.CommandError('Mapping not found: %s' % args.counter_name)
else:
field_labels = ['Name',
'Group id']
@@ -280,7 +267,7 @@ def do_hashmap_group_delete(cc, args={}):
try:
cc.hashmap.groups.delete(group_id=args.group_id,
recursive=args.recursive)
except exceptions.NotFound:
except exc.HTTPNotFound:
raise exc.CommandError('Group not found: %s' % args.group_id)
@@ -292,15 +279,12 @@ def common_hashmap_threshold_arguments(create=False):
@utils.arg('-c', '--cost',
help='Threshold cost',
required=create)
@utils.arg('-t', '--type',
@utils.arg('-m', '--map-type',
help='Threshold type (flat, rate)',
required=False)
@utils.arg('-g', '--group-id',
help='Group id',
required=False)
@utils.arg('-p', '--project-id',
help='Project/tenant id',
required=False)
@functools.wraps(func)
def _wrapped(*args, **kwargs):
return func(*args, **kwargs)
@@ -320,11 +304,10 @@ def do_hashmap_threshold_create(cc, args={}):
arg_to_field_mapping = {
'level': 'level',
'cost': 'cost',
'type': 'type',
'map_type': 'map_type',
'service_id': 'service_id',
'field_id': 'field_id',
'group_id': 'group_id',
'project_id': 'tenant_id',
}
fields = {}
for k, v in vars(args).items():
@@ -335,7 +318,7 @@ def do_hashmap_threshold_create(cc, args={}):
utils.print_dict(out.to_dict())
@utils.arg('-i', '--threshold-id',
@utils.arg('-t', '--threshold-id',
help='Threshold id',
required=True)
@common_hashmap_threshold_arguments()
@@ -345,14 +328,13 @@ def do_hashmap_threshold_update(cc, args={}):
'threshold_id': 'threshold_id',
'cost': 'cost',
'level': 'level',
'type': 'type',
'map_type': 'map_type',
'group_id': 'group_id',
'project_id': 'tenant_id',
}
try:
threshold = cc.hashmap.thresholds.get(threshold_id=args.threshold_id)
except exceptions.NotFound:
raise exc.CommandError('Threshold not found: %s' % args.threshold_id)
except exc.HTTPNotFound:
raise exc.CommandError('Modules not found: %s' % args.counter_name)
for k, v in vars(args).items():
if k in arg_to_field_mapping:
if v is not None:
@@ -373,9 +355,6 @@ def do_hashmap_threshold_update(cc, args={}):
type=_bool_strict, metavar='{True,False}',
help='If True, list only orhpaned thresholds',
required=False)
@utils.arg('-p', '--project-id',
help='Project/tenant id',
required=False)
def do_hashmap_threshold_list(cc, args={}):
"""List thresholds."""
if (args.group_id is None and
@@ -387,48 +366,48 @@ def do_hashmap_threshold_list(cc, args={}):
field_id=args.field_id,
group_id=args.group_id,
no_group=args.no_group)
except exceptions.NotFound:
raise exc.CommandError('Thresholds not found')
except exc.HTTPNotFound:
raise exc.CommandError('Threshold not found: %s' % args.counter_name)
else:
field_labels = ['Threshold id', 'Level', 'Cost',
'Type', 'Field id',
'Service id', 'Group id', 'Tenant id']
'Service id', 'Group id']
fields = ['threshold_id', 'level', 'cost',
'type', 'field_id',
'service_id', 'group_id', 'tenant_id']
'map_type', 'field_id',
'service_id', 'group_id']
utils.print_list(thresholds, fields, field_labels, sortby=0)
@utils.arg('-i', '--threshold-id',
@utils.arg('-t', '--threshold-id',
help='Threshold uuid',
required=True)
def do_hashmap_threshold_delete(cc, args={}):
"""Delete a threshold."""
try:
cc.hashmap.thresholds.delete(threshold_id=args.threshold_id)
except exceptions.NotFound:
except exc.HTTPNotFound:
raise exc.CommandError('Threshold not found: %s' % args.threshold_id)
@utils.arg('-i', '--threshold-id',
@utils.arg('-t', '--threshold-id',
help='Threshold uuid',
required=True)
def do_hashmap_threshold_get(cc, args={}):
"""Get a threshold."""
try:
threshold = cc.hashmap.thresholds.get(threshold_id=args.threshold_id)
except exceptions.NotFound:
except exc.HTTPNotFound:
raise exc.CommandError('Threshold not found: %s' % args.threshold_id)
utils.print_dict(threshold.to_dict())
@utils.arg('-i', '--threshold-id',
@utils.arg('-t', '--threshold-id',
help='Threshold uuid',
required=True)
def do_hashmap_threshold_group(cc, args={}):
"""Get a threshold group."""
try:
threshold = cc.hashmap.thresholds.group(threshold_id=args.threshold_id)
except exceptions.NotFound:
except exc.HTTPNotFound:
raise exc.CommandError('Threshold not found: %s' % args.threshold_id)
utils.print_dict(threshold.to_dict())

View File

@@ -1,355 +0,0 @@
# 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)

View File

@@ -17,7 +17,6 @@ import functools
from oslo_utils import strutils
import six
from cloudkittyclient.apiclient import exceptions
from cloudkittyclient.common import utils
from cloudkittyclient import exc
@@ -65,7 +64,7 @@ def do_pyscripts_script_get(cc, args={}):
"""Get script."""
try:
script = cc.pyscripts.scripts.get(script_id=args.script_id)
except exceptions.NotFound:
except exc.HTTPNotFound:
raise exc.CommandError('Script not found: %s' % args.script_id)
utils.print_dict(script.to_dict())
@@ -77,7 +76,7 @@ def do_pyscripts_script_get_data(cc, args={}):
"""Get script data."""
try:
script = cc.pyscripts.scripts.get(script_id=args.script_id)
except exceptions.NotFound:
except exc.HTTPNotFound:
raise exc.CommandError('Script not found: %s' % args.script_id)
six.print_(script.data)
@@ -89,8 +88,8 @@ def do_pyscripts_script_delete(cc, args={}):
"""Delete a script."""
try:
cc.pyscripts.scripts.delete(script_id=args.script_id)
except exceptions.NotFound:
raise exc.CommandError('Script not found: %s' % args.script_id)
except exc.HTTPNotFound:
raise exc.CommandError('Script not found: %s' % args.counter_name)
@utils.arg('-s', '--script-id',
@@ -108,7 +107,7 @@ def do_pyscripts_script_update(cc, args={}):
content = fp.read()
try:
script = cc.pyscripts.scripts.get(script_id=args.script_id)
except exceptions.NotFound:
except exc.HTTPNotFound:
raise exc.CommandError('Script not found: %s' % args.script_id)
script_dict = script.to_dict()
for field in excluded_fields:

View File

@@ -1,115 +0,0 @@
# 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)

View File

@@ -15,31 +15,22 @@
from cloudkittyclient.common import base
class ReportSummary(base.Resource):
class ReportResult(base.Resource):
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
key = 'report'
def __repr__(self):
return "<Summary %s" % self._info
return "<Report %s>" % self._info
class ReportManager(base.CrudManager):
class ReportManager(base.Manager):
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, all_tenants=False):
def get_total(self, tenant_id=None, begin=None, end=None, service=None):
url = self.base_url + "/total"
filters = list()
if tenant_id:
@@ -50,32 +41,6 @@ class ReportManager(base.CrudManager):
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)

View File

@@ -30,37 +30,6 @@ 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)
@@ -70,27 +39,12 @@ def do_total_get(cc, args):
@utils.arg('-s', '--service',
help='Service Type',
required=False)
@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."""
def do_total_get(cc, args):
"""Get total reports."""
begin = utils.ts2dt(args.begin) if args.begin else None
end = utils.ts2dt(args.end) if args.end else None
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)
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})

View File

@@ -1,88 +0,0 @@
# 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)

View File

@@ -13,7 +13,6 @@
# 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
@@ -22,11 +21,11 @@ def do_module_list(cc, args):
'''List the samples for this meters.'''
try:
modules = cc.modules.list()
except exceptions.NotFound:
raise exc.CommandError('Modules not found')
except exc.HTTPNotFound:
raise exc.CommandError('Modules not found: %s' % args.counter_name)
else:
field_labels = ['Module', 'Enabled', 'Priority']
fields = ['module_id', 'enabled', 'priority']
field_labels = ['Module', 'Enabled']
fields = ['module_id', 'enabled']
utils.print_list(modules, fields, field_labels,
sortby=0)
@@ -39,11 +38,11 @@ def do_module_enable(cc, args):
try:
module = cc.modules.get(module_id=args.name)
module.enable()
except exceptions.NotFound:
raise exc.CommandError('Module not found: %s' % args.name)
except exc.HTTPNotFound:
raise exc.CommandError('Modules not found: %s' % args.counter_name)
else:
field_labels = ['Module', 'Enabled', 'Priority']
fields = ['module_id', 'enabled', 'priority']
field_labels = ['Module', 'Enabled']
fields = ['module_id', 'enabled']
modules = [cc.modules.get(module_id=args.name)]
utils.print_list(modules, fields, field_labels,
sortby=0)
@@ -57,58 +56,11 @@ def do_module_disable(cc, args):
try:
module = cc.modules.get(module_id=args.name)
module.disable()
except exceptions.NotFound:
raise exc.CommandError('Module not found: %s' % args.name)
except exc.HTTPNotFound:
raise exc.CommandError('Modules not found: %s' % args.counter_name)
else:
field_labels = ['Module', 'Enabled', 'Priority']
fields = ['module_id', 'enabled', 'priority']
field_labels = ['Module', 'Enabled']
fields = ['module_id', 'enabled']
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)

View File

@@ -1,91 +0,0 @@
# 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)

View File

@@ -17,17 +17,17 @@
from cloudkittyclient.common import utils
@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',
@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',
help='Tenant ID',
required=False,
default=None)
@utils.arg('-r', '--resource-type',
@utils.arg('--resource-type',
help='Resource type (compute, image, ...)',
required=False,
default=None)

View File

@@ -1,44 +0,0 @@
# 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)

View File

@@ -0,0 +1,42 @@
Name: python-cloudkittyclient
Version: @VERSION@
Release: 1%{?dist}
Summary: Client library for CloudKitty
License: ASL 2.0
Source: %{name}-%{version}.tar.gz
BuildArch: noarch
BuildRequires: python-setuptools
BuildRequires: python-pbr
BuildRequires: python-keystoneclient
BuildRequires: python-stevedore
BuildRequires: python-babel
Requires: python-keystoneclient
Requires: python-stevedore
Requires: python-babel
%description
Client library for CloudKitty
%prep
%setup -q
%build
%{__python} setup.py build
%install
%{__python} setup.py install -O1 --skip-build --root %{buildroot}
#export PYTHONPATH="$( pwd ):$PYTHONPATH"
#sphinx-build -b html doc/source html
%files
%{_bindir}/*
%{python_sitelib}/*
#%doc html
%changelog
* Sun Apr 19 2015 Gauvain Pocentek <gauvain.pocentek@objectif-libre.com> @VERSION@-1
- Initial release

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

@@ -1,3 +1,4 @@
# -*- 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

8
openstack-common.conf Normal file
View File

@@ -0,0 +1,8 @@
[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

View File

@@ -3,11 +3,9 @@
# process, which may cause wedges in the gate later.
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
Babel>=1.3 # BSD
python-keystoneclient!=1.8.0,!=2.1.0,>=1.6.0 # Apache-2.0
stevedore>=1.5.0 # Apache-2.0
oslo.i18n>=2.1.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
oslo.utils>=3.11.0 # Apache-2.0
PrettyTable<0.8,>=0.7 # BSD
oslo.utils>=3.5.0 # Apache-2.0

View File

@@ -30,59 +30,6 @@ 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

View File

@@ -5,6 +5,7 @@
hacking<0.10,>=0.9.2
coverage>=3.6 # Apache-2.0
discover # BSD
python-subunit>=0.0.18 # Apache-2.0/BSD
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD
oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0

10
tox.ini
View File

@@ -5,16 +5,13 @@ skipsdist = True
[testenv]
usedevelop = True
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -U {opts} {packages}
install_command = pip install -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
@@ -28,12 +25,13 @@ 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
ignore = E123,E125,H803
builtins = _
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build
[hacking]
import_exceptions = cloudkittyclient.i18n