ISPConfig API - Serverbefehle

Dieses Thema im Forum "Entwicklerforum" wurde erstellt von shadowcast, 25. Juni 2014.

  1. shadowcast

    shadowcast Member

    Hallo,

    wie bereits aus einem anderen Thread ersichtlich, arbeite ich aktuell an einigen Schnittstellen. Dabei wird mir bereits über die ISPConfig API eine neue Site inkl. Datenbank angelegt.

    Im nächsten Schritt würde ich gerne auf dem gleichen Gerät den angelegten WEB Ordner füllen. Also schlichtweg ein copy&paste z.b. von einer anderen Seite bzw. von einem Ordner auf dem Server. (später wird das ein ZIP)

    Anschließend solll eine SQL-Datei in die angelegte Datenbank gespielt werden.

    Nun meine Frage, kann ich das mit der ISPConfig API abwickeln über einen SSH Benutzer? Diesem dann lediglich die "cp -R /user/quellordner /var/www/neueseite/web" senden?
    Oder sollte ich hier eine andere Schnittstelle in Betracht ziehen? Welche würdet ihr mir empfehlen? Einfaches XML? Soap? XML-RPC?

    LG
     
  2. Till

    Till Administrator

    Ich würde das über ein ispconfig plugin lösen und nicht über das api, denn plugins laufen ja immer lokal Du brauchst keine extra ssh user. einfach ein neues server plugin anlegen, an den web_domain_insert event binden und dort den cp Befehl einfügen. das plugin wird dann automatisch aufgerufen, wenn Du ein neues web anlegst.
     
  3. shadowcast

    shadowcast Member

    Hallo Till,

    ich habe mir deine Empfehlung mal etwas betrachtet und bestehendes apache2_plugin.in.php enthält soweit wohl schon fast alles was ich benötige.

    Denn hier werden bereits ab Zeile 600 in den Webroot die Errorseiten, index.html etc. eingefügt. Auch bereits von einem vordefiniertem Ort. Das wäre ja genau das Copy&Paste was ich angedacht hatte.

    Dem müsste ich quasi nur noch die MySQL Insert Zeile einfügen, wo dann auch nur eine definierte SQL Datei von einem definiertem Ordner importiert wird.
    Ich muss nur zusehen, dass das Plugin die benötigten Daten für den SQL Befehl bekommt. Sprich DB, User und Passwort.

    Ich versuch mal die Datei aus dem plugins-enabled Ordner in eine "mein_plugin.inc" zu kopieren, bis auf die notwendige Passage zu reduzieren und die Benennung anzupassen und werde dann schon sehen, ob mir auch was anders als die default Seite einkopiert wird.

    Möglich dass ich aber bezüglich dem SQL Befehl noch etwas Unterstützung benötige, aber erst mal ist ausprobieren und selbst forschen angesagt.

    DANKE
     
  4. florian030

    florian030 Member

    Die SQL-Abfragen sind nicht wirklich kompliziert. Z.B.
    $records = $app->db->queryAllRecords("select * from mail_user");
    schreibt die Tabelle mail_user nach $records.
     
  5. shadowcast

    shadowcast Member

    Hallo,

    ich habe nun wie bereits erwähnt die apache2_plugin.inc.php soweit modifiziert, frag mich aber ernsthaft, ob das so überhaupt funktionieren kann? Ich hätte gerne eure Meinung / Tips bevor ichs live ausprobieren.

    Im Ordner "plugins-enabled" werde ich die Datei hochladen, welche gerade noch offline liegt: "myinstall_plugin.inc.php"

    Der aktuelle Inhalt:
    Code:
    <?php
    class myinstall_plugin {
    
        var $plugin_name = 'myinstall_plugin';
        var $class_name = 'myinstall_plugin';
    
        // private variables
        var $action = '';
    
        /*
             This function is called when the plugin is loaded
        */
    
        function onLoad() {
            global $app;
    
            /*
            Register for the events
            */
            $app->plugins->registerEvent('web_domain_insert', $this->plugin_name, 'ssl');
            $app->plugins->registerEvent('web_domain_update', $this->plugin_name, 'ssl');
            $app->plugins->registerEvent('web_domain_delete', $this->plugin_name, 'ssl');
    
            $app->plugins->registerEvent('web_domain_insert', $this->plugin_name, 'insert');
            $app->plugins->registerEvent('web_domain_update', $this->plugin_name, 'update');
            $app->plugins->registerEvent('web_domain_delete', $this->plugin_name, 'delete');
    
            $app->plugins->registerEvent('web_folder_user_insert', $this->plugin_name, 'web_folder_user');
            $app->plugins->registerEvent('web_folder_user_update', $this->plugin_name, 'web_folder_user');
            $app->plugins->registerEvent('web_folder_user_delete', $this->plugin_name, 'web_folder_user');
    
            $app->plugins->registerEvent('web_folder_update', $this->plugin_name, 'web_folder_update');
            $app->plugins->registerEvent('web_folder_delete', $this->plugin_name, 'web_folder_delete');
        }
    
        function insert($event_name, $data) {
            global $app, $conf;
    
            $this->action = 'insert';
            // just run the update function
            $this->update($event_name, $data);
    
    
        }
    
        function update($event_name, $data) {
            global $app, $conf;
    
            if($this->action != 'insert') $this->action = 'update';
    
            // load the server configuration options
            $app->uses('getconf');
            $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
    
            $app->system->web_folder_protection($data['new']['document_root'], true);
    
            // Get the client ID
            $client = $app->dbmaster->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = '.intval($data['new']['sys_groupid']));
            $client_id = intval($client['client_id']);
            unset($client);
    
            // Install the Standard or Custom Error, Index and other related files
            // /usr/local/ispconfig/server/conf is for the standard files
            // /usr/local/ispconfig/server/conf-custom is for the custom files
            // setting a local var here
    
            $conf['templates'] = "/usr/local/ispconfig/server/myownconf";
    
            if($this->action == 'insert' && ($data['new']['type'] == 'vhost')) {
    
                // copy complete folder
                exec('cp -R ' . $conf['templates'] . '/* ' . escapeshellcmd($data['new']['document_root']) . '/' . $web_folder . '/');
    
                exec('chmod -R a+r '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/');
            }
    
            if($this->action == 'insert') {
                // Chown and chmod the directories below the document root
                $this->_exec('chown -R '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder);
            }
    
            //* Unset action to clean it for next processed vhost.
            $this->action = '';
        }
    
        //* Wrapper for exec function for easier debugging
        private function _exec($command) {
            global $app;
            $app->log('exec: '.$command, LOGLEVEL_DEBUG);
            exec($command);
        }
    
    }
    
    Kurze Beschreibung meiner Gedanken:
    Das Plugin soll ausgeführt werden, wenn eine Webdomain hinzugefügt wird. Deshalb habe ich die onLoad Funktion fast komplett belassen.

    Die insert Funktion macht auch hier nicht mehr als die update Funktion aufzurufen.

    Ab Zeile 67 wird dann mein eigener Ordner kopiert. Dies soll er rigoros machen, sprich existiert die jeweilige Datei, schlichtweg überschreiben.
    Dem CP Befehl habe ich noch ein -R rangehängt, damit er auch alle Unterordner und Dateien kopiert.
    Dann wird noch der CHOWN ausgeführt, wobei ich hier schonmal bemerke, dass $username und $groupname nirgendwo gesetzt werden?

    Vermutlich wird auch escapeshellcmd() nicht klappen?

    Momentan prasselt da hübsch was auf mich ein...

    Ziel ist lediglich bei einer neuen Website anlegen, dass mir in den Ordner zusätzlich eigene Dateien kopiert werden.

    Denke das deutlich einfachere hinzufügen in der apache2_plugin.inc.php ist keine gute Lösung, denn beim nächsten Update müsste ich erneut meine Anpassungen abgleichen.

    Mir fällt auch auf, dass ich an dieser Stelle eigentlich noch gar keinen SQL-Befehl ausführen brauche, da hier die Datenbank ja noch gar nicht existiert.
    Die wird ja von der API erst nach der Domainerstellung aufgerufen.

    LG
     
  6. shadowcast

    shadowcast Member

    Sorry meines voreiligen Posts. Mit Hilfe der ISPCOnfig Logfiles speziell der cron.log konnte ich bisherige Meldungen beheben, sodass mir jetzt schon mal die Datei aus dem besagten Ordner korrekt kopiert wird.
     
  7. shadowcast

    shadowcast Member

    So nun ist es aber soweit, dass ich Unterstützung benötigen würde.

    Das erste Plugin läuft bereits nachdem eine Domain eingefügt wurde und kopiert ein individuelles Ergebnis als Standardinstallation in den Folder. Das Plugin setzt mir inzwischen auch den korrekten User, die Group und passt mir die Schreib/Leserechte der Ordner und Dateien an.

    Im nächsten Plugin möchte ich nun eine vorgegebene SQL Datei importieren. Es läuft bei einem db_insert. Kopiert habe ich die Daten von der mysql_clientdb_plugin.inc.php, komm aber nicht wirklich weiter.

    Hier steht folgende Zeile:
    Code:
    $link = new mysqli($clientdb_host, $clientdb_user, $clientdb_password);
    Die 3 Variablen werden aber nirgendwo definiert.
    Gut hier würde ein einfacher exec() auch schon ausreichen, sofern ich aber an den Benutzer, die Datenbank und das Passwort käme. Möglich dass diese Daten bereits im $data Parameter enthalten sind, oder in der $app?

    Die Frage ist, wie kann ich deren Inhalte denn auslesen?
    Und kann ich diesen auch eigene Werte geben?

    Ich müsste nämlich im Anschluss eine config.php entsprechend /tmp und /log Verzeichnis aktualisieren, sowie die Datenbankinformationen / User / Passwort eintragen. Damit dies gelingt, benötige ich hier auch den Webroot des entsprechenden Webs.

    Aktuell bekomme ich mit folgenden Code nicht mal eine einfache Tabelle angelegt:
    Code:
    if($data['new']['type'] == 'mysql') {
        if(!include ISPC_LIB_PATH.'/mysql_clientdb.conf') {
            $app->log('Unable to open'.ISPC_LIB_PATH.'/mysql_clientdb.conf', LOGLEVEL_ERROR);
            return;
        }
    
        // my installation file
        $sql = "/usr/local/ispconfig/server/conf/myfolder/myinstall.sql";
    
        // connect to the database
        $link = new mysqli($clientdb_host, $clientdb_user, $clientdb_password);
        if ($link->connect_error) {
            $app->log('Unable to connect to mysql'.$link->connect_error, LOGLEVEL_ERROR);
            return;
        }
    
        $link->query('CREATE TABLE example (id INT, data VARCHAR(100));');
    $link->close();
    }
    
    LG
     
  8. nowayback

    nowayback Well-Known Member

    hi,

    Code:
    $link->query('CREATE TABLE example (id INT, data VARCHAR(100));');
    Sieht irgendwie falsch aus da 2x;...

    Probier doch mal:
    Code:
    $link->query('CREATE TABLE example (id INT, data VARCHAR(100))');

    *** Edit ***
    Du kannst auch prüfen ob der Eintrag geklappt hat:
    Code:
    if ($mysqli->query('CREATE TABLE example (id INT, data VARCHAR(100))') === TRUE) {
        printf("Table example created or whatever you want.\n");
    }
    Grüße
    nwb
     
    Zuletzt bearbeitet: 26. Juni 2014
  9. florian030

    florian030 Member

    Die Werte werden durch ISPC_LIB_PATH.'/mysql_clientdb.conf gesetzt.

    Wenn Du alle Werte sehen willst, nimm doch print_r in deinem Plugin.

    Das Webroot des Users kannst Du doch abfragen?

    Warum machst Du das nicht über die function db_insert aus dem mysql_clientdb_plugin.inc.php?
     
  10. shadowcast

    shadowcast Member

    Morgen,

    @nwb
    Ja kann ich versuchen.
    Wobei das 1. Semikolon ja der Abschluss des SQL Querys ist und innerhalb des ' liegt.

    @florian
    Danke der Erklärung mit ISPC_LIB_PATH.
    Ich denke den Webroot erhalte ich über die db_insert, denn hier wird ja u.A. dieser gesetzt.
    Genau die Funktion db_insert der mysql_clientdb_plugin.inc.php ist wie schon oben beschrieben in Verwendung.

    @all
    Mit print_r() bekam ich aktuell leider keinerlei Ausgaben im Browser zu sehen. Vermutlich weil die Plugins nacheinander einfach nur abgearbeitet werden? Vermutlich müsste ich ein exit() oder break() setzen?

    LG
     
  11. shadowcast

    shadowcast Member

    Okay aktueller Stand der Dinge:

    Code:
    class myinsert_plugin {
    
        var $plugin_name = 'myinsert_plugin';
        var $class_name  = 'myinsert_plugin';
    
        function onLoad() {
            global $app;
            // register the events
            $app->plugins->registerEvent('database_insert', $this->plugin_name, 'db_insert');
        }
    
    function db_insert($event_name, $data) {
            global $app, $conf;
    
            if($data['new']['type'] == 'mysql') {
                if(!include ISPC_LIB_PATH.'/mysql_clientdb.conf') {
                    $app->log('Unable to open'.ISPC_LIB_PATH.'/mysql_clientdb.conf', LOGLEVEL_ERROR);
                    return;
                }
    
                print_r($event_name);
                print_r($data);
                print_r($app);
                print_r($conf);
    
                // connect to the database
                $link = new mysqli($clientdb_host, $clientdb_user, $clientdb_password);
                if ($link->connect_error) {
                    $app->log('Unable to connect to mysql'.$link->connect_error, LOGLEVEL_ERROR);
                    return;
                }
    
                $link->query('CREATE TABLE example (id INT, data VARCHAR(100))');
                $link->close();
             }
        }
    
    }
    
    Die print_r()s funktionieren leider durch die Bank nicht. (Die folgende Änderung kann bis zu 1 Minuten dauern wie üblich erscheint. Mehr nicht.)
    Ist ja irgendwo auch klar, dass die noch nicht angezeigt werden können, wenn das Plugin noch gar nicht läuft.

    Auch die SQL Create Tabele klappt nicht.
    Wird denn bei "$link = new mysqli($clientdb_host, $clientdb_user, $clientdb_password);" überhaupt die Datenbank auch ausgewählt?

    LG
     
  12. Till

    Till Administrator

    Das mit dem Debuggen beim Entwickeln geht einfacher und ohne Wartezeit.

    1) server.sh cronjob in root crontab auskommentieren.
    2) /usr/local/ispconfig/server/server.sh as root user auf der shell selbst ausführen. dann siehst Du auch die print_r's.

    Nein, da ist keine ausgewählt, denn die root Verbindung wird an sich ja nur für das Anlegen neuer Datenbanken verwendet.
     
  13. shadowcast

    shadowcast Member

    Hi,

    irgendwie will es noch nicht so.

    Code:
    function db_insert($event_name, $data) {
            global $app, $conf;
    
            // load the server configuration options
             $app->uses("getconf");
             $app->db->queryOneRecords("CREATE TABLE example (id INT, data VARCHAR(100)"); 
    
             $this->action = '';
    
    Hiermit klappts leider auch nicht. Hinzugefügt habe ich die Zeile $app->uses um die Konfiguration zu laden? Oder ist das alles bereits in der $app?

    Klappt gar nicht. Im Gegenteil. Neue Datenbank anlegen: 1 bleibt sogar bestehen. Da hängts also.

    LG
     
    Zuletzt bearbeitet: 27. Juni 2014
  14. Till

    Till Administrator

    Die Konfiguration hast Du bereits und das $app-db Objekt ist auch bereits mit der DB verbunden, "app->uses()" läd auch nur Klassen nach und getconf brauchst Du hier nicht, das dient nur zum lesen und umwandeln von .ini Konfigurationen.

    nimm mal Deinen code aus #11 und füge vor der abfrage noch code ein dass er zu der datenbank wechselt in der due die tabelle einfügen willst.
     
  15. shadowcast

    shadowcast Member

    Code:
                // connect to the database
                $link = new mysqli($clientdb_host, $clientdb_user, $clientdb_password);
                if ($link->connect_error) {
                    $app->log('Unable to connect to mysql'.$link->connect_error, LOGLEVEL_ERROR);
                    return;
                }
    
                $link->query('USE ' . $link->escape_string($data['new']['database_name']) . ')');
                $link->query('CREATE TABLE example (id INT, data VARCHAR(100))');
    
    Klappt leider auch nicht.

    Bezüglich den Crontab deaktivieren:
    in der /etc/crontab steht leider nichts von der server.sh
    Auch im /etc/cron.d/ kann ich hierzu nichts finden.
    Muss ich diesen denn überhaupt deaktivieren, wenn ich ihn manuell ausprobieren will, um an die Inhalte der Variablen zu kommen?
     
  16. Till

    Till Administrator

    ja.

    Die root crontab editiert man mit dem Befehl:

    crontab -e
     
  17. shadowcast

    shadowcast Member

    Okay ich glaub mit langsamen Schritten näher ich mich dem Ziel.

    Code:
                //* Connect to the database
                $link = new mysqli($clientdb_host, $clientdb_user, $clientdb_password);
                if ($link->connect_error) {
                    $app->log('Unable to connect to mysql'.$link->connect_error, LOGLEVEL_ERROR);
                    return;
                }
    
                // get the users for this database
                 $db_user = $app->db->queryOneRecord("SELECT `database_user`, `database_password` FROM `web_database_user` WHERE `database_user_id` = '" . intval($data['new']['database_user_id']) . "'");
                 
                print_r($db_user);
                
                // installation file from joowi
                $myinstall = "/usr/local/ispconfig/server/conf/myinstall/myinstall.sql";
    
                 exec('mysql --user=' . $link->escape_string($db_user['database_user']) . ' --password=' . $link->escape_string($db_user['database_password']) . ' --database=' . $link->escape_string($data['new']['database_name']) . '< ' . $myinstall);
    
    Klappt nur noch nicht ganz. Ich bekomme zwar den Benutzernamen und auch das Passwort, aber im Shell steht ein Verbindungsfehler, dass wohl das Passwort nicht korrekt ist.
    ERROR 1045 (28000): Access denied for user 'myuser'@'localhost' (using password: YES)
    Zu diesem Zeitpunkt ist das Passwort mit einem vorangehenden * verschlüsselt?!?

    Mein SQL Query steht nun in der myinstall.sql
    Der Funktioniert, wurde mit PHPMyAdmin geprüft.
     
    Zuletzt bearbeitet: 27. Juni 2014
  18. Till

    Till Administrator

    So kann das doch nicht gehen, die Passworte in der ispconfig DB sind natürlich verschlüsselt und zwar so, dass Du sie auch nicht entschlüsseln kannst (hash). Du brauchst die Passworte für die einzelnen DB's ja auch garnicht denn Du kannst ja den root user zum import nehmen.
     
  19. shadowcast

    shadowcast Member

    Huuuh. Bisher mit allen Tests gescheitert. Denke mal am nächsten war ich mit Post 11 und anschließendem 15, wo ich dann die Datenbank auswählen wollte, was aber so auch nicht geklappt hat.

    Bin ich wirklich noch so weit von der Lösung entfernt?

    Mit folgender Zeile schreibt mir das System: unknown database

    Kann es sein dass mein Plugin früher ausgeführt wird, als das, welches die Datenbank anlegt?

    HAH es funktioniert.

    Der Pluginname war vor alphabetisch vor MYSQL_CLIENTDB_PLUGIN.
    Einfach ein X vorangesetzt und plötzlich gehts.

    Oh Gott es ist 16 Uhr. Ein kompletter Arbeitstag mit solch einer "Kleinigkeit"
     
    Zuletzt bearbeitet: 27. Juni 2014

Diese Seite empfehlen