Implement quota-class management commands for KB.

"quota-class show"  List the quotas for a quota class.
"quota-class update"  Update quotas for a quota class.
"quota-class delete"  Delete quotas for a quota-class.
Add test-cases for the same.
Depends-on: I7c3f809afcf65077701e320fc97135a3c21c7786

Change-Id: I182ef0d84d5fbcca2b443b14d8f4bd6d42735659
This commit is contained in:
Goutham Pratapa 2017-01-03 14:40:46 +05:30
parent f57144cfcb
commit 3333a3c6be
6 changed files with 357 additions and 0 deletions

View File

@ -50,6 +50,20 @@ class ResourceManager(object):
resource = self._generate_resource(json_response_key)
return resource
def _update(self, url, data):
data = json.dumps(data)
resp = self.http_client.put(url, data)
if resp.status_code != 200:
self._raise_api_exception(resp)
json_response_key = get_json(resp)
result = self._generate_resource(json_response_key)
return result
def _delete(self, url):
resp = self.http_client.delete(url)
if resp.status_code != 200:
self._raise_api_exception(resp)
def _raise_api_exception(self, resp):
error_data = resp.content
raise exceptions.APIException(error_code=resp.status_code,

View File

@ -19,6 +19,7 @@ import six
import osprofiler.profiler
from kingbirdclient.api import httpclient
from kingbirdclient.api.v1 import quota_class_manager as qcm
from kingbirdclient.api.v1 import quota_manager as qm
_DEFAULT_KINGBIRD_URL = "http://localhost:8118/v1.0"
@ -76,6 +77,7 @@ class Client(object):
# Create all resource managers
self.quota_manager = qm.quota_manager(self.http_client)
self.quota_class_manager = qcm.quota_class_manager(self.http_client)
def authenticate(kingbird_url=None, username=None,

View File

@ -0,0 +1,42 @@
# Copyright (c) 2017 Ericsson AB.
#
# 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 kingbirdclient.api import base
class QuotaClass(base.Resource):
resource_name = 'os-quota-class-sets'
class quota_class_manager(base.ResourceManager):
resource_class = QuotaClass
def list_quota_class(self, quota_class):
tenant = self.http_client.project_id
url = '/%s/os-quota-class-sets/%s' % (tenant, quota_class)
return self._list(url)
def quota_class_update(self, quota_class, **kwargs):
if kwargs:
data = dict()
data['quota_class_set'] = {
k: int(v) for k, v in kwargs.items() if v is not None}
tenant = self.http_client.project_id
url = '/%s/os-quota-class-sets/%s' % (tenant, quota_class)
return self._update(url, data)
def delete_quota_class(self, quota_class):
tenant = self.http_client.project_id
url = '/%s/os-quota-class-sets/%s' % (tenant, quota_class)
return self._delete(url)

View File

@ -0,0 +1,229 @@
# Copyright (c) 2017 Ericsson AB.
#
# 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 kingbirdclient.commands.v1 import base
from kingbirdclient import exceptions
def format(quotas=None):
columns = (
'Quota',
'Limit'
)
if quotas:
data = (
quotas._data,
quotas._values,
)
else:
data = (tuple('<none>' for _ in range(len(columns))),)
return columns, data
class ListQuotaClass(base.KingbirdLister):
"""List the quotas for a quota class."""
def _get_format_function(self):
return format
def get_parser(self, parsed_args):
parser = super(ListQuotaClass, self).get_parser(parsed_args)
parser.add_argument(
'quota_class',
help='Name of quota class to list the quotas.'
)
return parser
def _get_resources(self, parsed_args):
kingbird_client = self.app.client_manager.sync_engine
quota_class = parsed_args.quota_class
return kingbird_client.quota_class_manager.\
list_quota_class(quota_class)
class UpdateQuotaClass(base.KingbirdLister):
"""Update quotas for a quota class."""
def _get_format_function(self):
return format
def get_parser(self, parsed_args):
parser = super(UpdateQuotaClass, self).get_parser(parsed_args)
parser.add_argument(
'quota_class',
help='Name of quota class to update the quotas.'
)
parser.add_argument(
'--metadata_items',
help='New value for the "metadata-items" quota'
)
parser.add_argument(
'--subnet',
help='New value for the "subnet" quota'
)
parser.add_argument(
'--network',
help='New value for the "network" quota'
)
parser.add_argument(
'--floatingip',
help='New value for the "floatingip" quota'
)
parser.add_argument(
'--gigabytes',
help='New value for the "gigabytes" quota'
)
parser.add_argument(
'--backup_gigabytes',
help='New value for the "backup_gigabytes" quota'
)
parser.add_argument(
'--ram',
help='New value for the "ram" quota'
)
parser.add_argument(
'--floating_ips',
help='New value for the "floating_ips" quota'
)
parser.add_argument(
'--snapshots',
help='New value for the "snapshots" quota'
)
parser.add_argument(
'--security_group_rule',
help='New value for the "security_group_rule" quota'
)
parser.add_argument(
'--instances',
help='New value for the "instances" quota'
)
parser.add_argument(
'--key_pairs',
help='New value for the "key_pairs" quota'
)
parser.add_argument(
'--volumes',
help='New value for the "volumes" quota'
)
parser.add_argument(
'--router',
help='New value for the "router" quota'
)
parser.add_argument(
'--security_group',
help='New value for the "security_group" quota'
)
parser.add_argument(
'--cores',
help='New value for the "cores" quota'
)
parser.add_argument(
'--backups',
help='New value for the "backups" quota'
)
parser.add_argument(
'--fixed_ips',
help='New value for the "fixed_ips" quota'
)
parser.add_argument(
'--port',
help='New value for the "port" quota'
)
parser.add_argument(
'--security_groups',
help='New value for the "security_groups" quota'
)
return parser
def _get_resources(self, parsed_args):
quota_class = parsed_args.quota_class
kingbird_client = self.app.client_manager.sync_engine
kwargs = {
"metadata_items": parsed_args.metadata_items,
"subnet": parsed_args.subnet,
"network": parsed_args.network,
"floatingip": parsed_args.floatingip,
"gigabytes": parsed_args.gigabytes,
"backup_gigabytes": parsed_args.backup_gigabytes,
"ram": parsed_args.ram,
"floating_ips": parsed_args.floating_ips,
"snapshots": parsed_args.snapshots,
"security_group_rule": parsed_args.security_group_rule,
"instances": parsed_args.instances,
"key_pairs": parsed_args.key_pairs,
"volumes": parsed_args.volumes,
"router": parsed_args.router,
"security_group": parsed_args.security_group,
"cores": parsed_args.cores,
"backups": parsed_args.backups,
"fixed_ips": parsed_args.fixed_ips,
"port": parsed_args.port,
"security_groups": parsed_args.security_groups
}
return kingbird_client.quota_class_manager.\
quota_class_update(quota_class, **kwargs)
class DeleteQuotaClass(command.Command):
"""Delete quotas for a quota-class."""
def get_parser(self, prog_name):
parser = super(DeleteQuotaClass, self).get_parser(prog_name)
parser.add_argument(
'quota_class',
help='Name of quota class to delete quotas.'
)
return parser
def take_action(self, parsed_args):
kingbird_client = self.app.client_manager.sync_engine
quota_class = parsed_args.quota_class
try:
kingbird_client.quota_class_manager.\
delete_quota_class(quota_class)
print("Request to delete %s quota_class has been accepted." %
(parsed_args.quota_class))
except Exception as e:
print(e)
error_msg = "Unable to delete the specified quota_class."
raise exceptions.KingbirdClientException(error_msg)

View File

@ -29,6 +29,7 @@ from cliff import commandmanager
from osc_lib.command import command
import argparse
from kingbirdclient.commands.v1 import quota_class_manager as qcm
from kingbirdclient.commands.v1 import quota_manager as qm
LOG = logging.getLogger(__name__)
@ -395,6 +396,9 @@ class KingbirdShell(app.App):
'bash-completion': BashCompletionCommand,
'quota defaults': qm.ListDefaults,
'quota show': qm.GlobalLimits,
'quota-class show': qcm.ListQuotaClass,
'quota-class update': qcm.UpdateQuotaClass,
'quota-class delete': qcm.DeleteQuotaClass,
}

View File

@ -0,0 +1,66 @@
# Copyright (c) 2017 Ericsson AB.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import mock
from kingbirdclient.api.v1 import quota_class_manager as qcm
from kingbirdclient.commands.v1 import quota_class_manager as quota_class_cmd
from kingbirdclient.tests import base
QUOTAS_DICT = {
'Quota': 'fake_item',
'Limit': '123'
}
CLASS_NAME = 'default'
QUOTACLASSMANAGER = qcm.QuotaClass(mock, QUOTAS_DICT['Quota'],
QUOTAS_DICT['Limit'])
class TestCLIQuotaClassManagerV1(base.BaseCommandTest):
def test_list_quota_class(self):
self.client.quota_class_manager.\
list_quota_class.return_value = [QUOTACLASSMANAGER]
actual_quota = self.call(quota_class_cmd.ListQuotaClass,
app_args=[CLASS_NAME])
self.assertEqual([('fake_item', '123')], actual_quota[1])
def test_negative_list_quota_class(self):
self.client.quota_class_manager.\
list_quota_class.return_value = []
actual_quota = self.call(quota_class_cmd.ListQuotaClass,
app_args=[CLASS_NAME])
self.assertEqual((('<none>', '<none>'),), actual_quota[1])
def test_update_quota_class(self):
self.client.quota_class_manager.\
quota_class_update.return_value = [QUOTACLASSMANAGER]
actual_quota = self.call(quota_class_cmd.UpdateQuotaClass,
app_args=[CLASS_NAME, '--ram', '51200'])
self.assertEqual([('fake_item', '123')], actual_quota[1])
def test_negative_update_quota_class(self):
self.client.quota_class_manager.\
quota_class_update.return_value = []
actual_quota = self.call(quota_class_cmd.UpdateQuotaClass,
app_args=[CLASS_NAME, '--ram', '51200'])
self.assertEqual((('<none>', '<none>'),), actual_quota[1])
def test_delete_quota_class(self):
self.call(quota_class_cmd.DeleteQuotaClass,
app_args=[CLASS_NAME])
self.client.quota_class_manager.delete_quota_class.\
assert_called_once_with(CLASS_NAME)