Normalize line endings

This commit is contained in:
Alessandro Pilotti 2014-02-09 21:41:45 +02:00
parent 9ef84f6bd8
commit b4b3f6bb4e
9 changed files with 843 additions and 841 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Always use LF
* text=lf

View File

@ -1,122 +1,122 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Cloudbase Solutions Srl # Copyright 2012 Cloudbase Solutions Srl
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # 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 # not use this file except in compliance with the License. You may obtain
# a copy of the License at # a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import sys import sys
from cloudbaseinit.metadata import factory as metadata_factory from cloudbaseinit.metadata import factory as metadata_factory
from cloudbaseinit.openstack.common import cfg from cloudbaseinit.openstack.common import cfg
from cloudbaseinit.openstack.common import log as logging from cloudbaseinit.openstack.common import log as logging
from cloudbaseinit.osutils import factory as osutils_factory from cloudbaseinit.osutils import factory as osutils_factory
from cloudbaseinit.plugins import base as plugins_base from cloudbaseinit.plugins import base as plugins_base
from cloudbaseinit.plugins import factory as plugins_factory from cloudbaseinit.plugins import factory as plugins_factory
opts = [ opts = [
cfg.BoolOpt('allow_reboot', default=True, help='Allows OS reboots ' cfg.BoolOpt('allow_reboot', default=True, help='Allows OS reboots '
'requested by plugins'), 'requested by plugins'),
cfg.BoolOpt('stop_service_on_exit', default=True, help='In case of ' cfg.BoolOpt('stop_service_on_exit', default=True, help='In case of '
'execution as a service, specifies if the service ' 'execution as a service, specifies if the service '
'must be gracefully stopped before exiting'), 'must be gracefully stopped before exiting'),
] ]
CONF = cfg.CONF CONF = cfg.CONF
CONF.register_opts(opts) CONF.register_opts(opts)
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
class InitManager(object): class InitManager(object):
_PLUGINS_CONFIG_SECTION = 'Plugins' _PLUGINS_CONFIG_SECTION = 'Plugins'
def _get_plugin_status(self, osutils, plugin_name): def _get_plugin_status(self, osutils, plugin_name):
return osutils.get_config_value(plugin_name, return osutils.get_config_value(plugin_name,
self._PLUGINS_CONFIG_SECTION) self._PLUGINS_CONFIG_SECTION)
def _set_plugin_status(self, osutils, plugin_name, status): def _set_plugin_status(self, osutils, plugin_name, status):
osutils.set_config_value(plugin_name, status, osutils.set_config_value(plugin_name, status,
self._PLUGINS_CONFIG_SECTION) self._PLUGINS_CONFIG_SECTION)
def _exec_plugin(self, osutils, service, plugin, shared_data): def _exec_plugin(self, osutils, service, plugin, shared_data):
plugin_name = plugin.get_name() plugin_name = plugin.get_name()
status = self._get_plugin_status(osutils, plugin_name) status = self._get_plugin_status(osutils, plugin_name)
if status == plugins_base.PLUGIN_EXECUTION_DONE: if status == plugins_base.PLUGIN_EXECUTION_DONE:
LOG.debug('Plugin \'%(plugin_name)s\' execution already done, ' LOG.debug('Plugin \'%(plugin_name)s\' execution already done, '
'skipping' % locals()) 'skipping' % locals())
else: else:
LOG.info('Executing plugin \'%(plugin_name)s\'' % LOG.info('Executing plugin \'%(plugin_name)s\'' %
locals()) locals())
try: try:
(status, reboot_required) = plugin.execute(service, (status, reboot_required) = plugin.execute(service,
shared_data) shared_data)
self._set_plugin_status(osutils, plugin_name, status) self._set_plugin_status(osutils, plugin_name, status)
return reboot_required return reboot_required
except Exception, ex: except Exception, ex:
LOG.error('plugin \'%(plugin_name)s\' failed ' LOG.error('plugin \'%(plugin_name)s\' failed '
'with error \'%(ex)s\'' % locals()) 'with error \'%(ex)s\'' % locals())
LOG.exception(ex) LOG.exception(ex)
def _check_plugin_os_requirements(self, osutils, plugin): def _check_plugin_os_requirements(self, osutils, plugin):
supported = False supported = False
plugin_name = plugin.get_name() plugin_name = plugin.get_name()
(required_platform, min_os_version) = plugin.get_os_requirements() (required_platform, min_os_version) = plugin.get_os_requirements()
if required_platform and sys.platform != required_platform: if required_platform and sys.platform != required_platform:
LOG.debug('Skipping plugin: \'%s\'. Platform not supported' % LOG.debug('Skipping plugin: \'%s\'. Platform not supported' %
plugin_name) plugin_name)
else: else:
if not min_os_version: if not min_os_version:
supported = True supported = True
else: else:
os_major, os_minor = min_os_version os_major, os_minor = min_os_version
if osutils.check_os_version(os_major, os_minor): if osutils.check_os_version(os_major, os_minor):
supported = True supported = True
else: else:
LOG.debug('Skipping plugin: \'%s\'. OS version not ' LOG.debug('Skipping plugin: \'%s\'. OS version not '
'supported' % plugin_name) 'supported' % plugin_name)
return supported return supported
def configure_host(self): def configure_host(self):
osutils = osutils_factory.OSUtilsFactory().get_os_utils() osutils = osutils_factory.OSUtilsFactory().get_os_utils()
osutils.wait_for_boot_completion() osutils.wait_for_boot_completion()
mdsf = metadata_factory.MetadataServiceFactory() mdsf = metadata_factory.MetadataServiceFactory()
service = mdsf.get_metadata_service() service = mdsf.get_metadata_service()
LOG.info('Metadata service loaded: \'%s\'' % LOG.info('Metadata service loaded: \'%s\'' %
service.get_name()) service.get_name())
plugins = plugins_factory.PluginFactory().load_plugins() plugins = plugins_factory.PluginFactory().load_plugins()
plugins_shared_data = {} plugins_shared_data = {}
reboot_required = False reboot_required = False
try: try:
for plugin in plugins: for plugin in plugins:
if self._check_plugin_os_requirements(osutils, plugin): if self._check_plugin_os_requirements(osutils, plugin):
if self._exec_plugin(osutils, service, plugin, if self._exec_plugin(osutils, service, plugin,
plugins_shared_data): plugins_shared_data):
reboot_required = True reboot_required = True
if CONF.allow_reboot: if CONF.allow_reboot:
break break
finally: finally:
service.cleanup() service.cleanup()
if reboot_required and CONF.allow_reboot: if reboot_required and CONF.allow_reboot:
try: try:
osutils.reboot() osutils.reboot()
except Exception, ex: except Exception, ex:
LOG.error('reboot failed with error \'%s\'' % ex) LOG.error('reboot failed with error \'%s\'' % ex)
elif CONF.stop_service_on_exit: elif CONF.stop_service_on_exit:
osutils.terminate() osutils.terminate()

