Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit cd925d7

Browse files
committed
runv cli refactor
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
1 parent 4332d61 commit cd925d7

30 files changed

Lines changed: 3682 additions & 550 deletions

container.go

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"os"
8+
"os/exec"
9+
"path/filepath"
10+
"syscall"
11+
12+
"github.com/golang/glog"
13+
"github.com/hyperhq/runv/api"
14+
"github.com/hyperhq/runv/hypervisor"
15+
"github.com/opencontainers/runtime-spec/specs-go"
16+
)
17+
18+
func startContainer(vm *hypervisor.Vm, container string, spec *specs.Spec, state *specs.State) error {
19+
20+
shim, err := os.FindProcess(state.Pid)
21+
if err != nil {
22+
return err
23+
}
24+
25+
err = vm.StartContainer(container)
26+
if err != nil {
27+
glog.V(1).Infof("Start Container fail: fail to start container with err: %#v\n", err)
28+
return err
29+
}
30+
31+
err = shim.Signal(syscall.SIGUSR1)
32+
if err != nil {
33+
// cli refactor todo: remove the container
34+
return err
35+
}
36+
37+
err = execPoststartHooks(spec, state)
38+
if err != nil {
39+
glog.V(1).Infof("execute Poststart hooks failed %s\n", err.Error())
40+
}
41+
42+
return nil
43+
}
44+
45+
func createContainer(options runvOptions, vm *hypervisor.Vm, container, bundle, stateRoot string, spec *specs.Spec) (shim *os.Process, err error) {
46+
containerSharedFs := filepath.Join(hypervisor.BaseDir, vm.Id, hypervisor.ShareDirTag, container)
47+
if err = setupFs(bundle, containerSharedFs, spec); err != nil {
48+
return nil, err
49+
}
50+
51+
glog.V(3).Infof("vm.AddContainer()")
52+
config := api.ContainerDescriptionFromOCF(container, spec)
53+
r := vm.AddContainer(config)
54+
if !r.IsSuccess() {
55+
return nil, fmt.Errorf("add container %s failed: %s", container, r.Message())
56+
}
57+
58+
// Prepare container state directory
59+
stateDir := filepath.Join(stateRoot, container)
60+
_, err = os.Stat(stateDir)
61+
if err == nil {
62+
glog.Errorf("Container %s exists\n", container)
63+
return nil, fmt.Errorf("Container %s exists", container)
64+
}
65+
err = os.MkdirAll(stateDir, 0644)
66+
if err != nil {
67+
glog.V(1).Infof("%s\n", err.Error())
68+
return nil, err
69+
}
70+
// Create sandbox dir symbol link in container root dir
71+
vmRootLinkPath := filepath.Join(stateDir, "sandbox")
72+
vmRootPath := sandboxPath(vm)
73+
if err = os.Symlink(vmRootPath, vmRootLinkPath); err != nil {
74+
return nil, fmt.Errorf("failed to create symbol link %q: %v", vmRootLinkPath, err)
75+
}
76+
77+
// create shim and save the state
78+
shim, err = createShim(options, container, "init")
79+
if err != nil {
80+
return nil, err
81+
}
82+
state := &specs.State{
83+
Version: spec.Version,
84+
ID: container,
85+
Pid: shim.Pid,
86+
Bundle: bundle,
87+
}
88+
glog.V(3).Infof("save state id %s, boundle %s", container, bundle)
89+
if err = saveStateFile(filepath.Join(stateDir, "state.json"), state); err != nil {
90+
return nil, err
91+
}
92+
93+
err = execPrestartHooks(spec, state)
94+
if err != nil {
95+
// cli refator todo stop container
96+
glog.V(1).Infof("execute Prestart hooks failed, %s\n", err.Error())
97+
return nil, err
98+
}
99+
100+
// If runv is launched via docker/containerd, we start netlistener to watch/collect network changes.
101+
// TODO: if runv is launched by cni compatible tools, the cni script can use `runv cni` cmdline to update the network.
102+
// Create the listener process which will enters into the netns of the shim
103+
options.withContainer = state
104+
if err = startNsListener(options, vm); err != nil {
105+
// cli refator todo stop container
106+
glog.Errorf("start ns listener fail: %v", err)
107+
return nil, err
108+
}
109+
110+
return shim, nil
111+
}
112+
113+
func deleteContainer(vm *hypervisor.Vm, container string, spec *specs.Spec, state *specs.State) error {
114+
err := execPoststopHooks(spec, state)
115+
if err != nil {
116+
glog.V(1).Infof("execute Poststop hooks failed %s\n", err.Error())
117+
return err
118+
}
119+
return nil
120+
}
121+
122+
func addProcess(options runvOptions, vm *hypervisor.Vm, container, process string, spec *specs.Process) (shim *os.Process, err error) {
123+
err = vm.AddProcess(&api.Process{
124+
Container: container,
125+
Id: process,
126+
Terminal: spec.Terminal,
127+
Args: spec.Args,
128+
Envs: spec.Env,
129+
Workdir: spec.Cwd}, nil)
130+
131+
if err != nil {
132+
glog.V(1).Infof("add process to container failed: %v\n", err)
133+
}
134+
135+
shim, err = createShim(options, container, process)
136+
if err != nil {
137+
// cli refactor todo: remove the process
138+
return nil, err
139+
}
140+
141+
// cli refactor todo (for the purpose of 'runv ps` command) save <container, process, shim-pid, spec> to persist file.
142+
143+
return shim, nil
144+
}
145+
146+
func execHook(hook specs.Hook, state *specs.State) error {
147+
b, err := json.Marshal(state)
148+
if err != nil {
149+
return err
150+
}
151+
cmd := exec.Cmd{
152+
Path: hook.Path,
153+
Args: hook.Args,
154+
Env: hook.Env,
155+
Stdin: bytes.NewReader(b),
156+
}
157+
return cmd.Run()
158+
}
159+
160+
func execPrestartHooks(rt *specs.Spec, state *specs.State) error {
161+
if rt.Hooks == nil {
162+
return nil
163+
}
164+
for _, hook := range rt.Hooks.Prestart {
165+
err := execHook(hook, state)
166+
if err != nil {
167+
return err
168+
}
169+
}
170+
171+
return nil
172+
}
173+
174+
func execPoststartHooks(rt *specs.Spec, state *specs.State) error {
175+
if rt.Hooks == nil {
176+
return nil
177+
}
178+
for _, hook := range rt.Hooks.Poststart {
179+
err := execHook(hook, state)
180+
if err != nil {
181+
glog.V(1).Infof("exec Poststart hook %s failed %s", hook.Path, err.Error())
182+
}
183+
}
184+
185+
return nil
186+
}
187+
188+
func execPoststopHooks(rt *specs.Spec, state *specs.State) error {
189+
if rt.Hooks == nil {
190+
return nil
191+
}
192+
for _, hook := range rt.Hooks.Poststop {
193+
err := execHook(hook, state)
194+
if err != nil {
195+
glog.V(1).Infof("exec Poststop hook %s failed %s", hook.Path, err.Error())
196+
}
197+
}
198+
199+
return nil
200+
}

0 commit comments

Comments
 (0)