Browse Source

Add support for retrieving unprocessed data

Change-Id: I3c0070d0c1f5d12e98f914be44f4ed52b01ea043
changes/04/743504/1
Dmitry Tantsur 1 year ago
parent
commit
cc7fcf4332
  1. 42
      api-ref/source/introspection-api-v1-introspection-management.inc
  2. 27
      doc/source/user/http-api.rst
  3. 20
      ironic_inspector/main.py
  4. 9
      ironic_inspector/test/functional.py
  5. 18
      ironic_inspector/test/unit/test_main.py
  6. 5
      releasenotes/notes/unprocessed-07842e56eb60e253.yaml

42
api-ref/source/introspection-api-v1-introspection-management.inc

@ -70,6 +70,48 @@ The response will contain introspection data in the form of json string.
:language: javascript
Get Unprocessed Introspection data
==================================
.. rest_method:: GET /v1/introspection/{node_id}/data/unprocessed
Return stored raw (unprocessed) data from introspection.
.. versionadded:: 1.17
Unprocessed introspection data can now be retrieved.
.. note::
We do not provide any backward compatibility guarantees regarding the
format and contents of the stored data. Notably, it depends on the ramdisk
used and plugins enabled both in the ramdisk and in inspector itself.
Normal response codes: 200
Error codes:
* 400 - bad request
* 401, 403 - missing or invalid authentication
* 404 - data cannot be found or data storage not configured
Request
-------
.. rest_parameters:: parameters.yaml
- node_id: node_id
Response
--------
The response will contain introspection data in the form of json string.
**Example JSON representation of an introspection data:**
.. literalinclude:: samples/api-v1-data-introspection-response.json
:language: javascript
Reapply Introspection on data
=============================

27
doc/source/user/http-api.rst

@ -134,6 +134,32 @@ details about the inventory key, refer to the
:ironic-python-agent-doc:`ironic-python-agent documentation
<admin/how_it_works.html#inspection-data>`.
.. note::
We do not provide any backward compatibility guarantees regarding the
format and contents of the stored data, other than the ``inventory``.
Notably, it depends on the ramdisk
used and plugins enabled both in the ramdisk and in inspector itself.
Get Unprocessed Introspection Data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``GET /v1/introspection/<Node ID>/data/unprocessed`` get raw (unprocessed) data
from introspection.
Requires X-Auth-Token header with Keystone token for authentication.
Response:
* 200 - OK
* 400 - bad request
* 401, 403 - missing or invalid authentication
* 404 - data cannot be found or data storage not configured
Response body: JSON dictionary with introspection data. For more
details about the inventory key, refer to the
:ironic-python-agent-doc:`ironic-python-agent documentation
<admin/how_it_works.html#inspection-data>`.
.. note::
We do not provide any backward compatibility guarantees regarding the
format and contents of the stored data, other than the ``inventory``.
@ -403,3 +429,4 @@ Version History
in the actions of introspection rules.
* **1.15** allows reapply with provided introspection data from request.
* **1.16** adds ``scope`` field to introspection rule.
* **1.17** adds ``GET /v1/introspection/<node>/data/unprocessed``.

20
ironic_inspector/main.py

