Migrationspaket-Customizing Neu ab S 39.5.0
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 Release Notes beschrieben.
- Der Status der Migrationspakete kann im jeweiligen Modul des Panels Migrationspakete überprüft werden.
Neu ab S 39.5.5
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()
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):
...
- 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
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
Klasse |
Verwendung |
StartupRunner |
Liest alle Pakete vom Dateisystem und führt alle aus mit Bei Systemstart = und Erledigt = |
DefaultRunner |
Führt alle Pakete aus bei denen Erledigt = |
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
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
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
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
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.
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
ChangeDTPPacket
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. |