¡@

Home 

OpenStack Study: block_device.py

OpenStack Index

**** CubicPower OpenStack Study ****

# Copyright 2011 Isaku Yamahata

# 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 re

from oslo.config import cfg

from nova import exception

from nova.openstack.common.gettextutils import _

from nova.openstack.common import log as logging

from nova.openstack.common import strutils

from nova import utils

from nova.virt import driver

CONF = cfg.CONF

CONF.import_opt('default_ephemeral_format', 'nova.virt.driver')

LOG = logging.getLogger(__name__)

DEFAULT_ROOT_DEV_NAME = '/dev/sda1'

_DEFAULT_MAPPINGS = {'ami': 'sda1',

'ephemeral0': 'sda2',

'root': DEFAULT_ROOT_DEV_NAME,

'swap': 'sda3'}

bdm_legacy_fields = set(['device_name', 'delete_on_termination',

'virtual_name', 'snapshot_id',

'volume_id', 'volume_size', 'no_device',

'connection_info'])

bdm_new_fields = set(['source_type', 'destination_type',

'guest_format', 'device_type', 'disk_bus', 'boot_index',

'device_name', 'delete_on_termination', 'snapshot_id',

'volume_id', 'volume_size', 'image_id', 'no_device',

'connection_info'])

bdm_db_only_fields = set(['id', 'instance_uuid'])

bdm_db_inherited_fields = set(['created_at', 'updated_at',

'deleted_at', 'deleted'])

bdm_new_non_api_fields = set(['volume_id', 'snapshot_id',

'image_id', 'connection_info'])

bdm_new_api_only_fields = set(['uuid'])

bdm_new_api_fields = ((bdm_new_fields - bdm_new_non_api_fields) |

bdm_new_api_only_fields)

**** CubicPower OpenStack Study ****

class BlockDeviceDict(dict):

"""Represents a Block Device Mapping in Nova."""

_fields = bdm_new_fields

_db_only_fields = (bdm_db_only_fields |

bdm_db_inherited_fields)

_required_fields = set(['source_type'])

**** CubicPower OpenStack Study ****

    def __init__(self, bdm_dict=None, do_not_default=None):

        super(BlockDeviceDict, self).__init__()

        bdm_dict = bdm_dict or {}

        do_not_default = do_not_default or set()

        self._validate(bdm_dict)

        # NOTE (ndipanov): Never default db fields

        self.update(

            dict((field, None)

                 for field in self._fields - do_not_default))

        self.update(list(bdm_dict.iteritems()))

**** CubicPower OpenStack Study ****

    def _validate(self, bdm_dict):

        """Basic data format validations."""

        dict_fields = set(key for key, _ in bdm_dict.iteritems())

        # Check that there are no bogus fields

        if not (dict_fields <=

                (self._fields | self._db_only_fields)):

            raise exception.InvalidBDMFormat(

                details="Some fields are invalid.")

        if bdm_dict.get('no_device'):

            return

        # Check that all required fields are there

        if (self._required_fields and

                not ((dict_fields & self._required_fields) ==

                      self._required_fields)):

            raise exception.InvalidBDMFormat(

                details="Some required fields are missing")

        if 'delete_on_termination' in bdm_dict:

            bdm_dict['delete_on_termination'] = strutils.bool_from_string(

                bdm_dict['delete_on_termination'])

        if bdm_dict.get('device_name') is not None:

            validate_device_name(bdm_dict['device_name'])

        validate_and_default_volume_size(bdm_dict)

        if bdm_dict.get('boot_index'):

            try:

                bdm_dict['boot_index'] = int(bdm_dict['boot_index'])

            except ValueError:

                raise exception.InvalidBDMFormat(

                    details="Boot index is invalid.")

    @classmethod

