Add shares to InstancePayload

This patch add share information to the InstancePayload that can be sent
if the include_share_mapping configuration parameter is enabled.

Manila is the OpenStack Shared Filesystems service.
These series of patches implement changes required in Nova to allow the shares
provided by Manila to be associated with and attached to instances using
virtiofs.

Implements: blueprint libvirt-virtiofs-attach-manila-shares

Change-Id: I3d5005eab9e3f23be149e955e8cb4608a6ee1312
This commit is contained in:
René Ribaud
2022-07-26 11:36:24 +02:00
parent 13d45b6d37
commit bf96ca7c9a
26 changed files with 542 additions and 153 deletions

View File

@ -5,5 +5,5 @@
},
"nova_object.name":"InstanceActionPayload",
"nova_object.namespace":"nova",
"nova_object.version":"1.8"
"nova_object.version":"1.9"
}

View File

@ -0,0 +1,9 @@
{
"$ref": "InstancePayloadShareActive.json",
"nova_object.data": {
"fault": null
},
"nova_object.name": "InstanceActionPayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.9"
}

View File

@ -0,0 +1,9 @@
{
"$ref": "InstancePayloadShareInactive.json",
"nova_object.data": {
"fault": null
},
"nova_object.name": "InstanceActionPayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.9"
}

View File

@ -1,13 +1,10 @@
{
"$ref": "InstanceActionPayload.json",
"nova_object.data": {
"architecture": null,
"image_uuid": "a2459075-d96c-40d5-893e-577ff92e721c",
"trusted_image_certificates": [
"rebuild-cert-id-1",
"rebuild-cert-id-2"
]
},
"nova_object.name": "InstanceActionRebuildPayload",
"nova_object.version": "1.9"
"$ref": "InstanceActionPayload.json",
"nova_object.data": {
"architecture": null,
"image_uuid": "a2459075-d96c-40d5-893e-577ff92e721c",
"trusted_image_certificates": ["rebuild-cert-id-1", "rebuild-cert-id-2"]
},
"nova_object.name": "InstanceActionRebuildPayload",
"nova_object.version": "1.10"
}

View File

@ -1,8 +1,8 @@
{
"$ref": "InstanceActionPayload.json",
"nova_object.data": {
"rescue_image_ref": "a2459075-d96c-40d5-893e-577ff92e721c"
},
"nova_object.name": "InstanceActionRescuePayload",
"nova_object.version": "1.3"
"$ref": "InstanceActionPayload.json",
"nova_object.data": {
"rescue_image_ref": "a2459075-d96c-40d5-893e-577ff92e721c"
},
"nova_object.name": "InstanceActionRescuePayload",
"nova_object.version": "1.4"
}

View File

@ -1,31 +1,31 @@
{
"$ref": "InstanceActionPayload.json",
"nova_object.data":{
"new_flavor": {
"nova_object.name": "FlavorPayload",
"nova_object.data": {
"description": null,
"disabled": false,
"ephemeral_gb": 0,
"extra_specs": {
"hw:watchdog_action": "reset"
},
"flavorid": "d5a8bb54-365a-45ae-abdb-38d249df7845",
"is_public": true,
"memory_mb": 256,
"name": "other_flavor",
"projects": null,
"root_gb": 1,
"rxtx_factor": 1.0,
"swap": 0,
"vcpu_weight": 0,
"vcpus": 1
},
"nova_object.namespace": "nova",
"nova_object.version": "1.4"
"$ref": "InstanceActionPayload.json",
"nova_object.data": {
"new_flavor": {
"nova_object.name": "FlavorPayload",
"nova_object.data": {
"description": null,
"disabled": false,
"ephemeral_gb": 0,
"extra_specs": {
"hw:watchdog_action": "reset"
},
"task_state": "resize_prep"
"flavorid": "d5a8bb54-365a-45ae-abdb-38d249df7845",
"is_public": true,
"memory_mb": 256,
"name": "other_flavor",
"projects": null,
"root_gb": 1,
"rxtx_factor": 1.0,
"swap": 0,
"vcpu_weight": 0,
"vcpus": 1
},
"nova_object.namespace": "nova",
"nova_object.version": "1.4"
},
"nova_object.name": "InstanceActionResizePrepPayload",
"nova_object.version": "1.3"
"task_state": "resize_prep"
},
"nova_object.name": "InstanceActionResizePrepPayload",
"nova_object.version": "1.4"
}

View File

@ -1,9 +1,9 @@
{
"$ref": "InstanceActionPayload.json",
"nova_object.data":{
"snapshot_image_id": "d2aae36f-785c-4518-8016-bc9534d9fc7f"
},
"nova_object.name":"InstanceActionSnapshotPayload",
"nova_object.namespace":"nova",
"nova_object.version":"1.9"
"$ref": "InstanceActionPayload.json",
"nova_object.data": {
"snapshot_image_id": "d2aae36f-785c-4518-8016-bc9534d9fc7f"
},
"nova_object.name": "InstanceActionSnapshotPayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.10"
}

View File

@ -1,9 +1,9 @@
{
"$ref": "InstanceActionPayload.json",
"nova_object.data":{
"volume_id": "a07f71dc-8151-4e7d-a0cc-cd24a3f11113"
},
"nova_object.name": "InstanceActionVolumePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.6"
}
"$ref": "InstanceActionPayload.json",
"nova_object.data": {
"volume_id": "a07f71dc-8151-4e7d-a0cc-cd24a3f11113"
},
"nova_object.name": "InstanceActionVolumePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.7"
}

View File

@ -6,5 +6,5 @@
},
"nova_object.name": "InstanceActionVolumeSwapPayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.8"
"nova_object.version": "1.9"
}

View File

@ -1,28 +1,25 @@
{
"$ref":"InstanceActionPayload.json",
"nova_object.data": {
"block_devices": [],
"keypairs": [
{
"nova_object.version": "1.0",
"nova_object.namespace": "nova",
"nova_object.name": "KeypairPayload",
"nova_object.data": {
"user_id": "fake",
"name": "my-key",
"fingerprint": "1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c",
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated-by-Nova",
"type": "ssh"
}
}
],
"tags": ["tag"],
"trusted_image_certificates": [
"cert-id-1",
"cert-id-2"
],
"instance_name": "instance-00000001"
},
"nova_object.name":"InstanceCreatePayload",
"nova_object.version": "1.12"
"$ref": "InstanceActionPayload.json",
"nova_object.data": {
"block_devices": [],
"keypairs": [
{
"nova_object.version": "1.0",
"nova_object.namespace": "nova",
"nova_object.name": "KeypairPayload",
"nova_object.data": {
"user_id": "fake",
"name": "my-key",
"fingerprint": "1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c",
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated-by-Nova",
"type": "ssh"
}
}
],
"tags": ["tag"],
"trusted_image_certificates": ["cert-id-1", "cert-id-2"],
"instance_name": "instance-00000001"
},
"nova_object.name": "InstanceCreatePayload",
"nova_object.version": "1.13"
}

View File

@ -1,9 +1,11 @@
{
"$ref": "InstancePayload.json",
"nova_object.data":{
"audit_period": {"$ref": "AuditPeriodPayload.json#"}
"nova_object.data": {
"audit_period": {
"$ref": "AuditPeriodPayload.json#"
}
},
"nova_object.name":"InstanceExistsPayload",
"nova_object.namespace":"nova",
"nova_object.version":"2.0"
"nova_object.name": "InstanceExistsPayload",
"nova_object.namespace": "nova",
"nova_object.version": "2.1"
}

View File

@ -38,9 +38,10 @@
"request_id": "req-5b6c791d-5709-4f36-8fbe-c3e02869e35d",
"action_initiator_user": "fake",
"action_initiator_project": "6f70656e737461636b20342065766572",
"locked_reason": null
"locked_reason": null,
"shares": []
},
"nova_object.name":"InstancePayload",
"nova_object.namespace":"nova",
"nova_object.version":"1.8"
"nova_object.version":"1.9"
}

View File

@ -0,0 +1,57 @@
{
"nova_object.data": {
"architecture": "x86_64",
"availability_zone": "nova",
"block_devices": [
{
"$ref": "BlockDevicePayload.json#"
}
],
"created_at": "2012-10-29T13:42:11Z",
"deleted_at": null,
"display_name": "some-server",
"display_description": "some-server",
"host": "compute",
"host_name": "some-server",
"ip_addresses": [
{
"$ref": "IpPayload.json#"
}
],
"kernel_id": "",
"key_name": "my-key",
"launched_at": "2012-10-29T13:42:11Z",
"image_uuid": "155d900f-4e14-4e4c-a73d-069cbf4541e6",
"metadata": {},
"locked": false,
"node": "fake-mini",
"os_type": null,
"progress": 0,
"ramdisk_id": "",
"reservation_id": "r-npxv0e40",
"state": "active",
"task_state": null,
"power_state": "running",
"tenant_id": "6f70656e737461636b20342065766572",
"terminated_at": null,
"auto_disk_config": "MANUAL",
"flavor": {
"$ref": "FlavorPayload.json#"
},
"updated_at": "2012-10-29T13:42:11Z",
"user_id": "fake",
"uuid": "178b0921-8f85-4257-88b6-2e743b5a975c",
"request_id": "req-5b6c791d-5709-4f36-8fbe-c3e02869e35d",
"action_initiator_user": "fake",
"action_initiator_project": "6f70656e737461636b20342065766572",
"locked_reason": null,
"shares": [
{
"$ref": "ShareActivePayload.json#"
}
]
},
"nova_object.name": "InstancePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.9"
}

