#! /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.
#
"""
Various bootloader interfaces for pybootmgmt
"""
import sys
from bootmgmt import BootmgmtError, BootmgmtInvalidBootloaderError
from bootmgmt.bootutil import LoggerMixin
from bootmgmt.bootloader import BootLoader, ProxyBootLoader
BOOT_LOADER_BACKENDS = ['grub2', 'legacygrub', 'sbb']
class BackendBootLoaderFactory(LoggerMixin):
"""Factory that returns BootLoader instances.
"""
@classmethod
def get(cls, **kwargs):
"""Returns an instance of bootloader.BootLoader appropriate for the
system identified by the keyword arguments passed in. Invokes a
probe function for each boot loader backend, and returns the loader
whose probe function returned the highest rank value. If multiple
boot loaders' probe functions succeed, a ProxyBootLoader instance is
returned that will manage access to both BootLoader instances.
"""
loaderlist = []
loader_instance = None
for loader in BOOT_LOADER_BACKENDS:
blmod = __name__ + '.' + loader
__import__(blmod, level=0)
namespc = sys.modules[blmod]
for loaderclass in namespc.bootloader_classes():
try:
loaderinst = loaderclass.probe(**kwargs)
if not loaderinst is None:
cls._debug('[PROBE SUCCEEDED] class %s',
loaderinst.__class__.__name__)
loaderlist.append(loaderinst)
except BootmgmtError as bmerr:
cls._debug('Exception during probe: %s', bmerr)
loaderclass = kwargs.get('loaderclass')
if loaderclass:
loaders = [x for x in loaderlist if isinstance(x, loaderclass)]
if len(loaders) == 0:
raise BootmgmtInvalidBootloaderError('Could not find an '
'instance of BootLoader class %s' % loaderclass.__name__)
cls._debug('OVERRIDDEN [class=%s] loaderlist => %s',
(loaderclass.__name__, loaders))
return loaders[0]
# Sort the loader list by decreasing rank:
loaderlist.sort(cmp=\
ProxyBootLoader.bootloader_cmp_by_artifacts_and_weight,
reverse=True)
cls._debug('loaderlist => %s', loaderlist)
if len(loaderlist) > 1:
bcfg = kwargs.get('bootconfig')
if bcfg and getattr(bcfg, 'EXCLUSIVE_LOADER', False):
cls._debug('boot config with exclusive loader requirement '
'detected')
loader_instance = loaderlist[0]
else:
cls._debug('Creating ProxyBootLoader with primary=%s, '
'secondary=%s', (repr(loaderlist[0]), repr(loaderlist[1])))
loader_instance = ProxyBootLoader(loaderlist[0], loaderlist[1])
elif len(loaderlist) > 0:
loader_instance = loaderlist[0]
return loader_instance