mirror of
https://github.com/token2/snapd.git
synced 2026-03-13 11:15:47 -07:00
* gadget,daemon: use Volume instead of LaidOutVolume when retrieving traits (we only need the information from the gadget). * gadget,overlord: use Volume instead of LaidOutVolume when saving storage traits (we only actually need the gadget info). * gadget: add function to get disk from installer gadget volume * gadget: apply installer gadget changes to volumes instead of applying to the laid out volumes, as in the end what the installer is providing us is a way to fill gadget information. * gadget: create temporary wrapper for LaidOutVolumesFromGadget * o/devicestate: build layouts after matching disk to volumes returned by the installer, so we make sure that the information we have received is accurate. * gadget/install: do not use laid out when encrypting a partition * gadget: change so Run uses laid out types only after the partitions have been created. * gadget: do not use laid out structures directly in FactoryReset * gadget: move ancillary function to gadgettest, as it is used there only * gadget: remove some duplicated lines left by mistake * gadget: pass around yaml index to installer It is used by muinstaller as it calls create partition functions that return maps that use this index as key. * revert prev * tests/muinstaller: update to latest snapd * gadget: fix and test OnDiskVolumeFromGadgetVol * gadget,overlord: set device from installer * gadget/install: really check error returned by LayoutVolumeStructure * gadget/install: fix nosecboot builds * gadget,overlord: minor changes in comments * gadget: add test for StructFromYamlIndex, add doc strings * gadget: add some additional tests * gadget: move up variable definition * gadget,overlord: move OnDiskVolumeFromGadgetVol to a better place * gadget: return OnDiskAndGadgetStructurePair pairs from buildPartitionList * gadget: add method to copy volumes * gadget,overlord: return a copy from ApplyInstallerVolumesToGadget instead of modifying the passed around volumes. * gadget,overlord: address review comments * daemon,gadget: some renames and error/comments string changes * gadget: move TestOnDiskVolumeFromGadgetVol to the right place * gadget: add case for testing volume copy * gadget/install: prevent reading twice gadget.yaml in Run * gadget/install: remove now unneeded dummy function * tests/muinstaller: update to latest snapd changes * gadget/install: fix nosecboot tests * gadget: unexport yamlIdxToStructureIdx * gadget,overlord: some var name and comment changes * gadget: add more unit tests for MatchDisksToGadgetVolumes * gadget,overlord: address some review comments
143 lines
4.0 KiB
Go
143 lines
4.0 KiB
Go
// -*- Mode: Go; indent-tabs-mode: t -*-
|
|
|
|
/*
|
|
* Copyright (C) 2023 Canonical Ltd
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 3 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
package gadget
|
|
|
|
import "fmt"
|
|
|
|
// ApplyInstallerVolumesToGadget takes the volume information returned
|
|
// by the installer and applies it to the gadget volumes for the
|
|
// device to install to and for properties partially defined,
|
|
// returning the result in a new Volume map. After that it checks that
|
|
// the gadget is now fully specified.
|
|
func ApplyInstallerVolumesToGadget(installerVols map[string]*Volume, gadgetVols map[string]*Volume) (map[string]*Volume, error) {
|
|
newVols := map[string]*Volume{}
|
|
for volName, gv := range gadgetVols {
|
|
newV := gv.Copy()
|
|
newVols[volName] = newV
|
|
|
|
insVol := installerVols[volName]
|
|
if insVol == nil {
|
|
return nil, fmt.Errorf("installer did not provide information for volume %q", volName)
|
|
}
|
|
|
|
// First, retrieve device specified by installer
|
|
for i := range newV.Structure {
|
|
insStr, err := structureByName(insVol.Structure, newV.Structure[i].Name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
newV.Structure[i].Device = insStr.Device
|
|
}
|
|
|
|
// Next changes are only for partial gadgets
|
|
if len(newV.Partial) == 0 {
|
|
continue
|
|
}
|
|
|
|
// TODO: partial structure, as it is not clear what will be possible when set
|
|
|
|
if newV.HasPartial(PartialSchema) {
|
|
if insVol.Schema == "" {
|
|
return nil, fmt.Errorf("installer did not provide schema for volume %q", volName)
|
|
}
|
|
newV.Schema = insVol.Schema
|
|
}
|
|
|
|
if newV.HasPartial(PartialFilesystem) {
|
|
if err := applyPartialFilesystem(insVol, newV, volName); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if newV.HasPartial(PartialSize) {
|
|
if err := applyPartialSize(insVol, newV, volName); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
// The only thing that can still be partial is the structure
|
|
if newV.HasPartial(PartialStructure) {
|
|
newV.Partial = []PartialProperty{PartialStructure}
|
|
} else {
|
|
newV.Partial = []PartialProperty{}
|
|
}
|
|
|
|
// Now validate finalized volume
|
|
if err := validateVolume(newV); err != nil {
|
|
return nil, fmt.Errorf("finalized volume %q is wrong: %v", newV.Name, err)
|
|
}
|
|
}
|
|
|
|
return newVols, nil
|
|
}
|
|
|
|
func applyPartialFilesystem(insVol *Volume, gadgetVol *Volume, volName string) error {
|
|
for sidx := range gadgetVol.Structure {
|
|
vs := &gadgetVol.Structure[sidx]
|
|
if vs.Filesystem != "" || !vs.HasFilesystem() {
|
|
continue
|
|
}
|
|
|
|
insStr, err := structureByName(insVol.Structure, vs.Name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if insStr.Filesystem == "" {
|
|
return fmt.Errorf("installer did not provide filesystem for structure %q in volume %q", vs.Name, volName)
|
|
}
|
|
|
|
vs.Filesystem = insStr.Filesystem
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func applyPartialSize(insVol *Volume, gadgetVol *Volume, volName string) error {
|
|
for sidx := range gadgetVol.Structure {
|
|
vs := &gadgetVol.Structure[sidx]
|
|
if !vs.hasPartialSize() {
|
|
continue
|
|
}
|
|
|
|
insStr, err := structureByName(insVol.Structure, vs.Name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if insStr.Size == 0 {
|
|
return fmt.Errorf("installer did not provide size for structure %q in volume %q", vs.Name, volName)
|
|
}
|
|
if insStr.Offset == nil {
|
|
return fmt.Errorf("installer did not provide offset for structure %q in volume %q", vs.Name, volName)
|
|
}
|
|
|
|
vs.Size = insStr.Size
|
|
vs.Offset = insStr.Offset
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func structureByName(vss []VolumeStructure, name string) (*VolumeStructure, error) {
|
|
for sidx := range vss {
|
|
if vss[sidx].Name == name {
|
|
return &vss[sidx], nil
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("cannot find structure %q", name)
|
|
}
|