finalize handlers even when another handler fails.
Instead of previously initializing and not finalizing the handles that completed successfully when a handler initializing or running failed we should attempt to always give said handlers a chance to finalize (even when another handler fails).
This commit is contained in:
@@ -151,10 +151,9 @@ def walker_handle_handler(pdata, _ctype, _filename, payload):
|
||||
try:
|
||||
mod = fixup_handler(importer.import_module(modname))
|
||||
call_begin(mod, pdata['data'], frequency)
|
||||
# Only register and increment
|
||||
# after the above have worked (so we don't if it
|
||||
# fails)
|
||||
handlers.register(mod)
|
||||
# Only register and increment after the above have worked, so we don't
|
||||
# register if it fails starting.
|
||||
handlers.register(mod, initialized=True)
|
||||
pdata['handlercount'] = curcount + 1
|
||||
except:
|
||||
util.logexc(LOG, "Failed at registering python file: %s (part "
|
||||
|
||||
@@ -281,6 +281,7 @@ class ContentHandlers(object):
|
||||
|
||||
def __init__(self):
|
||||
self.registered = {}
|
||||
self.initialized = []
|
||||
|
||||
def __contains__(self, item):
|
||||
return self.is_registered(item)
|
||||
@@ -291,11 +292,13 @@ class ContentHandlers(object):
|
||||
def is_registered(self, content_type):
|
||||
return content_type in self.registered
|
||||
|
||||
def register(self, mod):
|
||||
def register(self, mod, initialized=False):
|
||||
types = set()
|
||||
for t in mod.list_types():
|
||||
self.registered[t] = mod
|
||||
types.add(t)
|
||||
if initialized and mod not in self.initialized:
|
||||
self.initialized.append(mod)
|
||||
return types
|
||||
|
||||
def _get_handler(self, content_type):
|
||||
|
||||
@@ -344,12 +344,13 @@ class Init(object):
|
||||
cdir = self.paths.get_cpath("handlers")
|
||||
idir = self._get_ipath("handlers")
|
||||
|
||||
# Add the path to the plugins dir to the top of our list for import
|
||||
# instance dir should be read before cloud-dir
|
||||
if cdir and cdir not in sys.path:
|
||||
sys.path.insert(0, cdir)
|
||||
if idir and idir not in sys.path:
|
||||
sys.path.insert(0, idir)
|
||||
# Add the path to the plugins dir to the top of our list for importing
|
||||
# new handlers.
|
||||
#
|
||||
# Note(harlowja): instance dir should be read before cloud-dir
|
||||
for d in [cdir, idir]:
|
||||
if d and d not in sys.path:
|
||||
sys.path.insert(0, d)
|
||||
|
||||
# Ensure datasource fetched before activation (just incase)
|
||||
user_data_msg = self.datasource.get_userdata(True)
|
||||
@@ -357,24 +358,34 @@ class Init(object):
|
||||
# This keeps track of all the active handlers
|
||||
c_handlers = helpers.ContentHandlers()
|
||||
|
||||
# Add handlers in cdir
|
||||
potential_handlers = util.find_modules(cdir)
|
||||
for (fname, mod_name) in potential_handlers.iteritems():
|
||||
try:
|
||||
mod_locs = importer.find_module(mod_name, [''],
|
||||
['list_types',
|
||||
'handle_part'])
|
||||
if not mod_locs:
|
||||
LOG.warn(("Could not find a valid user-data handler"
|
||||
" named %s in file %s"), mod_name, fname)
|
||||
continue
|
||||
mod = importer.import_module(mod_locs[0])
|
||||
mod = handlers.fixup_handler(mod)
|
||||
types = c_handlers.register(mod)
|
||||
LOG.debug("Added handler for %s from %s", types, fname)
|
||||
except:
|
||||
util.logexc(LOG, "Failed to register handler from %s", fname)
|
||||
def register_handlers_in_dir(path):
|
||||
# Attempts to register any handler modules under the given path.
|
||||
if not path or not os.path.isdir(path):
|
||||
return
|
||||
potential_handlers = util.find_modules(path)
|
||||
for (fname, mod_name) in potential_handlers.iteritems():
|
||||
try:
|
||||
mod_locs = importer.find_module(mod_name, [''],
|
||||
['list_types',
|
||||
'handle_part'])
|
||||
if not mod_locs:
|
||||
LOG.warn(("Could not find a valid user-data handler"
|
||||
" named %s in file %s"), mod_name, fname)
|
||||
continue
|
||||
mod = importer.import_module(mod_locs[0])
|
||||
mod = handlers.fixup_handler(mod)
|
||||
types = c_handlers.register(mod)
|
||||
LOG.debug("Added handler for %s from %s", types, fname)
|
||||
except Exception:
|
||||
util.logexc(LOG, "Failed to register handler from %s",
|
||||
fname)
|
||||
|
||||
# Add any handlers in the cloud-dir
|
||||
register_handlers_in_dir(cdir)
|
||||
|
||||
# Register any other handlers that come from the default set. This
|
||||
# is done after the cloud-dir handlers so that the cdir modules can
|
||||
# take over the default user-data handler content-types.
|
||||
def_handlers = self._default_userdata_handlers()
|
||||
applied_def_handlers = c_handlers.register_defaults(def_handlers)
|
||||
if applied_def_handlers:
|
||||
@@ -383,36 +394,51 @@ class Init(object):
|
||||
# Form our cloud interface
|
||||
data = self.cloudify()
|
||||
|
||||
# Init the handlers first
|
||||
called = []
|
||||
for (_ctype, mod) in c_handlers.iteritems():
|
||||
if mod in called:
|
||||
continue
|
||||
handlers.call_begin(mod, data, frequency)
|
||||
called.append(mod)
|
||||
def init_handlers():
|
||||
# Init the handlers first
|
||||
for (_ctype, mod) in c_handlers.iteritems():
|
||||
if mod in c_handlers.initialized:
|
||||
# Avoid initing the same module twice (if said module
|
||||
# is registered to more than one content-type).
|
||||
continue
|
||||
handlers.call_begin(mod, data, frequency)
|
||||
c_handlers.initialized.append(mod)
|
||||
|
||||
# Walk the user data
|
||||
part_data = {
|
||||
'handlers': c_handlers,
|
||||
# Any new handlers that are encountered get writen here
|
||||
'handlerdir': idir,
|
||||
'data': data,
|
||||
# The default frequency if handlers don't have one
|
||||
'frequency': frequency,
|
||||
# This will be used when new handlers are found
|
||||
# to help write there contents to files with numbered
|
||||
# names...
|
||||
'handlercount': 0,
|
||||
}
|
||||
handlers.walk(user_data_msg, handlers.walker_callback, data=part_data)
|
||||
def walk_handlers():
|
||||
# Walk the user data
|
||||
part_data = {
|
||||
'handlers': c_handlers,
|
||||
# Any new handlers that are encountered get writen here
|
||||
'handlerdir': idir,
|
||||
'data': data,
|
||||
# The default frequency if handlers don't have one
|
||||
'frequency': frequency,
|
||||
# This will be used when new handlers are found
|
||||
# to help write there contents to files with numbered
|
||||
# names...
|
||||
'handlercount': 0,
|
||||
}
|
||||
handlers.walk(user_data_msg, handlers.walker_callback,
|
||||
data=part_data)
|
||||
|
||||
# Give callbacks opportunity to finalize
|
||||
called = []
|
||||
for (_ctype, mod) in c_handlers.iteritems():
|
||||
if mod in called:
|
||||
continue
|
||||
handlers.call_end(mod, data, frequency)
|
||||
called.append(mod)
|
||||
def finalize_handlers():
|
||||
# Give callbacks opportunity to finalize
|
||||
for (_ctype, mod) in c_handlers.iteritems():
|
||||
if mod not in c_handlers.initialized:
|
||||
# Said module was never inited in the first place, so lets
|
||||
# not attempt to finalize those that never got called.
|
||||
continue
|
||||
c_handlers.initialized.remove(mod)
|
||||
try:
|
||||
handlers.call_end(mod, data, frequency)
|
||||
except:
|
||||
util.logexc(LOG, "Failed to finalize handler: %s", mod)
|
||||
|
||||
try:
|
||||
init_handlers()
|
||||
walk_handlers()
|
||||
finally:
|
||||
finalize_handlers()
|
||||
|
||||
# Perform post-consumption adjustments so that
|
||||
# modules that run during the init stage reflect
|
||||
|
||||
Reference in New Issue
Block a user