Merge "Support port name"
This commit is contained in:
commit
f11f330d00
@ -77,6 +77,10 @@ class PortAlreadyExists(Conflict):
|
|||||||
_msg_fmt = _("A port with UUID %(uuid)s already exists.")
|
_msg_fmt = _("A port with UUID %(uuid)s already exists.")
|
||||||
|
|
||||||
|
|
||||||
|
class PortDuplicateName(Conflict):
|
||||||
|
_msg_fmt = _("A port with name %(name)s already exists.")
|
||||||
|
|
||||||
|
|
||||||
class PortgroupAlreadyExists(Conflict):
|
class PortgroupAlreadyExists(Conflict):
|
||||||
_msg_fmt = _("A portgroup with UUID %(uuid)s already exists.")
|
_msg_fmt = _("A portgroup with UUID %(uuid)s already exists.")
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ RELEASE_MAPPING = {
|
|||||||
'Chassis': ['1.3'],
|
'Chassis': ['1.3'],
|
||||||
'Deployment': ['1.0'],
|
'Deployment': ['1.0'],
|
||||||
'DeployTemplate': ['1.1'],
|
'DeployTemplate': ['1.1'],
|
||||||
'Port': ['1.9'],
|
'Port': ['1.10'],
|
||||||
'Portgroup': ['1.4'],
|
'Portgroup': ['1.4'],
|
||||||
'Trait': ['1.0'],
|
'Trait': ['1.0'],
|
||||||
'TraitList': ['1.0'],
|
'TraitList': ['1.0'],
|
||||||
|
@ -251,6 +251,14 @@ class Connection(object, metaclass=abc.ABCMeta):
|
|||||||
:returns: A port.
|
:returns: A port.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_port_by_name(self, port_name):
|
||||||
|
"""Return a network port representation.
|
||||||
|
|
||||||
|
:param port_name: The name of a port.
|
||||||
|
:returns: A port.
|
||||||
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def get_port_list(self, limit=None, marker=None,
|
def get_port_list(self, limit=None, marker=None,
|
||||||
sort_key=None, sort_dir=None):
|
sort_key=None, sort_dir=None):
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
"""port-name
|
||||||
|
|
||||||
|
Revision ID: c0455649680c
|
||||||
|
Revises: cf1a80fdb352
|
||||||
|
Create Date: 2020-11-27 20:12:24.752897
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'c0455649680c'
|
||||||
|
down_revision = 'cf1a80fdb352'
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column('ports', sa.Column('name', sa.String(length=255),
|
||||||
|
nullable=True))
|
||||||
|
op.create_unique_constraint('uniq_ports0name', 'ports', ['name'])
|
@ -705,6 +705,13 @@ class Connection(api.Connection):
|
|||||||
except NoResultFound:
|
except NoResultFound:
|
||||||
raise exception.PortNotFound(port=address)
|
raise exception.PortNotFound(port=address)
|
||||||
|
|
||||||
|
def get_port_by_name(self, port_name):
|
||||||
|
query = model_query(models.Port).filter_by(name=port_name)
|
||||||
|
try:
|
||||||
|
return query.one()
|
||||||
|
except NoResultFound:
|
||||||
|
raise exception.PortNotFound(port=port_name)
|
||||||
|
|
||||||
def get_port_list(self, limit=None, marker=None,
|
def get_port_list(self, limit=None, marker=None,
|
||||||
sort_key=None, sort_dir=None, owner=None,
|
sort_key=None, sort_dir=None, owner=None,
|
||||||
project=None):
|
project=None):
|
||||||
@ -773,8 +780,11 @@ class Connection(api.Connection):
|
|||||||
session.flush()
|
session.flush()
|
||||||
except NoResultFound:
|
except NoResultFound:
|
||||||
raise exception.PortNotFound(port=port_id)
|
raise exception.PortNotFound(port=port_id)
|
||||||
except db_exc.DBDuplicateEntry:
|
except db_exc.DBDuplicateEntry as exc:
|
||||||
raise exception.MACAlreadyExists(mac=values['address'])
|
if 'name' in exc.columns:
|
||||||
|
raise exception.PortDuplicateName(name=values['name'])
|
||||||
|
else:
|
||||||
|
raise exception.MACAlreadyExists(mac=values['address'])
|
||||||
return ref
|
return ref
|
||||||
|
|
||||||
@oslo_db_api.retry_on_deadlock
|
@oslo_db_api.retry_on_deadlock
|
||||||
|
@ -210,6 +210,7 @@ class Port(Base):
|
|||||||
__table_args__ = (
|
__table_args__ = (
|
||||||
schema.UniqueConstraint('address', name='uniq_ports0address'),
|
schema.UniqueConstraint('address', name='uniq_ports0address'),
|
||||||
schema.UniqueConstraint('uuid', name='uniq_ports0uuid'),
|
schema.UniqueConstraint('uuid', name='uniq_ports0uuid'),
|
||||||
|
schema.UniqueConstraint('name', name='uniq_ports0name'),
|
||||||
table_args())
|
table_args())
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
uuid = Column(String(36))
|
uuid = Column(String(36))
|
||||||
@ -222,6 +223,7 @@ class Port(Base):
|
|||||||
internal_info = Column(db_types.JsonEncodedDict)
|
internal_info = Column(db_types.JsonEncodedDict)
|
||||||
physical_network = Column(String(64), nullable=True)
|
physical_network = Column(String(64), nullable=True)
|
||||||
is_smartnic = Column(Boolean, nullable=True, default=False)
|
is_smartnic = Column(Boolean, nullable=True, default=False)
|
||||||
|
name = Column(String(255), nullable=True)
|
||||||
|
|
||||||
|
|
||||||
class Portgroup(Base):
|
class Portgroup(Base):
|
||||||
|
@ -20,6 +20,7 @@ from oslo_utils import versionutils
|
|||||||
from oslo_versionedobjects import base as object_base
|
from oslo_versionedobjects import base as object_base
|
||||||
|
|
||||||
from ironic.common import exception
|
from ironic.common import exception
|
||||||
|
from ironic.common import utils
|
||||||
from ironic.db import api as dbapi
|
from ironic.db import api as dbapi
|
||||||
from ironic.objects import base
|
from ironic.objects import base
|
||||||
from ironic.objects import fields as object_fields
|
from ironic.objects import fields as object_fields
|
||||||
@ -42,7 +43,8 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat):
|
|||||||
# internal_info['tenant_vif_port_id'] (not an explicit db
|
# internal_info['tenant_vif_port_id'] (not an explicit db
|
||||||
# change)
|
# change)
|
||||||
# Version 1.9: Add support for Smart NIC port
|
# Version 1.9: Add support for Smart NIC port
|
||||||
VERSION = '1.9'
|
# Version 1.10: Add name field
|
||||||
|
VERSION = '1.10'
|
||||||
|
|
||||||
dbapi = dbapi.get_instance()
|
dbapi = dbapi.get_instance()
|
||||||
|
|
||||||
@ -60,8 +62,26 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat):
|
|||||||
'physical_network': object_fields.StringField(nullable=True),
|
'physical_network': object_fields.StringField(nullable=True),
|
||||||
'is_smartnic': object_fields.BooleanField(nullable=True,
|
'is_smartnic': object_fields.BooleanField(nullable=True,
|
||||||
default=False),
|
default=False),
|
||||||
|
'name': object_fields.StringField(nullable=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _convert_name_field(self, target_version,
|
||||||
|
remove_unavailable_fields=True):
|
||||||
|
name_is_set = self.obj_attr_is_set('name')
|
||||||
|
if target_version >= (1, 10):
|
||||||
|
# Target version supports name. Set it to its default
|
||||||
|
# value if it is not set.
|
||||||
|
if not name_is_set:
|
||||||
|
self.name = None
|
||||||
|
elif name_is_set:
|
||||||
|
# Target version does not support name, and it is set.
|
||||||
|
if remove_unavailable_fields:
|
||||||
|
# (De)serialising: remove unavailable fields.
|
||||||
|
delattr(self, 'name')
|
||||||
|
elif self.name is not None:
|
||||||
|
# DB: set unavailable fields to their default.
|
||||||
|
self.name = None
|
||||||
|
|
||||||
def _convert_to_version(self, target_version,
|
def _convert_to_version(self, target_version,
|
||||||
remove_unavailable_fields=True):
|
remove_unavailable_fields=True):
|
||||||
"""Convert to the target version.
|
"""Convert to the target version.
|
||||||
@ -82,6 +102,9 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat):
|
|||||||
Version 1.9: remove is_smartnic field for unsupported versions if
|
Version 1.9: remove is_smartnic field for unsupported versions if
|
||||||
remove_unavailable_fields is True.
|
remove_unavailable_fields is True.
|
||||||
|
|
||||||
|
Version 1.10: remove name field for unsupported versions if
|
||||||
|
remove_unavailable_fields is True.
|
||||||
|
|
||||||
:param target_version: the desired version of the object
|
:param target_version: the desired version of the object
|
||||||
:param remove_unavailable_fields: True to remove fields that are
|
:param remove_unavailable_fields: True to remove fields that are
|
||||||
unavailable in the target version; set this to True when
|
unavailable in the target version; set this to True when
|
||||||
@ -134,6 +157,9 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat):
|
|||||||
# DB: set unavailable fields to their default.
|
# DB: set unavailable fields to their default.
|
||||||
self.is_smartnic = False
|
self.is_smartnic = False
|
||||||
|
|
||||||
|
# Convert the name field.
|
||||||
|
self._convert_name_field(target_version, remove_unavailable_fields)
|
||||||
|
|
||||||
# NOTE(xek): We don't want to enable RPC on this call just yet. Remotable
|
# NOTE(xek): We don't want to enable RPC on this call just yet. Remotable
|
||||||
# methods can be used in the future to replace current explicit RPC calls.
|
# methods can be used in the future to replace current explicit RPC calls.
|
||||||
# Implications of calling new remote procedures should be thought through.
|
# Implications of calling new remote procedures should be thought through.
|
||||||
@ -142,11 +168,11 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat):
|
|||||||
def get(cls, context, port_id):
|
def get(cls, context, port_id):
|
||||||
"""Find a port.
|
"""Find a port.
|
||||||
|
|
||||||
Find a port based on its id or uuid or MAC address and return a Port
|
Find a port based on its id or uuid or name or MAC address and return
|
||||||
object.
|
a Port object.
|
||||||
|
|
||||||
:param context: Security context
|
:param context: Security context
|
||||||
:param port_id: the id *or* uuid *or* MAC address of a port.
|
:param port_id: the id *or* uuid *or* name *or* MAC address of a port.
|
||||||
:returns: a :class:`Port` object.
|
:returns: a :class:`Port` object.
|
||||||
:raises: InvalidIdentity
|
:raises: InvalidIdentity
|
||||||
|
|
||||||
@ -157,6 +183,8 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat):
|
|||||||
return cls.get_by_uuid(context, port_id)
|
return cls.get_by_uuid(context, port_id)
|
||||||
elif netutils.is_valid_mac(port_id):
|
elif netutils.is_valid_mac(port_id):
|
||||||
return cls.get_by_address(context, port_id)
|
return cls.get_by_address(context, port_id)
|
||||||
|
elif utils.is_valid_logical_name(port_id):
|
||||||
|
return cls.get_by_name(context, port_id)
|
||||||
else:
|
else:
|
||||||
raise exception.InvalidIdentity(identity=port_id)
|
raise exception.InvalidIdentity(identity=port_id)
|
||||||
|
|
||||||
@ -221,6 +249,25 @@ class Port(base.IronicObject, object_base.VersionedObjectDictCompat):
|
|||||||
port = cls._from_db_object(context, cls(), db_port)
|
port = cls._from_db_object(context, cls(), db_port)
|
||||||
return port
|
return port
|
||||||
|
|
||||||
|
# NOTE(xek): We don't want to enable RPC on this call just yet. Remotable
|
||||||
|
# methods can be used in the future to replace current explicit RPC calls.
|
||||||
|
# Implications of calling new remote procedures should be thought through.
|
||||||
|
# @object_base.remotable_classmethod
|
||||||
|
@classmethod
|
||||||
|
def get_by_name(cls, context, name):
|
||||||
|
"""Find a port based on name and return a :class:`Port` object.
|
||||||
|
|
||||||
|
:param cls: the :class:`Port`
|
||||||
|
:param context: Security context
|
||||||
|
:param name: the name of a port.
|
||||||
|
:returns: a :class:`Port` object.
|
||||||
|
:raises: PortNotFound
|
||||||
|
|
||||||
|
"""
|
||||||
|
db_port = cls.dbapi.get_port_by_name(name)
|
||||||
|
port = cls._from_db_object(context, cls(), db_port)
|
||||||
|
return port
|
||||||
|
|
||||||
# NOTE(xek): We don't want to enable RPC on this call just yet. Remotable
|
# NOTE(xek): We don't want to enable RPC on this call just yet. Remotable
|
||||||
# methods can be used in the future to replace current explicit RPC calls.
|
# methods can be used in the future to replace current explicit RPC calls.
|
||||||
# Implications of calling new remote procedures should be thought through.
|
# Implications of calling new remote procedures should be thought through.
|
||||||
@ -435,7 +482,8 @@ class PortCRUDPayload(notification.NotificationPayloadBase):
|
|||||||
# Version 1.1: Add "portgroup_uuid" field
|
# Version 1.1: Add "portgroup_uuid" field
|
||||||
# Version 1.2: Add "physical_network" field
|
# Version 1.2: Add "physical_network" field
|
||||||
# Version 1.3: Add "is_smartnic" field
|
# Version 1.3: Add "is_smartnic" field
|
||||||
VERSION = '1.3'
|
# Version 1.4: Add "name" field
|
||||||
|
VERSION = '1.4'
|
||||||
|
|
||||||
SCHEMA = {
|
SCHEMA = {
|
||||||
'address': ('port', 'address'),
|
'address': ('port', 'address'),
|
||||||
@ -447,6 +495,7 @@ class PortCRUDPayload(notification.NotificationPayloadBase):
|
|||||||
'updated_at': ('port', 'updated_at'),
|
'updated_at': ('port', 'updated_at'),
|
||||||
'uuid': ('port', 'uuid'),
|
'uuid': ('port', 'uuid'),
|
||||||
'is_smartnic': ('port', 'is_smartnic'),
|
'is_smartnic': ('port', 'is_smartnic'),
|
||||||
|
'name': ('port', 'name'),
|
||||||
}
|
}
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
@ -463,6 +512,7 @@ class PortCRUDPayload(notification.NotificationPayloadBase):
|
|||||||
'uuid': object_fields.UUIDField(),
|
'uuid': object_fields.UUIDField(),
|
||||||
'is_smartnic': object_fields.BooleanField(nullable=True,
|
'is_smartnic': object_fields.BooleanField(nullable=True,
|
||||||
default=False),
|
default=False),
|
||||||
|
'name': object_fields.StringField(nullable=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, port, node_uuid, portgroup_uuid):
|
def __init__(self, port, node_uuid, portgroup_uuid):
|
||||||
|
@ -1002,6 +1002,11 @@ class MigrationCheckersMixin(object):
|
|||||||
col_names = [column.name for column in nodes.c]
|
col_names = [column.name for column in nodes.c]
|
||||||
self.assertIn('lessee', col_names)
|
self.assertIn('lessee', col_names)
|
||||||
|
|
||||||
|
def _check_c0455649680c(self, engine, data):
|
||||||
|
ports = db_utils.get_table(engine, 'ports')
|
||||||
|
col_names = [column.name for column in ports.c]
|
||||||
|
self.assertIn('name', col_names)
|
||||||
|
|
||||||
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')
|
||||||
|
@ -32,7 +32,8 @@ class DbPortTestCase(base.DbTestCase):
|
|||||||
lessee='54321')
|
lessee='54321')
|
||||||
self.portgroup = db_utils.create_test_portgroup(node_id=self.node.id)
|
self.portgroup = db_utils.create_test_portgroup(node_id=self.node.id)
|
||||||
self.port = db_utils.create_test_port(node_id=self.node.id,
|
self.port = db_utils.create_test_port(node_id=self.node.id,
|
||||||
portgroup_id=self.portgroup.id)
|
portgroup_id=self.portgroup.id,
|
||||||
|
name='port-name')
|
||||||
|
|
||||||
def test_get_port_by_id(self):
|
def test_get_port_by_id(self):
|
||||||
res = self.dbapi.get_port_by_id(self.port.id)
|
res = self.dbapi.get_port_by_id(self.port.id)
|
||||||
@ -68,6 +69,10 @@ class DbPortTestCase(base.DbTestCase):
|
|||||||
self.port.address,
|
self.port.address,
|
||||||
project='55555')
|
project='55555')
|
||||||
|
|
||||||
|
def test_get_port_by_name(self):
|
||||||
|
res = self.dbapi.get_port_by_name(self.port.name)
|
||||||
|
self.assertEqual(self.port.id, res.id)
|
||||||
|
|
||||||
def test_get_port_list(self):
|
def test_get_port_list(self):
|
||||||
uuids = []
|
uuids = []
|
||||||
for i in range(1, 6):
|
for i in range(1, 6):
|
||||||
|
@ -277,6 +277,7 @@ def get_test_port(**kw):
|
|||||||
'internal_info': kw.get('internal_info', {"bar": "buzz"}),
|
'internal_info': kw.get('internal_info', {"bar": "buzz"}),
|
||||||
'physical_network': kw.get('physical_network'),
|
'physical_network': kw.get('physical_network'),
|
||||||
'is_smartnic': kw.get('is_smartnic', False),
|
'is_smartnic': kw.get('is_smartnic', False),
|
||||||
|
'name': kw.get('name'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -679,7 +679,7 @@ expected_object_fingerprints = {
|
|||||||
'Node': '1.35-aee8ecf5c4d0ed590eb484762aee7fca',
|
'Node': '1.35-aee8ecf5c4d0ed590eb484762aee7fca',
|
||||||
'MyObj': '1.5-9459d30d6954bffc7a9afd347a807ca6',
|
'MyObj': '1.5-9459d30d6954bffc7a9afd347a807ca6',
|
||||||
'Chassis': '1.3-d656e039fd8ae9f34efc232ab3980905',
|
'Chassis': '1.3-d656e039fd8ae9f34efc232ab3980905',
|
||||||
'Port': '1.9-0cb9202a4ec442e8c0d87a324155eaaf',
|
'Port': '1.10-67381b065c597c8d3a13c5dbc6243c33',
|
||||||
'Portgroup': '1.4-71923a81a86743b313b190f5c675e258',
|
'Portgroup': '1.4-71923a81a86743b313b190f5c675e258',
|
||||||
'Conductor': '1.3-d3f53e853b4d58cae5bfbd9a8341af4a',
|
'Conductor': '1.3-d3f53e853b4d58cae5bfbd9a8341af4a',
|
||||||
'EventType': '1.1-aa2ba1afd38553e3880c267404e8d370',
|
'EventType': '1.1-aa2ba1afd38553e3880c267404e8d370',
|
||||||
@ -700,7 +700,7 @@ expected_object_fingerprints = {
|
|||||||
'NodeCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',
|
'NodeCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',
|
||||||
'NodeCRUDPayload': '1.13-8f673253ff8d7389897a6a80d224ac33',
|
'NodeCRUDPayload': '1.13-8f673253ff8d7389897a6a80d224ac33',
|
||||||
'PortCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',
|
'PortCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',
|
||||||
'PortCRUDPayload': '1.3-21235916ed54a91b2a122f59571194e7',
|
'PortCRUDPayload': '1.4-9411a1701077ae9dc0aea27d6bf586fc',
|
||||||
'NodeMaintenanceNotification': '1.0-59acc533c11d306f149846f922739c15',
|
'NodeMaintenanceNotification': '1.0-59acc533c11d306f149846f922739c15',
|
||||||
'NodeConsoleNotification': '1.0-59acc533c11d306f149846f922739c15',
|
'NodeConsoleNotification': '1.0-59acc533c11d306f149846f922739c15',
|
||||||
'PortgroupCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',
|
'PortgroupCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',
|
||||||
|
@ -34,7 +34,7 @@ class TestPortObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestPortObject, self).setUp()
|
super(TestPortObject, self).setUp()
|
||||||
self.fake_port = db_utils.get_test_port()
|
self.fake_port = db_utils.get_test_port(name='port-name')
|
||||||
|
|
||||||
def test_get_by_id(self):
|
def test_get_by_id(self):
|
||||||
port_id = self.fake_port['id']
|
port_id = self.fake_port['id']
|
||||||
@ -69,9 +69,20 @@ class TestPortObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
|
|||||||
mock_get_port.assert_called_once_with(address, project=None)
|
mock_get_port.assert_called_once_with(address, project=None)
|
||||||
self.assertEqual(self.context, port._context)
|
self.assertEqual(self.context, port._context)
|
||||||
|
|
||||||
def test_get_bad_id_and_uuid_and_address(self):
|
def test_get_by_name(self):
|
||||||
|
name = self.fake_port['name']
|
||||||
|
with mock.patch.object(self.dbapi, 'get_port_by_name',
|
||||||
|
autospec=True) as mock_get_port:
|
||||||
|
mock_get_port.return_value = self.fake_port
|
||||||
|
|
||||||
|
port = objects.Port.get(self.context, name)
|
||||||
|
|
||||||
|
mock_get_port.assert_called_once_with(name)
|
||||||
|
self.assertEqual(self.context, port._context)
|
||||||
|
|
||||||
|
def test_get_bad_id_and_uuid_and_name_and_address(self):
|
||||||
self.assertRaises(exception.InvalidIdentity,
|
self.assertRaises(exception.InvalidIdentity,
|
||||||
objects.Port.get, self.context, 'not-a-uuid')
|
objects.Port.get, self.context, '#not-valid')
|
||||||
|
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
port = objects.Port(self.context, **self.fake_port)
|
port = objects.Port(self.context, **self.fake_port)
|
||||||
@ -349,3 +360,59 @@ class TestConvertToVersion(db_base.DbTestCase):
|
|||||||
port._convert_to_version("1.8", False)
|
port._convert_to_version("1.8", False)
|
||||||
self.assertFalse(port.is_smartnic)
|
self.assertFalse(port.is_smartnic)
|
||||||
self.assertNotIn('is_smartnic', port.obj_get_changes())
|
self.assertNotIn('is_smartnic', port.obj_get_changes())
|
||||||
|
|
||||||
|
def test_name_supported_missing(self):
|
||||||
|
# name not set, should be set to default.
|
||||||
|
port = objects.Port(self.context, **self.fake_port)
|
||||||
|
delattr(port, 'name')
|
||||||
|
port.obj_reset_changes()
|
||||||
|
port._convert_to_version("1.10")
|
||||||
|
self.assertIsNone(port.name)
|
||||||
|
self.assertIn('name', port.obj_get_changes())
|
||||||
|
self.assertIsNone(port.obj_get_changes()['name'])
|
||||||
|
|
||||||
|
def test_name_supported_set(self):
|
||||||
|
# Physical network set, no change required.
|
||||||
|
port = objects.Port(self.context, **self.fake_port)
|
||||||
|
port.name = 'meow'
|
||||||
|
port.obj_reset_changes()
|
||||||
|
port._convert_to_version("1.10")
|
||||||
|
self.assertEqual('meow', port.name)
|
||||||
|
self.assertNotIn('name', port.obj_get_changes())
|
||||||
|
|
||||||
|
def test_name_unsupported_missing(self):
|
||||||
|
# name not set, no change required.
|
||||||
|
port = objects.Port(self.context, **self.fake_port)
|
||||||
|
delattr(port, 'name')
|
||||||
|
port.obj_reset_changes()
|
||||||
|
port._convert_to_version("1.9")
|
||||||
|
self.assertNotIn('name', port)
|
||||||
|
self.assertNotIn('name', port.obj_get_changes())
|
||||||
|
|
||||||
|
def test_name_unsupported_set_remove(self):
|
||||||
|
# name set, should be removed.
|
||||||
|
port = objects.Port(self.context, **self.fake_port)
|
||||||
|
port.name = 'meow'
|
||||||
|
port.obj_reset_changes()
|
||||||
|
port._convert_to_version("1.9")
|
||||||
|
self.assertNotIn('name', port)
|
||||||
|
self.assertNotIn('name', port.obj_get_changes())
|
||||||
|
|
||||||
|
def test_name_unsupported_set_no_remove_non_default(self):
|
||||||
|
# name set, should be set to default.
|
||||||
|
port = objects.Port(self.context, **self.fake_port)
|
||||||
|
port.name = 'meow'
|
||||||
|
port.obj_reset_changes()
|
||||||
|
port._convert_to_version("1.9", False)
|
||||||
|
self.assertIsNone(port.name)
|
||||||
|
self.assertIn('name', port.obj_get_changes())
|
||||||
|
self.assertIsNone(port.obj_get_changes()['name'])
|
||||||
|
|
||||||
|
def test_name_unsupported_set_no_remove_default(self):
|
||||||
|
# name set, no change required.
|
||||||
|
port = objects.Port(self.context, **self.fake_port)
|
||||||
|
port.name = None
|
||||||
|
port.obj_reset_changes()
|
||||||
|
port._convert_to_version("1.9", False)
|
||||||
|
self.assertIsNone(port.name)
|
||||||
|
self.assertNotIn('name', port.obj_get_changes())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user