[CRIU] [PATCH 2/7] pycriu: add python package, v3
Pavel Emelyanov
xemul at parallels.com
Tue Dec 2 05:04:56 PST 2014
> 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) $@
Why do we need rpc.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..234bfe9
> --- /dev/null
> +++ b/pycriu/images/.gitignore
> @@ -0,0 +1,4 @@
> +*.pyc
> +*_pb2.py
> +magic.py
> +pb.py
> diff --git a/pycriu/images/Makefile b/pycriu/images/Makefile
> new file mode 100644
> index 0000000..6aa115e
> --- /dev/null
> +++ b/pycriu/images/Makefile
> @@ -0,0 +1,26 @@
> +all: pb.py protobuf magic.py
> +
> +.PHONY: all protobuf clean pb.py
> +
> +proto := $(filter-out $(SRC_DIR)/protobuf/rpc.proto, $(wildcard $(SRC_DIR)/protobuf/*.proto))
> +proto-py-modules := $(foreach m,$(proto),$(subst -,_,$(notdir $(m:.proto=_pb2))))
> +
> +# 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 $^ $@
> +
> +pb.py: protobuf
> + $(Q) echo "# Autogenerated. Do not edit!" > $@
> + $(Q) for m in $(proto-py-modules); do \
> + echo "from $$m import *" >> $@ ;\
> + done
> +
> +clean:
> + $(Q) $(RM) ./*_pb2.py ./*.pyc magic.py pb.py
> diff --git a/pycriu/images/__init__.py b/pycriu/images/__init__.py
> new file mode 100644
> index 0000000..379943b
> --- /dev/null
> +++ b/pycriu/images/__init__.py
> @@ -0,0 +1,3 @@
> +from magic import *
> +from images import *
> +from pb import *
> diff --git a/pycriu/images/images.py b/pycriu/images/images.py
> new file mode 100644
> index 0000000..afcaa87
> --- /dev/null
> +++ b/pycriu/images/images.py
> @@ -0,0 +1,208 @@
> +#!/bin/env python
> +import io
> +import google
> +import struct
> +import os
> +import sys
> +
> +from magic import *
> +from pb import *
> +
> +class _cr_desc:
> + def __init__(self, magic, head, body='', single=False):
I'm not sure the single bit is needed. But what's needed is some
sign that image may have raw data inside. For example:
# ../crit convert --in dump/static/pipe00/6596/1/pipes-data.img
Traceback (most recent call last):
...
File "/usr/lib/python2.7/site-packages/google/protobuf/internal/decoder.py", line 685, in _RaiseInvalidWireType
raise _DecodeError('Tag had invalid wire type.')
google.protobuf.message.DecodeError: Tag had invalid wire type.
That's because crit tries todecode raw pipe data as message.
> + 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 get(self, magic):
> + desc = None
> + for d in self.descs:
> + if d.magic == magic or d.magic_name == magic:
> + desc = d
> + break
Can we utilize python power to search objects in lists/hashes/sets
and not do it by hands?
> + 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):
Let's make this call be ParseFromFile and pass here not
sting, but an object from which we can read().
> + 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)
Why?
> + 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