diff --git a/novaclient/base.py b/novaclient/base.py index 40e100a9d..431ac7d6f 100644 --- a/novaclient/base.py +++ b/novaclient/base.py @@ -358,15 +358,19 @@ class Manager(HookableMixin): return self.resource_class(self, content, loaded=True, resp=resp) - def _create(self, url, body, response_key, return_raw=False, **kwargs): + def _create(self, url, body, response_key, return_raw=False, + obj_class=None, **kwargs): self.run_hooks('modify_body_for_create', body, **kwargs) resp, body = self.api.client.post(url, body=body) if return_raw: return self.convert_into_with_meta(body[response_key], resp) - with self.completion_cache('human_id', self.resource_class, mode="a"): - with self.completion_cache('uuid', self.resource_class, mode="a"): - return self.resource_class(self, body[response_key], resp=resp) + if obj_class is None: + obj_class = self.resource_class + + with self.completion_cache('human_id', obj_class, mode="a"): + with self.completion_cache('uuid', obj_class, mode="a"): + return obj_class(self, body[response_key], resp=resp) def _delete(self, url): resp, body = self.api.client.delete(url) diff --git a/novaclient/tests/functional/v2/test_servers.py b/novaclient/tests/functional/v2/test_servers.py index 8d5fd02c9..47fb9e061 100644 --- a/novaclient/tests/functional/v2/test_servers.py +++ b/novaclient/tests/functional/v2/test_servers.py @@ -326,3 +326,20 @@ class TestServersDetailsFlavorInfo(base.ClientTestBase): flavor_output = self.nova("flavor-show %s" % self.flavor.id) flavor_val = self._get_value_from_the_table(flavor_output, 'disk') self.assertEqual(flavor_val, server_flavor_val) + + +class TestInterfaceAttach(base.ClientTestBase): + + COMPUTE_API_VERSION = '2.latest' + + def test_interface_attach(self): + server = self._create_server() + output = self.nova("interface-attach --net-id %s %s" % + (self.network.id, server.id)) + + for key in ('ip_address', 'mac_addr', 'port_id', 'port_state'): + self._get_value_from_the_table(output, key) + + self.assertEqual( + self.network.id, + self._get_value_from_the_table(output, 'net_id')) diff --git a/novaclient/tests/unit/v2/test_servers.py b/novaclient/tests/unit/v2/test_servers.py index e153fd571..c9a3f8d10 100644 --- a/novaclient/tests/unit/v2/test_servers.py +++ b/novaclient/tests/unit/v2/test_servers.py @@ -941,6 +941,7 @@ class ServersTest(utils.FixturedTestCase): ret = s.interface_attach(None, None, None) self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST) self.assert_called('POST', '/servers/1234/os-interface') + self.assertIsInstance(ret, servers.NetworkInterface) def test_interface_detach(self): s = self.cs.servers.get(1234) @@ -1409,6 +1410,7 @@ class ServersV249Test(ServersV2_37Test): {'interfaceAttachment': {'port_id': '7f42712e-63fe-484c-a6df-30ae4867ff66', 'tag': 'test_tag'}}) + self.assertIsInstance(ret, servers.NetworkInterface) def test_add_fixed_ip(self): # novaclient.v2.servers.Server.add_fixed_ip() diff --git a/novaclient/v2/servers.py b/novaclient/v2/servers.py index fa296bf62..eed80694d 100644 --- a/novaclient/v2/servers.py +++ b/novaclient/v2/servers.py @@ -1944,7 +1944,8 @@ class ServerManager(base.BootingManagerWithFind): {'ip_address': fixed_ip}] return self._create('/servers/%s/os-interface' % base.getid(server), - body, 'interfaceAttachment') + body, 'interfaceAttachment', + obj_class=NetworkInterface) @api_versions.wraps("2.49") def interface_attach(self, server, port_id, net_id, fixed_ip, tag=None): @@ -1973,7 +1974,8 @@ class ServerManager(base.BootingManagerWithFind): body['interfaceAttachment']['tag'] = tag return self._create('/servers/%s/os-interface' % base.getid(server), - body, 'interfaceAttachment') + body, 'interfaceAttachment', + obj_class=NetworkInterface) def interface_detach(self, server, port_id): """ diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py index a86c0d8ed..eadd7b97d 100644 --- a/novaclient/v2/shell.py +++ b/novaclient/v2/shell.py @@ -4530,10 +4530,21 @@ def do_interface_attach(cs, args): if 'tag' in args and args.tag: update_kwargs['tag'] = args.tag - res = server.interface_attach(args.port_id, args.net_id, args.fixed_ip, - **update_kwargs) - if isinstance(res, dict): - utils.print_dict(res) + network_interface = server.interface_attach( + args.port_id, args.net_id, args.fixed_ip, **update_kwargs) + + _print_interface(network_interface) + + +def _print_interface(interface): + ni_dict = interface.to_dict() + + fixed_ips = ni_dict.pop('fixed_ips', None) + ni_dict['ip_address'] = (",".join( + [fip['ip_address'] for fip in fixed_ips]) + if fixed_ips is not None else None) + + utils.print_dict(ni_dict) @utils.arg('server', metavar='', help=_('Name or ID of server.')) @@ -4541,10 +4552,7 @@ def do_interface_attach(cs, args): def do_interface_detach(cs, args): """Detach a network interface from a server.""" server = _find_server(cs, args.server) - - res = server.interface_detach(args.port_id) - if isinstance(res, dict): - utils.print_dict(res) + server.interface_detach(args.port_id) @api_versions.wraps("2.17") diff --git a/releasenotes/notes/interface-attach-output-02d633d9b2a60da1.yaml b/releasenotes/notes/interface-attach-output-02d633d9b2a60da1.yaml new file mode 100644 index 000000000..af855a1ea --- /dev/null +++ b/releasenotes/notes/interface-attach-output-02d633d9b2a60da1.yaml @@ -0,0 +1,11 @@ +--- +upgrade: + - The ``nova interface-attach`` command shows output of its result + when it is successful. + - | + The following methods return a ``NetworkInterface`` object + instead of a ``Server`` object. + + * The ``interface_attach`` method in the ``novaclient.v2.Server`` class + * The ``interface_attach`` method in the ``novaclient.v2.ServerManager`` + class