Skip to content

Commit

Permalink
Start from snapshot.
Browse files Browse the repository at this point in the history
- This operation is also known as snapshot restore.
  • Loading branch information
ser-io committed Oct 2, 2024
1 parent 23a223d commit c945bd6
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
5 changes: 5 additions & 0 deletions frontend/src/host_orchestrator/api/v1/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,8 @@ type CreateSnapshotResponse struct {
type EmptyResponse struct{}

type StopCVDResponse = EmptyResponse

type StartCVDRequest struct {
// Start from the relevant snaphost if not empty.
SnapshotID string `json:"snapshot_id,omitempty"`
}
31 changes: 31 additions & 0 deletions frontend/src/host_orchestrator/orchestrator/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ func (c *Controller) AddRoutes(router *mux.Router) {
httpHandler(newCreateCVDBugReportHandler(c.Config, c.OperationManager))).Methods("POST")
router.Handle("/cvds/{group}/{name}",
httpHandler(newExecCVDCommandHandler(c.Config, c.OperationManager, "remove"))).Methods("DELETE")
router.Handle("/cvds/{group}/{name}/:start",
httpHandler(newStartCVDHandler(c.Config, c.OperationManager))).Methods("POST")
router.Handle("/cvds/{group}/{name}/:stop",
httpHandler(newExecCVDCommandHandler(c.Config, c.OperationManager, "stop"))).Methods("POST")
router.Handle("/cvds/{group}/{name}/:powerwash",
Expand Down Expand Up @@ -295,6 +297,35 @@ func (h *createSnapshotHandler) Handle(r *http.Request) (interface{}, error) {
return NewCreateSnapshotAction(opts).Run()
}

type startCVDHandler struct {
Config Config
OM OperationManager
}

func newStartCVDHandler(c Config, om OperationManager) *startCVDHandler {
return &startCVDHandler{Config: c, OM: om}
}

func (h *startCVDHandler) Handle(r *http.Request) (interface{}, error) {
req := &apiv1.StartCVDRequest{}
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
return nil, operator.NewBadRequestError("Malformed JSON in request", err)
}
vars := mux.Vars(r)
group := vars["group"]
name := vars["name"]
opts := StartCVDActionOpts{
Request: req,
Selector: CVDSelector{Group: group, Name: name},
Paths: h.Config.Paths,
OperationManager: h.OM,
ExecContext: exec.CommandContext,
CVDUser: h.Config.CVDUser,
}
return NewStartCVDAction(opts).Run()
}

type getCVDLogsHandler struct {
Config Config
}
Expand Down
78 changes: 78 additions & 0 deletions frontend/src/host_orchestrator/orchestrator/startcvdaction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package orchestrator

import (
"log"
"os/user"
"path/filepath"

apiv1 "github.com/google/android-cuttlefish/frontend/src/host_orchestrator/api/v1"
"github.com/google/android-cuttlefish/frontend/src/host_orchestrator/orchestrator/cvd"
"github.com/google/android-cuttlefish/frontend/src/liboperator/operator"
)

type StartCVDActionOpts struct {
Request *apiv1.StartCVDRequest
Selector CVDSelector
Paths IMPaths
OperationManager OperationManager
ExecContext ExecContext
CVDUser *user.User
}

type StartCVDAction struct {
req *apiv1.StartCVDRequest
selector CVDSelector
paths IMPaths
om OperationManager
execContext cvd.CVDExecContext
}

func NewStartCVDAction(opts StartCVDActionOpts) *StartCVDAction {
return &StartCVDAction{
req: opts.Request,
selector: opts.Selector,
paths: opts.Paths,
om: opts.OperationManager,
execContext: newCVDExecContext(opts.ExecContext, opts.CVDUser),
}
}

func (a *StartCVDAction) Run() (apiv1.Operation, error) {
op := a.om.New()
go func(op apiv1.Operation) {
result := &OperationResult{}
result.Value, result.Error = a.exec(op)
if err := a.om.Complete(op.Name, result); err != nil {
log.Printf("error completing operation %q: %v\n", op.Name, err)
}
}(op)
return op, nil
}

func (a *StartCVDAction) exec(op apiv1.Operation) (*apiv1.EmptyResponse, error) {
args := a.selector.ToCVDCLI()
args = append(args, "start")
if a.req.SnapshotID != "" {
dir := filepath.Join(a.paths.SnapshotsRootDir, a.req.SnapshotID)
args = append(args, "--snapshot_path", dir)
}
cmd := cvd.NewCommand(a.execContext, args, cvd.CommandOpts{})
if err := cmd.Run(); err != nil {
return nil, operator.NewInternalError("cvd start failed", err)
}
return &apiv1.EmptyResponse{}, nil
}

0 comments on commit c945bd6

Please sign in to comment.