View File

@ -0,0 +1,57 @@
{
"nova_object.data": {
"architecture": "x86_64",
"availability_zone": "nova",
"block_devices": [
{
"$ref": "BlockDevicePayload.json#"
}
],
"created_at": "2012-10-29T13:42:11Z",
"deleted_at": null,
"display_name": "some-server",
"display_description": "some-server",
"host": "compute",
"host_name": "some-server",
"ip_addresses": [
{
"$ref": "IpPayload.json#"
}
],
"kernel_id": "",
"key_name": "my-key",
"launched_at": "2012-10-29T13:42:11Z",
"image_uuid": "155d900f-4e14-4e4c-a73d-069cbf4541e6",
"metadata": {},
"locked": false,
"node": "fake-mini",
"os_type": null,
"progress": 0,
"ramdisk_id": "",
"reservation_id": "r-npxv0e40",
"state": "active",
"task_state": null,
"power_state": "running",
"tenant_id": "6f70656e737461636b20342065766572",
"terminated_at": null,
"auto_disk_config": "MANUAL",
"flavor": {
"$ref": "FlavorPayload.json#"
},
"updated_at": "2012-10-29T13:42:11Z",
"user_id": "fake",
"uuid": "178b0921-8f85-4257-88b6-2e743b5a975c",
"request_id": "req-5b6c791d-5709-4f36-8fbe-c3e02869e35d",
"action_initiator_user": "fake",
"action_initiator_project": "6f70656e737461636b20342065766572",
"locked_reason": null,
"shares": [
{
"$ref": "ShareInactivePayload.json#"
}
]
},
"nova_object.name": "InstancePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.9"
}

View File

