Exemple #1
0
    def set_profile(self, profile_name, save_instantly=False):
        if self.is_running():
            raise TunedException(
                self._notify_profile_changed(
                    profile_name, False,
                    "Cannot set profile while the daemon is running."))

        if profile_name == "" or profile_name is None:
            self._profile = None
        elif profile_name not in self.profile_loader.profile_locator.get_known_names(
        ):

            raise TunedException(
                self._notify_profile_changed(
                    profile_name, False,
                    "Requested profile '%s' doesn't exist." % profile_name))
        else:
            try:
                self._profile = self._profile_loader.load(profile_name)
            except InvalidProfileException as e:
                raise TunedException(
                    self._notify_profile_changed(
                        profile_name, False,
                        "Cannot load profile '%s': %s" % (profile_name, e)))

        if save_instantly:
            if profile_name is None:
                profile_name = ""
            self._save_active_profile(profile_name)
Exemple #2
0
	def get_active_profile(self):
		profile_name = ""
		mode = ""
		try:
			with open(consts.ACTIVE_PROFILE_FILE, "r") as f:
				profile_name = f.read().strip()
		except IOError as e:
			if e.errno != errno.ENOENT:
				raise TunedException("Failed to read active profile: %s" % e)
		except (OSError, EOFError) as e:
			raise TunedException("Failed to read active profile: %s" % e)
		try:
			with open(consts.PROFILE_MODE_FILE, "r") as f:
				mode = f.read().strip()
				if mode not in ["", consts.ACTIVE_PROFILE_AUTO, consts.ACTIVE_PROFILE_MANUAL]:
					raise TunedException("Invalid value in file %s." % consts.PROFILE_MODE_FILE)
		except IOError as e:
			if e.errno != errno.ENOENT:
				raise TunedException("Failed to read profile mode: %s" % e)
		except (OSError, EOFError) as e:
			raise TunedException("Failed to read profile mode: %s" % e)
		if mode == "":
			manual = None
		else:
			manual = mode == consts.ACTIVE_PROFILE_MANUAL
		if profile_name == "":
			profile_name = None
		return (profile_name, manual)
Exemple #3
0
    def _load_global_config(self, file_name=consts.GLOBAL_CONFIG_FILE):
        """
        Loads global configuration file.
        """

        try:
            config_parser = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'))
            config_parser.optionxform = str
            with open(file_name) as f:
                config_parser.read_string("[" + consts.MAGIC_HEADER_NAME + "]\n" + f.read(), file_name)
            config, functions = GlobalConfig.get_global_config_spec()
            for option in config_parser.options(consts.MAGIC_HEADER_NAME):
                if option in config:
                    try:
                        func = getattr(config_parser, functions[option])
                        config[option] = func(consts.MAGIC_HEADER_NAME, option)
                    except Error:
                        raise TunedException("Global TuneD configuration file '%s' is not valid."
                                             % file_name)
                else:
                    config[option] = config_parser.get(consts.MAGIC_HEADER_NAME, option, raw=True)
        except IOError as e:
            raise TunedException("Global TuneD configuration file '%s' not found."
                                  % file_name)
        except Error as e:
            raise TunedException("Error parsing global TuneD configuration file '%s'."
                                  % file_name)
        return config
    def _load_global_config(self, file_name=consts.GLOBAL_CONFIG_FILE):
        """
        Loads global configuration file.
        """

        try:
            config = ConfigObj.ConfigObj(file_name,
                                         configspec=global_config_spec,
                                         raise_errors=True,
                                         file_error=True,
                                         list_values=False,
                                         interpolation=False)
        except IOError as e:
            raise TunedException(
                "Global tuned configuration file '%s' not found." % file_name)
        except ConfigObj.ConfigObjError as e:
            raise TunedException(
                "Error parsing global tuned configuration file '%s'." %
                file_name)
        vdt = Validator()
        if not config.validate(vdt, copy=True):
            raise TunedException(
                "Global tuned configuration file '%s' is not valid." %
                file_name)
        return config
Exemple #5
0
    def _load_profiles(self, profile_names, manual):
        profile_names = profile_names or ""
        profile_list = profile_names.split()

        if self._post_loaded_profile:
            log.info("Using post-loaded profile '%s'" %
                     self._post_loaded_profile)
            profile_list = profile_list + [self._post_loaded_profile]
        for profile in profile_list:
            if profile not in self.profile_loader.profile_locator.get_known_names(
            ):
                errstr = "Requested profile '%s' doesn't exist." % profile
                self._notify_profile_changed(profile_names, False, errstr)
                raise TunedException(errstr)
        try:
            if profile_list:
                self._profile = self._profile_loader.load(profile_list)
            else:
                self._profile = None

            self._manual = manual
            self._active_profiles = profile_names.split()
        except InvalidProfileException as e:
            errstr = "Cannot load profile(s) '%s': %s" % (
                " ".join(profile_list), e)
            self._notify_profile_changed(profile_names, False, errstr)
            raise TunedException(errstr)
Exemple #6
0
    def set_profile(self, profile_names, manual, save_instantly=False):
        if self.is_running():
            raise TunedException(
                self._notify_profile_changed(
                    profile_names, False,
                    "Cannot set profile while the daemon is running."))

        if profile_names == "" or profile_names is None:
            self._profile = None
            self._manual = manual
        else:
            profile_list = profile_names.split()
            for profile in profile_list:
                if profile not in self.profile_loader.profile_locator.get_known_names(
                ):
                    raise TunedException(self._notify_profile_changed(\
                      profile_names, False,\
                      "Requested profile '%s' doesn't exist." % profile))
            try:
                self._profile = self._profile_loader.load(profile_names)
                self._manual = manual
            except InvalidProfileException as e:
                raise TunedException(
                    self._notify_profile_changed(
                        profile_names, False,
                        "Cannot load profile(s) '%s': %s" %
                        (profile_names, e)))

        if save_instantly:
            if profile_names is None:
                profile_names = ""
            self._save_active_profile(profile_names, manual)
Exemple #7
0
    def _daemonize_parent(self, parent_in_fd, child_out_fd):
        """
		Wait till the child signalizes that the initialization is complete by writing
		some uninteresting data into the pipe.
		"""
        os.close(child_out_fd)
        (read_ready, drop,
         drop) = select.select([parent_in_fd], [], [],
                               consts.DAEMONIZE_PARENT_TIMEOUT)

        if len(read_ready) != 1:
            os.close(parent_in_fd)
            raise TunedException(
                "Cannot daemonize, timeout when waiting for the child process."
            )

        response = os.read(parent_in_fd, 8)
        os.close(parent_in_fd)

        if len(response) == 0:
            raise TunedException(
                "Cannot daemonize, no response from child process received.")

        if response != ("%c" % True):
            raise TunedException(
                "Cannot daemonize, child process reports failure.")
Exemple #8
0
	def save_active_profile(self, profile_name, manual):
		try:
			with open(consts.ACTIVE_PROFILE_FILE, "w") as f:
				if profile_name is not None:
					f.write(profile_name + "\n")
		except (OSError,IOError) as e:
			raise TunedException("Failed to save active profile: %s" % e.strerror)
		try:
			with open(consts.PROFILE_MODE_FILE, "w") as f:
				mode = consts.ACTIVE_PROFILE_MANUAL if manual else consts.ACTIVE_PROFILE_AUTO
				f.write(mode + "\n")
		except (OSError,IOError) as e:
			raise TunedException("Failed to save profile mode: %s" % e.strerror)
Exemple #9
0
	def get_post_loaded_profile(self):
		profile_name = ""
		try:
			with open(consts.POST_LOADED_PROFILE_FILE, "r") as f:
				profile_name = f.read().strip()
		except IOError as e:
			if e.errno != errno.ENOENT:
				raise TunedException("Failed to read the active post-loaded profile: %s" % e)
		except (OSError, EOFError) as e:
			raise TunedException("Failed to read the active post-loaded profile: %s" % e)
		if profile_name == "":
			profile_name = None
		return profile_name
	def load_config(self, file_name = consts.GLOBAL_CONFIG_FILE):
		"""
		Loads global configuration file.
		"""
		log.debug("reading and parsing global configuration file '%s'" % consts.GLOBAL_CONFIG_FILE)
		try:
			self._cfg = ConfigObj(file_name, configspec = self.global_config_spec, raise_errors = True, \
				file_error = True, list_values = False, interpolation = False)
		except IOError as e:
			raise TunedException("Global tuned configuration file '%s' not found." % file_name)
		except ConfigObjError as e:
			raise TunedException("Error parsing global tuned configuration file '%s'." % file_name)
		vdt = Validator()
		if (not self._cfg.validate(vdt, copy=True)):
			raise TunedException("Global tuned configuration file '%s' is not valid." % file_name)
