diff --git a/README.md b/README.md index abfec1dca..e28964604 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/lib/go/.gitignore b/lib/go/.gitignore deleted file mode 100644 index 8cab5691e..000000000 --- a/lib/go/.gitignore +++ /dev/null @@ -1 +0,0 @@ -src/rpc/rpc.pb.go diff --git a/lib/go/Makefile b/lib/go/Makefile deleted file mode 100644 index c8551d609..000000000 --- a/lib/go/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -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 diff --git a/lib/go/src/criu/main.go b/lib/go/src/criu/main.go deleted file mode 100644 index 90866ea18..000000000 --- a/lib/go/src/criu/main.go +++ /dev/null @@ -1,177 +0,0 @@ -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) -} diff --git a/lib/go/src/criu/notify.go b/lib/go/src/criu/notify.go deleted file mode 100644 index 8ce16b7f7..000000000 --- a/lib/go/src/criu/notify.go +++ /dev/null @@ -1,52 +0,0 @@ -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 -} diff --git a/lib/go/src/test/main.go b/lib/go/src/test/main.go deleted file mode 100644 index ae38befdf..000000000 --- a/lib/go/src/test/main.go +++ /dev/null @@ -1,114 +0,0 @@ -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") -}