gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/overlord/devicestate/handlers_bootconfig.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  /*
     3   * Copyright (C) 2021 Canonical Ltd
     4   *
     5   * This program is free software: you can redistribute it and/or modify
     6   * it under the terms of the GNU General Public License version 3 as
     7   * published by the Free Software Foundation.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   *
    17   */
    18  
    19  package devicestate
    20  
    21  import (
    22  	"fmt"
    23  
    24  	"gopkg.in/tomb.v2"
    25  
    26  	"github.com/snapcore/snapd/asserts"
    27  	"github.com/snapcore/snapd/boot"
    28  	"github.com/snapcore/snapd/overlord/state"
    29  	"github.com/snapcore/snapd/release"
    30  )
    31  
    32  func (m *DeviceManager) doUpdateManagedBootConfig(t *state.Task, _ *tomb.Tomb) error {
    33  	if release.OnClassic {
    34  		return fmt.Errorf("cannot run update boot config task on a classic system")
    35  	}
    36  
    37  	st := t.State()
    38  	st.Lock()
    39  	defer st.Unlock()
    40  
    41  	var seeded bool
    42  	err := st.Get("seeded", &seeded)
    43  	if err != nil && err != state.ErrNoState {
    44  		return err
    45  	}
    46  	if !seeded {
    47  		// do nothing during first boot & seeding
    48  		return nil
    49  	}
    50  	devCtx, err := DeviceCtx(st, t, nil)
    51  	if err != nil {
    52  		return err
    53  	}
    54  
    55  	if devCtx.Model().Grade() == asserts.ModelGradeUnset {
    56  		// pre UC20 system, do nothing
    57  		return nil
    58  	}
    59  	if devCtx.ForRemodeling() {
    60  		// TODO:UC20: we may need to update the boot config when snapd
    61  		// channel is changed during remodel
    62  		return nil
    63  	}
    64  
    65  	currentData, err := currentGadgetInfo(st, devCtx)
    66  	if err != nil {
    67  		return fmt.Errorf("cannot obtain current gadget data: %v", err)
    68  	}
    69  	if currentData == nil {
    70  		// we should be past seeding
    71  		return fmt.Errorf("internal error: no current gadget")
    72  	}
    73  
    74  	// TODO:UC20 update recovery boot config
    75  	updated, err := boot.UpdateManagedBootConfigs(devCtx, currentData.RootDir)
    76  	if err != nil {
    77  		return fmt.Errorf("cannot update boot config assets: %v", err)
    78  	}
    79  	if updated {
    80  		t.Logf("updated boot config assets")
    81  		// boot assets were updated, request a restart now so that the
    82  		// situation does not end up more complicated if more updates of
    83  		// boot assets were to be applied
    84  		st.RequestRestart(state.RestartSystem)
    85  	}
    86  
    87  	// minimize wasteful redos
    88  	t.SetStatus(state.DoneStatus)
    89  	return nil
    90  }