# Copyright 2016 Huawei Technologies Co.,LTD.
# 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 json
import re
import types

from nova.compute import power_state
from nova.i18n import _
from nova.virt.fusioncomputeapi import osconfig
from oslo_config import cfg
from oslo_log import log as logging


LOG = logging.getLogger(__name__)
CONF = cfg.CONF


fusion_compute_opts = [
    cfg.StrOpt('fc_user',
               default='',
               help='FusionCompute user name'),
    cfg.StrOpt('fc_pwd',
               default='',
               help='FusionCompute user password',
               secret=True),
    cfg.StrOpt('fc_ip',
               default=None,
               help='Management IP of FusionCompute'),
    cfg.StrOpt('fc_image_path',
               default=None,
               help='NFS Image server path'),
    cfg.StrOpt('vxlan_dvs_name',
               default=None,
               help='FusionCompute dvswitch name for vxlan network'),
    cfg.StrOpt('enhanced_network_dvs_name',
               default=None,
               help='FusionCompute dvs_name for enhanced_network network'),
    cfg.BoolOpt('use_admin_pass',
                default=False,
                help='Create vm using the admin pass or fusionCompute pass'),
    cfg.StrOpt('clusters',
               default='',
               help='FusionCompute clusters mapped to hypervisors'),
    cfg.FloatOpt('cpu_ratio',
                 default=1,
                 help='FusionCompute cpu multiplexing ratio'),
    cfg.StrOpt('glance_server_ip',
               default=None,
               help='FusionSphere glance server ip'),
    cfg.StrOpt('uds_access_key',
               default=None,
               help='FusionCompute uds image access key',
               secret=True),
    cfg.StrOpt('uds_secret_key',
               default=None,
               help='FusionCompute uds image secret key',
               secret=True),
    cfg.StrOpt('instance_initial_mode',
               default='FusionCompute',
               help='Instance initial mode '
                    'which is cloud_init or FusionCompute'),
    cfg.IntOpt('resource_reduced_rate',
               default=100,
               help='Resource reduced rate for '
                    'cpu and memory in FusionCompute'),
    cfg.StrOpt('reserve_disk_symbol',
               default='True',
               help='Reserve b/c/d disk symbol in FusionCompute.'),
    cfg.StrOpt('fusioncompute_file_inject',
               default='enabled',
               help='Use file inject by FusionCompute'),
    cfg.IntOpt('cdrom_sequence_num',
               default=0,
               help='cdrom letter in FusionCompute'),
    cfg.IntOpt('cpu_usage_monitor_period',
               default=3600,
               help='FusionCompute cpu usage monitor period'),
    cfg.IntOpt('workers',
               default=4,
               help='FusionCompute compute process number'),
    cfg.IntOpt('fc_request_timeout_max',
               default=3600,
               help='FusionCompute request timeout max'),
    cfg.IntOpt('fc_request_timeout_min',
               default=300,
               help='FusionCompute request timeout min'),
    cfg.IntOpt('attach_int_timeout',
               default=90,
               help='Attach interface timeout'),
    cfg.IntOpt('safe_stop_vm_timeout',
               default=600,
               help='Safe stop vm timeout'),
    cfg.IntOpt('fc_request_timeout_delete_vm',
               default=36000,
               help='FusionCompute request timeout delete vm'),
    cfg.IntOpt('fc_request_timeout_delete_vm_timelimited',
               default=30000,
               help='FusionCompute request timeout delete vm'),
    cfg.BoolOpt('enable_virtualio',
                default=False,
                help='Vm virtual IO'),
    cfg.BoolOpt('enable_snapshot_auto_del',
                default=False,
                help='enable backup snapshot auto '
                     'delete before volume detach'),
    cfg.StrOpt('host',
               default="",
               help='glance host'),
    cfg.StrOpt('port',
               default="",
               help='glance port')
]

CONF.register_opts(fusion_compute_opts, group='fusioncompute')

virt_opts = [
    cfg.BoolOpt('use_kbox',
                default=False,
                help='use kbox in libvirt'),
    cfg.BoolOpt('local_resume_instance',
                default=True,
                help='Auto start the instance when stop itself')
]

