diff --git a/cloudbaseinit/init.py b/cloudbaseinit/init.py index 1720d6a8..0391652f 100644 --- a/cloudbaseinit/init.py +++ b/cloudbaseinit/init.py @@ -17,53 +17,60 @@ from cloudbaseinit.metadata import factory as metadata_factory from cloudbaseinit.openstack.common import log as logging from cloudbaseinit.osutils import factory as osutils_factory +from cloudbaseinit.plugins import base as plugins_base from cloudbaseinit.plugins import factory as plugins_factory LOG = logging.getLogger(__name__) class InitManager(object): - _config_done_key = 'config_done' + _PLUGINS_CONFIG_SECTION = 'Plugins' - def _is_already_configured(self, osutils): - return osutils.get_config_value(self._config_done_key) == 1 + def _get_plugin_status(self, osutils, plugin_name): + return osutils.get_config_value(plugin_name, + self._PLUGINS_CONFIG_SECTION) - def _mark_as_configured(self, osutils): - osutils.set_config_value(self._config_done_key, 1) + def _set_plugin_status(self, osutils, plugin_name, status): + osutils.set_config_value(plugin_name, status, + self._PLUGINS_CONFIG_SECTION) + + def _exec_plugin(self, osutils, service, plugin): + plugin_name = plugin.__class__.__name__ + + status = self._get_plugin_status(osutils, plugin_name) + if status == plugins_base.PLUGIN_EXECUTION_DONE: + LOG.debug('Plugin \'%(plugin_name)s\' execution already done, ' + 'skipping' % locals()) + else: + LOG.info('Executing plugin \'%(plugin_name)s\'' % + locals()) + try: + (status, reboot_required) = plugin.execute(service) + self._set_plugin_status(osutils, plugin_name, status) + return reboot_required + except Exception, ex: + LOG.error('plugin \'%(plugin_name)s\' failed ' + 'with error \'%(ex)s\'' % locals()) def configure_host(self): - osutils = osutils_factory.OSUtilsFactory().get_os_utils() - - if self._is_already_configured(osutils): - LOG.info('Host already configured, skipping configuration') - osutils.terminate() - return - - plugins = plugins_factory.PluginFactory().load_plugins() mdsf = metadata_factory.MetadataServiceFactory() service = mdsf.get_metadata_service() LOG.info('Metadata service loaded: \'%s\'' % service.__class__.__name__) + osutils = osutils_factory.OSUtilsFactory().get_os_utils() osutils.wait_for_boot_completion() + plugins = plugins_factory.PluginFactory().load_plugins() + reboot_required = False try: for plugin in plugins: - plugin_name = plugin.__class__.__name__ - LOG.info('Executing plugin \'%(plugin_name)s\'' % locals()) - try: - plugin_requires_reboot = plugin.execute(service) - if plugin_requires_reboot: - reboot_required = True - except Exception, ex: - LOG.error('plugin \'%(plugin_name)s\' failed ' - 'with error \'%(ex)s\'' % locals()) + if self._exec_plugin(osutils, service, plugin): + reboot_required = True finally: service.cleanup() - self._mark_as_configured(osutils) - if reboot_required: try: osutils.reboot() diff --git a/cloudbaseinit/osutils/base.py b/cloudbaseinit/osutils/base.py index fe9f7645..165309dd 100644 --- a/cloudbaseinit/osutils/base.py +++ b/cloudbaseinit/osutils/base.py @@ -58,10 +58,10 @@ class BaseOSUtils(object): dnsnameservers): pass - def set_config_value(self, name, value): + def set_config_value(self, name, value, section=None): pass - def get_config_value(self, name): + def get_config_value(self, name, section=None): pass def wait_for_boot_completion(self): diff --git a/cloudbaseinit/osutils/windows.py b/cloudbaseinit/osutils/windows.py index 2044f4da..e00803e0 100644 --- a/cloudbaseinit/osutils/windows.py +++ b/cloudbaseinit/osutils/windows.py @@ -263,19 +263,29 @@ class WindowsUtils(base.BaseOSUtils): return reboot_required - def set_config_value(self, name, value): + def _get_config_key_name(self, section): + key_name = self._config_key + if section: + key_name += section + '\\' + return key_name + + def set_config_value(self, name, value, section=None): + key_name = self._get_config_key_name(section) + with _winreg.CreateKey(_winreg.HKEY_LOCAL_MACHINE, - self._config_key) as key: + key_name) as key: if type(value) == int: regtype = _winreg.REG_DWORD else: regtype = _winreg.REG_SZ _winreg.SetValueEx(key, name, 0, regtype, value) - def get_config_value(self, name): + def get_config_value(self, name, section=None): + key_name = self._get_config_key_name(section) + try: with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, - self._config_key) as key: + key_name) as key: (value, regtype) = _winreg.QueryValueEx(key, name) return value except WindowsError: diff --git a/cloudbaseinit/plugins/base.py b/cloudbaseinit/plugins/base.py index dcc7eb65..3e5c03a6 100644 --- a/cloudbaseinit/plugins/base.py +++ b/cloudbaseinit/plugins/base.py @@ -14,6 +14,9 @@ # License for the specific language governing permissions and limitations # under the License. +PLUGIN_EXECUTION_DONE = 1 +PLUGIN_EXECUTE_ON_NEXT_BOOT = 2 + class BasePlugin(object): def execute(self, service): diff --git a/cloudbaseinit/plugins/windows/createuser.py b/cloudbaseinit/plugins/windows/createuser.py index 256749fe..99e5cf95 100644 --- a/cloudbaseinit/plugins/windows/createuser.py +++ b/cloudbaseinit/plugins/windows/createuser.py @@ -137,4 +137,4 @@ class CreateUserPlugin(base.BasePlugin): LOG.exception(ex) LOG.error('Cannot add user to group "%s"' % group_name) - return False + return (base.PLUGIN_EXECUTION_DONE, False) diff --git a/cloudbaseinit/plugins/windows/extendvolumes.py b/cloudbaseinit/plugins/windows/extendvolumes.py index fbb1b7b1..545cbf4b 100644 --- a/cloudbaseinit/plugins/windows/extendvolumes.py +++ b/cloudbaseinit/plugins/windows/extendvolumes.py @@ -166,3 +166,5 @@ class ExtendVolumesPlugin(base.BasePlugin): packs = self._query_packs(provider) for pack in packs: self._extend_volumes(pack, volumes_to_extend) + + return (base.PLUGIN_EXECUTE_ON_NEXT_BOOT, False) diff --git a/cloudbaseinit/plugins/windows/networkconfig.py b/cloudbaseinit/plugins/windows/networkconfig.py index 4c69a06b..250d5296 100644 --- a/cloudbaseinit/plugins/windows/networkconfig.py +++ b/cloudbaseinit/plugins/windows/networkconfig.py @@ -81,4 +81,4 @@ class NetworkConfigPlugin(base.BasePlugin): network_adapter_name, address, netmask, broadcast, gateway, dnsnameservers) - return reboot_required + return (base.PLUGIN_EXECUTION_DONE, reboot_required) diff --git a/cloudbaseinit/plugins/windows/sethostname.py b/cloudbaseinit/plugins/windows/sethostname.py index 92a92c1f..f42e4c07 100644 --- a/cloudbaseinit/plugins/windows/sethostname.py +++ b/cloudbaseinit/plugins/windows/sethostname.py @@ -31,4 +31,6 @@ class SetHostNamePlugin(base.BasePlugin): osutils = osutils_factory.OSUtilsFactory().get_os_utils() new_host_name = meta_data['hostname'].split('.', 1)[0] - return osutils.set_host_name(new_host_name) + reboot_required = osutils.set_host_name(new_host_name) + + return (base.PLUGIN_EXECUTION_DONE, reboot_required) diff --git a/cloudbaseinit/plugins/windows/sshpublickeys.py b/cloudbaseinit/plugins/windows/sshpublickeys.py index 84a4b9b9..58a48810 100644 --- a/cloudbaseinit/plugins/windows/sshpublickeys.py +++ b/cloudbaseinit/plugins/windows/sshpublickeys.py @@ -50,3 +50,5 @@ class SetUserSSHPublicKeysPlugin(base.BasePlugin): public_keys = meta_data['public_keys'] for k in public_keys: f.write(public_keys[k]) + + return (base.PLUGIN_EXECUTION_DONE, False) diff --git a/cloudbaseinit/plugins/windows/userdata.py b/cloudbaseinit/plugins/windows/userdata.py index 595d46bd..5c7ac249 100644 --- a/cloudbaseinit/plugins/windows/userdata.py +++ b/cloudbaseinit/plugins/windows/userdata.py @@ -70,4 +70,4 @@ class UserDataPlugin(base.BasePlugin): if os.path.exists(target_path): os.remove(target_path) - return False + return (base.PLUGIN_EXECUTION_DONE, False) diff --git a/setup.py b/setup.py index d8b212d7..d7f9a70d 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ requires = common_setup.parse_requirements() dependency_links = common_setup.parse_dependency_links() setuptools.setup(name='cloudbase-init', - version='0.9.0', + version='0.9.1', description='Portable cloud initialization service', author='Cloudbase Solutions Srl', author_email='apilotti@cloudbasesolutions.com',