From 6ef4fc936ec22e37b0e8a2670b5362fcfc0a1b25 Mon Sep 17 00:00:00 2001 From: vermeul <swen@ethz.ch> Date: Fri, 10 Jan 2020 13:26:10 +0100 Subject: [PATCH] SSDM-9151: implemented mount() and unmount() methods --- pybis/src/python/pybis/pybis.py | 124 +++++++++++++++++++++++++++----- 1 file changed, 107 insertions(+), 17 deletions(-) diff --git a/pybis/src/python/pybis/pybis.py b/pybis/src/python/pybis/pybis.py index 90ad1561f1a..e7bb1bd5a4b 100644 --- a/pybis/src/python/pybis/pybis.py +++ b/pybis/src/python/pybis/pybis.py @@ -11,6 +11,8 @@ Work with openBIS from Python. from __future__ import print_function import os import random +import subprocess +import errno import requests from requests.packages.urllib3.exceptions import InsecureRequestWarning @@ -932,11 +934,100 @@ class Openbis: os.environ['OPENBIS_TOKEN'] = self.token return self.token - def mount(self, username, servername, mountpoint, volname, password, path='/', port=2222, kex_algorithms ='+diffie-hellman-group1-sha1', shell=False): - """Mounts openBIS dataStore without root, using sshfs and fuse. + def unmount(self, mountpoint=None): + """Unmount a given mountpoint or unmount the stored mountpoint. + If the umount command does not work, try the pkill command. + If still not successful, throw an error message. """ + if mountpoint is None and not getattr(self, 'mountpoint', None): + raise ValueError("please provide a mountpoint to unmount") + + if mountpoint is None: + mountpoint = self.mountpoint + + full_mountpoint_path = os.path.abspath(os.path.expanduser(mountpoint)) + + if not os.path.exists(full_mountpoint_path): + return + + # mountpoint is not a mountpoint path + if not os.path.ismount(full_mountpoint_path): + return + + status = subprocess.call('umount {}'.format(full_mountpoint_path), shell=True) + if status == 1: + status = subprocess.call( + 'pkill -9 sshfs && umount "{}"'.format(full_mountpoint_path), + shell = True + ) + + if status == 1: + raise OSError("could not unmount mountpoint: {} Please try to unmount manually".format(full_mountpoint_path)) + else: + self.mountpoint = None + + + def is_mounted(self, mountpoint, None): + if mountpoint is None: + mountpoint = getattr(self, 'mountpoint', None) + + if mountpoint is None: + return False + + return os.path.ismount(mountpoint) + + + def mount(self, username, password, servername, mountpoint, volname=None, path='/', port=2222, kex_algorithms ='+diffie-hellman-group1-sha1'): + + """Mounts openBIS dataStore without being root, using sshfs and fuse. Both SSHFS and FUSE must be installed on the system (the installation requires root privileges): + + Mac OS X + ======== + Follow the installation instructions on + https://osxfuse.github.io + + Unix Cent OS 7 + ============== + $ sudo yum install epel-release + $ sudo yum --enablerepo=epel -y install fuse-sshfs + $ user="$(whoami)" + $ usermod -a -G fuse "$user" + """ + + def check_sshfs_is_installed(): + import subprocess + import errno + try: + subprocess.call('sshfs --help', shell=True) + except OSError as e: + if e.errno == errno.ENOENT: + raise ValueError('Your system seems not to have SSHFS installed. For Mac OS X, see installation instructions on https://osxfuse.github.io For Unix: $ sudo yum install epel-release && sudo yum --enablerepo=epel -y install fuse-sshfs && user="$(whoami)" && usermod -a -G fuse "$user"') + + check_sshfs_is_installed() + + # check if mountpoint exists, otherwise create it + full_mountpoint_path = os.path.abspath(os.path.expanduser(mountpoint)) + if not os.path.exists(full_mountpoint_path): + os.makedirs(full_mountpoint_path) + + self.mountpoint = full_mountpoint_path + + from sys import platform + supported_platforms = ['darwin', 'linux'] + if platform not in supported_platforms: + raise ValueError("This method is not yet supported on {} plattform".format(platform)) + + + os_options = { + "darwin": "-oauto_cache,reconnect,defer_permissions,noappledouble,negative_vncache,volname={}".format(servername), + "linux": "-oauto_cache,reconnect", + } + + if volname is None: + volname = servername + import subprocess args = { "username": username, @@ -946,22 +1037,21 @@ class Openbis: "path": path, "mountpoint": mountpoint, "volname": volname, - "kex_algroithms": kex_algroithms, - } - cmd = ( - 'echo "{password}" | sshfs -o port={port}' - ' -o ssh_command="ssh -oKexAlgorithms={kex_algroithms}+diffie-hellman-group1-sha1"' - ' {username}@{servername}:{path} {mountpoint}' - ' -oauto_cache,reconnect,defer_permissions,noappledouble,negative_vncache,volname={volname}' - ' -o password_stdin' - ) + "os_options": os_options[platform], + "kex_algorithms": kex_algorithms, + } - subprocess.run(cmd.format(**args), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - input=password, - shell=shell - ) + cmd = 'echo "{password}" | sshfs'\ + ' {username}@{servername}:{path} {mountpoint}' \ + ' -o port={port} -o ssh_command="ssh -oKexAlgorithms={kex_algorithms}" -o password_stdin'\ + ' {os_options}'.format(**args) + + status = subprocess.call(cmd, shell=True) + + if status == 0: + if VERBOSE: print("Mounted successfully to {}".format(full_mountpoint_path)) + else: + raise OSError("mount failed") def get_server_information(self): -- GitLab