**** CubicPower OpenStack Study ****

    def from_legacy(cls, legacy_bdm):

        copy_over_fields = bdm_legacy_fields & bdm_new_fields

        copy_over_fields |= (bdm_db_only_fields |

                             bdm_db_inherited_fields)

        # NOTE (ndipanov): These fields cannot be computed

        # from legacy bdm, so do not default them

        # to avoid overwriting meaningful values in the db

        non_computable_fields = set(['boot_index', 'disk_bus',

                                     'guest_format', 'device_type'])

        new_bdm = dict((fld, val) for fld, val in legacy_bdm.iteritems()

                        if fld in copy_over_fields)

        virt_name = legacy_bdm.get('virtual_name')

        if is_swap_or_ephemeral(virt_name):

            new_bdm['source_type'] = 'blank'

            new_bdm['delete_on_termination'] = True

            new_bdm['destination_type'] = 'local'

            if virt_name == 'swap':

                new_bdm['guest_format'] = 'swap'

            else:

                new_bdm['guest_format'] = CONF.default_ephemeral_format

        elif legacy_bdm.get('snapshot_id'):

            new_bdm['source_type'] = 'snapshot'

            new_bdm['destination_type'] = 'volume'

        elif legacy_bdm.get('volume_id'):

            new_bdm['source_type'] = 'volume'

            new_bdm['destination_type'] = 'volume'

        elif legacy_bdm.get('no_device'):

            # NOTE (ndipanov): Just keep the BDM for now,

            pass

        else:

            raise exception.InvalidBDMFormat(

                details="Unrecognized legacy format.")

        return cls(new_bdm, non_computable_fields)

    @classmethod

**** CubicPower OpenStack Study ****

    def from_api(cls, api_dict):

        """Transform the API format of data to the internally used one.

        Only validate if the source_type field makes sense.

        """

        if not api_dict.get('no_device'):

            source_type = api_dict.get('source_type')

            device_uuid = api_dict.get('uuid')

            if source_type not in ('volume', 'image', 'snapshot', 'blank'):

                raise exception.InvalidBDMFormat(

                    details="Invalid source_type field.")

            elif source_type != 'blank':

                if not device_uuid:

                    raise exception.InvalidBDMFormat(

                        details="Missing device UUID.")

                api_dict[source_type + '_id'] = device_uuid

        api_dict.pop('uuid', None)

        return cls(api_dict)

**** CubicPower OpenStack Study ****

    def legacy(self):

        copy_over_fields = bdm_legacy_fields - set(['virtual_name'])

        copy_over_fields |= (bdm_db_only_fields |

                             bdm_db_inherited_fields)

        legacy_block_device = dict((field, self.get(field))

            for field in copy_over_fields if field in self)

        source_type = self.get('source_type')

        destination_type = self.get('destination_type')

        no_device = self.get('no_device')

        if source_type == 'blank':

            if self['guest_format'] == 'swap':

                legacy_block_device['virtual_name'] = 'swap'

            else:

                # NOTE (ndipanov): Always label as 0, it is up to

                # the calling routine to re-enumerate them

                legacy_block_device['virtual_name'] = 'ephemeral0'

        elif source_type in ('volume', 'snapshot') or no_device:

            legacy_block_device['virtual_name'] = None

        elif source_type == 'image':

            if destination_type != 'volume':

            # NOTE(ndipanov): Image bdms with local destination

            # have no meaning in the legacy format - raise

                raise exception.InvalidBDMForLegacy()

            legacy_block_device['virtual_name'] = None

        return legacy_block_device

**** CubicPower OpenStack Study ****

    def get_image_mapping(self):

        drop_fields = (set(['connection_info', 'device_name']) |

                       self._db_only_fields)

        mapping_dict = dict(self)

        for fld in drop_fields:

            mapping_dict.pop(fld, None)

        return mapping_dict

def is_safe_for_update(block_device_dict):

    """Determine if passed dict is a safe subset for update.

    Safe subset in this case means a safe subset of both legacy

    and new versions of data, that can be passed to an UPDATE query

    without any transformation.

    """

    fields = set(block_device_dict.keys())

    return fields <= (bdm_new_fields |

                      bdm_db_inherited_fields |

                      bdm_db_only_fields)

