def DoRm(self, request, context): lback_output("Received COMMAND DoRm") try: lback_backup_remove(request.id) except Exception, ex: print_exc(ex) return shared_pb2.RmCmdStatus(errored=True)
def RouteBackup(self, request, context): lback_output("Received COMMAND RouteBackup") def chunked_iterator(agent): lback_output("Ready to pack CHUNKS for backup %s" % request.id) chunked_file = lback_backup_chunked_file(request.id) for backup_file_chunk in chunked_file: lback_output("Packing CHUNK") yield shared_pb2.BackupCmdStream(id=request.id, raw_data=backup_file_chunk) def route_fn(agent): lback_output("RUNNING CHUNKED ITERATOR") iterator = chunked_iterator(agent) backup_res = agent.DoBackup(iterator) lback_output("COMPLETED BACKUP") return backup_res try: iterator = self._RouteOnAllAgents(route_fn) for cmd_response in iterator: yield cmd_response except Exception, ex: print_exc(ex) yield shared_pb2.BackupCmdStatus(errored=True)
def chunked_iterator(agent): lback_output("Ready to pack CHUNKS for backup %s" % request.id) chunked_file = lback_backup_chunked_file(request.id) for backup_file_chunk in chunked_file: lback_output("Packing CHUNK") yield shared_pb2.BackupCmdStream(id=request.id, raw_data=backup_file_chunk)
def safe_rpc(agent, agent_fn): res = None try: res = agent_fn(agent) except Exception, ex: lback_output(ex) lback_output("Unable to send command to LBACK AGENT: {}".format( make_connection_string(agent[0])))
def _RouteOnAllAgents(self, fn): agents = self.agents for agent in agents: agent_object = agent[0] agent_channel = agent[1] connection_string = agent_object.host + ":" + agent_object.port lback_output("DELIVERING to AGENT %s" % (connection_string)) result = fn(agent_channel) yield result
def DoRelocateTake(self, request, context): lback_output("Received COMMAND DoRelocateTake") try: iterator = lback_backup_file_chunks(request.id) for file_chunk_res in iterator: lback_output("PACKING RELOCATE BACKUP CHUNK") yield shared_pb2.RelocateCmdGiveStatus(raw_data=file_chunk_res, errored=False) except Exception, ex: yield shared_pb2.RelocateCmdGiveStatus(errored=True)
def __init__(self): agent_objects = lback_agents() self.agents = [] ## STUBS and CHANNELS for agent_object in agent_objects: connection_string = agent_object.host + ":" + agent_object.port lback_output("Registering AGENT %s" % (connection_string)) channel = grpc.insecure_channel(connection_string) self.agents.append(( agent_object, agent_pb2_grpc.AgentStub(channel), ))
def DoRestore(self, request, context): lback_output("Received COMMAND DoRestore") try: iterator = lback_backup_chunked_file( lback_id(id=request.id, shard=protobuf_empty_to_none(request.shard))) for restore_file_chunk in iterator: lback_output("PACKING RESTORE CHUNK") yield shared_pb2.RestoreCmdStatus(errored=False, raw_data=restore_file_chunk) except Exception, ex: print_exc(ex) yield shared_pb2.RestoreCmdStatus(errored=True)
def DoRestore(self, request, context): lback_output("Received COMMAND DoRestore") db_backup = lback_backup(request.id) restore = Restore(request.id, folder=db_backup.folder) try: iterator = restore.read_chunked() for restore_file_chunk in iterator: lback_output("PACKING RESTORE CHUNK") yield shared_pb2.RestoreCmdStatus(errored=False, raw_data=restore_file_chunk) except Exception, ex: print_exc(ex) yield shared_pb2.RestoreCmdStatus(errored=True)
def DoBackupAcceptDiff(self, request_iterator, context): lback_output("Received COMMAND DoBackupAcceptDiff") request_iterator, iter_copy = tee(request_iterator) request = next(iter_copy) id = request.id folder = request.folder lback_output("ID %s" % (request.id)) bkp = Backup(id, folder, diff=True, encryption_key=request.encryption_key, compression=request.compression) def chunked_restore_iterator(): for res in request_iterator: yield res.raw_data try: restore_path = lback_temp_path() os.makedirs(restore_path) lback_output("Running DIFF RESTORE") restore = Restore(id, folder=restore_path) restore.run_chunked(chunked_restore_iterator()) lback_output("Running DIFF BACKUP") bkp.run_diff(restore_path) os.remove(restore_path) except Exception, ex: return shared_pb2.BackupCmdAcceptStatus(errored=True)
def _file(self, anchor, prefix=''): lback_output("added => " + prefix + anchor) self.things.append(prefix + anchor) args = self.eventArgs args['progressSz'] += Util().getFileSize(prefix+anchor) args['progressPct']= "{0:.2f}".format((args['progressSz']/args['size'])*100) meta = BackupMeta(**args) self.state.setState( Events.getProgressEvent( status=EventStatuses.STATUS_IN_PROGRESS, obj=EventObjects.OBJECT_BACKUP, data=meta.serialize(), message=EventMessages.MSG_BACKUP_IN_PROGRESS)) return prefix + anchor
def RouteRelocate(self, request, context): lback_output("Received COMMAND RouteRelocate") src_agent = self._GetAgent(request.src) dst_agent = self._GetAgent(request.dst) def chunked_iterator(): iterator = src_agent.DoRelocateTake(request) for relocate_take_chunk in iterator: yield relocate_take_chunk try: iterator = dst_agent.DoRelocateGive(chunked_iterator()) for _ in iterator: pass except Exception, ex: print_exc(ex) return shared_pb2.RelocateCmdStatus(errored=True)
def DoRestoreAccept(self, request_iterator, context): lback_output("Received COMMAND DoRestoreAccept") request_iterator, iter_copy = tee(request_iterator) request = next(iter_copy) def chunked_iterator(): for chunk in request_iterator: lback_output("STORING RESTORE CHUNK") yield chunk.raw_data try: restore = Restore(request.id, folder=request.folder) restore.run_chunked(chunked_iterator()) lback_output("RESTORE SUCCESSFULL") except Exception, ex: print_exc(ex) return shared_pb2.RestoreAcceptCmdStatus(errored=True)
def DoBackup(self, request_iterator, context): lback_output("Received COMMAND DoBackup") request_iterator, iter_copy = tee(request_iterator) request = next(iter_copy) db_backup = lback_backup(request.id) lback_output("Running backup on %s" % (request.id)) backup = Backup(request.id, db_backup.folder) def backup_chunked_iterator(): for backup_cmd_chunk in request_iterator: yield backup_cmd_chunk.raw_data try: backup.write_chunked(backup_chunked_iterator()) except Exception, ex: print_exc(ex) return shared_pb2.BackupCmdStatus(errored=True)
def RouteRestore(self, request, context): lback_output("Received COMMAND RouteRestore") dst_agent = self._GetRestoreCandidate() db_backup = lback_backup(request.id) restore = Restore(request.id, folder=db_backup.folder) agent_iterator = dst_agent.DoRestore(request) def chunked_iterator(): for restore_cmd_chunk in agent_iterator: yield restore_cmd_chunk.raw_data try: iterator = chunked_iterator() restore.run_chunked(iterator) except Exception, ex: print_exc(ex) return shared_pb2.RestoreCmdStatus(errored=True)
def run(self, cmd='BACKUP', folder=None, uid='', contents='',name='',version='1.0.0',size=0, jit=False): s = socket.socket() size = str(size) #s.setblocking(0) s.connect((self.server['ip'], int(self.server['port']))) #smessage = cmd + ', ' + 'UID: "' + uid + '", ' + 'FOLDER: "' + os.path.abspath(folder) + '", ' + 'JIT: "' + str(jit) + '", ' + "SIZE: " + size + ', ' + "VERSION: " + version + ', ' + "NAME: " + name + "\nCONTENTS: " + contents smessage = LBack_Protobuf_Message() smessage.CMD = cmd smessage.UID = uid smessage.FOLDER = folder smessage.JIT = jit smessage.SIZE = str(size) smessage.VERSION =version smessage.NAME = name smessage.CONTENTS = contents.encode("hex").encode("utf-8") lback_output("Message passing: (FOLDER: %s, SIZE: %s, UID: %s, JIT: %s, VERSION: %s)" % (folder, str(size), str(uid), str(jit), str(version))) s.sendall(smessage.SerializeToString()) out = False ### shorter spurts for commands not ## needing heavy TCP/IP communication if cmd == 'BACKUP' or cmd == 'DELETE': self.m = recvall(s) else: self.m = "" while True: if out: break try: m = s.recv(2048) if not m: break if m == "": out = True break if m != "" or m: self.m += m except socket.error, e: lback_output("??") if e.errno != errno.EAGAIN: raise e select.select([s], [], [])
def DoRelocateGive(self, request_iterator, context): lback_output("Received COMMAND DoRelocateGive") request_iterator, iter_copy = tee(request_iterator) request = next(iter_copy) db_backup = lback_backup(request.id) backup = Backup(request.id, db_backup.folder) def relocate_cmd_chunked_iterator(): for relocate_cmd_chunk in request_iterator: lback_output("SAVING RELOCATE BACKUP GIVE CHUNK") yield relocate_cmd_chunk.raw_data try: iterator = backup.run_chunked(relocate_chunked_iterator) for relocate_chunk_res in iterator: yield shared_pb2.RelocateCmdStatus(errored=False) except Exception, ex: print_exc(ex) yield shared_pb2.RelocateCmdStatus(errored=True)
def _run_remove(self, operation_instance, backup): lback_output("Routing REMOVE") def handle_replies(replies): for reply in replies: if not reply.errored: lback_output("REMOVE propagated") else: lback_output("REMOVE could not be propagated") if operation_instance.args.all: replies = self.server.RouteRm( shared_pb2.RmCmd(id=backup.id, all=operation_instance.args.all)) handle_replies(replies) else: target = operation_instance.args.target replies = self.server.RouteRm( shared_pb2.RmCmd(id=backup.id, target=target)) handle_replies(replies)
def DoRelocateGive(self, request_iterator, context): lback_output("Received COMMAND DoRelocateGive") lback_output("ID %s, SHARD %s" % ( request.id, request.shard, )) request_iterator, iter_copy = tee(request_iterator) request = next(iter_copy) full_id = lback_id(request.id, shard=protobuf_empty_to_none(request.shard)) backup = Backup(full_id, request.folder) def relocate_cmd_chunked_iterator(): for relocate_cmd_chunk in request_iterator: lback_output("SAVING RELOCATE BACKUP GIVE CHUNK") yield relocate_cmd_chunk.raw_data try: backup.write_chunked(relocate_cmd_chunked_iterator()) except Exception, ex: print_exc(ex) return shared_pb2.RelocateCmdGiveStatus(errored=True)
def DoRelocateTake(self, request, context): lback_output("Received COMMAND DoRelocateTake") lback_output("ID %s, SHARD %s" % ( request.id, request.shard, )) shard = protobuf_empty_to_none(request.shard) shard_iterator = protobuf_empty_to_none(request.shard_iterator) lback_output("SHARD ITERATOR: %s" % (shard_iterator)) full_id = lback_id(request.id, shard=shard) lback_output("FULL ID %s" % (full_id)) backup_full_path = lback_backup_path(full_id) shard_size = None try: if request.delete: temp_file = lback_temp_file() shutil.move(lback_backup_path(full_id), temp_file.name) backup_full_path = temp_file.name backup_size = os.stat(backup_full_path).st_size if not shard_iterator is None: shard_size = lback_backup_shard_size(backup_size, int(request.total_shards)) shard_start, shard_end = lback_backup_shard_start_end( int(shard_iterator), shard_size) iterator = lback_backup_chunked_file(backup_full_path, chunk_start=shard_start, chunk_end=shard_end, use_backup_path=False) else: iterator = lback_backup_chunked_file(backup_full_path, use_backup_path=False) for file_chunk_res in iterator: lback_output("PACKING RELOCATE BACKUP CHUNK") yield shared_pb2.RelocateCmdTakeStatus(raw_data=file_chunk_res, errored=False) except Exception, ex: print_exc(ex) yield shared_pb2.RelocateCmdTakeStatus(errored=True)
def _help(self): lback_output(""" usage: lback [options] required_input required_input2 options: -c, --client Run a command as a client (required) -s, --server Initiate a server (required) -b, --backup Run a backup -r, --restore Run a restore -f, --folder Specify a folder (required *) for backups -i, --id, Specify an id (required *) for restores [ this can be a folder or name of backup ] -n, --name Name for backup (optional) -rm, --remove Remove a directory on backup -x, --compress Compress an archive (default) -l, --list Generate a full list of your backups -i, --ip Specify an ip (overridden by settings.json if found) -p, --port Specify a port (overridden by settings.json if found) -h, --help Print this text -del, --delete Delete a backup -jit, --just-in-time Just in time backups (read docs for more) [accepts singular file or document] -v, --version specify a version to restore (for restores you can use: LATEST|OLDEST) --settings Opens settings in VIM SERVER SPECIFIC -g, --graceful Perform a graceful shutdown -re, --restart Restart the server -st, --start Start the server -sp, --stop Force a shutdown -st, --status Is the server running or stopped PROFILER SPECIFIC -st, --start Start the profiler --stop_profiler Stop the profiler JIT SPECIFIC --st, --start starts a JIT instance --stop Stop the JIT instance """, tag=False)
def pack(self): lback_output( "Files have been gathered. Forming archive.." ) for i in self.things: self.archive.obj.write(i, os.path.relpath(i, self.folder)) lback_output( "Files found: ") lback_output(self.things) #Util().archive(self.folder, self.get()) self.archive.obj.close() self.status = 1
def _run_relocate(self, operation_instance, backup): lback_output("Routing RELOCATE") reply = self.server.RouteRelocate( shared_pb2.RelocateCmd(id=backup.id, src=operation_instance.args.src, dst=operation_instance.args.dst)) if not reply.errored: lback_output("RELOCATE successful") else: lback_output("RELOCATE could not be performed") return reply
def DoBackupAcceptFull(self, request, context): lback_output("Received COMMAND DoBackupAcceptFull") lback_output("ID %s" % (request.id)) folder = request.folder id = request.id bkp = Backup(id, folder, diff=False, encryption_key=request.encryption_key, compression=request.compression) try: lback_output("RUNNING FULL BACKUP AT %s" % (bkp.get_file())) bkp.run() if request.remove: shutil.rmtree(folder) lback_output("Directory successfully deleted..") except Exception, ex: print_exc(ex) return shared_pb2.BackupCmdAcceptStatus(errored=True)
def DoCheckBackupExists(self, request, context): lback_output("Received COMMAND DoCheckBackupExists") lback_output("ID %s, SHARD %s" % ( request.id, request.shard, )) if os.path.exists( lback_backup_path(request.id, shard=protobuf_empty_to_none( request.shard))): return shared_pb2.CheckCmdStatus(errored=False) lback_output("BACKUP DOES NOT EXIST") return shared_pb2.CheckCmdStatus(errored=True)
def _run_restore(self, operation_instance, backup): lback_output("Routing RESTORE") cmd = shared_pb2.RestoreCmd(id=backup.id, target=operation_instance.args.target) if operation_instance.args.folder: cmd = shared_pb2.RestoreCmd(id=backup.id, use_temp_folder=True, folder=operation_instance.args.folder, target=operation_instance.args.target) reply = self.server.RouteRestore(cmd) if not reply.errored: lback_output("RESTORE successful") else: lback_output("RESTORE could not be performed") return reply
class Agent(agent_pb2_grpc.AgentServicer): def DoBackup(self, request_iterator, context): lback_output("Received COMMAND DoBackup") request_iterator, iter_copy = tee(request_iterator) request = next(iter_copy) full_id = lback_id(request.id, shard=protobuf_empty_to_none(request.shard)) lback_output("Running backup on %s" % (request.id)) lback_output("Running backup on shard %s" % (request.shard)) backup = Backup(full_id, request.folder) def backup_chunked_iterator(): for backup_cmd_chunk in request_iterator: yield backup_cmd_chunk.raw_data try: backup.write_chunked(backup_chunked_iterator()) except Exception, ex: print_exc(ex) return shared_pb2.BackupCmdStatus(errored=True) lback_output("BACKUP COMPLETE") return shared_pb2.BackupCmdStatus(errored=False)
def RouteRm(self, request, context): lback_output("Received COMMAND RouteRm") all = request.all target = request.target id = request.id def route_fn(agent): status = agent.DoRm(request) yield status try: if all: iterator = self._RouteOnAllAgents(route_fn) for rm_cmd_reply in iterator: yield shared_pb2.RmCmdStatus(errored=False) lback_output("COMPLETED REMOVE") else: yield shared_pb2.RmCmdStatus(errored=False) lback_output("COMPLETED REMOVE") except Exception, ex: print_exc(ex) yield shared_pb2.RmCmdStatus(errored=True)
class Runtime(object): db = lback_db() db_host = '' db_table = 'backups' db_user_table = 'users' db_user = '' def __init__(self, a): self._settings() self._profiles() ##self.propagate() ##self.uid = Record().generate() ##self.state = BackupState( self.uid ) self.args = a ##self.initv2(a) def initv2(self): parser = argparse.ArgumentParser() parser.add_argument("--adduser", action="store_true", help="Add a new user to Lback", default=False) parser.add_argument("--deluser", action="store_true", help="Delete a user from Lback", default=False) parser.add_argument("--backup", action="store_true", help="Backup files and folders") parser.add_argument("--client", action="store_true", help="Run LBack in client mode") parser.add_argument("--restore", action="store_true", help="Run a restore") parser.add_argument("--server", action="store_true", help="Run Lback in server mode") parser.add_argument("--folder", help="Select a folder", default="") parser.add_argument("--id", help="An ID for Lback", default=Record().generate()) parser.add_argument("--rid", help="A restore ID for Lback", default=Record().generate()) parser.add_argument("--rpc", help="Run the RPC server for Lback", action="store_true", default=False) parser.add_argument("--rpcapi", help="Run LBack in RPC Mode", action="store_true", default=False) parser.add_argument("--name", help="Name for backup", default="Untitled Backup") parser.add_argument("--clean", action="store_true", help="Clean backup on completion") parser.add_argument("--delete", action="store_true", help="Delete existing backup") parser.add_argument("--remove", action="store_true", help="Remove backup when done", default=False) parser.add_argument("--listall", action="store_true", help="List backups", default=False) parser.add_argument("--listusers", action="store_true", default=False) parser.add_argument("--version", default=False, help="Select a version tag") parser.add_argument("--local", default=False, action="store_true") parser.add_argument("--remote", default=False, action="store_true") parser.add_argument("--stop", default=False, action="store_true") parser.add_argument("--start", default=False, action="store_true") parser.add_argument("--restart", default=False, action="store_true") parser.add_argument("--graceful", default=False, action="store_true") parser.add_argument("--status", default=False, action="store_true") parser.add_argument("--settings", default=False, action="store_true") parser.add_argument("--username", default="admin") parser.add_argument("--password", default="admin") parser.add_argument("--snapshot", action="store_true", help="Make a snapshot") parser.add_argument("--profiler", default=False, action="store_true") parser.add_argument("--jit", default=False, action="store_true") parser.add_argument("--port", default="8050") parser.add_argument("--host", default="0.0.0.0") parser.add_argument("--encrypt", action="store_true", help="Make an encrypted backup") parsed = parser.parse_args() parsed.type = 'CLIENT' if parsed.server: parsed.type == 'SERVER' self.args = parsed self.perform() def initv1(self): a = self.args backupDir = lback_backup_dir() ext = lback_backup_ext() self.uid = Record().generate() self.type = 'CLIENT' self.help = 0 args.clean = 0 args.name = "N/A" self.version = "1.0.0" self.is_jit = False self.s3 = False self.version = False if not len(a) > 1: self.help = True self.type = '' for _i in range(0, len(a)): i = a[_i] try: j = a[_i + 1] except: j = a[_i] if i in ['-c', '--client']: self.type = 'CLIENT' if i in ['-s', '--server']: self.type = 'SERVER' if i in ['-h', '--help']: self.help = True if i in ['-b', '--backup']: self.backup = True if i in ['-r', '--restore']: self.restore = True if i in ['-i', '--ip']: self.ip = j if i in ['-p', '--port']: self.port = j if i in ['-x', '--compress']: self.compress = True if i in ['-e', '--encrypt']: self.encrypt = True if i in ['-l', '--local']: self.local = True if i in ['-f', '--folder']: self.folder = os.path.abspath(j) + "/" if i in ['-li', '--list']: self.list = True if i in ['-p', '--profiler']: self.profiler = True self.type = 'PROFILER' if i in ['-rm', '--remove']: self.remove = True if i in ['-del', '--delete']: self.delete = True if i in ['-n', '--name']: args.name = j if i in ['-cl', '--clean']: args.clean = True if i in ['-id', '--id']: self.id = j if i in ['-g', '--graceful']: self.graceful = True if i in ['-re', '--restart']: self.restart = True if i in ['-st', '--start']: self.start = True if i in ['-sp', '--stop']: self.stop = True if i in ['-sn', '--snapshot']: self.snapshot = True if i in ['-v', '--version']: self.version = j self.version = True if i in ['-j', '--just-in-time', '-jit']: self.jit = True self.is_jit = True if i in ['--settings']: self.settings = True if i in ['--stop-profiler']: self.stop_profiler = True if i in ['-st', '--status']: self.status = True if i in ['-s3', '--s3']: self.s3 = True if self.help: self._help() return if not self.version and 'restore' in dir(self): self.version = "latest" lback_output("Running in {0} mode".format(self.type)) self.args = self self.perform() """ try to set up the database """ def propagate(self): pass def perform(self): args = self.args is_success = False backupDir = lback_backup_dir() ext = lback_backup_ext() if check_arg(args, "id"): state = BackupState(args.id) if check_arg(args, "rid"): rstate = RestoreState(args.rid) if check_arg(args, "settings"): lback_output('Opening settings') os.system('vim /usr/local/lback/settings.json') if check_arg(args, "graceful"): """ TODO add graceful shutdown """ lback_output("Stopping server..") os.system("pkill -f 'python ./lback.py --server'") os.system("pkill -f 'python /usr/bin/lback.py --server'") exit() return if check_arg(args, "stop"): lback_output("Stopping server..") os.system("pkill -f 'python ./lback.py --server'") os.system("pkill -f 'python /usr/bin/lback.py --server'") quit() return if check_arg(args, "start"): lback_output("Restarting server..") os.system("pkill -f 'python ./lback.py --server'") os.system("pkill -f 'python /usr/bin/lback.py --server'") lback_output("Started new instance..") time.sleep(1) os.system("lback-server --start") quit() return if check_arg(args, "status"): lback_output("Status of SERVER:") return if check_arg(args, "profiler") and check_arg(args, "stop"): lback_output("Stopping profiler..") os.system("pkill -f 'python ./lback.py --profiler'") os.system("pkill -f 'python /usr/bin/lback.py --profiler'") return if check_arg(args, "folder"): self.size = str(Util().getFolderSize(args.folder)) if check_arg(args, "jit") and check_arg(args, "stop"): lback_output("Stopping JIT instance..") os.system("pkill -f 'python ./lback.py --jit'") os.system("pkill -f 'python /usr/bin/lback.py --profiler'") return if check_arg(args, "rpc"): lback_output("RPC - Starting WebSocket server on {0}:{1}".format( "0.0.0.0", "9000")) #server = SimpleWebSocketServer("0.0.0.0",9000,BackupServer) #server.serveforever() server = WebSocketServer("0.0.0.0", 9000) if check_arg(args, "server"): args.local = False if self.type == 'CLIENT': client = Client(self.port, args.host, dict(ip=args.host, port=args.port)) lback_output("Running on port: {0}, ip: {1}".format( args.port, args.host)) else: server = Server(args.port, args.host, self.db, self.db_table) lback_output("Running on port: {0}, ip: {1}".format( args.port, args.host)) server.run() # exit now and loop else: args.local = True if check_arg(args, "backup"): if not args.folder: pass else: lback_output("Gathering files.. this can take awhile") bkp = Backup(args.id, args.folder, state=state) meta = BackupMeta(id=args.id) state.setState( Events.getStartEvent( status=EventStatuses.STATUS_STARTED, message=EventMessages.MSG_BACKUP_STARTED, obj=EventObjects.OBJECT_BACKUP, data=meta.serialize())) bkp.run() if bkp.status == 1: if check_arg(args, "version") and args.version == '1.0.0': """ try to get previous version """ """ and up the patch by one """ r = self.db(self.db[self.db_table].folder == args.folder).select().last() if r: v = r['version'] cv = re.findall("\d\.\d\.(\d)", v)[0] nv = int(cv) + 1 args.version = re.sub('\d$', str(nv), v) self.db[self.db_table].insert(uid=args.id, time=time.time(), folder=args.folder, size=self.size, local=args.local, name=args.name, version=args.version) self.db.commit() is_success = True if check_arg(args, "local"): state.setState( Events.getFinishedEvent( status=EventStatuses.STATUS_FINISHED, message=EventMessages.MSG_BACKUP_FINISHED, obj=EventObjects.OBJECT_BACKUP, data=meta.serialize())) lback_output("Transaction ID: " + args.id) lback_output("Backup Ok -- Now saving to disk") lback_output( "Local Backup has been successfully stored") lback_output("Transaction ID: " + args.id) else: fc = open(bkp.get(), 'r').read() client.run(cmd='BACKUP', folder=args.folder, uid=args.id, contents=fc, name=args.name, version=args.version, size=self.size) if client.status: lback_output( "Backup Ok -- Now transferring to server") fp = client.get() if len(re.findall("SUCCESS", fp)) > 0: lback_output( "Remote Backup has been successfully transferred" ) lback_output("Transaction ID: " + args.id) os.remove(bkp.get()) else: lback_output( "Something went wrong on the server.. couldnt back that folder. Reverting changes" ) else: pass else: pass if check_arg(args, "restore"): if args.id: id = check_for_id(args.id, self.db) record = self.db.restores.insert(backupId=id, uid=args.rid, time=time.time()) meta = RestoreMeta(id=args.rid) rstate.setState( Events.getStartEvent( status=EventStatuses.STATUS_STARTED, message=EventMessages.MSG_RESTORE_STARTED, obj=EventObjects.OBJECT_RESTORE, data=meta.serialize())) if not check_arg(args, "version"): r = self.db((self.db[self.db_table].uid == id) | \ (self.db[self.db_table].name == id) | \ (self.db[self.db_table].folder == id)).select().last() else: if args.version == "latest": r = self.db((self.db[self.db_table].uid == id) | \ (self.db[self.db_table].name == id) | \ (self.db[self.db_table].folder == id)).select().last() elif args.version.lower() == "oldest": r = self.db((self.db[self.db_table].uid == id) | \ (self.db[self.db_table].name == id) | \ (self.db[self.db_table].folder == id)).select().first() else: r = self.db(((self.db[self.db_table].uid == id) | \ (self.db[self.db_table].name == id) | \ (self.db[self.db_table].folder == id)) \ & (self.db[self.db_table].version == args.version)).select().first() if not r: lback_output("ERROR: Backup not found.") return args.folder = r['folder'] args.local = r['local'] args.clean = check_arg(args, "clean") ruid = r['uid'] archive_loc = backupDir + ruid + ext ## restore an s3 instance #if s3 in dir(self) and self.s3: # pass okargs = dict(status=EventStatuses.STATUS_STOPPED, message=EventMessages.MSG_RESTORE_FINISHED, obj=EventObjects.OBJECT_RESTORE, data=meta.serialize()) errargs = dict(status=EventStatuses.STATUS_ERR, message=EventMessages.MSG_RESTORE_STOPPED, obj=EventObjects.OBJECT_RESTORE, data=meta.serialize()) if check_arg(args, "clean"): lback_output("Cleaning directory..") if not os.path.isdir(args.folder): os.makedirs(args.folder) if args.local: lback_output("Restore Ok -- Now restoring compartment") rst = Restore(archive_loc, folder=args.folder, clean=args.clean, state=rstate) rst.run(local=True, uid=ruid, rid=record.uid) if rst.status: lback_output("Restore has been successfully performed") rstate.setState(Events.getFinishedEvent(**okargs)) else: lback_output("Backup was unsuccessfull") rstate.setState(Events.getStopEvent(**errargs)) else: lback_output("Pinging server for restore..") client.run(cmd='RESTORE', folder=args.folder, uid=ruid, version=args.version) lback_output("Forming archive.. this can take some time") if client.status: lback_output( "Restore Retrieval Ok -- now attempting to restore" ) fp = open(backupDir + ruid + ext, 'w+') fp.write(client.get().decode("utf-8").decode("hex")) fp.close() rst = Restore(archive_loc, folder=args.folder, clean=args.clean, state=rstate) rst.run(local=False, uid=ruid, rid=record.uid) if rst.status: lback_output("Restore Successful") rstate.setState(Events.getFinishedEvent(**okargs)) else: rstate.setState(Events.getStopvent(**errargs)) else: lback_output("Please provide an ID") if check_arg(args, "jit"): if args.id: id = check_for_id(args.id, self.db) jit = JIT(self.db, self.db_table).check(id) else: lback_output("Starting a JIT instance on this backup") os.system("lback-jit --id '{0}' > /dev/null 2>&1".format( args.id)) ## important to check for success ## on this command if check_arg(args, "remove") and is_success: if args.folder: shutil.rmtree(args.folder) lback_output("Directory successfully deleted..") if check_arg(args, "delete"): client = Client(self.port, args.host, dict(ip=args.host, port=self.port)) if args.id: id = check_for_id(args.id, self.db) row = self.db( self.db[self.db_table].uid == id).select().first() if row: lback_output("Removing backup: " + row.name) if not row.local: client.run("DELETE", uid=row.uid) lback_output(client.m) else: os.remove(backupDir + row.uid + ext) if not os.path.isfile(backupDir + row.uid + ext): lback_output("Removed backup successfully") else: lback_output( "Could not delete backup device or resource busy" ) self.db(self.db[self.db_table].uid == id).delete() else: row = self.db( self.db[self.db_table].folder == args.folder).select() if len(row) > 0: lback_output("There are multiple backups with: " + args.folder) counter = 1 counterOfBackups = dict() for i in row: lback_output("Press " + counter + " to delete: ") lback_output(i.as_dict()) counterOfBackups[counter] = i.uid counter += 1 numberSelected = "" while numberSelected != "QUIT": numberSelected = raw_input() if numberSelected > 0 and numberSelected < len( counterOfBackups): thisBackup = counterOfBackups[numberSelected] theBackup = self.db( self.db[self.db_table].uid == thisBackup).select().first() lback_output("removing: " + theBackup.name) if not theBackup.local: client.run("DELETE", uid=theBackup.uid) lback_output(client.m) else: os.remove(backupDir + theBackup.uid + ext) if not os.path.isfile(backupDir + theBackup.uid + ext): lback_output( "Removed the backup successfully") else: lback_output( "Could not delete the backup device or resource is busy" ) self.db(self.db[self.db_table].uid == thisBackup).delete() lback_output( "removed this backup successfully") else: lback_output( "not a valid number please press one of: " + ",".join(counterOfBackups.keys())) lback_output( "Press QUIT to exit or another number to delete more" ) elif len(row) == 1: row = row.first() if not row.local: client.run("DELETE", uid=row.uid) else: os.remove(backupDir + row.uid + ext) if not os.path.isfile(backupDir + row.uid + ext): lback_output("Backup removed successfully") else: lback_output("Could not remove the backup") self.db(self.db[self.db_table].folder == args.folder).delete() lback_output("removed this backup successfully ") else: lback_output("Could not find this backup") if check_arg(args, "listall"): rows = self.db(self.db[self.db_table].time > 0).select().as_list() lback_output("Full list of stored backups") for i in rows: lback_output("Backup", i) if check_arg(args, "listusers"): rows = self.db( self.db[self.db_user_table].id > 0).select().as_list() lback_output("Full list of users") for i in rows: lback_output("User", i) if check_arg(args, "listbackups"): backups = lback_backups(page=args.page, amount=args.amount) result = backups.as_list() return lback_output("", json={ "type": "listbackups", "error": False, "data": result, "message": RPCMessages.LISTED_BACKUPS }) if check_arg(args, "listrestores"): restores = lback_restores(args.page, amount=args.amount) result = restores.as_list() return lback_output("", json={ "type": "listrestores", "error": False, "data": result, "message": RPCMessages.LISTED_RESTORES }) elif check_arg(args, "getbackup"): backup = lback_backup(id=args.id) result = backup.as_dict() return lback_output("", json={ "type": "getbackup", "error": False, "data": result, "message": RPCMessages.LISTED_BACKUP }) elif check_arg(args, "getrestore"): ## restore = lback_restore(id=args.rid) result = restore.as_dict() return lback_output("", json={ "type": "getrestore", "error": False, "data": result, "message": RPCMessages.LISTED_RESTORE }) if check_arg(args, "adduser"): currentUser = self.db(self.db[self.db_user_table].username == args.username).select().first() if currentUser: return lback_output("User with username %s already exists" % (currentUser.username), json={ "error": True, "message": "User with username exists" }) else: try: newRecord = self.db[self.db_user_table].insert( username=args.username, password=args.password) self.db.commit() return lback_output("User with username %s was added " % (newRecord.username), json={ "error": False, "data": newRecord.as_dict(), "message": "Got response" }) except Exception, ex: return lback_output("Unable to add user %s (ERROR: %s)" % (args.username, str(ex)), json={ "error": True, "data": [], "message": "Added new user successfully" }) if check_arg(args, "deluser"): try: self.db(self.db[self.db_user_table].username == args.username).delete() self.db.commit() return lback_output("User was deleted successfully", json={ "error": False, "message": "Deleted user" }) except Exception, ex: return lback_output("User could not be deleted. (ERROR: %s)" % (str(ex)), json={ "message": "User could not be deleted", "error": True })
def perform(self): args = self.args is_success = False backupDir = lback_backup_dir() ext = lback_backup_ext() if check_arg(args, "id"): state = BackupState(args.id) if check_arg(args, "rid"): rstate = RestoreState(args.rid) if check_arg(args, "settings"): lback_output('Opening settings') os.system('vim /usr/local/lback/settings.json') if check_arg(args, "graceful"): """ TODO add graceful shutdown """ lback_output("Stopping server..") os.system("pkill -f 'python ./lback.py --server'") os.system("pkill -f 'python /usr/bin/lback.py --server'") exit() return if check_arg(args, "stop"): lback_output("Stopping server..") os.system("pkill -f 'python ./lback.py --server'") os.system("pkill -f 'python /usr/bin/lback.py --server'") quit() return if check_arg(args, "start"): lback_output("Restarting server..") os.system("pkill -f 'python ./lback.py --server'") os.system("pkill -f 'python /usr/bin/lback.py --server'") lback_output("Started new instance..") time.sleep(1) os.system("lback-server --start") quit() return if check_arg(args, "status"): lback_output("Status of SERVER:") return if check_arg(args, "profiler") and check_arg(args, "stop"): lback_output("Stopping profiler..") os.system("pkill -f 'python ./lback.py --profiler'") os.system("pkill -f 'python /usr/bin/lback.py --profiler'") return if check_arg(args, "folder"): self.size = str(Util().getFolderSize(args.folder)) if check_arg(args, "jit") and check_arg(args, "stop"): lback_output("Stopping JIT instance..") os.system("pkill -f 'python ./lback.py --jit'") os.system("pkill -f 'python /usr/bin/lback.py --profiler'") return if check_arg(args, "rpc"): lback_output("RPC - Starting WebSocket server on {0}:{1}".format( "0.0.0.0", "9000")) #server = SimpleWebSocketServer("0.0.0.0",9000,BackupServer) #server.serveforever() server = WebSocketServer("0.0.0.0", 9000) if check_arg(args, "server"): args.local = False if self.type == 'CLIENT': client = Client(self.port, args.host, dict(ip=args.host, port=args.port)) lback_output("Running on port: {0}, ip: {1}".format( args.port, args.host)) else: server = Server(args.port, args.host, self.db, self.db_table) lback_output("Running on port: {0}, ip: {1}".format( args.port, args.host)) server.run() # exit now and loop else: args.local = True if check_arg(args, "backup"): if not args.folder: pass else: lback_output("Gathering files.. this can take awhile") bkp = Backup(args.id, args.folder, state=state) meta = BackupMeta(id=args.id) state.setState( Events.getStartEvent( status=EventStatuses.STATUS_STARTED, message=EventMessages.MSG_BACKUP_STARTED, obj=EventObjects.OBJECT_BACKUP, data=meta.serialize())) bkp.run() if bkp.status == 1: if check_arg(args, "version") and args.version == '1.0.0': """ try to get previous version """ """ and up the patch by one """ r = self.db(self.db[self.db_table].folder == args.folder).select().last() if r: v = r['version'] cv = re.findall("\d\.\d\.(\d)", v)[0] nv = int(cv) + 1 args.version = re.sub('\d$', str(nv), v) self.db[self.db_table].insert(uid=args.id, time=time.time(), folder=args.folder, size=self.size, local=args.local, name=args.name, version=args.version) self.db.commit() is_success = True if check_arg(args, "local"): state.setState( Events.getFinishedEvent( status=EventStatuses.STATUS_FINISHED, message=EventMessages.MSG_BACKUP_FINISHED, obj=EventObjects.OBJECT_BACKUP, data=meta.serialize())) lback_output("Transaction ID: " + args.id) lback_output("Backup Ok -- Now saving to disk") lback_output( "Local Backup has been successfully stored") lback_output("Transaction ID: " + args.id) else: fc = open(bkp.get(), 'r').read() client.run(cmd='BACKUP', folder=args.folder, uid=args.id, contents=fc, name=args.name, version=args.version, size=self.size) if client.status: lback_output( "Backup Ok -- Now transferring to server") fp = client.get() if len(re.findall("SUCCESS", fp)) > 0: lback_output( "Remote Backup has been successfully transferred" ) lback_output("Transaction ID: " + args.id) os.remove(bkp.get()) else: lback_output( "Something went wrong on the server.. couldnt back that folder. Reverting changes" ) else: pass else: pass if check_arg(args, "restore"): if args.id: id = check_for_id(args.id, self.db) record = self.db.restores.insert(backupId=id, uid=args.rid, time=time.time()) meta = RestoreMeta(id=args.rid) rstate.setState( Events.getStartEvent( status=EventStatuses.STATUS_STARTED, message=EventMessages.MSG_RESTORE_STARTED, obj=EventObjects.OBJECT_RESTORE, data=meta.serialize())) if not check_arg(args, "version"): r = self.db((self.db[self.db_table].uid == id) | \ (self.db[self.db_table].name == id) | \ (self.db[self.db_table].folder == id)).select().last() else: if args.version == "latest": r = self.db((self.db[self.db_table].uid == id) | \ (self.db[self.db_table].name == id) | \ (self.db[self.db_table].folder == id)).select().last() elif args.version.lower() == "oldest": r = self.db((self.db[self.db_table].uid == id) | \ (self.db[self.db_table].name == id) | \ (self.db[self.db_table].folder == id)).select().first() else: r = self.db(((self.db[self.db_table].uid == id) | \ (self.db[self.db_table].name == id) | \ (self.db[self.db_table].folder == id)) \ & (self.db[self.db_table].version == args.version)).select().first() if not r: lback_output("ERROR: Backup not found.") return args.folder = r['folder'] args.local = r['local'] args.clean = check_arg(args, "clean") ruid = r['uid'] archive_loc = backupDir + ruid + ext ## restore an s3 instance #if s3 in dir(self) and self.s3: # pass okargs = dict(status=EventStatuses.STATUS_STOPPED, message=EventMessages.MSG_RESTORE_FINISHED, obj=EventObjects.OBJECT_RESTORE, data=meta.serialize()) errargs = dict(status=EventStatuses.STATUS_ERR, message=EventMessages.MSG_RESTORE_STOPPED, obj=EventObjects.OBJECT_RESTORE, data=meta.serialize()) if check_arg(args, "clean"): lback_output("Cleaning directory..") if not os.path.isdir(args.folder): os.makedirs(args.folder) if args.local: lback_output("Restore Ok -- Now restoring compartment") rst = Restore(archive_loc, folder=args.folder, clean=args.clean, state=rstate) rst.run(local=True, uid=ruid, rid=record.uid) if rst.status: lback_output("Restore has been successfully performed") rstate.setState(Events.getFinishedEvent(**okargs)) else: lback_output("Backup was unsuccessfull") rstate.setState(Events.getStopEvent(**errargs)) else: lback_output("Pinging server for restore..") client.run(cmd='RESTORE', folder=args.folder, uid=ruid, version=args.version) lback_output("Forming archive.. this can take some time") if client.status: lback_output( "Restore Retrieval Ok -- now attempting to restore" ) fp = open(backupDir + ruid + ext, 'w+') fp.write(client.get().decode("utf-8").decode("hex")) fp.close() rst = Restore(archive_loc, folder=args.folder, clean=args.clean, state=rstate) rst.run(local=False, uid=ruid, rid=record.uid) if rst.status: lback_output("Restore Successful") rstate.setState(Events.getFinishedEvent(**okargs)) else: rstate.setState(Events.getStopvent(**errargs)) else: lback_output("Please provide an ID") if check_arg(args, "jit"): if args.id: id = check_for_id(args.id, self.db) jit = JIT(self.db, self.db_table).check(id) else: lback_output("Starting a JIT instance on this backup") os.system("lback-jit --id '{0}' > /dev/null 2>&1".format( args.id)) ## important to check for success ## on this command if check_arg(args, "remove") and is_success: if args.folder: shutil.rmtree(args.folder) lback_output("Directory successfully deleted..") if check_arg(args, "delete"): client = Client(self.port, args.host, dict(ip=args.host, port=self.port)) if args.id: id = check_for_id(args.id, self.db) row = self.db( self.db[self.db_table].uid == id).select().first() if row: lback_output("Removing backup: " + row.name) if not row.local: client.run("DELETE", uid=row.uid) lback_output(client.m) else: os.remove(backupDir + row.uid + ext) if not os.path.isfile(backupDir + row.uid + ext): lback_output("Removed backup successfully") else: lback_output( "Could not delete backup device or resource busy" ) self.db(self.db[self.db_table].uid == id).delete() else: row = self.db( self.db[self.db_table].folder == args.folder).select() if len(row) > 0: lback_output("There are multiple backups with: " + args.folder) counter = 1 counterOfBackups = dict() for i in row: lback_output("Press " + counter + " to delete: ") lback_output(i.as_dict()) counterOfBackups[counter] = i.uid counter += 1 numberSelected = "" while numberSelected != "QUIT": numberSelected = raw_input() if numberSelected > 0 and numberSelected < len( counterOfBackups): thisBackup = counterOfBackups[numberSelected] theBackup = self.db( self.db[self.db_table].uid == thisBackup).select().first() lback_output("removing: " + theBackup.name) if not theBackup.local: client.run("DELETE", uid=theBackup.uid) lback_output(client.m) else: os.remove(backupDir + theBackup.uid + ext) if not os.path.isfile(backupDir + theBackup.uid + ext): lback_output( "Removed the backup successfully") else: lback_output( "Could not delete the backup device or resource is busy" ) self.db(self.db[self.db_table].uid == thisBackup).delete() lback_output( "removed this backup successfully") else: lback_output( "not a valid number please press one of: " + ",".join(counterOfBackups.keys())) lback_output( "Press QUIT to exit or another number to delete more" ) elif len(row) == 1: row = row.first() if not row.local: client.run("DELETE", uid=row.uid) else: os.remove(backupDir + row.uid + ext) if not os.path.isfile(backupDir + row.uid + ext): lback_output("Backup removed successfully") else: lback_output("Could not remove the backup") self.db(self.db[self.db_table].folder == args.folder).delete() lback_output("removed this backup successfully ") else: lback_output("Could not find this backup") if check_arg(args, "listall"): rows = self.db(self.db[self.db_table].time > 0).select().as_list() lback_output("Full list of stored backups") for i in rows: lback_output("Backup", i) if check_arg(args, "listusers"): rows = self.db( self.db[self.db_user_table].id > 0).select().as_list() lback_output("Full list of users") for i in rows: lback_output("User", i) if check_arg(args, "listbackups"): backups = lback_backups(page=args.page, amount=args.amount) result = backups.as_list() return lback_output("", json={ "type": "listbackups", "error": False, "data": result, "message": RPCMessages.LISTED_BACKUPS }) if check_arg(args, "listrestores"): restores = lback_restores(args.page, amount=args.amount) result = restores.as_list() return lback_output("", json={ "type": "listrestores", "error": False, "data": result, "message": RPCMessages.LISTED_RESTORES }) elif check_arg(args, "getbackup"): backup = lback_backup(id=args.id) result = backup.as_dict() return lback_output("", json={ "type": "getbackup", "error": False, "data": result, "message": RPCMessages.LISTED_BACKUP }) elif check_arg(args, "getrestore"): ## restore = lback_restore(id=args.rid) result = restore.as_dict() return lback_output("", json={ "type": "getrestore", "error": False, "data": result, "message": RPCMessages.LISTED_RESTORE }) if check_arg(args, "adduser"): currentUser = self.db(self.db[self.db_user_table].username == args.username).select().first() if currentUser: return lback_output("User with username %s already exists" % (currentUser.username), json={ "error": True, "message": "User with username exists" }) else: try: newRecord = self.db[self.db_user_table].insert( username=args.username, password=args.password) self.db.commit() return lback_output("User with username %s was added " % (newRecord.username), json={ "error": False, "data": newRecord.as_dict(), "message": "Got response" }) except Exception, ex: return lback_output("Unable to add user %s (ERROR: %s)" % (args.username, str(ex)), json={ "error": True, "data": [], "message": "Added new user successfully" })
def initv1(self): a = self.args backupDir = lback_backup_dir() ext = lback_backup_ext() self.uid = Record().generate() self.type = 'CLIENT' self.help = 0 args.clean = 0 args.name = "N/A" self.version = "1.0.0" self.is_jit = False self.s3 = False self.version = False if not len(a) > 1: self.help = True self.type = '' for _i in range(0, len(a)): i = a[_i] try: j = a[_i + 1] except: j = a[_i] if i in ['-c', '--client']: self.type = 'CLIENT' if i in ['-s', '--server']: self.type = 'SERVER' if i in ['-h', '--help']: self.help = True if i in ['-b', '--backup']: self.backup = True if i in ['-r', '--restore']: self.restore = True if i in ['-i', '--ip']: self.ip = j if i in ['-p', '--port']: self.port = j if i in ['-x', '--compress']: self.compress = True if i in ['-e', '--encrypt']: self.encrypt = True if i in ['-l', '--local']: self.local = True if i in ['-f', '--folder']: self.folder = os.path.abspath(j) + "/" if i in ['-li', '--list']: self.list = True if i in ['-p', '--profiler']: self.profiler = True self.type = 'PROFILER' if i in ['-rm', '--remove']: self.remove = True if i in ['-del', '--delete']: self.delete = True if i in ['-n', '--name']: args.name = j if i in ['-cl', '--clean']: args.clean = True if i in ['-id', '--id']: self.id = j if i in ['-g', '--graceful']: self.graceful = True if i in ['-re', '--restart']: self.restart = True if i in ['-st', '--start']: self.start = True if i in ['-sp', '--stop']: self.stop = True if i in ['-sn', '--snapshot']: self.snapshot = True if i in ['-v', '--version']: self.version = j self.version = True if i in ['-j', '--just-in-time', '-jit']: self.jit = True self.is_jit = True if i in ['--settings']: self.settings = True if i in ['--stop-profiler']: self.stop_profiler = True if i in ['-st', '--status']: self.status = True if i in ['-s3', '--s3']: self.s3 = True if self.help: self._help() return if not self.version and 'restore' in dir(self): self.version = "latest" lback_output("Running in {0} mode".format(self.type)) self.args = self self.perform()
def closed(self, code, reason=""): lback_output("Received disconnection")
def getState(self): lback_output("RPC - Getting state {}: {}".format( self.obj, self.objectId ) ) data = self.client.get(self.prefix+self.objectId) lback_output("RPC - Got state: {0}".format( data ) ) return data
def setState(self,data): lback_output("RPC - Setting state {}: {}: {}".format( self.obj, self.objectId, data) ) return self.client.set(self.prefix+self.objectId, data)
def received_message(self, message): lback_output("Received message: %s"%(str(message))) BackupServer.received_message(self, message.data)
def _run(self, operation_instance, backup=None): if isinstance(operation_instance, OperationBackup): lback_output("Routing BACKUP") msg = shared_pb2.BackupCmd(id=backup.id) replies = self.server.RouteBackup(msg) for reply in replies: if not reply.errored: lback_output("BACKUP propagated") else: lback_output("BACKUP could not be propagated") elif isinstance(operation_instance, OperationRestore): lback_output("Routing RESTORE") reply = self.server.RouteRestore( shared_pb2.RestoreCmd(id=backup.id)) if not reply.errored: lback_output("RESTORE successful") else: lback_output("RESTORE could not be performed") elif isinstance(operation_instance, OperationRelocate): lback_output("Routing RELOCATE") reply = self.server.RouteRelocate( shared_pb2.RelocateCmd(id=id, src=operation_instance.args.src, dst=operation_instance.args.dst)) if not not reply.errored: lback_output("RELOCATE successful") else: lback_output("RELOCATE could not be performed") elif isinstance(operation_instance, OperationRm): lback_output("Routing REMOVE") if operation_instance.args.all: replies = self.server.RouteRm( shared_pb2.RmCmd(id=backup.id, all=operation_instance.args.all)) else: target = operation_instance.args.target replies = self.server.RouteRm( shared_pb2.RmCmd(id=backup.id, target=target)) for reply in replies: if not not reply.errored: lback_output("REMOVE propagated") else: lback_output("REMOVE could not be propagated")
def opened(self): lback_output("Received connection for Lback RPC ")