from teuthology.orchestra.daemon import DaemonGroup
from teuthology.orchestra.remote import Remote
from teuthology.config import config as teuth_config
+from teuthology.contextutil import safe_while
import six
import logging
self.subproc = subproc
self.stdout = stdout or BytesIO()
self.stderr = stderr or BytesIO()
+ # this variable is meant for instance of this class named fuse_daemon.
+ # child process of the command launched with sudo must be killed,
+ # since killing parent process alone has no impact on the child
+ # process.
+ self.fuse_pid = -1
self.check_status = check_status
self.exitstatus = self.returncode = None
if self.subproc.pid and not self.finished:
log.info("kill: killing pid {0} ({1})".format(
self.subproc.pid, self.args))
- safe_kill(self.subproc.pid)
+ if self.fuse_pid != -1:
+ safe_kill(self.fuse_pid)
+ else:
+ safe_kill(self.subproc.pid)
else:
log.info("kill: already terminated ({0})".format(self.args))
if asok_conf:
d = asok_conf.groups(1)[0]
break
- path = "{0}/client.{1}.{2}.asok".format(d, self.client_id, self.fuse_daemon.subproc.pid)
- log.info("I think my launching pid was {0}".format(self.fuse_daemon.subproc.pid))
+ path = "{0}/client.{1}.*.asok".format(d, self.client_id)
return path
def mount(self, mount_path=None, mount_fs_name=None, mount_options=[]):
if asok_conf:
d = asok_conf.groups(1)[0]
break
- path = "{0}/client.{1}.{2}.asok".format(d, self.client_id, self.fuse_daemon.subproc.pid)
- log.info("I think my launching pid was {0}".format(self.fuse_daemon.subproc.pid))
+ path = "{0}/client.{1}.*.asok".format(d, self.client_id)
return path
def mount(self, mount_path=None, mount_fs_name=None, mountpoint=None, mount_options=[]):
pre_mount_conns = list_connections()
log.info("Pre-mount connections: {0}".format(pre_mount_conns))
- prefix = [os.path.join(BIN_PREFIX, "ceph-fuse")]
+ prefix = ['sudo', 'nsenter',
+ '--net=/var/run/netns/{0}'.format(self.netns_name),
+ '--setuid', str(os.getuid()),
+ os.path.join(BIN_PREFIX, "ceph-fuse")]
if os.getuid() != 0:
prefix += ["--client_die_on_failed_dentry_invalidate=false"]
-
if mount_path is not None:
prefix += ["--client_mountpoint={0}".format(mount_path)]
-
if mount_fs_name is not None:
prefix += ["--client_fs={0}".format(mount_fs_name)]
-
prefix += mount_options;
+ fuse_cmd_args = prefix + ["-f", "--name",
+ "client.{0}".format(self.client_id),
+ self.mountpoint]
- self.fuse_daemon = self.client_remote.run(args=
- ['nsenter',
- '--net=/var/run/netns/{0}'.format(self.netns_name),
- ] + prefix + [
- "-f",
- "--name",
- "client.{0}".format(self.client_id),
- self.mountpoint
- ], wait=False)
-
- log.info("Mounting client.{0} with pid {1}".format(self.client_id, self.fuse_daemon.subproc.pid))
+ self.fuse_daemon = self.client_remote.run(args=fuse_cmd_args,
+ wait=False)
+ self._set_fuse_daemon_pid()
+ log.info("Mounting client.{0} with pid "
+ "{1}".format(self.client_id, self.fuse_daemon.subproc.pid))
# Wait for the connection reference to appear in /sys
waited = 0
self.gather_mount_info()
self.mounted = True
+ def _set_fuse_daemon_pid(self):
+ # NOTE: When a command <args> is launched with sudo, two processes are
+ # launched, one with sudo in <args> and other without. Make sure we
+ # get the PID of latter one.
+ with safe_while(sleep=1, tries=15) as proceed:
+ while proceed():
+ try:
+ sock = self.find_admin_socket()
+ except (RuntimeError, CommandFailedError):
+ continue
+
+ self.fuse_daemon.fuse_pid = int(re.match(".*\.(\d+)\.asok$",
+ sock).group(1))
+ break
def _run_python(self, pyscript, py_version='python'):
"""