def create_image_bdm(image_ref, boot_index=0):

    """Create a block device dict based on the image_ref.

    This is useful in the API layer to keep the compatibility

    with having an image_ref as a field in the instance requests

    """

    return BlockDeviceDict(

        {'source_type': 'image',

         'image_id': image_ref,

         'delete_on_termination': True,

         'boot_index': boot_index,

         'device_type': 'disk',

         'destination_type': 'local'})

def snapshot_from_bdm(snapshot_id, template):

    """Create a basic volume snapshot BDM from a given template bdm."""

    copy_from_template = ['disk_bus', 'device_type', 'boot_index']

    snapshot_dict = {'source_type': 'snapshot',

                     'destination_type': 'volume',

                     'snapshot_id': snapshot_id}

    for key in copy_from_template:

        snapshot_dict[key] = template.get(key)

    return BlockDeviceDict(snapshot_dict)

def legacy_mapping(block_device_mapping):

    """Transform a list of block devices of an instance back to the

    legacy data format.

    """

    legacy_block_device_mapping = []

    for bdm in block_device_mapping:

        try:

            legacy_block_device = BlockDeviceDict(bdm).legacy()

        except exception.InvalidBDMForLegacy:

            continue

        legacy_block_device_mapping.append(legacy_block_device)

    # Re-enumerate the ephemeral devices

    for i, dev in enumerate(dev for dev in legacy_block_device_mapping

                            if dev['virtual_name'] and

                            is_ephemeral(dev['virtual_name'])):

        dev['virtual_name'] = dev['virtual_name'][:-1] + str(i)

    return legacy_block_device_mapping

def from_legacy_mapping(legacy_block_device_mapping, image_uuid='',

                        root_device_name=None, no_root=False):

    """Transform a legacy list of block devices to the new data format."""

    new_bdms = [BlockDeviceDict.from_legacy(legacy_bdm)

                for legacy_bdm in legacy_block_device_mapping]

    # NOTE (ndipanov): We will not decide which device is root here - we assume

    # that it will be supplied later. This is useful for having the root device

    # as part of the image defined mappings that are already in the v2 format.

    if no_root:

        for bdm in new_bdms:

            bdm['boot_index'] = -1

        return new_bdms

    image_bdm = None

    volume_backed = False

    # Try to assign boot_device

    if not root_device_name and not image_uuid:

        # NOTE (ndipanov): If there is no root_device, pick the first non

        #                  blank one.

        non_blank = [bdm for bdm in new_bdms if bdm['source_type'] != 'blank']

        if non_blank:

            non_blank[0]['boot_index'] = 0

    else:

        for bdm in new_bdms:

            if (bdm['source_type'] in ('volume', 'snapshot', 'image') and

                    root_device_name is not None and

                    (strip_dev(bdm.get('device_name')) ==

                     strip_dev(root_device_name))):

                bdm['boot_index'] = 0

                volume_backed = True

            elif not bdm['no_device']:

                bdm['boot_index'] = -1

            else:

                bdm['boot_index'] = None

        if not volume_backed and image_uuid:

            image_bdm = create_image_bdm(image_uuid, boot_index=0)

    return ([image_bdm] if image_bdm else []) + new_bdms

def properties_root_device_name(properties):

    """get root device name from image meta data.

    If it isn't specified, return None.

    """

    root_device_name = None

    # NOTE(yamahata): see image_service.s3.s3create()

    for bdm in properties.get('mappings', []):

        if bdm['virtual'] == 'root':

            root_device_name = bdm['device']

    # NOTE(yamahata): register_image's command line can override

    #                 .manifest.xml

    if 'root_device_name' in properties:

        root_device_name = properties['root_device_name']

    return root_device_name

