Merge "Improve Hitachi HNAS volume drivers log messages"
This commit is contained in:
commit
dbebca66b0
@ -254,10 +254,20 @@ class HNASiSCSIDriverTest(test.TestCase):
|
|||||||
'172.17.39.133': {'evs_number': 2},
|
'172.17.39.133': {'evs_number': 2},
|
||||||
'172.17.39.134': {'evs_number': 3}}
|
'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',
|
self.mock_object(HNASSSHBackend, 'get_fs_info',
|
||||||
mock.Mock(return_value=True))
|
mock.Mock(return_value=True))
|
||||||
self.mock_object(HNASSSHBackend, 'get_evs_info',
|
self.mock_object(HNASSSHBackend, 'get_evs_info',
|
||||||
mock.Mock(return_value=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)
|
self.driver.do_setup(None)
|
||||||
|
|
||||||
@ -269,10 +279,20 @@ class HNASiSCSIDriverTest(test.TestCase):
|
|||||||
'172.17.39.133': {'evs_number': 2},
|
'172.17.39.133': {'evs_number': 2},
|
||||||
'172.17.39.134': {'evs_number': 3}}
|
'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',
|
self.mock_object(HNASSSHBackend, 'get_fs_info',
|
||||||
mock.Mock(return_value=True))
|
mock.Mock(return_value=True))
|
||||||
self.mock_object(HNASSSHBackend, 'get_evs_info',
|
self.mock_object(HNASSSHBackend, 'get_evs_info',
|
||||||
mock.Mock(return_value=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.assertRaises(exception.InvalidParameterValue,
|
||||||
self.driver.do_setup, None)
|
self.driver.do_setup, None)
|
||||||
|
@ -82,12 +82,12 @@ class HNASSSHBackend(object):
|
|||||||
return out, err
|
return out, err
|
||||||
except putils.ProcessExecutionError as e:
|
except putils.ProcessExecutionError as e:
|
||||||
if 'Failed to establish SSC connection' in e.stderr:
|
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)
|
raise exception.HNASConnError(msg)
|
||||||
elif 'Connection reset' in e.stderr:
|
elif 'Connection reset' in e.stderr:
|
||||||
LOG.debug("HNAS connection reset!")
|
msg = _("HNAS connection reset!")
|
||||||
msg = _("HNAS has disconnected SSC")
|
LOG.exception(msg)
|
||||||
raise exception.HNASConnError(msg)
|
raise exception.HNASConnError(msg)
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
@ -124,6 +124,7 @@ class HNASSSHBackend(object):
|
|||||||
|
|
||||||
self.storage_version = version_info
|
self.storage_version = version_info
|
||||||
|
|
||||||
|
LOG.debug("version_info: %(info)s", {'info': self.storage_version})
|
||||||
return self.storage_version
|
return self.storage_version
|
||||||
|
|
||||||
def get_evs_info(self):
|
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
|
# When the FS is found in the list of known FS, returns the EVS ID
|
||||||
for key in self.fslist:
|
for key in self.fslist:
|
||||||
if fs_label == self.fslist[key]['label']:
|
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']
|
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):
|
def _get_targets(self, evs_id, tgt_alias=None, refresh=False):
|
||||||
"""Gets the target list of an EVS.
|
"""Gets the target list of an EVS.
|
||||||
@ -365,11 +369,13 @@ class HNASSSHBackend(object):
|
|||||||
if not fs:
|
if not fs:
|
||||||
LOG.error(_LE("Can't find file %(file)s in FS %(label)s"),
|
LOG.error(_LE("Can't find file %(file)s in FS %(label)s"),
|
||||||
{'file': src, 'label': fs_label})
|
{'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)
|
raise exception.InvalidParameterValue(err=msg)
|
||||||
|
|
||||||
self._run_cmd("console-context", "--evs", fs['evsid'],
|
self._run_cmd("console-context", "--evs", fs['evsid'],
|
||||||
'file-clone-create', '-f', fs_label, src, name)
|
'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):
|
def extend_lu(self, fs_label, new_size, lu_name):
|
||||||
"""Extends an iSCSI volume.
|
"""Extends an iSCSI volume.
|
||||||
@ -433,6 +439,7 @@ class HNASSSHBackend(object):
|
|||||||
|
|
||||||
LOG.debug('add_iscsi_conn: LU %(lu)s added to %(tgt)s.',
|
LOG.debug('add_iscsi_conn: LU %(lu)s added to %(tgt)s.',
|
||||||
{'lu': lu_name, 'tgt': tgt_alias})
|
{'lu': lu_name, 'tgt': tgt_alias})
|
||||||
|
LOG.debug('conn_info: %(conn_info)s', {'conn_info': conn_info})
|
||||||
|
|
||||||
return conn_info
|
return conn_info
|
||||||
|
|
||||||
@ -487,7 +494,10 @@ class HNASSSHBackend(object):
|
|||||||
for line in lines:
|
for line in lines:
|
||||||
if 'Globally unique name' in line:
|
if 'Globally unique name' in line:
|
||||||
full_iqn = line.split()[3]
|
full_iqn = line.split()[3]
|
||||||
|
LOG.debug('get_target_iqn: %(iqn)s', {'iqn': full_iqn})
|
||||||
return 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):
|
def set_target_secret(self, targetalias, fs_label, secret):
|
||||||
"""Sets the chap secret for the specified target.
|
"""Sets the chap secret for the specified target.
|
||||||
@ -598,7 +608,8 @@ class HNASSSHBackend(object):
|
|||||||
lu_info['id'] = 0
|
lu_info['id'] = 0
|
||||||
lu_info['tgt'] = None
|
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
|
return lu_info
|
||||||
|
|
||||||
@ -769,6 +780,7 @@ class HNASSSHBackend(object):
|
|||||||
|
|
||||||
export_list.append(export_info)
|
export_list.append(export_info)
|
||||||
|
|
||||||
|
LOG.debug("get_export_list: %(exp_list)s", {'exp_list': export_list})
|
||||||
return export_list
|
return export_list
|
||||||
|
|
||||||
def create_cloned_lu(self, src_lu, fs_label, clone_name):
|
def create_cloned_lu(self, src_lu, fs_label, clone_name):
|
||||||
@ -799,3 +811,5 @@ class HNASSSHBackend(object):
|
|||||||
'iscsi-target', 'add', tgt_alias, secret)
|
'iscsi-target', 'add', tgt_alias, secret)
|
||||||
|
|
||||||
self._get_targets(_evs_id, refresh=True)
|
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})
|
||||||
|
@ -140,15 +140,15 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
configuration is found.
|
configuration is found.
|
||||||
:raises: ParameterNotFound
|
:raises: ParameterNotFound
|
||||||
"""
|
"""
|
||||||
|
LOG.debug("Available services: %(svc)s.",
|
||||||
|
{'svc': self.config['services'].keys()})
|
||||||
label = utils.extract_host(volume.host, level='pool')
|
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():
|
if label in self.config['services'].keys():
|
||||||
svc = self.config['services'][label]
|
svc = self.config['services'][label]
|
||||||
|
LOG.info(_LI("Using service label: %(lbl)s."), {'lbl': label})
|
||||||
return svc['hdp']
|
return svc['hdp']
|
||||||
else:
|
else:
|
||||||
LOG.info(_LI("Available services: %(svc)s."),
|
|
||||||
{'svc': self.config['services'].keys()})
|
|
||||||
LOG.error(_LE("No configuration found for service: %(lbl)s."),
|
LOG.error(_LE("No configuration found for service: %(lbl)s."),
|
||||||
{'lbl': label})
|
{'lbl': label})
|
||||||
raise exception.ParameterNotFound(param=label)
|
raise exception.ParameterNotFound(param=label)
|
||||||
@ -176,6 +176,10 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
service = (
|
service = (
|
||||||
svc['iscsi_ip'], svc['iscsi_port'], svc['evs'], svc['port'],
|
svc['iscsi_ip'], svc['iscsi_port'], svc['evs'], svc['port'],
|
||||||
fs_label, lu_info['tgt']['alias'], lu_info['tgt']['secret'])
|
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
|
return service
|
||||||
|
|
||||||
# Each EVS can have up to 32 targets. Each target can have up to 32
|
# 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
|
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
|
return hnas_stat
|
||||||
|
|
||||||
def _check_fs_list(self):
|
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
|
Verify that all FSs specified in the configuration files actually
|
||||||
exists on the storage.
|
exists on the storage.
|
||||||
@ -304,8 +308,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
|
|
||||||
for fs in fs_list:
|
for fs in fs_list:
|
||||||
if not self.backend.get_fs_info(fs):
|
if not self.backend.get_fs_info(fs):
|
||||||
msg = (
|
msg = (_("File system not found or not mounted: %(fs)s") %
|
||||||
_("File system not found or not mounted: %(fs)s") %
|
|
||||||
{'fs': fs})
|
{'fs': fs})
|
||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise exception.ParameterNotFound(param=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_vol_type = hnas_utils.get_pool(self.config, volume)
|
||||||
|
|
||||||
pool_from_host = utils.extract_host(volume.host, level='pool')
|
pool_from_host = utils.extract_host(volume.host, level='pool')
|
||||||
|
pool = self.config['services'][pool_from_vol_type]['hdp']
|
||||||
if self.config['services'][pool_from_vol_type]['hdp'] != fs_label:
|
if pool != fs_label:
|
||||||
msg = (_("Failed to manage existing volume because the pool of "
|
msg = (_("Failed to manage existing volume because the "
|
||||||
"the volume type chosen does not match the file system "
|
"pool %(pool)s of the volume type chosen does not "
|
||||||
"passed in the volume reference."),
|
"match the file system %(fs_label)s passed in the "
|
||||||
{'File System passed': fs_label,
|
"volume reference.")
|
||||||
'File System for volume type':
|
% {'pool': pool, 'fs_label': fs_label})
|
||||||
self.config['services'][pool_from_vol_type]['hdp']})
|
LOG.error(msg)
|
||||||
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
|
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
|
||||||
|
|
||||||
if pool_from_host != pool_from_vol_type:
|
if pool_from_host != pool_from_vol_type:
|
||||||
msg = (_("Failed to manage existing volume because the pool of "
|
msg = (_("Failed to manage existing volume because the pool "
|
||||||
"the volume type chosen does not match the pool of "
|
"%(pool)s of the volume type chosen does not match the "
|
||||||
"the host."),
|
"pool %(pool_host)s of the host.") %
|
||||||
{'Pool of the volume type': pool_from_vol_type,
|
{'pool': pool_from_vol_type, 'pool_host': pool_from_host})
|
||||||
'Pool of the host': pool_from_host})
|
LOG.error(msg)
|
||||||
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
|
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
|
||||||
|
|
||||||
def _get_info_from_vol_ref(self, vol_ref):
|
def _get_info_from_vol_ref(self, vol_ref):
|
||||||
@ -360,9 +363,10 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
|
|
||||||
return fs_label, vol_name
|
return fs_label, vol_name
|
||||||
else:
|
else:
|
||||||
msg = (_("The reference to the volume in the backend should have "
|
msg = _("The reference to the volume in the backend should have "
|
||||||
"the format file_system/volume_name (volume_name cannot "
|
"the format file_system/volume_name (volume_name cannot "
|
||||||
"contain '/')"))
|
"contain '/')")
|
||||||
|
LOG.error(msg)
|
||||||
raise exception.ManageExistingInvalidReference(
|
raise exception.ManageExistingInvalidReference(
|
||||||
existing_ref=vol_ref, reason=msg)
|
existing_ref=vol_ref, reason=msg)
|
||||||
|
|
||||||
@ -374,6 +378,14 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
self.context = context
|
self.context = context
|
||||||
self._check_fs_list()
|
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()
|
service_list = self.config['services'].keys()
|
||||||
for svc in service_list:
|
for svc in service_list:
|
||||||
svc = self.config['services'][svc]
|
svc = self.config['services'][svc]
|
||||||
@ -384,7 +396,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
|
|
||||||
self.pools.append(pool)
|
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()
|
evs_info = self.backend.get_evs_info()
|
||||||
LOG.info(_LI("Configured EVSs: %(evs)s"), {'evs': 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():
|
for svc in self.config['services'].keys():
|
||||||
svc_ip = self.config['services'][svc]['iscsi_ip']
|
svc_ip = self.config['services'][svc]['iscsi_ip']
|
||||||
if svc_ip in evs_info.keys():
|
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'] = (
|
self.config['services'][svc]['evs'] = (
|
||||||
evs_info[svc_ip]['evs_number'])
|
evs_info[svc_ip]['evs_number'])
|
||||||
self.config['services'][svc]['iscsi_port'] = '3260'
|
self.config['services'][svc]['iscsi_port'] = '3260'
|
||||||
@ -401,6 +414,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
LOG.error(_LE("iSCSI portal not found "
|
LOG.error(_LE("iSCSI portal not found "
|
||||||
"for service: %(svc)s"), {'svc': svc_ip})
|
"for service: %(svc)s"), {'svc': svc_ip})
|
||||||
raise exception.InvalidParameterValue(err=svc_ip)
|
raise exception.InvalidParameterValue(err=svc_ip)
|
||||||
|
LOG.info(_LI("HNAS iSCSI Driver loaded successfully."))
|
||||||
|
|
||||||
def ensure_export(self, context, volume):
|
def ensure_export(self, context, volume):
|
||||||
pass
|
pass
|
||||||
@ -411,6 +425,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
def remove_export(self, context, volume):
|
def remove_export(self, context, volume):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@cinder_utils.trace
|
||||||
def create_volume(self, volume):
|
def create_volume(self, volume):
|
||||||
"""Creates a LU on HNAS.
|
"""Creates a LU on HNAS.
|
||||||
|
|
||||||
@ -422,11 +437,9 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
|
|
||||||
self.backend.create_lu(fs, size, volume.name)
|
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)}
|
return {'provider_location': self._get_provider_location(volume)}
|
||||||
|
|
||||||
|
@cinder_utils.trace
|
||||||
def create_cloned_volume(self, dst, src):
|
def create_cloned_volume(self, dst, src):
|
||||||
"""Creates a clone of a volume.
|
"""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)
|
self.backend.create_cloned_lu(src.name, fs_label, dst.name)
|
||||||
|
|
||||||
if src.size < dst.size:
|
if src.size < dst.size:
|
||||||
size = dst.size
|
LOG.debug("Increasing dest size from %(old_size)s to "
|
||||||
self.extend_volume(dst, size)
|
"%(new_size)s",
|
||||||
|
{'old_size': src.size, 'new_size': dst.size})
|
||||||
LOG.debug("LU %(lu)s of size %(size)d GB is cloned.",
|
self.extend_volume(dst, dst.size)
|
||||||
{'lu': src.name, 'size': src.size})
|
|
||||||
|
|
||||||
return {'provider_location': self._get_provider_location(dst)}
|
return {'provider_location': self._get_provider_location(dst)}
|
||||||
|
|
||||||
|
@cinder_utils.trace
|
||||||
def extend_volume(self, volume, new_size):
|
def extend_volume(self, volume, new_size):
|
||||||
"""Extends an existing volume.
|
"""Extends an existing volume.
|
||||||
|
|
||||||
@ -456,9 +469,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
fs = self._get_service(volume)
|
fs = self._get_service(volume)
|
||||||
self.backend.extend_lu(fs, new_size, volume.name)
|
self.backend.extend_lu(fs, new_size, volume.name)
|
||||||
|
|
||||||
LOG.info(_LI("LU %(lu)s extended to %(size)s GB."),
|
@cinder_utils.trace
|
||||||
{'lu': volume.name, 'size': new_size})
|
|
||||||
|
|
||||||
def delete_volume(self, volume):
|
def delete_volume(self, volume):
|
||||||
"""Deletes the volume on HNAS.
|
"""Deletes the volume on HNAS.
|
||||||
|
|
||||||
@ -467,9 +478,8 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
fs = self._get_service(volume)
|
fs = self._get_service(volume)
|
||||||
self.backend.delete_lu(fs, volume.name)
|
self.backend.delete_lu(fs, volume.name)
|
||||||
|
|
||||||
LOG.debug("Delete LU %(lu)s", {'lu': volume.name})
|
|
||||||
|
|
||||||
@cinder_utils.synchronized('volume_mapping')
|
@cinder_utils.synchronized('volume_mapping')
|
||||||
|
@cinder_utils.trace
|
||||||
def initialize_connection(self, volume, connector):
|
def initialize_connection(self, volume, connector):
|
||||||
"""Maps the created volume to connector['initiator'].
|
"""Maps the created volume to connector['initiator'].
|
||||||
|
|
||||||
@ -478,9 +488,6 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
:returns: The connection information
|
:returns: The connection information
|
||||||
:raises: ISCSITargetAttachFailed
|
:raises: ISCSITargetAttachFailed
|
||||||
"""
|
"""
|
||||||
LOG.info(_LI("initialize volume %(vol)s connector %(conn)s"),
|
|
||||||
{'vol': volume, 'conn': connector})
|
|
||||||
|
|
||||||
service_info = self._get_service_target(volume)
|
service_info = self._get_service_target(volume)
|
||||||
(ip, ipp, evs, port, _fs, tgtalias, secret) = service_info
|
(ip, ipp, evs, port, _fs, tgtalias, secret) = service_info
|
||||||
|
|
||||||
@ -492,7 +499,8 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
except processutils.ProcessExecutionError:
|
except processutils.ProcessExecutionError:
|
||||||
msg = (_("Error attaching volume %(vol)s. "
|
msg = (_("Error attaching volume %(vol)s. "
|
||||||
"Target limit might be reached!") % {'vol': volume.id})
|
"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
|
hnas_portal = ip + ':' + ipp
|
||||||
lu_id = six.text_type(conn['lu_id'])
|
lu_id = six.text_type(conn['lu_id'])
|
||||||
@ -501,7 +509,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
volume.provider_location + ',' + evs + ',' +
|
volume.provider_location + ',' + evs + ',' +
|
||||||
port + ',' + lu_id)
|
port + ',' + lu_id)
|
||||||
|
|
||||||
LOG.info(_LI("initiate: connection %s"), tgt)
|
LOG.info(_LI("initiate: connection %(tgt)s"), {'tgt': tgt})
|
||||||
|
|
||||||
properties = {}
|
properties = {}
|
||||||
properties['provider_location'] = tgt
|
properties['provider_location'] = tgt
|
||||||
@ -517,12 +525,11 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
properties['auth_password'] = secret
|
properties['auth_password'] = secret
|
||||||
|
|
||||||
conn_info = {'driver_volume_type': 'iscsi', 'data': properties}
|
conn_info = {'driver_volume_type': 'iscsi', 'data': properties}
|
||||||
LOG.debug("initialize_connection: conn_info: %(conn)s.",
|
|
||||||
{'conn': conn_info})
|
|
||||||
|
|
||||||
return conn_info
|
return conn_info
|
||||||
|
|
||||||
@cinder_utils.synchronized('volume_mapping')
|
@cinder_utils.synchronized('volume_mapping')
|
||||||
|
@cinder_utils.trace
|
||||||
def terminate_connection(self, volume, connector, **kwargs):
|
def terminate_connection(self, volume, connector, **kwargs):
|
||||||
"""Terminate a connection to a volume.
|
"""Terminate a connection to a volume.
|
||||||
|
|
||||||
@ -535,9 +542,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
|
|
||||||
self.backend.del_iscsi_conn(evs, tgtalias, lu_info['id'])
|
self.backend.del_iscsi_conn(evs, tgtalias, lu_info['id'])
|
||||||
|
|
||||||
LOG.info(_LI("terminate_connection: %(vol)s"),
|
@cinder_utils.trace
|
||||||
{'vol': volume.provider_location})
|
|
||||||
|
|
||||||
def create_volume_from_snapshot(self, volume, snapshot):
|
def create_volume_from_snapshot(self, volume, snapshot):
|
||||||
"""Creates a volume from a 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)
|
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)}
|
return {'provider_location': self._get_provider_location(snapshot)}
|
||||||
|
|
||||||
|
@cinder_utils.trace
|
||||||
def create_snapshot(self, snapshot):
|
def create_snapshot(self, snapshot):
|
||||||
"""Creates a snapshot.
|
"""Creates a snapshot.
|
||||||
|
|
||||||
@ -564,11 +567,9 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
|
|
||||||
self.backend.create_cloned_lu(snapshot.volume_name, fs, snapshot.name)
|
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)}
|
return {'provider_location': self._get_provider_location(snapshot)}
|
||||||
|
|
||||||
|
@cinder_utils.trace
|
||||||
def delete_snapshot(self, snapshot):
|
def delete_snapshot(self, snapshot):
|
||||||
"""Deletes a snapshot.
|
"""Deletes a snapshot.
|
||||||
|
|
||||||
@ -577,8 +578,6 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
fs = self._get_service(snapshot.volume)
|
fs = self._get_service(snapshot.volume)
|
||||||
self.backend.delete_lu(fs, snapshot.name)
|
self.backend.delete_lu(fs, snapshot.name)
|
||||||
|
|
||||||
LOG.debug("Delete lu %(lu)s", {'lu': snapshot.name})
|
|
||||||
|
|
||||||
def get_volume_stats(self, refresh=False):
|
def get_volume_stats(self, refresh=False):
|
||||||
"""Gets the volume driver stats.
|
"""Gets the volume driver stats.
|
||||||
|
|
||||||
@ -590,6 +589,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
|
|
||||||
return self.driver_stats
|
return self.driver_stats
|
||||||
|
|
||||||
|
@cinder_utils.trace
|
||||||
def manage_existing_get_size(self, volume, existing_vol_ref):
|
def manage_existing_get_size(self, volume, existing_vol_ref):
|
||||||
"""Gets the size to manage_existing.
|
"""Gets the size to manage_existing.
|
||||||
|
|
||||||
@ -627,6 +627,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
'If your volume name contains "/", please rename it '
|
'If your volume name contains "/", please rename it '
|
||||||
'and try to manage again.'))
|
'and try to manage again.'))
|
||||||
|
|
||||||
|
@cinder_utils.trace
|
||||||
def manage_existing(self, volume, existing_vol_ref):
|
def manage_existing(self, volume, existing_vol_ref):
|
||||||
"""Manages an existing volume.
|
"""Manages an existing volume.
|
||||||
|
|
||||||
@ -641,13 +642,13 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
volume
|
volume
|
||||||
:returns: the provider location of the volume managed
|
: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 = (
|
fs_label, vol_name = (
|
||||||
self._get_info_from_vol_ref(existing_vol_ref['source-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:
|
if volume.volume_type is not None:
|
||||||
self._check_pool_and_fs(volume, fs_label)
|
self._check_pool_and_fs(volume, fs_label)
|
||||||
|
|
||||||
@ -658,6 +659,7 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
|
|
||||||
return {'provider_location': self._get_provider_location(volume)}
|
return {'provider_location': self._get_provider_location(volume)}
|
||||||
|
|
||||||
|
@cinder_utils.trace
|
||||||
def unmanage(self, volume):
|
def unmanage(self, volume):
|
||||||
"""Unmanages a volume from cinder.
|
"""Unmanages a volume from cinder.
|
||||||
|
|
||||||
@ -674,9 +676,10 @@ class HNASISCSIDriver(driver.ISCSIDriver):
|
|||||||
|
|
||||||
self.backend.rename_existing_lu(fslabel, volume.name, new_name)
|
self.backend.rename_existing_lu(fslabel, volume.name, new_name)
|
||||||
|
|
||||||
LOG.info(_LI("Cinder ISCSI volume with current path %(path)s is "
|
LOG.info(_LI("The volume with path %(old)s is no longer being managed "
|
||||||
"no longer being managed. The new name is %(unm)s."),
|
"by Cinder. However, it was not deleted and can be found "
|
||||||
{'path': vol_path, 'unm': new_name})
|
"with the new name %(cr)s on backend."),
|
||||||
|
{'old': vol_path, 'cr': new_name})
|
||||||
|
|
||||||
def _get_provider_location(self, volume):
|
def _get_provider_location(self, volume):
|
||||||
"""Gets the provider location of a given volume
|
"""Gets the provider location of a given volume
|
||||||
|
@ -130,7 +130,7 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
|
|
||||||
if label in self.config['services'].keys():
|
if label in self.config['services'].keys():
|
||||||
svc = self.config['services'][label]
|
svc = self.config['services'][label]
|
||||||
LOG.info(_LI("_get_service: %(lbl)s->%(svc)s"),
|
LOG.debug("_get_service: %(lbl)s->%(svc)s",
|
||||||
{'lbl': label, 'svc': svc['export']['fs']})
|
{'lbl': label, 'svc': svc['export']['fs']})
|
||||||
service = (svc['hdp'], svc['export']['path'], svc['export']['fs'])
|
service = (svc['hdp'], svc['export']['path'], svc['export']['fs'])
|
||||||
else:
|
else:
|
||||||
@ -142,6 +142,7 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
|
|
||||||
return service
|
return service
|
||||||
|
|
||||||
|
@cutils.trace
|
||||||
def extend_volume(self, volume, new_size):
|
def extend_volume(self, volume, new_size):
|
||||||
"""Extend an existing volume.
|
"""Extend an existing volume.
|
||||||
|
|
||||||
@ -153,7 +154,7 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
path = self._get_volume_path(nfs_mount, volume.name)
|
path = self._get_volume_path(nfs_mount, volume.name)
|
||||||
|
|
||||||
# Resize the image file on share to new size.
|
# 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):
|
if not self._is_file_size_equal(path, new_size):
|
||||||
LOG.info(_LI("Resizing file to %(sz)sG"), {'sz': 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."),
|
LOG.info(_LI("LUN %(id)s extended to %(size)s GB."),
|
||||||
{'id': volume.id, 'size': new_size})
|
{'id': volume.id, 'size': new_size})
|
||||||
else:
|
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):
|
def _is_file_size_equal(self, path, size):
|
||||||
"""Checks if file size at path is equal to size."""
|
"""Checks if file size at path is equal to size."""
|
||||||
@ -175,6 +178,7 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@cutils.trace
|
||||||
def create_volume_from_snapshot(self, volume, snapshot):
|
def create_volume_from_snapshot(self, volume, snapshot):
|
||||||
"""Creates a volume from a snapshot.
|
"""Creates a volume from a snapshot.
|
||||||
|
|
||||||
@ -182,13 +186,12 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
:param snapshot: source snapshot
|
:param snapshot: source snapshot
|
||||||
:returns: the provider_location of the volume created
|
: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)
|
self._clone_volume(snapshot.volume, volume.name, snapshot.name)
|
||||||
share = snapshot.volume.provider_location
|
share = snapshot.volume.provider_location
|
||||||
|
|
||||||
return {'provider_location': share}
|
return {'provider_location': share}
|
||||||
|
|
||||||
|
@cutils.trace
|
||||||
def create_snapshot(self, snapshot):
|
def create_snapshot(self, snapshot):
|
||||||
"""Create a snapshot.
|
"""Create a snapshot.
|
||||||
|
|
||||||
@ -203,12 +206,12 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
# returns the mount point (not path)
|
# returns the mount point (not path)
|
||||||
return {'provider_location': share}
|
return {'provider_location': share}
|
||||||
|
|
||||||
|
@cutils.trace
|
||||||
def delete_snapshot(self, snapshot):
|
def delete_snapshot(self, snapshot):
|
||||||
"""Deletes a snapshot.
|
"""Deletes a snapshot.
|
||||||
|
|
||||||
:param snapshot: dictionary snapshot reference
|
:param snapshot: dictionary snapshot reference
|
||||||
"""
|
"""
|
||||||
|
|
||||||
nfs_mount = snapshot.volume.provider_location
|
nfs_mount = snapshot.volume.provider_location
|
||||||
|
|
||||||
if self._volume_not_present(nfs_mount, snapshot.name):
|
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),
|
return os.path.join(self._get_mount_point_for_share(nfs_share),
|
||||||
volume_name)
|
volume_name)
|
||||||
|
|
||||||
|
@cutils.trace
|
||||||
def create_cloned_volume(self, volume, src_vref):
|
def create_cloned_volume(self, volume, src_vref):
|
||||||
"""Creates a clone of the specified volume.
|
"""Creates a clone of the specified volume.
|
||||||
|
|
||||||
@ -277,6 +281,8 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
'reserved_percentage': percentage of size reserved
|
'reserved_percentage': percentage of size reserved
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
LOG.info(_LI("Getting volume stats"))
|
||||||
|
|
||||||
_stats = super(HNASNFSDriver, self).get_volume_stats(refresh)
|
_stats = super(HNASNFSDriver, self).get_volume_stats(refresh)
|
||||||
_stats["vendor_name"] = 'Hitachi'
|
_stats["vendor_name"] = 'Hitachi'
|
||||||
_stats["driver_version"] = HNAS_NFS_VERSION
|
_stats["driver_version"] = HNAS_NFS_VERSION
|
||||||
@ -292,18 +298,20 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
|
|
||||||
_stats['pools'] = self.pools
|
_stats['pools'] = self.pools
|
||||||
|
|
||||||
LOG.info(_LI('Driver stats: %(stat)s'), {'stat': _stats})
|
LOG.debug('Driver stats: %(stat)s', {'stat': _stats})
|
||||||
|
|
||||||
return _stats
|
return _stats
|
||||||
|
|
||||||
def do_setup(self, context):
|
def do_setup(self, context):
|
||||||
"""Perform internal driver setup."""
|
"""Perform internal driver setup."""
|
||||||
version_info = self.backend.get_version()
|
version_info = self.backend.get_version()
|
||||||
LOG.info(_LI("HNAS Array NFS driver"))
|
LOG.info(_LI("HNAS NFS driver."))
|
||||||
LOG.info(_LI("HNAS model: %s"), version_info['model'])
|
LOG.info(_LI("HNAS model: %(mdl)s"), {'mdl': version_info['model']})
|
||||||
LOG.info(_LI("HNAS version: %s"), version_info['version'])
|
LOG.info(_LI("HNAS version: %(ver)s"),
|
||||||
LOG.info(_LI("HNAS hardware: %s"), version_info['hardware'])
|
{'ver': version_info['version']})
|
||||||
LOG.info(_LI("HNAS S/N: %s"), version_info['serial'])
|
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.context = context
|
||||||
self._load_shares_config(
|
self._load_shares_config(
|
||||||
@ -328,7 +336,7 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
try:
|
try:
|
||||||
out, err = self._execute('showmount', '-e', server_ip)
|
out, err = self._execute('showmount', '-e', server_ip)
|
||||||
except processutils.ProcessExecutionError:
|
except processutils.ProcessExecutionError:
|
||||||
LOG.error(_LE("NFS server %(srv)s not reachable!"),
|
LOG.exception(_LE("NFS server %(srv)s not reachable!"),
|
||||||
{'srv': server_ip})
|
{'srv': server_ip})
|
||||||
raise
|
raise
|
||||||
|
|
||||||
@ -342,7 +350,7 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
LOG.error(_LE("Configured share %(share)s is not present"
|
LOG.error(_LE("Configured share %(share)s is not present"
|
||||||
"in %(srv)s."),
|
"in %(srv)s."),
|
||||||
{'share': mountpoint, 'srv': server_ip})
|
{'share': mountpoint, 'srv': server_ip})
|
||||||
msg = _('Section: %s') % svc_name
|
msg = _('Section: %(svc_name)s') % {'svc_name': svc_name}
|
||||||
raise exception.InvalidParameterValue(err=msg)
|
raise exception.InvalidParameterValue(err=msg)
|
||||||
|
|
||||||
LOG.debug("Loading services: %(svc)s", {
|
LOG.debug("Loading services: %(svc)s", {
|
||||||
@ -358,7 +366,8 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
|
|
||||||
self.pools.append(pool)
|
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):
|
def _clone_volume(self, src_vol, clone_name, src_name=None):
|
||||||
"""Clones mounted volume using the HNAS file_clone.
|
"""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)
|
self.backend.file_clone(fs_label, source_path, target_path)
|
||||||
|
|
||||||
|
@cutils.trace
|
||||||
def create_volume(self, volume):
|
def create_volume(self, volume):
|
||||||
"""Creates a volume.
|
"""Creates a volume.
|
||||||
|
|
||||||
@ -424,7 +434,7 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
try:
|
try:
|
||||||
vol_ref_share_ip = cutils.resolve_hostname(share_split[0])
|
vol_ref_share_ip = cutils.resolve_hostname(share_split[0])
|
||||||
except socket.gaierror as e:
|
except socket.gaierror as e:
|
||||||
LOG.error(_LE('Invalid hostname %(host)s'),
|
LOG.exception(_LE('Invalid hostname %(host)s'),
|
||||||
{'host': share_split[0]})
|
{'host': share_split[0]})
|
||||||
LOG.debug('error: %(err)s', {'err': e.strerror})
|
LOG.debug('error: %(err)s', {'err': e.strerror})
|
||||||
raise
|
raise
|
||||||
@ -468,8 +478,8 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
file_path) = vol_ref_share.partition(cfg_share)
|
file_path) = vol_ref_share.partition(cfg_share)
|
||||||
if work_share == cfg_share:
|
if work_share == cfg_share:
|
||||||
file_path = file_path[1:] # strip off leading path divider
|
file_path = file_path[1:] # strip off leading path divider
|
||||||
LOG.debug("Found possible share %s; checking mount.",
|
LOG.debug("Found possible share %(shr)s; checking mount.",
|
||||||
work_share)
|
{'shr': work_share})
|
||||||
nfs_mount = self._get_mount_point_for_share(nfs_share)
|
nfs_mount = self._get_mount_point_for_share(nfs_share)
|
||||||
vol_full_path = os.path.join(nfs_mount, file_path)
|
vol_full_path = os.path.join(nfs_mount, file_path)
|
||||||
if os.path.isfile(vol_full_path):
|
if os.path.isfile(vol_full_path):
|
||||||
@ -486,6 +496,7 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
existing_ref=vol_ref,
|
existing_ref=vol_ref,
|
||||||
reason=_('Volume not found on configured storage backend.'))
|
reason=_('Volume not found on configured storage backend.'))
|
||||||
|
|
||||||
|
@cutils.trace
|
||||||
def manage_existing(self, volume, existing_vol_ref):
|
def manage_existing(self, volume, existing_vol_ref):
|
||||||
"""Manages an existing volume.
|
"""Manages an existing volume.
|
||||||
|
|
||||||
@ -507,7 +518,8 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
(nfs_share, nfs_mount, vol_name
|
(nfs_share, nfs_mount, vol_name
|
||||||
) = self._get_share_mount_and_vol_from_vol_ref(existing_vol_ref)
|
) = 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.",
|
LOG.info(_LI("Asked to manage NFS volume %(vol)s, "
|
||||||
|
"with vol ref %(ref)s."),
|
||||||
{'vol': volume.id,
|
{'vol': volume.id,
|
||||||
'ref': existing_vol_ref['source-name']})
|
'ref': existing_vol_ref['source-name']})
|
||||||
|
|
||||||
@ -526,12 +538,13 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
"to %(vol)s.", {'vol': volume.name})
|
"to %(vol)s.", {'vol': volume.name})
|
||||||
self._set_rw_permissions_for_all(dst_vol)
|
self._set_rw_permissions_for_all(dst_vol)
|
||||||
except (OSError, processutils.ProcessExecutionError) as err:
|
except (OSError, processutils.ProcessExecutionError) as err:
|
||||||
exception_msg = (_("Failed to manage existing volume "
|
msg = (_("Failed to manage existing volume "
|
||||||
"%(name)s, because rename operation "
|
"%(name)s, because rename operation "
|
||||||
"failed: Error msg: %(msg)s."),
|
"failed: Error msg: %(msg)s.") %
|
||||||
{'name': existing_vol_ref['source-name'],
|
{'name': existing_vol_ref['source-name'],
|
||||||
'msg': six.text_type(err)})
|
'msg': six.text_type(err)})
|
||||||
raise exception.VolumeBackendAPIException(data=exception_msg)
|
LOG.error(msg)
|
||||||
|
raise exception.VolumeBackendAPIException(data=msg)
|
||||||
return {'provider_location': nfs_share}
|
return {'provider_location': nfs_share}
|
||||||
|
|
||||||
def _check_pool_and_share(self, volume, 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_vol_type = hnas_utils.get_pool(self.config, volume)
|
||||||
|
|
||||||
pool_from_host = utils.extract_host(volume.host, level='pool')
|
pool_from_host = utils.extract_host(volume.host, level='pool')
|
||||||
|
pool = self.config['services'][pool_from_vol_type]['hdp']
|
||||||
if self.config['services'][pool_from_vol_type]['hdp'] != nfs_share:
|
if pool != nfs_share:
|
||||||
msg = (_("Failed to manage existing volume because the pool of "
|
msg = (_("Failed to manage existing volume because the pool of "
|
||||||
"the volume type chosen does not match the NFS share "
|
"the volume type chosen (%(pool)s) does not match the "
|
||||||
"passed in the volume reference."),
|
"NFS share passed in the volume reference (%(share)s).")
|
||||||
{'Share passed': nfs_share, 'Share for volume type':
|
% {'share': nfs_share, 'pool': pool})
|
||||||
self.config['services'][pool_from_vol_type]['hdp']})
|
LOG.error(msg)
|
||||||
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
|
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
|
||||||
|
|
||||||
if pool_from_host != pool_from_vol_type:
|
if pool_from_host != pool_from_vol_type:
|
||||||
msg = (_("Failed to manage existing volume because the pool of "
|
msg = (_("Failed to manage existing volume because the pool of "
|
||||||
"the volume type chosen does not match the pool of "
|
"the volume type chosen (%(pool)s) does not match the "
|
||||||
"the host."),
|
"pool of the host %(pool_host)s") %
|
||||||
{'Pool of the volume type': pool_from_vol_type,
|
{'pool': pool_from_vol_type,
|
||||||
'Pool of the host': pool_from_host})
|
'pool_host': pool_from_host})
|
||||||
|
LOG.error(msg)
|
||||||
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
|
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
|
||||||
|
|
||||||
|
@cutils.trace
|
||||||
def manage_existing_get_size(self, volume, existing_vol_ref):
|
def manage_existing_get_size(self, volume, existing_vol_ref):
|
||||||
"""Returns the size of volume to be managed by manage_existing.
|
"""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 "
|
"%(name)s, because of error in getting "
|
||||||
"volume size."),
|
"volume size."),
|
||||||
{'name': existing_vol_ref['source-name']})
|
{'name': existing_vol_ref['source-name']})
|
||||||
|
LOG.exception(exception_message)
|
||||||
raise exception.VolumeBackendAPIException(data=exception_message)
|
raise exception.VolumeBackendAPIException(data=exception_message)
|
||||||
|
|
||||||
LOG.debug("Reporting size of NFS volume ref %(ref)s as %(size)d GB.",
|
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
|
return vol_size
|
||||||
|
|
||||||
|
@cutils.trace
|
||||||
def unmanage(self, volume):
|
def unmanage(self, volume):
|
||||||
"""Removes the specified volume from Cinder management.
|
"""Removes the specified volume from Cinder management.
|
||||||
|
|
||||||
@ -623,9 +640,11 @@ class HNASNFSDriver(nfs.NfsDriver):
|
|||||||
self._try_execute("mv", vol_path, new_path,
|
self._try_execute("mv", vol_path, new_path,
|
||||||
run_as_root=False, check_exit_code=True)
|
run_as_root=False, check_exit_code=True)
|
||||||
|
|
||||||
LOG.info(_LI("Cinder NFS volume with current path %(cr)s is "
|
LOG.info(_LI("The volume with path %(old)s is no longer being "
|
||||||
"no longer being managed."), {'cr': new_path})
|
"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):
|
except (OSError, ValueError):
|
||||||
LOG.error(_LE("The NFS Volume %(cr)s does not exist."),
|
LOG.exception(_LE("The NFS Volume %(cr)s does not exist."),
|
||||||
{'cr': new_path})
|
{'cr': vol_path})
|
||||||
|
@ -26,8 +26,7 @@ import six
|
|||||||
from xml.etree import ElementTree as ETree
|
from xml.etree import ElementTree as ETree
|
||||||
|
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
|
from cinder.i18n import _, _LW, _LE
|
||||||
from cinder.i18n import _, _LW
|
|
||||||
from cinder.volume import volume_types
|
from cinder.volume import volume_types
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -45,7 +44,7 @@ drivers_common_opts = [
|
|||||||
'the SMU IP.'),
|
'the SMU IP.'),
|
||||||
cfg.StrOpt('hnas_ssc_cmd',
|
cfg.StrOpt('hnas_ssc_cmd',
|
||||||
default='ssc',
|
default='ssc',
|
||||||
help='Command to communicate to HNAS array.'),
|
help='Command to communicate to HNAS.'),
|
||||||
cfg.StrOpt('hnas_username',
|
cfg.StrOpt('hnas_username',
|
||||||
help='HNAS username.'),
|
help='HNAS username.'),
|
||||||
cfg.StrOpt('hnas_password',
|
cfg.StrOpt('hnas_password',
|
||||||
@ -96,6 +95,7 @@ def _check_conf_params(config, vol_type, dv_type, idx):
|
|||||||
if config['username'] is None:
|
if config['username'] is None:
|
||||||
msg = (_("The config parameter hnas_username "
|
msg = (_("The config parameter hnas_username "
|
||||||
"is not set in the cinder.conf."))
|
"is not set in the cinder.conf."))
|
||||||
|
LOG.error(msg)
|
||||||
raise exception.InvalidParameterValue(err=msg)
|
raise exception.InvalidParameterValue(err=msg)
|
||||||
|
|
||||||
if (config['password'] is None and
|
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 "
|
"missing: you need to set hnas_password "
|
||||||
"or hnas_ssh_private_key "
|
"or hnas_ssh_private_key "
|
||||||
"in the cinder.conf."))
|
"in the cinder.conf."))
|
||||||
|
LOG.error(msg)
|
||||||
raise exception.InvalidParameterValue(err=msg)
|
raise exception.InvalidParameterValue(err=msg)
|
||||||
|
|
||||||
if config['mgmt_ip0'] is None:
|
if config['mgmt_ip0'] is None:
|
||||||
msg = (_("The config parameter hnas_mgmt_ip0 "
|
msg = (_("The config parameter hnas_mgmt_ip0 "
|
||||||
"is not set in the cinder.conf."))
|
"is not set in the cinder.conf."))
|
||||||
|
LOG.error(msg)
|
||||||
raise exception.InvalidParameterValue(err=msg)
|
raise exception.InvalidParameterValue(err=msg)
|
||||||
|
|
||||||
if config['services'][vol_type]['hdp'] is None:
|
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 "
|
"not set in the cinder.conf. Note that you need to "
|
||||||
"have at least one pool configured.") %
|
"have at least one pool configured.") %
|
||||||
{'idx': idx})
|
{'idx': idx})
|
||||||
|
LOG.error(msg)
|
||||||
raise exception.InvalidParameterValue(err=msg)
|
raise exception.InvalidParameterValue(err=msg)
|
||||||
|
|
||||||
if config['services'][vol_type]['volume_type'] is None:
|
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 "
|
"in the cinder.conf. Note that you need to "
|
||||||
"have at least one pool configured.") %
|
"have at least one pool configured.") %
|
||||||
{'idx': idx})
|
{'idx': idx})
|
||||||
|
LOG.error(msg)
|
||||||
raise exception.InvalidParameterValue(err=msg)
|
raise exception.InvalidParameterValue(err=msg)
|
||||||
|
|
||||||
if (dv_type == 'iscsi' and
|
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 "
|
"hnas_svc%(idx)s_iscsi_ip is not set "
|
||||||
"in the cinder.conf. Note that you need to "
|
"in the cinder.conf. Note that you need to "
|
||||||
"have at least one pool configured.") % {'idx': idx})
|
"have at least one pool configured.") % {'idx': idx})
|
||||||
|
LOG.error(msg)
|
||||||
raise exception.InvalidParameterValue(err=msg)
|
raise exception.InvalidParameterValue(err=msg)
|
||||||
|
|
||||||
|
|
||||||
@ -147,6 +152,7 @@ def _xml_read(root, element, check=None):
|
|||||||
|
|
||||||
# mandatory parameter not found
|
# mandatory parameter not found
|
||||||
if val is None and check:
|
if val is None and check:
|
||||||
|
LOG.error(_LE("Mandatory parameter not found: %(p)s"), {'p': element})
|
||||||
raise exception.ParameterNotFound(param=element)
|
raise exception.ParameterNotFound(param=element)
|
||||||
|
|
||||||
# tag not found
|
# tag not found
|
||||||
@ -158,6 +164,7 @@ def _xml_read(root, element, check=None):
|
|||||||
if not val.strip():
|
if not val.strip():
|
||||||
if svc_tag_pattern.search(element):
|
if svc_tag_pattern.search(element):
|
||||||
return ""
|
return ""
|
||||||
|
LOG.error(_LE("Parameter not found: %(param)s"), {'param': element})
|
||||||
raise exception.ParameterNotFound(param=element)
|
raise exception.ParameterNotFound(param=element)
|
||||||
|
|
||||||
LOG.debug("%(element)s: %(val)s",
|
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):
|
if not os.access(xml_config_file, os.R_OK):
|
||||||
msg = (_("Can't find HNAS configurations on cinder.conf neither "
|
msg = (_("Can't find HNAS configurations on cinder.conf neither "
|
||||||
"on the path %(xml)s.") % {'xml': xml_config_file})
|
"on the path %(xml)s.") % {'xml': xml_config_file})
|
||||||
|
LOG.error(msg)
|
||||||
raise exception.ConfigNotFound(message=msg)
|
raise exception.ConfigNotFound(message=msg)
|
||||||
else:
|
else:
|
||||||
LOG.warning(_LW("This XML configuration file %(xml)s is deprecated. "
|
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:
|
try:
|
||||||
root = ETree.parse(xml_config_file).getroot()
|
root = ETree.parse(xml_config_file).getroot()
|
||||||
except ETree.ParseError:
|
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)
|
raise exception.ConfigNotFound(message=msg)
|
||||||
|
|
||||||
# mandatory parameters for NFS and iSCSI
|
# 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')
|
config['password'] = _xml_read(root, 'password')
|
||||||
|
|
||||||
if config['ssh_private_key'] is None and config['password'] is None:
|
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)
|
raise exception.ConfigNotFound(message=msg)
|
||||||
|
|
||||||
if _xml_read(root, 'ssh_port') is not None:
|
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!
|
# at least one service required!
|
||||||
if not config['services'].keys():
|
if not config['services'].keys():
|
||||||
msg = (_("svc_0"))
|
LOG.error(_LE("No service found in xml config file"))
|
||||||
raise exception.ParameterNotFound(param=msg)
|
raise exception.ParameterNotFound(param="svc_0")
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user