Skip to content

Commit deec9a3

Browse files
committed
Move waiting logic for host orchestrator settlement to backend
Context: b/501288123
1 parent 7fe0489 commit deec9a3

7 files changed

Lines changed: 69 additions & 18 deletions

File tree

pkg/app/app_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ func (hc *testHostClient) GetReverseProxy() *httputil.ReverseProxy {
111111
return httputil.NewSingleHostReverseProxy(hc.url)
112112
}
113113

114+
func (hc *testHostClient) WaitForHostReady() error {
115+
return nil
116+
}
117+
114118
func TestListZonesSucceeds(t *testing.T) {
115119
controller := NewApp(&testInstanceManager{}, &testAccountManager{}, nil, nil, nil, "", nil, apiv1.InfraConfig{}, &config.Config{})
116120
ts := httptest.NewServer(controller.Handler())

pkg/app/instances/docker.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,13 @@ func (m *DockerInstanceManager) waitCreateHostOperation(host string) (*apiv1.Hos
188188
return nil, fmt.Errorf("failed to inspect docker container: %w", err)
189189
}
190190
if res.State.Running {
191+
client, err := m.GetHostClient("local", host)
192+
if err != nil {
193+
return nil, err
194+
}
195+
if err := client.WaitForHostReady(); err != nil {
196+
return nil, err
197+
}
191198
return &apiv1.HostInstance{
192199
Name: host,
193200
}, nil

pkg/app/instances/gce.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,12 @@ func (m *GCEInstanceManager) WaitOperation(zone string, user accounts.User, name
253253
if op.Status != operationStatusDone {
254254
return nil, errors.NewServiceUnavailableError("Wait for operation timed out", nil)
255255
}
256-
getter := opResultGetter{Service: m.Service, Op: op}
256+
getter := opResultGetter{
257+
Service: m.Service,
258+
Op: op,
259+
InstanceManager: m,
260+
Zone: zone,
261+
}
257262
return getter.Get()
258263
}
259264

@@ -324,8 +329,10 @@ var (
324329
)
325330

326331
type opResultGetter struct {
327-
Service *compute.Service
328-
Op *compute.Operation
332+
Service *compute.Service
333+
Op *compute.Operation
334+
InstanceManager *GCEInstanceManager
335+
Zone string
329336
}
330337

331338
func (g *opResultGetter) Get() (any, error) {
@@ -362,7 +369,19 @@ func (g *opResultGetter) buildCreateInstanceResult() (*apiv1.HostInstance, error
362369
if err != nil {
363370
return nil, toAppError(err)
364371
}
365-
return BuildHostInstance(ins)
372+
373+
host, err := BuildHostInstance(ins)
374+
if err != nil {
375+
return nil, err
376+
}
377+
client, err := g.InstanceManager.GetHostClient(g.Zone, host.Name)
378+
if err != nil {
379+
return nil, err
380+
}
381+
if err := client.WaitForHostReady(); err != nil {
382+
return nil, err
383+
}
384+
return host, nil
366385
}
367386

368387
// Converts compute API errors to AppError if relevant, return the same error otherwise

pkg/app/instances/gce_test.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"net/http/httptest"
2525
"net/url"
2626
"reflect"
27+
"strconv"
2728
"strings"
2829
"testing"
2930

@@ -572,9 +573,14 @@ func TestWaitCreateInstanceOperationSucceeds(t *testing.T) {
572573
Name: "foo",
573574
MachineType: "mt",
574575
MinCpuPlatform: "mcp",
576+
NetworkInterfaces: []*compute.NetworkInterface{
577+
{NetworkIP: "127.0.0.1"},
578+
},
575579
}
576580
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
577581
switch path := r.URL.Path; path {
582+
case "/":
583+
replyJSON(w, map[string]string{})
578584
case "/projects/google.com:test-project/zones/us-central1-a/operations/operation-1/wait":
579585
replyJSON(w, operation)
580586
case "/projects/google.com:test-project/zones/us-central1-a/instances/foo":
@@ -584,7 +590,18 @@ func TestWaitCreateInstanceOperationSucceeds(t *testing.T) {
584590
}
585591
}))
586592
defer ts.Close()
587-
im := NewGCEInstanceManager(testConfig, buildTestService(t, ts), testNameGenerator)
593+
594+
tsURL, _ := url.Parse(ts.URL)
595+
port, _ := strconv.Atoi(tsURL.Port())
596+
597+
cfg := testConfig
598+
cfg.HostOrchestratorProtocol = "http"
599+
600+
gcpCfg := *cfg.GCP
601+
gcpCfg.HostOrchestratorPort = port
602+
cfg.GCP = &gcpCfg
603+
604+
im := NewGCEInstanceManager(cfg, buildTestService(t, ts), testNameGenerator)
588605

589606
res, _ := im.WaitOperation(zone, &TestUser{}, opName)
590607

pkg/app/instances/hostclient.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"net/http"
2424
"net/http/httputil"
2525
"net/url"
26+
"time"
2627

2728
apiv1 "github.com/google/cloud-android-orchestration/api/v1"
2829
)
@@ -94,6 +95,21 @@ func (c *NetHostClient) Post(path, query string, bodyJSON any, out *HostResponse
9495
return res.StatusCode, err
9596
}
9697

98+
func (c *NetHostClient) WaitForHostReady() error {
99+
maxWait := 2 * time.Minute
100+
retryDelay := 5 * time.Second
101+
deadline := time.Now().Add(maxWait)
102+
103+
for time.Now().Before(deadline) {
104+
status, err := c.Get("/", "", nil)
105+
if err == nil && status != http.StatusBadGateway {
106+
return nil
107+
}
108+
time.Sleep(retryDelay)
109+
}
110+
return fmt.Errorf("wait for host orchestrator timed out")
111+
}
112+
97113
func (c *NetHostClient) GetReverseProxy() *httputil.ReverseProxy {
98114
devProxy := httputil.NewSingleHostReverseProxy(c.url)
99115
if c.client != http.DefaultClient {

pkg/app/instances/instances.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ type HostClient interface {
4444
Get(URLPath, URLQuery string, res *HostResponse) (int, error)
4545
Post(URLPath, URLQuery string, bodyJSON any, res *HostResponse) (int, error)
4646
GetReverseProxy() *httputil.ReverseProxy
47+
WaitForHostReady() error
4748
}
4849

4950
type HostResponse struct {

pkg/client/client.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,19 +126,6 @@ func (c *clientImpl) CreateHost(req *apiv1.CreateHostRequest) (*apiv1.HostInstan
126126
return nil, err
127127
}
128128

129-
// There is a short delay between the creation of the host and the availability of the host
130-
// orchestrator. This call ensures the host orchestrator had time to start before returning
131-
// from the this function.
132-
retryOpts := hoclient.RetryOptions{
133-
StatusCodes: []int{http.StatusBadGateway},
134-
RetryDelay: 5 * time.Second,
135-
MaxWait: 2 * time.Minute,
136-
}
137-
hostPath := fmt.Sprintf("/hosts/%s/", ins.Name)
138-
if err := c.httpHelper.NewGetRequest(hostPath).JSONResDoWithRetries(nil, retryOpts); err != nil {
139-
return nil, fmt.Errorf("unable to communicate with host orchestrator: %w", err)
140-
}
141-
142129
return ins, nil
143130
}
144131

0 commit comments

Comments
 (0)