Пример #1
0
class NM08ProfileManager(NMProfileManager):
    """I manage profiles in the system"""

    def __init__(self):
        super(NM08ProfileManager, self).__init__()

        self.helper = GConfHelper()
        self.gpath = GCONF_PROFILES_BASE

        # connect to signals
        self._connect_to_signals()

    def _init_nm_manager(self):
        obj = self.bus.get_object(NM08_USER_SETTINGS, NM08_SYSTEM_SETTINGS_OBJ)
        self.nm_manager = dbus.Interface(obj, NM08_SYSTEM_SETTINGS)

    def _connect_to_signals(self):
        self.nm_manager.connect_to_signal("NewConnection",
                       self._on_new_nm_profile, NM08_SYSTEM_SETTINGS)

    def _on_new_nm_profile(self, opath):
        obj = self.bus.get_object(NM08_USER_SETTINGS, opath)
        props = obj.GetSettings(dbus_interface=NM08_SYSTEM_SETTINGS_CONNECTION)
        # filter out non GSM profiles
        if props['connection']['type'] == 'gsm':
            self._add_nm_profile(obj, props)

    def _add_nm_profile(self, obj, props):
        uuid = props['connection']['uuid']
        assert uuid not in self.nm_profiles, "Adding twice the same profile?"
        self.nm_profiles[uuid] = obj

        # handle when a NM profile has been externally added
        if uuid not in self.profiles:
            try:
                profile = self._get_profile_from_nm_connection(uuid)
            except ex.ProfileNotFoundError:
                log.msg("Removing non existing NM profile %s" % uuid)
                del self.nm_profiles[uuid]
            else:
                self.profiles[uuid] = profile
                self.NewConnection(profile.opath)

    def _get_next_free_gpath(self):
        """Returns the next unused slot of /system/networking/connections"""
        all_dirs = list(self.helper.client.all_dirs(self.gpath))
        try:
            max_index = max(map(int, [d.split('/')[-1] for d in all_dirs]))
        except ValueError:
            # /system/networking/connections is empty
            max_index = -1

        index = 0 if not all_dirs else max_index + 1
        return os.path.join(self.gpath, str(index))

    def _get_profile_from_nm_connection(self, uuid):
        for gpath in self.helper.client.all_dirs(self.gpath):
            # filter out wlan connections
            if self.helper.client.dir_exists(os.path.join(gpath, 'gsm')):
                path = os.path.join(gpath, 'connection', 'uuid')
                value = self.helper.client.get(path)
                if value and uuid == self.helper.get_value(value):
                    return self._get_profile_from_gconf_path(gpath)

        msg = "NM profile identified by uuid %s could not be found"
        raise ex.ProfileNotFoundError(msg % uuid)

    def _get_profile_from_gconf_path(self, gconf_path):
        props = defaultdict(dict)
        for path in self.helper.client.all_dirs(gconf_path):
            for entry in self.helper.client.all_entries(path):
                section, key = entry.get_key().split('/')[-2:]
                value = entry.get_value()
                if value is not None:
                    props[section][key] = self.helper.get_value(value)

        props = transpose_from_NM(props)
        uuid = props['connection']['uuid']
        try:
            return NM08Profile(self.get_next_dbus_opath(),
                               self.nm_profiles[uuid],
                               gconf_path, props, self)
        except KeyError:
            raise ex.ProfileNotFoundError("Profile '%s' could not "
                                          "be found" % uuid)

    def _do_set_profile(self, path, props):
        props = transpose_to_NM(props)

        for key in props:
            for name in props[key]:
                value = props[key][name]
                _path = os.path.join(path, key, name)

                self.helper.set_value(_path, value)

        self.helper.client.notify(path)
        self.helper.client.suggest_sync()

    def add_profile(self, props):
        """Adds a profile with settings ``props``"""
        gconf_path = self._get_next_free_gpath()
        self._do_set_profile(gconf_path, props)
        # the rest will be handled by _on_new_nm_profile

    def get_profiles(self):
        """Returns all the profiles in the system"""
        if not self.nm_profiles:
            # cache existing profiles
            map(self._on_new_nm_profile, self.nm_manager.ListConnections())

        if not self.profiles:
            for path in self.helper.client.all_dirs(self.gpath):
                # filter out wlan connections
                if self.helper.client.dir_exists(os.path.join(path, 'gsm')):
                    # profile = self._get_profile_from_gconf_path(path)
                    # uuid = profile.get_settings()['connection']['uuid']
                    # self.profiles[uuid] = profile
                    try:
                        profile = self._get_profile_from_gconf_path(path)
                        uuid = profile.get_settings()['connection']['uuid']
                        self.profiles[uuid] = profile
                    except ex.ProfileNotFoundError:
                        pass

        return self.profiles.values()

    def remove_profile(self, profile):
        """Removes profile ``profile``"""
        uuid = profile.get_settings()['connection']['uuid']
        assert uuid in self.profiles, "Removing a non-existent profile?"

        self.profiles[uuid].remove()
        del self.profiles[uuid]

        # as NetworkManager listens for GConf-DBus signals, we don't need
        # to manually sync it
        if uuid in self.nm_profiles:
            del self.nm_profiles[uuid]

    def update_profile(self, profile, props):
        """Updates ``profile`` with settings ``props``"""
        uuid = profile.get_settings()['connection']['uuid']
        assert uuid in self.profiles, "Updating a non-existent profile?"

        _profile = self.profiles[uuid]
        _profile.update(props)

        props = transpose_to_NM(props, new=False)

        if uuid in self.nm_profiles:
            obj = self.nm_profiles[uuid]
            obj.Update(props,
                       dbus_interface=NM08_SYSTEM_SETTINGS_CONNECTION)