CONF.register_opts(virt_opts)

FC_DRIVER_JOINT_CFG = {
    'user_type': '2',
    'fc_port': 7443,
    'api_version': '6.0',
    'hypervisor_version': 60,
    'hypervisor_type': 'FusionCompute',
    'request_time_out': 120,
    'dvs_mapping': 'physnet1:service',
    'volume_is_thin': True
}


def str_to_bool(cver_str):
    """convert string to boolean

    :param cver_str: string should to convert
    :return: Boolean
    """
    if isinstance(cver_str, types.BooleanType):
        return cver_str
    elif isinstance(cver_str, types.StringType):
        bool_map = {'true': True, 'false': False}
        bool_str = cver_str.lower() if cver_str else ""
        if bool_str not in bool_map:
            raise ValueError('%s is not valid boolean.' % cver_str)
        else:
            return bool_map[bool_str]
    else:
        raise ValueError('%s is not valid boolean.' % cver_str)


class Enum(dict):
    """enum object

    """

    def __init__(self, **enums):
        super(Enum, self).__init__()
        for key in enums:
            self[key] = enums[key]

    def __getattr__(self, name):
        return self.get(name)

CONFIG_ITEM_TYPE = Enum(STR=0,
                        INT=1,
                        BOOL=2)

# ignore pylint:disable=R0903


class ConfigItemValue(object):
    """fc config detail item

    """

    def __init__(self, key, value, conf_type=CONFIG_ITEM_TYPE.STR):
        self.key = key
        self.value = value
        self.conf_type = conf_type
        if conf_type is None:
            raise TypeError('item %s set value %s type eror.' % (key, value))

    def set_value(self, value):
        """set item value basis by type

        """
        if self.conf_type == CONFIG_ITEM_TYPE.STR:
            self.value = str(value)
        elif self.conf_type == CONFIG_ITEM_TYPE.INT:
            try:
                int_value = int(value)
                self.value = int_value
            except ValueError:
                LOG.error(_("%s config to int fail."), str(value))
        elif self.conf_type == CONFIG_ITEM_TYPE.BOOL:
            try:
                bool_value = str_to_bool(value)
                self.value = bool_value
            except ValueError:
                LOG.error(_("%s config to bool fail."), str(value))
        else:
            LOG.error(_("config type %s is error."), self.conf_type)


class FcConfig(dict):
    """fc config file manager

    """

    def __init__(self, cfg_path, default_value):
        super(FcConfig, self).__init__()
        for key, value in default_value.items():
            self[key] = value

        for key, value in json.load(open(cfg_path, 'r')).items():
            if self.get(key):
                self[key].set_value(value)
            else:
                LOG.error(_("%s not exists in config."), key)

    def __getattr__(self, name):
        if self.get(name):
            return self.get(name).value
        else:
            return None

# ================CONFIG constant begin========================
FC_PLUG_CONFIG_PATH = '/etc/nova/fc-nova-compute'

TEMPLATE_VHD_SIZE = 1024
TEMPLATE_VHD_FILE = '%s/template.vhd' % FC_PLUG_CONFIG_PATH

OS_CONFIG_FILE = '%s/huawei-os-config.conf' % FC_PLUG_CONFIG_PATH
VIRTUAL_IO_OS_CONFIG_FILE = '%s/virtualio-os-config.conf' % FC_PLUG_CONFIG_PATH

