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
This commit is contained in:
parent
874b03068f
commit
14a45183ee
@ -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>``
|
||||
|
@ -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")
|
||||
|
@ -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,
|
||||
|
@ -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")
|
||||
|
@ -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(
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user