Merge "Improve Hitachi HNAS volume drivers log messages"

This commit is contained in:
Jenkins 2016-08-24 23:30:37 +00:00 committed by Gerrit Code Review
commit dbebca66b0
5 changed files with 188 additions and 121 deletions

View File

@ -254,10 +254,20 @@ class HNASiSCSIDriverTest(test.TestCase):
'172.17.39.133': {'evs_number': 2},
'172.17.39.134': {'evs_number': 3}}
version_info = {
'mac': '83-68-96-AA-DA-5D',
'model': 'HNAS 4040',
'version': '12.4.3924.11',
'hardware': 'NAS Platform',
'serial': 'B1339109',
}
self.mock_object(HNASSSHBackend, 'get_fs_info',
mock.Mock(return_value=True))
self.mock_object(HNASSSHBackend, 'get_evs_info',
mock.Mock(return_value=evs_info))
self.mock_object(HNASSSHBackend, 'get_version',
mock.Mock(return_value=version_info))
self.driver.do_setup(None)
@ -269,10 +279,20 @@ class HNASiSCSIDriverTest(test.TestCase):
'172.17.39.133': {'evs_number': 2},
'172.17.39.134': {'evs_number': 3}}
version_info = {
'mac': '83-68-96-AA-DA-5D',
'model': 'HNAS 4040',
'version': '12.4.3924.11',
'hardware': 'NAS Platform',
'serial': 'B1339109',
}
self.mock_object(HNASSSHBackend, 'get_fs_info',
mock.Mock(return_value=True))
self.mock_object(HNASSSHBackend, 'get_evs_info',
mock.Mock(return_value=evs_info))
self.mock_object(HNASSSHBackend, 'get_version',
mock.Mock(return_value=version_info))
self.assertRaises(exception.InvalidParameterValue,
self.driver.do_setup, None)

View File

