Commit 12fb7f5a authored by Radostin Stoyanov's avatar Radostin Stoyanov Committed by Andrei Vagin

Go-criu clean up

The Go bindings for CRIU and the P.Haul extension have been moved into
a separate repository.

This patch removes the following from the criu-dev branch:

- lib/go/*
- phaul/*
- scripts/travis/phaul

The removed files are available in

https://github.com/checkpoint-restore/go-criuSigned-off-by: 's avatarRadostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@gmail.com>
parent 44a10467
......@@ -39,7 +39,9 @@ injection and libsoccr for TCP connections checkpoint-restore.
True [live migration](https://criu.org/Live_migration) using CRIU is possible, but doing
all the steps by hands might be complicated. The [phaul sub-project](https://criu.org/P.Haul)
provides a Go library that encapsulates most of the complexity.
provides a Go library that encapsulates most of the complexity. This library and the Go bindings
for CRIU are stored in the [go-criu](https://github.com/checkpoint-restore/go-criu) repository.
### Parasite code injection
......
all: test
test: rpc
GOPATH=$(shell pwd):/usr/share/gocode go build -o test test
rpc:
mkdir -p src/rpc/
protoc --go_out=src/rpc/ --proto_path=../../images/ ../../images/rpc.proto
package criu
import (
"errors"
"fmt"
"github.com/golang/protobuf/proto"
"os"
"os/exec"
"rpc"
"strconv"
"syscall"
)
type Criu struct {
swrk_cmd *exec.Cmd
swrk_sk *os.File
}
func MakeCriu() *Criu {
return &Criu{}
}
func (c *Criu) Prepare() error {
fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET, 0)
if err != nil {
return err
}
cln := os.NewFile(uintptr(fds[0]), "criu-xprt-cln")
syscall.CloseOnExec(fds[0])
srv := os.NewFile(uintptr(fds[1]), "criu-xprt-srv")
defer srv.Close()
args := []string{"swrk", strconv.Itoa(fds[1])}
cmd := exec.Command("criu", args...)
err = cmd.Start()
if err != nil {
cln.Close()
return err
}
c.swrk_cmd = cmd
c.swrk_sk = cln
return nil
}
func (c *Criu) Cleanup() {
if c.swrk_cmd != nil {
c.swrk_sk.Close()
c.swrk_sk = nil
c.swrk_cmd.Wait()
c.swrk_cmd = nil
}
}
func (c *Criu) sendAndRecv(req_b []byte) ([]byte, int, error) {
cln := c.swrk_sk
_, err := cln.Write(req_b)
if err != nil {
return nil, 0, err
}
resp_b := make([]byte, 2*4096)
n, err := cln.Read(resp_b)
if err != nil {
return nil, 0, err
}
return resp_b, n, nil
}
func (c *Criu) doSwrk(req_type rpc.CriuReqType, opts *rpc.CriuOpts, nfy CriuNotify) error {
req := rpc.CriuReq{
Type: &req_type,
Opts: opts,
}
if nfy != nil {
opts.NotifyScripts = proto.Bool(true)
}
if c.swrk_cmd == nil {
err := c.Prepare()
if err != nil {
return err
}
defer c.Cleanup()
}
for {
req_b, err := proto.Marshal(&req)
if err != nil {
return err
}
resp_b, resp_s, err := c.sendAndRecv(req_b)
if err != nil {
return err
}
resp := &rpc.CriuResp{}
err = proto.Unmarshal(resp_b[:resp_s], resp)
if err != nil {
return err
}
if !resp.GetSuccess() {
return fmt.Errorf("operation failed (msg:%s err:%d)",
resp.GetCrErrmsg(), resp.GetCrErrno())
}
resp_type := resp.GetType()
if resp_type == req_type {
break
}
if resp_type != rpc.CriuReqType_NOTIFY {
return errors.New("unexpected responce")
}
if nfy == nil {
return errors.New("unexpected notify")
}
notify := resp.GetNotify()
switch notify.GetScript() {
case "pre-dump":
err = nfy.PreDump()
case "post-dump":
err = nfy.PostDump()
case "pre-restore":
err = nfy.PreRestore()
case "post-restore":
err = nfy.PostRestore(notify.GetPid())
case "network-lock":
err = nfy.NetworkLock()
case "network-unlock":
err = nfy.NetworkUnlock()
case "setup-namespaces":
err = nfy.SetupNamespaces(notify.GetPid())
case "post-setup-namespaces":
err = nfy.PostSetupNamespaces()
case "post-resume":
err = nfy.PostResume()
default:
err = nil
}
if err != nil {
return err
}
req = rpc.CriuReq{
Type: &resp_type,
NotifySuccess: proto.Bool(true),
}
}
return nil
}
func (c *Criu) Dump(opts rpc.CriuOpts, nfy CriuNotify) error {
return c.doSwrk(rpc.CriuReqType_DUMP, &opts, nfy)
}
func (c *Criu) Restore(opts rpc.CriuOpts, nfy CriuNotify) error {
return c.doSwrk(rpc.CriuReqType_RESTORE, &opts, nfy)
}
func (c *Criu) PreDump(opts rpc.CriuOpts, nfy CriuNotify) error {
return c.doSwrk(rpc.CriuReqType_PRE_DUMP, &opts, nfy)
}
func (c *Criu) StartPageServer(opts rpc.CriuOpts) error {
return c.doSwrk(rpc.CriuReqType_PAGE_SERVER, &opts, nil)
}
package criu
type CriuNotify interface {
PreDump() error
PostDump() error
PreRestore() error
PostRestore(pid int32) error
NetworkLock() error
NetworkUnlock() error
SetupNamespaces(pid int32) error
PostSetupNamespaces() error
PostResume() error
}
type CriuNoNotify struct {
}
func (c CriuNoNotify) PreDump() error {
return nil
}
func (c CriuNoNotify) PostDump() error {
return nil
}
func (c CriuNoNotify) PreRestore() error {
return nil
}
func (c CriuNoNotify) PostRestore(pid int32) error {
return nil
}
func (c CriuNoNotify) NetworkLock() error {
return nil
}
func (c CriuNoNotify) NetworkUnlock() error {
return nil
}
func (c CriuNoNotify) SetupNamespaces(pid int32) error {
return nil
}
func (c CriuNoNotify) PostSetupNamespaces() error {
return nil
}
func (c CriuNoNotify) PostResume() error {
return nil
}
package main
import (
"criu"
"fmt"
"github.com/golang/protobuf/proto"
"os"
"rpc"
"strconv"
)
type TestNfy struct {
criu.CriuNoNotify
}
func (c TestNfy) PreDump() error {
fmt.Printf("TEST PRE DUMP\n")
return nil
}
func doDump(c *criu.Criu, pid_s string, img_dir string, pre bool, prev_img string) error {
fmt.Printf("Dumping\n")
pid, _ := strconv.Atoi(pid_s)
img, err := os.Open(img_dir)
if err != nil {
return fmt.Errorf("can't open image dir (%s)", err)
}
defer img.Close()
opts := rpc.CriuOpts{
Pid: proto.Int32(int32(pid)),
ImagesDirFd: proto.Int32(int32(img.Fd())),
LogLevel: proto.Int32(4),
LogFile: proto.String("dump.log"),
}
if prev_img != "" {
opts.ParentImg = proto.String(prev_img)
opts.TrackMem = proto.Bool(true)
}
if pre {
err = c.PreDump(opts, TestNfy{})
} else {
err = c.Dump(opts, TestNfy{})
}
if err != nil {
return fmt.Errorf("dump fail (%s)", err)
}
return nil
}
// Usage: test $act $pid $images_dir
func main() {
c := criu.MakeCriu()
act := os.Args[1]
switch act {
case "dump":
err := doDump(c, os.Args[2], os.Args[3], false, "")
if err != nil {
fmt.Print(err)
os.Exit(1)
}
case "dump2":
err := c.Prepare()
if err != nil {
fmt.Print(err)
os.Exit(1)
}
err = doDump(c, os.Args[2], os.Args[3]+"/pre", true, "")
if err != nil {
fmt.Printf("pre-dump failed")
fmt.Print(err)
os.Exit(1)
}
err = doDump(c, os.Args[2], os.Args[3], false, "./pre")
if err != nil {
fmt.Printf("dump failed")
fmt.Print(err)
os.Exit(1)
}
c.Cleanup()
case "restore":
fmt.Printf("Restoring\n")
img, err := os.Open(os.Args[2])
if err != nil {
fmt.Printf("can't open image dir")
os.Exit(1)
}
defer img.Close()
opts := rpc.CriuOpts{
ImagesDirFd: proto.Int32(int32(img.Fd())),
LogLevel: proto.Int32(4),
LogFile: proto.String("restore.log"),
}
err = c.Restore(opts, nil)
if err != nil {
fmt.Printf("Error:")
fmt.Print(err)
fmt.Printf("\n")
os.Exit(1)
}
default:
fmt.Printf("unknown action\n")
os.Exit(1)
}
fmt.Printf("Success\n")
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment