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