[CRIU] [PATCH 3/4] p.haul: change --fdfs argument semantics to handle multiple disks

Nikita Spiridonov nspiridonov at odin.com
Thu Dec 10 02:12:04 PST 2015


change --fdfs argument semantics to handle multiple disks. Now for
Virtuozzo module --fdfs option accept list of active ploop deltas
with corresponding sockets in format
%delta_path1%:%socket_fd1%[,...].

Not sure if we have to rename --fdfs options to something like
--fschannel or preserve old name for uniformity
(--fdrpc/--fdmem/--fdfs). Preserve old name for now.

Signed-off-by: Nikita Spiridonov <nspiridonov at odin.com>
---
 p.haul                 |    6 +++---
 phaul/args_parser.py   |    5 +++--
 phaul/connection.py    |   18 +++++++++---------
 phaul/iters.py         |    2 +-
 phaul/p_haul_docker.py |    4 ++--
 phaul/p_haul_lxc.py    |    4 ++--
 phaul/p_haul_pid.py    |    4 ++--
 phaul/p_haul_vz.py     |   43 +++++++++++++++++++++++++++++++++++++++----
 phaul/service.py       |    9 ++++-----
 9 files changed, 65 insertions(+), 30 deletions(-)

diff --git a/p.haul b/p.haul
index b56fb5c..b6fb234 100755
--- a/p.haul
+++ b/p.haul
@@ -7,7 +7,7 @@ import phaul.iters
 import phaul.connection
 
 # Usage idea
-# p.haul <type> <id> --fdrpc <fd> --fdmem <fd> --fdfs <fd>
+# p.haul <type> <id> --fdrpc <fd> --fdmem <fd>
 #
 # p.haul work over existing connections specified via command line arguments
 # as file descriptors. Three arguments required - --fdrpc for rpc calls,
@@ -16,8 +16,8 @@ import phaul.connection
 # connections with target host and call p.haul or p.haul-service.
 #
 # E.g.
-# p.haul vz 100 --fdrpc 3 --fdmem 4 --fdfs 5
-# p.haul lxc myct --fdrpc 3 --fdmem 4 --fdfs 5
+# p.haul vz 100 --fdrpc 3 --fdmem 4 --fdfs root.hdd/root.hds:5
+# p.haul lxc myct --fdrpc 3 --fdmem 4
 #
 
 
diff --git a/phaul/args_parser.py b/phaul/args_parser.py
index 8e519b4..a98b64f 100644
--- a/phaul/args_parser.py
+++ b/phaul/args_parser.py
@@ -22,7 +22,7 @@ def parse_client_args():
 	parser.add_argument("--to", help="IP where to haul")
 	parser.add_argument("--fdrpc", type=int, required=True, help="File descriptor of rpc socket")
 	parser.add_argument("--fdmem", type=int, required=True, help="File descriptor of memory socket")
-	parser.add_argument("--fdfs", type=int, required=True, help="File descriptor of fs socket")
+	parser.add_argument("--fdfs", help="Module specific definition of fs channel")
 	parser.add_argument("-v", default=criu_api.def_verb, type=int, dest="verbose", help="Verbosity level")
 	parser.add_argument("--keep-images", default=False, action='store_true', help="Keep images after migration")
 	parser.add_argument("--dst-rpid", default=None, help="Write pidfile on restore")
@@ -52,7 +52,8 @@ def parse_service_args():
 
 	parser.add_argument("--fdrpc", type=int, required=True, help="File descriptor of rpc socket")
 	parser.add_argument("--fdmem", type=int, required=True, help="File descriptor of memory socket")
-	parser.add_argument("--fdfs", type=int, required=True, help="File descriptor of fs socket")
+	parser.add_argument("--fdfs", help="Module specific definition of fs channel")
+
 	parser.add_argument("--log-file", help="Write logging messages to specified file")
 
 	return parser.parse_args()
diff --git a/phaul/connection.py b/phaul/connection.py
index 33da9fd..7838bc3 100644
--- a/phaul/connection.py
+++ b/phaul/connection.py
@@ -13,18 +13,17 @@ class connection:
 
 	Class encapsulate connections reqired for p.haul work, including rpc socket
 	(socket for RPC calls), memory socket (socket for c/r images migration) and
