Allgemein

Informationen

  • Migrationspakete werden in Python geschrieben und vom Server aufgerufen. Dadurch hat man vollen Zugriff auf die Funktionen der Python API.
  • Pakete sollten immer prüfen, ob der Zustand des Systems den Erwartungen entspricht, bevor Änderungen übernommen werden .
    Dadurch soll gewährleistet werden, dass kundenindividuelles Customizing nicht durch Pakete überschrieben wird.
  • Um korrekt als Migrationspaket erkannt zu werden, müssen Pakete von der BasePacket Basisklasse erben.
  • Für einige häufig auftauchende Fälle gibt es spezialisierte Basisklassen, die hilfreiche Methoden mitbringen.
  • Sämtliche hier aufgelisteten Klassen können von ppms.migration importiert werden.
  • Ein Paket teilt seinen Zustand über die Methoden success(), fail() und skip() an das Framework mit.
    • Diese Methoden setzen einen internen Flag. Nachdem sie aufgerufen wurden, darf kein weiterer Paketcode ausgeführt werden .
  • Mehrere Pakete können problemlos in einem Modul definiert werden.
  • Die von PLANTA mitgelieferten Migrationspakete sind in den Releases und Downloads des jeweiligen Releases aufgeführt.
  • Der Status der Migrationspakete kann im jeweiligen Modul des Panels Migrationspakete überprüft werden.

Details

  • Die Ausführungsreihenfolge ist wie folgt:
    • 1. Server-Version
    • 2. Kategorie (z.B. "Pflichtpaket")
    • 3. Dateinname

Hinweis

  • An den Dateien start_migration.py (unter /py/planta_de/ppms und /py/system/ppms) dürfen keine Änderungen vorgenommen werden.

Template

# -*- coding: utf-8 -*-
from ppms import ppms
from ppms.migration.packet import *

class ExamplePacket(BasePacket):
    '''Short 80 character line summarizing what this packet does


    A longer description that goes into more detail and explains
    what corner cases one could run into
    '''
    wi_number = None  # The workitem number this packet belongs to. Only relevant for packets by PLANTA
    version = 1
    done_after_success = True  # Sets the "Erledigt" flag after running successfully
    run_on_startup = True  # Runs this migration packet when the server is started in migration mode
    category = PacketCategory.CATEGORY_MANDATORY  # Categorizes the packet

    def fix(self, runner):
        # do something useful
        if errors:
           return self.fail('Encountered errors')

        return self.success()
PY

Hinweis

  • done_after_success = False wird bei (Hilfs-)Paketen, die das Customizing prüfen, empfohlen, sodass diese auch nach der Ausführung weiterhin im Bereich Auszuführende Pakete angezeigt werden.

Sonderfunktionen

Informationen

  • Von ppms.migration kann die StopMigrationProcessException Klasse importiert werden. Wird diese Exception von einem Paket geraised, werden danach keine weiteren Pakete ausgeführt.
  • Das ppms.migration package bringt auch zwei decorators mit, um Pakete einfach zu überspringen: skipIf und skipUnless.
@skipIf(dbms_name == 'Oracle', 'Not necessary on a Oracle db')
def fix(self, packet_runner):
    ...

@skipUnless(dbms_name == 'Oracle', 'Only necessary with a Oracle db')
def fix(self, packet_runner):
    ...
PY
  • Standardmäßig schreiben Pakete ihr Logfile als simplen Text. Dies kann jedoch bei Bedarf auch individualisiert werden. Geändert werden müssen hierzu zwei propertys in der Paketklasse:
propertyStandardwert
logging_prefixGibt standardmäßig einen Zeitstempel zurück, der vor jeden Logeintrag geschrieben wird
logfile_suffixSetzt die Endung der Logdatei standardmäßig auf .log

Best Practice

Informationen

  • Hat ein Paket mehrere Zwischenschritte, die unabhängig davon, ob sie erfolgreich oder fehlerhaft abgeschlossen wurden, problemlos wiederholt werden könnten, empfiehlt es sich die Fehler zu sammeln und am Ende der fix() Methode je nach Fehleranzahl success() oder fail() aufzurufen.
  • Führt ein Paket DML Statements aus, die nicht mit einem simplen rollback rückgängig gemacht werden können, dann sollte die rollback() Methode des Pakets implementiert werden um die Änderungen ggf. rückgängig zu machen.

