From: zhangchao010 Date: Mon, 4 Mar 2013 16:07:41 +0000 (+0800) Subject: Fix bugs for Huawei driver X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=c09f69948df29e84907960f69fb5ef46745ebef6;p=openstack-build%2Fcinder-build.git Fix bugs for Huawei driver This fixes two bugs for Huawei iscsi driver. (1)If firstly we map LUN 1(just not LUN 0) to host,we can also find LUN 0 mapped,whose device path is '-'.Then we will failed to map a real LUN 0.So,we avoid mapping LUN 0 to host by setting every volume's host LUN ID larger than 0,instead of generating it automatically. (2)Check valid size of resource pools when creating snapshot and make sure it larger than 1 GB. Fixes bug: 1135618 Fixes bug: 1136980 Change-Id: I412e78bf84c95cb51431c45cc084e9ec6a8efb78 --- diff --git a/cinder/tests/test_huawei.py b/cinder/tests/test_huawei.py index 032476170..fc4d2249e 100644 --- a/cinder/tests/test_huawei.py +++ b/cinder/tests/test_huawei.py @@ -793,6 +793,18 @@ Link Status Multipath Type FakePoolInfo['Status'], FakePoolInfo['Free Capacity'], FakePoolInfo['Disk List'], FakePoolInfo['Name']) + elif cmd == 'showrespool': + out = """/>showrespool +============================================================================ + Resource Pool Information +---------------------------------------------------------------------------- + Pool ID Size(MB) Usage(MB) Valid Size(MB) Alarm Threshold(%) +---------------------------------------------------------------------------- + A 5130.0 0.0 5130.0 80 + B 3082.0 0.0 3082.0 80 +============================================================================ +""" + out = out.replace('\n', '\r\n') return out diff --git a/cinder/volume/drivers/huawei/huawei_iscsi.py b/cinder/volume/drivers/huawei/huawei_iscsi.py index f5d732ce1..7f0ed0b35 100644 --- a/cinder/volume/drivers/huawei/huawei_iscsi.py +++ b/cinder/volume/drivers/huawei/huawei_iscsi.py @@ -274,14 +274,22 @@ class HuaweiISCSIDriver(driver.ISCSIDriver): hostlun_id = None map_info = self._get_map_info(host_id) + # Make sure the hostLUN ID starts from 1. + new_hostlun_id = 1 + new_hostlunid_found = False if map_info: for map in map_info: if map['devlunid'] == lun_id: hostlun_id = map['hostlunid'] break + elif not new_hostlunid_found: + if new_hostlun_id < int(map['hostlunid']): + new_hostlunid_found = True + else: + new_hostlun_id = int(map['hostlunid']) + 1 # The LUN is not mapped to the host. if not hostlun_id: - self._map_lun(lun_id, host_id) + self._map_lun(lun_id, host_id, new_hostlun_id) hostlun_id = self._get_hostlunid(host_id, lun_id) # Return iSCSI properties. @@ -382,6 +390,13 @@ class HuaweiISCSIDriver(driver.ISCSIDriver): self.login_info = self._get_login_info() if self.device_type['type'] == 'Dorado2100 G2': err_msg = (_('create_snapshot:Device does not support snapshot.')) + + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + if self._is_resource_pool_enough() is False: + err_msg = (_('create_snapshot:' + 'Resource pool needs 1GB valid size at least.')) LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) @@ -979,19 +994,26 @@ class HuaweiISCSIDriver(driver.ISCSIDriver): return iscsiIPinfo return None - def _map_lun(self, lunid, hostid): - """Map a lun to a host.""" + def _map_lun(self, lunid, hostid, new_hostlun_id): + """Map a lun to a host. + + Here we give the hostlun ID which starts from 1. + """ cli_cmd = ('addhostmap -host %(hostid)s -devlun %(lunid)s' + '-hostlun %(hostlunid)s' % {'hostid': hostid, - 'lunid': lunid}) + 'lunid': lunid, + 'hostlunid': new_hostlun_id}) out = self._execute_cli(cli_cmd) if not re.search('command operates successfully', out): err_msg = (_('_map_lun:Failed to add hostmap.' 'hostid:%(host)s' - 'lunid:%(lun)s.' + 'lunid:%(lun)s' + 'hostlunid:%(hostlunid)s.' 'out:%(out)s') % {'host': hostid, 'lun': lunid, + 'hostlunid': new_hostlun_id, 'out': out}) LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) @@ -1048,7 +1070,13 @@ class HuaweiISCSIDriver(driver.ISCSIDriver): raise exception.VolumeBackendAPIException(data=err_msg) def _get_map_info(self, hostid): - """Get map infomation of the given host.""" + """Get map infomation of the given host. + + This method return a map information list. Every item in the list + is a dictionary. The dictionarie includes three keys: mapid, + devlunid, hostlunid. These items are sorted by hostlunid value + from small to large. + """ cli_cmd = ('showhostmap -host %(hostid)s' % {'hostid': hostid}) out = self._execute_cli(cli_cmd) @@ -1064,7 +1092,19 @@ class HuaweiISCSIDriver(driver.ISCSIDriver): list_tmp = en[i].split() list_val = [list_tmp[0], list_tmp[2], list_tmp[4]] dic = dict(map(None, list_key, list_val)) - mapinfo.append(dic) + inserted = False + mapinfo_length = len(mapinfo) + if mapinfo_length == 0: + mapinfo.append(dic) + continue + for index in range(0, mapinfo_length): + if (int(mapinfo[mapinfo_length - index - 1]['hostlunid']) < + int(dic['hostlunid'])): + mapinfo.insert(mapinfo_length - index, dic) + inserted = True + break + if not inserted: + mapinfo.insert(0, dic) return mapinfo def _get_device_type(self): @@ -1332,6 +1372,28 @@ class HuaweiISCSIDriver(driver.ISCSIDriver): return r[1] return None + def _is_resource_pool_enough(self): + """Check whether resource pools' valid size is more than 1G.""" + cli_cmd = ('showrespool') + out = self._execute_cli(cli_cmd) + en = re.split('\r\n', out) + if len(en) <= 6: + LOG.error(_('_is_resource_pool_enough:Resource pool for snapshot' + 'not be added.')) + return False + resource_pools = [] + list_key = ['pool id', 'size', 'usage', 'valid size', + 'alarm threshold'] + for i in range(6, len(en) - 2): + list_val = en[i].split() + dic = dict(map(None, list_key, list_val)) + resource_pools.append(dic) + + for pool in resource_pools: + if float(pool['valid size']) < 1024.0: + return False + return True + def _update_volume_status(self): """Retrieve status info from volume group."""