source: opsi/server/dass-opsi-tools/usr/bin/opsiclient

Last change on this file was 1239, checked in by joergs, 2 years ago

added createBareosConfigFiles

  • try to allow alternatives to jsonrpc, however tests with jsonrpclib (jsonrpclib_pelix-0.3.1) have not been successful.
  • createBareosConfigFiles
    • replaced createBaculaConfigFiles
    • provide default parameter for JobDefs and FileSet
    • store resulting files to correct location /etc/bareos/bareos-dir.d/*/opsi-*-generated.conf
  • Property svn:executable set to *
File size: 26.3 KB
Line 
1#!/usr/bin/env python
2
3# -*- coding: utf-8 -*-
4
5"""ospi-client: performs operation for opsi clients on opsi server via JSON-RPC."""
6
7from __future__ import print_function
8
9__author__ = "Joerg Steffens"
10__copyright__ = "Copyright 2012-2018, dass IT GmbH"
11__license__ = "GPL"
12__version__ = "1.2"
13__email__ = "joerg.steffens@dass-it.de"
14
15#self.command("opsi-admin -d method host_createOpsiClient "+ \
16        #computername + " null " + "\\'"+description+"\\'" + \
17        #" \\'created by dassadmin\\' " + mac_address + " " + \
18        #ip_address)
19#self.command("opsi-admin -d method configState_create clientconfig.depot.id " + \
20        #computername + " " + depotName)
21
22import argparse
23from   datetime import datetime, timedelta
24from   dateutil import parser as dateparser
25import logging
26import os
27from   pprint import pprint, pformat
28import sys
29import ssl
30import time
31
32try:
33    import jsonrpc
34except ImportError:
35    import jsonrpclib
36
37
38UrlJsonRpc="https://<username>:<password>@opsi:4447/rpc"
39
40HelpEpilog="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. It might also be neccesary to set variable PYTHONHTTPSVERIFY=0"
41
42class Nrpe:
43    OK = 0
44    WARNING = 1
45    CRITICAL = 2
46    UNKNOWN = 3
47   
48    def toString(self, status):
49        if status == self.OK:
50            return 'OK'
51        elif status == self.WARNING:
52            return 'WARNING'
53        elif status == self.CRITICAL:
54            return 'CRITICAL'
55        else:
56            return 'UNKNOWN'
57
58class Output(Nrpe):
59    def __init__(self, nagios=False):
60        self.nagios = nagios
61        self.result = Nrpe.UNKNOWN
62        self.message = ''
63
64    def setStatus(self, status, message = None):
65        self.result = status
66        if message is not None:
67            self.setMessage(message)
68
69    def setMessage(self, string):
70        self.message = string
71
72    def finalize(self):
73        if self.nagios:
74            print('{0} - {1}'.format(self.toString(self.result), self.message))
75            sys.exit(self.result)
76        else:
77            print('{0} - {1}'.format(self.toString(self.result), self.message))
78            return (self.result == Nrpe.OK)
79
80class OpsiRpc:
81
82    UrlJsonRpcDefault="https://opsi:4447/rpc"
83
84    ProductAttributesCopy = ['actionRequest','actionResult','installationStatus','packageVersion','productVersion']
85
86    def __init__(self, urlJsonRpc = UrlJsonRpcDefault, debug=False, nagios=False):
87        self.logger=logging.getLogger(__name__)
88        self.debug=debug
89        self.nagios=nagios
90        self.urlJsonRpc=urlJsonRpc
91        if 'jsonrpc' in sys.modules:
92            self.rpc=jsonrpc.ServiceProxy(self.urlJsonRpc)
93        else:
94            self.rpc=jsonrpclib.ServerProxy(self.urlJsonRpc)
95        self.logger.debug( "initialized: " + self.urlJsonRpc )
96        self.logger.debug(dir(self.rpc))
97
98
99    def list(self):
100        exceptions = []
101        if 'jsonrpc' in sys.modules:
102            exceptions = [ jsonrpc.json.JSONDecodeException ]
103        try:
104            print( "\n".join( self.rpc.getClientIds_list() ) )
105        except exceptions as e:
106            self.logger.debug( pformat(self.rpc.getClientIds_list()) )
107            self.logger.exception( "failed" )
108            return True
109
110
111    def getClientsWithProduct( self, product ):
112        return self.rpc.productOnClient_getObjects( [], { "productId": product, "installationStatus": "installed" } )
113
114    def getHardwareSerialNumber(self, src):
115        serialNumbers  = self.rpc.auditHardwareOnHost_getHashes( [], {"hostId":src, "hardwareClass":"BIOS", "serialNumber":"*"} )
116        serialNumbers += self.rpc.auditHardwareOnHost_getHashes( [], {"hostId":src, "hardwareClass":"CHASSIS", "serialNumber":"*"} )
117        result = set()
118        for i in serialNumbers:
119            if i['serialNumber']:
120                result.add(i['serialNumber'])
121        if len(result) == 1:
122            return result.pop()
123        elif len(result) > 1:
124            self.logger.warning("found more then one serial number")
125            return list(result)
126
127    def listClients( self, product ):
128        if product:
129            for client in self.getClientsWithProduct( product ):
130                print(client['clientId'])
131        else:
132            return self.list()
133        return True
134
135    def exists(self, src):
136        return len( self.rpc.host_getObjects( [], {"id":src} ) ) == 1
137
138    def info(self, src):
139        if not self.exists( src ):
140            print("failed: opsi client", src, "does not exist")
141            return False
142        print(src + ":")
143        host = self.rpc.host_getHashes( [], {"id":src} )[0]
144        print("  IP:", host["ipAddress"])
145        print("  MAC:", host["hardwareAddress"])
146        print("  inventory:", host["inventoryNumber"])
147        print("  serial number:", self.getHardwareSerialNumber(src))
148        print("  last seen:", host["lastSeen"])
149        print("  notes:", host["notes"])
150        print("  depot:", self.clientGetDepot(src))
151
152        print("  products:")
153        products = self.getProductOnClient( src, [] )
154        for i in products:
155            print("    " + i['productId'] + ":")
156            print("      " + i['installationStatus'], "(", end='')
157            if i['actionRequest']:
158                print(i['actionRequest'], end='')
159                if i['actionProgress']:
160                    print(i['actionProgress'], end='')
161            print(")")
162            print("      ", end='')
163            pprint( i, indent=8 )
164        return True
165
166    def clean(self, src):
167        if not self.exists( src ):
168            return False
169        products = self.rpc.productOnClient_getObjects( [], { 'clientId': src } )
170        self.rpc.productOnClient_deleteObjects( products )
171
172        products = self.rpc.productPropertyState_getObjects( [], { 'objectId': src } )
173        self.rpc.productPropertyState_deleteObjects( products )
174
175        if self.debug:
176            pprint( self.getProductOnClient( src ) )
177        return True
178
179    def getOpsiConfigserverId(self):
180        # there should always be only one OpsiConfigserver
181        opsiConfigservers=self.rpc.host_getHashes( [], { "type": "OpsiConfigserver" } )
182        try:
183            return opsiConfigservers[0]['id']
184        except (KeyError,IndexError) as e:
185            self.logger.error( "failed to retreive OpsiConfigserver" )
186
187    def createClient(self, name, opsiHostKey, description, notes, hardwareAddress, ipAddress):
188        #    self.rpc.host_createOpsiClient( name, opsiHostKey, description, notes, hardwareAddress, ipAddress )
189        self.updateClient( name, opsiHostKey, description, notes, None, hardwareAddress, ipAddress )
190
191    def deleteClient(self, name):
192        self.rpc.host_delete( name )
193
194    def updateClient(self, src, opsiHostKey = None, description = None, notes = None, inventoryNumber = None, hardwareAddress = None, ipAddress = None, depot = None ):
195        obj = {
196          "id" : src,
197          "type" : "OpsiClient",
198        }
199        if opsiHostKey:
200            obj['opsiHostKey'] = opsiHostKey
201        if description:
202            obj['description'] = description
203        if notes:
204            obj['notes'] = notes
205        if inventoryNumber:
206            obj['inventoryNumber'] = inventoryNumber
207        if hardwareAddress:
208            obj['hardwareAddress'] = hardwareAddress
209        if ipAddress:
210            obj['ipAddress'] = ipAddress
211
212        if self.exists( src ):
213            self.rpc.host_updateObject(obj)
214        else:
215            self.rpc.host_insertObject(obj)
216
217        if depot:
218            self.clientSetDepot(src,depot)
219        return True
220
221    def clientGetDepot(self, name):
222        depot = self.rpc.configState_getHashes( [], {
223            "configId": "clientconfig.depot.id",
224            "objectId": name } )
225        try:
226            return depot[0]["values"][0]
227        except (IndexError,KeyError):
228            return self.getOpsiConfigserverId()
229
230    def clientSetDepot(self, name, depot):
231        self.rpc.configState_create( "clientconfig.depot.id", name, depot )
232
233    def copyClient( self, src, dst, ipAddress = None, hardwareAddress = None, depot = None, description = "", copyProperties = True ):
234
235        print("create/update", dst, "from template", src + ":", end='')
236        obj = {
237          "id" : dst,
238          "type" : "OpsiClient",
239          "notes" : "copy of " + src,
240          "description" : description,
241          #"inventoryNumber" : "",
242        }
243        if hardwareAddress:
244            obj['hardwareAddress'] = hardwareAddress
245        if ipAddress:
246            obj['ipAddress'] = ipAddress
247
248        if self.exists( dst ):
249            self.rpc.host_updateObject(obj)
250        else:
251            self.rpc.host_insertObject(obj)
252
253        if depot:
254            self.clientSetDepot(dst,depot)
255
256        if self.debug:
257            pprint( self.getProductOnClient( src ) )
258        self.copyProductOnClient( src, dst )
259        if copyProperties:
260            if self.debug:
261                print("copy product properties")
262            if not depot:
263                # get default Properties from Master Depot Server (OpsiConfigserver)
264                depot = self.getOpsiConfigserverId()
265            self.copyProductPropertyState( src, dst, depot )
266        print("done")
267        return True
268
269    def getProductOnClient( self, client, attributes = ProductAttributesCopy ):
270        return self.rpc.productOnClient_getHashes( [], { 'clientId': client } )
271
272    def copyProductOnClient( self, src, dst, attributes = ProductAttributesCopy ):
273        products_src = self.rpc.productOnClient_getHashes( attributes, { 'clientId': src } )
274        products_dst = []
275        for i in products_src:
276            if self.debug:
277                print(i['productId'])
278                pprint( i )
279            i['clientId'] = dst
280            products_dst.append(i)
281        self.rpc.productOnClient_createObjects( products_dst )
282        if self.debug:
283            pprint( self.getProductOnClient( dst ) )
284
285
286    def getProductPropertyState( self, client, attributes = [] ):
287        return self.rpc.productPropertyState_getHashes( [], { 'objectId': client } )
288
289
290    def copyProductPropertyState( self, src, dst, default = None, attributes = [] ):
291        if default:
292            productProperties_default = self.getProductPropertyState( default, attributes )
293        else:
294            productProperties_default = []
295        productProperties_src = self.getProductPropertyState( src, attributes )
296        productProperties_dst = []
297        for i in productProperties_src:
298            use_default=False
299            default_value=None
300            for j in productProperties_default:
301                if i['productId'] == j['productId'] and i["propertyId"] == j["propertyId"]:
302                    default_value = j['values']
303                    if i['values'] == j['values']:
304                        use_default=True
305            if self.debug:
306                print(i['productId'], "-", i["propertyId"] + ": ", pformat(i["values"]), end='')
307                if use_default:
308                    print("(use default)")
309                else:
310                    print("(set, default:", default_value, ")")
311            if not use_default:
312                i['objectId'] = dst
313                productProperties_dst.append(i)
314        self.rpc.productPropertyState_createObjects( productProperties_dst )
315        if self.debug:
316            pprint( self.getProductPropertyState( dst ) )
317
318
319    def getClientProductProperty( self, client, product ):
320        return self.rpc.getProductProperties_hash( product, [ client ] )
321
322    def setProductPropertiesOnClient( self, dst, product, properties ):
323        self.rpc.setProductProperties(product,properties,dst)
324
325    def setProductPropertyOnClient( self, dst, product, prop, value):
326        self.rpc.setProductProperty(product,prop,value,dst)
327
328
329
330    def write_value_conf(self, fd, key, properties, default=None):
331        value = None
332        comment = ''
333        try:
334            value = properties[key.lower()]
335        except KeyError:
336            pass
337        if not value and default:
338            value = default
339        if not value:
340            # prevent a None to be written
341            value = ''
342            comment = '# '
343        fd.write('  {}{} = "{}"\n'.format(comment, key, value))
344
345
346
347    def write_client_conf( self, fd, client, properties ):
348        #Client {
349        #Name = ting-fd
350        #Address = ting.dass-it
351        #FDPort = 9102
352        #Password = "D5w2V5w6B8a9H5Z"
353        #Catalog = MyCatalog
354        #File Retention = 6 months
355        #Job Retention = 6 months
356        #AutoPrune = yes
357        #}
358        params = [ 'catalog', "FDPort", "FileRetention", "JobRetention", "AutoPrune" ]
359        fd.write( "Client {\n" )
360        fd.write( '  Name     = "' + properties['filedaemon_full_name'] + '"' + "\n" )
361        fd.write( '  Address  = "' + properties['filedaemon_client_address'] + '"' + "\n" )
362        # ipAddress: method host_getObjects [] '{"id":client['clientId']}'
363        #print("  # Address =", ipAddress)
364        fd.write( '  Password = "' + properties['filedaemon_full_password'] + '"' + "\n" )
365        for i in params:
366            self.write_value_conf(fd, i, properties)
367        fd.write( "}\n")
368        fd.write( "\n" )
369
370
371    def write_job_conf(self, fd, client, properties, defaultjobdefs, defaultfileset):
372        #Job {
373        #FileSet = "tingfileset"
374        #Name = "ting"
375        #Client = ting-fd
376        #JobDefs = "LaptopJob"
377        ## Write Bootstrap = "/var/lib/bacula/ting.bsr"
378        #}
379        params = [ "JobDefs", "FileSet" ]
380        fd.write( "Job {" + "\n" )
381        fd.write( '  Name    = "' + client['clientId'] + '-job"' + "\n" )
382        fd.write( '  Client  = "' + properties['filedaemon_full_name'] + '"' + "\n" )
383        self.write_value_conf(fd, 'JobDefs', properties, defaultjobdefs)
384        self.write_value_conf(fd, 'FileSet', properties, defaultfileset)
385        fd.write( "}" + "\n" )
386        fd.write( "\n" )
387
388
389    def write_config_file_header( self, fd ):
390        try:
391            fd.write( "#\n" )
392            fd.write( "# automatically generated at {0}\n".format( time.asctime() ) )
393            fd.write( "#\n\n" )
394        except BaseException as e:
395            self.logger.exception( "failed to create files" )
396            return False
397        return True
398
399
400
401    def createBareosConfigFiles(self, defaultjobdefs, defaultfileset):
402        bareosDirConfigPath = '/etc/bareos/bareos-dir.d/'
403        clientsWithBacula=self.getClientsWithProduct('winbareos')
404        if clientsWithBacula:
405            try:
406                configfile = bareosDirConfigPath + 'client/opsi-clients-generated.conf'
407                file_opsi_clients = open(configfile, 'w')
408                self.write_config_file_header( file_opsi_clients )
409            except (BaseException, IOError) as e:
410                self.logger.exception( "failed to create configuration file {}".format(configfile) )
411                return False
412
413            try:
414                configfile = bareosDirConfigPath + 'job/opsi-jobs-generated.conf'
415                file_opsi_jobs = open(configfile, 'w')
416                self.write_config_file_header( file_opsi_jobs )
417            except (BaseException, IOError) as e:
418                self.logger.exception( "failed to create configuration file {}".format(configfile) )
419                return False
420
421            for client in clientsWithBacula:
422                clientId = client['clientId']
423                try:
424                    clientBaculaProperties=self.getClientProductProperty( clientId, 'winbareos' )
425                except ValueError as e:
426                    self.logger.warn( "%s: no valid information found: %s" %(clientId, e) )
427                else:
428                    if clientBaculaProperties:
429                        #pprint( clientBaculaProperties )
430                        self.write_client_conf(file_opsi_clients, client, clientBaculaProperties)
431                        self.write_job_conf(file_opsi_jobs, client, clientBaculaProperties, defaultjobdefs, defaultfileset)
432                        self.logger.info( "%s: OK" % clientId )
433                    else:
434                        self.logger.warn( "%s: failed: no product properties defined" %(clientId) )
435            return True
436
437    def __getVersionString(self, product):
438        return '{productVersion}-{packageVersion}'.format(**product)
439
440    def getProductCurrentVersion(self, productId):
441        products = self.rpc.product_getHashes( [], { 'id': productId } )
442        if products:
443            return self.__getVersionString(products[0])
444        else:
445            return None
446
447    def __getClientId(self, d):
448        return d.get("clientId")
449
450    def listInstalled(self, productId):
451        productVersion = self.getProductCurrentVersion(productId)
452        self.logger.debug('version: {0}'.format(productVersion))
453        products = self.rpc.productOnClient_getHashes( [], { 'productId': productId } )
454        for i in sorted(products, key=self.__getClientId):
455            i['version'] = self.__getVersionString(i)
456            if i.get('installationStatus') == 'installed':
457                if productVersion != i['version']:
458                    i['proposedAction'] = 'update'
459                else:
460                    i['proposedAction'] = 'None'
461                print('{clientId}: {version} (proposed action={proposedAction})'.format(**i))
462            else:
463                i['proposedAction'] = 'install'
464                print('{clientId}: (proposed action={proposedAction})'.format(**i))
465                self.logger.debug('{clientId}: {actionRequest} {installationStatus} {version}'.format(**i))
466            #pprint( i, indent=8 )
467        return True
468
469    def isInstalled(self, clientId, productId):
470        """
471        CRITICAL: not installed
472        WARNING: installed, but not current version
473        OK: current version is installed
474        UNKNOWN: otherwise
475        """
476        output = Output(self.nagios)
477        if not self.exists(clientId):
478            output.setMessage("failed: opsi client {0} does not exist".format(clientId))
479            return output.finalize()
480        productVersion = self.getProductCurrentVersion(productId)
481        if not productVersion:
482            output.setMessage("failed: product {0} does not exist".format(productId))
483            return output.finalize()
484        self.logger.debug('version: {0}'.format(productVersion))
485        products = self.rpc.productOnClient_getHashes( [], { "clientId": clientId,'productId': productId } )
486        if len(products) != 1:
487            print("failed: opsi client ({0}) product ({1}) combination does not exist".format(clientId, productId))
488            return False           
489        for i in sorted(products, key=self.__getClientId):
490            i['version'] = self.__getVersionString(i)
491            if i.get('installationStatus') == 'installed':
492                if productVersion != i['version']:
493                    i['proposedAction'] = 'update'
494                    output.setStatus(Nrpe.WARNING)
495                else:
496                    i['proposedAction'] = 'None'
497                    output.setStatus(Nrpe.OK)
498                output.setMessage('{version} (proposed action={proposedAction})'.format(**i))
499            else:
500                i['proposedAction'] = 'install'
501                output.setStatus(Nrpe.CRITICAL, 'not installed (proposed action={proposedAction})'.format(**i))
502                self.logger.debug('{clientId}: {actionRequest} {installationStatus} {version}'.format(**i))
503        return output.finalize()
504
505
506    def clientLastSeen(self, clientId):
507        """
508        < 1 day: OK
509        < 2 days: WARNING
510        otherwise: CRITICAL
511        """
512        output = Output(self.nagios)
513        if not self.exists(clientId):
514            output.setMessage("failed: opsi client {0} does not exist".format(clientId))
515            return output.finalize()
516        host = self.rpc.host_getHashes( [], {"id":clientId} )[0]
517        lastSeen = dateparser.parse(host["lastSeen"])
518        output.setMessage(str(lastSeen))
519        diff = datetime.now() - lastSeen
520        output.setMessage('{0} ({1} ago)'.format(str(lastSeen), diff))
521        if diff < timedelta(1):
522            output.setStatus(Nrpe.OK)
523        elif diff < timedelta(2):
524            output.setStatus(Nrpe.WARNING)
525        else:
526            output.setStatus(Nrpe.CRITICAL)
527        return output.finalize()
528
529
530
531if __name__ == '__main__':
532    logging.basicConfig(format='%(message)s')
533    logger = logging.getLogger(__name__)
534    logger.setLevel(logging.INFO)
535   
536    parser = argparse.ArgumentParser(
537        description='Command line tool for OPSI configuration.',
538        epilog=HelpEpilog
539    )
540
541    parser.add_argument( '--debug', action='store_true', help="enable debugging output" )
542    parser.add_argument('--nagios', action='store_true', help='output in Nagios NRPE format')
543
544    parser_url = parser.add_mutually_exclusive_group(required=True)
545    parser_url.add_argument( '--url', help="OPSI Server JSON-RPC url, in following format: " + UrlJsonRpc )
546   
547    parser_url.add_argument( '--server', help="OPSI Server (instead of URL)" )
548    username_default=os.getlogin()
549   
550    parser.add_argument( '--username', help="username (instead of URL), default: " + username_default, default=username_default )
551    parser.add_argument( '--password', help="password (instead of URL)" )
552   
553    subparsers = parser.add_subparsers(title='subcommands',
554        description='valid subcommands',
555        help='additional help',
556        dest='subcommand' )
557
558    parser_clean = subparsers.add_parser('clean', help='remove all product states from a opsi client' )
559    parser_clean.add_argument( 'src', help="source opsi client to clean" )
560
561    parser_copy = subparsers.add_parser('copy', help='copy/create a opsi client from a template opsi client')
562    parser_copy.add_argument( 'src', help="source/template opsi client" )
563    parser_copy.add_argument( 'dst', help="opsi client to be created" )
564    parser_copy.add_argument( '--ip', help="IP address of the new opsi client" )
565    parser_copy.add_argument( '--mac', help="MAC address of the new opsi client" )
566    parser_copy.add_argument( '--depot', help="depot server the new opsi client should be located" )
567    #parser_copy.add_argument( '--no-properties', action='store_false', help="don't copy product properties" )
568
569    parser_createBareosConfigFiles = subparsers.add_parser(
570        'createBareosConfigFiles',
571        help='create Bareos config files for all clients that have winbareos installed',
572        formatter_class=argparse.ArgumentDefaultsHelpFormatter
573    )
574    parser_createBareosConfigFiles.add_argument(
575        '--defaultjobdefs',
576        metavar='JobDefs',
577        default='DefaultJob',
578        help="use this JobDefs if no other is defined for a client"
579    )
580    parser_createBareosConfigFiles.add_argument(
581        '--defaultfileset',
582        metavar='FileSet',
583        help="use this FileSet if no other is defined for a client"
584    )
585
586    parser_exists = subparsers.add_parser('exists', help='check, if a opsi clients exists' )
587    parser_exists.add_argument( 'src', help="source opsi client" )
588    #parser_list = subparsers.add_parser('list', help='list all opsi clients' )
589
590    parser_listClients = subparsers.add_parser('listClients', help='list opsi clients')
591    parser_listClients.add_argument( '--product', help="only list clients, that have product installed" )
592
593    parser_info = subparsers.add_parser('info', help='print information about a opsi client' )
594    parser_info.add_argument( 'src', help="opsi client" )
595   
596    parser_clientLastSeen = subparsers.add_parser('clientLastSeen', help='print information about a opsi client' )
597    parser_clientLastSeen.add_argument( 'client', help="opsi client" )
598
599    parser_listInstalled = subparsers.add_parser('listInstalled', help='check if product is installed on client')
600    parser_listInstalled.add_argument('product', help='opsi product')
601
602    parser_isInstalled = subparsers.add_parser('isInstalled', help='check if product is installed on client')
603    parser_isInstalled.add_argument('client', help='opsi client')
604    parser_isInstalled.add_argument('product', help='opsi product')
605
606    parser_update = subparsers.add_parser('update', help='update/create a opsi client')
607    parser_update.add_argument( 'src', help="opsi client to be created/updated" )
608    parser_update.add_argument( '--ip', help="IP address of the opsi client" )
609    parser_update.add_argument( '--mac', help="MAC address of the opsi client" )
610    parser_update.add_argument( '--description', help="a description of the client" )
611    parser_update.add_argument( '--notes', help="notes about the client" )
612    parser_update.add_argument( '--inventory', help="inventory number" )
613    parser_update.add_argument( '--depot', help="depot server the opsi client should be located" )
614
615    args = parser.parse_args()
616
617    if args.debug:
618        logger.setLevel(logging.DEBUG)
619
620    url=args.url
621    if (not url):
622        if args.server:
623            account=""
624            if args.username and args.password:
625                account=args.username + ":" + args.password + "@"
626            elif args.username:
627                account=args.username + "@"
628            url="https://" + account + args.server + ":4447/rpc"
629        else:
630            parser.error( "argument --url is required" )
631
632    opsi=OpsiRpc(url, args.debug, args.nagios)
633
634    result = True
635
636    try:
637        if args.subcommand == "clean":
638            result = opsi.clean( args.src )
639        elif args.subcommand == "copy":
640            result = opsi.copyClient( args.src, args.dst, args.ip, args.mac, args.depot )
641        elif args.subcommand == "createBareosConfigFiles":
642            result = opsi.createBareosConfigFiles(args.defaultjobdefs, args.defaultfileset)
643        elif args.subcommand == "exists":
644            result = opsi.exists( args.src )
645        elif args.subcommand == "list":
646            result = opsi.list()
647        elif args.subcommand == "listClients":
648            result = opsi.listClients( args.product )
649        elif args.subcommand == "info":
650            result = opsi.info( args.src )
651        elif args.subcommand == "update":
652            result = opsi.updateClient( args.src, None, args.description, args.notes, args.inventory, args.mac, args.ip, args.depot )
653        elif args.subcommand == 'listInstalled':
654            result = opsi.listInstalled(args.product)
655        elif args.subcommand == 'isInstalled':
656            result = opsi.isInstalled(args.client, args.product)
657        elif args.subcommand == 'clientLastSeen':
658            result = opsi.clientLastSeen(args.client)
659        else:
660            print("not yet implemented")
661    except IOError as e:
662        result = False
663        # connection refused
664        print("failed:", e)
665
666    if args.debug: print(result)
667
668    if result:
669        exit(0)
670    else:
671        exit(1)
Note: See TracBrowser for help on using the repository browser.