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.
376 lines
16 KiB
376 lines
16 KiB
# Copyright (C) 2005-2025 Splunk Inc. All Rights Reserved.
|
|
|
|
"""
|
|
disable_enable_itsi.py
|
|
A script that allows for the following:
|
|
- Move objects from kvstore collection(s) to a file on disk
|
|
- Restore objects from file on disk to kvstore:
|
|
- by replacing existing kv store data
|
|
- by appending to existing kv store data if possible
|
|
"""
|
|
|
|
import sys
|
|
import getpass
|
|
import json
|
|
from collections import defaultdict
|
|
import splunk.rest as rest
|
|
|
|
from splunk import auth
|
|
from splunk.clilib.bundle_paths import make_splunkhome_path
|
|
|
|
sys.path.append(make_splunkhome_path(['etc', 'apps', 'SA-ITOA', 'lib']))
|
|
import itsi_path
|
|
import itsi_py3
|
|
from ITOA.setup_logging import logger
|
|
from ITOA.saved_search_utility import SavedSearch
|
|
from itsi.itsi_utils import ITOAInterfaceUtils
|
|
from itsi.service_template.service_template_utils import ServiceTemplateUtils
|
|
from itsi.objects.itsi_backup_restore import ItsiBackupRestore
|
|
|
|
|
|
SPLUNKD_HOST_PATH = 'https://localhost'
|
|
SPLUNKD_PORT = '8089'
|
|
SPLUNK_USER = 'admin'
|
|
|
|
block_list = ['udp', 'ssl', 'splunktcptoken', 'all', 'http',
|
|
'oneshot', 'script', 'tcp', 'cooked', 'monitor']
|
|
|
|
print('\n#################################################\n'
|
|
' Enable/Disable ITSI \n'
|
|
'Use this script to enable and disable ITSI. \n'
|
|
'The following knowledge objects are disabled\n'
|
|
'when you execute this script:\n'
|
|
' * All ITSI modular inputs\n'
|
|
' * All scheduled, ad-hoc, and base searches\n'
|
|
' * Rules Engine Java processes\n'
|
|
'You have the choice to disable modular inputs,\n'
|
|
'saved searches, or both.\n'
|
|
'Warning:\n'
|
|
'This script does not terminate ongoing processes\n'
|
|
'such as service template syncs and backup/restore jobs.\n'
|
|
'It is advised to wait for those operations to\n'
|
|
'complete before disabling ITSI.\n'
|
|
'##################################################\n')
|
|
|
|
|
|
def toggle_ui(is_visible):
|
|
try:
|
|
postargs = {'visible': is_visible}
|
|
response, content = rest.simpleRequest('/services/apps/local/itsi',
|
|
sessionKey=session_key,
|
|
postargs=postargs,
|
|
method='POST')
|
|
if response.status != 200 and response.status != 201:
|
|
logger.error("Failed to set UI access to: %s, error: %s", False, response)
|
|
else:
|
|
if is_visible:
|
|
logger.info("Successfully enabled UI access.")
|
|
else:
|
|
logger.info("Successfully disabled UI access.")
|
|
except Exception as e:
|
|
logger.exception(e)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
retries = 3
|
|
splunkd_port = None
|
|
handle_mi = False
|
|
handle_ss = False
|
|
count_updated_mi = 0
|
|
count_updated_ss = 0
|
|
while not splunkd_port and retries:
|
|
splunkd_port = input(('Enter splunkd port. Press enter to use'
|
|
' %s: ') % SPLUNKD_PORT)
|
|
if not splunkd_port.strip():
|
|
splunkd_port = SPLUNKD_PORT
|
|
else:
|
|
try:
|
|
int(splunkd_port)
|
|
except ValueError:
|
|
retries -= 1
|
|
print('Invalid port. Try again. {} retries left.'.format(retries))
|
|
continue
|
|
if not retries and not splunkd_port:
|
|
print('You have reached the maximum number of retries. Run the script again.')
|
|
sys.exit(0)
|
|
|
|
hostpath = SPLUNKD_HOST_PATH + ':' + splunkd_port + ''
|
|
print('Your Splunk instance is: %s' % hostpath)
|
|
|
|
retries = 3
|
|
session_key = None
|
|
while not session_key and retries:
|
|
username = SPLUNK_USER
|
|
password = getpass.getpass(prompt='Enter password for %s: ' % username)
|
|
|
|
print('Trying to obtain a Splunk session key...')
|
|
try:
|
|
session_key = auth.getSessionKey(username, password, hostpath)
|
|
except Exception as e:
|
|
retries -= 1
|
|
print('Encountered an error when logging in - ' + str(e))
|
|
print('Try again. %d retries left.' % retries)
|
|
|
|
if not retries and not session_key:
|
|
print('You have reached the maximum number of retries. Run the script again.')
|
|
sys.exit(0)
|
|
print('Splunk session key successfully obtained\n')
|
|
print('Perform precheck...\n')
|
|
status = ServiceTemplateUtils(session_key, 'nobody').service_template_sync_job_in_progress_or_sync_now()
|
|
if status.get('status', False):
|
|
print('One or more service templates are currently syncing. Please wait for them to complete.\n')
|
|
sys.exit(0)
|
|
backup_restore_interface = ItsiBackupRestore(session_key, 'nobody')
|
|
if backup_restore_interface.is_any_backup_restore_job_in_progress('owner'):
|
|
print('A backup or restore operation is in progress. Please wait for the operation to complete.\n')
|
|
sys.exit(0)
|
|
|
|
print('Precheck completed.\n')
|
|
|
|
option = input('Enter Y to disable ITSI and N to enable ITSI: (Y/N)? ')
|
|
if option.strip().lower() == 'y':
|
|
action = 'disable'
|
|
else:
|
|
action = 'enable'
|
|
|
|
if action == 'disable':
|
|
delete_option = input('Do you want to disable all modular inputs? (Y/N) ')
|
|
if delete_option.strip().lower() == 'y':
|
|
handle_mi = True
|
|
delete_option = input('Do you want to disable all saved searches? (Y/N) ')
|
|
if delete_option.strip().lower() == 'y':
|
|
handle_ss = True
|
|
elif action == 'enable':
|
|
enable_option = input('Do you want to enable all modular inputs? (Y/N) ')
|
|
if enable_option.strip().lower() == 'y':
|
|
handle_mi = True
|
|
enable_option = input('Do you want to enable all saved searches? (Y/N) ')
|
|
if enable_option.strip().lower() == 'y':
|
|
handle_ss = True
|
|
|
|
snapshot_search_cache = defaultdict()
|
|
snapshot_mod_cache = defaultdict()
|
|
|
|
params = {
|
|
'output_mode': 'json'
|
|
}
|
|
# Get a list of all the mod inputs
|
|
try:
|
|
response, content = rest.simpleRequest(
|
|
'/servicesNS/nobody/SA-ITOA/data/inputs/',
|
|
sessionKey=session_key,
|
|
getargs=params,
|
|
raiseAllErrors=False
|
|
)
|
|
except Exception as e:
|
|
logger.exception(e)
|
|
|
|
new_content = json.loads(content)
|
|
entry_list = new_content.get('entry')
|
|
|
|
# Get all the KPI searches
|
|
searches = SavedSearch.get_all_searches(session_key, 'itsi', 'nobody')
|
|
|
|
print('\n##############################################################################')
|
|
print('A total of {0} modular inputs and {1} saved searches were found on the system.'.format(len(entry_list),
|
|
len(searches)))
|
|
print('################################################################################\n')
|
|
confirm = input('Please confirm before proceeding (Y/N)? ')
|
|
if confirm.strip().lower() != 'y':
|
|
print('Abort........')
|
|
sys.exit(0)
|
|
|
|
# Get the content from the itsi_configuration_snapshot collection first
|
|
# ITSI is already enabled if this collection is empty.
|
|
snapshot_uri = '/servicesNS/nobody/SA-ITOA/storage/collections/data/itsi_configuration_snapshot'
|
|
try:
|
|
response, content = rest.simpleRequest(
|
|
snapshot_uri,
|
|
sessionKey=session_key,
|
|
raiseAllErrors=False,
|
|
getargs=params
|
|
)
|
|
except Exception as e:
|
|
logger.exception(e)
|
|
|
|
try:
|
|
for item in json.loads(content):
|
|
if item.get('object_type') == 'mod_input':
|
|
snapshot_mod_cache[item.get('name')] = item.get('disabled')
|
|
else:
|
|
snapshot_search_cache[item.get('name')] = item.get('disabled')
|
|
except Exception:
|
|
print('Unable to create snapshot cache, maybe the KVStore is not available, please try it again')
|
|
sys.exit(1)
|
|
|
|
if action == 'disable':
|
|
print('Disable ITSI UI\n')
|
|
toggle_ui(False)
|
|
elif action == 'enable':
|
|
if len(snapshot_mod_cache) == 0 and len(snapshot_search_cache) == 0:
|
|
print('All knowledge objects are already in their current state. There is no need to enable them again.')
|
|
sys.exit(0)
|
|
print('Enable ITSI UI\n')
|
|
toggle_ui(True)
|
|
|
|
if handle_ss:
|
|
retry = []
|
|
# managing all the savedsearches
|
|
if action == 'disable':
|
|
if len(snapshot_search_cache) > 0:
|
|
# already disabled
|
|
print('ITSI disable is already performed!\n')
|
|
sys.exit(0)
|
|
for search in searches:
|
|
if action == 'disable':
|
|
disabled = False
|
|
if search.get('disabled').strip() == '1':
|
|
disabled = True
|
|
data = {'name': search.name,
|
|
'disabled': disabled,
|
|
'object_type': 'saved_search'}
|
|
rsp, content = rest.simpleRequest(snapshot_uri,
|
|
sessionKey=session_key,
|
|
raiseAllErrors=False,
|
|
jsonargs=json.dumps(data),
|
|
method='POST')
|
|
# then disabled all the searches
|
|
if search.get('disabled').strip() == '1':
|
|
print('Search: {0} is already disabled'.format(search.name))
|
|
continue
|
|
search_param = {
|
|
'disabled': '1'
|
|
}
|
|
try:
|
|
is_update = SavedSearch.update_search(session_key,
|
|
search.name,
|
|
**search_param)
|
|
print('Disable search: {0}'.format(search.name))
|
|
count_updated_ss += 1
|
|
except Exception:
|
|
print('Error while disabling search = {0}'.format(search.name))
|
|
elif action == 'enable':
|
|
# enable the search
|
|
if not snapshot_search_cache.get(search.name, False):
|
|
search_param = {
|
|
'disabled': '0'
|
|
}
|
|
try:
|
|
is_update = SavedSearch.update_search(session_key,
|
|
search.name,
|
|
**search_param)
|
|
print('Enable search: {0}'.format(search.name))
|
|
if is_update:
|
|
count_updated_ss += 1
|
|
except Exception:
|
|
print('Error while enabling search = {0}'.format(search.name))
|
|
retry.append(search.name)
|
|
# this could only happen in enable case
|
|
if len(retry) > 0:
|
|
for search in searches:
|
|
if search.name in retry:
|
|
# enable the search
|
|
if not snapshot_search_cache.get(search.name, False):
|
|
search_param = {
|
|
'disabled': '0'
|
|
}
|
|
try:
|
|
is_update = SavedSearch.update_search(session_key,
|
|
search.name,
|
|
**search_param)
|
|
print('Enable search: {0}'.format(search.name))
|
|
if is_update:
|
|
count_updated_ss += 1
|
|
except Exception:
|
|
print('Retry enabling failed for search = {0}'.format(search.name))
|
|
|
|
if handle_mi:
|
|
# managing all the mod inputs
|
|
if action == 'disable':
|
|
if len(snapshot_mod_cache) > 0:
|
|
# already disabled
|
|
print('ITSI disable is already performed!\n')
|
|
sys.exit(0)
|
|
for entry in entry_list:
|
|
name = entry.get('name')
|
|
if name in block_list:
|
|
continue
|
|
response, content = rest.simpleRequest(
|
|
'/servicesNS/nobody/SA-ITOA/data/inputs/' + name,
|
|
sessionKey=session_key,
|
|
getargs=params,
|
|
raiseAllErrors=False
|
|
)
|
|
parsed_content = json.loads(content)
|
|
modinput_list = parsed_content.get('entry')
|
|
for modinput in modinput_list:
|
|
modinput_name = modinput.get('name')
|
|
key_name = name + '___' + modinput_name
|
|
if action == 'disable':
|
|
# populate the snapshot before disable
|
|
disabled = modinput.get('content', {}).get('disabled')
|
|
data = {'name': key_name,
|
|
'disabled': disabled,
|
|
'object_type': 'mod_input'}
|
|
rsp, content = rest.simpleRequest(snapshot_uri,
|
|
sessionKey=session_key,
|
|
raiseAllErrors=False,
|
|
jsonargs=json.dumps(data),
|
|
method='POST')
|
|
if not disabled:
|
|
status = ITOAInterfaceUtils.control_modular_input(session_key,
|
|
'SA-ITOA',
|
|
'nobody',
|
|
name,
|
|
modinput_name,
|
|
action)
|
|
if status:
|
|
print('Modular input {0} disabled successfully.'.format(key_name))
|
|
count_updated_mi += 1
|
|
else:
|
|
print('Failed to disable modular input {0}.'.format(key_name))
|
|
else:
|
|
print('Modular input {0} is already disabled.'.format(key_name))
|
|
elif action == 'enable':
|
|
if not snapshot_mod_cache.get(key_name, False):
|
|
status = ITOAInterfaceUtils.control_modular_input(session_key,
|
|
'SA-ITOA',
|
|
'nobody',
|
|
name,
|
|
modinput_name,
|
|
action)
|
|
if status:
|
|
print('Modular input {0} enabled successfully'.format(key_name))
|
|
count_updated_mi += 1
|
|
else:
|
|
print('Failed to enable modular input {0}'.format(key_name))
|
|
|
|
print('\n########################################################################')
|
|
print('A total of {0} modular inputs and {1} saved searches have been updated.'.format(count_updated_mi,
|
|
count_updated_ss))
|
|
print('########################################################################\n')
|
|
|
|
# If everything is enabled, clear the cache.
|
|
if action == 'enable':
|
|
filter_data = {}
|
|
get_args = {}
|
|
if handle_mi and handle_ss:
|
|
pass
|
|
elif handle_mi:
|
|
filter_data['object_type'] = 'mod_input'
|
|
elif handle_ss:
|
|
filter_data['object_type'] = 'saved_search'
|
|
get_args['query'] = json.dumps(filter_data)
|
|
try:
|
|
response, content = rest.simpleRequest(
|
|
snapshot_uri,
|
|
sessionKey=session_key,
|
|
getargs=get_args,
|
|
raiseAllErrors=False,
|
|
method='DELETE')
|
|
except Exception as e:
|
|
logger.exception(e)
|
|
|
|
count_updated_mi = 0
|
|
count_updated_ss = 0
|