[CRIU] [PATCH 09/10] crit: add ability to convert to/from json, v2
Ruslan Kuprieiev
kupruser at gmail.com
Tue Nov 4 04:57:44 PST 2014
v2, don't fail if json is not in "nice" format
Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
---
crit | 6 +++-
pycriu/images/images.py | 57 ++++++++++++++++++++++++++++++--
pycriu/images/pb2dict.py | 84 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 144 insertions(+), 3 deletions(-)
create mode 100644 pycriu/images/pb2dict.py
diff --git a/crit b/crit
index 438ef3b..657610a 100755
--- a/crit
+++ b/crit
@@ -20,6 +20,10 @@ def handle_cmdline_opts():
'--format',
choices = ['raw', 'nice'],
help = 'well-formated output (by default: raw for files and nice for stdout)')
+ parser.add_argument('-t',
+ '--type',
+ choices = ['json'],
+ help = 'Type of output file (by default img is converted to txt and vice versa)')
opts = vars(parser.parse_args())
@@ -52,7 +56,7 @@ def convert_img(opts):
# img remembers data type it was parsed from, so
# SerializeToString will return data in type that
# is oposite to the original.
- out_str = img.SerializeToString(nice=nice)
+ out_str = img.SerializeToString(nice=nice, typ=opts['type'])
# If no output file is set -- stdout is used.
if opts['out']:
diff --git a/pycriu/images/images.py b/pycriu/images/images.py
index afcaa87..ee7c9cf 100644
--- a/pycriu/images/images.py
+++ b/pycriu/images/images.py
@@ -4,6 +4,8 @@ import google
import struct
import os
import sys
+import json
+import pb2dict
from magic import *
from pb import *
@@ -153,10 +155,33 @@ class criu_image:
self.msgs.append(pb)
pb = self.desc.body()
+ def ParseFromStringJSON(self, s):
+ img = json.loads(s)
+ magic = img["magic"]
+
+ descs = criu_image_descs()
+ try:
+ self.desc = descs.get(magic)
+ except Exception as e:
+ raise e
+
+ pb = self.desc.head()
+ index = 0
+ while pb != None and img.get(str(index)) != None:
+ entry = img[str(index)]
+ entry.pop("pbtype", None)
+ pb2dict.dict2pb(entry, pb)
+ self.msgs.append(pb)
+ pb = self.desc.body()
+ index += 1
+
def ParseFromString(self, s):
if s[0] == '#':
self.orig_type = 'txt'
self.ParseFromStringTXT(s)
+ elif s[0] == '{':
+ self.orig_type = 'json'
+ self.ParseFromStringJSON(s)
else:
self.orig_type = 'img'
self.ParseFromStringIMG(s)
@@ -201,8 +226,36 @@ class criu_image:
s.seek(0)
return s.read()
- def SerializeToString(self, nice=False):
- if self.orig_type == 'img':
+ def SerializeToStringJSON(self, nice=False):
+ if nice:
+ magic = self.desc.magic_name
+ indent = 4
+ else:
+ magic = self.desc.magic
+ indent = 0
+
+ img = {}
+ img["magic"] = magic
+
+ index = 0
+ for pb in self.msgs:
+ js = pb2dict.pb2dict(pb)
+
+ if nice:
+ if index == 0:
+ js["pbtype"] = self.desc.head_name
+ else:
+ js["pbtype"] = self.desc.body_name
+
+ img[str(index)] = js
+ index += 1
+
+ return json.dumps(img, indent=indent)
+
+ def SerializeToString(self, nice=False, typ=None):
+ if typ == 'json':
+ return self.SerializeToStringJSON(nice=nice)
+ elif self.orig_type == 'img':
return self.SerializeToStringTXT(nice=nice)
else:
return self.SerializeToStringIMG()
diff --git a/pycriu/images/pb2dict.py b/pycriu/images/pb2dict.py
new file mode 100644
index 0000000..b304824
--- /dev/null
+++ b/pycriu/images/pb2dict.py
@@ -0,0 +1,84 @@
+import google
+import io
+
+# pb2dict and dict2pb are using protobuf text format to properly
+# convert protobuf msgs to/from dictionary.
+
+def pb2dict(pb):
+ """
+ Convert protobuf msg to dictionary
+ """
+ pb_text = io.BytesIO('')
+ google.protobuf.text_format.PrintMessage(pb, pb_text)
+ pb_text.seek(0)
+ return _text2dict(pb_text)
+
+def _text2dict(pb_text):
+ """
+ Convert protobuf text format msg to dict
+ """
+ d = {}
+ while True:
+ s = pb_text.readline()
+ s.strip()
+ if s == '' or '}' in s:
+ break
+
+ name, value = s.split()
+ if value == '{':
+ value = _text2dict(pb_text)
+ elif name.endswith(':'):
+ name = name[:-1]
+ else:
+ raise Exception("Unknown format" + s)
+
+ if d.get(name):
+ if not isinstance(d[name], list):
+ d[name] = [d[name]]
+ d[name].append(value)
+ else:
+ d[name] = value
+
+ return d
+
+def dict2pb(d, pb):
+ """
+ Convert dictionary to protobuf msg
+ """
+ pb_text = io.BytesIO('')
+ _dict2text(d, pb_text, 0)
+ pb_text.seek(0)
+ s = pb_text.read()
+ google.protobuf.text_format.Merge(s, pb)
+
+def _write_struct(name, text, indent, inside):
+ """
+ Convert "inside" dict to protobuf text format
+ wrap it inside block named "name" and write
+ it to "text".
+ """
+ text.write(indent*" " + name.encode() + " {\n")
+ _dict2text(inside, text, indent+2)
+ text.write(indent*" " + "}\n")
+
+def _write_field(name, value, text, indent):
+ """
+ Write "name: value" to "text".
+ """
+ text.write(indent*" " + name.encode() + ": " + value.encode() + "\n")
+
+def _dict2text(d, pb_text, indent):
+ """
+ Convert dict to protobuf text format
+ """
+ for name, value in d.iteritems():
+ if isinstance(value, unicode):
+ _write_field(name, value, pb_text, indent)
+ elif isinstance(value, list):
+ for x in value:
+ if isinstance(x, dict):
+ _write_struct(name, pb_text, indent, x)
+ else:
+ _write_field(name, x, pb_text, indent)
+ else:
+ _write_struct(name, pb_text, indent, value)
--
1.9.3
More information about the CRIU
mailing list