Merge "Fix volume transfers request commands"
This commit is contained in:
commit
ca06a09d4d
@ -16,6 +16,17 @@ this backwards incompatible change handling.
|
|||||||
Backwards Incompatible Changes
|
Backwards Incompatible Changes
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
|
.. Carry this section as comments until 4.0 release
|
||||||
|
.. Release 4.0
|
||||||
|
.. -----------
|
||||||
|
|
||||||
|
.. 1. Change ``volume transfer request accept`` to use new option ``--auth-key``
|
||||||
|
.. rather than a second positional argument.
|
||||||
|
|
||||||
|
.. * As of: 4.0
|
||||||
|
.. * Remove in: <5.0>
|
||||||
|
.. * Commit: <tbd>
|
||||||
|
|
||||||
Release 3.0
|
Release 3.0
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@ -13,17 +13,19 @@ Accept volume transfer request
|
|||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
openstack volume transfer request accept
|
openstack volume transfer request accept
|
||||||
<transfer-request>
|
--auth-key <key>
|
||||||
<auth-key>
|
<transfer-request-id>
|
||||||
|
|
||||||
|
.. option:: --auth-key <key>
|
||||||
|
|
||||||
|
Volume transfer request authentication key
|
||||||
|
|
||||||
.. _volume_transfer_request_accept:
|
.. _volume_transfer_request_accept:
|
||||||
.. describe:: <transfer-request>
|
.. describe:: <transfer-request-id>
|
||||||
|
|
||||||
Volume transfer request to accept (name or ID)
|
Volume transfer request to accept (ID only)
|
||||||
|
|
||||||
.. describe:: <auth-key>
|
Non-admin users are only able to specify the transfer request by ID.
|
||||||
|
|
||||||
Authentication key of transfer request
|
|
||||||
|
|
||||||
volume transfer request create
|
volume transfer request create
|
||||||
------------------------------
|
------------------------------
|
||||||
@ -65,7 +67,7 @@ Delete volume transfer request(s)
|
|||||||
volume transfer request list
|
volume transfer request list
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
Lists all volume transfer requests.
|
Lists all volume transfer requests
|
||||||
|
|
||||||
.. program:: volume transfer request list
|
.. program:: volume transfer request list
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
@ -75,8 +77,7 @@ Lists all volume transfer requests.
|
|||||||
|
|
||||||
.. option:: --all-projects
|
.. option:: --all-projects
|
||||||
|
|
||||||
Shows detail for all projects. Admin only.
|
Include all projects (admin only)
|
||||||
(defaults to False)
|
|
||||||
|
|
||||||
volume transfer request show
|
volume transfer request show
|
||||||
----------------------------
|
----------------------------
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import json
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from openstackclient.tests.functional.volume.v1 import common
|
from openstackclient.tests.functional.volume.v1 import common
|
||||||
@ -67,11 +68,12 @@ class TransferRequestTests(common.BaseVolumeTests):
|
|||||||
self.assertNotEqual('', auth_key)
|
self.assertNotEqual('', auth_key)
|
||||||
|
|
||||||
# accept the volume transfer request
|
# accept the volume transfer request
|
||||||
opts = self.get_opts(self.FIELDS)
|
json_output = json.loads(self.openstack(
|
||||||
raw_output = self.openstack(
|
'volume transfer request accept -f json ' +
|
||||||
'volume transfer request accept ' + name +
|
name + ' ' +
|
||||||
' ' + auth_key + opts)
|
'--auth-key ' + auth_key
|
||||||
self.assertEqual(name + '\n', raw_output)
|
))
|
||||||
|
self.assertEqual(name, json_output.get('name'))
|
||||||
|
|
||||||
# the volume transfer will be removed by default after accepted
|
# the volume transfer will be removed by default after accepted
|
||||||
# so just need to delete the volume here
|
# so just need to delete the volume here
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import json
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from openstackclient.tests.functional.volume.v2 import common
|
from openstackclient.tests.functional.volume.v2 import common
|
||||||
@ -67,11 +68,12 @@ class TransferRequestTests(common.BaseVolumeTests):
|
|||||||
self.assertNotEqual('', auth_key)
|
self.assertNotEqual('', auth_key)
|
||||||
|
|
||||||
# accept the volume transfer request
|
# accept the volume transfer request
|
||||||
opts = self.get_opts(self.FIELDS)
|
json_output = json.loads(self.openstack(
|
||||||
raw_output = self.openstack(
|
'volume transfer request accept -f json ' +
|
||||||
'volume transfer request accept ' + name +
|
name + ' ' +
|
||||||
' ' + auth_key + opts)
|
'--auth-key ' + auth_key
|
||||||
self.assertEqual(name + '\n', raw_output)
|
))
|
||||||
|
self.assertEqual(name, json_output.get('name'))
|
||||||
|
|
||||||
# the volume transfer will be removed by default after accepted
|
# the volume transfer will be removed by default after accepted
|
||||||
# so just need to delete the volume here
|
# so just need to delete the volume here
|
||||||
|
@ -64,24 +64,62 @@ class TestTransferAccept(TestTransfer):
|
|||||||
|
|
||||||
def test_transfer_accept(self):
|
def test_transfer_accept(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
|
'--auth-key', 'key_value',
|
||||||
self.volume_transfer.id,
|
self.volume_transfer.id,
|
||||||
'auth_key',
|
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('transfer_request', self.volume_transfer.id),
|
('transfer_request', self.volume_transfer.id),
|
||||||
('auth_key', 'auth_key'),
|
('auth_key', 'key_value'),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.transfer_mock.get.assert_called_once_with(
|
self.transfer_mock.get.assert_called_once_with(
|
||||||
self.volume_transfer.id)
|
self.volume_transfer.id,
|
||||||
|
)
|
||||||
self.transfer_mock.accept.assert_called_once_with(
|
self.transfer_mock.accept.assert_called_once_with(
|
||||||
self.volume_transfer.id, 'auth_key')
|
self.volume_transfer.id,
|
||||||
|
'key_value',
|
||||||
|
)
|
||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
self.assertEqual(self.data, data)
|
self.assertEqual(self.data, data)
|
||||||
|
|
||||||
|
def test_transfer_accept_deprecated(self):
|
||||||
|
arglist = [
|
||||||
|
self.volume_transfer.id,
|
||||||
|
'key_value',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('transfer_request', self.volume_transfer.id),
|
||||||
|
('old_auth_key', 'key_value'),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.transfer_mock.accept.assert_called_once_with(
|
||||||
|
self.volume_transfer.id,
|
||||||
|
'key_value',
|
||||||
|
)
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertEqual(self.data, data)
|
||||||
|
|
||||||
|
def test_transfer_accept_no_option(self):
|
||||||
|
arglist = [
|
||||||
|
self.volume_transfer.id,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('transfer_request', self.volume_transfer.id),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exceptions.CommandError,
|
||||||
|
self.cmd.take_action,
|
||||||
|
parsed_args,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestTransferCreate(TestTransfer):
|
class TestTransferCreate(TestTransfer):
|
||||||
|
|
||||||
@ -219,7 +257,7 @@ class TestTransferDelete(TestTransfer):
|
|||||||
self.fail('CommandError should be raised.')
|
self.fail('CommandError should be raised.')
|
||||||
except exceptions.CommandError as e:
|
except exceptions.CommandError as e:
|
||||||
self.assertEqual('1 of 2 volume transfer requests failed '
|
self.assertEqual('1 of 2 volume transfer requests failed '
|
||||||
'to delete.', str(e))
|
'to delete', str(e))
|
||||||
|
|
||||||
find_mock.assert_any_call(
|
find_mock.assert_any_call(
|
||||||
self.transfer_mock, self.volume_transfers[0].id)
|
self.transfer_mock, self.volume_transfers[0].id)
|
||||||
@ -256,8 +294,8 @@ class TestTransferList(TestTransfer):
|
|||||||
|
|
||||||
expected_columns = [
|
expected_columns = [
|
||||||
'ID',
|
'ID',
|
||||||
'Volume',
|
|
||||||
'Name',
|
'Name',
|
||||||
|
'Volume',
|
||||||
]
|
]
|
||||||
|
|
||||||
# confirming if all expected columns are present in the result.
|
# confirming if all expected columns are present in the result.
|
||||||
@ -265,8 +303,8 @@ class TestTransferList(TestTransfer):
|
|||||||
|
|
||||||
datalist = ((
|
datalist = ((
|
||||||
self.volume_transfers.id,
|
self.volume_transfers.id,
|
||||||
self.volume_transfers.volume_id,
|
|
||||||
self.volume_transfers.name,
|
self.volume_transfers.name,
|
||||||
|
self.volume_transfers.volume_id,
|
||||||
), )
|
), )
|
||||||
|
|
||||||
# confirming if all expected values are present in the result.
|
# confirming if all expected values are present in the result.
|
||||||
@ -295,8 +333,8 @@ class TestTransferList(TestTransfer):
|
|||||||
|
|
||||||
expected_columns = [
|
expected_columns = [
|
||||||
'ID',
|
'ID',
|
||||||
'Volume',
|
|
||||||
'Name',
|
'Name',
|
||||||
|
'Volume',
|
||||||
]
|
]
|
||||||
|
|
||||||
# confirming if all expected columns are present in the result.
|
# confirming if all expected columns are present in the result.
|
||||||
@ -304,8 +342,8 @@ class TestTransferList(TestTransfer):
|
|||||||
|
|
||||||
datalist = ((
|
datalist = ((
|
||||||
self.volume_transfers.id,
|
self.volume_transfers.id,
|
||||||
self.volume_transfers.volume_id,
|
|
||||||
self.volume_transfers.name,
|
self.volume_transfers.name,
|
||||||
|
self.volume_transfers.volume_id,
|
||||||
), )
|
), )
|
||||||
|
|
||||||
# confirming if all expected values are present in the result.
|
# confirming if all expected values are present in the result.
|
||||||
|
@ -64,24 +64,62 @@ class TestTransferAccept(TestTransfer):
|
|||||||
|
|
||||||
def test_transfer_accept(self):
|
def test_transfer_accept(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
|
'--auth-key', 'key_value',
|
||||||
self.volume_transfer.id,
|
self.volume_transfer.id,
|
||||||
'auth_key',
|
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('transfer_request', self.volume_transfer.id),
|
('transfer_request', self.volume_transfer.id),
|
||||||
('auth_key', 'auth_key'),
|
('auth_key', 'key_value'),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.transfer_mock.get.assert_called_once_with(
|
self.transfer_mock.get.assert_called_once_with(
|
||||||
self.volume_transfer.id)
|
self.volume_transfer.id,
|
||||||
|
)
|
||||||
self.transfer_mock.accept.assert_called_once_with(
|
self.transfer_mock.accept.assert_called_once_with(
|
||||||
self.volume_transfer.id, 'auth_key')
|
self.volume_transfer.id,
|
||||||
|
'key_value',
|
||||||
|
)
|
||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
self.assertEqual(self.data, data)
|
self.assertEqual(self.data, data)
|
||||||
|
|
||||||
|
def test_transfer_accept_deprecated(self):
|
||||||
|
arglist = [
|
||||||
|
self.volume_transfer.id,
|
||||||
|
'key_value',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('transfer_request', self.volume_transfer.id),
|
||||||
|
('old_auth_key', 'key_value'),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.transfer_mock.accept.assert_called_once_with(
|
||||||
|
self.volume_transfer.id,
|
||||||
|
'key_value',
|
||||||
|
)
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertEqual(self.data, data)
|
||||||
|
|
||||||
|
def test_transfer_accept_no_option(self):
|
||||||
|
arglist = [
|
||||||
|
self.volume_transfer.id,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('transfer_request', self.volume_transfer.id),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exceptions.CommandError,
|
||||||
|
self.cmd.take_action,
|
||||||
|
parsed_args,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestTransferCreate(TestTransfer):
|
class TestTransferCreate(TestTransfer):
|
||||||
|
|
||||||
@ -219,7 +257,7 @@ class TestTransferDelete(TestTransfer):
|
|||||||
self.fail('CommandError should be raised.')
|
self.fail('CommandError should be raised.')
|
||||||
except exceptions.CommandError as e:
|
except exceptions.CommandError as e:
|
||||||
self.assertEqual('1 of 2 volume transfer requests failed '
|
self.assertEqual('1 of 2 volume transfer requests failed '
|
||||||
'to delete.', str(e))
|
'to delete', str(e))
|
||||||
|
|
||||||
find_mock.assert_any_call(
|
find_mock.assert_any_call(
|
||||||
self.transfer_mock, self.volume_transfers[0].id)
|
self.transfer_mock, self.volume_transfers[0].id)
|
||||||
@ -256,8 +294,8 @@ class TestTransferList(TestTransfer):
|
|||||||
|
|
||||||
expected_columns = [
|
expected_columns = [
|
||||||
'ID',
|
'ID',
|
||||||
'Volume',
|
|
||||||
'Name',
|
'Name',
|
||||||
|
'Volume',
|
||||||
]
|
]
|
||||||
|
|
||||||
# confirming if all expected columns are present in the result.
|
# confirming if all expected columns are present in the result.
|
||||||
@ -265,8 +303,8 @@ class TestTransferList(TestTransfer):
|
|||||||
|
|
||||||
datalist = ((
|
datalist = ((
|
||||||
self.volume_transfers.id,
|
self.volume_transfers.id,
|
||||||
self.volume_transfers.volume_id,
|
|
||||||
self.volume_transfers.name,
|
self.volume_transfers.name,
|
||||||
|
self.volume_transfers.volume_id,
|
||||||
), )
|
), )
|
||||||
|
|
||||||
# confirming if all expected values are present in the result.
|
# confirming if all expected values are present in the result.
|
||||||
@ -295,8 +333,8 @@ class TestTransferList(TestTransfer):
|
|||||||
|
|
||||||
expected_columns = [
|
expected_columns = [
|
||||||
'ID',
|
'ID',
|
||||||
'Volume',
|
|
||||||
'Name',
|
'Name',
|
||||||
|
'Volume',
|
||||||
]
|
]
|
||||||
|
|
||||||
# confirming if all expected columns are present in the result.
|
# confirming if all expected columns are present in the result.
|
||||||
@ -304,8 +342,8 @@ class TestTransferList(TestTransfer):
|
|||||||
|
|
||||||
datalist = ((
|
datalist = ((
|
||||||
self.volume_transfers.id,
|
self.volume_transfers.id,
|
||||||
self.volume_transfers.volume_id,
|
|
||||||
self.volume_transfers.name,
|
self.volume_transfers.name,
|
||||||
|
self.volume_transfers.volume_id,
|
||||||
), )
|
), )
|
||||||
|
|
||||||
# confirming if all expected values are present in the result.
|
# confirming if all expected values are present in the result.
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
"""Volume v1 transfer action implementations"""
|
"""Volume v1 transfer action implementations"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from osc_lib.command import command
|
from osc_lib.command import command
|
||||||
@ -34,22 +35,54 @@ class AcceptTransferRequest(command.ShowOne):
|
|||||||
parser = super(AcceptTransferRequest, self).get_parser(prog_name)
|
parser = super(AcceptTransferRequest, self).get_parser(prog_name)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'transfer_request',
|
'transfer_request',
|
||||||
metavar="<transfer-request>",
|
metavar="<transfer-request-id>",
|
||||||
help=_('Volume transfer request to accept (name or ID)'),
|
help=_('Volume transfer request to accept (ID only)'),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'auth_key',
|
'old_auth_key',
|
||||||
metavar="<auth-key>",
|
metavar="<key>",
|
||||||
help=_('Authentication key of transfer request'),
|
nargs="?",
|
||||||
|
help=argparse.SUPPRESS,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--auth-key',
|
||||||
|
metavar="<key>",
|
||||||
|
help=_('Volume transfer request authentication key'),
|
||||||
)
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
volume_client = self.app.client_manager.volume
|
volume_client = self.app.client_manager.volume
|
||||||
transfer_request_id = utils.find_resource(
|
|
||||||
volume_client.transfers, parsed_args.transfer_request).id
|
try:
|
||||||
|
transfer_request_id = utils.find_resource(
|
||||||
|
volume_client.transfers,
|
||||||
|
parsed_args.transfer_request
|
||||||
|
).id
|
||||||
|
except exceptions.CommandError:
|
||||||
|
# Non-admin users will fail to lookup name -> ID so we just
|
||||||
|
# move on and attempt with the user-supplied information
|
||||||
|
transfer_request_id = parsed_args.transfer_request
|
||||||
|
|
||||||
|
# Remain backward-compatible for the previous command layout
|
||||||
|
# TODO(dtroyer): Remove this back-compat in 4.0 or Oct 2017
|
||||||
|
if not parsed_args.auth_key:
|
||||||
|
if parsed_args.old_auth_key:
|
||||||
|
# Move the old one into the correct place
|
||||||
|
parsed_args.auth_key = parsed_args.old_auth_key
|
||||||
|
self.log.warning(_(
|
||||||
|
'Specifying the auth-key as a positional argument '
|
||||||
|
'has been deprecated. Please use the --auth-key '
|
||||||
|
'option in the future.'
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
msg = _("argument --auth-key is required")
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
transfer_accept = volume_client.transfers.accept(
|
transfer_accept = volume_client.transfers.accept(
|
||||||
transfer_request_id, parsed_args.auth_key)
|
transfer_request_id,
|
||||||
|
parsed_args.auth_key,
|
||||||
|
)
|
||||||
transfer_accept._info.pop("links", None)
|
transfer_accept._info.pop("links", None)
|
||||||
|
|
||||||
return zip(*sorted(six.iteritems(transfer_accept._info)))
|
return zip(*sorted(six.iteritems(transfer_accept._info)))
|
||||||
@ -75,9 +108,12 @@ class CreateTransferRequest(command.ShowOne):
|
|||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
volume_client = self.app.client_manager.volume
|
volume_client = self.app.client_manager.volume
|
||||||
volume_id = utils.find_resource(
|
volume_id = utils.find_resource(
|
||||||
volume_client.volumes, parsed_args.volume).id
|
volume_client.volumes,
|
||||||
|
parsed_args.volume,
|
||||||
|
).id
|
||||||
volume_transfer_request = volume_client.transfers.create(
|
volume_transfer_request = volume_client.transfers.create(
|
||||||
volume_id, parsed_args.name,
|
volume_id,
|
||||||
|
parsed_args.name,
|
||||||
)
|
)
|
||||||
volume_transfer_request._info.pop("links", None)
|
volume_transfer_request._info.pop("links", None)
|
||||||
|
|
||||||
@ -104,7 +140,9 @@ class DeleteTransferRequest(command.Command):
|
|||||||
for t in parsed_args.transfer_request:
|
for t in parsed_args.transfer_request:
|
||||||
try:
|
try:
|
||||||
transfer_request_id = utils.find_resource(
|
transfer_request_id = utils.find_resource(
|
||||||
volume_client.transfers, t).id
|
volume_client.transfers,
|
||||||
|
t,
|
||||||
|
).id
|
||||||
volume_client.transfers.delete(transfer_request_id)
|
volume_client.transfers.delete(transfer_request_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result += 1
|
result += 1
|
||||||
@ -115,7 +153,7 @@ class DeleteTransferRequest(command.Command):
|
|||||||
if result > 0:
|
if result > 0:
|
||||||
total = len(parsed_args.transfer_request)
|
total = len(parsed_args.transfer_request)
|
||||||
msg = (_("%(result)s of %(total)s volume transfer requests failed"
|
msg = (_("%(result)s of %(total)s volume transfer requests failed"
|
||||||
" to delete.") % {'result': result, 'total': total})
|
" to delete") % {'result': result, 'total': total})
|
||||||
raise exceptions.CommandError(msg)
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
|
||||||
@ -129,20 +167,19 @@ class ListTransferRequest(command.Lister):
|
|||||||
dest='all_projects',
|
dest='all_projects',
|
||||||
action="store_true",
|
action="store_true",
|
||||||
default=False,
|
default=False,
|
||||||
help=_('Shows detail for all projects. Admin only. '
|
help=_('Include all projects (admin only)'),
|
||||||
'(defaults to False)')
|
|
||||||
)
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
columns = ['ID', 'Volume ID', 'Name']
|
columns = ['ID', 'Name', 'Volume ID']
|
||||||
column_headers = ['ID', 'Volume', 'Name']
|
column_headers = ['ID', 'Name', 'Volume']
|
||||||
|
|
||||||
volume_client = self.app.client_manager.volume
|
volume_client = self.app.client_manager.volume
|
||||||
|
|
||||||
volume_transfer_result = volume_client.transfers.list(
|
volume_transfer_result = volume_client.transfers.list(
|
||||||
detailed=True,
|
detailed=True,
|
||||||
search_opts={'all_tenants': parsed_args.all_projects}
|
search_opts={'all_tenants': parsed_args.all_projects},
|
||||||
)
|
)
|
||||||
|
|
||||||
return (column_headers, (
|
return (column_headers, (
|
||||||
@ -165,7 +202,9 @@ class ShowTransferRequest(command.ShowOne):
|
|||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
volume_client = self.app.client_manager.volume
|
volume_client = self.app.client_manager.volume
|
||||||
volume_transfer_request = utils.find_resource(
|
volume_transfer_request = utils.find_resource(
|
||||||
volume_client.transfers, parsed_args.transfer_request)
|
volume_client.transfers,
|
||||||
|
parsed_args.transfer_request,
|
||||||
|
)
|
||||||
volume_transfer_request._info.pop("links", None)
|
volume_transfer_request._info.pop("links", None)
|
||||||
|
|
||||||
return zip(*sorted(six.iteritems(volume_transfer_request._info)))
|
return zip(*sorted(six.iteritems(volume_transfer_request._info)))
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
"""Volume v2 transfer action implementations"""
|
"""Volume v2 transfer action implementations"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from osc_lib.command import command
|
from osc_lib.command import command
|
||||||
@ -34,22 +35,54 @@ class AcceptTransferRequest(command.ShowOne):
|
|||||||
parser = super(AcceptTransferRequest, self).get_parser(prog_name)
|
parser = super(AcceptTransferRequest, self).get_parser(prog_name)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'transfer_request',
|
'transfer_request',
|
||||||
metavar="<transfer-request>",
|
metavar="<transfer-request-id>",
|
||||||
help=_('Volume transfer request to accept (name or ID)'),
|
help=_('Volume transfer request to accept (ID only)'),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'auth_key',
|
'old_auth_key',
|
||||||
metavar="<auth-key>",
|
metavar="<key>",
|
||||||
help=_('Authentication key of transfer request'),
|
nargs="?",
|
||||||
|
help=argparse.SUPPRESS,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--auth-key',
|
||||||
|
metavar="<key>",
|
||||||
|
help=_('Volume transfer request authentication key'),
|
||||||
)
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
volume_client = self.app.client_manager.volume
|
volume_client = self.app.client_manager.volume
|
||||||
transfer_request_id = utils.find_resource(
|
|
||||||
volume_client.transfers, parsed_args.transfer_request).id
|
try:
|
||||||
|
transfer_request_id = utils.find_resource(
|
||||||
|
volume_client.transfers,
|
||||||
|
parsed_args.transfer_request
|
||||||
|
).id
|
||||||
|
except exceptions.CommandError:
|
||||||
|
# Non-admin users will fail to lookup name -> ID so we just
|
||||||
|
# move on and attempt with the user-supplied information
|
||||||
|
transfer_request_id = parsed_args.transfer_request
|
||||||
|
|
||||||
|
# Remain backward-compatible for the previous command layout
|
||||||
|
# TODO(dtroyer): Remove this back-compat in 4.0 or Oct 2017
|
||||||
|
if not parsed_args.auth_key:
|
||||||
|
if parsed_args.old_auth_key:
|
||||||
|
# Move the old one into the correct place
|
||||||
|
parsed_args.auth_key = parsed_args.old_auth_key
|
||||||
|
self.log.warning(_(
|
||||||
|
'Specifying the auth-key as a positional argument '
|
||||||
|
'has been deprecated. Please use the --auth-key '
|
||||||
|
'option in the future.'
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
msg = _("argument --auth-key is required")
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
transfer_accept = volume_client.transfers.accept(
|
transfer_accept = volume_client.transfers.accept(
|
||||||
transfer_request_id, parsed_args.auth_key)
|
transfer_request_id,
|
||||||
|
parsed_args.auth_key,
|
||||||
|
)
|
||||||
transfer_accept._info.pop("links", None)
|
transfer_accept._info.pop("links", None)
|
||||||
|
|
||||||
return zip(*sorted(six.iteritems(transfer_accept._info)))
|
return zip(*sorted(six.iteritems(transfer_accept._info)))
|
||||||
@ -75,9 +108,12 @@ class CreateTransferRequest(command.ShowOne):
|
|||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
volume_client = self.app.client_manager.volume
|
volume_client = self.app.client_manager.volume
|
||||||
volume_id = utils.find_resource(
|
volume_id = utils.find_resource(
|
||||||
volume_client.volumes, parsed_args.volume).id
|
volume_client.volumes,
|
||||||
|
parsed_args.volume,
|
||||||
|
).id
|
||||||
volume_transfer_request = volume_client.transfers.create(
|
volume_transfer_request = volume_client.transfers.create(
|
||||||
volume_id, parsed_args.name,
|
volume_id,
|
||||||
|
parsed_args.name,
|
||||||
)
|
)
|
||||||
volume_transfer_request._info.pop("links", None)
|
volume_transfer_request._info.pop("links", None)
|
||||||
|
|
||||||
@ -104,7 +140,9 @@ class DeleteTransferRequest(command.Command):
|
|||||||
for t in parsed_args.transfer_request:
|
for t in parsed_args.transfer_request:
|
||||||
try:
|
try:
|
||||||
transfer_request_id = utils.find_resource(
|
transfer_request_id = utils.find_resource(
|
||||||
volume_client.transfers, t).id
|
volume_client.transfers,
|
||||||
|
t,
|
||||||
|
).id
|
||||||
volume_client.transfers.delete(transfer_request_id)
|
volume_client.transfers.delete(transfer_request_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result += 1
|
result += 1
|
||||||
@ -115,7 +153,7 @@ class DeleteTransferRequest(command.Command):
|
|||||||
if result > 0:
|
if result > 0:
|
||||||
total = len(parsed_args.transfer_request)
|
total = len(parsed_args.transfer_request)
|
||||||
msg = (_("%(result)s of %(total)s volume transfer requests failed"
|
msg = (_("%(result)s of %(total)s volume transfer requests failed"
|
||||||
" to delete.") % {'result': result, 'total': total})
|
" to delete") % {'result': result, 'total': total})
|
||||||
raise exceptions.CommandError(msg)
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
|
||||||
@ -129,20 +167,19 @@ class ListTransferRequest(command.Lister):
|
|||||||
dest='all_projects',
|
dest='all_projects',
|
||||||
action="store_true",
|
action="store_true",
|
||||||
default=False,
|
default=False,
|
||||||
help=_('Shows detail for all projects. Admin only. '
|
help=_('Include all projects (admin only)'),
|
||||||
'(defaults to False)')
|
|
||||||
)
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
columns = ['ID', 'Volume ID', 'Name']
|
columns = ['ID', 'Name', 'Volume ID']
|
||||||
column_headers = ['ID', 'Volume', 'Name']
|
column_headers = ['ID', 'Name', 'Volume']
|
||||||
|
|
||||||
volume_client = self.app.client_manager.volume
|
volume_client = self.app.client_manager.volume
|
||||||
|
|
||||||
volume_transfer_result = volume_client.transfers.list(
|
volume_transfer_result = volume_client.transfers.list(
|
||||||
detailed=True,
|
detailed=True,
|
||||||
search_opts={'all_tenants': parsed_args.all_projects}
|
search_opts={'all_tenants': parsed_args.all_projects},
|
||||||
)
|
)
|
||||||
|
|
||||||
return (column_headers, (
|
return (column_headers, (
|
||||||
@ -165,7 +202,9 @@ class ShowTransferRequest(command.ShowOne):
|
|||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
volume_client = self.app.client_manager.volume
|
volume_client = self.app.client_manager.volume
|
||||||
volume_transfer_request = utils.find_resource(
|
volume_transfer_request = utils.find_resource(
|
||||||
volume_client.transfers, parsed_args.transfer_request)
|
volume_client.transfers,
|
||||||
|
parsed_args.transfer_request,
|
||||||
|
)
|
||||||
volume_transfer_request._info.pop("links", None)
|
volume_transfer_request._info.pop("links", None)
|
||||||
|
|
||||||
return zip(*sorted(six.iteritems(volume_transfer_request._info)))
|
return zip(*sorted(six.iteritems(volume_transfer_request._info)))
|
||||||
|
17
releasenotes/notes/bug-1633582-df2bee534c2da7fc.yaml
Normal file
17
releasenotes/notes/bug-1633582-df2bee534c2da7fc.yaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
deprecations:
|
||||||
|
- |
|
||||||
|
``volume transfer request accept`` has been changed to move the ``auth-key``
|
||||||
|
positional argument to a requried option ``--auth-key``. This leaves
|
||||||
|
the transfer request ID as the only positional arguemnt, as per the
|
||||||
|
OpenStackClient command format. The old format is still functional, but is
|
||||||
|
dperecated and will be removed in the next major release.
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fix ``volume transfer request accept`` to not fail the transfer request
|
||||||
|
name/ID lookup for non-admin users as the Volume API does not allow non-admin
|
||||||
|
users access to transfers in other projects.
|
||||||
|
[Bug `1633582 <https://bugs.launchpad.net/python-openstackclient/+bug/1633582>`_]
|
||||||
|
- |
|
||||||
|
Change the output column order in ``volume transfer request list`` to have
|
||||||
|
``ID`` followed by ``Name`` then the remaining columns.
|
Loading…
Reference in New Issue
Block a user