def validate_device_name(value):

    try:

        # NOTE (ndipanov): Do not allow empty device names

        #                  until assigning default values

        #                  is supported by nova.compute

        utils.check_string_length(value, 'Device name',

                                  min_length=1, max_length=255)

    except exception.InvalidInput as e:

        raise exception.InvalidBDMFormat(

            details="Device name empty or too long.")

    if ' ' in value:

        raise exception.InvalidBDMFormat(

            details="Device name contains spaces.")

def validate_and_default_volume_size(bdm):

    if bdm.get('volume_size'):

        try:

            bdm['volume_size'] = utils.validate_integer(

                bdm['volume_size'], 'volume_size', min_value=0)

        except exception.InvalidInput as e:

            raise exception.InvalidBDMFormat(

                details="Invalid volume_size.")

_ephemeral = re.compile('^ephemeral(\d|[1-9]\d+)$')

def is_ephemeral(device_name):

    return _ephemeral.match(device_name) is not None

def ephemeral_num(ephemeral_name):

    assert is_ephemeral(ephemeral_name)

    return int(_ephemeral.sub('\\1', ephemeral_name))

def is_swap_or_ephemeral(device_name):

    return (device_name and

            (device_name == 'swap' or is_ephemeral(device_name)))

def new_format_is_swap(bdm):

    if (bdm.get('source_type') == 'blank' and

            bdm.get('destination_type') == 'local' and

            bdm.get('guest_format') == 'swap'):

        return True

    return False

def new_format_is_ephemeral(bdm):

    if (bdm.get('source_type') == 'blank' and not

            new_format_is_swap(bdm)):

        return True

    return False

def get_root_bdm(bdms):

    try:

        return (bdm for bdm in bdms if bdm.get('boot_index', -1) == 0).next()

    except StopIteration:

        return None

def mappings_prepend_dev(mappings):

    """Prepend '/dev/' to 'device' entry of swap/ephemeral virtual type."""

    for m in mappings:

        virtual = m['virtual']

        if (is_swap_or_ephemeral(virtual) and

                (not m['device'].startswith('/'))):

            m['device'] = '/dev/' + m['device']

    return mappings

_dev = re.compile('^/dev/')

def strip_dev(device_name):

    """remove leading '/dev/'."""

    return _dev.sub('', device_name) if device_name else device_name

def prepend_dev(device_name):

    """Make sure there is a leading '/dev/'."""

    return device_name and '/dev/' + strip_dev(device_name)

_pref = re.compile('^((x?v|s)d)')

def strip_prefix(device_name):

    """remove both leading /dev/ and xvd or sd or vd."""

    device_name = strip_dev(device_name)

    return _pref.sub('', device_name)

def instance_block_mapping(instance, bdms):

    root_device_name = instance['root_device_name']

    # NOTE(clayg): remove this when xenapi is setting default_root_device

    if root_device_name is None:

        if driver.compute_driver_matches('xenapi.XenAPIDriver'):

            root_device_name = '/dev/xvda'

        else:

            return _DEFAULT_MAPPINGS

    mappings = {}

    mappings['ami'] = strip_dev(root_device_name)

    mappings['root'] = root_device_name

    default_ephemeral_device = instance.get('default_ephemeral_device')

    if default_ephemeral_device:

        mappings['ephemeral0'] = default_ephemeral_device

    default_swap_device = instance.get('default_swap_device')

    if default_swap_device:

        mappings['swap'] = default_swap_device

    ebs_devices = []

    blanks = []

    # 'ephemeralN', 'swap' and ebs

    for bdm in bdms:

        # ebs volume case

        if bdm.destination_type == 'volume':

            ebs_devices.append(bdm.device_name)

            continue

        if bdm.source_type == 'blank':

            blanks.append(bdm)

    # NOTE(yamahata): I'm not sure how ebs device should be numbered.

    #                 Right now sort by device name for deterministic

    #                 result.

    if ebs_devices:

        ebs_devices.sort()

        for nebs, ebs in enumerate(ebs_devices):

            mappings['ebs%d' % nebs] = ebs

    swap = [bdm for bdm in blanks if bdm.guest_format == 'swap']

    if swap:

        mappings['swap'] = swap.pop().device_name

    ephemerals = [bdm for bdm in blanks if bdm.guest_format != 'swap']

    if ephemerals:

        for num, eph in enumerate(ephemerals):

            mappings['ephemeral%d' % num] = eph.device_name

    return mappings

