2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-22 09:58:09 +00:00

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>
This commit is contained in:
Andrei Vagin 2019-09-07 15:46:22 +03:00
parent 5ff4fcb753
commit 5aa72e7237
28 changed files with 5738 additions and 5167 deletions

View File

@ -54,11 +54,8 @@ status = {
"VMA_AREA_UNSUPP": 1 << 31
}
prot = {
"PROT_READ" : 0x1,
"PROT_WRITE" : 0x2,
"PROT_EXEC" : 0x4
}
prot = {"PROT_READ": 0x1, "PROT_WRITE": 0x2, "PROT_EXEC": 0x4}
class elf_note:
nhdr = None # Elf_Nhdr;
@ -75,6 +72,7 @@ class coredump:
phdrs = [] # Array of Phdrs;
notes = [] # Array of elf_notes;
vmas = [] # Array of BytesIO with memory content;
# FIXME keeping all vmas in memory is a bad idea;
def write(self, f):
@ -146,7 +144,6 @@ class coredump_generator:
else:
return img["entries"]
def __call__(self, imgs_dir):
"""
Parse criu images stored in directory imgs_dir to fill core dumps.
@ -161,7 +158,8 @@ class coredump_generator:
for tid in p['threads']:
self.cores[tid] = self._img_open_and_strip("core", True, tid)
self.mms[pid] = self._img_open_and_strip("mm", True, pid)
self.pagemaps[pid] = self._img_open_and_strip("pagemap", False, pid)
self.pagemaps[pid] = self._img_open_and_strip(
"pagemap", False, pid)
files = self._img_open_and_strip("files", False)
self.reg_files = [x["reg"] for x in files if x["type"] == "REG"]
@ -171,7 +169,6 @@ class coredump_generator:
return self.coredumps
def write(self, coredumps_dir, pid=None):
"""
Write core dumpt to cores_dir directory. Specify pid to choose
@ -298,9 +295,11 @@ class coredump_generator:
prpsinfo.pr_state = 3
# Don't even ask me why it is so, just borrowed from linux
# source and made pr_state match.
prpsinfo.pr_sname = '.' if prpsinfo.pr_state > 5 else "RSDTZW"[prpsinfo.pr_state]
prpsinfo.pr_sname = '.' if prpsinfo.pr_state > 5 else "RSDTZW" [
prpsinfo.pr_state]
prpsinfo.pr_zomb = 1 if prpsinfo.pr_state == 4 else 0
prpsinfo.pr_nice = core["thread_core"]["sched_prio"] if "sched_prio" in core["thread_core"] else 0
prpsinfo.pr_nice = core["thread_core"][
"sched_prio"] if "sched_prio" in core["thread_core"] else 0
prpsinfo.pr_flag = core["tc"]["flags"]
prpsinfo.pr_uid = core["thread_core"]["creds"]["uid"]
prpsinfo.pr_gid = core["thread_core"]["creds"]["gid"]
@ -399,8 +398,10 @@ class coredump_generator:
fpregset.rdp = regs["rdp"]
fpregset.mxcsr = regs["mxcsr"]
fpregset.mxcr_mask = regs["mxcsr_mask"]
fpregset.st_space = (ctypes.c_uint * len(regs["st_space"]))(*regs["st_space"])
fpregset.xmm_space = (ctypes.c_uint * len(regs["xmm_space"]))(*regs["xmm_space"])
fpregset.st_space = (ctypes.c_uint * len(regs["st_space"]))(
*regs["st_space"])
fpregset.xmm_space = (ctypes.c_uint * len(regs["xmm_space"]))(
*regs["xmm_space"])
#fpregset.padding = regs["padding"] unused
nhdr = elf.Elf64_Nhdr()
@ -433,12 +434,16 @@ class coredump_generator:
data.i387.rdp = fpregs["rdp"]
data.i387.mxcsr = fpregs["mxcsr"]
data.i387.mxcsr_mask = fpregs["mxcsr_mask"]
data.i387.st_space = (ctypes.c_uint * len(fpregs["st_space"]))(*fpregs["st_space"])
data.i387.xmm_space = (ctypes.c_uint * len(fpregs["xmm_space"]))(*fpregs["xmm_space"])
data.i387.st_space = (ctypes.c_uint * len(fpregs["st_space"]))(
*fpregs["st_space"])
data.i387.xmm_space = (ctypes.c_uint * len(fpregs["xmm_space"]))(
*fpregs["xmm_space"])
if "xsave" in fpregs:
data.xsave_hdr.xstate_bv = fpregs["xsave"]["xstate_bv"]
data.ymmh.ymmh_space = (ctypes.c_uint * len(fpregs["xsave"]["ymmh_space"]))(*fpregs["xsave"]["ymmh_space"])
data.ymmh.ymmh_space = (ctypes.c_uint *
len(fpregs["xsave"]["ymmh_space"]))(
*fpregs["xsave"]["ymmh_space"])
nhdr = elf.Elf64_Nhdr()
nhdr.n_namesz = 6
@ -551,7 +556,8 @@ class coredump_generator:
fields.append(("end" + str(i), ctypes.c_long))
fields.append(("file_ofs" + str(i), ctypes.c_long))
for i in range(len(infos)):
fields.append(("name"+str(i), ctypes.c_char*(len(infos[i].name)+1)))
fields.append(
("name" + str(i), ctypes.c_char * (len(infos[i].name) + 1)))
class elf_files(ctypes.Structure):
_fields_ = fields
@ -639,7 +645,8 @@ class coredump_generator:
ppid = self.pstree[pid]["ppid"]
return self._get_page(ppid, page_no)
else:
with open(self._imgs_dir+"/"+"pages-"+str(pages_id)+".img") as f:
with open(self._imgs_dir + "/" + "pages-" + str(pages_id) +
".img") as f:
f.seek(off * PAGESIZE)
return f.read(PAGESIZE)

View File

