#! /usr/bin/python2.6
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
#
"""
ChainBootInstance autogenerator backend for pybootmgmt
"""
from solaris_install import Popen, CalledProcessError
from bootmgmt import BootmgmtUnsupportedOperationError
from bootmgmt.bootconfig import BootConfig, ChainDiskBootInstance
from bootmgmt.bootutil import LoggerMixin, get_current_arch_string
from bootmgmt.bootinfo import SystemFirmware
class ChainDiskBootInstanceAutogenerator(LoggerMixin):
"""Autogenerator implementation for ChainDiskBootInstance generation.
This implementation invokes a helper script that scans the system's
disks for OS instances that can be chainloaded, then outputs information
in an easily-parseable format.
"""
def autogen(self, bootconfig):
"The workhorse of the autogenerator"
if bootconfig.boot_class != BootConfig.BOOT_CLASS_DISK:
raise BootmgmtUnsupportedOperationError('Chain loader autogen '
'not supported on non-disk BootConfigs')
cur_fw = SystemFirmware.get()
if cur_fw is not None:
cur_fw_name = cur_fw.fw_name
else:
cur_fw_name = None
# This is only supported on x86 BIOS:
if get_current_arch_string() != 'x86' or cur_fw_name != 'bios':
self._debug('Chainloader entry autogeneration only supported on '
'x86 BIOS')
return []
try:
helper_cmd = ['/usr/lib/boot/bootmgmt-helper-chain']
script_output = Popen.check_call(helper_cmd, stdout=Popen.STORE,
stderr=Popen.STORE)
script_stdout = script_output.stdout
except OSError as error_exc:
self._debug('Executing helper script failed: %s', error_exc)
return []
except CalledProcessError as cpe:
self._debug('Helper script returned %d', cpe.returncode)
if cpe.popen and cpe.popen.stdout:
self._debug('stdout was: %s\n', cpe.popen.stdout)
if cpe.popen and cpe.popen.stderr:
self._debug('stderr was: %s\n', cpe.popen.stderr)
return []
inst_list = []
lineno = 0
for line in script_stdout.splitlines():
lineno += 1
self._debug('Output line %d: "%s"', (lineno, line))
if line.startswith('#') or line.strip() == '':
continue
try:
title, disk, partition, active = line.split(':')
disk = int(disk)
# partition can be empty, an int or a comma-separated list of
# strings
if partition.strip() != '':
if partition.find(',') != -1:
partition = tuple(partition.split(','))
else:
partition = int(partition)
else:
partition = None
active = True if active == 'True' else False
except ValueError:
self._debug('Malformed output line from helper: "%s"', line)
continue
if partition is None:
chain_info = (disk,)
else:
chain_info = (disk, partition)
bootinst = ChainDiskBootInstance(None, title=title,
chaininfo=chain_info,
forceactive=active)
inst_list.append(bootinst)
self._debug('%d line(s) read from helper script.', lineno)
self._debug('%d boot instances autogenerated.', len(inst_list))
return inst_list
def autogenerate_boot_instances(bootconfig):
"Main entry point used by the autogenerator factory"
cdbia = ChainDiskBootInstanceAutogenerator()
return cdbia.autogen(bootconfig)