def match_device(device):

    """Matches device name and returns prefix, suffix."""

    match = re.match("(^/dev/x{0,1}[a-z]{0,1}d{0,1})([a-z]+)[0-9]*$", device)

    if not match:

        return None

    return match.groups()

def volume_in_mapping(mount_device, block_device_info):

    block_device_list = [strip_dev(vol['mount_device'])

                         for vol in

                         driver.block_device_info_get_mapping(

                         block_device_info)]

    swap = driver.block_device_info_get_swap(block_device_info)

    if driver.swap_is_usable(swap):

        block_device_list.append(strip_dev(swap['device_name']))

    block_device_list += [strip_dev(ephemeral['device_name'])

                          for ephemeral in

                          driver.block_device_info_get_ephemerals(

                          block_device_info)]

    LOG.debug(_("block_device_list %s"), block_device_list)

    return strip_dev(mount_device) in block_device_list

**** CubicPower OpenStack Study ****

def is_safe_for_update(block_device_dict):

    """Determine if passed dict is a safe subset for update.

    Safe subset in this case means a safe subset of both legacy

    and new versions of data, that can be passed to an UPDATE query

    without any transformation.

    """

    fields = set(block_device_dict.keys())

    return fields <= (bdm_new_fields |

                      bdm_db_inherited_fields |

                      bdm_db_only_fields)

**** CubicPower OpenStack Study ****

def create_image_bdm(image_ref, boot_index=0):

    """Create a block device dict based on the image_ref.

    This is useful in the API layer to keep the compatibility

    with having an image_ref as a field in the instance requests

    """

    return BlockDeviceDict(

        {'source_type': 'image',

         'image_id': image_ref,

         'delete_on_termination': True,

         'boot_index': boot_index,

         'device_type': 'disk',

         'destination_type': 'local'})

**** CubicPower OpenStack Study ****

def snapshot_from_bdm(snapshot_id, template):

    """Create a basic volume snapshot BDM from a given template bdm."""

    copy_from_template = ['disk_bus', 'device_type', 'boot_index']

    snapshot_dict = {'source_type': 'snapshot',

                     'destination_type': 'volume',

                     'snapshot_id': snapshot_id}

    for key in copy_from_template:

        snapshot_dict[key] = template.get(key)

    return BlockDeviceDict(snapshot_dict)

**** CubicPower OpenStack Study ****

def legacy_mapping(block_device_mapping):

    """Transform a list of block devices of an instance back to the

    legacy data format.

    """

    legacy_block_device_mapping = []

    for bdm in block_device_mapping:

        try:

            legacy_block_device = BlockDeviceDict(bdm).legacy()

        except exception.InvalidBDMForLegacy:

            continue

        legacy_block_device_mapping.append(legacy_block_device)

    # Re-enumerate the ephemeral devices

    for i, dev in enumerate(dev for dev in legacy_block_device_mapping

                            if dev['virtual_name'] and

                            is_ephemeral(dev['virtual_name'])):

        dev['virtual_name'] = dev['virtual_name'][:-1] + str(i)

    return legacy_block_device_mapping

**** CubicPower OpenStack Study ****