@ -16,13 +16,16 @@ EI_MAG0 = 0 # #define EI_MAG0 0 /* File identification b
ELFMAG0 = 0x7f # #define ELFMAG0 0x7f /* Magic number byte 0 */
EI_MAG1 = 1 # #define EI_MAG1 1 /* File identification byte 1 index */
ELFMAG1 = ord('E') # #define ELFMAG1 'E' /* Magic number byte 1 */
ELFMAG1 = ord(
'E') # #define ELFMAG1 'E' /* Magic number byte 1 */
EI_MAG2 = 2 # #define EI_MAG2 2 /* File identification byte 2 index */
ELFMAG2 = ord('L') # #define ELFMAG2 'L' /* Magic number byte 2 */
ELFMAG2 = ord(
'L') # #define ELFMAG2 'L' /* Magic number byte 2 */
EI_MAG3 = 3 # #define EI_MAG3 3 /* File identification byte 3 index */
ELFMAG3 = ord('F') # #define ELFMAG3 'F' /* Magic number byte 3 */
ELFMAG3 = ord(
'F') # #define ELFMAG3 'F' /* Magic number byte 3 */
EI_CLASS = 4 # #define EI_CLASS 4 /* File class byte index */
@ -43,9 +46,11 @@ EM_X86_64 = 62 # #define EM_X86_64 62 /* AMD x86-64 architec
# Legal values for e_version (version).
EV_CURRENT = 1 # #define EV_CURRENT 1 /* Current version */
class Elf64_Ehdr(ctypes.Structure): # typedef struct
_fields_ = [ # {
("e_ident", ctypes.c_ubyte*EI_NIDENT), # unsigned char e_ident[EI_NIDENT];
("e_ident",
ctypes.c_ubyte * EI_NIDENT), # unsigned char e_ident[EI_NIDENT];
("e_type", Elf64_Half), # Elf64_Half e_type;
("e_machine", Elf64_Half), # Elf64_Half e_machine;
("e_version", Elf64_Word), # Elf64_Word e_version;
@ -73,6 +78,7 @@ PF_X = 1 # #define PF_X (1 << 0) /* Segment is executable */
PF_W = 1 << 1 # #define PF_W (1 << 1) /* Segment is writable */
PF_R = 1 << 2 # #define PF_R (1 << 2) /* Segment is readable */
class Elf64_Phdr(ctypes.Structure): # typedef struct
_fields_ = [ # {
("p_type", Elf64_Word), # Elf64_Word p_type;
@ -88,14 +94,15 @@ class Elf64_Phdr(ctypes.Structure): # typedef struct
# Elf64_auxv_t related constants.
class _Elf64_auxv_t_U(ctypes.Union):
_fields_ = [
("a_val", ctypes.c_uint64)
]
_fields_ = [("a_val", ctypes.c_uint64)]
class Elf64_auxv_t(ctypes.Structure): # typedef struct
_fields_ = [ # {
("a_type", ctypes.c_uint64), # uint64_t a_type; /* Entry type */
("a_type",
ctypes.c_uint64), # uint64_t a_type; /* Entry type */
("a_un", _Elf64_auxv_t_U) # union
# {
# uint64_t a_val; /* Integer value */
@ -118,101 +125,178 @@ NT_FILE = 0x46494c45 # #define NT_FILE 0x46494c45 /* Contains info
# files */
NT_X86_XSTATE = 0x202 # #define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
class Elf64_Nhdr(ctypes.Structure): # typedef struct
_fields_ = [ # {
("n_namesz", Elf64_Word), # Elf64_Word n_namesz; /* Length of the note's name. */
("n_descsz", Elf64_Word), # Elf64_Word n_descsz; /* Length of the note's descriptor. */
("n_type", Elf64_Word), # Elf64_Word n_type; /* Type of the note. */
(
"n_namesz", Elf64_Word
), # Elf64_Word n_namesz; /* Length of the note's name. */
(
"n_descsz", Elf64_Word
), # Elf64_Word n_descsz; /* Length of the note's descriptor. */
("n_type", Elf64_Word
), # Elf64_Word n_type; /* Type of the note. */
] # } Elf64_Nhdr;
# Elf64_Shdr related constants.
class Elf64_Shdr(ctypes.Structure): # typedef struct
_fields_ = [ # {
("sh_name", Elf64_Word), # Elf64_Word sh_name; /* Section name (string tbl index) */
("sh_type", Elf64_Word), # Elf64_Word sh_type; /* Section type */
("sh_flags", Elf64_Xword), # Elf64_Xword sh_flags; /* Section flags */
("sh_addr", Elf64_Addr), # Elf64_Addr sh_addr; /* Section virtual addr at execution */
("sh_offset", Elf64_Off), # Elf64_Off sh_offset; /* Section file offset */
("sh_size", Elf64_Xword), # Elf64_Xword sh_size; /* Section size in bytes */
("sh_link", Elf64_Word), # Elf64_Word sh_link; /* Link to another section */
("sh_info", Elf64_Word), # Elf64_Word sh_info; /* Additional section information */
("sh_addralign",Elf64_Xword), # Elf64_Xword sh_addralign; /* Section alignment */
("sh_entsize", Elf64_Xword) # Elf64_Xword sh_entsize; /* Entry size if section holds table */
(
"sh_name", Elf64_Word
), # Elf64_Word sh_name; /* Section name (string tbl index) */
("sh_type", Elf64_Word
), # Elf64_Word sh_type; /* Section type */
("sh_flags", Elf64_Xword
), # Elf64_Xword sh_flags; /* Section flags */
(
"sh_addr", Elf64_Addr
), # Elf64_Addr sh_addr; /* Section virtual addr at execution */
(
"sh_offset", Elf64_Off
), # Elf64_Off sh_offset; /* Section file offset */
(
"sh_size", Elf64_Xword
), # Elf64_Xword sh_size; /* Section size in bytes */
(
"sh_link", Elf64_Word
), # Elf64_Word sh_link; /* Link to another section */
(
"sh_info", Elf64_Word
), # Elf64_Word sh_info; /* Additional section information */
("sh_addralign", Elf64_Xword
), # Elf64_Xword sh_addralign; /* Section alignment */
(
"sh_entsize", Elf64_Xword
) # Elf64_Xword sh_entsize; /* Entry size if section holds table */
] # } Elf64_Shdr;
# elf_prstatus related constants.
# Signal info.
class elf_siginfo(ctypes.Structure): # struct elf_siginfo
_fields_ = [ # {
("si_signo", ctypes.c_int), # int si_signo; /* Signal number. */
("si_code", ctypes.c_int), # int si_code; /* Extra code. */
("si_errno", ctypes.c_int) # int si_errno; /* Errno. */
("si_signo", ctypes.c_int
), # int si_signo; /* Signal number. */
("si_code", ctypes.c_int
), # int si_code; /* Extra code. */
("si_errno", ctypes.c_int
) # int si_errno; /* Errno. */
] # };
# A time value that is accurate to the nearest
# microsecond but also has a range of years.
class timeval(ctypes.Structure): # struct timeval
_fields_ = [ # {
("tv_sec", ctypes.c_long), # __time_t tv_sec; /* Seconds. */
("tv_usec", ctypes.c_long) # __suseconds_t tv_usec; /* Microseconds. */
("tv_sec",
ctypes.c_long), # __time_t tv_sec; /* Seconds. */
("tv_usec", ctypes.c_long
) # __suseconds_t tv_usec; /* Microseconds. */
] # };
class user_regs_struct(ctypes.Structure): # struct user_regs_struct
_fields_ = [ # {
("r15", ctypes.c_ulonglong), # __extension__ unsigned long long int r15;
("r14", ctypes.c_ulonglong), # __extension__ unsigned long long int r14;
("r13", ctypes.c_ulonglong), # __extension__ unsigned long long int r13;
("r12", ctypes.c_ulonglong), # __extension__ unsigned long long int r12;
("rbp", ctypes.c_ulonglong), # __extension__ unsigned long long int rbp;
("rbx", ctypes.c_ulonglong), # __extension__ unsigned long long int rbx;
("r11", ctypes.c_ulonglong), # __extension__ unsigned long long int r11;
("r10", ctypes.c_ulonglong), # __extension__ unsigned long long int r10;
("r9", ctypes.c_ulonglong), # __extension__ unsigned long long int r9;
("r8", ctypes.c_ulonglong), # __extension__ unsigned long long int r8;
("rax", ctypes.c_ulonglong), # __extension__ unsigned long long int rax;
("rcx", ctypes.c_ulonglong), # __extension__ unsigned long long int rcx;
("rdx", ctypes.c_ulonglong), # __extension__ unsigned long long int rdx;
("rsi", ctypes.c_ulonglong), # __extension__ unsigned long long int rsi;
("rdi", ctypes.c_ulonglong), # __extension__ unsigned long long int rdi;
("orig_rax", ctypes.c_ulonglong), # __extension__ unsigned long long int orig_rax;
("rip", ctypes.c_ulonglong), # __extension__ unsigned long long int rip;
("cs", ctypes.c_ulonglong), # __extension__ unsigned long long int cs;
("eflags", ctypes.c_ulonglong), # __extension__ unsigned long long int eflags;
("rsp", ctypes.c_ulonglong), # __extension__ unsigned long long int rsp;
("ss", ctypes.c_ulonglong), # __extension__ unsigned long long int ss;
("fs_base", ctypes.c_ulonglong), # __extension__ unsigned long long int fs_base;
("gs_base", ctypes.c_ulonglong), # __extension__ unsigned long long int gs_base;
("ds", ctypes.c_ulonglong), # __extension__ unsigned long long int ds;
("es", ctypes.c_ulonglong), # __extension__ unsigned long long int es;
("fs", ctypes.c_ulonglong), # __extension__ unsigned long long int fs;
("gs", ctypes.c_ulonglong) # __extension__ unsigned long long int gs;
("r15",
ctypes.c_ulonglong), # __extension__ unsigned long long int r15;
("r14",
ctypes.c_ulonglong), # __extension__ unsigned long long int r14;
("r13",
ctypes.c_ulonglong), # __extension__ unsigned long long int r13;
("r12",
ctypes.c_ulonglong), # __extension__ unsigned long long int r12;
("rbp",
ctypes.c_ulonglong), # __extension__ unsigned long long int rbp;
("rbx",
ctypes.c_ulonglong), # __extension__ unsigned long long int rbx;
("r11",
ctypes.c_ulonglong), # __extension__ unsigned long long int r11;
("r10",
ctypes.c_ulonglong), # __extension__ unsigned long long int r10;
("r9",
ctypes.c_ulonglong), # __extension__ unsigned long long int r9;
("r8",
ctypes.c_ulonglong), # __extension__ unsigned long long int r8;
("rax",
ctypes.c_ulonglong), # __extension__ unsigned long long int rax;
("rcx",
ctypes.c_ulonglong), # __extension__ unsigned long long int rcx;
("rdx",
ctypes.c_ulonglong), # __extension__ unsigned long long int rdx;
("rsi",
ctypes.c_ulonglong), # __extension__ unsigned long long int rsi;
("rdi",
ctypes.c_ulonglong), # __extension__ unsigned long long int rdi;
("orig_rax", ctypes.c_ulonglong
), # __extension__ unsigned long long int orig_rax;
("rip",
ctypes.c_ulonglong), # __extension__ unsigned long long int rip;
("cs",
ctypes.c_ulonglong), # __extension__ unsigned long long int cs;
("eflags",
ctypes.c_ulonglong), # __extension__ unsigned long long int eflags;
("rsp",
ctypes.c_ulonglong), # __extension__ unsigned long long int rsp;
("ss",
ctypes.c_ulonglong), # __extension__ unsigned long long int ss;
("fs_base", ctypes.c_ulonglong
), # __extension__ unsigned long long int fs_base;
("gs_base", ctypes.c_ulonglong
), # __extension__ unsigned long long int gs_base;
("ds",
ctypes.c_ulonglong), # __extension__ unsigned long long int ds;
("es",
ctypes.c_ulonglong), # __extension__ unsigned long long int es;
("fs",
ctypes.c_ulonglong), # __extension__ unsigned long long int fs;
("gs", ctypes.c_ulonglong
) # __extension__ unsigned long long int gs;
] # };
#elf_greg_t = ctypes.c_ulonglong
#ELF_NGREG = ctypes.sizeof(user_regs_struct)/ctypes.sizeof(elf_greg_t)
#elf_gregset_t = elf_greg_t*ELF_NGREG
elf_gregset_t = user_regs_struct
class elf_prstatus(ctypes.Structure): # struct elf_prstatus
_fields_ = [ # {
("pr_info", elf_siginfo), # struct elf_siginfo pr_info; /* Info associated with signal. */
("pr_cursig", ctypes.c_short), # short int pr_cursig; /* Current signal. */
("pr_sigpend", ctypes.c_ulong), # unsigned long int pr_sigpend; /* Set of pending signals. */
("pr_sighold", ctypes.c_ulong), # unsigned long int pr_sighold; /* Set of held signals. */
(
"pr_info", elf_siginfo
), # struct elf_siginfo pr_info; /* Info associated with signal. */
("pr_cursig", ctypes.c_short
), # short int pr_cursig; /* Current signal. */
(
"pr_sigpend", ctypes.c_ulong
), # unsigned long int pr_sigpend; /* Set of pending signals. */
(
"pr_sighold", ctypes.c_ulong
), # unsigned long int pr_sighold; /* Set of held signals. */
("pr_pid", ctypes.c_int), # __pid_t pr_pid;
("pr_ppid", ctypes.c_int), # __pid_t pr_ppid;
("pr_pgrp", ctypes.c_int), # __pid_t pr_pgrp;
("pr_sid", ctypes.c_int), # __pid_t pr_sid;
("pr_utime", timeval), # struct timeval pr_utime; /* User time. */
("pr_stime", timeval), # struct timeval pr_stime; /* System time. */
("pr_cutime", timeval), # struct timeval pr_cutime; /* Cumulative user time. */
("pr_cstime", timeval), # struct timeval pr_cstime; /* Cumulative system time. */
("pr_reg", elf_gregset_t), # elf_gregset_t pr_reg; /* GP registers. */
("pr_fpvalid", ctypes.c_int) # int pr_fpvalid; /* True if math copro being used. */
("pr_utime",
timeval), # struct timeval pr_utime; /* User time. */
("pr_stime", timeval
), # struct timeval pr_stime; /* System time. */
(
"pr_cutime", timeval
), # struct timeval pr_cutime; /* Cumulative user time. */
(
"pr_cstime", timeval
), # struct timeval pr_cstime; /* Cumulative system time. */
("pr_reg", elf_gregset_t
), # elf_gregset_t pr_reg; /* GP registers. */
(
"pr_fpvalid", ctypes.c_int
) # int pr_fpvalid; /* True if math copro being used. */
] # };
@ -220,13 +304,21 @@ class elf_prstatus(ctypes.Structure): # struct elf_prstatus
ELF_PRARGSZ = 80 # #define ELF_PRARGSZ (80) /* Number of chars for args. */
class elf_prpsinfo(ctypes.Structure): # struct elf_prpsinfo
_fields_ = [ # {
("pr_state", ctypes.c_byte), # char pr_state; /* Numeric process state. */
("pr_sname", ctypes.c_char), # char pr_sname; /* Char for pr_state. */
("pr_zomb", ctypes.c_byte), # char pr_zomb; /* Zombie. */
("pr_nice", ctypes.c_byte), # char pr_nice; /* Nice val. */
("pr_flag", ctypes.c_ulong), # unsigned long int pr_flag; /* Flags. */
(
"pr_state", ctypes.c_byte
), # char pr_state; /* Numeric process state. */
(
"pr_sname", ctypes.c_char
), # char pr_sname; /* Char for pr_state. */
("pr_zomb", ctypes.c_byte
), # char pr_zomb; /* Zombie. */
("pr_nice", ctypes.c_byte
), # char pr_nice; /* Nice val. */
("pr_flag", ctypes.c_ulong
), # unsigned long int pr_flag; /* Flags. */
# #if __WORDSIZE == 32
# unsigned short int pr_uid;
# unsigned short int pr_gid;
@ -239,8 +331,12 @@ class elf_prpsinfo(ctypes.Structure): # struct elf_prpsinfo
("pr_pgrp", ctypes.c_int),
("pr_sid", ctypes.c_int),
# /* Lots missing */
("pr_fname", ctypes.c_char*16), # char pr_fname[16]; /* Filename of executable. */
("pr_psargs", ctypes.c_char*ELF_PRARGSZ) # char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */
(
"pr_fname", ctypes.c_char * 16
), # char pr_fname[16]; /* Filename of executable. */
(
"pr_psargs", ctypes.c_char * ELF_PRARGSZ
) # char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */
] # };
@ -250,33 +346,42 @@ class user_fpregs_struct(ctypes.Structure): # struct user_fpregs_struct
("swd", ctypes.c_ushort), # unsigned short int swd;
("ftw", ctypes.c_ushort), # unsigned short int ftw;
("fop", ctypes.c_ushort), # unsigned short int fop;
("rip", ctypes.c_ulonglong), # __extension__ unsigned long long int rip;
("rdp", ctypes.c_ulonglong), # __extension__ unsigned long long int rdp;
("rip",
ctypes.c_ulonglong), # __extension__ unsigned long long int rip;
("rdp",
ctypes.c_ulonglong), # __extension__ unsigned long long int rdp;
("mxcsr", ctypes.c_uint), # unsigned int mxcsr;
("mxcr_mask", ctypes.c_uint), # unsigned int mxcr_mask;
("st_space", ctypes.c_uint*32), # unsigned int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
("xmm_space", ctypes.c_uint*64), # unsigned int xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */
("padding", ctypes.c_uint*24), # unsigned int padding[24];
(
"st_space", ctypes.c_uint * 32
), # unsigned int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
(
"xmm_space", ctypes.c_uint * 64
), # unsigned int xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */
("padding",
ctypes.c_uint * 24), # unsigned int padding[24];
] # };
elf_fpregset_t = user_fpregs_struct
# siginfo_t related constants.
_SI_MAX_SIZE = 128
_SI_PAD_SIZE = (_SI_MAX_SIZE / ctypes.sizeof(ctypes.c_int)) - 4
# /* kill(). */
class _siginfo_t_U_kill(ctypes.Structure): # struct
_fields_ = [ # {
("si_pid", ctypes.c_int), # __pid_t si_pid; /* Sending process ID. */
("si_uid", ctypes.c_uint) # __uid_t si_uid; /* Real user ID of sending process. */
("si_pid", ctypes.c_int
), # __pid_t si_pid; /* Sending process ID. */
(
"si_uid", ctypes.c_uint
) # __uid_t si_uid; /* Real user ID of sending process. */
] # } _kill;
# Type for data associated with a signal.
class sigval_t(ctypes.Union): # typedef union sigval
_fields_ = [ # {
@ -284,45 +389,63 @@ class sigval_t(ctypes.Union): # typedef union sigval
("sical_ptr", ctypes.c_void_p), # void *sival_ptr;
] # } sigval_t;
# /* POSIX.1b timers. */
class _siginfo_t_U_timer(ctypes.Structure): # struct
_fields_ = [ # {
("si_tid", ctypes.c_int), # int si_tid; /* Timer ID. */
("si_overrun", ctypes.c_int), # int si_overrun; /* Overrun count. */
("si_sigval", sigval_t) # sigval_t si_sigval; /* Signal value. */
("si_tid",
ctypes.c_int), # int si_tid; /* Timer ID. */
("si_overrun", ctypes.c_int
), # int si_overrun; /* Overrun count. */
("si_sigval", sigval_t
) # sigval_t si_sigval; /* Signal value. */
] # } _timer;
# /* POSIX.1b signals. */
class _siginfo_t_U_rt(ctypes.Structure): # struct
_fields_ = [ # {
("si_pid", ctypes.c_int), # __pid_t si_pid; /* Sending process ID. */
("si_uid", ctypes.c_uint), # __uid_t si_uid; /* Real user ID of sending process. */
("si_sigval", sigval_t) # sigval_t si_sigval; /* Signal value. */
("si_pid", ctypes.c_int
), # __pid_t si_pid; /* Sending process ID. */
(
"si_uid", ctypes.c_uint
), # __uid_t si_uid; /* Real user ID of sending process. */
("si_sigval", sigval_t
) # sigval_t si_sigval; /* Signal value. */
] # } _rt;
# /* SIGCHLD. */
class _siginfo_t_U_sigchld(ctypes.Structure): # struct
_fields_ = [ # {
("si_pid", ctypes.c_int), # __pid_t si_pid; /* Which child. */
("si_uid", ctypes.c_uint), # __uid_t si_uid; /* Real user ID of sending process. */
("si_status", ctypes.c_int), # int si_status; /* Exit value or signal. */
("si_pid",
ctypes.c_int), # __pid_t si_pid; /* Which child. */
(
"si_uid", ctypes.c_uint
), # __uid_t si_uid; /* Real user ID of sending process. */
("si_status", ctypes.c_int
), # int si_status; /* Exit value or signal. */
("si_utime", ctypes.c_long), # __sigchld_clock_t si_utime;
("si_stime", ctypes.c_long) # __sigchld_clock_t si_stime;
] # } _sigchld;
# /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */
class _siginfo_t_U_sigfault(ctypes.Structure): # struct
_fields_ = [ # {
("si_addr", ctypes.c_void_p), # void *si_addr; /* Faulting insn/memory ref. */
("si_addr_lsb", ctypes.c_short) # short int si_addr_lsb; /* Valid LSB of the reported address. */
("si_addr", ctypes.c_void_p
), # void *si_addr; /* Faulting insn/memory ref. */
(
"si_addr_lsb", ctypes.c_short
) # short int si_addr_lsb; /* Valid LSB of the reported address. */
] # } _sigfault;
# /* SIGPOLL. */
class _siginfo_t_U_sigpoll(ctypes.Structure): # struct
_fields_ = [ # {
("si_band", ctypes.c_long), # long int si_band; /* Band event for SIGPOLL. */
("si_band", ctypes.c_long
), # long int si_band; /* Band event for SIGPOLL. */
("si_fd", ctypes.c_int) # int si_fd;
] # } _sigpoll;
@ -330,15 +453,20 @@ class _siginfo_t_U_sigpoll(ctypes.Structure): # struct
# /* SIGSYS. */
class _siginfo_t_U_sigsys(ctypes.Structure): # struct
_fields_ = [ # {
("_call_addr", ctypes.c_void_p), # void *_call_addr; /* Calling user insn. */
("_syscall", ctypes.c_int), # int _syscall; /* Triggering system call number. */
("_arch", ctypes.c_uint) # unsigned int _arch; /* AUDIT_ARCH_* of syscall. */
("_call_addr", ctypes.c_void_p
), # void *_call_addr; /* Calling user insn. */
(
"_syscall", ctypes.c_int
), # int _syscall; /* Triggering system call number. */
("_arch", ctypes.c_uint
) # unsigned int _arch; /* AUDIT_ARCH_* of syscall. */
] # } _sigsys;
class _siginfo_t_U(ctypes.Union): # union
_fields_ = [ # {
("_pad", ctypes.c_int*_SI_PAD_SIZE), # int _pad[__SI_PAD_SIZE];
("_pad",
ctypes.c_int * _SI_PAD_SIZE), # int _pad[__SI_PAD_SIZE];
#
# /* kill(). */
("_kill", _siginfo_t_U_kill), # struct
@ -396,12 +524,17 @@ class _siginfo_t_U(ctypes.Union): # union
# } _sigsys;
] # } _sifields;
class siginfo_t(ctypes.Structure): # typedef struct
_fields_ = [ # {
("si_signo", ctypes.c_int), # int si_signo; /* Signal number. */
("si_errno", ctypes.c_int), # int si_errno; /* If non-zero, an errno value associated with
("si_signo", ctypes.c_int
), # int si_signo; /* Signal number. */
(
"si_errno", ctypes.c_int
), # int si_errno; /* If non-zero, an errno value associated with
# this signal, as defined in <errno.h>. */
("si_code", ctypes.c_int), # int si_code; /* Signal code. */
("si_code", ctypes.c_int
), # int si_code; /* Signal code. */
#
("_sifields", _siginfo_t_U) # union
# {
@ -467,30 +600,46 @@ class siginfo_t(ctypes.Structure): # typedef struct
# xsave related.
class ymmh_struct(ctypes.Structure): # struct ymmh_struct {
_fields_ = [
("ymmh_space", 64*ctypes.c_uint) # u32 ymmh_space[64];
_fields_ = [("ymmh_space", 64 * ctypes.c_uint
) # u32 ymmh_space[64];
] # } __packed;
class xsave_hdr_struct(ctypes.Structure): # struct xsave_hdr_struct {
_fields_ = [
("xstate_bv", ctypes.c_ulonglong), # u64 xstate_bv;
("reserved1", ctypes.c_ulonglong*2), # u64 reserved1[2];
("reserved2", ctypes.c_ulonglong*5) # u64 reserved2[5];
("xstate_bv", ctypes.c_ulonglong
), # u64 xstate_bv;
("reserved1", ctypes.c_ulonglong *
2), # u64 reserved1[2];
("reserved2", ctypes.c_ulonglong * 5
) # u64 reserved2[5];
] # } __packed;
class i387_fxsave_struct(ctypes.Structure): # struct i387_fxsave_struct {
_fields_ = [
("cwd", ctypes.c_ushort), # u16 cwd; /* Control Word */
("swd", ctypes.c_ushort), # u16 swd; /* Status Word */
("twd", ctypes.c_ushort), # u16 twd; /* Tag Word */
("fop", ctypes.c_ushort), # u16 fop; /* Last Instruction Opcode */
(
"cwd", ctypes.c_ushort
), # u16 cwd; /* Control Word */
(
"swd", ctypes.c_ushort
), # u16 swd; /* Status Word */
(
"twd", ctypes.c_ushort
), # u16 twd; /* Tag Word */
(
"fop", ctypes.c_ushort
), # u16 fop; /* Last Instruction Opcode */
# union {
# struct {
("rip", ctypes.c_ulonglong), # u64 rip; /* Instruction Pointer */
("rdp", ctypes.c_ulonglong), # u64 rdp; /* Data Pointer */
(
"rip", ctypes.c_ulonglong
), # u64 rip; /* Instruction Pointer */
(
"rdp", ctypes.c_ulonglong
), # u64 rdp; /* Data Pointer */
# };
# struct {
# u32 fip; /* FPU IP Offset */
@ -499,19 +648,27 @@ class i387_fxsave_struct(ctypes.Structure): # struct i387_fxsave_struct {
# u32 fos; /* FPU Operand Selector */
# };
# };
("mxcsr", ctypes.c_uint), # u32 mxcsr; /* MXCSR Register State */
("mxcsr_mask", ctypes.c_uint), # u32 mxcsr_mask; /* MXCSR Mask */
(
"mxcsr", ctypes.c_uint
), # u32 mxcsr; /* MXCSR Register State */
(
"mxcsr_mask", ctypes.c_uint
), # u32 mxcsr_mask; /* MXCSR Mask */
#
# /* 8*16 bytes for each FP-reg = 128 bytes */
("st_space", ctypes.c_uint*32), # u32 st_space[32];
("st_space", ctypes.c_uint * 32
), # u32 st_space[32];
#
# /* 16*16 bytes for each XMM-reg = 256 bytes */
("xmm_space", ctypes.c_uint*64), # u32 xmm_space[64];
("xmm_space", ctypes.c_uint * 64
), # u32 xmm_space[64];
#
("padding", ctypes.c_uint*12), # u32 padding[12];
("padding", ctypes.c_uint * 12
), # u32 padding[12];
#
# union {
("padding1", ctypes.c_uint*12) # u32 padding1[12];
("padding1", ctypes.c_uint * 12
) # u32 padding1[12];
# u32 sw_reserved[12];
# };
#
@ -520,7 +677,9 @@ class i387_fxsave_struct(ctypes.Structure): # struct i387_fxsave_struct {
class elf_xsave_struct(ctypes.Structure): # struct xsave_struct {
_fields_ = [
("i387", i387_fxsave_struct), # struct i387_fxsave_struct i387;
("xsave_hdr", xsave_hdr_struct), # struct xsave_hdr_struct xsave_hdr;
("i387",
i387_fxsave_struct), # struct i387_fxsave_struct i387;
("xsave_hdr", xsave_hdr_struct
), # struct xsave_hdr_struct xsave_hdr;
("ymmh", ymmh_struct) # struct ymmh_struct ymmh;
] # } __aligned(FP_MIN_ALIGN_BYTES) __packed;

View File

@ -6,21 +6,25 @@ 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
@ -40,21 +44,27 @@ def decode(opts):
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')
@ -63,17 +73,21 @@ class ps_item:
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']))
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')))
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
@ -91,8 +105,10 @@ def explore_ps(opts):
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
@ -124,14 +140,17 @@ def ftype_find_in_image(opts, ft, fid, img):
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:
@ -140,17 +159,33 @@ def ftype_unix(opts, ft, fid):
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'},
'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)
@ -161,6 +196,7 @@ def get_file_str(opts, fd):
return f
def explore_fds(opts):
ps_img = pycriu.images.load(dinf(opts, 'pstree.img'))
for p in ps_img['entries']:
@ -174,8 +210,16 @@ def explore_fds(opts):
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']})))
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:
@ -192,6 +236,7 @@ class vma_id:
return ret
def explore_mems(opts):
ps_img = pycriu.images.load(dinf(opts, 'pstree.img'))
vids = vma_id()
@ -200,7 +245,11 @@ def explore_mems(opts):
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']})))
print("\t%-36s %s" % ('exe',
get_file_str(opts, {
'type': 'REG',
'id': mmi['exe_file_id']
})))
for vma in mmi['vmas']:
st = vma['status']
@ -211,7 +260,10 @@ def explore_mems(opts):
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']})
fn = ' ' + get_file_str(opts, {
'type': 'REG',
'id': vma['shmid']
})
if vma['pgoff']:
fn += ' + %#lx' % vma['pgoff']
if st & (1 << 7):
@ -242,7 +294,8 @@ 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']
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)
@ -260,9 +313,13 @@ def explore_rss(opts):
if vmi == pvmi:
vstr += ' ~'
else:
vstr += ' %08lx / %-8d' % (vma['start'], (vma['end'] - vma['start'])>>12)
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']})
vstr += ' ' + get_file_str(opts, {
'type': 'REG',
'id': vma['shmid']
})
pvmi = vmi
vstr += '\n\t%23s' % ''
vmi += 1
@ -272,47 +329,59 @@ def explore_rss(opts):
print('%-24s%s' % (pstr, vstr))
explorers = {
'ps': explore_ps,
'fds': explore_fds,
'mems': explore_mems,
'rss': explore_rss
}
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)
parser = argparse.ArgumentParser(
description=desc, formatter_class=argparse.RawTextHelpFormatter)
subparsers = parser.add_subparsers(help='Use crit CMD --help for command-specific help')
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',
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',
decode_parser.add_argument(
'-i',
'--in',
help='criu image in binary format to be decoded (stdin by default)')
decode_parser.add_argument('-o',
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',
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',
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 = subparsers.add_parser('info', help='show info about image')
info_parser.add_argument("in")
info_parser.set_defaults(func=info)
@ -323,10 +392,12 @@ def main():
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 = 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.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())
@ -338,5 +409,6 @@ def main():
opts["func"](opts)
if __name__ == '__main__':
main()

View File

@ -8,6 +8,7 @@ import struct
import pycriu.rpc_pb2 as rpc
class _criu_comm:
"""
Base class for communication classes.
@ -37,6 +38,7 @@ class _criu_comm_sk(_criu_comm):
"""
Communication class for unix socket.
"""
def __init__(self, sk_path):
self.comm_type = self.COMM_SK
self.comm = sk_path
@ -55,22 +57,26 @@ class _criu_comm_fd(_criu_comm):
"""
Communication class for file descriptor.
"""
def __init__(self, fd):
self.comm_type = self.COMM_FD
self.comm = fd
def connect(self, daemon):
self.sk = socket.fromfd(self.comm, socket.AF_UNIX, socket.SOCK_SEQPACKET)
self.sk = socket.fromfd(self.comm, socket.AF_UNIX,
socket.SOCK_SEQPACKET)
return self.sk
def disconnect(self):
self.sk.close()
class _criu_comm_bin(_criu_comm):
"""
Communication class for binary.
"""
def __init__(self, bin_path):
self.comm_type = self.COMM_BIN
self.comm = bin_path
@ -90,13 +96,16 @@ class _criu_comm_bin(_criu_comm):
p = os.fork()
if p == 0:
def exec_criu():
os.close(0)
os.close(1)
os.close(2)
css[0].send(struct.pack('i', os.getpid()))
os.execv(self.comm, [self.comm, 'swrk', "%d" % css[0].fileno()])
os.execv(self.comm,
[self.comm, 'swrk',
"%d" % css[0].fileno()])
os._exit(1)
if daemon:
@ -143,9 +152,11 @@ class CRIUExceptionInternal(CRIUException):
"""
Exception class for handling and storing internal errors.
"""
def __init__(self, typ, s):
self.typ = typ
self._str = "%s failed with internal error: %s" % (rpc.criu_req_type.Name(self.typ), s)
self._str = "%s failed with internal error: %s" % (
rpc.criu_req_type.Name(self.typ), s)
class CRIUExceptionExternal(CRIUException):

View File

@ -57,14 +57,17 @@ sizeof_u16 = 2
sizeof_u32 = 4
sizeof_u64 = 8
# A helper for rounding
def round_up(x, y):
return (((x - 1) | (y - 1)) + 1)
class MagicException(Exception):
def __init__(self, magic):
self.magic = magic
# Generic class to handle loading/dumping criu images entries from/to bin
# format to/from dict(json).
class entry_handler:
@ -72,6 +75,7 @@ class entry_handler:
Generic class to handle loading/dumping criu images
entries from/to bin format to/from dict(json).
"""
def __init__(self, payload, extra_handler=None):
"""
Sets payload class and extra handler class.
@ -102,6 +106,7 @@ class entry_handler:
# Read extra
if self.extra_handler:
if no_payload:
def human_readable(num):
for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:
if num < 1024.0:
@ -174,6 +179,7 @@ class entry_handler:
return entries
# Special handler for pagemap.img
class pagemap_handler:
"""
@ -181,6 +187,7 @@ class pagemap_handler:
that it has a header of pagemap_head type followed by entries
of pagemap_entry type.
"""
def load(self, f, pretty=False, no_payload=False):
entries = []
@ -220,6 +227,7 @@ class pagemap_handler:
def count(self, f):
return entry_handler(None).count(f) - 1
# Special handler for ghost-file.img
class ghost_file_handler:
def load(self, f, pretty=False, no_payload=False):
@ -306,6 +314,7 @@ class pipes_data_extra_handler:
f.seek(pload.bytes, os.SEEK_CUR)
return pload.bytes
class sk_queues_extra_handler:
def load(self, f, pload):
size = pload.length
@ -344,6 +353,7 @@ class tcp_stream_extra_handler:
f.seek(0, os.SEEK_END)
return pbuff.inq_len + pbuff.outq_len
class ipc_sem_set_handler:
def load(self, f, pbuff):
entry = pb2dict.pb2dict(pbuff)
@ -375,6 +385,7 @@ class ipc_sem_set_handler:
f.seek(round_up(size, sizeof_u64), os.SEEK_CUR)
return size
class ipc_msg_queue_handler:
def load(self, f, pbuff):
entry = pb2dict.pb2dict(pbuff)
@ -423,6 +434,7 @@ class ipc_msg_queue_handler:
return pl_len
class ipc_shm_handler:
def load(self, f, pbuff):
entry = pb2dict.pb2dict(pbuff)
@ -459,7 +471,8 @@ handlers = {
'GHOST_FILE': ghost_file_handler(),
'MM': entry_handler(pb.mm_entry),
'CGROUP': entry_handler(pb.cgroup_entry),
'TCP_STREAM' : entry_handler(pb.tcp_stream_entry, tcp_stream_extra_handler()),
'TCP_STREAM': entry_handler(pb.tcp_stream_entry,
tcp_stream_extra_handler()),
'STATS': entry_handler(pb.stats_entry),
'PAGEMAP': pagemap_handler(), # Special one
'PSTREE': entry_handler(pb.pstree_entry),
@ -496,7 +509,8 @@ handlers = {
'ITIMERS': entry_handler(pb.itimer_entry),
'POSIX_TIMERS': entry_handler(pb.posix_timer_entry),
'NETDEV': entry_handler(pb.net_device_entry),
'PIPES_DATA' : entry_handler(pb.pipe_data_entry, pipes_data_extra_handler()),
'PIPES_DATA': entry_handler(pb.pipe_data_entry,
pipes_data_extra_handler()),
'FIFO_DATA': entry_handler(pb.pipe_data_entry, pipes_data_extra_handler()),
'SK_QUEUES': entry_handler(pb.sk_packet_entry, sk_queues_extra_handler()),
'IPCNS_SHM': entry_handler(pb.ipc_shm_entry, ipc_shm_handler()),
@ -510,10 +524,12 @@ handlers = {
'CPUINFO': entry_handler(pb.cpuinfo_entry),
}
def __rhandler(f):
# Images v1.1 NOTE: First read "first" magic.
img_magic, = struct.unpack('i', f.read(4))
if img_magic in (magic.by_name['IMG_COMMON'], magic.by_name['IMG_SERVICE']):
if img_magic in (magic.by_name['IMG_COMMON'],
magic.by_name['IMG_SERVICE']):
img_magic, = struct.unpack('i', f.read(4))
try:
@ -528,6 +544,7 @@ def __rhandler(f):
return m, handler
def load(f, pretty=False, no_payload=False):
"""
Convert criu image from binary format to dict(json).
@ -543,6 +560,7 @@ def load(f, pretty = False, no_payload = False):
return image
def info(f):
res = {}
@ -553,6 +571,7 @@ def info(f):
return res
def loads(s, pretty=False):
"""
Same as load(), but takes a string.
@ -560,6 +579,7 @@ def loads(s, pretty = False):
f = io.BytesIO(s)
return load(f, pretty)
def dump(img, f):
"""
Convert criu image from dict(json) format to binary.
@ -586,6 +606,7 @@ def dump(img, f):
handler.dump(img['entries'], f)
def dumps(img):
"""
Same as dump(), but takes only an image and returns

View File

@ -29,47 +29,50 @@ if "encodebytes" not in dir(base64):
# enums to string value too. (i.e. "march : x86_64" is better then
# "march : 1").
_basic_cast = {
FD.TYPE_FIXED64: int,
FD.TYPE_FIXED32: int,
FD.TYPE_SFIXED64: int,
FD.TYPE_SFIXED32: int,
FD.TYPE_INT64: int,
FD.TYPE_UINT64: int,
FD.TYPE_SINT64: int,
FD.TYPE_INT32: int,
FD.TYPE_UINT32: int,
FD.TYPE_SINT32: int,
FD.TYPE_BOOL: bool,
FD.TYPE_STRING: str
}
def _marked_as_hex(field):
return field.GetOptions().Extensions[opts_pb2.criu].hex
def _marked_as_ip(field):
return field.GetOptions().Extensions[opts_pb2.criu].ipadd
def _marked_as_flags(field):
return field.GetOptions().Extensions[opts_pb2.criu].flags
def _marked_as_dev(field):
return field.GetOptions().Extensions[opts_pb2.criu].dev
def _marked_as_odev(field):
return field.GetOptions().Extensions[opts_pb2.criu].odev
def _marked_as_dict(field):
return field.GetOptions().Extensions[opts_pb2.criu].dict
def _custom_conv(field):
return field.GetOptions().Extensions[opts_pb2.criu].conv
mmap_prot_map = [
('PROT_READ', 0x1),
('PROT_WRITE', 0x2),
@ -90,17 +93,14 @@ mmap_status_map = [
('VMA_AREA_VSYSCALL', 1 << 2),
('VMA_AREA_VDSO', 1 << 3),
('VMA_AREA_HEAP', 1 << 5),
('VMA_FILE_PRIVATE', 1 << 6),
('VMA_FILE_SHARED', 1 << 7),
('VMA_ANON_SHARED', 1 << 8),
('VMA_ANON_PRIVATE', 1 << 9),
('VMA_AREA_SYSVIPC', 1 << 10),
('VMA_AREA_SOCKET', 1 << 11),
('VMA_AREA_VVAR', 1 << 12),
('VMA_AREA_AIORING', 1 << 13),
('VMA_UNSUPP', 1 << 31),
]
@ -127,21 +127,30 @@ flags_maps = {
}
gen_maps = {
'task_state' : { 1: 'Alive', 3: 'Zombie', 6: 'Stopped' },
'task_state': {
1: 'Alive',
3: 'Zombie',
6: 'Stopped'
},
}
sk_maps = {
'family' : { 1: 'UNIX',
'family': {
1: 'UNIX',
2: 'INET',
10: 'INET6',
16: 'NETLINK',
17: 'PACKET' },
'type' : { 1: 'STREAM',
17: 'PACKET'
},
'type': {
1: 'STREAM',
2: 'DGRAM',
3: 'RAW',
5: 'SEQPACKET',
10: 'PACKET' },
'state' : { 1: 'ESTABLISHED',
10: 'PACKET'
},
'state': {
1: 'ESTABLISHED',
2: 'SYN_SENT',
3: 'SYN_RECV',
4: 'FIN_WAIT1',
@ -150,21 +159,33 @@ sk_maps = {
7: 'CLOSE',
8: 'CLOSE_WAIT',
9: 'LAST_ACK',
10: 'LISTEN' },
'proto' : { 0: 'IP',
10: 'LISTEN'
},
'proto': {
0: 'IP',
6: 'TCP',
17: 'UDP',
136: 'UDPLITE' },
136: 'UDPLITE'
},
}
gen_rmaps = { k: {v2:k2 for k2,v2 in list(v.items())} for k,v in list(gen_maps.items()) }
sk_rmaps = { k: {v2:k2 for k2,v2 in list(v.items())} for k,v in list(sk_maps.items()) }
gen_rmaps = {
k: {v2: k2
for k2, v2 in list(v.items())}
for k, v in list(gen_maps.items())
}
sk_rmaps = {
k: {v2: k2
for k2, v2 in list(v.items())}
for k, v in list(sk_maps.items())
}
dict_maps = {
'gen': (gen_maps, gen_rmaps),
'sk': (sk_maps, sk_rmaps),
}
def map_flags(value, flags_map):
bs = [x[0] for x in [x for x in flags_map if value & x[1]]]
value &= ~sum([x[1] for x in flags_map])
@ -172,20 +193,28 @@ def map_flags(value, flags_map):
bs.append("0x%x" % value)
return " | ".join(bs)
def unmap_flags(value, flags_map):
if value == '':
return 0
bd = dict(flags_map)
return sum([int(str(bd.get(x, x)), 0) for x in [x.strip() for x in value.split('|')]])
return sum([
int(str(bd.get(x, x)), 0)
for x in [x.strip() for x in value.split('|')]
])
kern_minorbits = 20 # This is how kernel encodes dev_t in new format
def decode_dev(field, value):
if _marked_as_odev(field):
return "%d:%d" % (os.major(value), os.minor(value))
else:
return "%d:%d" % (value >> kern_minorbits, value & ((1 << kern_minorbits) - 1))
return "%d:%d" % (value >> kern_minorbits,
value & ((1 << kern_minorbits) - 1))
def encode_dev(field, value):
dev = [int(x) for x in value.split(':')]
@ -194,19 +223,27 @@ def encode_dev(field, value):
else:
return dev[0] << kern_minorbits | dev[1]
def encode_base64(value):
return base64.encodebytes(value)
def decode_base64(value):
return base64.decodebytes(value)
def encode_unix(value):
return quopri.encodestring(value)
def decode_unix(value):
return quopri.decodestring(value)
encode = {'unix_name': encode_unix}
decode = {'unix_name': decode_unix}
def get_bytes_enc(field):
c = _custom_conv(field)
if c:
@ -214,6 +251,7 @@ def get_bytes_enc(field):
else:
return encode_base64
def get_bytes_dec(field):
c = _custom_conv(field)
if c:
@ -221,6 +259,7 @@ def get_bytes_dec(field):
else:
return decode_base64
def is_string(value):
# Python 3 compatibility
if "basestring" in __builtins__:
@ -229,6 +268,7 @@ def is_string(value):
string_types = (str, bytes)
return isinstance(value, string_types)
def _pb2dict_cast(field, value, pretty=False, is_hex=False):
if not is_hex:
is_hex = _marked_as_hex(field)
@ -254,7 +294,7 @@ def _pb2dict_cast(field, value, pretty = False, is_hex = False):
if flags:
try:
flags_map = flags_maps[flags]
except:
except Exception:
return "0x%x" % value # flags are better seen as hex anyway
else:
return map_flags(value, flags_map)
@ -265,7 +305,9 @@ def _pb2dict_cast(field, value, pretty = False, is_hex = False):
return cast(value)
else:
raise Exception("Field(%s) has unsupported type %d" % (field.name, field.type))
raise Exception("Field(%s) has unsupported type %d" %
(field.name, field.type))
def pb2dict(pb, pretty=False, is_hex=False):
"""
@ -297,6 +339,7 @@ def pb2dict(pb, pretty = False, is_hex = False):
d[field.name] = d_val
return d
def _dict2pb_cast(field, value):
# Not considering TYPE_MESSAGE here, as repeated
# and non-repeated messages need special treatment
@ -315,7 +358,7 @@ def _dict2pb_cast(field, value):
if flags:
try:
flags_map = flags_maps[flags]
except:
except Exception:
pass # Try to use plain string cast
else:
return unmap_flags(value, flags_map)
@ -323,7 +366,7 @@ def _dict2pb_cast(field, value):
dct = _marked_as_dict(field)
if dct:
ret = dict_maps[dct][1][field.name].get(value, None)
if ret == None:
if ret is None:
ret = cast(value, 0)
return ret
@ -333,7 +376,9 @@ def _dict2pb_cast(field, value):
else:
return cast(value)
else:
raise Exception("Field(%s) has unsupported type %d" % (field.name, field.type))
raise Exception("Field(%s) has unsupported type %d" %
(field.name, field.type))
def dict2pb(d, pb):
"""
@ -357,7 +402,8 @@ def dict2pb(d, pb):
pb_val.append(socket.htonl((ival >> (32 * 1)) & 0xFFFFFFFF))
pb_val.append(socket.htonl((ival >> (32 * 0)) & 0xFFFFFFFF))
else:
raise Exception("Unknown IP address version %d" % val.version)
raise Exception("Unknown IP address version %d" %
val.version)
continue
for v in value:

View File

@ -8,5 +8,4 @@ setup(name = "crit",
url="https://github.com/checkpoint-restore/criu",
package_dir={'pycriu': 'lib/py'},
packages=["pycriu", "pycriu.images"],
scripts = ["crit/crit"]
)
scripts=["crit/crit"])

View File

@ -1,6 +1,7 @@
#!/bin/env python2
import sys
# This program parses criu magic.h file and produces
# magic.py with all *_MAGIC constants except RAW and V1.
def main(argv):
@ -57,5 +58,6 @@ def main(argv):
f.close()
out.close()
if __name__ == "__main__":
main(sys.argv)

View File

@ -13,15 +13,15 @@ sport = os.getenv("TCP_SPORT", "12345")
dport = os.getenv("TCP_DPORT", "54321")
print(sys.argv[1])
args = [sys.argv[1],
"--addr", src, "--port", sport, "--seq", "555",
"--next",
"--addr", dst, "--port", dport, "--seq", "666",
"--reverse", "--", "./tcp-test.py"]
args = [
sys.argv[1], "--addr", src, "--port", sport, "--seq", "555", "--next",
"--addr", dst, "--port", dport, "--seq", "666", "--reverse", "--",
"./tcp-test.py"
]
p1 = Popen(args + ["dst"], stdout=PIPE, stdin=PIPE)
args.remove("--reverse");
args.remove("--reverse")
p2 = Popen(args + ["src"], stdout=PIPE, stdin=PIPE)
@ -42,7 +42,7 @@ str2 = m.hexdigest()
if str2 != eval(s):
print("FAIL", repr(str2), repr(s))
sys.exit(5);
sys.exit(5)
s = p1.stdout.read()
m = hashlib.md5()
@ -52,7 +52,7 @@ str1 = m.hexdigest()
s = p2.stdout.read()
if str1 != eval(s):
print("FAIL", repr(str1), s)
sys.exit(5);
sys.exit(5)
if p1.wait():
sys.exit(1)

View File

@ -25,7 +25,8 @@ for act in open(af):
if act[2] == 'EMPTY':
errors.append('Action %s misses CRTOOLS_INIT_PID' % act[0])
elif not act[2].isdigit() or int(act[2]) == 0:
errors.append('Action %s PID is not number (%s)' % (act[0], act[2]))
errors.append('Action %s PID is not number (%s)' %
(act[0], act[2]))
actions -= set([act[0]])

View File

@ -6,11 +6,13 @@ import sys
import os
import subprocess
find = subprocess.Popen(['find', 'test/dump/', '-size', '+0', '-name', '*.img'],
find = subprocess.Popen(
['find', 'test/dump/', '-size', '+0', '-name', '*.img'],
stdout=subprocess.PIPE)
test_pass = True
def recode_and_check(imgf, o_img, pretty):
try:
pb = pycriu.images.loads(o_img, pretty)

View File

@ -10,6 +10,7 @@ import subprocess
criu_bin = '../../criu/criu'
def mix(nr_tasks, nr_pipes):
# Returned is the list of combinations.
# Each combination is the lists of pipe descriptors.
@ -114,6 +115,7 @@ def check_pipe(kids, fds, comb, inos):
return res + 'end(%d)' % e
return None
def check_pipes(kids, pipes, comb):
# Kids contain pids
# Pipes contain pipe FDs
@ -198,14 +200,20 @@ def cr_test(pid):
img_dir = 'pimg_%d' % pid
try:
os.mkdir(img_dir)
subprocess.check_call([criu_bin, 'dump', '-t', '%d' % pid, '-D', img_dir, '-o', 'dump.log', '-v4', '-j'])
subprocess.check_call([
criu_bin, 'dump', '-t',
'%d' % pid, '-D', img_dir, '-o', 'dump.log', '-v4', '-j'
])
except:
print('`- dump fail')
return False
try:
os.waitpid(pid, 0)
subprocess.check_call([criu_bin, 'restore', '-D', img_dir, '-o', 'rst.log', '-v4', '-j', '-d', '-S'])
subprocess.check_call([
criu_bin, 'restore', '-D', img_dir, '-o', 'rst.log', '-v4', '-j',
'-d', '-S'
])
except:
print('`- restore fail')
return False

View File

@ -25,12 +25,14 @@ sk_type_s = {
# - do() method, that actually does what's required
# - show() method to return the string description of what's done
def mk_socket(st, typ):
st.sk_id += 1
sk = sock(st.sk_id, typ)
st.add_socket(sk)
return sk
class act_socket:
def __init__(self, typ):
self.typ = typ
@ -174,12 +176,14 @@ class act_sendmsg:
sk.sendto(msgv, sock.real_name_for(self.to_id))
def show(self):
return 'send(%d, %d, $message-%d)' % (self.sk_id, self.to_id, self.msg_id)
return 'send(%d, %d, $message-%d)' % (self.sk_id, self.to_id,
self.msg_id)
@staticmethod
def msgval(msgid, pref=''):
return '%sMSG%d' % (pref, msgid)
#
# Description of a socket
#
@ -425,6 +429,7 @@ def set_nonblock(sk):
flags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
CHK_FAIL_UNKNOWN = 10
CHK_FAIL_SOCKET = 11
CHK_FAIL_STAT = 12
@ -455,6 +460,7 @@ fail_desc = {
CHK_FAIL_RESTORE: 'Cannot restore',
}
def chk_real_state(st):
# Before enything else -- check that we still have
# all the sockets at hands
@ -485,16 +491,16 @@ def chk_real_state(st):
rsk = st.real_sockets[sk.sk_id]
r_listen = rsk.getsockopt(socket.SOL_SOCKET, socket.SO_ACCEPTCONN)
if (sk.listen and r_listen == 0) or (not sk.listen and r_listen == 1):
print("FAIL: Socket %d listen %d, expected %d"
% (sk.sk_id, r_listen, sk.listen and 1 or 0))
print("FAIL: Socket %d listen %d, expected %d" %
(sk.sk_id, r_listen, sk.listen and 1 or 0))
return CHK_FAIL_LISTEN
if sk.name:
r_name = rsk.getsockname()
w_name = sock.real_name_for(sk.name)
if r_name != w_name:
print('FAIL: Socket %d name mismatch [%s], want [%s]'
% (sk.sk_id, r_name, w_name))
print('FAIL: Socket %d name mismatch [%s], want [%s]' %
(sk.sk_id, r_name, w_name))
return CHK_FAIL_NAME
# Second -- check (accept) pending connections
@ -513,7 +519,8 @@ def chk_real_state(st):
try:
acc.do(st)
except:
print('FAIL: Cannot accept pending connection for %d' % sk.sk_id)
print('FAIL: Cannot accept pending connection for %d' %
sk.sk_id)
return CHK_FAIL_ACCEPT
print(' `- did %s' % acc.show())
@ -536,13 +543,13 @@ def chk_real_state(st):
w_msg = act_sendmsg.msgval(msg[1])
if r_msg != w_msg:
print('FAIL: Message misorder: %s want %s (from %d)'
%(r_msg, w_msg, msg[0]))
print('FAIL: Message misorder: %s want %s (from %d)' %
(r_msg, w_msg, msg[0]))
return CHK_FAIL_RECV_MIX
# TODO -- check sender
print(' `- recvd %d.%d msg %s -> %d'
% (msg[0], msg[1], m_from, sk.sk_id))
print(' `- recvd %d.%d msg %s -> %d' %
(msg[0], msg[1], m_from, sk.sk_id))
# Finally, after all sockets are visible and all inqueues are
# drained -- check the sockets connectivity
@ -557,7 +564,8 @@ def chk_real_state(st):
rsk = st.real_sockets[sk.sk_id]
psk = st.real_sockets[sk.peer]
set_nonblock(psk)
msgv = act_sendmsg.msgval(3 * sk.sk_id + 5 * sk.peer, 'C') # just random
msgv = act_sendmsg.msgval(3 * sk.sk_id + 5 * sk.peer,
'C') # just random
try:
rsk.send(msgv)
@ -572,8 +580,8 @@ def chk_real_state(st):
# the hard way -- also check for the message being
# delivered for real
if rmsg != msgv:
print('FAIL: Connectivity %d -> %d not verified'
% (sk.sk_id, sk.peer))
print('FAIL: Connectivity %d -> %d not verified' %
(sk.sk_id, sk.peer))
return CHK_FAIL_CONNECT2
print(' `- checked %d -> %d with %s' % (sk.sk_id, sk.peer, msgv))
@ -609,7 +617,10 @@ def chk_state(st, opts):
img_path = "sti_" + st.describe()
try:
os.mkdir(img_path)
subprocess.check_call([criu_bin, "dump", "-t", "%d" % pid, "-D", img_path, "-v4", "-o", "dump.log", "-j"])
subprocess.check_call([
criu_bin, "dump", "-t",
"%d" % pid, "-D", img_path, "-v4", "-o", "dump.log", "-j"
])
except:
print("Dump failed")
os.kill(pid, signal.SIGKILL)
@ -618,7 +629,10 @@ def chk_state(st, opts):
print("`- restore")
try:
os.waitpid(pid, 0)
subprocess.check_call([criu_bin, "restore", "-D", img_path, "-v4", "-o", "rst.log", "-j", "-d", "-S"])
subprocess.check_call([
criu_bin, "restore", "-D", img_path, "-v4", "-o", "rst.log", "-j",
"-d", "-S"
])
except:
print("Restore failed")
return CHK_FAIL_RESTORE
@ -722,8 +736,12 @@ p.add_argument("--depth", help = "Depth of generated tree", default = '8')
p.add_argument("--sockets", help="Maximum number of sockets", default='1')
p.add_argument("--dgram", help="Use SOCK_DGRAM sockets", action='store_true')
p.add_argument("--stream", help="Use SOCK_STREAM sockets", action='store_true')
p.add_argument("--gen", help = "Only generate and show states", action = 'store_true')
p.add_argument("--run", help = "Run the states, but don't C/R", action = 'store_true')
p.add_argument("--gen",
help="Only generate and show states",
action='store_true')
p.add_argument("--run",
help="Run the states, but don't C/R",
action='store_true')
p.add_argument("--keep", help="Don't stop on error", action='store_true')
opts = p.parse_args()
opts.depth = int(opts.depth)
@ -751,4 +769,5 @@ if len(failed) == 0:
else:
print('FAIL %d/%d' % (len(failed), len(seen)))
for f in failed:
print("\t%-50s: %s" % (f[0], fail_desc.get(f[1], 'unknown reason %d' % f[1])))
print("\t%-50s: %s" %
(f[0], fail_desc.get(f[1], 'unknown reason %d' % f[1])))

View File

@ -4,7 +4,6 @@ import os
import pty
import termios
ctl = False

View File

@ -5,13 +5,19 @@ import os, sys, time, signal, pty
master, slave = pty.openpty()
p = subprocess.Popen(["setsid", "--ctty", "sleep", "10000"],
stdin = slave, stdout = slave, stderr = slave, close_fds = True)
stdin=slave,
stdout=slave,
stderr=slave,
close_fds=True)
st = os.stat("/proc/self/fd/%d" % slave)
ttyid = "tty[%x:%x]" % (st.st_rdev, st.st_dev)
os.close(slave)
time.sleep(1)
ret = subprocess.Popen(["../../../criu/criu", "dump", "-t", str(p.pid), "-v4", "--external", ttyid]).wait()
ret = subprocess.Popen([
"../../../criu/criu", "dump", "-t",
str(p.pid), "-v4", "--external", ttyid
]).wait()
if ret:
sys.exit(ret)
p.wait()
@ -21,7 +27,10 @@ os.close(master)
ttyid = "fd[%d]:tty[%x:%x]" % (slave, st.st_rdev, st.st_dev)
ret = subprocess.Popen(["../../../criu/criu", "restore", "-v4", "--inherit-fd", ttyid, "--restore-sibling", "--restore-detach"]).wait()
ret = subprocess.Popen([
"../../../criu/criu", "restore", "-v4", "--inherit-fd", ttyid,
"--restore-sibling", "--restore-detach"
]).wait()
if ret:
sys.exit(ret)
os.close(slave)

View File

@ -1,6 +1,7 @@
import os
import tempfile, random
def mount(src, dst, shared, private, slave):
cmd = "mount"
if shared:
@ -19,6 +20,7 @@ def mount(src, dst, shared, private, slave):
if ret:
print("failed")
root = tempfile.mkdtemp(prefix="root.mount", dir="/tmp")
mount(None, root, 1, 0, 0)
mounts = [root]
@ -27,5 +29,8 @@ for i in range(10):
dstdir = random.choice(mounts)
dst = tempfile.mkdtemp(prefix="mount", dir=dstdir)
src = random.choice(mounts + [None])
mount(src, dst, random.randint(0,100) > 50, random.randint(0,100) > 90, random.randint(0,100) > 50)
mount(src, dst,
random.randint(0, 100) > 50,
random.randint(0, 100) > 90,
random.randint(0, 100) > 50)
mounts.append(dst)

View File

@ -99,7 +99,9 @@ def test_broken_configuration_file():
def search_in_log_file(log, message):
with open(os.path.join(args['dir'], log)) as f:
if message not in f.read():
print('FAIL: Missing the expected error message (%s) in the log file' % message)
print(
'FAIL: Missing the expected error message (%s) in the log file'
% message)
sys.exit(-1)
@ -175,8 +177,11 @@ def test_rpc_with_configuration_file_overwriting_rpc():
check_results(resp, log)
parser = argparse.ArgumentParser(description="Test config files using CRIU RPC")
parser.add_argument('dir', type = str, help = "Directory where CRIU images should be placed")
parser = argparse.ArgumentParser(
description="Test config files using CRIU RPC")
parser.add_argument('dir',
type=str,
help="Directory where CRIU images should be placed")
args = vars(parser.parse_args())

View File

@ -7,10 +7,13 @@ import argparse
parser = argparse.ArgumentParser(description="Test errno reported by CRIU RPC")
parser.add_argument('socket', type=str, help="CRIU service socket")
parser.add_argument('dir', type = str, help = "Directory where CRIU images should be placed")
parser.add_argument('dir',
type=str,
help="Directory where CRIU images should be placed")
args = vars(parser.parse_args())
# Prepare dir for images
class test:
def __init__(self):
@ -73,7 +76,9 @@ class test:
print('Success')
def process_exists(self):
print('Try to restore process which pid is already taken by other process')
print(
'Try to restore process which pid is already taken by other process'
)
# Perform self-dump
req = self.get_base_req()
@ -131,5 +136,6 @@ class test:
self.bad_options()
self.bad_request()
t = test()
t.run()

View File

@ -6,7 +6,9 @@ import argparse
parser = argparse.ArgumentParser(description="Test page-server using CRIU RPC")
parser.add_argument('socket', type=str, help="CRIU service socket")
parser.add_argument('dir', type = str, help = "Directory where CRIU images should be placed")
parser.add_argument('dir',
type=str,
help="Directory where CRIU images should be placed")
args = vars(parser.parse_args())
@ -42,12 +44,12 @@ else:
else:
print('Can\'t check that process %d exists' % (resp.ps.pid))
sys.exit(1)
print('Success, page-server pid %d started on port %u' %(resp.ps.pid, resp.ps.port))
print('Success, page-server pid %d started on port %u' %
(resp.ps.pid, resp.ps.port))
else:
print('Failed to start page-server')
sys.exit(1)
# Perform self-dump
print('Dumping myself using page-server')
req.type = rpc.DUMP

View File

@ -4,9 +4,12 @@ import socket, os, sys
import rpc_pb2 as rpc
import argparse
parser = argparse.ArgumentParser(description="Test ability to restore a process from images using CRIU RPC")
parser = argparse.ArgumentParser(
description="Test ability to restore a process from images using CRIU RPC")
parser.add_argument('socket', type=str, help="CRIU service socket")
parser.add_argument('dir', type = str, help = "Directory where CRIU images could be found")
parser.add_argument('dir',
type=str,
help="Directory where CRIU images could be found")
args = vars(parser.parse_args())

View File

@ -4,9 +4,12 @@ import socket, os, sys
import rpc_pb2 as rpc
import argparse
parser = argparse.ArgumentParser(description="Test dump/restore using CRIU RPC")
parser = argparse.ArgumentParser(
description="Test dump/restore using CRIU RPC")
parser.add_argument('socket', type=str, help="CRIU service socket")
parser.add_argument('dir', type = str, help = "Directory where CRIU images should be placed")
parser.add_argument('dir',
type=str,
help="Directory where CRIU images should be placed")
args = vars(parser.parse_args())

View File

@ -6,10 +6,12 @@ cr_bin = "../../../criu/criu"
os.chdir(os.getcwd())
def create_pty():
(fd1, fd2) = pty.openpty()
return (os.fdopen(fd1, "w+"), os.fdopen(fd2, "w+"))
if not os.access("work", os.X_OK):
os.mkdir("work", 0755)
@ -53,7 +55,8 @@ if cpid == 0:
fcntl.ioctl(m.fileno(), termios.TIOCSCTTY, 1)
cmd = [cr_bin, "restore", "-j", "-D", "work", "-v"]
print("Run: %s" % " ".join(cmd))
ret = subprocess.Popen([cr_bin, "restore", "-j", "-D", "work", "-v"]).wait()
ret = subprocess.Popen([cr_bin, "restore", "-j", "-D", "work",
"-v"]).wait()
if ret != 0:
sys.exit(1)
sys.exit(0)

View File

@ -122,7 +122,8 @@ def check_core_files():
if not reports:
return False
while subprocess.Popen(r"ps axf | grep 'abrt\.sh'", shell = True).wait() == 0:
while subprocess.Popen(r"ps axf | grep 'abrt\.sh'",
shell=True).wait() == 0:
time.sleep(1)
for i in reports:
@ -164,7 +165,10 @@ class host_flavor:
class ns_flavor:
__root_dirs = ["/bin", "/sbin", "/etc", "/lib", "/lib64", "/dev", "/dev/pts", "/dev/net", "/tmp", "/usr", "/proc", "/run"]
__root_dirs = [
"/bin", "/sbin", "/etc", "/lib", "/lib64", "/dev", "/dev/pts",
"/dev/net", "/tmp", "/usr", "/proc", "/run"
]
def __init__(self, opts):
self.name = "ns"
@ -183,27 +187,36 @@ class ns_flavor:
except OSError as e:
if e.errno != errno.EEXIST:
raise
dst = tempfile.mktemp(".tso", "", self.root + os.path.dirname(fname))
dst = tempfile.mktemp(".tso", "",
self.root + os.path.dirname(fname))
shutil.copy2(fname, dst)
os.rename(dst, tfname)
def __copy_libs(self, binary):
ldd = subprocess.Popen(["ldd", binary], stdout=subprocess.PIPE)
xl = re.compile(r'^(linux-gate.so|linux-vdso(64)?.so|not a dynamic|.*\s*ldd\s)')
xl = re.compile(
r'^(linux-gate.so|linux-vdso(64)?.so|not a dynamic|.*\s*ldd\s)')
# This Mayakovsky-style code gets list of libraries a binary
# needs minus vdso and gate .so-s
libs = map(lambda x: x[1] == '=>' and x[2] or x[0],
map(lambda x: str(x).split(),
filter(lambda x: not xl.match(x),
map(lambda x: str(x).strip(),
filter(lambda x: str(x).startswith('\t'), ldd.stdout.read().decode('ascii').splitlines())))))
libs = map(
lambda x: x[1] == '=>' and x[2] or x[0],
map(
lambda x: str(x).split(),
filter(
lambda x: not xl.match(x),
map(
lambda x: str(x).strip(),
filter(lambda x: str(x).startswith('\t'),
ldd.stdout.read().decode(
'ascii').splitlines())))))
ldd.wait()
for lib in libs:
if not os.access(lib, os.F_OK):
raise test_fail_exc("Can't find lib %s required by %s" % (lib, binary))
raise test_fail_exc("Can't find lib %s required by %s" %
(lib, binary))
self.__copy_one(lib)
def __mknod(self, name, rdev=None):
@ -242,7 +255,8 @@ class ns_flavor:
raise test_fail_exc("Deps check %s failed" % deps)
def init(self, l_bins, x_bins):
subprocess.check_call(["mount", "--make-slave", "--bind", ".", self.root])
subprocess.check_call(
["mount", "--make-slave", "--bind", ".", self.root])
self.root_mounted = True
if not os.access(self.root + "/.constructed", os.F_OK):
@ -308,8 +322,7 @@ def decode_flav(i):
def tail(path):
p = subprocess.Popen(['tail', '-n1', path],
stdout = subprocess.PIPE)
p = subprocess.Popen(['tail', '-n1', path], stdout=subprocess.PIPE)
out = p.stdout.readline()
p.wait()
return out.decode()
@ -342,6 +355,7 @@ def wait_pid_die(pid, who, tmo = 30):
def test_flag(tdesc, flag):
return flag in tdesc.get('flags', '').split()
#
# Exception thrown when something inside the test goes wrong,
# e.g. test doesn't start, criu returns with non zero code or
@ -361,6 +375,7 @@ class test_fail_expected_exc(Exception):
def __init__(self, cr_action):
self.cr_action = cr_action
#
# A test from zdtm/ directory.
#
@ -384,14 +399,20 @@ class zdtm_test:
def __make_action(self, act, env=None, root=None):
sys.stdout.flush() # Not to let make's messages appear before ours
tpath = self.__name + '.' + act
s_args = ['make', '--no-print-directory',
'-C', os.path.dirname(tpath),
os.path.basename(tpath)]
s_args = [
'make', '--no-print-directory', '-C',
os.path.dirname(tpath),
os.path.basename(tpath)
]
if env:
env = dict(os.environ, **env)
s = subprocess.Popen(s_args, env = env, cwd = root, close_fds = True,
s = subprocess.Popen(
s_args,
env=env,
cwd=root,
close_fds=True,
preexec_fn=self.__freezer and self.__freezer.attach or None)
if act == "pid":
try_run_hook(self, ["--post-start"])
@ -480,8 +501,10 @@ class zdtm_test:
if self.__pid == 0:
self.getpid()
notify_fdout_path = "/proc/%s/fd/%s" % (self.__pid, env['ZDTM_NOTIFY_FDOUT'])
notify_fdin_path = "/proc/%s/fd/%s" % (self.__pid, env['ZDTM_NOTIFY_FDIN'])
notify_fdout_path = "/proc/%s/fd/%s" % (self.__pid,
env['ZDTM_NOTIFY_FDOUT'])
notify_fdin_path = "/proc/%s/fd/%s" % (self.__pid,
env['ZDTM_NOTIFY_FDIN'])
print("Send pre-dump notify to %s" % (self.__pid))
with open(notify_fdout_path, "rb") as fdout:
@ -516,18 +539,25 @@ class zdtm_test:
return self.__name
def __getcropts(self):
opts = self.__desc.get('opts', '').split() + ["--pidfile", os.path.realpath(self.__pidfile())]
opts = self.__desc.get('opts', '').split() + [
"--pidfile", os.path.realpath(self.__pidfile())
]
if self.__flavor.ns:
opts += ["--root", self.__flavor.root]
if test_flag(self.__desc, 'crlib'):
opts += ["-L", os.path.dirname(os.path.realpath(self.__name)) + '/lib']
opts += [
"-L",
os.path.dirname(os.path.realpath(self.__name)) + '/lib'
]
return opts
def getdopts(self):
return self.__getcropts() + self.__freezer.getdopts() + self.__desc.get('dopts', '').split()
return self.__getcropts() + self.__freezer.getdopts(
) + self.__desc.get('dopts', '').split()
def getropts(self):
return self.__getcropts() + self.__freezer.getropts() + self.__desc.get('ropts', '').split()
return self.__getcropts() + self.__freezer.getropts(
) + self.__desc.get('ropts', '').split()
def unlink_pidfile(self):
self.__pid = 0
@ -568,11 +598,13 @@ class zdtm_test:
subprocess.check_call(["make", "zdtm_ct"])
if not os.access("zdtm/lib/libzdtmtst.a", os.F_OK):
subprocess.check_call(["make", "-C", "zdtm/"])
subprocess.check_call(["flock", "zdtm_mount_cgroups.lock", "./zdtm_mount_cgroups"])
subprocess.check_call(
["flock", "zdtm_mount_cgroups.lock", "./zdtm_mount_cgroups"])
@staticmethod
def cleanup():
subprocess.check_call(["flock", "zdtm_mount_cgroups.lock", "./zdtm_umount_cgroups"])
subprocess.check_call(
["flock", "zdtm_mount_cgroups.lock", "./zdtm_umount_cgroups"])
def load_module_from_file(name, path):
@ -601,7 +633,9 @@ class inhfd_test:
def __get_message(self, i):
m = self.__messages.get(i, None)
if not m:
m = b"".join([random.choice(string.ascii_letters).encode() for _ in range(10)]) + b"%06d" % i
m = b"".join([
random.choice(string.ascii_letters).encode() for _ in range(10)
]) + b"%06d" % i
self.__messages[i] = m
return m
@ -631,7 +665,8 @@ class inhfd_test:
os.unlink(self.__name + ".out")
except Exception as e:
print(e)
fd = os.open(self.__name + ".out", os.O_WRONLY | os.O_APPEND | os.O_CREAT)
fd = os.open(self.__name + ".out",
os.O_WRONLY | os.O_APPEND | os.O_CREAT)
os.dup2(fd, 1)
os.dup2(fd, 2)
os.close(fd)
@ -669,7 +704,8 @@ class inhfd_test:
def stop(self):
fds = set(os.listdir("/proc/%s/fd" % self.__peer_pid))
if fds != self.__fds:
raise test_fail_exc("File descriptors mismatch: %s %s" % (fds, self.__fds))
raise test_fail_exc("File descriptors mismatch: %s %s" %
(fds, self.__fds))
i = 0
for my_file, _ in self.__files:
msg = self.__get_message(i)
@ -753,7 +789,8 @@ class groups_test(zdtm_test):
s_args = ['make', '--no-print-directory', '-C', tdir]
subprocess.check_call(s_args + [tname + '.cleanout'])
s = subprocess.Popen(s_args + ['--dry-run', tname + '.pid'], stdout = subprocess.PIPE)
s = subprocess.Popen(s_args + ['--dry-run', tname + '.pid'],
stdout=subprocess.PIPE)
cmd = s.stdout.readlines().pop().strip()
s.wait()
@ -792,15 +829,26 @@ join_ns_file = '/run/netns/zdtm_netns'
class criu_cli:
@staticmethod
def run(action, args, criu_bin, fault = None, strace = [], preexec = None, nowait = False):
env = dict(os.environ, ASAN_OPTIONS = "log_path=asan.log:disable_coredump=0:detect_leaks=0")
def run(action,
args,
criu_bin,
fault=None,
strace=[],
preexec=None,
nowait=False):
env = dict(
os.environ,
ASAN_OPTIONS="log_path=asan.log:disable_coredump=0:detect_leaks=0")
if fault:
print("Forcing %s fault" % fault)
env['CRIU_FAULT'] = fault
cr = subprocess.Popen(strace + [criu_bin, action, "--no-default-config"] + args,
env = env, close_fds = False, preexec_fn = preexec)
cr = subprocess.Popen(strace +
[criu_bin, action, "--no-default-config"] + args,
env=env,
close_fds=False,
preexec_fn=preexec)
if nowait:
return cr
return cr.wait()
@ -884,7 +932,13 @@ class criu_rpc:
raise test_fail_exc('RPC for %s required' % arg)
@staticmethod
def run(action, args, criu_bin, fault = None, strace = [], preexec = None, nowait = False):
def run(action,
args,
criu_bin,
fault=None,
strace=[],
preexec=None,
nowait=False):
if fault:
raise test_fail_exc('RPC and FAULT not supported')
if strace:
@ -905,7 +959,8 @@ class criu_rpc:
criu.pre_dump()
elif action == 'restore':
if 'rd' not in ctx:
raise test_fail_exc('RPC Non-detached restore is impossible')
raise test_fail_exc(
'RPC Non-detached restore is impossible')
res = criu.restore()
pidf = ctx.get('pidf')
@ -1001,7 +1056,8 @@ class criu:
os.rename(self.__dump_path, newpath)
break
else:
raise test_fail_exc("couldn't find dump dir %s" % self.__dump_path)
raise test_fail_exc("couldn't find dump dir %s" %
self.__dump_path)
os.makedirs(self.__dump_path)
@ -1012,10 +1068,11 @@ class criu:
def __tls_options(self):
pki_dir = os.path.dirname(os.path.abspath(__file__)) + "/pki"
return ["--tls", "--tls-no-cn-verify",
"--tls-key", pki_dir + "/key.pem",
"--tls-cert", pki_dir + "/cert.pem",
"--tls-cacert", pki_dir + "/cacert.pem"]
return [
"--tls", "--tls-no-cn-verify", "--tls-key", pki_dir + "/key.pem",
"--tls-cert", pki_dir + "/cert.pem", "--tls-cacert",
pki_dir + "/cacert.pem"
]
def __ddir(self):
return os.path.join(self.__dump_path, "%d" % self.__iter)
@ -1043,7 +1100,10 @@ class criu:
strace = ["strace", "-o", fname, '-T']
if action == 'restore':
strace += ['-f']
s_args += ['--action-script', os.getcwd() + '/../scripts/fake-restore.sh']
s_args += [
'--action-script',
os.getcwd() + '/../scripts/fake-restore.sh'
]
if self.__script:
s_args += ['--action-script', self.__script]
@ -1066,7 +1126,8 @@ class criu:
with open("/proc/sys/kernel/ns_last_pid") as ns_last_pid_fd:
ns_last_pid = ns_last_pid_fd.read()
ret = self.__criu.run(action, s_args, self.__criu_bin, self.__fault, strace, preexec, nowait)
ret = self.__criu.run(action, s_args, self.__criu_bin, self.__fault,
strace, preexec, nowait)
if nowait:
os.close(status_fds[1])
@ -1075,7 +1136,8 @@ class criu:
if self.__test.blocking():
raise test_fail_expected_exc(action)
else:
raise test_fail_exc("criu %s exited with %s" % (action, ret))
raise test_fail_exc("criu %s exited with %s" %
(action, ret))
os.close(status_fds[0])
return ret
@ -1090,19 +1152,23 @@ class criu:
os.chmod(__ddir, 0o777)
else:
# on restore we move only a log file, because we need images
os.rename(os.path.join(__ddir, log), os.path.join(__ddir, log + ".fail"))
os.rename(os.path.join(__ddir, log),
os.path.join(__ddir, log + ".fail"))
# restore ns_last_pid to avoid a case when criu gets
# PID of one of restored processes.
with open("/proc/sys/kernel/ns_last_pid", "w+") as fd:
fd.write(ns_last_pid)
# try again without faults
print("Run criu " + action)
ret = self.__criu.run(action, s_args, self.__criu_bin, False, strace, preexec)
ret = self.__criu.run(action, s_args, self.__criu_bin, False,
strace, preexec)
grep_errors(os.path.join(__ddir, log))
if ret == 0:
return
rst_succeeded = os.access(os.path.join(__ddir, "restore-succeeded"), os.F_OK)
if self.__test.blocking() or (self.__sat and action == 'restore' and rst_succeeded):
rst_succeeded = os.access(
os.path.join(__ddir, "restore-succeeded"), os.F_OK)
if self.__test.blocking() or (self.__sat and action == 'restore' and
rst_succeeded):
raise test_fail_expected_exc(action)
else:
raise test_fail_exc("CRIU %s" % action)
@ -1114,7 +1180,8 @@ class criu:
if not self.__show_stats:
return
subprocess.Popen([self.__crit_bin, "show", self.__stats_file(action)]).wait()
subprocess.Popen([self.__crit_bin, "show",
self.__stats_file(action)]).wait()
def check_pages_counts(self):
if not os.access(self.__stats_file("dump"), os.R_OK):
@ -1124,7 +1191,8 @@ class criu:
with open(self.__stats_file("dump"), 'rb') as stfile:
stats = crpc.images.load(stfile)
stent = stats['entries'][0]['dump']
stats_written = int(stent['shpages_written']) + int(stent['pages_written'])
stats_written = int(stent['shpages_written']) + int(
stent['pages_written'])
real_written = 0
for f in os.listdir(self.__ddir()):
@ -1134,7 +1202,8 @@ class criu:
r_pages = real_written / mmap.PAGESIZE
r_off = real_written % mmap.PAGESIZE
if (stats_written != r_pages) or (r_off != 0):
print("ERROR: bad page counts, stats = %d real = %d(%d)" % (stats_written, r_pages, r_off))
print("ERROR: bad page counts, stats = %d real = %d(%d)" %
(stats_written, r_pages, r_off))
raise test_fail_exc("page counts mismatch")
def dump(self, action, opts=[]):
@ -1144,7 +1213,10 @@ class criu:
a_opts = ["-t", self.__test.getpid()]
if self.__prev_dump_iter:
a_opts += ["--prev-images-dir", "../%d" % self.__prev_dump_iter, "--track-mem"]
a_opts += [
"--prev-images-dir",
"../%d" % self.__prev_dump_iter, "--track-mem"
]
self.__prev_dump_iter = self.__iter
if self.__page_server:
@ -1154,8 +1226,12 @@ class criu:
if self.__dedup:
ps_opts += ["--auto-dedup"]
self.__page_server_p = self.__criu_act("page-server", opts = ps_opts, nowait = True)
a_opts += ["--page-server", "--address", "127.0.0.1", "--port", "12345"] + self.__tls
self.__page_server_p = self.__criu_act("page-server",
opts=ps_opts,
nowait=True)
a_opts += [
"--page-server", "--address", "127.0.0.1", "--port", "12345"
] + self.__tls
a_opts += self.__test.getdopts()
@ -1178,7 +1254,9 @@ class criu:
if self.__lazy_migrate and action == "dump":
a_opts += ["--lazy-pages", "--port", "12345"] + self.__tls
nowait = True
self.__dump_process = self.__criu_act(action, opts = a_opts + opts, nowait = nowait)
self.__dump_process = self.__criu_act(action,
opts=a_opts + opts,
nowait=nowait)
if self.__mdedup and self.__iter > 1:
self.__criu_act("dedup", opts=[])
@ -1212,9 +1290,6 @@ class criu:
if self.__dedup:
r_opts += ["--auto-dedup"]
if self.__dedup:
r_opts += ["--auto-dedup"]
self.__prev_dump_iter = None
criu_dir = os.path.dirname(os.getcwd())
if os.getenv("GCOV"):
@ -1224,14 +1299,21 @@ class criu:
if self.__lazy_pages or self.__lazy_migrate:
lp_opts = []
if self.__remote_lazy_pages or self.__lazy_migrate:
lp_opts += ["--page-server", "--port", "12345",
"--address", "127.0.0.1"] + self.__tls
lp_opts += [
"--page-server", "--port", "12345", "--address",
"127.0.0.1"
] + self.__tls
if self.__remote_lazy_pages:
ps_opts = ["--pidfile", "ps.pid",
"--port", "12345", "--lazy-pages"] + self.__tls
self.__page_server_p = self.__criu_act("page-server", opts = ps_opts, nowait = True)
self.__lazy_pages_p = self.__criu_act("lazy-pages", opts = lp_opts, nowait = True)
ps_opts = [
"--pidfile", "ps.pid", "--port", "12345", "--lazy-pages"
] + self.__tls
self.__page_server_p = self.__criu_act("page-server",
opts=ps_opts,
nowait=True)
self.__lazy_pages_p = self.__criu_act("lazy-pages",
opts=lp_opts,
nowait=True)
r_opts += ["--lazy-pages"]
if self.__leave_stopped:
@ -1246,8 +1328,9 @@ class criu:
@staticmethod
def check(feature):
return criu_cli.run("check", ["--no-default-config", "-v0",
"--feature", feature], opts['criu_bin']) == 0
return criu_cli.run(
"check", ["--no-default-config", "-v0", "--feature", feature],
opts['criu_bin']) == 0
@staticmethod
def available():
@ -1258,12 +1341,14 @@ class criu:
def kill(self):
if self.__lazy_pages_p:
self.__lazy_pages_p.terminate()
print("criu lazy-pages exited with %s" % self.__lazy_pages_p.wait())
print("criu lazy-pages exited with %s" %
self.__lazy_pages_p.wait())
grep_errors(os.path.join(self.__ddir(), "lazy-pages.log"))
self.__lazy_pages_p = None
if self.__page_server_p:
self.__page_server_p.terminate()
print("criu page-server exited with %s" % self.__page_server_p.wait())
print("criu page-server exited with %s" %
self.__page_server_p.wait())
grep_errors(os.path.join(self.__ddir(), "page-server.log"))
self.__page_server_p = None
if self.__dump_process:
@ -1354,6 +1439,7 @@ def cr(cr_api, test, opts):
# Additional checks that can be done outside of test process
def get_visible_state(test):
maps = {}
files = {}
@ -1364,9 +1450,11 @@ def get_visible_state(test):
return ({}, {}, {})
r = re.compile('^[0-9]+$')
pids = filter(lambda p: r.match(p), os.listdir("/proc/%s/root/proc/" % test.getpid()))
pids = filter(lambda p: r.match(p),
os.listdir("/proc/%s/root/proc/" % test.getpid()))
for pid in pids:
files[pid] = set(os.listdir("/proc/%s/root/proc/%s/fd" % (test.getpid(), pid)))
files[pid] = set(
os.listdir("/proc/%s/root/proc/%s/fd" % (test.getpid(), pid)))
cmaps = [[0, 0, ""]]
last = 0
@ -1376,7 +1464,8 @@ def get_visible_state(test):
m.append(mp.split()[1])
f = "/proc/%s/root/proc/%s/map_files/%s" % (test.getpid(), pid, mp.split()[0])
f = "/proc/%s/root/proc/%s/map_files/%s" % (test.getpid(), pid,
mp.split()[0])
if os.access(f, os.F_OK):
st = os.lstat(f)
m.append(oct(st.st_mode))
@ -1388,12 +1477,16 @@ def get_visible_state(test):
last += 1
mapsfd.close()
maps[pid] = set(map(lambda x: '%x-%x %s' % (x[0], x[1], " ".join(x[2:])), cmaps))
maps[pid] = set(
map(lambda x: '%x-%x %s' % (x[0], x[1], " ".join(x[2:])), cmaps))
cmounts = []
try:
r = re.compile(r"^\S+\s\S+\s\S+\s(\S+)\s(\S+)\s(\S+)\s[^-]*?(shared)?[^-]*?(master)?[^-]*?-")
with open("/proc/%s/root/proc/%s/mountinfo" % (test.getpid(), pid)) as mountinfo:
r = re.compile(
r"^\S+\s\S+\s\S+\s(\S+)\s(\S+)\s(\S+)\s[^-]*?(shared)?[^-]*?(master)?[^-]*?-"
)
with open("/proc/%s/root/proc/%s/mountinfo" %
(test.getpid(), pid)) as mountinfo:
for m in mountinfo:
cmounts.append(r.match(m).groups())
except IOError as e:
@ -1442,9 +1535,11 @@ def check_visible_state(test, state, opts):
if '--link-remap' in test.getdopts():
import glob
link_remap_list = glob.glob(os.path.dirname(test.getname()) + '/link_remap*')
link_remap_list = glob.glob(
os.path.dirname(test.getname()) + '/link_remap*')
if link_remap_list:
print("%s: link-remap files left: %s" % (test.getname(), link_remap_list))
print("%s: link-remap files left: %s" %
(test.getname(), link_remap_list))
raise test_fail_exc("link remaps left")
@ -1631,7 +1726,8 @@ def do_run_test(tname, tdesc, flavs, opts):
cr_api.kill()
try_run_hook(t, ["--clean"])
if cr_api.logs():
add_to_report(cr_api.logs(), tname.replace('/', '_') + "_" + f + "/images")
add_to_report(cr_api.logs(),
tname.replace('/', '_') + "_" + f + "/images")
if opts['keep_img'] == 'never':
cr_api.cleanup()
# When option --keep-going not specified this exit
@ -1672,9 +1768,12 @@ class Launcher:
att = 0
reportname = os.path.join(report_dir, "criu-testreport.tap")
junitreport = os.path.join(report_dir, "criu-testreport.xml")
while os.access(reportname, os.F_OK) or os.access(junitreport, os.F_OK):
reportname = os.path.join(report_dir, "criu-testreport" + ".%d.tap" % att)
junitreport = os.path.join(report_dir, "criu-testreport" + ".%d.xml" % att)
while os.access(reportname, os.F_OK) or os.access(
junitreport, os.F_OK):
reportname = os.path.join(report_dir,
"criu-testreport" + ".%d.tap" % att)
junitreport = os.path.join(report_dir,
"criu-testreport" + ".%d.xml" % att)
att += 1
self.__junit_file = open(junitreport, 'a')
@ -1683,7 +1782,9 @@ class Launcher:
self.__file_report = open(reportname, 'a')
print(u"TAP version 13", file=self.__file_report)
print(u"# Hardware architecture: " + arch, file=self.__file_report)
print(u"# Timestamp: " + now.strftime("%Y-%m-%d %H:%M") + " (GMT+1)", file=self.__file_report)
print(u"# Timestamp: " + now.strftime("%Y-%m-%d %H:%M") +
" (GMT+1)",
file=self.__file_report)
print(u"# ", file=self.__file_report)
print(u"1.." + str(nr_tests), file=self.__file_report)
with open("/proc/sys/kernel/tainted") as taintfd:
@ -1695,7 +1796,8 @@ class Launcher:
def __show_progress(self, msg):
perc = int(self.__nr * 16 / self.__total)
print("=== Run %d/%d %s %s" % (self.__nr, self.__total, '=' * perc + '-' * (16 - perc), msg))
print("=== Run %d/%d %s %s" %
(self.__nr, self.__total, '=' * perc + '-' * (16 - perc), msg))
def skip(self, name, reason):
print("Skipping %s (%s)" % (name, reason))
@ -1719,7 +1821,8 @@ class Launcher:
with open("/proc/sys/kernel/tainted") as taintfd:
taint = taintfd.read()
if self.__taint != taint:
raise Exception("The kernel is tainted: %r (%r)" % (taint, self.__taint))
raise Exception("The kernel is tainted: %r (%r)" %
(taint, self.__taint))
if test_flag(desc, 'excl'):
self.wait_all()
@ -1727,11 +1830,12 @@ class Launcher:
self.__nr += 1
self.__show_progress(name)
nd = ('nocr', 'norst', 'pre', 'iters', 'page_server', 'sibling', 'stop', 'empty_ns',
'fault', 'keep_img', 'report', 'snaps', 'sat', 'script', 'rpc', 'lazy_pages',
'join_ns', 'dedup', 'sbs', 'freezecg', 'user', 'dry_run', 'noauto_dedup',
'remote_lazy_pages', 'show_stats', 'lazy_migrate', 'tls',
'criu_bin', 'crit_bin')
nd = ('nocr', 'norst', 'pre', 'iters', 'page_server', 'sibling',
'stop', 'empty_ns', 'fault', 'keep_img', 'report', 'snaps',
'sat', 'script', 'rpc', 'lazy_pages', 'join_ns', 'dedup', 'sbs',
'freezecg', 'user', 'dry_run', 'noauto_dedup',
'remote_lazy_pages', 'show_stats', 'lazy_migrate',
'tls', 'criu_bin', 'crit_bin')
arg = repr((name, desc, flavor, {d: self.__opts[d] for d in nd}))
if self.__use_log:
@ -1743,8 +1847,15 @@ class Launcher:
sub = subprocess.Popen(["./zdtm_ct", "zdtm.py"],
env=dict(os.environ, CR_CT_TEST_INFO=arg),
stdout = log, stderr = subprocess.STDOUT, close_fds = True)
self.__subs[sub.pid] = {'sub': sub, 'log': logf, 'name': name, "start": time.time()}
stdout=log,
stderr=subprocess.STDOUT,
close_fds=True)
self.__subs[sub.pid] = {
'sub': sub,
'log': logf,
'name': name,
"start": time.time()
}
if test_flag(desc, 'excl'):
self.wait()
@ -1771,21 +1882,26 @@ class Launcher:
sub = self.__subs.pop(pid)
tc = None
if self.__junit_test_cases is not None:
tc = TestCase(sub['name'], elapsed_sec=time.time() - sub['start'])
tc = TestCase(sub['name'],
elapsed_sec=time.time() - sub['start'])
self.__junit_test_cases.append(tc)
if status != 0:
self.__fail = True
failed_flavor = decode_flav(os.WEXITSTATUS(status))
self.__failed.append([sub['name'], failed_flavor])
if self.__file_report:
testline = u"not ok %d - %s # flavor %s" % (self.__runtest, sub['name'], failed_flavor)
testline = u"not ok %d - %s # flavor %s" % (
self.__runtest, sub['name'], failed_flavor)
with open(sub['log']) as sublog:
output = sublog.read()
details = {'output': output}
tc.add_error_info(output=output)
print(testline, file=self.__file_report)
print("%s" % yaml.safe_dump(details, explicit_start=True,
explicit_end=True, default_style='|'), file=self.__file_report)
print("%s" % yaml.safe_dump(details,
explicit_start=True,
explicit_end=True,
default_style='|'),
file=self.__file_report)
if sub['log']:
add_to_output(sub['log'])
else:
@ -1795,7 +1911,8 @@ class Launcher:
if sub['log']:
with open(sub['log']) as sublog:
print("%s" % sublog.read().encode('ascii', 'ignore').decode('utf-8'))
print("%s" % sublog.read().encode(
'ascii', 'ignore').decode('utf-8'))
os.unlink(sub['log'])
return True
@ -1824,20 +1941,23 @@ class Launcher:
if not opts['fault'] and check_core_files():
self.__fail = True
if self.__file_report:
ts = TestSuite(opts['title'], self.__junit_test_cases, os.getenv("NODE_NAME"))
ts = TestSuite(opts['title'], self.__junit_test_cases,
os.getenv("NODE_NAME"))
self.__junit_file.write(TestSuite.to_xml_string([ts]))
self.__junit_file.close()
self.__file_report.close()
if opts['keep_going']:
if self.__fail:
print_sep("%d TEST(S) FAILED (TOTAL %d/SKIPPED %d)"
% (len(self.__failed), self.__total, self.__nr_skip), "#")
print_sep(
"%d TEST(S) FAILED (TOTAL %d/SKIPPED %d)" %
(len(self.__failed), self.__total, self.__nr_skip), "#")
for failed in self.__failed:
print(" * %s(%s)" % (failed[0], failed[1]))
else:
print_sep("ALL TEST(S) PASSED (TOTAL %d/SKIPPED %d)"
% (self.__total, self.__nr_skip), "#")
print_sep(
"ALL TEST(S) PASSED (TOTAL %d/SKIPPED %d)" %
(self.__total, self.__nr_skip), "#")
if self.__fail:
print_sep("FAIL", "#")
@ -1860,12 +1980,9 @@ def all_tests(opts):
continue
files.append(fp)
excl = list(map(lambda x: os.path.join(desc['dir'], x), desc['exclude']))
tlist = filter(lambda x:
not x.endswith('.checkskip') and
not x.endswith('.hook') and
x not in excl,
map(lambda x: x.strip(), files)
)
tlist = filter(
lambda x: not x.endswith('.checkskip') and not x.endswith('.hook') and
x not in excl, map(lambda x: x.strip(), files))
return tlist
@ -1966,7 +2083,9 @@ def run_tests(opts):
torun = list(torun)
if opts['keep_going'] and len(torun) < 2:
print("[WARNING] Option --keep-going is more useful when running multiple tests")
print(
"[WARNING] Option --keep-going is more useful when running multiple tests"
)
opts['keep_going'] = False
if opts['exclude']:
@ -1983,17 +2102,23 @@ def run_tests(opts):
if opts['join_ns']:
if subprocess.Popen(["ip", "netns", "add", "zdtm_netns"]).wait():
raise Exception("Unable to create a network namespace")
if subprocess.Popen(["ip", "netns", "exec", "zdtm_netns", "ip", "link", "set", "up", "dev", "lo"]).wait():
if subprocess.Popen([
"ip", "netns", "exec", "zdtm_netns", "ip", "link", "set", "up",
"dev", "lo"
]).wait():
raise Exception("ip link set up dev lo")
if opts['lazy_pages'] or opts['remote_lazy_pages'] or opts['lazy_migrate']:
uffd = criu.check("uffd")
uffd_noncoop = criu.check("uffd-noncoop")
if not uffd:
raise Exception("UFFD is not supported, cannot run with --lazy-pages")
raise Exception(
"UFFD is not supported, cannot run with --lazy-pages")
if not uffd_noncoop:
# Most tests will work with 4.3 - 4.11
print("[WARNING] Non-cooperative UFFD is missing, some tests might spuriously fail")
print(
"[WARNING] Non-cooperative UFFD is missing, some tests might spuriously fail"
)
launcher = Launcher(opts, len(torun))
try:
@ -2047,7 +2172,8 @@ def run_tests(opts):
launcher.skip(t, "samens test in the same namespace")
continue
if opts['lazy_pages'] or opts['remote_lazy_pages'] or opts['lazy_migrate']:
if opts['lazy_pages'] or opts['remote_lazy_pages'] or opts[
'lazy_migrate']:
if test_flag(tdesc, 'nolazy'):
launcher.skip(t, "lazy pages are not supported")
continue
@ -2137,8 +2263,7 @@ class group:
# which will call all tests' scripts in turn
def __dump_meta(self, fname, ext):
scripts = filter(lambda names: os.access(names[1], os.X_OK),
map(lambda test: (test, test + ext),
self.__tests))
map(lambda test: (test, test + ext), self.__tests))
if scripts:
f = open(fname + ext, "w")
f.write("#!/bin/sh -e\n")
@ -2250,7 +2375,9 @@ if 'CR_CT_TEST_INFO' in os.environ:
sys.exit(status)
p = argparse.ArgumentParser("CRIU test suite")
p.add_argument("--debug", help = "Print what's being executed", action = 'store_true')
p.add_argument("--debug",
help="Print what's being executed",
action='store_true')
p.add_argument("--set", help="Which set of tests to use", default='zdtm')
sp = p.add_subparsers(help="Use --help for list of actions")
@ -2262,53 +2389,115 @@ rp.add_argument("-t", "--test", help = "Test name", action = 'append')
rp.add_argument("-T", "--tests", help="Regexp")
rp.add_argument("-F", "--from", help="From file")
rp.add_argument("-f", "--flavor", help="Flavor to run")
rp.add_argument("-x", "--exclude", help = "Exclude tests from --all run", action = 'append')
rp.add_argument("-x",
"--exclude",
help="Exclude tests from --all run",
action='append')
rp.add_argument("--sibling", help = "Restore tests as siblings", action = 'store_true')
rp.add_argument("--join-ns", help = "Restore tests and join existing namespace", action = 'store_true')
rp.add_argument("--empty-ns", help = "Restore tests in empty net namespace", action = 'store_true')
rp.add_argument("--sibling",
help="Restore tests as siblings",
action='store_true')
rp.add_argument("--join-ns",
help="Restore tests and join existing namespace",
action='store_true')
rp.add_argument("--empty-ns",
help="Restore tests in empty net namespace",
action='store_true')
rp.add_argument("--pre", help="Do some pre-dumps before dump (n[:pause])")
rp.add_argument("--snaps", help = "Instead of pre-dumps do full dumps", action = 'store_true')
rp.add_argument("--dedup", help = "Auto-deduplicate images on iterations", action = 'store_true')
rp.add_argument("--noauto-dedup", help = "Manual deduplicate images on iterations", action = 'store_true')
rp.add_argument("--nocr", help = "Do not CR anything, just check test works", action = 'store_true')
rp.add_argument("--norst", help = "Don't restore tasks, leave them running after dump", action = 'store_true')
rp.add_argument("--stop", help = "Check that --leave-stopped option stops ps tree.", action = 'store_true')
rp.add_argument("--iters", help = "Do CR cycle several times before check (n[:pause])")
rp.add_argument("--snaps",
help="Instead of pre-dumps do full dumps",
action='store_true')
rp.add_argument("--dedup",
help="Auto-deduplicate images on iterations",
action='store_true')
rp.add_argument("--noauto-dedup",
help="Manual deduplicate images on iterations",
action='store_true')
rp.add_argument("--nocr",
help="Do not CR anything, just check test works",
action='store_true')
rp.add_argument("--norst",
help="Don't restore tasks, leave them running after dump",
action='store_true')
rp.add_argument("--stop",
help="Check that --leave-stopped option stops ps tree.",
action='store_true')
rp.add_argument("--iters",
help="Do CR cycle several times before check (n[:pause])")
rp.add_argument("--fault", help="Test fault injection")
rp.add_argument("--sat", help = "Generate criu strace-s for sat tool (restore is fake, images are kept)", action = 'store_true')
rp.add_argument("--sbs", help = "Do step-by-step execution, asking user for keypress to continue", action = 'store_true')
rp.add_argument(
"--sat",
help="Generate criu strace-s for sat tool (restore is fake, images are kept)",
action='store_true')
rp.add_argument(
"--sbs",
help="Do step-by-step execution, asking user for keypress to continue",
action='store_true')
rp.add_argument("--freezecg", help="Use freeze cgroup (path:state)")
rp.add_argument("--user", help="Run CRIU as regular user", action='store_true')
rp.add_argument("--rpc", help = "Run CRIU via RPC rather than CLI", action = 'store_true')
rp.add_argument("--rpc",
help="Run CRIU via RPC rather than CLI",
action='store_true')
rp.add_argument("--page-server", help = "Use page server dump", action = 'store_true')
rp.add_argument("--page-server",
help="Use page server dump",
action='store_true')
rp.add_argument("--remote",
help="Use remote option for diskless C/R",
action='store_true')
rp.add_argument("-p", "--parallel", help="Run test in parallel")
rp.add_argument("--dry-run", help="Don't run tests, just pretend to", action='store_true')
rp.add_argument("--dry-run",
help="Don't run tests, just pretend to",
action='store_true')
rp.add_argument("--script", help="Add script to get notified by criu")
rp.add_argument("-k", "--keep-img", help = "Whether or not to keep images after test",
choices = ['always', 'never', 'failed'], default = 'failed')
rp.add_argument("-k",
"--keep-img",
help="Whether or not to keep images after test",
choices=['always', 'never', 'failed'],
default='failed')
rp.add_argument("--report", help="Generate summary report in directory")
rp.add_argument("--keep-going", help = "Keep running tests in spite of failures", action = 'store_true')
rp.add_argument("--ignore-taint", help = "Don't care about a non-zero kernel taint flag", action = 'store_true')
rp.add_argument("--lazy-pages", help = "restore pages on demand", action = 'store_true')
rp.add_argument("--lazy-migrate", help = "restore pages on demand", action = 'store_true')
rp.add_argument("--remote-lazy-pages", help = "simulate lazy migration", action = 'store_true')
rp.add_argument("--keep-going",
help="Keep running tests in spite of failures",
action='store_true')
rp.add_argument("--ignore-taint",
help="Don't care about a non-zero kernel taint flag",
action='store_true')
rp.add_argument("--lazy-pages",
help="restore pages on demand",
action='store_true')
rp.add_argument("--lazy-migrate",
help="restore pages on demand",
action='store_true')
rp.add_argument("--remote-lazy-pages",
help="simulate lazy migration",
action='store_true')
rp.add_argument("--tls", help="use TLS for migration", action='store_true')
rp.add_argument("--title", help="A test suite title", default="criu")
rp.add_argument("--show-stats", help = "Show criu statistics", action = 'store_true')
rp.add_argument("--criu-bin", help = "Path to criu binary", default = '../criu/criu')
rp.add_argument("--crit-bin", help = "Path to crit binary", default = '../crit/crit')
rp.add_argument("--show-stats",
help="Show criu statistics",
action='store_true')
rp.add_argument("--criu-bin",
help="Path to criu binary",
default='../criu/criu')
rp.add_argument("--crit-bin",
help="Path to crit binary",
default='../crit/crit')
lp = sp.add_parser("list", help="List tests")
lp.set_defaults(action=list_tests)
lp.add_argument('-i', '--info', help = "Show more info about tests", action = 'store_true')
lp.add_argument('-i',
'--info',
help="Show more info about tests",
action='store_true')
gp = sp.add_parser("group", help="Generate groups")
gp.set_defaults(action=group_tests)
gp.add_argument("-m", "--max-size", help="Maximum number of tests in group")
gp.add_argument("-n", "--name", help="Common name for group tests")
gp.add_argument("-x", "--exclude", help = "Exclude tests from --all run", action = 'append')
gp.add_argument("-x",
"--exclude",
help="Exclude tests from --all run",
action='append')
cp = sp.add_parser("clean", help="Clean something")
cp.set_defaults(action=clean_stuff)