From 39c30022bf4c40240e507059e30d32d1b771a8b9 Mon Sep 17 00:00:00 2001 From: zhangchao010 Date: Thu, 12 Sep 2013 22:34:22 +0800 Subject: [PATCH] Improves the parsing way of ssh returns Huawei driver failed to parse ssh result when firstly logging in storage system on paramiko 1.8.0. The update of paramiko make the order of ssh returns changed. This patch improves the parsing way of ssh returns. This patch also does some changes for log punctuations. fixes bug 1224499 Change-Id: Ia8761081dff998884f45312355b62aa27ab5417c --- cinder/volume/drivers/huawei/huawei_t.py | 16 +++--- cinder/volume/drivers/huawei/ssh_common.py | 57 ++++++++++++---------- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/cinder/volume/drivers/huawei/huawei_t.py b/cinder/volume/drivers/huawei/huawei_t.py index 911727bff..67ca7d2d6 100644 --- a/cinder/volume/drivers/huawei/huawei_t.py +++ b/cinder/volume/drivers/huawei/huawei_t.py @@ -95,8 +95,8 @@ class HuaweiTISCSIDriver(driver.ISCSIDriver): def initialize_connection(self, volume, connector): """Map a volume to a host and return target iSCSI information.""" - LOG.debug(_('initialize_connection: volume name: %(vol)s ' - 'host: %(host)s initiator: %(ini)s') + LOG.debug(_('initialize_connection: volume name: %(vol)s, ' + 'host: %(host)s, initiator: %(ini)s') % {'vol': volume['name'], 'host': connector['host'], 'ini': connector['initiator']}) @@ -227,7 +227,7 @@ class HuaweiTISCSIDriver(driver.ISCSIDriver): iqn = iqn_prefix + ':' + iqn_suffix + ':' + port_info[3] - LOG.debug(_('_get_tgt_iqn: iSCSI target iqn is %s') % iqn) + LOG.debug(_('_get_tgt_iqn: iSCSI target iqn is %s.') % iqn) return (iqn, port_info[0]) @@ -316,7 +316,7 @@ class HuaweiTISCSIDriver(driver.ISCSIDriver): def terminate_connection(self, volume, connector, **kwargs): """Terminate the map.""" - LOG.debug(_('terminate_connection: volume: %(vol)s host: %(host)s ' + LOG.debug(_('terminate_connection: volume: %(vol)s, host: %(host)s, ' 'connector: %(initiator)s') % {'vol': volume['name'], 'host': connector['host'], @@ -344,7 +344,7 @@ class HuaweiTISCSIDriver(driver.ISCSIDriver): break else: LOG.warn(_('_remove_iscsi_port: iSCSI port was not found ' - 'on host %(hostid)s') % {'hostid': hostid}) + 'on host %(hostid)s.') % {'hostid': hostid}) # Delete host if no initiator added to it. if port_num == 0: @@ -431,8 +431,8 @@ class HuaweiTFCDriver(driver.FibreChannelDriver): def initialize_connection(self, volume, connector): """Create FC connection between a volume and a host.""" - LOG.debug(_('initialize_connection: volume name: %(vol)s ' - 'host: %(host)s initiator: %(wwn)s') + LOG.debug(_('initialize_connection: volume name: %(vol)s, ' + 'host: %(host)s, initiator: %(wwn)s') % {'vol': volume['name'], 'host': connector['host'], 'wwn': connector['wwpns']}) @@ -540,7 +540,7 @@ class HuaweiTFCDriver(driver.FibreChannelDriver): def terminate_connection(self, volume, connector, **kwargs): """Terminate the map.""" - LOG.debug(_('terminate_connection: volume: %(vol)s host: %(host)s ' + LOG.debug(_('terminate_connection: volume: %(vol)s, host: %(host)s, ' 'connector: %(initiator)s') % {'vol': volume['name'], 'host': connector['host'], diff --git a/cinder/volume/drivers/huawei/ssh_common.py b/cinder/volume/drivers/huawei/ssh_common.py index 3de97b2ee..e4dae758d 100644 --- a/cinder/volume/drivers/huawei/ssh_common.py +++ b/cinder/volume/drivers/huawei/ssh_common.py @@ -64,23 +64,26 @@ def ssh_read(user, channel, cmd, timeout): result = result + channel.recv(8192) except socket.timeout: raise exception.CinderException(_('ssh_read: Read ' - 'SSH timeout')) + 'SSH timeout.')) else: - # Complete CLI response starts with CLI cmd and - # ends with "username:/>". - if result.startswith(cmd) and result.endswith(user + ':/>'): - if not re.search('Welcome', result): + # CLI returns welcome information when first log in. So need to + # deal differently. + if not re.search('Welcome', result): + # Complete CLI response starts with CLI cmd and + # ends with "username:/>". + if result.startswith(cmd) and result.endswith(user + ':/>'): break - # CLI returns welcome information when first log in. - elif re.search(user + ':/>' + cmd, result): + # Some commands need to send 'y'. + elif re.search('(y/n)', result): break - # Some commands need to send 'y'. - elif re.search('(y/n)', result): + # Reach maximum limit of SSH connection. + elif re.search('No response message', result): + msg = _('No response message. Please check system status.') + raise exception.CinderException(msg) + elif (re.search(user + ':/>' + cmd, result) and + result.endswith(user + ':/>')): break - # Reach maximum limit of SSH connection. - elif re.search('No response message', result): - msg = _('No response message. Please check system status.') - raise exception.CinderException(msg) + # Filter the last line: username:/> . result = '\r\n'.join(result.split('\r\n')[:-1]) # Filter welcome information. @@ -104,7 +107,7 @@ class TseriesCommon(): def do_setup(self, context): """Check config file.""" - LOG.debug(_('do_setup.')) + LOG.debug(_('do_setup')) self._check_conf_file() self.login_info = self._get_login_info() @@ -208,7 +211,7 @@ class TseriesCommon(): """Create a new volume.""" volume_name = self._name_translate(volume['name']) - LOG.debug(_('create_volume: volume name: %s.') % volume_name) + LOG.debug(_('create_volume: volume name: %s') % volume_name) self._update_login_info() if int(volume['size']) == 0: @@ -379,7 +382,7 @@ class TseriesCommon(): conf_params['PrefetchTimes'] = prefetch.attrib['Value'].strip() else: LOG.debug(_('_parse_conf_lun_params: Use default prefetch type. ' - 'Prefetch type: Intelligent.')) + 'Prefetch type: Intelligent')) pools_conf = root.findall('LUN/StoragePool') for pool in pools_conf: @@ -492,7 +495,7 @@ class TseriesCommon(): def delete_volume(self, volume): volume_name = self._name_translate(volume['name']) - LOG.debug(_('delete_volume: volume name: %s.') % volume_name) + LOG.debug(_('delete_volume: volume name: %s') % volume_name) self._update_login_info() volume_id = volume.get('provider_location', None) @@ -530,7 +533,7 @@ class TseriesCommon(): volume_name = self._name_translate(volume['name']) LOG.debug(_('create_volume_from_snapshot: snapshot ' - 'name: %(snapshot)s, volume name: %(volume)s.') + 'name: %(snapshot)s, volume name: %(volume)s') % {'snapshot': snapshot_name, 'volume': volume_name}) @@ -647,7 +650,7 @@ class TseriesCommon(): src_vol_name = self._name_translate(src_volume['name']) tgt_vol_name = self._name_translate(tgt_volume['name']) - LOG.debug(_('create_cloned_volume: src volume: %(src)s ' + LOG.debug(_('create_cloned_volume: src volume: %(src)s, ' 'tgt volume: %(tgt)s') % {'src': src_vol_name, 'tgt': tgt_vol_name}) @@ -694,7 +697,7 @@ class TseriesCommon(): snapshot_name = self._name_translate(snapshot['name']) volume_name = self._name_translate(snapshot['volume_name']) - LOG.debug(_('create_snapshot: snapshot name: %(snapshot)s ' + LOG.debug(_('create_snapshot: snapshot name: %(snapshot)s, ' 'volume name: %(volume)s') % {'snapshot': snapshot_name, 'volume': volume_name}) @@ -770,7 +773,7 @@ class TseriesCommon(): snapshot_name = self._name_translate(snapshot['name']) volume_name = self._name_translate(snapshot['volume_name']) - LOG.debug(_('delete_snapshot: snapshot name: %(snapshot)s ' + LOG.debug(_('delete_snapshot: snapshot name: %(snapshot)s, ' 'volume name: %(volume)s') % {'snapshot': snapshot_name, 'volume': volume_name}) @@ -873,7 +876,7 @@ class TseriesCommon(): 'hostlunid': new_hostlun_id}) out = self._execute_cli(cli_cmd) - msg = ('Failed to map lun %s to host %s. host lun ID: %s' + msg = ('Failed to map LUN %s to host %s. host LUN ID: %s' % (volume_id, host_id, new_hostlun_id)) self._assert_cli_operate_out('map_volume', msg, cli_cmd, out) @@ -981,7 +984,7 @@ class TseriesCommon(): return lun_details def change_lun_ctr(self, lun_id, ctr): - LOG.debug(_('change_lun_ctr: Changing LUN %(lun)s ctr to %(ctr)s') + LOG.debug(_('change_lun_ctr: Changing LUN %(lun)s ctr to %(ctr)s.') % {'lun': lun_id, 'ctr': ctr}) cli_cmd = 'chglun -lun %s -c %s' % (lun_id, ctr) @@ -1080,7 +1083,7 @@ class TseriesCommon(): def _update_volume_stats(self): """Retrieve stats info from volume group.""" - LOG.debug(_("_update_volume_stats: Updating volume stats")) + LOG.debug(_("_update_volume_stats: Updating volume stats.")) data = {} data['vendor_name'] = 'Huawei' data['total_capacity_gb'] = 'infinite' @@ -1144,7 +1147,7 @@ class DoradoCommon(TseriesCommon): def do_setup(self, context): """Check config file.""" - LOG.debug(_('do_setup.')) + LOG.debug(_('do_setup')) self._check_conf_file() self.lun_distribution = self._get_lun_ctr_info() @@ -1192,7 +1195,7 @@ class DoradoCommon(TseriesCommon): elif re.search('Dorado5100$', line): return 'Dorado5100' else: - LOG.error(_('_get_device_type: The drivers only support' + LOG.error(_('_get_device_type: The driver only supports ' 'Dorado5100 and Dorado 2100 G2 now.')) raise exception.InvalidResults() @@ -1201,7 +1204,7 @@ class DoradoCommon(TseriesCommon): 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[n].startswith(VOL_AND_SNAP_NAME_PREFIX): if lun[c] == 'A': ctr_info[0] += 1 else: -- 2.45.2