Fix bugs of GPFSNFS & GPFSRemote Driver initialization failure

Due to lack of GPFS path ('/usr/lpp/mmfs/bin/') export,
GPFSNFS driver configuration & GPFSRemote driver configuration are
not able to find the GPFS commands causing the initialization failure.
With this patch, GPFS will be able to run all GPFS commands
irrespective of GPFS path export.

Change-Id: Ia44cc1495320ebd1ee6f442f5d94c45f06383dd3
Closes-bug: #1691739
This commit is contained in:
digvijay2016 2017-05-18 18:32:57 +05:30
parent e2fda841d5
commit 50630ffbb0
3 changed files with 50 additions and 36 deletions

View File

@ -162,6 +162,7 @@ class GPFSDriver(driver.CloneableImageVD,
self.configuration.append_config_values(gpfs_opts) self.configuration.append_config_values(gpfs_opts)
self.gpfs_execute = self._gpfs_local_execute self.gpfs_execute = self._gpfs_local_execute
self._execute = utils.execute self._execute = utils.execute
self.GPFS_PATH = ''
def _gpfs_local_execute(self, *cmd, **kwargs): def _gpfs_local_execute(self, *cmd, **kwargs):
if 'run_as_root' not in kwargs: if 'run_as_root' not in kwargs:
@ -172,7 +173,7 @@ class GPFSDriver(driver.CloneableImageVD,
def _get_gpfs_state(self): def _get_gpfs_state(self):
"""Return GPFS state information.""" """Return GPFS state information."""
try: try:
(out, err) = self.gpfs_execute('mmgetstate', '-Y') (out, err) = self.gpfs_execute(self.GPFS_PATH + 'mmgetstate', '-Y')
return out return out
except processutils.ProcessExecutionError as exc: except processutils.ProcessExecutionError as exc:
LOG.error('Failed to issue mmgetstate command, error: %s.', LOG.error('Failed to issue mmgetstate command, error: %s.',
@ -207,7 +208,8 @@ class GPFSDriver(driver.CloneableImageVD,
def _get_gpfs_cluster_id(self): def _get_gpfs_cluster_id(self):
"""Return the id for GPFS cluster being used.""" """Return the id for GPFS cluster being used."""
try: try:
(out, err) = self.gpfs_execute('mmlsconfig', 'clusterId', '-Y') (out, err) = self.gpfs_execute(self.GPFS_PATH + 'mmlsconfig',
'clusterId', '-Y')
lines = out.splitlines() lines = out.splitlines()
value_token = lines[0].split(':').index('value') value_token = lines[0].split(':').index('value')
cluster_id = lines[1].split(':')[value_token] cluster_id = lines[1].split(':')[value_token]
@ -221,7 +223,8 @@ class GPFSDriver(driver.CloneableImageVD,
"""Return the GPFS fileset for specified path.""" """Return the GPFS fileset for specified path."""
fs_regex = re.compile(r'.*fileset.name:\s+(?P<fileset>\w+)', re.S) fs_regex = re.compile(r'.*fileset.name:\s+(?P<fileset>\w+)', re.S)
try: try:
(out, err) = self.gpfs_execute('mmlsattr', '-L', path) (out, err) = self.gpfs_execute(self.GPFS_PATH + 'mmlsattr', '-L',
path)
except processutils.ProcessExecutionError as exc: except processutils.ProcessExecutionError as exc:
LOG.error('Failed to issue mmlsattr command on path %(path)s, ' LOG.error('Failed to issue mmlsattr command on path %(path)s, '
'error: %(error)s', 'error: %(error)s',
@ -242,7 +245,8 @@ class GPFSDriver(driver.CloneableImageVD,
def _verify_gpfs_pool(self, storage_pool): def _verify_gpfs_pool(self, storage_pool):
"""Return true if the specified pool is a valid GPFS storage pool.""" """Return true if the specified pool is a valid GPFS storage pool."""
try: try:
self.gpfs_execute('mmlspool', self._gpfs_device, storage_pool) self.gpfs_execute(self.GPFS_PATH + 'mmlspool', self._gpfs_device,
storage_pool)
return True return True
except processutils.ProcessExecutionError: except processutils.ProcessExecutionError:
return False return False
@ -259,7 +263,8 @@ class GPFSDriver(driver.CloneableImageVD,
raise exception.VolumeBackendAPIException(data=msg) raise exception.VolumeBackendAPIException(data=msg)
try: try:
self.gpfs_execute('mmchattr', '-P', new_pool, local_path) self.gpfs_execute(self.GPFS_PATH + 'mmchattr', '-P', new_pool,
local_path)
LOG.debug('Updated storage pool with mmchattr to %s.', new_pool) LOG.debug('Updated storage pool with mmchattr to %s.', new_pool)
return True return True
except processutils.ProcessExecutionError as exc: except processutils.ProcessExecutionError as exc:
@ -276,7 +281,8 @@ class GPFSDriver(driver.CloneableImageVD,
""" """
filesystem = self._get_filesystem_from_path(path) filesystem = self._get_filesystem_from_path(path)
try: try:
(out, err) = self.gpfs_execute('mmlsfs', filesystem, '-V', '-Y') (out, err) = self.gpfs_execute(self.GPFS_PATH + 'mmlsfs',
filesystem, '-V', '-Y')
except processutils.ProcessExecutionError as exc: except processutils.ProcessExecutionError as exc:
LOG.error('Failed to issue mmlsfs command for path %(path)s, ' LOG.error('Failed to issue mmlsfs command for path %(path)s, '
'error: %(error)s.', 'error: %(error)s.',
@ -295,7 +301,7 @@ class GPFSDriver(driver.CloneableImageVD,
def _get_gpfs_cluster_release_level(self): def _get_gpfs_cluster_release_level(self):
"""Return the GPFS version of current cluster.""" """Return the GPFS version of current cluster."""
try: try:
(out, err) = self.gpfs_execute('mmlsconfig', (out, err) = self.gpfs_execute(self.GPFS_PATH + 'mmlsconfig',
'minreleaseLeveldaemon', 'minreleaseLeveldaemon',
'-Y') '-Y')
except processutils.ProcessExecutionError as exc: except processutils.ProcessExecutionError as exc:
@ -314,7 +320,7 @@ class GPFSDriver(driver.CloneableImageVD,
If not part of a gpfs file system, raise ProcessExecutionError. If not part of a gpfs file system, raise ProcessExecutionError.
""" """
try: try:
self.gpfs_execute('mmlsattr', directory) self.gpfs_execute(self.GPFS_PATH + 'mmlsattr', directory)
except processutils.ProcessExecutionError as exc: except processutils.ProcessExecutionError as exc:
LOG.error('Failed to issue mmlsattr command ' LOG.error('Failed to issue mmlsattr command '
'for path %(path)s, ' 'for path %(path)s, '
@ -495,7 +501,7 @@ class GPFSDriver(driver.CloneableImageVD,
def _gpfs_change_attributes(self, options, path): def _gpfs_change_attributes(self, options, path):
"""Update GPFS attributes on the specified file.""" """Update GPFS attributes on the specified file."""
cmd = ['mmchattr'] cmd = [self.GPFS_PATH + 'mmchattr']
cmd.extend(options) cmd.extend(options)
cmd.append(path) cmd.append(path)
LOG.debug('Update volume attributes with mmchattr to %s.', options) LOG.debug('Update volume attributes with mmchattr to %s.', options)
@ -614,7 +620,8 @@ class GPFSDriver(driver.CloneableImageVD,
if not os.path.exists(fchild_local_path): if not os.path.exists(fchild_local_path):
return return
(out, err) = self.gpfs_execute('mmclone', 'show', fchild) (out, err) = self.gpfs_execute(self.GPFS_PATH + 'mmclone', 'show',
fchild)
fparent = None fparent = None
delete_parent = False delete_parent = False
inode_regex = re.compile( inode_regex = re.compile(
@ -692,13 +699,13 @@ class GPFSDriver(driver.CloneableImageVD,
max_depth = self.configuration.gpfs_max_clone_depth max_depth = self.configuration.gpfs_max_clone_depth
if max_depth == 0: if max_depth == 0:
return False return False
(out, err) = self.gpfs_execute('mmclone', 'show', src) (out, err) = self.gpfs_execute(self.GPFS_PATH + 'mmclone', 'show', src)
depth_regex = re.compile(r'.*\s+no\s+(?P<depth>\d+)', re.M | re.S) depth_regex = re.compile(r'.*\s+no\s+(?P<depth>\d+)', re.M | re.S)
match = depth_regex.match(out) match = depth_regex.match(out)
if match: if match:
depth = int(match.group('depth')) depth = int(match.group('depth'))
if depth > max_depth: if depth > max_depth:
self.gpfs_execute('mmclone', 'redirect', src) self.gpfs_execute(self.GPFS_PATH + 'mmclone', 'redirect', src)
return True return True
return False return False
@ -712,7 +719,7 @@ class GPFSDriver(driver.CloneableImageVD,
def _create_gpfs_copy(self, src, dest): def _create_gpfs_copy(self, src, dest):
"""Create a GPFS file clone copy for the specified file.""" """Create a GPFS file clone copy for the specified file."""
self.gpfs_execute('mmclone', 'copy', src, dest) self.gpfs_execute(self.GPFS_PATH + 'mmclone', 'copy', src, dest)
def _gpfs_full_copy(self, src, dest): def _gpfs_full_copy(self, src, dest):
"""Create a full copy from src to dest.""" """Create a full copy from src to dest."""
@ -721,13 +728,14 @@ class GPFSDriver(driver.CloneableImageVD,
def _create_gpfs_snap(self, src, dest=None): def _create_gpfs_snap(self, src, dest=None):
"""Create a GPFS file clone snapshot for the specified file.""" """Create a GPFS file clone snapshot for the specified file."""
if dest is None: if dest is None:
self.gpfs_execute('mmclone', 'snap', src) self.gpfs_execute(self.GPFS_PATH + 'mmclone', 'snap', src)
else: else:
self.gpfs_execute('mmclone', 'snap', src, dest) self.gpfs_execute(self.GPFS_PATH + 'mmclone', 'snap', src, dest)
def _is_gpfs_parent_file(self, gpfs_file): def _is_gpfs_parent_file(self, gpfs_file):
"""Return true if the specified file is a gpfs clone parent.""" """Return true if the specified file is a gpfs clone parent."""
out, err = self.gpfs_execute('mmclone', 'show', gpfs_file) out, err = self.gpfs_execute(self.GPFS_PATH + 'mmclone', 'show',
gpfs_file)
ptoken = out.splitlines().pop().split()[0] ptoken = out.splitlines().pop().split()[0]
return ptoken == 'yes' return ptoken == 'yes'
@ -780,7 +788,8 @@ class GPFSDriver(driver.CloneableImageVD,
def _get_gpfs_encryption_status(self): def _get_gpfs_encryption_status(self):
"""Determine if the backend is configured with key manager.""" """Determine if the backend is configured with key manager."""
try: try:
(out, err) = self.gpfs_execute('mmlsfs', self._gpfs_device, (out, err) = self.gpfs_execute(self.GPFS_PATH + 'mmlsfs',
self._gpfs_device,
'--encryption', '-Y') '--encryption', '-Y')
lines = out.splitlines() lines = out.splitlines()
value_token = lines[0].split(':').index('data') value_token = lines[0].split(':').index('data')
@ -1156,7 +1165,7 @@ class GPFSDriver(driver.CloneableImageVD,
cgpath = os.path.join(self.configuration.gpfs_mount_point_base, cgpath = os.path.join(self.configuration.gpfs_mount_point_base,
cgname) cgname)
try: try:
self.gpfs_execute('mmcrfileset', fsdev, cgname, self.gpfs_execute(self.GPFS_PATH + 'mmcrfileset', fsdev, cgname,
'--inode-space', 'new') '--inode-space', 'new')
except processutils.ProcessExecutionError as e: except processutils.ProcessExecutionError as e:
msg = (_('Failed to create consistency group: %(cgid)s. ' msg = (_('Failed to create consistency group: %(cgid)s. '
@ -1166,7 +1175,7 @@ class GPFSDriver(driver.CloneableImageVD,
raise exception.VolumeBackendAPIException(data=msg) raise exception.VolumeBackendAPIException(data=msg)
try: try:
self.gpfs_execute('mmlinkfileset', fsdev, cgname, self.gpfs_execute(self.GPFS_PATH + 'mmlinkfileset', fsdev, cgname,
'-J', cgpath) '-J', cgpath)
except processutils.ProcessExecutionError as e: except processutils.ProcessExecutionError as e:
msg = (_('Failed to link fileset for the share %(cgname)s. ' msg = (_('Failed to link fileset for the share %(cgname)s. '
@ -1199,7 +1208,8 @@ class GPFSDriver(driver.CloneableImageVD,
# Unlink and delete the fileset associated with the consistency group. # Unlink and delete the fileset associated with the consistency group.
# All of the volumes and volume snapshot data will also be deleted. # All of the volumes and volume snapshot data will also be deleted.
try: try:
self.gpfs_execute('mmunlinkfileset', fsdev, cgname, '-f') self.gpfs_execute(self.GPFS_PATH + 'mmunlinkfileset', fsdev,
cgname, '-f')
except processutils.ProcessExecutionError as e: except processutils.ProcessExecutionError as e:
msg = (_('Failed to unlink fileset for consistency group ' msg = (_('Failed to unlink fileset for consistency group '
'%(cgname)s. Error: %(excmsg)s.') % '%(cgname)s. Error: %(excmsg)s.') %
@ -1208,7 +1218,8 @@ class GPFSDriver(driver.CloneableImageVD,
raise exception.VolumeBackendAPIException(data=msg) raise exception.VolumeBackendAPIException(data=msg)
try: try:
self.gpfs_execute('mmdelfileset', fsdev, cgname, '-f') self.gpfs_execute(self.GPFS_PATH + 'mmdelfileset', fsdev, cgname,
'-f')
except processutils.ProcessExecutionError as e: except processutils.ProcessExecutionError as e:
msg = (_('Failed to delete fileset for consistency group ' msg = (_('Failed to delete fileset for consistency group '
'%(cgname)s. Error: %(excmsg)s.') % '%(cgname)s. Error: %(excmsg)s.') %
@ -1295,6 +1306,7 @@ class GPFSRemoteDriver(GPFSDriver, san.SanDriver):
self.configuration.gpfs_private_key) self.configuration.gpfs_private_key)
self.configuration.san_ssh_port = self.configuration.gpfs_ssh_port self.configuration.san_ssh_port = self.configuration.gpfs_ssh_port
self.gpfs_execute = self._gpfs_remote_execute self.gpfs_execute = self._gpfs_remote_execute
self.GPFS_PATH = '/usr/lpp/mmfs/bin/'
def _gpfs_remote_execute(self, *cmd, **kwargs): def _gpfs_remote_execute(self, *cmd, **kwargs):
check_exit_code = kwargs.pop('check_exit_code', None) check_exit_code = kwargs.pop('check_exit_code', None)
@ -1357,7 +1369,8 @@ class GPFSRemoteDriver(GPFSDriver, san.SanDriver):
continue continue
try: try:
# check if GPFS state is active on the node # check if GPFS state is active on the node
(out, __) = processutils.ssh_execute(ssh, 'mmgetstate -Y') (out, __) = processutils.ssh_execute(ssh, self.GPFS_PATH +
'mmgetstate -Y')
lines = out.splitlines() lines = out.splitlines()
state_token = lines[0].split(':').index('state') state_token = lines[0].split(':').index('state')
gpfs_state = lines[1].split(':')[state_token] gpfs_state = lines[1].split(':')[state_token]
@ -1414,6 +1427,7 @@ class GPFSNFSDriver(GPFSDriver, nfs.NfsDriver, san.SanDriver):
self.configuration.san_private_key = ( self.configuration.san_private_key = (
self.configuration.nas_private_key) self.configuration.nas_private_key)
self.configuration.san_ssh_port = self.configuration.nas_ssh_port self.configuration.san_ssh_port = self.configuration.nas_ssh_port
self.GPFS_PATH = '/usr/lpp/mmfs/bin/'
def _gpfs_remote_execute(self, *cmd, **kwargs): def _gpfs_remote_execute(self, *cmd, **kwargs):
check_exit_code = kwargs.pop('check_exit_code', None) check_exit_code = kwargs.pop('check_exit_code', None)

View File

@ -10,7 +10,7 @@ filters_path=/etc/cinder/rootwrap.d,/usr/share/cinder/rootwrap
# explicitely specify a full path (separated by ',') # explicitely specify a full path (separated by ',')
# If not specified, defaults to system PATH environment variable. # If not specified, defaults to system PATH environment variable.
# These directories MUST all be only writeable by root ! # These directories MUST all be only writeable by root !
exec_dirs=/sbin,/usr/sbin,/bin,/usr/bin,/usr/local/bin,/usr/local/sbin exec_dirs=/sbin,/usr/sbin,/bin,/usr/bin,/usr/local/bin,/usr/local/sbin,/usr/lpp/mmfs/bin
# Enable logging to syslog # Enable logging to syslog
# Default value is False # Default value is False

View File

@ -153,20 +153,20 @@ mv: CommandFilter, mv, root
# cinder/volume/drivers/ibm/gpfs.py # cinder/volume/drivers/ibm/gpfs.py
cp: CommandFilter, cp, root cp: CommandFilter, cp, root
mmgetstate: CommandFilter, /usr/lpp/mmfs/bin/mmgetstate, root mmgetstate: CommandFilter, mmgetstate, root
mmclone: CommandFilter, /usr/lpp/mmfs/bin/mmclone, root mmclone: CommandFilter, mmclone, root
mmlsattr: CommandFilter, /usr/lpp/mmfs/bin/mmlsattr, root mmlsattr: CommandFilter, mmlsattr, root
mmchattr: CommandFilter, /usr/lpp/mmfs/bin/mmchattr, root mmchattr: CommandFilter, mmchattr, root
mmlsconfig: CommandFilter, /usr/lpp/mmfs/bin/mmlsconfig, root mmlsconfig: CommandFilter, mmlsconfig, root
mmlsfs: CommandFilter, /usr/lpp/mmfs/bin/mmlsfs, root mmlsfs: CommandFilter, mmlsfs, root
mmlspool: CommandFilter, /usr/lpp/mmfs/bin/mmlspool, root mmlspool: CommandFilter, mmlspool, root
mkfs: CommandFilter, mkfs, root mkfs: CommandFilter, mkfs, root
mmcrfileset: CommandFilter, /usr/lpp/mmfs/bin/mmcrfileset, root mmcrfileset: CommandFilter, mmcrfileset, root
mmlinkfileset: CommandFilter, /usr/lpp/mmfs/bin/mmlinkfileset, root mmlinkfileset: CommandFilter, mmlinkfileset, root
mmunlinkfileset: CommandFilter, /usr/lpp/mmfs/bin/mmunlinkfileset, root mmunlinkfileset: CommandFilter, mmunlinkfileset, root
mmdelfileset: CommandFilter, /usr/lpp/mmfs/bin/mmdelfileset, root mmdelfileset: CommandFilter, mmdelfileset, root
mmcrsnapshot: CommandFilter, /usr/lpp/mmfs/bin/mmcrsnapshot, root mmcrsnapshot: CommandFilter, mmcrsnapshot, root
mmdelsnapshot: CommandFilter, /usr/lpp/mmfs/bin/mmdelsnapshot, root mmdelsnapshot: CommandFilter, mmdelsnapshot, root
# cinder/volume/drivers/ibm/gpfs.py # cinder/volume/drivers/ibm/gpfs.py
# cinder/volume/drivers/ibm/ibmnas.py # cinder/volume/drivers/ibm/ibmnas.py