@ -82,12 +82,12 @@ class HNASSSHBackend(object):
return out, err
except putils.ProcessExecutionError as e:
if 'Failed to establish SSC connection' in e.stderr:
LOG.debug("SSC connection error!")
msg = _("Failed to establish SSC connection.")
msg = _("Failed to establish SSC connection!")
LOG.exception(msg)
raise exception.HNASConnError(msg)
elif 'Connection reset' in e.stderr:
LOG.debug("HNAS connection reset!")
msg = _("HNAS has disconnected SSC")
msg = _("HNAS connection reset!")
LOG.exception(msg)
raise exception.HNASConnError(msg)
else:
raise
@ -124,6 +124,7 @@ class HNASSSHBackend(object):
self.storage_version = version_info
LOG.debug("version_info: %(info)s", {'info': self.storage_version})
return self.storage_version
def get_evs_info(self):
@ -236,7 +237,10 @@ class HNASSSHBackend(object):
# When the FS is found in the list of known FS, returns the EVS ID
for key in self.fslist:
if fs_label == self.fslist[key]['label']:
LOG.debug("EVS ID for fs %(fs)s: %(id)s.",
{'fs': fs_label, 'id': self.fslist[key]['evsid']})
return self.fslist[key]['evsid']
LOG.debug("Can't find EVS ID for fs %(fs)s.", {'fs': fs_label})
def _get_targets(self, evs_id, tgt_alias=None, refresh=False):
"""Gets the target list of an EVS.
@ -365,11 +369,13 @@ class HNASSSHBackend(object):
if not fs:
LOG.error(_LE("Can't find file %(file)s in FS %(label)s"),
{'file': src, 'label': fs_label})
msg = _('FS label: %s') % fs_label
msg = _('FS label: %(fs_label)s') % {'fs_label': fs_label}
raise exception.InvalidParameterValue(err=msg)
self._run_cmd("console-context", "--evs", fs['evsid'],
'file-clone-create', '-f', fs_label, src, name)
LOG.debug('file_clone: fs:%(fs_label)s %(src)s/src: -> %(name)s/dst',
{'fs_label': fs_label, 'src': src, 'name': name})
def extend_lu(self, fs_label, new_size, lu_name):
"""Extends an iSCSI volume.
@ -433,6 +439,7 @@ class HNASSSHBackend(object):
LOG.debug('add_iscsi_conn: LU %(lu)s added to %(tgt)s.',
{'lu': lu_name, 'tgt': tgt_alias})
LOG.debug('conn_info: %(conn_info)s', {'conn_info': conn_info})
return conn_info
@ -487,7 +494,10 @@ class HNASSSHBackend(object):
for line in lines:
if 'Globally unique name' in line:
full_iqn = line.split()[3]
LOG.debug('get_target_iqn: %(iqn)s', {'iqn': full_iqn})
return full_iqn
LOG.debug("Could not find iqn for alias %(alias)s on fs %(fs_label)s",
{'alias': tgt_alias, 'fs_label': fs_label})
def set_target_secret(self, targetalias, fs_label, secret):
"""Sets the chap secret for the specified target.
@ -598,7 +608,8 @@ class HNASSSHBackend(object):
lu_info['id'] = 0
lu_info['tgt'] = None
LOG.debug("LU %(lu)s not attached.", {'lu': vol_name})
LOG.debug("LU %(lu)s not attached. lu_info: %(lu_info)s",
{'lu': vol_name, 'lu_info': lu_info})
return lu_info
@ -769,6 +780,7 @@ class HNASSSHBackend(object):
export_list.append(export_info)
LOG.debug("get_export_list: %(exp_list)s", {'exp_list': export_list})
return export_list
def create_cloned_lu(self, src_lu, fs_label, clone_name):
@ -799,3 +811,5 @@ class HNASSSHBackend(object):
'iscsi-target', 'add', tgt_alias, secret)
self._get_targets(_evs_id, refresh=True)
LOG.debug("create_target: alias: %(alias)s fs_label: %(fs_label)s",
{'alias': tgt_alias, 'fs_label': fs_label})

View File

@ -140,15 +140,15 @@ class HNASISCSIDriver(driver.ISCSIDriver):
configuration is found.
:raises: ParameterNotFound
"""
LOG.debug("Available services: %(svc)s.",
{'svc': self.config['services'].keys()})
label = utils.extract_host(volume.host, level='pool')
LOG.info(_LI("Using service label: %(lbl)s."), {'lbl': label})
if label in self.config['services'].keys():
svc = self.config['services'][label]
LOG.info(_LI("Using service label: %(lbl)s."), {'lbl': label})
return svc['hdp']
else:
LOG.info(_LI("Available services: %(svc)s."),
{'svc': self.config['services'].keys()})
LOG.error(_LE("No configuration found for service: %(lbl)s."),
{'lbl': label})
raise exception.ParameterNotFound(param=label)
@ -176,6 +176,10 @@ class HNASISCSIDriver(driver.ISCSIDriver):
service = (
svc['iscsi_ip'], svc['iscsi_port'], svc['evs'], svc['port'],
fs_label, lu_info['tgt']['alias'], lu_info['tgt']['secret'])
LOG.info(_LI("Volume %(vol_name)s already mapped on target "
"%(tgt)s to LUN %(lunid)s."),
{'vol_name': volume.name, 'tgt': lu_info['tgt']['alias'],
'lunid': lu_info['id']})
return service
# Each EVS can have up to 32 targets. Each target can have up to 32
@ -291,11 +295,11 @@ class HNASISCSIDriver(driver.ISCSIDriver):
hnas_stat['pools'] = self.pools
LOG.info(_LI("stats: %(stat)s."), {'stat': hnas_stat})
LOG.debug("stats: %(stat)s.", {'stat': hnas_stat})
return hnas_stat
def _check_fs_list(self):
"""Verifies the FSs in HNAS array.
"""Verifies the FSs list in HNAS.
Verify that all FSs specified in the configuration files actually
exists on the storage.
@ -304,9 +308,8 @@ class HNASISCSIDriver(driver.ISCSIDriver):
for fs in fs_list:
if not self.backend.get_fs_info(fs):
msg = (
_("File system not found or not mounted: %(fs)s") %
{'fs': fs})
msg = (_("File system not found or not mounted: %(fs)s") %
{'fs': fs})
LOG.error(msg)
raise exception.ParameterNotFound(param=msg)
@ -324,22 +327,22 @@ class HNASISCSIDriver(driver.ISCSIDriver):
pool_from_vol_type = hnas_utils.get_pool(self.config, volume)
pool_from_host = utils.extract_host(volume.host, level='pool')
if self.config['services'][pool_from_vol_type]['hdp'] != fs_label:
msg = (_("Failed to manage existing volume because the pool of "
"the volume type chosen does not match the file system "
"passed in the volume reference."),
{'File System passed': fs_label,
'File System for volume type':
self.config['services'][pool_from_vol_type]['hdp']})
pool = self.config['services'][pool_from_vol_type]['hdp']
if pool != fs_label:
msg = (_("Failed to manage existing volume because the "
"pool %(pool)s of the volume type chosen does not "
"match the file system %(fs_label)s passed in the "
"volume reference.")
% {'pool': pool, 'fs_label': fs_label})
LOG.error(msg)
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
if pool_from_host != pool_from_vol_type:
msg = (_("Failed to manage existing volume because the pool of "
"the volume type chosen does not match the pool of "
"the host."),
{'Pool of the volume type': pool_from_vol_type,
'Pool of the host': pool_from_host})
msg = (_("Failed to manage existing volume because the pool "
"%(pool)s of the volume type chosen does not match the "
"pool %(pool_host)s of the host.") %
{'pool': pool_from_vol_type, 'pool_host': pool_from_host})
LOG.error(msg)
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
def _get_info_from_vol_ref(self, vol_ref):
@ -360,9 +363,10 @@ class HNASISCSIDriver(driver.ISCSIDriver):
return fs_label, vol_name
else:
msg = (_("The reference to the volume in the backend should have "
"the format file_system/volume_name (volume_name cannot "
"contain '/')"))
msg = _("The reference to the volume in the backend should have "
"the format file_system/volume_name (volume_name cannot "
"contain '/')")
LOG.error(msg)
raise exception.ManageExistingInvalidReference(
existing_ref=vol_ref, reason=msg)
@ -374,6 +378,14 @@ class HNASISCSIDriver(driver.ISCSIDriver):
self.context = context
self._check_fs_list()
version_info = self.backend.get_version()
LOG.info(_LI("HNAS iSCSI driver."))
LOG.info(_LI("HNAS model: %(mdl)s"), {'mdl': version_info['model']})
LOG.info(_LI("HNAS version: %(version)s"),
{'version': version_info['version']})
LOG.info(_LI("HNAS hardware: %(hw)s"),
{'hw': version_info['hardware']})
LOG.info(_LI("HNAS S/N: %(sn)s"), {'sn': version_info['serial']})
service_list = self.config['services'].keys()
for svc in service_list:
svc = self.config['services'][svc]
@ -384,7 +396,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
self.pools.append(pool)
LOG.info(_LI("Configured pools: %(pool)s"), {'pool': self.pools})
LOG.debug("Configured pools: %(pool)s", {'pool': self.pools})
evs_info = self.backend.get_evs_info()
LOG.info(_LI("Configured EVSs: %(evs)s"), {'evs': evs_info})
@ -392,7 +404,8 @@ class HNASISCSIDriver(driver.ISCSIDriver):
for svc in self.config['services'].keys():
svc_ip = self.config['services'][svc]['iscsi_ip']
if svc_ip in evs_info.keys():
LOG.info(_LI("iSCSI portal found for service: %s"), svc_ip)
LOG.info(_LI("iSCSI portal found for service: %(svc_ip)s"),
{'svc_ip': svc_ip})
self.config['services'][svc]['evs'] = (
evs_info[svc_ip]['evs_number'])
self.config['services'][svc]['iscsi_port'] = '3260'
@ -401,6 +414,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
LOG.error(_LE("iSCSI portal not found "
"for service: %(svc)s"), {'svc': svc_ip})
raise exception.InvalidParameterValue(err=svc_ip)
LOG.info(_LI("HNAS iSCSI Driver loaded successfully."))
def ensure_export(self, context, volume):
pass
@ -411,6 +425,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
def remove_export(self, context, volume):
pass
@cinder_utils.trace
def create_volume(self, volume):
"""Creates a LU on HNAS.
@ -422,11 +437,9 @@ class HNASISCSIDriver(driver.ISCSIDriver):
self.backend.create_lu(fs, size, volume.name)
LOG.info(_LI("LU %(lu)s of size %(sz)s GB is created."),
{'lu': volume.name, 'sz': volume.size})
return {'provider_location': self._get_provider_location(volume)}
@cinder_utils.trace
def create_cloned_volume(self, dst, src):
"""Creates a clone of a volume.
@ -439,14 +452,14 @@ class HNASISCSIDriver(driver.ISCSIDriver):
self.backend.create_cloned_lu(src.name, fs_label, dst.name)
if src.size < dst.size:
size = dst.size
self.extend_volume(dst, size)
LOG.debug("LU %(lu)s of size %(size)d GB is cloned.",
{'lu': src.name, 'size': src.size})
LOG.debug("Increasing dest size from %(old_size)s to "
"%(new_size)s",
{'old_size': src.size, 'new_size': dst.size})
self.extend_volume(dst, dst.size)
return {'provider_location': self._get_provider_location(dst)}
@cinder_utils.trace
def extend_volume(self, volume, new_size):
"""Extends an existing volume.
@ -456,9 +469,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
fs = self._get_service(volume)
self.backend.extend_lu(fs, new_size, volume.name)
LOG.info(_LI("LU %(lu)s extended to %(size)s GB."),
{'lu': volume.name, 'size': new_size})
@cinder_utils.trace
def delete_volume(self, volume):
"""Deletes the volume on HNAS.
@ -467,9 +478,8 @@ class HNASISCSIDriver(driver.ISCSIDriver):
fs = self._get_service(volume)
self.backend.delete_lu(fs, volume.name)
LOG.debug("Delete LU %(lu)s", {'lu': volume.name})
@cinder_utils.synchronized('volume_mapping')
@cinder_utils.trace
def initialize_connection(self, volume, connector):
"""Maps the created volume to connector['initiator'].
@ -478,9 +488,6 @@ class HNASISCSIDriver(driver.ISCSIDriver):
:returns: The connection information
:raises: ISCSITargetAttachFailed
"""
LOG.info(_LI("initialize volume %(vol)s connector %(conn)s"),
{'vol': volume, 'conn': connector})
service_info = self._get_service_target(volume)
(ip, ipp, evs, port, _fs, tgtalias, secret) = service_info
@ -492,7 +499,8 @@ class HNASISCSIDriver(driver.ISCSIDriver):
except processutils.ProcessExecutionError:
msg = (_("Error attaching volume %(vol)s. "
"Target limit might be reached!") % {'vol': volume.id})
raise exception.ISCSITargetAttachFailed(message=msg)
LOG.error(msg)
raise exception.ISCSITargetAttachFailed(volume_id=volume.id)
hnas_portal = ip + ':' + ipp
lu_id = six.text_type(conn['lu_id'])
@ -501,7 +509,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
volume.provider_location + ',' + evs + ',' +
port + ',' + lu_id)
LOG.info(_LI("initiate: connection %s"), tgt)
LOG.info(_LI("initiate: connection %(tgt)s"), {'tgt': tgt})
properties = {}
properties['provider_location'] = tgt
@ -517,12 +525,11 @@ class HNASISCSIDriver(driver.ISCSIDriver):
properties['auth_password'] = secret
conn_info = {'driver_volume_type': 'iscsi', 'data': properties}
LOG.debug("initialize_connection: conn_info: %(conn)s.",
{'conn': conn_info})
return conn_info
@cinder_utils.synchronized('volume_mapping')
@cinder_utils.trace
def terminate_connection(self, volume, connector, **kwargs):
"""Terminate a connection to a volume.
@ -535,9 +542,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
self.backend.del_iscsi_conn(evs, tgtalias, lu_info['id'])
LOG.info(_LI("terminate_connection: %(vol)s"),
{'vol': volume.provider_location})
@cinder_utils.trace
def create_volume_from_snapshot(self, volume, snapshot):
"""Creates a volume from a snapshot.
@ -549,11 +554,9 @@ class HNASISCSIDriver(driver.ISCSIDriver):
self.backend.create_cloned_lu(snapshot.name, fs, volume.name)
LOG.info(_LI("LU %(lu)s of size %(sz)d MB is created."),
{'lu': snapshot.name, 'sz': snapshot.volume_size})
return {'provider_location': self._get_provider_location(snapshot)}
@cinder_utils.trace
def create_snapshot(self, snapshot):
"""Creates a snapshot.
@ -564,11 +567,9 @@ class HNASISCSIDriver(driver.ISCSIDriver):
self.backend.create_cloned_lu(snapshot.volume_name, fs, snapshot.name)
LOG.debug("LU %(lu)s of size %(size)d GB is created.",
{'lu': snapshot.name, 'size': snapshot.volume_size})
return {'provider_location': self._get_provider_location(snapshot)}
@cinder_utils.trace
def delete_snapshot(self, snapshot):
"""Deletes a snapshot.
@ -577,8 +578,6 @@ class HNASISCSIDriver(driver.ISCSIDriver):
fs = self._get_service(snapshot.volume)
self.backend.delete_lu(fs, snapshot.name)
LOG.debug("Delete lu %(lu)s", {'lu': snapshot.name})
def get_volume_stats(self, refresh=False):
"""Gets the volume driver stats.
@ -590,6 +589,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
return self.driver_stats
@cinder_utils.trace
def manage_existing_get_size(self, volume, existing_vol_ref):
"""Gets the size to manage_existing.
@ -627,6 +627,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
'If your volume name contains "/", please rename it '
'and try to manage again.'))
@cinder_utils.trace
def manage_existing(self, volume, existing_vol_ref):
"""Manages an existing volume.
@ -641,13 +642,13 @@ class HNASISCSIDriver(driver.ISCSIDriver):
volume
:returns: the provider location of the volume managed
"""
LOG.info(_LI("Asked to manage ISCSI volume %(vol)s, with vol "
"ref %(ref)s."), {'vol': volume.id,
'ref': existing_vol_ref['source-name']})
fs_label, vol_name = (
self._get_info_from_vol_ref(existing_vol_ref['source-name']))
LOG.debug("Asked to manage ISCSI volume %(vol)s, with vol "
"ref %(ref)s.", {'vol': volume.id,
'ref': existing_vol_ref['source-name']})
if volume.volume_type is not None:
self._check_pool_and_fs(volume, fs_label)
@ -658,6 +659,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
return {'provider_location': self._get_provider_location(volume)}
@cinder_utils.trace
def unmanage(self, volume):
"""Unmanages a volume from cinder.
@ -674,9 +676,10 @@ class HNASISCSIDriver(driver.ISCSIDriver):
self.backend.rename_existing_lu(fslabel, volume.name, new_name)
LOG.info(_LI("Cinder ISCSI volume with current path %(path)s is "
"no longer being managed. The new name is %(unm)s."),
{'path': vol_path, 'unm': new_name})
LOG.info(_LI("The volume with path %(old)s is no longer being managed "
"by Cinder. However, it was not deleted and can be found "
"with the new name %(cr)s on backend."),
{'old': vol_path, 'cr': new_name})
def _get_provider_location(self, volume):
"""Gets the provider location of a given volume

