
Add both nova and neutron dom0 plugins, and only keep the ones with .py suffix, also change the plugin version to 2.0 Change-Id: I71f4640866efa48a0de7bfd2f86cc5f1293835f9
141 lines
4.1 KiB
Python
141 lines
4.1 KiB
Python
#!/usr/bin/env python
|
|
|
|
# Copyright (c) 2013 OpenStack Foundation
|
|
#
|
|
# 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.
|
|
|
|
# NOTE: XenServer still only supports Python 2.4 in it's dom0 userspace
|
|
# which means the Nova xenapi plugins must use only Python 2.4 features
|
|
|
|
# TODO(sfinucan): Resolve all 'noqa' items once the above is no longer true
|
|
|
|
"""Inject network configuration into iPXE ISO for boot."""
|
|
|
|
import logging
|
|
import os
|
|
import shutil
|
|
|
|
import utils
|
|
|
|
# FIXME(sirp): should this use pluginlib from 5.6?
|
|
import dom0_pluginlib
|
|
dom0_pluginlib.configure_logging('ipxe')
|
|
|
|
|
|
ISOLINUX_CFG = """SAY iPXE ISO boot image
|
|
TIMEOUT 30
|
|
DEFAULT ipxe.krn
|
|
LABEL ipxe.krn
|
|
KERNEL ipxe.krn
|
|
INITRD netcfg.ipxe
|
|
"""
|
|
|
|
NETCFG_IPXE = """#!ipxe
|
|
:start
|
|
imgfree
|
|
ifclose net0
|
|
set net0/ip %(ip_address)s
|
|
set net0/netmask %(netmask)s
|
|
set net0/gateway %(gateway)s
|
|
set dns %(dns)s
|
|
ifopen net0
|
|
goto menu
|
|
|
|
:menu
|
|
chain %(boot_menu_url)s
|
|
goto boot
|
|
|
|
:boot
|
|
sanboot --no-describe --drive 0x80
|
|
"""
|
|
|
|
|
|
def _write_file(filename, data):
|
|
# If the ISO was tampered with such that the destination is a symlink,
|
|
# that could allow a malicious user to write to protected areas of the
|
|
# dom0 filesystem. /HT to comstud for pointing this out.
|
|
#
|
|
# Short-term, checking that the destination is not a symlink should be
|
|
# sufficient.
|
|
#
|
|
# Long-term, we probably want to perform all file manipulations within a
|
|
# chroot jail to be extra safe.
|
|
if os.path.islink(filename):
|
|
raise RuntimeError('SECURITY: Cannot write to symlinked destination')
|
|
|
|
logging.debug("Writing to file '%s'" % filename)
|
|
f = open(filename, 'w')
|
|
try:
|
|
f.write(data)
|
|
finally:
|
|
f.close()
|
|
|
|
|
|
def _unbundle_iso(sr_path, filename, path):
|
|
logging.debug("Unbundling ISO '%s'" % filename)
|
|
read_only_path = utils.make_staging_area(sr_path)
|
|
try:
|
|
utils.run_command(['mount', '-o', 'loop', filename, read_only_path])
|
|
try:
|
|
shutil.copytree(read_only_path, path)
|
|
finally:
|
|
utils.run_command(['umount', read_only_path])
|
|
finally:
|
|
utils.cleanup_staging_area(read_only_path)
|
|
|
|
|
|
def _create_iso(mkisofs_cmd, filename, path):
|
|
logging.debug("Creating ISO '%s'..." % filename)
|
|
orig_dir = os.getcwd()
|
|
os.chdir(path)
|
|
try:
|
|
utils.run_command([mkisofs_cmd, '-quiet', '-l', '-o', filename,
|
|
'-c', 'boot.cat', '-b', 'isolinux.bin',
|
|
'-no-emul-boot', '-boot-load-size', '4',
|
|
'-boot-info-table', '.'])
|
|
finally:
|
|
os.chdir(orig_dir)
|
|
|
|
|
|
def inject(session, sr_path, vdi_uuid, boot_menu_url, ip_address, netmask,
|
|
gateway, dns, mkisofs_cmd):
|
|
|
|
iso_filename = '%s.img' % os.path.join(sr_path, 'iso', vdi_uuid)
|
|
|
|
# Create staging area so we have a unique path but remove it since
|
|
# shutil.copytree will recreate it
|
|
staging_path = utils.make_staging_area(sr_path)
|
|
utils.cleanup_staging_area(staging_path)
|
|
|
|
try:
|
|
_unbundle_iso(sr_path, iso_filename, staging_path)
|
|
|
|
# Write Configs
|
|
_write_file(os.path.join(staging_path, 'netcfg.ipxe'),
|
|
NETCFG_IPXE % {"ip_address": ip_address,
|
|
"netmask": netmask,
|
|
"gateway": gateway,
|
|
"dns": dns,
|
|
"boot_menu_url": boot_menu_url})
|
|
|
|
_write_file(os.path.join(staging_path, 'isolinux.cfg'),
|
|
ISOLINUX_CFG)
|
|
|
|
_create_iso(mkisofs_cmd, iso_filename, staging_path)
|
|
finally:
|
|
utils.cleanup_staging_area(staging_path)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
utils.register_plugin_calls(inject)
|