View File

@ -1,52 +1,52 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Cloudbase Solutions Srl # Copyright 2012 Cloudbase Solutions Srl
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # 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 # not use this file except in compliance with the License. You may obtain
# a copy of the License at # a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from cloudbaseinit.openstack.common import cfg from cloudbaseinit.openstack.common import cfg
from cloudbaseinit.openstack.common import log as logging from cloudbaseinit.openstack.common import log as logging
from cloudbaseinit.utils import classloader from cloudbaseinit.utils import classloader
opts = [ opts = [
cfg.ListOpt('metadata_services', cfg.ListOpt('metadata_services',
default=[ default=[
'cloudbaseinit.metadata.services.httpservice.HttpService', 'cloudbaseinit.metadata.services.httpservice.HttpService',
'cloudbaseinit.metadata.services.configdrive.configdrive.' 'cloudbaseinit.metadata.services.configdrive.configdrive.'
'ConfigDriveService', 'ConfigDriveService',
'cloudbaseinit.metadata.services.ec2service.EC2Service' 'cloudbaseinit.metadata.services.ec2service.EC2Service'
], ],
help='List of enabled metadata service classes, ' help='List of enabled metadata service classes, '
'to be tested fro availability in the provided order. ' 'to be tested fro availability in the provided order. '
'The first available service will be used to retrieve ' 'The first available service will be used to retrieve '
'metadata') 'metadata')
] ]
CONF = cfg.CONF CONF = cfg.CONF
CONF.register_opts(opts) CONF.register_opts(opts)
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
class MetadataServiceFactory(object): class MetadataServiceFactory(object):
def get_metadata_service(self): def get_metadata_service(self):
# Return the first service that loads correctly # Return the first service that loads correctly
cl = classloader.ClassLoader() cl = classloader.ClassLoader()
for class_path in CONF.metadata_services: for class_path in CONF.metadata_services:
service = cl.load_class(class_path)() service = cl.load_class(class_path)()
try: try:
if service.load(): if service.load():
return service return service
except Exception, ex: except Exception, ex:
LOG.error('Failed to load metadata service \'%(class_path)s\'') LOG.error('Failed to load metadata service \'%(class_path)s\'')
LOG.exception(ex) LOG.exception(ex)
raise Exception("No available service found") raise Exception("No available service found")

View File

