baremetal: Add Node console methods

Add Node.get_console and Node.set_console_mode methods. Noted while
attempting to migrate nova from ironicclient to openstacksdk

Change-Id: I6eb255de711b55d56056f8a29828f30e45a105c8
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2022-12-05 11:31:29 +00:00
parent d0e8970503
commit 397562bc42
5 changed files with 132 additions and 3 deletions

View File

@ -21,7 +21,8 @@ Node Operations
set_node_secure_boot, inject_nmi_to_node, wait_for_nodes_provision_state,
set_node_power_state, wait_for_node_power_state,
wait_for_node_reservation, validate_node, set_node_maintenance,
unset_node_maintenance, delete_node, list_node_vendor_passthru
unset_node_maintenance, delete_node, list_node_vendor_passthru,
get_node_console, enable_node_console, disable_node_console
Node Trait Operations
^^^^^^^^^^^^^^^^^^^^^

View File

@ -1103,10 +1103,12 @@ class Proxy(proxy.Proxy):
def call_node_vendor_passthru(self, node, verb, method, body=None):
"""Calls vendor_passthru for a node.
:param session: The session to use for making this request.
:param node: The value can be the name or ID of a node or a
:class:`~openstack.baremetal.v1.node.Node` instance.
:param verb: The HTTP verb, one of GET, SET, POST, DELETE.
:param method: The method to call using vendor_passthru.
:param body: The JSON body in the HTTP call.
:returns: The raw response from the method.
"""
res = self._get_resource(_node.Node, node)
return res.call_vendor_passthru(self, verb, method, body)
@ -1114,11 +1116,43 @@ class Proxy(proxy.Proxy):
def list_node_vendor_passthru(self, node):
"""Lists vendor_passthru for a node.
:param session: The session to use for making this request.
:param node: The value can be the name or ID of a node or a
:class:`~openstack.baremetal.v1.node.Node` instance.
:returns: A list of vendor_passthru methods for the node.
"""
res = self._get_resource(_node.Node, node)
return res.list_vendor_passthru(self)
def get_node_console(self, node):
"""Get the console for a node.
:param node: The value can be the name or ID of a node or a
:class:`~openstack.baremetal.v1.node.Node` instance.
:returns: Connection information for the console.
"""
res = self._get_resource(_node.Node, node)
return res.get_node_console(self)
def enable_node_console(self, node):
"""Enable the console for a node.
:param node: The value can be the name or ID of a node or a
:class:`~openstack.baremetal.v1.node.Node` instance.
:returns: None
"""
res = self._get_resource(_node.Node, node)
return res.set_console_mode(self, True)
def disable_node_console(self, node):
"""Disable the console for a node.
:param node: The value can be the name or ID of a node or a
:class:`~openstack.baremetal.v1.node.Node` instance.
:returns: None
"""
res = self._get_resource(_node.Node, node)
return res.set_console_mode(self, False)
def set_node_traits(self, node, traits):
"""Set traits for a node.

View File

@ -1080,6 +1080,52 @@ class Node(_common.ListMixin, resource.Resource):
return response.json()
def get_console(self, session):
session = self._get_session(session)
version = self._get_microversion(session, action='fetch')
request = self._prepare_request(requires_id=True)
request.url = utils.urljoin(request.url, 'states', 'console')
response = session.get(
request.url,
headers=request.headers,
microversion=version,
retriable_status_codes=_common.RETRIABLE_STATUS_CODES,
)
msg = "Failed to get console for node {node}".format(
node=self.id,
)
exceptions.raise_from_response(response, error_message=msg)
return response.json()
def set_console_mode(self, session, enabled):
session = self._get_session(session)
version = self._get_microversion(session, action='commit')
request = self._prepare_request(requires_id=True)
request.url = utils.urljoin(request.url, 'states', 'console')
if not isinstance(enabled, bool):
raise ValueError(
"Invalid enabled %s. It should be True or False "
"corresponding to console enabled or disabled"
% enabled
)
body = {'enabled': enabled}
response = session.put(
request.url,
json=body,
headers=request.headers,
microversion=version,
retriable_status_codes=_common.RETRIABLE_STATUS_CODES,
)
msg = "Failed to change console mode for {node}".format(
node=self.id,
)
exceptions.raise_from_response(response, error_message=msg)
def patch(self, session, patch=None, prepend_key=True, has_body=True,
retry_on_conflict=None, base_path=None, reset_interfaces=None):

View File

@ -990,3 +990,43 @@ class TestNodePassthru(object):
'nodes/%s/vendor_passthru/methods' % self.node.id,
headers=mock.ANY, microversion='1.37',
retriable_status_codes=_common.RETRIABLE_STATUS_CODES)
@mock.patch.object(node.Node, 'fetch', lambda self, session: self)
@mock.patch.object(exceptions, 'raise_from_response', mock.Mock())
class TestNodeConsole(base.TestCase):
def setUp(self):
super().setUp()
self.node = node.Node(**FAKE)
self.session = mock.Mock(
spec=adapter.Adapter,
default_microversion='1.1',
)
def test_get_console(self):
self.node.get_console(self.session)
self.session.get.assert_called_once_with(
'nodes/%s/states/console' % self.node.id,
headers=mock.ANY,
microversion=mock.ANY,
retriable_status_codes=_common.RETRIABLE_STATUS_CODES,
)
def test_set_console_mode(self):
self.node.set_console_mode(self.session, True)
self.session.put.assert_called_once_with(
'nodes/%s/states/console' % self.node.id,
json={'enabled': True},
headers=mock.ANY,
microversion=mock.ANY,
retriable_status_codes=_common.RETRIABLE_STATUS_CODES,
)
def test_set_console_mode_invalid_enabled(self):
self.assertRaises(
ValueError,
self.node.set_console_mode,
self.session,
'true', # not a bool
)

View File

@ -0,0 +1,8 @@
---
features:
- |
Adds ``get_console`` and ``set_console_state`` to
``openstack.baremetal.v1.Node``.
- |
Adds ``get_node_console``, ``enable_node_console`` and
``disable_node_console`` to the baremetal Proxy.