Example #1
0
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())
Example #2
0
    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)
Example #3
0
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))
Example #4
0
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,
    )
Example #5
0
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))
Example #6
0
    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)
Example #7
0
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")
Example #8
0
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
Example #9
0
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
Example #10
0
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
Example #11
0
    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
Example #12
0
    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)