[CRIU] [PATCH 2/7] pycriu: add python package, v2

Ruslan Kuprieiev kupruser at gmail.com
Tue Oct 28 21:02:43 PDT 2014


pycriu is a python package, that, for now, consists
of rpc module and images package. rpc module contains
data structures for interacting with CRIU RPC.
images package contains data structures for criu images,
magic from criu images and criu_image class that has
methods to convert criu image to\from human-readable
format.

v2, enhance pb python modules gen

Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
---
 pycriu/.gitignore         |   3 +
 pycriu/Makefile           |  16 +++
 pycriu/__init__.py        |   2 +
 pycriu/images/.gitignore  |   3 +
 pycriu/images/Makefile    |  19 ++++
 pycriu/images/__init__.py |  53 ++++++++++
 pycriu/images/images.py   | 259 ++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 355 insertions(+)
 create mode 100644 pycriu/.gitignore
 create mode 100644 pycriu/Makefile
 create mode 100644 pycriu/__init__.py
 create mode 100644 pycriu/images/.gitignore
 create mode 100644 pycriu/images/Makefile
 create mode 100644 pycriu/images/__init__.py
 create mode 100644 pycriu/images/images.py

diff --git a/pycriu/.gitignore b/pycriu/.gitignore
new file mode 100644
index 0000000..8d503da
--- /dev/null
+++ b/pycriu/.gitignore
@@ -0,0 +1,3 @@
+*_pb2.py
+*.pyc
+rpc.py
diff --git a/pycriu/Makefile b/pycriu/Makefile
new file mode 100644
index 0000000..135fe1c
--- /dev/null
+++ b/pycriu/Makefile
@@ -0,0 +1,16 @@
+all: images rpc.py
+
+.PHONY: all images clean
+
+images:
+	$(Q) $(MAKE) -C images all
+
+# rpc_pb2.py doesn't depend on any other file, so
+# it is safe to rename it, dropping ugly _pb2 suffix.
+rpc.py:
+	$(Q) protoc -I=$(SRC_DIR)/protobuf/ --python_out=./ $(SRC_DIR)/protobuf/$(@:.py=.proto)
+	$(Q) mv $(@:.py=_pb2.py) $@
+
+clean:
+	$(Q) $(MAKE) -C images clean
+	$(Q) $(RM) rpc.py *.pyc
diff --git a/pycriu/__init__.py b/pycriu/__init__.py
new file mode 100644
index 0000000..5205973
--- /dev/null
+++ b/pycriu/__init__.py
@@ -0,0 +1,2 @@
+import rpc
+import images
diff --git a/pycriu/images/.gitignore b/pycriu/images/.gitignore
new file mode 100644
index 0000000..dc2a959
--- /dev/null
+++ b/pycriu/images/.gitignore
@@ -0,0 +1,3 @@
+*.pyc
+*_pb2.py
+magic.py
diff --git a/pycriu/images/Makefile b/pycriu/images/Makefile
new file mode 100644
index 0000000..6e0a6b9
--- /dev/null
+++ b/pycriu/images/Makefile
@@ -0,0 +1,19 @@
+all: protobuf magic.py
+
+.PHONY: all protobuf clean
+
+proto := $(filter-out $(SRC_DIR)/protobuf/rpc.proto, $(wildcard $(SRC_DIR)/protobuf/*.proto))
+
+# We don't need rpc_pb2.py here, as it is not related to the
+# images.
+# Unfortunately, we can't drop ugly _pb2 suffixes here, because
+# some _pb2 files depend on others _pb2 files.
+protobuf:
+	$(Q) protoc -I=$(SRC_DIR)/protobuf --python_out=./ $(proto)
+
+magic.py: $(SRC_DIR)/scripts/magic-gen.py $(SRC_DIR)/include/magic.h
+	$(E) "  GEN  " $@
+	$(Q) python $^ $@
+
+clean:
+	$(Q) $(RM) ./*_pb2.py ./*.pyc magic.py
diff --git a/pycriu/images/__init__.py b/pycriu/images/__init__.py
new file mode 100644
index 0000000..6ad6d6b
--- /dev/null
+++ b/pycriu/images/__init__.py
@@ -0,0 +1,53 @@
+from images import *
+
+import stats_pb2
+import timer_pb2
+import ipc_sem_pb2
+import core_pb2
+import core_x86_pb2
+import remap_file_path_pb2
+import fsnotify_pb2
+import inventory_pb2
+import tcp_stream_pb2
+import mnt_pb2
+import packet_sock_pb2
+import pipe_data_pb2
+import ipc_var_pb2
+import sa_pb2
+import tun_pb2
+import fown_pb2
+import tty_pb2
+import rlimit_pb2
+import ipc_shm_pb2
+import file_lock_pb2
+import sk_unix_pb2
+import sk_packet_pb2
+import pagemap_pb2
+import pipe_pb2
+import pstree_pb2
+import sk_opts_pb2
+import siginfo_pb2
+import cgroup_pb2
+import fh_pb2
+import ipc_msg_pb2
+import mm_pb2
+import netdev_pb2
+import timerfd_pb2
+import ns_pb2
+import fs_pb2
+import ext_file_pb2
+import signalfd_pb2
+import ipc_desc_pb2
+import fdinfo_pb2
+import fifo_pb2
+import eventpoll_pb2
+import regfile_pb2
+import core_arm_pb2
+import sk_netlink_pb2
+import sk_inet_pb2
+import utsns_pb2
+import core_aarch64_pb2
+import eventfd_pb2
+import creds_pb2
+import vma_pb2
+import ghost_file_pb2
diff --git a/pycriu/images/images.py b/pycriu/images/images.py
new file mode 100644
index 0000000..e45d432
--- /dev/null
+++ b/pycriu/images/images.py
@@ -0,0 +1,259 @@
+#!/bin/env python
+import io
+import google
+import struct
+import os
+import sys
+
+from magic import *
+
+from stats_pb2 import *
+from timer_pb2 import *
+from ipc_sem_pb2 import *
+from core_pb2 import *
+from core_x86_pb2 import *
+from remap_file_path_pb2 import *
+from fsnotify_pb2 import *
+from inventory_pb2 import *
+from tcp_stream_pb2 import *
+from mnt_pb2 import *
+from packet_sock_pb2 import *
+from pipe_data_pb2 import *
+from ipc_var_pb2 import *
+from sa_pb2 import *
+from tun_pb2 import *
+from fown_pb2 import *
+from tty_pb2 import *
+from rlimit_pb2 import *
+from ipc_shm_pb2 import *
+from file_lock_pb2 import *
+from sk_unix_pb2 import *
+from sk_packet_pb2 import *
+from pagemap_pb2 import *
+from pipe_pb2 import *
+from pstree_pb2 import *
+from sk_opts_pb2 import *
+from siginfo_pb2 import *
+from cgroup_pb2 import *
+from fh_pb2 import *
+from ipc_msg_pb2 import *
+from mm_pb2 import *
+from netdev_pb2 import *
+from timerfd_pb2 import *
+from ns_pb2 import *
+from fs_pb2 import *
+from ext_file_pb2 import *
+from signalfd_pb2 import *
+from ipc_desc_pb2 import *
+from fdinfo_pb2 import *
+from fifo_pb2 import *
+from eventpoll_pb2 import *
+from regfile_pb2 import *
+from core_arm_pb2 import *
+from sk_netlink_pb2 import *
+from sk_inet_pb2 import *
+from utsns_pb2 import *
+from core_aarch64_pb2 import *
+from eventfd_pb2 import *
+from creds_pb2 import *
+from vma_pb2 import *
+from ghost_file_pb2 import *
+
+class _cr_desc:
+	def __init__(self, magic, head, body='', single=False):
+		self.magic_name = magic
+		self.magic = eval(magic+"_MAGIC")
+		self.head_name = head
+		self.head = eval(head)
+		if single:
+			self.body_name = ''
+			self.body = lambda : None
+		else:
+			if body == '':
+				body = head
+			self.body_name = body
+			self.body = eval(body)
+
+class criu_image_descs:
+	def __init__(self):
+		self.descs = [
+	_cr_desc('INVENTORY',	'inventory_entry',	single=True),
+	_cr_desc('CORE',	'core_entry',		single=True),
+	_cr_desc('IDS',		'task_kobj_ids_entry',	single=True),
+	_cr_desc('CREDS',	'creds_entry',		single=True),
+	_cr_desc('UTSNS',	'utsns_entry',		single=True),
+	_cr_desc('IPC_VAR',	'ipc_var_entry',	single=True),
+	_cr_desc('FS',		'fs_entry',		single=True),
+	_cr_desc('GHOST_FILE',	'ghost_file_entry',	single=True),
+	_cr_desc('MM',		'mm_entry',		single=True),
+	_cr_desc('CGROUP',	'cgroup_entry',		single=True),
+	_cr_desc('TCP_STREAM',	'tcp_stream_entry',	single=True),
+	_cr_desc('STATS',	'stats_entry',		single=True),
+
+	_cr_desc('PAGEMAP',	'pagemap_head',		body='pagemap_entry'),
+
+	_cr_desc('PSTREE',		'pstree_entry'),
+	_cr_desc('REG_FILES',		'reg_file_entry'),
+	_cr_desc('NS_FILES',		'ns_file_entry'),
+	_cr_desc('EVENTFD_FILE',	'eventfd_file_entry'),
+	_cr_desc('EVENTPOLL_FILE',	'eventpoll_file_entry'),
+	_cr_desc('EVENTPOLL_TFD',	'eventpoll_tfd_entry'),
+	_cr_desc('SIGNALFD',		'signalfd_entry'),
+	_cr_desc('TIMERFD',		'timerfd_entry'),
+	_cr_desc('INOTIFY_FILE',	'inotify_file_entry'),
+	_cr_desc('INOTIFY_WD',		'inotify_wd_entry'),
+	_cr_desc('FANOTIFY_FILE',	'fanotify_file_entry'),
+	_cr_desc('FANOTIFY_MARK',	'fanotify_mark_entry'),
+	_cr_desc('VMAS',		'vma_entry'),
+	_cr_desc('PIPES',		'pipe_entry'),
+	_cr_desc('FIFO',		'fifo_entry'),
+	_cr_desc('SIGACT',		'sa_entry'),
+	_cr_desc('NETLINK_SK',		'netlink_sk_entry'),
+	_cr_desc('REMAP_FPATH',		'remap_file_path_entry'),
+	_cr_desc('MNTS',		'mnt_entry'),
+	_cr_desc('TTY_FILES',		'tty_file_entry'),
+	_cr_desc('TTY_INFO',		'tty_info_entry'),
+	_cr_desc('RLIMIT',		'rlimit_entry'),
+	_cr_desc('TUNFILE',		'tunfile_entry'),
+	_cr_desc('EXT_FILES',		'ext_file_entry'),
+	_cr_desc('IRMAP_CACHE',		'irmap_cache_entry'),
+	_cr_desc('FILE_LOCKS',		'file_lock_entry'),
+	_cr_desc('FDINFO',		'fdinfo_entry'),
+	_cr_desc('UNIXSK',		'unix_sk_entry'),
+	_cr_desc('INETSK',		'inet_sk_entry'),
+	_cr_desc('PACKETSK', 		'packet_sock_entry'),
+	_cr_desc('ITIMERS',		'itimer_entry'),
+	_cr_desc('POSIX_TIMERS',	'posix_timer_entry'),
+	_cr_desc('NETDEV',		'net_device_entry'),
+	_cr_desc('PIPES_DATA',		'pipe_data_entry'),
+	_cr_desc('FIFO_DATA',		'pipe_data_entry'),
+	_cr_desc('SK_QUEUES',		'sk_packet_entry'),
+	_cr_desc('IPCNS_SHM',		'ipc_shm_entry'),
+	_cr_desc('IPCNS_SEM',		'ipc_sem_entry'),
+	_cr_desc('IPCNS_MSG',		'ipc_msg_entry')
+	]
+
+	def get(self, magic):
+		desc = None
+		for d in self.descs:
+			if d.magic == magic or d.magic_name == magic:
+				desc = d
+				break
+		if desc == None:
+			raise Exception("Unknown magic")
+		else:
+			return desc
+
+class criu_image:
+	def __init__(self):
+		self.desc	= None
+		self.msgs	= []
+		self.orig_type	= None
+
+	def ParseFromStringIMG(self, s):
+		s = io.BytesIO(s)
+		magic, = struct.unpack('i', s.read(4))
+		magic = "0x{0:x}".format(magic)
+
+		descs = criu_image_descs()
+		try:
+			self.desc = descs.get(magic)
+		except Exception as e:
+			raise e
+
+		pb = self.desc.head()
+		while pb != None:
+			buf = s.read(4)
+			if buf == '':
+				break
+			size, = struct.unpack('i', buf)
+			pb.ParseFromString(s.read(size))
+			self.msgs.append(pb)
+			pb = self.desc.body()
+
+	def ParseFromStringTXT(self, s):
+		s = io.BytesIO(s)
+		magic = (s.readline())[1:-1]
+
+		descs = criu_image_descs()
+		try:
+			self.desc = descs.get(magic)
+		except Exception as e:
+			raise e
+
+		pb = self.desc.head()
+		while pb != None:
+			buf = s.readline()
+			if buf == '':
+				break
+			if buf[0] != '#':
+				raise Exception('# expected')
+			pb_text = ''
+			while True:
+				buf = s.readline()
+				if buf == '':
+					break
+				if buf[0] == '#':
+					s.seek(-len(buf), 1)
+					break
+				elif buf[0] == '':
+					raise Exception("data expected")
+				else:
+					pb_text += buf
+			google.protobuf.text_format.Merge(pb_text, pb)
+			self.msgs.append(pb)
+			pb = self.desc.body()
+
+	def ParseFromString(self, s):
+		if s[0] == '#':
+			self.orig_type = 'txt'
+			self.ParseFromStringTXT(s)
+		else:
+			self.orig_type = 'img'
+			self.ParseFromStringIMG(s)
+
+	def SerializeToStringIMG(self):
+		s = io.BytesIO('')
+		s.write(struct.pack('i', int(self.desc.magic, 16)))
+
+		for pb in self.msgs:
+			pb_str = pb.SerializeToString()
+			size = len(pb_str)
+			s.write(struct.pack('i', size))
+			s.write(pb_str)
+		s.seek(0)
+		return s.read()
+
+	def SerializeToStringTXT(self, nice=False):
+		s = io.BytesIO('')
+
+		if nice:
+			magic = self.desc.magic_name
+			indent = 4
+		else:
+			magic = self.desc.magic
+			indent = 0
+
+		s.write('#'+magic+'\n')
+
+		index = 0
+		for pb in self.msgs:
+			if nice:
+				if index == 0:
+					pb_name = self.desc.head_name
+				else:
+					pb_name = self.desc.body_name
+			else:
+				pb_name = ''
+
+			s.write('#'+str(index)+' '+pb_name+'\n')
+			google.protobuf.text_format.PrintMessage(pb, s, indent=indent)
+			index += 1
+		s.seek(0)
+		return s.read()
+
+	def SerializeToString(self, nice=False):
+		if self.orig_type == 'img':
+			return self.SerializeToStringTXT(nice=nice)
+		else:
+			return self.SerializeToStringIMG()
-- 
1.9.3



More information about the CRIU mailing list