@ -1,145 +1,145 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Cloudbase Solutions Srl # Copyright 2012 Cloudbase Solutions Srl
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # 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 # not use this file except in compliance with the License. You may obtain
# a copy of the License at # a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import ctypes import ctypes
from ctypes import windll from ctypes import windll
from ctypes import wintypes from ctypes import wintypes
kernel32 = windll.kernel32 kernel32 = windll.kernel32
# VirtDisk.dll is available starting from Windows Server 2008 R2 / Windows7 # VirtDisk.dll is available starting from Windows Server 2008 R2 / Windows7
virtdisk = None virtdisk = None
class Win32_GUID(ctypes.Structure): class Win32_GUID(ctypes.Structure):
_fields_ = [("Data1", wintypes.DWORD), _fields_ = [("Data1", wintypes.DWORD),
("Data2", wintypes.WORD), ("Data2", wintypes.WORD),
("Data3", wintypes.WORD), ("Data3", wintypes.WORD),
("Data4", wintypes.BYTE * 8)] ("Data4", wintypes.BYTE * 8)]
def get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT(): def get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT():
guid = Win32_GUID() guid = Win32_GUID()
guid.Data1 = 0xec984aec guid.Data1 = 0xec984aec
guid.Data2 = 0xa0f9 guid.Data2 = 0xa0f9
guid.Data3 = 0x47e9 guid.Data3 = 0x47e9
ByteArray8 = wintypes.BYTE * 8 ByteArray8 = wintypes.BYTE * 8
guid.Data4 = ByteArray8(0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b) guid.Data4 = ByteArray8(0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b)
return guid return guid
class Win32_VIRTUAL_STORAGE_TYPE(ctypes.Structure): class Win32_VIRTUAL_STORAGE_TYPE(ctypes.Structure):
_fields_ = [ _fields_ = [
('DeviceId', wintypes.DWORD), ('DeviceId', wintypes.DWORD),
('VendorId', Win32_GUID) ('VendorId', Win32_GUID)
] ]
class VirtualDisk(object): class VirtualDisk(object):
VIRTUAL_STORAGE_TYPE_DEVICE_ISO = 1 VIRTUAL_STORAGE_TYPE_DEVICE_ISO = 1
VIRTUAL_DISK_ACCESS_ATTACH_RO = 0x10000 VIRTUAL_DISK_ACCESS_ATTACH_RO = 0x10000
VIRTUAL_DISK_ACCESS_READ = 0xd0000 VIRTUAL_DISK_ACCESS_READ = 0xd0000
OPEN_VIRTUAL_DISK_FLAG_NONE = 0 OPEN_VIRTUAL_DISK_FLAG_NONE = 0
DETACH_VIRTUAL_DISK_FLAG_NONE = 0 DETACH_VIRTUAL_DISK_FLAG_NONE = 0
ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY = 1 ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY = 1
ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER = 2 ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER = 2
def __init__(self, path): def __init__(self, path):
self._path = path self._path = path
self._handle = 0 self._handle = 0
def _load_virtdisk_dll(self): def _load_virtdisk_dll(self):
global virtdisk global virtdisk
if not virtdisk: if not virtdisk:
virtdisk = windll.virtdisk virtdisk = windll.virtdisk
def open(self): def open(self):
if self._handle: if self._handle:
self.close() self.close()
self._load_virtdisk_dll() self._load_virtdisk_dll()
vst = Win32_VIRTUAL_STORAGE_TYPE() vst = Win32_VIRTUAL_STORAGE_TYPE()
vst.DeviceId = self.VIRTUAL_STORAGE_TYPE_DEVICE_ISO vst.DeviceId = self.VIRTUAL_STORAGE_TYPE_DEVICE_ISO
vst.VendorId = get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT() vst.VendorId = get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT()
handle = wintypes.HANDLE() handle = wintypes.HANDLE()
ret_val = virtdisk.OpenVirtualDisk(ctypes.byref(vst), ret_val = virtdisk.OpenVirtualDisk(ctypes.byref(vst),
ctypes.c_wchar_p(self._path), ctypes.c_wchar_p(self._path),
self.VIRTUAL_DISK_ACCESS_ATTACH_RO | self.VIRTUAL_DISK_ACCESS_ATTACH_RO |
self.VIRTUAL_DISK_ACCESS_READ, self.VIRTUAL_DISK_ACCESS_READ,
self.OPEN_VIRTUAL_DISK_FLAG_NONE, 0, self.OPEN_VIRTUAL_DISK_FLAG_NONE, 0,
ctypes.byref(handle)) ctypes.byref(handle))
if ret_val: if ret_val:
raise Exception("Cannot open virtual disk") raise Exception("Cannot open virtual disk")
self._handle = handle self._handle = handle
def attach(self): def attach(self):
ret_val = virtdisk.AttachVirtualDisk( ret_val = virtdisk.AttachVirtualDisk(
self._handle, 0, self.ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY, 0, 0, 0) self._handle, 0, self.ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY, 0, 0, 0)
if ret_val: if ret_val:
raise Exception("Cannot attach virtual disk") raise Exception("Cannot attach virtual disk")
def detach(self): def detach(self):
ret_val = virtdisk.DetachVirtualDisk( ret_val = virtdisk.DetachVirtualDisk(
self._handle, self.DETACH_VIRTUAL_DISK_FLAG_NONE, 0) self._handle, self.DETACH_VIRTUAL_DISK_FLAG_NONE, 0)
if ret_val: if ret_val:
raise Exception("Cannot detach virtual disk") raise Exception("Cannot detach virtual disk")
def get_physical_path(self): def get_physical_path(self):
buf = ctypes.create_unicode_buffer(1024) buf = ctypes.create_unicode_buffer(1024)
bufLen = wintypes.DWORD(ctypes.sizeof(buf)) bufLen = wintypes.DWORD(ctypes.sizeof(buf))
ret_val = virtdisk.GetVirtualDiskPhysicalPath(self._handle, ret_val = virtdisk.GetVirtualDiskPhysicalPath(self._handle,
ctypes.byref(bufLen), ctypes.byref(bufLen),
buf) buf)
if ret_val: if ret_val:
raise Exception("Cannot get virtual disk physical path") raise Exception("Cannot get virtual disk physical path")
return buf.value return buf.value
def get_cdrom_drive_mount_point(self): def get_cdrom_drive_mount_point(self):
mount_point = None mount_point = None
buf = ctypes.create_unicode_buffer(2048) buf = ctypes.create_unicode_buffer(2048)
buf_len = kernel32.GetLogicalDriveStringsW( buf_len = kernel32.GetLogicalDriveStringsW(
ctypes.sizeof(buf) / ctypes.sizeof(wintypes.WCHAR), buf) ctypes.sizeof(buf) / ctypes.sizeof(wintypes.WCHAR), buf)
if not buf_len: if not buf_len:
raise Exception("Cannot enumerate logical devices") raise Exception("Cannot enumerate logical devices")
cdrom_dev = self.get_physical_path().rsplit('\\')[-1].upper() cdrom_dev = self.get_physical_path().rsplit('\\')[-1].upper()
i = 0 i = 0
while not mount_point and i < buf_len: while not mount_point and i < buf_len:
curr_drive = ctypes.wstring_at(ctypes.addressof(buf) + i * curr_drive = ctypes.wstring_at(ctypes.addressof(buf) + i *
ctypes.sizeof(wintypes.WCHAR))[:-1] ctypes.sizeof(wintypes.WCHAR))[:-1]
dev = ctypes.create_unicode_buffer(2048) dev = ctypes.create_unicode_buffer(2048)
ret_val = kernel32.QueryDosDeviceW(curr_drive, dev, ret_val = kernel32.QueryDosDeviceW(curr_drive, dev,
ctypes.sizeof(dev) / ctypes.sizeof(dev) /
ctypes.sizeof(wintypes.WCHAR)) ctypes.sizeof(wintypes.WCHAR))
if not ret_val: if not ret_val:
raise Exception("Cannot query NT device") raise Exception("Cannot query NT device")
if dev.value.rsplit('\\')[-1].upper() == cdrom_dev: if dev.value.rsplit('\\')[-1].upper() == cdrom_dev:
mount_point = curr_drive mount_point = curr_drive
else: else:
i += len(curr_drive) + 2 i += len(curr_drive) + 2
return mount_point return mount_point
def close(self): def close(self):
kernel32.CloseHandle(self._handle) kernel32.CloseHandle(self._handle)
self._handle = 0 self._handle = 0

