[CRIU] [PATCH 4/9] pycriu: add python package

Pavel Emelyanov xemul at parallels.com
Wed Oct 8 09:04:45 PDT 2014


> --- /dev/null
> +++ b/pycriu/images/Makefile
> @@ -0,0 +1,17 @@
> +all: protobuf magic.py
> +
> +.PHONY: all protobuf clean
> +
> +# 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) cp $(SRC_DIR)/protobuf/*_pb2.py ./ ; rm rpc_pb2.py

Wow... Cyrill, can we do it in a nicer way?

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

Can this file be generated like the magic.py is?

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

This part is almost the same as the __init__.py is. Can it be merged?

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

Can we store d-s in a dict and just make dict[magic] here?

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



More information about the CRIU mailing list