Introspection on stored data
this commit introduces Inspector service endpoint ``POST@/v1/introspection/<uuid>/data/unprocessed`` to the client code to be able to reprocess stored introspection data Change-Id: I45d57eb903c02e50a3ce98a9fb3e6f7d8d36d79b Related-bug: #1525237
This commit is contained in:
parent
d6585166c3
commit
a89a6043ee
15
README.rst
15
README.rst
@ -140,6 +140,21 @@ CLI::
|
||||
|
||||
$ openstack baremetal introspection abort UUID
|
||||
|
||||
Reprocess stored introspection data
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``client.reprocess(uuid)``
|
||||
|
||||
* ``uuid`` - Ironic node UUID.
|
||||
|
||||
CLI::
|
||||
|
||||
$ openstack baremetal introspection reprocess UUID
|
||||
|
||||
.. note::
|
||||
This feature requires Swift store to be enabled for **Ironic Inspector**
|
||||
by setting ``[processing]store_data`` configuration option to ``swift``.
|
||||
|
||||
Introspection Rules API
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -104,6 +104,19 @@ class StartCommand(lister.Lister):
|
||||
return self.COLUMNS, result
|
||||
|
||||
|
||||
class ReprocessCommand(command.Command):
|
||||
"""Reprocess stored introspection data"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ReprocessCommand, self).get_parser(prog_name)
|
||||
parser.add_argument('uuid', help='baremetal node UUID')
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.baremetal_introspection
|
||||
client.reprocess(parsed_args.uuid)
|
||||
|
||||
|
||||
class StatusCommand(show.ShowOne):
|
||||
"""Get introspection status."""
|
||||
|
||||
|
@ -14,9 +14,12 @@
|
||||
import eventlet
|
||||
eventlet.monkey_patch()
|
||||
|
||||
import json
|
||||
import mock
|
||||
import requests
|
||||
import unittest
|
||||
|
||||
from ironic_inspector.common import swift
|
||||
from ironic_inspector.test import functional
|
||||
|
||||
import ironic_inspector_client as client
|
||||
@ -26,6 +29,7 @@ class TestV1PythonAPI(functional.Base):
|
||||
def setUp(self):
|
||||
super(TestV1PythonAPI, self).setUp()
|
||||
self.client = client.ClientV1()
|
||||
functional.cfg.CONF.set_override('store_data', '', 'processing')
|
||||
|
||||
def test_introspect_get_status(self):
|
||||
self.client.introspect(self.uuid)
|
||||
@ -47,6 +51,53 @@ class TestV1PythonAPI(functional.Base):
|
||||
status = self.client.get_status(self.uuid)
|
||||
self.assertEqual({'finished': True, 'error': None}, status)
|
||||
|
||||
@mock.patch.object(swift, 'store_introspection_data', autospec=True)
|
||||
@mock.patch.object(swift, 'get_introspection_data', autospec=True)
|
||||
def test_reprocess_stored_introspection_data(self, get_mock,
|
||||
store_mock):
|
||||
functional.cfg.CONF.set_override('store_data', 'swift', 'processing')
|
||||
port_create_call = mock.call(node_uuid=self.uuid,
|
||||
address='11:22:33:44:55:66')
|
||||
get_mock.return_value = json.dumps(self.data)
|
||||
|
||||
# assert reprocessing doesn't work before introspection
|
||||
self.assertRaises(client.ClientError, self.client.reprocess,
|
||||
self.uuid)
|
||||
|
||||
self.client.introspect(self.uuid)
|
||||
eventlet.greenthread.sleep(functional.DEFAULT_SLEEP)
|
||||
self.cli.node.set_power_state.assert_called_once_with(self.uuid,
|
||||
'reboot')
|
||||
status = self.client.get_status(self.uuid)
|
||||
self.assertEqual({'finished': False, 'error': None},
|
||||
status)
|
||||
|
||||
res = self.call_continue(self.data)
|
||||
self.assertEqual({'uuid': self.uuid}, res)
|
||||
eventlet.greenthread.sleep(functional.DEFAULT_SLEEP)
|
||||
|
||||
status = self.client.get_status(self.uuid)
|
||||
self.assertEqual({'finished': True, 'error': None},
|
||||
status)
|
||||
self.cli.port.create.assert_has_calls([port_create_call],
|
||||
any_order=True)
|
||||
self.assertFalse(get_mock.called)
|
||||
self.assertTrue(store_mock.called)
|
||||
|
||||
res = self.client.reprocess(self.uuid)
|
||||
self.assertEqual(202, res.status_code)
|
||||
self.assertEqual('', res.text)
|
||||
eventlet.greenthread.sleep(functional.DEFAULT_SLEEP)
|
||||
self.assertEqual({'finished': True, 'error': None},
|
||||
status)
|
||||
|
||||
self.cli.port.create.assert_has_calls([port_create_call,
|
||||
port_create_call],
|
||||
any_order=True)
|
||||
self.assertTrue(get_mock.called)
|
||||
# incoming, processing, reapplying data
|
||||
self.assertEqual(3, store_mock.call_count)
|
||||
|
||||
def test_abort_introspection(self):
|
||||
# assert abort doesn't work before introspect request
|
||||
self.assertRaises(client.ClientError, self.client.abort,
|
||||
|
@ -104,6 +104,21 @@ class TestIntrospect(BaseTest):
|
||||
for uuid in uuids]
|
||||
self.assertEqual(calls, self.client.introspect.call_args_list)
|
||||
|
||||
def test_reprocess(self):
|
||||
node = 'uuid1'
|
||||
arglist = [node]
|
||||
verifylist = [('uuid', node)]
|
||||
response_mock = mock.Mock(status_code=202, content=b'')
|
||||
self.client.reprocess.return_value = response_mock
|
||||
|
||||
cmd = shell.ReprocessCommand(self.app, None)
|
||||
|
||||
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||
result = cmd.take_action(parsed_args)
|
||||
|
||||
self.client.reprocess.assert_called_once_with(node)
|
||||
self.assertIs(None, result)
|
||||
|
||||
def test_wait(self):
|
||||
nodes = ['uuid1', 'uuid2', 'uuid3']
|
||||
arglist = ['--wait'] + nodes
|
||||
|
@ -101,6 +101,20 @@ class TestIntrospect(BaseTest):
|
||||
params={'new_ipmi_username': 'u', 'new_ipmi_password': 'p'})
|
||||
|
||||
|
||||
@mock.patch.object(http.BaseClient, 'request')
|
||||
class TestReprocess(BaseTest):
|
||||
def test(self, mock_req):
|
||||
self.get_client().reprocess(self.uuid)
|
||||
mock_req.assert_called_once_with(
|
||||
'post',
|
||||
'/introspection/%s/data/unprocessed' % self.uuid
|
||||
)
|
||||
|
||||
def test_invalid_input(self, mock_req):
|
||||
self.assertRaises(TypeError, self.get_client().reprocess, 42)
|
||||
self.assertFalse(mock_req.called)
|
||||
|
||||
|
||||
@mock.patch.object(http.BaseClient, 'request')
|
||||
class TestGetStatus(BaseTest):
|
||||
def test(self, mock_req):
|
||||
|
@ -23,7 +23,7 @@ from ironic_inspector_client.common.i18n import _
|
||||
|
||||
|
||||
DEFAULT_API_VERSION = (1, 0)
|
||||
MAX_API_VERSION = (1, 3)
|
||||
MAX_API_VERSION = (1, 4)
|
||||
|
||||
# using huge timeout by default, as precise timeout should be set in
|
||||
# ironic-inspector settings
|
||||
@ -74,6 +74,23 @@ class ClientV1(http.BaseClient):
|
||||
'new_ipmi_password': new_ipmi_password}
|
||||
self.request('post', '/introspection/%s' % uuid, params=params)
|
||||
|
||||
def reprocess(self, uuid):
|
||||
"""Reprocess stored introspection data.
|
||||
|
||||
:param uuid: node UUID.
|
||||
:raises: ClientError on error reported from the server.
|
||||
:raises: VersionNotSupported if requested api_version is not supported.
|
||||
:raises: *requests* library exception on connection problems.
|
||||
:raises: TypeError if uuid is not a string.
|
||||
"""
|
||||
if not isinstance(uuid, six.string_types):
|
||||
raise TypeError(_("Expected string for uuid argument, got"
|
||||
" %r instead") % uuid)
|
||||
|
||||
return self.request('post',
|
||||
'/introspection/%s/data/unprocessed' %
|
||||
uuid)
|
||||
|
||||
def get_status(self, uuid):
|
||||
"""Get introspection status for a node.
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- Introduced command "openstack baremetal introspection reprocess <UUID>"
|
||||
to reprocess stored introspection data
|
@ -23,6 +23,7 @@ openstack.cli.extension =
|
||||
openstack.baremetal_introspection.v1 =
|
||||
baremetal_introspection_start = ironic_inspector_client.shell:StartCommand
|
||||
baremetal_introspection_status = ironic_inspector_client.shell:StatusCommand
|
||||
baremetal_introspection_reprocess = ironic_inspector_client.shell:ReprocessCommand
|
||||
baremetal_introspection_abort = ironic_inspector_client.shell:AbortCommand
|
||||
baremetal_introspection_data_save = ironic_inspector_client.shell:DataSaveCommand
|
||||
baremetal_introspection_rule_import = ironic_inspector_client.shell:RuleImportCommand
|
||||
|
Loading…
Reference in New Issue
Block a user