# Copyright 2013 Red Hat, Inc.
# All Rights Reserved.
#
#    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 collections

from oslo_concurrency import lockutils
from oslo_config import cfg
from oslo_log import log
from stevedore import dispatch

from ironic.common import exception
from ironic.common.i18n import _
from ironic.common.i18n import _LI
from ironic.common.i18n import _LW
from ironic.drivers import base as driver_base


LOG = log.getLogger(__name__)

driver_opts = [
    cfg.ListOpt('enabled_drivers',
                default=['pxe_ipmitool'],
                help=_('Specify the list of drivers to load during service '
                       'initialization. Missing drivers, or drivers which '
                       'fail to initialize, will prevent the conductor '
                       'service from starting. The option default is a '
                       'recommended set of production-oriented drivers. A '
                       'complete list of drivers present on your system may '
                       'be found by enumerating the "ironic.drivers" '
                       'entrypoint. An example may be found in the '
                       'developer documentation online.')),
    cfg.ListOpt('enabled_network_interfaces',
                default=['flat', 'noop'],
                help=_('Specify the list of network interfaces to load during '
                       'service initialization. Missing network interfaces, '
                       'or network interfaces which fail to initialize, will '
                       'prevent the conductor service from starting. The '
                       'option default is a recommended set of '
                       'production-oriented network interfaces. A complete '
                       'list of network interfaces present on your system may '
                       'be found by enumerating the '
                       '"ironic.hardware.interfaces.network" entrypoint.')),
    cfg.StrOpt('default_network_interface',
               help=_('Default network interface to be used for nodes that '
                      'do not have network_interface field set. A complete '
                      'list of network interfaces present on your system may '
                      'be found by enumerating the '
                      '"ironic.hardware.interfaces.network" entrypoint.'))
]

CONF = cfg.CONF
CONF.register_opts(driver_opts)

EM_SEMAPHORE = 'extension_manager'


def build_driver_for_task(task, driver_name=None):
    """Builds a composable driver for a given task.

    Starts with a `BareDriver` object, and attaches implementations of the
    various driver interfaces to it. Currently these all come from the
    monolithic driver singleton, but later will come from separate
    driver factories and configurable via the database.

    :param task: The task containing the node to build a driver for.
    :param driver_name: The name of the monolithic driver to use as a base,
                        if different than task.node.driver.
    :returns: A driver object for the task.
    :raises: DriverNotFound if node.driver could not be
             found in the "ironic.drivers" namespace.
    """
    node = task.node
    driver = driver_base.BareDriver()
    _attach_interfaces_to_driver(driver, node, driver_name=driver_name)
    return driver


def _attach_interfaces_to_driver(driver, node, driver_name=None):
    driver_singleton = get_driver(driver_name or node.driver)
    for iface in driver_singleton.all_interfaces:
        impl = getattr(driver_singleton, iface, None)