View File

@ -1,123 +1,123 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Mirantis Inc. # Copyright 2012 Mirantis Inc.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # 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 # not use this file except in compliance with the License. You may obtain
# a copy of the License at # a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import posixpath import posixpath
import urllib2 import urllib2
import traceback import traceback
import os import os
from cloudbaseinit.metadata.services import base from cloudbaseinit.metadata.services import base
from cloudbaseinit.openstack.common import cfg from cloudbaseinit.openstack.common import cfg
from cloudbaseinit.openstack.common import log as logging from cloudbaseinit.openstack.common import log as logging
opts = [ opts = [
cfg.StrOpt('ec2_metadata_base_url', cfg.StrOpt('ec2_metadata_base_url',
default='http://169.254.169.254/2009-04-04/', default='http://169.254.169.254/2009-04-04/',
help='The base URL where the service looks for metadata'), help='The base URL where the service looks for metadata'),
] ]
ec2nodes = [ ec2nodes = [
'ami-id', 'ami-launch-index', 'ami-manifest-path', 'ancestor-ami-ids', 'ami-id', 'ami-launch-index', 'ami-manifest-path', 'ancestor-ami-ids',
'hostname', 'block-device-mapping', 'kernel-id', 'hostname', 'block-device-mapping', 'kernel-id',
'placement/availability-zone', 'instance-action', 'instance-id', 'placement/availability-zone', 'instance-action', 'instance-id',
'instance-type', 'product-codes', 'local-hostname', 'local-ipv4', 'instance-type', 'product-codes', 'local-hostname', 'local-ipv4',
'public-hostname', 'public-ipv4', 'ramdisk-id', 'reservation-id', 'public-hostname', 'public-ipv4', 'ramdisk-id', 'reservation-id',
'security-groups', 'public-keys/', 'public-keys/0/', 'security-groups', 'public-keys/', 'public-keys/0/',
'public-keys/0/openssh-key', 'admin_pass'] 'public-keys/0/openssh-key', 'admin_pass']
CONF = cfg.CONF CONF = cfg.CONF
CONF.register_opts(opts) CONF.register_opts(opts)
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
class EC2Service(base.BaseMetadataService): class EC2Service(base.BaseMetadataService):
def __init__(self): def __init__(self):
super(EC2Service, self).__init__() super(EC2Service, self).__init__()
self._enable_retry = True self._enable_retry = True
self.error_count = 0 self.error_count = 0
def load(self): def load(self):
super(EC2Service, self).load() super(EC2Service, self).load()
try: try:
self.get_meta_data('openstack') self.get_meta_data('openstack')
return True return True
except Exception, err: except Exception, err:
LOG.debug(err) LOG.debug(err)
LOG.debug(traceback.format_exc()) LOG.debug(traceback.format_exc())
LOG.debug('Metadata not found at URL \'%s\'' % LOG.debug('Metadata not found at URL \'%s\'' %
CONF.ec2_metadata_base_url) CONF.ec2_metadata_base_url)
return False return False
def _get_data(self, path): def _get_data(self, path):
data = {} data = {}
LOG.debug("Check for EC2 interface availability...") LOG.debug("Check for EC2 interface availability...")
if not self._check_EC2(): if not self._check_EC2():
raise Exception("EC2 interface is not available") raise Exception("EC2 interface is not available")
LOG.debug('Getting data for the path: %s' % path) LOG.debug('Getting data for the path: %s' % path)
if path.endswith('meta_data.json'): if path.endswith('meta_data.json'):
for key in ec2nodes: for key in ec2nodes:
LOG.debug('Getting metadata from: %s' % key) LOG.debug('Getting metadata from: %s' % key)
try: try:
data[key] = self._get_EC2_value(key) data[key] = self._get_EC2_value(key)
except: except:
LOG.info("EC2 value %s is not available. Skip it." % key) LOG.info("EC2 value %s is not available. Skip it." % key)
# Saving keys to the local folder # Saving keys to the local folder
self._load_public_keys(data) self._load_public_keys(data)
if path.endswith('user_data'): if path.endswith('user_data'):
norm_path = posixpath.join(CONF.ec2_metadata_base_url, 'user-data') norm_path = posixpath.join(CONF.ec2_metadata_base_url, 'user-data')
LOG.debug('Getting metadata from: %(norm_path)s' % locals()) LOG.debug('Getting metadata from: %(norm_path)s' % locals())
try: try:
req = urllib2.Request(norm_path) req = urllib2.Request(norm_path)
response = urllib2.urlopen(req) response = urllib2.urlopen(req)
data = response.read() data = response.read()
LOG.debug("Got data: %s" % data) LOG.debug("Got data: %s" % data)
except: except:
LOG.error("EC2 user-data is not available.") LOG.error("EC2 user-data is not available.")
return data return data
def _check_EC2(self): def _check_EC2(self):
try: try:
data = self._get_EC2_value('') data = self._get_EC2_value('')
return True return True
except: except:
return False return False
def _get_EC2_value(self, key): def _get_EC2_value(self, key):
meta_path = posixpath.join( meta_path = posixpath.join(
CONF.ec2_metadata_base_url, 'meta-data', key) CONF.ec2_metadata_base_url, 'meta-data', key)
req = urllib2.Request(meta_path) req = urllib2.Request(meta_path)
response = urllib2.urlopen(req) response = urllib2.urlopen(req)
return response.read() return response.read()
def _load_public_keys(self, data): def _load_public_keys(self, data):
try: try:
key_list = self._get_EC2_value('public-keys/') key_list = self._get_EC2_value('public-keys/')
LOG.debug("Got a list of keys %s" % key_list) LOG.debug("Got a list of keys %s" % key_list)
data['public_keys'] = {} data['public_keys'] = {}
for key_name in key_list.split('\n'): for key_name in key_list.split('\n'):
key_index = key_name.split('=')[0] key_index = key_name.split('=')[0]
LOG.debug('Loading key %s' % key_index) LOG.debug('Loading key %s' % key_index)
key = self._get_EC2_value( key = self._get_EC2_value(
'public-keys/%s/openssh-key' % key_index) 'public-keys/%s/openssh-key' % key_index)
data['public_keys'].update({key_index: key}) data['public_keys'].update({key_index: key})
except Exception, ex: except Exception, ex:
LOG.debug("Can't save public key %s" % ex) LOG.debug("Can't save public key %s" % ex)
LOG.debug(traceback.format_exc()) LOG.debug(traceback.format_exc())

