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

Last change on this file since 1244 was 1239, checked in by joergs, on Feb 28, 2018 at 6:41:10 PM

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
RevLine 
[1027]1#!/usr/bin/env python
2
[1061]3# -*- coding: utf-8 -*-
4
[1055]5"""ospi-client: performs operation for opsi clients on opsi server via JSON-RPC."""
6
[1234]7from __future__ import print_function
8
[1061]9__author__ = "Joerg Steffens"
[1239]10__copyright__ = "Copyright 2012-2018, dass IT GmbH"
[1055]11__license__ = "GPL"
[1234]12__version__ = "1.2"
[1055]13__email__ = "joerg.steffens@dass-it.de"
14
[1051]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 " + \
[1174]20 #computername + " " + depotName)
21
[1047]22import argparse
[1239]23from datetime import datetime, timedelta
24from dateutil import parser as dateparser
[1110]25import logging
26import os
[1239]27from pprint import pprint, pformat
[1234]28import sys
[1239]29import ssl
[1110]30import time
[1027]31
[1239]32try:
33 import jsonrpc
34except ImportError:
35 import jsonrpclib
36
37
[1063]38UrlJsonRpc="https://<username>:<password>@opsi:4447/rpc"
[1027]39
[1239]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"
[1063]41
[1234]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
[1087]80class OpsiRpc:
81
82 UrlJsonRpcDefault="https://opsi:4447/rpc"
[1174]83
[1087]84 ProductAttributesCopy = ['actionRequest','actionResult','installationStatus','packageVersion','productVersion']
[1174]85
[1234]86 def __init__(self, urlJsonRpc = UrlJsonRpcDefault, debug=False, nagios=False):
[1174]87 self.logger=logging.getLogger(__name__)
[1087]88 self.debug=debug
[1234]89 self.nagios=nagios
[1087]90 self.urlJsonRpc=urlJsonRpc
[1239]91 if 'jsonrpc' in sys.modules:
92 self.rpc=jsonrpc.ServiceProxy(self.urlJsonRpc)
93 else:
94 self.rpc=jsonrpclib.ServerProxy(self.urlJsonRpc)
[1110]95 self.logger.debug( "initialized: " + self.urlJsonRpc )
[1239]96 self.logger.debug(dir(self.rpc))
[1110]97
[1174]98
[1110]99 def list(self):
[1239]100 exceptions = []
101 if 'jsonrpc' in sys.modules:
102 exceptions = [ jsonrpc.json.JSONDecodeException ]
[1234]103 try:
104 print( "\n".join( self.rpc.getClientIds_list() ) )
[1239]105 except exceptions as e:
[1234]106 self.logger.debug( pformat(self.rpc.getClientIds_list()) )
107 self.logger.exception( "failed" )
108 return True
[1087]109
[1174]110
[1110]111 def getClientsWithProduct( self, product ):
112 return self.rpc.productOnClient_getObjects( [], { "productId": product, "installationStatus": "installed" } )
113
[1234]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)
[1110]126
127 def listClients( self, product ):
128 if product:
129 for client in self.getClientsWithProduct( product ):
[1234]130 print(client['clientId'])
[1110]131 else:
132 return self.list()
133 return True
[1174]134
[1087]135 def exists(self, src):
136 return len( self.rpc.host_getObjects( [], {"id":src} ) ) == 1
[1174]137
[1087]138 def info(self, src):
139 if not self.exists( src ):
[1234]140 print("failed: opsi client", src, "does not exist")
[1087]141 return False
[1234]142 print(src + ":")
[1087]143 host = self.rpc.host_getHashes( [], {"id":src} )[0]
[1234]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))
[1174]151
[1234]152 print(" products:")
[1087]153 products = self.getProductOnClient( src, [] )
154 for i in products:
[1234]155 print(" " + i['productId'] + ":")
156 print(" " + i['installationStatus'], "(", end='')
[1087]157 if i['actionRequest']:
[1234]158 print(i['actionRequest'], end='')
[1087]159 if i['actionProgress']:
[1234]160 print(i['actionProgress'], end='')
161 print(")")
162 print(" ", end='')
[1087]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 )
[1088]171
[1109]172 products = self.rpc.productPropertyState_getObjects( [], { 'objectId': src } )
[1088]173 self.rpc.productPropertyState_deleteObjects( products )
[1174]174
[1087]175 if self.debug:
176 pprint( self.getProductOnClient( src ) )
177 return True
[1174]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
[1087]187 def createClient(self, name, opsiHostKey, description, notes, hardwareAddress, ipAddress):
[1117]188 # self.rpc.host_createOpsiClient( name, opsiHostKey, description, notes, hardwareAddress, ipAddress )
[1177]189 self.updateClient( name, opsiHostKey, description, notes, None, hardwareAddress, ipAddress )
[1087]190
[1175]191 def deleteClient(self, name):
192 self.rpc.host_delete( name )
193
[1177]194 def updateClient(self, src, opsiHostKey = None, description = None, notes = None, inventoryNumber = None, hardwareAddress = None, ipAddress = None, depot = None ):
[1117]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:
[1174]204 obj['notes'] = notes
[1177]205 if inventoryNumber:
206 obj['inventoryNumber'] = inventoryNumber
[1117]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)
[1174]216
[1117]217 if depot:
218 self.clientSetDepot(src,depot)
219 return True
220
[1176]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()
[1117]229
[1087]230 def clientSetDepot(self, name, depot):
[1174]231 self.rpc.configState_create( "clientconfig.depot.id", name, depot )
[1087]232
[1088]233 def copyClient( self, src, dst, ipAddress = None, hardwareAddress = None, depot = None, description = "", copyProperties = True ):
[1174]234
[1234]235 print("create/update", dst, "from template", src + ":", end='')
[1087]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)
[1174]252
[1087]253 if depot:
254 self.clientSetDepot(dst,depot)
[1174]255
[1087]256 if self.debug:
257 pprint( self.getProductOnClient( src ) )
258 self.copyProductOnClient( src, dst )
[1088]259 if copyProperties:
260 if self.debug:
[1234]261 print("copy product properties")
[1174]262 if not depot:
263 # get default Properties from Master Depot Server (OpsiConfigserver)
264 depot = self.getOpsiConfigserverId()
265 self.copyProductPropertyState( src, dst, depot )
[1234]266 print("done")
[1087]267 return True
268
269 def getProductOnClient( self, client, attributes = ProductAttributesCopy ):
270 return self.rpc.productOnClient_getHashes( [], { 'clientId': client } )
[1110]271
[1087]272 def copyProductOnClient( self, src, dst, attributes = ProductAttributesCopy ):
[1088]273 products_src = self.rpc.productOnClient_getHashes( attributes, { 'clientId': src } )
274 products_dst = []
275 for i in products_src:
[1087]276 if self.debug:
[1234]277 print(i['productId'])
[1087]278 pprint( i )
279 i['clientId'] = dst
[1088]280 products_dst.append(i)
281 self.rpc.productOnClient_createObjects( products_dst )
[1087]282 if self.debug:
283 pprint( self.getProductOnClient( dst ) )
[1088]284
[1174]285
[1088]286 def getProductPropertyState( self, client, attributes = [] ):
287 return self.rpc.productPropertyState_getHashes( [], { 'objectId': client } )
[1174]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 = []
[1088]295 productProperties_src = self.getProductPropertyState( src, attributes )
296 productProperties_dst = []
297 for i in productProperties_src:
[1174]298 use_default=False
[1176]299 default_value=None
[1174]300 for j in productProperties_default:
301 if i['productId'] == j['productId'] and i["propertyId"] == j["propertyId"]:
[1176]302 default_value = j['values']
[1174]303 if i['values'] == j['values']:
304 use_default=True
305 if self.debug:
[1234]306 print(i['productId'], "-", i["propertyId"] + ": ", pformat(i["values"]), end='')
[1174]307 if use_default:
[1234]308 print("(use default)")
[1174]309 else:
[1234]310 print("(set, default:", default_value, ")")
[1174]311 if not use_default:
312 i['objectId'] = dst
313 productProperties_dst.append(i)
[1088]314 self.rpc.productPropertyState_createObjects( productProperties_dst )
315 if self.debug:
316 pprint( self.getProductPropertyState( dst ) )
[1110]317
318
319 def getClientProductProperty( self, client, product ):
320 return self.rpc.getProductProperties_hash( product, [ client ] )
321
[1118]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
[1239]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
[1110]347 def write_client_conf( self, fd, client, properties ):
348 #Client {
349 #Name = ting-fd
350 #Address = ting.dass-it
351 #FDPort = 9102
[1239]352 #Password = "D5w2V5w6B8a9H5Z"
[1110]353 #Catalog = MyCatalog
354 #File Retention = 6 months
355 #Job Retention = 6 months
356 #AutoPrune = yes
357 #}
[1239]358 params = [ 'catalog', "FDPort", "FileRetention", "JobRetention", "AutoPrune" ]
[1110]359 fd.write( "Client {\n" )
360 fd.write( ' Name = "' + properties['filedaemon_full_name'] + '"' + "\n" )
[1239]361 fd.write( ' Address = "' + properties['filedaemon_client_address'] + '"' + "\n" )
[1110]362 # ipAddress: method host_getObjects [] '{"id":client['clientId']}'
[1234]363 #print(" # Address =", ipAddress)
[1110]364 fd.write( ' Password = "' + properties['filedaemon_full_password'] + '"' + "\n" )
365 for i in params:
[1239]366 self.write_value_conf(fd, i, properties)
[1110]367 fd.write( "}\n")
368 fd.write( "\n" )
[1087]369
370
[1239]371 def write_job_conf(self, fd, client, properties, defaultjobdefs, defaultfileset):
[1110]372 #Job {
373 #FileSet = "tingfileset"
374 #Name = "ting"
375 #Client = ting-fd
376 #JobDefs = "LaptopJob"
377 ## Write Bootstrap = "/var/lib/bacula/ting.bsr"
378 #}
[1239]379 params = [ "JobDefs", "FileSet" ]
[1110]380 fd.write( "Job {" + "\n" )
381 fd.write( ' Name = "' + client['clientId'] + '-job"' + "\n" )
382 fd.write( ' Client = "' + properties['filedaemon_full_name'] + '"' + "\n" )
[1239]383 self.write_value_conf(fd, 'JobDefs', properties, defaultjobdefs)
384 self.write_value_conf(fd, 'FileSet', properties, defaultfileset)
[1110]385 fd.write( "}" + "\n" )
386 fd.write( "\n" )
387
388
389 def write_config_file_header( self, fd ):
[1174]390 try:
[1110]391 fd.write( "#\n" )
[1114]392 fd.write( "# automatically generated at {0}\n".format( time.asctime() ) )
[1110]393 fd.write( "#\n\n" )
[1177]394 except BaseException as e:
[1110]395 self.logger.exception( "failed to create files" )
396 return False
397 return True
398
[1174]399
[1239]400
401 def createBareosConfigFiles(self, defaultjobdefs, defaultfileset):
402 bareosDirConfigPath = '/etc/bareos/bareos-dir.d/'
403 clientsWithBacula=self.getClientsWithProduct('winbareos')
[1110]404 if clientsWithBacula:
405 try:
[1239]406 configfile = bareosDirConfigPath + 'client/opsi-clients-generated.conf'
407 file_opsi_clients = open(configfile, 'w')
[1110]408 self.write_config_file_header( file_opsi_clients )
[1239]409 except (BaseException, IOError) as e:
410 self.logger.exception( "failed to create configuration file {}".format(configfile) )
411 return False
[1174]412
[1239]413 try:
414 configfile = bareosDirConfigPath + 'job/opsi-jobs-generated.conf'
415 file_opsi_jobs = open(configfile, 'w')
[1110]416 self.write_config_file_header( file_opsi_jobs )
[1239]417 except (BaseException, IOError) as e:
418 self.logger.exception( "failed to create configuration file {}".format(configfile) )
[1110]419 return False
[1239]420
[1110]421 for client in clientsWithBacula:
[1174]422 clientId = client['clientId']
[1110]423 try:
[1239]424 clientBaculaProperties=self.getClientProductProperty( clientId, 'winbareos' )
[1110]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 )
[1239]430 self.write_client_conf(file_opsi_clients, client, clientBaculaProperties)
431 self.write_job_conf(file_opsi_jobs, client, clientBaculaProperties, defaultjobdefs, defaultfileset)
[1110]432 self.logger.info( "%s: OK" % clientId )
433 else:
434 self.logger.warn( "%s: failed: no product properties defined" %(clientId) )
435 return True
436
[1234]437 def __getVersionString(self, product):
438 return '{productVersion}-{packageVersion}'.format(**product)
[1110]439
[1234]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
[1110]446
[1234]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
[1047]531if __name__ == '__main__':
[1110]532 logging.basicConfig(format='%(message)s')
533 logger = logging.getLogger(__name__)
534 logger.setLevel(logging.INFO)
535
[1239]536 parser = argparse.ArgumentParser(
537 description='Command line tool for OPSI configuration.',
538 epilog=HelpEpilog
539 )
[1063]540
[1047]541 parser.add_argument( '--debug', action='store_true', help="enable debugging output" )
[1234]542 parser.add_argument('--nagios', action='store_true', help='output in Nagios NRPE format')
[1028]543
[1110]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
[1050]553 subparsers = parser.add_subparsers(title='subcommands',
554 description='valid subcommands',
555 help='additional help',
556 dest='subcommand' )
[1047]557
[1050]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" )
[1174]560
561 parser_copy = subparsers.add_parser('copy', help='copy/create a opsi client from a template opsi client')
[1050]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" )
[1088]567 #parser_copy.add_argument( '--no-properties', action='store_false', help="don't copy product properties" )
[1174]568
[1239]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 )
[1110]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' )
[1174]589
[1110]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" )
[1174]592
[1110]593 parser_info = subparsers.add_parser('info', help='print information about a opsi client' )
594 parser_info.add_argument( 'src', help="opsi client" )
[1234]595
596 parser_clientLastSeen = subparsers.add_parser('clientLastSeen', help='print information about a opsi client' )
597 parser_clientLastSeen.add_argument( 'client', help="opsi client" )
[1174]598
[1234]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
[1117]606 parser_update = subparsers.add_parser('update', help='update/create a opsi client')
[1177]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
[1047]615 args = parser.parse_args()
[1177]616
[1110]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" )
[1174]631
[1234]632 opsi=OpsiRpc(url, args.debug, args.nagios)
[1174]633
[1051]634 result = True
635
[1174]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 )
[1239]641 elif args.subcommand == "createBareosConfigFiles":
642 result = opsi.createBareosConfigFiles(args.defaultjobdefs, args.defaultfileset)
[1174]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":
[1177]652 result = opsi.updateClient( args.src, None, args.description, args.notes, args.inventory, args.mac, args.ip, args.depot )
[1234]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)
[1174]659 else:
[1234]660 print("not yet implemented")
[1174]661 except IOError as e:
662 result = False
663 # connection refused
[1234]664 print("failed:", e)
[1050]665
[1234]666 if args.debug: print(result)
[1174]667
[1051]668 if result:
669 exit(0)
670 else:
671 exit(1)
Note: See TracBrowser for help on using the repository browser.