RPC

From CRIU
Revision as of 14:01, 1 December 2014 by Efiop (talk | contribs)
Jump to navigation Jump to search

CRIU-RPC is a remote procedure call (RPC) protocol which uses Google Protocol Buffers to encode its calls. The requests are served by CRIU service launched with criu service command. It uses a SEQPACKET Unix domain socket listening at /var/run/criu-service.socket as a transport.

Protobuf messages

criu_req/criu_resp -- wrappers for requests/responses. They are to be used for transferring messages and needed to provide compatibility with an older versions of rpc. Field type in them _must_ be set accordingly to type of request/response that is stored. Types of request/response are defined in enum criu_req_type.

Request

criu_req

message criu_req {
	required criu_req_type type	= 1;

	optional criu_opts opts		= 2;
}

criu_req_type

There are 8 request/response types for now. Comments show cmdline analogs.

enum criu_req_type {
	EMPTY		= 0;
	DUMP		= 1; /* criu dump */
	RESTORE		= 2; /* criu restore */
	CHECK		= 3; /* criu check */
	PRE_DUMP	= 4; /* criu pre-dump */
	PAGE_SERVER	= 5; /* criu page-server */

	NOTIFY		= 6;

	CPUINFO_DUMP	= 7; /* criu cpuinfo dump */
	CPUINFO_CHECK	= 8; /* criu cpuinfo check */
}

criu_opts

It is used to store options.

message criu_opts {
	required int32			images_dir_fd	= 1;
	optional int32			pid		= 2; /* if not set on dump, will dump requesting process */

	optional bool			leave_running	= 3;
	optional bool			ext_unix_sk	= 4;
	optional bool			tcp_established	= 5;
	optional bool			evasive_devices	= 6;
	optional bool			shell_job	= 7;
	optional bool			file_locks	= 8;
	optional int32			log_level	= 9 [default = 2];
	optional string			log_file	= 10; /* No subdirs are allowed. Consider using work-dir */

	optional criu_page_server_info	ps		= 11;

	optional bool			notify_scripts	= 12;

	optional string			root		= 13;
	optional string			parent_img	= 14;
	optional bool			track_mem	= 15;
	optional bool			auto_dedup	= 16;

	optional int32			work_dir_fd	= 17;
	optional bool			link_remap	= 18;
	repeated criu_veth_pair		veths		= 19;

	optional uint32			cpu_cap		= 20 [default = 0xffffffff];
	optional bool			force_irmap	= 21;
	repeated string			exec_cmd	= 22;

	repeated ext_mount_map		ext_mnt		= 23;
	optional bool			manage_cgroups	= 24;
	repeated cgroup_root		cg_root		= 25;

	optional bool			rst_sibling	= 26; /* swrk only */
}

If no pid is set and type is DUMP, CRIU will dump client process by default. Note: Whole tree <pid> must have the same uid, as a client, or client's uid must be == 0, otherwise CRIU won't dump nothing at all.

Only images_dir_fd is required, all other fields may not be set. Client must open directory for/with images by himself and set images_dir_fd to it's fd. CRIU will open /proc/<client's_pid>/fd/<images_dir_fd>, so it will work, if client is in another namespace.

The logic of setting request is the same as when setting options in console. Here is an example:

#criu restore -D /path/to/imgs_dir -v4 -o restore.log

is equal to:

request.type = RESTORE;

request.opts.imgs_dir_fd	= open("/path/to/imgs_dir")
request.opts.log_level		= 4
request.opts.log_file		= "restore.log"
criu_page_server_info

Stores info about page-server.

message criu_page_server_info {
	optional string		address	= 1; /* bind address -- if not set 0.0.0.0 is used */
	optional int32		port	= 2; /* bind port -- if not set on request, autobind is used and port is returned in response */
	optional int32		pid	= 3; /* page-server pid -- returned in response */
	optional int32		fd	= 4; /* could be used to inherit fd by page-server */
}
criu_veth_pair

--veth-pair analog.

message criu_veth_pair {
	required string		if_in	= 1; /* inside veth device name */
	required string		if_out	= 2; /* outside veth device name */
};
ext_mount_map

--ext-mount-map analog.

message ext_mount_map {
	required string		key	= 1;
	required string		val	= 2;
};
cgroup_root

--cgroup-root analog.

message cgroup_root {
	optional string		ctrl	= 1;
	required string		path	= 2;
};

Response

criu_resp

message criu_resp {
	required criu_req_type		type		= 1;
	required bool			success		= 2;

	optional criu_dump_resp		dump		= 3;
	optional criu_restore_resp	restore		= 4;
	optional criu_notify		notify		= 5;
	optional criu_page_server_info	ps		= 6;
}

Field "success" reports result of processing request, while criu_***_resp store some request-specific information. The response type is set to the corresponding request type or to EMPTY to report a "generic" error.

criu_dump_resp

criu_dump_resp is used to store dump response from CRIU.

message criu_dump_resp {
	optional bool restored		= 1;
}

Field "restored" is set to "true" if process was restored.

criu_restore_resp

message criu_restore_resp {
	required int32 pid		= 1;
}

Field "pid" is set to the PID of the restored process.

criu_notify

--action-script analog.

message criu_notify {
	optional string script		= 1;
	optional int32	pid		= 2;
}

Run

Server

On a server side, CRIU creates SOCK_SEQPACKET Unix socket and listens for connections on it. After receiving criu_req, CRIU processes it, do what is requested and sends criu_resp with set request-specific criu_***_resp field back. If CRIU gets unknown type of request, it will return criu_resp with type == EMPTY and success == false.

To launch service server, run:

#criu service [options]

Options accepted by service are

--address <path>
is where to put listening socket
--pid-file <path>
is where to write pid of service process
--daemon
tells service to daemonize
-o <file>
says where to write logs
-v[N]
sets the log-level

systemd

If you are running systemd you can make service start and operate automatically. First do

make install

to make files criu.service and criu.socket appear in systemd configs (/lib/systemd/system/). Then

systemctl start criu.socket

to get /var/run/criu-service.socket, and

systemctl enable criu.socket

to make /var/run/criu-service.socket available at boot.

Client

Client, in its turn, must connect to service socket, send criu_req with request in it, and wait for a criu_resp with response. You can find examples of client programs in C and Python in test/rpc/.

With RPC facilities one can perform a self dump.

There's a library that implements simple wrappers on top of RPC.

Security

See Security.