Transfer snapshots with volumes
This patch will support to transfer volumes with or without snapshots in new V3 api after mircoversion 3.55. Change-Id: I61a84b5abf386a4073baea57d8820c8fd762ae03 Depends-On: https://review.openstack.org/533564/ Implements: blueprint transfer-snps-with-vols
This commit is contained in:
parent
8f933a9a34
commit
a554faa653
@ -630,6 +630,45 @@ class FakeHTTPClient(fake_v2.FakeHTTPClient):
|
||||
def get_resource_filters(self, **kw):
|
||||
return 200, {}, {'resource_filters': []}
|
||||
|
||||
def get_volume_transfers_detail(self, **kw):
|
||||
base_uri = 'http://localhost:8776'
|
||||
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
||||
transfer1 = '5678'
|
||||
transfer2 = 'f625ec3e-13dd-4498-a22a-50afd534cc41'
|
||||
return (200, {},
|
||||
{'transfers': [
|
||||
fake_v2._stub_transfer_full(transfer1, base_uri,
|
||||
tenant_id),
|
||||
fake_v2._stub_transfer_full(transfer2, base_uri,
|
||||
tenant_id)]})
|
||||
|
||||
def get_volume_transfers_5678(self, **kw):
|
||||
base_uri = 'http://localhost:8776'
|
||||
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
||||
transfer1 = '5678'
|
||||
return (200, {},
|
||||
{'transfer':
|
||||
fake_v2._stub_transfer_full(transfer1, base_uri, tenant_id)})
|
||||
|
||||
def delete_volume_transfers_5678(self, **kw):
|
||||
return (202, {}, None)
|
||||
|
||||
def post_volume_transfers(self, **kw):
|
||||
base_uri = 'http://localhost:8776'
|
||||
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
||||
transfer1 = '5678'
|
||||
return (202, {},
|
||||
{'transfer': fake_v2._stub_transfer(transfer1, base_uri,
|
||||
tenant_id)})
|
||||
|
||||
def post_volume_transfers_5678_accept(self, **kw):
|
||||
base_uri = 'http://localhost:8776'
|
||||
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
||||
transfer1 = '5678'
|
||||
return (200, {},
|
||||
{'transfer': fake_v2._stub_transfer(transfer1, base_uri,
|
||||
tenant_id)})
|
||||
|
||||
|
||||
def fake_request_get():
|
||||
versions = {'versions': [{'id': 'v1.0',
|
||||
|
@ -1299,3 +1299,12 @@ class ShellTest(utils.TestCase):
|
||||
'service_id': 1}
|
||||
|
||||
self.assert_called('POST', '/workers/cleanup', body=expected)
|
||||
|
||||
def test_create_transfer(self):
|
||||
self.run_command('--os-volume-api-version 3.55 transfer-create '
|
||||
'--no-snapshots 1234')
|
||||
expected = {'transfer': {'volume_id': 1234,
|
||||
'name': None,
|
||||
'no_snapshots': True
|
||||
}}
|
||||
self.assert_called('POST', '/volume-transfers', body=expected)
|
||||
|
67
cinderclient/tests/unit/v3/test_volume_transfers.py
Normal file
67
cinderclient/tests/unit/v3/test_volume_transfers.py
Normal file
@ -0,0 +1,67 @@
|
||||
# Copyright 2018 FiberHome Telecommunication Technologies CO.,LTD
|
||||
# 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.
|
||||
|
||||
from cinderclient.tests.unit import utils
|
||||
from cinderclient.tests.unit.v3 import fakes
|
||||
|
||||
|
||||
cs = fakes.FakeClient()
|
||||
|
||||
|
||||
class VolumeTransfersTest(utils.TestCase):
|
||||
|
||||
def test_create(self):
|
||||
vol = cs.transfers.create('1234')
|
||||
cs.assert_called('POST', '/volume-transfers',
|
||||
body={'transfer': {'volume_id': '1234', 'name': None,
|
||||
'no_snapshots': False}})
|
||||
self._assert_request_id(vol)
|
||||
|
||||
def test_create_without_snapshots(self):
|
||||
vol = cs.transfers.create('1234', no_snapshots=True)
|
||||
cs.assert_called('POST', '/volume-transfers',
|
||||
body={'transfer': {'volume_id': '1234', 'name': None,
|
||||
'no_snapshots': True}})
|
||||
self._assert_request_id(vol)
|
||||
|
||||
def test_get(self):
|
||||
transfer_id = '5678'
|
||||
vol = cs.transfers.get(transfer_id)
|
||||
cs.assert_called('GET', '/volume-transfers/%s' % transfer_id)
|
||||
self._assert_request_id(vol)
|
||||
|
||||
def test_list(self):
|
||||
lst = cs.transfers.list()
|
||||
cs.assert_called('GET', '/volume-transfers/detail')
|
||||
self._assert_request_id(lst)
|
||||
|
||||
def test_delete(self):
|
||||
b = cs.transfers.list()[0]
|
||||
vol = b.delete()
|
||||
cs.assert_called('DELETE', '/volume-transfers/5678')
|
||||
self._assert_request_id(vol)
|
||||
vol = cs.transfers.delete('5678')
|
||||
self._assert_request_id(vol)
|
||||
cs.assert_called('DELETE', '/volume-transfers/5678')
|
||||
vol = cs.transfers.delete(b)
|
||||
cs.assert_called('DELETE', '/volume-transfers/5678')
|
||||
self._assert_request_id(vol)
|
||||
|
||||
def test_accept(self):
|
||||
transfer_id = '5678'
|
||||
auth_key = '12345'
|
||||
vol = cs.transfers.accept(transfer_id, auth_key)
|
||||
cs.assert_called('POST', '/volume-transfers/%s/accept' % transfer_id)
|
||||
self._assert_request_id(vol)
|
@ -2375,7 +2375,7 @@ def do_backup_create(cs, args):
|
||||
|
||||
kwargs = {}
|
||||
if getattr(args, 'metadata', None):
|
||||
kwargs['metadata'] = shell_utils.extract_metadata(args)
|
||||
kwargs['metadata'] = shell_utils.extract_metadata(args)
|
||||
az = getattr(args, 'availability_zone', None)
|
||||
if az:
|
||||
kwargs['availability_zone'] = az
|
||||
@ -2396,3 +2396,38 @@ def do_backup_create(cs, args):
|
||||
info.pop('links')
|
||||
|
||||
utils.print_dict(info)
|
||||
|
||||
|
||||
@utils.arg('volume', metavar='<volume>',
|
||||
help='Name or ID of volume to transfer.')
|
||||
@utils.arg('--name',
|
||||
metavar='<name>',
|
||||
default=None,
|
||||
help='Transfer name. Default=None.')
|
||||
@utils.arg('--display-name',
|
||||
help=argparse.SUPPRESS)
|
||||
@utils.arg('--no-snapshots',
|
||||
action='store_true',
|
||||
help='Allows or disallows transfer volumes without snapshots. '
|
||||
'Default=False.',
|
||||
start_version='3.55',
|
||||
default=False)
|
||||
def do_transfer_create(cs, args):
|
||||
"""Creates a volume transfer."""
|
||||
if args.display_name is not None:
|
||||
args.name = args.display_name
|
||||
|
||||
kwargs = {}
|
||||
no_snapshots = getattr(args, 'no_snapshots', None)
|
||||
if no_snapshots is not None:
|
||||
kwargs['no_snapshots'] = no_snapshots
|
||||
|
||||
volume = utils.find_volume(cs, args.volume)
|
||||
transfer = cs.transfers.create(volume.id,
|
||||
args.name,
|
||||
**kwargs)
|
||||
info = dict()
|
||||
info.update(transfer._info)
|
||||
|
||||
info.pop('links', None)
|
||||
utils.print_dict(info)
|
||||
|
@ -17,4 +17,70 @@
|
||||
Volume transfer interface (v3 extension).
|
||||
"""
|
||||
|
||||
from cinderclient.v2.volume_transfers import * # flake8: noqa
|
||||
from cinderclient import api_versions
|
||||
from cinderclient import base
|
||||
from cinderclient import utils
|
||||
from cinderclient.v2 import volume_transfers
|
||||
|
||||
|
||||
VolumeTransfer = volume_transfers.VolumeTransfer
|
||||
|
||||
|
||||
class VolumeTransferManager(volume_transfers.VolumeTransferManager):
|
||||
@api_versions.wraps("3.55")
|
||||
def create(self, volume_id, name=None, no_snapshots=False):
|
||||
"""Creates a volume transfer.
|
||||
|
||||
:param volume_id: The ID of the volume to transfer.
|
||||
:param name: The name of the transfer.
|
||||
:param no_snapshots: Transfer volumes without snapshots.
|
||||
:rtype: :class:`VolumeTransfer`
|
||||
"""
|
||||
body = {'transfer': {'volume_id': volume_id,
|
||||
'name': name,
|
||||
'no_snapshots': no_snapshots}}
|
||||
return self._create('/volume-transfers', body, 'transfer')
|
||||
|
||||
@api_versions.wraps("3.55")
|
||||
def accept(self, transfer_id, auth_key):
|
||||
"""Accept a volume transfer.
|
||||
|
||||
:param transfer_id: The ID of the transfer to accept.
|
||||
:param auth_key: The auth_key of the transfer.
|
||||
:rtype: :class:`VolumeTransfer`
|
||||
"""
|
||||
body = {'accept': {'auth_key': auth_key}}
|
||||
return self._create('/volume-transfers/%s/accept' % transfer_id,
|
||||
body, 'transfer')
|
||||
|
||||
@api_versions.wraps("3.55")
|
||||
def get(self, transfer_id):
|
||||
"""Show details of a volume transfer.
|
||||
|
||||
:param transfer_id: The ID of the volume transfer to display.
|
||||
:rtype: :class:`VolumeTransfer`
|
||||
"""
|
||||
return self._get("/volume-transfers/%s" % transfer_id, "transfer")
|
||||
|
||||
@api_versions.wraps("3.55")
|
||||
def list(self, detailed=True, search_opts=None):
|
||||
"""Get a list of all volume transfer.
|
||||
|
||||
:rtype: list of :class:`VolumeTransfer`
|
||||
"""
|
||||
query_string = utils.build_query_param(search_opts)
|
||||
|
||||
detail = ""
|
||||
if detailed:
|
||||
detail = "/detail"
|
||||
|
||||
return self._list("/volume-transfers%s%s" % (detail, query_string),
|
||||
"transfers")
|
||||
|
||||
@api_versions.wraps("3.55")
|
||||
def delete(self, transfer_id):
|
||||
"""Delete a volume transfer.
|
||||
|
||||
:param transfer_id: The :class:`VolumeTransfer` to delete.
|
||||
"""
|
||||
return self._delete("/volume-transfers/%s" % base.getid(transfer_id))
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Starting with microversion 3.55, the volume transfer command now has the
|
||||
ability to exclude a volume's snapshots when transferring a volume to another
|
||||
project. The new command format is `cinder transfer-create --no-snapshots`.
|
Loading…
Reference in New Issue
Block a user