Пример #2
0
class NM08Profile(NMProfile):

    def __init__(self, opath, nm_obj, gpath, props, manager):
        super(NM08Profile, self).__init__(opath, nm_obj, props, manager)

        self.helper = GConfHelper()
        self.gpath = gpath

        from wader.common.backends import get_backend
        keyring = get_backend().get_keyring()
        self.secrets = ProfileSecrets(self, keyring)

        self._connect_to_signals()

    def _on_removed(self):
        log.msg("Profile %s has been removed externally" % self.opath)
        self.manager.remove_profile(self)

    def _on_updated(self, props):
        log.msg("Profile %s has been updated" % self.opath)
        self.update(props)

    def _write(self, props):
        self.props = props

        props = transpose_to_NM(props)

        for key, value in props.iteritems():
            new_path = os.path.join(self.gpath, key)
            self.helper.set_value(new_path, value)

        self.helper.client.notify(self.gpath)
        self.helper.client.suggest_sync()

    def _load_info(self):
        props = {}

        if self.helper.client.dir_exists(self.gpath):
            self._load_dir(self.gpath, props)

        self.props = transpose_from_NM(props)

    def _load_dir(self, directory, info):
        for entry in self.helper.client.all_entries(directory):
            key = os.path.basename(entry.key)
            info[key] = self.helper.get_value(entry.value)

        for _dir in self.helper.client.all_dirs(directory):
            dirname = os.path.basename(_dir)
            info[dirname] = {}
            self._load_dir(_dir, info[dirname])

    def update(self, props):
        """Updates the profile with settings ``props``"""
        self._write(props)
        self._load_info()
        self.Updated(patch_list_signature(self.props))

    def remove(self):
        """Removes the profile"""
        from gconf import UNSET_INCLUDING_SCHEMA_NAMES
        self.helper.client.recursive_unset(self.gpath,
                                           UNSET_INCLUDING_SCHEMA_NAMES)
        # emit Removed and unexport from DBus
        self.Removed()
        self.remove_from_connection()