Seite 1 von 1

auf allen Clients mit Software X Software Y auf setup setzen

Verfasst: 05 Feb 2015, 15:02
von holgerv

Code: Alles auswählen

opsi-admin -dS method productOnClient_getHashes '["clientId"]' '{"productId":"X","installationStatus":"installed"}'|grep "^clientId="| cut -d "=" -f 2- > /tmp/liste.txt
while read opsihostname; do echo opsi-admin -dS method setProductActionRequestWithDependencies \"Y\" \"${opsihostname}\" \"setup\"; done < /tmp/liste.txt > /tmp/opsi-admin-commands.sh
sh /tmp//tmp/opsi-admin-commands.sh
Geht das nicht eleganter? Das Abarbeiten der /tmp/opsi-admin-commands.sh braucht schon bei unter 100 Rechnern mehrere Minuten (auf ansonsten zufriedenstellender Hardware).

Vielen Dank!


Holger

Re: auf allen Clients mit Software X Software Y auf setup se

Verfasst: 05 Feb 2015, 17:48
von pandel
Na ja, ich denke, du hast, was Softwareinstallation anbelangt, eben generell zwei Möglichkeiten:

- configed, und damit grafisch
- oder via API

Bei letzterem finde ich deine Lösung schon ganz schön elegant. Es ist auf's Nötigste reduziert und macht exakt was du willst.

Hast du das MySQL Modul im Einsatz als Backend für alles, oder speicherst du deine Config im File Backend? MySQL soll ja auch ne ganze Ecke fixer sein. Wir haben bis dato auch leider nur das File Backend am Start und das schneckt eben vor sich hin...

Inoffizielle Backend-Alternative:
MongoDB: https://github.com/dheid/opsi_mongodb/
PostgreSQL: https://github.com/kochd/opsi-postgres

Lieber Gruß
Holger

Re: auf allen Clients mit Software X Software Y auf setup se

Verfasst: 06 Feb 2015, 11:26
von dkoch
wiki/userspace:webservice_corner:ruby-rpc

Code: Alles auswählen

opsirpc.productOnClient_getHashes(['clientId'], {productId: 'X', installationStatus: "installed"}).each do |match|
  opsirpc.setProductActionRequestWithDependencies('Y', match['clientId'], 'setup')
end
Hier nochmal als Einzeiller dem Golffactor wegen:

Code: Alles auswählen

opsirpc.productOnClient_getHashes(['clientId'], {productId: 'X', installationStatus: "installed"}).each { |match| opsirpc.setProductActionRequestWithDependencies('Y', match['clientId'], 'setup') }


Das Problem beim Scripten mit Bash und nutzen von opsi-admin ist ganz einfach zu erklären:

Code: Alles auswählen

time opsi-admin -dS exit

real    0m0.694s
user    0m0.392s
sys     0m0.064s

Das bloße aufrufen und verlassen von opsi-admin dauert bereits 0.7 Sekunden.
Und das ist dein overhead pro Client ganz ohne den RPC weil Bash für jeden Client einen neuen Prozess von opsi-admin startet.

Re: auf allen Clients mit Software X Software Y auf setup se

Verfasst: 06 Feb 2015, 13:36
von pandel
dkoch hat geschrieben: Das bloße aufrufen und verlassen von opsi-admin dauert bereits 0.7 Sekunden.
Und das ist dein overhead pro Client ganz ohne den RPC weil Bash für jeden Client einen neuen Prozess von opsi-admin startet.
Hast du eine Ahnung, wieso? Liegt das am Python Interpreter?

Re: auf allen Clients mit Software X Software Y auf setup se

Verfasst: 06 Feb 2015, 13:41
von holgerv
Das sieht gut aus. Wenn ich häufiger solche Aufgaben kriege, sollte ich mir mal ein Äquivalent in Python schreiben.
dkoch hat geschrieben:Das bloße aufrufen und verlassen von opsi-admin dauert bereits 0.7 Sekunden.
Und das ist dein overhead pro Client ganz ohne den RPC weil Bash für jeden Client einen neuen Prozess von opsi-admin startet.
Ja, das leuchtet ein. Danke!


Holger

Re: auf allen Clients mit Software X Software Y auf setup se

Verfasst: 06 Feb 2015, 14:19
von dkoch
pandel hat geschrieben:
dkoch hat geschrieben: Das bloße aufrufen und verlassen von opsi-admin dauert bereits 0.7 Sekunden.
Und das ist dein overhead pro Client ganz ohne den RPC weil Bash für jeden Client einen neuen Prozess von opsi-admin startet.
Hast du eine Ahnung, wieso? Liegt das am Python Interpreter?
Authentifizierung, Logo, Completion, etc. pp., unnötige libraries wie curses werden geladen.

opsi-admin ist eigentlich als Shell designend und nicht als Interpreter.
Also anstatt das die Methode ausgeführt wird wird erst mal jede menge Zeug gemacht, dass man gar nicht bräuchte.

Das ist so als würde man ein Bashscript schreiben in dem dann sowas steht :

Code: Alles auswählen

for i in `seq 1 1000`
    echo "echo foo" | bash
done

Für eine interaktive Shell ist das alles wichtig und hilfreich. Für einen bloßen Interpreter aber unnötig

Re: auf allen Clients mit Software X Software Y auf setup se

Verfasst: 06 Feb 2015, 15:02
von pandel
Nachvollziehbar, danke! Wünschenswert wäre ja dann, wenn bspw. die Parameter -S, -s oder -r dafür sorgen würden, dass dieser ganze overhead nicht geladen wird. Das würds wahrscheinlich beschleunigen...

Re: auf allen Clients mit Software X Software Y auf setup se

Verfasst: 09 Feb 2015, 10:32
von n.wenselowski
Guten Morgen zusammen,
pandel hat geschrieben:Nachvollziehbar, danke! Wünschenswert wäre ja dann, wenn bspw. die Parameter -S, -s oder -r dafür sorgen würden, dass dieser ganze overhead nicht geladen wird. Das würds wahrscheinlich beschleunigen...
Hm, schwierig. Würde dann dazu führen dass irgendwo imports gemacht werden und sowas ist ziemlich schlechter Stil. Ein anderer Ansatz wäre der von wiederverwendbaren Interpretern, wie bspw. in The Python I Would Like To See beschrieben.

Ich würde vorschlagen das ganze entweder über ein eigenes Python-Script, in welchem der Backend-Zugang wiederverwendet wird, oder eine Erweiterung.
Hier eine (ungetestete) Backend-Erweiterung, die genau das machen sollte, was dein Script macht. Die kann dann über opsi-admin -d method installProductOnClientsWithProduct "foo" "bar" aufgerufen werden.

Code: Alles auswählen

def installProductOnClientsWithProduct(self, requiredProduct, productToInstall):
    clients = set([poc.clientId for poc  in self.productOnClient_getObjects(productId=requiredProduct, installationStatus="installed")])
    for clientId in clients:
        self.setProductActionRequestWithDependencies(productToInstall, clientId, "setup")

Für den Golffactor :D kann man das auch in einen Einzeiler packen:

Code: Alles auswählen

def installProductOnClientsWithProduct(self, requiredProduct, productToInstall):
    [self.setProductActionRequestWithDependencies(productToInstall, clientId, "setup") for clientId in set([poc.clientId for poc  in self.productOnClient_getObjects(productId=requiredProduct, installationStatus="installed")])]

Viele Grüße

Niko