Implement etcd API for ResourceClass
Porposed change of this commit is: 1.Add etcd db model and implements etcd API for ResourceClass. 2.Add 'uuid' field into ResourceClass. Part of blueprint expose-host-capabilities Change-Id: I9e5678e8742fd4c6a26b9ced6d6eccd6b7976363
This commit is contained in:
parent
3a84375531
commit
cf1ad08b0f
@ -366,34 +366,34 @@ def get_resource_class(context, resource_ident):
|
||||
"""Return a resource class.
|
||||
|
||||
:param context: The security context
|
||||
:param resource_ident: The id or name of a resource class.
|
||||
:param resource_ident: The uuid or name of a resource class.
|
||||
:returns: A resource class.
|
||||
"""
|
||||
return _get_dbdriver_instance().get_resource_class(
|
||||
context, resource_ident)
|
||||
|
||||
|
||||
def destroy_resource_class(context, resource_id):
|
||||
def destroy_resource_class(context, resource_uuid):
|
||||
"""Destroy a resource class and all associated interfaces.
|
||||
|
||||
:param context: Request context
|
||||
:param resource_id: The id of a resource class.
|
||||
:param resource_uuid: The uuid of a resource class.
|
||||
"""
|
||||
return _get_dbdriver_instance().destroy_resource_class(
|
||||
context, resource_id)
|
||||
context, resource_uuid)
|
||||
|
||||
|
||||
def update_resource_class(context, resource_id, values):
|
||||
def update_resource_class(context, resource_uuid, values):
|
||||
"""Update properties of a resource class.
|
||||
|
||||
:context: Request context
|
||||
:param resource_id: The id of a resource class.
|
||||
:param resource_uuid: The uuid of a resource class.
|
||||
:values: The properties to be updated
|
||||
:returns: A resource class.
|
||||
:raises: ResourceClassNotFound
|
||||
"""
|
||||
return _get_dbdriver_instance().update_resource_class(
|
||||
context, resource_id, values)
|
||||
context, resource_uuid, values)
|
||||
|
||||
|
||||
def list_inventories(context, filters=None, limit=None, marker=None,
|
||||
|
@ -76,6 +76,8 @@ def translate_etcd_result(etcd_result, model_type):
|
||||
ret = models.ZunService(data)
|
||||
elif model_type == 'image':
|
||||
ret = models.Image(data)
|
||||
elif model_type == 'resource_class':
|
||||
ret = models.ResourceClass(data)
|
||||
else:
|
||||
raise exception.InvalidParameterValue(
|
||||
_('The model_type value: %s is invalid.'), model_type)
|
||||
@ -436,3 +438,100 @@ class EtcdAPI(object):
|
||||
if len(images) == 0:
|
||||
return None
|
||||
return images[0]
|
||||
|
||||
def list_resource_classes(self, context, filters=None, limit=None,
|
||||
marker=None, sort_key=None, sort_dir=None):
|
||||
try:
|
||||
res = getattr(self.client.read('/resource_classes'),
|
||||
'children', None)
|
||||
except etcd.EtcdKeyNotFound:
|
||||
return []
|
||||
except Exception as e:
|
||||
LOG.error(
|
||||
_LE('Error occurred while reading from etcd server: %s'),
|
||||
six.text_type(e))
|
||||
raise
|
||||
|
||||
resource_classes = []
|
||||
for r in res:
|
||||
if r.value is not None:
|
||||
resource_classes.append(
|
||||
translate_etcd_result(r, 'resource_class'))
|
||||
|
||||
if filters:
|
||||
resource_classes = self._filter_resources(
|
||||
resource_classes, filters)
|
||||
|
||||
return self._process_list_result(
|
||||
resource_classes, limit=limit, sort_key=sort_key)
|
||||
|
||||
@lockutils.synchronized('etcd_resource_class')
|
||||
def create_resource_class(self, context, values):
|
||||
resource_class = models.ResourceClass(values)
|
||||
resource_class.save()
|
||||
return resource_class
|
||||
|
||||
def get_resource_class(self, context, ident):
|
||||
if uuidutils.is_uuid_like(ident):
|
||||
return self._get_resource_class_by_uuid(context, ident)
|
||||
else:
|
||||
return self._get_resource_class_by_name(context, ident)
|
||||
|
||||
def _get_resource_class_by_uuid(self, context, uuid):
|
||||
try:
|
||||
resource_class = None
|
||||
res = self.client.read('/resource_classes/' + uuid)
|
||||
resource_class = translate_etcd_result(res, 'resource_class')
|
||||
except etcd.EtcdKeyNotFound:
|
||||
raise exception.ResourceClassNotFound(resource_class=uuid)
|
||||
except Exception as e:
|
||||
LOG.error(
|
||||
_LE('Error occurred while retriving resource class: %s'),
|
||||
six.text_type(e))
|
||||
raise
|
||||
return resource_class
|
||||
|
||||
def _get_resource_class_by_name(self, context, name):
|
||||
try:
|
||||
rcs = self.list_resource_classes(
|
||||
context, filters={'name': name})
|
||||
except etcd.EtcdKeyNotFound:
|
||||
raise exception.ResourceClassNotFound(resource_class=name)
|
||||
except Exception as e:
|
||||
LOG.error(
|
||||
_LE('Error occurred while retriving resource class: %s'),
|
||||
six.text_type(e))
|
||||
raise
|
||||
|
||||
if len(rcs) > 1:
|
||||
raise exception.Conflict('Multiple resource classes exist with '
|
||||
'same name. Please use uuid instead.')
|
||||
elif len(rcs) == 0:
|
||||
raise exception.ResourceClassNotFound(resource_class=name)
|
||||
|
||||
return rcs[0]
|
||||
|
||||
@lockutils.synchronized('etcd_resource_class')
|
||||
def destroy_resource_class(self, context, uuid):
|
||||
resource_class = self._get_resource_class_by_uuid(context, uuid)
|
||||
self.client.delete('/resource_classes/' + resource_class.uuid)
|
||||
|
||||
@lockutils.synchronized('etcd_resource_class')
|
||||
def update_resource_class(self, context, uuid, values):
|
||||
if 'uuid' in values:
|
||||
msg = _("Cannot override UUID for an existing resource class.")
|
||||
raise exception.InvalidParameterValue(err=msg)
|
||||
try:
|
||||
target = self.client.read('/resource_classes/' + uuid)
|
||||
target_value = json.loads(target.value)
|
||||
target_value.update(values)
|
||||
target.value = json.dumps(target_value)
|
||||
self.client.update(target)
|
||||
except etcd.EtcdKeyNotFound:
|
||||
raise exception.ResourceClassNotFound(resource_class=uuid)
|
||||
except Exception as e:
|
||||
LOG.error(
|
||||
_LE('Error occurred while updating resource class: %s'),
|
||||
six.text_type(e))
|
||||
raise
|
||||
return translate_etcd_result(target, 'resource_class')
|
||||
|
@ -154,3 +154,26 @@ class Image(Base):
|
||||
@classmethod
|
||||
def fields(cls):
|
||||
return cls._fields
|
||||
|
||||
|
||||
class ResourceClass(Base):
|
||||
"""Represents a resource class."""
|
||||
|
||||
_path = '/resource_classes'
|
||||
|
||||
_fields = objects.ResourceClass.fields.keys()
|
||||
|
||||
def __init__(self, resource_class_data):
|
||||
self.path = ResourceClass.path()
|
||||
for f in ResourceClass.fields():
|
||||
setattr(self, f, None)
|
||||
self.id = 1
|
||||
self.update(resource_class_data)
|
||||
|
||||
@classmethod
|
||||
def path(cls):
|
||||
return cls._path
|
||||
|
||||
@classmethod
|
||||
def fields(cls):
|
||||
return cls._fields
|
||||
|
@ -0,0 +1,36 @@
|
||||
# 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.
|
||||
|
||||
"""add uuid_to_resource_class
|
||||
|
||||
Revision ID: 8192905fd835
|
||||
Revises: e4d145e195f4
|
||||
Create Date: 2017-02-24 07:00:22.344162
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '8192905fd835'
|
||||
down_revision = 'e4d145e195f4'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('resource_class',
|
||||
sa.Column('uuid', sa.String(length=36), nullable=False))
|
||||
op.create_unique_constraint('uniq_resource_class0uuid',
|
||||
'resource_class', ['uuid'])
|
||||
op.drop_index('uniq_container0name', table_name='resource_class')
|
@ -472,23 +472,23 @@ class Connection(object):
|
||||
resource.save()
|
||||
except db_exc.DBDuplicateEntry:
|
||||
raise exception.ResourceClassAlreadyExists(
|
||||
field='name', value=values['name'])
|
||||
field='uuid', value=values['uuid'])
|
||||
return resource
|
||||
|
||||
def get_resource_class(self, context, resource_ident):
|
||||
if strutils.is_int_like(resource_ident):
|
||||
return self._get_resource_class_by_id(context, resource_ident)
|
||||
if uuidutils.is_uuid_like(resource_ident):
|
||||
return self._get_resource_class_by_uuid(context, resource_ident)
|
||||
else:
|
||||
return self._get_resource_class_by_name(context, resource_ident)
|
||||
|
||||
def _get_resource_class_by_id(self, context, resource_id):
|
||||
def _get_resource_class_by_uuid(self, context, resource_uuid):
|
||||
query = model_query(models.ResourceClass)
|
||||
query = query.filter_by(id=resource_id)
|
||||
query = query.filter_by(uuid=resource_uuid)
|
||||
try:
|
||||
return query.one()
|
||||
except NoResultFound:
|
||||
raise exception.ResourceClassNotFound(
|
||||
resource_class=resource_id)
|
||||
resource_class=resource_uuid)
|
||||
|
||||
def _get_resource_class_by_name(self, context, resource_name):
|
||||
query = model_query(models.ResourceClass)
|
||||
|
@ -194,10 +194,11 @@ class ResourceClass(Base):
|
||||
|
||||
__tablename__ = 'resource_class'
|
||||
__table_args__ = (
|
||||
schema.UniqueConstraint('name', name='uniq_resource_class0name'),
|
||||
schema.UniqueConstraint('uuid', name='uniq_resource_class0uuid'),
|
||||
table_args()
|
||||
)
|
||||
id = Column(Integer, primary_key=True, nullable=False)
|
||||
uuid = Column(String(36), nullable=False)
|
||||
name = Column(String(255), nullable=False)
|
||||
|
||||
|
||||
|
@ -20,10 +20,12 @@ from zun.objects import fields as z_fields
|
||||
@base.ZunObjectRegistry.register
|
||||
class ResourceClass(base.ZunPersistentObject, base.ZunObject):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
# Version 1.1: Add uuid field
|
||||
VERSION = '1.1'
|
||||
|
||||
fields = {
|
||||
'id': fields.IntegerField(read_only=True),
|
||||
'uuid': fields.UUIDField(nullable=False),
|
||||
'name': z_fields.ResourceClassField(nullable=False),
|
||||
}
|
||||
|
||||
@ -43,14 +45,14 @@ class ResourceClass(base.ZunPersistentObject, base.ZunObject):
|
||||
for obj in db_objects]
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_id(cls, context, rc_id):
|
||||
"""Find a resource class based on id.
|
||||
def get_by_uuid(cls, context, uuid):
|
||||
"""Find a resource class based on uuid.
|
||||
|
||||
:param rc_id: the id of a resource class.
|
||||
:param uuid: the uuid of a resource class.
|
||||
:param context: Security context
|
||||
:returns: a :class:`ResourceClass` object.
|
||||
"""
|
||||
db_resource = dbapi.get_resource_class(context, rc_id)
|
||||
db_resource = dbapi.get_resource_class(context, uuid)
|
||||
resource = ResourceClass._from_db_object(cls(context), db_resource)
|
||||
return resource
|
||||
|
||||
@ -112,7 +114,7 @@ class ResourceClass(base.ZunPersistentObject, base.ZunObject):
|
||||
A context should be set when instantiating the
|
||||
object, e.g.: ResourceClass(context)
|
||||
"""
|
||||
dbapi.destroy_resource_class(context, self.id)
|
||||
dbapi.destroy_resource_class(context, self.uuid)
|
||||
self.obj_reset_changes()
|
||||
|
||||
@base.remotable
|
||||
@ -130,7 +132,7 @@ class ResourceClass(base.ZunPersistentObject, base.ZunObject):
|
||||
object, e.g.: ResourceClass(context)
|
||||
"""
|
||||
updates = self.obj_get_changes()
|
||||
dbapi.update_resource_class(context, self.id, updates)
|
||||
dbapi.update_resource_class(context, self.uuid, updates)
|
||||
|
||||
self.obj_reset_changes()
|
||||
|
||||
@ -150,7 +152,7 @@ class ResourceClass(base.ZunPersistentObject, base.ZunObject):
|
||||
A context should be set when instantiating the
|
||||
object, e.g.: ResourceClass(context)
|
||||
"""
|
||||
current = self.__class__.get_by_id(self._context, rc_id=self.id)
|
||||
current = self.__class__.get_by_uuid(self._context, self.uuid)
|
||||
for field in self.fields:
|
||||
if self.obj_attr_is_set(field) and \
|
||||
getattr(self, field) != getattr(current, field):
|
||||
|
@ -11,8 +11,13 @@
|
||||
# under the License.
|
||||
|
||||
"""Tests for manipulating resource classes via the DB API"""
|
||||
import json
|
||||
import mock
|
||||
|
||||
import etcd
|
||||
from etcd import Client as etcd_client
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
import six
|
||||
|
||||
from zun.common import exception
|
||||
@ -20,6 +25,8 @@ import zun.conf
|
||||
from zun.db import api as dbapi
|
||||
from zun.tests.unit.db import base
|
||||
from zun.tests.unit.db import utils
|
||||
from zun.tests.unit.db.utils import FakeEtcdMultipleResult
|
||||
from zun.tests.unit.db.utils import FakeEtcdResult
|
||||
|
||||
CONF = zun.conf.CONF
|
||||
|
||||
@ -35,16 +42,16 @@ class DbResourceClassTestCase(base.DbTestCase):
|
||||
|
||||
def test_create_resource_class_already_exists(self):
|
||||
utils.create_test_resource_class(
|
||||
context=self.context, name='123')
|
||||
context=self.context, uuid='123')
|
||||
with self.assertRaisesRegexp(exception.ResourceClassAlreadyExists,
|
||||
'A resource class with name 123.*'):
|
||||
'A resource class with uuid 123.*'):
|
||||
utils.create_test_resource_class(
|
||||
context=self.context, name='123')
|
||||
context=self.context, uuid='123')
|
||||
|
||||
def test_get_resource_class_by_id(self):
|
||||
def test_get_resource_class_by_uuid(self):
|
||||
resource = utils.create_test_resource_class(context=self.context)
|
||||
res = dbapi.get_resource_class(self.context, resource.id)
|
||||
self.assertEqual(resource.id, res.id)
|
||||
res = dbapi.get_resource_class(self.context, resource.uuid)
|
||||
self.assertEqual(resource.uuid, res.uuid)
|
||||
self.assertEqual(resource.name, res.name)
|
||||
|
||||
def test_get_resource_class_by_name(self):
|
||||
@ -54,17 +61,16 @@ class DbResourceClassTestCase(base.DbTestCase):
|
||||
self.assertEqual(resource.name, res.name)
|
||||
|
||||
def test_get_resource_class_that_does_not_exist(self):
|
||||
bad_id = 1111111
|
||||
self.assertRaises(exception.ResourceClassNotFound,
|
||||
dbapi.get_resource_class,
|
||||
self.context,
|
||||
bad_id)
|
||||
self.context, uuidutils.generate_uuid())
|
||||
|
||||
def test_list_resource_classes(self):
|
||||
names = []
|
||||
for i in range(1, 6):
|
||||
resource = utils.create_test_resource_class(
|
||||
context=self.context,
|
||||
uuid=uuidutils.generate_uuid(),
|
||||
name='class'+str(i))
|
||||
names.append(six.text_type(resource['name']))
|
||||
res = dbapi.list_resource_classes(self.context)
|
||||
@ -76,6 +82,7 @@ class DbResourceClassTestCase(base.DbTestCase):
|
||||
for i in range(5):
|
||||
resource = utils.create_test_resource_class(
|
||||
context=self.context,
|
||||
uuid=uuidutils.generate_uuid(),
|
||||
name='class'+str(i))
|
||||
names.append(six.text_type(resource.name))
|
||||
res = dbapi.list_resource_classes(self.context, sort_key='name')
|
||||
@ -116,3 +123,151 @@ class DbResourceClassTestCase(base.DbTestCase):
|
||||
self.assertRaises(exception.ResourceClassNotFound,
|
||||
dbapi.update_resource_class, self.context,
|
||||
bad_id, {'name': new_name})
|
||||
|
||||
|
||||
class EtcdDbResourceClassTestCase(base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
cfg.CONF.set_override('db_type', 'etcd')
|
||||
super(EtcdDbResourceClassTestCase, self).setUp()
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
@mock.patch.object(etcd_client, 'write')
|
||||
def test_create_resource_class(self, mock_write, mock_read):
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
utils.create_test_resource_class(context=self.context)
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
@mock.patch.object(etcd_client, 'write')
|
||||
def test_create_resource_class_already_exists(self, mock_write,
|
||||
mock_read):
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
utils.create_test_resource_class(context=self.context, name='123')
|
||||
mock_read.side_effect = lambda *args: None
|
||||
self.assertRaises(exception.ResourceExists,
|
||||
utils.create_test_resource_class,
|
||||
context=self.context, name='123')
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
@mock.patch.object(etcd_client, 'write')
|
||||
def test_get_resource_class_by_uuid(self, mock_write, mock_read):
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
resource_class = utils.create_test_resource_class(
|
||||
context=self.context)
|
||||
mock_read.side_effect = lambda *args: FakeEtcdResult(
|
||||
resource_class.as_dict())
|
||||
res = dbapi.get_resource_class(self.context, resource_class.uuid)
|
||||
self.assertEqual(resource_class.uuid, res.uuid)
|
||||
self.assertEqual(resource_class.name, res.name)
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
@mock.patch.object(etcd_client, 'write')
|
||||
def test_get_resource_class_by_name(self, mock_write, mock_read):
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
rcs = utils.create_test_resource_class(context=self.context)
|
||||
mock_read.side_effect = lambda *args: FakeEtcdMultipleResult(
|
||||
[rcs.as_dict()])
|
||||
res = dbapi.get_resource_class(self.context, rcs.name)
|
||||
self.assertEqual(rcs.uuid, res.uuid)
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
def test_get_resource_class_that_does_not_exist(self, mock_read):
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
self.assertRaises(exception.ResourceClassNotFound,
|
||||
dbapi.get_resource_class,
|
||||
self.context, 'fake-ident')
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
@mock.patch.object(etcd_client, 'write')
|
||||
def test_list_resource_classes(self, mock_write, mock_read):
|
||||
names = []
|
||||
resource_classes = []
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
for i in range(1, 6):
|
||||
res_class = utils.create_test_resource_class(
|
||||
context=self.context, name='class'+str(i))
|
||||
resource_classes.append(res_class.as_dict())
|
||||
names.append(six.text_type(res_class['name']))
|
||||
mock_read.side_effect = lambda *args: FakeEtcdMultipleResult(
|
||||
resource_classes)
|
||||
res = dbapi.list_resource_classes(self.context)
|
||||
res_names = [r.name for r in res]
|
||||
self.assertEqual(sorted(names), sorted(res_names))
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
@mock.patch.object(etcd_client, 'write')
|
||||
def test_list_resource_classes_sorted(self, mock_write, mock_read):
|
||||
names = []
|
||||
resource_classes = []
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
for i in range(1, 6):
|
||||
res_class = utils.create_test_resource_class(
|
||||
context=self.context, name='class'+str(i))
|
||||
resource_classes.append(res_class.as_dict())
|
||||
names.append(six.text_type(res_class['name']))
|
||||
mock_read.side_effect = lambda *args: FakeEtcdMultipleResult(
|
||||
resource_classes)
|
||||
res = dbapi.list_resource_classes(self.context, sort_key='name')
|
||||
res_names = [r.name for r in res]
|
||||
self.assertEqual(sorted(names), res_names)
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
@mock.patch.object(etcd_client, 'write')
|
||||
@mock.patch.object(etcd_client, 'delete')
|
||||
def test_destroy_resource_class(self, mock_delete,
|
||||
mock_write, mock_read):
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
resource_class = utils.create_test_resource_class(
|
||||
context=self.context)
|
||||
mock_read.side_effect = lambda *args: FakeEtcdResult(
|
||||
resource_class.as_dict())
|
||||
dbapi.destroy_resource_class(self.context, resource_class.uuid)
|
||||
mock_delete.assert_called_once_with(
|
||||
'/resource_classes/%s' % resource_class.uuid)
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
def test_destroy_resource_class_that_does_not_exist(self, mock_read):
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
self.assertRaises(exception.ResourceClassNotFound,
|
||||
dbapi.destroy_resource_class,
|
||||
self.context,
|
||||
'ca3e2a25-2901-438d-8157-de7ffd68d535')
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
@mock.patch.object(etcd_client, 'write')
|
||||
@mock.patch.object(etcd_client, 'update')
|
||||
def test_update_resource_class(self, mock_update,
|
||||
mock_write, mock_read):
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
resource_class = utils.create_test_resource_class(
|
||||
context=self.context)
|
||||
old_name = resource_class.name
|
||||
new_name = 'new-name'
|
||||
self.assertNotEqual(old_name, new_name)
|
||||
mock_read.side_effect = lambda *args: FakeEtcdResult(
|
||||
resource_class.as_dict())
|
||||
dbapi.update_resource_class(
|
||||
self.context, resource_class.uuid, {'name': new_name})
|
||||
self.assertEqual(new_name, json.loads(
|
||||
mock_update.call_args_list[0][0][0].value)['name'])
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
def test_update_resource_class_not_found(self, mock_read):
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
new_name = 'new-name'
|
||||
self.assertRaises(exception.ResourceClassNotFound,
|
||||
dbapi.update_resource_class,
|
||||
self.context,
|
||||
'ca3e2a25-2901-438d-8157-de7ffd68d535',
|
||||
{'name': new_name})
|
||||
|
||||
@mock.patch.object(etcd_client, 'read')
|
||||
@mock.patch.object(etcd_client, 'write')
|
||||
def test_update_resource_class_uuid(self, mock_write, mock_read):
|
||||
mock_read.side_effect = etcd.EtcdKeyNotFound
|
||||
resource_class = utils.create_test_resource_class(
|
||||
context=self.context)
|
||||
self.assertRaises(exception.InvalidParameterValue,
|
||||
dbapi.update_resource_class,
|
||||
self.context, resource_class.uuid,
|
||||
{'uuid': ''})
|
||||
|
@ -172,6 +172,7 @@ def create_test_resource_provider(**kw):
|
||||
def get_test_resource_class(**kw):
|
||||
return {
|
||||
'id': kw.get('id', 42),
|
||||
'uuid': kw.get('uuid', '1136bf0e-66db-409d-aa4d-3af94eed8bcc'),
|
||||
'name': kw.get('name', 'VCPU'),
|
||||
'created_at': kw.get('created_at'),
|
||||
'updated_at': kw.get('updated_at'),
|
||||
|
@ -359,7 +359,7 @@ object_data = {
|
||||
'MyObj': '1.0-34c4b1aadefd177b13f9a2f894cc23cd',
|
||||
'NUMANode': '1.0-cba878b70b2f8b52f1e031b41ac13b4e',
|
||||
'NUMATopology': '1.0-b54086eda7e4b2e6145ecb6ee2c925ab',
|
||||
'ResourceClass': '1.0-2c41abea55d0f7cb47a97bdb345b37fd',
|
||||
'ResourceClass': '1.1-d661c7675b3cd5b8c3618b68ba64324e',
|
||||
'ResourceProvider': '1.0-92b427359d5a4cf9ec6c72cbe630ee24',
|
||||
'ZunService': '1.0-2a19ab9987a746621b2ada02d8aadf22',
|
||||
}
|
||||
|
@ -25,16 +25,6 @@ class TestResourceClassObject(base.DbTestCase):
|
||||
super(TestResourceClassObject, self).setUp()
|
||||
self.fake_resource = utils.get_test_resource_class()
|
||||
|
||||
def test_get_by_id(self):
|
||||
rc_id = self.fake_resource['id']
|
||||
with mock.patch.object(self.dbapi, 'get_resource_class',
|
||||
autospec=True) as mock_get_resource_class:
|
||||
mock_get_resource_class.return_value = self.fake_resource
|
||||
resource = objects.ResourceClass.get_by_id(self.context, rc_id)
|
||||
mock_get_resource_class.assert_called_once_with(
|
||||
self.context, rc_id)
|
||||
self.assertEqual(self.context, resource._context)
|
||||
|
||||
def test_get_by_name(self):
|
||||
name = self.fake_resource['name']
|
||||
with mock.patch.object(self.dbapi, 'get_resource_class',
|
||||
@ -67,51 +57,52 @@ class TestResourceClassObject(base.DbTestCase):
|
||||
self.assertEqual(self.context, resource._context)
|
||||
|
||||
def test_destroy(self):
|
||||
rc_id = self.fake_resource['id']
|
||||
rc_uuid = self.fake_resource['uuid']
|
||||
with mock.patch.object(self.dbapi, 'get_resource_class',
|
||||
autospec=True) as mock_get_resource_class:
|
||||
mock_get_resource_class.return_value = self.fake_resource
|
||||
with mock.patch.object(self.dbapi, 'destroy_resource_class',
|
||||
autospec=True) as mock_destroy:
|
||||
resource = objects.ResourceClass.get_by_id(
|
||||
self.context, rc_id)
|
||||
resource = objects.ResourceClass.get_by_uuid(
|
||||
self.context, rc_uuid)
|
||||
resource.destroy()
|
||||
mock_get_resource_class.assert_called_once_with(
|
||||
self.context, rc_id)
|
||||
mock_destroy.assert_called_once_with(None, rc_id)
|
||||
self.context, rc_uuid)
|
||||
mock_destroy.assert_called_once_with(None, rc_uuid)
|
||||
self.assertEqual(self.context, resource._context)
|
||||
|
||||
def test_save(self):
|
||||
rc_id = self.fake_resource['id']
|
||||
rc_uuid = self.fake_resource['uuid']
|
||||
with mock.patch.object(self.dbapi, 'get_resource_class',
|
||||
autospec=True) as mock_get_resource_class:
|
||||
mock_get_resource_class.return_value = self.fake_resource
|
||||
with mock.patch.object(self.dbapi, 'update_resource_class',
|
||||
autospec=True) as mock_update:
|
||||
resource = objects.ResourceClass.get_by_id(
|
||||
self.context, rc_id)
|
||||
resource = objects.ResourceClass.get_by_uuid(
|
||||
self.context, rc_uuid)
|
||||
resource.name = 'MEMORY_MB'
|
||||
resource.save()
|
||||
|
||||
mock_get_resource_class.assert_called_once_with(
|
||||
self.context, rc_id)
|
||||
self.context, rc_uuid)
|
||||
mock_update.assert_called_once_with(
|
||||
None, rc_id,
|
||||
None, rc_uuid,
|
||||
{'name': 'MEMORY_MB'})
|
||||
self.assertEqual(self.context, resource._context)
|
||||
|
||||
def test_refresh(self):
|
||||
rc_id = self.fake_resource['id']
|
||||
rc_uuid = self.fake_resource['uuid']
|
||||
name = self.fake_resource['name']
|
||||
new_name = 'MEMORY_MB'
|
||||
returns = [dict(self.fake_resource, name=name),
|
||||
dict(self.fake_resource, name=new_name)]
|
||||
expected = [mock.call(self.context, rc_id),
|
||||
mock.call(self.context, rc_id)]
|
||||
expected = [mock.call(self.context, rc_uuid),
|
||||
mock.call(self.context, rc_uuid)]
|
||||
with mock.patch.object(self.dbapi, 'get_resource_class',
|
||||
side_effect=returns,
|
||||
autospec=True) as mock_get_resource_class:
|
||||
resource = objects.ResourceClass.get_by_id(self.context, rc_id)
|
||||
resource = objects.ResourceClass.get_by_uuid(
|
||||
self.context, rc_uuid)
|
||||
self.assertEqual(name, resource.name)
|
||||
resource.refresh()
|
||||
self.assertEqual(new_name, resource.name)
|
||||
|
Loading…
Reference in New Issue
Block a user