def updates_tail(_context, request): logger.info("Tailing log file ...") sequence = request.matchdict.get('sequence') rollback = request.matchdict.get('rollback', '') logger.debug('admins.py ::: updates_tail - sequence = %s' % sequence) logger.debug('admins.py ::: updates_tail - rollback = %s' % rollback) if rollback == 'rollback' and request.db.updates.find_one({ '_id': sequence }).get('rollback', 0) == 0: # Update mongo document request.db.updates.update_one({'_id': sequence}, { '$set': { 'rollback': 1, 'timestamp_rollback': int(time.time()), 'rolluser': request.user['username'] } }) # Celery task script_runner.delay(request.user, sequence, rollback=True) return { 'websockets_enabled': json.dumps(is_websockets_enabled()), 'request': request, 'sequence': sequence, 'rollback': rollback }
def save(self, update): settings = get_current_registry().settings update = update['local_file'] if update['local_file'] is not None else update['remote_file'] sequence = re.match('^update-(\w+)\.zip$', update['filename']).group(1) logger.debug("forms.py ::: UpdateForm - sequence = %s" % sequence) # Updates directory: /opt/gecoscc/updates/<sequence> updatesdir = settings['updates.dir'] + sequence logger.debug("forms.py ::: UpdateForm - updatesdir = %s" % updatesdir) # Update zip file zipped = settings['updates.tmp'] + update['filename'] logger.debug("forms.py ::: UpdateForm - zipped = %s" % zipped) try: # https://docs.python.org/2/library/shutil.html # The destination directory, named by dst, must not already exist; it will be created as well as missing parent directories # Checking copytree NFS shutil.copytree(update['decompress'], updatesdir) shutil.rmtree(update['decompress']) # Move zip file to updates dir shutil.move(zipped, updatesdir) # Decompress cookbook zipfile cookbookdir = settings['updates.cookbook'].format(sequence) logger.debug("forms.py ::: UpdateForm - cookbookdir = %s" % cookbookdir) for cookbook in os.listdir(cookbookdir): cookbook = cookbookdir + os.sep + cookbook logger.debug("forms.py ::: UpdateForm - cookbook = %s" % cookbook) if zipfile.is_zipfile(cookbook): zip_ref = zipfile.ZipFile(cookbook,'r') zip_ref.extractall(cookbookdir + os.sep + settings['chef.cookbook_name']) zip_ref.close() # Insert update register self.request.db.updates.insert({'_id': sequence, 'name': update['filename'], 'path': updatesdir, 'timestamp': int(time.time()), 'rollback':0, 'user': self.request.user['username']}) # Launching task for script execution script_runner.delay(self.request.user, sequence) link = '<a href="' + self.request.route_url('updates_tail',sequence=sequence) + '">' + _("here") + '</a>' self.created_msg(_("Update log. %s") % link) except OSError as e: error = True if e.errno == errno.EACCES: self.created_msg(_('Permission denied: %s') % updatesdir, 'danger') else: self.created_msg(_('There was an error attempting to upload an update. Please contact an administrator'), 'danger') except (IOError, os.error) as e: pass except errors.DuplicateKeyError as e: logger.error('Duplicate key error') self.created_msg(_('There was an error attempting to upload an update. Please contact an administrator'), 'danger')
def updates_tail(_context, request): logger.info("Tailing log file ...") sequence = request.matchdict.get('sequence') rollback = request.matchdict.get('rollback', '') logger.debug('admins.py ::: updates_tail - sequence = %s' % sequence) logger.debug('admins.py ::: updates_tail - rollback = %s' % rollback) if rollback == 'rollback' and request.db.updates.find_one({'_id': sequence}).get('rollback', 0) == 0: # Update mongo document request.db.updates.update({'_id':sequence},{'$set':{'rollback':1, 'timestamp_rollback': int(time.time()), 'rolluser': request.user['username']}}) # Celery task script_runner.delay(request.user, sequence, rollback=True) return { 'websockets_enabled': json.dumps(is_websockets_enabled()), 'request': request, 'sequence': sequence, 'rollback': rollback }
def updates_repeat(_context, request): settings = get_current_registry().settings sequence = request.matchdict.get('sequence') logger.debug('admins.py ::: updates_repeat - sequence = %s' % sequence) # Check sequence number to_repeat = request.db.updates.find_one({'_id': sequence}) if to_repeat is None: logging.error('admins.py ::: updates_repeat: ' + \ 'update not found with sequence=%s'%(sequence)) raise HTTPNotFound() updatefile = os.path.join(to_repeat['path'], to_repeat['name']) if not os.path.isfile(updatefile): raise HTTPNotFound() if re.match(SERIALIZED_UPDATE_PATTERN, to_repeat['name']) is not None: logging.error('admins.py ::: updates_repeat: ' + \ 'update %s is a serialized update!'%(sequence)) raise HTTPBadRequest() if 'repetition' in to_repeat: logging.error('admins.py ::: updates_repeat: ' + \ 'update %s is repetition!'%(sequence)) raise HTTPBadRequest() try: # Calculate the next repetition number for this update count = request.db.updates.count_documents({ 'name': to_repeat['name'], 'repetition': { '$exists': True } }) nrep = 0 if count > 0: cursor = request.db.updates.find( { 'name': to_repeat['name'], 'repetition': { '$exists': True } }, { '_id': 1, 'repetition': 1 }).sort('repetition', -1).limit(1) latest = int(cursor.next().get('repetition')) nrep = (latest + 1) logger.debug('admins.py ::: updates_repeat - repetition = %s' % nrep) # Copy the zip file separator = '_' rsequence = '%s%s%s' % (sequence, separator, nrep) updatesdir = settings['updates.dir'] + rsequence while os.path.exists(updatesdir): separator = separator + '_' rsequence = '%s%s%s' % (sequence, separator, nrep) updatesdir = settings['updates.dir'] + rsequence os.mkdir(updatesdir) shutil.copy(updatefile, os.path.join(updatesdir, to_repeat['name'])) # Decompress zip file zip_ref = zipfile.ZipFile(updatefile, 'r') zip_ref.extractall(updatesdir) zip_ref.close() # Decompress cookbook zipfile cookbookdir = settings['updates.cookbook'].format(rsequence) logger.debug('admins.py ::: updates_repeat - ' + \ ' cookbookdir = %s' % cookbookdir) for cookbook in os.listdir(cookbookdir): cookbook = cookbookdir + os.sep + cookbook logger.debug("admins.py ::: updates_repeat - cookbook = %s" % cookbook) if zipfile.is_zipfile(cookbook): zip_ref = zipfile.ZipFile(cookbook, 'r') zip_ref.extractall( os.path.join(cookbookdir, settings['chef.cookbook_name'])) zip_ref.close() # Insert update register request.db.updates.insert_one({ '_id': rsequence, 'name': to_repeat['name'], 'path': updatesdir, 'timestamp': int(time.time()), 'rollback': 0, 'user': request.user['username'], 'repetition': nrep }) # Launching task for script execution script_runner.delay(request.user, rsequence) messages.created_msg(request, _('The update has been repeated!'), 'success') except: e = sys.exc_info()[0] logger.error("admins.py ::: updates_repeat - " + \ "error repeating update: %s"%(str(e))) logger.error("Traceback: %s" % (traceback.format_exc())) messages.created_msg( request, _('There was an error trying to repeat an update'), 'danger') return HTTPFound(request.route_url('updates'))
def save(self, update): settings = get_current_registry().settings update = update['local_file'] if update[ 'local_file'] is not None else update['remote_file'] sequence = re.match(BASE_UPDATE_PATTERN, update['filename']).group(1) logger.debug("forms.py ::: UpdateForm - sequence = %s" % sequence) # Updates directory: /opt/gecoscc/updates/<sequence> updatesdir = settings['updates.dir'] + sequence logger.debug("forms.py ::: UpdateForm - updatesdir = %s" % updatesdir) # Update zip file zipped = settings['updates.tmp'] + update['filename'] logger.debug("forms.py ::: UpdateForm - zipped = %s" % zipped) try: # https://docs.python.org/2/library/shutil.html # The destination directory, named by dst, must not already exist; it will be created as well as missing parent directories # Checking copytree NFS shutil.copytree(update['decompress'], updatesdir) shutil.rmtree(update['decompress']) # Move zip file to updates dir shutil.move(zipped, updatesdir) # Decompress cookbook zipfile cookbookdir = settings['updates.cookbook'].format(sequence) logger.debug("forms.py ::: UpdateForm - cookbookdir = %s" % cookbookdir) for cookbook in os.listdir(cookbookdir): cookbook = cookbookdir + os.sep + cookbook logger.debug("forms.py ::: UpdateForm - cookbook = %s" % cookbook) if zipfile.is_zipfile(cookbook): zip_ref = zipfile.ZipFile(cookbook, 'r') zip_ref.extractall(cookbookdir + os.sep + settings['chef.cookbook_name']) zip_ref.close() # Insert update register self.request.db.updates.insert_one({ '_id': sequence, 'name': update['filename'], 'path': updatesdir, 'timestamp': int(time.time()), 'rollback': 0, 'user': self.request.user['username'] }) # Launching task for script execution script_runner.delay(self.request.user, sequence) link = '<a href="' + self.request.route_url( 'updates_tail', sequence=sequence) + '">' + _("here") + '</a>' self.created_msg(_("Update log. %s") % link) except OSError as e: if e.errno == errno.EACCES: self.created_msg( _('Permission denied: %s') % updatesdir, 'danger') else: self.created_msg( _('There was an error attempting to upload an update. Please contact an administrator' ), 'danger') logger.error("forms.py ::: UpdateForm - - " + \ "error saving update: %s"%(str(e))) logger.error("Traceback: %s" % (traceback.format_exc())) except (IOError, os.error) as e: logger.error("forms.py ::: UpdateForm - - " + \ "error saving update: %s"%(str(e))) logger.error("Traceback: %s" % (traceback.format_exc())) except errors.DuplicateKeyError as e: logger.error('Duplicate key error') self.created_msg( _('There was an error attempting to upload an update. Please contact an administrator' ), 'danger')