FC_DRIVER_DEFAULT_CFG = {
    'fc_user': ConfigItemValue('fc_user', ''),
    'fc_pwd': ConfigItemValue('fc_pwd', ''),
    'fc_ip': ConfigItemValue('fc_ip', None),
    'user_type': ConfigItemValue('user_type', 2, CONFIG_ITEM_TYPE.INT),
    'fc_port': ConfigItemValue('fc_port', 7443, CONFIG_ITEM_TYPE.INT),
    'api_version': ConfigItemValue('api_version', '6.0'),
    'hypervisor_version': ConfigItemValue('hypervisor_version', 60,
                                          CONFIG_ITEM_TYPE.INT),
    'hypervisor_type': ConfigItemValue('hypervisor_type', 'FusionCompute'),
    'fc_image_path': ConfigItemValue('fc_image_path', None),
    'dvs_vxlan': ConfigItemValue('dvs_vxlan', None),
    'cluster': ConfigItemValue('cluster', None),
    'dvs_mapping': ConfigItemValue('dvs_mapping', 'physnet1:service'),
    'request_time_out': ConfigItemValue('request_time_out', 120,
                                        CONFIG_ITEM_TYPE.INT),
    'gen_admin_pass': ConfigItemValue('gen_admin_pass', False,
                                      CONFIG_ITEM_TYPE.BOOL),
    'volume_is_thin': ConfigItemValue('volume_is_thin', True,
                                      CONFIG_ITEM_TYPE.BOOL),
    'clusters': ConfigItemValue('clusters', ''),
    'cpu_rate': ConfigItemValue('cpu_rate', 1, CONFIG_ITEM_TYPE.INT),
    'glance_server_ip': ConfigItemValue('glance_server_ip', None),
    'uds_access_key': ConfigItemValue('uds_access_key', None),
    'uds_secret_key': ConfigItemValue('uds_secret_key', None),
    'cpu_usage_monitor_period': ConfigItemValue('cpu_usage_monitor_period',
                                                60 * 60, CONFIG_ITEM_TYPE.INT)
}

FC_PLUG_CONFIG_FILE = '%s/fc-nova-compute.conf' % FC_PLUG_CONFIG_PATH
"""FC_CONF = FcConfig(FC_PLUG_CONFIG_FILE, FC_DRIVER_DEFAULT_CFG)

"""


# ============================vm constant begin===============

VM_GROUP_FLAG = 'FSP'

VM_STATUS = Enum(UNKNOWN='unknown', RUNNING='running',
                 STOPPED='stopped', STOPPING='stopping',
                 PAUSED='pause', SUSPENDED='hibernated',
                 MIGRATING='migrating',
                 FAULTRESUMING='fault-resuming')

NOTIFY_NEUTRON = Enum(FALSE='false',
                      TRUE='true')

PV_STATUS = Enum(STARTING='starting', RUNNING='running',
                 NOTRUNNING='notRunning')

VM_POWER_STATE_MAPPING = {
    VM_STATUS.UNKNOWN: power_state.NOSTATE,
    VM_STATUS.RUNNING: power_state.RUNNING,
    VM_STATUS.PAUSED: power_state.PAUSED,
    VM_STATUS.STOPPING: power_state.SHUTDOWN,
    VM_STATUS.STOPPED: power_state.SHUTDOWN,
    VM_STATUS.SUSPENDED: power_state.SUSPENDED
}

FC_RETURN_ERROR = "FusionCompute return failed."

REBOOT_TYPE = Enum(SOFT='SOFT', HARD='HARD')
FC_REBOOT_TYPE = {
    REBOOT_TYPE.HARD: 'force',
    REBOOT_TYPE.SOFT: 'safe'
}

HUAWEI_OS_TYPE = 'os_type'
HUAWEI_OS_VERSION = 'os_distro'
HUAWEI_IMAGE_LOCATION = '__image_location'
HUAWEI_IMAGE_TYPE = '__image_source_type'
HUAWEI_IS_LINK_CLONE = '__linked_clone'

HUAWEI_OS_TYPE_MAP = {
    'windows': 'Windows',
    'linux': 'Linux',
    'other': 'Other'
}

DEFAULT_HUAWEI_OS_TYPE = 'Other'
DEFAULT_HUAWEI_OS_VERSION = 'Other(32 bit)'

# ComputeOps._init_os_config() will do real initialization
DEFAULT_HUAWEI_OS_CONFIG = ['', '']

HUAWEI_OS_VERSION_INT = osconfig.OS_VERSION_INT
HUAWEI_OS_VERSION_STR = osconfig.OS_VERSION_STR
HUAWEI_VIRTUAL_IO_OS_VERSION_INT = osconfig.VIRTUAL_IO_OS_VERSION_INT
VIRTUAL_IO_OS_LIST = []

BOOT_OPTION_MAP = {
    'hd': 'disk',
    'hd,network': 'disk',
    'network': 'pxe',
    'network,hd': 'pxe',
    'default': 'disk'
}

