[CRIU] [PATCH] p.haul: LinuX Containers hauler module

Andrey Vagin avagin at openvz.org
Wed Mar 19 03:15:24 PDT 2014


Known issues:
* It works only in one direction, because the lxc control
  process isn't executed after migration.
* Network isn't supported yet

[root at 40 p.haul]# ./p.haul lxc centos-lxc-4 192.168.122.36
Loading config file from /var/lib/lxc/centos-lxc-4/config
Connecting to target host
Initilized shared FS hauler
Connecting to CRIU service
Preliminary FS migration
Starting iterations
* Iteration 0
        Making directory /var/local/p.haul-fs/rDf7q4/img/1
        Issuing pre-dump command to service
        Pre-dump succeeded
Dumped 2508 pages, 0 skipped
Checking iteration progress:
        > Proceed to next iteration
* Iteration 1
        Making directory /var/local/p.haul-fs/rDf7q4/img/2
        Issuing pre-dump command to service
        Pre-dump succeeded
Dumped 39 pages, 2469 skipped
Checking iteration progress:
        > Small dump
Final dump and restore
        Making directory /var/local/p.haul-fs/rDf7q4/img/3
        Issuing dump command to service
                Notify (network-lock)
Dump complete
Final FS and images sync
Sending images to target
        Pack
        Add htype images
        Save CG for 6212 into /var/local/p.haul-fs/rDf7q4/img/3/lxccg.img
        Copy
        Unpack
Asking target host to restore
Final dump -- 25 pages, 2483 skipped
Removing images
Migration succeeded
           total time is ~3.08 sec
          frozen time is ~2.71 sec ( ['0.08', '0.11', '2.52'] )
         restore time is ~1.83 sec
        img sync time is ~0.31 sec

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 p_haul_lxc.py  | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 p_haul_type.py |   4 +-
 2 files changed, 148 insertions(+), 1 deletion(-)
 create mode 100644 p_haul_lxc.py

diff --git a/p_haul_lxc.py b/p_haul_lxc.py
new file mode 100644
index 0000000..f3edf16
--- /dev/null
+++ b/p_haul_lxc.py
@@ -0,0 +1,145 @@
+#
+# LinuX Containers hauler module
+#
+
+import os
+import shutil
+import p_haul_cgroup
+import p_haul_netifapi as netif
+import p_haul_fsapi as fsapi
+import fs_haul_shared
+import fs_haul_subtree
+from subprocess import Popen, PIPE
+
+name = "lxc"
+lxc_dir = "/var/lib/lxc/"
+lxc_rootfs_dir = "/usr/lib64/lxc/rootfs"
+cg_image_name = "lxccg.img"
+
+class p_haul_type:
+	def __init__(self, name):
+		self._ctname = name
+		#
+		# This list would contain (v_in, v_out, v_br) tuples where
+		# v_in is the name of veth device in CT
+		# v_out is its peer on the host
+		# v_bridge is the bridge to which thie veth is attached
+		#
+		self._veths = []
+		self._cfg = {}
+
+	def __load_ct_config(self):
+		self._cfg = {}
+		print "Loading config file from %s" % self.__ct_config()
+		ifd = open(self.__ct_config())
+		for line in ifd:
+			if not ("=" in line):
+				continue
+			k, v = map(lambda a: a.strip(), line.split("=", 1))
+			self._cfg[k] = v
+		ifd.close()
+
+	def __apply_cg_config(self):
+		print "Applying CT configs"
+		# FIXME -- implement
+		pass
+
+	def id(self):
+		return (name, self._ctname)
+
+	def init_src(self):
+		self._fs_mounted = True
+		self._bridged = True
+		self.__load_ct_config()
+
+	def init_dst(self):
+		self._fs_mounted = False
+		self._bridged = False
+		self.__load_ct_config()
+
+	def root_task_pid(self):
+		pid = -1;
+
+		pd = Popen(["lxc-info", "-n", self._ctname], stdout = PIPE)
+		for l in pd.stdout:
+			if l.startswith("PID:"):
+				pid = int(l.split(":")[1])
+		status = pd.wait()
+		if status:
+			print "lxc info -n %s failed" % self._ctname
+			pid = -1
+		return pid
+
+	def __ct_rootfs(self):
+		return self._cfg['lxc.rootfs']
+
+	def __ct_root(self):
+		return os.path.join(lxc_rootfs_dir, self._ctname)
+
+	def __ct_config(self):
+		return os.path.join(lxc_dir, self._ctname, "config")
+
+	#
+	# Meta-images for OVZ -- container config and info about CGroups
+	#
+	def get_meta_images(self, dir):
+		cg_img = os.path.join(dir, cg_image_name)
+		p_haul_cgroup.dump_hier(self.root_task_pid(), cg_img)
+		cfg_name = self.__ct_config()
+		return [ (cfg_name, "config"),
+			 (cg_img, cg_image_name) ]
+
+	def put_meta_images(self, dir):
+		print "Putting config file into %s" % lxc_dir
+
+		shutil.copy(os.path.join(dir, "config"), self.__ct_config())
+
+		# Keep this name, we'll need one in prepare_ct()
+		self.cg_img = os.path.join(dir, cg_image_name)
+
+	#
+	# Create cgroup hierarchy and put root task into it
+	# Hierarchy is unlimited, we will apply config limitations
+	# in ->restored->__apply_cg_config later
+	#
+	def prepare_ct(self, pid):
+		p_haul_cgroup.restore_hier(pid, self.cg_img)
+
+	def mount(self):
+		nroot = self.__ct_root()
+		print "Mounting CT root to %s" % nroot
+		if not os.access(nroot, os.F_OK):
+			os.makedirs(nroot)
+		os.system("mount --bind %s %s" % (self.__ct_rootfs(), nroot))
+		self._fs_mounted = True
+		return nroot
+
+	def get_fs(self):
+		return fs_haul_shared.p_haul_fs()
+
+	def restored(self, pid):
+		self.__apply_cg_config()
+
+	def net_lock(self):
+		for veth in self._veths:
+			netif.ifdown(veth[1])
+
+	def net_unlock(self):
+		for veth in self._veths:
+			netif.ifup(veth[1])
+			if veth[2] and not self._bridged:
+				netif.bridge_add(veth[1], veth[2])
+
+	def can_migrate_tcp(self):
+		return True
+
+	def umount(self):
+		pass
+
+	def veths(self):
+		#
+		# Caller wants to see list of tuples with [0] being name
+		# in CT and [1] being name on host. Just return existing
+		# tuples, the [2] with bridge name wouldn't hurt
+		#
+		return self._veths
diff --git a/p_haul_type.py b/p_haul_type.py
index 6ed6c76..6ac093d 100644
--- a/p_haul_type.py
+++ b/p_haul_type.py
@@ -6,10 +6,12 @@
 
 import p_haul_ovz
 import p_haul_pid
+import p_haul_lxc
 
 haul_types = {
 	p_haul_ovz.name: p_haul_ovz,
-	p_haul_pid.name: p_haul_pid
+	p_haul_pid.name: p_haul_pid,
+	p_haul_lxc.name: p_haul_lxc,
 }
 
 def __get(id):
-- 
1.8.5.3



More information about the CRIU mailing list