
from __future__ import absolute_import
from __future__ import division


from vdsm.common import xmlutils
from vdsm.virt.vmdevices import core
from vdsm.virt.vmdevices import hwclass
from vdsm.virt import vmxml


def device_from_xml_alias(devices, device_xml):
    dev = xmlutils.fromstring(device_xml)
    alias = core.find_device_alias(dev)
    return device_by_alias(devices, alias)


def drive_from_element(disk_devices, disk_element):
    serial_elem = vmxml.find_first(disk_element, 'serial', None)
    if serial_elem is not None:
        serial = vmxml.text(serial_elem)
        try:
            return drive_by_serial(disk_devices, serial)
        except LookupError:

    alias = core.find_device_alias(disk_element)
    return device_by_alias(disk_devices, alias)


def device_by_alias(devices, alias):
    for device in devices:
        if getattr(device, 'alias', None) == alias:
            return device
    raise LookupError("No such device: alias=%r" % alias)


def hotpluggable_device_by_alias(device_dict, alias):
    for device_hwclass in hwclass.HOTPLUGGABLE:
        try:
            return device_by_alias(device_dict[device_hwclass][:], alias), \
                device_hwclass
        except LookupError:
            pass
    raise LookupError("No such device: alias=%r" % alias)


def drive_by_serial(disk_devices, serial):
    for device in disk_devices:
        if device.serial == serial:
            return device
    raise LookupError("No such drive: '%s'" % serial)


def drive_by_name(disk_devices, name):
    for device in disk_devices:
        if device.name == name:
            return device
    raise LookupError("No such drive: '%s'" % name)


def conf_by_alias(conf, dev_type, alias):
    for dev_conf in conf[:]:
        try:
            if dev_conf['alias'] == alias and dev_conf['type'] == dev_type:
                return dev_conf
        except KeyError:
            continue
    raise LookupError('Configuration of device identified by alias %s '
                      'and type %s not found' % (alias, dev_type,))


def conf_by_path(conf, path):
    for dev_conf in conf[:]:
        if dev_conf.get('path') == path:
            return dev_conf
    raise LookupError(
        'Configuration of device with path %r not found' % path)
