Additional userdata refactoring

This commit is contained in:
Alessandro Pilotti 2014-01-20 13:43:16 +02:00
parent 247e9dfeeb
commit e725b82913
6 changed files with 117 additions and 36 deletions

View File

@ -59,49 +59,75 @@ class UserDataPlugin(base.BasePlugin):
if reboot: if reboot:
break break
if not reboot:
for handler_func in list(set(user_handlers.values())):
self._end_part_process_event(handler_func)
return (plugin_status, reboot) return (plugin_status, reboot)
else: else:
return self._process_non_multi_part(user_data) return self._process_non_multi_part(user_data)
def _process_part(self, part, user_data_plugins, user_handlers): def _process_part(self, part, user_data_plugins, user_handlers):
ret_val = None ret_val = None
content_type = part.get_content_type() try:
user_data_plugin = user_data_plugins.get(content_type) content_type = part.get_content_type()
if not user_data_plugin:
LOG.info("Userdata plugin not found for content type: %s" % handler_func = user_handlers.get(content_type)
content_type) if handler_func:
else: LOG.debug("Calling user part handler for content type: %s" %
try: content_type)
if content_type == self._part_handler_content_type: handler_func(None, content_type, part.get_filename(),
user_handlers.update(user_data_plugin.process(part)) part.get_payload())
else:
user_data_plugin = user_data_plugins.get(content_type)
if not user_data_plugin:
LOG.info("Userdata plugin not found for content type: %s" %
content_type)
else: else:
handler_func = user_handlers.get(part.get_content_type()) LOG.debug("Executing userdata plugin: %s" %
self._begin_part_process_event(part, handler_func) user_data_plugin.__class__.__name__)
LOG.info("Executing user data plugin: %s" % if content_type == self._part_handler_content_type:
user_data_plugin.__class__.__name__) new_user_handlers = user_data_plugin.process(part)
self._add_part_handlers(user_data_plugins,
ret_val = user_data_plugin.process(part) user_handlers,
new_user_handlers)
self._end_part_process_event(part, handler_func) else:
except Exception, ex: ret_val = user_data_plugin.process(part)
LOG.error('Exception during multipart part handling: ' except Exception, ex:
'%(content_type)s, %(filename)s' % LOG.error('Exception during multipart part handling: '
{'content_type': part.get_content_type(), '%(content_type)s, %(filename)s' %
'filename': part.get_filename()}) {'content_type': part.get_content_type(),
LOG.exception(ex) 'filename': part.get_filename()})
LOG.exception(ex)
return self._get_plugin_return_value(ret_val) return self._get_plugin_return_value(ret_val)
def _begin_part_process_event(self, part, handler_func): def _add_part_handlers(self, user_data_plugins, user_handlers,
if handler_func: new_user_handlers):
handler_func("", "__begin__", part.get_filename(), handler_funcs = set()
part.get_payload())
def _end_part_process_event(self, part, handler_func): for (content_type,
if handler_func: handler_func) in new_user_handlers.items():
handler_func("", "__end__", part.get_filename(), if not user_data_plugins.get(content_type):
part.get_payload()) LOG.info("Adding part handler for content "
"type: %s" % content_type)
user_handlers[content_type] = handler_func
handler_funcs.add(handler_func)
else:
LOG.info("Skipping part handler for content type \"%s\" as it "
"is already managed by a plugin" % content_type)
for handler_func in handler_funcs:
self._begin_part_process_event(handler_func)
def _begin_part_process_event(self, handler_func):
LOG.debug("Calling part handler \"__begin__\" event")
handler_func(None, "__begin__", None, None)
def _end_part_process_event(self, handler_func):
LOG.debug("Calling part handler \"__end__\" event")
handler_func(None, "__end__", None, None)
def _get_plugin_return_value(self, ret_val): def _get_plugin_return_value(self, ret_val):
plugin_status = base.PLUGIN_EXECUTION_DONE plugin_status = base.PLUGIN_EXECUTION_DONE

View File

@ -0,0 +1,27 @@
# Copyright 2014 Cloudbase Solutions Srl
#
# 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.
from cloudbaseinit.openstack.common import log as logging
from cloudbaseinit.plugins.windows.userdataplugins import base
LOG = logging.getLogger(__name__)
class CloudBootHookPlugin(base.BaseUserDataPlugin):
def __init__(self):
super(CloudBootHookPlugin, self).__init__("text/cloud-boothook")
def process(self, part):
LOG.info("%s content is currently not supported" %
self.get_mime_type())

View File

@ -24,4 +24,5 @@ class CloudConfigPlugin(base.BaseUserDataPlugin):
super(CloudConfigPlugin, self).__init__("text/cloud-config") super(CloudConfigPlugin, self).__init__("text/cloud-config")
def process(self, part): def process(self, part):
LOG.info("text/cloud-config content is not currently supported") LOG.info("%s content is currently not supported" %
self.get_mime_type())

View File

@ -21,12 +21,16 @@ opts = [
default=[ default=[
'cloudbaseinit.plugins.windows.userdataplugins.parthandler.' 'cloudbaseinit.plugins.windows.userdataplugins.parthandler.'
'PartHandlerPlugin', 'PartHandlerPlugin',
'cloudbaseinit.plugins.windows.userdataplugins.heat.'
'HeatPlugin',
'cloudbaseinit.plugins.windows.userdataplugins.cloudconfig.' 'cloudbaseinit.plugins.windows.userdataplugins.cloudconfig.'
'CloudConfigPlugin', 'CloudConfigPlugin',
'cloudbaseinit.plugins.windows.userdataplugins.cloudboothook.'
'CloudBootHookPlugin',
'cloudbaseinit.plugins.windows.userdataplugins.shellscript.' 'cloudbaseinit.plugins.windows.userdataplugins.shellscript.'
'ShellScriptPlugin', 'ShellScriptPlugin',
'cloudbaseinit.plugins.windows.userdataplugins.multipartmixed.'
'MultipartMixedPlugin',
'cloudbaseinit.plugins.windows.userdataplugins.heat.'
'HeatPlugin',
], ],
help='List of enabled userdata content plugins'), help='List of enabled userdata content plugins'),
] ]

View File

@ -27,7 +27,7 @@ class HeatPlugin(base.BaseUserDataPlugin):
super(HeatPlugin, self).__init__("text/x-cfninitdata") super(HeatPlugin, self).__init__("text/x-cfninitdata")
def process(self, part): def process(self, part):
# Only user-data part of Heat multipart data is supported.
# All other cfinitdata part will be skipped
if part.get_filename() == self._heat_user_data_filename: if part.get_filename() == self._heat_user_data_filename:
return userdatautils.execute_user_data_script(part.get_payload()) return userdatautils.execute_user_data_script(part.get_payload())
else:
LOG.info("Heat content not supported: %s" % part.get_filename())

View File

@ -0,0 +1,23 @@
# Copyright 2014 Cloudbase Solutions Srl
#
# 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.
from cloudbaseinit.plugins.windows.userdataplugins import base
class MultipartMixedPlugin(base.BaseUserDataPlugin):
def __init__(self):
super(MultipartMixedPlugin, self).__init__("multipart/mixed")
def process(self, part):
pass