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

Pavel Emelyanov xemul at parallels.com
Wed Jun 24 12:22:15 PDT 2015


On 06/24/2015 08:57 PM, Nikita Spiridonov wrote:
> 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.

Please, split the patch into

[PATCH 1/2] Move all requests-related code to separate mothods
[PATCH 2/2] Allos specify module-specific criu request options

> 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)
> 



More information about the CRIU mailing list