From a1156097d207061b6fa9d7fc6b9114d2e17302d6 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 13 Apr 2018 16:54:27 -0400 Subject: [PATCH] Add facility to disable autosense discovery autosense at scale may produce undesirable performance. Provide an interface to turn off the autosense. If autosense is off, manual scan can still be performed. --- .../confluent/config/configmanager.py | 18 +++++++- confluent_server/confluent/discovery/core.py | 41 +++++++++++++++++-- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/confluent_server/confluent/config/configmanager.py b/confluent_server/confluent/config/configmanager.py index 7bad6802..9d2087af 100644 --- a/confluent_server/confluent/config/configmanager.py +++ b/confluent_server/confluent/config/configmanager.py @@ -1684,19 +1684,33 @@ def restore_db_from_directory(location, password): if e.errno == 2: raise Exception("Cannot restore without keys, this may be a " "redacted dump") + try: + moreglobals = json.load(open(os.path.join(location, 'globals.json'))) + for globvar in moreglobals: + set_global(globvar, moreglobals[globvar]) + except IOError as e: + if e.errno != 2: + raise with open(os.path.join(location, 'main.json'), 'r') as cfgfile: cfgdata = cfgfile.read() ConfigManager(tenant=None)._load_from_json(cfgdata) -def dump_db_to_directory(location, password, redact=None): - if not redact: +def dump_db_to_directory(location, password, redact=None, skipkeys=False): + if not redact and not skipkeys: with open(os.path.join(location, 'keys.json'), 'w') as cfgfile: cfgfile.write(_dump_keys(password)) cfgfile.write('\n') with open(os.path.join(location, 'main.json'), 'w') as cfgfile: cfgfile.write(ConfigManager(tenant=None)._dump_to_json(redact=redact)) cfgfile.write('\n') + bkupglobals = {} + for globvar in _cfgstore['globals']: + if globvar.endswith('_key'): + continue + bkupglobals[globvar] = _cfgstore['globals'][globvar] + if bkupglobals: + json.dump(bkupglobals, open(os.path.join(location, 'globals.json'))) try: for tenant in os.listdir( os.path.join(ConfigManager._cfgdir, '/tenants/')): diff --git a/confluent_server/confluent/discovery/core.py b/confluent_server/confluent/discovery/core.py index 9dfc76db..1cc31a9c 100644 --- a/confluent_server/confluent/discovery/core.py +++ b/confluent_server/confluent/discovery/core.py @@ -85,6 +85,7 @@ import eventlet import eventlet.greenpool import eventlet.semaphore +autosensors = set() class nesteddict(dict): def __missing__(self, key): @@ -350,7 +351,28 @@ def _parameterize_path(pathcomponents): return validselectors, keyparams, listrequested, childcoll +def handle_autosense_config(operation, inputdata): + autosense = cfm.get_global('discovery.autosense') + autosense = autosense or autosense is None + if operation == 'retrieve': + yield msg.KeyValueData({'enabled': autosense}) + elif operation == 'update': + enabled = inputdata['enabled'] + if type(enabled) in (unicode, str): + enabled = enabled.lower() in ('true', '1', 'y', 'yes', 'enable', + 'enabled') + if autosense == enabled: + return + cfm.set_global('discovery.autosense', enabled) + if enabled: + start_autosense() + else: + stop_autosense() + + def handle_api_request(configmanager, inputdata, operation, pathcomponents): + if pathcomponents == ['discovery', 'autosense']: + return handle_autosense_config(operation, inputdata) if operation == 'retrieve': return handle_read_api_request(pathcomponents) elif (operation in ('update', 'create') and @@ -398,6 +420,7 @@ def handle_read_api_request(pathcomponents): if len(pathcomponents) == 1: dirlist = [msg.ChildCollection(x + '/') for x in sorted(list(subcats))] dirlist.append(msg.ChildCollection('rescan')) + dirlist.append(msg.ChildCollection('autosense')) return dirlist if not coll: return show_info(queryparms['by-mac']) @@ -1083,8 +1106,9 @@ def newnodes(added, deleting, configmanager): allnodes = configmanager.list_nodes() attribwatcher = configmanager.watch_attributes( allnodes, ('discovery.policy', 'net*.switch', - 'hardwaremanagement.manager', 'net*.switchport', 'id.uuid', - 'pubkeys.tls_hardwaremanager', 'net*.bootable'), _recheck_nodes) + 'hardwaremanagement.manager', 'net*.switchport', + 'id.uuid', 'pubkeys.tls_hardwaremanager', + 'net*.bootable'), _recheck_nodes) if nodeaddhandler: needaddhandled = True else: @@ -1130,14 +1154,23 @@ def start_detection(): 'hardwaremanagement.manager', 'net*.switchport', 'id.uuid', 'pubkeys.tls_hardwaremanager'), _recheck_nodes) cfg.watch_nodecollection(newnodes) - eventlet.spawn_n(slp.snoop, safe_detected) - eventlet.spawn_n(pxe.snoop, safe_detected) + autosense = cfm.get_global('discovery.autosense') + if autosense or autosense is None: + start_autosense() if rechecker is None: rechecktime = util.monotonic_time() + 900 rechecker = eventlet.spawn_after(900, _periodic_recheck, cfg) # eventlet.spawn_n(ssdp.snoop, safe_detected) +def stop_autosense(): + for watcher in list(autosensors): + watcher.kill() + autosensors.discard(watcher) + +def start_autosense(): + autosensors.add(eventlet.spawn(slp.snoop, safe_detected)) + autosensors.add(eventlet.spawn(pxe.snoop, safe_detected)) nodes_by_fprint = {}