Skip to content

Commit

Permalink
Create device snapshot.
Browse files Browse the repository at this point in the history
  • Loading branch information
ser-io committed Oct 2, 2024
1 parent 1eb18e6 commit 23a223d
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 0 deletions.
4 changes: 4 additions & 0 deletions frontend/src/host_orchestrator/api/v1/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ type ListUploadDirectoriesResponse struct {
Items []*UploadDirectory `json:"items"`
}

type CreateSnapshotResponse struct {
SnapshotID string `json:"snapshot_id"`
}

type EmptyResponse struct{}

type StopCVDResponse = EmptyResponse
1 change: 1 addition & 0 deletions frontend/src/host_orchestrator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ func main() {
RootDir: *imRootDir,
ArtifactsRootDir: filepath.Join(*imRootDir, "artifacts"),
CVDBugReportsDir: filepath.Join(*imRootDir, "cvdbugreports"),
SnapshotsRootDir: filepath.Join(*imRootDir, "snapshots"),
}

var cvdUser *user.User
Expand Down
25 changes: 25 additions & 0 deletions frontend/src/host_orchestrator/orchestrator/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ func (c *Controller) AddRoutes(router *mux.Router) {
httpHandler(newExecCVDCommandHandler(c.Config, c.OperationManager, "stop"))).Methods("POST")
router.Handle("/cvds/{group}/{name}/:powerwash",
httpHandler(newExecCVDCommandHandler(c.Config, c.OperationManager, "powerwash"))).Methods("POST")
router.Handle("/cvds/{group}/{name}/snapshots",
httpHandler(newCreateSnapshotHandler(c.Config, c.OperationManager))).Methods("POST")
router.Handle("/operations", httpHandler(&listOperationsHandler{om: c.OperationManager})).Methods("GET")
router.Handle("/operations/{name}", httpHandler(&getOperationHandler{om: c.OperationManager})).Methods("GET")
// The expected response of the operation in case of success. If the original method returns no data on
Expand Down Expand Up @@ -270,6 +272,29 @@ func (h *execCVDCommandHandler) Handle(r *http.Request) (interface{}, error) {
return NewExecCVDCommandAction(opts).Run()
}

type createSnapshotHandler struct {
Config Config
OM OperationManager
}

func newCreateSnapshotHandler(c Config, om OperationManager) *createSnapshotHandler {
return &createSnapshotHandler{Config: c, OM: om}
}

func (h *createSnapshotHandler) Handle(r *http.Request) (interface{}, error) {
vars := mux.Vars(r)
group := vars["group"]
name := vars["name"]
opts := CreateSnapshotActionOpts{
Selector: CVDSelector{Group: group, Name: name},
Paths: h.Config.Paths,
OperationManager: h.OM,
ExecContext: exec.CommandContext,
CVDUser: h.Config.CVDUser,
}
return NewCreateSnapshotAction(opts).Run()
}

type getCVDLogsHandler struct {
Config Config
}
Expand Down
100 changes: 100 additions & 0 deletions frontend/src/host_orchestrator/orchestrator/createsnapshotaction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright 2024 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 CreateSnapshotActionOpts struct {
Selector CVDSelector
Paths IMPaths
OperationManager OperationManager
ExecContext ExecContext
CVDUser *user.User
}

type CreateSnapshotAction struct {
selector CVDSelector
paths IMPaths
om OperationManager
execContext cvd.CVDExecContext
}

func NewCreateSnapshotAction(opts CreateSnapshotActionOpts) *CreateSnapshotAction {
return &CreateSnapshotAction{
selector: opts.Selector,
paths: opts.Paths,
om: opts.OperationManager,
execContext: newCVDExecContext(opts.ExecContext, opts.CVDUser),
}
}

func (a *CreateSnapshotAction) Run() (apiv1.Operation, error) {
if err := createDir(a.paths.SnapshotsRootDir); err != nil {
return apiv1.Operation{}, err
}
op := a.om.New()
go func(op apiv1.Operation) {
result := &OperationResult{}
result.Value, result.Error = a.createSnapshot(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 *CreateSnapshotAction) createSnapshot(op apiv1.Operation) (*apiv1.CreateSnapshotResponse, error) {
if err := a.suspend(); err != nil {
return nil, operator.NewInternalError("cvd suspend failed", err)
}
snapshotID := op.Name
dir := filepath.Join(a.paths.SnapshotsRootDir, snapshotID)
if err := a.takeSnapshot(dir); err != nil {
return nil, operator.NewInternalError("cvd snapshot_take failed", err)
}
if err := a.resume(); err != nil {
return nil, operator.NewInternalError("cvd resume failed", err)
}
return &apiv1.CreateSnapshotResponse{SnapshotID: snapshotID}, nil
}

func (a *CreateSnapshotAction) suspend() error {
args := a.selector.ToCVDCLI()
args = append(args, "suspend")
cmd := cvd.NewCommand(a.execContext, args, cvd.CommandOpts{})
return cmd.Run()
}

func (a *CreateSnapshotAction) resume() error {
args := a.selector.ToCVDCLI()
args = append(args, "resume")
cmd := cvd.NewCommand(a.execContext, args, cvd.CommandOpts{})
return cmd.Run()
}

func (a *CreateSnapshotAction) takeSnapshot(dir string) error {
args := a.selector.ToCVDCLI()
args = append(args, "snapshot_take", "--snapshot_path", dir)
cmd := cvd.NewCommand(a.execContext, args, cvd.CommandOpts{})
return cmd.Run()
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type IMPaths struct {
RootDir string
ArtifactsRootDir string
CVDBugReportsDir string
SnapshotsRootDir string
}

type CVDSelector struct {
Expand Down

0 comments on commit 23a223d

Please sign in to comment.