diff --git a/nova/objects/fields.py b/nova/objects/fields.py index 332acf95a6..b476f40209 100644 --- a/nova/objects/fields.py +++ b/nova/objects/fields.py @@ -529,11 +529,13 @@ class RNGModel(BaseNovaEnum): class ShareMappingStatus(BaseNovaEnum): """Represents the possible status of a share mapping""" + ATTACHING = "attaching" + DETACHING = "detaching" ACTIVE = "active" INACTIVE = "inactive" ERROR = "error" - ALL = (ACTIVE, INACTIVE, ERROR) + ALL = (ATTACHING, DETACHING, ACTIVE, INACTIVE, ERROR) class ShareMappingProto(BaseNovaEnum): diff --git a/nova/objects/share_mapping.py b/nova/objects/share_mapping.py index 687e135e84..da246b658a 100644 --- a/nova/objects/share_mapping.py +++ b/nova/objects/share_mapping.py @@ -11,6 +11,9 @@ # under the License. import logging + +from oslo_utils import versionutils + from nova.db.main import api as db from nova import exception from nova.objects import base @@ -21,8 +24,10 @@ LOG = logging.getLogger(__name__) @base.NovaObjectRegistry.register class ShareMapping(base.NovaTimestampObject, base.NovaObject): - # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.0: Initial version. + # Version 1.1: Add "attaching" and "detaching" to possible values + # of status field. + VERSION = '1.1' fields = { 'id': fields.IntegerField(read_only=True), @@ -35,6 +40,22 @@ class ShareMapping(base.NovaTimestampObject, base.NovaObject): 'share_proto': fields.ShareMappingProtoField() } + def obj_make_compatible(self, primitive, target_version): + super(ShareMapping, self).obj_make_compatible( + primitive, target_version + ) + target_version = versionutils.convert_version_to_tuple(target_version) + if target_version < (1, 1): + status = primitive.get('status') + if status in ( + fields.ShareMappingStatus.ATTACHING, + fields.ShareMappingStatus.DETACHING, + ): + raise exception.ObjectActionError( + action='obj_make_compatible', + reason='status=%s not supported in version %s' % ( + status, target_version)) + @staticmethod def _from_db_object(context, share_mapping, db_share_mapping): for field in share_mapping.fields: @@ -52,7 +73,7 @@ class ShareMapping(base.NovaTimestampObject, base.NovaObject): def create(self): LOG.info( - "Associate share '%s' to instance '%s'.", + "Attaching share '%s' to instance '%s'.", self.share_id, self.instance_uuid) self.save() @@ -60,7 +81,7 @@ class ShareMapping(base.NovaTimestampObject, base.NovaObject): @base.remotable def delete(self): LOG.info( - "Dissociate share '%s' from instance '%s'.", + "Detaching share '%s' from instance '%s'.", self.share_id, self.instance_uuid, ) @@ -68,17 +89,17 @@ class ShareMapping(base.NovaTimestampObject, base.NovaObject): self._context, self.instance_uuid, self.share_id ) - def attach(self): + def activate(self): LOG.info( - "Share '%s' about to be attached to instance '%s'.", + "Share '%s' about to be activated on instance '%s'.", self.share_id, self.instance_uuid) self.status = fields.ShareMappingStatus.ACTIVE self.save() - def detach(self): + def deactivate(self): LOG.info( - "Share '%s' about to be detached from instance '%s'.", + "Share '%s' about to be deactivated on instance '%s'.", self.share_id, self.instance_uuid, ) @@ -135,10 +156,10 @@ class ShareMappingList(base.ObjectListBase, base.NovaObject): return base.obj_make_list( context, cls(context), ShareMapping, db_share_mappings) - def attach_all(self): + def activate_all(self): for share in self: - share.attach() + share.activate() - def detach_all(self): + def deactivate_all(self): for share in self: - share.detach() + share.deactivate() diff --git a/nova/tests/unit/objects/test_objects.py b/nova/tests/unit/objects/test_objects.py index 0966783d55..808ad69462 100644 --- a/nova/tests/unit/objects/test_objects.py +++ b/nova/tests/unit/objects/test_objects.py @@ -1168,7 +1168,7 @@ object_data = { 'Selection': '1.1-548e3c2f04da2a61ceaf9c4e1589f264', 'Service': '1.22-8a740459ab9bf258a19c8fcb875c2d9a', 'ServiceList': '1.19-5325bce13eebcbf22edc9678285270cc', - 'ShareMapping': '1.0-5ed0db9b97582e84d582c0b8488aa5df', + 'ShareMapping': '1.1-3f1f4e053d37c1ddcdd0040cee569c1f', 'ShareMappingList': '1.0-634980d5efdf3656e28c8dec3d862ab9', 'Tag': '1.1-8b8d7d5b48887651a0e01241672e2963', 'TagList': '1.1-55231bdb671ecf7641d6a2e9109b5d8e', diff --git a/nova/tests/unit/objects/test_share_mapping.py b/nova/tests/unit/objects/test_share_mapping.py index d9dd39d30b..36d8cd06ea 100644 --- a/nova/tests/unit/objects/test_share_mapping.py +++ b/nova/tests/unit/objects/test_share_mapping.py @@ -16,6 +16,7 @@ from nova.db.main import api as db from nova.db.main import models from nova import exception from nova import objects +from nova.objects import fields from nova.objects import share_mapping as sm from nova.tests.unit.objects import test_objects from oslo_utils.fixture import uuidsentinel as uuids @@ -60,6 +61,20 @@ class _TestShareMapping(object): fake_share_mapping, allow_missing=['deleted', 'deleted_at']) + def test_obj_make_compatible_attaching_status(self): + obj = objects.ShareMapping() + obj.status = fields.ShareMappingStatus.ATTACHING + primitive = obj.obj_to_primitive('1.1') + self.assertIn("status", primitive['nova_object.data']) + + exc = self.assertRaises( + exception.ObjectActionError, obj.obj_to_primitive, "1.0" + ) + + self.assertIn( + "status=attaching not supported in version (1, 0)", str(exc) + ) + @mock.patch( 'nova.db.main.api.share_mapping_update', return_value=fake_share_mapping) @@ -137,7 +152,7 @@ class _TestShareMapping(object): @mock.patch( 'nova.db.main.api.share_mapping_update', return_value=fake_share_mapping_attached) - def test_attach(self, mock_upd): + def test_activate(self, mock_upd): share_mapping = objects.ShareMapping(self.context) share_mapping.uuid = uuids.share_mapping share_mapping.instance_uuid = uuids.instance @@ -146,7 +161,7 @@ class _TestShareMapping(object): share_mapping.tag = 'fake_tag' share_mapping.export_location = '192.168.122.152:/manila/share' share_mapping.share_proto = 'NFS' - share_mapping.attach() + share_mapping.activate() mock_upd.assert_called_once_with( self.context, uuids.share_mapping, @@ -163,7 +178,7 @@ class _TestShareMapping(object): @mock.patch( 'nova.db.main.api.share_mapping_update', return_value=fake_share_mapping) - def test_detach(self, mock_upd): + def test_deactivate(self, mock_upd): share_mapping = objects.ShareMapping(self.context) share_mapping.uuid = uuids.share_mapping share_mapping.instance_uuid = uuids.instance @@ -172,7 +187,7 @@ class _TestShareMapping(object): share_mapping.tag = 'fake_tag' share_mapping.export_location = '192.168.122.152:/manila/share' share_mapping.share_proto = 'NFS' - share_mapping.detach() + share_mapping.deactivate() mock_upd.assert_called_once_with( self.context, uuids.share_mapping,