Add volume_targets table to database
This patch adds a "volume_targets" DB table in order to save the volume target information of physical nodes. With this patch, Ironic can put/get volume target information to/from the database. Co-Authored-By: Stephane Miller <stephane@alum.mit.edu> Co-Authored-By: Ruby Loo <ruby.loo@intel.com> Change-Id: I79063f9d0aafd7b740785a883732536704e43b7c Partial-Bug: 1526231
This commit is contained in:
parent
f857a883d3
commit
07541047be
|
@ -217,6 +217,15 @@ class VolumeConnectorTypeAndIdAlreadyExists(Conflict):
|
|||
"%(connector_id)s already exists.")
|
||||
|
||||
|
||||
class VolumeTargetAlreadyExists(Conflict):
|
||||
_msg_fmt = _("A volume target with UUID %(uuid)s already exists.")
|
||||
|
||||
|
||||
class VolumeTargetBootIndexAlreadyExists(Conflict):
|
||||
_msg_fmt = _("A volume target with boot index '%(boot_index)s' "
|
||||
"for the same node already exists.")
|
||||
|
||||
|
||||
class InvalidUUID(Invalid):
|
||||
_msg_fmt = _("Expected a UUID but received %(uuid)s.")
|
||||
|
||||
|
@ -372,6 +381,10 @@ class VolumeConnectorNotFound(NotFound):
|
|||
_msg_fmt = _("Volume connector %(connector)s could not be found.")
|
||||
|
||||
|
||||
class VolumeTargetNotFound(NotFound):
|
||||
_msg_fmt = _("Volume target %(target)s could not be found.")
|
||||
|
||||
|
||||
class NoDriversLoaded(IronicException):
|
||||
_msg_fmt = _("Conductor %(conductor)s cannot be started "
|
||||
"because no drivers were loaded.")
|
||||
|
|
105
ironic/db/api.py
105
ironic/db/api.py
|
@ -183,9 +183,12 @@ class Connection(object):
|
|||
|
||||
@abc.abstractmethod
|
||||
def destroy_node(self, node_id):
|
||||
"""Destroy a node and all associated interfaces.
|
||||
"""Destroy a node and its associated resources.
|
||||
|
||||
:param node_id: The id or uuid of a node.
|
||||
Destroy a node, including any associated ports, port groups,
|
||||
tags, volume connectors, and volume targets.
|
||||
|
||||
:param node_id: The ID or UUID of a node.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
|
@ -687,6 +690,7 @@ class Connection(object):
|
|||
:raises: VolumeConnectorAlreadyExists If a volume connector with
|
||||
the same UUID already exists.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def update_volume_connector(self, ident, connector_info):
|
||||
"""Update properties of a volume connector.
|
||||
|
@ -712,3 +716,100 @@ class Connection(object):
|
|||
:raises: VolumeConnectorNotFound If a volume connector
|
||||
with the specified ident does not exist.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_volume_target_list(self, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
"""Return a list of volume targets.
|
||||
|
||||
:param limit: Maximum number of volume targets to return.
|
||||
:param marker: the last item of the previous page; we return the next
|
||||
result set.
|
||||
:param sort_key: Attribute by which results should be sorted.
|
||||
:param sort_dir: direction in which results should be sorted.
|
||||
(asc, desc)
|
||||
:returns: A list of volume targets.
|
||||
:raises: InvalidParameterValue if sort_key does not exist.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_volume_target_by_id(self, db_id):
|
||||
"""Return a volume target representation.
|
||||
|
||||
:param db_id: The database primary key (integer) ID of a volume target.
|
||||
:returns: A volume target.
|
||||
:raises: VolumeTargetNotFound if no volume target with this ID
|
||||
exists.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_volume_target_by_uuid(self, uuid):
|
||||
"""Return a volume target representation.
|
||||
|
||||
:param uuid: The UUID of a volume target.
|
||||
:returns: A volume target.
|
||||
:raises: VolumeTargetNotFound if no volume target with this UUID
|
||||
exists.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_volume_targets_by_node_id(self, node_id, limit=None,
|
||||
marker=None, sort_key=None,
|
||||
sort_dir=None):
|
||||
"""List all the volume targets for a given node.
|
||||
|
||||
:param node_id: The integer node ID.
|
||||
:param limit: Maximum number of volume targets to return.
|
||||
:param marker: the last item of the previous page; we return the next
|
||||
result set.
|
||||
:param sort_key: Attribute by which results should be sorted
|
||||
:param sort_dir: direction in which results should be sorted
|
||||
(asc, desc)
|
||||
:returns: A list of volume targets.
|
||||
:raises: InvalidParameterValue if sort_key does not exist.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_volume_target(self, target_info):
|
||||
"""Create a new volume target.
|
||||
|
||||
:param target_info: Dictionary containing the information about the
|
||||
volume target. Example::
|
||||
|
||||
{
|
||||
'uuid': '000000-..',
|
||||
'node_id': 2,
|
||||
'boot_index': 0,
|
||||
'volume_id': '12345678-...'
|
||||
'volume_type': 'some type',
|
||||
}
|
||||
:returns: A volume target.
|
||||
:raises: VolumeTargetBootIndexAlreadyExists if a volume target already
|
||||
exists with the same boot index and node ID.
|
||||
:raises: VolumeTargetAlreadyExists if a volume target with the same
|
||||
UUID exists.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def update_volume_target(self, ident, target_info):
|
||||
"""Update information for a volume target.
|
||||
|
||||
:param ident: The UUID or integer ID of a volume target.
|
||||
:param target_info: Dictionary containing the information about
|
||||
volume target to update.
|
||||
:returns: A volume target.
|
||||
:raises: InvalidParameterValue if a UUID is included in target_info.
|
||||
:raises: VolumeTargetBootIndexAlreadyExists if a volume target already
|
||||
exists with the same boot index and node ID.
|
||||
:raises: VolumeTargetNotFound if no volume target with this ident
|
||||
exists.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def destroy_volume_target(self, ident):
|
||||
"""Destroy a volume target.
|
||||
|
||||
:param ident: The UUID or integer ID of a volume target.
|
||||
:raises: VolumeTargetNotFound if a volume target with the specified
|
||||
ident does not exist.
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
# 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 volume_targets table
|
||||
|
||||
Revision ID: 1a59178ebdf6
|
||||
Revises: daa1ba02d98
|
||||
Create Date: 2016-02-25 11:25:29.836535
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '1a59178ebdf6'
|
||||
down_revision = 'daa1ba02d98'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table('volume_targets',
|
||||
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=True),
|
||||
sa.Column('node_id', sa.Integer(), nullable=True),
|
||||
sa.Column('volume_type', sa.String(length=64),
|
||||
nullable=True),
|
||||
sa.Column('properties', sa.Text(), nullable=True),
|
||||
sa.Column('boot_index', sa.Integer(), nullable=True),
|
||||
sa.Column('volume_id',
|
||||
sa.String(length=36), nullable=True),
|
||||
sa.Column('extra', sa.Text(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['node_id'], ['nodes.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('node_id', 'boot_index',
|
||||
name='uniq_volumetargets0node_id0'
|
||||
'boot_index'),
|
||||
sa.UniqueConstraint('uuid',
|
||||
name='uniq_volumetargets0uuid'),
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB')
|
|
@ -386,6 +386,10 @@ class Connection(api.Connection):
|
|||
models.VolumeConnector).filter_by(node_id=node_id)
|
||||
volume_connector_query.delete()
|
||||
|
||||
volume_target_query = model_query(
|
||||
models.VolumeTarget).filter_by(node_id=node_id)
|
||||
volume_target_query.delete()
|
||||
|
||||
query.delete()
|
||||
|
||||
def update_node(self, node_id, values):
|
||||
|
@ -952,3 +956,74 @@ class Connection(api.Connection):
|
|||
count = query.delete()
|
||||
if count == 0:
|
||||
raise exception.VolumeConnectorNotFound(connector=ident)
|
||||
|
||||
def get_volume_target_list(self, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
return _paginate_query(models.VolumeTarget, limit, marker,
|
||||
sort_key, sort_dir)
|
||||
|
||||
def get_volume_target_by_id(self, db_id):
|
||||
query = model_query(models.VolumeTarget).filter_by(id=db_id)
|
||||
try:
|
||||
return query.one()
|
||||
except NoResultFound:
|
||||
raise exception.VolumeTargetNotFound(target=db_id)
|
||||
|
||||
def get_volume_target_by_uuid(self, uuid):
|
||||
query = model_query(models.VolumeTarget).filter_by(uuid=uuid)
|
||||
try:
|
||||
return query.one()
|
||||
except NoResultFound:
|
||||
raise exception.VolumeTargetNotFound(target=uuid)
|
||||
|
||||
def get_volume_targets_by_node_id(self, node_id, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
query = model_query(models.VolumeTarget).filter_by(node_id=node_id)
|
||||
return _paginate_query(models.VolumeTarget, limit, marker, sort_key,
|
||||
sort_dir, query)
|
||||
|
||||
def create_volume_target(self, target_info):
|
||||
if 'uuid' not in target_info:
|
||||
target_info['uuid'] = uuidutils.generate_uuid()
|
||||
|
||||
target = models.VolumeTarget()
|
||||
target.update(target_info)
|
||||
with _session_for_write() as session:
|
||||
try:
|
||||
session.add(target)
|
||||
session.flush()
|
||||
except db_exc.DBDuplicateEntry as exc:
|
||||
if 'boot_index' in exc.columns:
|
||||
raise exception.VolumeTargetBootIndexAlreadyExists(
|
||||
boot_index=target_info['boot_index'])
|
||||
raise exception.VolumeTargetAlreadyExists(
|
||||
uuid=target_info['uuid'])
|
||||
return target
|
||||
|
||||
def update_volume_target(self, ident, target_info):
|
||||
if 'uuid' in target_info:
|
||||
msg = _("Cannot overwrite UUID for an existing Volume Target.")
|
||||
raise exception.InvalidParameterValue(err=msg)
|
||||
|
||||
try:
|
||||
with _session_for_write() as session:
|
||||
query = model_query(models.VolumeTarget)
|
||||
query = add_identity_filter(query, ident)
|
||||
ref = query.one()
|
||||
orig_boot_index = ref['boot_index']
|
||||
ref.update(target_info)
|
||||
session.flush()
|
||||
except db_exc.DBDuplicateEntry:
|
||||
raise exception.VolumeTargetBootIndexAlreadyExists(
|
||||
boot_index=target_info.get('boot_index', orig_boot_index))
|
||||
except NoResultFound:
|
||||
raise exception.VolumeTargetNotFound(target=ident)
|
||||
return ref
|
||||
|
||||
def destroy_volume_target(self, ident):
|
||||
with _session_for_write():
|
||||
query = model_query(models.VolumeTarget)
|
||||
query = add_identity_filter(query, ident)
|
||||
count = query.delete()
|
||||
if count == 0:
|
||||
raise exception.VolumeTargetNotFound(target=ident)
|
||||
|
|
|
@ -229,3 +229,23 @@ class VolumeConnector(Base):
|
|||
type = Column(String(32))
|
||||
connector_id = Column(String(255))
|
||||
extra = Column(db_types.JsonEncodedDict)
|
||||
|
||||
|
||||
class VolumeTarget(Base):
|
||||
"""Represents a volume target of a bare metal node."""
|
||||
|
||||
__tablename__ = 'volume_targets'
|
||||
__table_args__ = (
|
||||
schema.UniqueConstraint('uuid', name='uniq_volumetargets0uuid'),
|
||||
schema.UniqueConstraint('node_id',
|
||||
'boot_index',
|
||||
name='uniq_volumetargets0node_id0boot_index'),
|
||||
table_args())
|
||||
id = Column(Integer, primary_key=True)
|
||||
uuid = Column(String(36))
|
||||
node_id = Column(Integer, ForeignKey('nodes.id'), nullable=True)
|
||||
volume_type = Column(String(64))
|
||||
properties = Column(db_types.JsonEncodedDict)
|
||||
boot_index = Column(Integer)
|
||||
volume_id = Column(String(36))
|
||||
extra = Column(db_types.JsonEncodedDict)
|
||||
|
|
|
@ -585,6 +585,35 @@ class MigrationCheckersMixin(object):
|
|||
self.assertEqual(1, connector['node_id'])
|
||||
self.assertEqual('{}', connector['extra'])
|
||||
|
||||
def _check_1a59178ebdf6(self, engine, data):
|
||||
targets = db_utils.get_table(engine, 'volume_targets')
|
||||
col_names = [column.name for column in targets.c]
|
||||
expected_names = ['created_at', 'updated_at', 'id', 'uuid', 'node_id',
|
||||
'boot_index', 'extra', 'properties', 'volume_type',
|
||||
'volume_id']
|
||||
self.assertEqual(sorted(expected_names), sorted(col_names))
|
||||
|
||||
self.assertIsInstance(targets.c.created_at.type,
|
||||
sqlalchemy.types.DateTime)
|
||||
self.assertIsInstance(targets.c.updated_at.type,
|
||||
sqlalchemy.types.DateTime)
|
||||
self.assertIsInstance(targets.c.id.type,
|
||||
sqlalchemy.types.Integer)
|
||||
self.assertIsInstance(targets.c.uuid.type,
|
||||
sqlalchemy.types.String)
|
||||
self.assertIsInstance(targets.c.node_id.type,
|
||||
sqlalchemy.types.Integer)
|
||||
self.assertIsInstance(targets.c.boot_index.type,
|
||||
sqlalchemy.types.Integer)
|
||||
self.assertIsInstance(targets.c.extra.type,
|
||||
sqlalchemy.types.TEXT)
|
||||
self.assertIsInstance(targets.c.properties.type,
|
||||
sqlalchemy.types.TEXT)
|
||||
self.assertIsInstance(targets.c.volume_type.type,
|
||||
sqlalchemy.types.String)
|
||||
self.assertIsInstance(targets.c.volume_id.type,
|
||||
sqlalchemy.types.String)
|
||||
|
||||
def test_upgrade_and_version(self):
|
||||
with patch_with_engine(self.engine):
|
||||
self.migration_api.upgrade('head')
|
||||
|
|
|
@ -379,6 +379,26 @@ class DbNodeTestCase(base.DbTestCase):
|
|||
self.assertRaises(exception.VolumeConnectorNotFound,
|
||||
self.dbapi.get_volume_connector_by_id, connector.id)
|
||||
|
||||
def test_volume_target_gets_destroyed_after_destroying_a_node(self):
|
||||
node = utils.create_test_node()
|
||||
|
||||
target = utils.create_test_volume_target(node_id=node.id)
|
||||
|
||||
self.dbapi.destroy_node(node.id)
|
||||
|
||||
self.assertRaises(exception.VolumeTargetNotFound,
|
||||
self.dbapi.get_volume_target_by_id, target.id)
|
||||
|
||||
def test_volume_target_gets_destroyed_after_destroying_a_node_uuid(self):
|
||||
node = utils.create_test_node()
|
||||
|
||||
target = utils.create_test_volume_target(node_id=node.id)
|
||||
|
||||
self.dbapi.destroy_node(node.uuid)
|
||||
|
||||
self.assertRaises(exception.VolumeTargetNotFound,
|
||||
self.dbapi.get_volume_target_by_id, target.id)
|
||||
|
||||
def test_update_node(self):
|
||||
node = utils.create_test_node()
|
||||
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
# Copyright 2016 Hitachi, Ltc
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Tests for manipulating VolumeTargets via the DB API"""
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
import six
|
||||
|
||||
from ironic.common import exception
|
||||
from ironic.tests.unit.db import base
|
||||
from ironic.tests.unit.db import utils as db_utils
|
||||
|
||||
|
||||
class DbVolumeTargetTestCase(base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
# This method creates a volume_target for every test.
|
||||
super(DbVolumeTargetTestCase, self).setUp()
|
||||
self.node = db_utils.create_test_node()
|
||||
self.target = db_utils.create_test_volume_target(node_id=self.node.id)
|
||||
|
||||
def test_create_volume_target(self):
|
||||
info = {'uuid': uuidutils.generate_uuid(),
|
||||
'node_id': self.node.id,
|
||||
'boot_index': 1,
|
||||
'volume_type': 'iscsi',
|
||||
'volume_id': '12345678'}
|
||||
|
||||
target = self.dbapi.create_volume_target(info)
|
||||
self.assertEqual(info['uuid'], target.uuid)
|
||||
self.assertEqual(info['node_id'], target.node_id)
|
||||
self.assertEqual(info['boot_index'], target.boot_index)
|
||||
self.assertEqual(info['volume_type'], target.volume_type)
|
||||
self.assertEqual(info['volume_id'], target.volume_id)
|
||||
self.assertIsNone(target.properties)
|
||||
self.assertIsNone(target.extra)
|
||||
|
||||
def test_create_volume_target_duplicated_nodeid_and_bootindex(self):
|
||||
self.assertRaises(exception.VolumeTargetBootIndexAlreadyExists,
|
||||
db_utils.create_test_volume_target,
|
||||
uuid=uuidutils.generate_uuid(),
|
||||
node_id=self.target.node_id,
|
||||
boot_index=self.target.boot_index)
|
||||
|
||||
def test_create_volume_target_duplicated_uuid(self):
|
||||
self.assertRaises(exception.VolumeTargetAlreadyExists,
|
||||
db_utils.create_test_volume_target,
|
||||
uuid=self.target.uuid,
|
||||
node_id=self.node.id,
|
||||
boot_index=100)
|
||||
|
||||
def test_get_volume_target_by_id(self):
|
||||
res = self.dbapi.get_volume_target_by_id(self.target.id)
|
||||
self.assertEqual(self.target.volume_type, res.volume_type)
|
||||
self.assertEqual(self.target.properties, res.properties)
|
||||
self.assertEqual(self.target.boot_index, res.boot_index)
|
||||
|
||||
self.assertRaises(exception.VolumeTargetNotFound,
|
||||
self.dbapi.get_volume_target_by_id,
|
||||
100)
|
||||
|
||||
def test_get_volume_target_by_uuid(self):
|
||||
res = self.dbapi.get_volume_target_by_uuid(self.target.uuid)
|
||||
self.assertEqual(self.target.id, res.id)
|
||||
|
||||
self.assertRaises(exception.VolumeTargetNotFound,
|
||||
self.dbapi.get_volume_target_by_uuid,
|
||||
'11111111-2222-3333-4444-555555555555')
|
||||
|
||||
def _create_list_of_volume_targets(self, num):
|
||||
uuids = [six.text_type(self.target.uuid)]
|
||||
for i in range(1, num):
|
||||
volume_target = db_utils.create_test_volume_target(
|
||||
uuid=uuidutils.generate_uuid(),
|
||||
properties={"target_iqn": "iqn.test-%s" % i},
|
||||
boot_index=i)
|
||||
uuids.append(six.text_type(volume_target.uuid))
|
||||
return uuids
|
||||
|
||||
def test_get_volume_target_list(self):
|
||||
uuids = self._create_list_of_volume_targets(6)
|
||||
res = self.dbapi.get_volume_target_list()
|
||||
res_uuids = [r.uuid for r in res]
|
||||
six.assertCountEqual(self, uuids, res_uuids)
|
||||
|
||||
def test_get_volume_target_list_sorted(self):
|
||||
uuids = self._create_list_of_volume_targets(5)
|
||||
res = self.dbapi.get_volume_target_list(sort_key='uuid')
|
||||
res_uuids = [r.uuid for r in res]
|
||||
self.assertEqual(sorted(uuids), res_uuids)
|
||||
|
||||
self.assertRaises(exception.InvalidParameterValue,
|
||||
self.dbapi.get_volume_target_list, sort_key='foo')
|
||||
|
||||
def test_get_volume_targets_by_node_id(self):
|
||||
node2 = db_utils.create_test_node(uuid=uuidutils.generate_uuid())
|
||||
target2 = db_utils.create_test_volume_target(
|
||||
uuid=uuidutils.generate_uuid(), node_id=node2.id)
|
||||
self._create_list_of_volume_targets(2)
|
||||
res = self.dbapi.get_volume_targets_by_node_id(node2.id)
|
||||
self.assertEqual(1, len(res))
|
||||
self.assertEqual(target2.uuid, res[0].uuid)
|
||||
|
||||
def test_get_volume_targets_by_node_id_that_does_not_exist(self):
|
||||
self.assertEqual([], self.dbapi.get_volume_targets_by_node_id(99))
|
||||
|
||||
def test_update_volume_target(self):
|
||||
old_boot_index = self.target.boot_index
|
||||
new_boot_index = old_boot_index + 1
|
||||
|
||||
res = self.dbapi.update_volume_target(self.target.id,
|
||||
{'boot_index': new_boot_index})
|
||||
self.assertEqual(new_boot_index, res.boot_index)
|
||||
|
||||
res = self.dbapi.update_volume_target(self.target.id,
|
||||
{'boot_index': old_boot_index})
|
||||
self.assertEqual(old_boot_index, res.boot_index)
|
||||
|
||||
def test_update_volume_target_uuid(self):
|
||||
self.assertRaises(exception.InvalidParameterValue,
|
||||
self.dbapi.update_volume_target,
|
||||
self.target.id,
|
||||
{'uuid': uuidutils.generate_uuid()})
|
||||
|
||||
def test_update_volume_target_fails_invalid_id(self):
|
||||
self.assertRaises(exception.VolumeTargetNotFound,
|
||||
self.dbapi.update_volume_target,
|
||||
99,
|
||||
{'boot_index': 6})
|
||||
|
||||
def test_update_volume_target_duplicated_nodeid_and_bootindex(self):
|
||||
t = db_utils.create_test_volume_target(uuid=uuidutils.generate_uuid(),
|
||||
boot_index=1)
|
||||
self.assertRaises(exception.VolumeTargetBootIndexAlreadyExists,
|
||||
self.dbapi.update_volume_target,
|
||||
t.uuid,
|
||||
{'boot_index': self.target.boot_index,
|
||||
'node_id': self.target.node_id})
|
||||
|
||||
def test_destroy_volume_target(self):
|
||||
self.dbapi.destroy_volume_target(self.target.id)
|
||||
self.assertRaises(exception.VolumeTargetNotFound,
|
||||
self.dbapi.get_volume_target_by_id,
|
||||
self.target.id)
|
||||
|
||||
# Ensure that destroy_volume_target returns the expected exception.
|
||||
self.assertRaises(exception.VolumeTargetNotFound,
|
||||
self.dbapi.destroy_volume_target,
|
||||
self.target.id)
|
|
@ -346,6 +346,39 @@ def create_test_volume_connector(**kw):
|
|||
return dbapi.create_volume_connector(connector)
|
||||
|
||||
|
||||
def get_test_volume_target(**kw):
|
||||
fake_properties = {"target_iqn": "iqn.foo"}
|
||||
return {
|
||||
'id': kw.get('id', 789),
|
||||
'uuid': kw.get('uuid', '1be26c0b-03f2-4d2e-ae87-c02d7f33c781'),
|
||||
'node_id': kw.get('node_id', 123),
|
||||
'volume_type': kw.get('volume_type', 'iscsi'),
|
||||
'properties': kw.get('properties', fake_properties),
|
||||
'boot_index': kw.get('boot_index', 0),
|
||||
'volume_id': kw.get('volume_id', '12345678'),
|
||||
'extra': kw.get('extra', {}),
|
||||
'created_at': kw.get('created_at'),
|
||||
'updated_at': kw.get('updated_at'),
|
||||
}
|
||||
|
||||
|
||||
def create_test_volume_target(**kw):
|
||||
"""Create test target entry in DB and return VolumeTarget DB object.
|
||||
|
||||
Function to be used to create test VolumeTarget objects in the database.
|
||||
|
||||
:param kw: kwargs with overriding values for target's attributes.
|
||||
:returns: Test VolumeTarget DB object.
|
||||
|
||||
"""
|
||||
target = get_test_volume_target(**kw)
|
||||
# Let DB generate ID if it isn't specified explicitly
|
||||
if 'id' not in kw:
|
||||
del target['id']
|
||||
dbapi = db_api.get_instance()
|
||||
return dbapi.create_volume_target(target)
|
||||
|
||||
|
||||
def get_test_chassis(**kw):
|
||||
return {
|
||||
'id': kw.get('id', 42),
|
||||
|
|
Loading…
Reference in New Issue