Ignore:
Timestamp:
Feb 18, 2015, 4:43:07 PM (10 years ago)
Author:
joergs
Message:

only copy properties that differ from default settings

File:
1 edited

Legend:

Unmodified
Added
Removed
  • opsi/server/dass-opsi-tools/usr/bin/opsiclient

    r1118 r1174  
    66
    77__author__ = "Joerg Steffens"
    8 __copyright__ = "Copyright 2012, dass IT GmbH"
     8__copyright__ = "Copyright 2012-2015, dass IT GmbH"
    99__license__ = "GPL"
    1010__version__ = "1.1"
     
    1616        #ip_address)
    1717#self.command("opsi-admin -d method configState_create clientconfig.depot.id " + \
    18         #computername + " " + depotName)                       
    19                        
     18        #computername + " " + depotName)
     19
    2020import argparse
    2121import jsonrpc
    2222import logging
    2323import os
    24 from pprint import pprint
     24from pprint import pprint, pformat
    2525import time
    2626
     
    3232
    3333    UrlJsonRpcDefault="https://opsi:4447/rpc"
    34    
     34
    3535    ProductAttributesCopy = ['actionRequest','actionResult','installationStatus','packageVersion','productVersion']
    36    
     36
    3737    def __init__(self, urlJsonRpc = UrlJsonRpcDefault, debug=False ):
    38         self.logger=logging.getLogger(__name__)       
     38        self.logger=logging.getLogger(__name__)
    3939        self.debug=debug
    4040        self.urlJsonRpc=urlJsonRpc
     
    4242        self.logger.debug( "initialized: " + self.urlJsonRpc )
    4343
    44        
     44
    4545    def list(self):
    4646        print( "\n".join( self.rpc.getClientIds_list() ) )
    4747        return True
    4848
    49        
     49
    5050    def getClientsWithProduct( self, product ):
    5151        return self.rpc.productOnClient_getObjects( [], { "productId": product, "installationStatus": "installed" } )
     
    5959            return self.list()
    6060        return True
    61        
    62        
     61
    6362    def exists(self, src):
    6463        return len( self.rpc.host_getObjects( [], {"id":src} ) ) == 1
    65        
     64
    6665    def info(self, src):
    6766        if not self.exists( src ):
     
    7574        print "  last seen:", host["lastSeen"]
    7675        print "  notes:", host["notes"]
    77        
     76
    7877        print "  products:"
    7978        products = self.getProductOnClient( src, [] )
     
    9897        products = self.rpc.productPropertyState_getObjects( [], { 'objectId': src } )
    9998        self.rpc.productPropertyState_deleteObjects( products )
    100        
     99
    101100        if self.debug:
    102101            pprint( self.getProductOnClient( src ) )
    103102        return True
    104        
     103
     104    def getOpsiConfigserverId(self):
     105        # there should always be only one OpsiConfigserver
     106        opsiConfigservers=self.rpc.host_getHashes( [], { "type": "OpsiConfigserver" } )
     107        try:
     108            return opsiConfigservers[0]['id']
     109        except (KeyError,IndexError) as e:
     110            self.logger.error( "failed to retreive OpsiConfigserver" )
     111
    105112    def createClient(self, name, opsiHostKey, description, notes, hardwareAddress, ipAddress):
    106113        #    self.rpc.host_createOpsiClient( name, opsiHostKey, description, notes, hardwareAddress, ipAddress )
     
    117124            obj['description'] = description
    118125        if notes:
    119             obj['notes'] = notes           
     126            obj['notes'] = notes
    120127        if hardwareAddress:
    121128            obj['hardwareAddress'] = hardwareAddress
     
    127134        else:
    128135            self.rpc.host_insertObject(obj)
    129            
     136
    130137        if depot:
    131138            self.clientSetDepot(src,depot)
     
    133140
    134141
    135        
    136142    def clientSetDepot(self, name, depot):
    137         self.rpc.configState_create( "clientconfig.depot.id", name, depot )       
     143        self.rpc.configState_create( "clientconfig.depot.id", name, depot )
    138144
    139145    def copyClient( self, src, dst, ipAddress = None, hardwareAddress = None, depot = None, description = "", copyProperties = True ):
    140    
     146
    141147        print "create/update", dst, "from template", src + ":",
    142148        obj = {
     
    156162        else:
    157163            self.rpc.host_insertObject(obj)
    158            
     164
    159165        if depot:
    160166            self.clientSetDepot(dst,depot)
    161            
     167
    162168        if self.debug:
    163169            pprint( self.getProductOnClient( src ) )
    164170        self.copyProductOnClient( src, dst )
    165         # TODO:
    166         #  copy product properties:
    167         #  opsiCallClientBaculaProperties=[ "method", "getProductProperties_hash", "bacula" ]
    168171        if copyProperties:
    169172            if self.debug:
    170173                print "copy product properties"
    171             self.copyProductPropertyState( src, dst )
     174            if not depot:
     175                # get default Properties from Master Depot Server (OpsiConfigserver)
     176                depot = self.getOpsiConfigserverId()
     177            self.copyProductPropertyState( src, dst, depot )
    172178        print "done"
    173179        return True
    174 
    175 
    176180
    177181    def getProductOnClient( self, client, attributes = ProductAttributesCopy ):
    178182        return self.rpc.productOnClient_getHashes( [], { 'clientId': client } )
    179 
    180 
    181183
    182184    def copyProductOnClient( self, src, dst, attributes = ProductAttributesCopy ):
     
    193195            pprint( self.getProductOnClient( dst ) )
    194196
     197
    195198    def getProductPropertyState( self, client, attributes = [] ):
    196199        return self.rpc.productPropertyState_getHashes( [], { 'objectId': client } )
    197                        
    198     def copyProductPropertyState( self, src, dst, attributes = [] ):
     200
     201
     202    def copyProductPropertyState( self, src, dst, default = None, attributes = [] ):
     203        if default:
     204            productProperties_default = self.getProductPropertyState( default, attributes )
     205        else:
     206            productProperties_default = []
    199207        productProperties_src = self.getProductPropertyState( src, attributes )
    200208        productProperties_dst = []
    201209        for i in productProperties_src:
    202             if self.debug:
    203                 print i['productId'], "-", i["propertyId"] + ": ",
    204                 pprint(i["values"])
    205                 #pprint( i )
    206             i['objectId'] = dst
    207             productProperties_dst.append(i)
     210            use_default=False
     211            for j in productProperties_default:
     212                if i['productId'] == j['productId'] and i["propertyId"] == j["propertyId"]:
     213                    if i['values'] == j['values']:
     214                        use_default=True
     215            if self.debug:
     216                print i['productId'], "-", i["propertyId"] + ": ", pformat(i["values"]),
     217                if use_default:
     218                    print "(use default)"
     219                else:
     220                    print "(set)"
     221            if not use_default:
     222                i['objectId'] = dst
     223                productProperties_dst.append(i)
    208224        self.rpc.productPropertyState_createObjects( productProperties_dst )
    209225        if self.debug:
     
    251267        fd.write( "}\n")
    252268        fd.write( "\n" )
    253        
    254        
    255269
    256270
     
    280294
    281295    def write_config_file_header( self, fd ):
    282         try:       
     296        try:
    283297            fd.write( "#\n" )
    284298            fd.write( "# automatically generated at {0}\n".format( time.asctime() ) )
     
    288302            return False
    289303        return True
    290            
     304
    291305
    292306    def createBaculaConfigFiles( self ):
     
    296310                file_opsi_clients = open('opsi-clients-generated.conf', 'w')
    297311                self.write_config_file_header( file_opsi_clients )
    298                
     312
    299313                file_opsi_jobs = open('opsi-jobs-generated.conf', 'w')
    300314                self.write_config_file_header( file_opsi_jobs )
    301             except BaseException as e:       
     315            except BaseException as e:
    302316                self.logger.exception( "failed to create files" )
    303317                return False
    304318            for client in clientsWithBacula:
    305                 clientId = client['clientId']               
     319                clientId = client['clientId']
    306320                try:
    307321                    clientBaculaProperties=self.getClientProductProperty( clientId, "bacula" )
     
    345359    parser_clean = subparsers.add_parser('clean', help='remove all product states from a opsi client' )
    346360    parser_clean.add_argument( 'src', help="source opsi client to clean" )
    347                    
    348     parser_copy = subparsers.add_parser('copy', help='copy/create a opsi client from a template opsi client')   
     361
     362    parser_copy = subparsers.add_parser('copy', help='copy/create a opsi client from a template opsi client')
    349363    parser_copy.add_argument( 'src', help="source/template opsi client" )
    350364    parser_copy.add_argument( 'dst', help="opsi client to be created" )
     
    353367    parser_copy.add_argument( '--depot', help="depot server the new opsi client should be located" )
    354368    #parser_copy.add_argument( '--no-properties', action='store_false', help="don't copy product properties" )
    355        
     369
    356370    parser_createBaculaConfigFiles = subparsers.add_parser('createBaculaConfigFiles', help='create Bacula config files for all clients that have bacula installed')
    357371
    358372    parser_exists = subparsers.add_parser('exists', help='check, if a opsi clients exists' )
    359373    parser_exists.add_argument( 'src', help="source opsi client" )
    360    
    361374    #parser_list = subparsers.add_parser('list', help='list all opsi clients' )
    362    
     375
    363376    parser_listClients = subparsers.add_parser('listClients', help='list opsi clients')
    364377    parser_listClients.add_argument( '--product', help="only list clients, that have product installed" )
    365    
     378
    366379    parser_info = subparsers.add_parser('info', help='print information about a opsi client' )
    367380    parser_info.add_argument( 'src', help="opsi client" )
    368    
     381
    369382    parser_update = subparsers.add_parser('update', help='update/create a opsi client')
    370383    parser_update.add_argument( 'src', help="opsi client to be created" )
     
    391404        else:
    392405            parser.error( "argument --url is required" )
    393        
     406
    394407    opsi=OpsiRpc( url, args.debug )
    395    
     408
    396409    result = True
    397410
    398     if args.subcommand == "clean":
    399         result = opsi.clean( args.src )
    400     elif args.subcommand == "copy":
    401         result = opsi.copyClient( args.src, args.dst, args.ip, args.mac, args.depot )
    402     elif args.subcommand == "createBaculaConfigFiles":
    403         result = opsi.createBaculaConfigFiles()
    404     elif args.subcommand == "exists":
    405         result = opsi.exists( args.src )       
    406     elif args.subcommand == "list":
    407         result = opsi.list()
    408     elif args.subcommand == "listClients":         
    409         result = opsi.listClients( args.product )       
    410     elif args.subcommand == "info":
    411         result = opsi.info( args.src )
    412     elif args.subcommand == "update":
    413         result = opsi.updateClient( args.src, None, args.description, args.notes, args.mac, args.ip, args.depot )
    414     else:
    415         print "not yet implemented"
    416 
    417     if args.debug: print result   
    418        
     411    try:
     412        if args.subcommand == "clean":
     413            result = opsi.clean( args.src )
     414        elif args.subcommand == "copy":
     415            result = opsi.copyClient( args.src, args.dst, args.ip, args.mac, args.depot )
     416        elif args.subcommand == "createBaculaConfigFiles":
     417            result = opsi.createBaculaConfigFiles()
     418        elif args.subcommand == "exists":
     419            result = opsi.exists( args.src )
     420        elif args.subcommand == "list":
     421            result = opsi.list()
     422        elif args.subcommand == "listClients":
     423            result = opsi.listClients( args.product )
     424        elif args.subcommand == "info":
     425            result = opsi.info( args.src )
     426        elif args.subcommand == "update":
     427            result = opsi.updateClient( args.src, None, args.description, args.notes, args.mac, args.ip, args.depot )
     428        else:
     429            print "not yet implemented"
     430    except IOError as e:
     431        result = False
     432        # connection refused
     433        print "failed:", e
     434
     435    if args.debug: print result
     436
    419437    if result:
    420438        exit(0)
Note: See TracChangeset for help on using the changeset viewer.