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
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import sys
|
||||
|
||||
from cloudbaseinit.metadata import factory as metadata_factory
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
from cloudbaseinit.osutils import factory as osutils_factory
|
||||
from cloudbaseinit.plugins import base as plugins_base
|
||||
from cloudbaseinit.plugins import factory as plugins_factory
|
||||
|
||||
opts = [
|
||||
cfg.BoolOpt('allow_reboot', default=True, help='Allows OS reboots '
|
||||
'requested by plugins'),
|
||||
cfg.BoolOpt('stop_service_on_exit', default=True, help='In case of '
|
||||
'execution as a service, specifies if the service '
|
||||
'must be gracefully stopped before exiting'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InitManager(object):
|
||||
_PLUGINS_CONFIG_SECTION = 'Plugins'
|
||||
|
||||
def _get_plugin_status(self, osutils, plugin_name):
|
||||
return osutils.get_config_value(plugin_name,
|
||||
self._PLUGINS_CONFIG_SECTION)
|
||||
|
||||
def _set_plugin_status(self, osutils, plugin_name, status):
|
||||
osutils.set_config_value(plugin_name, status,
|
||||
self._PLUGINS_CONFIG_SECTION)
|
||||
|
||||
def _exec_plugin(self, osutils, service, plugin, shared_data):
|
||||
plugin_name = plugin.get_name()
|
||||
|
||||
status = self._get_plugin_status(osutils, plugin_name)
|
||||
if status == plugins_base.PLUGIN_EXECUTION_DONE:
|
||||
LOG.debug('Plugin \'%(plugin_name)s\' execution already done, '
|
||||
'skipping' % locals())
|
||||
else:
|
||||
LOG.info('Executing plugin \'%(plugin_name)s\'' %
|
||||
locals())
|
||||
try:
|
||||
(status, reboot_required) = plugin.execute(service,
|
||||
shared_data)
|
||||
self._set_plugin_status(osutils, plugin_name, status)
|
||||
return reboot_required
|
||||
except Exception, ex:
|
||||
LOG.error('plugin \'%(plugin_name)s\' failed '
|
||||
'with error \'%(ex)s\'' % locals())
|
||||
LOG.exception(ex)
|
||||
|
||||
def _check_plugin_os_requirements(self, osutils, plugin):
|
||||
supported = False
|
||||
plugin_name = plugin.get_name()
|
||||
|
||||
(required_platform, min_os_version) = plugin.get_os_requirements()
|
||||
if required_platform and sys.platform != required_platform:
|
||||
LOG.debug('Skipping plugin: \'%s\'. Platform not supported' %
|
||||
plugin_name)
|
||||
else:
|
||||
if not min_os_version:
|
||||
supported = True
|
||||
else:
|
||||
os_major, os_minor = min_os_version
|
||||
if osutils.check_os_version(os_major, os_minor):
|
||||
supported = True
|
||||
else:
|
||||
LOG.debug('Skipping plugin: \'%s\'. OS version not '
|
||||
'supported' % plugin_name)
|
||||
return supported
|
||||
|
||||
def configure_host(self):
|
||||
osutils = osutils_factory.OSUtilsFactory().get_os_utils()
|
||||
osutils.wait_for_boot_completion()
|
||||
|
||||
mdsf = metadata_factory.MetadataServiceFactory()
|
||||
service = mdsf.get_metadata_service()
|
||||
LOG.info('Metadata service loaded: \'%s\'' %
|
||||
service.get_name())
|
||||
|
||||
plugins = plugins_factory.PluginFactory().load_plugins()
|
||||
|
||||
plugins_shared_data = {}
|
||||
|
||||
reboot_required = False
|
||||
try:
|
||||
for plugin in plugins:
|
||||
if self._check_plugin_os_requirements(osutils, plugin):
|
||||
if self._exec_plugin(osutils, service, plugin,
|
||||
plugins_shared_data):
|
||||
reboot_required = True
|
||||
if CONF.allow_reboot:
|
||||
break
|
||||
finally:
|
||||
service.cleanup()
|
||||
|
||||
if reboot_required and CONF.allow_reboot:
|
||||
try:
|
||||
osutils.reboot()
|
||||
except Exception, ex:
|
||||
LOG.error('reboot failed with error \'%s\'' % ex)
|
||||
elif CONF.stop_service_on_exit:
|
||||
osutils.terminate()
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import sys
|
||||
|
||||
from cloudbaseinit.metadata import factory as metadata_factory
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
from cloudbaseinit.osutils import factory as osutils_factory
|
||||
from cloudbaseinit.plugins import base as plugins_base
|
||||
from cloudbaseinit.plugins import factory as plugins_factory
|
||||
|
||||
opts = [
|
||||
cfg.BoolOpt('allow_reboot', default=True, help='Allows OS reboots '
|
||||
'requested by plugins'),
|
||||
cfg.BoolOpt('stop_service_on_exit', default=True, help='In case of '
|
||||
'execution as a service, specifies if the service '
|
||||
'must be gracefully stopped before exiting'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InitManager(object):
|
||||
_PLUGINS_CONFIG_SECTION = 'Plugins'
|
||||
|
||||
def _get_plugin_status(self, osutils, plugin_name):
|
||||
return osutils.get_config_value(plugin_name,
|
||||
self._PLUGINS_CONFIG_SECTION)
|
||||
|
||||
def _set_plugin_status(self, osutils, plugin_name, status):
|
||||
osutils.set_config_value(plugin_name, status,
|
||||
self._PLUGINS_CONFIG_SECTION)
|
||||
|
||||
def _exec_plugin(self, osutils, service, plugin, shared_data):
|
||||
plugin_name = plugin.get_name()
|
||||
|
||||
status = self._get_plugin_status(osutils, plugin_name)
|
||||
if status == plugins_base.PLUGIN_EXECUTION_DONE:
|
||||
LOG.debug('Plugin \'%(plugin_name)s\' execution already done, '
|
||||
'skipping' % locals())
|
||||
else:
|
||||
LOG.info('Executing plugin \'%(plugin_name)s\'' %
|
||||
locals())
|
||||
try:
|
||||
(status, reboot_required) = plugin.execute(service,
|
||||
shared_data)
|
||||
self._set_plugin_status(osutils, plugin_name, status)
|
||||
return reboot_required
|
||||
except Exception, ex:
|
||||
LOG.error('plugin \'%(plugin_name)s\' failed '
|
||||
'with error \'%(ex)s\'' % locals())
|
||||
LOG.exception(ex)
|
||||
|
||||
def _check_plugin_os_requirements(self, osutils, plugin):
|
||||
supported = False
|
||||
plugin_name = plugin.get_name()
|
||||
|
||||
(required_platform, min_os_version) = plugin.get_os_requirements()
|
||||
if required_platform and sys.platform != required_platform:
|
||||
LOG.debug('Skipping plugin: \'%s\'. Platform not supported' %
|
||||
plugin_name)
|
||||
else:
|
||||
if not min_os_version:
|
||||
supported = True
|
||||
else:
|
||||
os_major, os_minor = min_os_version
|
||||
if osutils.check_os_version(os_major, os_minor):
|
||||
supported = True
|
||||
else:
|
||||
LOG.debug('Skipping plugin: \'%s\'. OS version not '
|
||||
'supported' % plugin_name)
|
||||
return supported
|
||||
|
||||
def configure_host(self):
|
||||
osutils = osutils_factory.OSUtilsFactory().get_os_utils()
|
||||
osutils.wait_for_boot_completion()
|
||||
|
||||
mdsf = metadata_factory.MetadataServiceFactory()
|
||||
service = mdsf.get_metadata_service()
|
||||
LOG.info('Metadata service loaded: \'%s\'' %
|
||||
service.get_name())
|
||||
|
||||
plugins = plugins_factory.PluginFactory().load_plugins()
|
||||
|
||||
plugins_shared_data = {}
|
||||
|
||||
reboot_required = False
|
||||
try:
|
||||
for plugin in plugins:
|
||||
if self._check_plugin_os_requirements(osutils, plugin):
|
||||
if self._exec_plugin(osutils, service, plugin,
|
||||
plugins_shared_data):
|
||||
reboot_required = True
|
||||
if CONF.allow_reboot:
|
||||
break
|
||||
finally:
|
||||
service.cleanup()
|
||||
|
||||
if reboot_required and CONF.allow_reboot:
|
||||
try:
|
||||
osutils.reboot()
|
||||
except Exception, ex:
|
||||
LOG.error('reboot failed with error \'%s\'' % ex)
|
||||
elif CONF.stop_service_on_exit:
|
||||
osutils.terminate()
|
||||
|
@ -1,52 +1,52 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
from cloudbaseinit.utils import classloader
|
||||
|
||||
opts = [
|
||||
cfg.ListOpt('metadata_services',
|
||||
default=[
|
||||
'cloudbaseinit.metadata.services.httpservice.HttpService',
|
||||
'cloudbaseinit.metadata.services.configdrive.configdrive.'
|
||||
'ConfigDriveService',
|
||||
'cloudbaseinit.metadata.services.ec2service.EC2Service'
|
||||
],
|
||||
help='List of enabled metadata service classes, '
|
||||
'to be tested fro availability in the provided order. '
|
||||
'The first available service will be used to retrieve '
|
||||
'metadata')
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MetadataServiceFactory(object):
|
||||
def get_metadata_service(self):
|
||||
# Return the first service that loads correctly
|
||||
cl = classloader.ClassLoader()
|
||||
for class_path in CONF.metadata_services:
|
||||
service = cl.load_class(class_path)()
|
||||
try:
|
||||
if service.load():
|
||||
return service
|
||||
except Exception, ex:
|
||||
LOG.error('Failed to load metadata service \'%(class_path)s\'')
|
||||
LOG.exception(ex)
|
||||
raise Exception("No available service found")
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
from cloudbaseinit.utils import classloader
|
||||
|
||||
opts = [
|
||||
cfg.ListOpt('metadata_services',
|
||||
default=[
|
||||
'cloudbaseinit.metadata.services.httpservice.HttpService',
|
||||
'cloudbaseinit.metadata.services.configdrive.configdrive.'
|
||||
'ConfigDriveService',
|
||||
'cloudbaseinit.metadata.services.ec2service.EC2Service'
|
||||
],
|
||||
help='List of enabled metadata service classes, '
|
||||
'to be tested fro availability in the provided order. '
|
||||
'The first available service will be used to retrieve '
|
||||
'metadata')
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MetadataServiceFactory(object):
|
||||
def get_metadata_service(self):
|
||||
# Return the first service that loads correctly
|
||||
cl = classloader.ClassLoader()
|
||||
for class_path in CONF.metadata_services:
|
||||
service = cl.load_class(class_path)()
|
||||
try:
|
||||
if service.load():
|
||||
return service
|
||||
except Exception, ex:
|
||||
LOG.error('Failed to load metadata service \'%(class_path)s\'')
|
||||
LOG.exception(ex)
|
||||
raise Exception("No available service found")
|
||||
|
@ -1,145 +1,145 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ctypes
|
||||
|
||||
from ctypes import windll
|
||||
from ctypes import wintypes
|
||||
|
||||
kernel32 = windll.kernel32
|
||||
# VirtDisk.dll is available starting from Windows Server 2008 R2 / Windows7
|
||||
virtdisk = None
|
||||
|
||||
|
||||
class Win32_GUID(ctypes.Structure):
|
||||
_fields_ = [("Data1", wintypes.DWORD),
|
||||
("Data2", wintypes.WORD),
|
||||
("Data3", wintypes.WORD),
|
||||
("Data4", wintypes.BYTE * 8)]
|
||||
|
||||
|
||||
def get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT():
|
||||
guid = Win32_GUID()
|
||||
guid.Data1 = 0xec984aec
|
||||
guid.Data2 = 0xa0f9
|
||||
guid.Data3 = 0x47e9
|
||||
ByteArray8 = wintypes.BYTE * 8
|
||||
guid.Data4 = ByteArray8(0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b)
|
||||
return guid
|
||||
|
||||
|
||||
class Win32_VIRTUAL_STORAGE_TYPE(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('DeviceId', wintypes.DWORD),
|
||||
('VendorId', Win32_GUID)
|
||||
]
|
||||
|
||||
|
||||
class VirtualDisk(object):
|
||||
VIRTUAL_STORAGE_TYPE_DEVICE_ISO = 1
|
||||
VIRTUAL_DISK_ACCESS_ATTACH_RO = 0x10000
|
||||
VIRTUAL_DISK_ACCESS_READ = 0xd0000
|
||||
OPEN_VIRTUAL_DISK_FLAG_NONE = 0
|
||||
DETACH_VIRTUAL_DISK_FLAG_NONE = 0
|
||||
ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY = 1
|
||||
ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER = 2
|
||||
|
||||
def __init__(self, path):
|
||||
self._path = path
|
||||
self._handle = 0
|
||||
|
||||
def _load_virtdisk_dll(self):
|
||||
global virtdisk
|
||||
if not virtdisk:
|
||||
virtdisk = windll.virtdisk
|
||||
|
||||
def open(self):
|
||||
if self._handle:
|
||||
self.close()
|
||||
|
||||
self._load_virtdisk_dll()
|
||||
|
||||
vst = Win32_VIRTUAL_STORAGE_TYPE()
|
||||
vst.DeviceId = self.VIRTUAL_STORAGE_TYPE_DEVICE_ISO
|
||||
vst.VendorId = get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT()
|
||||
|
||||
handle = wintypes.HANDLE()
|
||||
ret_val = virtdisk.OpenVirtualDisk(ctypes.byref(vst),
|
||||
ctypes.c_wchar_p(self._path),
|
||||
self.VIRTUAL_DISK_ACCESS_ATTACH_RO |
|
||||
self.VIRTUAL_DISK_ACCESS_READ,
|
||||
self.OPEN_VIRTUAL_DISK_FLAG_NONE, 0,
|
||||
ctypes.byref(handle))
|
||||
if ret_val:
|
||||
raise Exception("Cannot open virtual disk")
|
||||
self._handle = handle
|
||||
|
||||
def attach(self):
|
||||
ret_val = virtdisk.AttachVirtualDisk(
|
||||
self._handle, 0, self.ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY, 0, 0, 0)
|
||||
if ret_val:
|
||||
raise Exception("Cannot attach virtual disk")
|
||||
|
||||
def detach(self):
|
||||
ret_val = virtdisk.DetachVirtualDisk(
|
||||
self._handle, self.DETACH_VIRTUAL_DISK_FLAG_NONE, 0)
|
||||
if ret_val:
|
||||
raise Exception("Cannot detach virtual disk")
|
||||
|
||||
def get_physical_path(self):
|
||||
buf = ctypes.create_unicode_buffer(1024)
|
||||
bufLen = wintypes.DWORD(ctypes.sizeof(buf))
|
||||
ret_val = virtdisk.GetVirtualDiskPhysicalPath(self._handle,
|
||||
ctypes.byref(bufLen),
|
||||
buf)
|
||||
if ret_val:
|
||||
raise Exception("Cannot get virtual disk physical path")
|
||||
return buf.value
|
||||
|
||||
def get_cdrom_drive_mount_point(self):
|
||||
|
||||
mount_point = None
|
||||
|
||||
buf = ctypes.create_unicode_buffer(2048)
|
||||
buf_len = kernel32.GetLogicalDriveStringsW(
|
||||
ctypes.sizeof(buf) / ctypes.sizeof(wintypes.WCHAR), buf)
|
||||
if not buf_len:
|
||||
raise Exception("Cannot enumerate logical devices")
|
||||
|
||||
cdrom_dev = self.get_physical_path().rsplit('\\')[-1].upper()
|
||||
|
||||
i = 0
|
||||
while not mount_point and i < buf_len:
|
||||
curr_drive = ctypes.wstring_at(ctypes.addressof(buf) + i *
|
||||
ctypes.sizeof(wintypes.WCHAR))[:-1]
|
||||
|
||||
dev = ctypes.create_unicode_buffer(2048)
|
||||
ret_val = kernel32.QueryDosDeviceW(curr_drive, dev,
|
||||
ctypes.sizeof(dev) /
|
||||
ctypes.sizeof(wintypes.WCHAR))
|
||||
if not ret_val:
|
||||
raise Exception("Cannot query NT device")
|
||||
|
||||
if dev.value.rsplit('\\')[-1].upper() == cdrom_dev:
|
||||
mount_point = curr_drive
|
||||
else:
|
||||
i += len(curr_drive) + 2
|
||||
|
||||
return mount_point
|
||||
|
||||
def close(self):
|
||||
kernel32.CloseHandle(self._handle)
|
||||
self._handle = 0
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ctypes
|
||||
|
||||
from ctypes import windll
|
||||
from ctypes import wintypes
|
||||
|
||||
kernel32 = windll.kernel32
|
||||
# VirtDisk.dll is available starting from Windows Server 2008 R2 / Windows7
|
||||
virtdisk = None
|
||||
|
||||
|
||||
class Win32_GUID(ctypes.Structure):
|
||||
_fields_ = [("Data1", wintypes.DWORD),
|
||||
("Data2", wintypes.WORD),
|
||||
("Data3", wintypes.WORD),
|
||||
("Data4", wintypes.BYTE * 8)]
|
||||
|
||||
|
||||
def get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT():
|
||||
guid = Win32_GUID()
|
||||
guid.Data1 = 0xec984aec
|
||||
guid.Data2 = 0xa0f9
|
||||
guid.Data3 = 0x47e9
|
||||
ByteArray8 = wintypes.BYTE * 8
|
||||
guid.Data4 = ByteArray8(0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b)
|
||||
return guid
|
||||
|
||||
|
||||
class Win32_VIRTUAL_STORAGE_TYPE(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('DeviceId', wintypes.DWORD),
|
||||
('VendorId', Win32_GUID)
|
||||
]
|
||||
|
||||
|
||||
class VirtualDisk(object):
|
||||
VIRTUAL_STORAGE_TYPE_DEVICE_ISO = 1
|
||||
VIRTUAL_DISK_ACCESS_ATTACH_RO = 0x10000
|
||||
VIRTUAL_DISK_ACCESS_READ = 0xd0000
|
||||
OPEN_VIRTUAL_DISK_FLAG_NONE = 0
|
||||
DETACH_VIRTUAL_DISK_FLAG_NONE = 0
|
||||
ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY = 1
|
||||
ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER = 2
|
||||
|
||||
def __init__(self, path):
|
||||
self._path = path
|
||||
self._handle = 0
|
||||
|
||||
def _load_virtdisk_dll(self):
|
||||
global virtdisk
|
||||
if not virtdisk:
|
||||
virtdisk = windll.virtdisk
|
||||
|
||||
def open(self):
|
||||
if self._handle:
|
||||
self.close()
|
||||
|
||||
self._load_virtdisk_dll()
|
||||
|
||||
vst = Win32_VIRTUAL_STORAGE_TYPE()
|
||||
vst.DeviceId = self.VIRTUAL_STORAGE_TYPE_DEVICE_ISO
|
||||
vst.VendorId = get_WIN32_VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT()
|
||||
|
||||
handle = wintypes.HANDLE()
|
||||
ret_val = virtdisk.OpenVirtualDisk(ctypes.byref(vst),
|
||||
ctypes.c_wchar_p(self._path),
|
||||
self.VIRTUAL_DISK_ACCESS_ATTACH_RO |
|
||||
self.VIRTUAL_DISK_ACCESS_READ,
|
||||
self.OPEN_VIRTUAL_DISK_FLAG_NONE, 0,
|
||||
ctypes.byref(handle))
|
||||
if ret_val:
|
||||
raise Exception("Cannot open virtual disk")
|
||||
self._handle = handle
|
||||
|
||||
def attach(self):
|
||||
ret_val = virtdisk.AttachVirtualDisk(
|
||||
self._handle, 0, self.ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY, 0, 0, 0)
|
||||
if ret_val:
|
||||
raise Exception("Cannot attach virtual disk")
|
||||
|
||||
def detach(self):
|
||||
ret_val = virtdisk.DetachVirtualDisk(
|
||||
self._handle, self.DETACH_VIRTUAL_DISK_FLAG_NONE, 0)
|
||||
if ret_val:
|
||||
raise Exception("Cannot detach virtual disk")
|
||||
|
||||
def get_physical_path(self):
|
||||
buf = ctypes.create_unicode_buffer(1024)
|
||||
bufLen = wintypes.DWORD(ctypes.sizeof(buf))
|
||||
ret_val = virtdisk.GetVirtualDiskPhysicalPath(self._handle,
|
||||
ctypes.byref(bufLen),
|
||||
buf)
|
||||
if ret_val:
|
||||
raise Exception("Cannot get virtual disk physical path")
|
||||
return buf.value
|
||||
|
||||
def get_cdrom_drive_mount_point(self):
|
||||
|
||||
mount_point = None
|
||||
|
||||
buf = ctypes.create_unicode_buffer(2048)
|
||||
buf_len = kernel32.GetLogicalDriveStringsW(
|
||||
ctypes.sizeof(buf) / ctypes.sizeof(wintypes.WCHAR), buf)
|
||||
if not buf_len:
|
||||
raise Exception("Cannot enumerate logical devices")
|
||||
|
||||
cdrom_dev = self.get_physical_path().rsplit('\\')[-1].upper()
|
||||
|
||||
i = 0
|
||||
while not mount_point and i < buf_len:
|
||||
curr_drive = ctypes.wstring_at(ctypes.addressof(buf) + i *
|
||||
ctypes.sizeof(wintypes.WCHAR))[:-1]
|
||||
|
||||
dev = ctypes.create_unicode_buffer(2048)
|
||||
ret_val = kernel32.QueryDosDeviceW(curr_drive, dev,
|
||||
ctypes.sizeof(dev) /
|
||||
ctypes.sizeof(wintypes.WCHAR))
|
||||
if not ret_val:
|
||||
raise Exception("Cannot query NT device")
|
||||
|
||||
if dev.value.rsplit('\\')[-1].upper() == cdrom_dev:
|
||||
mount_point = curr_drive
|
||||
else:
|
||||
i += len(curr_drive) + 2
|
||||
|
||||
return mount_point
|
||||
|
||||
def close(self):
|
||||
kernel32.CloseHandle(self._handle)
|
||||
self._handle = 0
|
||||
|
@ -1,123 +1,123 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import posixpath
|
||||
import urllib2
|
||||
import traceback
|
||||
import os
|
||||
|
||||
from cloudbaseinit.metadata.services import base
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('ec2_metadata_base_url',
|
||||
default='http://169.254.169.254/2009-04-04/',
|
||||
help='The base URL where the service looks for metadata'),
|
||||
]
|
||||
|
||||
ec2nodes = [
|
||||
'ami-id', 'ami-launch-index', 'ami-manifest-path', 'ancestor-ami-ids',
|
||||
'hostname', 'block-device-mapping', 'kernel-id',
|
||||
'placement/availability-zone', 'instance-action', 'instance-id',
|
||||
'instance-type', 'product-codes', 'local-hostname', 'local-ipv4',
|
||||
'public-hostname', 'public-ipv4', 'ramdisk-id', 'reservation-id',
|
||||
'security-groups', 'public-keys/', 'public-keys/0/',
|
||||
'public-keys/0/openssh-key', 'admin_pass']
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EC2Service(base.BaseMetadataService):
|
||||
def __init__(self):
|
||||
super(EC2Service, self).__init__()
|
||||
self._enable_retry = True
|
||||
self.error_count = 0
|
||||
|
||||
def load(self):
|
||||
super(EC2Service, self).load()
|
||||
try:
|
||||
self.get_meta_data('openstack')
|
||||
return True
|
||||
except Exception, err:
|
||||
LOG.debug(err)
|
||||
LOG.debug(traceback.format_exc())
|
||||
LOG.debug('Metadata not found at URL \'%s\'' %
|
||||
CONF.ec2_metadata_base_url)
|
||||
return False
|
||||
|
||||
def _get_data(self, path):
|
||||
data = {}
|
||||
LOG.debug("Check for EC2 interface availability...")
|
||||
if not self._check_EC2():
|
||||
raise Exception("EC2 interface is not available")
|
||||
|
||||
LOG.debug('Getting data for the path: %s' % path)
|
||||
if path.endswith('meta_data.json'):
|
||||
for key in ec2nodes:
|
||||
LOG.debug('Getting metadata from: %s' % key)
|
||||
try:
|
||||
data[key] = self._get_EC2_value(key)
|
||||
except:
|
||||
LOG.info("EC2 value %s is not available. Skip it." % key)
|
||||
# Saving keys to the local folder
|
||||
self._load_public_keys(data)
|
||||
|
||||
if path.endswith('user_data'):
|
||||
norm_path = posixpath.join(CONF.ec2_metadata_base_url, 'user-data')
|
||||
LOG.debug('Getting metadata from: %(norm_path)s' % locals())
|
||||
try:
|
||||
req = urllib2.Request(norm_path)
|
||||
response = urllib2.urlopen(req)
|
||||
data = response.read()
|
||||
LOG.debug("Got data: %s" % data)
|
||||
except:
|
||||
LOG.error("EC2 user-data is not available.")
|
||||
return data
|
||||
|
||||
def _check_EC2(self):
|
||||
try:
|
||||
data = self._get_EC2_value('')
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def _get_EC2_value(self, key):
|
||||
meta_path = posixpath.join(
|
||||
CONF.ec2_metadata_base_url, 'meta-data', key)
|
||||
req = urllib2.Request(meta_path)
|
||||
response = urllib2.urlopen(req)
|
||||
return response.read()
|
||||
|
||||
def _load_public_keys(self, data):
|
||||
try:
|
||||
key_list = self._get_EC2_value('public-keys/')
|
||||
LOG.debug("Got a list of keys %s" % key_list)
|
||||
data['public_keys'] = {}
|
||||
|
||||
for key_name in key_list.split('\n'):
|
||||
key_index = key_name.split('=')[0]
|
||||
LOG.debug('Loading key %s' % key_index)
|
||||
key = self._get_EC2_value(
|
||||
'public-keys/%s/openssh-key' % key_index)
|
||||
data['public_keys'].update({key_index: key})
|
||||
|
||||
except Exception, ex:
|
||||
LOG.debug("Can't save public key %s" % ex)
|
||||
LOG.debug(traceback.format_exc())
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import posixpath
|
||||
import urllib2
|
||||
import traceback
|
||||
import os
|
||||
|
||||
from cloudbaseinit.metadata.services import base
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('ec2_metadata_base_url',
|
||||
default='http://169.254.169.254/2009-04-04/',
|
||||
help='The base URL where the service looks for metadata'),
|
||||
]
|
||||
|
||||
ec2nodes = [
|
||||
'ami-id', 'ami-launch-index', 'ami-manifest-path', 'ancestor-ami-ids',
|
||||
'hostname', 'block-device-mapping', 'kernel-id',
|
||||
'placement/availability-zone', 'instance-action', 'instance-id',
|
||||
'instance-type', 'product-codes', 'local-hostname', 'local-ipv4',
|
||||
'public-hostname', 'public-ipv4', 'ramdisk-id', 'reservation-id',
|
||||
'security-groups', 'public-keys/', 'public-keys/0/',
|
||||
'public-keys/0/openssh-key', 'admin_pass']
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EC2Service(base.BaseMetadataService):
|
||||
def __init__(self):
|
||||
super(EC2Service, self).__init__()
|
||||
self._enable_retry = True
|
||||
self.error_count = 0
|
||||
|
||||
def load(self):
|
||||
super(EC2Service, self).load()
|
||||
try:
|
||||
self.get_meta_data('openstack')
|
||||
return True
|
||||
except Exception, err:
|
||||
LOG.debug(err)
|
||||
LOG.debug(traceback.format_exc())
|
||||
LOG.debug('Metadata not found at URL \'%s\'' %
|
||||
CONF.ec2_metadata_base_url)
|
||||
return False
|
||||
|
||||
def _get_data(self, path):
|
||||
data = {}
|
||||
LOG.debug("Check for EC2 interface availability...")
|
||||
if not self._check_EC2():
|
||||
raise Exception("EC2 interface is not available")
|
||||
|
||||
LOG.debug('Getting data for the path: %s' % path)
|
||||
if path.endswith('meta_data.json'):
|
||||
for key in ec2nodes:
|
||||
LOG.debug('Getting metadata from: %s' % key)
|
||||
try:
|
||||
data[key] = self._get_EC2_value(key)
|
||||
except:
|
||||
LOG.info("EC2 value %s is not available. Skip it." % key)
|
||||
# Saving keys to the local folder
|
||||
self._load_public_keys(data)
|
||||
|
||||
if path.endswith('user_data'):
|
||||
norm_path = posixpath.join(CONF.ec2_metadata_base_url, 'user-data')
|
||||
LOG.debug('Getting metadata from: %(norm_path)s' % locals())
|
||||
try:
|
||||
req = urllib2.Request(norm_path)
|
||||
response = urllib2.urlopen(req)
|
||||
data = response.read()
|
||||
LOG.debug("Got data: %s" % data)
|
||||
except:
|
||||
LOG.error("EC2 user-data is not available.")
|
||||
return data
|
||||
|
||||
def _check_EC2(self):
|
||||
try:
|
||||
data = self._get_EC2_value('')
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def _get_EC2_value(self, key):
|
||||
meta_path = posixpath.join(
|
||||
CONF.ec2_metadata_base_url, 'meta-data', key)
|
||||
req = urllib2.Request(meta_path)
|
||||
response = urllib2.urlopen(req)
|
||||
return response.read()
|
||||
|
||||
def _load_public_keys(self, data):
|
||||
try:
|
||||
key_list = self._get_EC2_value('public-keys/')
|
||||
LOG.debug("Got a list of keys %s" % key_list)
|
||||
data['public_keys'] = {}
|
||||
|
||||
for key_name in key_list.split('\n'):
|
||||
key_index = key_name.split('=')[0]
|
||||
LOG.debug('Loading key %s' % key_index)
|
||||
key = self._get_EC2_value(
|
||||
'public-keys/%s/openssh-key' % key_index)
|
||||
data['public_keys'].update({key_index: key})
|
||||
|
||||
except Exception, ex:
|
||||
LOG.debug("Can't save public key %s" % ex)
|
||||
LOG.debug(traceback.format_exc())
|
||||
|
@ -1,117 +1,117 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import posixpath
|
||||
import urllib2
|
||||
import urlparse
|
||||
|
||||
from cloudbaseinit.metadata.services import base
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
from cloudbaseinit.osutils import factory as osutils_factory
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('metadata_base_url', default='http://169.254.169.254/',
|
||||
help='The base URL where the service looks for metadata'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HttpService(base.BaseMetadataService):
|
||||
def __init__(self):
|
||||
super(HttpService, self).__init__()
|
||||
self._enable_retry = True
|
||||
|
||||
def _check_metadata_ip_route(self):
|
||||
'''
|
||||
Workaround for: https://bugs.launchpad.net/quantum/+bug/1174657
|
||||
'''
|
||||
osutils = osutils_factory.OSUtilsFactory().get_os_utils()
|
||||
|
||||
if osutils.check_os_version(6, 0):
|
||||
# 169.254.x.x addresses are not getting routed starting from
|
||||
# Windows Vista / 2008
|
||||
metadata_netloc = urlparse.urlparse(CONF.metadata_base_url).netloc
|
||||
metadata_host = metadata_netloc.split(':')[0]
|
||||
|
||||
if metadata_host.startswith("169.254."):
|
||||
if not osutils.check_static_route_exists(metadata_host):
|
||||
(interface_index, gateway) = osutils.get_default_gateway()
|
||||
if gateway:
|
||||
try:
|
||||
osutils.add_static_route(metadata_host,
|
||||
"255.255.255.255",
|
||||
gateway,
|
||||
interface_index,
|
||||
10)
|
||||
except Exception, ex:
|
||||
# Ignore it
|
||||
LOG.exception(ex)
|
||||
|
||||
def load(self):
|
||||
super(HttpService, self).load()
|
||||
|
||||
self._check_metadata_ip_route()
|
||||
|
||||
try:
|
||||
self.get_meta_data('openstack')
|
||||
return True
|
||||
except:
|
||||
LOG.debug('Metadata not found at URL \'%s\'' %
|
||||
CONF.metadata_base_url)
|
||||
return False
|
||||
|
||||
@property
|
||||
def can_post_password(self):
|
||||
return True
|
||||
|
||||
def _get_response(self, req):
|
||||
try:
|
||||
return urllib2.urlopen(req)
|
||||
except urllib2.HTTPError as ex:
|
||||
if ex.code == 404:
|
||||
raise base.NotExistingMetadataException()
|
||||
else:
|
||||
raise
|
||||
|
||||
def _get_data(self, path):
|
||||
norm_path = posixpath.join(CONF.metadata_base_url, path)
|
||||
LOG.debug('Getting metadata from: %(norm_path)s' % locals())
|
||||
req = urllib2.Request(norm_path)
|
||||
response = self._get_response(req)
|
||||
return response.read()
|
||||
|
||||
def _post_data(self, path, data):
|
||||
norm_path = posixpath.join(CONF.metadata_base_url, path)
|
||||
LOG.debug('Posting metadata to: %(norm_path)s' % locals())
|
||||
req = urllib2.Request(norm_path, data=data)
|
||||
self._get_response(req)
|
||||
return True
|
||||
|
||||
def post_password(self, enc_password_b64, version='latest'):
|
||||
try:
|
||||
return super(HttpService, self).post_password(enc_password_b64,
|
||||
version)
|
||||
except urllib2.HTTPError as ex:
|
||||
if ex.code == 409:
|
||||
# Password already set
|
||||
return False
|
||||
else:
|
||||
raise
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import posixpath
|
||||
import urllib2
|
||||
import urlparse
|
||||
|
||||
from cloudbaseinit.metadata.services import base
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
from cloudbaseinit.osutils import factory as osutils_factory
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('metadata_base_url', default='http://169.254.169.254/',
|
||||
help='The base URL where the service looks for metadata'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HttpService(base.BaseMetadataService):
|
||||
def __init__(self):
|
||||
super(HttpService, self).__init__()
|
||||
self._enable_retry = True
|
||||
|
||||
def _check_metadata_ip_route(self):
|
||||
'''
|
||||
Workaround for: https://bugs.launchpad.net/quantum/+bug/1174657
|
||||
'''
|
||||
osutils = osutils_factory.OSUtilsFactory().get_os_utils()
|
||||
|
||||
if osutils.check_os_version(6, 0):
|
||||
# 169.254.x.x addresses are not getting routed starting from
|
||||
# Windows Vista / 2008
|
||||
metadata_netloc = urlparse.urlparse(CONF.metadata_base_url).netloc
|
||||
metadata_host = metadata_netloc.split(':')[0]
|
||||
|
||||
if metadata_host.startswith("169.254."):
|
||||
if not osutils.check_static_route_exists(metadata_host):
|
||||
(interface_index, gateway) = osutils.get_default_gateway()
|
||||
if gateway:
|
||||
try:
|
||||
osutils.add_static_route(metadata_host,
|
||||
"255.255.255.255",
|
||||
gateway,
|
||||
interface_index,
|
||||
10)
|
||||
except Exception, ex:
|
||||
# Ignore it
|
||||
LOG.exception(ex)
|
||||
|
||||
def load(self):
|
||||
super(HttpService, self).load()
|
||||
|
||||
self._check_metadata_ip_route()
|
||||
|
||||
try:
|
||||
self.get_meta_data('openstack')
|
||||
return True
|
||||
except:
|
||||
LOG.debug('Metadata not found at URL \'%s\'' %
|
||||
CONF.metadata_base_url)
|
||||
return False
|
||||
|
||||
@property
|
||||
def can_post_password(self):
|
||||
return True
|
||||
|
||||
def _get_response(self, req):
|
||||
try:
|
||||
return urllib2.urlopen(req)
|
||||
except urllib2.HTTPError as ex:
|
||||
if ex.code == 404:
|
||||
raise base.NotExistingMetadataException()
|
||||
else:
|
||||
raise
|
||||
|
||||
def _get_data(self, path):
|
||||
norm_path = posixpath.join(CONF.metadata_base_url, path)
|
||||
LOG.debug('Getting metadata from: %(norm_path)s' % locals())
|
||||
req = urllib2.Request(norm_path)
|
||||
response = self._get_response(req)
|
||||
return response.read()
|
||||
|
||||
def _post_data(self, path, data):
|
||||
norm_path = posixpath.join(CONF.metadata_base_url, path)
|
||||
LOG.debug('Posting metadata to: %(norm_path)s' % locals())
|
||||
req = urllib2.Request(norm_path, data=data)
|
||||
self._get_response(req)
|
||||
return True
|
||||
|
||||
def post_password(self, enc_password_b64, version='latest'):
|
||||
try:
|
||||
return super(HttpService, self).post_password(enc_password_b64,
|
||||
version)
|
||||
except urllib2.HTTPError as ex:
|
||||
if ex.code == 409:
|
||||
# Password already set
|
||||
return False
|
||||
else:
|
||||
raise
|
||||
|
@ -1,52 +1,52 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.utils import classloader
|
||||
|
||||
opts = [
|
||||
cfg.ListOpt(
|
||||
'plugins',
|
||||
default=[
|
||||
'cloudbaseinit.plugins.windows.sethostname.SetHostNamePlugin',
|
||||
'cloudbaseinit.plugins.windows.createuser.CreateUserPlugin',
|
||||
'cloudbaseinit.plugins.windows.networkconfig.NetworkConfigPlugin',
|
||||
'cloudbaseinit.plugins.windows.sshpublickeys.'
|
||||
'SetUserSSHPublicKeysPlugin',
|
||||
'cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin',
|
||||
'cloudbaseinit.plugins.windows.userdata.UserDataPlugin',
|
||||
'cloudbaseinit.plugins.windows.setuserpassword.'
|
||||
'SetUserPasswordPlugin',
|
||||
'cloudbaseinit.plugins.windows.winrmlistener.'
|
||||
'ConfigWinRMListenerPlugin',
|
||||
'cloudbaseinit.plugins.windows.winrmcertificateauth.'
|
||||
'ConfigWinRMCertificateAuthPlugin',
|
||||
],
|
||||
help='List of enabled plugin classes, '
|
||||
'to executed in the provided order'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
|
||||
|
||||
class PluginFactory(object):
|
||||
def load_plugins(self):
|
||||
plugins = []
|
||||
cl = classloader.ClassLoader()
|
||||
for class_path in CONF.plugins:
|
||||
plugins.append(cl.load_class(class_path)())
|
||||
return plugins
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.utils import classloader
|
||||
|
||||
opts = [
|
||||
cfg.ListOpt(
|
||||
'plugins',
|
||||
default=[
|
||||
'cloudbaseinit.plugins.windows.sethostname.SetHostNamePlugin',
|
||||
'cloudbaseinit.plugins.windows.createuser.CreateUserPlugin',
|
||||
'cloudbaseinit.plugins.windows.networkconfig.NetworkConfigPlugin',
|
||||
'cloudbaseinit.plugins.windows.sshpublickeys.'
|
||||
'SetUserSSHPublicKeysPlugin',
|
||||
'cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin',
|
||||
'cloudbaseinit.plugins.windows.userdata.UserDataPlugin',
|
||||
'cloudbaseinit.plugins.windows.setuserpassword.'
|
||||
'SetUserPasswordPlugin',
|
||||
'cloudbaseinit.plugins.windows.winrmlistener.'
|
||||
'ConfigWinRMListenerPlugin',
|
||||
'cloudbaseinit.plugins.windows.winrmcertificateauth.'
|
||||
'ConfigWinRMCertificateAuthPlugin',
|
||||
],
|
||||
help='List of enabled plugin classes, '
|
||||
'to executed in the provided order'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
|
||||
|
||||
class PluginFactory(object):
|
||||
def load_plugins(self):
|
||||
plugins = []
|
||||
cl = classloader.ClassLoader()
|
||||
for class_path in CONF.plugins:
|
||||
plugins.append(cl.load_class(class_path)())
|
||||
return plugins
|
||||
|
@ -1,85 +1,85 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import re
|
||||
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
from cloudbaseinit.osutils import factory as osutils_factory
|
||||
from cloudbaseinit.plugins import base
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('network_adapter', default=None, help='Network adapter to '
|
||||
'configure. If not specified, the first available ethernet '
|
||||
'adapter will be chosen'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
|
||||
|
||||
class NetworkConfigPlugin(base.BasePlugin):
|
||||
def execute(self, service, shared_data):
|
||||
meta_data = service.get_meta_data('openstack')
|
||||
if 'network_config' not in meta_data:
|
||||
return (base.PLUGIN_EXECUTION_DONE, False)
|
||||
|
||||
network_config = meta_data['network_config']
|
||||
if 'content_path' not in network_config:
|
||||
return (base.PLUGIN_EXECUTION_DONE, False)
|
||||
|
||||
content_path = network_config['content_path']
|
||||
content_name = content_path.rsplit('/', 1)[-1]
|
||||
debian_network_conf = service.get_content('openstack', content_name)
|
||||
|
||||
LOG.debug('network config content:\n%s' % debian_network_conf)
|
||||
|
||||
# TODO (alexpilotti): implement a proper grammar
|
||||
m = re.search(r'iface eth0 inet static\s+'
|
||||
r'address\s+(?P<address>[^\s]+)\s+'
|
||||
r'netmask\s+(?P<netmask>[^\s]+)\s+'
|
||||
r'broadcast\s+(?P<broadcast>[^\s]+)\s+'
|
||||
r'gateway\s+(?P<gateway>[^\s]+)\s+'
|
||||
r'dns\-nameservers\s+(?P<dnsnameservers>[^\r\n]+)\s+',
|
||||
debian_network_conf)
|
||||
if not m:
|
||||
raise Exception("network_config format not recognized")
|
||||
|
||||
address = m.group('address')
|
||||
netmask = m.group('netmask')
|
||||
broadcast = m.group('broadcast')
|
||||
gateway = m.group('gateway')
|
||||
dnsnameservers = m.group('dnsnameservers').strip().split(' ')
|
||||
|
||||
osutils = osutils_factory.OSUtilsFactory().get_os_utils()
|
||||
|
||||
network_adapter_name = CONF.network_adapter
|
||||
if not network_adapter_name:
|
||||
# Get the first available one
|
||||
available_adapters = osutils.get_network_adapters()
|
||||
if not len(available_adapters):
|
||||
raise Exception("No network adapter available")
|
||||
network_adapter_name = available_adapters[0]
|
||||
|
||||
LOG.info('Configuring network adapter: \'%s\'' % network_adapter_name)
|
||||
|
||||
reboot_required = osutils.set_static_network_config(
|
||||
network_adapter_name, address, netmask, broadcast,
|
||||
gateway, dnsnameservers)
|
||||
|
||||
return (base.PLUGIN_EXECUTION_DONE, reboot_required)
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import re
|
||||
|
||||
from cloudbaseinit.openstack.common import cfg
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
from cloudbaseinit.osutils import factory as osutils_factory
|
||||
from cloudbaseinit.plugins import base
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('network_adapter', default=None, help='Network adapter to '
|
||||
'configure. If not specified, the first available ethernet '
|
||||
'adapter will be chosen'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
|
||||
|
||||
class NetworkConfigPlugin(base.BasePlugin):
|
||||
def execute(self, service, shared_data):
|
||||
meta_data = service.get_meta_data('openstack')
|
||||
if 'network_config' not in meta_data:
|
||||
return (base.PLUGIN_EXECUTION_DONE, False)
|
||||
|
||||
network_config = meta_data['network_config']
|
||||
if 'content_path' not in network_config:
|
||||
return (base.PLUGIN_EXECUTION_DONE, False)
|
||||
|
||||
content_path = network_config['content_path']
|
||||
content_name = content_path.rsplit('/', 1)[-1]
|
||||
debian_network_conf = service.get_content('openstack', content_name)
|
||||
|
||||
LOG.debug('network config content:\n%s' % debian_network_conf)
|
||||
|
||||
# TODO (alexpilotti): implement a proper grammar
|
||||
m = re.search(r'iface eth0 inet static\s+'
|
||||
r'address\s+(?P<address>[^\s]+)\s+'
|
||||
r'netmask\s+(?P<netmask>[^\s]+)\s+'
|
||||
r'broadcast\s+(?P<broadcast>[^\s]+)\s+'
|
||||
r'gateway\s+(?P<gateway>[^\s]+)\s+'
|
||||
r'dns\-nameservers\s+(?P<dnsnameservers>[^\r\n]+)\s+',
|
||||
debian_network_conf)
|
||||
if not m:
|
||||
raise Exception("network_config format not recognized")
|
||||
|
||||
address = m.group('address')
|
||||
netmask = m.group('netmask')
|
||||
broadcast = m.group('broadcast')
|
||||
gateway = m.group('gateway')
|
||||
dnsnameservers = m.group('dnsnameservers').strip().split(' ')
|
||||
|
||||
osutils = osutils_factory.OSUtilsFactory().get_os_utils()
|
||||
|
||||
network_adapter_name = CONF.network_adapter
|
||||
if not network_adapter_name:
|
||||
# Get the first available one
|
||||
available_adapters = osutils.get_network_adapters()
|
||||
if not len(available_adapters):
|
||||
raise Exception("No network adapter available")
|
||||
network_adapter_name = available_adapters[0]
|
||||
|
||||
LOG.info('Configuring network adapter: \'%s\'' % network_adapter_name)
|
||||
|
||||
reboot_required = osutils.set_static_network_config(
|
||||
network_adapter_name, address, netmask, broadcast,
|
||||
gateway, dnsnameservers)
|
||||
|
||||
return (base.PLUGIN_EXECUTION_DONE, reboot_required)
|
||||
|
@ -1,145 +1,145 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import email
|
||||
|
||||
from cloudbaseinit.metadata.services import base as metadata_services_base
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
from cloudbaseinit.plugins import base
|
||||
from cloudbaseinit.plugins.windows import userdatautils
|
||||
from cloudbaseinit.plugins.windows.userdataplugins import factory
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UserDataPlugin(base.BasePlugin):
|
||||
_part_handler_content_type = "text/part-handler"
|
||||
|
||||
def execute(self, service, shared_data):
|
||||
try:
|
||||
user_data = service.get_user_data('openstack')
|
||||
except metadata_services_base.NotExistingMetadataException:
|
||||
return (base.PLUGIN_EXECUTION_DONE, False)
|
||||
|
||||
if not user_data:
|
||||
return (base.PLUGIN_EXECUTION_DONE, False)
|
||||
|
||||
return self._process_user_data(user_data)
|
||||
|
||||
def _parse_mime(self, user_data):
|
||||
return email.message_from_string(user_data).walk()
|
||||
|
||||
def _process_user_data(self, user_data):
|
||||
plugin_status = base.PLUGIN_EXECUTION_DONE
|
||||
reboot = False
|
||||
|
||||
LOG.debug('User data content:\n%s' % user_data)
|
||||
if user_data.startswith('Content-Type: multipart'):
|
||||
user_data_plugins_factory = factory.UserDataPluginsFactory()
|
||||
user_data_plugins = user_data_plugins_factory.load_plugins()
|
||||
user_handlers = {}
|
||||
|
||||
for part in self._parse_mime(user_data):
|
||||
(plugin_status, reboot) = self._process_part(part,
|
||||
user_data_plugins,
|
||||
user_handlers)
|
||||
if reboot:
|
||||
break
|
||||
|
||||
if not reboot:
|
||||
for handler_func in list(set(user_handlers.values())):
|
||||
self._end_part_process_event(handler_func)
|
||||
|
||||
return (plugin_status, reboot)
|
||||
else:
|
||||
return self._process_non_multi_part(user_data)
|
||||
|
||||
def _process_part(self, part, user_data_plugins, user_handlers):
|
||||
ret_val = None
|
||||
try:
|
||||
content_type = part.get_content_type()
|
||||
|
||||
handler_func = user_handlers.get(content_type)
|
||||
if handler_func:
|
||||
LOG.debug("Calling user part handler for content type: %s" %
|
||||
content_type)
|
||||
handler_func(None, content_type, part.get_filename(),
|
||||
part.get_payload())
|
||||
else:
|
||||
user_data_plugin = user_data_plugins.get(content_type)
|
||||
if not user_data_plugin:
|
||||
LOG.info("Userdata plugin not found for content type: %s" %
|
||||
content_type)
|
||||
else:
|
||||
LOG.debug("Executing userdata plugin: %s" %
|
||||
user_data_plugin.__class__.__name__)
|
||||
|
||||
if content_type == self._part_handler_content_type:
|
||||
new_user_handlers = user_data_plugin.process(part)
|
||||
self._add_part_handlers(user_data_plugins,
|
||||
user_handlers,
|
||||
new_user_handlers)
|
||||
else:
|
||||
ret_val = user_data_plugin.process(part)
|
||||
except Exception, ex:
|
||||
LOG.error('Exception during multipart part handling: '
|
||||
'%(content_type)s, %(filename)s' %
|
||||
{'content_type': part.get_content_type(),
|
||||
'filename': part.get_filename()})
|
||||
LOG.exception(ex)
|
||||
|
||||
return self._get_plugin_return_value(ret_val)
|
||||
|
||||
def _add_part_handlers(self, user_data_plugins, user_handlers,
|
||||
new_user_handlers):
|
||||
handler_funcs = set()
|
||||
|
||||
for (content_type,
|
||||
handler_func) in new_user_handlers.items():
|
||||
if not user_data_plugins.get(content_type):
|
||||
LOG.info("Adding part handler for content "
|
||||
"type: %s" % content_type)
|
||||
user_handlers[content_type] = handler_func
|
||||
handler_funcs.add(handler_func)
|
||||
else:
|
||||
LOG.info("Skipping part handler for content type \"%s\" as it "
|
||||
"is already managed by a plugin" % content_type)
|
||||
|
||||
for handler_func in handler_funcs:
|
||||
self._begin_part_process_event(handler_func)
|
||||
|
||||
def _begin_part_process_event(self, handler_func):
|
||||
LOG.debug("Calling part handler \"__begin__\" event")
|
||||
handler_func(None, "__begin__", None, None)
|
||||
|
||||
def _end_part_process_event(self, handler_func):
|
||||
LOG.debug("Calling part handler \"__end__\" event")
|
||||
handler_func(None, "__end__", None, None)
|
||||
|
||||
def _get_plugin_return_value(self, ret_val):
|
||||
plugin_status = base.PLUGIN_EXECUTION_DONE
|
||||
reboot = False
|
||||
|
||||
if ret_val >= 1001 and ret_val <= 1003:
|
||||
reboot = bool(ret_val & 1)
|
||||
if ret_val & 2:
|
||||
plugin_status = base.PLUGIN_EXECUTE_ON_NEXT_BOOT
|
||||
|
||||
return (plugin_status, reboot)
|
||||
|
||||
def _process_non_multi_part(self, user_data):
|
||||
ret_val = userdatautils.execute_user_data_script(user_data)
|
||||
return self._get_plugin_return_value(ret_val)
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import email
|
||||
|
||||
from cloudbaseinit.metadata.services import base as metadata_services_base
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
from cloudbaseinit.plugins import base
|
||||
from cloudbaseinit.plugins.windows import userdatautils
|
||||
from cloudbaseinit.plugins.windows.userdataplugins import factory
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UserDataPlugin(base.BasePlugin):
|
||||
_part_handler_content_type = "text/part-handler"
|
||||
|
||||
def execute(self, service, shared_data):
|
||||
try:
|
||||
user_data = service.get_user_data('openstack')
|
||||
except metadata_services_base.NotExistingMetadataException:
|
||||
return (base.PLUGIN_EXECUTION_DONE, False)
|
||||
|
||||
if not user_data:
|
||||
return (base.PLUGIN_EXECUTION_DONE, False)
|
||||
|
||||
return self._process_user_data(user_data)
|
||||
|
||||
def _parse_mime(self, user_data):
|
||||
return email.message_from_string(user_data).walk()
|
||||
|
||||
def _process_user_data(self, user_data):
|
||||
plugin_status = base.PLUGIN_EXECUTION_DONE
|
||||
reboot = False
|
||||
|
||||
LOG.debug('User data content:\n%s' % user_data)
|
||||
if user_data.startswith('Content-Type: multipart'):
|
||||
user_data_plugins_factory = factory.UserDataPluginsFactory()
|
||||
user_data_plugins = user_data_plugins_factory.load_plugins()
|
||||
user_handlers = {}
|
||||
|
||||
for part in self._parse_mime(user_data):
|
||||
(plugin_status, reboot) = self._process_part(part,
|
||||
user_data_plugins,
|
||||
user_handlers)
|
||||
if reboot:
|
||||
break
|
||||
|
||||
if not reboot:
|
||||
for handler_func in list(set(user_handlers.values())):
|
||||
self._end_part_process_event(handler_func)
|
||||
|
||||
return (plugin_status, reboot)
|
||||
else:
|
||||
return self._process_non_multi_part(user_data)
|
||||
|
||||
def _process_part(self, part, user_data_plugins, user_handlers):
|
||||
ret_val = None
|
||||
try:
|
||||
content_type = part.get_content_type()
|
||||
|
||||
handler_func = user_handlers.get(content_type)
|
||||
if handler_func:
|
||||
LOG.debug("Calling user part handler for content type: %s" %
|
||||
content_type)
|
||||
handler_func(None, content_type, part.get_filename(),
|
||||
part.get_payload())
|
||||
else:
|
||||
user_data_plugin = user_data_plugins.get(content_type)
|
||||
if not user_data_plugin:
|
||||
LOG.info("Userdata plugin not found for content type: %s" %
|
||||
content_type)
|
||||
else:
|
||||
LOG.debug("Executing userdata plugin: %s" %
|
||||
user_data_plugin.__class__.__name__)
|
||||
|
||||
if content_type == self._part_handler_content_type:
|
||||
new_user_handlers = user_data_plugin.process(part)
|
||||
self._add_part_handlers(user_data_plugins,
|
||||
user_handlers,
|
||||
new_user_handlers)
|
||||
else:
|
||||
ret_val = user_data_plugin.process(part)
|
||||
except Exception, ex:
|
||||
LOG.error('Exception during multipart part handling: '
|
||||
'%(content_type)s, %(filename)s' %
|
||||
{'content_type': part.get_content_type(),
|
||||
'filename': part.get_filename()})
|
||||
LOG.exception(ex)
|
||||
|
||||
return self._get_plugin_return_value(ret_val)
|
||||
|
||||
def _add_part_handlers(self, user_data_plugins, user_handlers,
|
||||
new_user_handlers):
|
||||
handler_funcs = set()
|
||||
|
||||
for (content_type,
|
||||
handler_func) in new_user_handlers.items():
|
||||
if not user_data_plugins.get(content_type):
|
||||
LOG.info("Adding part handler for content "
|
||||
"type: %s" % content_type)
|
||||
user_handlers[content_type] = handler_func
|
||||
handler_funcs.add(handler_func)
|
||||
else:
|
||||
LOG.info("Skipping part handler for content type \"%s\" as it "
|
||||
"is already managed by a plugin" % content_type)
|
||||
|
||||
for handler_func in handler_funcs:
|
||||
self._begin_part_process_event(handler_func)
|
||||
|
||||
def _begin_part_process_event(self, handler_func):
|
||||
LOG.debug("Calling part handler \"__begin__\" event")
|
||||
handler_func(None, "__begin__", None, None)
|
||||
|
||||
def _end_part_process_event(self, handler_func):
|
||||
LOG.debug("Calling part handler \"__end__\" event")
|
||||
handler_func(None, "__end__", None, None)
|
||||
|
||||
def _get_plugin_return_value(self, ret_val):
|
||||
plugin_status = base.PLUGIN_EXECUTION_DONE
|
||||
reboot = False
|
||||
|
||||
if ret_val >= 1001 and ret_val <= 1003:
|
||||
reboot = bool(ret_val & 1)
|
||||
if ret_val & 2:
|
||||
plugin_status = base.PLUGIN_EXECUTE_ON_NEXT_BOOT
|
||||
|
||||
return (plugin_status, reboot)
|
||||
|
||||
def _process_non_multi_part(self, user_data):
|
||||
ret_val = userdatautils.execute_user_data_script(user_data)
|
||||
return self._get_plugin_return_value(ret_val)
|
||||
|
Loading…
Reference in New Issue
Block a user