#!/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