def ack_notify(self, success = True): req = cr_rpc.criu_req() req.type = cr_rpc.NOTIFY req.notify_success = True self._cs.send(req.SerializeToString()) return self._recv_resp()
def ack_notify(self, success=True): req = cr_rpc.criu_req() req.type = cr_rpc.NOTIFY req.notify_success = True self._cs.send(req.SerializeToString()) return self._recv_resp()
def rpc_check_cpuinfo(self): print "Checking cpuinfo" req = cr_rpc.criu_req() req.type = cr_rpc.CPUINFO_CHECK req.opts.images_dir_fd = self.img.work_dir_fd() req.keep_open = True resp = self.criu.send_req(req) print " `-", resp.success return resp.success
def rpc_restore_from_images(self): print "Restoring from images" self.htype.put_meta_images(self.img.image_dir()) req = cr_rpc.criu_req() req.type = cr_rpc.RESTORE req.opts.images_dir_fd = self.img.image_dir_fd() req.opts.work_dir_fd = self.img.work_dir_fd() req.opts.notify_scripts = True if self.htype.can_migrate_tcp(): req.opts.tcp_established = True for veth in self.htype.veths(): v = req.opts.veths.add() v.if_in = veth.name v.if_out = veth.pair nroot = self.htype.mount() if nroot: req.opts.root = nroot print "Restore root set to %s" % req.opts.root cc = self.criu resp = cc.send_req(req) while True: if resp.type == cr_rpc.NOTIFY: print "\t\tNotify (%s.%d)" % (resp.notify.script, resp.notify.pid) if resp.notify.script == "setup-namespaces": # # At that point we have only one task # living in namespaces and waiting for # us to ACK the notify. Htype might want # to configure namespace (external net # devices) and cgroups # self.htype.prepare_ct(resp.notify.pid) elif resp.notify.script == "network-unlock": self.htype.net_unlock() elif resp.notify.script == "network-lock": raise Exception("Locking network on restore?") resp = cc.ack_notify() continue if not resp.success: raise Exception("Restore failed") print "Restore succeeded" break self.htype.restored(resp.restore.pid) self.restored = True
def POST(self): """ Attempt to restore a process, where the directory where the proccess images are is given in the URL parameter "dir". """ web.header("Content-Type", "application/json") web.header("Access-Control-Allow-Origin", "*") if "data" not in web.input(): result = {"succeeded": False, "why": "No image data provided"} raise web.badrequest(json.dumps(result, separators=",:")) if "dir" not in web.input(): result = {"succeeded": False, "why": "No image directory provided"} raise web.badrequest(json.dumps(result, separators=",:")) # Extract the images from the base64-encoding tarball. temptar = tempfile.mktemp() self.tempdir = web.input()["dir"] print self.tempdir with open(temptar, "w") as tar: tar.write(base64.b64decode(web.input()["data"])) with tarfile.open(temptar, "r:gz") as tar: tar.list() tar.extractall("/") try: dir_fd = os.open(self.tempdir, os.O_DIRECTORY) except OSError as e: result = {"succeeded": False, "why": e.strerror} raise web.badrequest(json.dumps(result, separators=",:")) self.connect() # Send a request to restore the specified process req = criu.criu_req() req.type = criu.RESTORE req.opts.shell_job = False req.opts.manage_cgroups = True req.opts.images_dir_fd = dir_fd resp = self.transaction(req) return json.dumps({"succeeded": True}, separators=",:")
def validate_cpu(self): print "Checking CPU compatibility" print " `- Dumping CPU info" req = cr_rpc.criu_req() req.type = cr_rpc.CPUINFO_DUMP req.opts.images_dir_fd = self.img.work_dir_fd() req.keep_open = True resp = self.criu.send_req(req) if not resp.success: raise Exception("Can't dump cpuinfo") print " `- Sending CPU info" self.img.send_cpuinfo(self.th, self.data_sk) print " `- Checking CPU info" if not self.th.check_cpuinfo(): raise Exception("CPUs mismatch")
def POST(self): """ Attempt to dump a process, where the PID is given in the URL parameter "pid". """ web.header("Content-Type", "application/json") web.header("Access-Control-Allow-Origin", "*") pid = web.input().get("pid") if not pid or not pid.isnumeric(): result = {"succeeded": False, "why": "No PID specified"} raise web.badrequest(json.dumps(result, separators=",:")) self.connect() self.tempdir = tempfile.mkdtemp() # Send a request to dump the specified process req = criu.criu_req() req.type = criu.DUMP req.opts.pid = int(pid) req.opts.shell_job = False req.opts.manage_cgroups = True req.opts.images_dir_fd = os.open(self.tempdir, os.O_DIRECTORY) resp = self.transaction(req) # Create a tar of all of the images and send it base64-encoded back to # the client. This is okay for a small demo, but obviously a real # application would probably not be this wasteful with resources. temptar = tempfile.mktemp() with tarfile.open(temptar, "w:gz") as tar: for f in os.listdir(self.tempdir): tar.add(self.tempdir + "/" + f) tar.close() with open(temptar, "r") as tar: data = base64.b64encode(tar.read()) return json.dumps({"succeeded": True, "data": data, "dir": self.tempdir}, separators=",:")
def start_page_server(self): print "Starting page server for iter %d" % self.dump_iter req = cr_rpc.criu_req() req.type = cr_rpc.PAGE_SERVER req.keep_open = True req.opts.ps.fd = self.criu.mem_sk_fileno() req.opts.images_dir_fd = self.img.image_dir_fd() req.opts.work_dir_fd = self.img.work_dir_fd() p_img = self.img.prev_image_dir() if p_img: req.opts.parent_img = p_img print "\tSending criu rpc req" resp = self.criu.send_req(req) if not resp.success: raise Exception("Failed to start page server") print "\tPage server started at %d" % resp.ps.pid
def make_dump_req(self, typ): # # Prepare generic request for (pre)dump # req = cr_rpc.criu_req() req.type = typ req.opts.pid = self.pid req.opts.ps.fd = self.criu.mem_sk_fileno() req.opts.track_mem = True req.opts.images_dir_fd = self.img.image_dir_fd() req.opts.work_dir_fd = self.img.work_dir_fd() p_img = self.img.prev_image_dir() if p_img: req.opts.parent_img = p_img if not self.fs.persistent_inodes(): req.opts.force_irmap = True return req