Helpermodul angelegt und Funktionen darauf umgestellt

This commit is contained in:
2018-03-08 10:43:21 +01:00
parent ab8272f199
commit a60a15690a
7 changed files with 160 additions and 143 deletions

View File

@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-5.1.dtd"> <!DOCTYPE Project SYSTEM "Project-5.1.dtd">
<!-- eric project file for project revpipyload --> <!-- eric project file for project revpipyload -->
<!-- Saved: 2017-12-03, 15:22:22 --> <!-- Saved: 2018-03-08, 10:30:46 -->
<!-- Copyright (C) 2017 Sven Sager, akira@narux.de --> <!-- Copyright (C) 2018 Sven Sager, akira@narux.de -->
<Project version="5.1"> <Project version="5.1">
<Language>en_US</Language> <Language>en_US</Language>
<Hash>89ddb4e70b339f832ee277085202b38acc6a125c</Hash> <Hash>89ddb4e70b339f832ee277085202b38acc6a125c</Hash>
<ProgLanguage mixed="0">Python3</ProgLanguage> <ProgLanguage mixed="0">Python3</ProgLanguage>
<ProjectType>Console</ProjectType> <ProjectType>Console</ProjectType>
<Description>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.</Description> <Description>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.</Description>
<Version>0.5.3</Version> <Version>0.6.0</Version>
<Author>Sven Sager</Author> <Author>Sven Sager</Author>
<Email>akira@narux.de</Email> <Email>akira@narux.de</Email>
<Eol index="1"/> <Eol index="1"/>
@@ -21,6 +21,8 @@
<Source>revpipyload/logsystem.py</Source> <Source>revpipyload/logsystem.py</Source>
<Source>revpipyload/plcsystem.py</Source> <Source>revpipyload/plcsystem.py</Source>
<Source>revpipyload/picontrolserver.py</Source> <Source>revpipyload/picontrolserver.py</Source>
<Source>revpipyload/xmlinterface.py</Source>
<Source>revpipyload/helper.py</Source>
</Sources> </Sources>
<Forms/> <Forms/>
<Translations/> <Translations/>

147
revpipyload/helper.py Normal file
View File

@@ -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)

View File

@@ -8,9 +8,9 @@
"""Modul fuer die Verwaltung der PLC-Slave Funktionen.""" """Modul fuer die Verwaltung der PLC-Slave Funktionen."""
import proginit import proginit
import socket import socket
from helper import _ipmatch
from threading import Event, Thread from threading import Event, Thread
from timeit import default_timer from timeit import default_timer
from revpipyload import _ipmatch
class RevPiSlave(Thread): class RevPiSlave(Thread):

View File

@@ -11,7 +11,7 @@ import proginit
import shlex import shlex
import subprocess import subprocess
from logsystem import PipeLogwriter from logsystem import PipeLogwriter
from proginit import _setuprt from helper import _setuprt, _zeroprocimg
from sys import stdout as sysstdout from sys import stdout as sysstdout
from threading import Event, Thread from threading import Event, Thread
from time import sleep, asctime from time import sleep, asctime
@@ -145,7 +145,7 @@ class RevPiPlc(Thread):
) )
) )
if self.zeroonerror: if self.zeroonerror:
proginit._zeroprocimg() _zeroprocimg()
proginit.logger.warning( proginit.logger.warning(
"set piControl0 to ZERO after PLC program error") "set piControl0 to ZERO after PLC program error")
@@ -153,7 +153,7 @@ class RevPiPlc(Thread):
# PLC Python Programm sauber beendet # PLC Python Programm sauber beendet
proginit.logger.info("plc program did a clean exit") proginit.logger.info("plc program did a clean exit")
if self.zeroonexit: if self.zeroonexit:
proginit._zeroprocimg() _zeroprocimg()
proginit.logger.info( proginit.logger.info(
"set piControl0 to ZERO after PLC program returns " "set piControl0 to ZERO after PLC program returns "
"clean exitcode") "clean exitcode")
@@ -221,7 +221,7 @@ class RevPiPlc(Thread):
self.exitcode = self._procplc.poll() self.exitcode = self._procplc.poll()
if self.zeroonexit and self.exitcode == 0 \ if self.zeroonexit and self.exitcode == 0 \
or self.zeroonerror and self.exitcode != 0: or self.zeroonerror and self.exitcode != 0:
proginit._zeroprocimg() _zeroprocimg()
if self._plw is not None: if self._plw is not None:
self._plw.stop() self._plw.stop()

View File

@@ -10,7 +10,6 @@ import logging
import os import os
import sys import sys
from argparse import ArgumentParser from argparse import ArgumentParser
from subprocess import Popen, PIPE
forked = False forked = False
globalconffile = None globalconffile = None
@@ -23,110 +22,6 @@ rapcatalog = None
startdir = 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(): def cleanup():
"""Clean up program.""" """Clean up program."""
# NOTE: Pidfile wirklich löschen? # NOTE: Pidfile wirklich löschen?

View File

@@ -41,8 +41,8 @@ import tarfile
import zipfile import zipfile
from concurrent import futures from concurrent import futures
from configparser import ConfigParser from configparser import ConfigParser
from helper import refullmatch
from json import loads as jloads from json import loads as jloads
from re import match as rematch
from shutil import rmtree from shutil import rmtree
from tempfile import mkstemp from tempfile import mkstemp
from threading import Event from threading import Event
@@ -50,37 +50,10 @@ from time import asctime
from xmlrpc.client import Binary from xmlrpc.client import Binary
from xmlrpc.server import SimpleXMLRPCServer from xmlrpc.server import SimpleXMLRPCServer
pyloadversion = "0.5.3" pyloadversion = "0.6.0"
re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[0-1] ?)*" 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(): class RevPiPyLoad():
"""Hauptklasse, die alle Funktionen zur Verfuegung stellt. """Hauptklasse, die alle Funktionen zur Verfuegung stellt.

View File

@@ -27,7 +27,7 @@ setup(
license="LGPLv3", license="LGPLv3",
name="revpipyload", name="revpipyload",
version="0.5.3", version="0.6.0",
scripts=["data/revpipyload"], scripts=["data/revpipyload"],