removed unused imports

parent 0348587e
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import os
import signal
import syslog
from . import const
from . import config
from . import logger
from . import server
from . import daemon
##### Public classes #####
class Application(object) :
def __init__(self, log_level, use_syslog_flag, bus_type, daemon_mode_flag) :
object.__init__(self)
#####
self.__log_level = log_level
self.__use_syslog_flag = use_syslog_flag
self.__bus_type = bus_type
self.__daemon_mode_flag = daemon_mode_flag
#####
self.__server = server.Server()
### Public ###
def run(self) :
self.prepare()
if self.__daemon_mode_flag :
logger.info("Run server in daemon mode")
self.runDaemon()
else :
logger.info("Run server in interactive mode")
self.runInteractive()
def server(self) :
return self.__server
###
def quit(self, signum = None, frame = None) :
if signum != None :
logger.info("Recieved signal %d, closing..." % (signum))
self.__server.closeServices()
self.__server.quitLoop()
logger.info("Closed")
### Private ###
def prepare(self) :
if self.__use_syslog_flag == None :
if self.__daemon_mode_flag :
syslog.openlog(const.MY_NAME, syslog.LOG_PID, syslog.LOG_DAEMON)
config.setValue(config.RUNTIME_SECTION, "use_syslog", True)
logger.verbose("Logger used syslog")
else :
syslog.openlog(const.MY_NAME, syslog.LOG_PID, ( syslog.LOG_DAEMON if self.__daemon_mode_flag else syslog.LOG_USER ))
config.setValue(config.RUNTIME_SECTION, "use_syslog", True)
logger.verbose("Logger used syslog")
try :
self.__server.loadServerConfigs()
except :
logger.error("Initialization error")
logger.attachException()
raise
logger.verbose("Preparing complete")
if self.__bus_type != None :
config.setValue(config.APPLICATION_SECTION, "bus_type", self.__bus_type)
if self.__log_level != None :
config.setValue(config.APPLICATION_SECTION, "log_level", self.__log_level)
config.setValue(config.RUNTIME_SECTION, "application", self)
###
def runInteractive(self) :
try :
self.__server.loadModules()
self.__server.loadServicesConfigs()
self.__server.initBus()
self.__server.initServices()
logger.info("Initialized")
except :
logger.error("Initialization error")
logger.attachException()
raise
try :
signal.signal(signal.SIGTERM, self.quit)
signal.signal(signal.SIGQUIT, self.quit)
except :
logger.error("signal() error")
logger.attachException()
try :
self.__server.runLoop()
except (SystemExit, KeyboardInterrupt) :
logger.info("Recieved KeyboardInterrupt or SystemExit, closing...")
self.quit()
except :
logger.error("Runtime error, trying to close services")
logger.attachException()
try :
self.quit()
except :
logger.attachException()
raise
raise
def runDaemon(self) :
work_dir_path = ( "/" if os.getuid() == 0 else None )
umask = ( 0o77 if os.getuid() == 0 else None )
logger.info("Run server as daemon: uid=%d, dir=%s, umask=%s" % ( os.getuid(),
( work_dir_path if work_dir_path != None else os.getcwd() ),
( str(umask) if umask != None else "%.4x" % os.umask(-1) ) ))
daemon.startDaemon(self.runInteractive, work_dir_path, umask)
# -*- coding: utf-8 -*-
import os
import configparser
from . import const
from . import validators
##### Public constants #####
APPLICATION_SECTION = const.MY_NAME
RUNTIME_SECTION = "runtime"
ALL_SECTIONS_LIST = (
APPLICATION_SECTION,
RUNTIME_SECTION
)
##### Private objects #####
ConfigDictObject = {
APPLICATION_SECTION : {
"service_name" : (const.DEFAULT_SERVICE_NAME, str),
"service_path" : (const.DEFAULT_SERVICE_PATH, str),
"bus_type" : (const.DEFAULT_BUS_TYPE, ( lambda arg : validators.common.validRange(arg, const.ALL_BUS_TYPES_LIST) )),
"log_level" : (const.DEFAULT_LOG_LEVEL, ( lambda arg : validators.common.validRange(int(arg), const.ALL_LOG_LEVELS_LIST) )),
"log_use_colors" :(const.DEFAULT_LOG_USE_COLORS_FLAG, validators.common.validBool)
},
RUNTIME_SECTION : {
"application" : (None, None),
"bus_name" : (None, None),
"use_syslog" : (False, None)
}
}
##### Public methods #####
def setValue(section, option, value, validator = None) :
global ConfigDictObject
if section not in ConfigDictObject :
ConfigDictObject[section] = {}
if option in ConfigDictObject[section] :
validator = ConfigDictObject[section][option][1]
if validator != None :
try :
value = validator(value)
except Exception as err1 :
raise validators.ValidatorError("Incorrect config option \"%s :: %s = %s\": %s" % (section, option, value, str(err1)))
ConfigDictObject[section][option] = (value, validator)
def value(section, option) :
return ConfigDictObject[section][option][0]
def validator(section, option) :
return ConfigDictObject[section][option][1]
def loadConfigs(only_sections_list = (), exclude_sections_list = ()) :
only_sections_list = list(only_sections_list)
exclude_sections_list = list(exclude_sections_list)
exclude_sections_list.append(RUNTIME_SECTION)
for config_files_list_item in os.listdir(const.CONFIGS_DIR) :
if not config_files_list_item.endswith(const.CONFIG_FILE_POSTFIX) :
continue
config_parser = configparser.ConfigParser()
config_parser.read(os.path.join(const.CONFIGS_DIR, config_files_list_item))
for section in config_parser.sections() :
if (len(only_sections_list) != 0 and not section in only_sections_list) or section in exclude_sections_list :
continue
for option in config_parser.options(section):
setValue(section, option, config_parser.get(section, option))
# -*- coding: utf-8 -*-
##### Public constants #####
MY_NAME = "settingsd"
VERSION = "0.3"
VERSION_STATUS = "beta"
FUNCTIONALITY_LEVEL = 132
FUNCTIONS_DIR = "plugins/functions"
ACTIONS_DIR = "plugins/actions"
CUSTOMS_DIR = "plugins/customs"
FUNCTIONS_DATA_DIR = "data/functions"
ACTIONS_DATA_DIR = "data/actions"
CUSTIOMS_DIR = "data/customs"
CONFIGS_DIR = "configs/settingsd"
CONFIG_FILE_POSTFIX = ".conf"
BUS_TYPE_SYSTEM = "system"
BUS_TYPE_SESSION = "session"
ALL_BUS_TYPES_LIST = (
BUS_TYPE_SYSTEM,
BUS_TYPE_SESSION
)
LOG_LEVEL_INFO = 0
LOG_LEVEL_VERBOSE = 1
LOG_LEVEL_DEBUG = 2
ALL_LOG_LEVELS_LIST = (
LOG_LEVEL_INFO,
LOG_LEVEL_VERBOSE,
LOG_LEVEL_DEBUG
)
DEFAULT_SERVICE_NAME = "org.etersoft.%s" % (MY_NAME)
DEFAULT_SERVICE_PATH = "/org/etersoft/%s" % (MY_NAME)
DEFAULT_BUS_TYPE = BUS_TYPE_SYSTEM
DEFAULT_LOG_LEVEL = LOG_LEVEL_INFO
DEFAULT_LOG_USE_COLORS_FLAG = True
# -*- coding: utf-8 -*-
import sys
import os
import signal
import errno
import resource
from . import const
from . import logger
##### Private methods #####
def pidsListOfPythonProc(proc_name, without_options_list = [], uid = 0) :
proc_name = os.path.basename(proc_name)
proc_pids_list = []
for proc_list_item in os.listdir("/proc") :
try :
proc_pid = int(proc_list_item)
except :
continue
cmdline_file_path = os.path.join("/proc", proc_list_item, "cmdline")
if os.stat(cmdline_file_path).st_uid != uid :
continue
cmdline_file = open(cmdline_file_path)
cmdline_list = cmdline_file.read().split("\0")
try :
cmdline_file.close()
except : pass
if len(cmdline_list) >= 2 and os.path.basename(cmdline_list[1]) == proc_name :
ignore_flag = False
for without_options_list_item in without_options_list :
if without_options_list_item in cmdline_list :
ignore_flag = True
break
if not ignore_flag :
proc_pids_list.append(proc_pid)
return proc_pids_list
def maxFd() :
max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
if max_fd == resource.RLIM_INFINITY :
max_fd = 1024
try :
max_fd = os.sysconf("SC_OPEN_MAX")
except ValueError :
pass
if max_fd < 0 :
max_fd = 1024
return max_fd
def closeFd(fd, retries_count = 5) :
for count in range(retries_count) :
try :
os.close(fd)
except OSError as err1 :
if err1.errno != errno.EBADF :
continue
break
##### Public methods #####
def startDaemon(function, work_dir_path = None, umask = None) :
pid = os.fork()
if pid > 0 :
try :
os.waitpid(pid, 0)
except OSError :
pass
elif pid == 0 :
logger.verbose("First fork() to %d as session lead" % (os.getpid()))
os.setsid()
pid = os.fork()
if pid > 0 :
os._exit(0)
elif pid == 0 :
logger.verbose("Second fork() to %d as main process" % (os.getpid()))
if work_dir_path != None :
os.chdir(work_dir_path)
logger.verbose("New working directory: %s" % (work_dir_path))
if umask != None :
os.umask(umask)
logger.verbose("Accapted new umask: %.3o" % (umask))
for fd in range(maxFd()) :
closeFd(fd)
null_fd = os.open("/dev/null", os.O_RDWR)
for fd in (0, 1, 2) :
os.dup2(null_fd, fd)
function()
def killDaemon() :
pids_list = pidsListOfPythonProc(sys.argv[0], ["-k", "--kill"], os.getuid())
if len(pids_list) != 0 :
for pids_list_item in pids_list :
os.kill(pids_list_item, signal.SIGTERM)
logger.info("SIGTERM has been sended to %s process \"%s\" with pid \"%d\"" % (
const.MY_NAME, os.path.basename(sys.argv[0]), pids_list_item ))
return 0
else :
logger.error("Cannot determine a %s daemon process of \"%s\"" % (const.MY_NAME, os.path.basename(sys.argv[0])))
return -1
def daemonStatus() :
pids_list = pidsListOfPythonProc(sys.argv[0], ["-s", "--status"], os.getuid())
if len(pids_list) != 0 :
for pids_list_item in pids_list :
logger.info("%s daemon has been founded with pid \"%d\"" % (const.MY_NAME, pids_list_item))
return 0
else :
logger.error("Cannot determine a %s daemon process of \"%s\"" % (const.MY_NAME, os.path.basename(sys.argv[0])))
return -1
# -*- coding: utf-8 -*-
import sys
import traceback
import syslog
import inspect
import time
from . import const
from . import config
##### Public constants #####
ERROR_MESSAGE = (0, syslog.LOG_ERR, const.LOG_LEVEL_INFO)
WARNING_MESSAGE = (1, syslog.LOG_WARNING, const.LOG_LEVEL_INFO)
NOTICE_MESSAGE = (2, syslog.LOG_NOTICE, const.LOG_LEVEL_INFO)
INFO_MESSAGE = (3, syslog.LOG_INFO, const.LOG_LEVEL_INFO)
VERBOSE_MESSAGE = (4, syslog.LOG_INFO, const.LOG_LEVEL_VERBOSE)
DEBUG_MESSAGE = (5, syslog.LOG_INFO, const.LOG_LEVEL_DEBUG) # syslog.LOG_DEBUG
ALL_MESSAGES_LIST = (
ERROR_MESSAGE,
INFO_MESSAGE,
NOTICE_MESSAGE,
WARNING_MESSAGE,
VERBOSE_MESSAGE,
DEBUG_MESSAGE
)
ALL_MESSAGES_TEXTS_LIST = (
(" Error ", "\033[31m Error \033[0m"),
("Warning", "\033[33mWarning\033[0m"),
("Notice ", "\033[32mNotice \033[0m"),
(" Info ", "\033[32m Info \033[0m"),
("Details", "\033[36mDetails\033[0m"),
(" Debug ", " Debug ")
)
MODULE_CALLER_NAME_TAG = "{mod}"
SUBMODULE_CALLER_NAME_TAG = "{submod}"
CURRENT_TIME_TAG = "{time}"
ALL_TAGS_LIST = (
MODULE_CALLER_NAME_TAG,
SUBMODULE_CALLER_NAME_TAG,
CURRENT_TIME_TAG
)
##### Exceptions #####
class UnknownMessageType(Exception) :
pass
##### Private methods #####
def log(message_type, message) :
if not message_type in ALL_MESSAGES_LIST :
raise UnknownMessageType("Message type \"%s\" not in list %s" % (str(message_type), ALL_MESSAGES_LIST))
if message_type[2] <= config.value(config.APPLICATION_SECTION, "log_level") :
for all_tags_list_item in ALL_TAGS_LIST :
if all_tags_list_item == MODULE_CALLER_NAME_TAG :
try :
message = message.replace(MODULE_CALLER_NAME_TAG,
inspect.getmodule(inspect.currentframe().f_back.f_back).__name__)
except : pass
elif all_tags_list_item == SUBMODULE_CALLER_NAME_TAG :
try :
message = message.replace(SUBMODULE_CALLER_NAME_TAG,
inspect.getmodule(inspect.currentframe().f_back.f_back.f_back).__name__)
except : pass
elif all_tags_list_item == CURRENT_TIME_TAG :
message = message.replace(CURRENT_TIME_TAG, time.ctime())
colored_index = int(sys.stderr.isatty() and config.value(config.APPLICATION_SECTION, "log_use_colors"))
for message_list_item in message.split("\n") :
print("[ %s ] %s" % (ALL_MESSAGES_TEXTS_LIST[message_type[0]][colored_index], message_list_item), file=sys.stderr)
if config.value(config.RUNTIME_SECTION, "use_syslog") :
syslog.syslog(message_type[1], "[ %s ] %s" % (ALL_MESSAGES_TEXTS_LIST[message_type[0]][0], message_list_item))
##### Public methods #####
def error(message) :
log(ERROR_MESSAGE, message)
def info(message) :
log(INFO_MESSAGE, message)
def notice(message) :
log(NOTICE_MESSAGE, message)
def warning(message) :
log(WARNING_MESSAGE, message)
def verbose(message) :
log(VERBOSE_MESSAGE, message)
def debug(message) :
log(DEBUG_MESSAGE, message)
###
def attachException(message_type = ERROR_MESSAGE) :
for line in traceback.format_exc().splitlines() :
log(message_type, line)
# -*- coding: utf-8 -*-
import sys
import os
import dbus
import dbus.service
import dbus.glib
from gi.repository import GLib
from . import const
from . import config
from . import logger
from . import validators
##### Public classes #####
class Server(object) :
def __init__(self) :
object.__init__(self)
#####
self.__modules_list = []
self.__services_dict = {}
GLib.threads_init()
self.__main_loop = GLib.MainLoop()
### Public ###
def runLoop(self) :
logger.verbose("Running GObject loop...")
self.__main_loop.run()
def quitLoop(self) :
self.__main_loop.quit()
logger.verbose("GObject loop closed")
###
def loadModules(self) :
for modules_path_list_item in (const.FUNCTIONS_DIR, const.ACTIONS_DIR, const.CUSTOMS_DIR) :
logger.debug("Processing directory \"%s\"..." % (modules_path_list_item))
sys.path.append(modules_path_list_item)
for module_name in [ item[:-3] for item in os.listdir(modules_path_list_item)
if item.endswith(".py") and not item.startswith(".") ] :
try :
self.__modules_list.append(__import__(module_name, globals(), locals(), [""]))
except :
logger.error("Import error on module \"%s\"" % (module_name))
logger.attachException()
continue
self.__services_dict[self.__modules_list[-1].Service.serviceName()] = {
"service_class" : self.__modules_list[-1].Service,
"service" : None
}
logger.verbose("Loaded module: %s" % (module_name))
sys.path.remove(modules_path_list_item)
###
def loadServerConfigs(self) :
config.loadConfigs(only_sections_list = (config.APPLICATION_SECTION,))
def loadServicesConfigs(self) :
for service_name in list(self.__services_dict.keys()) :
service_options_list = list(self.__services_dict[service_name]["service_class"].options())
service_options_list.append((service_name, "enabled", "no", validators.common.validBool))
for service_options_list_item in service_options_list :
try :
config.setValue(*service_options_list_item)
except :
logger.error("Error on set options tuple %s" % (str(service_options_list_item)))
logger.attachException()
config.loadConfigs(exclude_sections_list = (config.APPLICATION_SECTION,))
###
def initBus(self) :
bus_type = config.value(config.APPLICATION_SECTION, "bus_type")
service_name = config.value(config.APPLICATION_SECTION, "service_name")
try :
config.setValue(config.RUNTIME_SECTION, "bus_name", dbus.service.BusName(service_name,
( dbus.SystemBus() if bus_type == const.BUS_TYPE_SYSTEM else dbus.SessionBus() )))
except :
logger.error("Could not connect to D-Bus \"%s\"" % (bus_type))
logger.attachException()
raise
logger.verbose("Connected to D-Bus \"%s\" as \"%s\"" % (bus_type, service_name))
###
def initServices(self) :
for service_name in list(self.__services_dict.keys()) :
if config.value(service_name, "enabled") :
logger.verbose("Enabling service \"%s\"..." % (service_name))
try :
self.__services_dict[service_name]["service"] = self.__services_dict[service_name]["service_class"]()
self.__services_dict[service_name]["service"].initService()
except :
logger.error("Cannot initialize service \"%s\"" % (service_name))
logger.attachException()
logger.info("Initialized service: %s" % (service_name))
def closeServices(self) :
for service_name in list(self.__services_dict.keys()) :
if self.__services_dict[service_name]["service"] != None :
logger.verbose("Disabling service \"%s\"..." % (service_name))
try :
self.__services_dict[service_name]["service"].closeService()
del self.__services_dict[service_name]["service"]
except :
logger.error("Cannot close service \"%s\"" % (service_name))
logger.attachException()
self.__services_dict[service_name]["service"] = None
logger.info("Closed service: %s" % (service_name))
# -*- coding: utf-8 -*-
import dbus
import dbus.service
import dbus.glib
import abc
from . import config
from . import tools
##### Private classes #####
class ServiceInterface(object, metaclass=abc.ABCMeta) :
@abc.abstractmethod
def initService(self) :
pass
def closeService(self) :
pass
class ServiceRequisitesInterface(object, metaclass=abc.ABCMeta) :
@classmethod
@abc.abstractmethod
def serviceName(self) :
pass
@classmethod
def options(self) :
return []
##### Public classes #####
class Service(ServiceInterface, ServiceRequisitesInterface) :
pass
#####
class CustomObject(dbus.service.Object) :
def __init__(self, object_path, service_object = None) :
dbus.service.Object.__init__(self, config.value(config.RUNTIME_SECTION, "bus_name"), object_path)
self.__object_path = object_path
self.__service_object = service_object
#####
self.__shared = None
### Public ###
def name(self) :
if self.shared() == None :
return None
for (shared_object_name, shared_object) in list(self.shared().sharedObjects().items()) :
if shared_object == self :
return shared_object_name
return None
def path(self) :
def build_path(shared) :
if shared != None :
path = build_path(shared.parentShared())
return ( shared.name() if path == None else tools.dbus.joinMethod(path, shared.name()) )
return None
return build_path(self.shared())
def objectPath(self) :
return self.__object_path
###
def setService(self, service_object) :
self.__service_object = service_object
def service(self) :
return self.__service_object
def setShared(self, shared) :
self.__shared = shared
def shared(self) :
return self.__shared
###
def addToConnection(self, connection = None, path = None) :
self.add_to_connection(connection, path)
def removeFromConnection(self, conneciton = None, path = None) :
self.remove_from_connection(conneciton, path)
class FunctionObject(CustomObject) :
def __init__(self, object_path, service_object = None) :
CustomObject.__init__(self, tools.dbus.joinPath(config.value(config.APPLICATION_SECTION, "service_path"),
"functions", object_path), service_object)
class ActionObject(CustomObject) :
def __init__(self, object_path, service_object = None) :
CustomObject.__init__(self, tools.dbus.joinPath(config.value(config.APPLICATION_SECTION, "service_path"),
"actions", object_path), service_object)
# -*- coding: utf-8 -*-
import dbus
import dbus.service
import dbus.glib
from . import const
from . import config
from . import logger
from . import tools
from .tools import dbus as dbus_tools
##### Private decorators #####
def tracer(function, statics_list=[0]) :
def wrapper(self, *args_list, **kwargs_dict) :
if config.value(config.APPLICATION_SECTION, "log_level") == const.LOG_LEVEL_DEBUG :
logger.debug("%s%s %s::%s" % ( " "*statics_list[0],
str(("_dbus_is_method" in function.__dict__ and "Called method") or
("_dbus_is_signal" in function.__dict__ and "Emited signal")),
self.objectPath(), dbus_tools.joinMethod(function._dbus_interface, function.__name__) ))
statics_list[0] += 1
try :
return_value = function(self, *args_list, **kwargs_dict)
except :
logger.attachException()
raise
finally :
statics_list[0] -= 1
logger.debug("%s... executed as %s::%s(%s, %s) --> %s" % ( " "*statics_list[0],
self.__class__.__name__, function.__name__, str(args_list), str(kwargs_dict), str(return_value) ))
return return_value
else :
try :
return function(self, *args_list, **kwargs_dict)
except :
logger.attachException()
raise
wrapper.__name__ = function.__name__
wrapper.__dict__ = function.__dict__
wrapper.__doc__ = function.__doc__
return wrapper
##### Public decorators #####
def customMethod(interface_name, **kwargs_dict) :
def decorator(function) :
return tracer(dbus.service.method(interface_name, **kwargs_dict)(function))
return decorator
def functionMethod(interface_name, **kwargs_dict) :
def decorator(function) :
return customMethod(tools.dbus.joinMethod(config.value(config.APPLICATION_SECTION, "service_name"),
"functions", interface_name), **kwargs_dict)(function)
return decorator
def actionMethod(interface_name, **kwargs_dict) :
def decorator(function) :
return customMethod(tools.dbus.joinMethod(config.value(config.APPLICATION_SECTION, "service_name"),
"actions", interface_name), **kwargs_dict)(function)
return decorator
###
def customSignal(interface_name, **kwargs_dict) :
def decorator(function) :
return tracer(dbus.service.signal(interface_name, **kwargs_dict)(function))
return decorator
def functionSignal(interface_name, **kwargs_dict) :
def decorator(function) :
return customSignal(tools.dbus.joinMethod(config.value(config.APPLICATION_SECTION, "service_name"),
"functions", interface_name), **kwargs_dict)(function)
return decorator
def actionSignal(interface_name, **kwargs_dict) :
def decorator(function) :
return customSignal(tools.dbus.joinMethod(config.value(config.APPLICATION_SECTION, "service_name"),
"actions", interface_name), **kwargs_dict)(function)
return decorator
# -*- coding: utf-8 -*-
##### Exceptions #####
class SharedsConflict(Exception) :
pass
class SharedNotExists(Exception) :
pass
class SharedObjectsConflict(Exception) :
pass
class SharedObjectNotExists(Exception) :
pass
##### Private classes #####
class SharedAbstract :
def __init__(entity) :
entity._shareds_dict = {}
entity._shared_objects_dict = {}
#####
entity._parent_shared = None
### Public ###
def setParentShared(entity, shared) :
entity._parent_shared = shared
def parentShared(entity) :
return entity._parent_shared
###
def name(entity) :
if entity.parentShared() == None :
return None
for (shared_name, shared) in list(entity.parentShared().shareds().items()) :
if shared == entity :
return shared_name
return None
###
def addShared(entity, shared_name) :
if shared_name in entity._shareds_dict :
raise SharedsConflict("Shared \"%s\" is already exists in collection \"%s\"" % (shared_name, entity.__name__))
entity._shareds_dict[shared_name] = Shared()
entity._shareds_dict[shared_name].setParentShared(entity)
setattr(entity, shared_name, entity._shareds_dict[shared_name])
def removeShared(entity, shared_name) :
if shared_name not in entity._shareds_dict :
raise SharedNotExists("Shared \"%s\" does not exist in collection \"%s\"" % (shared_name, entity.__name__))
entity._shareds_dict[shared_name].setParentShared(None)
entity._shareds_dict.pop(shared_name)
delattr(entity, shared_name)
def hasShared(entity, shared_name) :
return shared_name in entity._shareds_dict
def shared(entity, shared_name) :
return entity._shareds_dict[shared_name]
def shareds(entity) :
return entity._shareds_dict
###
def addSharedObject(entity, shared_object_name, shared_object) :
if shared_object_name in entity._shared_objects_dict :
raise SharedObjectsConflict("Shared object \"%s\" is already exists in collection \"%s\"" % (shared_object_name, entity.__name__))
entity._shared_objects_dict[shared_object_name] = shared_object
entity._shared_objects_dict[shared_object_name].setShared(entity)
setattr(entity, shared_object_name, entity._shared_objects_dict[shared_object_name])
def removeSharedObject(entity, shared_object_name) :
if shared_object_name not in entity._shared_objects_dict :
raise SharedObjectNotExists("Shared object \"%s\" does not exist in collection \"%s\"" % (shared_object_name, entity.__name__))
entity._shared_objects_dict[shared_object_name].setShared(None)
entity._shared_objects_dict.pop(shared_object_name)
delattr(entity, shared_object_name)
def hasSharedObject(entity, shared_object) :
return ( shared_object in entity._shared_objects_dict or shared_object in list(entity._shared_objects_dict.values()) )
def sharedObject(entity, shared_object_name) :
return entity._shared_objects_dict[shared_object_name]
def sharedObjects(entity) :
return entity._shared_objects_dict
class SharedRootMeta(type, SharedAbstract) :
def __init__(cls, name, bases_list, attrs_dict) :
type.__init__(cls, name, bases_list, attrs_dict)
SharedAbstract.__init__(cls)
class Shared(SharedAbstract) :
def __init__(self) :
object.__init__(self)
SharedAbstract.__init__(self)
##### Public classes #####
class Functions(object, metaclass=SharedRootMeta) :
@classmethod
def name(self) :
return "Functions"
class Actions(object, metaclass=SharedRootMeta) :
@classmethod
def name(self) :
return "Actions"
class Customs(object, metaclass=SharedRootMeta) :
@classmethod
def name(self) :
return "Customs"
# -*- coding: utf-8 -*-
__all__ = ["dbus", "process", "editors"]
# -*- coding: utf-8 -*-
##### Public methods #####
def joinPath(first, *others_list) :
return "/".join((first,) + others_list)
def joinMethod(first, *others_list) :
return ".".join((first,) + others_list)
# -*- coding: utf-8 -*-
import os
import re
import shutil
from .. import logger
##### Exceptions #####
class NotAssociated(Exception) :
pass
class AlreadyAssociated(Exception) :
pass
##### Public classes #####
class PlainEditor(object) :
def __init__(self, delimiter = "=", spaces_list = ["\\s"], quotes_list= ["\"", "\'"], comments_list = ["#"]) :
object.__init__(self)
#####
self.__delimiter = delimiter
self.__spaces_list = list(spaces_list)
self.__quotes_list = list(quotes_list)
self.__comments_list = list(comments_list)
#####
self.__config_file_path = None
self.__config_file_data_list = None
###
spaces = ( "[%s]*" % ("".join(self.__spaces_list)) if len(self.__spaces_list) > 0 else "" )
comments = "".join(self.__comments_list)
self.__comments_regexp = re.compile(r"%s(?<!\\)[%s]%s" % (spaces, comments, spaces))
self.__variable_regexp = re.compile(r"%s%s%s" % (spaces, self.__delimiter, spaces))
### Public ###
def open(self, config_file_path, sample_config_file_path = None) :
if self.__config_file_path != None :
raise AlreadyAssociated("This parser already associated with config \"%s\"" % self.__config_file_path)
if not os.access(config_file_path, os.F_OK) :
logger.debug("{submod}: Config file \"%s\" does not exist" % (config_file_path))
try :
if sample_config_file_path != None and os.access(sample_config_file_path, os.F_OK) :
shutil.copy2(sample_config_file_path, config_file_path)
logger.debug("{submod}: Config file \"%s\" has been created from sample \"%s\"" % (
config_file_path, sample_config_file_path ))
else :
open(config_file_path, "w").close()
logger.debug("{submod}: Created empty file \"%s\"" % (config_file_path))
except :
logger.error("Cannot create config file \"%s\"" % (config_file_path))
logger.attachException()
config_file = open(config_file_path, "r")
self.__config_file_data_list = config_file.read().split("\n")
self.__config_file_path = config_file_path
try :
config_file.close()
except : pass
logger.debug("{submod}: Cached and associated config file \"%s\"" % (config_file_path))
def save(self) :
if self.__config_file_path == None :
raise NotAssociated("This parser is not associated with config")
config_file = open(self.__config_file_path, "w")
config_file.write("\n".join(self.__config_file_data_list))
try :
config_file.close()
except : pass
logger.debug("{submod}: Saved config file \"%s\"" % (self.__config_file_path))
def close(self) :
if self.__config_file_path == None :
raise NotAssociated("This parser is not associated with config")
logger.debug("{submod}: Unassociated parser from config file \"%s\"" % (self.__config_file_path))
self.__config_file_data_list = None
self.__config_file_path = None
###
def setValue(self, variable_name, values_list) :
if self.__config_file_path == None :
raise NotAssociated("This parser is not associated with config")
if values_list == None :
values_list = []
elif not type(values_list).__name__ in ("list", "tuple") :
values_list = [values_list]
last_variable_index = len(self.__config_file_data_list) - 1
count = 0
while count < len(self.__config_file_data_list) :
variable = self.__comments_regexp.split(self.__config_file_data_list[count].strip(), 1)[0]
variable_parts_list = self.__variable_regexp.split(variable, 1)
if variable_parts_list[0] == variable_name :
self.__config_file_data_list.pop(count)
last_variable_index = count
else :
count += 1
space = ( " " if len(self.__spaces_list) > 0 else "" )
quote = ( self.__quotes_list[0] if len(self.__quotes_list) > 0 else "" )
for count in range(len(values_list)) :
variable = variable_name + space + self.__delimiter + space + quote + str(values_list[count]) + quote
self.__config_file_data_list.insert(last_variable_index + count, variable)
def value(self, variable_name) :
if self.__config_file_path == None :
raise NotAssociated("This parser is not associated with config")
values_list = []
for config_file_data_list_item in self.__config_file_data_list :
variable = self.__comments_regexp.split(config_file_data_list_item.strip(), 1)[0]
variable_parts_list = self.__variable_regexp.split(variable, 1)
if variable_parts_list[0] == variable_name :
if len(variable_parts_list) > 1 :
value = variable_parts_list[1]
for quotes_list_item in self.__quotes_list :
if len(value) > 2 and value[0] == value[-1] == quotes_list_item :
value = value[1:-1]
values_list.append(value)
else :
values_list.append("")
return values_list
class IniEditor(object) :
def __init__(self) :
object.__init__(self)
#####
self.__config_file_path = None
self.__config_file_data_list = None
###
self.__comments_regexp = re.compile(r"\s*(?<!\\)[;#]\s*")
self.__section_regexp = re.compile(r"^\s*\[([^];#]+)\]")
self.__variable_regexp = re.compile(r"\s*=\s*")
### Public ###
def open(self, config_file_path, sample_config_file_path = None) :
if self.__config_file_path != None :
raise AlreadyAssociated("This parser already associated with config \"%s\"" % self.__config_file_path)
if not os.access(config_file_path, os.F_OK) :
logger.debug("{submod}: Config file \"%s\" does not exist" % (config_file_path))
try :
if sample_config_file_path != None and os.access(sample_config_file_path, os.F_OK) :
shutil.copy2(sample_config_file_path, config_file_path)
logger.debug("{submod}: Config file \"%s\" has been created from sample \"%s\"" % (
config_file_path, sample_config_file_path ))
else :
open(config_file_path, "w").close()
logger.debug("{submod}: Created empty file \"%s\"" % (config_file_path))
except :
logger.error("Cannot create config file \"%s\"" % (config_file_path))
logger.attachException()
config_file = open(config_file_path, "r")
self.__config_file_data_list = config_file.read().split("\n")
self.__config_file_path = config_file_path
try :
config_file.close()
except : pass
logger.debug("{submod}: Cached and associated config file \"%s\"" % (config_file_path))
def save(self) :
if self.__config_file_path == None :
raise NotAssociated("This parser is not associated with config")
config_file = open(self.__config_file_path, "w")
config_file.write("\n".join(self.__config_file_data_list))
try :
config_file.close()
except : pass
logger.debug("{submod}: Saved config file \"%s\"" % (self.__config_file_path))
def close(self) :
if self.__config_file_path == None :
raise NotAssociated("This parser is not associated with config")
logger.debug("{submod}: Unassociated parser from config file \"%s\"" % (self.__config_file_path))
self.__config_file_data_list = None
self.__config_file_path = None
###
def setValue(self, section_name, variable_name, values_list) :
if self.__config_file_path == None :
raise NotAssociated("This parser is not associated with config")
if values_list == None :
values_list = []
elif not type(values_list).__name__ in ("list", "tuple") :
values_list = [values_list]
active_section_flag = False
section_exists_flag = False
last_variable_index = len(self.__config_file_data_list) - 1
count = 0
while count < len(self.__config_file_data_list) :
record = self.__comments_regexp.split(self.__config_file_data_list[count].strip(), 1)[0]
section_match = self.__section_regexp.search(record)
if section_match != None :
new_active_section_flag = ( section_match.group(1) == section_name )
if new_active_section_flag :
section_exists_flag = True
if active_section_flag and not new_active_section_flag :
last_variable_index = count
active_section_flag = new_active_section_flag
elif active_section_flag :
if self.__variable_regexp.split(record, 1)[0] == variable_name :
self.__config_file_data_list.pop(count)
last_variable_index = count
continue
count += 1
if not section_exists_flag :
self.__config_file_data_list.insert(last_variable_index, "")
self.__config_file_data_list.insert(last_variable_index + 1, "[%s]" % (section_name))
last_variable_index += 2
for count in range(len(values_list)) :
self.__config_file_data_list.insert(last_variable_index + count, "%s = %s" % (variable_name, str(values_list[count])))
def value(self, section_name, variable_name) :
if self.__config_file_path == None :
raise NotAssociated("This parser is not associated with config")
section_founded_flag = False
values_list = []
for config_file_data_list_item in self.__config_file_data_list :
record = self.__comments_regexp.split(config_file_data_list_item.strip(), 1)[0]
section_match = self.__section_regexp.search(record)
if section_match != None :
section_founded_flag = ( section_match.group(1) == section_name )
continue
if section_founded_flag :
variable_parts_list = self.__variable_regexp.split(record, 1)
if variable_parts_list[0] == variable_name :
if len(variable_parts_list) > 1 :
values_list.append(variable_parts_list[1])
else :
values_list.append("")
return values_list
# -*- coding: utf-8 -*-
import subprocess
from os import environ
from .. import const
from .. import config
from .. import logger
##### Exceptions #####
class SubprocessFailure(Exception) :
pass
##### Public methods #####
def execProcess(proc_args_list, proc_input = None, fatal_flag = True,
confidential_input_flag = False, inherit_env=False, shell=False) :
if shell and not isinstance(proc_args_list, str):
proc_args_list = ' '.join(proc_args_list)
logger.debug("{submod}: Executing child process \"%s\"" % (str(proc_args_list)))
env = { "LC_ALL" : "C" }
if inherit_env:
env = { **environ, **env }
proc = subprocess.Popen(proc_args_list, bufsize=1024, close_fds=True,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
env=env, shell=shell)
(proc_stdout, proc_stderr) = proc.communicate(proc_input)
if proc.returncode != 0 :
if proc_input == None :
proc_input = ""
elif confidential_input_flag and config.value(config.APPLICATION_SECTION, "log_level") != const.LOG_LEVEL_DEBUG :
proc_input = "<CONFIDENTIAL>"
error_text = "Error while execute \"%s\"\nStdout: %s\nStderr: %s\nStdin: %s\nReturn code: %d" % (
str(proc_args_list), proc_stdout.strip(), proc_stderr.strip(), proc_input, proc.returncode )
if fatal_flag :
logger.error("{submod}: "+error_text)
raise SubprocessFailure(error_text)
logger.debug("{submod}: Child process \"%s\" finished, return_code=%d" % (str(proc_args_list), proc.returncode))
return (proc_stdout, proc_stderr, proc.returncode)
# -*- coding: utf-8 -*-
__all__ = ["common", "network", "os"]
# -*- coding: utf-8 -*-
import re
##### Exceptions #####
class ValidatorError(Exception) :
pass
##### Public methods #####
def validBool(arg) :
arg = str(arg).lower()
true_args_list = ("1", "true", "yes")
false_args_list = ("0", "false", "no")
if not arg in true_args_list + false_args_list :
raise ValidatorError("Argument \"%s\" not in list %s or %s" % (arg, true_args_list, false_args_list))
return ( arg in true_args_list )
def validRange(arg, valid_args_list) :
if not arg in valid_args_list :
raise ValidatorError("Argument \"%s\" not in range %s" % (arg, str(valid_args_list)))
return arg
def validStringList(arg) :
return re.split(r"[,\t ]+", str(arg))
# -*- coding: utf-8 -*-
from .common import ValidatorError
##### Public methods #####
def validIpv4Address(arg) :
arg = str(arg).strip()
octets_list = arg.split(".")
if len(octets_list) != 4 :
raise ValidatorError("Argument \"%s\" is not valid IPv4 address" % (arg))
for count in range(4) :
try :
octets_list[count] = int(octets_list[count])
if not 0 <= octets_list[count] <= 255 :
raise Exception
except :
raise ValidatorError("Argument \"%s\" is not valid IPv4 address" % (arg))
return (arg, octets_list)
def validIpv4Netmask(arg) :
arg = str(arg).strip()
octets_list = arg.split(".")
if len(octets_list) == 1 :
try :
arg = int(arg)
if not 0 <= arg <= 32 :
raise ValidatorError("Argument \"%s\" is not valid IPv4 netmask" % (arg))
except :
raise ValidatorError("Argument \"%s\" is not valid IPv4 netmask" % (arg))
octets_list = [0] * 4
one_count = arg
for count in range(4) :
octet_one_count = 8
while one_count and octet_one_count :
octets_list[count] |= 128 >> 8 - octet_one_count
one_count -= 1
octet_one_count -= 1
elif len(octets_list) == 4 :
for count in range(4) :
try :
octets_list[count] = int(octets_list[count])
if not 0 <= octets_list[count] <= 255 :
raise Exception
except :
raise ValidatorError("Argument \"%s\" is not valid IPv4 netmask" % (arg))
else :
raise ValidatorError("Argument \"%s\" is not valid IPv4 netmask" % (arg))
return (arg, octets_list)
def validMacAddress(arg) :
arg = str(arg).strip()
octets_list = arg.split(":")
if len(octets_list) != 6 :
raise ValidatorError("Argument \"%s\" is not valid MAC address" % (arg))
for count in range(6) :
try :
octets_list[count] = int(octets_list[count], 16)
if not 0 <= octets_list[count] <= 255 :
raise Exception
except :
raise ValidatorError("Argument \"%s\" is not valid MAC address" % (arg))
return (arg, octets_list)
# -*- coding: utf-8 -*-
import re
from .common import ValidatorError
##### Public methods #####
def validUserName(arg) :
if re.match(r"^[a-z_][a-z0-9_-]*$", arg) == None :
raise ValidatorError("Argument \"%s\" is not valid UNIX user name" % (arg))
return arg
def validGroupName(arg) :
if re.match(r"^[a-z_][a-z0-9_-]*$", arg) == None :
raise ValidatorError("Argument \"%s\" is not valid UNIX group name" % (arg))
return arg
#!/usr/bin/python3.6
# -*- coding: utf-8 -*-
import sys
import getopt
from settingsd import const
from settingsd import validators
from settingsd import application
from settingsd import daemon
##### Private methods #####
def help() :
print(( "Usage: %s [options]\n"
"Options:\n"
"\t-h, --help -- Print this text\n"
"\t-v, --version -- Print version and license info\n"
"\t--log-level=<0|1|2> -- Log level, replace value from config\n"
"\t--use-syslog=<yes|no> -- Force enable or disable useage of syslog\n"
"\t--bus-type=<system|session> -- Use system or session bus, replace value from config\n"
"\t-d, --daemon -- Run application as daemon, by default using interactive mode\n"
"\t-s, --status -- Check status of daemon\n"
"\t-k, --kill -- Kill daemon process" % (const.MY_NAME) ))
def version() :
print("%s version %s-%s, functionality_level=%d" % (const.MY_NAME, const.VERSION, const.VERSION_STATUS, const.FUNCTIONALITY_LEVEL))
##### Main #####
if __name__ == "__main__" :
log_level = None
use_syslog_flag = None
bus_type = None
daemon_mode_flag = False
try :
(opts_list, args_list) = getopt.getopt(sys.argv[1:], "hdsk", ( "help", "version",
"log-level=", "use-syslog=", "bus-type=", "daemon", "status", "kill" ))
for (opts_list_item, args_list_item) in opts_list :
if opts_list_item in ("-h", "--help") :
help()
sys.exit(0)
elif opts_list_item in ("-v", "--version") :
version()
sys.exit(0)
elif opts_list_item in ("--log-level",) :
try :
log_level = validators.common.validRange(int(args_list_item), const.ALL_LOG_LEVELS_LIST)
except Exception as err1 :
print("Incorrect option \"%s\": %s" % (opts_list_item, str(err1)))
sys.exit(1)
elif opts_list_item in ("--use-syslog",) :
try :
use_syslog_flag = validators.common.validBool(args_list_item)
except Exception as err1 :
print("Incorrect option \"%s\": %s" % (opts_list_item, str(err1)))
sys.exit(1)
elif opts_list_item in ("--bus-type",) :
try :
bus_type = validators.common.validRange(args_list_item, const.ALL_BUS_TYPES_LIST)
except Exception as err1 :
print("Incorrect option \"%s\": %s" % (opts_list_item, str(err1)))
sys.exit(1)
elif opts_list_item in ("-d", "--daemon") :
daemon_mode_flag = True
elif opts_list_item in ("-s", "--status") :
try :
sys.exit(abs(daemon.daemonStatus()))
except Exception as err1 :
print("Daemon status error: %s" % (str(err1)))
sys.exit(1)
elif opts_list_item in ("-k", "--kill") :
try :
sys.exit(abs(daemon.killDaemon()))
except Exception as err1 :
print("Daemon kill error: %s" % (str(err1)))
sys.exit(1)
else :
print("Unknown option \"%s\"" % (opts_list_item))
except Exception as err1 :
print("Bad command line options: %s" % (str(err1)))
#####
application.Application(log_level, use_syslog_flag, bus_type, daemon_mode_flag).run()
......@@ -4,10 +4,8 @@
from settingsd import config
from settingsd import service
from settingsd import shared
from settingsd import logger
import settingsd.tools as tools
import settingsd.tools.process
##### Private constants #####
......
......@@ -5,7 +5,6 @@ import os
import time
import re
import hashlib
import shutil
from settingsd import const
from settingsd import config
......@@ -13,8 +12,6 @@ from settingsd import service
from settingsd import shared
import settingsd.tools as tools
import settingsd.tools.process
import settingsd.tools.editors
##### Private constants #####
......
# -*- coding: utf-8 -*-
import os
import re
import gudev
import glib
from settingsd import config
from settingsd import service
......@@ -12,8 +10,6 @@ from settingsd import shared
from settingsd import logger
import settingsd.tools as tools
import settingsd.tools.dbus
import settingsd.tools.process
##### Private constants #####
......
......@@ -2,9 +2,7 @@
import os
import re
import signal
import shutil
from settingsd import const
from settingsd import config
......@@ -13,10 +11,8 @@ from settingsd import shared
from settingsd import logger
import settingsd.validators as validators
import settingsd.validators.network
import settingsd.tools as tools
import settingsd.tools.editors
##### Private constants #####
......
......@@ -12,12 +12,8 @@ from settingsd import shared
from settingsd import logger
import settingsd.validators as validators
import settingsd.validators.os
import settingsd.tools as tools
import settingsd.tools.dbus
import settingsd.tools.process
import settingsd.tools.editors
##### Private constants #####
......
......@@ -13,12 +13,8 @@ from settingsd import shared
from settingsd import logger
import settingsd.validators as validators
import settingsd.validators.os
import settingsd.tools as tools
import settingsd.tools.dbus
import settingsd.tools.process
import settingsd.tools.editors
##### Private constants #####
......
......@@ -4,13 +4,10 @@
from settingsd import config
from settingsd import service
from settingsd import shared
from settingsd import logger
import settingsd.tools as tools
import settingsd.tools.process
import settingsd.validators as validators
import settingsd.validators.common
##### Private constants #####
......
......@@ -7,15 +7,10 @@ from pyroute2.netlink.rtnl.ifinfmsg import IFF_UP
from ipaddress import IPv4Address, IPv4Network
from yaml import dump, safe_load
from settingsd import const
from settingsd import config
from settingsd import service
from settingsd import shared
from settingsd import logger
import settingsd.tools as tools
from settingsd.tools.process import execProcess
import settingsd.tools.editors
from jinja2 import Template
......
......@@ -12,12 +12,8 @@ from settingsd import shared
from settingsd import logger
import settingsd.validators as validators
import settingsd.validators.os
import settingsd.tools as tools
import settingsd.tools.dbus
import settingsd.tools.process
import settingsd.tools.editors
##### Private constants #####
......
......@@ -2,18 +2,13 @@
import os
import re
import shutil
from settingsd import const
from settingsd import config
from settingsd import service
from settingsd import shared
from settingsd import logger
import settingsd.tools as tools
import settingsd.tools.process
import settingsd.tools.editors
##### Private constants #####
SERVICE_NAME = "ntp_config"
......
import os
import errno
import re
from datetime import datetime
from settingsd import const
from settingsd import config
from settingsd import service
from settingsd import shared
from settingsd.tools.process import execProcess
......
......@@ -2,8 +2,6 @@
import os
import re
import shutil
from settingsd import const
from settingsd import config
......@@ -11,7 +9,6 @@ from settingsd import service
from settingsd import shared
import settingsd.tools as tools
import settingsd.tools.editors
##### Private constants #####
......
......@@ -7,7 +7,6 @@ from settingsd import service
from settingsd import shared
import settingsd.tools as tools
import settingsd.tools.dbus
##### Private constants #####
......
# -*- coding: utf-8 -*-
import socket
import os
from settingsd import const
from settingsd import config
from settingsd import service
from settingsd import shared
from settingsd import logger
from settingsd.tools.process import execProcess, SubprocessFailure
from os import path
from configparser import ConfigParser as Cfp
......
......@@ -7,7 +7,6 @@ from settingsd import service
from settingsd import shared
import settingsd.tools as tools
import settingsd.tools.dbus
import psutil
from os import getloadavg
......
......@@ -2,16 +2,11 @@
from dbus import SystemBus, Interface as DBusInterface
from settingsd import config
from settingsd import service
from settingsd import shared
from settingsd import logger
from settingsd import validators
import settingsd.tools as tools
import settingsd.tools.dbus
import settingsd.tools.process
##### Private constants #####
......
......@@ -3,7 +3,6 @@
import sys
import syslog
import getopt
from settingsd import const
......
# -*- coding: utf-8 -*-
import sys
import os
import signal
import syslog
......
......@@ -6,13 +6,9 @@ import dbus.service
import dbus.glib
import abc
from . import const
from . import config
from . import shared
from . import logger
from . import tools
from .service_decorators import *
##### Private classes #####
......
......@@ -4,5 +4,4 @@
__all__ = ["common", "network", "os"]
from .common import ValidatorError
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment