#!/usr/bin/env python # -*- coding: utf-8 -*- """ospi-client: performs operation for opsi clients on opsi server via JSON-RPC.""" __author__ = "Joerg Steffens" __copyright__ = "Copyright 2012, dass IT GmbH" __license__ = "GPL" __version__ = "1.0" __email__ = "joerg.steffens@dass-it.de" # # Skript, dass ein OPSI-Rechner-Eintrag kopiert. # D.h. die Produkte, Anforderung. # Ggf. optional Stand und ggf. Versionsnummer # Ggf. optional ProductProperties # #self.command("opsi-admin -d method host_createOpsiClient "+ \ #computername + " null " + "\\'"+description+"\\'" + \ #" \\'created by dassadmin\\' " + mac_address + " " + \ #ip_address) #self.command("opsi-admin -d method configState_create clientconfig.depot.id " + \ #computername + " " + depotName) import argparse import jsonrpc from pprint import pprint UrlJsonRpc="https://:@opsi:4447/rpc" HelpEpilog="WARNING: python-json-rpc is known to have problems with HTTP proxies. In case of problems, make sure, the environment variables http_proxy and/or https_proxy are *not* set." class OpsiRpc: ProductAttributesCopy = ['actionRequest','actionResult','installationStatus','packageVersion','productVersion'] def __init__(self, urlJsonRpc, debug=False ): self.debug=debug self.urlJsonRpc=urlJsonRpc self.rpc=jsonrpc.ServiceProxy(self.urlJsonRpc) def dump(self): print self.urlJsonRpc print self.rpc.getClientIds_list() def list(self): return self.rpc.getClientIds_list() def exists(self, src): return len( self.rpc.host_getObjects( [], {"id":src} ) ) == 1 def info(self, src): if not self.exists( src ): print "failed: opsi client", src, "does not exist" return False print src + ":" host = self.rpc.host_getHashes( [], {"id":src} )[0] print " IP:", host["ipAddress"] print " MAC:", host["hardwareAddress"] print " inventory:", host["inventoryNumber"] print " last seen:", host["lastSeen"] print " notes:", host["notes"] print " products:" products = self.getProductOnClient( src, [] ) for i in products: print " " + i['productId'] + ":" print " " + i['installationStatus'], "(", if i['actionRequest']: print i['actionRequest'], if i['actionProgress']: print i['actionProgress'], print ")" print " ", pprint( i, indent=8 ) return True def clean(self, src): if not self.exists( src ): return False products = self.rpc.productOnClient_getObjects( [], { 'clientId': src } ) self.rpc.productOnClient_deleteObjects( products ) if self.debug: pprint( self.getProductOnClient( src ) ) return True def copyClient( self, src, dst, ipAddress = None, hardwareAddress = None, depot = None ): print "create/update", dst, "from template", src + ":", obj = { "id" : dst, "type" : "OpsiClient", "notes" : "copy of " + src, #"description" : "", #"inventoryNumber" : "", } if hardwareAddress: obj['hardwareAddress'] = hardwareAddress if ipAddress: obj['ipAddress'] = ipAddress if self.exists( dst ): self.rpc.host_updateObject(obj) else: self.rpc.host_insertObject(obj) if depot: self.rpc.configState_create( "clientconfig.depot.id", dst, depot ) if self.debug: pprint( self.getProductOnClient( src ) ) self.copyProductOnClient( src, dst ) # TODO: # copy product properties: # opsiCallClientBaculaProperties=[ "method", "getProductProperties_hash", "bacula" ] print "done" return True def getProductOnClient( self, client, attributes = ProductAttributesCopy ): #pprint( self.rpc.productOnClient_getObjects( [], { 'clientId': client } ) ) #pprint( self.rpc.productOnClient_getHashes( attributes, { 'clientId': client } ) ) return self.rpc.productOnClient_getHashes( [], { 'clientId': client } ) def copyProductOnClient( self, src, dst, attributes = ProductAttributesCopy ): products = self.rpc.productOnClient_getHashes( attributes, { 'clientId': src } ) for i in products: if self.debug: print i['productId'] pprint( i ) i['clientId'] = dst self.rpc.productOnClient_createObjects( i ) if self.debug: pprint( self.getProductOnClient( dst ) ) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Command line tool for OPSI configuration.', epilog=HelpEpilog ) parser.add_argument( '--url', required=True, help="OPSI Server JSON-RPC url, in following format: " + UrlJsonRpc ) parser.add_argument( '--debug', action='store_true', help="enable debugging output" ) #parser.add_argument( '--verbose', type=bool, help="add debugging output" ) subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands', help='additional help', dest='subcommand' ) parser_list = subparsers.add_parser('list', help='list all opsi clients' ) parser_exists = subparsers.add_parser('exists', help='check, if a opsi clients exists' ) parser_exists.add_argument( 'src', help="source opsi client" ) parser_info = subparsers.add_parser('info', help='print information about a opsi client' ) parser_info.add_argument( 'src', help="opsi client" ) parser_clean = subparsers.add_parser('clean', help='remove all product states from a opsi client' ) parser_clean.add_argument( 'src', help="source opsi client to clean" ) parser_copy = subparsers.add_parser('copy', help='copy/create a opsi client from a template opsi client') parser_copy.add_argument( 'src', help="source/template opsi client" ) parser_copy.add_argument( 'dst', help="opsi client to be created" ) parser_copy.add_argument( '--ip', help="IP address of the new opsi client" ) parser_copy.add_argument( '--mac', help="MAC address of the new opsi client" ) parser_copy.add_argument( '--depot', help="depot server the new opsi client should be located" ) args = parser.parse_args() opsi=OpsiRpc( args.url, args.debug ) result = True if args.subcommand == "list": print( "\n".join( opsi.list() ) ) elif args.subcommand == "exists": result = opsi.exists( args.src ) elif args.subcommand == "info": result = opsi.info( args.src ) elif args.subcommand == "clean": result = opsi.clean( args.src ) elif args.subcommand == "copy": result = opsi.copyClient( args.src, args.dst, args.ip, args.mac, args.depot ) else: print "not yet implemented" if args.debug: print result if result: exit(0) else: exit(1)