Merge "Refactor huawei Dorado array iSCSI driver"
This commit is contained in:
commit
2a76d0c81b
@ -161,6 +161,10 @@ class FakeChannel():
|
||||
def __init__(self):
|
||||
if Curr_test[0] == 'T':
|
||||
self.simu = HuaweiTCLIResSimulator()
|
||||
elif Curr_test[0] == 'Dorado5100':
|
||||
self.simu = HuaweiDorado5100CLIResSimulator()
|
||||
else:
|
||||
self.simu = HuaweiDorado2100G2CLIResSimulator()
|
||||
|
||||
def resize_pty(self, width=80, height=24):
|
||||
pass
|
||||
@ -830,6 +834,196 @@ Multipath Type
|
||||
return out
|
||||
|
||||
|
||||
class HuaweiDorado5100CLIResSimulator(HuaweiTCLIResSimulator):
|
||||
def cli_showsys(self, params):
|
||||
out = """/>showsys
|
||||
=============================================================
|
||||
System Information
|
||||
-------------------------------------------------------------
|
||||
System Name | SN_Dorado5100
|
||||
Device Type | Oceanstor Dorado5100
|
||||
Current System Mode | Double Controllers Normal
|
||||
Mirroring Link Status | Link Up
|
||||
Location |
|
||||
Time | 2013-01-01 01:01:01
|
||||
Product Version | V100R001C00
|
||||
=============================================================
|
||||
"""
|
||||
return out
|
||||
|
||||
def cli_showlun(self, params):
|
||||
if '-lun' not in params:
|
||||
if LUN_INFO['ID'] is None:
|
||||
out = 'command operates successfully, but no information.'
|
||||
elif CLONED_LUN_INFO['ID'] is None:
|
||||
out = """/>showlun
|
||||
===========================================================================
|
||||
LUN Information
|
||||
---------------------------------------------------------------------------
|
||||
ID RAIDgroup ID Status Controller Visible Capacity(MB) LUN Name..\
|
||||
Strip Unit Size(KB) Lun Type
|
||||
---------------------------------------------------------------------------
|
||||
%s %s Normal %s %s %s 64 THICK
|
||||
===========================================================================
|
||||
""" % (LUN_INFO['ID'], LUN_INFO['RAID Group ID'],
|
||||
LUN_INFO['Owner Controller'], str(int(LUN_INFO['Size']) * 1024),
|
||||
LUN_INFO['Name'])
|
||||
else:
|
||||
out = """/>showlun
|
||||
===========================================================================
|
||||
LUN Information
|
||||
---------------------------------------------------------------------------
|
||||
ID RAIDgroup ID Status Controller Visible Capacity(MB) LUN Name \
|
||||
Strip Unit Size(KB) Lun Type
|
||||
---------------------------------------------------------------------------
|
||||
%s %s Normal %s %s %s 64 THICK
|
||||
%s %s Norma %s %s %s 64 THICK
|
||||
===========================================================================
|
||||
""" % (LUN_INFO['ID'], LUN_INFO['RAID Group ID'], LUN_INFO['Owner Controller'],
|
||||
str(int(LUN_INFO['Size']) * 1024), LUN_INFO['Name'],
|
||||
CLONED_LUN_INFO['ID'], CLONED_LUN_INFO['RAID Group ID'],
|
||||
CLONED_LUN_INFO['Owner Controller'],
|
||||
str(int(CLONED_LUN_INFO['Size']) * 1024),
|
||||
CLONED_LUN_INFO['Name'])
|
||||
elif params[params.index('-lun') + 1] in VOLUME_SNAP_ID.values():
|
||||
out = """/>showlun
|
||||
================================================
|
||||
LUN Information
|
||||
------------------------------------------------
|
||||
ID | %s
|
||||
Name | %s
|
||||
LUN WWN | --
|
||||
Visible Capacity | %s
|
||||
RAID GROUP ID | %s
|
||||
Owning Controller | %s
|
||||
Workong Controller | %s
|
||||
Lun Type | %s
|
||||
SnapShot ID | %s
|
||||
LunCopy ID | %s
|
||||
================================================
|
||||
""" % ((LUN_INFO['ID'], LUN_INFO['Name'], LUN_INFO['Visible Capacity'],
|
||||
LUN_INFO['RAID Group ID'], LUN_INFO['Owner Controller'],
|
||||
LUN_INFO['Worker Controller'], LUN_INFO['Lun Type'],
|
||||
LUN_INFO['SnapShot ID'], LUN_INFO['LunCopy ID'])
|
||||
if params[params.index('-lun')] == VOLUME_SNAP_ID['vol'] else
|
||||
(CLONED_LUN_INFO['ID'], CLONED_LUN_INFO['Name'],
|
||||
CLONED_LUN_INFO['Visible Capacity'], CLONED_LUN_INFO['RAID Group ID'],
|
||||
CLONED_LUN_INFO['Owner Controller'],
|
||||
CLONED_LUN_INFO['Worker Controller'],
|
||||
CLONED_LUN_INFO['Lun Type'], CLONED_LUN_INFO['SnapShot ID'],
|
||||
CLONED_LUN_INFO['LunCopy ID']))
|
||||
else:
|
||||
out = 'ERROR: The object does not exist.'
|
||||
return out
|
||||
|
||||
|
||||
class HuaweiDorado2100G2CLIResSimulator(HuaweiTCLIResSimulator):
|
||||
def cli_showsys(self, params):
|
||||
out = """/>showsys
|
||||
==========================================================================
|
||||
System Information
|
||||
--------------------------------------------------------------------------
|
||||
System Name | SN_Dorado2100_G2
|
||||
Device Type | Oceanstor Dorado2100 G2
|
||||
Current System Mode | Double Controllers Normal
|
||||
Mirroring Link Status | Link Up
|
||||
Location |
|
||||
Time | 2013-01-01 01:01:01
|
||||
Product Version | V100R001C00
|
||||
===========================================================================
|
||||
"""
|
||||
return out
|
||||
|
||||
def cli_createlun(self, params):
|
||||
lun_type = ('THIN' if params[params.index('-type') + 1] == '2' else
|
||||
'THICK')
|
||||
if LUN_INFO['ID'] is None:
|
||||
LUN_INFO['Name'] = self._name_translate(FAKE_VOLUME['name'])
|
||||
LUN_INFO['ID'] = VOLUME_SNAP_ID['vol']
|
||||
LUN_INFO['Size'] = FAKE_VOLUME['size']
|
||||
LUN_INFO['Lun Type'] = lun_type
|
||||
LUN_INFO['Owner Controller'] = 'A'
|
||||
LUN_INFO['Worker Controller'] = 'A'
|
||||
LUN_INFO['RAID Group ID'] = POOL_SETTING['ID']
|
||||
FAKE_VOLUME['provider_location'] = LUN_INFO['ID']
|
||||
else:
|
||||
CLONED_LUN_INFO['Name'] = \
|
||||
self._name_translate(FAKE_CLONED_VOLUME['name'])
|
||||
CLONED_LUN_INFO['ID'] = VOLUME_SNAP_ID['vol_copy']
|
||||
CLONED_LUN_INFO['Size'] = FAKE_CLONED_VOLUME['size']
|
||||
CLONED_LUN_INFO['Lun Type'] = lun_type
|
||||
CLONED_LUN_INFO['Owner Controller'] = 'A'
|
||||
CLONED_LUN_INFO['Worker Controller'] = 'A'
|
||||
CLONED_LUN_INFO['RAID Group ID'] = POOL_SETTING['ID']
|
||||
CLONED_LUN_INFO['provider_location'] = CLONED_LUN_INFO['ID']
|
||||
FAKE_CLONED_VOLUME['provider_location'] = CLONED_LUN_INFO['ID']
|
||||
out = 'command operates successfully'
|
||||
return out
|
||||
|
||||
def cli_showlun(self, params):
|
||||
if '-lun' not in params:
|
||||
if LUN_INFO['ID'] is None:
|
||||
out = 'command operates successfully, but no information.'
|
||||
elif CLONED_LUN_INFO['ID'] is None:
|
||||
out = """/>showlun
|
||||
===========================================================================
|
||||
LUN Information
|
||||
---------------------------------------------------------------------------
|
||||
ID Status Controller Visible Capacity(MB) LUN Name Lun Type
|
||||
---------------------------------------------------------------------------
|
||||
%s Normal %s %s %s THICK
|
||||
===========================================================================
|
||||
""" % (LUN_INFO['ID'], LUN_INFO['Owner Controller'],
|
||||
str(int(LUN_INFO['Size']) * 1024), LUN_INFO['Name'])
|
||||
else:
|
||||
out = """/>showlun
|
||||
===========================================================================
|
||||
LUN Information
|
||||
---------------------------------------------------------------------------
|
||||
ID Status Controller Visible Capacity(MB) LUN Name Lun Type
|
||||
---------------------------------------------------------------------------
|
||||
%s Normal %s %s %s THICK
|
||||
%s Normal %s %s %s THICK
|
||||
===========================================================================
|
||||
""" % (LUN_INFO['ID'], LUN_INFO['Owner Controller'],
|
||||
str(int(LUN_INFO['Size']) * 1024), LUN_INFO['Name'],
|
||||
CLONED_LUN_INFO['ID'], CLONED_LUN_INFO['Owner Controller'],
|
||||
str(int(CLONED_LUN_INFO['Size']) * 1024), CLONED_LUN_INFO['Name'])
|
||||
|
||||
elif params[params.index('-lun') + 1] in VOLUME_SNAP_ID.values():
|
||||
out = """/>showlun
|
||||
================================================
|
||||
LUN Information
|
||||
------------------------------------------------
|
||||
ID | %s
|
||||
Name | %s
|
||||
LUN WWN | --
|
||||
Visible Capacity | %s
|
||||
RAID GROUP ID | %s
|
||||
Owning Controller | %s
|
||||
Workong Controller | %s
|
||||
Lun Type | %s
|
||||
SnapShot ID | %s
|
||||
LunCopy ID | %s
|
||||
================================================
|
||||
""" % ((LUN_INFO['ID'], LUN_INFO['Name'], LUN_INFO['Visible Capacity'],
|
||||
LUN_INFO['RAID Group ID'], LUN_INFO['Owner Controller'],
|
||||
LUN_INFO['Worker Controller'], LUN_INFO['Lun Type'],
|
||||
LUN_INFO['SnapShot ID'], LUN_INFO['LunCopy ID'])
|
||||
if params[params.index('-lun')] == VOLUME_SNAP_ID['vol'] else
|
||||
(CLONED_LUN_INFO['ID'], CLONED_LUN_INFO['Name'],
|
||||
CLONED_LUN_INFO['Visible Capacity'], CLONED_LUN_INFO['RAID Group ID'],
|
||||
CLONED_LUN_INFO['Owner Controller'],
|
||||
CLONED_LUN_INFO['Worker Controller'],
|
||||
CLONED_LUN_INFO['Lun Type'], CLONED_LUN_INFO['SnapShot ID'],
|
||||
CLONED_LUN_INFO['LunCopy ID']))
|
||||
|
||||
else:
|
||||
out = 'ERROR: The object does not exist.'
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class HuaweiTISCSIDriverTestCase(test.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(HuaweiTISCSIDriverTestCase, self).__init__(*args, **kwargs)
|
||||
@ -1199,6 +1393,81 @@ class HuaweiTISCSIDriverTestCase(test.TestCase):
|
||||
self.assertEqual(stats['storage_protocol'], 'iSCSI')
|
||||
|
||||
|
||||
class HuaweiDorado5100ISCSIDriverTestCase(HuaweiTISCSIDriverTestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(HuaweiDorado5100ISCSIDriverTestCase, self).__init__(*args,
|
||||
**kwargs)
|
||||
|
||||
def setUp(self):
|
||||
super(HuaweiDorado5100ISCSIDriverTestCase, self).setUp()
|
||||
|
||||
def _init_driver(self):
|
||||
Curr_test[0] = 'Dorado5100'
|
||||
modify_conf(self.fake_conf_file, 'Storage/Product', 'Dorado')
|
||||
self.driver = HuaweiVolumeDriver(configuration=self.configuration)
|
||||
self.driver.do_setup(None)
|
||||
|
||||
def test_create_delete_cloned_volume(self):
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.create_cloned_volume,
|
||||
FAKE_CLONED_VOLUME, FAKE_VOLUME)
|
||||
|
||||
def test_create_delete_snapshot_volume(self):
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.create_volume_from_snapshot,
|
||||
FAKE_CLONED_VOLUME, FAKE_SNAPSHOT)
|
||||
|
||||
def test_volume_type(self):
|
||||
pass
|
||||
|
||||
|
||||
class HuaweiDorado2100G2ISCSIDriverTestCase(HuaweiTISCSIDriverTestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(HuaweiDorado2100G2ISCSIDriverTestCase, self).__init__(*args,
|
||||
**kwargs)
|
||||
|
||||
def setUp(self):
|
||||
super(HuaweiDorado2100G2ISCSIDriverTestCase, self).setUp()
|
||||
|
||||
def _init_driver(self):
|
||||
Curr_test[0] = 'Dorado2100G2'
|
||||
modify_conf(self.fake_conf_file, 'Storage/Product', 'Dorado')
|
||||
self.driver = HuaweiVolumeDriver(configuration=self.configuration)
|
||||
self.driver.do_setup(None)
|
||||
|
||||
def test_conf_invalid(self):
|
||||
pass
|
||||
|
||||
def test_create_delete_cloned_volume(self):
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.create_cloned_volume,
|
||||
FAKE_CLONED_VOLUME, FAKE_VOLUME)
|
||||
|
||||
def test_create_delete_snapshot(self):
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.create_snapshot, FAKE_SNAPSHOT)
|
||||
|
||||
def test_create_delete_snapshot_volume(self):
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.driver.create_volume_from_snapshot,
|
||||
FAKE_CLONED_VOLUME, FAKE_SNAPSHOT)
|
||||
|
||||
def test_initialize_connection(self):
|
||||
self.driver.create_volume(FAKE_VOLUME)
|
||||
ret = self.driver.initialize_connection(FAKE_VOLUME, FAKE_CONNECTOR)
|
||||
iscsi_propers = ret['data']
|
||||
self.assertEquals(iscsi_propers['target_iqn'],
|
||||
INITIATOR_SETTING['TargetIQN-form'])
|
||||
self.assertEquals(iscsi_propers['target_portal'],
|
||||
INITIATOR_SETTING['Initiator TargetIP'] + ':3260')
|
||||
self.assertEqual(MAP_INFO["DEV LUN ID"], LUN_INFO['ID'])
|
||||
self.assertEqual(MAP_INFO["INI Port Info"],
|
||||
FAKE_CONNECTOR['initiator'])
|
||||
self.driver.terminate_connection(FAKE_VOLUME, FAKE_CONNECTOR)
|
||||
self.driver.delete_volume(FAKE_VOLUME)
|
||||
self.assertEqual(LUN_INFO['ID'], None)
|
||||
|
||||
|
||||
class SSHMethodTestCase(test.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SSHMethodTestCase, self).__init__(*args, **kwargs)
|
||||
|
@ -27,6 +27,7 @@ from cinder import exception
|
||||
from cinder.openstack.common import log as logging
|
||||
from cinder.volume.configuration import Configuration
|
||||
from cinder.volume import driver
|
||||
from cinder.volume.drivers.huawei import huawei_dorado
|
||||
from cinder.volume.drivers.huawei import huawei_t
|
||||
from cinder.volume.drivers.huawei import ssh_common
|
||||
|
||||
@ -46,7 +47,7 @@ class HuaweiVolumeDriver(object):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(HuaweiVolumeDriver, self).__init__()
|
||||
self._product = {'T': huawei_t}
|
||||
self._product = {'T': huawei_t, 'Dorado': huawei_dorado}
|
||||
self._protocol = {'iSCSI': 'ISCSIDriver'}
|
||||
|
||||
self.driver = self._instantiate_driver(*args, **kwargs)
|
||||
@ -83,7 +84,7 @@ class HuaweiVolumeDriver(object):
|
||||
return (product, protocol)
|
||||
else:
|
||||
msg = (_('"Product" or "Protocol" is illegal. "Product" should '
|
||||
'be set to T. "Protocol" should be set '
|
||||
'be set to either T or Dorado. "Protocol" should be set '
|
||||
'to iSCSI. Product: %(product)s '
|
||||
'Protocol: %(protocol)s')
|
||||
% {'product': str(product),
|
||||
|
38
cinder/volume/drivers/huawei/huawei_dorado.py
Normal file
38
cinder/volume/drivers/huawei/huawei_dorado.py
Normal file
@ -0,0 +1,38 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright (c) 2013 Huawei Technologies Co., Ltd.
|
||||
# Copyright (c) 2012 OpenStack LLC.
|
||||
# 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.
|
||||
"""
|
||||
Volume Drivers for Huawei OceanStor Dorado series storage arrays.
|
||||
"""
|
||||
|
||||
from cinder.volume.drivers.huawei import huawei_t
|
||||
from cinder.volume.drivers.huawei import ssh_common
|
||||
|
||||
|
||||
class HuaweiDoradoISCSIDriver(huawei_t.HuaweiTISCSIDriver):
|
||||
"""ISCSI driver class for Huawei OceanStor Dorado storage arrays."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(HuaweiDoradoISCSIDriver, self).__init__(*args, **kwargs)
|
||||
|
||||
def do_setup(self, context):
|
||||
"""Instantiate common class."""
|
||||
self.common = ssh_common.DoradoCommon(configuration=self.configuration)
|
||||
|
||||
self.common.do_setup(context)
|
||||
self._assert_cli_out = self.common._assert_cli_out
|
||||
self._assert_cli_operate_out = self.common._assert_cli_operate_out
|
@ -1127,3 +1127,235 @@ class TseriesCommon():
|
||||
|
||||
pool = out.split('\r\n')[6:-2]
|
||||
return [line.split() for line in pool]
|
||||
|
||||
|
||||
class DoradoCommon(TseriesCommon):
|
||||
"""Common class for Huawei Dorado2100 G2 and Dorado5100 storage arrays.
|
||||
|
||||
Dorados share a lot of common codes with T series storage systems,
|
||||
so this class inherited from class TseriesCommon and just rewrite some
|
||||
methods.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, configuration=None):
|
||||
TseriesCommon.__init__(self, configuration)
|
||||
self.device_type = None
|
||||
|
||||
def do_setup(self, context):
|
||||
"""Check config file."""
|
||||
LOG.debug(_('do_setup.'))
|
||||
|
||||
self._check_conf_file()
|
||||
self.lun_distribution = self._get_lun_ctr_info()
|
||||
|
||||
def _check_conf_file(self):
|
||||
"""Check the config file, make sure the key elements are set."""
|
||||
root = parse_xml_file(self.xml_conf)
|
||||
# Check login infomation
|
||||
IP1 = root.findtext('Storage/ControllerIP0')
|
||||
IP2 = root.findtext('Storage/ControllerIP1')
|
||||
username = root.findtext('Storage/UserName')
|
||||
pwd = root.findtext('Storage/UserPassword')
|
||||
if (not IP1 and not IP2) or (not username) or (not pwd):
|
||||
err_msg = (_('Config file invalid. Controler IP, UserName, '
|
||||
'UserPassword must be specified.'))
|
||||
LOG.error(err_msg)
|
||||
raise exception.InvalidInput(reason=err_msg)
|
||||
|
||||
# Check storage pool
|
||||
# No need for Dorado2100 G2
|
||||
self.login_info = self._get_login_info()
|
||||
self.device_type = self._get_device_type()
|
||||
if self.device_type == 'Dorado5100':
|
||||
pool_node = root.findall('LUN/StoragePool')
|
||||
if not pool_node:
|
||||
err_msg = (_('_check_conf_file: Config file invalid. '
|
||||
'StoragePool must be specified.'))
|
||||
LOG.error(err_msg)
|
||||
raise exception.InvalidInput(reason=err_msg)
|
||||
|
||||
def _get_device_type(self):
|
||||
"""Run CLI command to get system type."""
|
||||
cli_cmd = 'showsys'
|
||||
out = self._execute_cli(cli_cmd)
|
||||
|
||||
self._assert_cli_out(re.search('System Information', out),
|
||||
'_get_device_type',
|
||||
'Failed to get system information',
|
||||
cli_cmd, out)
|
||||
|
||||
for line in out.split('\r\n')[4:-2]:
|
||||
if re.search('Device Type', line):
|
||||
if re.search('Dorado2100 G2$', line):
|
||||
return 'Dorado2100 G2'
|
||||
elif re.search('Dorado5100$', line):
|
||||
return 'Dorado5100'
|
||||
else:
|
||||
LOG.error(_('_get_device_type: The drivers only support'
|
||||
'Dorado5100 and Dorado 2100 G2 now.'))
|
||||
raise exception.InvalidResults()
|
||||
|
||||
def _get_lun_ctr_info(self):
|
||||
luns = self._get_all_luns_info()
|
||||
ctr_info = [0, 0]
|
||||
(c, n) = ((2, 4) if self.device_type == 'Dorado2100 G2' else (3, 5))
|
||||
for lun in luns:
|
||||
if lun[n].startswith('OpenStack'):
|
||||
if lun[c] == 'A':
|
||||
ctr_info[0] += 1
|
||||
else:
|
||||
ctr_info[1] += 1
|
||||
return ctr_info
|
||||
|
||||
def _create_volume(self, name, size, params):
|
||||
"""Create a new volume with the given name and size."""
|
||||
cli_cmd = ('createlun -n %(name)s -lunsize %(size)s '
|
||||
'-wrtype %(wrtype)s '
|
||||
% {'name': name,
|
||||
'size': size,
|
||||
'wrtype': params['WriteType']})
|
||||
|
||||
# If write type is "write through", no need to set mirror switch.
|
||||
if params['WriteType'] != '2':
|
||||
cli_cmd = cli_cmd + ('-mirrorsw %(mirrorsw)s '
|
||||
% {'mirrorsw': params['MirrorSwitch']})
|
||||
|
||||
ctr = self._calculate_lun_ctr()
|
||||
# Dorado5100 does not support thin LUN.
|
||||
if self.device_type == 'Dorado5100':
|
||||
cli_cmd = cli_cmd + ('-rg %(raidgroup)s -susize %(susize)s '
|
||||
'-c %(ctr)s'
|
||||
% {'raidgroup': params['StoragePool'],
|
||||
'susize': params['StripUnitSize'],
|
||||
'ctr': ctr})
|
||||
else:
|
||||
if params['LUNType'] == 'Thin':
|
||||
# Not allowed to specify ctr for thin LUN.
|
||||
ctr_str = ''
|
||||
luntype_str = '-type 2'
|
||||
else:
|
||||
ctr_str = ' -c %s' % ctr
|
||||
luntype_str = '-type 3'
|
||||
|
||||
cli_cmd = cli_cmd + luntype_str + ctr_str
|
||||
|
||||
out = self._execute_cli(cli_cmd)
|
||||
|
||||
self._assert_cli_operate_out('_create_volume',
|
||||
'Failed to create volume %s' % name,
|
||||
cli_cmd, out)
|
||||
|
||||
self._update_lun_distribution(ctr)
|
||||
|
||||
return self._get_lun_id(name)
|
||||
|
||||
def _get_lun_id(self, name):
|
||||
luns = self._get_all_luns_info()
|
||||
if luns:
|
||||
n_index = (4 if 'Dorado2100 G2' == self.device_type else 5)
|
||||
for lun in luns:
|
||||
if lun[n_index] == name:
|
||||
return lun[0]
|
||||
return None
|
||||
|
||||
def create_volume_from_snapshot(self, volume, snapshot):
|
||||
err_msg = (_('create_volume_from_snapshot: %(device)s does '
|
||||
'not support create volume from snapshot.')
|
||||
% {'device': self.device_type})
|
||||
LOG.error(err_msg)
|
||||
raise exception.VolumeBackendAPIException(data=err_msg)
|
||||
|
||||
def create_cloned_volume(self, volume, src_vref):
|
||||
err_msg = (_('create_cloned_volume: %(device)s does '
|
||||
'not support clone volume.')
|
||||
% {'device': self.device_type})
|
||||
LOG.error(err_msg)
|
||||
raise exception.VolumeBackendAPIException(data=err_msg)
|
||||
|
||||
def create_snapshot(self, snapshot):
|
||||
if self.device_type == 'Dorado2100 G2':
|
||||
err_msg = (_('create_snapshot: %(device)s does not support '
|
||||
'snapshot.') % {'device': self.device_type})
|
||||
LOG.error(err_msg)
|
||||
raise exception.VolumeBackendAPIException(data=err_msg)
|
||||
else:
|
||||
return TseriesCommon.create_snapshot(self, snapshot)
|
||||
|
||||
def delete_snapshot(self, snapshot):
|
||||
if self.device_type == 'Dorado2100 G2':
|
||||
return
|
||||
else:
|
||||
TseriesCommon.delete_snapshot(self, snapshot)
|
||||
|
||||
def _get_lun_params(self):
|
||||
params_conf = self._parse_conf_lun_params()
|
||||
# Select a pool with maximum capacity.
|
||||
if self.device_type == 'Dorado5100':
|
||||
pools_dev = self._get_dev_pool_info('Thick')
|
||||
params_conf['StoragePool'] = \
|
||||
self._get_maximum_capacity_pool_id(params_conf['StoragePool'],
|
||||
pools_dev, 'Thick')
|
||||
return params_conf
|
||||
|
||||
def _parse_conf_lun_params(self):
|
||||
"""Get parameters from config file for creating LUN."""
|
||||
# Default LUN parameters.
|
||||
conf_params = {'LUNType': 'Thin',
|
||||
'StripUnitSize': '64',
|
||||
'WriteType': '1',
|
||||
'MirrorSwitch': '1'}
|
||||
|
||||
root = parse_xml_file(self.xml_conf)
|
||||
|
||||
luntype = root.findtext('LUN/LUNType')
|
||||
if luntype:
|
||||
if luntype.strip() in ['Thick', 'Thin']:
|
||||
conf_params['LUNType'] = luntype.strip()
|
||||
else:
|
||||
err_msg = (_('LUNType must be "Thin" or "Thick". '
|
||||
'LUNType:%(type)s') % {'type': luntype})
|
||||
raise exception.InvalidInput(reason=err_msg)
|
||||
|
||||
# Here we do not judge whether the parameters are set correct.
|
||||
# CLI will return error responses if the parameters are invalid.
|
||||
stripunitsize = root.findtext('LUN/StripUnitSize')
|
||||
if stripunitsize:
|
||||
conf_params['StripUnitSize'] = stripunitsize.strip()
|
||||
writetype = root.findtext('LUN/WriteType')
|
||||
if writetype:
|
||||
conf_params['WriteType'] = writetype.strip()
|
||||
mirrorswitch = root.findtext('LUN/MirrorSwitch')
|
||||
if mirrorswitch:
|
||||
conf_params['MirrorSwitch'] = mirrorswitch.strip()
|
||||
|
||||
# No need to set StoragePool for Dorado2100 G2.
|
||||
if self.device_type == 'Dorado2100 G2':
|
||||
return conf_params
|
||||
|
||||
pools_conf = root.findall('LUN/StoragePool')
|
||||
conf_params['StoragePool'] = []
|
||||
for pool in pools_conf:
|
||||
conf_params['StoragePool'].append(pool.attrib['Name'].strip())
|
||||
|
||||
return conf_params
|
||||
|
||||
def _get_free_capacity(self):
|
||||
"""Get total free capacity of pools."""
|
||||
self._update_login_info()
|
||||
lun_type = ('Thin' if self.device_type == 'Dorado2100 G2' else 'Thick')
|
||||
pools_dev = self._get_dev_pool_info(lun_type)
|
||||
total_free_capacity = 0.0
|
||||
for pool_dev in pools_dev:
|
||||
if self.device_type == 'Dorado2100 G2':
|
||||
total_free_capacity += float(pool_dev[2])
|
||||
continue
|
||||
else:
|
||||
params_conf = self._parse_conf_lun_params()
|
||||
pools_conf = params_conf['StoragePool']
|
||||
for pool_conf in pools_conf:
|
||||
if pool_dev[5] == pool_conf:
|
||||
total_free_capacity += float(pool_dev[3])
|
||||
break
|
||||
|
||||
return total_free_capacity / 1024
|
||||
|
Loading…
x
Reference in New Issue
Block a user