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

View File

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

View File

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

View File

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

View File

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