auf allen Clients mit Software X Software Y auf setup setzen

Antworten
holgerv
Beiträge: 288
Registriert: 20 Aug 2012, 09:35

auf allen Clients mit Software X Software Y auf setup setzen

Beitrag 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
pandel
Beiträge: 830
Registriert: 25 Jan 2013, 16:47

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

Beitrag 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
dkoch
Beiträge: 309
Registriert: 25 Nov 2011, 14:03

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

Beitrag 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.
pandel
Beiträge: 830
Registriert: 25 Jan 2013, 16:47

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

Beitrag 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?
holgerv
Beiträge: 288
Registriert: 20 Aug 2012, 09:35

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

Beitrag 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
dkoch
Beiträge: 309
Registriert: 25 Nov 2011, 14:03

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

Beitrag 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
pandel
Beiträge: 830
Registriert: 25 Jan 2013, 16:47

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

Beitrag 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...
Benutzeravatar
n.wenselowski
Ex-uib-Team
Beiträge: 3194
Registriert: 04 Apr 2013, 12:15

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

Beitrag 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

Code: Alles auswählen

import OPSI
Antworten