summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSurya Seetharaman <suryaseetharaman.9@gmail.com>2018-07-02 15:46:13 +0200
committerMatt Riedemann <mriedem.os@gmail.com>2019-02-20 11:58:39 -0500
commit14a45183ee9558281fd38a60471adf5db55637c8 (patch)
tree287c1424f1ae8b4b8d2147d9a652df344730881c
parent874b03068f1682cb0fe94d59f64e858b1514308d (diff)
downloadpython-novaclient-14a45183ee9558281fd38a60471adf5db55637c8.tar.gz
API microversion 2.69: Handles Down Cells
This patch explicitly points out the change needed while forming the detailed lists for embedded flavor information. In those cases where the server response for nova list has the flavor key missing for the instances in the down cell, the servers will be skipped. Depends-On: https://review.openstack.org/591657/ Related to blueprint handling-down-cell Change-Id: I007d9a68309b0d3aa85a4edf5026043154d4f42a
-rw-r--r--doc/source/cli/nova.rst12
-rw-r--r--novaclient/__init__.py2
-rw-r--r--novaclient/tests/unit/v2/fakes.py116
-rw-r--r--novaclient/tests/unit/v2/test_shell.py88
-rw-r--r--novaclient/v2/shell.py13
-rw-r--r--releasenotes/notes/bp-handling-down-cell-728cdb1efd1ea75b.yaml9
6 files changed, 216 insertions, 24 deletions
diff --git a/doc/source/cli/nova.rst b/doc/source/cli/nova.rst
index f3bc8eab..64bdf2da 100644
--- a/doc/source/cli/nova.rst
+++ b/doc/source/cli/nova.rst
@@ -2195,6 +2195,10 @@ nova list
List servers.
+Note that from microversion 2.69, during partial infrastructure failures in the
+deployment, the output of this command may return partial results for the servers
+present in the failure domain.
+
**Optional arguments:**
``--reservation-id <reservation-id>``
@@ -3363,6 +3367,10 @@ nova service-list
Show a list of all running services. Filter by host & binary.
+Note that from microversion 2.69, during partial infrastructure failures in the
+deployment, the output of this command may return partial results for the
+services present in the failure domain.
+
**Optional arguments:**
``--host <hostname>``
@@ -3430,6 +3438,10 @@ nova show
Show details about the given server.
+Note that from microversion 2.69, during partial infrastructure failures in the
+deployment, the output of this command may return partial results for the server
+if it exists in the failure domain.
+
**Positional arguments:**
``<server>``
diff --git a/novaclient/__init__.py b/novaclient/__init__.py
index a4eef58c..a41a77af 100644
--- a/novaclient/__init__.py
+++ b/novaclient/__init__.py
@@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
# when client supported the max version, and bumped sequentially, otherwise
# the client may break due to server side new version may include some
# backward incompatible change.
-API_MAX_VERSION = api_versions.APIVersion("2.68")
+API_MAX_VERSION = api_versions.APIVersion("2.69")
diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py
index c6f34c34..0b72a677 100644
--- a/novaclient/tests/unit/v2/fakes.py
+++ b/novaclient/tests/unit/v2/fakes.py
@@ -392,14 +392,32 @@ class FakeSessionClient(base_client.SessionClient):
#
def get_servers(self, **kw):
- return (200, {}, {"servers": [
+ servers = {"servers": [
{'id': '1234', 'name': 'sample-server'},
{'id': '5678', 'name': 'sample-server2'},
{'id': '9014', 'name': 'help'}
- ]})
+ ]}
+ if self.api_version >= api_versions.APIVersion('2.69'):
+ # include "partial results" from non-responsive part of
+ # infrastructure.
+ servers['servers'].append(
+ {'id': '9015',
+ 'status': "UNKNOWN",
+ "links": [
+ {
+ "href": "http://fake/v2.1/",
+ "rel": "self"
+ },
+ {
+ "href": "http://fake",
+ "rel": "bookmark"
+ }
+ ]}
+ )
+ return (200, {}, servers)
def get_servers_detail(self, **kw):
- return (200, {}, {"servers": [
+ servers = {"servers": [
{
"id": '1234',
"name": "sample-server",
@@ -538,7 +556,29 @@ class FakeSessionClient(base_client.SessionClient):
"hostId": "9e107d9d372bb6826bd81d3542a419d6",
"status": "ACTIVE",
},
- ]})
+ ]}
+ if self.api_version >= api_versions.APIVersion('2.69'):
+ # include "partial results" from non-responsive part of
+ # infrastructure.
+ servers['servers'].append(
+ {
+ "id": "9015",
+ "status": "UNKNOWN",
+ "tenant_id": "6f70656e737461636b20342065766572",
+ "created": "2018-12-03T21:06:18Z",
+ "links": [
+ {
+ "href": "http://fake/v2.1/",
+ "rel": "self"
+ },
+ {
+ "href": "http://fake",
+ "rel": "bookmark"
+ }
+ ]
+ }
+ )
+ return (200, {}, servers)
def post_servers(self, body, **kw):
assert set(body.keys()) <= set(['server', 'os:scheduler_hints'])
@@ -599,6 +639,27 @@ class FakeSessionClient(base_client.SessionClient):
r = {'server': self.get_servers_detail()[2]['servers'][4]}
return (200, {}, r)
+ def get_servers_9015(self, **kw):
+ r = {'server': self.get_servers_detail()[2]['servers'][5]}
+ r['server']["OS-EXT-AZ:availability_zone"] = 'geneva'
+ r['server']["OS-EXT-STS:power_state"] = 0
+ flavor = {
+ "disk": 1,
+ "ephemeral": 0,
+ "original_name": "m1.tiny",
+ "ram": 512,
+ "swap": 0,
+ "vcpus": 1,
+ "extra_specs": {}
+ }
+ image = {
+ "id": "c99d7632-bd66-4be9-aed5-3dd14b223a76",
+ }
+ r['server']['image'] = image
+ r['server']['flavor'] = flavor
+ r['server']['user_id'] = "fake"
+ return (200, {}, r)
+
def delete_os_server_groups_12345(self, **kw):
return (202, {}, None)
@@ -1644,24 +1705,35 @@ class FakeSessionClient(base_client.SessionClient):
else:
service_id_1 = 1
service_id_2 = 2
- return (200, FAKE_RESPONSE_HEADERS,
- {'services': [{'binary': binary,
- 'host': host,
- 'zone': 'nova',
- 'status': 'enabled',
- 'state': 'up',
- 'updated_at': datetime.datetime(
- 2012, 10, 29, 13, 42, 2),
- 'id': service_id_1},
- {'binary': binary,
- 'host': host,
- 'zone': 'nova',
- 'status': 'disabled',
- 'state': 'down',
- 'updated_at': datetime.datetime(
- 2012, 9, 18, 8, 3, 38),
- 'id': service_id_2},
- ]})
+ services = {
+ 'services': [
+ {'binary': binary,
+ 'host': host,
+ 'zone': 'nova',
+ 'status': 'enabled',
+ 'state': 'up',
+ 'updated_at': datetime.datetime(
+ 2012, 10, 29, 13, 42, 2),
+ 'id': service_id_1},
+ {'binary': binary,
+ 'host': host,
+ 'zone': 'nova',
+ 'status': 'disabled',
+ 'state': 'down',
+ 'updated_at': datetime.datetime(
+ 2012, 9, 18, 8, 3, 38),
+ 'id': service_id_2},
+ ]
+ }
+ if self.api_version >= api_versions.APIVersion('2.69'):
+ services['services'].append(
+ {
+ "binary": "nova-compute",
+ "host": "host-down",
+ "status": "UNKNOWN"
+ }
+ )
+ return (200, FAKE_RESPONSE_HEADERS, services)
def put_os_services_enable(self, body, **kw):
return (200, FAKE_RESPONSE_HEADERS,
diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py
index fbf93910..eecd9315 100644
--- a/novaclient/tests/unit/v2/test_shell.py
+++ b/novaclient/tests/unit/v2/test_shell.py
@@ -2939,6 +2939,21 @@ class ShellTest(utils.TestCase):
self.run_command('service-list', api_version='2.53')
self.assert_called('GET', '/os-services')
+ def test_services_list_v269_with_down_cells(self):
+ """Tests nova service-list at the 2.69 microversion."""
+ stdout, _stderr = self.run_command('service-list', api_version='2.69')
+ self.assertEqual('''\
++--------------------------------------+--------------+-----------+------+----------+-------+---------------------+-----------------+-------------+
+| Id | Binary | Host | Zone | Status | State | Updated_at | Disabled Reason | Forced down |
++--------------------------------------+--------------+-----------+------+----------+-------+---------------------+-----------------+-------------+
+| 75e9eabc-ed3b-4f11-8bba-add1e7e7e2de | nova-compute | host1 | nova | enabled | up | 2012-10-29 13:42:02 | | |
+| 1f140183-c914-4ddf-8757-6df73028aa86 | nova-compute | host1 | nova | disabled | down | 2012-09-18 08:03:38 | | |
+| | nova-compute | host-down | | UNKNOWN | | | | |
++--------------------------------------+--------------+-----------+------+----------+-------+---------------------+-----------------+-------------+
+''', # noqa
+ stdout)
+ self.assert_called('GET', '/os-services')
+
def test_services_list_with_host(self):
self.run_command('service-list --host host1')
self.assert_called('GET', '/os-services?host=host1')
@@ -4021,6 +4036,15 @@ class ShellTest(utils.TestCase):
63, # There are no version-wrapped shell method changes for this.
65, # There are no version-wrapped shell method changes for this.
67, # There are no version-wrapped shell method changes for this.
+ 69, # NOTE(tssurya): 2.69 adds support for missing keys in the
+ # responses of `GET /servers``, ``GET /servers/detail``,
+ # ``GET /servers/{server_id}`` and ``GET /os-services`` when
+ # a cell is down to return minimal constructs. From 2.69 and
+ # upwards, if the response for ``GET /servers/detail`` does
+ # not have the 'flavor' key for those instances in the down
+ # cell, they will be handled on the client side by being
+ # skipped when forming the detailed lists for embedded
+ # flavor information.
])
versions_supported = set(range(0,
novaclient.API_MAX_VERSION.ver_minor + 1))
@@ -4098,6 +4122,70 @@ class ShellTest(utils.TestCase):
self.run_command('list --not-tags-any tag1,tag2', api_version='2.26')
self.assert_called('GET', '/servers/detail?not-tags-any=tag1%2Ctag2')
+ def test_list_detail_v269_with_down_cells(self):
+ """Tests nova list at the 2.69 microversion."""
+ stdout, _stderr = self.run_command('list', api_version='2.69')
+ self.assertIn('''\
++------+----------------+---------+------------+-------------+----------------------------------------------+
+| ID | Name | Status | Task State | Power State | Networks |
++------+----------------+---------+------------+-------------+----------------------------------------------+
+| 9015 | | UNKNOWN | N/A | N/A | |
+| 9014 | help | ACTIVE | N/A | N/A | |
+| 1234 | sample-server | BUILD | N/A | N/A | private=10.11.12.13; public=1.2.3.4, 5.6.7.8 |
+| 5678 | sample-server2 | ACTIVE | N/A | N/A | private=10.13.12.13; public=4.5.6.7, 5.6.9.8 |
+| 9012 | sample-server3 | ACTIVE | N/A | N/A | private=10.13.12.13; public=4.5.6.7, 5.6.9.8 |
+| 9013 | sample-server4 | ACTIVE | N/A | N/A | |
++------+----------------+---------+------------+-------------+----------------------------------------------+
+''', # noqa
+ stdout)
+ self.assert_called('GET', '/servers/detail')
+
+ def test_list_v269_with_down_cells(self):
+ stdout, _stderr = self.run_command(
+ 'list --minimal', api_version='2.69')
+ expected = '''\
++------+----------------+
+| ID | Name |
++------+----------------+
+| 9015 | |
+| 9014 | help |
+| 1234 | sample-server |
+| 5678 | sample-server2 |
++------+----------------+
+'''
+ self.assertEqual(expected, stdout)
+ self.assert_called('GET', '/servers')
+
+ def test_show_v269_with_down_cells(self):
+ stdout, _stderr = self.run_command('show 9015', api_version='2.69')
+ self.assertEqual('''\
++-----------------------------+---------------------------------------------------+
+| Property | Value |
++-----------------------------+---------------------------------------------------+
+| OS-EXT-AZ:availability_zone | geneva |
+| OS-EXT-STS:power_state | 0 |
+| created | 2018-12-03T21:06:18Z |
+| flavor:disk | 1 |
+| flavor:ephemeral | 0 |
+| flavor:extra_specs | {} |
+| flavor:original_name | m1.tiny |
+| flavor:ram | 512 |
+| flavor:swap | 0 |
+| flavor:vcpus | 1 |
+| id | 9015 |
+| image | CentOS 5.2 (c99d7632-bd66-4be9-aed5-3dd14b223a76) |
+| status | UNKNOWN |
+| tenant_id | 6f70656e737461636b20342065766572 |
+| user_id | fake |
++-----------------------------+---------------------------------------------------+
+''', # noqa
+ stdout)
+ FAKE_UUID_2 = 'c99d7632-bd66-4be9-aed5-3dd14b223a76'
+ self.assert_called('GET', '/servers?name=9015', pos=0)
+ self.assert_called('GET', '/servers?name=9015', pos=1)
+ self.assert_called('GET', '/servers/9015', pos=2)
+ self.assert_called('GET', '/v2/images/%s' % FAKE_UUID_2, pos=3)
+
class PollForStatusTestCase(utils.TestCase):
@mock.patch("novaclient.v2.shell.time")
diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py
index a86c0d8e..0ff60156 100644
--- a/novaclient/v2/shell.py
+++ b/novaclient/v2/shell.py
@@ -1670,7 +1670,18 @@ def do_list(cs, args):
# For detailed lists, if we have embedded flavor information then replace
# the "flavor" attribute with more detailed information.
if detailed and have_embedded_flavor_info:
- _expand_dict_attr(servers, 'flavor')
+ if cs.api_version >= api_versions.APIVersion('2.69'):
+ # NOTE(tssurya): From 2.69, we will have the key 'flavor' missing
+ # in the server response during infrastructure failure situations.
+ # For those servers with partial constructs we just skip the
+ # process of expanding the flavor information.
+ servers_final = []
+ for server in servers:
+ if hasattr(server, 'flavor'):
+ servers_final.append(server)
+ _expand_dict_attr(servers_final, 'flavor')
+ else:
+ _expand_dict_attr(servers, 'flavor')
if servers:
cols, fmts = _get_list_table_columns_and_formatters(
diff --git a/releasenotes/notes/bp-handling-down-cell-728cdb1efd1ea75b.yaml b/releasenotes/notes/bp-handling-down-cell-728cdb1efd1ea75b.yaml
new file mode 100644
index 00000000..0403d80f
--- /dev/null
+++ b/releasenotes/notes/bp-handling-down-cell-728cdb1efd1ea75b.yaml
@@ -0,0 +1,9 @@
+---
+features:
+ - |
+ From microversion 2.69 the results of ``nova list``, ``nova show`` and
+ ``nova service-list`` may contain missing information in their outputs
+ when there are partial infrastructure failure periods in the deployment.
+ See `Handling Down Cells`_ for more information on the missing keys/info.
+
+ .. _Handling Down Cells: https://developer.openstack.org/api-guide/compute/down_cells.html