diff --git a/revpipyload.e4p b/revpipyload.e4p index 146655c..2616947 100644 --- a/revpipyload.e4p +++ b/revpipyload.e4p @@ -1,15 +1,15 @@ - - + + en_US 89ddb4e70b339f832ee277085202b38acc6a125c Python3 Console Dieser Loader wird über das Init-System geladen und führt das angegebene Pythonprogramm aus. Es ist für den RevolutionPi gedacht um automatisch das SPS-Programm zu starten. - 0.5.3 + 0.6.0 Sven Sager akira@narux.de @@ -21,6 +21,8 @@ revpipyload/logsystem.py revpipyload/plcsystem.py revpipyload/picontrolserver.py + revpipyload/xmlinterface.py + revpipyload/helper.py diff --git a/revpipyload/helper.py b/revpipyload/helper.py new file mode 100644 index 0000000..59c3c39 --- /dev/null +++ b/revpipyload/helper.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +# +# RevPiPyLoad +# +# Webpage: https://revpimodio.org/revpipyplc/ +# (c) Sven Sager, License: LGPLv3 +# +"""Helperfunktionen fuer das gesamte RevPiPyLoad-System.""" +import os +import proginit +from re import match as rematch +from subprocess import Popen, PIPE + + +def _ipmatch(ipaddress, dict_acl): + """Prueft IP gegen ACL List und gibt ACL aus. + + @param ipaddress zum pruefen + @param dict_acl ACL Dict gegen die IP zu pruefen ist + @return int() ACL Wert oder -1 wenn nicht gefunden + + """ + for aclip in sorted(dict_acl, reverse=True): + regex = aclip.replace(".", "\\.").replace("*", "\\d{1,3}") + if refullmatch(regex, ipaddress): + return dict_acl[aclip] + return -1 + + +def _setuprt(pid, evt_exit): + """Konfiguriert Programm fuer den RT-Scheduler. + @param pid PID, der angehoben werden soll + @return None""" + if proginit.logger is not None: + proginit.logger.debug("enter _setuprt()") + + dict_change = { + "ksoftirqd/0,ksoftirqd/1,ksoftirqd/2,ksoftirqd/3": 10, + "ktimersoftd/0,ktimersoftd/1,ktimersoftd/2,ktimersoftd/3": 20 + } + + for ps_change in dict_change: + # pid und prio ermitteln + kpidps = Popen([ + "/bin/ps", "-o", "pid=,rtprio=", "-C", ps_change + ], bufsize=1, stdout=PIPE) + + # Timeout nachbilden da in Python 3.2 nicht vorhanden + count = 10 + while kpidps.poll() is None: + count -= 1 + if count == 0: + kpidps.kill() + if proginit.logger is not None: + proginit.logger.error( + "ps timeout to get rt prio info - no rt active" + ) + return None + + evt_exit.wait(0.5) + if evt_exit.is_set(): + return None + + try: + kpiddat = kpidps.communicate()[0] + lst_kpids = kpiddat.split() + except: + kpidps.kill() + if proginit.logger is not None: + proginit.logger.error( + "can not get pid and prio - no rt active" + ) + return None + + while len(lst_kpids) > 0: + # Elemente paarweise übernehmen + kpid = lst_kpids.pop(0) + kprio = lst_kpids.pop(0) + + # Daten prüfen + if not kpid.isdigit(): + if proginit.logger is not None: + proginit.logger.error( + "pid={} and prio={} are not valid - no rt active" + "".format(kpid, kprio) + ) + return None + kpid = int(kpid) + + # RTPrio ermitteln + if kprio.isdigit(): + kprio = int(kprio) + else: + kprio = 0 + + if kprio < 10: + # Profile anpassen + ec = os.system("/usr/bin/env chrt -fp {} {}".format( + dict_change[ps_change], kpid + )) + if ec != 0: + if proginit.logger is not None: + proginit.logger.error( + "could not adjust scheduler - no rt active" + ) + return None + + # SCHED_RR für pid setzen + if proginit.logger is not None: + proginit.logger.info("set scheduler profile of pid {}".format(pid)) + + ec = os.system("/usr/bin/env chrt -p 1 {}".format(pid)) + if ec != 0 and proginit.logger is not None: + proginit.logger.error( + "could not set scheduler profile of pid {}" + "".format(pid) + ) + + if proginit.logger is not None: + proginit.logger.debug("leave _setuprt()") + + +def _zeroprocimg(): + """Setzt Prozessabbild auf NULL.""" + procimg = "/dev/piControl0" if proginit.pargs is None \ + else proginit.pargs.procimg + + if os.access(procimg, os.W_OK): + with open(procimg, "w+b", 0) as f: + f.write(bytes(4096)) + else: + if proginit.logger is not None: + proginit.logger.error( + "zeroprocimg can not write to piControl device" + ) + + +def refullmatch(regex, string): + """re.fullmatch wegen alter python version aus wheezy nachgebaut. + + @param regex RegEx Statement + @param string Zeichenfolge gegen die getestet wird + @return True, wenn komplett passt sonst False + + """ + m = rematch(regex, string) + return m is not None and m.end() == len(string) diff --git a/revpipyload/picontrolserver.py b/revpipyload/picontrolserver.py index 2acf263..5ac32fa 100644 --- a/revpipyload/picontrolserver.py +++ b/revpipyload/picontrolserver.py @@ -8,9 +8,9 @@ """Modul fuer die Verwaltung der PLC-Slave Funktionen.""" import proginit import socket +from helper import _ipmatch from threading import Event, Thread from timeit import default_timer -from revpipyload import _ipmatch class RevPiSlave(Thread): diff --git a/revpipyload/plcsystem.py b/revpipyload/plcsystem.py index eb8b867..aca9587 100644 --- a/revpipyload/plcsystem.py +++ b/revpipyload/plcsystem.py @@ -11,7 +11,7 @@ import proginit import shlex import subprocess from logsystem import PipeLogwriter -from proginit import _setuprt +from helper import _setuprt, _zeroprocimg from sys import stdout as sysstdout from threading import Event, Thread from time import sleep, asctime @@ -145,7 +145,7 @@ class RevPiPlc(Thread): ) ) if self.zeroonerror: - proginit._zeroprocimg() + _zeroprocimg() proginit.logger.warning( "set piControl0 to ZERO after PLC program error") @@ -153,7 +153,7 @@ class RevPiPlc(Thread): # PLC Python Programm sauber beendet proginit.logger.info("plc program did a clean exit") if self.zeroonexit: - proginit._zeroprocimg() + _zeroprocimg() proginit.logger.info( "set piControl0 to ZERO after PLC program returns " "clean exitcode") @@ -221,7 +221,7 @@ class RevPiPlc(Thread): self.exitcode = self._procplc.poll() if self.zeroonexit and self.exitcode == 0 \ or self.zeroonerror and self.exitcode != 0: - proginit._zeroprocimg() + _zeroprocimg() if self._plw is not None: self._plw.stop() diff --git a/revpipyload/proginit.py b/revpipyload/proginit.py index fe0b69e..9583afb 100644 --- a/revpipyload/proginit.py +++ b/revpipyload/proginit.py @@ -10,7 +10,6 @@ import logging import os import sys from argparse import ArgumentParser -from subprocess import Popen, PIPE forked = False globalconffile = None @@ -23,110 +22,6 @@ rapcatalog = None startdir = None -def _setuprt(pid, evt_exit): - """Konfiguriert Programm fuer den RT-Scheduler. - @param pid PID, der angehoben werden soll - @return None""" - if logger is not None: - logger.debug("enter _setuprt()") - - dict_change = { - "ksoftirqd/0,ksoftirqd/1,ksoftirqd/2,ksoftirqd/3": 10, - "ktimersoftd/0,ktimersoftd/1,ktimersoftd/2,ktimersoftd/3": 20 - } - - for ps_change in dict_change: - # pid und prio ermitteln - kpidps = Popen([ - "/bin/ps", "-o", "pid=,rtprio=", "-C", ps_change - ], bufsize=1, stdout=PIPE) - - # Timeout nachbilden da in Python 3.2 nicht vorhanden - count = 10 - while kpidps.poll() is None: - count -= 1 - if count == 0: - kpidps.kill() - if logger is not None: - logger.error( - "ps timeout to get rt prio info - no rt active" - ) - return None - - evt_exit.wait(0.5) - if evt_exit.is_set(): - return None - - try: - kpiddat = kpidps.communicate()[0] - lst_kpids = kpiddat.split() - except: - kpidps.kill() - if logger is not None: - logger.error( - "can not get pid and prio - no rt active" - ) - return None - - while len(lst_kpids) > 0: - # Elemente paarweise übernehmen - kpid = lst_kpids.pop(0) - kprio = lst_kpids.pop(0) - - # Daten prüfen - if not kpid.isdigit(): - if logger is not None: - logger.error( - "pid={} and prio={} are not valid - no rt active" - "".format(kpid, kprio) - ) - return None - kpid = int(kpid) - - # RTPrio ermitteln - if kprio.isdigit(): - kprio = int(kprio) - else: - kprio = 0 - - if kprio < 10: - # Profile anpassen - ec = os.system("/usr/bin/env chrt -fp {} {}".format( - dict_change[ps_change], kpid - )) - if ec != 0: - if logger is not None: - logger.error( - "could not adjust scheduler - no rt active" - ) - return None - - # SCHED_RR für pid setzen - if logger is not None: - logger.info("set scheduler profile of pid {}".format(pid)) - - ec = os.system("/usr/bin/env chrt -p 1 {}".format(pid)) - if ec != 0 and logger is not None: - logger.error( - "could not set scheduler profile of pid {}" - "".format(pid) - ) - - if logger is not None: - logger.debug("leave _setuprt()") - - -def _zeroprocimg(): - """Setzt Prozessabbild auf NULL.""" - procimg = "/dev/piControl0" if pargs is None else pargs.procimg - if os.access(procimg, os.W_OK): - with open(procimg, "w+b", 0) as f: - f.write(bytes(4096)) - else: - if logger is not None: - logger.error("zeroprocimg can not write to piControl device") - - def cleanup(): """Clean up program.""" # NOTE: Pidfile wirklich löschen? diff --git a/revpipyload/revpipyload.py b/revpipyload/revpipyload.py index 3c7392c..f4261f9 100755 --- a/revpipyload/revpipyload.py +++ b/revpipyload/revpipyload.py @@ -41,8 +41,8 @@ import tarfile import zipfile from concurrent import futures from configparser import ConfigParser +from helper import refullmatch from json import loads as jloads -from re import match as rematch from shutil import rmtree from tempfile import mkstemp from threading import Event @@ -50,37 +50,10 @@ from time import asctime from xmlrpc.client import Binary from xmlrpc.server import SimpleXMLRPCServer -pyloadversion = "0.5.3" +pyloadversion = "0.6.0" re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[0-1] ?)*" -def _ipmatch(ipaddress, dict_acl): - """Prueft IP gegen ACL List und gibt ACL aus. - - @param ipaddress zum pruefen - @param dict_acl ACL Dict gegen die IP zu pruefen ist - @return int() ACL Wert oder -1 wenn nicht gefunden - - """ - for aclip in sorted(dict_acl, reverse=True): - regex = aclip.replace(".", "\\.").replace("*", "\\d{1,3}") - if refullmatch(regex, ipaddress): - return dict_acl[aclip] - return -1 - - -def refullmatch(regex, string): - """re.fullmatch wegen alter python version aus wheezy nachgebaut. - - @param regex RegEx Statement - @param string Zeichenfolge gegen die getestet wird - @return True, wenn komplett passt sonst False - - """ - m = rematch(regex, string) - return m is not None and m.end() == len(string) - - class RevPiPyLoad(): """Hauptklasse, die alle Funktionen zur Verfuegung stellt. diff --git a/setup.py b/setup.py index b5bbc9a..07ca3b9 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ setup( license="LGPLv3", name="revpipyload", - version="0.5.3", + version="0.6.0", scripts=["data/revpipyload"],