6ca6f6fce6
When an admin creates a snapshot of another project owners instance, either via the createImage API directly, or via the shelve or createBackup APIs, the admin project is the owner of the image and the owner of the instance (in another project) cannot "see" the image. This is a problem, for example, if an admin shelves a tenant user's server and then the user tries to unshelve the server because the user will not have access to get the shelved snapshot image. This change fixes the problem by leveraging the sharing feature [1] in the v2 image API. When a snapshot is created where the request context project_id does not match the owner of the instance project_id, the instance owner project_id is granted sharing access to the image. By default, this means the instance owner (tenant user) can get the image directly via the image ID if they know it, but otherwise the image is not listed for the user to avoid spamming their image listing. In the case of unshelve, the end user does not need to know the image ID since it is stored in the instance system_metadata. Regardless, the user could accept the pending image membership if they want to see the snapshot show up when listing available images. Note that while the non-admin project has access to the snapshot image, they cannot delete it. For example, if the user tries to delete or unshelve a shelved offloaded server, nova will try to delete the snapshot image which will fail and log a warning since the user does not own the image (the admin does). However, the delete/unshelve operations will not fail because the image cannot be deleted, which is an acceptable trade-off. Due to some very old legacy virt driver code which started in the libvirt driver and was copied to several other drivers, several virt drivers had to be modified to not overwrite the "visibility=shared" image property by passing "is_public=False" when uploading the image data. There was no point in the virt drivers setting is_public=False since the API already controls that. It does mean, however, that the bug fix is not really in effect until both the API and compute service code has this fix. A functional test is added which depends on tracking the owner/member values in the _FakeImageService fixture. Impacted unit tests are updated accordingly. [1] https://developer.openstack.org/api-ref/image/v2/index.html#sharing Conflicts: nova/compute/api.py nova/compute/utils.py NOTE(seyeongkim): The conflict is due to not having change7e229ba40d
in Rocky. nova/tests/functional/test_images.py NOTE(seyeongkim) The conflict is due to not having correct uuidsentiel position. Change-Id: If53bc8fa8ab4a8a9072061af7afed53fc12c97a5 Closes-Bug: #1675791 (cherry picked from commit35cc0f5e94
)
63 lines
2.3 KiB
Python
63 lines
2.3 KiB
Python
# Copyright 2015, 2018 IBM Corp.
|
|
#
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
"""Utilities related to glance image management for the PowerVM driver."""
|
|
|
|
from nova import utils
|
|
|
|
|
|
def stream_blockdev_to_glance(context, image_api, image_id, metadata, devpath):
|
|
"""Stream the entire contents of a block device to a glance image.
|
|
|
|
:param context: Nova security context.
|
|
:param image_api: Handle to the glance image API.
|
|
:param image_id: UUID of the prepared glance image.
|
|
:param metadata: Dictionary of metadata for the image.
|
|
:param devpath: String path to device file of block device to be uploaded,
|
|
e.g. "/dev/sde".
|
|
"""
|
|
# Make the device file owned by the current user for the duration of the
|
|
# operation.
|
|
with utils.temporary_chown(devpath), open(devpath, 'rb') as stream:
|
|
# Stream it. This is synchronous.
|
|
image_api.update(context, image_id, metadata, stream)
|
|
|
|
|
|
def generate_snapshot_metadata(context, image_api, image_id, instance):
|
|
"""Generate a metadata dictionary for an instance snapshot.
|
|
|
|
:param context: Nova security context.
|
|
:param image_api: Handle to the glance image API.
|
|
:param image_id: UUID of the prepared glance image.
|
|
:param instance: The Nova instance whose disk is to be snapshotted.
|
|
:return: A dict of metadata suitable for image_api.update.
|
|
"""
|
|
image = image_api.get(context, image_id)
|
|
|
|
# TODO(esberglu): Update this to v2 metadata
|
|
metadata = {
|
|
'name': image['name'],
|
|
'status': 'active',
|
|
'disk_format': 'raw',
|
|
'container_format': 'bare',
|
|
'properties': {
|
|
'image_location': 'snapshot',
|
|
'image_state': 'available',
|
|
'owner_id': instance.project_id,
|
|
}
|
|
}
|
|
return metadata
|