diff --git a/data/etc/revpipyload/revpipyload.conf b/data/etc/revpipyload/revpipyload.conf
index 71ed1ab..89ccd4d 100644
--- a/data/etc/revpipyload/revpipyload.conf
+++ b/data/etc/revpipyload/revpipyload.conf
@@ -1,17 +1,24 @@
[DEFAULT]
autoreload = 1
+autoreloaddelay = 5
autostart = 1
plcworkdir = /var/lib/revpipyload
plcprogram = program.py
plcarguments =
plcuid = 1000
plcgid = 1000
-plcslave = 0
-plcslaveacl =
-plcslaveport = 55234
pythonversion = 3
rtlevel = 0
-xmlrpc = 0
-xmlrpcacl =
zeroonerror = 0
zeroonexit = 0
+
+[PLCSLAVE]
+plcslave = 0
+acl =
+bindip = *
+port = 55234
+
+[XMLRPC]
+xmlrpc = 0
+acl =
+bindip = *
diff --git a/doc/helper.html b/doc/helper.html
index 5a3e665..fac8094 100644
--- a/doc/helper.html
+++ b/doc/helper.html
@@ -74,8 +74,8 @@ Methods
get_acllevel |
Prueft IP gegen ACL List und gibt ACL-Wert aus. |
-| valid_acl_string |
-Prueft ob ein ACL-String gueltig ist. |
+loadacl |
+Laed ACL String und gibt erfolg zurueck. |
@@ -135,17 +135,21 @@ zum pruefen
ACL Wert oder -1 wenn nicht gefunden
-
+
-IpAclManager.valid_acl_string
-valid_acl_string(str_acl)
+IpAclManager.loadacl
+loadacl(str_acl)
-Prueft ob ein ACL-String gueltig ist.
+Laed ACL String und gibt erfolg zurueck.
- str_acl
-
- zum ueberpruefen
- return ACL Level als
+ACL als
+
+
+- Returns:
+-
+True, wenn erfolgreich uebernommen
diff --git a/doc/xrpcserver.html b/doc/xrpcserver.html
index ed0f8c0..8ff5aec 100644
--- a/doc/xrpcserver.html
+++ b/doc/xrpcserver.html
@@ -101,9 +101,15 @@ Methods
SaveXMLRPCServer |
Init SaveXMLRPCServer class. |
+| _dispatch |
+Prueft ACL Level fuer angeforderte Methode. |
+
| isAlive |
Prueft ob der XML RPC Server laeuft. |
+| register_function |
+Override register_function to add acl_level. |
+
| start |
Startet den XML-RPC Server. |
@@ -122,7 +128,26 @@ SaveXMLRPCServer (Constructor)
SaveXMLRPCServer(addr, logRequests=True, allow_none=False, use_builtin_types=False, ipacl=IpAclManager())
Init SaveXMLRPCServer class.
-
+
+
+SaveXMLRPCServer._dispatch
+_dispatch(method, params)
+
+Prueft ACL Level fuer angeforderte Methode.
+
+- method
+-
+Angeforderte Methode
+
- params
+-
+Argumente fuer Methode
+
+
+- Returns:
+-
+Dispatched data
+
+
SaveXMLRPCServer.isAlive
isAlive()
@@ -133,6 +158,23 @@ Prueft ob der XML RPC Server laeuft.
True, wenn Server noch laeuft
+
+
+SaveXMLRPCServer.register_function
+register_function(acl_level, function, name=None)
+
+Override register_function to add acl_level.
+
+- acl_level
+-
+ACL level to call this function
+
- function
+-
+Function to register
+
- name
+-
+Alternative name to use
+
SaveXMLRPCServer.start
diff --git a/eric-revpipyload.api b/eric-revpipyload.api
index 382abc0..a6a64d2 100644
--- a/eric-revpipyload.api
+++ b/eric-revpipyload.api
@@ -3,8 +3,8 @@ helper.IpAclManager.__get_regex_acl?6()
helper.IpAclManager.__set_acl?6(value)
helper.IpAclManager.acl?7
helper.IpAclManager.get_acllevel?4(ipaddress)
+helper.IpAclManager.loadacl?4(str_acl)
helper.IpAclManager.regex_acl?7
-helper.IpAclManager.valid_acl_string?4(str_acl)
helper.IpAclManager?1(acl=None, minlevel=0, maxlevel=0)
helper._setuprt?5(pid, evt_exit)
helper._zeroprocimg?5()
@@ -85,7 +85,9 @@ revpipyload.RevPiPyLoad.xml_setpictoryrsc?4(filebytes, reset=False)
revpipyload.RevPiPyLoad?1()
revpipyload.pyloadversion?7
xrpcserver.SaveXMLRPCRequestHandler.parse_request?4()
+xrpcserver.SaveXMLRPCServer._dispatch?5(method, params)
xrpcserver.SaveXMLRPCServer.isAlive?4()
+xrpcserver.SaveXMLRPCServer.register_function?4(acl_level, function, name=None)
xrpcserver.SaveXMLRPCServer.start?4()
xrpcserver.SaveXMLRPCServer.stop?4()
xrpcserver.SaveXMLRPCServer?1(addr, logRequests=True, allow_none=False, use_builtin_types=False, ipacl=IpAclManager())
diff --git a/revpipyload/helper.py b/revpipyload/helper.py
index 870bc96..2e9e3bc 100644
--- a/revpipyload/helper.py
+++ b/revpipyload/helper.py
@@ -50,7 +50,7 @@ class IpAclManager():
if type(value) != str:
raise ValueError("parameter acl must be ")
- if not self.valid_acl_string(value):
+ if not refullmatch(self.__re_ipacl, value):
raise ValueError("acl format ist not okay - 1.2.3.4,0 5.6.7.8,1")
# Klassenwerte übernehmen
@@ -82,11 +82,14 @@ class IpAclManager():
return -1
- def valid_acl_string(self, str_acl):
- """Prueft ob ein ACL-String gueltig ist.
- @param str_acl zum ueberpruefen
- return ACL Level als """
- return refullmatch(self.__re_ipacl, str_acl)
+ def loadacl(self, str_acl):
+ """Laed ACL String und gibt erfolg zurueck.
+ @param str_acl ACL als
+ @return True, wenn erfolgreich uebernommen"""
+ if refullmatch(self.__re_ipacl, str_acl):
+ self.__set_acl(str_acl)
+ return True
+ return False
acl = property(__get_acl, __set_acl)
regex_acl = property(__get_regex_acl)
diff --git a/revpipyload/procimgserver.py b/revpipyload/procimgserver.py
index a2cb0b7..cf86d95 100644
--- a/revpipyload/procimgserver.py
+++ b/revpipyload/procimgserver.py
@@ -173,13 +173,12 @@ class ProcimgServer():
# Registriere Funktionen
for xmlfunc in self.xmlreadfuncs:
self.xmlsrv.register_function(
- self.xmlreadfuncs[xmlfunc], xmlfunc
+ 1, self.xmlreadfuncs[xmlfunc], xmlfunc
+ )
+ for xmlfunc in self.xmlwritefuncs:
+ self.xmlsrv.register_function(
+ 3, self.xmlwritefuncs[xmlfunc], xmlfunc
)
- if self.acl >= 3:
- for xmlfunc in self.xmlwritefuncs:
- self.xmlsrv.register_function(
- self.xmlwritefuncs[xmlfunc], xmlfunc
- )
ec = True
proginit.logger.debug("leave ProcimgServer.start()")
diff --git a/revpipyload/revpipyload.py b/revpipyload/revpipyload.py
index 75839b7..7e30af5 100755
--- a/revpipyload/revpipyload.py
+++ b/revpipyload/revpipyload.py
@@ -108,50 +108,78 @@ class RevPiPyLoad():
)
self.globalconfig.read(proginit.globalconffile)
- # Konfiguration verarbeiten
+ # Konfiguration verarbeiten [DEFAULT]
self.autoreload = \
int(self.globalconfig["DEFAULT"].get("autoreload", 1))
+ self.autoreloaddelay = \
+ int(self.globalconfig["DEFAULT"].get("autoreloaddelay", 5))
self.autostart = \
int(self.globalconfig["DEFAULT"].get("autostart", 0))
- self.plcprog = \
+ self.plcworkdir = \
+ self.globalconfig["DEFAULT"].get("plcworkdir", ".")
+ self.plcprogram = \
self.globalconfig["DEFAULT"].get("plcprogram", "none.py")
self.plcarguments = \
self.globalconfig["DEFAULT"].get("plcarguments", "")
- self.plcworkdir = \
- self.globalconfig["DEFAULT"].get("plcworkdir", ".")
-
- # PLC Slave ACL laden und prüfen
- self.plcslave = \
- int(self.globalconfig["DEFAULT"].get("plcslave", 0))
- self.plcslaveacl = IpAclManager(minlevel=0, maxlevel=1)
- str_acl = self.globalconfig["DEFAULT"].get("plcslaveacl", "")
- if not self.plcslaveacl.valid_acl_string(str_acl):
- proginit.logger.warning("can not load plcslaveacl - wrong format")
- else:
- self.plcslaveacl.acl = str_acl
- self.plcslaveport = \
- int(self.globalconfig["DEFAULT"].get("plcslaveport", 55234))
-
- self.pythonver = \
+ self.plcuid = \
+ int(self.globalconfig["DEFAULT"].get("plcuid", 65534))
+ self.plcgid = \
+ int(self.globalconfig["DEFAULT"].get("plcgid", 65534))
+ self.pythonversion = \
int(self.globalconfig["DEFAULT"].get("pythonversion", 3))
self.rtlevel = \
int(self.globalconfig["DEFAULT"].get("rtlevel", 0))
-
- # XML ACL laden und prüfen
- self.xmlrpc = \
- int(self.globalconfig["DEFAULT"].get("xmlrpc", 0))
- self.xmlrpcacl = IpAclManager(minlevel=0, maxlevel=3)
- str_acl = self.globalconfig["DEFAULT"].get("xmlrpcacl", "")
- if not self.xmlrpcacl.valid_acl_string(str_acl):
- proginit.logger.warning("can not load xmlrpcacl - wrong format")
- else:
- self.xmlrpcacl.acl = str_acl
-
self.zeroonerror = \
int(self.globalconfig["DEFAULT"].get("zeroonerror", 1))
self.zeroonexit = \
int(self.globalconfig["DEFAULT"].get("zeroonexit", 1))
+ # Konfiguration verarbeiten [PLCSLAVE]
+ self.plcslave = 0
+ if "PLCSLAVE" in self.globalconfig:
+ self.plcslave = \
+ int(self.globalconfig["PLCSLAVE"].get("plcslave", 0))
+ self.plcslaveacl = IpAclManager(minlevel=0, maxlevel=1)
+ if not self.plcslaveacl.loadacl(
+ self.globalconfig["PLCSLAVE"].get("acl", "")):
+ proginit.logger.warning(
+ "can not load plcslave acl - wrong format"
+ )
+
+ # Bind IP lesen und anpassen
+ self.plcslavebindip = \
+ self.globalconfig["PLCSLAVE"].get("bindip", "127.0.0.1")
+ if self.plcslavebindip == "*":
+ self.plcslavebindip = ""
+ elif self.plcslavebindip == "":
+ self.plcslavebindip = "127.0.0.1"
+
+ self.plcslaveport = \
+ int(self.globalconfig["PLCSLAVE"].get("port", 55234))
+
+ # Konfiguration verarbeiten [XMLRPC]
+ self.xmlrpc = 0
+ if "XMLRPC" in self.globalconfig:
+ self.xmlrpc = \
+ int(self.globalconfig["XMLRPC"].get("xmlrpc", 0))
+ self.xmlrpcacl = IpAclManager(minlevel=0, maxlevel=3)
+ if not self.xmlrpcacl.loadacl(
+ self.globalconfig["XMLRPC"].get("acl", "")):
+ proginit.logger.warning(
+ "can not load xmlrpc acl - wrong format"
+ )
+
+ # Bind IP lesen und anpassen
+ self.xmlrpcbindip = \
+ self.globalconfig["XMLRPC"].get("bindip", "127.0.0.1")
+ if self.xmlrpcbindip == "*":
+ self.xmlrpcbindip = ""
+ elif self.xmlrpcbindip == "":
+ self.xmlrpcbindip = "127.0.0.1"
+
+ self.xmlrpcport = \
+ int(self.globalconfig["XMLRPC"].get("port", 55123))
+
# Workdirectory wechseln
if not os.access(self.plcworkdir, os.R_OK | os.W_OK | os.X_OK):
raise ValueError(
@@ -159,18 +187,15 @@ class RevPiPyLoad():
)
os.chdir(self.plcworkdir)
- # PLC Thread konfigurieren
+ # PLC Threads konfigurieren
self.plc = self._plcthread()
self.th_plcslave = self._plcslave()
# XMLRPC-Server Instantiieren und konfigurieren
- if self.xmlrpc >= 1:
+ if self.xmlrpc == 1:
proginit.logger.debug("create xmlrpc server")
self.xsrv = SaveXMLRPCServer(
- (
- "",
- int(self.globalconfig["DEFAULT"].get("xmlrpcport", 55123))
- ),
+ (self.xmlrpcbindip, self.xmlrpcport),
logRequests=False,
allow_none=True,
ipacl=self.xmlrpcacl
@@ -178,17 +203,27 @@ class RevPiPyLoad():
self.xsrv.register_introspection_functions()
self.xsrv.register_multicall_functions()
+ # Allgemeine Funktionen
+ self.xsrv.register_function(0, lambda: pyloadversion, "version")
+ self.xsrv.register_function(0, lambda acl: acl, "xmlmodus")
+
# XML Modus 1 Nur Logs lesen und PLC Programm neu starten
- self.xsrv.register_function(self.logr.load_applog, "load_applog")
- self.xsrv.register_function(self.logr.load_plclog, "load_plclog")
- self.xsrv.register_function(self.xml_plcexitcode, "plcexitcode")
- self.xsrv.register_function(self.xml_plcrunning, "plcrunning")
- self.xsrv.register_function(self.xml_plcstart, "plcstart")
- self.xsrv.register_function(self.xml_plcstop, "plcstop")
- self.xsrv.register_function(self.xml_reload, "reload")
self.xsrv.register_function(
- self.xml_plcslaverunning, "plcslaverunning"
- )
+ 0, self.logr.load_applog, "load_applog")
+ self.xsrv.register_function(
+ 0, self.logr.load_plclog, "load_plclog")
+ self.xsrv.register_function(
+ 0, self.xml_plcexitcode, "plcexitcode")
+ self.xsrv.register_function(
+ 0, self.xml_plcrunning, "plcrunning")
+ self.xsrv.register_function(
+ 0, self.xml_plcstart, "plcstart")
+ self.xsrv.register_function(
+ 0, self.xml_plcstop, "plcstop")
+ self.xsrv.register_function(
+ 0, self.xml_reload, "reload")
+ self.xsrv.register_function(
+ 0, self.xml_plcslaverunning, "plcslaverunning")
# Erweiterte Funktionen anmelden
try:
@@ -196,8 +231,8 @@ class RevPiPyLoad():
self.xml_ps = procimgserver.ProcimgServer(
self.xsrv, self.xmlrpc
)
- self.xsrv.register_function(self.xml_psstart, "psstart")
- self.xsrv.register_function(self.xml_psstop, "psstop")
+ self.xsrv.register_function(1, self.xml_psstart, "psstart")
+ self.xsrv.register_function(1, self.xml_psstop, "psstop")
except:
self.xml_ps = None
proginit.logger.warning(
@@ -208,38 +243,36 @@ class RevPiPyLoad():
)
# XML Modus 2 Einstellungen lesen und Programm herunterladen
- if self.xmlrpc >= 2:
- self.xsrv.register_function(
- self.xml_getconfig, "get_config")
- self.xsrv.register_function(
- self.xml_getfilelist, "get_filelist")
- self.xsrv.register_function(
- self.xml_getpictoryrsc, "get_pictoryrsc")
- self.xsrv.register_function(
- self.xml_getprocimg, "get_procimg")
- self.xsrv.register_function(
- self.xml_plcdownload, "plcdownload")
+ self.xsrv.register_function(
+ 2, self.xml_getconfig, "get_config")
+ self.xsrv.register_function(
+ 2, self.xml_getfilelist, "get_filelist")
+ self.xsrv.register_function(
+ 2, self.xml_getpictoryrsc, "get_pictoryrsc")
+ self.xsrv.register_function(
+ 2, self.xml_getprocimg, "get_procimg")
+ self.xsrv.register_function(
+ 2, self.xml_plcdownload, "plcdownload")
# XML Modus 3 Programm und Konfiguration hochladen
- if self.xmlrpc >= 3:
- self.xsrv.register_function(
- self.xml_plcupload, "plcupload")
- self.xsrv.register_function(
- self.xml_plcuploadclean, "plcuploadclean")
- self.xsrv.register_function(
- lambda: os.system(proginit.picontrolreset),
- "resetpicontrol")
- self.xsrv.register_function(
- self.xml_plcslavestart, "plcslavestart")
- self.xsrv.register_function(
- self.xml_plcslavestop, "plcslavestop")
- self.xsrv.register_function(
- self.xml_setconfig, "set_config")
- self.xsrv.register_function(
- self.xml_setpictoryrsc, "set_pictoryrsc")
+ self.xsrv.register_function(
+ 3, self.xml_plcupload, "plcupload")
+ self.xsrv.register_function(
+ 3, self.xml_plcuploadclean, "plcuploadclean")
+ self.xsrv.register_function(
+ 3,
+ lambda: os.system(proginit.picontrolreset),
+ "resetpicontrol"
+ )
+ self.xsrv.register_function(
+ 3, self.xml_plcslavestart, "plcslavestart")
+ self.xsrv.register_function(
+ 3, self.xml_plcslavestop, "plcslavestop")
+ self.xsrv.register_function(
+ 3, self.xml_setconfig, "set_config")
+ self.xsrv.register_function(
+ 3, self.xml_setpictoryrsc, "set_pictoryrsc")
- self.xsrv.register_function(lambda: pyloadversion, "version")
- self.xsrv.register_function(lambda: self.xmlrpc, "xmlmodus")
proginit.logger.debug("created xmlrpc server")
if pauseproc:
@@ -257,21 +290,21 @@ class RevPiPyLoad():
th_plc = None
# Prüfen ob Programm existiert
- if not os.path.exists(os.path.join(self.plcworkdir, self.plcprog)):
+ if not os.path.exists(os.path.join(self.plcworkdir, self.plcprogram)):
proginit.logger.error("plc file does not exists {}".format(
- os.path.join(self.plcworkdir, self.plcprog)
+ os.path.join(self.plcworkdir, self.plcprogram)
))
return None
proginit.logger.debug("create PLC watcher")
th_plc = plcsystem.RevPiPlc(
- os.path.join(self.plcworkdir, self.plcprog),
+ os.path.join(self.plcworkdir, self.plcprogram),
self.plcarguments,
- self.pythonver
+ self.pythonversion
)
th_plc.autoreload = self.autoreload
- th_plc.gid = int(self.globalconfig["DEFAULT"].get("plcgid", 65534))
- th_plc.uid = int(self.globalconfig["DEFAULT"].get("plcuid", 65534))
+ th_plc.gid = self.plcgid
+ th_plc.uid = self.plcuid
th_plc.rtlevel = self.rtlevel
th_plc.zeroonerror = self.zeroonerror
th_plc.zeroonexit = self.zeroonexit
@@ -459,12 +492,12 @@ class RevPiPyLoad():
dc["autoreload"] = self.autoreload
dc["autostart"] = self.autostart
dc["plcworkdir"] = self.plcworkdir
- dc["plcprogram"] = self.plcprog
+ dc["plcprogram"] = self.plcprogram
dc["plcarguments"] = self.plcarguments
dc["plcslave"] = self.plcslave
dc["plcslaveacl"] = self.plcslaveacl.acl
dc["plcslaveport"] = self.plcslaveport
- dc["pythonversion"] = self.pythonver
+ dc["pythonversion"] = self.pythonversion
dc["rtlevel"] = self.rtlevel
dc["xmlrpc"] = self.xmlrpc
dc["xmlrpcacl"] = self.xmlrpcacl.acl
diff --git a/revpipyload/xrpcserver.py b/revpipyload/xrpcserver.py
index f6f6a0d..2320006 100644
--- a/revpipyload/xrpcserver.py
+++ b/revpipyload/xrpcserver.py
@@ -35,16 +35,52 @@ class SaveXMLRPCServer(SimpleXMLRPCServer):
# Klassenvariablen
self.aclmgr = ipacl
+ self.funcacls = {}
+ self.requestacl = -1
self.tpe = futures.ThreadPoolExecutor(max_workers=1)
self.fut = None
proginit.logger.debug("leave SaveXMLRPCServer.__init__()")
+ def _dispatch(self, method, params):
+ """Prueft ACL Level fuer angeforderte Methode.
+
+ @param method Angeforderte Methode
+ @param params Argumente fuer Methode
+ @return Dispatched data
+
+ """
+ # ACL Level für angeforderte Methode prüfen
+ if self.requestacl < self.funcacls.get(method, -1):
+ raise RuntimeError("function call not allowed")
+
+ # ACL Mode abfragen (Gibt ACL Level als Parameter)
+ if method == "xmlmodus":
+ params = (self.requestacl, )
+
+ return super()._dispatch(method, params)
+
def isAlive(self):
"""Prueft ob der XML RPC Server laeuft.
@return True, wenn Server noch laeuft"""
return False if self.fut is None else self.fut.running()
+ def register_function(self, acl_level, function, name=None):
+ """Override register_function to add acl_level.
+
+ @param acl_level ACL level to call this function
+ @param function Function to register
+ @param name Alternative name to use
+
+ """
+ if type(acl_level) != int:
+ raise ValueError("parameter acl_level must be ")
+
+ if name is None:
+ name = function.__name__
+ self.funcs[name] = function
+ self.funcacls[name] = acl_level
+
def start(self):
"""Startet den XML-RPC Server."""
proginit.logger.debug("enter SaveXMLRPCServer.start()")
@@ -83,15 +119,15 @@ class SaveXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
if not super().parse_request():
return False
- # IP-Adresse prüfen
- int_acl = self.server.aclmgr.get_acllevel(self.address_string())
- if int_acl >= 0:
+ # ACL für IP-Adresse übernehmen
+ self.server.requestacl = \
+ self.server.aclmgr.get_acllevel(self.address_string())
+
+ if self.server.requestacl >= 0:
return True
else:
self.send_error(
- 401,
- "IP '{}' not allowed with acl level '{}'"
- "".format(self.address_string(), int_acl)
+ 401, "IP '{}' not allowed".format(self.address_string())
)
return False