Skip to content

Commit

Permalink
feat(region,host,climc): container exec sync (yunionio#20377)
Browse files Browse the repository at this point in the history
  • Loading branch information
zexi committed May 28, 2024
1 parent 8a0c2d3 commit d8c4a28
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 19 deletions.
1 change: 1 addition & 0 deletions cmd/climc/shell/compute/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func init() {
cmd.BatchPerform("start", new(options.ContainerStartOptions))
cmd.BatchPerform("syncstatus", new(options.ContainerIdsOptions))
cmd.Perform("save-volume-mount-image", new(options.ContainerSaveVolumeMountImage))
cmd.Perform("exec-sync", new(options.ContainerExecSyncOptions))

type UpdateSpecOptions struct {
ID string `help:"ID or name of server" json:"-"`
Expand Down
12 changes: 12 additions & 0 deletions pkg/apis/compute/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,15 @@ type ContainerExecInput struct {
Command []string `json:"command"`
Tty bool `json:"tty"`
}

type ContainerExecSyncInput struct {
Command []string `json:"command"`
// Timeout in seconds to stop the command. Default: 0 (run forever).
Timeout int64 `json:"timeout"`
}

type ContainerExecSyncResponse struct {
Stdout string `json:"stdout"`
Stderr string `json:"stderr"`
ExitCode int32 `json:"exit_code"`
}
9 changes: 9 additions & 0 deletions pkg/compute/guestdrivers/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,15 @@ func (p *SPodDriver) RequestExecContainer(ctx context.Context, userCred mcclient
return nil
}

func (p *SPodDriver) RequestExecSyncContainer(ctx context.Context, userCred mcclient.TokenCredential, container *models.SContainer, input *api.ContainerExecSyncInput) (jsonutils.JSONObject, error) {
pod := container.GetPod()
host, _ := pod.GetHost()
url := fmt.Sprintf("%s/pods/%s/containers/%s/exec-sync", host.ManagerUri, pod.GetId(), container.GetId())
header := mcclient.GetTokenHeaders(userCred)
_, ret, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, jsonutils.Marshal(input), false)
return ret, err
}

func (p *SPodDriver) OnDeleteGuestFinalCleanup(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential) error {
// clean disk records in DB
return guest.DeleteAllDisksInDB(ctx, userCred)
Expand Down
13 changes: 3 additions & 10 deletions pkg/compute/models/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -560,16 +560,9 @@ func (c *SContainer) GetDetailsExecInfo(ctx context.Context, userCred mcclient.T
return out, nil
}

/*func (c *SContainer) PerformExec(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
func (c *SContainer) PerformExecSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.ContainerExecSyncInput) (jsonutils.JSONObject, error) {
if c.Status != api.CONTAINER_STATUS_RUNNING {
return nil, httperrors.NewInvalidStatusError("Can't exec container in status %s", c.Status)
}
input := new(api.ContainerExecInput)
if err := query.Unmarshal(input); err != nil {
return nil, errors.Wrapf(err, "unmarshal query to input: %s", query)
}
if err := c.GetPodDriver().RequestExecContainer(ctx, userCred, c, input); err != nil {
return nil, errors.Wrap(err, "RequestExecContainer")
}
return nil, nil
}*/
return c.GetPodDriver().RequestExecSyncContainer(ctx, userCred, c, input)
}
4 changes: 3 additions & 1 deletion pkg/compute/models/pod_driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package models
import (
"context"

"yunion.io/x/jsonutils"

"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/mcclient"
Expand All @@ -39,5 +41,5 @@ type IPodDriver interface {
RequestSyncContainerStatus(ctx context.Context, userCred mcclient.TokenCredential, task IContainerTask) error
RequestPullContainerImage(ctx context.Context, userCred mcclient.TokenCredential, task IContainerTask) error
RequestSaveVolumeMountImage(ctx context.Context, userCred mcclient.TokenCredential, task IContainerTask) error
RequestExecContainer(ctx context.Context, userCred mcclient.TokenCredential, ctr *SContainer, input *compute.ContainerExecInput) error
RequestExecSyncContainer(ctx context.Context, userCred mcclient.TokenCredential, ctr *SContainer, input *compute.ContainerExecSyncInput) (jsonutils.JSONObject, error)
}
22 changes: 22 additions & 0 deletions pkg/hostman/guestman/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ type PodInstance interface {
PullImage(ctx context.Context, userCred mcclient.TokenCredential, ctrId string, input *hostapi.ContainerPullImageInput) (jsonutils.JSONObject, error)
SaveVolumeMountToImage(ctx context.Context, userCred mcclient.TokenCredential, input *hostapi.ContainerSaveVolumeMountToImageInput, ctrId string) (jsonutils.JSONObject, error)
ExecContainer(ctx context.Context, userCred mcclient.TokenCredential, ctrId string, input *computeapi.ContainerExecInput) (*url.URL, error)
ContainerExecSync(ctx context.Context, userCred mcclient.TokenCredential, ctrId string, input *computeapi.ContainerExecSyncInput) (jsonutils.JSONObject, error)
}

type sContainer struct {
Expand Down Expand Up @@ -1588,3 +1589,24 @@ func (s *sPodGuestInstance) DeleteSnapshot(ctx context.Context, params *SDeleteD
res.Set("deleted", jsonutils.JSONTrue)
return res, nil
}

func (s *sPodGuestInstance) ContainerExecSync(ctx context.Context, userCred mcclient.TokenCredential, ctrId string, input *computeapi.ContainerExecSyncInput) (jsonutils.JSONObject, error) {
ctrCriId, err := s.getContainerCRIId(ctrId)
if err != nil {
return nil, errors.Wrap(err, "get container cri id")
}
cli := s.getCRI().GetRuntimeClient()
resp, err := cli.ExecSync(ctx, &runtimeapi.ExecSyncRequest{
ContainerId: ctrCriId,
Cmd: input.Command,
Timeout: input.Timeout,
})
if err != nil {
return nil, errors.Wrapf(err, "exec sync %#v to %s", input.Command, ctrCriId)
}
return jsonutils.Marshal(&computeapi.ContainerExecSyncResponse{
Stdout: string(resp.Stdout),
Stderr: string(resp.Stderr),
ExitCode: resp.ExitCode,
}), nil
}
43 changes: 35 additions & 8 deletions pkg/hostman/guestman/podhandlers/podhandlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,15 @@ type containerDelayActionParams struct {
body jsonutils.JSONObject
}

func containerSyncActionHandler(cf containerActionFunc) appsrv.FilterHandler {
return _containerActionHandler(cf, true)
}

func containerActionHandler(cf containerActionFunc) appsrv.FilterHandler {
return _containerActionHandler(cf, false)
}

func _containerActionHandler(cf containerActionFunc, isSync bool) appsrv.FilterHandler {
return auth.Authenticate(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
params, _, body := appsrv.FetchEnv(ctx, w, r)
podId := params[POD_ID]
Expand All @@ -73,11 +81,21 @@ func containerActionHandler(cf containerActionFunc) appsrv.FilterHandler {
containerId: ctrId,
body: body,
}
hostutils.DelayTask(ctx, func(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
dp := params.(*containerDelayActionParams)
return cf(ctx, userCred, dp.pod, dp.containerId, dp.body)
}, delayParams)
hostutils.ResponseOk(ctx, w)
if isSync {
data, err := cf(ctx, userCred, delayParams.pod, delayParams.containerId, delayParams.body)
if err != nil {
hostutils.Response(ctx, w, httperrors.NewBadRequestError("error: %v", err))
return
}
hostutils.Response(ctx, w, data)
return
} else {
hostutils.DelayTask(ctx, func(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
dp := params.(*containerDelayActionParams)
return cf(ctx, userCred, dp.pod, dp.containerId, dp.body)
}, delayParams)
hostutils.ResponseOk(ctx, w)
}
})
}

Expand All @@ -98,7 +116,8 @@ func AddPodHandlers(prefix string, app *appsrv.Application) {
}

execWorker := appsrv.NewWorkerManager("exec-worker", 16, appsrv.DEFAULT_BACKLOG, false)
app.AddHandler3(newExecContainerHandler("POST", fmt.Sprintf("%s/pods/%s/containers/%s/exec", prefix, POD_ID, CONTAINER_ID), execWorker))
app.AddHandler3(newExecContainerHandler("POST", fmt.Sprintf("%s/pods/%s/containers/%s/exec-sync", prefix, POD_ID, CONTAINER_ID), execWorker, containerSyncActionHandler(containerExecSync)))
app.AddHandler3(newExecContainerHandler("POST", fmt.Sprintf("%s/pods/%s/containers/%s/exec", prefix, POD_ID, CONTAINER_ID), execWorker, execContainer()))
}

func pullImage(ctx context.Context, userCred mcclient.TokenCredential, pod guestman.PodInstance, ctrId string, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
Expand Down Expand Up @@ -145,11 +164,11 @@ func saveVolumeMountToImage(ctx context.Context, userCred mcclient.TokenCredenti
return pod.SaveVolumeMountToImage(ctx, userCred, input, ctrId)
}

func newExecContainerHandler(method, urlPath string, worker *appsrv.SWorkerManager) *appsrv.SHandlerInfo {
func newExecContainerHandler(method, urlPath string, worker *appsrv.SWorkerManager, hander appsrv.FilterHandler) *appsrv.SHandlerInfo {
hi := &appsrv.SHandlerInfo{}
hi.SetMethod(method)
hi.SetPath(urlPath)
hi.SetHandler(execContainer())
hi.SetHandler(hander)
hi.SetProcessTimeout(1 * time.Hour)
hi.SetWorkerManager(worker)
return hi
Expand Down Expand Up @@ -198,3 +217,11 @@ func proxyStream(w http.ResponseWriter, r *http.Request, url *url.URL) {
handler := proxy.NewUpgradeAwareHandler(url, nil, false, true, &responder{})
handler.ServeHTTP(w, r)
}

func containerExecSync(ctx context.Context, userCred mcclient.TokenCredential, pod guestman.PodInstance, containerId string, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
input := new(compute.ContainerExecSyncInput)
if err := body.Unmarshal(input); err != nil {
return nil, errors.Wrap(err, "unmarshal to ContainerExecSyncInput")
}
return pod.ContainerExecSync(ctx, userCred, containerId, input)
}
16 changes: 16 additions & 0 deletions pkg/mcclient/options/compute/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,19 @@ func (o *ContainerExecOptions) ToAPIInput() *computeapi.ContainerExecInput {
func (o *ContainerExecOptions) Params() (jsonutils.JSONObject, error) {
return jsonutils.Marshal(o.ToAPIInput()), nil
}

type ContainerExecSyncOptions struct {
ServerIdOptions
COMMAND string
Args []string
Timeout int64
}

func (o *ContainerExecSyncOptions) Params() (jsonutils.JSONObject, error) {
cmd := []string{o.COMMAND}
cmd = append(cmd, o.Args...)
return jsonutils.Marshal(&computeapi.ContainerExecSyncInput{
Command: cmd,
Timeout: o.Timeout,
}), nil
}

0 comments on commit d8c4a28

Please sign in to comment.