View File

@ -1,117 +1,117 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Cloudbase Solutions Srl # Copyright 2012 Cloudbase Solutions Srl
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # 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 # not use this file except in compliance with the License. You may obtain
# a copy of the License at # a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import posixpath import posixpath
import urllib2 import urllib2
import urlparse import urlparse
from cloudbaseinit.metadata.services import base from cloudbaseinit.metadata.services import base
from cloudbaseinit.openstack.common import cfg from cloudbaseinit.openstack.common import cfg
from cloudbaseinit.openstack.common import log as logging from cloudbaseinit.openstack.common import log as logging
from cloudbaseinit.osutils import factory as osutils_factory from cloudbaseinit.osutils import factory as osutils_factory
opts = [ opts = [
cfg.StrOpt('metadata_base_url', default='http://169.254.169.254/', cfg.StrOpt('metadata_base_url', default='http://169.254.169.254/',
help='The base URL where the service looks for metadata'), help='The base URL where the service looks for metadata'),
] ]
CONF = cfg.CONF CONF = cfg.CONF
CONF.register_opts(opts) CONF.register_opts(opts)
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
class HttpService(base.BaseMetadataService): class HttpService(base.BaseMetadataService):
def __init__(self): def __init__(self):
super(HttpService, self).__init__() super(HttpService, self).__init__()
self._enable_retry = True self._enable_retry = True
def _check_metadata_ip_route(self): def _check_metadata_ip_route(self):
''' '''
Workaround for: https://bugs.launchpad.net/quantum/+bug/1174657 Workaround for: https://bugs.launchpad.net/quantum/+bug/1174657
''' '''
osutils = osutils_factory.OSUtilsFactory().get_os_utils() osutils = osutils_factory.OSUtilsFactory().get_os_utils()
if osutils.check_os_version(6, 0): if osutils.check_os_version(6, 0):
# 169.254.x.x addresses are not getting routed starting from # 169.254.x.x addresses are not getting routed starting from
# Windows Vista / 2008 # Windows Vista / 2008
metadata_netloc = urlparse.urlparse(CONF.metadata_base_url).netloc metadata_netloc = urlparse.urlparse(CONF.metadata_base_url).netloc
metadata_host = metadata_netloc.split(':')[0] metadata_host = metadata_netloc.split(':')[0]
if metadata_host.startswith("169.254."): if metadata_host.startswith("169.254."):
if not osutils.check_static_route_exists(metadata_host): if not osutils.check_static_route_exists(metadata_host):
(interface_index, gateway) = osutils.get_default_gateway() (interface_index, gateway) = osutils.get_default_gateway()
if gateway: if gateway:
try: try:
osutils.add_static_route(metadata_host, osutils.add_static_route(metadata_host,
"255.255.255.255", "255.255.255.255",
gateway, gateway,
interface_index, interface_index,
10) 10)
except Exception, ex: except Exception, ex:
# Ignore it # Ignore it
LOG.exception(ex) LOG.exception(ex)
def load(self): def load(self):
super(HttpService, self).load() super(HttpService, self).load()
self._check_metadata_ip_route() self._check_metadata_ip_route()
try: try:
self.get_meta_data('openstack') self.get_meta_data('openstack')
return True return True
except: except:
LOG.debug('Metadata not found at URL \'%s\'' % LOG.debug('Metadata not found at URL \'%s\'' %
CONF.metadata_base_url) CONF.metadata_base_url)
return False return False
@property @property
def can_post_password(self): def can_post_password(self):
return True return True
def _get_response(self, req): def _get_response(self, req):
try: try:
return urllib2.urlopen(req) return urllib2.urlopen(req)
except urllib2.HTTPError as ex: except urllib2.HTTPError as ex:
if ex.code == 404: if ex.code == 404:
raise base.NotExistingMetadataException() raise base.NotExistingMetadataException()
else: else:
raise raise
def _get_data(self, path): def _get_data(self, path):
norm_path = posixpath.join(CONF.metadata_base_url, path) norm_path = posixpath.join(CONF.metadata_base_url, path)
LOG.debug('Getting metadata from: %(norm_path)s' % locals()) LOG.debug('Getting metadata from: %(norm_path)s' % locals())
req = urllib2.Request(norm_path) req = urllib2.Request(norm_path)
response = self._get_response(req) response = self._get_response(req)
return response.read() return response.read()
def _post_data(self, path, data): def _post_data(self, path, data):
norm_path = posixpath.join(CONF.metadata_base_url, path) norm_path = posixpath.join(CONF.metadata_base_url, path)
LOG.debug('Posting metadata to: %(norm_path)s' % locals()) LOG.debug('Posting metadata to: %(norm_path)s' % locals())
req = urllib2.Request(norm_path, data=data) req = urllib2.Request(norm_path, data=data)
self._get_response(req) self._get_response(req)
return True return True
def post_password(self, enc_password_b64, version='latest'): def post_password(self, enc_password_b64, version='latest'):
try: try:
return super(HttpService, self).post_password(enc_password_b64, return super(HttpService, self).post_password(enc_password_b64,
version) version)
except urllib2.HTTPError as ex: except urllib2.HTTPError as ex:
if ex.code == 409: if ex.code == 409:
# Password already set # Password already set
return False return False
else: else:
raise raise

