Adding impl for tar image overwrite
In order to comply with Test Before Uprev, we add the capability to
overwrite files as provided in a linked tar.
BUG=None
TEST=unit
Cq-Depend: chromium:3182687
Change-Id: Ic287a8639c07d02a54bc12f00e94d3f6a935391a
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/3183181
Tested-by: Jaques Clapauch <jaquesc@google.com>
Auto-Submit: Jaques Clapauch <jaquesc@google.com>
Commit-Queue: Jaques Clapauch <jaquesc@google.com>
Reviewed-by: Sean McAllister <smcallis@google.com>
diff --git a/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/crosservice/crosservice.go b/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/crosservice/crosservice.go
index 7d56ef7..fbe4d60 100644
--- a/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/crosservice/crosservice.go
+++ b/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/crosservice/crosservice.go
@@ -24,6 +24,7 @@
type CrOSService struct {
connection services.ServiceAdapterInterface
imagePath *conf.StoragePath
+ overwritePayload *conf.StoragePath
preserverStateful bool
dlcSpecs []*api.InstallCrosRequest_DLCSpec
}
@@ -32,6 +33,7 @@
return CrOSService{
connection: services.NewServiceAdapter(dutName, dutClient, wiringConn, req.GetPreventReboot()),
imagePath: req.CrosImagePath,
+ overwritePayload: req.OverwritePayload,
preserverStateful: req.PreserveStateful,
dlcSpecs: req.DlcSpecs,
}
@@ -39,10 +41,11 @@
// NewCrOSServiceFromExistingConnection is equivalent to the above constructor,
// but recycles a ServiceAdapter. Generally useful for tests.
-func NewCrOSServiceFromExistingConnection(conn services.ServiceAdapterInterface, imagePath *conf.StoragePath, preserverStateful bool, dlcSpecs []*api.InstallCrosRequest_DLCSpec) CrOSService {
+func NewCrOSServiceFromExistingConnection(conn services.ServiceAdapterInterface, imagePath *conf.StoragePath, overwritePayload *conf.StoragePath, preserverStateful bool, dlcSpecs []*api.InstallCrosRequest_DLCSpec) CrOSService {
return CrOSService{
connection: conn,
imagePath: imagePath,
+ overwritePayload: overwritePayload,
preserverStateful: preserverStateful,
dlcSpecs: dlcSpecs,
}
@@ -278,6 +281,26 @@
return err
}
+func (c *CrOSService) OverwiteInstall(ctx context.Context) error {
+ if c.overwritePayload == nil {
+ log.Printf("skipping overwrite install, because none was specified.")
+ return nil
+ }
+ if c.overwritePayload.HostType == conf.StoragePath_LOCAL || c.overwritePayload.HostType == conf.StoragePath_HOSTTYPE_UNSPECIFIED {
+ return fmt.Errorf("only GS copying is implemented")
+ }
+ url, err := c.connection.CopyData(ctx, c.overwritePayload.GetPath())
+ if err != nil {
+ return fmt.Errorf("failed to get GS Cache URL, %s", err)
+ }
+ _, err = c.connection.RunCmd(ctx, curlWithRetries, []string{
+ url,
+ "|",
+ "tar", "xf", "-", "-C", "/",
+ })
+ return err
+}
+
// StopDLCService stops a DLC service
func (c *CrOSService) StopDLCService(ctx context.Context) {
if _, err := c.connection.RunCmd(ctx, "stop", []string{"dlcservice"}); err != nil {
diff --git a/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/crosservice/postinstallstate.go b/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/crosservice/postinstallstate.go
index 42ff0fe..0d04b2e 100644
--- a/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/crosservice/postinstallstate.go
+++ b/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/crosservice/postinstallstate.go
@@ -30,6 +30,10 @@
return fmt.Errorf("failed to provision stateful, %s", err)
}
+ if err := s.service.OverwiteInstall(ctx); err != nil {
+ return fmt.Errorf("failed to overwite install, %s", err)
+ }
+
if err := s.service.connection.Restart(ctx); err != nil {
return fmt.Errorf("failed to restart dut, %s", err)
}
diff --git a/src/chromiumos/test/provision/cmd/provisionserver/provisionserver_test.go b/src/chromiumos/test/provision/cmd/provisionserver/provisionserver_test.go
index f4312e0..530f9c5 100644
--- a/src/chromiumos/test/provision/cmd/provisionserver/provisionserver_test.go
+++ b/src/chromiumos/test/provision/cmd/provisionserver/provisionserver_test.go
@@ -33,6 +33,7 @@
HostType: conf.StoragePath_GS,
Path: "path/to/image",
},
+ nil,
false,
[]*api.InstallCrosRequest_DLCSpec{{Id: "1"}},
)
@@ -159,6 +160,7 @@
HostType: conf.StoragePath_GS,
Path: "path/to/image",
},
+ nil,
false,
[]*api.InstallCrosRequest_DLCSpec{{Id: "1"}},
)
@@ -242,6 +244,7 @@
HostType: conf.StoragePath_GS,
Path: "path/to/image",
},
+ nil,
false,
[]*api.InstallCrosRequest_DLCSpec{{Id: "1"}},
)
@@ -325,6 +328,7 @@
HostType: conf.StoragePath_GS,
Path: "path/to/image",
},
+ nil,
true, // <- preserve stateful
[]*api.InstallCrosRequest_DLCSpec{},
)
@@ -361,6 +365,7 @@
HostType: conf.StoragePath_GS,
Path: "path/to/image",
},
+ nil,
true, // <- preserve stateful
[]*api.InstallCrosRequest_DLCSpec{},
)
@@ -398,6 +403,7 @@
HostType: conf.StoragePath_GS,
Path: "path/to/image",
},
+ nil,
false,
[]*api.InstallCrosRequest_DLCSpec{},
)
@@ -425,6 +431,7 @@
HostType: conf.StoragePath_GS,
Path: "path/to/image",
},
+ nil,
false,
[]*api.InstallCrosRequest_DLCSpec{{Id: "1"}},
)
@@ -450,6 +457,49 @@
}
}
+func TestPostInstallOverwriteWhenSpecified(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ sam := mock_services.NewMockServiceAdapterInterface(ctrl)
+
+ cs := crosservice.NewCrOSServiceFromExistingConnection(
+ sam,
+ &conf.StoragePath{
+ HostType: conf.StoragePath_GS,
+ Path: "path/to/image",
+ },
+ &conf.StoragePath{
+ HostType: conf.StoragePath_GS,
+ Path: "path/to/image/overwite.tar",
+ },
+ false,
+ []*api.InstallCrosRequest_DLCSpec{{Id: "1"}},
+ )
+
+ ctx := context.Background()
+
+ // Install -> PostInstall
+ st := cs.GetFirstState().Next()
+
+ gomock.InOrder(
+ sam.EXPECT().RunCmd(gomock.Any(), gomock.Eq("echo"), gomock.Eq([]string{"'fast keepimg'", ">", "/mnt/stateful_partition/factory_install_reset"})).Return("", nil),
+ sam.EXPECT().Restart(gomock.Any()).Return(nil),
+ sam.EXPECT().RunCmd(gomock.Any(), gomock.Eq("stop"), gomock.Eq([]string{"ui"})).Return("", nil),
+ sam.EXPECT().RunCmd(gomock.Any(), gomock.Eq("stop"), gomock.Eq([]string{"update-engine"})).Return("", nil),
+ sam.EXPECT().CopyData(gomock.Any(), gomock.Eq("path/to/image/stateful.tgz")).Return("stateful.url", nil),
+ sam.EXPECT().RunCmd(gomock.Any(), gomock.Eq(""), gomock.Eq([]string{"rm -rf /mnt/stateful_partition/.update_available /mnt/stateful_partition/var_new /mnt/stateful_partition/dev_image_new", "&&", "curl -S -s -v -# -C - --retry 3 --retry-delay 60 stateful.url | tar --ignore-command-error --overwrite --directory=/mnt/stateful_partition -xzf -", "&&", "echo -n clobber > /mnt/stateful_partition/.update_available"})).Return("", nil),
+ sam.EXPECT().CopyData(gomock.Any(), gomock.Eq("path/to/image/overwite.tar")).Return("overwrite.url.tar", nil),
+ sam.EXPECT().RunCmd(gomock.Any(), gomock.Eq("curl -S -s -v -# -C - --retry 3 --retry-delay 60"), gomock.Eq([]string{"overwrite.url.tar", "|", "tar", "xf", "-", "-C", "/"})).Return("", nil),
+ sam.EXPECT().Restart(gomock.Any()).Return(nil),
+ )
+
+ if err := st.Execute(ctx); err != nil {
+ t.Fatalf("failed post-install state: %v", err)
+ }
+
+}
+
func TestLaCrOSInstallStateTransitions(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()