View File

@ -130,8 +130,8 @@ class HNASNFSDriver(nfs.NfsDriver):
if label in self.config['services'].keys():
svc = self.config['services'][label]
LOG.info(_LI("_get_service: %(lbl)s->%(svc)s"),
{'lbl': label, 'svc': svc['export']['fs']})
LOG.debug("_get_service: %(lbl)s->%(svc)s",
{'lbl': label, 'svc': svc['export']['fs']})
service = (svc['hdp'], svc['export']['path'], svc['export']['fs'])
else:
LOG.info(_LI("Available services: %(svc)s"),
@ -142,6 +142,7 @@ class HNASNFSDriver(nfs.NfsDriver):
return service
@cutils.trace
def extend_volume(self, volume, new_size):
"""Extend an existing volume.
@ -153,7 +154,7 @@ class HNASNFSDriver(nfs.NfsDriver):
path = self._get_volume_path(nfs_mount, volume.name)
# Resize the image file on share to new size.
LOG.debug("Checking file for resize")
LOG.info(_LI("Checking file for resize."))
if not self._is_file_size_equal(path, new_size):
LOG.info(_LI("Resizing file to %(sz)sG"), {'sz': new_size})
@ -163,7 +164,9 @@ class HNASNFSDriver(nfs.NfsDriver):
LOG.info(_LI("LUN %(id)s extended to %(size)s GB."),
{'id': volume.id, 'size': new_size})
else:
raise exception.InvalidResults(_("Resizing image file failed."))
msg = _("Resizing image file failed.")
LOG.error(msg)
raise exception.InvalidResults(msg)
def _is_file_size_equal(self, path, size):
"""Checks if file size at path is equal to size."""
@ -175,6 +178,7 @@ class HNASNFSDriver(nfs.NfsDriver):
else:
return False
@cutils.trace
def create_volume_from_snapshot(self, volume, snapshot):
"""Creates a volume from a snapshot.
@ -182,13 +186,12 @@ class HNASNFSDriver(nfs.NfsDriver):
:param snapshot: source snapshot
:returns: the provider_location of the volume created
"""
LOG.debug("create_volume_from %(vol)s", {'vol': volume})
self._clone_volume(snapshot.volume, volume.name, snapshot.name)
share = snapshot.volume.provider_location
return {'provider_location': share}
@cutils.trace
def create_snapshot(self, snapshot):
"""Create a snapshot.
@ -203,12 +206,12 @@ class HNASNFSDriver(nfs.NfsDriver):
# returns the mount point (not path)
return {'provider_location': share}
@cutils.trace
def delete_snapshot(self, snapshot):
"""Deletes a snapshot.
:param snapshot: dictionary snapshot reference
"""
nfs_mount = snapshot.volume.provider_location
if self._volume_not_present(nfs_mount, snapshot.name):
@ -244,6 +247,7 @@ class HNASNFSDriver(nfs.NfsDriver):
return os.path.join(self._get_mount_point_for_share(nfs_share),
volume_name)
@cutils.trace
def create_cloned_volume(self, volume, src_vref):
"""Creates a clone of the specified volume.
@ -277,6 +281,8 @@ class HNASNFSDriver(nfs.NfsDriver):
'reserved_percentage': percentage of size reserved
}
"""
LOG.info(_LI("Getting volume stats"))
_stats = super(HNASNFSDriver, self).get_volume_stats(refresh)
_stats["vendor_name"] = 'Hitachi'
_stats["driver_version"] = HNAS_NFS_VERSION
@ -292,18 +298,20 @@ class HNASNFSDriver(nfs.NfsDriver):
_stats['pools'] = self.pools
LOG.info(_LI('Driver stats: %(stat)s'), {'stat': _stats})
LOG.debug('Driver stats: %(stat)s', {'stat': _stats})
return _stats
def do_setup(self, context):
"""Perform internal driver setup."""
version_info = self.backend.get_version()
LOG.info(_LI("HNAS Array NFS driver"))
LOG.info(_LI("HNAS model: %s"), version_info['model'])
LOG.info(_LI("HNAS version: %s"), version_info['version'])
LOG.info(_LI("HNAS hardware: %s"), version_info['hardware'])
LOG.info(_LI("HNAS S/N: %s"), version_info['serial'])
LOG.info(_LI("HNAS NFS driver."))
LOG.info(_LI("HNAS model: %(mdl)s"), {'mdl': version_info['model']})
LOG.info(_LI("HNAS version: %(ver)s"),
{'ver': version_info['version']})
LOG.info(_LI("HNAS hardware: %(hw)s"),
{'hw': version_info['hardware']})
LOG.info(_LI("HNAS S/N: %(sn)s"), {'sn': version_info['serial']})
self.context = context
self._load_shares_config(
@ -328,8 +336,8 @@ class HNASNFSDriver(nfs.NfsDriver):
try:
out, err = self._execute('showmount', '-e', server_ip)
except processutils.ProcessExecutionError:
LOG.error(_LE("NFS server %(srv)s not reachable!"),
{'srv': server_ip})
LOG.exception(_LE("NFS server %(srv)s not reachable!"),
{'srv': server_ip})
raise
export_list = out.split('\n')[1:]
@ -342,7 +350,7 @@ class HNASNFSDriver(nfs.NfsDriver):
LOG.error(_LE("Configured share %(share)s is not present"
"in %(srv)s."),
{'share': mountpoint, 'srv': server_ip})
msg = _('Section: %s') % svc_name
msg = _('Section: %(svc_name)s') % {'svc_name': svc_name}
raise exception.InvalidParameterValue(err=msg)
LOG.debug("Loading services: %(svc)s", {
@ -358,7 +366,8 @@ class HNASNFSDriver(nfs.NfsDriver):
self.pools.append(pool)
LOG.info(_LI("Configured pools: %(pool)s"), {'pool': self.pools})
LOG.debug("Configured pools: %(pool)s", {'pool': self.pools})
LOG.info(_LI("HNAS NFS Driver loaded successfully."))
def _clone_volume(self, src_vol, clone_name, src_name=None):
"""Clones mounted volume using the HNAS file_clone.
@ -387,6 +396,7 @@ class HNASNFSDriver(nfs.NfsDriver):
self.backend.file_clone(fs_label, source_path, target_path)
@cutils.trace
def create_volume(self, volume):
"""Creates a volume.
@ -424,8 +434,8 @@ class HNASNFSDriver(nfs.NfsDriver):
try:
vol_ref_share_ip = cutils.resolve_hostname(share_split[0])
except socket.gaierror as e:
LOG.error(_LE('Invalid hostname %(host)s'),
{'host': share_split[0]})
LOG.exception(_LE('Invalid hostname %(host)s'),
{'host': share_split[0]})
LOG.debug('error: %(err)s', {'err': e.strerror})
raise
@ -468,8 +478,8 @@ class HNASNFSDriver(nfs.NfsDriver):
file_path) = vol_ref_share.partition(cfg_share)
if work_share == cfg_share:
file_path = file_path[1:] # strip off leading path divider
LOG.debug("Found possible share %s; checking mount.",
work_share)
LOG.debug("Found possible share %(shr)s; checking mount.",
{'shr': work_share})
nfs_mount = self._get_mount_point_for_share(nfs_share)
vol_full_path = os.path.join(nfs_mount, file_path)
if os.path.isfile(vol_full_path):
@ -486,6 +496,7 @@ class HNASNFSDriver(nfs.NfsDriver):
existing_ref=vol_ref,
reason=_('Volume not found on configured storage backend.'))
@cutils.trace
def manage_existing(self, volume, existing_vol_ref):
"""Manages an existing volume.
@ -507,9 +518,10 @@ class HNASNFSDriver(nfs.NfsDriver):
(nfs_share, nfs_mount, vol_name
) = self._get_share_mount_and_vol_from_vol_ref(existing_vol_ref)
LOG.debug("Asked to manage NFS volume %(vol)s, with vol ref %(ref)s.",
{'vol': volume.id,
'ref': existing_vol_ref['source-name']})
LOG.info(_LI("Asked to manage NFS volume %(vol)s, "
"with vol ref %(ref)s."),
{'vol': volume.id,
'ref': existing_vol_ref['source-name']})
self._check_pool_and_share(volume, nfs_share)
@ -526,12 +538,13 @@ class HNASNFSDriver(nfs.NfsDriver):
"to %(vol)s.", {'vol': volume.name})
self._set_rw_permissions_for_all(dst_vol)
except (OSError, processutils.ProcessExecutionError) as err:
exception_msg = (_("Failed to manage existing volume "
"%(name)s, because rename operation "
"failed: Error msg: %(msg)s."),
{'name': existing_vol_ref['source-name'],
'msg': six.text_type(err)})
raise exception.VolumeBackendAPIException(data=exception_msg)
msg = (_("Failed to manage existing volume "
"%(name)s, because rename operation "
"failed: Error msg: %(msg)s.") %
{'name': existing_vol_ref['source-name'],
'msg': six.text_type(err)})
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
return {'provider_location': nfs_share}
def _check_pool_and_share(self, volume, nfs_share):
@ -548,23 +561,25 @@ class HNASNFSDriver(nfs.NfsDriver):
pool_from_vol_type = hnas_utils.get_pool(self.config, volume)
pool_from_host = utils.extract_host(volume.host, level='pool')
if self.config['services'][pool_from_vol_type]['hdp'] != nfs_share:
pool = self.config['services'][pool_from_vol_type]['hdp']
if pool != nfs_share:
msg = (_("Failed to manage existing volume because the pool of "
"the volume type chosen does not match the NFS share "
"passed in the volume reference."),
{'Share passed': nfs_share, 'Share for volume type':
self.config['services'][pool_from_vol_type]['hdp']})
"the volume type chosen (%(pool)s) does not match the "
"NFS share passed in the volume reference (%(share)s).")
% {'share': nfs_share, 'pool': pool})
LOG.error(msg)
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
if pool_from_host != pool_from_vol_type:
msg = (_("Failed to manage existing volume because the pool of "
"the volume type chosen does not match the pool of "
"the host."),
{'Pool of the volume type': pool_from_vol_type,
'Pool of the host': pool_from_host})
"the volume type chosen (%(pool)s) does not match the "
"pool of the host %(pool_host)s") %
{'pool': pool_from_vol_type,
'pool_host': pool_from_host})
LOG.error(msg)
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
@cutils.trace
def manage_existing_get_size(self, volume, existing_vol_ref):
"""Returns the size of volume to be managed by manage_existing.
@ -595,6 +610,7 @@ class HNASNFSDriver(nfs.NfsDriver):
"%(name)s, because of error in getting "
"volume size."),
{'name': existing_vol_ref['source-name']})
LOG.exception(exception_message)
raise exception.VolumeBackendAPIException(data=exception_message)
LOG.debug("Reporting size of NFS volume ref %(ref)s as %(size)d GB.",
@ -602,6 +618,7 @@ class HNASNFSDriver(nfs.NfsDriver):
return vol_size
@cutils.trace
def unmanage(self, volume):
"""Removes the specified volume from Cinder management.
@ -623,9 +640,11 @@ class HNASNFSDriver(nfs.NfsDriver):
self._try_execute("mv", vol_path, new_path,
run_as_root=False, check_exit_code=True)
LOG.info(_LI("Cinder NFS volume with current path %(cr)s is "
"no longer being managed."), {'cr': new_path})
LOG.info(_LI("The volume with path %(old)s is no longer being "
"managed by Cinder. However, it was not deleted "
"and can be found in the new path %(cr)s."),
{'old': vol_path, 'cr': new_path})
except (OSError, ValueError):
LOG.error(_LE("The NFS Volume %(cr)s does not exist."),
{'cr': new_path})
LOG.exception(_LE("The NFS Volume %(cr)s does not exist."),
{'cr': vol_path})

View File

@ -26,8 +26,7 @@ import six
from xml.etree import ElementTree as ETree
from cinder import exception
from cinder.i18n import _, _LW
from cinder.i18n import _, _LW, _LE
from cinder.volume import volume_types
LOG = logging.getLogger(__name__)
@ -45,7 +44,7 @@ drivers_common_opts = [
'the SMU IP.'),
cfg.StrOpt('hnas_ssc_cmd',
default='ssc',
help='Command to communicate to HNAS array.'),
help='Command to communicate to HNAS.'),
cfg.StrOpt('hnas_username',
help='HNAS username.'),
cfg.StrOpt('hnas_password',
@ -96,6 +95,7 @@ def _check_conf_params(config, vol_type, dv_type, idx):
if config['username'] is None:
msg = (_("The config parameter hnas_username "
"is not set in the cinder.conf."))
LOG.error(msg)
raise exception.InvalidParameterValue(err=msg)
if (config['password'] is None and
@ -104,11 +104,13 @@ def _check_conf_params(config, vol_type, dv_type, idx):
"missing: you need to set hnas_password "
"or hnas_ssh_private_key "
"in the cinder.conf."))
LOG.error(msg)
raise exception.InvalidParameterValue(err=msg)
if config['mgmt_ip0'] is None:
msg = (_("The config parameter hnas_mgmt_ip0 "
"is not set in the cinder.conf."))
LOG.error(msg)
raise exception.InvalidParameterValue(err=msg)
if config['services'][vol_type]['hdp'] is None:
@ -116,6 +118,7 @@ def _check_conf_params(config, vol_type, dv_type, idx):
"not set in the cinder.conf. Note that you need to "
"have at least one pool configured.") %
{'idx': idx})
LOG.error(msg)
raise exception.InvalidParameterValue(err=msg)
if config['services'][vol_type]['volume_type'] is None:
@ -124,6 +127,7 @@ def _check_conf_params(config, vol_type, dv_type, idx):
"in the cinder.conf. Note that you need to "
"have at least one pool configured.") %
{'idx': idx})
LOG.error(msg)
raise exception.InvalidParameterValue(err=msg)
if (dv_type == 'iscsi' and
@ -132,6 +136,7 @@ def _check_conf_params(config, vol_type, dv_type, idx):
"hnas_svc%(idx)s_iscsi_ip is not set "
"in the cinder.conf. Note that you need to "
"have at least one pool configured.") % {'idx': idx})
LOG.error(msg)
raise exception.InvalidParameterValue(err=msg)
@ -147,6 +152,7 @@ def _xml_read(root, element, check=None):
# mandatory parameter not found
if val is None and check:
LOG.error(_LE("Mandatory parameter not found: %(p)s"), {'p': element})
raise exception.ParameterNotFound(param=element)
# tag not found
@ -158,6 +164,7 @@ def _xml_read(root, element, check=None):
if not val.strip():
if svc_tag_pattern.search(element):
return ""
LOG.error(_LE("Parameter not found: %(param)s"), {'param': element})
raise exception.ParameterNotFound(param=element)
LOG.debug("%(element)s: %(val)s",
@ -180,6 +187,7 @@ def read_xml_config(xml_config_file, svc_params, optional_params):
if not os.access(xml_config_file, os.R_OK):
msg = (_("Can't find HNAS configurations on cinder.conf neither "
"on the path %(xml)s.") % {'xml': xml_config_file})
LOG.error(msg)
raise exception.ConfigNotFound(message=msg)
else:
LOG.warning(_LW("This XML configuration file %(xml)s is deprecated. "
@ -191,7 +199,9 @@ def read_xml_config(xml_config_file, svc_params, optional_params):
try:
root = ETree.parse(xml_config_file).getroot()
except ETree.ParseError:
msg = (_("Error parsing config file: %s") % xml_config_file)
msg = (_("Error parsing config file: %(xml_config_file)s") %
{'xml_config_file': xml_config_file})
LOG.error(msg)
raise exception.ConfigNotFound(message=msg)
# mandatory parameters for NFS and iSCSI
@ -210,7 +220,8 @@ def read_xml_config(xml_config_file, svc_params, optional_params):
config['password'] = _xml_read(root, 'password')
if config['ssh_private_key'] is None and config['password'] is None:
msg = (_("Missing authentication option (passw or private key file)."))
msg = _("Missing authentication option (passw or private key file).")
LOG.error(msg)
raise exception.ConfigNotFound(message=msg)
if _xml_read(root, 'ssh_port') is not None:
@ -235,8 +246,8 @@ def read_xml_config(xml_config_file, svc_params, optional_params):
# at least one service required!
if not config['services'].keys():
msg = (_("svc_0"))
raise exception.ParameterNotFound(param=msg)
LOG.error(_LE("No service found in xml config file"))
raise exception.ParameterNotFound(param="svc_0")
return config