blob: 390f35fa79881154fdf944162ff15c3e16565890 [file] [log] [blame]
// Copyright 2019 The Chromium OS 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 hostinfo
import (
"context"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"go.chromium.org/luci/common/errors"
"infra/libs/skylab/autotest/hostinfo"
)
// File represents a hostinfo file exposed for Autotest to use.
type File struct {
hostInfo *hostinfo.HostInfo
path string
}
// hostInfoSubDir is the filename of the directory for storing host info.
const hostInfoSubDir = "host_info_store"
// Expose exposes the HostInfo as a file for Autotest to use.
func Expose(hi *hostinfo.HostInfo, resultsDir string, dutHostname string) (*File, error) {
blob, err := hostinfo.Marshal(hi)
if err != nil {
return nil, errors.Annotate(err, "expose hostinfo").Err()
}
storeDir := filepath.Join(resultsDir, hostInfoSubDir)
if err := os.Mkdir(storeDir, 0755); err != nil {
return nil, errors.Annotate(err, "expose hostinfo").Err()
}
storeFile := filepath.Join(storeDir, fmt.Sprintf("%s.store", dutHostname))
if err := ioutil.WriteFile(storeFile, blob, 0644); err != nil {
return nil, errors.Annotate(err, "expose hostinfo").Err()
}
// Write the secondary host info store file.
// TODO(gregorynisbet): Remove secondary host info file or remove original host info file.
// Failure to create a secondary host info store file
// is not a serious enough error to make the whole Expose action
// unsuccessful.
content, err := hostinfo.MarshalIndent(hi)
if err != nil {
log.Printf("Expose: failed to marshalIndent hostinfo file (%#v)", err)
content = []byte{}
}
hostInfoStore2 := filepath.Join(storeDir, fmt.Sprintf("%s.host_info_store2", dutHostname))
// NOTE(gregorynisbet): we always want to create this file, even if it has length zero due to a previous error
if err := ioutil.WriteFile(hostInfoStore2, content, 0o644); err != nil {
log.Printf("Expose: failed to write file contents to path (%s)", hostInfoStore2)
}
return &File{
hostInfo: hi,
path: storeFile,
}, nil
}
// Close marks that Autotest is finished using the exposed HostInfo
// file and loads any changes back into the original HostInfo.
// Subsequent calls do nothing. This is safe to call on a nil pointer.
func (f *File) Close(ctx context.Context) error {
if f == nil {
return nil
}
if f.path == "" {
return nil
}
blob, err := ioutil.ReadFile(f.path)
if err != nil {
return errors.Annotate(err, "close exposed hostinfo").Err()
}
hi, err := hostinfo.Unmarshal(blob)
if err != nil {
return errors.Annotate(err, "close exposed hostinfo").Err()
}
f.path = ""
*f.hostInfo = *hi
return nil
}