View File

@ -1,52 +1,52 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Cloudbase Solutions Srl # Copyright 2012 Cloudbase Solutions Srl
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # 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 # not use this file except in compliance with the License. You may obtain
# a copy of the License at # a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from cloudbaseinit.openstack.common import cfg from cloudbaseinit.openstack.common import cfg
from cloudbaseinit.utils import classloader from cloudbaseinit.utils import classloader
opts = [ opts = [
cfg.ListOpt( cfg.ListOpt(
'plugins', 'plugins',
default=[ default=[
'cloudbaseinit.plugins.windows.sethostname.SetHostNamePlugin', 'cloudbaseinit.plugins.windows.sethostname.SetHostNamePlugin',
'cloudbaseinit.plugins.windows.createuser.CreateUserPlugin', 'cloudbaseinit.plugins.windows.createuser.CreateUserPlugin',
'cloudbaseinit.plugins.windows.networkconfig.NetworkConfigPlugin', 'cloudbaseinit.plugins.windows.networkconfig.NetworkConfigPlugin',
'cloudbaseinit.plugins.windows.sshpublickeys.' 'cloudbaseinit.plugins.windows.sshpublickeys.'
'SetUserSSHPublicKeysPlugin', 'SetUserSSHPublicKeysPlugin',
'cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin', 'cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin',
'cloudbaseinit.plugins.windows.userdata.UserDataPlugin', 'cloudbaseinit.plugins.windows.userdata.UserDataPlugin',
'cloudbaseinit.plugins.windows.setuserpassword.' 'cloudbaseinit.plugins.windows.setuserpassword.'
'SetUserPasswordPlugin', 'SetUserPasswordPlugin',
'cloudbaseinit.plugins.windows.winrmlistener.' 'cloudbaseinit.plugins.windows.winrmlistener.'
'ConfigWinRMListenerPlugin', 'ConfigWinRMListenerPlugin',
'cloudbaseinit.plugins.windows.winrmcertificateauth.' 'cloudbaseinit.plugins.windows.winrmcertificateauth.'
'ConfigWinRMCertificateAuthPlugin', 'ConfigWinRMCertificateAuthPlugin',
], ],
help='List of enabled plugin classes, ' help='List of enabled plugin classes, '
'to executed in the provided order'), 'to executed in the provided order'),
] ]
CONF = cfg.CONF CONF = cfg.CONF
CONF.register_opts(opts) CONF.register_opts(opts)
class PluginFactory(object): class PluginFactory(object):
def load_plugins(self): def load_plugins(self):
plugins = [] plugins = []
cl = classloader.ClassLoader() cl = classloader.ClassLoader()
for class_path in CONF.plugins: for class_path in CONF.plugins:
plugins.append(cl.load_class(class_path)()) plugins.append(cl.load_class(class_path)())
return plugins return plugins

View File

