Merge "compute: Add 'server * --all-projects' option"
This commit is contained in:
commit
011991bcf3
@ -31,6 +31,7 @@ from osc_lib.cli import parseractions
|
|||||||
from osc_lib.command import command
|
from osc_lib.command import command
|
||||||
from osc_lib import exceptions
|
from osc_lib import exceptions
|
||||||
from osc_lib import utils
|
from osc_lib import utils
|
||||||
|
from oslo_utils import strutils
|
||||||
|
|
||||||
from openstackclient.i18n import _
|
from openstackclient.i18n import _
|
||||||
from openstackclient.identity import common as identity_common
|
from openstackclient.identity import common as identity_common
|
||||||
@ -193,6 +194,24 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
|
|||||||
return info
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
def boolenv(*vars, default=False):
|
||||||
|
"""Search for the first defined of possibly many bool-like env vars.
|
||||||
|
|
||||||
|
Returns the first environment variable defined in vars, or returns the
|
||||||
|
default.
|
||||||
|
|
||||||
|
:param vars: Arbitrary strings to search for. Case sensitive.
|
||||||
|
:param default: The default to return if no value found.
|
||||||
|
:returns: A boolean corresponding to the value found, else the default if
|
||||||
|
no value found.
|
||||||
|
"""
|
||||||
|
for v in vars:
|
||||||
|
value = os.environ.get(v, None)
|
||||||
|
if value:
|
||||||
|
return strutils.bool_from_string(value)
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
class AddFixedIP(command.Command):
|
class AddFixedIP(command.Command):
|
||||||
_description = _("Add fixed IP address to server")
|
_description = _("Add fixed IP address to server")
|
||||||
|
|
||||||
@ -1322,6 +1341,15 @@ class DeleteServer(command.Command):
|
|||||||
action='store_true',
|
action='store_true',
|
||||||
help=_('Force delete server(s)'),
|
help=_('Force delete server(s)'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--all-projects',
|
||||||
|
action='store_true',
|
||||||
|
default=boolenv('ALL_PROJECTS'),
|
||||||
|
help=_(
|
||||||
|
'Delete server(s) in another project by name (admin only)'
|
||||||
|
'(can be specified using the ALL_PROJECTS envvar)'
|
||||||
|
),
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--wait',
|
'--wait',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
@ -1339,7 +1367,8 @@ class DeleteServer(command.Command):
|
|||||||
compute_client = self.app.client_manager.compute
|
compute_client = self.app.client_manager.compute
|
||||||
for server in parsed_args.server:
|
for server in parsed_args.server:
|
||||||
server_obj = utils.find_resource(
|
server_obj = utils.find_resource(
|
||||||
compute_client.servers, server)
|
compute_client.servers, server,
|
||||||
|
all_tenants=parsed_args.all_projects)
|
||||||
|
|
||||||
if parsed_args.force:
|
if parsed_args.force:
|
||||||
compute_client.servers.force_delete(server_obj.id)
|
compute_client.servers.force_delete(server_obj.id)
|
||||||
@ -1347,11 +1376,13 @@ class DeleteServer(command.Command):
|
|||||||
compute_client.servers.delete(server_obj.id)
|
compute_client.servers.delete(server_obj.id)
|
||||||
|
|
||||||
if parsed_args.wait:
|
if parsed_args.wait:
|
||||||
if not utils.wait_for_delete(compute_client.servers,
|
if not utils.wait_for_delete(
|
||||||
server_obj.id,
|
compute_client.servers,
|
||||||
callback=_show_progress):
|
server_obj.id,
|
||||||
LOG.error(_('Error deleting server: %s'),
|
callback=_show_progress,
|
||||||
server_obj.id)
|
):
|
||||||
|
msg = _('Error deleting server: %s')
|
||||||
|
LOG.error(msg, server_obj.id)
|
||||||
self.app.stdout.write(_('Error deleting server\n'))
|
self.app.stdout.write(_('Error deleting server\n'))
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
|
|
||||||
@ -1446,8 +1477,11 @@ class ListServer(command.Lister):
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--all-projects',
|
'--all-projects',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
default=bool(int(os.environ.get("ALL_PROJECTS", 0))),
|
default=boolenv('ALL_PROJECTS'),
|
||||||
help=_('Include all projects (admin only)'),
|
help=_(
|
||||||
|
'Include all projects (admin only) '
|
||||||
|
'(can be specified using the ALL_PROJECTS envvar)'
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--project',
|
'--project',
|
||||||
@ -3939,6 +3973,15 @@ class StartServer(command.Command):
|
|||||||
nargs="+",
|
nargs="+",
|
||||||
help=_('Server(s) to start (name or ID)'),
|
help=_('Server(s) to start (name or ID)'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--all-projects',
|
||||||
|
action='store_true',
|
||||||
|
default=boolenv('ALL_PROJECTS'),
|
||||||
|
help=_(
|
||||||
|
'Start server(s) in another project by name (admin only)'
|
||||||
|
'(can be specified using the ALL_PROJECTS envvar)'
|
||||||
|
),
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -3947,6 +3990,7 @@ class StartServer(command.Command):
|
|||||||
utils.find_resource(
|
utils.find_resource(
|
||||||
compute_client.servers,
|
compute_client.servers,
|
||||||
server,
|
server,
|
||||||
|
all_tenants=parsed_args.all_projects,
|
||||||
).start()
|
).start()
|
||||||
|
|
||||||
|
|
||||||
@ -3961,6 +4005,15 @@ class StopServer(command.Command):
|
|||||||
nargs="+",
|
nargs="+",
|
||||||
help=_('Server(s) to stop (name or ID)'),
|
help=_('Server(s) to stop (name or ID)'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--all-projects',
|
||||||
|
action='store_true',
|
||||||
|
default=boolenv('ALL_PROJECTS'),
|
||||||
|
help=_(
|
||||||
|
'Stop server(s) in another project by name (admin only)'
|
||||||
|
'(can be specified using the ALL_PROJECTS envvar)'
|
||||||
|
),
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -3969,6 +4022,7 @@ class StopServer(command.Command):
|
|||||||
utils.find_resource(
|
utils.find_resource(
|
||||||
compute_client.servers,
|
compute_client.servers,
|
||||||
server,
|
server,
|
||||||
|
all_tenants=parsed_args.all_projects,
|
||||||
).stop()
|
).stop()
|
||||||
|
|
||||||
|
|
||||||
|
@ -2913,6 +2913,28 @@ class TestServerDelete(TestServer):
|
|||||||
self.servers_mock.delete.assert_has_calls(calls)
|
self.servers_mock.delete.assert_has_calls(calls)
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
@mock.patch.object(common_utils, 'find_resource')
|
||||||
|
def test_server_delete_with_all_projects(self, mock_find_resource):
|
||||||
|
servers = self.setup_servers_mock(count=1)
|
||||||
|
mock_find_resource.side_effect = compute_fakes.FakeServer.get_servers(
|
||||||
|
servers, 0,
|
||||||
|
)
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
servers[0].id,
|
||||||
|
'--all-projects',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('server', [servers[0].id]),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
mock_find_resource.assert_called_once_with(
|
||||||
|
mock.ANY, servers[0].id, all_tenants=True,
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(common_utils, 'wait_for_delete', return_value=True)
|
@mock.patch.object(common_utils, 'wait_for_delete', return_value=True)
|
||||||
def test_server_delete_wait_ok(self, mock_wait_for_delete):
|
def test_server_delete_wait_ok(self, mock_wait_for_delete):
|
||||||
servers = self.setup_servers_mock(count=1)
|
servers = self.setup_servers_mock(count=1)
|
||||||
@ -6781,6 +6803,28 @@ class TestServerStart(TestServer):
|
|||||||
def test_server_start_multi_servers(self):
|
def test_server_start_multi_servers(self):
|
||||||
self.run_method_with_servers('start', 3)
|
self.run_method_with_servers('start', 3)
|
||||||
|
|
||||||
|
@mock.patch.object(common_utils, 'find_resource')
|
||||||
|
def test_server_start_with_all_projects(self, mock_find_resource):
|
||||||
|
servers = self.setup_servers_mock(count=1)
|
||||||
|
mock_find_resource.side_effect = compute_fakes.FakeServer.get_servers(
|
||||||
|
servers, 0,
|
||||||
|
)
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
servers[0].id,
|
||||||
|
'--all-projects',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('server', [servers[0].id]),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
mock_find_resource.assert_called_once_with(
|
||||||
|
mock.ANY, servers[0].id, all_tenants=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestServerStop(TestServer):
|
class TestServerStop(TestServer):
|
||||||
|
|
||||||
@ -6801,6 +6845,28 @@ class TestServerStop(TestServer):
|
|||||||
def test_server_stop_multi_servers(self):
|
def test_server_stop_multi_servers(self):
|
||||||
self.run_method_with_servers('stop', 3)
|
self.run_method_with_servers('stop', 3)
|
||||||
|
|
||||||
|
@mock.patch.object(common_utils, 'find_resource')
|
||||||
|
def test_server_start_with_all_projects(self, mock_find_resource):
|
||||||
|
servers = self.setup_servers_mock(count=1)
|
||||||
|
mock_find_resource.side_effect = compute_fakes.FakeServer.get_servers(
|
||||||
|
servers, 0,
|
||||||
|
)
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
servers[0].id,
|
||||||
|
'--all-projects',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('server', [servers[0].id]),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
mock_find_resource.assert_called_once_with(
|
||||||
|
mock.ANY, servers[0].id, all_tenants=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestServerSuspend(TestServer):
|
class TestServerSuspend(TestServer):
|
||||||
|
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The ``server delete``, ``server start`` and ``server stop`` commands now
|
||||||
|
support the ``--all-projects`` option. This allows you to perform the
|
||||||
|
specified action on a server in another project using the server name.
|
||||||
|
This is an admin-only action by default.
|
@ -8,6 +8,7 @@ iso8601>=0.1.11 # MIT
|
|||||||
openstacksdk>=0.53.0 # Apache-2.0
|
openstacksdk>=0.53.0 # Apache-2.0
|
||||||
osc-lib>=2.3.0 # Apache-2.0
|
osc-lib>=2.3.0 # Apache-2.0
|
||||||
oslo.i18n>=3.15.3 # Apache-2.0
|
oslo.i18n>=3.15.3 # Apache-2.0
|
||||||
|
oslo.utils>=3.33.0 # Apache-2.0
|
||||||
python-keystoneclient>=3.22.0 # Apache-2.0
|
python-keystoneclient>=3.22.0 # Apache-2.0
|
||||||
python-novaclient>=17.0.0 # Apache-2.0
|
python-novaclient>=17.0.0 # Apache-2.0
|
||||||
python-cinderclient>=3.3.0 # Apache-2.0
|
python-cinderclient>=3.3.0 # Apache-2.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user