You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
3.3 KiB

import sys
import os
from .base_util import is_valid_identifier, get_apps_path
from .searchinfo_util import should_use_btool, validate_searchinfo_for_btool
from .algo_loader import AlgoLoader, BtoolAlgoLoadingStrategy, RestAlgoLoadingStrategy
import cexc
logger = cexc.get_logger(__name__)
def load_algos_from_searchinfo(searchinfo):
"""
Load the list of algorithms supported from Splunk
Args:
searchinfo (dict): information required for search
Returns:
(dict): mapping of algorithm name to a dict containing
information about the algo (app, disabled, package)
"""
if not searchinfo:
return {}
algo_loader = algo_loader_from_searchinfo(searchinfo)
return algo_loader.load_algos()
def algo_loader_from_searchinfo(searchinfo):
"""
Create an AlgoLoader object with the correct algo loading strategy based on information from the searchinfo
Args:
searchinfo (dict): information required for search
Returns:
(AlgoLoader): AlgoLoader instance with the correct algo loading strategy
"""
if should_use_btool(searchinfo):
is_valid, err = validate_searchinfo_for_btool(searchinfo)
if is_valid:
# On an indexer, we need to iterate through the roles and merge the results manually
# since btool does not have user-to-role mapping there. Pass the roles instead of the username.
algo_loader = AlgoLoader(BtoolAlgoLoadingStrategy(searchinfo))
else:
raise RuntimeError('Failed to load algorithm on remote Splunk: %s' % err)
else:
# On a search head or a standalone node, REST API will get us the correctly merged results.
algo_loader = AlgoLoader(RestAlgoLoadingStrategy(searchinfo))
return algo_loader
def initialize_algo_class(algo_name, searchinfo):
"""Import and initialize the algorithm.
Args:
algo_name (str): the usual suspect
searchinfo (dict): information required for search
Returns:
algo_class (class): the suspect's class
"""
if not is_valid_identifier(algo_name):
raise RuntimeError('Failed to load algorithm with an invalid name: %s' % algo_name)
all_algos = load_algos_from_searchinfo(searchinfo)
algo = {}
try:
if algo_name in all_algos:
algo = all_algos[algo_name]
if not algo['disabled']:
bundle_path = searchinfo.get('bundle_path')
new_sys_path = os.path.join(get_apps_path(bundle_path), algo['app'], 'bin')
if new_sys_path not in sys.path:
sys.path.append(new_sys_path)
algos = __import__("%s.%s" % (algo['package'], algo_name))
else:
raise RuntimeError('Algorithm "%s" is disabled' % algo_name)
else:
raise RuntimeError('Algorithm "%s" cannot be loaded' % algo_name)
algo_package = getattr(algos, algo_name)
algo_class = getattr(algo_package, algo_name)
return algo_class
except (ImportError, AttributeError) as e:
package_name = algo.get('package', '')
algo_name = '{}.{}'.format(package_name, algo_name) if package_name else algo_name
logger.debug(e)
raise RuntimeError('Failed to load algorithm "%s"' % algo_name)