VNC_KEY_MAP_SETTING = {
    'en-us': 7,
    'de': 4,
    'fr': 12,
    'ru': 30,
    'es': 8,
    'default': 7
}

IPV4_VERSION = 4

DRS_RULES_TYPE_MAP = {
    'affinity': 1,
    'anti-affinity': 2
}

DRS_RULES_OP_TYPE_MAP = {
    'delete': 0,
    'modify': 1,
    'create': 2
}

# =================uri constant begin================
VM_URI_MAP = {
    'start': '/action/start',
    'stop': '/action/stop',
    'reboot': '/action/reboot',
    'pause': '/action/pause',
    'unpause': '/action/resume',
    'import': '/action/import',
    'export': '/action/export',
    'unresume': '/action/unresume',
    'migrate': '/action/migrate',
    'clone': '/action/clone',
    'set_vm_data': '/action/uploadVmData',
    'attachvol': '/action/attachvol',
    'detachvol': '/action/detachvol',
    'expandvol': '/action/expandvol',
    'suspend': '/action/hibernate',
    'attach_gpu': '/action/attachgpu',
    'detach_gpu': '/action/detachgpu',
    'nics': '/virtualNics'
}

VOL_URI_MAP = {
    'modio': '/modifyIOpropertyOfVolume'
}

FC_SITE_URI_MAP = {
    'vm_uri': {
        'baseuri': '%(site_uri)s/vms'
    },

    'import_vm_uri': {
        'baseuri': '%(vm_uri)s/action/import',
        'dependuri': ['vm_uri']
    },
    'cluster_uri': {
        'baseuri': '%(site_uri)s/clusters'
    },
    'host_uri': {
        'baseuri': '%(site_uri)s/hosts'
    },
    'datastore_uri': {
        'baseuri': '%(site_uri)s/datastores'
    },
    'volume_uri': {
        'baseuri': '%(site_uri)s/volumes'
    },
    'dvswitchs_uri': {
        'baseuri': '%(site_uri)s/dvswitchs'
    },
    'current_time_uri': {
        'baseuri': '%(site_uri)s/monitors/getSysCurrentTime'
    },
    'metric_curvedata_uri': {
        'baseuri': '%(site_uri)s/monitors/objectmetric-curvedata'
    }

}

TOKEN_URI = '/service/session'
SITE_URI = '/service/sites'

# =================network====================
TYPE_FNC = 2
TYPE_VLAN = 'vlan'
TYPE_VXLAN = 'vxlan'
TYPE_FLAT = 'flat'

DVSWITCHS = 'dvSwitchs'
DVS_URI = '/dvswitchs'
PORT_GROUP_URI = DVS_URI + '/%(dvs_id)s/portgroups'
PORT_GROUP_ID_URI = PORT_GROUP_URI + '/%(pg_id)s'
VSP_URI = DVS_URI + '/%(dvs_id)s/vsps'

VSP_TAG_KEY = 'NeutronPort'

# =================other====================
ID_IN_URN_REGEX = re.compile(r':(?P<id>[^:]+)$')
CPU_QOS_NOVA_KEY = ['quota:cpu_shares',
                    'quota:cpu_limit',
                    'quota:cpu_reserve']
CPU_QOS_FC_KEY = ['weight',
                  'limit',
                  'reservation']
CPU_QOS_FC_DEFAULT_VALUE = [1000, 0, 0]

