2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-22 09:58:09 +00:00
criu/lib/py/cli.py
Andrei Vagin 5aa72e7237 py: Reformat everything into pep8 style
As discussed on the mailing list, current .py files formatting does not
conform to the world standard, so we should better reformat it. For this
the yapf tool is used. The command I used was

  yapf -i $(find -name *.py)

Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
2019-09-07 15:59:56 +03:00

415 lines
11 KiB
Python
Executable File

from __future__ import print_function
import argparse
import sys
import json
import os
import pycriu
def inf(opts):
if opts['in']:
return open(opts['in'], 'rb')
else:
return sys.stdin
def outf(opts):
if opts['out']:
return open(opts['out'], 'w+')
else:
return sys.stdout
def dinf(opts, name):
return open(os.path.join(opts['dir'], name))
def decode(opts):
indent = None
try:
img = pycriu.images.load(inf(opts), opts['pretty'], opts['nopl'])
except pycriu.images.MagicException as exc:
print("Unknown magic %#x.\n"\
"Maybe you are feeding me an image with "\
"raw data(i.e. pages.img)?" % exc.magic, file=sys.stderr)
sys.exit(1)
if opts['pretty']:
indent = 4
f = outf(opts)
json.dump(img, f, indent=indent)
if f == sys.stdout:
f.write("\n")
def encode(opts):
img = json.load(inf(opts))
pycriu.images.dump(img, outf(opts))
def info(opts):
infs = pycriu.images.info(inf(opts))
json.dump(infs, sys.stdout, indent=4)
print()
def get_task_id(p, val):
return p[val] if val in p else p['ns_' + val][0]
#
# Explorers
#
class ps_item:
def __init__(self, p, core):
self.pid = get_task_id(p, 'pid')
self.ppid = p['ppid']
self.p = p
self.core = core
self.kids = []
def show_ps(p, opts, depth=0):
print("%7d%7d%7d %s%s" %
(p.pid, get_task_id(p.p, 'pgid'), get_task_id(p.p, 'sid'), ' ' *
(4 * depth), p.core['tc']['comm']))
for kid in p.kids:
show_ps(kid, opts, depth + 1)
def explore_ps(opts):
pss = {}
ps_img = pycriu.images.load(dinf(opts, 'pstree.img'))
for p in ps_img['entries']:
core = pycriu.images.load(
dinf(opts, 'core-%d.img' % get_task_id(p, 'pid')))
ps = ps_item(p, core['entries'][0])
pss[ps.pid] = ps
# Build tree
psr = None
for pid in pss:
p = pss[pid]
if p.ppid == 0:
psr = p
continue
pp = pss[p.ppid]
pp.kids.append(p)
print("%7s%7s%7s %s" % ('PID', 'PGID', 'SID', 'COMM'))
show_ps(psr, opts)
files_img = None
def ftype_find_in_files(opts, ft, fid):
global files_img
if files_img is None:
try:
files_img = pycriu.images.load(dinf(opts, "files.img"))['entries']
except:
files_img = []
if len(files_img) == 0:
return None
for f in files_img:
if f['id'] == fid:
return f
return None
def ftype_find_in_image(opts, ft, fid, img):
f = ftype_find_in_files(opts, ft, fid)
if f:
return f[ft['field']]
if ft['img'] == None:
ft['img'] = pycriu.images.load(dinf(opts, img))['entries']
for f in ft['img']:
if f['id'] == fid:
return f
return None
def ftype_reg(opts, ft, fid):
rf = ftype_find_in_image(opts, ft, fid, 'reg-files.img')
return rf and rf['name'] or 'unknown path'
def ftype_pipe(opts, ft, fid):
p = ftype_find_in_image(opts, ft, fid, 'pipes.img')
return p and 'pipe[%d]' % p['pipe_id'] or 'pipe[?]'
def ftype_unix(opts, ft, fid):
ux = ftype_find_in_image(opts, ft, fid, 'unixsk.img')
if not ux:
return 'unix[?]'
n = ux['name'] and ' %s' % ux['name'] or ''
return 'unix[%d (%d)%s]' % (ux['ino'], ux['peer'], n)
file_types = {
'REG': {
'get': ftype_reg,
'img': None,
'field': 'reg'
},
'PIPE': {
'get': ftype_pipe,
'img': None,
'field': 'pipe'
},
'UNIXSK': {
'get': ftype_unix,
'img': None,
'field': 'usk'
},
}
def ftype_gen(opts, ft, fid):
return '%s.%d' % (ft['typ'], fid)
files_cache = {}
def get_file_str(opts, fd):
key = (fd['type'], fd['id'])
f = files_cache.get(key, None)
if not f:
ft = file_types.get(fd['type'], {'get': ftype_gen, 'typ': fd['type']})
f = ft['get'](opts, ft, fd['id'])
files_cache[key] = f
return f
def explore_fds(opts):
ps_img = pycriu.images.load(dinf(opts, 'pstree.img'))
for p in ps_img['entries']:
pid = get_task_id(p, 'pid')
idi = pycriu.images.load(dinf(opts, 'ids-%s.img' % pid))
fdt = idi['entries'][0]['files_id']
fdi = pycriu.images.load(dinf(opts, 'fdinfo-%d.img' % fdt))
print("%d" % pid)
for fd in fdi['entries']:
print("\t%7d: %s" % (fd['fd'], get_file_str(opts, fd)))
fdi = pycriu.images.load(dinf(opts, 'fs-%d.img' % pid))['entries'][0]
print("\t%7s: %s" %
('cwd', get_file_str(opts, {
'type': 'REG',
'id': fdi['cwd_id']
})))
print("\t%7s: %s" %
('root', get_file_str(opts, {
'type': 'REG',
'id': fdi['root_id']
})))
class vma_id:
def __init__(self):
self.__ids = {}
self.__last = 1
def get(self, iid):
ret = self.__ids.get(iid, None)
if not ret:
ret = self.__last
self.__last += 1
self.__ids[iid] = ret
return ret
def explore_mems(opts):
ps_img = pycriu.images.load(dinf(opts, 'pstree.img'))
vids = vma_id()
for p in ps_img['entries']:
pid = get_task_id(p, 'pid')
mmi = pycriu.images.load(dinf(opts, 'mm-%d.img' % pid))['entries'][0]
print("%d" % pid)
print("\t%-36s %s" % ('exe',
get_file_str(opts, {
'type': 'REG',
'id': mmi['exe_file_id']
})))
for vma in mmi['vmas']:
st = vma['status']
if st & (1 << 10):
fn = ' ' + 'ips[%lx]' % vids.get(vma['shmid'])
elif st & (1 << 8):
fn = ' ' + 'shmem[%lx]' % vids.get(vma['shmid'])
elif st & (1 << 11):
fn = ' ' + 'packet[%lx]' % vids.get(vma['shmid'])
elif st & ((1 << 6) | (1 << 7)):
fn = ' ' + get_file_str(opts, {
'type': 'REG',
'id': vma['shmid']
})
if vma['pgoff']:
fn += ' + %#lx' % vma['pgoff']
if st & (1 << 7):
fn += ' (s)'
elif st & (1 << 1):
fn = ' [stack]'
elif st & (1 << 2):
fn = ' [vsyscall]'
elif st & (1 << 3):
fn = ' [vdso]'
elif vma['flags'] & 0x0100: # growsdown
fn = ' [stack?]'
else:
fn = ''
if not st & (1 << 0):
fn += ' *'
prot = vma['prot'] & 0x1 and 'r' or '-'
prot += vma['prot'] & 0x2 and 'w' or '-'
prot += vma['prot'] & 0x4 and 'x' or '-'
astr = '%08lx-%08lx' % (vma['start'], vma['end'])
print("\t%-36s%s%s" % (astr, prot, fn))
def explore_rss(opts):
ps_img = pycriu.images.load(dinf(opts, 'pstree.img'))
for p in ps_img['entries']:
pid = get_task_id(p, 'pid')
vmas = pycriu.images.load(dinf(opts, 'mm-%d.img' %
pid))['entries'][0]['vmas']
pms = pycriu.images.load(dinf(opts, 'pagemap-%d.img' % pid))['entries']
print("%d" % pid)
vmi = 0
pvmi = -1
for pm in pms[1:]:
pstr = '\t%lx / %-8d' % (pm['vaddr'], pm['nr_pages'])
while vmas[vmi]['end'] <= pm['vaddr']:
vmi += 1
pme = pm['vaddr'] + (pm['nr_pages'] << 12)
vstr = ''
while vmas[vmi]['start'] < pme:
vma = vmas[vmi]
if vmi == pvmi:
vstr += ' ~'
else:
vstr += ' %08lx / %-8d' % (
vma['start'], (vma['end'] - vma['start']) >> 12)
if vma['status'] & ((1 << 6) | (1 << 7)):
vstr += ' ' + get_file_str(opts, {
'type': 'REG',
'id': vma['shmid']
})
pvmi = vmi
vstr += '\n\t%23s' % ''
vmi += 1
vmi -= 1
print('%-24s%s' % (pstr, vstr))
explorers = {
'ps': explore_ps,
'fds': explore_fds,
'mems': explore_mems,
'rss': explore_rss
}
def explore(opts):
explorers[opts['what']](opts)
def main():
desc = 'CRiu Image Tool'
parser = argparse.ArgumentParser(
description=desc, formatter_class=argparse.RawTextHelpFormatter)
subparsers = parser.add_subparsers(
help='Use crit CMD --help for command-specific help')
# Decode
decode_parser = subparsers.add_parser(
'decode', help='convert criu image from binary type to json')
decode_parser.add_argument(
'--pretty',
help=
'Multiline with indents and some numerical fields in field-specific format',
action='store_true')
decode_parser.add_argument(
'-i',
'--in',
help='criu image in binary format to be decoded (stdin by default)')
decode_parser.add_argument(
'-o',
'--out',
help='where to put criu image in json format (stdout by default)')
decode_parser.set_defaults(func=decode, nopl=False)
# Encode
encode_parser = subparsers.add_parser(
'encode', help='convert criu image from json type to binary')
encode_parser.add_argument(
'-i',
'--in',
help='criu image in json format to be encoded (stdin by default)')
encode_parser.add_argument(
'-o',
'--out',
help='where to put criu image in binary format (stdout by default)')
encode_parser.set_defaults(func=encode)
# Info
info_parser = subparsers.add_parser('info', help='show info about image')
info_parser.add_argument("in")
info_parser.set_defaults(func=info)
# Explore
x_parser = subparsers.add_parser('x', help='explore image dir')
x_parser.add_argument('dir')
x_parser.add_argument('what', choices=['ps', 'fds', 'mems', 'rss'])
x_parser.set_defaults(func=explore)
# Show
show_parser = subparsers.add_parser(
'show', help="convert criu image from binary to human-readable json")
show_parser.add_argument("in")
show_parser.add_argument('--nopl',
help='do not show entry payload (if exists)',
action='store_true')
show_parser.set_defaults(func=decode, pretty=True, out=None)
opts = vars(parser.parse_args())
if not opts:
sys.stderr.write(parser.format_usage())
sys.stderr.write("crit: error: too few arguments\n")
sys.exit(1)
opts["func"](opts)
if __name__ == '__main__':
main()