@ -1,85 +1,85 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Cloudbase Solutions Srl # Copyright 2012 Cloudbase Solutions Srl
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # 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 # not use this file except in compliance with the License. You may obtain
# a copy of the License at # a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import re import re
from cloudbaseinit.openstack.common import cfg from cloudbaseinit.openstack.common import cfg
from cloudbaseinit.openstack.common import log as logging from cloudbaseinit.openstack.common import log as logging
from cloudbaseinit.osutils import factory as osutils_factory from cloudbaseinit.osutils import factory as osutils_factory
from cloudbaseinit.plugins import base from cloudbaseinit.plugins import base
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
opts = [ opts = [
cfg.StrOpt('network_adapter', default=None, help='Network adapter to ' cfg.StrOpt('network_adapter', default=None, help='Network adapter to '
'configure. If not specified, the first available ethernet ' 'configure. If not specified, the first available ethernet '
'adapter will be chosen'), 'adapter will be chosen'),
] ]
CONF = cfg.CONF CONF = cfg.CONF
CONF.register_opts(opts) CONF.register_opts(opts)
class NetworkConfigPlugin(base.BasePlugin): class NetworkConfigPlugin(base.BasePlugin):
def execute(self, service, shared_data): def execute(self, service, shared_data):
meta_data = service.get_meta_data('openstack') meta_data = service.get_meta_data('openstack')
if 'network_config' not in meta_data: if 'network_config' not in meta_data:
return (base.PLUGIN_EXECUTION_DONE, False) return (base.PLUGIN_EXECUTION_DONE, False)
network_config = meta_data['network_config'] network_config = meta_data['network_config']
if 'content_path' not in network_config: if 'content_path' not in network_config:
return (base.PLUGIN_EXECUTION_DONE, False) return (base.PLUGIN_EXECUTION_DONE, False)
content_path = network_config['content_path'] content_path = network_config['content_path']
content_name = content_path.rsplit('/', 1)[-1] content_name = content_path.rsplit('/', 1)[-1]
debian_network_conf = service.get_content('openstack', content_name) debian_network_conf = service.get_content('openstack', content_name)
LOG.debug('network config content:\n%s' % debian_network_conf) LOG.debug('network config content:\n%s' % debian_network_conf)
# TODO (alexpilotti): implement a proper grammar # TODO (alexpilotti): implement a proper grammar
m = re.search(r'iface eth0 inet static\s+' m = re.search(r'iface eth0 inet static\s+'
r'address\s+(?P<address>[^\s]+)\s+' r'address\s+(?P<address>[^\s]+)\s+'
r'netmask\s+(?P<netmask>[^\s]+)\s+' r'netmask\s+(?P<netmask>[^\s]+)\s+'
r'broadcast\s+(?P<broadcast>[^\s]+)\s+' r'broadcast\s+(?P<broadcast>[^\s]+)\s+'
r'gateway\s+(?P<gateway>[^\s]+)\s+' r'gateway\s+(?P<gateway>[^\s]+)\s+'
r'dns\-nameservers\s+(?P<dnsnameservers>[^\r\n]+)\s+', r'dns\-nameservers\s+(?P<dnsnameservers>[^\r\n]+)\s+',
debian_network_conf) debian_network_conf)
if not m: if not m:
raise Exception("network_config format not recognized") raise Exception("network_config format not recognized")
address = m.group('address') address = m.group('address')
netmask = m.group('netmask') netmask = m.group('netmask')
broadcast = m.group('broadcast') broadcast = m.group('broadcast')
gateway = m.group('gateway') gateway = m.group('gateway')
dnsnameservers = m.group('dnsnameservers').strip().split(' ') dnsnameservers = m.group('dnsnameservers').strip().split(' ')
osutils = osutils_factory.OSUtilsFactory().get_os_utils() osutils = osutils_factory.OSUtilsFactory().get_os_utils()
network_adapter_name = CONF.network_adapter network_adapter_name = CONF.network_adapter
if not network_adapter_name: if not network_adapter_name:
# Get the first available one # Get the first available one
available_adapters = osutils.get_network_adapters() available_adapters = osutils.get_network_adapters()
if not len(available_adapters): if not len(available_adapters):
raise Exception("No network adapter available") raise Exception("No network adapter available")
network_adapter_name = available_adapters[0] network_adapter_name = available_adapters[0]
LOG.info('Configuring network adapter: \'%s\'' % network_adapter_name) LOG.info('Configuring network adapter: \'%s\'' % network_adapter_name)
reboot_required = osutils.set_static_network_config( reboot_required = osutils.set_static_network_config(
network_adapter_name, address, netmask, broadcast, network_adapter_name, address, netmask, broadcast,
gateway, dnsnameservers) gateway, dnsnameservers)
return (base.PLUGIN_EXECUTION_DONE, reboot_required) return (base.PLUGIN_EXECUTION_DONE, reboot_required)

View File

