blob: 1a5fac63f1a809b2ae27397f337b95d931277565 [file] [edit]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package cros
import (
"context"
"time"
"go.chromium.org/luci/common/errors"
"go.chromium.org/infra/cros/recovery/internal/components"
"go.chromium.org/infra/cros/recovery/internal/components/cros/android"
"go.chromium.org/infra/cros/recovery/internal/components/linux"
"go.chromium.org/infra/cros/recovery/internal/log"
"go.chromium.org/infra/cros/recovery/internal/retry"
"go.chromium.org/infra/cros/recovery/tlw"
)
const (
DefaultPingCount = 2
// Default timeout for simple timeout check
DefaultSSHTimeout = 10 * time.Second
)
// IsPingable checks whether the resource is pingable
func IsPingable(ctx context.Context, count int, ping components.Pinger) error {
err := ping(ctx, count)
return errors.WrapIf(err, "is pingable")
}
// IsNotPingable checks whether the resource is not pingable
func IsNotPingable(ctx context.Context, count int, ping components.Pinger) error {
if err := ping(ctx, count); err != nil {
log.Debugf(ctx, "Resource is not pingable, but expected!")
return nil
}
return errors.Reason("not pingable: is pingable")
}
// IsAccessible checks whether the resource is accessible via ssh or adb
func IsAccessible(ctx context.Context, run components.Runner, timeout time.Duration) error {
_, err := run(ctx, timeout, "true")
return errors.WrapIf(err, "is accessible")
}
// IsFileSystemWritable confirms the stateful file systems are writable.
//
// The standard linux response to certain unexpected file system errors
// (including hardware errors in block devices) is to change the file
// system status to read-only. This checks that it hasn't happened.
//
// The test doesn't check various bind mounts; those are expected to
// fail the same way as their underlying main mounts. Whether the
// Linux kernel can guarantee that is untested...
func IsFileSystemWritable(ctx context.Context, run components.Runner, testDirs []string) error {
for _, testDir := range testDirs {
if err := linux.IsPathWritable(ctx, run, testDir); err != nil {
return errors.Annotate(err, "file system writable")
}
log.Debugf(ctx, "Directory %s is writable.", testDir)
}
return nil
}
const (
PingRetryInterval = 5 * time.Second
AccessRetryInterval = 10 * time.Second
)
// WaitUntilPingable waiting resource to be pingable.
func WaitUntilPingable(ctx context.Context, waitTime, waitInterval time.Duration, countPerAttempt int, ping components.Pinger) error {
return retry.WithTimeout(ctx, waitInterval, waitTime, func() error {
return IsPingable(ctx, countPerAttempt, ping)
}, "wait until ping")
}
// WaitUntilNotPingable waiting resource to be not pingable.
func WaitUntilNotPingable(ctx context.Context, waitTime, waitInterval time.Duration, countPerAttempt int, ping components.Pinger) error {
return retry.WithTimeout(ctx, waitInterval, waitTime, func() error {
return IsNotPingable(ctx, countPerAttempt, ping)
}, "wait until not pingable")
}
// WaitUntilSSHable waiting resource to be sshable.
func WaitUntilSSHable(ctx context.Context, waitTime, waitInterval time.Duration, run components.Runner) error {
return retry.WithTimeout(ctx, waitInterval, waitTime, func() error {
return IsAccessible(ctx, run, DefaultSSHTimeout)
}, "wait until sshable")
}
// WaitUntilDutAccessible waiting on DUT until accessible.
// First try to ping and then ssh or adb to the DUT based on underlying OS type.
func WaitUntilDutAccessible(ctx context.Context, dut *tlw.Dut, waitTime, waitInterval time.Duration, run components.Runner, ping components.Pinger) error {
return retry.WithTimeout(ctx, waitInterval, waitTime, func() error {
if err := IsPingable(ctx, DefaultPingCount, ping); err != nil {
return err
}
// If that is android then before check access we need verify that device is connected to ADB.
if dut.GetChromeos().GetIsAndroidBased() {
forceReconnect := false
if err := android.ADBConnect(ctx, 3, time.Second, forceReconnect, 3*time.Second, dut); err != nil {
return err
}
}
return IsAccessible(ctx, run, DefaultSSHTimeout)
}, "wait until accessible")
}