Merge "Revise driver api for introspection data backend"

This commit is contained in:
Zuul 2019-02-25 17:24:50 +00:00 committed by Gerrit Code Review
commit b738f2c305
3 changed files with 43 additions and 32 deletions

View File

@ -42,10 +42,10 @@ def _filter_data_excluded_keys(data):
class BaseStorageBackend(object):
@abc.abstractmethod
def get(self, node_id, processed=True, get_json=False):
def get(self, node_uuid, processed=True, get_json=False):
"""Get introspected data from storage backend.
:param node_id: node UUID or name.
:param node_uuid: node UUID.
:param processed: Specify whether the data to be retrieved is
processed or not.
:param get_json: Specify whether return the introspection data in json
@ -55,10 +55,10 @@ class BaseStorageBackend(object):
"""
@abc.abstractmethod
def save(self, node_info, data, processed=True):
def save(self, node_uuid, data, processed=True):
"""Save introspected data to storage backend.
:param node_info: a NodeInfo object.
:param node_uuid: node UUID.
:param data: the introspected data to be saved, in dict format.
:param processed: Specify whether the data to be saved is processed or
not.
@ -67,57 +67,62 @@ class BaseStorageBackend(object):
class NoStore(BaseStorageBackend):
def get(self, node_id, processed=True, get_json=False):
def get(self, node_uuid, processed=True, get_json=False):
raise utils.IntrospectionDataStoreDisabled(
'Introspection data storage is disabled')
def save(self, node_info, data, processed=True):
def save(self, node_uuid, data, processed=True):
LOG.debug('Introspection data storage is disabled, the data will not '
'be saved', node_info=node_info)
'be saved for node %(node)s', {'node': node_uuid})
class SwiftStore(object):
def get(self, node_id, processed=True, get_json=False):
def get(self, node_uuid, processed=True, get_json=False):
suffix = None if processed else _UNPROCESSED_DATA_STORE_SUFFIX
LOG.debug('Fetching introspection data from Swift for %s', node_id)
data = swift.get_introspection_data(node_id, suffix=suffix)
LOG.debug('Fetching introspection data from Swift for %s', node_uuid)
data = swift.get_introspection_data(node_uuid, suffix=suffix)
if get_json:
return json.loads(data)
return data
def save(self, node_info, data, processed=True):
def save(self, node_uuid, data, processed=True):
suffix = None if processed else _UNPROCESSED_DATA_STORE_SUFFIX
swift_object_name = swift.store_introspection_data(
_filter_data_excluded_keys(data),
node_info.uuid,
node_uuid,
suffix=suffix
)
LOG.info('Introspection data was stored in Swift object %s',
swift_object_name, node_info=node_info)
LOG.info('Introspection data was stored for node %(node)s in Swift '
'object %(obj_name)s', {'node': node_uuid,
'obj_name': swift_object_name})
if CONF.processing.store_data_location:
node_info = node_cache.get_node(node_uuid)
# TODO(kaifeng) node_info is not synced back, while we are not
# using extra in the processing logic, it looks fine at the moment,
# but we should consider refactor in a later time.
node_info.patch([{'op': 'add', 'path': '/extra/%s' %
CONF.processing.store_data_location,
'value': swift_object_name}])
class DatabaseStore(object):
def get(self, node_id, processed=True, get_json=False):
def get(self, node_uuid, processed=True, get_json=False):
LOG.debug('Fetching introspection data from database for %(node)s',
{'node': node_id})
data = node_cache.get_introspection_data(node_id, processed)
{'node': node_uuid})
data = node_cache.get_introspection_data(node_uuid, processed)
if get_json:
return data
return json.dumps(data)
def save(self, node_info, data, processed=True):
def save(self, node_uuid, data, processed=True):
introspection_data = _filter_data_excluded_keys(data)
try:
node_cache.store_introspection_data(node_info.uuid,
node_cache.store_introspection_data(node_uuid,
introspection_data, processed)
except Exception as e:
with excutils.save_and_reraise_exception():
LOG.exception('Failed to store introspection data in '
'database: %(exc)s', {'exc': e})
else:
LOG.info('Introspection data was stored in database',
node_info=node_info)
LOG.info('Introspection data was stored in database for node '
'%(node)s', {'node': node_uuid})

View File

@ -140,21 +140,20 @@ def _filter_data_excluded_keys(data):
if k not in _STORAGE_EXCLUDED_KEYS}
def _store_data(node_info, data, processed=True):
def _store_data(node_uuid, data, processed=True):
introspection_data_manager = plugins_base.introspection_data_manager()
store = CONF.processing.store_data
ext = introspection_data_manager[store].obj
ext.save(node_info, data, processed)
ext.save(node_uuid, data, processed)
def _store_unprocessed_data(node_info, data):
def _store_unprocessed_data(node_uuid, data):
# runs in background
try:
_store_data(node_info, data, processed=False)
_store_data(node_uuid, data, processed=False)
except Exception:
LOG.exception('Encountered exception saving unprocessed '
'introspection data', node_info=node_info,
data=data)
'introspection data for node %s', node_uuid, data=data)
def get_introspection_data(uuid, processed=True, get_json=False):
@ -198,7 +197,7 @@ def process(introspection_data):
# Note(mkovacik): store data now when we're sure that a background
# thread won't race with other process() or introspect.abort()
# call
utils.executor().submit(_store_unprocessed_data, node_info,
utils.executor().submit(_store_unprocessed_data, node_info.uuid,
unprocessed_data)
try:
@ -243,7 +242,7 @@ def _process_node(node_info, node, introspection_data):
# NOTE(dtantsur): repeat the check in case something changed
ir_utils.check_provision_state(node)
_run_post_hooks(node_info, introspection_data)
_store_data(node_info, introspection_data)
_store_data(node_info.uuid, introspection_data)
ironic = ir_utils.get_client()
pxe_filter.driver().sync(ironic)
@ -351,6 +350,6 @@ def _reapply_with_data(node_info, introspection_data):
'\n'.join(failures), node_info=node_info)
_run_post_hooks(node_info, introspection_data)
_store_data(node_info, introspection_data)
_store_data(node_info.uuid, introspection_data)
node_info.invalidate_cache()
rules.apply(node_info, introspection_data)

View File

@ -72,16 +72,23 @@ class TestSwiftStore(BaseTest):
swift_conn.create_object.assert_called_once_with(name,
json.dumps(data))
def _create_node(self):
session = db.get_writer_session()
with session.begin():
db.Node(uuid=self.node_info.uuid,
state=istate.States.starting).save(session)
def test_store_data_location(self, swift_mock):
CONF.set_override('store_data_location', 'inspector_data_object',
'processing')
self._create_node()
swift_conn = swift_mock.return_value
name = 'inspector_data-%s' % self.uuid
patch = [{'path': '/extra/inspector_data_object',
'value': name, 'op': 'add'}]
expected = self.data
self.driver.save(self.node_info, self.data)
self.driver.save(self.node_info.uuid, self.data)
data = introspection_data._filter_data_excluded_keys(self.data)
swift_conn.create_object.assert_called_once_with(name,
@ -101,7 +108,7 @@ class TestDatabaseStore(BaseTest):
state=istate.States.starting).save(session)
def test_store_and_get_data(self):
self.driver.save(self.node_info, self.data)
self.driver.save(self.node_info.uuid, self.data)
res_data = self.driver.get(self.node_info.uuid)