Exemple #11
0
    def _thread_code(self):
        if self._profile is None:
            raise TunedException(
                "Cannot start the daemon without setting a profile.")

        self._unit_manager.create(self._profile.units)
        self._save_active_profile(self._profile.name)
        self._unit_manager.start_tuning()
        self._profile_applied.set()
        log.info("static tuning from profile '%s' applied" %
                 self._profile.name)
        self._notify_profile_changed(self._profile.name, True, "OK")

        if self._daemon:
            # In python 2 interpreter with applied patch for rhbz#917709 we need to periodically
            # poll, otherwise the python will not have chance to update events / locks (due to GIL)
            # and e.g. DBus control will not work. The polling interval of 1 seconds (which is
            # the default) is still much better than 50 ms polling with unpatched interpreter.
            # For more details see tuned rhbz#917587.
            _sleep_cnt = self._sleep_cycles
            while not self._cmd.wait(self._terminate, self._sleep_interval):
                if self._dynamic_tuning:
                    _sleep_cnt -= 1
                    if _sleep_cnt <= 0:
                        _sleep_cnt = self._sleep_cycles
                        log.debug("updating monitors")
                        self._unit_manager.update_monitors()
                        log.debug("performing tunings")
                        self._unit_manager.update_tuning()

        self._profile_applied.clear()

        # wait for others to complete their tasks, use timeout 3 x sleep_interval to prevent
        # deadlocks
        i = 0
        while not self._cmd.wait(self._not_used,
                                 self._sleep_interval) and i < 3:
            i += 1

        # if terminating due to profile switch
        if self._terminate_profile_switch.is_set():
            full_rollback = True
        else:
            # with systemd it detects system shutdown and in such case it doesn't perform
            # full cleanup, if not shutting down it means that Tuned was explicitly
            # stopped by user and in such case do full cleanup, without systemd never
            # do full cleanup
            full_rollback = False
            retcode, out = self._cmd.execute(
                ["systemctl", "is-system-running"], no_errors=[0])
            if retcode >= 0:
                if out[:8] == "stopping":
                    log.info(
                        "terminating Tuned due to system shutdown / reboot")
                else:
                    log.info("terminating Tuned, rolling back all changes")
                    full_rollback = True
        if self._daemon:
            self._unit_manager.stop_tuning(full_rollback)
        self._unit_manager.destroy_all()
Exemple #12
0
	def attach_to_dbus(self, bus_name, object_name, interface_name):
		if self._dbus_exporter is not None:
			raise TunedException("DBus interface is already initialized.")

		self._dbus_exporter = exports.dbus.DBusExporter(bus_name, interface_name, object_name)
		exports.register_exporter(self._dbus_exporter)
		exports.register_object(self._controller)
Exemple #13
0
	def save_post_loaded_profile(self, profile_name):
		try:
			with open(consts.POST_LOADED_PROFILE_FILE, "w") as f:
				if profile_name is not None:
					f.write(profile_name + "\n")
		except (OSError,IOError) as e:
			raise TunedException("Failed to save the active post-loaded profile: %s" % e.strerror)
Exemple #14
0
    def _daemonize_child(self, pid_file, parent_in_fd, child_out_fd):
        """
		Finishes daemonizing process, writes a PID file and signalizes to the parent
		that the initialization is complete.
		"""
        os.close(parent_in_fd)

        os.chdir("/")
        os.setsid()
        os.umask(0)

        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0)
        except OSError as error:
            log.critical("cannot daemonize, fork() error: %s" % str(error))
            os.write(child_out_fd, "%c" % False)
            os.close(child_out_fd)
            raise TunedException("Cannot daemonize, second fork() failed.")

        si = file("/dev/null", "r")
        so = file("/dev/null", "a+")
        se = file("/dev/null", "a+", 0)
        os.dup2(si.fileno(), sys.stdin.fileno())
        os.dup2(so.fileno(), sys.stdout.fileno())
        os.dup2(se.fileno(), sys.stderr.fileno())

        self.write_pid_file(pid_file)

        log.debug("successfully daemonized")
        os.write(child_out_fd, "%c" % True)
        os.close(child_out_fd)
Exemple #15
0
    def set_profile(self, profile_names, manual):
        if self.is_running():
            errstr = "Cannot set profile while the daemon is running."
            self._notify_profile_changed(profile_names, False, errstr)
            raise TunedException(errstr)

        self._load_profiles(profile_names, manual)