-	fs socket (socket for disk migration).
+	module specific definition of fs channel needed for disk migration.
 	"""
 
-	def __init__(self, rpc_sk, mem_sk, fs_sk):
+	def __init__(self, rpc_sk, mem_sk, fdfs):
 		self.rpc_sk = rpc_sk
 		self.mem_sk = mem_sk
-		self.fs_sk = fs_sk
+		self.fdfs = fdfs
 
 	def close(self):
 		self.rpc_sk.close()
 		self.mem_sk.close()
-		self.fs_sk.close()
 
 
 def establish(fdrpc, fdmem, fdfs):
@@ -34,13 +33,14 @@ def establish(fdrpc, fdmem, fdfs):
 	with domain AF_INET and type SOCK_STREAM.
 	"""
 
-	logging.info("Use existing connections, fdrpc=%d fdmem=%d fdfs=%d", fdrpc,
+	logging.info("Use existing connections, fdrpc=%d fdmem=%d fdfs=%s", fdrpc,
 		fdmem, fdfs)
 
+	# Create rpc socket
 	rpc_sk = socket.fromfd(fdrpc, socket.AF_INET, socket.SOCK_STREAM)
-	mem_sk = socket.fromfd(fdmem, socket.AF_INET, socket.SOCK_STREAM)
-	fs_sk = socket.fromfd(fdfs, socket.AF_INET, socket.SOCK_STREAM)
-
 	util.set_cloexec(rpc_sk)
 
-	return connection(rpc_sk, mem_sk, fs_sk)
+	# Create memory socket
+	mem_sk = socket.fromfd(fdmem, socket.AF_INET, socket.SOCK_STREAM)
+
+	return connection(rpc_sk, mem_sk, fdfs)
diff --git a/phaul/iters.py b/phaul/iters.py
index 8728e7e..89a7841 100644
--- a/phaul/iters.py
+++ b/phaul/iters.py
@@ -40,7 +40,7 @@ class phaul_iter_worker:
 		if not self.htype:
 			raise Exception("No htype driver found")
 
-		self.fs = self.htype.get_fs(self.connection.fs_sk)
+		self.fs = self.htype.get_fs(self.connection.fdfs)
 		if not self.fs:
 			raise Exception("No FS driver found")
 
diff --git a/phaul/p_haul_docker.py b/phaul/p_haul_docker.py
index 81e7533..e957103 100644
--- a/phaul/p_haul_docker.py
+++ b/phaul/p_haul_docker.py
@@ -66,11 +66,11 @@ class p_haul_type:
 	def umount(self):
 		pass
 
-	def get_fs(self, fs_sk=None):
+	def get_fs(self, fdfs=None):
 		# use rsync for rootfs and configuration directories
 		return fs_haul_subtree.p_haul_fs([self._ct_rootfs, self._ct_config_dir])
 
-	def get_fs_receiver(self, fs_sk=None):
+	def get_fs_receiver(self, fdfs=None):
 		return None
 
 	def get_full_ctid(self):
diff --git a/phaul/p_haul_lxc.py b/phaul/p_haul_lxc.py
index 5e1fe7b..4b3d789 100644
--- a/phaul/p_haul_lxc.py
+++ b/phaul/p_haul_lxc.py
@@ -133,10 +133,10 @@ class p_haul_type:
 		self._fs_mounted = True
 		return nroot
 
-	def get_fs(self, fs_sk=None):
+	def get_fs(self, fdfs=None):
 		return fs_haul_shared.p_haul_fs()
 
-	def get_fs_receiver(self, fs_sk=None):
+	def get_fs_receiver(self, fdfs=None):
 		return None
 
 	def restored(self, pid):
diff --git a/phaul/p_haul_pid.py b/phaul/p_haul_pid.py
index a53d594..75dfd26 100644
--- a/phaul/p_haul_pid.py
+++ b/phaul/p_haul_pid.py
@@ -46,10 +46,10 @@ class p_haul_type:
 		pass
 
 	# Get driver for FS migration
-	def get_fs(self, fs_sk=None):
+	def get_fs(self, fdfs=None):
 		return fs_haul_shared.p_haul_fs()
 
-	def get_fs_receiver(self, fs_sk=None):
+	def get_fs_receiver(self, fdfs=None):
 		return None
 
 	# Get list of files which should be copied to
diff --git a/phaul/p_haul_vz.py b/phaul/p_haul_vz.py
index db13f2d..85c8857 100644
--- a/phaul/p_haul_vz.py
+++ b/phaul/p_haul_vz.py
@@ -188,14 +188,49 @@ class p_haul_type:
 			logging.info(proc_output)
 			self._fs_mounted = False
 
-	def get_fs(self, fs_sk=None):
-		deltas = [(os.path.join(self._ct_priv, "root.hdd", "root.hds"), fs_sk)]
+	def get_fs(self, fdfs=None):
+		deltas = self.__parse_fdfs_arg(fdfs)
 		return fs_haul_ploop.p_haul_fs(deltas)
 
-	def get_fs_receiver(self, fs_sk=None):
-		deltas = [(os.path.join(self._ct_priv, "root.hdd", "root.hds"), fs_sk)]
+	def get_fs_receiver(self, fdfs=None):
+		deltas = self.__parse_fdfs_arg(fdfs)
 		return fs_haul_ploop.p_haul_fs_receiver(deltas)
 
+	def __parse_fdfs_arg(self, fdfs):
+		"""
+		Parse string containing list of ploop deltas with socket fds
+
+		String contain list of active ploop deltas with corresponding socket
+		file descriptors in format %delta_path1%:%socket_fd1%[,...]. Parse it
+		and return list of tuples.
+		"""
+
+		FDFS_DELTAS_SEPARATOR = ","
+		FDFS_PAIR_SEPARATOR = ":"
+
+		if not fdfs:
+			return []
+
+		deltas = []
+		for delta in fdfs.split(FDFS_DELTAS_SEPARATOR):
+			path, dummy, fd = delta.rpartition(FDFS_PAIR_SEPARATOR)
+			deltas.append((self.__get_ploop_delta_abspath(path), int(fd)))
+
+		return deltas
+
+	def __get_ploop_delta_abspath(self, delta_path):
+		"""
+		Transform delta path to absolute form
+
+		If delta path starts with a slash it is already in absolute form,
+		otherwise it is relative to containers private.
+		"""
+
+		if delta_path.startswith("/"):
+			return delta_path
+		else:
+			return os.path.join(self._ct_priv, delta_path)
+
 	def restored(self, pid):
 		pass
 
diff --git a/phaul/service.py b/phaul/service.py
index 577278e..5a3a380 100644
--- a/phaul/service.py
+++ b/phaul/service.py
@@ -11,9 +11,8 @@ import htype
 
 class phaul_service:
 	def __init__(self, connection):
+		self.connection = connection
 		self.criu_connection = None
-		self._mem_sk = connection.mem_sk
-		self._fs_sk = connection.fs_sk
 		self.img = None
 		self.htype = None
 		self.__fs_receiver = None
@@ -45,11 +44,11 @@ class phaul_service:
 		logging.info("Setting up service side %s", htype_id)
 		self.img = images.phaul_images("rst")
 
-		self.criu_connection = criu_api.criu_conn(self._mem_sk)
+		self.criu_connection = criu_api.criu_conn(self.connection.mem_sk)
 		self.htype = htype.get_dst(htype_id)
 
 		# Create and start fs receiver if current p.haul module provide it
-		self.__fs_receiver = self.htype.get_fs_receiver(self._fs_sk)
+		self.__fs_receiver = self.htype.get_fs_receiver(self.connection.fdfs)
 		if self.__fs_receiver:
 			self.__fs_receiver.start_receive()
 
@@ -79,7 +78,7 @@ class phaul_service:
 		pass
 
 	def rpc_start_accept_images(self, dir_id):
-		self.img.start_accept_images(dir_id, self._mem_sk)
+		self.img.start_accept_images(dir_id, self.connection.mem_sk)
 
 	def rpc_stop_accept_images(self):
 		self.img.stop_accept_images()
-- 
1.7.1



More information about the CRIU mailing list