mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-07 19:14:10 +00:00
API: add sandbox waitprocess api
It waits a process inside the container of a sandbox. Signed-off-by: Peng Tao <bergwolf@gmail.com>
This commit is contained in:
parent
992c895eaa
commit
45970ba796
@ -168,6 +168,9 @@ type agent interface {
|
|||||||
// processListContainer will list the processes running inside the container
|
// processListContainer will list the processes running inside the container
|
||||||
processListContainer(sandbox *Sandbox, c Container, options ProcessListOptions) (ProcessList, error)
|
processListContainer(sandbox *Sandbox, c Container, options ProcessListOptions) (ProcessList, error)
|
||||||
|
|
||||||
|
// waitProcess will wait for the exit code of a process
|
||||||
|
waitProcess(c *Container, processID string) (int32, error)
|
||||||
|
|
||||||
// onlineCPUMem will online CPUs and Memory inside the Sandbox.
|
// onlineCPUMem will online CPUs and Memory inside the Sandbox.
|
||||||
// This function should be called after hot adding vCPUs or Memory.
|
// This function should be called after hot adding vCPUs or Memory.
|
||||||
// cpus specifies the number of CPUs that were added and the agent should online
|
// cpus specifies the number of CPUs that were added and the agent should online
|
||||||
|
@ -724,6 +724,16 @@ func (c *Container) enter(cmd Cmd) (*Process, error) {
|
|||||||
return process, nil
|
return process, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Container) wait(processID string) (int32, error) {
|
||||||
|
if c.state.State != StateReady &&
|
||||||
|
c.state.State != StateRunning {
|
||||||
|
return 0, fmt.Errorf("Container not ready or running, " +
|
||||||
|
"impossible to wait")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.sandbox.agent.waitProcess(c, processID)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Container) kill(signal syscall.Signal, all bool) error {
|
func (c *Container) kill(signal syscall.Signal, all bool) error {
|
||||||
if c.sandbox.state.State != StateReady && c.sandbox.state.State != StateRunning {
|
if c.sandbox.state.State != StateReady && c.sandbox.state.State != StateRunning {
|
||||||
return fmt.Errorf("Sandbox not ready or running, impossible to signal the container")
|
return fmt.Errorf("Sandbox not ready or running, impossible to signal the container")
|
||||||
|
@ -359,3 +359,29 @@ func TestContainerEnterErrorsOnContainerStates(t *testing.T) {
|
|||||||
_, err = c.enter(cmd)
|
_, err = c.enter(cmd)
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContainerWaitErrorState(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
c := &Container{
|
||||||
|
sandbox: &Sandbox{
|
||||||
|
state: State{
|
||||||
|
State: StateRunning,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
processID := "foobar"
|
||||||
|
|
||||||
|
// Container state undefined
|
||||||
|
_, err := c.wait(processID)
|
||||||
|
assert.Error(err)
|
||||||
|
|
||||||
|
// Container paused
|
||||||
|
c.state.State = StatePaused
|
||||||
|
_, err = c.wait(processID)
|
||||||
|
assert.Error(err)
|
||||||
|
|
||||||
|
// Container stopped
|
||||||
|
c.state.State = StateStopped
|
||||||
|
_, err = c.wait(processID)
|
||||||
|
assert.Error(err)
|
||||||
|
}
|
||||||
|
@ -806,3 +806,8 @@ func (h *hyper) check() error {
|
|||||||
// cc-agent does not support check
|
// cc-agent does not support check
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *hyper) waitProcess(c *Container, processID string) (int32, error) {
|
||||||
|
// cc-agent does not support wait process
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
@ -57,6 +57,7 @@ type VCSandbox interface {
|
|||||||
StartContainer(containerID string) (VCContainer, error)
|
StartContainer(containerID string) (VCContainer, error)
|
||||||
StatusContainer(containerID string) (ContainerStatus, error)
|
StatusContainer(containerID string) (ContainerStatus, error)
|
||||||
EnterContainer(containerID string, cmd Cmd) (VCContainer, *Process, error)
|
EnterContainer(containerID string, cmd Cmd) (VCContainer, *Process, error)
|
||||||
|
WaitProcess(containerID, processID string) (int32, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VCContainer is the Container interface
|
// VCContainer is the Container interface
|
||||||
|
@ -937,6 +937,18 @@ func (k *kataAgent) check() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *kataAgent) waitProcess(c *Container, processID string) (int32, error) {
|
||||||
|
resp, err := k.sendReq(&grpc.WaitProcessRequest{
|
||||||
|
ContainerId: c.id,
|
||||||
|
ExecId: processID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.(*grpc.WaitProcessResponse).Status, nil
|
||||||
|
}
|
||||||
|
|
||||||
type reqFunc func(context.Context, interface{}, ...golangGrpc.CallOption) (interface{}, error)
|
type reqFunc func(context.Context, interface{}, ...golangGrpc.CallOption) (interface{}, error)
|
||||||
|
|
||||||
func (k *kataAgent) installReqFunc(c *kataclient.AgentClient) {
|
func (k *kataAgent) installReqFunc(c *kataclient.AgentClient) {
|
||||||
@ -979,6 +991,9 @@ func (k *kataAgent) installReqFunc(c *kataclient.AgentClient) {
|
|||||||
k.reqHandlers["grpc.ListProcessesRequest"] = func(ctx context.Context, req interface{}, opts ...golangGrpc.CallOption) (interface{}, error) {
|
k.reqHandlers["grpc.ListProcessesRequest"] = func(ctx context.Context, req interface{}, opts ...golangGrpc.CallOption) (interface{}, error) {
|
||||||
return k.client.ListProcesses(ctx, req.(*grpc.ListProcessesRequest), opts...)
|
return k.client.ListProcesses(ctx, req.(*grpc.ListProcessesRequest), opts...)
|
||||||
}
|
}
|
||||||
|
k.reqHandlers["grpc.WaitProcessRequest"] = func(ctx context.Context, req interface{}, opts ...golangGrpc.CallOption) (interface{}, error) {
|
||||||
|
return k.client.WaitProcess(ctx, req.(*grpc.WaitProcessRequest), opts...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *kataAgent) sendReq(request interface{}) (interface{}, error) {
|
func (k *kataAgent) sendReq(request interface{}) (interface{}, error) {
|
||||||
@ -992,7 +1007,7 @@ func (k *kataAgent) sendReq(request interface{}) (interface{}, error) {
|
|||||||
msgName := proto.MessageName(request.(proto.Message))
|
msgName := proto.MessageName(request.(proto.Message))
|
||||||
handler := k.reqHandlers[msgName]
|
handler := k.reqHandlers[msgName]
|
||||||
if msgName == "" || handler == nil {
|
if msgName == "" || handler == nil {
|
||||||
return nil, fmt.Errorf("Invalid request type")
|
return nil, errors.New("Invalid request type")
|
||||||
}
|
}
|
||||||
|
|
||||||
return handler(context.Background(), request)
|
return handler(context.Background(), request)
|
||||||
|
@ -217,6 +217,7 @@ var reqList = []interface{}{
|
|||||||
&pb.RemoveContainerRequest{},
|
&pb.RemoveContainerRequest{},
|
||||||
&pb.SignalProcessRequest{},
|
&pb.SignalProcessRequest{},
|
||||||
&pb.CheckRequest{},
|
&pb.CheckRequest{},
|
||||||
|
&pb.WaitProcessRequest{},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKataAgentSendReq(t *testing.T) {
|
func TestKataAgentSendReq(t *testing.T) {
|
||||||
|
@ -83,3 +83,8 @@ func (n *noopAgent) onlineCPUMem(cpus uint32) error {
|
|||||||
func (n *noopAgent) check() error {
|
func (n *noopAgent) check() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// waitProcess is the Noop agent process waiter. It does nothing.
|
||||||
|
func (n *noopAgent) waitProcess(c *Container, processID string) (int32, error) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
@ -104,3 +104,8 @@ func (p *Sandbox) EnterContainer(containerID string, cmd vc.Cmd) (vc.VCContainer
|
|||||||
func (p *Sandbox) Monitor() (chan error, error) {
|
func (p *Sandbox) Monitor() (chan error, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WaitProcess implements the VCSandbox function of the same name.
|
||||||
|
func (p *Sandbox) WaitProcess(containerID, processID string) (int32, error) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
@ -587,6 +587,20 @@ func (s *Sandbox) Monitor() (chan error, error) {
|
|||||||
return s.monitor.newWatcher()
|
return s.monitor.newWatcher()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WaitProcess waits on a container process and return its exit code
|
||||||
|
func (s *Sandbox) WaitProcess(containerID, processID string) (int32, error) {
|
||||||
|
if s.state.State != StateRunning {
|
||||||
|
return 0, fmt.Errorf("Sandbox not running")
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := s.findContainer(containerID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.wait(processID)
|
||||||
|
}
|
||||||
|
|
||||||
func createAssets(sandboxConfig *SandboxConfig) error {
|
func createAssets(sandboxConfig *SandboxConfig) error {
|
||||||
kernel, err := newAsset(sandboxConfig, kernelAsset)
|
kernel, err := newAsset(sandboxConfig, kernelAsset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1408,3 +1408,33 @@ func TestMonitor(t *testing.T) {
|
|||||||
|
|
||||||
s.monitor.stop()
|
s.monitor.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWaitProcess(t *testing.T) {
|
||||||
|
s, err := testCreateSandbox(t, testSandboxID, MockHypervisor, newHypervisorConfig(nil, nil), NoopAgentType, NoopNetworkModel, NetworkConfig{}, nil, nil)
|
||||||
|
assert.Nil(t, err, "VirtContainers should not allow empty sandboxes")
|
||||||
|
defer cleanUp()
|
||||||
|
|
||||||
|
contID := "foo"
|
||||||
|
execID := "bar"
|
||||||
|
_, err = s.WaitProcess(contID, execID)
|
||||||
|
assert.NotNil(t, err, "Wait process in stopped sandbox should fail")
|
||||||
|
|
||||||
|
err = s.start()
|
||||||
|
assert.Nil(t, err, "Failed to start sandbox: %v", err)
|
||||||
|
|
||||||
|
_, err = s.WaitProcess(contID, execID)
|
||||||
|
assert.NotNil(t, err, "Wait process in non-existing container should fail")
|
||||||
|
|
||||||
|
contConfig := newTestContainerConfigNoop(contID)
|
||||||
|
_, err = s.CreateContainer(contConfig)
|
||||||
|
assert.Nil(t, err, "Failed to create container %+v in sandbox %+v: %v", contConfig, s, err)
|
||||||
|
|
||||||
|
_, err = s.WaitProcess(contID, execID)
|
||||||
|
assert.Nil(t, err, "Wait process in ready container failed: %v", err)
|
||||||
|
|
||||||
|
_, err = s.StartContainer(contID)
|
||||||
|
assert.Nil(t, err, "Start container failed: %v", err)
|
||||||
|
|
||||||
|
_, err = s.WaitProcess(contID, execID)
|
||||||
|
assert.Nil(t, err, "Wait process failed: %v", err)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user