[CRIU] [PATCH V2] p.haul: allow specify module-specific criu request options

Nikita Spiridonov nspiridonov at odin.com
Wed Jun 24 10:57:23 PDT 2015


We have to specify --ext-mount-map auto, --enable-external-sharing
and --enable-external-masters options in criu dump and restore
requests during Virtuozzo container migration to make it work. To
make it real add possibility that allow specify module-specific
criu request options.

Now every phaul module (e.g. Virtuozzo or LXC) have method
adjust_criu_req; any module-specific request options can be
specified in this method.

Additionally move all requests-related code to separate methods in
phaul_iter_worker and phaul_service classes to simplify migration
logic.

Signed-off-by: Nikita Spiridonov <nspiridonov at odin.com>
---
 phaul/p_haul_iters.py   |   95 +++++++++++++++++++++++++++--------------------
 phaul/p_haul_lxc.py     |    4 ++
 phaul/p_haul_pid.py     |    4 ++
 phaul/p_haul_service.py |   92 +++++++++++++++++++++++++++------------------
 phaul/p_haul_vz.py      |    9 ++++
 5 files changed, 127 insertions(+), 77 deletions(-)

diff --git a/phaul/p_haul_iters.py b/phaul/p_haul_iters.py
index 7a898da..3a2585a 100644
--- a/phaul/p_haul_iters.py
+++ b/phaul/p_haul_iters.py
@@ -47,28 +47,6 @@ class phaul_iter_worker:
 		print "Setting up remote"
 		self.th.setup(p_type)
 
-
-	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
-
 	def set_options(self, opts):
 		self.th.set_options(opts)
 		self.criu.verbose(opts["verbose"])
@@ -80,10 +58,7 @@ class phaul_iter_worker:
 		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
+		req = self.__make_cpuinfo_dump_req()
 		resp = self.criu.send_req(req)
 		if not resp.success:
 			raise Exception("Can't dump cpuinfo")
@@ -106,7 +81,6 @@ class phaul_iter_worker:
 		self.fs.start_migration()
 
 		print "Starting iterations"
-		cc = self.criu
 
 		while True:
 			print "* Iteration %d" % self.iteration
@@ -116,8 +90,8 @@ class phaul_iter_worker:
 
 			print "\tIssuing pre-dump command to service"
 
-			req = self.make_dump_req(cr_rpc.PRE_DUMP)
-			resp = cc.send_req(req)
+			req = self.__make_predump_req()
+			resp = self.criu.send_req(req)
 			if not resp.success:
 				raise Exception("Pre-dump failed")
 
@@ -168,15 +142,9 @@ class phaul_iter_worker:
 		self.img.new_image_dir()
 
 		print "\tIssuing dump command to service"
-		req = self.make_dump_req(cr_rpc.DUMP)
-		req.opts.notify_scripts = True
-		req.opts.file_locks = True
-		req.opts.evasive_devices = True
-		req.opts.link_remap = True
-		if self.htype.can_migrate_tcp():
-			req.opts.tcp_established = True
 
-		resp = cc.send_req(req)
+		req = self.__make_dump_req()
+		resp = self.criu.send_req(req)
 		while True:
 			if resp.type != cr_rpc.NOTIFY:
 				raise Exception("Dump failed")
@@ -195,7 +163,7 @@ class phaul_iter_worker:
 				self.htype.net_unlock()
 
 			print "\t\tNotify (%s)" % resp.notify.script
-			resp = cc.ack_notify()
+			resp = self.criu.ack_notify()
 
 		print "Dump complete"
 		self.th.end_iter()
@@ -219,7 +187,7 @@ class phaul_iter_worker:
 		# DUMP/success message
 		#
 
-		resp = cc.ack_notify()
+		resp = self.criu.ack_notify()
 		if not resp.success:
 			raise Exception("Dump screwed up")
 
@@ -229,4 +197,51 @@ class phaul_iter_worker:
 		self._mstat.iteration(stats)
 		self._mstat.stop(self)
 		self.img.close()
