Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

snap-repair: add uc20 support #9383

Merged
merged 10 commits into from Sep 29, 2020
84 changes: 71 additions & 13 deletions cmd/snap-repair/runner.go
Expand Up @@ -38,6 +38,7 @@ import (
"syscall"
"time"

"github.com/mvo5/goconfigparser"
"gopkg.in/retry.v1"

"github.com/snapcore/snapd/arch"
Expand Down Expand Up @@ -575,11 +576,9 @@ func (run *Runner) initState() error {
os.Remove(dirs.SnapRepairStateFile)
run.state = state{}
// initialize time lower bound with image built time/seed.yaml time
info, err := os.Stat(filepath.Join(dirs.SnapSeedDir, "seed.yaml"))
if err != nil {
if err := run.findTimeLowerBound(); err != nil {
return err
}
run.moveTimeLowerBound(info.ModTime())
// initialize device info
if err := run.initDeviceInfo(); err != nil {
return err
Expand Down Expand Up @@ -655,14 +654,65 @@ func verifySignatures(a asserts.Assertion, workBS asserts.Backstore, trusted ass
return nil
}

func (run *Runner) initDeviceInfo() error {
const errPrefix = "cannot set device information: "
func (run *Runner) findTimeLowerBound() error {
timeLowerBoundSources := []string{
// uc16
filepath.Join(dirs.SnapSeedDir, "seed.yaml"),
// uc20+
dirs.SnapModeenvFile,
}
// add all model files from uc20 seeds
allModels, err := filepath.Glob(filepath.Join(dirs.SnapSeedDir, "systems/*/model"))
if err != nil {
return err
}
timeLowerBoundSources = append(timeLowerBoundSources, allModels...)

// use all files as potential time inputs
for _, p := range timeLowerBoundSources {
info, err := os.Stat(p)
if os.IsNotExist(err) {
continue
}
if err != nil {
return err
}
run.moveTimeLowerBound(info.ModTime())
}
return nil
}

func findBrandAndModel() (string, string, error) {
if osutil.FileExists(dirs.SnapModeenvFile) {
return findBrandAndModel20()
}
return findBrandAndModel16()
}

func findBrandAndModel20() (brand string, model string, err error) {
cfg := goconfigparser.New()
cfg.AllowNoSectionHeader = true
if err := cfg.ReadFile(dirs.SnapModeenvFile); err != nil {
return "", "", err
}
brandAndModel, err := cfg.Get("", "model")
if err != nil {
return "", "", err
}
l := strings.SplitN(brandAndModel, "/", 2)
if len(l) != 2 {
return "", "", fmt.Errorf("cannot find brand/model in modeenv model string %q", brandAndModel)
}

return l[0], l[1], nil
}

func findBrandAndModel16() (string, string, error) {
mvo5 marked this conversation as resolved.
Show resolved Hide resolved
workBS := asserts.NewMemoryBackstore()
assertSeedDir := filepath.Join(dirs.SnapSeedDir, "assertions")
dc, err := ioutil.ReadDir(assertSeedDir)
if err != nil {
return err
return "", "", err
}
var model *asserts.Model
for _, fi := range dc {
Expand All @@ -682,7 +732,7 @@ func (run *Runner) initDeviceInfo() error {
switch a.Type() {
case asserts.ModelType:
if model != nil {
return fmt.Errorf(errPrefix + "multiple models in seed assertions")
return "", "", fmt.Errorf("multiple models in seed assertions")
}
model = a.(*asserts.Model)
case asserts.AccountType, asserts.AccountKeyType:
Expand All @@ -691,11 +741,11 @@ func (run *Runner) initDeviceInfo() error {
}
}
if model == nil {
return fmt.Errorf(errPrefix + "no model assertion in seed data")
return "", "", fmt.Errorf("no model assertion in seed data")
}
trustedBS := trustedBackstore(sysdb.Trusted())
if err := verifySignatures(model, workBS, trustedBS); err != nil {
return fmt.Errorf(errPrefix+"%v", err)
return "", "", err
}
acctPK := []string{model.BrandID()}
acctMaxSupFormat := asserts.AccountType.MaxSupportedFormat()
Expand All @@ -704,14 +754,22 @@ func (run *Runner) initDeviceInfo() error {
var err error
acct, err = workBS.Get(asserts.AccountType, acctPK, acctMaxSupFormat)
if err != nil {
return fmt.Errorf(errPrefix + "no brand account assertion in seed data")
return "", "", fmt.Errorf("no brand account assertion in seed data")
}
}
if err := verifySignatures(acct, workBS, trustedBS); err != nil {
return fmt.Errorf(errPrefix+"%v", err)
return "", "", err
}
return model.BrandID(), model.Model(), nil
}

func (run *Runner) initDeviceInfo() error {
brandID, model, err := findBrandAndModel()
if err != nil {
return fmt.Errorf("cannot set device information: %v", err)
}
run.state.Device.Brand = model.BrandID()
run.state.Device.Model = model.Model()
run.state.Device.Brand = brandID
run.state.Device.Model = model
return nil
}

Expand Down