SDB:KIWI Kochbuch Datentrennung
Getestet mit openSUSE | Empfohlene Artikel | Verwandte Artikel | |||
|
Inhaltsverzeichnis
Datentrennung oder Handhabung der Partitionierung
Dieses Beispiel unterstützt einen einfachen Denkansatz zur Trennung der Anwendungsdaten von den Dateien des Betriebssystems.
Immer wenn die Verwendung eines OEM-Abbildes diskutiert wird, in irgend einer Form der Einrichtung, scheint es unvermeidlich, dass irgend jemand nach der Partitionierung fragt. Wie auch immer, woran die meisten Menschen wirklich interessiert sind, ist die Trennung der Anwendungsdaten von den Betriebssystemdaten mit den Mitteln der Partitionierung. Es gibt einen feinen aber wichtigen Unterschied im Spiel, der unten angesprochen wird. Dieses Rezept zeigt, wie man eine Datentrennung für ein OEM-Abbild erreichen kann.
Partitionierung im Vergleich zur Datentrennung über Aufteilung
Wenn man über Partitionierung spricht, muss man das ganze Spektrum an Möglichkeiten betrachten. Dies schließt beliebig komplizierte Schemen ein, die Partitionen für Verzeichnisse einschließen mögen oder nicht, für die das Betriebssystem sorgt. Dieser Partitionierungstyp während einer normalen interaktiven Installation und während einer Installation mittels AutoYaST unterstützt. In diesem Anwendungsfall könnte ein Benutzer, wenn er möchte, Partitionen erstellen für /opt, /var, /usr, /home, etc. Basisverzeichnisse, die eine spezielle Bedeutung für ein Betriebssystem haben. Dies funktioniert für die interaktive Installation und AutoYaST als ein Prozess, der vor der konkreten Software-Installation auf dem Zielsystem läuft. Wenn die Software-Installation beginnt, werden die Pakete einfach in die geeigneten Zielverzeichnisse entpackt und der Installer selbst schert sich nicht darum, ob das Zielverzeichnis in eine spezielle Partition eingehängt ist oder ob das vorgegebene Verzeichnis einfach Teil der Root-Partition (/) ist.
Für Kiwi funktioniert dieses Schema nicht. Wenn ein Kiwi-Abbild erstellt ist, findet die Installation der Software in einem Verzeichnis statt, unterstützt durch das Argument --root für den Vorbereitungsschritt. In diesem Installationsmodus ist per Definition keine Idee von Partitionen vorhanden. Das Einzige was existiert, ist ein Verzeichnis. Im Erstellungsschritt ist dieses Verzeichnis "einfach" in ein Festplatten-Abbild, für den Abbildtyp "vmx" oder "oem", umgewandelt. Während der OEM-Installation wird das Festplatten-Abbild dann auf das Ziel-Speichermedium verfrachtet. Und so erhalten wir grundsätzlich ein Einzelpartitions-System (außer dem Swap-Bereich). Die Gründe für diese Implementierung können wie folgt erklärt werden:
- Es gibt keinen Prozess, der vor der Installation läuft, wenn man ein OEM-System von einem ISO-Abbild oder einem USB-Stick auf der Zielmaschine installiert, ungleich der interaktiven und der Auto YaST-Installation. Sobald das Installations- Medium startet, sind wir im von Kiwi erzeugten Prozess, der das Abbild auf das Ziel-Speicher-Gerät verfrachtet. Darum müsste jedes Partitionierungs-Schema in diesen Selbst-Installations-Prozess integriert werden.
- Die Partitionierung kann beliebig kompliziert sein, abhängig von der Speicherplatzkonfiguration auf dem Zielsystem, der Verwendung von primären und erweiterten Partitionen, dem Typ des Dateisystems, der Partitionsgrösse usw. Das führt schnell zum Alptraum des Management-Overhead. Der grundsätzliche Partitionierungscode mit Sondierung, Kalkulation, Fehler-Handhabung usw. ist nicht nur kompliziert einzubringen und zu warten innerhalb der extrem minimalen Selbst-Installations-Umgebung, sondern birgt das mögliche Risiko, dass man schließlich nach der OEM-Verfrachtung bei einem nicht funktionierenden System landen könnte. Das Letztere wäre ein ziemlich unangenehmes Vorkommnis, wenn das bei einem Kunden passieren würde.
- Generell wird die Partitionierung im Zusammenhang mit Geräten nicht wirklich benötigt. Wenn Leute von Partitionierung im Zusammenhang mit Geräten sprechen, was grundsätzlich gewünscht ist, ist eine Trennung von Daten für die Anwendungen, die Teil des Gerätes sind, und den Daten (wie /usr, /bin, /sbin, etc.) , die als Teil des Betriebssystems betrachtet werden. Das ist es, worin der feine aber bedeutende Unterschied zwischen der generellen Partitionierung und der Datentrennung über Aufteilung liegt.
Mit diesem im Hinterkopf wird der Rest dieses Beispiels alle notwendigen Informationen liefern, um die Datentrennung über Aufteilung zu erreichen, ohne grundsätzlich Unterstützung einer Partitionierungs-Funktion in Kiwi zu benötigen.
Kiwi Abbild Konfiguration
Dieses Beispiel verwendet eine sehr einfache datei config.xml, da der Hauptfokus auf die Erstellung der Datenaufteilung gerichtet ist, die in das Verzeichnis myData eingehängt ist.
Grundeinstellung
Erstellen Sie ein Verzeichnis, um es als Kiwi-Konfigurations-Verzeichnis zu verwenden.
Die Datei config.xml
Verwenden Sie Ihren bevorzugten Editor und erstellen Sie /tmp/dataSep_exa/config.xml. Sie können das Beispiel unten kopieren und einfügen, Ihren eigenen Inhalt von Grund auf erstellen oder das Beispiel modifizieren, um die Pakete einzubinden, die Sie gerne enthalten haben möchten.
<?xml version="1.0" encoding="utf-8"?> <image schemaversion="4.7" name="suse-11.3-oem-dataseparation"> <description type="system"> <author>Robert Schweikert</author> <contact>rschweikert at novell dot com</contact> <specification> openSUSE 11.3 based example showing data separation based on partitions </specification> </description> <preferences> <type image="oem" filesystem="ext4" boot="oemboot/suse-11.3" installiso="true"> <oemconfig> <oem-boot-title>Data-Separation</oem-boot-title> <oem-home>false</oem-home> <oem-swap>true</oem-swap> <oem-swapsize>4096</oem-swapsize> <oem-systemsize>8192</oem-systemsize> </oemconfig> </type> <version>1.0.0</version> <packagemanager>zypper</packagemanager> <keytable>us.map.gz</keytable> <timezone>US/Eastern</timezone> <rpm-excludedocs>true</rpm-excludedocs> </preferences> <users group="root"> <user pwd="linux" pwdformat="plain" home="/root" name="root"/> </users> <users group="users"> <user pwd="linux" pwdformat="plain" home="/home/tux" name="tux"/> </users> <repository type="yast2"> <source path="opensuse://11.3/repo/oss/"/> </repository> <packages type="image" patternType="plusRecommended"> <package name="kernel-default"/> <package name="ifplugd"/> <package name="python"/> <package name="vim"/> <namedCollection name="default"/> </packages> <packages type="bootstrap"> <package name="filesystem"/> <package name="glibc-locale"/> </packages> </image>
Es gibt wirklich nichts spezielles über die vorherige Konfigurationsdatei. Beachten Sie, dass das Elemente <oem-systemsize> verwendet wird, um die Größe des OS-Abbildes zu begrenzen, in diesem Fall auf 8 GB. Innerhalb 8 GB kann man eine ganze Menge installieren, alle Pakete die mit einer Standard SUSE-Distribution veröffentlicht werden. Die Pakete und Muster (Pattern), die in der obigen Datei config.xml ausgewählt wurden, geben eine minimale Auswahl wieder, da mit dem Beispiel beabsichtigt ist, das Konzept zu demonstrieren und nicht die Erstellung einer brauchbaren Anwendung. Python wird verwendet, um das Script auszuführen, das verwendet wird, um die Datentrennung zu erzeugen.
Das Element <oem-systemsize> begrenzt den Speicherplatz, der von der Root-Partition verwendet wird. Das lässt einigen extra Platz auf dem Speichermedium unangetastet. Ohne die Verwendung des Elements <oem-systemsize> würde sich das Root-System-Abbild auf den verfügbaren Speicherplatz auf dem Medium ausdehnen. Das lässt keinen Platz für extra Aufteilungs-Operationen. Darum ist die Verwendung des Elements <oem-systemsize> erforderlich, wenn Sie zusätzliche Partitionen erstellen müssen, nachdem das System auf das Ziel-Speichergerät verfrachtet wurde.
Wenn Sie Ihre eigene Anwendung in den Bau einbinden, könnten Sie eine geeignete Menge Speicherplatz hinzufügen wollen, um die Binärdateien für Ihre Anwendung anzupassen. Fügen Sie keinen Speicherplatz für Ihre Anwendungsdaten hinzu, da wir die Daten auf eine getrennte Partition geben werden, was schließlich das Anliegen von diesem Beispiel ist.
Die Datei config.sh
Das Script config.sh für die Konfiguration wurde nicht dargestellt, da es ein "Standard" config.sh-Script ist, das Info-Dateien löscht, usw. wie im vorherigen Rezept.
Partition Einrichtung
Zuerst erstellen Sie einen Ort für das Script in unseren Kiwi-Konfigurations-Baum.
Dann erstellen Sie mit Ihrem bevorzugten Editor die Datei /tmp/dataSep_exa/root/sbin/setUpPartitions. Kopien Sie das Script-Beispiel unten, um dem Beispiel zu folgen oder das Script nach Ihren Vorstellungen zu verändern.
#!/usr/bin/python import os import time def getSizeAndUnit(valueStr): """Extrahiere die Information zu Zahl und Einheit aus einer Zeichenkette des Formats 111MB""" size = '' idx = 0 for char in valueStr: if char.isdigit() or char == '.': size += char idx += 1 unit = valueStr[idx:] return size, unit diskInfoCmd = '/usr/sbin/parted %s print' %(os.environ["imageDiskDevice"]) diskInfo = os.popen(diskInfoCmd).readlines() partCnt = 0 diskSize = '' diskUnit = '' lastPartEnd = '' lastPartEndUnit = '' foundPartTbl = None numPartitions = 0 for diskLn in diskInfo: if diskLn.find('Disk') != -1: diskSize, diskUnit = getSizeAndUnit(diskLn.split(':')[-1].strip()) continue if diskLn.find('Number') != -1: foundPartTbl = 1 continue if foundPartTbl and diskLn.split(): numPartitions += 1 lastPartEnd, lastPartEndUnit = getSizeAndUnit(diskLn.split()[2]) if (lastPartEnd == diskSize) and (lastPartEndUnit == diskUnit): print "No free space on device" exit(1) # Erstelle die Partition, die den kompletten verfügbaren Speicherplatz verwendet partCmd = '/usr/sbin/parted %s mkpart primary %s%s %s%s >& /dev/null' %( os.environ["imageDiskDevice"], lastPartEnd, lastPartEndUnit, diskSize, diskUnit) os.system(partCmd) # Erzwinge, dass die Partitionstabelle erneut gelesen wird partReadCmd = 'partx -a %s >& /dev/null' %(os.environ["imageDiskDevice"]) os.system(partReadCmd) # Erstelle das Dateisystem auf der neuen Partition fsCmd = '/sbin/mkfs -t ext4 %s%d >& /dev/null' %(os.environ["imageDiskDevice"], numPartitions + 1) os.system(fsCmd) # Bestimme die Platten ID auf dem vorhandenen fstab Eintrag fstabData = open('/etc/fstab', 'r').readlines() diskID = '' for fstabLn in fstabData: if fstabLn.find('by-id') != -1: diskID = fstabLn.split()[0] break # Erzeuge einen Eintrag in /etc/fstab fstab = open('/etc/fstab', 'a') fstab.write('\n\n#Autogenerated data partition information\n') fstab.write(diskID[:diskID.index('part')]) fstab.write('part%d' %(numPartitions + 1)) fstab.write(' /myData') fstab.write(' ext4') fstab.write(' defaults 1 2\n') fstab.close() # Gib dem System etwas Zeit, die Änderungen einzurichten time.sleep(10) # Erstelle einen Einhängepunkt und hänge die neue Partition ein os.mkdir('/myData') mntCmd = '/bin/mount /myData >& /dev/null' os.system(mntCmd) # Bereinigung os.system('rm /tmp/partSetup') bootInfo = open('/etc/init.d/boot.local', 'r').readlines() bootLocal = open('/etc/init.d/boot.local', 'w') skipBlock = None for ln in bootInfo: if ln.find('# Begin init data setup') != -1: skipBlock = 1 if ln.find('# End init data setup') != -1: skipBlock = None continue if skipBlock: continue bootLocal.write(ln) bootLocal.close() os.system('rm sbin/setUpPartitions')
Sichere die Datei und füge die Ausführungserlaubnis hinzu.
Lassen Sie uns das Script näher betrachten. Zuerst ist eine Funktion definiert, die eine Zeichenkette der Form "12.6GB" in zwei Zeichenketten teilt. Die erste Zeichenkette die erwidert ist die Größe, "12.6" in diesem Fall, und die zweite ist die Einheit "GB" in diesem Beispiel.
Der Funktionsdefinition folgend sammeln wir die Information, die von parted /dev/sda print geliefert wird, so dass wir die Daten zerlegen können und extrahieren können, was für uns nützlich ist.
In diesem Rezept wird angenommen, dass das Abbild auf dem ersten Speichergerät, das erkannte wird, installiert wird (/dev/sda) und dass die Datenpartition auch auf diesem Gerät platziert wird.
Die for-Schleife überprüft einfach die Ausgabe vom Kommando parted und extrahiert die interessierenden Daten. Die Größe des Speichergeräts ist in der Variablen diskSize enthalten, die aus einer Zeile in der geteilten Ausgabe extrahiert wurde, die mit Disk anfängt. Die berichtete Einheit für die Speichergröße in der Variablen diskUnit gespeichert. Die Schleife zählt auch die vorher existierenden Partitionen (numPartitions counter) und legt die Größe mit der die letzte vorhandene Partition endet unter der Variablen lastPartEnd ab. Die Einheit des Endes der letzten Partition wird unter der Variablen lastPartEndUnit abgelegt.
In diesem Rezept gibt es zwei bereits existierende Partitionen, die Root-Partition (/) und die Swap-Partition.
Ein schneller Vergleich des Endes der letzten Partition und die Größe der Festplatte bestimmt, ob noch Speicherplatz zur Verfügung steht.
Nachdem wir wissen, dass noch Speicherplatz vorhanden ist, erzeugt das Script einfach eine einzelne Partition, die am Ende der vorherigen letzten Partition beginnt und den ganzen noch verfügbaren Speicherplatz einnimmt. Man kann einen willkürlichen Algorithmus hier einfügen, um ein Partitions-Layout nach eigenen Wünschen zu erzeugen. Behalten Sie im Hinterkopf, dass jedes vorhandene Speichergerät nur 4 primäre Partitionen haben kann.
Nach Partitions-Erzeugung, wird ein Dateisystem auf der Partition erstellt, ext4 in diesem Beispiel.
Als nächstes erzwingt das Script den laufenden Kernel die Partitions-Tabelle neu zu lesen, das Kommando partx, um sicher zu stellen, dass die geeigneten Geräteknoten in /dev erstellt sind.
Nachdem die neuen Geräteknoten erstellt sind, hängt das Script eine neue Zeile in der Datei /etc/fstab an, um sicher zu stellen, dass unsere Partition zur Boot-Zeit eingehängt ist. Nach einem kurzen Schlaf, um dem System Zeit zu geben, auf den neuesten Stand zu kommen, wird das Einhängepunktverzeichnis erstellt und die neue Partition eingehängt.
Zum Schluss räumt das Script die Datei boot.local auf (das wird unten gezeigt und diskutiert) und dann löscht sie sich selbst vom System. Es wird keine Spur dieser Partitions-Zauberei, die gerade passierte, hinterlassen.
Anstoßen des Partitionierungs-Prozesses
Wir wollen die Partitionierung so einrichten, dass sie aus der Gerätebenutzerperspektive unsichtbar ist. Da alles was wir brauchen, auf einem laufenden System ausgeführt werden kann, können wir das Partitionierungsscript während des Boot-Prozesses starten. Und wir brauchen uns keine Gedanken über die Verwendung des Yast Firstboot Mechanismus zu machen.
Erstellen Sie das Verzeichnis init.d in Ihrem Kiwi-Konfigurations-Baum.
Mit Ihrem bevorzugten Editor erstellen Sie /tmp/dataSep_exa/root/etc/init.d/boot.local und folgen dem Beispiel, kopieren das untere Script und fügen es ein.
#! /bin/sh # Beginn des init Daten setup if [ -f /tmp/partSetup ]; then /sbin/setUpPartitions fi # Ende des init Daten setup
Sie können die Kommentare sehen, die von Partitionierungs-Script verwendet werden, um für die Existenz der Trigger-Datei in /tmp aufzuräumen und zu testen.
Für ein mehr modulares Design sollte das Partitionierungs-Script nicht boot.local aufräumen. Diese Aufgabe sollte von einem getrennten Script ausgeführt werden. Für dieses Beispiel wird das Mischen von Verantwortlichkeiten ausreichen. In einer Produktionsumgebung sollte man die Angelegenheiten eindeutig trennen. Vergessen Sie nicht das Script boot.local ausführbar zu machen und erstellen Sie eine Trigger-Datei im Kiwi-Konfigurationsbaum.
Das vervollständigt die Einrichtung des Konfigurationsbaums.
Bau und Test des Beispiels
Es gibt nichts spezielles zum Bau, wenn die vorhergehenden Rezepte vergleicht.
Nun erstellen Sie ein Festplatten-Abbild mit einer willkürlichen Größe (250 GB in diesem Beispiel).
Mit dem Festplatten-Abbild können wir nun Qemu verwenden, um das OEM-Abbild zu testen, das wir mit Kiwi erstellt haben.
Wenn das Abbild startet, werden Sie den Selbstinstallationsprozess wie gewöhnlich sehen, gefolgt vom Boot-Prozess des installierten Systems. Wenn Sie auf dem Anmeldebildschirm sind, melden Sie sich als Root an, Passwort linux und listen die Partitionstabelle mit dem folgenden Kommando auf:
Sie werden sehen, dass da nun 3 Partitionen auf dem System sind. Wenn Sie das Kommando mount eingeben, werden Sie sehen, dass /dev/sda3 unter /myData eingehängt ist.