-		cc.close()
+		self.criu.close()
+
+	def __make_req(self, typ):
+		"""Prepare generic criu request"""
+		req = cr_rpc.criu_req()
+		req.type = typ
+		self.htype.adjust_criu_req(req)
+		return req
+
+	def __make_common_dump_req(self, typ):
+		"""Prepare common criu request for pre-dump or dump"""
+
+		req = self.__make_req(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
+
+	def __make_cpuinfo_dump_req(self):
+		"""Prepare cpuinfo dump criu request"""
+		req = self.__make_req(cr_rpc.CPUINFO_DUMP)
+		req.opts.images_dir_fd = self.img.work_dir_fd()
+		req.keep_open = True
+		return req
+
+	def __make_predump_req(self):
+		"""Prepare pre-dump criu request"""
+		return self.__make_common_dump_req(cr_rpc.PRE_DUMP)
+
+	def __make_dump_req(self):
+		"""Prepare dump criu request"""
+		req = self.__make_common_dump_req(cr_rpc.DUMP)
+		req.opts.notify_scripts = True
+		req.opts.file_locks = True
+		req.opts.evasive_devices = True
+		req.opts.link_remap = True
+		if self.htype.can_migrate_tcp():
+			req.opts.tcp_established = True
+		return req
diff --git a/phaul/p_haul_lxc.py b/phaul/p_haul_lxc.py
index 27df698..13640d2 100644
--- a/phaul/p_haul_lxc.py
+++ b/phaul/p_haul_lxc.py
@@ -76,6 +76,10 @@ class p_haul_type:
 	def set_options(self, opts):
 		pass
 
+	def adjust_criu_req(self, req):
+		"""Add module-specific options to criu request"""
+		pass
+
 	def root_task_pid(self):
 		pid = -1;
 
diff --git a/phaul/p_haul_pid.py b/phaul/p_haul_pid.py
index f0051b0..5bd2d5d 100644
--- a/phaul/p_haul_pid.py
+++ b/phaul/p_haul_pid.py
@@ -24,6 +24,10 @@ class p_haul_type:
 		self._pidfile = opts["dst_rpid"]
 		self._fs_root = opts["pid_root"]
 
+	def adjust_criu_req(self, req):
+		"""Add module-specific options to criu request"""
+		pass
+
 	# Report the pid of the root task of what we're
 	# goung to migrate
 	def root_task_pid(self):
diff --git a/phaul/p_haul_service.py b/phaul/p_haul_service.py
index d3e19ff..50eab03 100644
--- a/phaul/p_haul_service.py
+++ b/phaul/p_haul_service.py
@@ -53,18 +53,8 @@ class phaul_service:
 	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"
+		req = self.__make_page_server_req()
 		resp = self.criu.send_req(req)
 		if not resp.success:
 			raise Exception("Failed to start page server")
@@ -87,10 +77,7 @@ class phaul_service:
 
 	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
+		req = self.__make_cpuinfo_check_req()
 		resp = self.criu.send_req(req)
 		print "   `-", resp.success
 		return resp.success
@@ -99,27 +86,8 @@ class phaul_service:
 		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)
+		req = self.__make_restore_req()
+		resp = self.criu.send_req(req)
 		while True:
 			if resp.type == cr_rpc.NOTIFY:
 				print "\t\tNotify (%s.%d)" % (resp.notify.script, resp.notify.pid)
@@ -137,7 +105,7 @@ class phaul_service:
 				elif resp.notify.script == "network-lock":
 					raise Exception("Locking network on restore?")
 
-				resp = cc.ack_notify()
+				resp = self.criu.ack_notify()
 				continue
 
 			if not resp.success:
@@ -152,3 +120,53 @@ class phaul_service:
 	def rpc_restore_time(self):
 		stats = criu_api.criu_get_rstats(self.img)
 		return stats.restore_time
+
+	def __make_req(self, typ):
+		"""Prepare generic criu request"""
+		req = cr_rpc.criu_req()
+		req.type = typ
+		self.htype.adjust_criu_req(req)
+		return req
+
+	def __make_page_server_req(self):
+		"""Prepare page server criu request"""
+
+		req = self.__make_req(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
+
+		return req
+
+	def __make_cpuinfo_check_req(self):
+		"""Prepare cpuinfo check criu request"""
+		req = self.__make_req(cr_rpc.CPUINFO_CHECK)
+		req.keep_open = True
+		req.opts.images_dir_fd = self.img.work_dir_fd()
+		return req
+
+	def __make_restore_req(self):
+		"""Prepare restore criu request"""
+
+		req = self.__make_req(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():
+			req.opts.veths.add(if_in = veth.name, if_out = veth.pair)
+
+		nroot = self.htype.mount()
+		if nroot:
+			req.opts.root = nroot
+			print "Restore root set to %s" % req.opts.root
+
+		return req
diff --git a/phaul/p_haul_vz.py b/phaul/p_haul_vz.py
index 40dc943..7f41816 100644
--- a/phaul/p_haul_vz.py
+++ b/phaul/p_haul_vz.py
@@ -8,6 +8,7 @@ import p_haul_cgroup
 import util
 import fs_haul_shared
 import fs_haul_subtree
+import pycriu.rpc
 
 name = "vz"
 vz_dir = "/vz"
@@ -72,6 +73,14 @@ class p_haul_type:
 	def set_options(self, opts):
 		pass
 
+	def adjust_criu_req(self, req):
+		"""Add module-specific options to criu request"""
+		if req.type == pycriu.rpc.DUMP or req.type == pycriu.rpc.RESTORE:
+			# Setup options for external mounts resolution
+			req.opts.auto_ext_mnt = True
+			req.opts.ext_sharing = True
+			req.opts.ext_masters = True
+
 	def root_task_pid(self):
 		# Expect first line of tasks file contain root pid of CT
 		path = "/sys/fs/cgroup/memory/{0}/tasks".format(self._ctid)
-- 
1.7.1



More information about the CRIU mailing list