Migrationspaket-Customizing Neu ab S 39.5.0

Allgemein

info 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.
    • stop 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 Release Notes beschrieben.
  • Im Modul Übersicht der Migrationspakete kann der Status aller Migrationspakete überprüft werden.

Neu ab S 39.5.5

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

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

warning 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

info 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):
    ...
  • 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:
property Standardwert
logging_prefix Gibt standardmäßig einen Zeitstempel zurück, der vor jeden Logeintrag geschrieben wird
logfile_suffix Setzt die Endung der Logdatei standardmäßig auf .log

Best Practice

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

info 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

Klasse Verwendung
StartupRunner Liest alle Pakete vom Dateisystem und führt alle aus mit Bei Systemstart = checked und Erledigt = unchecked
DefaultRunner Führt alle Pakete aus bei denen Erledigt = unchecked
SinglePacketRunner Führt ein einzelnes Paket aus
RegtestRunner Führt eine beliebige Anzahl von Paketen aus, schreibt aber keine Einträge in die Historietabelle
RegtestRunnerWithHistory Abgewandelte Version vom RegtestRunner, der auch Einträge in die Historietabelle macht

Übersicht über die verschiedenen Basisklassen

BasePacket

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

Klassenattribute

Attribut Erwarteter Typ Funktion
version Integer Gibt die Version des Pakets an
done_after_success Boolean Setzt den Haken in das Feld Erledigt wenn das Migrationspaket erfolgreich gelaufen ist
run_on_startup Boolean Führt das Paket aus, wenn der Server im Migrationsmodus gestartet wird

Abstrakte Methoden

Methode Funktion Muss implementiert werden
fix(self, packet_runner) fix() wird vom Migrationsframework aufgerufen. Diese Methode beinhaltet die eigentliche Logik des Pakets Ja
update(self, packet_runner, previous_packet_uuid) Die update() Methode wird aufgerufen wenn ein Paket bereits mit einer geringeren Version ausgeführt wurde Nein
rollback(self) Diese Methode wird vom Framework nach der fix() oder update() Methode aufgerufen, wenn das Paket fehlgeschlagen ist Nein

Nützliche Methoden

Methode Funktion
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!
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

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

Klassenattribute

Attribut Wert
sql_planta_de_dbms Der Pfad zum sql/planta_de/<dbms> Verzeichnis. Wobei <dbms> durch das jeweilige Datenbanksystem ersetzt wird (oracle/mssql)
sql_planta_ch_dbms Der Pfad zum sql/planta_ch/<dbms> Verzeichnis. Wobei <dbms> durch das jeweilige Datenbanksystem ersetzt wird (oracle/mssql)
sql_customer_dbms Der Pfad zum sql/customer/<dbms> Verzeichnis. Wobei <dbms> durch das jeweilige Datenbanksystem ersetzt wird (oracle/mssql)
sql_planta_de_ansi Der Pfad zum sql/planta_de/<ansi> Verzeichnis.
sql_planta_ch_ansi Der Pfad zum sql/planta_ch/<ansi> Verzeichnis.
sql_customer_ansi Der Pfad zum sql/customer/<ansi> Verzeichnis.

Methoden

Methode Funktion
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

info 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

Methode Funktion
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

property Funktion
custom_server_folder_blacklist Ein tuple von Ordnernamen die bei der Suche ausgeschlossen werden sollen
custom_server_file_blacklist Ein tuple von Dateinamen die bei der Suche ausgeschlossen werden sollen

MigratePythonPacket

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

Attribut Feld das geändert werden soll
CU_TYPE_DATAITEM Wertebereich
CU_TYPE_IRONPYTHON IronPython-Skript
CU_TYPE_DF_CONFIG Datenfeld-Konfiguration
CU_TYPE_MODULE Makro
CU_TYPE_PROCESS_RULE Regel
CU_TYPE_GLOBAL_SETTING Template-Code

Methoden

Methode Funktion
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_type Erwarteter Datentyp Erwarteter Wert
CU_TYPE_DATAITEM String DI
CU_TYPE_IRONPYTHON Liste DA als String, DF als Integer
CU_TYPE_DF_CONFIG Liste DA als String, DF als Integer
CU_TYPE_MODULE String MOD
CU_TYPE_PROCESS_RULE String Prozessregel
CU_TYPE_GLOBAL_SETTING String UUID

ChangeDTPPacket

info Information
  • Klasse mit Methoden, um beliebige Attribute von DTP Records zu ändern
Methoden
Methode Funktion
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.





 
  • Suche in Topic-Namen

  • Suche in Topic-Inhalten