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:
@ -5,5 +5,5 @@
|
||||
},
|
||||
"nova_object.name":"InstanceActionPayload",
|
||||
"nova_object.namespace":"nova",
|
||||
"nova_object.version":"1.8"
|
||||
"nova_object.version":"1.9"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -6,5 +6,5 @@
|
||||
},
|
||||
"nova_object.name": "InstanceActionVolumeSwapPayload",
|
||||
"nova_object.namespace": "nova",
|
||||
"nova_object.version": "1.8"
|
||||
"nova_object.version": "1.9"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"event_type": "instance.power_on.end",
|
||||
"payload": {
|
||||
"$ref": "common_payloads/InstanceActionPayloadShareActive.json#"
|
||||
},
|
||||
"priority": "INFO",
|
||||
"publisher_id": "nova-compute:compute"
|
||||
}
|
13
doc/notification_samples/instance-power_on_share-start.json
Normal file
13
doc/notification_samples/instance-power_on_share-start.json
Normal 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"
|
||||
}
|
@ -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.
|
||||
""")
|
||||
]
|
||||
|
||||
|
@ -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'),
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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',
|
||||
|
Reference in New Issue
Block a user