MOUNT_DEVICE_SEQNUM_MAP = {
    '/dev/sda': 1, '/dev/vda': 1, '/dev/xvda': 1,
    '/dev/sdb': 2, '/dev/vdb': 2, '/dev/xvdb': 2,
    '/dev/sdc': 3, '/dev/vdc': 3, '/dev/xvdc': 3,
    '/dev/sdd': 4, '/dev/vdd': 4, '/dev/xvdd': 4,
    '/dev/sde': 5, '/dev/vde': 5, '/dev/xvde': 5,
    '/dev/sdf': 6, '/dev/vdf': 6, '/dev/xvdf': 6,
    '/dev/sdg': 7, '/dev/vdg': 7, '/dev/xvdg': 7,
    '/dev/sdh': 8, '/dev/vdh': 8, '/dev/xvdh': 8,
    '/dev/sdi': 9, '/dev/vdi': 9, '/dev/xvdi': 9,
    '/dev/sdj': 10, '/dev/vdj': 10, '/dev/xvdj': 10,
    '/dev/sdk': 11, '/dev/vdk': 11, '/dev/xvdk': 11,
    '/dev/sdl': 12, '/dev/vdl': 12, '/dev/xvdl': 12,
    '/dev/sdm': 13, '/dev/vdm': 13, '/dev/xvdm': 13,
    '/dev/sdn': 14, '/dev/vdn': 14, '/dev/xvdn': 14,
    '/dev/sdo': 15, '/dev/vdo': 15, '/dev/xvdo': 15,
    '/dev/sdp': 16, '/dev/vdp': 16, '/dev/xvdp': 16,
    '/dev/sdq': 17, '/dev/vdq': 17, '/dev/xvdq': 17,
    '/dev/sdr': 18, '/dev/vdr': 18, '/dev/xvdr': 18,
    '/dev/sds': 19, '/dev/vds': 19, '/dev/xvds': 19,
    '/dev/sdt': 20, '/dev/vdt': 20, '/dev/xvdt': 20,
    '/dev/sdu': 21, '/dev/vdu': 21, '/dev/xvdu': 21,
    '/dev/sdv': 22, '/dev/vdv': 22, '/dev/xvdv': 22,
    '/dev/sdw': 23, '/dev/vdw': 23, '/dev/xvdw': 23,
    '/dev/sdx': 24, '/dev/vdx': 24, '/dev/xvdx': 24,
    '/dev/sdy': 25, '/dev/vdy': 25, '/dev/xvdy': 25,
    '/dev/sdz': 26, '/dev/vdz': 26, '/dev/xvdz': 26,
    '/dev/sdaa': 27, '/dev/vdaa': 27, '/dev/xvdaa': 27,
    '/dev/sdab': 28, '/dev/vdab': 28, '/dev/xvdab': 28,
    '/dev/sdac': 29, '/dev/vdac': 29, '/dev/xvdac': 29,
    '/dev/sdad': 30, '/dev/vdad': 30, '/dev/xvdad': 30,
    '/dev/sdae': 31, '/dev/vdae': 31, '/dev/xvdae': 31,
    '/dev/sdaf': 32, '/dev/vdaf': 32, '/dev/xvdaf': 32,
    '/dev/sdag': 33, '/dev/vdag': 33, '/dev/xvdag': 33,
    '/dev/sdah': 34, '/dev/vdah': 34, '/dev/xvdah': 34,
    '/dev/sdai': 35, '/dev/vdai': 35, '/dev/xvdai': 35,
    '/dev/sdaj': 36, '/dev/vdaj': 36, '/dev/xvdaj': 36,
    '/dev/sdak': 37, '/dev/vdak': 37, '/dev/xvdak': 37,
    '/dev/sdal': 38, '/dev/vdal': 38, '/dev/xvdal': 38,
    '/dev/sdam': 39, '/dev/vdam': 39, '/dev/xvdam': 39,
    '/dev/sdan': 40, '/dev/vdan': 40, '/dev/xvdan': 40,
    '/dev/sdao': 41, '/dev/vdao': 41, '/dev/xvdao': 41,
    '/dev/sdap': 42, '/dev/vdap': 42, '/dev/xvdap': 42,
    '/dev/sdaq': 43, '/dev/vdaq': 43, '/dev/xvdaq': 43,
    '/dev/sdar': 44, '/dev/vdar': 44, '/dev/xvdar': 44,
    '/dev/sdas': 45, '/dev/vdas': 45, '/dev/xvdas': 45,
    '/dev/sdat': 46, '/dev/vdat': 46, '/dev/xvdat': 46,
    '/dev/sdau': 47, '/dev/vdau': 47, '/dev/xvdau': 47,
    '/dev/sdav': 48, '/dev/vdav': 48, '/dev/xvdav': 48,
    '/dev/sdaw': 49, '/dev/vdaw': 49, '/dev/xvdaw': 49,
    '/dev/sdax': 50, '/dev/vdax': 50, '/dev/xvdax': 50,
    '/dev/sday': 51, '/dev/vday': 51, '/dev/xvday': 51,
    '/dev/sdaz': 52, '/dev/vdaz': 52, '/dev/xvdaz': 52,
    '/dev/sdba': 53, '/dev/vdba': 53, '/dev/xvdba': 53,
    '/dev/sdbb': 54, '/dev/vdbb': 54, '/dev/xvdbb': 54,
    '/dev/sdbc': 55, '/dev/vdbc': 55, '/dev/xvdbc': 55,
    '/dev/sdbd': 56, '/dev/vdbd': 56, '/dev/xvdbd': 56,
    '/dev/sdbe': 57, '/dev/vdbe': 57, '/dev/xvdbe': 57,
    '/dev/sdbf': 58, '/dev/vdbf': 58, '/dev/xvdbf': 58,
    '/dev/sdbg': 59, '/dev/vdbg': 59, '/dev/xvdbg': 59,
    '/dev/sdbh': 60, '/dev/vdbh': 60, '/dev/xvdbh': 60,
    '/dev/sdbi': 61, '/dev/vdbi': 61, '/dev/xvdbi': 61,
    '/dev/sdbj': 62, '/dev/vdbj': 62, '/dev/xvdbj': 62,
    '/dev/sdbk': 63, '/dev/vdbk': 63, '/dev/xvdbk': 63,
    '/dev/sdbl': 64, '/dev/vdbl': 64, '/dev/xvdbl': 64,
    '/dev/sdbm': 65, '/dev/vdbm': 65, '/dev/xvdbm': 65
}

