Normalize line endings
This commit is contained in:
parent
9ef84f6bd8
commit
b4b3f6bb4e
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Always use LF
|
||||||
|
* text=lf
|
@ -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()
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
|
@ -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())
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user