def from_legacy_mapping(legacy_block_device_mapping, image_uuid='',

                        root_device_name=None, no_root=False):

    """Transform a legacy list of block devices to the new data format."""

    new_bdms = [BlockDeviceDict.from_legacy(legacy_bdm)

                for legacy_bdm in legacy_block_device_mapping]

    # NOTE (ndipanov): We will not decide which device is root here - we assume

    # that it will be supplied later. This is useful for having the root device

    # as part of the image defined mappings that are already in the v2 format.

    if no_root:

        for bdm in new_bdms:

            bdm['boot_index'] = -1

        return new_bdms

    image_bdm = None

    volume_backed = False

    # Try to assign boot_device

    if not root_device_name and not image_uuid:

        # NOTE (ndipanov): If there is no root_device, pick the first non

        #                  blank one.

        non_blank = [bdm for bdm in new_bdms if bdm['source_type'] != 'blank']

        if non_blank:

            non_blank[0]['boot_index'] = 0

    else:

        for bdm in new_bdms:

            if (bdm['source_type'] in ('volume', 'snapshot', 'image') and

                    root_device_name is not None and

                    (strip_dev(bdm.get('device_name')) ==

                     strip_dev(root_device_name))):

                bdm['boot_index'] = 0

                volume_backed = True

            elif not bdm['no_device']:

                bdm['boot_index'] = -1

            else:

                bdm['boot_index'] = None

        if not volume_backed and image_uuid:

            image_bdm = create_image_bdm(image_uuid, boot_index=0)

    return ([image_bdm] if image_bdm else []) + new_bdms

**** CubicPower OpenStack Study ****

def properties_root_device_name(properties):

    """get root device name from image meta data.

    If it isn't specified, return None.

    """

    root_device_name = None

    # NOTE(yamahata): see image_service.s3.s3create()

    for bdm in properties.get('mappings', []):

        if bdm['virtual'] == 'root':

            root_device_name = bdm['device']

    # NOTE(yamahata): register_image's command line can override

    #                 .manifest.xml

    if 'root_device_name' in properties:

        root_device_name = properties['root_device_name']

    return root_device_name

**** CubicPower OpenStack Study ****

def validate_device_name(value):

    try:

        # NOTE (ndipanov): Do not allow empty device names

        #                  until assigning default values

        #                  is supported by nova.compute

        utils.check_string_length(value, 'Device name',

                                  min_length=1, max_length=255)

    except exception.InvalidInput as e:

        raise exception.InvalidBDMFormat(

            details="Device name empty or too long.")

    if ' ' in value:

        raise exception.InvalidBDMFormat(

            details="Device name contains spaces.")

**** CubicPower OpenStack Study ****

def validate_and_default_volume_size(bdm):

    if bdm.get('volume_size'):

        try:

            bdm['volume_size'] = utils.validate_integer(

                bdm['volume_size'], 'volume_size', min_value=0)

        except exception.InvalidInput as e:

            raise exception.InvalidBDMFormat(

                details="Invalid volume_size.")

_ephemeral = re.compile('^ephemeral(\d|[1-9]\d+)$')

**** CubicPower OpenStack Study ****

def is_ephemeral(device_name):

    return _ephemeral.match(device_name) is not None

**** CubicPower OpenStack Study ****

def ephemeral_num(ephemeral_name):

    assert is_ephemeral(ephemeral_name)

    return int(_ephemeral.sub('\\1', ephemeral_name))

**** CubicPower OpenStack Study ****

def is_swap_or_ephemeral(device_name):

    return (device_name and

            (device_name == 'swap' or is_ephemeral(device_name)))

**** CubicPower OpenStack Study ****

def new_format_is_swap(bdm):

    if (bdm.get('source_type') == 'blank' and

            bdm.get('destination_type') == 'local' and

            bdm.get('guest_format') == 'swap'):

        return True

    return False

**** CubicPower OpenStack Study ****

def new_format_is_ephemeral(bdm):

    if (bdm.get('source_type') == 'blank' and not

            new_format_is_swap(bdm)):

        return True

    return False

**** CubicPower OpenStack Study ****

def get_root_bdm(bdms):

    try:

        return (bdm for bdm in bdms if bdm.get('boot_index', -1) == 0).next()

    except StopIteration:

        return None

