# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Backends for storing introspection data."""
import abc
import json
from oslo_config import cfg
from oslo_utils import excutils
from ironic_inspector.common import swift
from ironic_inspector.db import api as db
from ironic_inspector import utils
CONF = cfg.CONF
LOG = utils.getProcessingLogger(__name__)
_STORAGE_EXCLUDED_KEYS = {'logs'}
_UNPROCESSED_DATA_STORE_SUFFIX = 'UNPROCESSED'
def _filter_data_excluded_keys(data):
return {k: v for k, v in data.items()
if k not in _STORAGE_EXCLUDED_KEYS}
[docs]
class BaseStorageBackend(object, metaclass=abc.ABCMeta):
[docs]
@abc.abstractmethod
def get(self, node_uuid, processed=True, get_json=False):
"""Get introspected data from storage backend.
: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
format, string value is returned if False.
:returns: the introspection data.
:raises: IntrospectionDataStoreDisabled if storage backend is disabled.
"""
[docs]
@abc.abstractmethod
def save(self, node_uuid, data, processed=True):
"""Save introspected data to storage backend.
: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.
:raises: IntrospectionDataStoreDisabled if storage backend is disabled.
"""
[docs]
class NoStore(BaseStorageBackend):
[docs]
def get(self, node_uuid, processed=True, get_json=False):
raise utils.IntrospectionDataStoreDisabled(
'Introspection data storage is disabled')
[docs]
def save(self, node_uuid, data, processed=True):
LOG.debug('Introspection data storage is disabled, the data will not '
'be saved for node %(node)s', {'node': node_uuid})
[docs]
class SwiftStore(object):
[docs]
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_uuid)
data = swift.get_introspection_data(node_uuid, suffix=suffix)
if get_json:
return json.loads(data)
return data
[docs]
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_uuid,
suffix=suffix
)
LOG.info('Introspection data was stored for node %(node)s in Swift '
'object %(obj_name)s', {'node': node_uuid,
'obj_name': swift_object_name})
[docs]
class DatabaseStore(object):
[docs]
def get(self, node_uuid, processed=True, get_json=False):
LOG.debug('Fetching introspection data from database for %(node)s',
{'node': node_uuid})
data = db.get_introspection_data(node_uuid, processed)
if get_json:
return data
return json.dumps(data)
[docs]
def save(self, node_uuid, data, processed=True):
introspection_data = _filter_data_excluded_keys(data)
try:
db.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 for node '
'%(node)s', {'node': node_uuid})