Add volume_connectors table to save connector information
This patch introduces a new "volume_connectors" table in order to save the volume connector information of physical nodes. With this patch, Ironic can put/get volume connector information to/from the database. Co-Authored-By: Tomoki Sekiyama <tomoki.sekiyama.qu@hitachi.com> Co-Authored-By: Stephane Miller <stephane@alum.mit.edu> Co-Authored-By: Julia Kreger <juliaashleykreger@gmail.com> Change-Id: I8237ab671a04ac9b01c8bdb2936cf0a661b9b1de Partial-Bug: 1526231
This commit is contained in:
parent
ab79b3eff2
commit
a82a0ceba1
|
@ -157,6 +157,15 @@ class DuplicateName(Conflict):
|
||||||
_msg_fmt = _("A node with name %(name)s already exists.")
|
_msg_fmt = _("A node with name %(name)s already exists.")
|
||||||
|
|
||||||
|
|
||||||
|
class VolumeConnectorAlreadyExists(Conflict):
|
||||||
|
_msg_fmt = _("A volume connector with UUID %(uuid)s already exists.")
|
||||||
|
|
||||||
|
|
||||||
|
class VolumeConnectorTypeAndIdAlreadyExists(Conflict):
|
||||||
|
_msg_fmt = _("A volume connector with type %(type)s and connector ID "
|
||||||
|
"%(connector_id)s already exists.")
|
||||||
|
|
||||||
|
|
||||||
class InvalidUUID(Invalid):
|
class InvalidUUID(Invalid):
|
||||||
_msg_fmt = _("Expected a UUID but received %(uuid)s.")
|
_msg_fmt = _("Expected a UUID but received %(uuid)s.")
|
||||||
|
|
||||||
|
@ -302,6 +311,10 @@ class ChassisNotFound(NotFound):
|
||||||
_msg_fmt = _("Chassis %(chassis)s could not be found.")
|
_msg_fmt = _("Chassis %(chassis)s could not be found.")
|
||||||
|
|
||||||
|
|
||||||
|
class VolumeConnectorNotFound(NotFound):
|
||||||
|
_msg_fmt = _("Volume connector %(connector)s could not be found.")
|
||||||
|
|
||||||
|
|
||||||
class NoDriversLoaded(IronicException):
|
class NoDriversLoaded(IronicException):
|
||||||
_msg_fmt = _("Conductor %(conductor)s cannot be started "
|
_msg_fmt = _("Conductor %(conductor)s cannot be started "
|
||||||
"because no drivers were loaded.")
|
"because no drivers were loaded.")
|
||||||
|
|
|
@ -614,3 +614,101 @@ class Connection(object):
|
||||||
:returns: Node object.
|
:returns: Node object.
|
||||||
:raises: NodeNotFound if none or several nodes are found.
|
:raises: NodeNotFound if none or several nodes are found.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_volume_connector_list(self, limit=None, marker=None,
|
||||||
|
sort_key=None, sort_dir=None):
|
||||||
|
"""Return a list of volume connectors.
|
||||||
|
|
||||||
|
:param limit: Maximum number of volume connectors 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 connectors.
|
||||||
|
:raises: InvalidParameterValue If sort_key does not exist.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_volume_connector_by_id(self, id):
|
||||||
|
"""Return a volume connector representation.
|
||||||
|
|
||||||
|
:param id: The ID of a volume connector.
|
||||||
|
:returns: A volume connector with the specified ID.
|
||||||
|
:raises: VolumeConnectorNotFound If a volume connector
|
||||||
|
with the specified ID is not found.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_volume_connector_by_uuid(self, connector_uuid):
|
||||||
|
"""Return a volume connector representation.
|
||||||
|
|
||||||
|
:param connector_uuid: The UUID of a connector.
|
||||||
|
:returns: A volume connector with the specified UUID.
|
||||||
|
:raises: VolumeConnectorNotFound If a volume connector
|
||||||
|
with the specified UUID is not found.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_volume_connectors_by_node_id(self, node_id, limit=None,
|
||||||
|
marker=None, sort_key=None,
|
||||||
|
sort_dir=None):
|
||||||
|
"""List all the volume connectors for a given node.
|
||||||
|
|
||||||
|
:param node_id: The integer node ID.
|
||||||
|
:param limit: Maximum number of volume connectors 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 connectors.
|
||||||
|
:raises: InvalidParameterValue If sort_key does not exist.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_volume_connector(self, connector_info):
|
||||||
|
"""Create a new volume connector.
|
||||||
|
|
||||||
|
:param connector_info: Dictionary containing information about the
|
||||||
|
connector. Example::
|
||||||
|
|
||||||
|
{
|
||||||
|
'uuid': '000000-..',
|
||||||
|
'type': 'wwnn',
|
||||||
|
'connector_id': '00:01:02:03:04:05:06',
|
||||||
|
'node_id': 2
|
||||||
|
}
|
||||||
|
|
||||||
|
:returns: A volume connector.
|
||||||
|
:raises: VolumeConnectorTypeAndIdAlreadyExists If a connector
|
||||||
|
already exists with a matching type and connector_id.
|
||||||
|
: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.
|
||||||
|
|
||||||
|
:param ident: The UUID or integer ID of a volume connector.
|
||||||
|
:param connector_info: Dictionary containing the information about
|
||||||
|
connector to update.
|
||||||
|
:returns: A volume connector.
|
||||||
|
:raises: VolumeConnectorTypeAndIdAlreadyExists If another
|
||||||
|
connector already exists with a matching type and
|
||||||
|
connector_id field.
|
||||||
|
:raises: VolumeConnectorNotFound If a volume connector
|
||||||
|
with the specified ident does not exist.
|
||||||
|
:raises: InvalidParameterValue When a UUID is included in
|
||||||
|
connector_info.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def destroy_volume_connector(self, ident):
|
||||||
|
"""Destroy a volume connector.
|
||||||
|
|
||||||
|
:param ident: The UUID or integer ID of a volume connector.
|
||||||
|
:raises: VolumeConnectorNotFound If a volume connector
|
||||||
|
with the specified ident does not exist.
|
||||||
|
"""
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
# 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_connectors table
|
||||||
|
|
||||||
|
Revision ID: daa1ba02d98
|
||||||
|
Revises: c14cef6dfedf
|
||||||
|
Create Date: 2015-11-26 17:19:22.074989
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'daa1ba02d98'
|
||||||
|
down_revision = 'bcdd431ba0bf'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.create_table('volume_connectors',
|
||||||
|
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('type', sa.String(length=32), nullable=True),
|
||||||
|
sa.Column('connector_id', sa.String(length=255),
|
||||||
|
nullable=True),
|
||||||
|
sa.Column('extra', sa.Text(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['node_id'], ['nodes.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
sa.UniqueConstraint('type', 'connector_id',
|
||||||
|
name='uniq_volumeconnectors0type0'
|
||||||
|
'connector_id'),
|
||||||
|
sa.UniqueConstraint('uuid',
|
||||||
|
name='uniq_volumeconnectors0uuid'),
|
||||||
|
mysql_charset='utf8',
|
||||||
|
mysql_engine='InnoDB')
|
|
@ -382,6 +382,10 @@ class Connection(api.Connection):
|
||||||
tag_query = model_query(models.NodeTag).filter_by(node_id=node_id)
|
tag_query = model_query(models.NodeTag).filter_by(node_id=node_id)
|
||||||
tag_query.delete()
|
tag_query.delete()
|
||||||
|
|
||||||
|
volume_connector_query = model_query(
|
||||||
|
models.VolumeConnector).filter_by(node_id=node_id)
|
||||||
|
volume_connector_query.delete()
|
||||||
|
|
||||||
query.delete()
|
query.delete()
|
||||||
|
|
||||||
def update_node(self, node_id, values):
|
def update_node(self, node_id, values):
|
||||||
|
@ -871,3 +875,80 @@ class Connection(api.Connection):
|
||||||
raise exception.NodeNotFound(
|
raise exception.NodeNotFound(
|
||||||
_('Multiple nodes with port addresses %s were found')
|
_('Multiple nodes with port addresses %s were found')
|
||||||
% addresses)
|
% addresses)
|
||||||
|
|
||||||
|
def get_volume_connector_list(self, limit=None, marker=None,
|
||||||
|
sort_key=None, sort_dir=None):
|
||||||
|
return _paginate_query(models.VolumeConnector, limit, marker,
|
||||||
|
sort_key, sort_dir)
|
||||||
|
|
||||||
|
def get_volume_connector_by_id(self, id):
|
||||||
|
query = model_query(models.VolumeConnector).filter_by(id=id)
|
||||||
|
try:
|
||||||
|
return query.one()
|
||||||
|
except NoResultFound:
|
||||||
|
raise exception.VolumeConnectorNotFound(connector=id)
|
||||||
|
|
||||||
|
def get_volume_connector_by_uuid(self, connector_uuid):
|
||||||
|
query = model_query(models.VolumeConnector).filter_by(
|
||||||
|
uuid=connector_uuid)
|
||||||
|
try:
|
||||||
|
return query.one()
|
||||||
|
except NoResultFound:
|
||||||
|
raise exception.VolumeConnectorNotFound(connector=connector_uuid)
|
||||||
|
|
||||||
|
def get_volume_connectors_by_node_id(self, node_id, limit=None,
|
||||||
|
marker=None, sort_key=None,
|
||||||
|
sort_dir=None):
|
||||||
|
query = model_query(models.VolumeConnector).filter_by(node_id=node_id)
|
||||||
|
return _paginate_query(models.VolumeConnector, limit, marker,
|
||||||
|
sort_key, sort_dir, query)
|
||||||
|
|
||||||
|
def create_volume_connector(self, connector_info):
|
||||||
|
if 'uuid' not in connector_info:
|
||||||
|
connector_info['uuid'] = uuidutils.generate_uuid()
|
||||||
|
|
||||||
|
connector = models.VolumeConnector()
|
||||||
|
connector.update(connector_info)
|
||||||
|
with _session_for_write() as session:
|
||||||
|
try:
|
||||||
|
session.add(connector)
|
||||||
|
session.flush()
|
||||||
|
except db_exc.DBDuplicateEntry as exc:
|
||||||
|
if 'type' in exc.columns:
|
||||||
|
raise exception.VolumeConnectorTypeAndIdAlreadyExists(
|
||||||
|
type=connector_info['type'],
|
||||||
|
connector_id=connector_info['connector_id'])
|
||||||
|
raise exception.VolumeConnectorAlreadyExists(
|
||||||
|
uuid=connector_info['uuid'])
|
||||||
|
return connector
|
||||||
|
|
||||||
|
def update_volume_connector(self, ident, connector_info):
|
||||||
|
if 'uuid' in connector_info:
|
||||||
|
msg = _("Cannot overwrite UUID for an existing Volume Connector.")
|
||||||
|
raise exception.InvalidParameterValue(err=msg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with _session_for_write() as session:
|
||||||
|
query = model_query(models.VolumeConnector)
|
||||||
|
query = add_identity_filter(query, ident)
|
||||||
|
ref = query.one()
|
||||||
|
orig_type = ref['type']
|
||||||
|
orig_connector_id = ref['connector_id']
|
||||||
|
ref.update(connector_info)
|
||||||
|
session.flush()
|
||||||
|
except db_exc.DBDuplicateEntry:
|
||||||
|
raise exception.VolumeConnectorTypeAndIdAlreadyExists(
|
||||||
|
type=connector_info.get('type', orig_type),
|
||||||
|
connector_id=connector_info.get('connector_id',
|
||||||
|
orig_connector_id))
|
||||||
|
except NoResultFound:
|
||||||
|
raise exception.VolumeConnectorNotFound(connector=ident)
|
||||||
|
return ref
|
||||||
|
|
||||||
|
def destroy_volume_connector(self, ident):
|
||||||
|
with _session_for_write():
|
||||||
|
query = model_query(models.VolumeConnector)
|
||||||
|
query = add_identity_filter(query, ident)
|
||||||
|
count = query.delete()
|
||||||
|
if count == 0:
|
||||||
|
raise exception.VolumeConnectorNotFound(connector=ident)
|
||||||
|
|
|
@ -210,3 +210,22 @@ class NodeTag(Base):
|
||||||
primaryjoin='and_(NodeTag.node_id == Node.id)',
|
primaryjoin='and_(NodeTag.node_id == Node.id)',
|
||||||
foreign_keys=node_id
|
foreign_keys=node_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class VolumeConnector(Base):
|
||||||
|
"""Represents a volume connector of a bare metal node."""
|
||||||
|
|
||||||
|
__tablename__ = 'volume_connectors'
|
||||||
|
__table_args__ = (
|
||||||
|
schema.UniqueConstraint('uuid', name='uniq_volumeconnectors0uuid'),
|
||||||
|
schema.UniqueConstraint(
|
||||||
|
'type',
|
||||||
|
'connector_id',
|
||||||
|
name='uniq_volumeconnectors0type0connector_id'),
|
||||||
|
table_args())
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
uuid = Column(String(36))
|
||||||
|
node_id = Column(Integer, ForeignKey('nodes.id'), nullable=True)
|
||||||
|
type = Column(String(32))
|
||||||
|
connector_id = Column(String(255))
|
||||||
|
extra = Column(db_types.JsonEncodedDict)
|
||||||
|
|
|
@ -547,6 +547,43 @@ class MigrationCheckersMixin(object):
|
||||||
self.assertIsInstance(getattr(nodes.c, name).type,
|
self.assertIsInstance(getattr(nodes.c, name).type,
|
||||||
sqlalchemy.types.String)
|
sqlalchemy.types.String)
|
||||||
|
|
||||||
|
def _check_daa1ba02d98(self, engine, data):
|
||||||
|
connectors = db_utils.get_table(engine, 'volume_connectors')
|
||||||
|
col_names = [column.name for column in connectors.c]
|
||||||
|
expected_names = ['created_at', 'updated_at', 'id', 'uuid', 'node_id',
|
||||||
|
'type', 'connector_id', 'extra']
|
||||||
|
self.assertEqual(sorted(expected_names), sorted(col_names))
|
||||||
|
|
||||||
|
self.assertIsInstance(connectors.c.created_at.type,
|
||||||
|
sqlalchemy.types.DateTime)
|
||||||
|
self.assertIsInstance(connectors.c.updated_at.type,
|
||||||
|
sqlalchemy.types.DateTime)
|
||||||
|
self.assertIsInstance(connectors.c.id.type,
|
||||||
|
sqlalchemy.types.Integer)
|
||||||
|
self.assertIsInstance(connectors.c.uuid.type,
|
||||||
|
sqlalchemy.types.String)
|
||||||
|
self.assertIsInstance(connectors.c.node_id.type,
|
||||||
|
sqlalchemy.types.Integer)
|
||||||
|
self.assertIsInstance(connectors.c.type.type,
|
||||||
|
sqlalchemy.types.String)
|
||||||
|
self.assertIsInstance(connectors.c.connector_id.type,
|
||||||
|
sqlalchemy.types.String)
|
||||||
|
self.assertIsInstance(connectors.c.extra.type,
|
||||||
|
sqlalchemy.types.TEXT)
|
||||||
|
|
||||||
|
typestring = 'a' * 32
|
||||||
|
connector_idstring = 'a' * 255
|
||||||
|
uuid = uuidutils.generate_uuid()
|
||||||
|
data = {'uuid': uuid, 'node_id': 1, 'type': typestring,
|
||||||
|
'connector_id': connector_idstring, 'extra': '{}'}
|
||||||
|
connectors.insert().execute(data)
|
||||||
|
connector = connectors.select(
|
||||||
|
connectors.c.uuid == uuid).execute().first()
|
||||||
|
self.assertEqual(typestring, connector['type'])
|
||||||
|
self.assertEqual(connector_idstring, connector['connector_id'])
|
||||||
|
self.assertEqual(1, connector['node_id'])
|
||||||
|
self.assertEqual('{}', connector['extra'])
|
||||||
|
|
||||||
def test_upgrade_and_version(self):
|
def test_upgrade_and_version(self):
|
||||||
with patch_with_engine(self.engine):
|
with patch_with_engine(self.engine):
|
||||||
self.migration_api.upgrade('head')
|
self.migration_api.upgrade('head')
|
||||||
|
|
|
@ -359,6 +359,26 @@ class DbNodeTestCase(base.DbTestCase):
|
||||||
self.dbapi.destroy_node(node.uuid)
|
self.dbapi.destroy_node(node.uuid)
|
||||||
self.assertFalse(self.dbapi.node_tag_exists(node.id, tag.tag))
|
self.assertFalse(self.dbapi.node_tag_exists(node.id, tag.tag))
|
||||||
|
|
||||||
|
def test_volume_connector_get_destroyed_after_destroying_a_node(self):
|
||||||
|
node = utils.create_test_node()
|
||||||
|
|
||||||
|
connector = utils.create_test_volume_connector(node_id=node.id)
|
||||||
|
|
||||||
|
self.dbapi.destroy_node(node.id)
|
||||||
|
|
||||||
|
self.assertRaises(exception.VolumeConnectorNotFound,
|
||||||
|
self.dbapi.get_volume_connector_by_id, connector.id)
|
||||||
|
|
||||||
|
def test_volume_connector_get_destroyed_after_destroying_a_node_uuid(self):
|
||||||
|
node = utils.create_test_node()
|
||||||
|
|
||||||
|
connector = utils.create_test_volume_connector(node_id=node.id)
|
||||||
|
|
||||||
|
self.dbapi.destroy_node(node.uuid)
|
||||||
|
|
||||||
|
self.assertRaises(exception.VolumeConnectorNotFound,
|
||||||
|
self.dbapi.get_volume_connector_by_id, connector.id)
|
||||||
|
|
||||||
def test_update_node(self):
|
def test_update_node(self):
|
||||||
node = utils.create_test_node()
|
node = utils.create_test_node()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
# Copyright 2015 Hitachi Data Systems
|
||||||
|
#
|
||||||
|
# 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 VolumeConnectors 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 DbVolumeConnectorTestCase(base.DbTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# This method creates a volume_connector for every test and
|
||||||
|
# replaces a test for creating a volume_connector.
|
||||||
|
super(DbVolumeConnectorTestCase, self).setUp()
|
||||||
|
self.node = db_utils.create_test_node()
|
||||||
|
self.connector = db_utils.create_test_volume_connector(
|
||||||
|
node_id=self.node.id, type='test',
|
||||||
|
connector_id='test-connector_id')
|
||||||
|
|
||||||
|
def test_create_volume_connector_duplicated_type_connector_id(self):
|
||||||
|
self.assertRaises(exception.VolumeConnectorTypeAndIdAlreadyExists,
|
||||||
|
db_utils.create_test_volume_connector,
|
||||||
|
uuid=uuidutils.generate_uuid(),
|
||||||
|
node_id=self.node.id,
|
||||||
|
type=self.connector.type,
|
||||||
|
connector_id=self.connector.connector_id)
|
||||||
|
|
||||||
|
def test_create_volume_connector_duplicated_uuid(self):
|
||||||
|
self.assertRaises(exception.VolumeConnectorAlreadyExists,
|
||||||
|
db_utils.create_test_volume_connector,
|
||||||
|
uuid=self.connector.uuid,
|
||||||
|
node_id=self.node.id,
|
||||||
|
type='test',
|
||||||
|
connector_id='test-connector_id-2')
|
||||||
|
|
||||||
|
def test_get_volume_connector_by_id(self):
|
||||||
|
res = self.dbapi.get_volume_connector_by_id(self.connector.id)
|
||||||
|
self.assertEqual(self.connector.type, res.type)
|
||||||
|
self.assertEqual(self.connector.connector_id, res.connector_id)
|
||||||
|
self.assertRaises(exception.VolumeConnectorNotFound,
|
||||||
|
self.dbapi.get_volume_connector_by_id,
|
||||||
|
-1)
|
||||||
|
|
||||||
|
def test_get_volume_connector_by_uuid(self):
|
||||||
|
res = self.dbapi.get_volume_connector_by_uuid(self.connector.uuid)
|
||||||
|
self.assertEqual(self.connector.id, res.id)
|
||||||
|
self.assertRaises(exception.VolumeConnectorNotFound,
|
||||||
|
self.dbapi.get_volume_connector_by_uuid,
|
||||||
|
-1)
|
||||||
|
|
||||||
|
def _connector_list_preparation(self):
|
||||||
|
uuids = [six.text_type(self.connector.uuid)]
|
||||||
|
for i in range(1, 6):
|
||||||
|
volume_connector = db_utils.create_test_volume_connector(
|
||||||
|
uuid=uuidutils.generate_uuid(),
|
||||||
|
type='iqn',
|
||||||
|
connector_id='iqn.test-%s' % i)
|
||||||
|
uuids.append(six.text_type(volume_connector.uuid))
|
||||||
|
return uuids
|
||||||
|
|
||||||
|
def test_get_volume_connector_list(self):
|
||||||
|
uuids = self._connector_list_preparation()
|
||||||
|
res = self.dbapi.get_volume_connector_list()
|
||||||
|
res_uuids = [r.uuid for r in res]
|
||||||
|
six.assertCountEqual(self, uuids, res_uuids)
|
||||||
|
|
||||||
|
def test_get_volume_connector_list_sorted(self):
|
||||||
|
uuids = self._connector_list_preparation()
|
||||||
|
res = self.dbapi.get_volume_connector_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_connector_list, sort_key='foo')
|
||||||
|
|
||||||
|
def test_get_volume_connectors_by_node_id(self):
|
||||||
|
res = self.dbapi.get_volume_connectors_by_node_id(self.node.id)
|
||||||
|
self.assertEqual(self.connector.type, res[0].type)
|
||||||
|
self.assertEqual(self.connector.connector_id, res[0].connector_id)
|
||||||
|
|
||||||
|
def test_get_volume_connectors_by_node_id_that_does_not_exist(self):
|
||||||
|
self.assertEqual([], self.dbapi.get_volume_connectors_by_node_id(99))
|
||||||
|
|
||||||
|
def test_update_volume_connector(self):
|
||||||
|
old_connector_id = self.connector.connector_id
|
||||||
|
new_connector_id = 'test-connector_id-2'
|
||||||
|
|
||||||
|
self.assertNotEqual(old_connector_id, new_connector_id)
|
||||||
|
|
||||||
|
res = self.dbapi.update_volume_connector(
|
||||||
|
self.connector.id,
|
||||||
|
{'connector_id': new_connector_id})
|
||||||
|
self.assertEqual(new_connector_id, res.connector_id)
|
||||||
|
res = self.dbapi.update_volume_connector(
|
||||||
|
self.connector.uuid,
|
||||||
|
{'connector_id': old_connector_id})
|
||||||
|
self.assertEqual(old_connector_id, res.connector_id)
|
||||||
|
|
||||||
|
def test_update_volume_connector_uuid(self):
|
||||||
|
self.assertRaises(exception.InvalidParameterValue,
|
||||||
|
self.dbapi.update_volume_connector,
|
||||||
|
self.connector.id,
|
||||||
|
{'uuid': ''})
|
||||||
|
|
||||||
|
def test_update_volume_connector_fails_invalid_id(self):
|
||||||
|
self.assertRaises(exception.VolumeConnectorNotFound,
|
||||||
|
self.dbapi.update_volume_connector,
|
||||||
|
-1,
|
||||||
|
{'node_id': ''})
|
||||||
|
|
||||||
|
def test_update_volume_connector_duplicated_type_connector_id(self):
|
||||||
|
type = self.connector.type
|
||||||
|
connector_id1 = self.connector.connector_id
|
||||||
|
connector_id2 = 'test-connector_id-2'
|
||||||
|
volume_connector2 = db_utils.create_test_volume_connector(
|
||||||
|
uuid=uuidutils.generate_uuid(),
|
||||||
|
node_id=self.node.id,
|
||||||
|
type=type,
|
||||||
|
connector_id=connector_id2)
|
||||||
|
self.assertRaises(exception.VolumeConnectorTypeAndIdAlreadyExists,
|
||||||
|
self.dbapi.update_volume_connector,
|
||||||
|
volume_connector2.id,
|
||||||
|
{'connector_id': connector_id1})
|
||||||
|
|
||||||
|
def test_destroy_volume_connector(self):
|
||||||
|
self.dbapi.destroy_volume_connector(self.connector.id)
|
||||||
|
# Attempt to retrieve the volume to verify it is gone.
|
||||||
|
self.assertRaises(exception.VolumeConnectorNotFound,
|
||||||
|
self.dbapi.get_volume_connector_by_id,
|
||||||
|
self.connector.id)
|
||||||
|
# Ensure that the destroy_volume_connector returns the
|
||||||
|
# expected exception.
|
||||||
|
self.assertRaises(exception.VolumeConnectorNotFound,
|
||||||
|
self.dbapi.destroy_volume_connector,
|
||||||
|
self.connector.id)
|
|
@ -315,6 +315,37 @@ def create_test_port(**kw):
|
||||||
return dbapi.create_port(port)
|
return dbapi.create_port(port)
|
||||||
|
|
||||||
|
|
||||||
|
def get_test_volume_connector(**kw):
|
||||||
|
return {
|
||||||
|
'id': kw.get('id', 789),
|
||||||
|
'uuid': kw.get('uuid', '1be26c0b-03f2-4d2e-ae87-c02d7f33c781'),
|
||||||
|
'node_id': kw.get('node_id', 123),
|
||||||
|
'type': kw.get('type', 'iqn'),
|
||||||
|
'connector_id': kw.get('connector_id',
|
||||||
|
'iqn.2012-06.com.example:initiator'),
|
||||||
|
'extra': kw.get('extra', {}),
|
||||||
|
'created_at': kw.get('created_at'),
|
||||||
|
'updated_at': kw.get('updated_at'),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def create_test_volume_connector(**kw):
|
||||||
|
"""Create test connector entry in DB and return VolumeConnector DB object.
|
||||||
|
|
||||||
|
Function to be used to create test VolumeConnector objects in the database.
|
||||||
|
|
||||||
|
:param kw: kwargs with overriding values for connector's attributes.
|
||||||
|
:returns: Test VolumeConnector DB object.
|
||||||
|
|
||||||
|
"""
|
||||||
|
connector = get_test_volume_connector(**kw)
|
||||||
|
# Let DB generate ID if it isn't specified explicitly
|
||||||
|
if 'id' not in kw:
|
||||||
|
del connector['id']
|
||||||
|
dbapi = db_api.get_instance()
|
||||||
|
return dbapi.create_volume_connector(connector)
|
||||||
|
|
||||||
|
|
||||||
def get_test_chassis(**kw):
|
def get_test_chassis(**kw):
|
||||||
return {
|
return {
|
||||||
'id': kw.get('id', 42),
|
'id': kw.get('id', 42),
|
||||||
|
|
Loading…
Reference in New Issue