**** CubicPower OpenStack Study ****

def mappings_prepend_dev(mappings):

    """Prepend '/dev/' to 'device' entry of swap/ephemeral virtual type."""

    for m in mappings:

        virtual = m['virtual']

        if (is_swap_or_ephemeral(virtual) and

                (not m['device'].startswith('/'))):

            m['device'] = '/dev/' + m['device']

    return mappings

_dev = re.compile('^/dev/')

**** CubicPower OpenStack Study ****

def strip_dev(device_name):

    """remove leading '/dev/'."""

    return _dev.sub('', device_name) if device_name else device_name

**** CubicPower OpenStack Study ****

def prepend_dev(device_name):

    """Make sure there is a leading '/dev/'."""

    return device_name and '/dev/' + strip_dev(device_name)

_pref = re.compile('^((x?v|s)d)')

**** CubicPower OpenStack Study ****

def strip_prefix(device_name):

    """remove both leading /dev/ and xvd or sd or vd."""

    device_name = strip_dev(device_name)

    return _pref.sub('', device_name)

**** CubicPower OpenStack Study ****

def instance_block_mapping(instance, bdms):

    root_device_name = instance['root_device_name']

    # NOTE(clayg): remove this when xenapi is setting default_root_device

    if root_device_name is None:

        if driver.compute_driver_matches('xenapi.XenAPIDriver'):

            root_device_name = '/dev/xvda'

        else:

            return _DEFAULT_MAPPINGS

    mappings = {}

    mappings['ami'] = strip_dev(root_device_name)

    mappings['root'] = root_device_name

    default_ephemeral_device = instance.get('default_ephemeral_device')

    if default_ephemeral_device:

        mappings['ephemeral0'] = default_ephemeral_device

    default_swap_device = instance.get('default_swap_device')

    if default_swap_device:

        mappings['swap'] = default_swap_device

    ebs_devices = []

    blanks = []

    # 'ephemeralN', 'swap' and ebs

    for bdm in bdms:

        # ebs volume case

        if bdm.destination_type == 'volume':

            ebs_devices.append(bdm.device_name)

            continue

        if bdm.source_type == 'blank':

            blanks.append(bdm)

    # NOTE(yamahata): I'm not sure how ebs device should be numbered.

    #                 Right now sort by device name for deterministic

    #                 result.

    if ebs_devices:

        ebs_devices.sort()

        for nebs, ebs in enumerate(ebs_devices):

            mappings['ebs%d' % nebs] = ebs

    swap = [bdm for bdm in blanks if bdm.guest_format == 'swap']

    if swap:

        mappings['swap'] = swap.pop().device_name

    ephemerals = [bdm for bdm in blanks if bdm.guest_format != 'swap']

    if ephemerals:

        for num, eph in enumerate(ephemerals):

            mappings['ephemeral%d' % num] = eph.device_name

    return mappings

**** CubicPower OpenStack Study ****

def match_device(device):

    """Matches device name and returns prefix, suffix."""

    match = re.match("(^/dev/x{0,1}[a-z]{0,1}d{0,1})([a-z]+)[0-9]*$", device)

    if not match:

        return None

    return match.groups()

**** CubicPower OpenStack Study ****

def volume_in_mapping(mount_device, block_device_info):

    block_device_list = [strip_dev(vol['mount_device'])

                         for vol in

                         driver.block_device_info_get_mapping(

                         block_device_info)]

    swap = driver.block_device_info_get_swap(block_device_info)

    if driver.swap_is_usable(swap):

        block_device_list.append(strip_dev(swap['device_name']))

    block_device_list += [strip_dev(ephemeral['device_name'])

                          for ephemeral in

                          driver.block_device_info_get_ephemerals(

                          block_device_info)]

    LOG.debug(_("block_device_list %s"), block_device_list)

    return strip_dev(mount_device) in block_device_list