def main(): # Check if running as administrator if not isAdmin(): sys.exit('error: Administrator permission required') # Define options parser = ArgParser( description='UpdatEngine client allow computer and server to be ' 'inventoried automatically on an UpdatEngine server and to deploy applications' ) parser.add_argument('-s', '--server', dest='server', type=str, help='UpdatEngine server URL') group = parser.add_mutually_exclusive_group() group.add_argument('-i', '--inventory', dest='inventory', action='store_true', help='to inventory the host') parser.add_argument('-n', '--noproxy', dest='noproxy', action='store_true', help='do not use any proxy') parser.add_argument('-m', '--minutes', dest='minute', type=int, help='minute between each inventory') parser.add_argument('-c', '--cert', dest='cert', type=str, help='absolute path to cacert.pem file') group.add_argument('-l', '--list', dest='list', action='store_true', help='to get public soft list') group.add_argument('-g', '--get', type=int, dest='get', help='package number to install manually') parser.add_argument('-o', '--out', type=str, dest='out', help='full path to logfile') parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='verbose mode') parser.add_argument('--version', action='version', version=ueconst.UE_CLIENT_VERSION, help='display version number') options = parser.parse_args() if len(sys.argv) == 1: parser.error('at least one argument is required') if (options.get is not None or options.list is True or options.inventory is True) and options.server is None: parser.error('a server URL is required') # Check options try: if options.out is not None: try: logging.basicConfig(level=logging.DEBUG, filename=options.out) except: logging.basicConfig(level=logging.DEBUG, filename='updatengine-client.log') logging.exception('can\'t write on ' + options.out + ' file use default file instead') else: logging.basicConfig(level=logging.DEBUG, filename='updatengine-client.log') last = False if options.list is True and options.server is not None: logging.info('*********************************\n') localtime = time.localtime() logging.info('Start: ' + time.strftime('%Y-%m-%d-%H:%M:%S', localtime)) print('Public packages software available on server') url = options.server + '/post/' softxml = uecommunication.get_public_software_list(url, options) uecommunication.printable_public_software(softxml) logging.info('List public packages available on server') localtime = time.localtime() logging.info('End: ' + time.strftime('%Y-%m-%d-%H:%M:%S', localtime)) if options.get is not None and options.server is not None: logging.info('*********************************\n') localtime = time.localtime() logging.info('Start: ' + time.strftime('%Y-%m-%d-%H:%M:%S', localtime)) url = options.server + '/post/' print('Trying to install package %d' % options.get) logging.info('Trying to install package %d' % options.get) ue = uedownload() ue.download_pack(url, options.get, options) localtime = time.localtime() logging.info('End: ' + time.strftime('%Y-%m-%d-%H:%M:%S', localtime)) if options.inventory is False and options.list is False and options.get is None: print('Just to test, inventory will not be send') last = True if options.minute is None: last = True download = uedownload() while True: ExitError = False if options.get is not None or options.list is True: break logging.info('*********************************\n') localtime = time.localtime() logging.info('Start: ' + time.strftime('%Y-%m-%d-%H:%M:%S', localtime)) try: inventory = ueinventory.build_inventory() except Exception: print('Error when building inventory') logging.exception('Error when building inventory') ExitError = True else: if inventory is not None: localtime = time.localtime() print(time.strftime('%Y-%m-%d-%H:%M:%S', localtime)) print('Inventory built') logging.info('Inventory built') if options.verbose is True: try: inventory_pretty = inventory[0].replace('&', '&') inventory_pretty = parseXML( inventory_pretty).toprettyxml(indent=' ') logging.info(inventory_pretty + inventory[1]) if len(sys.argv) == 2: print(inventory_pretty) except: logging.info(inventory) if options.inventory is True and options.server is not None: url = options.server + '/post/' try: response_inventory = uecommunication.send_inventory( url, inventory[0], options) except Exception: print('Error on send_inventory process') logging.exception('Error on send_inventory process') ExitError = True else: print('Inventory sent to ' + url) logging.info('Inventory sent to ' + url) if options.verbose is True: print( parseXML(response_inventory).toprettyxml( indent=' ')) uecommunication.print_warninfo(response_inventory) try: extended_inventory = ueinventory.build_extended_inventory( response_inventory) if extended_inventory: if options.verbose is True: extended_pretty = extended_inventory.replace( '&', '&') logging.info( parseXML(extended_pretty).toprettyxml( indent=' ')) response_inventory = uecommunication.send_extended_inventory( url, extended_inventory, options) except Exception: print('Error on extended inventory function') logging.exception( 'Error on extended inventory function') ExitError = True else: if extended_inventory: print('Extended inventory sent to ' + url) logging.info('Extended inventory sent to ' + url) if options.verbose is True: print( parseXML(response_inventory). toprettyxml(indent=' ')) try: download.max_download_action = 5 download.download_action( url, response_inventory, options) except Exception: print('Error on download_action function') logging.exception( 'Error on download_action function') try: # Send a last inventory time.sleep(5) inventory = ueinventory.build_inventory() response_inventory = uecommunication.send_inventory( url, inventory[0], options) except: pass ExitError = True localtime = time.localtime() logging.info('End: ' + time.strftime('%Y-%m-%d-%H:%M:%S', localtime)) if last: if ExitError: sys.exit(1) break else: logging.info('Waiting ' + str(options.minute) + ' minute(s) until next inventory') try: wait(options.minute, inventory[1]) except: logging.exception('Error in wait() function') raise except: logging.exception('Error in main() function') sys.exit(1)
print 'Operation completed' self.download_print_time() self.download_send_status('Operation completed') logging.info("Operation completed") time.sleep(5) except: print "Error detected when launching download_action" logging.exception("Error detected when lauching download_action") raise else: # Loop download action if download_launch: try: print "End of download and install " self.download_print_time() inventory = ueinventory.build_inventory() response_inventory = uecommunication.send_inventory(self.urlinv, inventory[0], options) # Break download action if an error occured during a previous install if break_download_action == None: self.download_action(self.urlinv,str(response_inventory),options) except: print "Error in loop download action" logging.exception("Error in loop download action") def download_send_status(self,message): try: header = '<Packstatus><Mid>'+self.mid+'</Mid><Pid>'+self.pid+'</Pid><Status>' tail = '</Status></Packstatus>' full_message = header + message + tail
def main(): # Define options parser = optparse.OptionParser("usage: %prog [options] arg1 arg2") parser.add_option("-s", "--server", dest="server", \ type="string", help="Your UpdatEngine server IP or DNS name") parser.add_option("-i", "--inventory", dest="inventory", \ action="store_false", help="Port of your UpdatEngine server") parser.add_option("-v", "--verbose", dest="verbose", \ action="store_false", help="Verbose mode") parser.add_option("-n", "--noproxy", dest="noproxy", \ action="store_false", help="do not use any proxy") parser.add_option("-m", "--minutes", dest="minute", \ type="int", help="Minute between each inventory") parser.add_option("-c", "--cert", dest="cert", \ type="string", help="Absolute path to cacert.pem file") parser.add_option("-l", "--list", dest="list", \ action="store_false", help="To get public soft list") parser.add_option("-g", "--get", type = "int", dest="get", \ help="Package number to install manualy") parser.add_option("-o", "--out", type = "string", dest="out", \ help="Full path to logfile") (options, args) = parser.parse_args() if options.out is not None: try: logging.basicConfig(level=logging.DEBUG, filename=options.out) except: logging.basicConfig(level=logging.DEBUG, filename='updatengine-client.log') logging.exception("can't write on "+options.out+" file use default file instead") else: logging.basicConfig(level=logging.DEBUG, filename='updatengine-client.log') last = False if options.list is not None and options.server is not None: logging.info("*********************************\n") localtime = time.localtime() logging.info("Start: "+ time.strftime("%Y-%m-%d-%H:%M:%S", localtime)) print "Public packages software available on server\n" url = options.server+'/post/' softxml = uecommunication.get_public_software_list(url, options) uecommunication.printable_public_software(softxml) logging.info("List public packages available on server") localtime = time.localtime() logging.info("End: "+ time.strftime("%Y-%m-%d-%H:%M:%S", localtime)) raw_input("Press Enter to Exit") if options.get is not None and options.server is not None: logging.info("*********************************\n") localtime = time.localtime() logging.info("Start: "+ time.strftime("%Y-%m-%d-%H:%M:%S", localtime)) url = options.server+'/post/' print "Will install package Number: %d \n" % options.get logging.info("Launch manual install of "+ str(options.get) +" package") ue = uedownload() ue.download_pack(url, options.get, options) raw_input("Operation finished, press Enter to Exit") localtime = time.localtime() logging.info("End: "+ time.strftime("%Y-%m-%d-%H:%M:%S", localtime)) if options.inventory is None and options.list is None and options.get is None: print "Just to test, inventory will not be send" last = True if options.minute is None: last = True download = uedownload() while True: if options.get is not None or options.list is not None: break logging.info("*********************************\n") localtime = time.localtime() logging.info("Start: "+ time.strftime("%Y-%m-%d-%H:%M:%S", localtime)) try: inventory = ueinventory.build_inventory() except Exception: print "Error when building inventory" logging.exception("Error when building inventory") else: if inventory is not None: localtime = time.localtime() print time.strftime("%Y-%m-%d-%H:%M:%S", localtime) print "Inventory built" logging.info("Inventory built") if options.verbose is not None: logging.info(inventory) if options.inventory is not None and options.server is not None: url = options.server+'/post/' try: response_inventory = uecommunication.send_inventory(url, inventory[0], options) except Exception: print "Error on send_inventory process" logging.exception("Error on send_inventory process") else: print "Inventory sent to "+url logging.info("Inventory sent to "+url) if options.verbose is not None: print response_inventory try: download.download_action(url, str(response_inventory), options) except Exception: print "Error on download_action function" logging.exception("Error on download_action function") localtime = time.localtime() logging.info("End: "+ time.strftime("%Y-%m-%d-%H:%M:%S", localtime)) if last: break else: logging.info("Waiting "+str(options.minute)+" minute(s) until next inventory\n") wait(options.minute, inventory[1])
def download_action(self, url, xml, options=None): self.urlinv = url self.xml = xml self.options = options try: root = etree.fromstring(self.xml) except: print(self.xml) print('Error reading xml response in download_action') logging.info('Error reading xml response in download_action') raise # download_launch is used to know if a download action append download_launch = None self.max_download_action -= 1 try: # Install packages for pack in root.findall('Package'): try: command = pack.find('Command').text if command.find('download_no_restart' ) != -1 and self.max_download_action < 4: continue self.download_print_time() print('Package: ' + pack.find('Name').text) logging.info('Package: ' + pack.find('Name').text) self.mid = pack.find('Id').text self.pid = pack.find('Pid').text no_break_on_error = None if command.find('no_break_on_error') != -1: no_break_on_error = True option_timeout = 'install_timeout_' self.timeout = self.default_timeout if command.find(option_timeout) != -1: match = re.search(option_timeout + '(.+?)(\r?\n|$)', command) try: option_timeout += match.group(1) command_value = int(match.group(1)) if command_value > 0: self.timeout = command_value except: logmsg = 'Ignoring invalid option \'' + option_timeout + '\'' print(logmsg) self.download_send_status(logmsg) logging.warning(logmsg) command = re.sub( "\n\s*\n*", " && ", command) # Remove blank lines and convert \n to && command = command.replace(' && download_no_restart', '') command = command.replace(' && no_break_on_error', '') command = command.replace(' && section_end', '') # for retro compatibility command = command.replace(' && ' + option_timeout, '') url = pack.find('Url').text packagesum = pack.find('Packagesum').text download_launch = True status_msg = True except: print('Error in package xml format') logging.exception('Error in package xml format') raise self.download_send_status('Ready to download and execute') logging.info('Ready to download and execute') if packagesum != 'nofile': try: self.tmpdir = tempfile.gettempdir( ) + '/updatengine/' + next( tempfile._get_candidate_names()) + "/" if not os.path.exists(self.tmpdir): os.makedirs(self.tmpdir) file_name = self.tmpdir + url.split('/')[-1] self.download_tmp(url, file_name, packagesum) except: self.download_print_time() print('Error when downloading: ' + file_name) self.download_send_status('Error downloading file ' + file_name) logging.exception('Error when downloading: ' + file_name) raise else: print('Install in progress') logging.info('Install in progress') self.download_send_status('Install in progress') try: os.chdir(self.tmpdir) p = subprocess.Popen(command, stderr=subprocess.PIPE, shell=True) retcode = p.wait(timeout=self.timeout) if retcode != 0: raise Exception(retcode) except subprocess.TimeoutExpired: p.kill() err = "Timeout expired" print('Error launching action: ' + err) self.download_send_status( 'Error launching action: ' + err) logging.exception('Error launching action: ' + err) if no_break_on_error is True: status_msg = None else: raise except Exception as e: import locale console_encoding = locale.getpreferredencoding() if console_encoding == 'cp1252': console_encoding = 'cp850' err = [ s.strip().decode(console_encoding) for s in p.stderr.readlines() ] err = ' '.join(err) if len(err): err = err[:450] + ( '...' if len(err) > 450 else '') + " | Exit code " + str(e) else: err = "Exit code " + str(e) print('Error launching action: ' + str(err)) self.download_send_status( 'Error launching action: ' + err) logging.exception('Error launching action: ' + err) if no_break_on_error is True: status_msg = None else: raise finally: try: os.chdir(tempfile.gettempdir()) shutil.rmtree(tempfile.gettempdir() + '/updatengine/') except: print('Can\'t delete temp file') logging.info('Can\'t delete temp file') else: print('Install in progress') logging.info('Install in progress') self.download_send_status('Install in progress') try: p = subprocess.Popen(command, stderr=subprocess.PIPE, shell=True) retcode = p.wait(timeout=self.timeout) if retcode != 0: raise Exception(retcode) except subprocess.TimeoutExpired: p.kill() err = "Timeout expired" print('Error launching action: ' + err) self.download_send_status('Error launching action: ' + err) logging.exception('Error launching action: ' + err) if no_break_on_error is True: status_msg = None else: raise except Exception as e: import locale console_encoding = locale.getpreferredencoding() if console_encoding == 'cp1252': console_encoding = 'cp850' err = [ s.strip().decode(console_encoding) for s in p.stderr.readlines() ] err = ' '.join(err) if len(err): err = err[:450] + ('...' if len(err) > 450 else '') + " | Exit code " + str(e) else: err = "Exit code " + str(e) print('Error launching action: ' + str(err)) self.download_send_status('Error launching action: ' + err) logging.exception('Error launching action: ' + err) if no_break_on_error is True: status_msg = None else: raise if status_msg is True: self.download_print_time() print('Operation completed') self.download_send_status('Operation completed') logging.info('Operation completed') if not root.findall('Package'): print('Done, no package to install') logging.info('Done, no package to install') except: print('Error detected when launching download_action') logging.exception('Error detected when lauching download_action') raise else: # Loop download action if download_launch: try: self.download_print_time() if self.max_download_action == 0: print('End of download and install') else: print('Perform a new check') time.sleep(5) inventory = ueinventory.build_inventory() response_inventory = uecommunication.send_inventory( self.urlinv, inventory[0], options) extended_inventory = ueinventory.build_extended_inventory( response_inventory) if extended_inventory: response_inventory = uecommunication.send_extended_inventory( self.urlinv, extended_inventory, options) if self.max_download_action > 0: self.download_action(self.urlinv, response_inventory, options) except: print('Error in loop download action') logging.exception('Error in loop download action')
print 'Operation completed' self.download_print_time() self.download_send_status('Operation completed') logging.info("Operation completed") time.sleep(5) except: print "Error detected when launching download_action" logging.exception("Error detected when lauching download_action") raise else: # Loop download action if download_launch: try: print "End of download and install " self.download_print_time() inventory = ueinventory.build_inventory() response_inventory = uecommunication.send_inventory( self.urlinv, inventory[0], options) # Break download action if an error occured during a previous install if break_download_action == None: self.download_action(self.urlinv, str(response_inventory), options) except: print "Error in loop download action" logging.exception("Error in loop download action") def download_send_status(self, message): try: header = '<Packstatus><Mid>' + self.mid + '</Mid><Pid>' + self.pid + '</Pid><Status>' tail = '</Status></Packstatus>' full_message = header + message + tail