From 5fdb861ad4835513c0cb78251cce85ac73f51dd4 Mon Sep 17 00:00:00 2001 From: Matt Riedemann <mriedem@us.ibm.com> Date: Wed, 10 Jun 2015 13:40:05 -0700 Subject: [PATCH] Show reserved status for a fixed_ip if available Commit 8886590f30daf736ae30a95b3e4a77cb586d4f02 adds the v2.4 microversion to nova so that we can get back the reserved value of a fixed IP. This change adds support to novaclient to display the reserved status from the fixed_ip resource if it's available in the response. Related blueprint show-reserved-status-in-os-fixed-ips-api Change-Id: Idf3df1728ba87006d1b0f82a1c01712202670e0a --- novaclient/tests/functional/base.py | 33 ++++++++++ novaclient/tests/functional/test_fixedips.py | 67 ++++++++++++++++++++ novaclient/v2/shell.py | 14 +++- 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 novaclient/tests/functional/test_fixedips.py diff --git a/novaclient/tests/functional/base.py b/novaclient/tests/functional/base.py index 8b0e17266..0f73aff17 100644 --- a/novaclient/tests/functional/base.py +++ b/novaclient/tests/functional/base.py @@ -243,3 +243,36 @@ class ClientTestBase(testtools.TestCase): if l_property.strip() == key: return l_value.strip() raise ValueError("Property '%s' is missing from the table." % key) + + def _get_column_value_from_single_row_table(self, table, column): + """Get the value for the column in the single-row table + + Example table: + + +----------+-------------+----------+----------+ + | address | cidr | hostname | host | + +----------+-------------+----------+----------+ + | 10.0.0.3 | 10.0.0.0/24 | test | myhost | + +----------+-------------+----------+----------+ + + :param table: newline-separated table with |-separated cells + :param column: name of the column to look for + :raises: ValueError if the column value is not found + """ + lines = table.split("\n") + # Determine the column header index first. + column_index = -1 + for line in lines: + if "|" in line: + if column_index == -1: + headers = line.split("|")[1:-1] + for index, header in enumerate(headers): + if header.strip() == column: + column_index = index + break + else: + # We expect a single-row table so we should be able to get + # the value now using the column index. + return line.split("|")[1:-1][column_index].strip() + + raise ValueError("Unable to find value for column '%s'.") diff --git a/novaclient/tests/functional/test_fixedips.py b/novaclient/tests/functional/test_fixedips.py new file mode 100644 index 000000000..f6983070f --- /dev/null +++ b/novaclient/tests/functional/test_fixedips.py @@ -0,0 +1,67 @@ +# Copyright 2015 IBM Corp. +# 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 oslo_utils import strutils + +from novaclient.tests.functional import base +from novaclient.v2 import shell + + +class TestFixedIPsNovaClient(base.ClientTestBase): + """FixedIPs functional tests.""" + + API_VERSION = '2.1' + + def nova(self, *args, **kwargs): + flags = '--os-compute-api-version %s ' % self.API_VERSION + return self.cli_clients.nova(flags=flags, *args, **kwargs) + + def _create_server(self): + name = self.name_generate(prefix='server') + server = self.client.servers.create(name, self.image, self.flavor) + shell._poll_for_status( + self.client.servers.get, server.id, + 'building', ['active']) + self.addCleanup(server.delete) + return server + + def _test_fixedip_get(self, expect_reserved=False): + server = self._create_server() + networks = server.networks + self.assertIn('private', networks) + fixed_ip = networks['private'][0] + table = self.nova('fixed-ip-get %s' % fixed_ip) + addr = self._get_column_value_from_single_row_table(table, 'address') + self.assertEqual(fixed_ip, addr) + if expect_reserved: + reserved = self._get_column_value_from_single_row_table(table, + 'reserved') + # By default the fixed IP should not be reserved. + self.assertEqual(False, strutils.bool_from_string(reserved, + strict=True)) + else: + self.assertRaises(ValueError, + self._get_column_value_from_single_row_table, + table, 'reserved') + + def test_fixedip_get(self): + self._test_fixedip_get() + + +class TestFixedIPsNovaClientV24(TestFixedIPsNovaClient): + """FixedIPs functional tests for v2.4 nova-api microversion.""" + + API_VERSION = '2.4' + + def test_fixedip_get(self): + self._test_fixedip_get(expect_reserved=True) diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py index 6a2d3dad5..dcd27843e 100644 --- a/novaclient/v2/shell.py +++ b/novaclient/v2/shell.py @@ -3621,11 +3621,23 @@ def do_service_delete(cs, args): cs.services.delete(args.id) +@api_versions.wraps("2.0", "2.3") +def _print_fixed_ip(cs, fixed_ip): + fields = ['address', 'cidr', 'hostname', 'host'] + utils.print_list([fixed_ip], fields) + + +@api_versions.wraps("2.4") +def _print_fixed_ip(cs, fixed_ip): + fields = ['address', 'cidr', 'hostname', 'host', 'reserved'] + utils.print_list([fixed_ip], fields) + + @cliutils.arg('fixed_ip', metavar='<fixed_ip>', help=_('Fixed IP Address.')) def do_fixed_ip_get(cs, args): """Retrieve info on a fixed IP.""" result = cs.fixed_ips.get(args.fixed_ip) - utils.print_list([result], ['address', 'cidr', 'hostname', 'host']) + _print_fixed_ip(cs, result) @cliutils.arg('fixed_ip', metavar='<fixed_ip>', help=_('Fixed IP Address.'))