Clear OVO history and compatibility
The Oslo Versioned Objects history is used to generate the manifests required to do compatibility changes to OVOs on data serialization between services running with different OVO history versions. We haven't updated our OVO history since Train so all the history and compatibility code (obj_make_compatible method) is no longer necessary. This patch consolidates the OVO history into a single version reflecting the current status of the OVO versions and removes the compatibility code from the OVO classes. Since we tend to forget to update the obj_make_compatible when we add a field (like it happened with Volume in version 1.8 when we added shared_targets) this patch also adds a note next to the "fields" attribute (except for the list OVOs which are never updated). Change-Id: Ibfacccfb7c7dc70bc8f8e5ab98cc9c8feae694fb
This commit is contained in:
parent
28d9bca7d6
commit
b78997c2bb
@ -15,7 +15,6 @@
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import base64
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import versionutils
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from cinder import db
|
||||
@ -45,6 +44,7 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
OPTIONAL_FIELDS = ('metadata', 'parent')
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.UUIDField(),
|
||||
|
||||
@ -110,17 +110,6 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
|
||||
def has_dependent_backups(self):
|
||||
return bool(self.num_dependent_backups)
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
"""Make an object representation compatible with a target version."""
|
||||
added_fields = (((1, 7), ('parent',)),)
|
||||
|
||||
super(Backup, self).obj_make_compatible(primitive, target_version)
|
||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
for version, remove_fields in added_fields:
|
||||
if target_version < version:
|
||||
for obj_field in remove_fields:
|
||||
primitive.pop(obj_field, None)
|
||||
|
||||
@classmethod
|
||||
def _from_db_object(cls, context, backup, db_backup, expected_attrs=None):
|
||||
if expected_attrs is None:
|
||||
|
@ -54,23 +54,45 @@ class CinderObjectVersionsHistory(dict):
|
||||
#
|
||||
# Please note that we do not need to add similar entires for each
|
||||
# release. Liberty is here just for historical reasons.
|
||||
self.versions = ['liberty']
|
||||
self['liberty'] = {
|
||||
'Backup': '1.1',
|
||||
'BackupImport': '1.1',
|
||||
self.versions = ['1.38']
|
||||
self['1.38'] = {
|
||||
'Backup': '1.7',
|
||||
'BackupDeviceInfo': '1.0',
|
||||
'BackupImport': '1.7',
|
||||
'BackupList': '1.0',
|
||||
'ConsistencyGroup': '1.1',
|
||||
'ConsistencyGroupList': '1.0',
|
||||
'Service': '1.0',
|
||||
'ServiceList': '1.0',
|
||||
'Snapshot': '1.0',
|
||||
'CleanupRequest': '1.0',
|
||||
'CGSnapshot': '1.1',
|
||||
'CGSnapshotList': '1.0',
|
||||
'Cluster': '1.1',
|
||||
'ClusterList': '1.0',
|
||||
'ConsistencyGroup': '1.4',
|
||||
'ConsistencyGroupList': '1.1',
|
||||
'Group': '1.2',
|
||||
'GroupList': '1.0',
|
||||
'GroupSnapshot': '1.0',
|
||||
'GroupSnapshotList': '1.0',
|
||||
'GroupType': '1.0',
|
||||
'GroupTypeList': '1.0',
|
||||
'LogLevel': '1.0',
|
||||
'LogLevelList': '1.0',
|
||||
'ManageableSnapshot': '1.0',
|
||||
'ManageableSnapshotList': '1.0',
|
||||
'ManageableVolume': '1.0',
|
||||
'ManageableVolumeList': '1.0',
|
||||
'QualityOfServiceSpecs': '1.0',
|
||||
'QualityOfServiceSpecsList': '1.0',
|
||||
'RequestSpec': '1.5',
|
||||
'Service': '1.6',
|
||||
'ServiceList': '1.1',
|
||||
'Snapshot': '1.5',
|
||||
'SnapshotList': '1.0',
|
||||
'Volume': '1.1',
|
||||
'VolumeAttachment': '1.0',
|
||||
'VolumeAttachmentList': '1.0',
|
||||
'Volume': '1.8',
|
||||
'VolumeAttachment': '1.3',
|
||||
'VolumeAttachmentList': '1.1',
|
||||
'VolumeList': '1.1',
|
||||
'VolumeType': '1.0',
|
||||
'VolumeTypeList': '1.0',
|
||||
'VolumeProperties': '1.1',
|
||||
'VolumeType': '1.3',
|
||||
'VolumeTypeList': '1.1',
|
||||
}
|
||||
|
||||
def get_current(self):
|
||||
@ -92,61 +114,25 @@ class CinderObjectVersionsHistory(dict):
|
||||
OBJ_VERSIONS = CinderObjectVersionsHistory()
|
||||
# NOTE(dulek): You should add a new version here each time you bump a version
|
||||
# of any object. As a second parameter you need to specify only what changed.
|
||||
|
||||
# On each release we should drop backward compatibility with -2 release, since
|
||||
# rolling upgrades only needs to support compatibility with previous release.
|
||||
# So if we are in N release we can remove history from L and earlier.
|
||||
# Example of how to keep track of this:
|
||||
# # TODO: (T release) remove up to next TODO (was added in R release) and
|
||||
# # update CinderObjectVersionsHistory
|
||||
# OBJ_VERSIONS.add('1.34', {'VolumeAttachment': '1.3'})
|
||||
# OBJ_VERSIONS.add('1.35', {'Backup': '1.6', 'BackupImport': '1.6'})
|
||||
#
|
||||
# When dropping backward compatibility with an OpenStack release we can rework
|
||||
# this and remove some history while keeping the versions order.
|
||||
OBJ_VERSIONS.add('1.0', {'Backup': '1.3', 'BackupImport': '1.3',
|
||||
'CGSnapshot': '1.0', 'CGSnapshotList': '1.0',
|
||||
'ConsistencyGroup': '1.2',
|
||||
'ConsistencyGroupList': '1.1', 'Service': '1.1',
|
||||
'Volume': '1.3', 'VolumeTypeList': '1.1'})
|
||||
OBJ_VERSIONS.add('1.1', {'Service': '1.2', 'ServiceList': '1.1'})
|
||||
OBJ_VERSIONS.add('1.2', {'Backup': '1.4', 'BackupImport': '1.4'})
|
||||
OBJ_VERSIONS.add('1.3', {'Service': '1.3'})
|
||||
OBJ_VERSIONS.add('1.4', {'Snapshot': '1.1'})
|
||||
OBJ_VERSIONS.add('1.5', {'VolumeType': '1.1'})
|
||||
OBJ_VERSIONS.add('1.6', {'QualityOfServiceSpecs': '1.0',
|
||||
'QualityOfServiceSpecsList': '1.0',
|
||||
'VolumeType': '1.2'})
|
||||
OBJ_VERSIONS.add('1.7', {'Cluster': '1.0', 'ClusterList': '1.0',
|
||||
'Service': '1.4', 'Volume': '1.4',
|
||||
'ConsistencyGroup': '1.3'})
|
||||
OBJ_VERSIONS.add('1.8', {'RequestSpec': '1.0', 'VolumeProperties': '1.0'})
|
||||
OBJ_VERSIONS.add('1.9', {'GroupType': '1.0', 'GroupTypeList': '1.0'})
|
||||
OBJ_VERSIONS.add('1.10', {'Group': '1.0', 'GroupList': '1.0', 'Volume': '1.5',
|
||||
'RequestSpec': '1.1', 'VolumeProperties': '1.1'})
|
||||
OBJ_VERSIONS.add('1.11', {'GroupSnapshot': '1.0', 'GroupSnapshotList': '1.0',
|
||||
'Group': '1.1'})
|
||||
OBJ_VERSIONS.add('1.12', {'VolumeType': '1.3'})
|
||||
OBJ_VERSIONS.add('1.13', {'CleanupRequest': '1.0'})
|
||||
OBJ_VERSIONS.add('1.14', {'VolumeAttachmentList': '1.1'})
|
||||
OBJ_VERSIONS.add('1.15', {'Volume': '1.6', 'Snapshot': '1.2'})
|
||||
OBJ_VERSIONS.add('1.16', {'BackupDeviceInfo': '1.0'})
|
||||
OBJ_VERSIONS.add('1.17', {'VolumeAttachment': '1.1'})
|
||||
OBJ_VERSIONS.add('1.18', {'Snapshot': '1.3'})
|
||||
OBJ_VERSIONS.add('1.19', {'ConsistencyGroup': '1.4', 'CGSnapshot': '1.1'})
|
||||
OBJ_VERSIONS.add('1.20', {'Cluster': '1.1'})
|
||||
OBJ_VERSIONS.add('1.21', {'ManageableSnapshot': '1.0',
|
||||
'ManageableVolume': '1.0',
|
||||
'ManageableVolumeList': '1.0',
|
||||
'ManageableSnapshotList': '1.0'})
|
||||
OBJ_VERSIONS.add('1.22', {'Snapshot': '1.4'})
|
||||
OBJ_VERSIONS.add('1.23', {'VolumeAttachment': '1.2'})
|
||||
OBJ_VERSIONS.add('1.24', {'LogLevel': '1.0', 'LogLevelList': '1.0'})
|
||||
OBJ_VERSIONS.add('1.25', {'Group': '1.2'})
|
||||
OBJ_VERSIONS.add('1.26', {'Snapshot': '1.5'})
|
||||
OBJ_VERSIONS.add('1.27', {'Backup': '1.5', 'BackupImport': '1.5'})
|
||||
OBJ_VERSIONS.add('1.28', {'Service': '1.5'})
|
||||
OBJ_VERSIONS.add('1.29', {'Service': '1.6'})
|
||||
OBJ_VERSIONS.add('1.30', {'RequestSpec': '1.2'})
|
||||
OBJ_VERSIONS.add('1.31', {'Volume': '1.7'})
|
||||
OBJ_VERSIONS.add('1.32', {'RequestSpec': '1.3'})
|
||||
OBJ_VERSIONS.add('1.33', {'Volume': '1.8'})
|
||||
OBJ_VERSIONS.add('1.34', {'VolumeAttachment': '1.3'})
|
||||
OBJ_VERSIONS.add('1.35', {'Backup': '1.6', 'BackupImport': '1.6'})
|
||||
OBJ_VERSIONS.add('1.36', {'RequestSpec': '1.4'})
|
||||
OBJ_VERSIONS.add('1.37', {'RequestSpec': '1.5'})
|
||||
OBJ_VERSIONS.add('1.38', {'Backup': '1.7', 'BackupImport': '1.7'})
|
||||
# # TODO: (U release) remove up to next TODO (was added in S release) and
|
||||
# # update CinderObjectVersionsHistory
|
||||
# OBJ_VERSIONS.add('1.36', {'RequestSpec': '1.4'})
|
||||
# OBJ_VERSIONS.add('1.37', {'RequestSpec': '1.5'})
|
||||
# OBJ_VERSIONS.add('1.38', {'Backup': '1.7', 'BackupImport': '1.7'})
|
||||
# When we reach T release we remove versions 1.34 and 1.35 and update __init__
|
||||
# method in CinderObjectVerseionsHistory to bump VolumeAttachment to 1.3,
|
||||
# Backup to 1.6 and BackupImport to 1.6, and changing the versions list to
|
||||
# '1.35' and the self['<versioname>'] = { to self['1.35'] = {
|
||||
|
||||
|
||||
class CinderObjectRegistry(base.VersionedObjectRegistry):
|
||||
|
@ -30,6 +30,7 @@ class CGSnapshot(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
OPTIONAL_FIELDS = ['consistencygroup', 'snapshots']
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.UUIDField(),
|
||||
'consistencygroup_id': fields.UUIDField(nullable=True),
|
||||
|
@ -24,6 +24,7 @@ class CleanupRequest(base.CinderObject, base.ClusteredObject):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'service_id': fields.IntegerField(nullable=True),
|
||||
'cluster_name': fields.StringField(nullable=True),
|
||||
|
@ -42,9 +42,7 @@ class Cluster(base.CinderPersistentObject, base.CinderObject,
|
||||
VERSION = '1.1'
|
||||
OPTIONAL_FIELDS = ('num_hosts', 'num_down_hosts', 'services')
|
||||
|
||||
# NOTE(geguileo): We don't want to expose race_preventer field at the OVO
|
||||
# layer since it is only meant for the DB layer internal mechanism to
|
||||
# prevent races.
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.IntegerField(),
|
||||
'name': fields.StringField(nullable=False),
|
||||
@ -60,20 +58,11 @@ class Cluster(base.CinderPersistentObject, base.CinderObject,
|
||||
'replication_status': c_fields.ReplicationStatusField(nullable=True),
|
||||
'frozen': fields.BooleanField(default=False),
|
||||
'active_backend_id': fields.StringField(nullable=True),
|
||||
|
||||
# Don't add race_preventer field, as it's a DB layer internal mechanism
|
||||
# piece to prevent races and should not be touched by other layers.
|
||||
}
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
"""Make a cluster representation compatible with a target version."""
|
||||
# Convert all related objects
|
||||
super(Cluster, self).obj_make_compatible(primitive, target_version)
|
||||
|
||||
# Before v1.1 we didn't have relication fields so we have to remove
|
||||
# them.
|
||||
if target_version == '1.0':
|
||||
for obj_field in ('replication_status', 'frozen',
|
||||
'active_backend_id'):
|
||||
primitive.pop(obj_field, None)
|
||||
|
||||
@classmethod
|
||||
def _get_expected_attrs(cls, context, *args, **kwargs):
|
||||
"""Return expected attributes when getting a cluster.
|
||||
|
@ -12,7 +12,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_utils import versionutils
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from cinder import db
|
||||
@ -54,18 +53,6 @@ class ConsistencyGroup(base.CinderPersistentObject, base.CinderObject,
|
||||
'volumes': fields.ObjectField('VolumeList', nullable=True),
|
||||
}
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
"""Make a CG representation compatible with a target version."""
|
||||
# Convert all related objects
|
||||
super(ConsistencyGroup, self).obj_make_compatible(primitive,
|
||||
target_version)
|
||||
|
||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
# Before v1.3 we didn't have cluster fields so we have to remove them.
|
||||
if target_version < (1, 3):
|
||||
for obj_field in ('cluster', 'cluster_name'):
|
||||
primitive.pop(obj_field, None)
|
||||
|
||||
@classmethod
|
||||
def _from_db_object(cls, context, consistencygroup, db_consistencygroup,
|
||||
expected_attrs=None):
|
||||
|
@ -24,6 +24,7 @@ class LogLevel(base.CinderObject):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'prefix': fields.StringField(nullable=True),
|
||||
'level': fields.StringField(nullable=True),
|
||||
|
@ -12,7 +12,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_utils import versionutils
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from cinder import db
|
||||
@ -35,6 +34,7 @@ class Group(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
OPTIONAL_FIELDS = ['volumes', 'volume_types', 'group_snapshots']
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.UUIDField(),
|
||||
'user_id': fields.StringField(),
|
||||
@ -57,17 +57,6 @@ class Group(base.CinderPersistentObject, base.CinderObject,
|
||||
nullable=True),
|
||||
}
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
"""Make an object representation compatible with target version."""
|
||||
super(Group, self).obj_make_compatible(primitive, target_version)
|
||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
if target_version < (1, 1):
|
||||
for key in ('group_snapshot_id', 'source_group_id',
|
||||
'group_snapshots'):
|
||||
primitive.pop(key, None)
|
||||
if target_version < (1, 2):
|
||||
primitive.pop('replication_status', None)
|
||||
|
||||
@staticmethod
|
||||
def _from_db_object(context, group, db_group,
|
||||
expected_attrs=None):
|
||||
|
@ -28,6 +28,7 @@ class GroupSnapshot(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
OPTIONAL_FIELDS = ['group', 'snapshots']
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.UUIDField(),
|
||||
'group_id': fields.UUIDField(nullable=False),
|
||||
|
@ -29,6 +29,7 @@ class GroupType(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
OPTIONAL_FIELDS = ['group_specs', 'projects']
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.UUIDField(),
|
||||
'name': fields.StringField(nullable=True),
|
||||
|
@ -19,6 +19,7 @@ from cinder.objects import base
|
||||
|
||||
class ManageableObject(object):
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'reference': fields.DictOfNullableStringsField(nullable=False),
|
||||
'size': fields.IntegerField(nullable=True),
|
||||
@ -58,6 +59,7 @@ class ManageableSnapshot(base.CinderObject, base.CinderObjectDictCompat,
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'source_reference': fields.DictOfNullableStringsField(),
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ class QualityOfServiceSpecs(base.CinderPersistentObject,
|
||||
|
||||
OPTIONAL_FIELDS = ['volume_types']
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.UUIDField(),
|
||||
'name': fields.StringField(),
|
||||
|
@ -12,7 +12,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_utils import versionutils
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from cinder import objects
|
||||
@ -30,6 +29,7 @@ class RequestSpec(base.CinderObject, base.CinderObjectDictCompat,
|
||||
# Version 1.5: Added 'availability_zones'
|
||||
VERSION = '1.5'
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'consistencygroup_id': fields.UUIDField(nullable=True),
|
||||
'group_id': fields.UUIDField(nullable=True),
|
||||
@ -95,20 +95,6 @@ class RequestSpec(base.CinderObject, base.CinderObjectDictCompat,
|
||||
|
||||
return spec_obj
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
"""Make an object representation compatible with target version."""
|
||||
super(RequestSpec, self).obj_make_compatible(primitive, target_version)
|
||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
added_fields = (((1, 1), ('group_id', 'group_backend')),
|
||||
((1, 2), ('resource_backend')),
|
||||
((1, 3), ('backup_id')),
|
||||
((1, 4), ('operation')),
|
||||
((1, 5), ('availability_zones')))
|
||||
for version, remove_fields in added_fields:
|
||||
if target_version < version:
|
||||
for obj_field in remove_fields:
|
||||
primitive.pop(obj_field, None)
|
||||
|
||||
|
||||
@base.CinderObjectRegistry.register
|
||||
class VolumeProperties(base.CinderObject, base.CinderObjectDictCompat):
|
||||
|
@ -44,6 +44,7 @@ class Service(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
OPTIONAL_FIELDS = ('cluster',)
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.IntegerField(),
|
||||
'host': fields.StringField(nullable=True),
|
||||
@ -70,19 +71,6 @@ class Service(base.CinderPersistentObject, base.CinderObject,
|
||||
'uuid': fields.StringField(),
|
||||
}
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
"""Make a service representation compatible with a target version."""
|
||||
# Convert all related objects
|
||||
super(Service, self).obj_make_compatible(primitive, target_version)
|
||||
|
||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
# Before v1.4 we didn't have cluster fields so we have to remove them.
|
||||
if target_version < (1, 4):
|
||||
for obj_field in ('cluster', 'cluster_name'):
|
||||
primitive.pop(obj_field, None)
|
||||
if target_version < (1, 5) and 'uuid' in primitive:
|
||||
del primitive['uuid']
|
||||
|
||||
@staticmethod
|
||||
def _from_db_object(context, service, db_service, expected_attrs=None):
|
||||
expected_attrs = expected_attrs or []
|
||||
|
@ -13,7 +13,6 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import versionutils
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from cinder import db
|
||||
@ -45,6 +44,7 @@ class Snapshot(cleanable.CinderCleanableObject, base.CinderObject,
|
||||
# are typically the relationship in the sqlalchemy object.
|
||||
OPTIONAL_FIELDS = ('volume', 'metadata', 'cgsnapshot', 'group_snapshot')
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.UUIDField(),
|
||||
|
||||
@ -116,25 +116,6 @@ class Snapshot(cleanable.CinderCleanableObject, base.CinderObject,
|
||||
|
||||
return changes
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
"""Make an object representation compatible with a target version."""
|
||||
super(Snapshot, self).obj_make_compatible(primitive, target_version)
|
||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
|
||||
backport_statuses = (((1, 3),
|
||||
(c_fields.SnapshotStatus.UNMANAGING,
|
||||
c_fields.SnapshotStatus.DELETING)),
|
||||
((1, 4),
|
||||
(c_fields.SnapshotStatus.BACKING_UP,
|
||||
c_fields.SnapshotStatus.AVAILABLE)),
|
||||
((1, 5),
|
||||
(c_fields.SnapshotStatus.RESTORING,
|
||||
c_fields.SnapshotStatus.AVAILABLE)))
|
||||
for version, status in backport_statuses:
|
||||
if target_version < version:
|
||||
if primitive.get('status') == status[0]:
|
||||
primitive['status'] = status[1]
|
||||
|
||||
@classmethod
|
||||
def _from_db_object(cls, context, snapshot, db_snapshot,
|
||||
expected_attrs=None):
|
||||
|
@ -13,7 +13,6 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import versionutils
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from cinder import db
|
||||
@ -69,6 +68,7 @@ class Volume(cleanable.CinderCleanableObject, base.CinderObject,
|
||||
'volume_type', 'volume_attachment', 'consistencygroup',
|
||||
'snapshots', 'cluster', 'group')
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.UUIDField(),
|
||||
'_name_id': fields.UUIDField(nullable=True),
|
||||
@ -239,21 +239,6 @@ class Volume(cleanable.CinderCleanableObject, base.CinderObject,
|
||||
|
||||
return changes
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
"""Make a Volume representation compatible with a target version."""
|
||||
added_fields = (((1, 4), ('cluster', 'cluster_name')),
|
||||
((1, 5), ('group', 'group_id')),
|
||||
((1, 7), ('service_uuid')))
|
||||
|
||||
# Convert all related objects
|
||||
super(Volume, self).obj_make_compatible(primitive, target_version)
|
||||
|
||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
for version, remove_fields in added_fields:
|
||||
if target_version < version:
|
||||
for obj_field in remove_fields:
|
||||
primitive.pop(obj_field, None)
|
||||
|
||||
@classmethod
|
||||
def _from_db_object(cls, context, volume, db_volume, expected_attrs=None):
|
||||
if expected_attrs is None:
|
||||
|
@ -13,7 +13,6 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import versionutils
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from cinder import db
|
||||
@ -37,6 +36,7 @@ class VolumeAttachment(base.CinderPersistentObject, base.CinderObject,
|
||||
OPTIONAL_FIELDS = ['volume']
|
||||
obj_extra_fields = ['project_id', 'volume_host']
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.UUIDField(),
|
||||
'volume_id': fields.UUIDField(),
|
||||
@ -67,16 +67,6 @@ class VolumeAttachment(base.CinderPersistentObject, base.CinderObject,
|
||||
def _get_expected_attrs(cls, context, *args, **kwargs):
|
||||
return ['volume']
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
"""Make an object representation compatible with target version."""
|
||||
super(VolumeAttachment, self).obj_make_compatible(primitive,
|
||||
target_version)
|
||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
if target_version < (1, 3):
|
||||
primitive.pop('connector', None)
|
||||
if target_version < (1, 2):
|
||||
primitive.pop('connection_info', None)
|
||||
|
||||
@classmethod
|
||||
def _from_db_object(cls, context, attachment, db_attachment,
|
||||
expected_attrs=None):
|
||||
|
@ -12,7 +12,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_utils import versionutils
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from cinder import db
|
||||
@ -35,6 +34,7 @@ class VolumeType(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
OPTIONAL_FIELDS = ('extra_specs', 'projects', 'qos_specs')
|
||||
|
||||
# NOTE: When adding a field obj_make_compatible needs to be updated
|
||||
fields = {
|
||||
'id': fields.UUIDField(),
|
||||
'name': fields.StringField(nullable=True),
|
||||
@ -47,21 +47,6 @@ class VolumeType(base.CinderPersistentObject, base.CinderObject,
|
||||
nullable=True),
|
||||
}
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
super(VolumeType, self).obj_make_compatible(primitive, target_version)
|
||||
|
||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
if target_version < (1, 1):
|
||||
if primitive.get('extra_specs'):
|
||||
# Before 1.1 extra_specs field didn't allowed None values. To
|
||||
# make sure we won't explode on receiver side - change Nones to
|
||||
# empty string.
|
||||
for k, v in primitive['extra_specs'].items():
|
||||
if v is None:
|
||||
primitive['extra_specs'][k] = ''
|
||||
if target_version < (1, 3):
|
||||
primitive.pop('qos_specs_id', None)
|
||||
|
||||
@classmethod
|
||||
def _get_expected_attrs(cls, context, *args, **kwargs):
|
||||
return 'extra_specs', 'projects'
|
||||
|
@ -356,19 +356,22 @@ class BackupTestCase(BaseBackupTest):
|
||||
@mock.patch('cinder.objects.service.Service.get_minimum_obj_version')
|
||||
@mock.patch('cinder.rpc.LAST_RPC_VERSIONS', {'cinder-backup': '1.3',
|
||||
'cinder-volume': '1.7'})
|
||||
@mock.patch('cinder.rpc.LAST_OBJ_VERSIONS', {'cinder-backup': '1.2',
|
||||
'cinder-volume': '1.4'})
|
||||
def test_reset(self, get_min_obj, get_min_rpc):
|
||||
get_min_obj.return_value = 'liberty'
|
||||
backup_mgr = manager.BackupManager()
|
||||
old_version = objects.base.OBJ_VERSIONS.versions[-2]
|
||||
|
||||
with mock.patch('cinder.rpc.LAST_OBJ_VERSIONS',
|
||||
{'cinder-volume': old_version,
|
||||
'cinder-scheduler': old_version,
|
||||
'cinder-backup': old_version}):
|
||||
backup_mgr = manager.BackupManager()
|
||||
|
||||
backup_rpcapi = backup_mgr.backup_rpcapi
|
||||
volume_rpcapi = backup_mgr.volume_rpcapi
|
||||
self.assertEqual('1.3', backup_rpcapi.client.version_cap)
|
||||
self.assertEqual('1.2',
|
||||
self.assertEqual(old_version,
|
||||
backup_rpcapi.client.serializer._base.version_cap)
|
||||
self.assertEqual('1.7', volume_rpcapi.client.version_cap)
|
||||
self.assertEqual('1.4',
|
||||
self.assertEqual(old_version,
|
||||
volume_rpcapi.client.serializer._base.version_cap)
|
||||
get_min_obj.return_value = objects.base.OBJ_VERSIONS.get_current()
|
||||
backup_mgr.reset()
|
||||
|
@ -36,6 +36,7 @@ from cinder.tests.unit import test
|
||||
class TestCinderObjectVersionHistory(test_objects.BaseObjectsTestCase):
|
||||
def test_add(self):
|
||||
history = test_objects.obj_base.CinderObjectVersionsHistory()
|
||||
first_version = history.versions[0]
|
||||
v10 = {'Backup': '2.0'}
|
||||
v11 = {'Backup': '2.1'}
|
||||
history.add('1.0', v10)
|
||||
@ -43,9 +44,9 @@ class TestCinderObjectVersionHistory(test_objects.BaseObjectsTestCase):
|
||||
# We have 3 elements because we have the liberty version by default
|
||||
self.assertEqual(2 + 1, len(history))
|
||||
|
||||
expected_v10 = history['liberty'].copy()
|
||||
expected_v10 = history[first_version].copy()
|
||||
expected_v10.update(v10)
|
||||
expected_v11 = history['liberty'].copy()
|
||||
expected_v11 = history[first_version].copy()
|
||||
expected_v11.update(v11)
|
||||
|
||||
self.assertEqual('1.1', history.get_current())
|
||||
|
@ -19,7 +19,6 @@ from unittest import mock
|
||||
from cinder import context
|
||||
from cinder import exception
|
||||
from cinder.objects import cleanable
|
||||
from cinder import rpc
|
||||
from cinder import service
|
||||
from cinder.tests.unit import objects as test_objects
|
||||
from cinder.volume import rpcapi
|
||||
@ -35,7 +34,7 @@ class Backup(cleanable.CinderCleanableObject):
|
||||
|
||||
@staticmethod
|
||||
def _is_cleanable(status, obj_version):
|
||||
if obj_version and obj_version <= 1003:
|
||||
if obj_version and obj_version < 1003:
|
||||
return False
|
||||
return status == 'cleanable'
|
||||
|
||||
@ -53,46 +52,52 @@ class TestCleanable(test_objects.BaseObjectsTestCase):
|
||||
vol_rpcapi = cleanable.CinderCleanableObject.get_rpc_api()
|
||||
self.assertEqual(rpcapi.VolumeAPI, vol_rpcapi)
|
||||
|
||||
def set_version(self, version):
|
||||
self.patch('cinder.volume.rpcapi.VolumeAPI.determine_obj_version_cap',
|
||||
mock.Mock(return_value='1.0'))
|
||||
self.patch('cinder.objects.base.OBJ_VERSIONS',
|
||||
{'1.0': {'Backup': version}})
|
||||
|
||||
def test_get_pinned_version(self):
|
||||
"""Test that we get the pinned version for this specific object."""
|
||||
rpc.LAST_OBJ_VERSIONS[Backup.get_rpc_api().BINARY] = '1.0'
|
||||
self.set_version('1.3')
|
||||
version = Backup.get_pinned_version()
|
||||
self.assertEqual(1003, version)
|
||||
|
||||
def test_is_cleanable_pinned_pinned_too_old(self):
|
||||
"""Test is_cleanable with pinned version with uncleanable version."""
|
||||
rpc.LAST_OBJ_VERSIONS[Backup.get_rpc_api().BINARY] = '1.0'
|
||||
self.set_version('1.0')
|
||||
backup = Backup(status='cleanable')
|
||||
self.assertFalse(backup.is_cleanable(pinned=True))
|
||||
|
||||
def test_is_cleanable_pinned_result_true(self):
|
||||
"""Test with pinned version with cleanable version and status."""
|
||||
rpc.LAST_OBJ_VERSIONS[Backup.get_rpc_api().BINARY] = '1.3'
|
||||
self.set_version('1.3')
|
||||
backup = Backup(status='cleanable')
|
||||
self.assertTrue(backup.is_cleanable(pinned=True))
|
||||
|
||||
def test_is_cleanable_pinned_result_false(self):
|
||||
"""Test with pinned version with cleanable version but not status."""
|
||||
rpc.LAST_OBJ_VERSIONS[Backup.get_rpc_api().BINARY] = '1.3'
|
||||
self.set_version('1.0')
|
||||
backup = Backup(status='not_cleanable')
|
||||
self.assertFalse(backup.is_cleanable(pinned=True))
|
||||
|
||||
def test_is_cleanable_unpinned_result_false(self):
|
||||
"""Test unpinned version with old version and non cleanable status."""
|
||||
rpc.LAST_OBJ_VERSIONS[Backup.get_rpc_api().BINARY] = '1.0'
|
||||
self.set_version('1.0')
|
||||
backup = Backup(status='not_cleanable')
|
||||
self.assertFalse(backup.is_cleanable(pinned=False))
|
||||
|
||||
def test_is_cleanable_unpinned_result_true(self):
|
||||
"""Test unpinned version with old version and cleanable status."""
|
||||
rpc.LAST_OBJ_VERSIONS[Backup.get_rpc_api().BINARY] = '1.0'
|
||||
self.set_version('1.0')
|
||||
backup = Backup(status='cleanable')
|
||||
self.assertTrue(backup.is_cleanable(pinned=False))
|
||||
|
||||
@mock.patch('cinder.db.worker_create', autospec=True)
|
||||
def test_create_worker(self, mock_create):
|
||||
"""Test worker creation as if it were from an rpc call."""
|
||||
rpc.LAST_OBJ_VERSIONS[Backup.get_rpc_api().BINARY] = '1.3'
|
||||
self.set_version('1.3')
|
||||
mock_create.return_value = mock.sentinel.worker
|
||||
backup = Backup(_context=self.context, status='cleanable',
|
||||
id=mock.sentinel.id)
|
||||
@ -106,7 +111,7 @@ class TestCleanable(test_objects.BaseObjectsTestCase):
|
||||
@mock.patch('cinder.db.worker_create', autospec=True)
|
||||
def test_create_worker_pinned_too_old(self, mock_create):
|
||||
"""Test worker creation when we are pinnned with an old version."""
|
||||
rpc.LAST_OBJ_VERSIONS[Backup.get_rpc_api().BINARY] = '1.0'
|
||||
self.set_version('1.0')
|
||||
mock_create.return_value = mock.sentinel.worker
|
||||
backup = Backup(_context=self.context, status='cleanable',
|
||||
id=mock.sentinel.id)
|
||||
@ -117,7 +122,7 @@ class TestCleanable(test_objects.BaseObjectsTestCase):
|
||||
@mock.patch('cinder.db.worker_create', autospec=True)
|
||||
def test_create_worker_non_cleanable(self, mock_create):
|
||||
"""Test worker creation when status is non cleanable."""
|
||||
rpc.LAST_OBJ_VERSIONS[Backup.get_rpc_api().BINARY] = '1.3'
|
||||
self.set_version('1.3')
|
||||
mock_create.return_value = mock.sentinel.worker
|
||||
backup = Backup(_context=self.context, status='non_cleanable',
|
||||
id=mock.sentinel.id)
|
||||
@ -129,7 +134,7 @@ class TestCleanable(test_objects.BaseObjectsTestCase):
|
||||
@mock.patch('cinder.db.worker_create', autospec=True)
|
||||
def test_create_worker_already_exists(self, mock_create, mock_update):
|
||||
"""Test worker creation when a worker for the resource exists."""
|
||||
rpc.LAST_OBJ_VERSIONS[Backup.get_rpc_api().BINARY] = '1.3'
|
||||
self.set_version('1.3')
|
||||
mock_create.side_effect = exception.WorkerExists(type='type', id='id')
|
||||
|
||||
backup = Backup(_context=self.context, status='cleanable',
|
||||
@ -152,7 +157,7 @@ class TestCleanable(test_objects.BaseObjectsTestCase):
|
||||
that the entry gets removed from the DB between our failure to create
|
||||
it and our try to update the entry.
|
||||
"""
|
||||
rpc.LAST_OBJ_VERSIONS[Backup.get_rpc_api().BINARY] = '1.3'
|
||||
self.set_version('1.3')
|
||||
mock_create.side_effect = [
|
||||
exception.WorkerExists(type='type', id='id'), mock.sentinel.worker]
|
||||
mock_update.side_effect = exception.WorkerNotFound
|
||||
|
@ -124,19 +124,6 @@ class TestCluster(test_objects.BaseObjectsTestCase):
|
||||
'active_backend_id': None},
|
||||
{'cluster_name': cluster.name})
|
||||
|
||||
@ddt.data('1.0', '1.1')
|
||||
def tests_obj_make_compatible(self, version):
|
||||
new_fields = {'replication_status': 'error', 'frozen': True,
|
||||
'active_backend_id': 'replication'}
|
||||
cluster = objects.Cluster(self.context, **new_fields)
|
||||
primitive = cluster.obj_to_primitive(version)
|
||||
converted_cluster = objects.Cluster.obj_from_primitive(primitive)
|
||||
for key, value in new_fields.items():
|
||||
if version == '1.0':
|
||||
self.assertFalse(converted_cluster.obj_attr_is_set(key))
|
||||
else:
|
||||
self.assertEqual(value, getattr(converted_cluster, key))
|
||||
|
||||
|
||||
class TestClusterList(test_objects.BaseObjectsTestCase):
|
||||
"""Test ClusterList Versioned Object methods."""
|
||||
|
@ -18,7 +18,6 @@ import ddt
|
||||
|
||||
from cinder import exception
|
||||
from cinder import objects
|
||||
from cinder.objects import base as ovo_base
|
||||
from cinder.objects import fields
|
||||
from cinder.tests.unit import fake_constants as fake
|
||||
from cinder.tests.unit import fake_volume
|
||||
@ -159,22 +158,6 @@ class TestGroup(test_objects.BaseObjectsTestCase):
|
||||
self.assertEqual(len(db_volumes), len(group.volumes))
|
||||
self._compare(self, db_volumes[0], group.volumes[0])
|
||||
|
||||
@ddt.data('1.10', '1.11')
|
||||
def test_obj_make_compatible(self, version):
|
||||
extra_data = {'group_snapshot_id': fake.GROUP_SNAPSHOT_ID,
|
||||
'source_group_id': fake.GROUP_ID,
|
||||
'group_snapshots': objects.GroupSnapshotList()}
|
||||
group = objects.Group(self.context, name='name', **extra_data)
|
||||
|
||||
serializer = ovo_base.CinderObjectSerializer(version)
|
||||
primitive = serializer.serialize_entity(self.context, group)
|
||||
|
||||
converted_group = objects.Group.obj_from_primitive(primitive)
|
||||
is_set = version == '1.11'
|
||||
for key in extra_data:
|
||||
self.assertEqual(is_set, converted_group.obj_attr_is_set(key))
|
||||
self.assertEqual('name', converted_group.name)
|
||||
|
||||
@mock.patch('cinder.volume.group_types.get_group_type_specs')
|
||||
def test_is_replicated_true(self, mock_get_specs):
|
||||
mock_get_specs.return_value = '<is> True'
|
||||
|
@ -80,6 +80,10 @@ class TestObjectVersions(test.TestCase):
|
||||
"and we just have to change the hash in this module.")
|
||||
|
||||
def test_versions_history(self):
|
||||
# If we inserted a fake element in history, remove it so we don't fail
|
||||
if base.OBJ_VERSIONS.get_current() == self.FAKE_OVO_HISTORY_VERSION:
|
||||
fake_version = base.OBJ_VERSIONS.versions.pop(-1)
|
||||
del base.OBJ_VERSIONS[fake_version]
|
||||
classes = base.CinderObjectRegistry.obj_classes()
|
||||
versions = base.OBJ_VERSIONS.get_current_versions()
|
||||
expected = {}
|
||||
|
@ -229,30 +229,6 @@ class TestSnapshot(test_objects.BaseObjectsTestCase):
|
||||
mock.call(self.context,
|
||||
fake.SNAPSHOT_ID)])
|
||||
|
||||
@ddt.data('1.1', '1.3')
|
||||
def test_obj_make_compatible_1_3(self, version):
|
||||
snapshot = objects.Snapshot(context=self.context)
|
||||
snapshot.status = fields.SnapshotStatus.UNMANAGING
|
||||
primitive = snapshot.obj_to_primitive(version)
|
||||
snapshot = objects.Snapshot.obj_from_primitive(primitive)
|
||||
if version == '1.3':
|
||||
status = fields.SnapshotStatus.UNMANAGING
|
||||
else:
|
||||
status = fields.SnapshotStatus.DELETING
|
||||
self.assertEqual(status, snapshot.status)
|
||||
|
||||
@ddt.data('1.3', '1.4')
|
||||
def test_obj_make_compatible_1_4(self, version):
|
||||
snapshot = objects.Snapshot(context=self.context)
|
||||
snapshot.status = fields.SnapshotStatus.BACKING_UP
|
||||
primitive = snapshot.obj_to_primitive(version)
|
||||
snapshot = objects.Snapshot.obj_from_primitive(primitive)
|
||||
if version == '1.4':
|
||||
status = fields.SnapshotStatus.BACKING_UP
|
||||
else:
|
||||
status = fields.SnapshotStatus.AVAILABLE
|
||||
self.assertEqual(status, snapshot.status)
|
||||
|
||||
|
||||
class TestSnapshotList(test_objects.BaseObjectsTestCase):
|
||||
@mock.patch('cinder.objects.volume.Volume.get_by_id')
|
||||
|
@ -21,7 +21,6 @@ import pytz
|
||||
from cinder import context
|
||||
from cinder import exception
|
||||
from cinder import objects
|
||||
from cinder.objects import base as ovo_base
|
||||
from cinder.objects import fields
|
||||
from cinder.tests.unit.consistencygroup import fake_consistencygroup
|
||||
from cinder.tests.unit import fake_constants as fake
|
||||
@ -532,36 +531,6 @@ class TestVolume(test_objects.BaseObjectsTestCase):
|
||||
self.assertEqual({}, volume.cinder_obj_get_changes())
|
||||
self.assertFalse(volume_attachment_get.called)
|
||||
|
||||
@ddt.data('1.6', '1.7')
|
||||
def test_obj_make_compatible_cluster_added(self, version):
|
||||
extra_data = {'cluster_name': 'cluster_name',
|
||||
'cluster': objects.Cluster()}
|
||||
volume = objects.Volume(self.context, host='host', **extra_data)
|
||||
|
||||
serializer = ovo_base.CinderObjectSerializer(version)
|
||||
primitive = serializer.serialize_entity(self.context, volume)
|
||||
|
||||
converted_volume = objects.Volume.obj_from_primitive(primitive)
|
||||
is_set = version == '1.7'
|
||||
for key in extra_data:
|
||||
self.assertEqual(is_set, converted_volume.obj_attr_is_set(key))
|
||||
self.assertEqual('host', converted_volume.host)
|
||||
|
||||
@ddt.data('1.9', '1.10')
|
||||
def test_obj_make_compatible_groups_added(self, version):
|
||||
extra_data = {'group_id': fake.GROUP_ID,
|
||||
'group': objects.Group()}
|
||||
volume = objects.Volume(self.context, host='host', **extra_data)
|
||||
|
||||
serializer = ovo_base.CinderObjectSerializer(version)
|
||||
primitive = serializer.serialize_entity(self.context, volume)
|
||||
|
||||
converted_volume = objects.Volume.obj_from_primitive(primitive)
|
||||
is_set = version == '1.10'
|
||||
for key in extra_data:
|
||||
self.assertEqual(is_set, converted_volume.obj_attr_is_set(key))
|
||||
self.assertEqual('host', converted_volume.host)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_is_replicated(self, result):
|
||||
volume_type = fake_volume.fake_volume_type_obj(self.context)
|
||||
|
@ -123,26 +123,6 @@ class TestVolumeAttachment(test_objects.BaseObjectsTestCase):
|
||||
self.assertEqual(fields.VolumeAttachStatus.ATTACHED,
|
||||
attachment.attach_status)
|
||||
|
||||
@ddt.data('1.0', '1.1', '1.2', '1.3')
|
||||
def test_obj_make_compatible(self, version):
|
||||
connection_info = {'field': 'value'}
|
||||
connector = {'host': '127.0.0.1'}
|
||||
vol_attach = objects.VolumeAttachment(self.context,
|
||||
connection_info=connection_info,
|
||||
connector=connector)
|
||||
primitive = vol_attach.obj_to_primitive(version)
|
||||
converted_vol_attach = objects.VolumeAttachment.obj_from_primitive(
|
||||
primitive)
|
||||
if version == '1.3':
|
||||
self.assertEqual(connector, converted_vol_attach.connector)
|
||||
elif version == '1.2':
|
||||
self.assertEqual(connection_info,
|
||||
converted_vol_attach.connection_info)
|
||||
else:
|
||||
self.assertNotIn('connector', converted_vol_attach)
|
||||
self.assertFalse(converted_vol_attach.obj_attr_is_set(
|
||||
'connection_info'))
|
||||
|
||||
def test_migrate_attachment_specs(self):
|
||||
# Create an attachment.
|
||||
attachment = objects.VolumeAttachment(
|
||||
|
@ -75,18 +75,6 @@ class TestVolumeType(test_objects.BaseObjectsTestCase):
|
||||
self.context, fake.VOLUME_TYPE_ID)
|
||||
self._compare(self, db_volume_type, volume_type)
|
||||
|
||||
@ddt.data('1.0', '1.1')
|
||||
def test_obj_make_compatible(self, version):
|
||||
volume_type = objects.VolumeType(context=self.context)
|
||||
volume_type.extra_specs = {'foo': None, 'bar': 'baz'}
|
||||
volume_type.qos_specs_id = fake.QOS_SPEC_ID
|
||||
primitive = volume_type.obj_to_primitive(version)
|
||||
volume_type = objects.VolumeType.obj_from_primitive(primitive)
|
||||
foo = '' if version == '1.0' else None
|
||||
self.assertEqual(foo, volume_type.extra_specs['foo'])
|
||||
self.assertEqual('baz', volume_type.extra_specs['bar'])
|
||||
self.assertFalse(volume_type.obj_attr_is_set('qos_specs_id'))
|
||||
|
||||
@mock.patch('cinder.volume.volume_types.create')
|
||||
def test_create(self, volume_type_create):
|
||||
db_volume_type = fake_volume.fake_db_volume_type()
|
||||
|
@ -120,17 +120,20 @@ class SchedulerManagerTestCase(test.TestCase):
|
||||
@mock.patch('cinder.objects.service.Service.get_minimum_rpc_version')
|
||||
@mock.patch('cinder.objects.service.Service.get_minimum_obj_version')
|
||||
@mock.patch('cinder.rpc.LAST_RPC_VERSIONS', {'cinder-volume': '1.3'})
|
||||
@mock.patch('cinder.rpc.LAST_OBJ_VERSIONS', {'cinder-volume': '1.4',
|
||||
'cinder-scheduler': '1.4',
|
||||
'cinder-backup': '1.5'})
|
||||
def test_reset(self, get_min_obj, get_min_rpc):
|
||||
mgr = self.manager_cls()
|
||||
old_version = objects.base.OBJ_VERSIONS.versions[-2]
|
||||
|
||||
with mock.patch('cinder.rpc.LAST_OBJ_VERSIONS',
|
||||
{'cinder-volume': old_version,
|
||||
'cinder-scheduler': old_version,
|
||||
'cinder-backup': old_version}):
|
||||
mgr = self.manager_cls()
|
||||
|
||||
volume_rpcapi = mgr.driver.volume_rpcapi
|
||||
self.assertEqual('1.3', volume_rpcapi.client.version_cap)
|
||||
self.assertEqual('1.4',
|
||||
self.assertEqual(old_version,
|
||||
volume_rpcapi.client.serializer._base.version_cap)
|
||||
get_min_obj.return_value = objects.base.OBJ_VERSIONS.get_current()
|
||||
get_min_obj.return_value = self.latest_ovo_version
|
||||
mgr.reset()
|
||||
|
||||
volume_rpcapi = mgr.driver.volume_rpcapi
|
||||
|
@ -112,8 +112,10 @@ class TestCase(testtools.TestCase):
|
||||
RESOURCE_FILTER_FILENAME)
|
||||
MOCK_WORKER = True
|
||||
MOCK_TOOZ = True
|
||||
FAKE_OVO_HISTORY_VERSION = '9999.999'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
super(TestCase, self).__init__(*args, **kwargs)
|
||||
|
||||
# Suppress some log messages during test runs
|
||||
@ -301,6 +303,16 @@ class TestCase(testtools.TestCase):
|
||||
|
||||
self.vt = volume_types.get_default_volume_type()
|
||||
|
||||
# Create fake RPC history if we don't have enough to do tests
|
||||
obj_versions = objects_base.OBJ_VERSIONS
|
||||
if len(obj_versions) == 1:
|
||||
vol_vers = obj_versions.get_current_versions()['Volume'].split('.')
|
||||
new_volume_version = '%s.%s' % (vol_vers[0], int(vol_vers[1]) + 1)
|
||||
obj_versions.add(self.FAKE_OVO_HISTORY_VERSION,
|
||||
{'Volume': new_volume_version})
|
||||
|
||||
self.latest_ovo_version = obj_versions.get_current()
|
||||
|
||||
def _restore_obj_registry(self):
|
||||
objects_base.CinderObjectRegistry._registry._obj_classes = \
|
||||
self._base_test_obj_backup
|
||||
|
@ -39,16 +39,16 @@ class RPCAPITestCase(test.TestCase):
|
||||
|
||||
@mock.patch('cinder.objects.Service.get_minimum_rpc_version',
|
||||
return_value='1.2')
|
||||
@mock.patch('cinder.objects.Service.get_minimum_obj_version',
|
||||
return_value='1.4')
|
||||
@mock.patch('cinder.objects.Service.get_minimum_obj_version')
|
||||
@mock.patch('cinder.rpc.get_client')
|
||||
def test_init(self, get_client, get_min_obj, get_min_rpc):
|
||||
def fake_get_client(target, version_cap, serializer):
|
||||
self.assertEqual(FakeAPI.TOPIC, target.topic)
|
||||
self.assertEqual(FakeAPI.RPC_API_VERSION, target.version)
|
||||
self.assertEqual('1.2', version_cap)
|
||||
self.assertEqual('1.4', serializer.version_cap)
|
||||
self.assertEqual(self.latest_ovo_version, serializer.version_cap)
|
||||
|
||||
get_min_obj.return_value = self.latest_ovo_version
|
||||
get_client.side_effect = fake_get_client
|
||||
FakeAPI()
|
||||
|
||||
@ -73,19 +73,20 @@ class RPCAPITestCase(test.TestCase):
|
||||
@mock.patch('cinder.objects.Service.get_minimum_obj_version')
|
||||
@mock.patch('cinder.rpc.get_client')
|
||||
@mock.patch('cinder.rpc.LAST_RPC_VERSIONS', {'cinder-scheduler': '1.4'})
|
||||
@mock.patch('cinder.rpc.LAST_OBJ_VERSIONS', {'cinder-scheduler': '1.3'})
|
||||
def test_init_cached_caps(self, get_client, get_min_obj, get_min_rpc):
|
||||
def fake_get_client(target, version_cap, serializer):
|
||||
self.assertEqual(FakeAPI.TOPIC, target.topic)
|
||||
self.assertEqual(FakeAPI.RPC_API_VERSION, target.version)
|
||||
self.assertEqual('1.4', version_cap)
|
||||
self.assertEqual('1.3', serializer.version_cap)
|
||||
self.assertEqual(self.latest_ovo_version, serializer.version_cap)
|
||||
|
||||
get_client.side_effect = fake_get_client
|
||||
FakeAPI()
|
||||
with mock.patch('cinder.rpc.LAST_OBJ_VERSIONS',
|
||||
{'cinder-scheduler': self.latest_ovo_version}):
|
||||
FakeAPI()
|
||||
|
||||
self.assertFalse(get_min_obj.called)
|
||||
self.assertFalse(get_min_rpc.called)
|
||||
get_min_obj.assert_not_called()
|
||||
get_min_rpc.assert_not_called()
|
||||
|
||||
@ddt.data([], ['noop'], ['noop', 'noop'])
|
||||
@mock.patch('oslo_messaging.JsonPayloadSerializer', wraps=True)
|
||||
|
@ -380,19 +380,11 @@ class ServiceTestCase(test.TestCase):
|
||||
|
||||
app.stop()
|
||||
|
||||
@mock.patch('cinder.objects.Service.get_minimum_obj_version',
|
||||
return_value='1.6')
|
||||
def test_start_rpc_and_init_host_no_cluster(self, is_upgrading_mock):
|
||||
"""Test that without cluster we don't create rpc service."""
|
||||
app = service.Service.create(host=self.host,
|
||||
binary=constants.VOLUME_BINARY,
|
||||
cluster=None, topic=self.topic)
|
||||
self._check_rpc_servers_and_init_host(app, False, None)
|
||||
|
||||
@mock.patch('cinder.objects.Service.get_minimum_obj_version')
|
||||
def test_start_rpc_and_init_host_cluster(self, get_min_obj_mock):
|
||||
"""Test that with cluster we create the rpc service."""
|
||||
get_min_obj_mock.return_value = '1.7'
|
||||
# cluster was introduced in 1.7, so latest will be enough to test this
|
||||
get_min_obj_mock.return_value = self.latest_ovo_version
|
||||
cluster = 'cluster@backend#pool'
|
||||
self.host = 'host@backend#pool'
|
||||
app = service.Service.create(host=self.host,
|
||||
|
@ -125,15 +125,18 @@ class VolumeTestCase(base.BaseVolumeTestCase):
|
||||
@mock.patch('cinder.objects.service.Service.get_minimum_rpc_version')
|
||||
@mock.patch('cinder.objects.service.Service.get_minimum_obj_version')
|
||||
@mock.patch('cinder.rpc.LAST_RPC_VERSIONS', {'cinder-scheduler': '1.3'})
|
||||
@mock.patch('cinder.rpc.LAST_OBJ_VERSIONS', {'cinder-scheduler': '1.4'})
|
||||
def test_reset(self, get_min_obj, get_min_rpc):
|
||||
vol_mgr = vol_manager.VolumeManager()
|
||||
old_version = objects.base.OBJ_VERSIONS.versions[-2]
|
||||
|
||||
with mock.patch('cinder.rpc.LAST_OBJ_VERSIONS',
|
||||
{'cinder-scheduler': old_version}):
|
||||
vol_mgr = vol_manager.VolumeManager()
|
||||
|
||||
scheduler_rpcapi = vol_mgr.scheduler_rpcapi
|
||||
self.assertEqual('1.3', scheduler_rpcapi.client.version_cap)
|
||||
self.assertEqual('1.4',
|
||||
self.assertEqual(old_version,
|
||||
scheduler_rpcapi.client.serializer._base.version_cap)
|
||||
get_min_obj.return_value = objects.base.OBJ_VERSIONS.get_current()
|
||||
get_min_obj.return_value = self.latest_ovo_version
|
||||
vol_mgr.reset()
|
||||
|
||||
scheduler_rpcapi = vol_mgr.scheduler_rpcapi
|
||||
|
Loading…
x
Reference in New Issue
Block a user