Exemple #16
0
    def daemonize(self, pid_file=consts.PID_FILE):
        """
		Daemonizes the application. In case of failure, TunedException is raised
		in the parent process. If the operation is successfull, the main process
		is terminated and only child process returns from this method.
		"""
        parent_child_fds = os.pipe()
        try:
            child_pid = os.fork()
        except OSError as error:
            os.close(parent_child_fds[0])
            os.close(parent_child_fds[1])
            raise TunedException("Cannot daemonize, fork() failed.")

        try:
            if child_pid > 0:
                self._daemonize_parent(*parent_child_fds)
                sys.exit(0)
            else:
                self._daemonize_child(pid_file, *parent_child_fds)
        except:
            # pass exceptions only into parent process
            if child_pid > 0:
                raise
            else:
                sys.exit(1)
Exemple #17
0
 def _set_post_loaded_profile(self, profile_name):
     if not profile_name:
         self._post_loaded_profile = None
     elif len(profile_name.split()) > 1:
         errstr = "Whitespace is not allowed in profile names; only a single post-loaded profile is allowed."
         raise TunedException(errstr)
     else:
         self._post_loaded_profile = profile_name
Exemple #18
0
    def set_profile(self, profile_name, save_instantly=False):
        if self.is_running():
            raise TunedException(
                "Cannot set profile while the daemon is running.")

        if profile_name == "" or profile_name is None:
            self._profile = None
        else:
            try:
                self._profile = self._profile_loader.load(profile_name)
            except:
                raise TunedException("Cannot load profile '%s'." %
                                     profile_name)

        if save_instantly:
            if profile_name is None:
                profile_name = ""
            self._save_active_profile(profile_name)
Exemple #19
0
	def set_all_profiles(self, active_profiles, manual, post_loaded_profile,
			     save_instantly=False):
		if self.is_running():
			errstr = "Cannot set profile while the daemon is running."
			self._notify_profile_changed(active_profiles, False,
						     errstr)
			raise TunedException(errstr)

		self._set_profile(active_profiles, manual)
		self._set_post_loaded_profile(post_loaded_profile)
		self._load_profiles()

		if save_instantly:
			self._save_active_profile(active_profiles, manual)
			self._save_post_loaded_profile(post_loaded_profile)
Exemple #20
0
    def _thread_code(self):
        if self._profile is None:
            raise TunedException(
                "Cannot start the daemon without setting a profile.")

        self._unit_manager.create(self._profile.units)
        self._save_active_profile(self._profile.name)
        self._unit_manager.start_tuning()

        self._terminate.clear()
        while not self._terminate.wait(10):
            log.debug("updating monitors")
            self._unit_manager.update_monitors()
            log.debug("performing tunings")
            self._unit_manager.update_tuning()

        self._unit_manager.stop_tuning()
        self._unit_manager.destroy_all()
Exemple #21
0
	def _thread_code(self):
		if self._profile is None:
			raise TunedException("Cannot start the daemon without setting a profile.")

		self._unit_manager.create(self._profile.units)
		self._save_active_profile(self._profile.name)
		self._unit_manager.start_tuning()
		self._profile_applied.set()
		log.info("static tuning from profile '%s' applied" % self._profile.name)
		self._notify_profile_changed(self._profile.name, True, "OK")

		if self._daemon:
			# In python 2 interpreter with applied patch for rhbz#917709 we need to periodically
			# poll, otherwise the python will not have chance to update events / locks (due to GIL)
			# and e.g. DBus control will not work. The polling interval of 1 seconds (which is
			# the default) is still much better than 50 ms polling with unpatched interpreter.
			# For more details see tuned rhbz#917587.
			_sleep_cnt = self._sleep_cycles
			while not self._cmd.wait(self._terminate, self._sleep_interval):
				if self._dynamic_tuning:
					_sleep_cnt -= 1
					if _sleep_cnt <= 0:
						_sleep_cnt = self._sleep_cycles
						log.debug("updating monitors")
						self._unit_manager.update_monitors()
						log.debug("performing tunings")
						self._unit_manager.update_tuning()

		self._profile_applied.clear()

		# wait for others to complete their tasks, use timeout 3 x sleep_interval to prevent
		# deadlocks
		i = 0
		while not self._cmd.wait(self._not_used, self._sleep_interval) and i < 3:
			i += 1

		# if terminating due to profile switch
		if self._terminate_profile_switch.is_set():
			profile_switch = True
		else:
			profile_switch = False
		if self._daemon:
			self._unit_manager.stop_tuning(profile_switch)
		self._unit_manager.destroy_all()