@ -1,32 +1,32 @@
{
"$ref": "InstancePayload.json",
"nova_object.data": {
"audit_period": {
"nova_object.data": {
"audit_period_beginning": "2012-10-01T00:00:00Z",
"audit_period_ending": "2012-10-29T13:42:11Z"
},
"nova_object.name": "AuditPeriodPayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
},
"block_devices": [],
"old_display_name": null,
"state_update": {
"nova_object.data": {
"new_task_state": null,
"old_state": "active",
"old_task_state": null,
"state": "active"
},
"nova_object.name": "InstanceStateUpdatePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
},
"tags": [],
"updated_at": "2012-10-29T13:42:11Z"
"$ref": "InstancePayload.json",
"nova_object.data": {
"audit_period": {
"nova_object.data": {
"audit_period_beginning": "2012-10-01T00:00:00Z",
"audit_period_ending": "2012-10-29T13:42:11Z"
},
"nova_object.name": "AuditPeriodPayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
},
"nova_object.name": "InstanceUpdatePayload",
"nova_object.namespace": "nova",
"nova_object.version": "2.0"
"block_devices": [],
"old_display_name": null,
"state_update": {
"nova_object.data": {
"new_task_state": null,
"old_state": "active",
"old_task_state": null,
"state": "active"
},
"nova_object.name": "InstanceStateUpdatePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
},
"tags": [],
"updated_at": "2012-10-29T13:42:11Z"
},
"nova_object.name": "InstanceUpdatePayload",
"nova_object.namespace": "nova",
"nova_object.version": "2.1"
}

View File

@ -0,0 +1,12 @@
{
"nova_object.data": {
"share_mapping_uuid": "f7c1726d-7622-42b3-8b2c-4473239d60d1",
"export_location": "10.0.0.50:/mnt/foo",
"share_id": "e8debdc0-447a-4376-a10a-4cd9122d7986",
"status": "active",
"tag": "e8debdc0-447a-4376-a10a-4cd9122d7986"
},
"nova_object.name": "SharePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
}

View File

@ -0,0 +1,12 @@
{
"nova_object.data": {
"share_mapping_uuid": "f7c1726d-7622-42b3-8b2c-4473239d60d1",
"export_location": "10.0.0.50:/mnt/foo",
"share_id": "e8debdc0-447a-4376-a10a-4cd9122d7986",
"status": "inactive",
"tag": "e8debdc0-447a-4376-a10a-4cd9122d7986"
},
"nova_object.name": "SharePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
}

View File

@ -0,0 +1,8 @@
{
"event_type": "instance.power_on.end",
"payload": {
"$ref": "common_payloads/InstanceActionPayloadShareActive.json#"
},
"priority": "INFO",
"publisher_id": "nova-compute:compute"
}

View File

@ -0,0 +1,13 @@
{
"event_type": "instance.power_on.start",
"payload": {
"$ref": "common_payloads/InstanceActionPayloadShareInactive.json#",
"nova_object.data": {
"task_state": "powering-on",
"state": "stopped",
"power_state": "shutdown"
}
},
"priority": "INFO",
"publisher_id": "nova-compute:compute"
}

View File

@ -105,6 +105,15 @@ If enabled, include block device information in the versioned notification
payload. Sending block device information is disabled by default as providing
that information can incur some overhead on the system since the information
may need to be loaded from the database.
"""),
cfg.BoolOpt(
'include_share_mapping',
default=False,
help="""
If enabled, include share mapping information in the versioned notification
payload. Sending share mapping information is disabled by default as providing
that information can incur some overhead on the system since the information
may need to be loaded from the database.
""")
]

View File

@ -69,7 +69,8 @@ class InstancePayload(base.NotificationPayloadBase):
# Version 1.7: Added action_initiator_user and action_initiator_project to
# InstancePayload
# Version 1.8: Added locked_reason field
VERSION = '1.8'
# Version 1.9: Add shares related data
VERSION = '1.9'
fields = {
'uuid': fields.UUIDField(),
'user_id': fields.StringField(nullable=True),
@ -115,6 +116,7 @@ class InstancePayload(base.NotificationPayloadBase):
'action_initiator_user': fields.StringField(nullable=True),
'action_initiator_project': fields.StringField(nullable=True),
'locked_reason': fields.StringField(nullable=True),
'shares': fields.ListOfObjectsField('SharePayload', nullable=True),
}
def __init__(self, context, instance, bdms=None):
@ -126,6 +128,7 @@ class InstancePayload(base.NotificationPayloadBase):
self.block_devices = BlockDevicePayload.from_bdms(bdms)
else:
self.block_devices = BlockDevicePayload.from_instance(instance)
self.shares = SharePayload.from_instance(instance)
# NOTE(Kevin_Zheng): Don't include request_id for periodic tasks,
# RequestContext for periodic tasks does not include project_id
# and user_id. Consider modify this once periodic tasks got a
@ -151,7 +154,8 @@ class InstanceActionPayload(InstancePayload):
# Version 1.7: Added action_initiator_user and action_initiator_project to
# InstancePayload
# Version 1.8: Added locked_reason field to InstancePayload
VERSION = '1.8'
# Version 1.9: Add shares related data
VERSION = '1.9'
fields = {
'fault': fields.ObjectField('ExceptionPayload', nullable=True),
'request_id': fields.StringField(nullable=True),
@ -174,7 +178,8 @@ class InstanceActionVolumePayload(InstanceActionPayload):
# Version 1.5: Added action_initiator_user and action_initiator_project to
# InstancePayload
# Version 1.6: Added locked_reason field to InstancePayload
VERSION = '1.6'
# Version 1.7: Add shares to InstancePayload
VERSION = '1.7'
fields = {
'volume_id': fields.UUIDField()
}
@ -216,7 +221,8 @@ class InstanceActionVolumeSwapPayload(InstanceActionPayload):
# Version 1.7: Added action_initiator_user and action_initiator_project to
# InstancePayload
# Version 1.8: Added locked_reason field to InstancePayload
VERSION = '1.8'
# Version 1.9: Add shares to InstancePayload
VERSION = '1.9'
fields = {
'old_volume_id': fields.UUIDField(),
'new_volume_id': fields.UUIDField(),
@ -252,7 +258,8 @@ class InstanceCreatePayload(InstanceActionPayload):
# InstancePayload
# 1.11: Added instance_name to InstanceCreatePayload
# Version 1.12: Added locked_reason field to InstancePayload
VERSION = '1.12'
# Version 1.13: Add shares to InstancePayload
VERSION = '1.13'
fields = {
'keypairs': fields.ListOfObjectsField('KeypairPayload'),
'tags': fields.ListOfStringsField(),
@ -286,7 +293,8 @@ class InstanceActionResizePrepPayload(InstanceActionPayload):
# Version 1.2: Added action_initiator_user and action_initiator_project to
# InstancePayload
# Version 1.3: Added locked_reason field to InstancePayload
VERSION = '1.3'
# Version 1.4: Add shares to InstancePayload
VERSION = '1.4'
fields = {
'new_flavor': fields.ObjectField('FlavorPayload', nullable=True)
}
@ -313,7 +321,8 @@ class InstanceUpdatePayload(InstancePayload):
# InstancePayload
# Version 1.9: Added locked_reason field to InstancePayload
# Version 2.0: Remove bandwidth field
VERSION = '2.0'
# Version 2.1: Add shares to InstancePayload
VERSION = '2.1'
fields = {
'state_update': fields.ObjectField('InstanceStateUpdatePayload'),
'audit_period': fields.ObjectField('AuditPeriodPayload'),
@ -339,7 +348,8 @@ class InstanceActionRescuePayload(InstanceActionPayload):
# Version 1.2: Added action_initiator_user and action_initiator_project to
# InstancePayload
# Version 1.3: Added locked_reason field to InstancePayload
VERSION = '1.3'
# Version 1.4: Add shares to InstancePayload
VERSION = '1.4'
fields = {
'rescue_image_ref': fields.UUIDField(nullable=True)
}
@ -364,7 +374,8 @@ class InstanceActionRebuildPayload(InstanceActionPayload):
# Version 1.8: Added action_initiator_user and action_initiator_project to
# InstancePayload
# Version 1.9: Added locked_reason field to InstancePayload
VERSION = '1.9'
# Version 1.10: Add shares to InstancePayload
VERSION = '1.10'
fields = {
'trusted_image_certificates': fields.ListOfStringsField(
nullable=True)
@ -492,6 +503,51 @@ class BlockDevicePayload(base.NotificationPayloadBase):
return payloads
@nova_base.NovaObjectRegistry.register_notification
class SharePayload(base.NotificationPayloadBase):
# Version 1.0: Initial version
VERSION = '1.0'
SCHEMA = {
'share_mapping_uuid': ('share', 'uuid'),
'share_id': ('share', 'share_id'),
'status': ('share', 'status'),
'tag': ('share', 'tag'),
# Do not include 'export_location' as it could contains sensitive data
# 'export_location': ('share', 'export_location')
}
fields = {
'share_mapping_uuid': fields.UUIDField(),
'share_id': fields.UUIDField(),
'status': fields.StringField(nullable=False),
'tag': fields.StringField(nullable=False),
# 'export_location': fields.StringField(nullable=False),
}
def __init__(self, share):
super(SharePayload, self).__init__()
self.populate_schema(share=share)
@classmethod
def from_instance(cls, instance):
"""Returns a list of SharePayload objects based on the passed
shares.
"""
if not CONF.notifications.include_share_mapping:
return None
instance_shares = instance.get_shares()
return [cls(share) for share in instance_shares]
@classmethod
def from_shares(cls, shares):
"""Returns a list of SharePayload objects based on the passed
ShareMappingList.
"""
return [cls(share) for share in shares]
@nova_base.NovaObjectRegistry.register_notification
class InstanceStateUpdatePayload(base.NotificationPayloadBase):
# Version 1.0: Initial version
@ -523,7 +579,9 @@ class InstanceStateUpdatePayload(base.NotificationPayloadBase):
@base.notification_sample('instance-suspend-start.json')
@base.notification_sample('instance-suspend-end.json')
@base.notification_sample('instance-power_on-start.json')
@base.notification_sample('instance-power_on_share-start.json')
@base.notification_sample('instance-power_on-end.json')
@base.notification_sample('instance-power_on_share-end.json')
@base.notification_sample('instance-power_off-start.json')
@base.notification_sample('instance-power_off-end.json')
@base.notification_sample('instance-reboot-start.json')
@ -712,7 +770,8 @@ class InstanceActionSnapshotPayload(InstanceActionPayload):
# Version 1.8: Added action_initiator_user and action_initiator_project to
# InstancePayload
# Version 1.9: Added locked_reason field to InstancePayload
VERSION = '1.9'
# Version 1.10: Add shares to InstancePayload
VERSION = '1.10'
fields = {
'snapshot_image_id': fields.UUIDField(),
}
@ -732,7 +791,8 @@ class InstanceExistsPayload(InstancePayload):
# InstancePayload
# Version 1.2: Added locked_reason field to InstancePayload
# Version 2.0: Remove bandwidth field
VERSION = '2.0'
# Version 2.1: Add shares to InstancePayload
VERSION = '2.1'
fields = {
'audit_period': fields.ObjectField('AuditPeriodPayload'),
}

View File

@ -1260,6 +1260,10 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
return objects.BlockDeviceMappingList.get_by_instance_uuid(
self._context, self.uuid)
def get_shares(self):
return objects.ShareMappingList.get_by_instance_uuid(
self._context, self.uuid)
def remove_pci_device_and_request(self, pci_device):
"""Remove the PciDevice and the related InstancePciRequest"""
if pci_device in self.pci_devices.objects:

View File

@ -550,7 +550,9 @@ class InstanceHelperMixin:
self.notifier.wait_for_versioned_notifications(
'instance.interface_detach.end')
def _get_share(self, server, share_id):
def _get_share(self, server, share_id, admin=False):
if admin:
return (self.admin_api.get_server_share(server['id'], share_id))
return (self.api.get_server_share(server['id'], share_id))
def _attach_share(self, server, share_id, tag=None):

View File

@ -28,6 +28,7 @@ class TestInstanceNotificationSampleWithMultipleCompute(
def setUp(self):
self.flags(compute_driver='fake.FakeLiveMigrateDriver')
self.flags(bdms_in_notifications='True', group='notifications')
self.flags(include_share_mapping='True', group='notifications')
super(TestInstanceNotificationSampleWithMultipleCompute, self).setUp()
self.neutron = fixtures.NeutronFixture(self)
self.useFixture(self.neutron)
@ -337,6 +338,7 @@ class TestInstanceNotificationSample(
def setUp(self):
self.flags(bdms_in_notifications='True', group='notifications')
self.flags(include_share_mapping='True', group='notifications')
super(TestInstanceNotificationSample, self).setUp()
self.neutron = fixtures.NeutronFixture(self)
self.useFixture(self.neutron)
@ -389,8 +391,7 @@ class TestInstanceNotificationSample(
self._test_interface_attach_error,
self._test_lock_unlock_instance,
self._test_lock_unlock_instance_with_reason,
self._test_share_attach,
self._test_share_detach,
self._test_share_attach_detach,
]
for action in actions:
@ -1703,12 +1704,35 @@ class TestInstanceNotificationSample(
'uuid': server['id']},
actual=self.notifier.versioned_notifications[1])
def _test_share_attach(self, server):
def _test_share_attach_detach(self, server):
expected_shares = [
{
"nova_object.name": "SharePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0",
"nova_object.data": {
"share_mapping_uuid": (
"f7c1726d-7622-42b3-8b2c-4473239d60d1"),
"share_id": "e8debdc0-447a-4376-a10a-4cd9122d7986",
"status": "attaching",
"tag": "e8debdc0-447a-4376-a10a-4cd9122d7986",
# 'export_location': '10.0.0.50:/mnt/foo',
},
}
]
self.api.post_server_action(server['id'], {'os-stop': {}})
self._wait_for_state_change(server, expected_status='SHUTOFF')
self.notifier.reset()
self._attach_share(server, "e8debdc0-447a-4376-a10a-4cd9122d7986")
share_info = self._get_share(
server, "e8debdc0-447a-4376-a10a-4cd9122d7986", admin=True
)
expected_shares[0]["nova_object.data"][
"share_mapping_uuid"
] = share_info["uuid"]
self.assertEqual(2, len(self.notifier.versioned_notifications),
self.notifier.versioned_notifications)
@ -1718,24 +1742,76 @@ class TestInstanceNotificationSample(
'reservation_id': server['reservation_id'],
'uuid': server['id'],
'state': 'stopped',
'power_state': 'shutdown'},
'power_state': 'shutdown',
'shares': expected_shares
},
actual=self.notifier.versioned_notifications[0])
expected_shares[0]['nova_object.data']['status'] = 'inactive'
self._verify_notification(
'instance-share_attach-end',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id'],
'state': 'stopped',
'power_state': 'shutdown'},
'power_state': 'shutdown',
'shares': expected_shares
},
actual=self.notifier.versioned_notifications[1])
# Start server
self.notifier.reset()
self.api.post_server_action(server['id'], {'os-start': {}})
self._wait_for_state_change(server, expected_status='ACTIVE')
self.assertEqual(2, len(self.notifier.versioned_notifications),
self.notifier.versioned_notifications)
self._verify_notification(
'instance-power_on_share-start',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id'],
'state': 'stopped',
'power_state': 'shutdown',
'shares': expected_shares,
},
actual=self.notifier.versioned_notifications[0])
expected_shares[0]['nova_object.data']['status'] = 'active'
self._verify_notification(
'instance-power_on_share-end',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id'],
'state': 'active',
'power_state': 'running',
'shares': expected_shares,
},
actual=self.notifier.versioned_notifications[1])
def _test_share_detach(self, server):
# Shutdown server
self.notifier.reset()
self.api.post_server_action(server['id'], {'os-stop': {}})
self._wait_for_state_change(server, expected_status='SHUTOFF')
self.assertEqual(2, len(self.notifier.versioned_notifications),
self.notifier.versioned_notifications)
self._verify_notification(
'instance-power_off-start',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id'],
'state': 'active',
'power_state': 'running',
},
actual=self.notifier.versioned_notifications[0])
self._verify_notification(
'instance-power_off-end',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id'],
'state': 'stopped',
'power_state': 'shutdown',
},
actual=self.notifier.versioned_notifications[1])
self.notifier.reset()
# Detach share
@ -1749,7 +1825,8 @@ class TestInstanceNotificationSample(
'reservation_id': server['reservation_id'],
'uuid': server['id'],
'state': 'stopped',
'power_state': 'shutdown'},
'power_state': 'shutdown',
},
actual=self.notifier.versioned_notifications[0])
self._verify_notification(
'instance-share_detach-end',
@ -1762,8 +1839,29 @@ class TestInstanceNotificationSample(
actual=self.notifier.versioned_notifications[1])
# Restart server
self.notifier.reset()
self.api.post_server_action(server['id'], {'os-start': {}})
self._wait_for_state_change(server, expected_status='ACTIVE')
self.assertEqual(2, len(self.notifier.versioned_notifications),
self.notifier.versioned_notifications)
self._verify_notification(
'instance-power_on-start',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id'],
'state': 'stopped',
'power_state': 'shutdown',
},
actual=self.notifier.versioned_notifications[0])
self._verify_notification(
'instance-power_on-end',
replacements={
'reservation_id': server['reservation_id'],
'uuid': server['id'],
'state': 'active',
'power_state': 'running',
},
actual=self.notifier.versioned_notifications[1])
def _test_rescue_unrescue_server(self, server):
# Both "rescue" and "unrescue" notification asserts are made here

View File

@ -172,3 +172,44 @@ class TestBlockDevicePayload(test.NoDBTestCase):
bmds = instance_notification.BlockDevicePayload.from_instance(
instance)
self.assertIsNone(bmds)
class TestSharePayload(test.NoDBTestCase):
@mock.patch('nova.objects.instance.Instance.get_shares')
def test_payload_contains_shares_if_requested(self, mock_get_shares):
self.flags(include_share_mapping='True', group='notifications')
context = mock.Mock()
instance = objects.Instance(uuid=uuids.instance_uuid)
share_mapping = objects.ShareMapping(context)
share_mapping.uuid = uuids.share_mapping
share_mapping.instance_uuid = uuids.instance
share_mapping.share_id = uuids.share
share_mapping.status = 'inactive'
share_mapping.tag = 'fake_tag'
share_mapping.export_location = '192.168.122.152:/manila/share'
share_mapping.share_proto = 'NFS'
mock_get_shares.return_value = [share_mapping]
shares = instance_notification.SharePayload.from_instance(
instance)
self.assertEqual(1, len(shares))
share = shares[0]
self.assertIsInstance(share, instance_notification.SharePayload)
self.assertEqual(uuids.share_mapping, share.share_mapping_uuid)
self.assertEqual(uuids.share, share.share_id)
self.assertEqual('inactive', share.status)
self.assertEqual('fake_tag', share.tag)
# self.assertEqual('192.168.122.152:/manila/share',
# share.export_location)
self.assertNotIn('export_location', share)
@mock.patch('nova.objects.instance.Instance.get_shares',
return_value=mock.NonCallableMock())
def test_shares_are_skipped_by_default(self, mock_get_shares):
instance = objects.Instance(uuid=uuids.instance_uuid)
shares = instance_notification.SharePayload.from_instance(
instance)
self.assertIsNone(shares)

View File

@ -387,37 +387,37 @@ notification_object_data = {
# more information.
'ImageMetaPropsPayload': '1.15-a3d7a75fedbf373bcab2d9d6ece249df',
'InstanceActionNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionPayload': '1.8-b948818df6ec562e4eb4b23e515e451b',
'InstanceActionPayload': '1.9-525dcf81b6e4592d935712a2675309dc',
'InstanceActionRebuildNotification':
'1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionRebuildPayload': '1.9-3c1ac23f70c03665797f792ace3d9176',
'InstanceActionRebuildPayload': '1.10-b741a7add29a8c1f584fd5d5b3362372',
'InstanceActionRescueNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionRescuePayload': '1.3-329dda4c0a516c0fedc68aa02ccf3e88',
'InstanceActionRescuePayload': '1.4-29e0327c2ad6953d367db68d9aceef20',
'InstanceActionResizePrepNotification':
'1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionResizePrepPayload': '1.3-8969438a48c496569c2add19b170dca1',
'InstanceActionResizePrepPayload': '1.4-214cb6123beb0ffe5eb1e08ce424086b',
'InstanceActionShareNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionSharePayload': '1.0-024003b187136ba4db3b958e8d22d540',
'InstanceActionSharePayload': '1.0-6dafbbd061f582e9c0ce100eeee790b9',
'InstanceActionVolumeNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionVolumePayload': '1.6-b5fd2b23dbafe33b72cdbbb7b937bf18',
'InstanceActionVolumePayload': '1.7-542d9e1485c6b925958df9912dc744ec',
'InstanceActionVolumeSwapNotification':
'1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionVolumeSwapPayload': '1.8-9d8edd0a3556a69f0bfe17ab2641ca19',
'InstanceActionVolumeSwapPayload': '1.9-dc4e9852819bc3283b0c809a1f6602d4',
'InstanceCreateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceCreatePayload': '1.12-bd007423bfdb634448ec589b28f7cd39',
'InstancePayload': '1.8-0bfe0b258ae4cf6ff68463c9e75adb80',
'InstanceCreatePayload': '1.13-95a394da335944f074ac1bf58696ad87',
'InstancePayload': '1.9-164048a4d38ed9a4b2f9c3927f1c9038',
'InstanceActionSnapshotNotification':
'1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionSnapshotPayload': '1.9-75809b8ef913f7d2e262c5c804213ac8',
'InstanceActionSnapshotPayload': '1.10-7a4878ef67da0939ee069bb78eab07ae',
'InstanceExistsNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceExistsPayload': '2.0-5eb1efc3d1b03d87be82062219adaf6d',
'InstanceExistsPayload': '2.1-264c20f9c5d76320c9129865b9bc6f8f',
'InstanceNUMACellPayload': '1.2-93c3cadf4f6ee427664c00039d0a1fed',
'InstanceNUMATopologyPayload': '1.0-c7885d5da4c66525f20e7d637a7267c4',
'InstancePCIRequestPayload': '1.1-ee482d38f6c84bb77bba3f4c8708231c',
'InstancePCIRequestsPayload': '1.0-29cb0fa1ba6756423a9606437c3f247f',
'InstanceStateUpdatePayload': '1.0-9d136730749479042d47f2a08c2c2e69',
'InstanceUpdateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceUpdatePayload': '2.0-f6edbd2b53373f120debf5570ec14676',
'InstanceUpdatePayload': '2.1-25c1e9c521bd350c20cbda94b7cc7dc0',
'IpPayload': '1.0-a9f0b3f1ef17ab12378096816faa4e55',
'KeypairNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'KeypairPayload': '1.0-84f5e6da739af31ea10b89858c67b512',
@ -434,6 +434,7 @@ notification_object_data = {
'ServerGroupPayload': '1.1-f866cf95bf64bfa799193807e66a6a1e',
'ServiceStatusNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'ServiceStatusPayload': '1.1-64c5f80b3865832b936898f11dcddad0',
'SharePayload': '1.0-80797287e01668692ee9beb70f269821',
'VirtCPUTopologyPayload': '1.0-24fa607e20f48c829953edad6b0b5cc8',
'VolumeUsageNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'VolumeUsagePayload': '1.0-a12c300f0ddbc7488685c9d9ed36d9e8',