Individual plugin execution completion
Each plugin can now determine if it needs to be executed during the next boot. Execution completion is now saved for each plugin upon completion. As a result, in case of an exception during the execution of a plugin, the plugin will be executed again during the next boot.
This commit is contained in:
parent
0644611d84
commit
9a4d0de82e
@ -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()
|
||||
|
@ -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):
|
||||
|
@ -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:
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
2
setup.py
2
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',
|
||||
|
Loading…
x
Reference in New Issue
Block a user