Port nvmet driver to use privsep

Now that we have privsep support in cinder,
we can start using privsep in various drivers
so we can drop rootwrap support.

Change-Id: I3cff61b4cde16e00ad23d534c5281a2f1afcd29f
Signed-off-by: Chuck Short <chucks@redhat.com>
This commit is contained in:
Chuck Short 2018-07-04 15:35:37 -04:00
parent 52deeff8d2
commit 5c1b5cbad7
4 changed files with 99 additions and 32 deletions

41
cinder/privsep/nvmcli.py Normal file
View File

@ -0,0 +1,41 @@
# Copyright 2018 Red Hat, Inc
# Copyright 2017 Rackspace Australia
# Copyright 2018 Michael Still and Aptira
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Helpers for nvmetcli related routines.
"""
from oslo_concurrency import processutils
import cinder.privsep
@cinder.privsep.sys_admin_pctxt.entrypoint
def restore(path):
cmd = [
'nvmetcli',
'restore',
path]
return processutils.execute(*cmd)
@cinder.privsep.sys_admin_pctxt.entrypoint
def save(path):
cmd = [
'nvmetcli',
'save',
path]
return processutils.execute(*cmd)

39
cinder/privsep/utils.py Normal file
View File

@ -0,0 +1,39 @@
# Copyright 2018 Red Hat, Inc
# Copyright 2017 Rackspace Australia
# Copyright 2018 Michael Still and Aptira
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Helpers for cgroup related routines.
"""
import os
from cinder import exception
import cinder.privsep
@cinder.privsep.sys_admin_pctxt.entrypoint
def readfile(path):
if not os.path.exists(path):
raise exception.FileNotFound(file_path=path)
with open(path, 'r') as f:
return f.read()
@cinder.privsep.sys_admin_pctxt.entrypoint
def removefile(path):
if not os.path.exists(path):
raise exception.FileNotFound(file_path=path)
os.unlink(path)

View File

@ -20,6 +20,7 @@ from oslo_utils import uuidutils
import six
from cinder import exception
import cinder.privsep
from cinder import utils
from cinder.volume.targets import nvmeof
@ -76,13 +77,8 @@ class NVMET(nvmeof.NVMeOF):
with tempfile.NamedTemporaryFile() as tmp_fd:
tmp_fd.write(json.dumps(nvmf_subsystems))
tmp_fd.flush()
cmd = [
'nvmetcli',
'restore',
tmp_fd.name]
try:
out, err = utils.execute(*cmd, run_as_root=True)
out, err = cinder.privsep.nvmcli.restore(tmp_fd.name)
except putils.ProcessExecutionError:
with excutils.save_and_reraise_exception():
LOG.exception('Error from nvmetcli restore')
@ -156,22 +152,22 @@ class NVMET(nvmeof.NVMeOF):
"for volume: %s", volume['id'])
def _delete_nvmf_subsystem(self, nvmf_subsystems, subsystem_name):
LOG.debug(
'Removing this subsystem: %s', subsystem_name)
LOG.debug(
'Removing this subsystem: %s', subsystem_name)
for port in nvmf_subsystems['ports']:
if subsystem_name in port['subsystems']:
port['subsystems'].remove(subsystem_name)
break
for subsys in nvmf_subsystems['subsystems']:
if subsys['nqn'] == subsystem_name:
nvmf_subsystems['subsystems'].remove(subsys)
break
for port in nvmf_subsystems['ports']:
if subsystem_name in port['subsystems']:
port['subsystems'].remove(subsystem_name)
break
for subsys in nvmf_subsystems['subsystems']:
if subsys['nqn'] == subsystem_name:
nvmf_subsystems['subsystems'].remove(subsys)
break
LOG.debug(
'Newly loaded subsystems will be: %s', nvmf_subsystems)
self._restore(nvmf_subsystems)
return subsystem_name
LOG.debug(
'Newly loaded subsystems will be: %s', nvmf_subsystems)
self._restore(nvmf_subsystems)
return subsystem_name
def _get_nvmf_subsystem(self, nvmf_subsystems, volume_id):
subsystem_name = self._get_target_info(
@ -184,12 +180,8 @@ class NVMET(nvmeof.NVMeOF):
__, tmp_file_path = tempfile.mkstemp(prefix='nvmet')
# nvmetcli doesn't support printing to stdout yet,
cmd = [
'nvmetcli',
'save',
tmp_file_path]
try:
out, err = utils.execute(*cmd, run_as_root=True)
out, err = cinder.privsep.nvmcli.save(tmp_file_path)
except putils.ProcessExecutionError:
with excutils.save_and_reraise_exception():
LOG.exception('Error from nvmetcli save')
@ -198,9 +190,8 @@ class NVMET(nvmeof.NVMeOF):
# temp file must be readable by this process user
# in order to avoid executing cat as root
with utils.temporary_chown(tmp_file_path):
cmd = ['cat', tmp_file_path]
try:
out, err = utils.execute(*cmd)
out = cinder.privsep.utils.readfile(tmp_file_path)
except putils.ProcessExecutionError:
with excutils.save_and_reraise_exception():
LOG.exception('Failed to read: %s', tmp_file_path)
@ -215,8 +206,7 @@ class NVMET(nvmeof.NVMeOF):
return "nqn.%s-%s" % (subsystem, volume_id)
def _delete_file(self, file_path):
cmd = ['rm', '-f', file_path]
try:
out, err = utils.execute(*cmd, run_as_root=True)
cinder.privsep.utils.removefile(file_path)
except putils.ProcessExecutionError:
LOG.exception('Failed to delete file: %s', file_path)

View File

@ -230,6 +230,3 @@ drv_cfg: CommandFilter, /opt/emc/scaleio/sdc/bin/drv_cfg, root, /opt/emc/scaleio
# cinder/volume/drivers/quobyte.py
mount.quobyte: CommandFilter, mount.quobyte, root
umount.quobyte: CommandFilter, umount.quobyte, root
# cinder/volume/targets/nvmet.py
nvmetcli: CommandFilter, nvmetcli, root