# HSAdmin über Skripte steuern {#kap-hsscript-skript} Im Abschnitt [Syntax](#kap-hsadmin-syntax) wurde die Option `-f` erwähnt, die gesetzt werden kann, um HSAdmin eine Datei zu übergeben, in der sich die Befehle befinden. Die Option ermöglicht es, ohne großen Aufwand Skriptdateien zu pflegen, mit denen wiederkehrende Aufgaben bequem erledigt werden können. Dieses Kapitel zeigt, wie Sie die Anlage einer neuen Wordpress-Website mit Hilfe eines solchen Skripts vereinfachen können. Bevor Sie die eigentliche Wordpress-Software installiert, müssen mehrere Schritte auf der Hostsharing-Plattform erledigt sein. 1. Es existiert ein Domain-Admin bzw. es wird ein neuer Domain-Admin angelegt. 2. Es wird eine Domain erstellt und dem Domain-Admin zugewiesen. 3. Es wird ein Datenbank-Nutzer angelegt. 4. Es wird eine Datenbank angelegt und dem Datenbank-Nutzer zugewiesen. Mit der folgenden Skript-Datei kann man diese vier Schritte mit einem Befehl ausführen. ```bash user.add ({set:{name:'xyz00-domains',comment:'Domain-Admin',password:'!1?2-3aBc',shell:'/bin/bash'}}) domain.add ({set:{name:'beispiel.de',user:'xyz00-domains'}}) mysqluser.add ({set:{name:'xyz00_owner',password:'?2?3-4cVg'}}) mysqldb.add ({set:{name:'xyz00_abc',owner:'xyz00_owner'}}) ``` In Zeile 1 wird der Domain-Admin erzeugt, in Zeile 2 die Domain `beispiel.de` angelegt, in Zeile 3 der Datenbank-Nutzer und in Zeile 4 die Datenbank. Es ist möglich, die Datei lesbarer zu formatieren, indem man jedem Key-Value-Paar eine eigene Zeile zuweist. ```bash user.add ({set:{ name:'xyz00-domains', comment:'Domain-Admin', password:'!1?2-3aBc', shell:'/bin/bash' }}) domain.add ({set:{ name:'beispiel.de', user:'xyz00-domains' }}) mysqluser.add ({set:{ name:'xyz00_owner', password:'?2?3-4cVg' }}) mysqldb.add ({set:{ name:'xyz00_abc', owner:'xyz00_owner' }}) ``` Wenn Sie die Datei unter dem Namen `befehlsskript.txt` im Verzeichnis des `Paket-Admin` speichern, können Sie alle Befehle mit einem HSAdmin-Aufruf abarbeiten: ``` console xyz00@h50:~$ hsscript -f befehlsskript.txt ``` Wenn Sie beispielsweise häufig Wordpress-Websites installieren, können Sie für jede Website eine solche Befehlsdatei anlegen und unter einem sinnvollen Namen (z.B. `wordpress-beispiel_de.txt`) abspeichern. ::: attention Beachten Sie die richtige Reihenfolge Bei der Anlage von Benutzern, Datenbanken und Domains ist die im Beispiel gezeigt Reihenfolge einzuhalten. Um eine Domain anzulegen, muss der Domain-Admin bereits existieren. Eine Datenbank kann nur erzeugt werden, wenn der Datenbank-Nutzer bereits angelegt ist. Beim Löschen müssen Sie die Reihenfolge umkehren: Datenbank löschen, Datenbank-Nutzer löschen, Domain löschen, Domain-Admin löschen. ::: Noch bequemer ist es, die notwendigen Benutzer, Domains und Datenbanken mit Hilfe eines ausführlicheren JS-Skripts oder über die Python-API anzulegen. ## HSAdmin mit Javascript ansprechen Im Folgenden zeigen wir zwei JS-Skripts, die in der Regel im Verzeichnis des Paket-Admin mit dessen Benutzerrechten aufgerufen werden. Mit dem ersten Skript erstellen wir eine Domain und weisen ihr einen eigenen Domain-Admin zu, dessen Name aus dem Namen der Domain abgeleitet wird. Mit dem zweiten Skript erzeugen wir eine Datenbank und einen Datenbank-Nutzer, sodass wir unter der gewünschten Domain zum Beispiel eine PHP-Anwendung wie Wordpress einrichten können. ### JS-Skript zur Anlage einer Domain Ein Skript, um eine Domain mit einem gesonderten Domain-Admin anzulegen, könnte so aussehen: ```bash #!/usr/local/bin/hsscript -f createDomainAndDomainAdmin(arguments); function pwGen() { var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_#%&+!?="; var pwLength = 12; var randomstring = ''; for (var i=0; i Anschließend klonen wir die Python-Bindings und installieren sie. ``` console $ git clone https://dev.hostsharing.net//r/ansible/hs.admin.api.git $ cd hs.admin.api $ python setup.py install ``` Nun steht uns das Modul mit dem Python-Bindings in der virtuellen Umgebung zur Verfügung, sodass wir es in einem Skript importieren können. ### Python-Skript Um die API in einem Skript nutzen zu können, müssen wir mit folgendem Code ein API-Objekt erzeugen. ```python from hs.admin.api import API api = API(cas=dict( uri='https://login.hostsharing.net/cas/v1/tickets', service='https://config.hostsharing.net:443/hsar/backend'), credentials=dict(username='xyz00', password='sehr-geheim'), backends=[ 'https://config.hostsharing.net:443/hsar/xmlrpc/hsadmin', 'https://config2.hostsharing.net:443/hsar/xmlrpc/hsadmin']) api.user.add(set={'name': 'xyz00-domain.de', 'password': 'geheim', 'shell': '/bin/bash'}) api.domain.add(set={'name': 'domain.de', 'user': 'xyz00-domain.de'}) ``` Nun ist es möglich, mit der üblichen Syntax HSAdmin im Skript anzusprechen. Mit diesen beiden Befehlen legen wir beispielsweise einen Domain-Admin und eine neue Domain an. ```python api.user.add(set={'name': 'xyz00-domain.de', 'password': 'geheim', 'shell': '/bin/bash'}) api.domain.add(set={'name': 'domain.de', 'user': 'xyz00-domain.de'}) ``` Eine Datenbank lässt sich folgendermaßen anlegen. ```python from hs.admin.api import API api = API(cas=dict( uri='https://login.hostsharing.net/cas/v1/tickets', service='https://config.hostsharing.net:443/hsar/backend'), credentials=dict(username='xyz00', password='sehr-geheim'), backends=[ 'https://config.hostsharing.net:443/hsar/xmlrpc/hsadmin', 'https://config2.hostsharing.net:443/hsar/xmlrpc/hsadmin']) api.mysqluser.add(set={'name': 'xyz00_domain_de', 'password': 'geheim'}) api.mysqldb.add(set={'name': 'xyz00_domain_de', 'owner': 'xyz00_domain_de'}) ``` Nun wollen wir diese Befehle in ein Skript einbauen, das noch einige andere nützliche Dinge für uns erledigt. Reseller und Webmaster, die viele Anwendungen betreuen, buchen häufig mehrere Pakete bei Hostsharing, sodass sie gerne ein Skript hätten, dem sie auch das Kürzel für das Paket übergeben können, in dem sie eine Domain mit Datenbank einrichten möchten. Außerdem wäre es hilfreich, wenn das Skript dafür sorgt, dass Benutzernamen und Datenbankenname immer nach einem einheitlichen Schema erzeugt werden, sodass die Orientierung leichter fällt. In unserem Beispielskript übergeben wir daher dem Skript drei Argumente: 1. das Kürzel für das Paket 2. den Domainnamen 3. eine Projekt-ID Die Projekt-ID darf nicht mehr als 10 Zeichen umfassen, da sie zusammen mit dem fünfstelligen Paketkürzel in den Namen für Datenbank und Datenbank-Nutzer verwendet wird. Diese dürfen aber nicht länger als 16 Zeichen sein. Als Schema für eine Projekt-ID kommt also beispielsweise eine Kombination aus einer Kundennummer und einer Abkürzung in Frage. Wir verwenden in unserem Beispiel dafür eine dreistellige Kundennummer und die Abkürzung `wp` für Wordpress. Die Elemente trennen wir mit dem Unterstrich, da nur dieser als Namensbestandteil erlaubt ist. Wenn wir für den Kunden mit der Kundennummer 23 im Paket `xyz00` eine Domain für einen Wordpress-Blog einrichten möchten, lautet der Aufruf des Skripts folgendermaßen: ``` console $ python createall.py xyz00 hs-example.de 023_wp ``` Der Code des Skripts sieht so aus: ```python import random import string import sys from hs.admin.api import API from subprocess import check_output paketadmin = sys.argv[1] domainname = sys.argv[2] projektid = sys.argv[3] pw = check_output(["pass", "hostsharing/"+paketadmin]).decode("utf-8").strip("\n") api = API(cas=dict( uri='https://login.hostsharing.net/cas/v1/tickets', service='https://config.hostsharing.net:443/hsar/backend'), credentials=dict(username=paketadmin, password=pw), backends=[ 'https://config.hostsharing.net:443/hsar/xmlrpc/hsadmin', 'https://config2.hostsharing.net:443/hsar/xmlrpc/hsadmin']) def pwGen(stringLength=12): """Function to generate a random password """ password_characters = string.ascii_letters + string.digits return ''.join(random.choice(password_characters) for i in range(stringLength)) pw_dadmin = pwGen() pw_dbuser = pwGen() dadmin = paketadmin+'-'+domainname.replace("-", "_") dbuser = paketadmin+'_'+projektid dbname = paketadmin+'_'+projektid api.user.add(set={'name': dadmin, 'password': pw_dadmin, 'shell': '/bin/bash'}) api.domain.add(set={'name': domainname, 'user': dadmin}) api.mysqluser.add(set={'name': dbuser, 'password': pw_dbuser}) api.mysqldb.add(set={'name': dbname, 'owner': dbuser}) print("Domainname:" +domainname) print("Domain-Admin: " + dadmin + " mit dem Passwort:" +pw_dadmin) print("Datenbank-Nutzer: " +dbuser + " Passwort:" +pw_dbuser) print("Datenbankname: " +dbname) ``` In den ersten fünf Zeilen importieren wir einige Module bzw. Funktionen, die wir benötigen. In den Zeilen 7 bis 9 lesen wir die übergebenen Argumente aus und speichern die Werte in entsprechenden Variablen. Um das API-Objekt zu erzeugen, benötigen wir das Passwort für den übergebenen Paket-Admin. Wir lesen in Zeile 11 das Passwort aus dem verschlüsselten Passwort-Tresor des Kommandozeilenprogramms `pass` aus und speichern es in der Variablen `pw`. Weitere Informationen zu dem Programm finden Sie auf der Website . Sie können natürlich andere Programme wählen, um ein Passwort aus einem Passwort-Tresor auszulesen. Falls Sie nur ein Paket bei Hostsharing verwalten, können Sie das Passwort auch direkt ins Skript eintragen. Aus Sicherheitsgründen sollten Sie dies möglichst vermeiden. Anschließend erzeugt das Skript das API-Objekt, wobei es als Credentials den Namen des Paket-Admin und sein Passwort übergibt. Der Namen des Paket-Admin ist identisch mit dem Paket, in dem die Domain angelegt werden soll. Danach wird ein Zufallsgenerator definiert, mit die Passworte erzeugt werden, die später benötigt werden. In Zeile 27 und 28 werden die Passworte für den Domain-Admin und den Datenbank-Nutzer erzeugt und in Variablen gespeichert. Direkt anschließend erzeugt das Skript aus den beim Aufruf übergebenen Werten die Namen für den Domain-Admin, den Datenbank-Nutzer und die Datenbank. In den Zeilen 33 bis 36 werden der Domain-Admin, die Domain, den Datenbank-Nutzer und die Datenbank angelegt. Und zum Schluss gibt das Skript alle Daten aus. Idealerweise würde ein solches Skript die neuen Benutzernamen mit den jeweiligen Passworten in den Passwort-Tresor eintragen, sodass dies nicht mit der Hand erledigt werden muss.