From dc918e56fcc9c1d5971f2efe50fd4d0bf7b15b6e Mon Sep 17 00:00:00 2001 From: archanaserver Date: Thu, 19 Aug 2021 03:14:11 +0000 Subject: [PATCH] [OSC] Implement Share Server Commands Added the implementation of the share server commands to OSC. Commands are: - openstack share server delete - openstack share server show - openstack share server list - openstack share server adopt - openstack share server abandon - openstack share server set --status Partially-implements: bp openstack-client-support Co-Authored-By: Carlos da Silva Change-Id: I01b0ee1a8092002d2c2aa916617b2db75654e8d8 --- doc/source/cli/osc/v2/index.rst | 7 + manilaclient/osc/v2/share_servers.py | 411 ++++++++++++++ manilaclient/tests/unit/osc/v2/fakes.py | 57 ++ .../tests/unit/osc/v2/test_share_servers.py | 511 ++++++++++++++++++ setup.cfg | 6 + 5 files changed, 992 insertions(+) create mode 100644 manilaclient/osc/v2/share_servers.py create mode 100644 manilaclient/tests/unit/osc/v2/test_share_servers.py diff --git a/doc/source/cli/osc/v2/index.rst b/doc/source/cli/osc/v2/index.rst index 5eafb9feb..84fe3dacf 100644 --- a/doc/source/cli/osc/v2/index.rst +++ b/doc/source/cli/osc/v2/index.rst @@ -195,3 +195,10 @@ share group snapshots .. autoprogram-cliff:: openstack.share.v2 :command: share group snapshot * + +============== +share servers +============== + +.. autoprogram-cliff:: openstack.share.v2 + :command: share server * diff --git a/manilaclient/osc/v2/share_servers.py b/manilaclient/osc/v2/share_servers.py new file mode 100644 index 000000000..f5f837f02 --- /dev/null +++ b/manilaclient/osc/v2/share_servers.py @@ -0,0 +1,411 @@ +# 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. + +import logging + +from openstackclient.identity import common as identity_common +from osc_lib.cli import parseractions +from osc_lib.command import command +from osc_lib import exceptions +from osc_lib import utils as osc_utils + +from manilaclient import api_versions +from manilaclient.common._i18n import _ +from manilaclient.common import constants + +LOG = logging.getLogger(__name__) + + +class DeleteShareServer(command.Command): + """Delete one or more share servers (Admin only)""" + _description = _( + "Delete one or more share servers") + + def get_parser(self, prog_name): + parser = super(DeleteShareServer, self).get_parser(prog_name) + parser.add_argument( + "share_servers", + metavar="", + nargs="+", + help=_("ID(s) of the server(s) to delete") + ) + parser.add_argument( + "--wait", + action='store_true', + default=False, + help=_("Wait for share server deletion.") + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + result = 0 + + for server in parsed_args.share_servers: + try: + server_obj = osc_utils.find_resource( + share_client.share_servers, server) + + share_client.share_servers.delete(server_obj) + if parsed_args.wait: + if not osc_utils.wait_for_delete( + manager=share_client.share_servers, + res_id=server_obj.id): + result += 1 + + except Exception as e: + result += 1 + LOG.error(_( + "Failed to delete a share server with " + "ID '%(server)s': %(e)s"), + {'server': server, 'e': e}) + + if result > 0: + total = len(parsed_args.share_servers) + msg = f'Failed to delete {result} servers out of {total}.' + raise exceptions.CommandError(_(msg)) + + +class ShowShareServer(command.ShowOne): + """Show share server (Admin only).""" + _description = _("Show details about a share server (Admin only).") + + def get_parser(self, prog_name): + parser = super(ShowShareServer, self).get_parser(prog_name) + parser.add_argument( + "share_server", + metavar="", + help=_("ID of share server.") + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + + share_server = osc_utils.find_resource( + share_client.share_servers, + parsed_args.share_server) + + # All 'backend_details' data already present as separated strings, + # so remove big dict from view. + if "backend_details" in share_server._info: + del share_server._info["backend_details"] + + share_server._info.pop('links', None) + return self.dict2columns(share_server._info) + + +class ListShareServer(command.Lister): + """List all share servers (Admin only).""" + _description = _("List all share servers (Admin only).") + + def get_parser(self, prog_name): + parser = super(ListShareServer, self).get_parser(prog_name) + parser.add_argument( + '--host', + metavar='', + default=None, + help=_('Filter results by name of host.'), + ) + parser.add_argument( + '--status', + metavar="", + default=None, + help=_('Filter results by status.') + ) + parser.add_argument( + '--share-network', + metavar='', + default=None, + help=_('Filter results by share network name or ID.'), + ) + parser.add_argument( + '--project', + metavar='', + default=None, + help=_('Filter results by project name or ID.') + ) + parser.add_argument( + '--share-network-subnet', + metavar='', + type=str, + default=None, + help=_("Filter results by share network subnet that the " + "share server's network allocation exists within. " + "Available for microversion >= 2.51 (Optional, " + "Default=None)") + ) + identity_common.add_project_domain_option_to_parser(parser) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + identity_client = self.app.client_manager.identity + + project_id = None + if parsed_args.project: + project_id = identity_common.find_project( + identity_client, + parsed_args.project, + parsed_args.project_domain).id + + if (parsed_args.share_network_subnet and + share_client.api_version < api_versions.APIVersion("2.51")): + raise exceptions.CommandError( + "Share network subnet can be specified only with manila API " + "version >= 2.51" + ) + + columns = [ + 'ID', + 'Host', + 'Status', + 'Share Network ID', + 'Project ID', + ] + + search_opts = { + 'status': parsed_args.status, + 'host': parsed_args.host, + 'project_id': project_id, + } + + if parsed_args.share_network: + share_network_id = osc_utils.find_resource( + share_client.share_networks, + parsed_args.share_network).id + search_opts['share_network'] = share_network_id + + if parsed_args.share_network_subnet: + search_opts['share_network_subnet_id'] = ( + parsed_args.share_network_subnet) + + share_servers = share_client.share_servers.list( + search_opts=search_opts) + + data = (osc_utils.get_dict_properties( + share_server._info, columns) for share_server in share_servers) + + return (columns, data) + + +class AdoptShareServer(command.ShowOne): + """Adopt share server not handled by Manila (Admin only).""" + + _description = _("Adopt share server not handled by Manila (Admin only).") + + def get_parser(self, prog_name): + parser = super(AdoptShareServer, self).get_parser(prog_name) + parser.add_argument( + 'host', + metavar='', + type=str, + help=_('Backend name as "@".') + ) + parser.add_argument( + "share_network", + metavar="", + help=_("Share network where share server has network " + "allocations in.") + ) + parser.add_argument( + 'identifier', + metavar='', + type=str, + help=_("A driver-specific share server identifier required " + "by the driver to manage the share server.") + ) + parser.add_argument( + '--driver-options', + metavar='', + action=parseractions.KeyValueAction, + default={}, + help=_("One or more driver-specific key=value pairs that may be " + "necessary to manage the share server (Optional, " + "Default=None).") + ) + parser.add_argument( + '--share-network-subnet', + type=str, + metavar='', + default=None, + help="Share network subnet where share server has network " + "allocations in.The default subnet will be used if " + "it's not specified. Available for microversion " + ">= 2.51 (Optional, Default=None)." + ) + parser.add_argument( + "--wait", + action='store_true', + help=_("Wait until share server is adopted") + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + + share_network = None + if parsed_args.share_network: + share_network = osc_utils.find_resource( + share_client.share_networks, + parsed_args.share_network).id + + share_network_subnet = None + if (parsed_args.share_network_subnet and + share_client.api_version < api_versions.APIVersion("2.51")): + raise exceptions.CommandError( + "Share network subnet can be specified only with manila API " + "version >= 2.51" + ) + elif parsed_args.share_network_subnet: + share_network_subnet = share_client.share_network_subnets.get( + share_network, parsed_args.share_network_subnet).id + + share_server = share_client.share_servers.manage( + host=parsed_args.host, + share_network_id=share_network, + identifier=parsed_args.identifier, + driver_options=parsed_args.driver_options, + share_network_subnet_id=share_network_subnet + ) + + if parsed_args.wait: + if not osc_utils.wait_for_status( + status_f=share_client.share_servers.get, + res_id=share_server.id, + success_status=['active'], + error_status=['manage_error', 'error'] + ): + LOG.error(_("ERROR: Share server is in error state.")) + + share_server = osc_utils.find_resource(share_client.share_servers, + share_server.id) + + share_server._info.pop('links', None) + + # All 'backend_details' data already present as separated strings, + # so remove big dict from view. + share_server._info.pop("backend_details", None) + + return self.dict2columns(share_server._info) + + +class AbandonShareServer(command.Command): + """Remove one or more share servers (Admin only).""" + + _description = _("Remove one or more share server(s) (Admin only).") + + def get_parser(self, prog_name): + parser = super(AbandonShareServer, self).get_parser(prog_name) + parser.add_argument( + "share_server", + metavar="", + nargs='+', + help=_("ID of the server(s) to be abandoned.") + ) + parser.add_argument( + "--force", + action='store_true', + default=False, + help=_("Enforces the unmanage share server operation, even " + "if the backend driver does not support it.") + ) + parser.add_argument( + "--wait", + action='store_true', + default=False, + help=_("Wait until share server is abandoned") + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + result = 0 + + for server in parsed_args.share_server: + try: + server_obj = osc_utils.find_resource( + share_client.share_servers, + server) + kwargs = {} + if parsed_args.force: + kwargs['force'] = parsed_args.force + share_client.share_servers.unmanage( + server_obj, **kwargs) + + if parsed_args.wait: + if not osc_utils.wait_for_delete( + manager=share_client.share_servers, + res_id=server_obj.id): + result += 1 + + except Exception as e: + result += 1 + LOG.error(_( + "Failed to abandon share server with " + "ID '%(server)s': %(e)s"), + {'server': server, 'e': e}) + + if result > 0: + total = len(parsed_args.share_server) + msg = f'Failed to abandon {result} of {total} servers.' + raise exceptions.CommandError(_(msg)) + + +class SetShareServer(command.Command): + """Set share server properties.""" + + _description = _("Set share server properties (Admin only).") + + def get_parser(self, prog_name): + parser = super(SetShareServer, self).get_parser(prog_name) + allowed_update_choices = [ + 'unmanage_starting', 'server_migrating_to', 'error', + 'unmanage_error', 'manage_error', 'inactive', 'active', + 'server_migrating', 'manage_starting', 'deleting', + 'network_change'] + allowed_update_choices_str = ', '.join(allowed_update_choices) + parser.add_argument( + "share_server", + metavar="", + help=_("ID of the share server to modify.") + ) + parser.add_argument( + "--status", + metavar="", + required=True, + default=constants.STATUS_ACTIVE, + help=_("Assign a status to the share server. Options " + "include: %s. If no state is " + "provided, active will be " + "used." % allowed_update_choices_str) + ) + return parser + + def take_action(self, parsed_args): + share_client = self.app.client_manager.share + + share_server = osc_utils.find_resource( + share_client.share_servers, + parsed_args.share_server) + + try: + share_client.share_servers.reset_state( + share_server, + parsed_args.status + ) + except Exception as e: + msg = (_( + "Failed to set status '%(status)s': %(exception)s"), + {'status': parsed_args.status, 'exception': e}) + LOG.error(msg) + raise exceptions.CommandError(msg) diff --git a/manilaclient/tests/unit/osc/v2/fakes.py b/manilaclient/tests/unit/osc/v2/fakes.py index 67e9cfcc1..1b1e958f0 100644 --- a/manilaclient/tests/unit/osc/v2/fakes.py +++ b/manilaclient/tests/unit/osc/v2/fakes.py @@ -59,6 +59,7 @@ class FakeShareClient(object): self.limits = mock.Mock() self.share_group_types = mock.Mock() self.share_group_type_access = mock.Mock() + self.share_servers = mock.Mock() class ManilaParseException(Exception): @@ -1343,3 +1344,59 @@ class FakeShareGroupSnapshot(object): share_group_snapshots.append( FakeShareGroupSnapshot.create_one_share_group_snapshot(attrs)) return share_group_snapshots + + +class FakeShareServer(object): + """Fake a share server""" + + @staticmethod + def create_one_server(attrs=None, methods=None): + """Create a fake share server + + :param Dictionary attrs: + A dictionary with all attributes + :return: + A FakeResource object, with project_id, resource and so on + """ + + attrs = attrs or {} + methods = methods or {} + + share_server = { + 'id': str(uuid.uuid4()), + 'project_id': uuid.uuid4().hex, + "updated_at": datetime.datetime.now().isoformat(), + 'status': None, + 'host': None, + 'share_network_name': None, + 'share_network_id': str(uuid.uuid4()), + 'share_network_subnet_id': str(uuid.uuid4()), + 'created_at': datetime.datetime.now().isoformat(), + 'is_auto_deletable': False, + 'identifier': str(uuid.uuid4()) + } + + share_server.update(attrs) + share_server = osc_fakes.FakeResource(info=copy.deepcopy( + share_server), + methods=methods, + loaded=True) + return share_server + + @staticmethod + def create_share_servers(attrs=None, count=2): + """Create multiple fake servers. + + :param dict attrs: + A dictionary with all attributes + :param int count: + The number of share server to be faked + :return: + A list of FakeResource objects + """ + attrs = attrs or {} + share_servers = [] + for n in range(count): + share_servers.append( + FakeShareServer.create_one_server(attrs)) + return share_servers diff --git a/manilaclient/tests/unit/osc/v2/test_share_servers.py b/manilaclient/tests/unit/osc/v2/test_share_servers.py new file mode 100644 index 000000000..e1b2942ca --- /dev/null +++ b/manilaclient/tests/unit/osc/v2/test_share_servers.py @@ -0,0 +1,511 @@ +# 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 unittest import mock + +from osc_lib import exceptions +from osc_lib import utils as oscutils + +from manilaclient import api_versions +from manilaclient.osc.v2 import share_servers as osc_share_servers +from manilaclient.tests.unit.osc import osc_utils +from manilaclient.tests.unit.osc.v2 import fakes as manila_fakes + + +class TestShareServer(manila_fakes.TestShare): + + def setUp(self): + super(TestShareServer, self).setUp() + + self.servers_mock = self.app.client_manager.share.share_servers + self.servers_mock.reset_mock() + + self.share_networks_mock = self.app.client_manager.share.share_networks + self.share_networks_mock.reset_mock() + + self.app.client_manager.share.api_version = api_versions.APIVersion( + api_versions.MAX_VERSION) + + +class TestDeleteShareServer(TestShareServer): + + def setUp(self): + super(TestDeleteShareServer, self).setUp() + + self.share_server = ( + manila_fakes.FakeShareServer.create_one_server()) + self.servers_mock.get.return_value = self.share_server + + self.cmd = osc_share_servers.DeleteShareServer(self.app, None) + + def test_share_server_delete_missing_args(self): + arglist = [] + verifylist = [] + + self.assertRaises(osc_utils.ParserException, + self.check_parser, self.cmd, arglist, verifylist) + + def test_share_server_delete(self): + arglist = [ + self.share_server.id + ] + verifylist = [ + ('share_servers', [self.share_server.id]) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.servers_mock.delete.assert_called_once_with( + self.share_server) + self.assertIsNone(result) + + def test_share_server_delete_wait(self): + arglist = [ + self.share_server.id, + '--wait' + ] + verifylist = [ + ('share_servers', [self.share_server.id]), + ('wait', True) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + with mock.patch('osc_lib.utils.wait_for_delete', return_value=True): + result = self.cmd.take_action(parsed_args) + + self.servers_mock.delete.assert_called_once_with( + self.share_server) + self.assertIsNone(result) + + def test_share_server_delete_wait_exception(self): + arglist = [ + self.share_server.id, + '--wait' + ] + verifylist = [ + ('share_servers', [self.share_server.id]), + ('wait', True) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): + self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, + parsed_args + ) + + +class TestShowShareServer(TestShareServer): + + def setUp(self): + super(TestShowShareServer, self).setUp() + + self.share_server = ( + manila_fakes.FakeShareServer.create_one_server()) + self.servers_mock.get.return_value = self.share_server + + self.cmd = osc_share_servers.ShowShareServer(self.app, None) + + self.data = tuple(self.share_server._info.values()) + self.columns = tuple(self.share_server._info.keys()) + + def test_share_server_show_missing_args(self): + arglist = [] + verifylist = [] + + self.assertRaises( + osc_utils.ParserException, + self.check_parser, self.cmd, arglist, verifylist) + + def test_share_server_show(self): + arglist = [ + self.share_server.id + ] + verifylist = [ + ('share_server', self.share_server.id) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.servers_mock.get.assert_called_with( + self.share_server.id + ) + + self.assertCountEqual(self.columns, columns) + self.assertCountEqual(self.data, data) + + +class TestListShareServer(TestShareServer): + + columns = [ + 'ID', + 'Host', + 'Status', + 'Share Network ID', + 'Project ID', + ] + + def setUp(self): + super(TestListShareServer, self).setUp() + + self.servers_list = ( + manila_fakes.FakeShareServer.create_share_servers( + count=2)) + self.servers_mock.list.return_value = self.servers_list + + self.values = (oscutils.get_dict_properties( + i._info, self.columns) for i in self.servers_list) + + self.cmd = osc_share_servers.ListShareServer(self.app, None) + + def test_list_share_server(self): + arglist = [] + verifylist = [] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.servers_mock.list.assert_called_with(search_opts={ + 'status': None, + 'host': None, + 'project_id': None, + }) + + self.assertEqual(self.columns, columns) + self.assertEqual(list(self.values), list(data)) + + def test_share_server_list_by_status(self): + arglist = [ + '--status', self.servers_list[0].status, + ] + verifylist = [ + ('status', self.servers_list[0].status), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + search_opts = { + 'status': None, + 'host': None, + 'project_id': None, + } + + self.servers_mock.list.assert_called_once_with( + search_opts=search_opts, + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(list(self.values), list(data)) + + +class TestAdoptShareServer(TestShareServer): + + def setUp(self): + super(TestAdoptShareServer, self).setUp() + + self.share_server = ( + manila_fakes.FakeShareServer.create_one_server( + attrs={'status': 'available'} + )) + self.servers_mock.get.return_value = self.share_server + self.servers_mock.manage.return_value = self.share_server + self.share_network_subnets_mock = ( + self.app.client_manager.share.share_network_subnets) + + self.share_network = ( + manila_fakes.FakeShareNetwork.create_one_share_network( + attrs={'status': 'available'} + )) + self.share_network_subnet = ( + manila_fakes.FakeShareNetworkSubnet.create_one_share_subnet()) + + self.share_networks_mock.get.return_value = self.share_network + self.share_network_subnets_mock.get.return_value = ( + self.share_network_subnet) + + self.cmd = osc_share_servers.AdoptShareServer(self.app, None) + + self.data = tuple(self.share_server._info.values()) + self.columns = tuple(self.share_server._info.keys()) + + def test_share_server_adopt_missing_args(self): + arglist = [] + verifylist = [] + + self.assertRaises(osc_utils.ParserException, + self.check_parser, self.cmd, arglist, verifylist) + + def test_share_server_adopt(self): + arglist = [ + 'somehost@backend', + self.share_network['id'], + 'share_server_identifier', + '--share-network-subnet', self.share_network_subnet['id'], + ] + verifylist = [ + ('host', 'somehost@backend'), + ('share_network', self.share_network['id']), + ('identifier', 'share_server_identifier'), + ('share_network_subnet', self.share_network_subnet['id']), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + self.servers_mock.manage.assert_called_with( + host='somehost@backend', + share_network_id=self.share_network['id'], + identifier='share_server_identifier', + driver_options={}, + share_network_subnet_id=self.share_network_subnet['id'], + ) + self.assertCountEqual(self.columns, columns) + self.assertCountEqual(self.data, data) + + def test_share_server_adopt_wait(self): + arglist = [ + 'somehost@backend', + self.share_network['id'], + 'share_server_identifier', + '--share-network-subnet', self.share_network_subnet['id'], + '--wait' + ] + verifylist = [ + ('host', 'somehost@backend'), + ('share_network', self.share_network['id']), + ('identifier', 'share_server_identifier'), + ('share_network_subnet', self.share_network_subnet['id']), + ('wait', True) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + with mock.patch('osc_lib.utils.wait_for_status', return_value=True): + self.cmd.take_action(parsed_args) + self.servers_mock.manage.assert_called_with( + host='somehost@backend', + share_network_id=self.share_network['id'], + identifier='share_server_identifier', + driver_options={}, + share_network_subnet_id=self.share_network_subnet['id'] + ) + + def test_share_server_adopt_subnet_not_supported(self): + arglist = [ + 'somehost@backend', + self.share_network['id'], + 'share_server_identifier', + '--share-network-subnet', self.share_network_subnet['id'], + '--wait' + ] + verifylist = [ + ('host', 'somehost@backend'), + ('share_network', self.share_network['id']), + ('identifier', 'share_server_identifier'), + ('share_network_subnet', self.share_network_subnet['id']), + ('wait', True) + ] + self.app.client_manager.share.api_version = api_versions.APIVersion( + "2.50") + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises(exceptions.CommandError, + self.cmd.take_action, + parsed_args) + + +class TestAbandonShareServer(TestShareServer): + + def setUp(self): + super(TestAbandonShareServer, self).setUp() + + self.share_server = ( + manila_fakes.FakeShareServer.create_one_server()) + self.servers_mock.get.return_value = self.share_server + + self.cmd = osc_share_servers.AbandonShareServer(self.app, None) + + self.data = tuple(self.share_server._info.values()) + self.columns = tuple(self.share_server._info.keys()) + + def test_share_server_abandon_missing_args(self): + arglist = [] + verifylist = [] + + self.assertRaises(osc_utils.ParserException, + self.check_parser, self.cmd, arglist, verifylist) + + def test_share_server_abandon(self): + arglist = [ + self.share_server.id + ] + verifylist = [ + ('share_server', [self.share_server.id]) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.servers_mock.unmanage.assert_called_with( + self.share_server) + self.assertIsNone(result) + + def test_share_server_abandon_multiple(self): + share_servers = ( + manila_fakes.FakeShareServer.create_share_servers( + count=2)) + arglist = [ + share_servers[0].id, + share_servers[1].id + ] + verifylist = [ + ('share_server', [share_servers[0].id, share_servers[1].id]) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.assertEqual(self.servers_mock.unmanage.call_count, + len(share_servers)) + self.assertIsNone(result) + + def test_share_server_abandon_force(self): + arglist = [ + self.share_server.id, + '--force' + ] + verifylist = [ + ('share_server', [self.share_server.id]), + ('force', True) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.servers_mock.unmanage.assert_called_with( + self.share_server, + force=True) + self.assertIsNone(result) + + def test_share_server_abandon_force_exception(self): + arglist = [ + self.share_server.id, + ] + verifylist = [ + ('share_server', [self.share_server.id]), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.servers_mock.unmanage.side_effect = exceptions.CommandError() + self.assertRaises(exceptions.CommandError, + self.cmd.take_action, + parsed_args) + + def test_share_server_abandon_wait(self): + arglist = [ + self.share_server.id, + '--wait' + ] + verifylist = [ + ('share_server', [self.share_server.id]), + ('wait', True) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + with mock.patch('osc_lib.utils.wait_for_delete', return_value=True): + result = self.cmd.take_action(parsed_args) + self.servers_mock.unmanage.assert_called_with( + self.share_server) + self.assertIsNone(result) + + def test_share_server_abandon_wait_error(self): + arglist = [ + self.share_server.id, + '--wait' + ] + verifylist = [ + ('share_server', [self.share_server.id]), + ('wait', True) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + with mock.patch('osc_lib.utils.wait_for_delete', return_value=False): + self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, + parsed_args) + + +class TestSetShareServer(TestShareServer): + + def setUp(self): + super(TestSetShareServer, self).setUp() + + self.share_server = ( + manila_fakes.FakeShareServer.create_one_server()) + self.servers_mock.get.return_value = self.share_server + + self.cmd = osc_share_servers.SetShareServer(self.app, None) + + def test_share_server_set_status(self): + arglist = [ + self.share_server.id, + '--status', 'active' + ] + verifylist = [ + ('share_server', self.share_server.id), + ('status', 'active') + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.servers_mock.reset_state.assert_called_with( + self.share_server, + parsed_args.status) + self.assertIsNone(result) + + def test_share_server_set_status_exception(self): + arglist = [ + self.share_server.id, + '--status', 'active' + ] + verifylist = [ + ('share_server', self.share_server.id), + ('status', 'active') + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.servers_mock.reset_state.side_effect = Exception() + + self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, + parsed_args) diff --git a/setup.cfg b/setup.cfg index eef4acac4..43fee1972 100644 --- a/setup.cfg +++ b/setup.cfg @@ -141,6 +141,12 @@ openstack.share.v2 = share_group_snapshot_set = manilaclient.osc.v2.share_group_snapshots:SetShareGroupSnapshot share_group_snapshot_unset = manilaclient.osc.v2.share_group_snapshots:UnsetShareGroupSnapshot share_group_snapshot_members_list = manilaclient.osc.v2.share_group_snapshots:ListShareGroupSnapshotMembers + share_server_delete = manilaclient.osc.v2.share_servers:DeleteShareServer + share_server_show = manilaclient.osc.v2.share_servers:ShowShareServer + share_server_list = manilaclient.osc.v2.share_servers:ListShareServer + share_server_adopt = manilaclient.osc.v2.share_servers:AdoptShareServer + share_server_abandon = manilaclient.osc.v2.share_servers:AbandonShareServer + share_server_set = manilaclient.osc.v2.share_servers:SetShareServer [coverage:run] omit = manilaclient/tests/*