CLI for resource classes (v1.2)
Set method was skipped due to two reason that from version 1.7 it is not allowed to rename resource classes. Change-Id: Id18aab2a95849bc60769f2f81c363c17d049b21f
This commit is contained in:
parent
4a0aa464fd
commit
73aaab7a02
|
@ -23,7 +23,8 @@ API_NAME = 'placement'
|
|||
API_VERSION_OPTION = 'os_placement_api_version'
|
||||
SUPPORTED_VERSIONS = [
|
||||
'1.0',
|
||||
'1.1'
|
||||
'1.1',
|
||||
'1.2'
|
||||
]
|
||||
API_VERSIONS = {v: 'osc_placement.http.SessionClient'
|
||||
for v in SUPPORTED_VERSIONS}
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
# 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 osc_lib import utils
|
||||
|
||||
from osc_placement import version
|
||||
|
||||
|
||||
BASE_URL = '/resource_classes'
|
||||
PER_CLASS_URL = BASE_URL + '/{name}'
|
||||
FIELDS = ('name',)
|
||||
|
||||
|
||||
class ListResourceClass(command.Lister):
|
||||
|
||||
"""Return a list of all resource classes.
|
||||
|
||||
This command requires at least --os-placement-api-version 1.2.
|
||||
"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListResourceClass, self).get_parser(prog_name)
|
||||
|
||||
return parser
|
||||
|
||||
@version.check(version.ge('1.2'))
|
||||
def take_action(self, parsed_args):
|
||||
http = self.app.client_manager.placement
|
||||
|
||||
resource_classes = http.request(
|
||||
'GET', BASE_URL).json()['resource_classes']
|
||||
rows = (utils.get_dict_properties(i, FIELDS) for i in resource_classes)
|
||||
return FIELDS, rows
|
||||
|
||||
|
||||
class CreateResourceClass(command.Command):
|
||||
|
||||
"""Create a new resource class.
|
||||
|
||||
This command requires at least --os-placement-api-version 1.2.
|
||||
"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateResourceClass, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'name',
|
||||
metavar='<name>',
|
||||
help='Name of the resource class'
|
||||
)
|
||||
return parser
|
||||
|
||||
@version.check(version.ge('1.2'))
|
||||
def take_action(self, parsed_args):
|
||||
http = self.app.client_manager.placement
|
||||
|
||||
http.request('POST', BASE_URL, json={'name': parsed_args.name})
|
||||
|
||||
|
||||
class ShowResourceClass(command.ShowOne):
|
||||
|
||||
"""Return a representation of the resource class identified by {name}.
|
||||
|
||||
This command requires at least --os-placement-api-version 1.2.
|
||||
"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowResourceClass, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'name',
|
||||
metavar='<name>',
|
||||
help='Name of the resource class'
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
@version.check(version.ge('1.2'))
|
||||
def take_action(self, parsed_args):
|
||||
http = self.app.client_manager.placement
|
||||
|
||||
url = PER_CLASS_URL.format(name=parsed_args.name)
|
||||
|
||||
resource = http.request('GET', url).json()
|
||||
return FIELDS, utils.get_dict_properties(resource, FIELDS)
|
||||
|
||||
|
||||
class DeleteResourceClass(command.Command):
|
||||
|
||||
"""Delete the resource class identified by {name}.
|
||||
|
||||
Only custom resource classes can be deleted.
|
||||
|
||||
This command requires at least --os-placement-api-version 1.2.
|
||||
"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteResourceClass, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'name',
|
||||
metavar='<name>',
|
||||
help='Name of the resource class'
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
@version.check(version.ge('1.2'))
|
||||
def take_action(self, parsed_args):
|
||||
http = self.app.client_manager.placement
|
||||
|
||||
url = PER_CLASS_URL.format(name=parsed_args.name)
|
||||
|
||||
http.request('DELETE', url)
|
|
@ -171,3 +171,15 @@ class BaseTestCase(base.BaseTestCase):
|
|||
cmd += ' '.join('--aggregate %s' % aggregate
|
||||
for aggregate in aggregates)
|
||||
return self.openstack(cmd, use_json=True)
|
||||
|
||||
def resource_class_list(self):
|
||||
return self.openstack('resource class list', use_json=True)
|
||||
|
||||
def resource_class_show(self, name):
|
||||
return self.openstack('resource class show ' + name, use_json=True)
|
||||
|
||||
def resource_class_create(self, name):
|
||||
return self.openstack('resource class create ' + name)
|
||||
|
||||
def resource_class_delete(self, name):
|
||||
return self.openstack('resource class delete ' + name)
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
# 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_placement.tests.functional import base
|
||||
|
||||
|
||||
class TestResourceClass(base.BaseTestCase):
|
||||
VERSION = '1.2'
|
||||
|
||||
def test_list(self):
|
||||
rcs = self.resource_class_list()
|
||||
names = [rc['name'] for rc in rcs]
|
||||
self.assertIn('VCPU', names)
|
||||
self.assertIn('MEMORY_MB', names)
|
||||
self.assertIn('DISK_GB', names)
|
||||
|
||||
def test_fail_create_if_incorrect_class(self):
|
||||
self.assertCommandFailed('JSON does not validate',
|
||||
self.resource_class_create, 'fake_class')
|
||||
self.assertCommandFailed('JSON does not validate',
|
||||
self.resource_class_create, 'CUSTOM_lower')
|
||||
self.assertCommandFailed('JSON does not validate',
|
||||
self.resource_class_create,
|
||||
'CUSTOM_GPU.INTEL')
|
||||
|
||||
def test_create(self):
|
||||
self.resource_class_create('CUSTOM_GPU_DEVICE')
|
||||
rcs = self.resource_class_list()
|
||||
names = [rc['name'] for rc in rcs]
|
||||
self.assertIn('CUSTOM_GPU_DEVICE', names)
|
||||
self.resource_class_delete('CUSTOM_GPU_DEVICE')
|
||||
|
||||
def test_fail_show_if_unknown_class(self):
|
||||
self.assertCommandFailed('No such resource class',
|
||||
self.resource_class_show, 'UNKNOWN')
|
||||
|
||||
def test_show(self):
|
||||
rc = self.resource_class_show('VCPU')
|
||||
self.assertEqual('VCPU', rc['name'])
|
||||
|
||||
def test_fail_delete_unknown_class(self):
|
||||
self.assertCommandFailed('No such resource class',
|
||||
self.resource_class_delete, 'UNKNOWN')
|
||||
|
||||
def test_fail_delete_standard_class(self):
|
||||
self.assertCommandFailed('Cannot delete standard resource class',
|
||||
self.resource_class_delete, 'VCPU')
|
|
@ -43,6 +43,10 @@ openstack.placement.v1 =
|
|||
resource_provider_inventory_delete = osc_placement.resources.inventory:DeleteInventory
|
||||
resource_provider_aggregate_list = osc_placement.resources.aggregate:ListAggregate
|
||||
resource_provider_aggregate_set = osc_placement.resources.aggregate:SetAggregate
|
||||
resource_class_list = osc_placement.resources.resource_class:ListResourceClass
|
||||
resource_class_create = osc_placement.resources.resource_class:CreateResourceClass
|
||||
resource_class_show = osc_placement.resources.resource_class:ShowResourceClass
|
||||
resource_class_delete = osc_placement.resources.resource_class:DeleteResourceClass
|
||||
|
||||
[build_sphinx]
|
||||
source-dir = doc/source
|
||||
|
|
Loading…
Reference in New Issue