Skip to content

Commit

Permalink
Introduce HO API for creating UA dir with specified name
Browse files Browse the repository at this point in the history
  • Loading branch information
0405ysj committed Feb 7, 2025
1 parent f697d8c commit c619b45
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 18 deletions.
5 changes: 3 additions & 2 deletions frontend/src/host_orchestrator/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/google/android-cuttlefish/frontend/src/host_orchestrator

go 1.17
go 1.21.0

require (
github.com/google/android-cuttlefish/frontend/src/liboperator v0.0.0-20240822182916-7bea0dafdbde
Expand All @@ -11,11 +11,12 @@ require (
)

require (
github.com/gofrs/flock v0.12.1 // indirect
github.com/golang/protobuf v1.4.3 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.3.0 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
google.golang.org/grpc v1.40.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/host_orchestrator/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down Expand Up @@ -84,6 +86,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/host_orchestrator/orchestrator/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ func (c *Controller) AddRoutes(router *mux.Router) {
router.Handle("/cvdbugreports/{uuid}", httpHandler(&deleteCVDBugReportHandler{c.Config})).Methods("DELETE")
router.Handle("/userartifacts",
httpHandler(&createUploadDirectoryHandler{c.UserArtifactsManager})).Methods("POST")
router.Handle("/userartifacts/{dir}",
httpHandler(&createUploadDirectoryHandler{c.UserArtifactsManager})).Methods("POST")
router.Handle("/userartifacts",
httpHandler(&listUploadDirectoriesHandler{c.UserArtifactsManager})).Methods("GET")
router.Handle("/userartifacts/{name}",
Expand Down Expand Up @@ -501,7 +503,8 @@ type createUploadDirectoryHandler struct {
}

func (h *createUploadDirectoryHandler) Handle(r *http.Request) (interface{}, error) {
return h.m.NewDir()
vars := mux.Vars(r)
return h.m.NewDir(vars["name"])
}

type listUploadDirectoriesHandler struct {
Expand Down
22 changes: 19 additions & 3 deletions frontend/src/host_orchestrator/orchestrator/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ func TestWaitOperationOperationIsDone(t *testing.T) {

type testUAM struct{}

func (testUAM) NewDir() (*apiv1.UploadDirectory, error) {
return &apiv1.UploadDirectory{}, nil
func (testUAM) NewDir(dir string) (*apiv1.UploadDirectory, error) {
return &apiv1.UploadDirectory{Name: dir}, nil
}

func (testUAM) ListDirs() (*apiv1.ListUploadDirectoriesResponse, error) {
Expand All @@ -209,7 +209,7 @@ func (testUAM) ExtractArtifact(string, string) error {
return nil
}

func TestCreateUploadDirectoryIsHandled(t *testing.T) {
func TestCreateUploadDirectoryWithoutDirNameIsHandled(t *testing.T) {
rr := httptest.NewRecorder()
req, err := http.NewRequest("POST", "/userartifacts", strings.NewReader("{}"))
if err != nil {
Expand All @@ -224,6 +224,22 @@ func TestCreateUploadDirectoryIsHandled(t *testing.T) {
}
}


func TestCreateUploadDirectoryWithDirNameIsHandled(t *testing.T) {
rr := httptest.NewRecorder()
req, err := http.NewRequest("POST", "/userartifacts/foo", strings.NewReader("{}"))
if err != nil {
t.Fatal(err)
}
controller := Controller{UserArtifactsManager: &testUAM{}}

makeRequest(rr, req, &controller)

if rr.Code != http.StatusOK {
t.Errorf("request was not handled. This failure implies an API breaking change.")
}
}

func TestListUploadDirectoriesIsHandled(t *testing.T) {
rr := httptest.NewRecorder()
req, err := http.NewRequest("GET", "/userartifacts", strings.NewReader("{}"))
Expand Down
39 changes: 31 additions & 8 deletions frontend/src/host_orchestrator/orchestrator/userartifacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package orchestrator

import (
"archive/zip"
"context"
"fmt"
"io"
"io/ioutil"
Expand All @@ -25,7 +26,9 @@ import (
"os/user"
"path/filepath"
"strings"
"time"

"github.com/gofrs/flock"
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"
Expand All @@ -49,7 +52,7 @@ type UserArtifactChunk struct {
type UserArtifactsManager interface {
UserArtifactsDirResolver
// Creates a new directory for uploading user artifacts in the future.
NewDir() (*apiv1.UploadDirectory, error)
NewDir(dir string) (*apiv1.UploadDirectory, error)
// List existing directories
ListDirs() (*apiv1.ListUploadDirectoriesResponse, error)
// Update artifact with the passed chunk.
Expand Down Expand Up @@ -78,11 +81,11 @@ func NewUserArtifactsManagerImpl(opts UserArtifactsManagerOpts) *UserArtifactsMa
}
}

func (m *UserArtifactsManagerImpl) NewDir() (*apiv1.UploadDirectory, error) {
func (m *UserArtifactsManagerImpl) NewDir(dir string) (*apiv1.UploadDirectory, error) {
if err := createDir(m.RootDir); err != nil {
return nil, err
}
dir, err := createNewUADir(m.RootDir, m.Owner)
dir, err := createNewUADir(m.RootDir, dir, m.Owner)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -225,13 +228,33 @@ func Unzip(dstDir string, src string, owner *user.User) error {
return nil
}

func createNewUADir(parent string, owner *user.User) (string, error) {
ctx := newCVDExecContext(exec.CommandContext, owner)
stdout, err := cvd.Exec(ctx, "mktemp", "--directory", "-p", parent)
func createNewUADir(parent string, dir string, owner *user.User) (string, error) {
flockCtx, cancel := context.WithCancel(context.TODO())
defer cancel()
lock := flock.New(filepath.Join(parent, "create_ua_dir.lock"))
defer lock.Unlock()
locked, err := lock.TryLockContext(flockCtx, time.Second)
if err != nil {
return "", err
return "", fmt.Errorf("failed acquiring create_ua_dir lock at %q: %w", parent, err)
}
if !locked {
return "", fmt.Errorf("failed acquiring create_ua_dir lock at %q", parent)
}

ctx := newCVDExecContext(exec.CommandContext, owner)
var name string
if dir == "" {
stdout, err := cvd.Exec(ctx, "mktemp", "--directory", "-p", parent)
if err != nil {
return "", err
}
name = strings.TrimRight(stdout, "\n")
} else {
name = filepath.Join(parent, dir)
if err := createDir(name); err != nil {
return "", err
}
}
name := strings.TrimRight(stdout, "\n")
// Sets permission regardless of umask.
if _, err := cvd.Exec(ctx, "chmod", "u=rwx,g=rwx,o=r", name); err != nil {
return "", err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestNewDir(t *testing.T) {
opts := UserArtifactsManagerOpts{RootDir: root}
am := NewUserArtifactsManagerImpl(opts)

upDir, err := am.NewDir()
upDir, err := am.NewDir("foo")

if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -64,8 +64,8 @@ func TestListTokens(t *testing.T) {
defer orchtesting.RemoveDir(t, root)
opts := UserArtifactsManagerOpts{RootDir: root}
am := NewUserArtifactsManagerImpl(opts)
am.NewDir()
am.NewDir()
am.NewDir("")
am.NewDir("")

res, err := am.ListDirs()

Expand Down Expand Up @@ -110,7 +110,7 @@ func TestCreateArtifactsSucceeds(t *testing.T) {
defer orchtesting.RemoveDir(t, root)
opts := UserArtifactsManagerOpts{RootDir: root}
am := NewUserArtifactsManagerImpl(opts)
upDir, err := am.NewDir()
upDir, err := am.NewDir("")
if err != nil {
t.Fatal(err)
}
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/libhoclient/host_orchestrator_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ type HostOrchestratorService interface {

// Creates a directory in the host where user artifacts can be uploaded to.
CreateUploadDir() (string, error)
CreateUploadDirWithName(uploadDir string) (string, error)

// Uploads file into the given directory.
UploadFile(uploadDir string, filename string) error
Expand Down Expand Up @@ -459,6 +460,14 @@ func (c *HostOrchestratorServiceImpl) CreateUploadDir() (string, error) {
return uploadDir.Name, nil
}

func (c *HostOrchestratorServiceImpl) CreateUploadDirWithName(dir string) (string, error) {
uploadDir := &hoapi.UploadDirectory{}
if err := c.HTTPHelper.NewPostRequest("/userartifacts/" + dir, nil).JSONResDo(uploadDir); err != nil {
return "", err
}
return uploadDir.Name, nil
}

func (c *HostOrchestratorServiceImpl) UploadFile(uploadDir string, filename string) error {
return c.UploadFileWithOptions(uploadDir, filename, DefaultUploadOptions())
}
Expand Down

0 comments on commit c619b45

Please sign in to comment.