@ -1,145 +1,145 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Cloudbase Solutions Srl # Copyright 2012 Cloudbase Solutions Srl
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # 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 # not use this file except in compliance with the License. You may obtain
# a copy of the License at # a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import email import email
from cloudbaseinit.metadata.services import base as metadata_services_base from cloudbaseinit.metadata.services import base as metadata_services_base
from cloudbaseinit.openstack.common import log as logging from cloudbaseinit.openstack.common import log as logging
from cloudbaseinit.plugins import base from cloudbaseinit.plugins import base
from cloudbaseinit.plugins.windows import userdatautils from cloudbaseinit.plugins.windows import userdatautils
from cloudbaseinit.plugins.windows.userdataplugins import factory from cloudbaseinit.plugins.windows.userdataplugins import factory
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
class UserDataPlugin(base.BasePlugin): class UserDataPlugin(base.BasePlugin):
_part_handler_content_type = "text/part-handler" _part_handler_content_type = "text/part-handler"
def execute(self, service, shared_data): def execute(self, service, shared_data):
try: try:
user_data = service.get_user_data('openstack') user_data = service.get_user_data('openstack')
except metadata_services_base.NotExistingMetadataException: except metadata_services_base.NotExistingMetadataException:
return (base.PLUGIN_EXECUTION_DONE, False) return (base.PLUGIN_EXECUTION_DONE, False)
if not user_data: if not user_data:
return (base.PLUGIN_EXECUTION_DONE, False) return (base.PLUGIN_EXECUTION_DONE, False)
return self._process_user_data(user_data) return self._process_user_data(user_data)
def _parse_mime(self, user_data): def _parse_mime(self, user_data):
return email.message_from_string(user_data).walk() return email.message_from_string(user_data).walk()
def _process_user_data(self, user_data): def _process_user_data(self, user_data):
plugin_status = base.PLUGIN_EXECUTION_DONE plugin_status = base.PLUGIN_EXECUTION_DONE
reboot = False reboot = False
LOG.debug('User data content:\n%s' % user_data) LOG.debug('User data content:\n%s' % user_data)
if user_data.startswith('Content-Type: multipart'): if user_data.startswith('Content-Type: multipart'):
user_data_plugins_factory = factory.UserDataPluginsFactory() user_data_plugins_factory = factory.UserDataPluginsFactory()
user_data_plugins = user_data_plugins_factory.load_plugins() user_data_plugins = user_data_plugins_factory.load_plugins()
user_handlers = {} user_handlers = {}
for part in self._parse_mime(user_data): for part in self._parse_mime(user_data):
(plugin_status, reboot) = self._process_part(part, (plugin_status, reboot) = self._process_part(part,
user_data_plugins, user_data_plugins,
user_handlers) user_handlers)
if reboot: if reboot:
break break
if not reboot: if not reboot:
for handler_func in list(set(user_handlers.values())): for handler_func in list(set(user_handlers.values())):
self._end_part_process_event(handler_func) 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
try: try:
content_type = part.get_content_type() content_type = part.get_content_type()
handler_func = user_handlers.get(content_type) handler_func = user_handlers.get(content_type)
if handler_func: if handler_func:
LOG.debug("Calling user part handler for content type: %s" % LOG.debug("Calling user part handler for content type: %s" %
content_type) content_type)
handler_func(None, content_type, part.get_filename(), handler_func(None, content_type, part.get_filename(),
part.get_payload()) part.get_payload())
else: else:
user_data_plugin = user_data_plugins.get(content_type) user_data_plugin = user_data_plugins.get(content_type)
if not user_data_plugin: if not user_data_plugin:
LOG.info("Userdata plugin not found for content type: %s" % LOG.info("Userdata plugin not found for content type: %s" %
content_type) content_type)
else: else:
LOG.debug("Executing userdata plugin: %s" % LOG.debug("Executing userdata plugin: %s" %
user_data_plugin.__class__.__name__) user_data_plugin.__class__.__name__)
if content_type == self._part_handler_content_type: if content_type == self._part_handler_content_type:
new_user_handlers = user_data_plugin.process(part) new_user_handlers = user_data_plugin.process(part)
self._add_part_handlers(user_data_plugins, self._add_part_handlers(user_data_plugins,
user_handlers, user_handlers,
new_user_handlers) new_user_handlers)
else: else:
ret_val = user_data_plugin.process(part) ret_val = user_data_plugin.process(part)
except Exception, ex: except Exception, ex:
LOG.error('Exception during multipart part handling: ' LOG.error('Exception during multipart part handling: '
'%(content_type)s, %(filename)s' % '%(content_type)s, %(filename)s' %
{'content_type': part.get_content_type(), {'content_type': part.get_content_type(),
'filename': part.get_filename()}) 'filename': part.get_filename()})
LOG.exception(ex) LOG.exception(ex)
return self._get_plugin_return_value(ret_val) return self._get_plugin_return_value(ret_val)
def _add_part_handlers(self, user_data_plugins, user_handlers, def _add_part_handlers(self, user_data_plugins, user_handlers,
new_user_handlers): new_user_handlers):
handler_funcs = set() handler_funcs = set()
for (content_type, for (content_type,
handler_func) in new_user_handlers.items(): handler_func) in new_user_handlers.items():
if not user_data_plugins.get(content_type): if not user_data_plugins.get(content_type):
LOG.info("Adding part handler for content " LOG.info("Adding part handler for content "
"type: %s" % content_type) "type: %s" % content_type)
user_handlers[content_type] = handler_func user_handlers[content_type] = handler_func
handler_funcs.add(handler_func) handler_funcs.add(handler_func)
else: else:
LOG.info("Skipping part handler for content type \"%s\" as it " LOG.info("Skipping part handler for content type \"%s\" as it "
"is already managed by a plugin" % content_type) "is already managed by a plugin" % content_type)
for handler_func in handler_funcs: for handler_func in handler_funcs:
self._begin_part_process_event(handler_func) self._begin_part_process_event(handler_func)
def _begin_part_process_event(self, handler_func): def _begin_part_process_event(self, handler_func):
LOG.debug("Calling part handler \"__begin__\" event") LOG.debug("Calling part handler \"__begin__\" event")
handler_func(None, "__begin__", None, None) handler_func(None, "__begin__", None, None)
def _end_part_process_event(self, handler_func): def _end_part_process_event(self, handler_func):
LOG.debug("Calling part handler \"__end__\" event") LOG.debug("Calling part handler \"__end__\" event")
handler_func(None, "__end__", None, None) 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
reboot = False reboot = False
if ret_val >= 1001 and ret_val <= 1003: if ret_val >= 1001 and ret_val <= 1003:
reboot = bool(ret_val & 1) reboot = bool(ret_val & 1)
if ret_val & 2: if ret_val & 2:
plugin_status = base.PLUGIN_EXECUTE_ON_NEXT_BOOT plugin_status = base.PLUGIN_EXECUTE_ON_NEXT_BOOT
return (plugin_status, reboot) return (plugin_status, reboot)
def _process_non_multi_part(self, user_data): def _process_non_multi_part(self, user_data):
ret_val = userdatautils.execute_user_data_script(user_data) ret_val = userdatautils.execute_user_data_script(user_data)
return self._get_plugin_return_value(ret_val) return self._get_plugin_return_value(ret_val)