MOUNT_DEVICE_SEQNUM_MAP_IDE = {
    '/dev/sda': 1, '/dev/vda': 1, '/dev/xvda': 1,
    '/dev/sdb': 1001, '/dev/vdb': 1001, '/dev/xvdb': 1001,
    '/dev/sdc': 1002, '/dev/vdc': 1002, '/dev/xvdc': 1002,
    '/dev/sdd': 1003, '/dev/vdd': 1003, '/dev/xvdd': 1003,
    '/dev/sde': 2, '/dev/vde': 2, '/dev/xvde': 2,
    '/dev/sdf': 3, '/dev/vdf': 3, '/dev/xvdf': 3,
    '/dev/sdg': 4, '/dev/vdg': 4, '/dev/xvdg': 4,
    '/dev/sdh': 5, '/dev/vdh': 5, '/dev/xvdh': 5,
    '/dev/sdi': 6, '/dev/vdi': 6, '/dev/xvdi': 6,
    '/dev/sdj': 7, '/dev/vdj': 7, '/dev/xvdj': 7,
    '/dev/sdk': 8, '/dev/vdk': 8, '/dev/xvdk': 8,
    '/dev/sdl': 9, '/dev/vdl': 9, '/dev/xvdl': 9,
    '/dev/sdm': 10, '/dev/vdm': 10, '/dev/xvdm': 10,
    '/dev/sdn': 11, '/dev/vdn': 11, '/dev/xvdn': 11,
    '/dev/sdo': 12, '/dev/vdo': 12, '/dev/xvdo': 12,
    '/dev/sdp': 13, '/dev/vdp': 13, '/dev/xvdp': 13,
    '/dev/sdq': 14, '/dev/vdq': 14, '/dev/xvdq': 14,
    '/dev/sdr': 15, '/dev/vdr': 15, '/dev/xvdr': 15,
    '/dev/sds': 16, '/dev/vds': 16, '/dev/xvds': 16,
    '/dev/sdt': 17, '/dev/vdt': 17, '/dev/xvdt': 17,
    '/dev/sdu': 18, '/dev/vdu': 18, '/dev/xvdu': 18,
    '/dev/sdv': 19, '/dev/vdv': 19, '/dev/xvdv': 19,
    '/dev/sdw': 20, '/dev/vdw': 20, '/dev/xvdw': 20,
    '/dev/sdx': 21, '/dev/vdx': 21, '/dev/xvdx': 21,
    '/dev/sdy': 22, '/dev/vdy': 22, '/dev/xvdy': 22,
    '/dev/sdz': 1004, '/dev/vdz': 1004, '/dev/xvdz': 1004,
    '/dev/sdaa': 23, '/dev/vdaa': 23, '/dev/xvdaa': 23,
    '/dev/sdab': 24, '/dev/vdab': 24, '/dev/xvdab': 24,
    '/dev/sdac': 25, '/dev/vdac': 25, '/dev/xvdac': 25,
    '/dev/sdad': 26, '/dev/vdad': 26, '/dev/xvdad': 26,
    '/dev/sdae': 27, '/dev/vdae': 27, '/dev/xvdae': 27,
    '/dev/sdaf': 28, '/dev/vdaf': 28, '/dev/xvdaf': 28,
    '/dev/sdag': 29, '/dev/vdag': 29, '/dev/xvdag': 29,
    '/dev/sdah': 30, '/dev/vdah': 30, '/dev/xvdah': 30,
    '/dev/sdai': 31, '/dev/vdai': 31, '/dev/xvdai': 31,
    '/dev/sdaj': 32, '/dev/vdaj': 32, '/dev/xvdaj': 32,
    '/dev/sdak': 33, '/dev/vdak': 33, '/dev/xvdak': 33,
    '/dev/sdal': 34, '/dev/vdal': 34, '/dev/xvdal': 34,
    '/dev/sdam': 35, '/dev/vdam': 35, '/dev/xvdam': 35,
    '/dev/sdan': 36, '/dev/vdan': 36, '/dev/xvdan': 36,
    '/dev/sdao': 37, '/dev/vdao': 37, '/dev/xvdao': 37,
    '/dev/sdap': 38, '/dev/vdap': 38, '/dev/xvdap': 38,
    '/dev/sdaq': 39, '/dev/vdaq': 39, '/dev/xvdaq': 39,
    '/dev/sdar': 40, '/dev/vdar': 40, '/dev/xvdar': 40,
    '/dev/sdas': 41, '/dev/vdas': 41, '/dev/xvdas': 41,
    '/dev/sdat': 42, '/dev/vdat': 42, '/dev/xvdat': 42,
    '/dev/sdau': 43, '/dev/vdau': 43, '/dev/xvdau': 43,
    '/dev/sdav': 44, '/dev/vdav': 44, '/dev/xvdav': 44,
    '/dev/sdaw': 45, '/dev/vdaw': 45, '/dev/xvdaw': 45,
    '/dev/sdax': 46, '/dev/vdax': 46, '/dev/xvdax': 46,
    '/dev/sday': 47, '/dev/vday': 47, '/dev/xvday': 47,
    '/dev/sdaz': 48, '/dev/vdaz': 48, '/dev/xvdaz': 48,
    '/dev/sdba': 49, '/dev/vdba': 49, '/dev/xvdba': 49,
    '/dev/sdbb': 50, '/dev/vdbb': 50, '/dev/xvdbb': 50,
    '/dev/sdbc': 51, '/dev/vdbc': 51, '/dev/xvdbc': 51,
    '/dev/sdbd': 52, '/dev/vdbd': 52, '/dev/xvdbd': 52,
    '/dev/sdbe': 53, '/dev/vdbe': 53, '/dev/xvdbe': 53,
    '/dev/sdbf': 54, '/dev/vdbf': 54, '/dev/xvdbf': 54,
    '/dev/sdbg': 55, '/dev/vdbg': 55, '/dev/xvdbg': 55,
    '/dev/sdbh': 56, '/dev/vdbh': 56, '/dev/xvdbh': 56,
    '/dev/sdbi': 57, '/dev/vdbi': 57, '/dev/xvdbi': 57,
    '/dev/sdbj': 58, '/dev/vdbj': 58, '/dev/xvdbj': 58,
    '/dev/sdbk': 59, '/dev/vdbk': 59, '/dev/xvdbk': 59,
    '/dev/sdbl': 60, '/dev/vdbl': 60, '/dev/xvdbl': 60,
    '/dev/sdbm': 61, '/dev/vdbm': 61, '/dev/xvdbm': 61
}

FUSIONCOMPUTE_MAX_VOLUME_NUM = 11