@ -43,7 +43,7 @@ _wsgi_app = _app.wsgi_app
LOG = utils.getProcessingLogger(__name__)
MINIMUM_API_VERSION = (1, 0)
CURRENT_API_VERSION = (1, 16)
CURRENT_API_VERSION = (1, 17)
DEFAULT_API_VERSION = CURRENT_API_VERSION
_LOGGING_EXCLUDED_KEYS = ('logs',)
@ -386,14 +386,12 @@ def api_introspection_abort(node_id):
return _generate_empty_response(202)
@api('/v1/introspection/<node_id>/data', rule="introspection:data",
methods=['GET'])
def api_introspection_data(node_id):
def _get_data(node_id, processed):
try:
if not uuidutils.is_uuid_like(node_id):
node = ir_utils.get_node(node_id, fields=['uuid'])
node_id = node.uuid
res = process.get_introspection_data(node_id)
res = process.get_introspection_data(node_id, processed=processed)
return res, 200, {'Content-Type': 'application/json'}
except utils.IntrospectionDataStoreDisabled:
return error_response(_('Inspector is not configured to store data. '
@ -402,6 +400,18 @@ def api_introspection_data(node_id):
code=404)
@api('/v1/introspection/<node_id>/data', rule="introspection:data",
methods=['GET'])
def api_introspection_data(node_id):
return _get_data(node_id, True)
@api('/v1/introspection/<node_id>/data/unprocessed', rule="introspection:data",
methods=['GET'])
def api_introspection_unprocessed_data(node_id):
return _get_data(node_id, False)
@api('/v1/introspection/<node_id>/data/unprocessed',
rule="introspection:reapply", methods=['POST'])
def api_introspection_reapply(node_id):

9
ironic_inspector/test/functional.py

@ -177,8 +177,9 @@ class Base(base.NodeTest):
def call_get_status(self, uuid, **kwargs):
return self.call('get', '/v1/introspection/%s' % uuid, **kwargs).json()
def call_get_data(self, uuid, **kwargs):
return self.call('get', '/v1/introspection/%s/data' % uuid,
def call_get_data(self, uuid, processed=True, **kwargs):
return self.call('get', '/v1/introspection/%s/data%s'
% (uuid, '' if processed else '/unprocessed'),
**kwargs).json()
@_query_string('marker', 'limit')
@ -626,6 +627,10 @@ class Test(Base):
data = self.call_get_data(self.uuid)
self.assertEqual(self.data['inventory'], data['inventory'])
self.assertIn('all_interfaces', data)
raw = self.call_get_data(self.uuid, processed=False)
self.assertEqual(self.data['inventory'], raw['inventory'])
self.assertNotIn('all_interfaces', raw)
res = self.call_reapply(self.uuid)
self.assertEqual(202, res.status_code)

18
ironic_inspector/test/unit/test_main.py

@ -371,6 +371,19 @@ class TestApiGetData(BaseAPITest):
self.assertEqual(self.introspection_data,
json.loads(res.data.decode('utf-8')))
@mock.patch.object(swift, 'SwiftAPI', autospec=True)
def test_get_unprocessed_data_from_swift(self, swift_mock):
CONF.set_override('store_data', 'swift', 'processing')
swift_conn = swift_mock.return_value
swift_conn.get_object.return_value = json.dumps(
self.introspection_data)
res = self.app.get('/v1/introspection/%s/data/unprocessed' % self.uuid)
name = 'inspector_data-%s-UNPROCESSED' % self.uuid
swift_conn.get_object.assert_called_once_with(name)
self.assertEqual(200, res.status_code)
self.assertEqual(self.introspection_data,
json.loads(res.data.decode('utf-8')))
@mock.patch.object(intros_data_plugin, 'DatabaseStore',
autospec=True)
def test_get_introspection_data_from_db(self, db_mock):
@ -389,6 +402,11 @@ class TestApiGetData(BaseAPITest):
res = self.app.get('/v1/introspection/%s/data' % self.uuid)
self.assertEqual(404, res.status_code)
def test_unprocessed_data_not_stored(self):
CONF.set_override('store_data', 'none', 'processing')
res = self.app.get('/v1/introspection/%s/data/unprocessed' % self.uuid)
self.assertEqual(404, res.status_code)
@mock.patch.object(ir_utils, 'get_node', autospec=True)
@mock.patch.object(main.process, 'get_introspection_data', autospec=True)
def test_with_name(self, process_mock, get_mock):

5
releasenotes/notes/unprocessed-07842e56eb60e253.yaml

@ -0,0 +1,5 @@
---
features:
- |
The new API ``GET /v1/introspection/<node>/data/unprocessed`` allows
retrieving raw (unprocessed) data if data store is enabled.
Loading…
Cancel
Save