diff options
author | Hariharasubramanian R <hramasub@in.ibm.com> | 2016-04-01 07:29:39 -0500 |
---|---|---|
committer | Hariharasubramanian R <hramasub@in.ibm.com> | 2016-04-01 07:29:39 -0500 |
commit | 0ae14c7bdbed84d52c90646c132abd22df597465 (patch) | |
tree | 7f9c09a8089b0d44e26c73f2ec1d517034c6cac7 | |
parent | 448e8d839d37532d2667b9a38bb3aadb6c804e2e (diff) | |
download | phosphor-networkd-0ae14c7bdbed84d52c90646c132abd22df597465.tar.gz phosphor-networkd-0ae14c7bdbed84d52c90646c132abd22df597465.zip |
Log management service to stream journals/syslogs to a remote syslog server.
-rwxr-xr-x | logman.py | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/logman.py b/logman.py new file mode 100755 index 0000000..05ca191 --- /dev/null +++ b/logman.py @@ -0,0 +1,266 @@ +#!/usr/bin/env python + +from subprocess import call +import sys +import subprocess +import dbus +import string +import socket +import os +import fcntl +import time +import glib +import gobject +import dbus.service +import dbus.mainloop.glib + +DBUS_NAME = 'org.openbmc.LogManager' +ERRL_INTF_NAME = 'org.openbmc.Errl' +SRVC_INTF_NAME = 'org.openbmc.Service' +OBJ_NAME_RSYSLOG = '/org/openbmc/LogManager/rsyslog' + +''' + Object Path > /org/openbmc/LogManager/rsyslog + Interface:Method > org.openbmc.Service.Enable dict:string:string + Interface:Method > org.openbmc.Service.Disable +''' + +class JournalUtils (): + def _isvalidip(self, family, ipaddr): + if family == socket.AF_INET: + try: + socket.inet_pton(socket.AF_INET, ipaddr) + except AttributeError: # no inet_pton here, sorry + try: + socket.inet_aton(ipaddr) + except socket.error: + return False + return ipaddr.count('.') == 3 + except socket.error: # not a valid address + return False + + return True + + elif family == socket.AF_INET6: + try: + socket.inet_pton(socket.AF_INET6, ipaddr) + except socket.error: # not a valid address + return False + return True + + else: return False + +class Rsyslog (dbus.service.Object): + def __init__(self, bus, name): + self.bus = bus + self.name = name + dbus.service.Object.__init__(self,bus,name) + + @dbus.service.method(dbus.PROPERTIES_IFACE, "ss", "v") + def Get(self, iface, ppty): + return self.GetAll(iface)[ppty] + + @dbus.service.method(dbus.PROPERTIES_IFACE, 's', 'a{sv}') + def GetAll(self, iface): + if iface == ERRL_INTF_NAME: + status, remote_ip, remote_port = self.Status() + return {'status': status, 'ipaddr': remote_ip, 'port': remote_port } + else: + raise dbus.exceptions.DBusException('org.openbmc.UnknownInterface', + 'This object does not implement the %s interface' % iface) + + @dbus.service.method(SRVC_INTF_NAME, "a{sv}", "x") + def Enable (self, argv_dict): + remote_ip = "" + remote_port = 0 + + params = len (argv_dict) + if params > 2 : ValueError("Invalid Parameters") + + for property_name in argv_dict: + if property_name == "ipaddr": + remote_ip = argv_dict [property_name] + elif property_name == "port": + remote_port = argv_dict [property_name] + else: + raise ValueError("Invalid Argument: IP Address/Port expected.") + + if not remote_ip: + cur_remote = self._GetConfig ('Remote') + if not cur_remote: + raise ValueError("Invalid Remote Syslog IP Address") + else: + cur_remote = cur_remote[3:] + remote_ip, port_str = cur_remote.split (":") + remote_port = int(port_str) + if not util._isvalidip (socket.AF_INET, remote_ip): raise ValueError, "Malformed IP Address" + if not remote_port : remote_port = 514 + if remote_port > 65535 : raise ValueError("Invalid Remote Syslog Port") + + remote_addr = remote_ip + ":" + str(remote_port) + r = self._ModifyService('Remote', remote_addr) + + cur_options = self._GetConfig ('Options') + new_options = self._GetOptions() + + if cur_options != new_options: + r = self._ModifyService('Options', new_options) + r = self._RestartService () + + return r + + @dbus.service.method(SRVC_INTF_NAME, "as", "x") + def Disable (self, argv_list): + params = len (argv_list) + if params : ValueError("Invalid Parameters") + + remote = self._GetConfig ('Remote') + if not remote : return 0 + + r = self._ModifyService('Options', '-C') # FIXME: Restore current options minus the remote. + r = self._RestartService () + return r + + def Status (self): + remote = self._GetConfig ('Remote') + if not remote : return ("Disabled", "0.0.0.0", 0) + + cur_remote = remote[3:] + remote_ip, remote_port = cur_remote.split (":") + + options = self._GetConfig ('Options') + if not options : return ("Disabled", remote_ip, remote_port) + + if remote in options : return ("Enabled", remote_ip, remote_port) + + return ("Disabled", remote_ip, remote_port) + + def _ModifyService (self, opt, val): + if not os.path.isfile(syslog_service_bbx_file): + r = call (["cp", syslog_service_lib_file, syslog_service_bbx_file]) + r = call (["ln", "-s", syslog_service_bbx_file, syslog_service_cfg_file]) + + if not os.path.isfile(syslog_service_env_file): + env_file = open(syslog_service_env_file, 'w') + env_file.write ("OPTIONS=\"-C\"") + env_file.close() + + if opt not in OptionKeys: raise ValueError("Invalid Option") + + self._ModifyParam (opt, val) + + return 0 + + def _StopService (self): + r = call (["systemctl", "stop", "syslog"]) + r = call (["systemctl", "--no-reload", "kill", "syslog"]) + return r + + def _StartService (self): + r = call (["systemctl", "daemon-reload"]) + r = call (["systemctl", "start", "syslog"]) + return r + + def _RestartService (self): + r = self._StopService() + r = self._StartService() + return r + + def _ModifyParam (self, opt, val): + env_file = open(syslog_service_env_file, 'r') + tmp_file = open(syslog_service_tmp_file, 'w') + + optkey = OptionKeySwitchMap [opt]['key'] + for line in env_file: + if line[0] == '#': + tmp_file.write(line) + continue + curkey = line.strip().split ("=")[0] + if curkey != optkey : + tmp_file.write(line) + + tmp_file.write(optkey + "=\"" + OptionKeySwitchMap[opt]['switch'] + val + "\"" + "\n") + + env_file.close () + tmp_file.close () + + r = call (["cp", syslog_service_tmp_file, syslog_service_env_file]) + return r + + def _GetConfig (self, opt): + with open(syslog_service_env_file, "r") as f: + for line in f: + if line[0] == '#': continue + config = line.split ("=") + var = config [0] + if var == OptionKeySwitchMap[opt]['key']: + val = config [1] + val = val[1:-2] # FIXME: Why is there a trailing space ??? + return val + return "" + + def _GetOptions(self): + cfg = {} + i = 0 + + for opt in OptionKeys: + if opt == 'Options' : continue + cfg [i] = self._GetConfig(opt) + i+=1 + + options = '' + j = 0 + while j<i-1: + if cfg[j] : options += cfg [j] + j+=1 + + return options + +def main(): + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + bus = dbus.SystemBus() + name = dbus.service.BusName(DBUS_NAME, bus) + + global util + global rsys + global syslog_service_lib_file + global syslog_service_bbx_file + global syslog_service_cfg_file + global syslog_service_env_file + global syslog_service_tmp_file + global OptionKeys + global OptionKeySwitchMap + + OptionKeys = ['Options', 'Outfile', 'Priority', 'Smaller', 'RotateSize', 'RotateNum', 'Remote', 'LocalAndNet', 'DropDup', 'SharedMem', 'ConfFile', 'MarkTime', 'Printk'] + OptionKeySwitchMap = { + 'Options' : { 'switch' : "", 'key' : "OPTIONS" }, + 'Outfile' : { 'switch' : "-O ", 'key' : "OBMC_SYSLOG_OUTFILE" }, + 'Priority' : { 'switch' : "-O ", 'key' : "OBMC_SYSLOG_PRIORITY" }, + 'Smaller' : { 'switch' : "-S ", 'key' : "OBMC_SYSLOG_SMALLER" }, + 'RotateSize' : { 'switch' : "-s ", 'key' : "OBMC_SYSLOG_ROTATESIZE" }, + 'RotateNum' : { 'switch' : "-b ", 'key' : "OBMC_SYSLOG_ROTATENUM" }, + 'Remote' : { 'switch' : "-R ", 'key' : "OBMC_SYSLOG_REMOTE" }, + 'LocalAndNet' : { 'switch' : "-L ", 'key' : "OBMC_SYSLOG_LOCALNET" }, + 'DropDup' : { 'switch' : "-D ", 'key' : "OBMC_SYSLOG_DROPDUP" }, + 'SharedMem' : { 'switch' : "-C ", 'key' : "OBMC_SYSLOG_SHAREDMEM" }, + 'ConfFile' : { 'switch' : "-f ", 'key' : "OBMC_SYSLOG_CONFFILE" }, + 'MarkTime' : { 'switch' : "-m ", 'key' : "OBMC_SYSLOG_MARKTIME" }, + 'Printk' : { 'switch' : "-K ", 'key' : "OBMC_SYSLOG_PRINTK" } + } + + syslog_service_lib_file = '/lib/systemd/system/busybox-syslog.service' + syslog_service_bbx_file = '/etc/systemd/system/busybox-syslog.service' + syslog_service_cfg_file = '/etc/systemd/system/syslog.service' + syslog_service_env_file = '/etc/default/busybox-syslog' + syslog_service_tmp_file = '/tmp/busybox-syslog.tmp' + + util = JournalUtils () + rsys = Rsyslog (bus, OBJ_NAME_RSYSLOG) + + mainloop = gobject.MainLoop() + print("Started") + mainloop.run() + +if __name__ == '__main__': + sys.exit(main()) + |