def save(self, snapshot, backup_id, cinder): job_stats_path = self._stats_file(snapshot['origin']) logger.rename('lunr.storage.helper.backup.save') setproctitle("lunr-save: " + backup_id) size = snapshot['size'] / 1024 / 1024 / 1024 try: op_start = time() worker = Worker(snapshot['origin'], conf=self.conf, stats_path=job_stats_path) except exc.ClientException, e: if e.http_status != 404: raise op_start = time() conn = get_conn(self.conf) conn.put_container(snapshot['origin']) logger.warning("failed to retrieve manifest;" " first time backup for this volume?") # TODO: write the block_size on the manifest at create? block_count, remainder = divmod(snapshot['size'], BLOCK_SIZE) if remainder: block_count += 1 # initial backup is the only time the we need to worry about # creating a new manifest for the worker worker = Worker(snapshot['origin'], conf=self.conf, manifest=Manifest.blank(block_count), stats_path=job_stats_path)
def app_factory(global_conf, **local_conf): """paste.deploy app factory for creating WSGI API server""" # Reload the paster config, since paster only passes us our config conf = LunrConfig.from_conf(global_conf['__file__']) # ensure global logger is named logger.rename(__name__) app = ApiWsgiApp(conf, urlmap) return app
def prune(self, volume, backup_id): logger.rename("lunr.storage.helper.backup.prune") setproctitle("lunr-prune: " + backup_id) try: op_start = time() worker = Worker(volume["id"], self.conf) except exc.ClientException, e: # If the manifest doesn't exist, We consider the backup deleted. # If anything else happens, we bail. if e.http_status != 404: raise logger.warning("No manifest found pruning volume: %s" % volume["id"]) return
def prune(self, volume, backup_id): logger.rename('lunr.storage.helper.backup.prune') setproctitle("lunr-prune: " + backup_id) try: op_start = time() worker = Worker(volume['id'], self.conf) except exc.ClientException, e: # If the manifest doesn't exist, We consider the backup deleted. # If anything else happens, we bail. if e.http_status != 404: raise logger.warning('No manifest found pruning volume: %s' % volume['id']) return
def audit(self, volume): logger.rename("lunr.storage.helper.backup.audit") setproctitle("lunr-audit: " + volume["id"]) try: op_start = time() worker = Worker(volume["id"], self.conf) except exc.ClientException, e: if e.http_status != 404: raise op_start = time() conn = get_conn(self.conf) conn.put_container(volume["id"]) logger.warning("failed to retrieve manifest;" " auditing volume with no backups") # creating a blank manifest for the worker worker = Worker(volume["id"], conf=self.conf, manifest=Manifest.blank(0))
def remove_lvm_snapshot(self, snapshot): try: op_start = time() volume = self.get(snapshot['origin']) logger.rename('lunr.storage.helper.volume.remove_lvm_snapshot') self.scrub.scrub_snapshot(snapshot, volume) self.remove(snapshot['path']) # TODO: Failure to scrub a snapshot is un-acceptable # If we catch an exception, we should mark the snapshot # Or make this as recoverable as possible duration = time() - op_start logger.info("STAT: remove_lvm_snapshot(%r) Time: %r" % (volume['path'], duration)) except Scrub, e: logger.exception( "scrub snapshot failed with '%r' after %r seconds" % (e, time() - op_start))
def audit(self, volume): logger.rename('lunr.storage.helper.backup.audit') setproctitle("lunr-audit: " + volume['id']) try: op_start = time() worker = Worker(volume['id'], self.conf) except exc.ClientException, e: if e.http_status != 404: raise op_start = time() conn = get_conn(self.conf) conn.put_container(volume['id']) logger.warning("failed to retrieve manifest;" " auditing volume with no backups") # creating a blank manifest for the worker worker = Worker(volume['id'], conf=self.conf, manifest=Manifest.blank(0))
def restore(self, dest_volume, backup_source_volume_id, backup_id, size, cinder): op_start = time() logger.rename('lunr.storage.helper.volume.restore') setproctitle("lunr-restore: " + dest_volume['id']) job_stats_path = self._stats_file(dest_volume['id']) worker = Worker(backup_source_volume_id, conf=self.conf, stats_path=job_stats_path) try: worker.restore(backup_id, dest_volume['path'], dest_volume['id'], cinder) finally: os.unlink(job_stats_path) self.update_tags(dest_volume, {}) duration = time() - op_start logger.info('STAT: Restore %r from %r. ' 'Size: %r GB Time: %r s Speed: %r MB/s' % (dest_volume['id'], backup_id, size, duration, size * 1024 / duration))
def remove_lvm_volume(self, volume): try: op_start = time() size = volume['size'] / 1024 / 1024 / 1024 logger.rename('lunr.storage.helper.volume.remove_lvm_volume') setproctitle("lunr-remove: " + volume['id']) # Scrub the volume self.scrub.scrub_volume(volume['path']) # Remove the device self.remove(volume['path']) duration = time() - op_start logger.info('STAT: remove_lvm_volume(%r) ' 'Size: %r GB Time: %r s Speed: %r MB/s' % (volume['path'], size, duration, size * 1024 / duration)) except ProcessError, e: logger.exception( "delete volume failed with '%r' after %r seconds" % (e, time() - op_start))
def copy_image(self, volume, image, glance, tmp_vol, scrub_callback): logger.rename('lunr.storage.helper.volume.copy_image') setproctitle("lunr-copy-image: " + volume['id']) copy_image_start = time() convert_dir = None try: if image.disk_format == 'raw': self.write_raw_image(glance, image, volume['path']) return convert_dir = self.prepare_tmp_vol(tmp_vol) if not os.path.exists(convert_dir): raise ValueError("Convert dir doesn't exist!") try: path = mkdtemp(dir=convert_dir) logger.info("Image convert tmp dir: %s" % path) image_file = os.path.join(path, 'image') self.write_raw_image(glance, image, image_file) if (image.disk_format == 'vhd' and image.container_format == 'ovf'): self.untar_image(path, image) image_file = self.get_coalesced_vhd(path) op_start = time() out = execute('qemu-img', 'convert', '-O', 'raw', image_file, volume['path']) duration = time() - op_start mbytes = os.path.getsize(image_file) / 1024 / 1024 logger.info('STAT: image convert %r. Image Size: %r MB ' 'Time: %r Speed: %r' % (image.id, mbytes, duration, mbytes / duration)) except Exception, e: logger.exception("Exception in image conversion") raise except Exception, e: # We have to clean this up no matter what happened. # Delete volume syncronously. Clean up db in callback. logger.exception('Unhandled exception in copy_image') self.remove_lvm_volume(volume)
def remove_lvm_volume(self, volume): try: op_start = time() size = volume['size'] / 1024 / 1024 / 1024 logger.rename('lunr.storage.helper.volume.remove_lvm_volume') setproctitle("lunr-remove: " + volume['id']) # Scrub the volume self.scrub.scrub_volume(volume['path']) # Remove the device self.remove(volume['path']) duration = time() - op_start logger.info( 'STAT: remove_lvm_volume(%r) ' 'Size: %r GB Time: %r s Speed: %r MB/s' % (volume['path'], size, duration, size * 1024 / duration)) except ProcessError, e: logger.exception( "delete volume failed with '%r' after %r seconds" % (e, time() - op_start))
def app_factory(global_conf, **local_conf): """paste.deploy app factory for creating WSGI API server""" # Reload the paster config, since paster only passes us our config conf = LunrConfig.from_conf(global_conf['__file__']) # ensure global logger is named logger.rename(__name__) app = StorageWsgiApp(conf, urlmap) # Check for a valid volume config app.helper.volumes.check_config() try: app.helper.check_registration() except Exception: logger.exception('Registration failed') volumes = app.helper.volumes.list() app.helper.cgroups.load_initial_cgroups(volumes) app.helper.exports.init_initiator_allows() return app
if e.errcode != 5 or 'already exists' not in e.err: raise raise AlreadyExists("snapshot id '%s' already in use" % id) def _copy_clone(self, snapshot, clone_id, size, iscsi_device, cinder=None): def progress_callback(percent): try: if cinder: cinder.update_volume_metadata( clone_id, {'clone-progress': "%.2f%%" % percent}) except CinderError, e: logger.warning( "Error updating clone-progress metadata: %s" % e) op_start = time() logger.rename('lunr.storage.helper.volume._copy_clone') setproctitle("lunr-clone: %s %s" % (snapshot['origin'], clone_id)) try: iscsi_device.copy_file_out(snapshot['path'], callback=progress_callback) except (ISCSINotConnected, ISCSICopyFailed), e: logger.error("copy_file_out failed: %s" % str(e)) raise try: iscsi_device.disconnect() except ISCSILogoutFailed: raise ServiceUnavailable("Unable to disconnect") duration = time() - op_start logger.info('STAT: Clone %r to %r. ' 'Size: %r GB Time: %r s Speed: %r MB/s' % (snapshot['origin'], clone_id, size, duration,
if e.errcode != 5 or 'already exists' not in e.err: raise raise AlreadyExists("snapshot id '%s' already in use" % id) def _copy_clone(self, snapshot, clone_id, size, iscsi_device, cinder=None): def progress_callback(percent): try: if cinder: cinder.update_volume_metadata( clone_id, {'clone-progress': "%.2f%%" % percent}) except CinderError, e: logger.warning("Error updating clone-progress metadata: %s" % e) op_start = time() logger.rename('lunr.storage.helper.volume._copy_clone') setproctitle("lunr-clone: %s %s" % (snapshot['origin'], clone_id)) try: iscsi_device.copy_file_out(snapshot['path'], callback=progress_callback) except (ISCSINotConnected, ISCSICopyFailed), e: logger.error("copy_file_out failed: %s" % str(e)) raise try: iscsi_device.disconnect() except ISCSILogoutFailed: raise ServiceUnavailable("Unable to disconnect") duration = time() - op_start logger.info('STAT: Clone %r to %r. ' 'Size: %r GB Time: %r s Speed: %r MB/s' % (snapshot['origin'], clone_id, size, duration,