From b4b3f6bb4ec8449f1565919cc51ad5d0bb97579d Mon Sep 17 00:00:00 2001 From: Alessandro Pilotti Date: Sun, 9 Feb 2014 21:41:45 +0200 Subject: [PATCH] Normalize line endings --- .gitattributes | 2 + cloudbaseinit/init.py | 244 +++++++-------- cloudbaseinit/metadata/factory.py | 104 +++---- .../configdrive/windows/disk/virtual_disk.py | 290 +++++++++--------- cloudbaseinit/metadata/services/ec2service.py | 246 +++++++-------- .../metadata/services/httpservice.py | 234 +++++++------- cloudbaseinit/plugins/factory.py | 104 +++---- .../plugins/windows/networkconfig.py | 170 +++++----- cloudbaseinit/plugins/windows/userdata.py | 290 +++++++++--------- 9 files changed, 843 insertions(+), 841 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..4379fcd3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Always use LF +* text=lf diff --git a/cloudbaseinit/init.py b/cloudbaseinit/init.py index c4b5385c..32e62c43 100644 --- a/cloudbaseinit/init.py +++ b/cloudbaseinit/init.py @@ -1,122 +1,122 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 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. - -import sys - -from cloudbaseinit.metadata import factory as metadata_factory -from cloudbaseinit.openstack.common import cfg -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 - -opts = [ - cfg.BoolOpt('allow_reboot', default=True, help='Allows OS reboots ' - 'requested by plugins'), - cfg.BoolOpt('stop_service_on_exit', default=True, help='In case of ' - 'execution as a service, specifies if the service ' - 'must be gracefully stopped before exiting'), -] - -CONF = cfg.CONF -CONF.register_opts(opts) - -LOG = logging.getLogger(__name__) - - -class InitManager(object): - _PLUGINS_CONFIG_SECTION = 'Plugins' - - def _get_plugin_status(self, osutils, plugin_name): - return osutils.get_config_value(plugin_name, - self._PLUGINS_CONFIG_SECTION) - - 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, shared_data): - plugin_name = plugin.get_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, - shared_data) - 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()) - LOG.exception(ex) - - def _check_plugin_os_requirements(self, osutils, plugin): - supported = False - plugin_name = plugin.get_name() - - (required_platform, min_os_version) = plugin.get_os_requirements() - if required_platform and sys.platform != required_platform: - LOG.debug('Skipping plugin: \'%s\'. Platform not supported' % - plugin_name) - else: - if not min_os_version: - supported = True - else: - os_major, os_minor = min_os_version - if osutils.check_os_version(os_major, os_minor): - supported = True - else: - LOG.debug('Skipping plugin: \'%s\'. OS version not ' - 'supported' % plugin_name) - return supported - - def configure_host(self): - osutils = osutils_factory.OSUtilsFactory().get_os_utils() - osutils.wait_for_boot_completion() - - mdsf = metadata_factory.MetadataServiceFactory() - service = mdsf.get_metadata_service() - LOG.info('Metadata service loaded: \'%s\'' % - service.get_name()) - - plugins = plugins_factory.PluginFactory().load_plugins() - - plugins_shared_data = {} - - reboot_required = False - try: - for plugin in plugins: - if self._check_plugin_os_requirements(osutils, plugin): - if self._exec_plugin(osutils, service, plugin, - plugins_shared_data): - reboot_required = True - if CONF.allow_reboot: - break - finally: - service.cleanup() - - if reboot_required and CONF.allow_reboot: - try: - osutils.reboot() - except Exception, ex: - LOG.error('reboot failed with error \'%s\'' % ex) - elif CONF.stop_service_on_exit: - osutils.terminate() +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 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. + +import sys + +from cloudbaseinit.metadata import factory as metadata_factory +from cloudbaseinit.openstack.common import cfg +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 + +opts = [ + cfg.BoolOpt('allow_reboot', default=True, help='Allows OS reboots ' + 'requested by plugins'), + cfg.BoolOpt('stop_service_on_exit', default=True, help='In case of ' + 'execution as a service, specifies if the service ' + 'must be gracefully stopped before exiting'), +] + +CONF = cfg.CONF +CONF.register_opts(opts) + +LOG = logging.getLogger(__name__) + + +class InitManager(object): + _PLUGINS_CONFIG_SECTION = 'Plugins' + + def _get_plugin_status(self, osutils, plugin_name): + return osutils.get_config_value(plugin_name, + self._PLUGINS_CONFIG_SECTION) + + 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, shared_data): + plugin_name = plugin.get_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, + shared_data) + 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()) + LOG.exception(ex) + + def _check_plugin_os_requirements(self, osutils, plugin): + supported = False + plugin_name = plugin.get_name() + + (required_platform, min_os_version) = plugin.get_os_requirements() + if required_platform and sys.platform != required_platform: + LOG.debug('Skipping plugin: \'%s\'. Platform not supported' % + plugin_name) + else: + if not min_os_version: + supported = True + else: + os_major, os_minor = min_os_version + if osutils.check_os_version(os_major, os_minor): + supported = True + else: + LOG.debug('Skipping plugin: \'%s\'. OS version not ' + 'supported' % plugin_name) + return supported + + def configure_host(self): + osutils = osutils_factory.OSUtilsFactory().get_os_utils() + osutils.wait_for_boot_completion() + + mdsf = metadata_factory.MetadataServiceFactory() + service = mdsf.get_metadata_service() + LOG.info('Metadata service loaded: \'%s\'' % + service.get_name()) + + plugins = plugins_factory.PluginFactory().load_plugins() + + plugins_shared_data = {} + + reboot_required = False + try: + for plugin in plugins: + if self._check_plugin_os_requirements(osutils, plugin): + if self._exec_plugin(osutils, service, plugin, + plugins_shared_data): + reboot_required = True + if CONF.allow_reboot: + break + finally: + service.cleanup() + + if reboot_required and CONF.allow_reboot: + try: + osutils.reboot() + except Exception, ex: + LOG.error('reboot failed with error \'%s\'' % ex) + elif CONF.stop_service_on_exit: + osutils.terminate() diff --git a/cloudbaseinit/metadata/factory.py b/cloudbaseinit/metadata/factory.py index 95dd1859..b44a21a3 100644 --- a/cloudbaseinit/metadata/factory.py +++ b/cloudbaseinit/metadata/factory.py @@ -1,52 +1,52 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 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 cfg -from cloudbaseinit.openstack.common import log as logging -from cloudbaseinit.utils import classloader - -opts = [ - cfg.ListOpt('metadata_services', - default=[ - 'cloudbaseinit.metadata.services.httpservice.HttpService', - 'cloudbaseinit.metadata.services.configdrive.configdrive.' - 'ConfigDriveService', - 'cloudbaseinit.metadata.services.ec2service.EC2Service' - ], - help='List of enabled metadata service classes, ' - 'to be tested fro availability in the provided order. ' - 'The first available service will be used to retrieve ' - 'metadata') -] - -CONF = cfg.CONF -CONF.register_opts(opts) -LOG = logging.getLogger(__name__) - - -class MetadataServiceFactory(object): - def get_metadata_service(self): - # Return the first service that loads correctly - cl = classloader.ClassLoader() - for class_path in CONF.metadata_services: - service = cl.load_class(class_path)() - try: - if service.load(): - return service - except Exception, ex: - LOG.error('Failed to load metadata service \'%(class_path)s\'') - LOG.exception(ex) - raise Exception("No available service found") +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 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 cfg +from cloudbaseinit.openstack.common import log as logging +from cloudbaseinit.utils import classloader + +opts = [ + cfg.ListOpt('metadata_services', + default=[ + 'cloudbaseinit.metadata.services.httpservice.HttpService', + 'cloudbaseinit.metadata.services.configdrive.configdrive.' + 'ConfigDriveService', + 'cloudbaseinit.metadata.services.ec2service.EC2Service' + ], + help='List of enabled metadata service classes, ' + 'to be tested fro availability in the provided order. ' + 'The first available service will be used to retrieve ' + 'metadata') +] + +CONF = cfg.CONF +CONF.register_opts(opts) +LOG = logging.getLogger(__name__) + + +class MetadataServiceFactory(object): + def get_metadata_service(self): + # Return the first service that loads correctly + cl = classloader.ClassLoader() + for class_path in CONF.metadata_services: + service = cl.load_class(class_path)() + try: + if service.load(): + return service + except Exception, ex: + LOG.error('Failed to load metadata service \'%(class_path)s\'') + LOG.exception(ex) + raise Exception("No available service found") diff --git a/cloudbaseinit/metadata/services/configdrive/windows/disk/virtual_disk.py b/cloudbaseinit/metadata/services/configdrive/windows/disk/virtual_disk.py index e63ed220..fbb2bae8 100644 --- a/cloudbaseinit/metadata/services/configdrive/windows/disk/virtual_disk.py +++ b/cloudbaseinit/metadata/services/configdrive/windows/disk/virtual_disk.py @@ -1,145 +1,145 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 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. - -import ctypes - -from ctypes import windll -from ctypes import wintypes - -kernel32 = windll.kernel32 -# VirtDisk.dll is available starting from Windows Server 2008 R2 / Windows7 -virtdisk = None - - -class Win32_GUID(ctypes.Structure): - _fields_ = [("Data1", wintypes.DWORD), - ("Data2", wintypes.WORD), - ("Data3", wintypes.WORD), - ("Data4", wintypes.BYTE * 8)] - - -def get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT(): - guid = Win32_GUID() - guid.Data1 = 0xec984aec - guid.Data2 = 0xa0f9 - guid.Data3 = 0x47e9 - ByteArray8 = wintypes.BYTE * 8 - guid.Data4 = ByteArray8(0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b) - return guid - - -class Win32_VIRTUAL_STORAGE_TYPE(ctypes.Structure): - _fields_ = [ - ('DeviceId', wintypes.DWORD), - ('VendorId', Win32_GUID) - ] - - -class VirtualDisk(object): - VIRTUAL_STORAGE_TYPE_DEVICE_ISO = 1 - VIRTUAL_DISK_ACCESS_ATTACH_RO = 0x10000 - VIRTUAL_DISK_ACCESS_READ = 0xd0000 - OPEN_VIRTUAL_DISK_FLAG_NONE = 0 - DETACH_VIRTUAL_DISK_FLAG_NONE = 0 - ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY = 1 - ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER = 2 - - def __init__(self, path): - self._path = path - self._handle = 0 - - def _load_virtdisk_dll(self): - global virtdisk - if not virtdisk: - virtdisk = windll.virtdisk - - def open(self): - if self._handle: - self.close() - - self._load_virtdisk_dll() - - vst = Win32_VIRTUAL_STORAGE_TYPE() - vst.DeviceId = self.VIRTUAL_STORAGE_TYPE_DEVICE_ISO - vst.VendorId = get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT() - - handle = wintypes.HANDLE() - ret_val = virtdisk.OpenVirtualDisk(ctypes.byref(vst), - ctypes.c_wchar_p(self._path), - self.VIRTUAL_DISK_ACCESS_ATTACH_RO | - self.VIRTUAL_DISK_ACCESS_READ, - self.OPEN_VIRTUAL_DISK_FLAG_NONE, 0, - ctypes.byref(handle)) - if ret_val: - raise Exception("Cannot open virtual disk") - self._handle = handle - - def attach(self): - ret_val = virtdisk.AttachVirtualDisk( - self._handle, 0, self.ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY, 0, 0, 0) - if ret_val: - raise Exception("Cannot attach virtual disk") - - def detach(self): - ret_val = virtdisk.DetachVirtualDisk( - self._handle, self.DETACH_VIRTUAL_DISK_FLAG_NONE, 0) - if ret_val: - raise Exception("Cannot detach virtual disk") - - def get_physical_path(self): - buf = ctypes.create_unicode_buffer(1024) - bufLen = wintypes.DWORD(ctypes.sizeof(buf)) - ret_val = virtdisk.GetVirtualDiskPhysicalPath(self._handle, - ctypes.byref(bufLen), - buf) - if ret_val: - raise Exception("Cannot get virtual disk physical path") - return buf.value - - def get_cdrom_drive_mount_point(self): - - mount_point = None - - buf = ctypes.create_unicode_buffer(2048) - buf_len = kernel32.GetLogicalDriveStringsW( - ctypes.sizeof(buf) / ctypes.sizeof(wintypes.WCHAR), buf) - if not buf_len: - raise Exception("Cannot enumerate logical devices") - - cdrom_dev = self.get_physical_path().rsplit('\\')[-1].upper() - - i = 0 - while not mount_point and i < buf_len: - curr_drive = ctypes.wstring_at(ctypes.addressof(buf) + i * - ctypes.sizeof(wintypes.WCHAR))[:-1] - - dev = ctypes.create_unicode_buffer(2048) - ret_val = kernel32.QueryDosDeviceW(curr_drive, dev, - ctypes.sizeof(dev) / - ctypes.sizeof(wintypes.WCHAR)) - if not ret_val: - raise Exception("Cannot query NT device") - - if dev.value.rsplit('\\')[-1].upper() == cdrom_dev: - mount_point = curr_drive - else: - i += len(curr_drive) + 2 - - return mount_point - - def close(self): - kernel32.CloseHandle(self._handle) - self._handle = 0 +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 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. + +import ctypes + +from ctypes import windll +from ctypes import wintypes + +kernel32 = windll.kernel32 +# VirtDisk.dll is available starting from Windows Server 2008 R2 / Windows7 +virtdisk = None + + +class Win32_GUID(ctypes.Structure): + _fields_ = [("Data1", wintypes.DWORD), + ("Data2", wintypes.WORD), + ("Data3", wintypes.WORD), + ("Data4", wintypes.BYTE * 8)] + + +def get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT(): + guid = Win32_GUID() + guid.Data1 = 0xec984aec + guid.Data2 = 0xa0f9 + guid.Data3 = 0x47e9 + ByteArray8 = wintypes.BYTE * 8 + guid.Data4 = ByteArray8(0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b) + return guid + + +class Win32_VIRTUAL_STORAGE_TYPE(ctypes.Structure): + _fields_ = [ + ('DeviceId', wintypes.DWORD), + ('VendorId', Win32_GUID) + ] + + +class VirtualDisk(object): + VIRTUAL_STORAGE_TYPE_DEVICE_ISO = 1 + VIRTUAL_DISK_ACCESS_ATTACH_RO = 0x10000 + VIRTUAL_DISK_ACCESS_READ = 0xd0000 + OPEN_VIRTUAL_DISK_FLAG_NONE = 0 + DETACH_VIRTUAL_DISK_FLAG_NONE = 0 + ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY = 1 + ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER = 2 + + def __init__(self, path): + self._path = path + self._handle = 0 + + def _load_virtdisk_dll(self): + global virtdisk + if not virtdisk: + virtdisk = windll.virtdisk + + def open(self): + if self._handle: + self.close() + + self._load_virtdisk_dll() + + vst = Win32_VIRTUAL_STORAGE_TYPE() + vst.DeviceId = self.VIRTUAL_STORAGE_TYPE_DEVICE_ISO + vst.VendorId = get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT() + + handle = wintypes.HANDLE() + ret_val = virtdisk.OpenVirtualDisk(ctypes.byref(vst), + ctypes.c_wchar_p(self._path), + self.VIRTUAL_DISK_ACCESS_ATTACH_RO | + self.VIRTUAL_DISK_ACCESS_READ, + self.OPEN_VIRTUAL_DISK_FLAG_NONE, 0, + ctypes.byref(handle)) + if ret_val: + raise Exception("Cannot open virtual disk") + self._handle = handle + + def attach(self): + ret_val = virtdisk.AttachVirtualDisk( + self._handle, 0, self.ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY, 0, 0, 0) + if ret_val: + raise Exception("Cannot attach virtual disk") + + def detach(self): + ret_val = virtdisk.DetachVirtualDisk( + self._handle, self.DETACH_VIRTUAL_DISK_FLAG_NONE, 0) + if ret_val: + raise Exception("Cannot detach virtual disk") + + def get_physical_path(self): + buf = ctypes.create_unicode_buffer(1024) + bufLen = wintypes.DWORD(ctypes.sizeof(buf)) + ret_val = virtdisk.GetVirtualDiskPhysicalPath(self._handle, + ctypes.byref(bufLen), + buf) + if ret_val: + raise Exception("Cannot get virtual disk physical path") + return buf.value + + def get_cdrom_drive_mount_point(self): + + mount_point = None + + buf = ctypes.create_unicode_buffer(2048) + buf_len = kernel32.GetLogicalDriveStringsW( + ctypes.sizeof(buf) / ctypes.sizeof(wintypes.WCHAR), buf) + if not buf_len: + raise Exception("Cannot enumerate logical devices") + + cdrom_dev = self.get_physical_path().rsplit('\\')[-1].upper() + + i = 0 + while not mount_point and i < buf_len: + curr_drive = ctypes.wstring_at(ctypes.addressof(buf) + i * + ctypes.sizeof(wintypes.WCHAR))[:-1] + + dev = ctypes.create_unicode_buffer(2048) + ret_val = kernel32.QueryDosDeviceW(curr_drive, dev, + ctypes.sizeof(dev) / + ctypes.sizeof(wintypes.WCHAR)) + if not ret_val: + raise Exception("Cannot query NT device") + + if dev.value.rsplit('\\')[-1].upper() == cdrom_dev: + mount_point = curr_drive + else: + i += len(curr_drive) + 2 + + return mount_point + + def close(self): + kernel32.CloseHandle(self._handle) + self._handle = 0 diff --git a/cloudbaseinit/metadata/services/ec2service.py b/cloudbaseinit/metadata/services/ec2service.py index 3e66ebfe..1a9778b3 100644 --- a/cloudbaseinit/metadata/services/ec2service.py +++ b/cloudbaseinit/metadata/services/ec2service.py @@ -1,123 +1,123 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Mirantis Inc. -# -# 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. - -import posixpath -import urllib2 -import traceback -import os - -from cloudbaseinit.metadata.services import base -from cloudbaseinit.openstack.common import cfg -from cloudbaseinit.openstack.common import log as logging - -opts = [ - cfg.StrOpt('ec2_metadata_base_url', - default='http://169.254.169.254/2009-04-04/', - help='The base URL where the service looks for metadata'), -] - -ec2nodes = [ - 'ami-id', 'ami-launch-index', 'ami-manifest-path', 'ancestor-ami-ids', - 'hostname', 'block-device-mapping', 'kernel-id', - 'placement/availability-zone', 'instance-action', 'instance-id', - 'instance-type', 'product-codes', 'local-hostname', 'local-ipv4', - 'public-hostname', 'public-ipv4', 'ramdisk-id', 'reservation-id', - 'security-groups', 'public-keys/', 'public-keys/0/', - 'public-keys/0/openssh-key', 'admin_pass'] - -CONF = cfg.CONF -CONF.register_opts(opts) - -LOG = logging.getLogger(__name__) - - -class EC2Service(base.BaseMetadataService): - def __init__(self): - super(EC2Service, self).__init__() - self._enable_retry = True - self.error_count = 0 - - def load(self): - super(EC2Service, self).load() - try: - self.get_meta_data('openstack') - return True - except Exception, err: - LOG.debug(err) - LOG.debug(traceback.format_exc()) - LOG.debug('Metadata not found at URL \'%s\'' % - CONF.ec2_metadata_base_url) - return False - - def _get_data(self, path): - data = {} - LOG.debug("Check for EC2 interface availability...") - if not self._check_EC2(): - raise Exception("EC2 interface is not available") - - LOG.debug('Getting data for the path: %s' % path) - if path.endswith('meta_data.json'): - for key in ec2nodes: - LOG.debug('Getting metadata from: %s' % key) - try: - data[key] = self._get_EC2_value(key) - except: - LOG.info("EC2 value %s is not available. Skip it." % key) - # Saving keys to the local folder - self._load_public_keys(data) - - if path.endswith('user_data'): - norm_path = posixpath.join(CONF.ec2_metadata_base_url, 'user-data') - LOG.debug('Getting metadata from: %(norm_path)s' % locals()) - try: - req = urllib2.Request(norm_path) - response = urllib2.urlopen(req) - data = response.read() - LOG.debug("Got data: %s" % data) - except: - LOG.error("EC2 user-data is not available.") - return data - - def _check_EC2(self): - try: - data = self._get_EC2_value('') - return True - except: - return False - - def _get_EC2_value(self, key): - meta_path = posixpath.join( - CONF.ec2_metadata_base_url, 'meta-data', key) - req = urllib2.Request(meta_path) - response = urllib2.urlopen(req) - return response.read() - - def _load_public_keys(self, data): - try: - key_list = self._get_EC2_value('public-keys/') - LOG.debug("Got a list of keys %s" % key_list) - data['public_keys'] = {} - - for key_name in key_list.split('\n'): - key_index = key_name.split('=')[0] - LOG.debug('Loading key %s' % key_index) - key = self._get_EC2_value( - 'public-keys/%s/openssh-key' % key_index) - data['public_keys'].update({key_index: key}) - - except Exception, ex: - LOG.debug("Can't save public key %s" % ex) - LOG.debug(traceback.format_exc()) +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 Mirantis Inc. +# +# 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. + +import posixpath +import urllib2 +import traceback +import os + +from cloudbaseinit.metadata.services import base +from cloudbaseinit.openstack.common import cfg +from cloudbaseinit.openstack.common import log as logging + +opts = [ + cfg.StrOpt('ec2_metadata_base_url', + default='http://169.254.169.254/2009-04-04/', + help='The base URL where the service looks for metadata'), +] + +ec2nodes = [ + 'ami-id', 'ami-launch-index', 'ami-manifest-path', 'ancestor-ami-ids', + 'hostname', 'block-device-mapping', 'kernel-id', + 'placement/availability-zone', 'instance-action', 'instance-id', + 'instance-type', 'product-codes', 'local-hostname', 'local-ipv4', + 'public-hostname', 'public-ipv4', 'ramdisk-id', 'reservation-id', + 'security-groups', 'public-keys/', 'public-keys/0/', + 'public-keys/0/openssh-key', 'admin_pass'] + +CONF = cfg.CONF +CONF.register_opts(opts) + +LOG = logging.getLogger(__name__) + + +class EC2Service(base.BaseMetadataService): + def __init__(self): + super(EC2Service, self).__init__() + self._enable_retry = True + self.error_count = 0 + + def load(self): + super(EC2Service, self).load() + try: + self.get_meta_data('openstack') + return True + except Exception, err: + LOG.debug(err) + LOG.debug(traceback.format_exc()) + LOG.debug('Metadata not found at URL \'%s\'' % + CONF.ec2_metadata_base_url) + return False + + def _get_data(self, path): + data = {} + LOG.debug("Check for EC2 interface availability...") + if not self._check_EC2(): + raise Exception("EC2 interface is not available") + + LOG.debug('Getting data for the path: %s' % path) + if path.endswith('meta_data.json'): + for key in ec2nodes: + LOG.debug('Getting metadata from: %s' % key) + try: + data[key] = self._get_EC2_value(key) + except: + LOG.info("EC2 value %s is not available. Skip it." % key) + # Saving keys to the local folder + self._load_public_keys(data) + + if path.endswith('user_data'): + norm_path = posixpath.join(CONF.ec2_metadata_base_url, 'user-data') + LOG.debug('Getting metadata from: %(norm_path)s' % locals()) + try: + req = urllib2.Request(norm_path) + response = urllib2.urlopen(req) + data = response.read() + LOG.debug("Got data: %s" % data) + except: + LOG.error("EC2 user-data is not available.") + return data + + def _check_EC2(self): + try: + data = self._get_EC2_value('') + return True + except: + return False + + def _get_EC2_value(self, key): + meta_path = posixpath.join( + CONF.ec2_metadata_base_url, 'meta-data', key) + req = urllib2.Request(meta_path) + response = urllib2.urlopen(req) + return response.read() + + def _load_public_keys(self, data): + try: + key_list = self._get_EC2_value('public-keys/') + LOG.debug("Got a list of keys %s" % key_list) + data['public_keys'] = {} + + for key_name in key_list.split('\n'): + key_index = key_name.split('=')[0] + LOG.debug('Loading key %s' % key_index) + key = self._get_EC2_value( + 'public-keys/%s/openssh-key' % key_index) + data['public_keys'].update({key_index: key}) + + except Exception, ex: + LOG.debug("Can't save public key %s" % ex) + LOG.debug(traceback.format_exc()) diff --git a/cloudbaseinit/metadata/services/httpservice.py b/cloudbaseinit/metadata/services/httpservice.py index de7781ca..d56e90a8 100644 --- a/cloudbaseinit/metadata/services/httpservice.py +++ b/cloudbaseinit/metadata/services/httpservice.py @@ -1,117 +1,117 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 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. - -import posixpath -import urllib2 -import urlparse - -from cloudbaseinit.metadata.services import base -from cloudbaseinit.openstack.common import cfg -from cloudbaseinit.openstack.common import log as logging -from cloudbaseinit.osutils import factory as osutils_factory - -opts = [ - cfg.StrOpt('metadata_base_url', default='http://169.254.169.254/', - help='The base URL where the service looks for metadata'), -] - -CONF = cfg.CONF -CONF.register_opts(opts) - -LOG = logging.getLogger(__name__) - - -class HttpService(base.BaseMetadataService): - def __init__(self): - super(HttpService, self).__init__() - self._enable_retry = True - - def _check_metadata_ip_route(self): - ''' - Workaround for: https://bugs.launchpad.net/quantum/+bug/1174657 - ''' - osutils = osutils_factory.OSUtilsFactory().get_os_utils() - - if osutils.check_os_version(6, 0): - # 169.254.x.x addresses are not getting routed starting from - # Windows Vista / 2008 - metadata_netloc = urlparse.urlparse(CONF.metadata_base_url).netloc - metadata_host = metadata_netloc.split(':')[0] - - if metadata_host.startswith("169.254."): - if not osutils.check_static_route_exists(metadata_host): - (interface_index, gateway) = osutils.get_default_gateway() - if gateway: - try: - osutils.add_static_route(metadata_host, - "255.255.255.255", - gateway, - interface_index, - 10) - except Exception, ex: - # Ignore it - LOG.exception(ex) - - def load(self): - super(HttpService, self).load() - - self._check_metadata_ip_route() - - try: - self.get_meta_data('openstack') - return True - except: - LOG.debug('Metadata not found at URL \'%s\'' % - CONF.metadata_base_url) - return False - - @property - def can_post_password(self): - return True - - def _get_response(self, req): - try: - return urllib2.urlopen(req) - except urllib2.HTTPError as ex: - if ex.code == 404: - raise base.NotExistingMetadataException() - else: - raise - - def _get_data(self, path): - norm_path = posixpath.join(CONF.metadata_base_url, path) - LOG.debug('Getting metadata from: %(norm_path)s' % locals()) - req = urllib2.Request(norm_path) - response = self._get_response(req) - return response.read() - - def _post_data(self, path, data): - norm_path = posixpath.join(CONF.metadata_base_url, path) - LOG.debug('Posting metadata to: %(norm_path)s' % locals()) - req = urllib2.Request(norm_path, data=data) - self._get_response(req) - return True - - def post_password(self, enc_password_b64, version='latest'): - try: - return super(HttpService, self).post_password(enc_password_b64, - version) - except urllib2.HTTPError as ex: - if ex.code == 409: - # Password already set - return False - else: - raise +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 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. + +import posixpath +import urllib2 +import urlparse + +from cloudbaseinit.metadata.services import base +from cloudbaseinit.openstack.common import cfg +from cloudbaseinit.openstack.common import log as logging +from cloudbaseinit.osutils import factory as osutils_factory + +opts = [ + cfg.StrOpt('metadata_base_url', default='http://169.254.169.254/', + help='The base URL where the service looks for metadata'), +] + +CONF = cfg.CONF +CONF.register_opts(opts) + +LOG = logging.getLogger(__name__) + + +class HttpService(base.BaseMetadataService): + def __init__(self): + super(HttpService, self).__init__() + self._enable_retry = True + + def _check_metadata_ip_route(self): + ''' + Workaround for: https://bugs.launchpad.net/quantum/+bug/1174657 + ''' + osutils = osutils_factory.OSUtilsFactory().get_os_utils() + + if osutils.check_os_version(6, 0): + # 169.254.x.x addresses are not getting routed starting from + # Windows Vista / 2008 + metadata_netloc = urlparse.urlparse(CONF.metadata_base_url).netloc + metadata_host = metadata_netloc.split(':')[0] + + if metadata_host.startswith("169.254."): + if not osutils.check_static_route_exists(metadata_host): + (interface_index, gateway) = osutils.get_default_gateway() + if gateway: + try: + osutils.add_static_route(metadata_host, + "255.255.255.255", + gateway, + interface_index, + 10) + except Exception, ex: + # Ignore it + LOG.exception(ex) + + def load(self): + super(HttpService, self).load() + + self._check_metadata_ip_route() + + try: + self.get_meta_data('openstack') + return True + except: + LOG.debug('Metadata not found at URL \'%s\'' % + CONF.metadata_base_url) + return False + + @property + def can_post_password(self): + return True + + def _get_response(self, req): + try: + return urllib2.urlopen(req) + except urllib2.HTTPError as ex: + if ex.code == 404: + raise base.NotExistingMetadataException() + else: + raise + + def _get_data(self, path): + norm_path = posixpath.join(CONF.metadata_base_url, path) + LOG.debug('Getting metadata from: %(norm_path)s' % locals()) + req = urllib2.Request(norm_path) + response = self._get_response(req) + return response.read() + + def _post_data(self, path, data): + norm_path = posixpath.join(CONF.metadata_base_url, path) + LOG.debug('Posting metadata to: %(norm_path)s' % locals()) + req = urllib2.Request(norm_path, data=data) + self._get_response(req) + return True + + def post_password(self, enc_password_b64, version='latest'): + try: + return super(HttpService, self).post_password(enc_password_b64, + version) + except urllib2.HTTPError as ex: + if ex.code == 409: + # Password already set + return False + else: + raise diff --git a/cloudbaseinit/plugins/factory.py b/cloudbaseinit/plugins/factory.py index 019d9a33..8b60442f 100644 --- a/cloudbaseinit/plugins/factory.py +++ b/cloudbaseinit/plugins/factory.py @@ -1,52 +1,52 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 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 cfg -from cloudbaseinit.utils import classloader - -opts = [ - cfg.ListOpt( - 'plugins', - default=[ - 'cloudbaseinit.plugins.windows.sethostname.SetHostNamePlugin', - 'cloudbaseinit.plugins.windows.createuser.CreateUserPlugin', - 'cloudbaseinit.plugins.windows.networkconfig.NetworkConfigPlugin', - 'cloudbaseinit.plugins.windows.sshpublickeys.' - 'SetUserSSHPublicKeysPlugin', - 'cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin', - 'cloudbaseinit.plugins.windows.userdata.UserDataPlugin', - 'cloudbaseinit.plugins.windows.setuserpassword.' - 'SetUserPasswordPlugin', - 'cloudbaseinit.plugins.windows.winrmlistener.' - 'ConfigWinRMListenerPlugin', - 'cloudbaseinit.plugins.windows.winrmcertificateauth.' - 'ConfigWinRMCertificateAuthPlugin', - ], - help='List of enabled plugin classes, ' - 'to executed in the provided order'), -] - -CONF = cfg.CONF -CONF.register_opts(opts) - - -class PluginFactory(object): - def load_plugins(self): - plugins = [] - cl = classloader.ClassLoader() - for class_path in CONF.plugins: - plugins.append(cl.load_class(class_path)()) - return plugins +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 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 cfg +from cloudbaseinit.utils import classloader + +opts = [ + cfg.ListOpt( + 'plugins', + default=[ + 'cloudbaseinit.plugins.windows.sethostname.SetHostNamePlugin', + 'cloudbaseinit.plugins.windows.createuser.CreateUserPlugin', + 'cloudbaseinit.plugins.windows.networkconfig.NetworkConfigPlugin', + 'cloudbaseinit.plugins.windows.sshpublickeys.' + 'SetUserSSHPublicKeysPlugin', + 'cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin', + 'cloudbaseinit.plugins.windows.userdata.UserDataPlugin', + 'cloudbaseinit.plugins.windows.setuserpassword.' + 'SetUserPasswordPlugin', + 'cloudbaseinit.plugins.windows.winrmlistener.' + 'ConfigWinRMListenerPlugin', + 'cloudbaseinit.plugins.windows.winrmcertificateauth.' + 'ConfigWinRMCertificateAuthPlugin', + ], + help='List of enabled plugin classes, ' + 'to executed in the provided order'), +] + +CONF = cfg.CONF +CONF.register_opts(opts) + + +class PluginFactory(object): + def load_plugins(self): + plugins = [] + cl = classloader.ClassLoader() + for class_path in CONF.plugins: + plugins.append(cl.load_class(class_path)()) + return plugins diff --git a/cloudbaseinit/plugins/windows/networkconfig.py b/cloudbaseinit/plugins/windows/networkconfig.py index 7849b0f0..b67edb8d 100644 --- a/cloudbaseinit/plugins/windows/networkconfig.py +++ b/cloudbaseinit/plugins/windows/networkconfig.py @@ -1,85 +1,85 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 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. - -import re - -from cloudbaseinit.openstack.common import cfg -from cloudbaseinit.openstack.common import log as logging -from cloudbaseinit.osutils import factory as osutils_factory -from cloudbaseinit.plugins import base - -LOG = logging.getLogger(__name__) - -opts = [ - cfg.StrOpt('network_adapter', default=None, help='Network adapter to ' - 'configure. If not specified, the first available ethernet ' - 'adapter will be chosen'), -] - -CONF = cfg.CONF -CONF.register_opts(opts) - - -class NetworkConfigPlugin(base.BasePlugin): - def execute(self, service, shared_data): - meta_data = service.get_meta_data('openstack') - if 'network_config' not in meta_data: - return (base.PLUGIN_EXECUTION_DONE, False) - - network_config = meta_data['network_config'] - if 'content_path' not in network_config: - return (base.PLUGIN_EXECUTION_DONE, False) - - content_path = network_config['content_path'] - content_name = content_path.rsplit('/', 1)[-1] - debian_network_conf = service.get_content('openstack', content_name) - - LOG.debug('network config content:\n%s' % debian_network_conf) - - # TODO (alexpilotti): implement a proper grammar - m = re.search(r'iface eth0 inet static\s+' - r'address\s+(?P
[^\s]+)\s+' - r'netmask\s+(?P[^\s]+)\s+' - r'broadcast\s+(?P[^\s]+)\s+' - r'gateway\s+(?P[^\s]+)\s+' - r'dns\-nameservers\s+(?P[^\r\n]+)\s+', - debian_network_conf) - if not m: - raise Exception("network_config format not recognized") - - address = m.group('address') - netmask = m.group('netmask') - broadcast = m.group('broadcast') - gateway = m.group('gateway') - dnsnameservers = m.group('dnsnameservers').strip().split(' ') - - osutils = osutils_factory.OSUtilsFactory().get_os_utils() - - network_adapter_name = CONF.network_adapter - if not network_adapter_name: - # Get the first available one - available_adapters = osutils.get_network_adapters() - if not len(available_adapters): - raise Exception("No network adapter available") - network_adapter_name = available_adapters[0] - - LOG.info('Configuring network adapter: \'%s\'' % network_adapter_name) - - reboot_required = osutils.set_static_network_config( - network_adapter_name, address, netmask, broadcast, - gateway, dnsnameservers) - - return (base.PLUGIN_EXECUTION_DONE, reboot_required) +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 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. + +import re + +from cloudbaseinit.openstack.common import cfg +from cloudbaseinit.openstack.common import log as logging +from cloudbaseinit.osutils import factory as osutils_factory +from cloudbaseinit.plugins import base + +LOG = logging.getLogger(__name__) + +opts = [ + cfg.StrOpt('network_adapter', default=None, help='Network adapter to ' + 'configure. If not specified, the first available ethernet ' + 'adapter will be chosen'), +] + +CONF = cfg.CONF +CONF.register_opts(opts) + + +class NetworkConfigPlugin(base.BasePlugin): + def execute(self, service, shared_data): + meta_data = service.get_meta_data('openstack') + if 'network_config' not in meta_data: + return (base.PLUGIN_EXECUTION_DONE, False) + + network_config = meta_data['network_config'] + if 'content_path' not in network_config: + return (base.PLUGIN_EXECUTION_DONE, False) + + content_path = network_config['content_path'] + content_name = content_path.rsplit('/', 1)[-1] + debian_network_conf = service.get_content('openstack', content_name) + + LOG.debug('network config content:\n%s' % debian_network_conf) + + # TODO (alexpilotti): implement a proper grammar + m = re.search(r'iface eth0 inet static\s+' + r'address\s+(?P
[^\s]+)\s+' + r'netmask\s+(?P[^\s]+)\s+' + r'broadcast\s+(?P[^\s]+)\s+' + r'gateway\s+(?P[^\s]+)\s+' + r'dns\-nameservers\s+(?P[^\r\n]+)\s+', + debian_network_conf) + if not m: + raise Exception("network_config format not recognized") + + address = m.group('address') + netmask = m.group('netmask') + broadcast = m.group('broadcast') + gateway = m.group('gateway') + dnsnameservers = m.group('dnsnameservers').strip().split(' ') + + osutils = osutils_factory.OSUtilsFactory().get_os_utils() + + network_adapter_name = CONF.network_adapter + if not network_adapter_name: + # Get the first available one + available_adapters = osutils.get_network_adapters() + if not len(available_adapters): + raise Exception("No network adapter available") + network_adapter_name = available_adapters[0] + + LOG.info('Configuring network adapter: \'%s\'' % network_adapter_name) + + reboot_required = osutils.set_static_network_config( + network_adapter_name, address, netmask, broadcast, + gateway, dnsnameservers) + + return (base.PLUGIN_EXECUTION_DONE, reboot_required) diff --git a/cloudbaseinit/plugins/windows/userdata.py b/cloudbaseinit/plugins/windows/userdata.py index 9088f1fd..3a60a09b 100644 --- a/cloudbaseinit/plugins/windows/userdata.py +++ b/cloudbaseinit/plugins/windows/userdata.py @@ -1,145 +1,145 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 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. - -import email - -from cloudbaseinit.metadata.services import base as metadata_services_base -from cloudbaseinit.openstack.common import log as logging -from cloudbaseinit.plugins import base -from cloudbaseinit.plugins.windows import userdatautils -from cloudbaseinit.plugins.windows.userdataplugins import factory - -LOG = logging.getLogger(__name__) - - -class UserDataPlugin(base.BasePlugin): - _part_handler_content_type = "text/part-handler" - - def execute(self, service, shared_data): - try: - user_data = service.get_user_data('openstack') - except metadata_services_base.NotExistingMetadataException: - return (base.PLUGIN_EXECUTION_DONE, False) - - if not user_data: - return (base.PLUGIN_EXECUTION_DONE, False) - - return self._process_user_data(user_data) - - def _parse_mime(self, user_data): - return email.message_from_string(user_data).walk() - - def _process_user_data(self, user_data): - plugin_status = base.PLUGIN_EXECUTION_DONE - reboot = False - - LOG.debug('User data content:\n%s' % user_data) - if user_data.startswith('Content-Type: multipart'): - user_data_plugins_factory = factory.UserDataPluginsFactory() - user_data_plugins = user_data_plugins_factory.load_plugins() - user_handlers = {} - - for part in self._parse_mime(user_data): - (plugin_status, reboot) = self._process_part(part, - user_data_plugins, - user_handlers) - if reboot: - break - - if not reboot: - for handler_func in list(set(user_handlers.values())): - self._end_part_process_event(handler_func) - - return (plugin_status, reboot) - else: - return self._process_non_multi_part(user_data) - - def _process_part(self, part, user_data_plugins, user_handlers): - ret_val = None - try: - content_type = part.get_content_type() - - handler_func = user_handlers.get(content_type) - if handler_func: - LOG.debug("Calling user part handler for content type: %s" % - content_type) - handler_func(None, content_type, part.get_filename(), - 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: - LOG.debug("Executing userdata plugin: %s" % - user_data_plugin.__class__.__name__) - - if content_type == self._part_handler_content_type: - new_user_handlers = user_data_plugin.process(part) - self._add_part_handlers(user_data_plugins, - user_handlers, - new_user_handlers) - else: - ret_val = user_data_plugin.process(part) - except Exception, ex: - LOG.error('Exception during multipart part handling: ' - '%(content_type)s, %(filename)s' % - {'content_type': part.get_content_type(), - 'filename': part.get_filename()}) - LOG.exception(ex) - - return self._get_plugin_return_value(ret_val) - - def _add_part_handlers(self, user_data_plugins, user_handlers, - new_user_handlers): - handler_funcs = set() - - for (content_type, - handler_func) in new_user_handlers.items(): - if not user_data_plugins.get(content_type): - 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): - plugin_status = base.PLUGIN_EXECUTION_DONE - reboot = False - - if ret_val >= 1001 and ret_val <= 1003: - reboot = bool(ret_val & 1) - if ret_val & 2: - plugin_status = base.PLUGIN_EXECUTE_ON_NEXT_BOOT - - return (plugin_status, reboot) - - def _process_non_multi_part(self, user_data): - ret_val = userdatautils.execute_user_data_script(user_data) - return self._get_plugin_return_value(ret_val) +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 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. + +import email + +from cloudbaseinit.metadata.services import base as metadata_services_base +from cloudbaseinit.openstack.common import log as logging +from cloudbaseinit.plugins import base +from cloudbaseinit.plugins.windows import userdatautils +from cloudbaseinit.plugins.windows.userdataplugins import factory + +LOG = logging.getLogger(__name__) + + +class UserDataPlugin(base.BasePlugin): + _part_handler_content_type = "text/part-handler" + + def execute(self, service, shared_data): + try: + user_data = service.get_user_data('openstack') + except metadata_services_base.NotExistingMetadataException: + return (base.PLUGIN_EXECUTION_DONE, False) + + if not user_data: + return (base.PLUGIN_EXECUTION_DONE, False) + + return self._process_user_data(user_data) + + def _parse_mime(self, user_data): + return email.message_from_string(user_data).walk() + + def _process_user_data(self, user_data): + plugin_status = base.PLUGIN_EXECUTION_DONE + reboot = False + + LOG.debug('User data content:\n%s' % user_data) + if user_data.startswith('Content-Type: multipart'): + user_data_plugins_factory = factory.UserDataPluginsFactory() + user_data_plugins = user_data_plugins_factory.load_plugins() + user_handlers = {} + + for part in self._parse_mime(user_data): + (plugin_status, reboot) = self._process_part(part, + user_data_plugins, + user_handlers) + if reboot: + break + + if not reboot: + for handler_func in list(set(user_handlers.values())): + self._end_part_process_event(handler_func) + + return (plugin_status, reboot) + else: + return self._process_non_multi_part(user_data) + + def _process_part(self, part, user_data_plugins, user_handlers): + ret_val = None + try: + content_type = part.get_content_type() + + handler_func = user_handlers.get(content_type) + if handler_func: + LOG.debug("Calling user part handler for content type: %s" % + content_type) + handler_func(None, content_type, part.get_filename(), + 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: + LOG.debug("Executing userdata plugin: %s" % + user_data_plugin.__class__.__name__) + + if content_type == self._part_handler_content_type: + new_user_handlers = user_data_plugin.process(part) + self._add_part_handlers(user_data_plugins, + user_handlers, + new_user_handlers) + else: + ret_val = user_data_plugin.process(part) + except Exception, ex: + LOG.error('Exception during multipart part handling: ' + '%(content_type)s, %(filename)s' % + {'content_type': part.get_content_type(), + 'filename': part.get_filename()}) + LOG.exception(ex) + + return self._get_plugin_return_value(ret_val) + + def _add_part_handlers(self, user_data_plugins, user_handlers, + new_user_handlers): + handler_funcs = set() + + for (content_type, + handler_func) in new_user_handlers.items(): + if not user_data_plugins.get(content_type): + 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): + plugin_status = base.PLUGIN_EXECUTION_DONE + reboot = False + + if ret_val >= 1001 and ret_val <= 1003: + reboot = bool(ret_val & 1) + if ret_val & 2: + plugin_status = base.PLUGIN_EXECUTE_ON_NEXT_BOOT + + return (plugin_status, reboot) + + def _process_non_multi_part(self, user_data): + ret_val = userdatautils.execute_user_data_script(user_data) + return self._get_plugin_return_value(ret_val)