Commit 13a3d5a4 by Coco

Add new DB schema: sqlachemy and alembic scripts.

Add the implementation of spec(https://review.openstack.org/615462)
This patch only contains new DB schema: sqlachemy and migration
scripts parts, and still lost object and model api parts of all tables
which will be submitted in the following patches. The initial owners
of remaining implementation are zhenghao, yumeng and Coco. This patch
delete the old unit test of object and api, we will add new unit test
once all ovos are ready.

Change-Id: I280b093076c8131a2ab2c925d3e050915a28977b
parent b12ae008
......@@ -90,8 +90,8 @@ class ConfigInvalid(CyborgException):
_msg_fmt = _("Invalid configuration file. %(error_msg)s")
class AcceleratorAlreadyExists(CyborgException):
_msg_fmt = _("Accelerator with uuid %(uuid)s already exists.")
class DeviceAlreadyExists(CyborgException):
_msg_fmt = _("Device with uuid %(uuid)s already exists.")
class DeployableAlreadyExists(CyborgException):
......@@ -148,8 +148,8 @@ class ConfGroupForServiceTypeNotFound(ServiceNotFound):
"%(stype)s.")
class AcceleratorNotFound(NotFound):
_msg_fmt = _("Accelerator %(uuid)s could not be found.")
class DeviceNotFound(NotFound):
_msg_fmt = _("Device %(uuid)s could not be found.")
class DeployableNotFound(NotFound):
......@@ -165,8 +165,8 @@ class Conflict(CyborgException):
code = http_client.CONFLICT
class DuplicateAcceleratorName(Conflict):
_msg_fmt = _("An accelerator with name %(name)s already exists.")
class DuplicateDeviceName(Conflict):
_msg_fmt = _("A device with name %(name)s already exists.")
class DuplicateDeployableName(Conflict):
......
......@@ -41,27 +41,26 @@ class Connection(object):
def __init__(self):
"""Constructor."""
# accelerator
# device
@abc.abstractmethod
def accelerator_create(self, context, values):
"""Create a new accelerator."""
def device_create(self, context, values):
"""Create a new device when device is inserted into the host."""
@abc.abstractmethod
def accelerator_get(self, context, uuid):
"""Get requested accelerator."""
def device_get(self, context, uuid):
"""Get requested device."""
@abc.abstractmethod
def accelerator_list(self, context, limit, marker, sort_key, sort_dir,
project_only):
"""Get requested list of accelerators."""
def device_list(self, context, limit, marker, sort_key, sort_dir):
"""Get requested list of devices."""
@abc.abstractmethod
def accelerator_update(self, context, uuid, values):
"""Update an accelerator."""
def device_update(self, context, uuid, values):
"""Update a device."""
@abc.abstractmethod
def accelerator_delete(self, context, uuid):
"""Delete an accelerator."""
def device_delete(self, context, uuid):
"""Delete a device when device is removed from the host."""
# deployable
@abc.abstractmethod
......
"""new_db_schema
Revision ID: ede4e3f1a232
Revises: d6f033d8fa5b
Create Date: 2018-11-27 22:00:52.080713
"""
# revision identifiers, used by Alembic.
revision = 'ede4e3f1a232'
down_revision = 'd6f033d8fa5b'
from alembic import op
import sqlalchemy as sa
# TODO: The enum value should be further discussed.
state = sa.Enum('Initial', 'Bound', 'BindFailed', name='state')
substate = sa.Enum('Initial', name='substate')
attach_type = sa.Enum('PCI', 'MDEV', name='attach_type')
control_type = sa.Enum('PCI', name='control_type')
def upgrade():
# drop old table: deployable, accelerator
op.drop_table('attributes')
op.drop_table('deployables')
op.drop_table('accelerators')
op.create_table(
'devices',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('uuid', sa.String(length=36), nullable=False),
sa.Column('type', sa.String(length=255), nullable=False),
sa.Column('vendor', sa.String(length=255), nullable=False),
sa.Column('model', sa.String(length=255), nullable=False),
sa.Column('std_board_info', sa.Text(), nullable=True),
sa.Column('vendor_board_info', sa.Text(), nullable=True),
sa.Column('hostname', sa.String(length=255), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('uuid', name='uniq_devices0uuid'),
mysql_ENGINE='InnoDB',
mysql_DEFAULT_CHARSET='UTF8'
)
op.create_table(
'deployables',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('uuid', sa.String(length=36), nullable=False),
sa.Column('parent_id', sa.Integer(),
sa.ForeignKey('deployables.id', ondelete='CASCADE'),
nullable=True),
sa.Column('root_id', sa.Integer(),
sa.ForeignKey('deployables.id', ondelete='CASCADE'),
nullable=True),
sa.Column('name', sa.String(length=32), nullable=False),
sa.Column('num_accelerators', sa.Integer(), nullable=False),
sa.Column('device_id', sa.Integer(),
sa.ForeignKey('devices.id', ondelete="RESTRICT"),
nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('uuid', name='uniq_deployables0uuid'),
sa.Index('deployables_parent_id_idx', 'parent_id'),
sa.Index('deployables_root_id_idx', 'root_id'),
sa.Index('deployables_device_id_idx', 'device_id'),
mysql_ENGINE='InnoDB',
mysql_DEFAULT_CHARSET='UTF8'
)
op.create_table(
'attributes',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('uuid', sa.String(length=36), nullable=False),
sa.Column('deployable_id', sa.Integer(),
sa.ForeignKey('deployables.id', ondelete="RESTRICT"),
nullable=False),
sa.Column('key', sa.Text(), nullable=False),
sa.Column('value', sa.Text(), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('uuid', name='uniq_attributes0uuid'),
sa.Index('attributes_deployable_id_idx', 'deployable_id'),
mysql_ENGINE='InnoDB',
mysql_DEFAULT_CHARSET='UTF8'
)
op.create_table(
'controlpath_ids',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('uuid', sa.String(length=36), nullable=False),
sa.Column('device_id', sa.Integer(),
sa.ForeignKey('devices.id', ondelete="RESTRICT"),
nullable=False),
sa.Column('cpid_type', control_type, nullable=False),
sa.Column('cpid_info', sa.Text(), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('uuid', name='uniq_controlpath_ids0uuid'),
sa.Index('controlpath_ids_device_id_idx', 'device_id'),
mysql_ENGINE='InnoDB',
mysql_DEFAULT_CHARSET='UTF8'
)
op.create_table(
'attach_handles',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('uuid', sa.String(length=36), nullable=False),
sa.Column('deployable_id', sa.Integer(),
sa.ForeignKey('deployables.id', ondelete="RESTRICT"),
nullable=False),
sa.Column('cpid_id', sa.Integer(),
sa.ForeignKey('controlpath_ids.id', ondelete="RESTRICT"),
nullable=False),
sa.Column('attach_type', attach_type, nullable=False),
sa.Column('attach_info', sa.Text(), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('uuid', name='uniq_attach_handles0uuid'),
sa.Index('attach_handles_deployable_id_idx', 'deployable_id'),
mysql_ENGINE='InnoDB',
mysql_DEFAULT_CHARSET='UTF8'
)
op.create_table(
'device_profiles',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('uuid', sa.String(length=36), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),
sa.Column('profile_json', sa.Text(), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('uuid', name='uniq_device_profiles0uuid'),
mysql_ENGINE='InnoDB',
mysql_DEFAULT_CHARSET='UTF8'
)
op.create_table(
'external_accelerator_requests',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('uuid', sa.String(length=36), nullable=False),
sa.Column('project_id', sa.String(length=255), nullable=False),
sa.Column('state', state, nullable=False, default='Initial'),
sa.Column('substate', substate, nullable=False, default='Initial'),
sa.Column('device_profile_id', sa.Integer(),
sa.ForeignKey('device_profiles.id', ondelete="RESTRICT"),
nullable=False),
sa.Column('hostname', sa.String(length=255), nullable=True),
sa.Column('device_rp_uuid', sa.String(length=36), nullable=True),
sa.Column('device_instance_uuid', sa.String(length=36),
nullable=True),
sa.Column('attach_handle_id', sa.Integer(),
sa.ForeignKey('attach_handles.id', ondelete="RESTRICT"),
nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('uuid',
name='uniq_external_accelerator_requests0uuid'),
sa.Index('external_accelerator_requests_project_id_idx', 'project_id'),
sa.Index('external_accelerator_requests_device_profile_id_idx',
'device_profile_id'),
sa.Index('external_accelerator_requests_device_rp_uuid_idx',
'device_rp_uuid'),
sa.Index('external_accelerator_requests_device_instance_uuid_idx',
'device_instance_uuid'),
sa.Index('external_accelerator_requests_attach_handle_id_idx',
'attach_handle_id'),
mysql_ENGINE='InnoDB',
mysql_DEFAULT_CHARSET='UTF8'
)
......@@ -127,69 +127,69 @@ class Connection(api.Connection):
def __init__(self):
pass
def accelerator_create(self, context, values):
def device_create(self, context, values):
if not values.get('uuid'):
values['uuid'] = uuidutils.generate_uuid()
accelerator = models.Accelerator()
accelerator.update(values)
device = models.Device()
device.update(values)
with _session_for_write() as session:
try:
session.add(accelerator)
session.add(device)
session.flush()
except db_exc.DBDuplicateEntry:
raise exception.AcceleratorAlreadyExists(uuid=values['uuid'])
return accelerator
raise exception.DeviceAlreadyExists(uuid=values['uuid'])
return device
def accelerator_get(self, context, uuid):
def device_get(self, context, uuid):
query = model_query(
context,
models.Accelerator).filter_by(uuid=uuid)
models.Device).filter_by(uuid=uuid)
try:
return query.one()
except NoResultFound:
raise exception.AcceleratorNotFound(uuid=uuid)
raise exception.DeviceNotFound(uuid=uuid)
def accelerator_list(self, context, limit, marker, sort_key, sort_dir,
project_only):
query = model_query(context, models.Accelerator,
def device_list(self, context, limit, marker, sort_key, sort_dir,
project_only):
query = model_query(context, models.Device,
project_only=project_only)
return _paginate_query(context, models.Accelerator, limit, marker,
return _paginate_query(context, models.Device, limit, marker,
sort_key, sort_dir, query)
def accelerator_update(self, context, uuid, values):
def device_update(self, context, uuid, values):
if 'uuid' in values:
msg = _("Cannot overwrite UUID for an existing Accelerator.")
msg = _("Cannot overwrite UUID for an existing Device.")
raise exception.InvalidParameterValue(err=msg)
try:
return self._do_update_accelerator(context, uuid, values)
return self._do_update_device(context, uuid, values)
except db_exc.DBDuplicateEntry as e:
if 'name' in e.columns:
raise exception.DuplicateAcceleratorName(name=values['name'])
raise exception.DuplicateDeviceName(name=values['name'])
@oslo_db_api.retry_on_deadlock
def _do_update_accelerator(self, context, uuid, values):
def _do_update_device(self, context, uuid, values):
with _session_for_write():
query = model_query(context, models.Accelerator)
query = model_query(context, models.Device)
query = add_identity_filter(query, uuid)
try:
ref = query.with_lockmode('update').one()
except NoResultFound:
raise exception.AcceleratorNotFound(uuid=uuid)
raise exception.DeviceNotFound(uuid=uuid)
ref.update(values)
return ref
@oslo_db_api.retry_on_deadlock
def accelerator_delete(self, context, uuid):
def device_delete(self, context, uuid):
with _session_for_write():
query = model_query(context, models.Accelerator)
query = model_query(context, models.Device)
query = add_identity_filter(query, uuid)
count = query.delete()
if count != 1:
raise exception.AcceleratorNotFound(uuid=uuid)
raise exception.DeviceNotFound(uuid=uuid)
def deployable_create(self, context, values):
if not values.get('uuid'):
......@@ -265,12 +265,8 @@ class Connection(api.Connection):
filters):
exact_match_filter_names = ['uuid', 'name',
'parent_uuid', 'root_uuid',
'address', 'host',
'board', 'vendor', 'version',
'type', 'interface_type', 'assignable',
'instance_uuid', 'availability',
'accelerator_id']
'parent_id', 'root_id',
'num_accelerators', 'device_id']
attribute_filters = {}
filters_copy = copy.deepcopy(filters)
for key, value in filters_copy.items():
......@@ -407,12 +403,8 @@ class Connection(api.Connection):
filters = copy.deepcopy(filters)
exact_match_filter_names = ['uuid', 'name',
'parent_uuid', 'root_uuid',
'address', 'host',
'board', 'vendor', 'version',
'type', 'interface_type', 'assignable',
'instance_uuid', 'availability',
'accelerator_id']
'parent_id', 'root_id',
'num_accelerators', 'device_id']
# Filter the query
query_prefix = self._exact_deployable_filter(query_prefix,
......@@ -653,14 +645,13 @@ class Connection(api.Connection):
def _sync_acc_res(self, context, resource, project_id):
"""Quota sync funciton"""
res_in_use = self._accelerator_data_get_for_project(context, resource,
project_id)
res_in_use = self._device_data_get_for_project(context, resource,
project_id)
return {resource: res_in_use}
def _accelerator_data_get_for_project(self, context, resource, project_id):
def _device_data_get_for_project(self, context, resource, project_id):
"""Return the number of resource which is being used by a project"""
query = model_query(context, models.Accelerator).\
filter_by(project_id=project_id).filter_by(device_type=resource)
query = model_query(context, models.Device).filter_by(type=resource)
return query.count()
......
......@@ -20,7 +20,7 @@ from oslo_db.sqlalchemy import models
from oslo_utils import timeutils
import six.moves.urllib.parse as urlparse
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer, Boolean, ForeignKey, Index
from sqlalchemy import Column, String, Integer, Enum, ForeignKey, Index
from sqlalchemy import Text
from sqlalchemy import schema
from sqlalchemy import DateTime
......@@ -67,27 +67,23 @@ class CyborgBase(models.TimestampMixin, models.ModelBase):
Base = declarative_base(cls=CyborgBase)
class Accelerator(Base):
"""Represents the accelerators."""
class Device(Base):
"""Represents the devices."""
__tablename__ = 'accelerators'
__tablename__ = 'devices'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_accelerators0uuid'),
schema.UniqueConstraint('uuid', name='uniq_devices0uuid'),
table_args()
)
id = Column(Integer, primary_key=True)
uuid = Column(String(36), nullable=False)
name = Column(String(255), nullable=False)
description = Column(String(255), nullable=True)
project_id = Column(String(36), nullable=True)
user_id = Column(String(36), nullable=True)
device_type = Column(String(255), nullable=False)
acc_type = Column(String(255), nullable=True)
acc_capability = Column(String(255), nullable=True)
vendor_id = Column(String(255), nullable=False)
product_id = Column(String(255), nullable=False)
remotable = Column(Integer, nullable=False)
type = Column(String(255), nullable=False)
vendor = Column(String(255), nullable=False)
model = Column(String(255), nullable=False)
std_board_info = Column(Text, nullable=True)
vendor_board_info = Column(Text, nullable=True)
hostname = Column(String(255), nullable=False)
class Deployable(Base):
......@@ -96,32 +92,20 @@ class Deployable(Base):
__tablename__ = 'deployables'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_deployables0uuid'),
Index('deployables_parent_uuid_idx', 'parent_uuid'),
Index('deployables_root_uuid_idx', 'root_uuid'),
Index('deployables_accelerator_id_idx', 'accelerator_id'),
Index('deployables_parent_id_idx', 'parent_id'),
Index('deployables_root_id_idx', 'root_id'),
Index('deployables_device_id_idx', 'device_id'),
table_args()
)
id = Column(Integer, primary_key=True)
uuid = Column(String(36), nullable=False)
name = Column(String(255), nullable=False)
parent_uuid = Column(String(36),
ForeignKey('deployables.uuid'), nullable=True)
root_uuid = Column(String(36),
ForeignKey('deployables.uuid'), nullable=True)
address = Column(String(255), nullable=False)
host = Column(String(255), nullable=False)
board = Column(String(255), nullable=False)
vendor = Column(String(255), nullable=False)
version = Column(String(255), nullable=False)
type = Column(String(255), nullable=False)
interface_type = Column(String(255), nullable=False)
assignable = Column(Boolean, nullable=False)
instance_uuid = Column(String(36), nullable=True)
availability = Column(String(255), nullable=False)
accelerator_id = Column(Integer,
ForeignKey('accelerators.id', ondelete="CASCADE"),
nullable=False)
parent_id = Column(Integer, ForeignKey('deployables.id'), nullable=True)
root_id = Column(Integer, ForeignKey('deployables.id'), nullable=True)
name = Column(String(32), nullable=False)
num_accelerators = Column(Integer, nullable=False)
device_id = Column(Integer, ForeignKey('devices.id', ondelete="RESTRICT"),
nullable=False)
class Attribute(Base):
......@@ -135,12 +119,105 @@ class Attribute(Base):
id = Column(Integer, primary_key=True)
uuid = Column(String(36), nullable=False)
deployable_id = Column(Integer,
ForeignKey('deployables.id', ondelete="CASCADE"),
ForeignKey('deployables.id', ondelete="RESTRICT"),
nullable=False)
key = Column(Text, nullable=False)
value = Column(Text, nullable=False)
class ControlpathID(Base):
"""Identifier for the Device when driver reporting to agent, IDs is
needed especially when multiple PFs exist in one Devices."""
__tablename__ = 'controlpath_ids'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_controlpath_ids0uuid'),
Index('controlpath_ids_device_id_idx', 'device_id'),
table_args()
)
id = Column(Integer, primary_key=True)
uuid = Column(String(36), nullable=False)
device_id = Column(Integer,
ForeignKey('devices.id', ondelete="RESTRICT"),
nullable=False)
cpid_type = Column(Enum('PCI', name='control_type'), nullable=False)
cpid_info = Column(Text, nullable=False)
class AttachHandle(Base):
"""Reprensents device's VFs and PFs which can be attached to a VM."""
__tablename__ = 'attach_handles'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_attach_handles0uuid'),
Index('attach_handles_deployable_id_idx', 'deployable_id'),
table_args()
)
id = Column(Integer, primary_key=True)
uuid = Column(String(36), nullable=False)
deployable_id = Column(Integer,
ForeignKey('deployables.id', ondelete="RESTRICT"),
nullable=False)
cpid_id = Column(Integer,
ForeignKey('controlpath_ids.id', ondelete="RESTRICT"),
nullable=False)
attach_type = Column(Enum('PCI', 'MDEV', name='attach_type'),
nullable=False)
attach_info = Column(Text, nullable=False)
class DeviceProfile(Base):
"""Represents users' specific requirements."""
__tablename__ = 'device_profiles'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_device_profiles0uuid'),
table_args()
)
id = Column(Integer, primary_key=True)
uuid = Column(String(36), nullable=False)
name = Column(String(255), nullable=False)
profile_json = Column(Text, nullable=False)
class ExternalAcceleratorRequest(Base):
"""Represents external nova requests for attach related operations."""
__tablename__ = 'external_accelerator_requests'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_ext_arqs0uuid'),
Index('external_accelerator_requests_project_id_idx', 'project_id'),
Index('external_accelerator_requests_device_profile_id_idx',
'device_profile_id'),
Index('external_accelerator_requests_device_rp_uuid_idx',
'device_rp_uuid'),
Index('external_accelerator_requests_device_instance_uuid_idx',
'device_instance_uuid'),
Index('external_accelerator_requests_attach_handle_id_idx',
'attach_handle_id'),
table_args()
)
id = Column(Integer, primary_key=True)
uuid = Column(String(36), nullable=False)
project_id = Column(String(255), nullable=False)
state = Column(Enum('Initial', 'Bound', 'BindFailed', name='state'),
nullable=False)
substate = Column(Enum('Initial', name='substate'), nullable=False),
device_profile_id = Column(Integer, ForeignKey('device_profiles.id',
ondelete="RESTRICT"),
nullable=False)
hostname = Column(String(255), nullable=True)
device_rp_uuid = Column(String(36), nullable=True)
device_instance_uuid = Column(String(36), nullable=True)
attach_handle_id = Column(Integer(), ForeignKey('attach_handles.id',
ondelete="RESTRICT"),
nullable=True)
class QuotaUsage(Base):
"""Represents the current usage for a given resource."""
......
# Copyright 2017 Huawei Technologies Co.,LTD.
# 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 datetime
import mock
from oslo_utils import timeutils
from six.moves import http_client
from cyborg.api.controllers.v1.accelerators import Accelerator
from cyborg.conductor import rpcapi
from cyborg.tests.unit.api.controllers.v1 import base as v1_test
from cyborg.tests.unit.db import utils as db_utils
from cyborg.tests.unit.objects import utils as obj_utils
def gen_post_body(**kw):
return db_utils.get_test_accelerator(**kw)
def _rpcapi_accelerator_create(context, obj_acc):
"""Fake used to mock out the conductor RPCAPI's accelerator_create method.
Performs creation of the accelerator object and returns the created
accelerator as-per the real method.
"""
obj_acc.create(context)
return obj_acc
class TestPost(v1_test.APITestV1):
ACCELERATOR_UUID = '10efe63d-dfea-4a37-ad94-4116fba50981'
def setUp(self):
super(TestPost, self).setUp()
self.headers = self.gen_headers(self.context)
p = mock.patch.object(rpcapi.ConductorAPI, 'accelerator_create')
self.mock_create = p.start()
self.mock_create.side_effect = _rpcapi_accelerator_create
self.addCleanup(p.stop)
@mock.patch('oslo_utils.uuidutils.generate_uuid')
def test_post(self, mock_uuid):
mock_uuid.return_value = self.ACCELERATOR_UUID
body = gen_post_body(name='post_accelerator')
response = self.post_json('/accelerators', body, headers=self.headers)
self.assertEqual(http_client.CREATED, response.status_int)
response = response.json
self.assertEqual(self.ACCELERATOR_UUID, response['uuid'])
self.assertEqual(body['name'], response['name'])
self.mock_create.assert_called_once_with(mock.ANY, mock.ANY)
class TestList(v1_test.APITestV1):
def setUp(self):
super(TestList, self).setUp()
self.accs = []
for i in range(3):
acc = obj_utils.create_test_accelerator(self.context)
self.accs.append(acc)
self.acc = self.accs[0]
self.context.tenant = self.acc.project_id
self.headers = self.gen_headers(self.context)
def test_get_one(self):
data = self.get_json('/accelerators/%s' % self.acc.uuid,
headers=self.headers)
self.assertEqual(self.acc.uuid, data['uuid'])
for attr in Accelerator._wsme_attributes:
self.assertIn(attr.name, data)
def test_get_all(self):
data = self.get_json('/accelerators', headers=self.headers)
self.assertEqual(3, len(data['accelerators']))
data_uuids = [d['uuid'] for d in data['accelerators']]
acc_uuids = [acc.uuid for acc in self.accs]
self.assertItemsEqual(acc_uuids, data_uuids)
def _rpcapi_accelerator_update(context, obj_acc):
"""Fake used to mock out the conductor RPCAPI's accelerator_update method.
Performs update of the accelerator object and returns the updated
accelerator as-per the real method.
"""
obj_acc.save(context)
return obj_acc
class TestPatch(v1_test.APITestV1):
def setUp(self):
super(TestPatch, self).setUp()
self.acc = obj_utils.create_test_accelerator(self.context)
self.context.tenant = self.acc.project_id
self.headers = self.gen_headers(self.context)
p = mock.patch.object(rpcapi.ConductorAPI, 'accelerator_update')
self.mock_update = p.start()
self.mock_update.side_effect = _rpcapi_accelerator_update
self.addCleanup(p.stop)
@mock.patch.object(timeutils, 'utcnow')
def test_patch(self, mock_utcnow):