Pakete ausführen (Framework)

Informationen

  • Migrationspakete werden über ein Framework vom Server ausgeführt.
  • Dieses Framework bestimmt, welche Pakete ausgeführt werden, führt diese aus und speichert ggf. das Logfile in der Datenbank.
  • Die Instanz des Frameworks, welches das Paket ausführt, wird an die fix() Methode übergeben.
  • Die Basisklasse des Frameworks ist der AbstractPacketRunner unter ppms.migration.framework.

Spezialisierte Frameworkklassen, die PLANTA mitliefert

KlasseVerwendung
StartupRunnerLiest alle Pakete vom Dateisystem und führt alle aus mit Bei Systemstart = und Erledigt =
DefaultRunnerFührt alle Pakete aus bei denen Erledigt =
SinglePacketRunnerFührt ein einzelnes Paket aus
RegtestRunnerFührt eine beliebige Anzahl von Paketen aus, schreibt aber keine Einträge in die Historietabelle
RegtestRunnerWithHistoryAbgewandelte Version vom RegtestRunner, der auch Einträge in die Historietabelle macht

Übersicht über die verschiedenen Basisklassen

BasePacket

Informationen

  • Alle Migrationspakete erben von dieser Klasse
  • Eignet sich als Basis für jede Art von Migrationsschritt

Klassenattribute

AttributErwarteter TypFunktion
versionIntegerGibt die Version des Pakets an
done_after_successBooleanSetzt den Haken in das Feld Erledigt wenn das Migrationspaket erfolgreich gelaufen ist
run_on_startupBooleanFührt das Paket aus, wenn der Server im Migrationsmodus gestartet wird

Abstrakte Methoden

MethodeFunktionMuss implementiert werden
fix(self, packet_runner)fix() wird vom Migrationsframework aufgerufen. Diese Methode beinhaltet die eigentliche Logik des PaketsJa
update(self, packet_runner, previous_packet_uuid)Die update() Methode wird aufgerufen wenn ein Paket bereits mit einer geringeren Version ausgeführt wurdeNein
rollback(self)Diese Methode wird vom Framework nach der fix() oder update() Methode aufgerufen, wenn das Paket fehlgeschlagen istNein

Nützliche Methoden

MethodeFunktion
log(self, text)

Schreibt einen übergebenen Text in das Logfile des Pakets.
Der Methode können auch Exception Instanzen übergeben werden, um diese mit vollem Traceback zu loggen.


try:
    ... # do something that might raise an error
except Exception as err:
    self.log(err) # Call log() from the except clause to get the correct stack frame!
PY
log_heading(self, text, level=0)Schreibt eine Überschrift in das Logfile. level muss ein integer zwischen 0 und 4 sein. Je höher, desto "kleiner" die Überschrift


SQLPacket

Information

  • Die SQLPacket Basisklasse bietet einige Attribute und Methoden für das Ausführen von SQL Statements

Klassenattribute

AttributWert
sql_planta_de_dbmsDer Pfad zum sql/planta_de/<dbms> Verzeichnis. Wobei <dbms> durch das jeweilige Datenbanksystem ersetzt wird (oracle/mssql)
sql_planta_ch_dbmsDer Pfad zum sql/planta_ch/<dbms> Verzeichnis. Wobei <dbms> durch das jeweilige Datenbanksystem ersetzt wird (oracle/mssql)
sql_customer_dbmsDer Pfad zum sql/customer/<dbms> Verzeichnis. Wobei <dbms> durch das jeweilige Datenbanksystem ersetzt wird (oracle/mssql)
sql_planta_de_ansiDer Pfad zum sql/planta_de/<ansi> Verzeichnis.
sql_planta_ch_ansiDer Pfad zum sql/planta_ch/<ansi> Verzeichnis.
sql_customer_ansiDer Pfad zum sql/customer/<ansi> Verzeichnis.

Methoden

