def main_CLI(args): Output.verbose("*" * 10 + " " + str(datetime.datetime.now()) + " " + "*" * 10) Output.verbose("ENACdrives " + CONST.FULL_VERSION) Output.verbose("Detected OS : " + CONST.OS_DISTRIB + " " + CONST.OS_SYS + " " + CONST.OS_VERSION + "\n") Output.debug("LOCAL_USERNAME:"******"LOCAL_GROUPNAME:" + CONST.LOCAL_GROUPNAME) Output.debug("LOCAL_UID:" + str(CONST.LOCAL_UID)) Output.debug("LOCAL_GID:" + str(CONST.LOCAL_GID)) Output.debug("HOME_DIR:" + CONST.HOME_DIR) Output.debug("USER_CONF_FILE:" + CONST.USER_CONF_FILE) Output.debug("RESOURCES_DIR:" + CONST.RESOURCES_DIR + "\n") Output.debug("IMAGES_DIR:" + CONST.IMAGES_DIR + "\n") Output.debug("DEFAULT_MNT_DIR:" + CONST.DEFAULT_MNT_DIR + "\n") release_number_validation = validate_release_number() if release_number_validation == 'too old': Output.warning(CONST.NEED_TO_UPDATE_MSG) elif release_number_validation == 'newer': Output.normal(CONST.NEWER_THAN_PROD_MSG) if args.version: Output.cli("ENACdrives " + CONST.FULL_VERSION) sys.exit(0) ui = CLI(args) sys.exit(ui.run())
def __init__(self, args): self.args = args self.key_chain = Key_Chain(self) self.returncode = None self.set_username(args) self.cfg = conf.get_config() Output.verbose(pprint.pformat(self.cfg)) self.networks_check = Networks_Check(self.cfg, self) self.networks_check.scan() self.entries = [] already_added = [] for m_name in self.cfg["global"].get("entries_order", ()): if m_name in self.cfg["CIFS_mount"]: entry = CIFS_Mount(self, self.cfg, m_name, self.key_chain) self.entries.append(entry) already_added.append(m_name) self.cfg["CIFS_mount"][m_name]["entry"] = entry else: Output.warning("Entry not found '{0}'.".format(m_name)) for m_name in self.cfg["CIFS_mount"]: if m_name not in already_added: entry = CIFS_Mount(self, self.cfg, m_name, self.key_chain) self.entries.append(entry) self.cfg["CIFS_mount"][m_name]["entry"] = entry os_check(self)
def cifs_post_umount(mount): """ Performs tasks when umount is done. May happen some seconds after cifs_umount is completed (OS) """ if (os.path.isdir(mount.settings["local_path"]) and os.listdir(mount.settings["local_path"]) == []): try: os.rmdir(mount.settings["local_path"]) except OSError as e: Output.warning("Could not rmdir : {0}".format(e))
def open_file_manager(mount): def _cb(success, output, exit_code): pass if (mount.settings["Linux_CIFS_method"] == "gvfs" and not mount.settings["Linux_gvfs_symlink"]): path = None for f in os.listdir(LIN_CONST.GVFS_DIR): if LIN_CONST.GVFS_GENERATION == 1: if re.match( r"{server_share} \S+ {server_name}".format( **mount.settings), f): path = os.path.join(LIN_CONST.GVFS_DIR, f, mount.settings["server_subdir"]) else: if (re.match(r"^smb-share:", f) and re.search( r"domain={realm_domain}(,|$)".format(**mount.settings), f, flags=re.IGNORECASE) and re.search( r"server={server_name}(,|$)".format( **mount.settings), f) and re.search( r"share={server_share}(,|$)".format( **mount.settings), f) and re.search( r"user={realm_username}(,|$)".format( **mount.settings), f)): path = os.path.join(LIN_CONST.GVFS_DIR, f, mount.settings["server_subdir"]) if path is None: raise Exception("Error: Could not find the GVFS mountpoint.") else: path = mount.settings["local_path"] if LIN_CONST.CMD_OPEN is None: Output.warning( "Cannot open location '{}', xdg-open not found.".format(path)) return cmd = [s.format(path=path) for s in LIN_CONST.CMD_OPEN.split(" ")] Output.verbose("cmd: " + " ".join(cmd)) NonBlockingQtProcess( cmd, _cb, )
def cifs_post_umount(mount): """ Performs tasks when umount is done. May happen some seconds after cifs_umount is completed (OS) """ if mount.settings["Linux_CIFS_method"] == "gvfs": # 2) Remove symlink if mount.settings["Linux_gvfs_symlink"]: if (os.path.lexists(mount.settings["local_path"]) and not os.path.exists(mount.settings["local_path"])): os.unlink(mount.settings["local_path"]) else: # "mount.cifs" # 2) Remove mount dir try: if (os.path.exists(mount.settings["local_path"]) and os.listdir(mount.settings["local_path"]) == []): os.rmdir(mount.settings["local_path"]) except OSError as e: Output.warning("Could not rmdir : {0}".format(e))
def load_config(self): self.cfg = conf.get_config() self.networks_check = Networks_Check(self.cfg, self) Output.verbose(pprint.pformat(self.cfg)) # Delete previous config for entry in self.entries: entry.destroy() self.entries = [] for msg in self.msgs: msg.destroy() self.msgs = [] # Instanciate new config objects entries_added = [] for entry_name in self.cfg["global"].get("entries_order", ()): if entry_name in self.cfg["CIFS_mount"]: entry = CIFS_Mount(self, self.cfg, entry_name, self.key_chain) self.entries.append(UI_Mount_Entry(self, entry)) entries_added.append(entry_name) else: Output.warning("Entry not found '{0}'.".format(entry_name)) for entry_name in self.cfg.get("CIFS_mount", {}): if entry_name not in entries_added: entry = CIFS_Mount(self, self.cfg, entry_name, self.key_chain) self.entries.append(UI_Mount_Entry(self, entry)) if CONST.OS_SYS == "Windows": self.windows_letter_manager.refresh_letters() for entry in self.entries: self.entries_layer.addLayout(entry) for msg in self.cfg["msg"]: msg_item = UI_Msg(self.cfg["msg"][msg]["text"], self.cfg["msg"][msg]["icon"]) self.msgs.append(msg_item) self.msgs_layout.addWidget(msg_item)
def cifs_mount(mount): # 1) Make mountpoint if not os.path.exists(mount.settings["local_path"]): try: os.makedirs(mount.settings["local_path"]) except OSError: pass if not os.path.isdir(mount.settings["local_path"]): raise Exception("Error while creating dir : %s" % mount.settings["local_path"]) # 2) Mount s_path = re.sub(r" ", r"%20", mount.settings["server_path"]) cmd = [ OSX_CONST.CMD_MOUNT_SMBFS, r"//{realm_domain}\;{realm_username}@{server_name}/{s_path}".format( s_path=s_path, **mount.settings), "\"{local_path}\"".format(**mount.settings) ] Output.verbose("cmd: " + " ".join(cmd)) for _ in range(3): # 3 attempts (for passwords mistyped) process_meta = { "was_cancelled": False, } try: (output, exit_status) = pexpect.runu( command=" ".join(cmd), events={ "(?i)password": pexpect_ask_password, }, extra_args={ "auth_realms": [(r"Password", mount.settings["realm"])], "key_chain": mount.key_chain, "process_meta": process_meta, }, env=dict(os.environ, LANG="C", LC_ALL="C"), withexitstatus=True, timeout=CONST.MOUNT_TIMEOUT, ) except pexpect.ExceptionPexpect as e: raise Exception("Error while mounting : %s" % e.value) if exit_status == 0: mount.key_chain.ack_password(mount.settings["realm"]) return True elif exit_status == 77: # Bad password mount.key_chain.invalidate_if_no_ack_password( mount.settings["realm"]) else: mount.key_chain.invalidate_if_no_ack_password( mount.settings["realm"]) if process_meta["was_cancelled"]: if (os.path.isdir(mount.settings["local_path"]) and os.listdir(mount.settings["local_path"]) == []): try: os.rmdir(mount.settings["local_path"]) except OSError as e: Output.warning("Could not rmdir : {}".format(e)) return False else: mount.ui.notify_user("Mount failure :<br>{}".format(output)) return False mount.ui.notify_user("Mount failure")
def cifs_mount(mount): if mount.settings["Linux_CIFS_method"] == "gvfs": # 1) Remove broken symlink or empty dir if mount.settings["Linux_gvfs_symlink"]: if (os.path.lexists(mount.settings["local_path"]) and not os.path.exists(mount.settings["local_path"])): os.unlink(mount.settings["local_path"]) if (os.path.isdir(mount.settings["local_path"]) and os.listdir(mount.settings["local_path"]) == []): os.rmdir(mount.settings["local_path"]) if os.path.exists(mount.settings["local_path"]): mount.ui.notify_user("Error : Path {} already exists".format( mount.settings["local_path"])) return False # 2) Mount share = re.sub(r" ", r"%20", mount.settings["server_share"]) if LIN_CONST.GVFS_GENERATION <= 3: cmd = [ LIN_CONST.CMD_GVFS_MOUNT, r"smb://{realm_domain}\;{realm_username}@{server_name}/{share}" .format(share=share, **mount.settings) ] else: cmd = [ LIN_CONST.CMD_GIO_MOUNT, "mount", r"smb://{realm_domain}\;{realm_username}@{server_name}/{share}" .format(share=share, **mount.settings) ] Output.verbose("cmd: " + " ".join(cmd)) process_meta = { "was_cancelled": False, } try: (output, exit_status) = pexpect.runu( command=" ".join(cmd), events={ "Password:"******"auth_realms": [(r"Password:"******"realm"])], "key_chain": mount.key_chain, "process_meta": process_meta, }, env=dict(os.environ, LANG="C", LC_ALL="C"), withexitstatus=True, timeout=CONST.MOUNT_TIMEOUT, ) except pexpect.ExceptionPexpect as exc: mount.ui.notify_user("Error while mounting :<br>{}".format( exc.value)) return False if "error" not in output.lower() and exit_status == 0: mount.key_chain.ack_password(mount.settings["realm"]) else: mount.key_chain.invalidate_if_no_ack_password( mount.settings["realm"]) if process_meta["was_cancelled"]: return False else: mount.ui.notify_user("Mount failure :<br>{}".format(output)) return False cifs_uncache_is_mounted(mount) else: # "mount.cifs" if LIN_CONST.CMD_MOUNT_CIFS is None: mount.ui.notify_user( "Error missing binary <b>mount.cifs</b>. On Ubuntu you can install it with <i>sudo apt-get install cifs-utils</i>" ) return False # 1) Make mount dir (remove broken symlink if needed) if (os.path.lexists(mount.settings["local_path"]) and not os.path.exists(mount.settings["local_path"])): os.unlink(mount.settings["local_path"]) if not os.path.exists(mount.settings["local_path"]): try: os.makedirs(mount.settings["local_path"]) except OSError: pass if (os.path.islink(mount.settings["local_path"]) or not os.path.isdir(mount.settings["local_path"])): mount.ui.notify_user("Error while creating dir : %s" % mount.settings["local_path"]) return False # 2) Mount s_path = re.sub(" ", "\\ ", mount.settings["server_path"]) cmd = [ LIN_CONST.CMD_MOUNT_CIFS, "//{server_name}/{s_path}", "{local_path}", "-o", "user={realm_username},domain={realm_domain}," "uid={local_uid},gid={local_gid}," "file_mode={Linux_mountcifs_filemode}," "dir_mode={Linux_mountcifs_filemode}," "{Linux_mountcifs_options}" ] if CONST.LOCAL_UID != 0: cmd.insert(0, "sudo") cmd = [s.format(s_path=s_path, **mount.settings) for s in cmd] Output.verbose("cmd: " + " ".join(cmd)) # for i in xrange(3): # 3 attempts (for passwords mistyped) process_meta = { "was_cancelled": False, } (output, exit_status) = pexpect.runu( command=" ".join(cmd), events={ "(?i)password": pexpect_ask_password, }, extra_args={ "auth_realms": [(r"\[sudo\] password", "sudo"), (r"Password", mount.settings["realm"])], "key_chain": mount.key_chain, "process_meta": process_meta, }, env=dict(os.environ, LANG="C", LC_ALL="C"), withexitstatus=True, timeout=CONST.MOUNT_TIMEOUT, ) if exit_status == 0: mount.key_chain.ack_password("sudo") mount.key_chain.ack_password(mount.settings["realm"]) else: mount.key_chain.invalidate_if_no_ack_password("sudo") mount.key_chain.invalidate_if_no_ack_password( mount.settings["realm"]) if process_meta["was_cancelled"]: if (os.path.exists(mount.settings["local_path"]) and os.listdir(mount.settings["local_path"]) == []): try: os.rmdir(mount.settings["local_path"]) except OSError as e: Output.warning("Could not rmdir : {0}".format(e)) else: mount.ui.notify_user("Mount failure : {}".format(output)) return False return True
def read_config_source(src): """ Readlines on src [global] username = bancal Linux_CIFS_method = gvfs Linux_mountcifs_filemode = 0770 Linux_mountcifs_dirmode = 0770 Linux_mountcifs_options = rw,nobrl,noserverino,iocharset=utf8,sec=ntlm Linux_gvfs_symlink = true [msg] name = name this msg text = This is a warning notification icon = warning [network] name = Internet ping = www.epfl.ch ping = enacit.epfl.ch error_msg = Error, you are not connected to the network. You won't be able to mount this resource. [network] name = Epfl parent = Internet cifs = files0.epfl.ch cifs = files1.epfl.ch cifs = files8.epfl.ch cifs = files9.epfl.ch cifs = enac1files.epfl.ch error_msg = Error, you are not connected to the intranet of EPFL. Run a VPN client to be able to mount this resource. [realm] name = EPFL domain = INTRANET username = bancal [CIFS_mount] name = private label = bancal@files9 require_network = Epfl realm = EPFL server_name = files9.epfl.ch server_path = data/bancal local_path = {MNT_DIR}/bancal_on_files9 # {MNT_DIR} # {HOME_DIR} # {DESKTOP_DIR} # {LOCAL_USERNAME} # {LOCAL_GROUPNAME} bookmark = false # default : False Linux_CIFS_method = gvfs # mount.cifs : Linux's mount.cifs (requires sudo ability) # gvfs : Linux's gvfs-mount Linux_mountcifs_filemode = 0770 Linux_mountcifs_dirmode = 0770 Linux_mountcifs_options = rw,nobrl,noserverino,iocharset=utf8,sec=ntlm Linux_gvfs_symlink = yes # Enables the creation of a symbolic link to "local_path" after mount with gvfs method. # default : False Windows_letter = Z: # Drive letter to use for the mount And return cfg as {'CIFS_mount': { 'private': { 'Linux_CIFS_method': 'gvfs', 'Linux_gvfs_symlink': True, 'Linux_mountcifs_dirmode': '0770', 'Linux_mountcifs_filemode': '0770', 'Linux_mountcifs_options': 'rw,nobrl,noserverino,iocharset=utf8,sec=ntlm', 'Windows_letter': 'Z:', 'label': 'bancal@files9', 'local_path': '{MNT_DIR}/bancal_on_files9', 'realm': 'EPFL', 'server_name': 'files9.epfl.ch', 'server_path': 'data/bancal', 'bookmark': False, 'require_network': 'Epfl'}}, 'network': { 'Internet': { 'ping': ['www.epfl.ch', 'enacit.epfl.ch'], 'error_msg': 'Error, you are not connected to the network. You won't be able to mount this resource.' }, 'Epfl': { 'ping': ['files0.epfl.ch', 'files1.epfl.ch', 'files8.epfl.ch', 'files9.epfl.ch'], 'parent': 'Internet', 'error_msg': 'Error, you are not connected to the intranet of EPFL. Run a VPN client to be able to mount this resource.' } } 'global': { 'username': '******', 'Linux_CIFS_method': 'gvfs', 'Linux_gvfs_symlink': True, 'Linux_mountcifs_dirmode': '0770', 'Linux_mountcifs_filemode': '0770', 'Linux_mountcifs_options': 'rw,nobrl,noserverino,iocharset=utf8,sec=ntlm'}, 'realm': { 'EPFL': { 'domain': 'INTRANET', 'username': '******'}}} If >50% of the lines have unexpected content ... then raise ConfigException() """ def save_current_section(): try: name = current_section_values["name"] del(current_section_values["name"]) cfg.setdefault(current_section_name, {}) cfg[current_section_name].setdefault(name, {}) cfg[current_section_name][name].update(current_section_values) except KeyError: Output.error("Expected name option not found at line {}. Skipping that section.".format(section_line_nb)) multi_entries_sections = ("msg", "CIFS_mount", "realm", "network") allowed_options = { "global": ( "username", "entries_order", "require_network", "realm", "Linux_CIFS_method", "Linux_mountcifs_filemode", "Linux_mountcifs_dirmode", "Linux_mountcifs_options", "Linux_gvfs_symlink", ), "msg": ( "name", "text", "icon", ), "CIFS_mount": ( "name", "label", "require_network", "realm", "unc", "server_name", "server_path", "local_path", "bookmark", "Linux_CIFS_method", "Linux_mountcifs_filemode", "Linux_mountcifs_dirmode", "Linux_mountcifs_options", "Linux_gvfs_symlink", "Windows_letter", ), "realm": ( "name", "domain", "username", ), "network": ( "name", "parent", "ping", "cifs", "error_msg", ) } cfg = {} current_section_name = "" current_section_values = {} line_nb = 0 section_line_nb = 0 nb_unexpected_lines = 0 for line in src.readlines(): if type(line) == bytes: line = bytes_decode(line) line_nb += 1 l = line l = re.sub(r"#.*", "", l) # remove comments l = l.strip() # remove white spaces if l == "": continue # Output.debug(l) # New section if l.startswith("["): try: new_section = re.match(r"\[(\S+)\]$", l).groups()[0] except AttributeError: Output.error("Unexpected content at line {}:\n{}".format(line_nb, line)) nb_unexpected_lines += 1 continue if current_section_name in multi_entries_sections and current_section_values != {}: # Save previous section content save_current_section() if new_section in allowed_options: current_section_name = new_section current_section_values = {} section_line_nb = line_nb else: Output.error("Unexpected section name '{}' at line {}:\n{}".format(new_section, line_nb, line)) current_section_name = "" nb_unexpected_lines += 1 continue if current_section_name == "": Output.error("Unexpected content at line {}:\n{}".format(line_nb, line)) nb_unexpected_lines += 1 continue # New option try: k, v = re.match(r"([^=]*)=(.*)", l).groups() k, v = k.strip(), v.strip() except AttributeError: nb_unexpected_lines += 1 continue if k not in allowed_options[current_section_name]: Output.error("Unexpected option at line {}:\n{}".format(line_nb, line)) nb_unexpected_lines += 1 continue try: if current_section_name in multi_entries_sections: # This is a multi entries section type if current_section_name == "network" and k == "ping": # network.ping is a list current_section_values.setdefault(k, []) current_section_values[k].append(validate_value(k, v)) elif current_section_name == "network" and k == "cifs": # network.cifs is a list current_section_values.setdefault(k, []) current_section_values[k].append(validate_value(k, v)) else: # other are literals current_section_values[k] = validate_value(k, v) else: # This is a single entry section type cfg.setdefault(current_section_name, {})[k] = validate_value(k, v) except ConfigException as e: Output.error(str(e)) # Output.debug("'{}' = '{}'".format(k, v)) if current_section_name in multi_entries_sections and current_section_values != {}: # Save last section content save_current_section() if nb_unexpected_lines > (line_nb / 2): Output.warning("Found {}/{} ({}%) unexpected lines. Skipping this source.".format(nb_unexpected_lines, line_nb, nb_unexpected_lines*100.0/line_nb)) raise ConfigException("Too many unexpected lines found. Skipping this source.") elif nb_unexpected_lines > 0: Output.warning("Found {}/{} ({}%) unexpected lines.".format(nb_unexpected_lines, line_nb, nb_unexpected_lines*100.0/line_nb)) return cfg
def get_config(): # Create cache_dir if not already existent if not os.path.exists(CONST.USER_CACHE_DIR): os.makedirs(CONST.USER_CACHE_DIR) # HARD CODED CONFIG default_config = { 'global': { 'Linux_CIFS_method': 'gvfs', 'Linux_gvfs_symlink': False, 'Linux_mountcifs_dirmode': '0770', 'Linux_mountcifs_filemode': '0770', 'Linux_mountcifs_options': 'rw,nobrl,noserverino,iocharset=utf8,sec=ntlm'}, 'CIFS_mount': {}, 'network': {}, 'realm': {}, 'msg': {}, } cfg = default_config # USER CONFIG -> get only username from [global] user_config = None username = None try: with open(CONST.USER_CONF_FILE, "r") as f: user_config = read_config_source(f) username = user_config.get("global", {}).get("username", None) if username is not None: Output.verbose("Loaded username '{}' from User context. ({})".format(username, CONST.USER_CONF_FILE)) else: Output.normal("Username not found in User context. ({})".format(CONST.USER_CONF_FILE)) except FileNotFoundException: Output.normal("Username not found in User context. ({})".format(CONST.USER_CONF_FILE)) if username is None: if CONST.AD_USERNAME is not None: username = CONST.AD_USERNAME Output.verbose("Loaded username '{}' from environment variables (user in domain '{}').".format(username, CONST.AD_DOMAIN)) # Save to config file and reload it for after save_username(username) with open(CONST.USER_CONF_FILE, "r") as f: user_config = read_config_source(f) else: Output.normal("Username not found in environment variables (user not in a domain).") # ENACDRIVE SERVER CONFIG (included cache function) if username is not None: config_url = CONST.CONFIG_URL.format(username=username) cache_filename = os.path.join(CONST.USER_CACHE_DIR, hashlib.md5(config_url.encode()).hexdigest()) try: with urllib.request.urlopen(config_url, timeout=CONST.URL_TIMEOUT) as response: lines = [bytes_decode(l) for l in response.readlines()] # Output.debug("get_config {} : {}".format(config_url, lines)) s_io = io.StringIO("".join(lines)) enacdrives_config = read_config_source(s_io) merge_configs(cfg, enacdrives_config) s_io.seek(0) with open(cache_filename, "w") as f: f.writelines(s_io.readlines()) Output.verbose("Loaded config from ENACdrives server ({})".format(config_url)) except (socket.timeout, urllib.error.URLError, ConfigException) as e: Output.warning("Could not load config ENACdrives server. ({})".format(config_url)) Output.warning("Got error : {}".format(e)) try: with open(cache_filename, "r") as f: cached_config = read_config_source(f) merge_configs(cfg, cached_config) Output.normal("Loaded config from cache file. ({})".format(cache_filename)) except FileNotFoundException: Output.warning("Could not load config from cache file. ({})".format(cache_filename)) else: Output.normal("Skipping config from ENACdrives server (no username).") # SYSTEM CONFIG try: with open(CONST.SYSTEM_CONF_FILE, "r") as f: system_config = read_config_source(f) merge_configs(cfg, system_config) Output.verbose("Loaded config from System context. ({})".format(CONST.SYSTEM_CONF_FILE)) except FileNotFoundException: Output.normal("No config found from System context. ({})".format(CONST.SYSTEM_CONF_FILE)) # USER CONFIG if user_config is not None: merge_configs(cfg, user_config) Output.verbose("Loaded config from User context. ({})".format(CONST.USER_CONF_FILE)) else: Output.normal("No config found from User context. ({})".format(CONST.USER_CONF_FILE)) cfg = validate_config(cfg) return cfg
def run(self): enacit1logs_notify(self) self.show_msgs() if self.returncode is not None: return self.returncode if self.args.add_bookmark is not None: self.execution_status(0) for m_name in self.args.add_bookmark: if m_name in self.cfg["CIFS_mount"]: conf.save_bookmark(m_name, True) self.cfg["CIFS_mount"][m_name]["entry"].settings[ "bookmark"] = True else: self.execution_status(1) Output.warning( "Skipping to add bookmark {}: Unknown entry.".format( m_name)) if self.args.rm_bookmark is not None: self.execution_status(0) for m_name in self.args.rm_bookmark: if m_name in self.cfg["CIFS_mount"]: conf.save_bookmark(m_name, False) self.cfg["CIFS_mount"][m_name]["entry"].settings[ "bookmark"] = False else: self.execution_status(1) Output.warning( "Skipping to rm bookmark {}: Unknown entry.".format( m_name)) if self.returncode is not None: self.show_summary() return self.returncode if self.args.summary: self.execution_status(0) self.show_summary() return self.returncode which_entries = [] if self.args.all: self.execution_status(0) for entry in self.entries: which_entries.append(entry) if self.args.named is not None: self.execution_status(0) for m_name in self.args.named: if m_name in self.cfg["CIFS_mount"]: which_entries.append( self.cfg["CIFS_mount"][m_name]["entry"]) else: self.execution_status(1) Output.warning( "Skipping named '{}'. Unknown entry.".format(m_name)) if self.args.bookmarked: self.execution_status(0) for entry in self.entries: if entry.settings["bookmark"]: which_entries.append(entry) if len(which_entries) == 0 and self.args.username is None: self.execution_status(1) Output.warning("No entry selected to (u)mount.") expected_status = {} if self.args.umount: umount_list = [] for entry in which_entries: if entry.is_mounted(): umount_list.append(entry) for entry in umount_list: required_network = entry.settings.get("require_network") if required_network is not None: net_status, net_msg = self.networks_check.get_status( required_network) if not net_status: print("! Skip Umounting {} : {}".format( entry.settings["name"], net_msg)) self.execution_status(1) continue print("- Umounting {}".format(entry.settings["name"])) entry.umount() expected_status[entry.settings["name"]] = False else: mount_list = [] for entry in which_entries: if not entry.is_mounted(): mount_list.append(entry) for entry in mount_list: required_network = entry.settings.get("require_network") if required_network is not None: net_status, net_msg = self.networks_check.get_status( required_network) if not net_status: print("! Skip Mounting {} : {}".format( entry.settings["name"], net_msg)) self.execution_status(1) continue print("+ Mounting {}".format(entry.settings["name"])) entry.mount() expected_status[entry.settings["name"]] = True self.show_summary(expected_status) return self.returncode
def show_summary(self, expected_status=None): if expected_status is None: expected_status = {} special_chars = { "unicode": { "stared": "\u272F", "unstared": " ", # "\u274F" # "\u274d" "no_network": "\u2757", "mounted": "\u2713", "umounted": "\u2717", }, "ascii": { "stared": "*", "unstared": " ", # "\u274F" # "\u274d" "no_network": "!", "mounted": "v", "umounted": "x", }, } display_mode = "unicode" # may be switched to "ascii" if necessary def is_bookmarked(entry): if entry.settings["bookmark"]: return "\033[01;33m{}\033[00m".format( special_chars[display_mode]["stared"]) else: return "{}".format(special_chars[display_mode]["unstared"]) def is_mounted(entry): required_network = entry.settings.get("require_network") if required_network is not None: net_status, net_msg = self.networks_check.get_status( required_network) if not net_status: return "\033[01;31m{}\033[00m {}".format( special_chars[display_mode]["no_network"], net_msg) if entry.is_mounted(): return "\033[01;32m{}\033[00m on {}".format( special_chars[display_mode]["mounted"], entry.settings["local_path"]) else: return "\033[01;31m{}\033[00m".format( special_chars[display_mode]["umounted"]) if self.cfg["global"].get("username") is None: Output.cli("\033[01;37m*** ENACdrives entries summary ***\033[00m") else: Output.cli( "\033[01;37m*** ENACdrives entries summary for user {} ***\033[00m" .format(self.cfg["global"]["username"])) name_width = 1 label_width = 1 for entry in self.entries: name_width = max(name_width, len(entry.settings["name"])) label_width = max(label_width, len(entry.settings["label"])) for entry in self.entries: if expected_status.get(entry.settings["name"]) is not None: iteration_max = 3 while expected_status[ entry.settings["name"]] != entry.is_mounted(): time.sleep(0.5) entry.uncache_is_mounted() iteration_max -= 1 if iteration_max <= 0: break try: Output.cli( "{} \033[00;37m{:<{name_width}}\033[00m \033[01;37m{:<{label_width}}\033[00m {}" .format(is_bookmarked(entry), entry.settings["name"], entry.settings["label"], is_mounted(entry), name_width=name_width, label_width=label_width)) except UnicodeEncodeError: # UnicodeEncodeError: 'ascii' codec can't encode character '\u2717' in position 86: ordinal not in range(128) display_mode = "ascii" Output.cli( "{} \033[00;37m{:<{name_width}}\033[00m \033[01;37m{:<{label_width}}\033[00m {}" .format(is_bookmarked(entry), entry.settings["name"], entry.settings["label"], is_mounted(entry), name_width=name_width, label_width=label_width)) if len(self.entries) == 0: Output.cli("No entry found.") if self.cfg["global"].get("username") is None: Output.warning( "username not defined. You can set it with argument --username=username" ) self.execution_status(1)