diff --git a/neutronclient/osc/v2/trunk/network_trunk.py b/neutronclient/osc/v2/trunk/network_trunk.py index 0cee32e..a6aadbb 100644 --- a/neutronclient/osc/v2/trunk/network_trunk.py +++ b/neutronclient/osc/v2/trunk/network_trunk.py @@ -58,6 +58,8 @@ class CreateNetworkTrunk(command.ShowOne): '--subport', metavar='', action=parseractions.MultiKeyValueAction, dest='add_subports', + optional_keys=['segmentation-id', 'segmentation-type'], + required_keys=['port'], help=_("Subport to add. Subport is of form " "\'port=,segmentation-type=,segmentation-ID=\' " "(--subport) option can be repeated") @@ -193,6 +195,8 @@ class SetNetworkTrunk(command.Command): '--subport', metavar='', action=parseractions.MultiKeyValueAction, dest='set_subports', + optional_keys=['segmentation-id', 'segmentation-type'], + required_keys=['port'], help=_("Subport to add. Subport is of form " "\'port=,segmentation-type=,segmentation-ID=\'" "(--subport) option can be repeated") 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 31c446c..8408f7e 100644 --- a/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py +++ b/neutronclient/tests/unit/osc/v2/trunk/test_network_trunk.py @@ -13,6 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. +import argparse +import copy import mock from mock import call import testtools @@ -162,6 +164,56 @@ class TestCreateNetworkTrunk(test_fakes.TestNeutronClientOSCV2): self.assertEqual("Segmentation-id 'boom' is not an integer", str(e)) + def test_create_network_trunk_subports_without_optional_keys(self): + subport = copy.copy(self._trunk['sub_ports'][0]) + # Pop out the segmentation-id and segmentation-type + subport.pop('segmentation_type') + subport.pop('segmentation_id') + arglist = [ + '--parent-port', self._trunk['port_id'], + '--subport', 'port=%(port)s' % {'port': subport['port_id']}, + self._trunk['name'], + ] + verifylist = [ + ('name', self._trunk['name']), + ('parent_port', self._trunk['port_id']), + ('add_subports', [{ + 'port': subport['port_id']}]), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = (self.cmd.take_action(parsed_args)) + + self.neutronclient.create_trunk.assert_called_once_with({ + trunk.TRUNK: {'name': self._trunk['name'], + 'admin_state_up': True, + 'sub_ports': [subport], + 'port_id': self._trunk['port_id']} + }) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + def test_create_network_trunk_subports_without_required_key_fail(self): + subport = self._trunk['sub_ports'][0] + arglist = [ + '--parent-port', self._trunk['port_id'], + '--subport', 'segmentation-type=%(seg_type)s,' + 'segmentation-id=%(seg_id)s' % { + 'seg_id': subport['segmentation_id'], + 'seg_type': subport['segmentation_type']}, + self._trunk['name'], + ] + verifylist = [ + ('name', self._trunk['name']), + ('parent_port', self._trunk['port_id']), + ('add_subports', [{ + 'segmentation-id': str(subport['segmentation_id']), + 'segmentation-type': subport['segmentation_type']}]), + ] + + with testtools.ExpectedException(argparse.ArgumentTypeError): + self.check_parser(self.cmd, arglist, verifylist) + class TestDeleteNetworkTrunk(test_fakes.TestNeutronClientOSCV2): # The trunk to be deleted. @@ -511,6 +563,50 @@ class TestSetNetworkTrunk(test_fakes.TestNeutronClientOSCV2): ) self.assertIsNone(result) + def test_set_network_trunk_subports_without_optional_keys(self): + subport = copy.copy(self._trunk['sub_ports'][0]) + # Pop out the segmentation-id and segmentation-type + subport.pop('segmentation_type') + subport.pop('segmentation_id') + arglist = [ + '--subport', 'port=%(port)s' % {'port': subport['port_id']}, + self._trunk['name'], + ] + verifylist = [ + ('trunk', self._trunk['name']), + ('set_subports', [{ + 'port': subport['port_id']}]), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + self.neutronclient.trunk_add_subports.assert_called_once_with( + self._trunk['name'], {'sub_ports': [subport]} + ) + self.assertIsNone(result) + + def test_set_network_trunk_subports_without_required_key_fail(self): + subport = self._trunk['sub_ports'][0] + arglist = [ + '--subport', 'segmentation-type=%(seg_type)s,' + 'segmentation-id=%(seg_id)s' % { + 'seg_id': subport['segmentation_id'], + 'seg_type': subport['segmentation_type']}, + self._trunk['name'], + ] + verifylist = [ + ('trunk', self._trunk['name']), + ('set_subports', [{ + 'segmentation-id': str(subport['segmentation_id']), + 'segmentation-type': subport['segmentation_type']}]), + ] + + with testtools.ExpectedException(argparse.ArgumentTypeError): + self.check_parser(self.cmd, arglist, verifylist) + + self.neutronclient.trunk_add_subports.assert_not_called() + def test_set_trunk_attrs_with_exception(self): arglist = [ '--name', 'reallylongname',