MethodeFunktion
get_queries_from_file(self, fpath)Liest die Datei am angegebenen Pfad, trennt den Inhalt am Semikolon und gibt das Ergebnis als Liste zurück
modify_and_log(self, query)Führt das übergebene Statement mit db_modify aus und gibt die Anzahl der Zeilen zurück. Hierbei wird das Statement sowie die Anzahl der geänderten Zeilen in das Logfile geschrieben


DeprecatedPythonPacket

Informationen

  • Die DeprecatedPythonPacket Klasse ist nützlich wenn man obsoleten Pythoncode im System finden will.
  • Die fix() Methode wird bei dieser Klasse nicht implementiert!

Abstrakte Methoden

MethodeFunktion
get_matching_objects(self, iterable_to_filter)Diese Methode bekommt eine Liste von Instanzen. Diese Instanzen haben ein source Attribut, welches den Quelltext des Objekts beinhaltet. Die Methode muss eine Liste dieser Instanzen zurück geben, die den obsoleten Pythoncode beinhalten
introduction(self)Die introduction Methode wird aufgerufen bevor der Code durchsucht wird und kann dazu verwendet werden einen kurzen Text ins Logfile zu schreiben


Propertys

propertyFunktion
custom_server_folder_blacklistEin tuple von Ordnernamen die bei der Suche ausgeschlossen werden sollen
custom_server_file_blacklistEin tuple von Dateinamen die bei der Suche ausgeschlossen werden sollen

MigratePythonPacket

Informationen

  • Eine Klasse um Felder mit Pythoncode auf einen neueren Stand zu migrieren
  • Die Klasse nimmt es dem Customizer ab zu prüfen, ob das System einen bestimmten Zustand hat und ob die Änderung korrekt angewandt wurde
  • Um diese Funktion zu nutzen muss ein md5-Hash vom Ausgangszustand sowie dem Zielzustand generiert werden

Attribute
Die folgenden Attribute sind Konstanten die als Parameter an die migrate_python Methode gegeben werden.

AttributFeld das geändert werden soll
CU_TYPE_DATAITEMWertebereich
CU_TYPE_IRONPYTHONIronPython-Skript
CU_TYPE_DF_CONFIGDatenfeld-Konfiguration
CU_TYPE_MODULEMakro
CU_TYPE_PROCESS_RULERegel
CU_TYPE_GLOBAL_SETTINGTemplate-Code

Methoden

MethodeFunktion
migrate_python(self, before_hash, after_hash, cu_type, keys, fix_func)Prüft ob der Zustand des Systems so ist wie erwartet, macht Änderungen am System und prüft ob der Zustand danach auch den Erwartungen entspricht.

before_hash: Der md5 Hash der im System erwartet wird
after_hash: Der md5 Hash der im System erwartet wird nachdem die Änderung vollzogen wurde
cu_type: Eine der oben angeführten Konstanten
keys: Siehe unten
fix_func: Eine Funktion die Quellcode als Argument nimmt und korrigiert zurück gibt.


Werte für keys Parameter

cu_typeErwarteter DatentypErwarteter Wert
CU_TYPE_DATAITEMStringDI
CU_TYPE_IRONPYTHONListeDA als String, DF als Integer
CU_TYPE_DF_CONFIGListeDA als String, DF als Integer
CU_TYPE_MODULEStringMOD
CU_TYPE_PROCESS_RULEStringProzessregel
CU_TYPE_GLOBAL_SETTINGStringUUID

ChangeDTPPacket

Information

  • Klasse mit Methoden, um beliebige Attribute von DTP Records zu ändern


Methoden

MethodeFunktion
get_record(self, dt_num, key_list, di_list)Ein Wrapper um die ppms.search_record Methode die um Logging erweitert wurde. Gibt entweder den DTPRecord oder None zurück
verify_value(self, record, attribute, value)Funktion um den Wert von beliebigen Attributen eines Records zu prüfen. Der attribute Parameter ist die DI-Python-ID des zu prüfenden Feldes. Gibt True oder False zurück
change_value(self, record, attribute, old_value, new_value)Prüft den Zustand des Systems, vollzieht die Änderung und prüft ob die Änderung auch korrekt gespeichert wurde. Der attribute Parameter ist die DI-Python-ID des zu ändernden Feldes. Gibt True oder False zurück.