various fixes
This commit is contained in:
parent
0932642421
commit
67e736a7f6
15 changed files with 447 additions and 48 deletions
2
AUTHORS
Normal file
2
AUTHORS
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
Phil Knirsch
|
||||
Jan Včelák
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
#
|
||||
# Author: Jan Vcelak <jvcelak@redhat.com>
|
||||
#
|
||||
|
||||
import controller
|
||||
import interfaces
|
||||
|
||||
def export(*args, **kwargs):
|
||||
"""Decorator, use to mark exportable methods."""
|
||||
def wrapper(method):
|
||||
method.export_params = [ args, kwargs ]
|
||||
return method
|
||||
return wrapper
|
||||
|
||||
def register_exporter(instance):
|
||||
if not isinstance(instance, interfaces.IExporter):
|
||||
raise Exception()
|
||||
ctl = controller.ExportsController.get_instance()
|
||||
return ctl.register_exporter(instance)
|
||||
|
||||
def register_object(instance):
|
||||
if not isinstance(instance, interfaces.IExportable):
|
||||
raise Exception()
|
||||
ctl = controller.ExportsController.get_instance()
|
||||
return ctl.register_object(instance)
|
||||
|
||||
def run():
|
||||
ctl = controller.ExportsController.get_instance()
|
||||
return ctl.run()
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#
|
||||
# Author: Jan Vcelak <jvcelak@redhat.com>
|
||||
#
|
||||
|
||||
class IExportable(object):
|
||||
pass
|
||||
|
||||
class IExporter(object):
|
||||
def export(self, method, in_signature, out_signature):
|
||||
# to be overriden by concrete implementation
|
||||
raise NotImplemented()
|
||||
|
||||
def serve(self):
|
||||
raise NotImplemented()
|
||||
2
src/__init__.py
Normal file
2
src/__init__.py
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
from logs import *
|
||||
from daemon import *
|
||||
|
|
@ -1,3 +1,20 @@
|
|||
# Copyright (C) 2008-2011 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import os
|
||||
import exports
|
||||
import exports.dbus
|
||||
|
|
@ -10,10 +27,9 @@ class Controller(exports.interfaces.IExportable):
|
|||
def __init__(self):
|
||||
super(self.__class__, self).__init__()
|
||||
|
||||
@exports.export("", "s")
|
||||
@exports.export("", "b")
|
||||
def start(self):
|
||||
print "== inner start called =="
|
||||
return "started (%s)" % self
|
||||
return False
|
||||
|
||||
@exports.export("", "b")
|
||||
def stop(self):
|
||||
129
src/daemon.py
Normal file
129
src/daemon.py
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
# Copyright (C) 2008-2011 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import logs
|
||||
import atexit
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
|
||||
log = logs.get("tuned")
|
||||
|
||||
CONFIG_FILE = "/etc/tuned/tuned.conf"
|
||||
INIT_TIMEOUT = 3
|
||||
|
||||
class Daemon(object):
|
||||
def __init__(self, config_file = None, debug = False):
|
||||
log.info("initializing")
|
||||
|
||||
if config_file is None:
|
||||
config_file = CONFIG_FILE
|
||||
|
||||
|
||||
self._config_file = config_file
|
||||
self._debug = debug
|
||||
|
||||
def daemonize(self):
|
||||
log.debug("daemonizing")
|
||||
|
||||
parent_pid = os.getpid()
|
||||
|
||||
signal.signal(signal.SIGALRM, self._daemonize_handle_signal)
|
||||
signal.signal(signal.SIGUSR1, self._daemonize_handle_signal)
|
||||
signal.signal(signal.SIGUSR2, self._daemonize_handle_signal)
|
||||
|
||||
if self._daemonize_fork():
|
||||
os.kill(parent_pid, signal.SIGUSR1)
|
||||
log.debug("daemonizing done")
|
||||
else:
|
||||
os.kill(parent_pid, signal.SIGUSR2)
|
||||
log.critical("daemonizing failed")
|
||||
sys.exit(1)
|
||||
|
||||
signal.signal(signal.SIGALRM, signal.SIG_DFL)
|
||||
signal.signal(signal.SIGUSR1, signal.SIG_DFL)
|
||||
signal.signal(signal.SIGUSR2, signal.SIG_DFL)
|
||||
|
||||
def _daemonize_fork(self):
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
self._daemonize_wait()
|
||||
assert False # unreachable
|
||||
except OSError as e:
|
||||
log.critical("fork: %s", str(e))
|
||||
return false
|
||||
|
||||
os.chdir("/")
|
||||
os.setsid()
|
||||
os.umask(0)
|
||||
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
sys.exit(0)
|
||||
except OSError as e:
|
||||
log.cricital("fork: %s", str(e))
|
||||
return false
|
||||
|
||||
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())
|
||||
|
||||
return True
|
||||
|
||||
def _daemonize_wait(self):
|
||||
signal.alarm(INIT_TIMEOUT)
|
||||
while True:
|
||||
signal.pause()
|
||||
|
||||
def _daemonize_handle_signal(self, signum, frame):
|
||||
if signum == signal.SIGUSR1:
|
||||
log.debug("daemonizing, got signal (success), exit")
|
||||
sys.exit(0)
|
||||
if signum == signal.SIGUSR2 or signum == signal.SIGALRM:
|
||||
log.critical("daemonizing, signal %d (failure), exit" % signum)
|
||||
sys.exit(1)
|
||||
else:
|
||||
log.warn("daemonizing, unknown signal %s, ignoring" % signum)
|
||||
|
||||
def run_controller(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
log.info("running")
|
||||
|
||||
import time
|
||||
|
||||
self._terminate = False
|
||||
while not self._terminate:
|
||||
time.sleep(1)
|
||||
|
||||
def terminate(self):
|
||||
log.info("terminating")
|
||||
self._terminate = True
|
||||
|
||||
def reload(self):
|
||||
log.info("reloading")
|
||||
pass
|
||||
|
||||
def cleanup(self):
|
||||
# TODO: do we need it?
|
||||
raise Exception()
|
||||
42
src/exports/__init__.py
Normal file
42
src/exports/__init__.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Copyright (C) 2008-2011 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import controller
|
||||
import interfaces
|
||||
|
||||
def export(*args, **kwargs):
|
||||
"""Decorator, use to mark exportable methods."""
|
||||
def wrapper(method):
|
||||
method.export_params = [ args, kwargs ]
|
||||
return method
|
||||
return wrapper
|
||||
|
||||
def register_exporter(instance):
|
||||
if not isinstance(instance, interfaces.IExporter):
|
||||
raise Exception()
|
||||
ctl = controller.ExportsController.get_instance()
|
||||
return ctl.register_exporter(instance)
|
||||
|
||||
def register_object(instance):
|
||||
if not isinstance(instance, interfaces.IExportable):
|
||||
raise Exception()
|
||||
ctl = controller.ExportsController.get_instance()
|
||||
return ctl.register_object(instance)
|
||||
|
||||
def run():
|
||||
ctl = controller.ExportsController.get_instance()
|
||||
return ctl.run()
|
||||
|
|
@ -1,5 +1,18 @@
|
|||
# Copyright (C) 2008-2011 Red Hat, Inc.
|
||||
#
|
||||
# Author: Jan Vcelak <jvcelak@redhat.com>
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import interfaces
|
||||
|
|
@ -1,5 +1,18 @@
|
|||
# Copyright (C) 2008-2011 Red Hat, Inc.
|
||||
#
|
||||
# Author: Jan Vcelak <jvcelak@redhat.com>
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
from __future__ import absolute_import
|
||||
27
src/exports/interfaces.py
Normal file
27
src/exports/interfaces.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Copyright (C) 2008-2011 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
class IExportable(object):
|
||||
pass
|
||||
|
||||
class IExporter(object):
|
||||
def export(self, method, in_signature, out_signature):
|
||||
# to be overriden by concrete implementation
|
||||
raise NotImplemented()
|
||||
|
||||
def serve(self):
|
||||
raise NotImplemented()
|
||||
82
src/logs.py
Normal file
82
src/logs.py
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# Copyright (C) 2008-2011 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import atexit
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import os.path
|
||||
|
||||
__all__ = [ "get" ]
|
||||
|
||||
LOG_FILENAME = "/var/log/tuned/tuned.log"
|
||||
LOG_FILE_MAXBYTES = 100*1000
|
||||
LOG_FILE_COUNT = 2
|
||||
|
||||
def get(name = "tuned"):
|
||||
return logging.getLogger(name)
|
||||
|
||||
class TunedLogger(logging.getLoggerClass()):
|
||||
"""Custom tuned daemon logger class."""
|
||||
_formatter = logging.Formatter("%(asctime)s %(levelname)-8s %(name)s: %(message)s")
|
||||
_console_handler = None
|
||||
_file_handler = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(self.__class__, self).__init__(*args, **kwargs)
|
||||
self.setLevel(logging.INFO)
|
||||
self.switch_to_console()
|
||||
|
||||
def set_level(self, level, default = logging.NOTSET):
|
||||
"""Set logging level. The 'level' parameter can be str or logging module constant."""
|
||||
if type(level) is str:
|
||||
level = logging._levelNames.get(level.upper(), logging.NOTSET)
|
||||
self.level = level
|
||||
|
||||
def switch_to_console(self):
|
||||
self._setup_console_handler()
|
||||
self.addHandler(self._console_handler)
|
||||
self.removeHandler(self._file_handler)
|
||||
|
||||
def switch_to_file(self):
|
||||
self._setup_file_handler()
|
||||
self.addHandler(self._file_handler)
|
||||
self.removeHandler(self._console_handler)
|
||||
|
||||
@classmethod
|
||||
def _setup_console_handler(cls):
|
||||
if cls._console_handler is not None:
|
||||
return
|
||||
|
||||
cls._console_handler = logging.StreamHandler()
|
||||
cls._console_handler.setFormatter(cls._formatter)
|
||||
|
||||
@classmethod
|
||||
def _setup_file_handler(cls):
|
||||
if cls._file_handler is not None:
|
||||
return
|
||||
|
||||
log_directory = os.path.dirname(LOG_FILENAME)
|
||||
if not os.path.exists(log_directory):
|
||||
os.makedirs(log_directory)
|
||||
|
||||
cls._file_handler = logging.handlers.RotatingFileHandler(
|
||||
LOG_FILENAME, maxBytes=LOG_FILE_MAXBYTES, backupCount=LOG_FILE_COUNT)
|
||||
cls._file_handler.setFormatter(cls._formatter)
|
||||
|
||||
logging.setLoggerClass(TunedLogger)
|
||||
atexit.register(logging.shutdown)
|
||||
25
src/main.py
Normal file
25
src/main.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Copyright (C) 2008-2011 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import logs
|
||||
|
||||
log = logs.get()
|
||||
|
||||
class Tuned(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
log.debug("something")
|
||||
pass
|
||||
1
tuned
Symbolic link
1
tuned
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
src
|
||||
90
tuned.py
Executable file
90
tuned.py
Executable file
|
|
@ -0,0 +1,90 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# tuned: A simple daemon that performs monitoring and adaptive configuration
|
||||
# of devices in the system
|
||||
#
|
||||
# Copyright (C) 2008-2011 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import tuned
|
||||
import atexit
|
||||
import getopt
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
|
||||
def usage():
|
||||
print "Usage: tuned [-d|--daemon] [-c conffile|--config=conffile] [-D|--debug]"
|
||||
|
||||
def error(message):
|
||||
print >>sys.stderr, message
|
||||
|
||||
def handle_signal(signum, callback):
|
||||
def wrapper(_signum, _frame):
|
||||
if signum == _signum:
|
||||
callback()
|
||||
signal.signal(signum, wrapper)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "dc:D", ["daemon", "config=", "debug"])
|
||||
except getopt.error as e:
|
||||
error("Error parsing command-line arguments: %s" % e)
|
||||
usage()
|
||||
sys.exit(1)
|
||||
|
||||
if len(args) > 0:
|
||||
error("Too many arguments.")
|
||||
usage()
|
||||
sys.exit(1)
|
||||
|
||||
config_file = None
|
||||
daemon = False
|
||||
debug = False
|
||||
|
||||
for (opt, val) in opts:
|
||||
if opt in ['-d', "--daemon"]:
|
||||
daemon = True
|
||||
elif opt in ['-c', "--config"]:
|
||||
config_file = val
|
||||
elif opt in ['-D', "--debug"]:
|
||||
debug = True
|
||||
|
||||
log = tuned.logs.get()
|
||||
if (debug):
|
||||
log.setLevel("DEBUG")
|
||||
|
||||
if os.getuid() != 0:
|
||||
if daemon:
|
||||
log.critical("Superuser permissions are needed.")
|
||||
sys.exit(1)
|
||||
else:
|
||||
log.warn("Superuser permissions are needed. Most tunings will not work!")
|
||||
|
||||
tuned_daemon = tuned.Daemon(config_file, debug)
|
||||
|
||||
handle_signal(signal.SIGHUP, tuned_daemon.reload)
|
||||
handle_signal(signal.SIGINT, tuned_daemon.terminate)
|
||||
handle_signal(signal.SIGTERM, tuned_daemon.terminate)
|
||||
|
||||
if daemon:
|
||||
log.switch_to_file()
|
||||
tuned_daemon.daemonize()
|
||||
|
||||
atexit.register(tuned_daemon.cleanup)
|
||||
|
||||
tuned_daemon.run()
|
||||
Loading…
Reference in a new issue