diff --git a/neutronclient/osc/v2/trunk/network_trunk.py b/neutronclient/osc/v2/trunk/network_trunk.py index fa8fb3f7a..e3eed827a 100644 --- a/neutronclient/osc/v2/trunk/network_trunk.py +++ b/neutronclient/osc/v2/trunk/network_trunk.py @@ -26,8 +26,6 @@ from osc_lib import utils from openstackclient.identity import common as identity_common from neutronclient._i18n import _ -# TODO(abhiraut): Switch to client methods -from neutronclient.neutron import v2_0 as neutronV20 LOG = logging.getLogger(__name__) @@ -58,7 +56,7 @@ class CreateNetworkTrunk(command.ShowOne): action=parseractions.MultiKeyValueAction, dest='add_subports', help=_("Subport to add. Subport is of form " "\'port=,segmentation-type=,segmentation-ID=\' " - "(--subport) option can be repeated)") + "(--subport) option can be repeated") ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( @@ -127,12 +125,38 @@ class DeleteNetworkTrunk(command.Command): class ListNetworkTrunk(command.Lister): """List all network trunks""" + def get_parser(self, prog_name): + parser = super(ListNetworkTrunk, self).get_parser(prog_name) + parser.add_argument( + '--long', + action='store_true', + default=False, + help=_("List additional fields in output") + ) + return parser + def take_action(self, parsed_args): client = self.app.client_manager.neutronclient data = client.list_trunks() - # TODO(abhiraut): List more columns using --long - headers = ('ID', 'Name', 'Parent Port') - columns = ('id', 'name', 'port_id') + headers = ( + 'ID', + 'Name', + 'Parent Port' + ) + columns = ( + 'id', + 'name', + 'port_id' + ) + if parsed_args.long: + headers += ( + 'Status', + 'State', + ) + columns += ( + 'status', + 'admin_state_up', + ) return (headers, (utils.get_dict_properties( s, columns, @@ -161,7 +185,7 @@ class SetNetworkTrunk(command.Command): action=parseractions.MultiKeyValueAction, dest='set_subports', help=_("Subport to add. Subport is of form " "\'port=,segmentation-type=,segmentation-ID=\'" - "(--subport) option can be repeated)") + "(--subport) option can be repeated") ) admin_group = parser.add_mutually_exclusive_group() admin_group.add_argument( @@ -181,11 +205,21 @@ class SetNetworkTrunk(command.Command): trunk_id = _get_id(client, parsed_args.trunk, TRUNK) attrs = _get_attrs_for_trunk(self.app.client_manager, parsed_args) body = {TRUNK: attrs} - client.update_trunk(trunk_id, body) + try: + client.update_trunk(trunk_id, body) + except Exception as e: + msg = (_("Failed to set trunk '%(t)s': %(e)s") + % {'t': parsed_args.trunk, 'e': e}) + raise exceptions.CommandError(msg) if parsed_args.set_subports: subport_attrs = _get_attrs_for_subports(self.app.client_manager, parsed_args) - client.trunk_add_subports(trunk_id, subport_attrs) + try: + client.trunk_add_subports(trunk_id, subport_attrs) + except Exception as e: + msg = (_("Failed to add subports to trunk '%(t)s': %(e)s") + % {'t': parsed_args.trunk, 'e': e}) + raise exceptions.CommandError(msg) class ShowNetworkTrunk(command.ShowOne): @@ -343,5 +377,4 @@ def _get_attrs_for_subports(client_manager, parsed_args): def _get_id(client, id_or_name, resource): - return neutronV20.find_resourceid_by_name_or_id( - client, resource, str(id_or_name)) + return client.find_resource(resource, str(id_or_name))['id'] diff --git a/neutronclient/tests/unit/osc/v2/fakes.py b/neutronclient/tests/unit/osc/v2/fakes.py index 45f2b253b..75277a952 100644 --- a/neutronclient/tests/unit/osc/v2/fakes.py +++ b/neutronclient/tests/unit/osc/v2/fakes.py @@ -14,7 +14,7 @@ import argparse import mock -from openstackclient.tests import utils +from osc_lib.tests import utils class TestNeutronClientOSCV2(utils.TestCommand): diff --git a/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py b/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py index ff9baa073..5bb5ea214 100644 --- a/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py +++ b/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py @@ -15,13 +15,12 @@ import mock from mock import call +import testtools from osc_lib import exceptions +from osc_lib.tests import utils as tests_utils from osc_lib import utils -# TODO(abhiraut): Switch to osc-lib test utils -from openstackclient.tests import utils as tests_utils - from neutronclient.osc.v2.trunk import network_trunk as trunk from neutronclient.tests.unit.osc.v2 import fakes as test_fakes from neutronclient.tests.unit.osc.v2.trunk import fakes @@ -147,10 +146,8 @@ class TestCreateNetworkTrunk(test_fakes.TestNeutronClientOSCV2): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - try: + with testtools.ExpectedException(exceptions.CommandError) as e: self.cmd.take_action(parsed_args) - self.fail('CommandError should be raised.') - except exceptions.CommandError as e: self.assertEqual("Segmentation-id 'boom' is not an integer", str(e)) @@ -217,10 +214,8 @@ class TestDeleteNetworkTrunk(test_fakes.TestNeutronClientOSCV2): trunk._get_id = ( mock.MagicMock(side_effect=get_mock_result) ) - try: + with testtools.ExpectedException(exceptions.CommandError) as e: self.cmd.take_action(parsed_args) - self.fail('CommandError should be raised.') - except exceptions.CommandError as e: self.assertEqual('1 of 2 trunks failed to delete.', str(e)) self.neutronclient.delete_trunk.assert_called_once_with( self._trunks[0] @@ -295,6 +290,10 @@ class TestListNetworkTrunk(test_fakes.TestNeutronClientOSCV2): 'Name', 'Parent Port', ) + columns_long = columns + ( + 'Status', + 'State', + ) data = [] for t in _trunks: data.append(( @@ -302,6 +301,15 @@ class TestListNetworkTrunk(test_fakes.TestNeutronClientOSCV2): t['name'], t['port_id'], )) + data_long = [] + for t in _trunks: + data_long.append(( + t['id'], + t['name'], + t['port_id'], + t['status'], + trunk._format_admin_state(t['admin_state_up']), + )) def setUp(self): super(TestListNetworkTrunk, self).setUp() @@ -324,6 +332,21 @@ class TestListNetworkTrunk(test_fakes.TestNeutronClientOSCV2): self.assertEqual(self.columns, columns) self.assertEqual(self.data, list(data)) + def test_trunk_list_long(self): + arglist = [ + '--long', + ] + verifylist = [ + ('long', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.neutronclient.list_trunks.assert_called_once_with() + self.assertEqual(self.columns_long, columns) + self.assertEqual(self.data_long, list(data)) + class TestSetNetworkTrunk(test_fakes.TestNeutronClientOSCV2): # Create trunks to be listed. @@ -435,7 +458,7 @@ class TestSetNetworkTrunk(test_fakes.TestNeutronClientOSCV2): def test_set_network_trunk_subports(self): subport = self._trunk['sub_ports'][0] arglist = [ - "--subport", 'port=%(port)s,segmentation-type=%(seg_type)s,' + '--subport', 'port=%(port)s,segmentation-type=%(seg_type)s,' 'segmentation-id=%(seg_id)s' % { 'seg_id': subport['segmentation_id'], 'seg_type': subport['segmentation_type'], @@ -458,6 +481,56 @@ class TestSetNetworkTrunk(test_fakes.TestNeutronClientOSCV2): ) self.assertIsNone(result) + def test_set_trunk_attrs_with_exception(self): + arglist = [ + '--name', 'reallylongname', + self._trunk['name'], + ] + verifylist = [ + ('trunk', self._trunk['name']), + ('name', 'reallylongname'), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.neutronclient.update_trunk = ( + mock.MagicMock(side_effect=exceptions.CommandError) + ) + with testtools.ExpectedException(exceptions.CommandError) as e: + self.cmd.take_action(parsed_args) + self.assertEqual( + "Failed to set trunk '%s': " % self._trunk['name'], + str(e)) + attrs = {'name': 'reallylongname'} + self.neutronclient.update_trunk.assert_called_once_with( + self._trunk['name'], {trunk.TRUNK: attrs}) + self.neutronclient.trunk_add_subports.assert_not_called() + + def test_set_trunk_add_subport_with_exception(self): + arglist = [ + '--subport', 'port=invalid_subport', + self._trunk['name'], + ] + verifylist = [ + ('trunk', self._trunk['name']), + ('set_subports', [{'port': 'invalid_subport'}]), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.neutronclient.trunk_add_subports = ( + mock.MagicMock(side_effect=exceptions.CommandError) + ) + with testtools.ExpectedException(exceptions.CommandError) as e: + self.cmd.take_action(parsed_args) + self.assertEqual( + "Failed to add subports to trunk '%s': " % self._trunk['name'], + str(e)) + self.neutronclient.update_trunk.assert_called_once_with( + self._trunk['name'], {trunk.TRUNK: {}}) + self.neutronclient.trunk_add_subports.assert_called_once_with( + self._trunk['name'], + {'sub_ports': [{'port_id': 'invalid_subport'}]} + ) + class TestListNetworkSubport(test_fakes.TestNeutronClientOSCV2):