Documentation ¶
Index ¶
- Constants
- Variables
- func AllDiskVolumeDeviceTraits(allVols map[string]*Volume, ...) (map[string]DiskVolumeDeviceTraits, error)
- func ApplyInstallerVolumesToGadget(installerVols map[string]*Volume, gadgetVols map[string]*Volume) (map[string]*Volume, error)
- func CheckValidStartOffset(off quantity.Offset, vss []VolumeStructure, idx int) error
- func EnsureVolumeCompatibility(gadgetVolume *Volume, diskVolume *OnDiskVolume, ...) (map[int]*OnDiskStructure, error)
- func FilterKernelCmdline(cmdline string, allowedSl []kcmdline.ArgumentPattern) (argsAllowed, argsDenied string)
- func FindDeviceForStructure(vs *VolumeStructure) (string, error)
- func HasRole(gadgetSnapRootDir string, roles []string) (foundRole string, err error)
- func IsCompatible(current, new *Info) error
- func IsCreatableAtInstall(gv *VolumeStructure) bool
- func KernelCommandLineFromGadget(gadgetDirOrSnapPath string, model Model) (cmdline string, full bool, removeArgs []kcmdline.ArgumentPattern, err error)
- func LaidOutVolumesFromGadget(vols map[string]*Volume, gadgetRoot, kernelRoot string, ...) (all map[string]*LaidOutVolume, err error)
- func LoadDiskVolumesDeviceTraits(dir string) (map[string]DiskVolumeDeviceTraits, error)
- func MaybeDeviceForStructure(vs *VolumeStructure) (string, error)
- func MaybeDeviceForVolume(volume *Volume) (string, error)
- func MockSysfsPathForBlockDevice(f func(device string) (string, error)) (restore func())
- func MockUpdaterForStructure(...) (restore func())
- func MockVolumeStructureToLocationMap(...) (restore func())
- func OnDiskStructsFromGadget(volume *Volume) (structures map[int]*OnDiskStructure)
- func SaveDiskVolumesDeviceTraits(dir string, mapping map[string]DiskVolumeDeviceTraits) error
- func SetEnclosingVolumeInStructs(vv map[string]*Volume)
- func SystemDefaults(gadgetDefaults map[string]map[string]interface{}) map[string]interface{}
- func Update(model Model, old, new GadgetData, rollbackDirPath string, ...) error
- func Validate(info *Info, model Model, extra *ValidationConstraints) error
- func ValidateContent(info *Info, gadgetSnapRootDir, kernelSnapRootDir string) error
- func VolumesForCurrentDevice(gi *Info) (vols map[string]*Volume, assigned bool, err error)
- func VolumesHaveRole(volumes map[string]*Volume, role string) bool
- type Connection
- type ConnectionPlug
- type ConnectionSlot
- type ContentChange
- type ContentChangeAction
- type ContentObserver
- type ContentOperation
- type ContentUpdateObserver
- type DeviceAssignment
- type DiskEncryptionMethod
- type DiskStructureDeviceTraits
- type DiskVolumeDeviceTraits
- type DiskVolumeValidationOptions
- type GadgetData
- type Info
- func InfoFromGadgetYaml(gadgetYaml []byte, model Model) (*Info, error)
- func ReadInfo(gadgetSnapRootDir string, model Model) (*Info, error)
- func ReadInfoAndValidate(gadgetSnapRootDir string, model Model, ...) (*Info, error)
- func ReadInfoFromSnapFile(snapf snap.Container, model Model) (*Info, error)
- func ReadInfoFromSnapFileNoValidate(snapf snap.Container, model Model) (*Info, error)
- type KernelCmdline
- type LaidOutContent
- type LaidOutStructure
- func (l LaidOutStructure) Filesystem() string
- func (l *LaidOutStructure) HasFilesystem() bool
- func (l *LaidOutStructure) IsPartition() bool
- func (l LaidOutStructure) Label() string
- func (l LaidOutStructure) Name() string
- func (l LaidOutStructure) Role() string
- func (p LaidOutStructure) String() string
- func (l LaidOutStructure) Type() string
- type LaidOutVolume
- type LayoutOptions
- type Model
- type MountedFilesystemWriter
- type OnDiskAndGadgetStructurePair
- type OnDiskStructure
- type OnDiskVolume
- type PartialProperty
- type PartiallyLaidOutVolume
- type RawStructureWriter
- type RelativeOffset
- type ResolvedContent
- type ResolvedContentFilterFunc
- type StructureEncryptionParameters
- type StructureLocation
- type UpdatePolicyFunc
- type Updater
- type ValidationConstraints
- type Volume
- type VolumeAssignment
- type VolumeCompatibilityOptions
- type VolumeContent
- type VolumeStructure
- type VolumeUpdate
Constants ¶
const ( SystemBoot = "system-boot" SystemData = "system-data" SystemSeed = "system-seed" SystemSeedNull = "system-seed-null" SystemSave = "system-save" // UnboundedStructureOffset is the maximum effective partition offset // that we can handle. UnboundedStructureOffset = quantity.Offset(math.MaxUint64) // UnboundedStructureSize is the maximum effective partition size // that we can handle. UnboundedStructureSize = quantity.Size(math.MaxUint64) )
const ( // SizeMBR is the maximum byte size of a structure of role 'mbr' SizeMBR = quantity.Size(446) // SizeLBA48Pointer is the byte size of a pointer value written at the // location described by 'offset-write' SizeLBA48Pointer = quantity.Size(4) )
const ( ContentWrite ContentOperation = iota ContentUpdate ContentRollback ChangeAbort ContentChangeAction = iota ChangeApply ChangeIgnore )
const GPTPartitionGUIDESP = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
const NonMBRStartOffset = 1 * quantity.OffsetMiB
NonMBRStartOffset is the minimum start offset of the first non-MBR structure in the volume that does not specify explicitly an offset. It can be ignored by setting explicitly offsets.
Variables ¶
var ( ErrDeviceNotFound = errors.New("device not found") ErrMountNotFound = errors.New("mount point not found") ErrNoFilesystemDefined = errors.New("no filesystem defined") )
var (
ErrNoUpdate = errors.New("nothing to update")
)
var VolumesForCurrentDeviceAssignment = volumesForCurrentDeviceAssignmentImpl
Indirection here for mocking
Functions ¶
func AllDiskVolumeDeviceTraits ¶
func AllDiskVolumeDeviceTraits(allVols map[string]*Volume, optsPerVolume map[string]*DiskVolumeValidationOptions) (map[string]DiskVolumeDeviceTraits, error)
AllDiskVolumeDeviceTraits takes a mapping of volume name to Volume and produces a map of volume name to DiskVolumeDeviceTraits. Since doing so uses DiskVolumeDeviceTraitsForDevice, it will also validate that disk devices identified for the volume are compatible and matching before returning.
func ApplyInstallerVolumesToGadget ¶
func ApplyInstallerVolumesToGadget(installerVols map[string]*Volume, gadgetVols map[string]*Volume) (map[string]*Volume, error)
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 CheckValidStartOffset ¶
func CheckValidStartOffset(off quantity.Offset, vss []VolumeStructure, idx int) error
CheckValidStartOffset returns an error if the input offset is not valid for the structure at idx, nil otherwise.
func EnsureVolumeCompatibility ¶
func EnsureVolumeCompatibility(gadgetVolume *Volume, diskVolume *OnDiskVolume, opts *VolumeCompatibilityOptions) (map[int]*OnDiskStructure, error)
EnsureVolumeCompatibility checks compatibility between a gadget volume and a real disk. It returns a map of the gadget structures yaml indexes to disk structures that was possible to match. TODO change to returning OnDiskAndGadgetStructurePair
func FilterKernelCmdline ¶
func FilterKernelCmdline(cmdline string, allowedSl []kcmdline.ArgumentPattern) (argsAllowed, argsDenied string)
FilterKernelCmdline returns a filtered command line, removing arguments that are not on a list of allowed kernel arguments. A wild card ('*') can be used in the allow list for the values. Additionally, a string with the arguments that have been filtered out is also returned.
func FindDeviceForStructure ¶
func FindDeviceForStructure(vs *VolumeStructure) (string, error)
FindDeviceForStructure attempts to find an existing block device matching given volume structure, by inspecting its name and, optionally, the filesystem label. Assumes that the host's udev has set up device symlinks correctly.
func HasRole ¶
HasRole reads the gadget specific metadata from meta/gadget.yaml in the snap root directory with minimal validation and checks whether any volume structure has one of the given roles returning it, otherwhise it returns the empty string. This is mainly intended to avoid compatibility issues from snap-bootstrap but could be used on any known to be properly installed gadget.
func IsCompatible ¶
IsCompatible checks whether the current and an update are compatible. Returns nil or an error describing the incompatibility. TODO: make this reasonably consistent with Update for multi-volume scenarios
func IsCreatableAtInstall ¶
func IsCreatableAtInstall(gv *VolumeStructure) bool
IsCreatableAtInstall returns whether the gadget structure would be created at install - currently that is only ubuntu-save, ubuntu-data, and ubuntu-boot
func KernelCommandLineFromGadget ¶
func KernelCommandLineFromGadget(gadgetDirOrSnapPath string, model Model) (cmdline string, full bool, removeArgs []kcmdline.ArgumentPattern, err error)
KernelCommandLineFromGadget returns the desired kernel command line provided by the gadget. The full flag indicates whether the gadget provides a full command line or just the extra parameters that will be appended to the static ones. A model is neededed to know how to interpret the gadget yaml from the gadget.
func LaidOutVolumesFromGadget ¶
func LaidOutVolumesFromGadget(vols map[string]*Volume, gadgetRoot, kernelRoot string, encType secboot.EncryptionType, volToGadgetToDiskStruct map[string]map[int]*OnDiskStructure) (all map[string]*LaidOutVolume, err error)
LaidOutVolumesFromGadget takes gadget volumes, gadget and kernel rootdirs and lays out the partitions on all volumes as specified. It returns the volumes mentioned in the gadget.yaml and their laid out representations.
func LoadDiskVolumesDeviceTraits ¶
func LoadDiskVolumesDeviceTraits(dir string) (map[string]DiskVolumeDeviceTraits, error)
LoadDiskVolumesDeviceTraits loads the mapping of volumes to disk traits if there is any. If there is no file with the mapping available, nil is returned.
func MaybeDeviceForStructure ¶
func MaybeDeviceForStructure(vs *VolumeStructure) (string, error)
MaybeDeviceForStructure does a best-effort of resolving a device node for the provided volume structure.
func MaybeDeviceForVolume ¶
MaybeDeviceForVolume does a best-effort of finding a matching device node for the provided volume. Optionally a device path can be specified that should be resolved instead of finding a matching device for one of the volume structures.
func MockUpdaterForStructure ¶
func MockUpdaterForStructure(mock func(loc StructureLocation, fromPs, ps *LaidOutStructure, rootDir, rollbackDir string, observer ContentUpdateObserver) (Updater, error)) (restore func())
MockUpdaterForStructure replace internal call with a mocked one, for use in tests only
func MockVolumeStructureToLocationMap ¶
func MockVolumeStructureToLocationMap(f func(_ Model, _, _ map[string]*Volume) ( map[string]map[int]StructureLocation, map[string]map[int]*OnDiskStructure, error)) (restore func())
func OnDiskStructsFromGadget ¶
func OnDiskStructsFromGadget(volume *Volume) (structures map[int]*OnDiskStructure)
OnDiskStructsFromGadget builds a map of gadget yaml index to OnDiskStructure by assuming that the gadget will match exactly one of the disks of the installation device. This is used only at disk image build time as we do not know yet the target disk.
func SaveDiskVolumesDeviceTraits ¶
func SaveDiskVolumesDeviceTraits(dir string, mapping map[string]DiskVolumeDeviceTraits) error
SaveDiskVolumesDeviceTraits saves the mapping of volume names to volume / device traits to a file inside the provided directory on disk for later loading and verification.
func SetEnclosingVolumeInStructs ¶
SetEnclosingVolumeInStructs is a helper that sets the pointer to the Volume in all VolumeStructure objects it contains.
func SystemDefaults ¶
SystemDefaults returns default system configuration from gadget defaults.
func Update ¶
func Update(model Model, old, new GadgetData, rollbackDirPath string, updatePolicy UpdatePolicyFunc, observer ContentUpdateObserver) error
Update applies the gadget update given the gadget information and data from old and new revisions. It errors out when the update is not possible or illegal, or a failure occurs at any of the steps. When there is no update, a special error ErrNoUpdate is returned.
Only structures selected by the update policy are part of the update. When the policy is nil, a default one is used. The default policy selects structures in an opt-in manner, only structures with a higher value of Edition field in the new gadget definition are part of the update.
Data that would be modified during the update is first backed up inside the rollback directory. Should the apply step fail, the modified data is recovered.
The rules for gadget/kernel updates with "$kernel:refs":
- When installing a kernel with assets that have "update: true" there *must* be a matching entry in gadget.yaml. If not we risk bricking the system because the kernel tells us that it *needs* this file to boot but without gadget.yaml we would not put it anywhere.
- When installing a gadget with "$kernel:ref" content it is okay if this content cannot get resolved as long as there is no "edition" jump. This means adding new "$kernel:ref" without "edition" updates is always possible.
To add a new "$kernel:ref" to gadget/kernel: a. Update gadget and gadget.yaml and add "$kernel:ref" but do not update edition (if edition update is needed, use epoch) b. Update kernel and kernel.yaml with new assets. c. snapd will refresh gadget (see rule 2) but refuse to take the new kernel (rule 1) d. After step (c) is completed the kernel refresh will now also work (no more violation of rule 1)
func Validate ¶
func Validate(info *Info, model Model, extra *ValidationConstraints) error
Validate checks that the given gadget metadata matches the consistency rules for role usage, labels etc as implied by the model and extra constraints that might be known only at runtime.
func ValidateContent ¶
ValidateContent checks whether the given directory contains valid matching content with respect to the given pre-validated gadget metadata.
func VolumesForCurrentDevice ¶
VolumesForCurrentDevice returns the correct list of volumes for the currently running device. If there is an active assignment, then those volumes are returned together with `assigned` being true.
Types ¶
type Connection ¶
type Connection struct { Plug ConnectionPlug `yaml:"plug"` Slot ConnectionSlot `yaml:"slot"` }
GadgetConnect describes an interface connection requested by the gadget between seeded snaps. The syntax is of a mapping like:
plug: (<plug-snap-id>|system):plug [slot: (<slot-snap-id>|system):slot]
"system" indicates a system plug or slot. Fully omitting the slot part indicates a system slot with the same name as the plug.
type ConnectionPlug ¶
func (*ConnectionPlug) Empty ¶
func (gcplug *ConnectionPlug) Empty() bool
func (*ConnectionPlug) UnmarshalYAML ¶
func (gcplug *ConnectionPlug) UnmarshalYAML(unmarshal func(interface{}) error) error
type ConnectionSlot ¶
func (*ConnectionSlot) Empty ¶
func (gcslot *ConnectionSlot) Empty() bool
func (*ConnectionSlot) UnmarshalYAML ¶
func (gcslot *ConnectionSlot) UnmarshalYAML(unmarshal func(interface{}) error) error
type ContentChange ¶
type ContentChange struct { // Before is a path to a file containing the original data before the // operation takes place (or took place in case of ContentRollback). Before string // After is a path to a file location of the data applied by the operation. After string }
ContentChange carries paths to files containing the content data being modified by the operation.
type ContentChangeAction ¶
type ContentChangeAction int
type ContentObserver ¶
type ContentObserver interface { // Observe is called to observe an pending or completed action, related // to content being written, updated or being rolled back. In each of // the scenarios, the target path is relative under the root. The role // of the affected partition is needed as different assets are tracked // depending on whether this is a boot or a seed partition. // // For a file write or update, the source path points to the content // that will be written. When called during rollback, observe call // happens after the original file has been restored (or removed if the // file was added during the update), the source path is empty. // // Returning ChangeApply indicates that the observer agrees for a given // change to be applied. When called with a ContentUpdate or // ContentWrite operation, returning ChangeIgnore indicates that the // change shall be ignored. ChangeAbort is expected to be returned along // with a non-nil error. Observe(op ContentOperation, partRole, targetRootDir, relativeTargetPath string, dataChange *ContentChange) (ContentChangeAction, error) }
ContentObserver allows for observing operations on the content of the gadget structures.
type ContentOperation ¶
type ContentOperation int
type ContentUpdateObserver ¶
type ContentUpdateObserver interface { ContentObserver // BeforeWrite is called when the backups of content that will get // modified during the update are complete and update is ready to be // applied. BeforeWrite() error // Canceled is called when the update has been canceled, or if changes // were written and the update has been reverted. Canceled() error }
ContentUpdateObserver allows for observing update (and potentially a rollback) of the gadget structure content.
type DeviceAssignment ¶
type DeviceAssignment struct { // Device is the actual block device available in the system, // eg. /dev/disk/by-path/pci-42:0 Device string `yaml:"device"` }
DeviceAssignment is the device data for each volume assignment. Currently just keeps the device the volume should be assigned to.
type DiskEncryptionMethod ¶
type DiskEncryptionMethod string
TODO:ICE: remove this as we only support LUKS (and ICE is a variant of LUKS now)
const ( // standard LUKS as it is used for automatic FDE using SecureBoot and TPM // 2.0 in UC20+ EncryptionLUKS DiskEncryptionMethod = "LUKS" )
type DiskStructureDeviceTraits ¶
type DiskStructureDeviceTraits struct { // OriginalDevicePath is the device path in sysfs and in /dev/disk/by-path the // partition was measured and observed at during UC20+ install mode. OriginalDevicePath string `json:"device-path"` // OriginalKernelPath is the device path like /dev/vda1 the partition was // measured and observed at during UC20+ install mode. OriginalKernelPath string `json:"kernel-path"` // PartitionUUID is the partuuid as defined by i.e. /dev/disk/by-partuuid PartitionUUID string `json:"partition-uuid"` // PartitionLabel is the label of the partition for GPT disks, i.e. // /dev/disk/by-partlabel PartitionLabel string `json:"partition-label"` // PartitionType is the type of the partition i.e. 0x83 for a // Linux native partition on DOS, or // 0FC63DAF-8483-4772-8E79-3D69D8477DE4 for a Linux filesystem // data partition on GPT. PartitionType string `json:"partition-type"` // FilesystemUUID is the UUID of the filesystem on the partition, i.e. // /dev/disk/by-uuid FilesystemUUID string `json:"filesystem-uuid"` // FilesystemLabel is the label of the filesystem for structures that have // filesystems, i.e. /dev/disk/by-label FilesystemLabel string `json:"filesystem-label"` // FilesystemType is the type of the filesystem, i.e. vfat or ext4, etc. FilesystemType string `json:"filesystem-type"` // Offset is the offset of the structure Offset quantity.Offset `json:"offset"` // Size is the size of the structure Size quantity.Size `json:"size"` }
DiskStructureDeviceTraits is a similar to DiskVolumeDeviceTraits, but is a set of traits for a specific structure on a disk rather than the full disk itself. Structures can be full partitions or just raw slices on a disk like the "BIOS Boot" structure on default amd64 grub Ubuntu Core systems.
type DiskVolumeDeviceTraits ¶
type DiskVolumeDeviceTraits struct { // OriginalDevicePath is the device path in sysfs and in /dev/disk/by-path // the volume was measured and observed at during UC20+ install mode. OriginalDevicePath string `json:"device-path"` // OriginalKernelPath is the device path like /dev/vda the volume was // measured and observed at during UC20+ install mode. OriginalKernelPath string `json:"kernel-path"` // DiskID is the disk's identifier, it is a UUID for GPT disks or an // unsigned integer for DOS disks encoded as a string in hexadecimal as in // "0x1212e868". DiskID string `json:"disk-id"` // Size is the physical size of the disk, regardless of usable space // considerations. Size quantity.Size `json:"size"` // SectorSize is the physical sector size of the disk, typically 512 or // 4096. SectorSize quantity.Size `json:"sector-size"` // Schema is the disk schema, either dos or gpt in lowercase. Schema string `json:"schema"` // Structure contains trait information about each individual structure in // the volume that may be useful in identifying whether a disk matches a // volume or not. Structure []DiskStructureDeviceTraits `json:"structure"` // StructureEncryption is the set of partitions that are encrypted on the // volume - this should only ever have ubuntu-data or ubuntu-save keys for // now in the map. The value indicates parameters of the encryption present // that enable matching/identifying encrypted structures with their laid out // counterparts in the gadget.yaml. StructureEncryption map[string]StructureEncryptionParameters `json:"structure-encryption"` }
DiskVolumeDeviceTraits is a set of traits about a disk that were measured at a previous point in time on the same device, and is used primarily to try and map a volume in the gadget.yaml to a physical device on the system after the initial installation is done. We don't have a steadfast and predictable way to always find the device again, so we need to do a search, trying to find a device which matches each trait in turn, and verify it matches the physical structure layout and if not move on to using the next trait.
func DiskTraitsFromDeviceAndValidate ¶
func DiskTraitsFromDeviceAndValidate(vol *Volume, dev string, opts *DiskVolumeValidationOptions) (res DiskVolumeDeviceTraits, err error)
DiskTraitsFromDeviceAndValidate takes a gadget volume and an expected disk device path and confirms that they are compatible, and then builds up the disk volume traits for that device. If the laid out volume is not compatible with the disk structure for the specified device an error is returned.
type DiskVolumeValidationOptions ¶
type DiskVolumeValidationOptions struct { // AllowImplicitSystemData has the same meaning as the eponymously named // field in VolumeCompatibilityOptions. AllowImplicitSystemData bool // ExpectedEncryptedPartitions is a map of the names (gadget structure // names) of partitions that are encrypted on the volume and information // about that encryption. ExpectedStructureEncryption map[string]StructureEncryptionParameters }
DiskVolumeValidationOptions is a set of options on how to validate a disk to volume mapping for a specific disk/volume pair. It is closely related to the options provided to EnsureVolumeCompatibility via EnsureVolumeCompatibilityOptions.
type GadgetData ¶
type GadgetData struct { // Info is the gadget metadata Info *Info // XXX: should be GadgetRootDir // RootDir is the root directory of gadget snap data RootDir string // KernelRootDir is the root directory of kernel snap data KernelRootDir string }
GadgetData holds references to a gadget revision metadata and its data directory.
type Info ¶
type Info struct { // Volumes is the list of volumes defined by the gadget Volumes map[string]*Volume `yaml:"volumes,omitempty"` // VolumeAssingments carries a list of possible assignments of a volume to an // actual device visible in the system. Can carry alternative assignments of the same // volume to a device. Best match is selected at runtime. VolumeAssignments []*VolumeAssignment `yaml:"volume-assignments,omitempty"` // Default configuration for snaps (snap-id => key => value). Defaults map[string]map[string]interface{} `yaml:"defaults,omitempty"` Connections []Connection `yaml:"connections"` KernelCmdline KernelCmdline `yaml:"kernel-cmdline"` }
func InfoFromGadgetYaml ¶
InfoFromGadgetYaml parses the provided gadget metadata. If model is nil only self-consistency checks are performed. If model is not nil implied values for filesystem labels will be set as well, based on whether the model is for classic, UC16/18 or UC20. UC gadget metadata is expected to have volumes definitions.
func ReadInfo ¶
ReadInfo reads the gadget specific metadata from meta/gadget.yaml in the snap root directory. See ReadInfoAndValidate for a variant that does role-usage consistency validation like Validate.
func ReadInfoAndValidate ¶
func ReadInfoAndValidate(gadgetSnapRootDir string, model Model, validationConstraints *ValidationConstraints) (*Info, error)
ReadInfoAndValidate reads the gadget specific metadata from meta/gadget.yaml in the snap root directory. It also performs role-usage consistency validation as Validate does using the given constraints. See ReadInfo for a variant that does not. See also ValidateContent for further validating the content itself instead of the metadata.
func ReadInfoFromSnapFile ¶
ReadInfoFromSnapFile reads the gadget specific metadata from meta/gadget.yaml in the given snap container. It also performs role-usage consistency validation as Validate does. See ReadInfoFromSnapFileNoValidate for a variant that does not.
func ReadInfoFromSnapFileNoValidate ¶
ReadInfoFromSnapFileNoValidate reads the gadget specific metadata from meta/gadget.yaml in the given snap container. See ReadInfoFromSnapFile for a variant that does role-usage consistency validation like Validate as well.
type KernelCmdline ¶
type KernelCmdline struct { // Allow is the list of allowed parameters for the system.kernel.cmdline-append // system option Allow []kcmdline.ArgumentPattern `yaml:"allow"` // Append are kernel parameters added by the gadget Append []kcmdline.Argument `yaml:"append"` // Remove are patterns to be removed from default command line Remove []kcmdline.ArgumentPattern `yaml:"remove"` }
type LaidOutContent ¶
type LaidOutContent struct { *VolumeContent // StartOffset defines the start offset of this content image StartOffset quantity.Offset // Size is the maximum size occupied by this image Size quantity.Size // Index of the content in structure declaration inside gadget YAML Index int }
LaidOutContent describes raw content that has been placed within the encompassing structure and volume
TODO: this can't have "$kernel:" refs at this point, fail in validate for bare structures with "$kernel:" refs
func (LaidOutContent) String ¶
func (p LaidOutContent) String() string
type LaidOutStructure ¶
type LaidOutStructure struct { OnDiskStructure // VolumeStructure is the volume structure defined in gadget.yaml VolumeStructure *VolumeStructure // LaidOutContent is a list of raw content inside the structure LaidOutContent []LaidOutContent // ResolvedContent is a list of filesystem content that has all // relative paths or references resolved ResolvedContent []ResolvedContent }
LaidOutStructure describes a VolumeStructure coming from the gadget plus the OnDiskStructure that describes how it would be applied to a given disk and additional content used when writing/updating data in the structure.
Note that we need to be careful while using the fields in OnDiskStructure as some times LaidOutStructure is created before we have information about the finally matched partition. This is especially important for StartOffset and Size fields. TODO We want to eventually create LaidOutStructure only after this information is available.
func LayoutVolumeStructure ¶
func LayoutVolumeStructure(dgpair *OnDiskAndGadgetStructurePair, kernelInfo *kernel.Info, opts *LayoutOptions) (*LaidOutStructure, error)
LayoutVolumeStructure lays out a structure given disk, gadget and kernel snaps information, and some options.
func ShiftStructureTo ¶
func ShiftStructureTo(ps LaidOutStructure, offset quantity.Offset) LaidOutStructure
ShiftStructureTo translates the starting offset of a laid out structure and its content to the provided offset.
func (LaidOutStructure) Filesystem ¶
func (l LaidOutStructure) Filesystem() string
Filesystem for formatting the structure.
func (*LaidOutStructure) HasFilesystem ¶
func (l *LaidOutStructure) HasFilesystem() bool
HasFilesystem returns true if the gadget expects a filesystem.
func (*LaidOutStructure) IsPartition ¶
func (l *LaidOutStructure) IsPartition() bool
IsPartition returns true when the structure describes a partition in a block device.
func (LaidOutStructure) Label ¶
func (l LaidOutStructure) Label() string
Label returns the filesystem label.
func (LaidOutStructure) Name ¶
func (l LaidOutStructure) Name() string
Name returns the partition label.
func (LaidOutStructure) Role ¶
func (l LaidOutStructure) Role() string
Role for the structure as specified in the gadget.
func (LaidOutStructure) String ¶
func (p LaidOutStructure) String() string
func (LaidOutStructure) Type ¶
func (l LaidOutStructure) Type() string
Type returns the type of the structure, which can be 2-hex digit MBR partition, 36-char GUID partition, comma separated <mbr>,<guid> for hybrid partitioning schemes, or 'bare' when the structure is not considered a partition.
For backwards compatibility type 'mbr' can also be returned, and that is equivalent to role 'mbr'.
type LaidOutVolume ¶
type LaidOutVolume struct { *Volume // LaidOutStructure is a list of structures within the volume, sorted // by their start offsets LaidOutStructure []LaidOutStructure }
LaidOutVolume defines the size of a volume and arrangement of all the structures within it
func LayoutVolume ¶
func LayoutVolume(volume *Volume, gadgetToDiskStruct map[int]*OnDiskStructure, opts *LayoutOptions) (*LaidOutVolume, error)
LayoutVolume attempts to completely lay out the volume, that is the structures and their content, using provided map of gadget structures to disk structures and options.
type LayoutOptions ¶
type LayoutOptions struct { // SkipResolveContent will skip resolving content paths // and `$kernel:` style references SkipResolveContent bool // IgnoreContent will skip laying out content structure data to the // volume. Settings this implies "SkipResolveContent". This // is used when only the partitions need to get // created and content gets written later. IgnoreContent bool // GadgetRootDir must be used only to find assets, not to load // gadget.yaml, as we might be using information provided by an // installer. GadgetRootDir string KernelRootDir string EncType secboot.EncryptionType }
LayoutOptions defines the options to layout a given volume.
type Model ¶
type Model interface { Classic() bool Grade() asserts.ModelGrade }
Model carries characteristics about the model that are relevant to gadget. Note *asserts.Model implements this, and that's the expected use case.
type MountedFilesystemWriter ¶
type MountedFilesystemWriter struct {
// contains filtered or unexported fields
}
MountedFilesystemWriter assists in writing contents of a structure to a mounted filesystem.
func NewMountedFilesystemWriter ¶
func NewMountedFilesystemWriter(fromPs, ps *LaidOutStructure, observer ContentObserver) (*MountedFilesystemWriter, error)
NewMountedFilesystemWriter returns a writer capable of writing provided structure, with content of the structure stored in the given root directory.
func (*MountedFilesystemWriter) Write ¶
func (m *MountedFilesystemWriter) Write(whereDir string, preserve []string) error
Write writes structure data into provided directory. All existing files are overwritten, unless their paths, relative to target directory, are listed in the preserve list. Permission bits and ownership of updated entries is not preserved.
type OnDiskAndGadgetStructurePair ¶
type OnDiskAndGadgetStructurePair struct { DiskStructure *OnDiskStructure GadgetStructure *VolumeStructure }
type OnDiskStructure ¶
type OnDiskStructure struct { // Name, when non empty, provides the name of the structure Name string // PartitionFSLabel provides the filesystem label PartitionFSLabel string // Type of the structure, which can be 2-hex digit MBR partition, // 36-char GUID partition, comma separated <mbr>,<guid> for hybrid // partitioning schemes, or 'bare' when the structure is not considered // a partition. // // For backwards compatibility type 'mbr' is also accepted, and the // structure is treated as if it is of role 'mbr'. Type string // PartitionFSType used for the partition filesystem: 'vfat', 'ext4', // 'none' for structures of type 'bare', or 'crypto_LUKS' for encrypted // partitions. PartitionFSType string // StartOffset defines the start offset of the structure within the // enclosing volume StartOffset quantity.Offset // Node identifies the device node of the block device. Node string // DiskIndex is the index of the structure on the disk - this should be // used instead of YamlIndex for an OnDiskStructure, YamlIndex comes from // the embedded LaidOutStructure which is 0-based and does not have the same // meaning. A LaidOutStructure's YamlIndex position will include that of // bare structures which will not show up as an OnDiskStructure, so the // range of OnDiskStructure.DiskIndex values is not necessarily the same as // the range of LaidOutStructure.YamlIndex values. DiskIndex int // Size of the on disk structure, which is at least equal to the // LaidOutStructure.Size but may be bigger if the partition was // expanded. Size quantity.Size }
OnDiskStructure represents a gadget structure laid on a block device.
func OnDiskStructureFromPartition ¶
func OnDiskStructureFromPartition(p disks.Partition) (OnDiskStructure, error)
type OnDiskVolume ¶
type OnDiskVolume struct { Structure []OnDiskStructure // ID is the disk's identifier, it is a UUID for GPT disks or an unsigned // integer for DOS disks encoded as a string in hexadecimal as in // "0x1212e868". ID string // Device is the full device node path for the disk, such as /dev/vda. Device string // Schema is the disk schema, GPT or DOS. Schema string // size in bytes Size quantity.Size // UsableSectorsEnd is the end (exclusive) of usable sectors on the disk, // this sector specifically is not usable for partitions, though it may be // used for i.e. GPT header backups on some disks. This should be used when // calculating the size of an auto-expanded partition instead of the Size // parameter which does not take this into account. UsableSectorsEnd uint64 // sector size in bytes SectorSize quantity.Size }
OnDiskVolume holds information about the disk device including its partitioning schema, the partition table, and the structure layout it contains.
func OnDiskVolumeFromDevice ¶
func OnDiskVolumeFromDevice(device string) (*OnDiskVolume, error)
OnDiskVolumeFromDevice obtains the partitioning and filesystem information from the block device.
func OnDiskVolumeFromDisk ¶
func OnDiskVolumeFromDisk(disk disks.Disk) (*OnDiskVolume, error)
func OnDiskVolumeFromGadgetVol ¶
func OnDiskVolumeFromGadgetVol(vol *Volume) (*OnDiskVolume, error)
OnDiskVolumeFromGadgetVol returns the disk volume matching a gadget volume that has the Device field set, which implies that this should be called only in the context of an installer that set the device in the gadget and returned it to snapd.
type PartialProperty ¶
type PartialProperty string
PartialProperty is a gadget property that can be partially defined.
const ( PartialSize PartialProperty = "size" PartialFilesystem PartialProperty = "filesystem" PartialSchema PartialProperty = "schema" PartialStructure PartialProperty = "structure" )
These are the different properties of the gadget that can be partially defined. TODO What is the exact meaning of having a partial "structure" is not yet fully defined, so enforcing it has not been implemented yet.
type PartiallyLaidOutVolume ¶
type PartiallyLaidOutVolume struct { *Volume // LaidOutStructure is a list of structures within the volume, sorted // by their start offsets LaidOutStructure []LaidOutStructure }
PartiallyLaidOutVolume defines the layout of volume structures, but lacks the details about the layout of raw image content within the bare structures.
type RawStructureWriter ¶
type RawStructureWriter struct {
// contains filtered or unexported fields
}
RawStructureWriter implements support for writing raw (bare) structures.
func NewRawStructureWriter ¶
func NewRawStructureWriter(contentDir string, ps *LaidOutStructure) (*RawStructureWriter, error)
NewRawStructureWriter returns a writer for the given structure, that will load the structure content data from the provided gadget content directory.
func (*RawStructureWriter) Write ¶
func (r *RawStructureWriter) Write(out io.WriteSeeker) error
Write will write whole contents of a structure into the output stream.
type RelativeOffset ¶
type RelativeOffset struct { // RelativeTo names the structure relative to which the location of the // address write will be calculated. RelativeTo string `yaml:"relative-to" json:"relative-to"` // Offset is a 32-bit value Offset quantity.Offset `yaml:"offset" json:"offset"` }
RelativeOffset describes an offset where structure data is written at. The position can be specified as byte-offset relative to the start of another named structure.
func (*RelativeOffset) String ¶
func (r *RelativeOffset) String() string
func (*RelativeOffset) UnmarshalYAML ¶
func (s *RelativeOffset) UnmarshalYAML(unmarshal func(interface{}) error) error
type ResolvedContent ¶
type ResolvedContent struct { *VolumeContent // ResolvedSource is the absolute path of the Source after resolving // any references (e.g. to a "$kernel:" snap). ResolvedSource string // KernelUpdate is true if this content comes from the kernel // and has the "Update" property set KernelUpdate bool }
type ResolvedContentFilterFunc ¶
type ResolvedContentFilterFunc func(*ResolvedContent) bool
ResolvedContentFilterFunc is a callback that evaluates the given ResolvedContent and returns true if it should be applied as part of an update. This is relevant for e.g. asset updates that come from the kernel snap.
func KernelUpdatePolicy ¶
func KernelUpdatePolicy(from, to *LaidOutStructure) (bool, ResolvedContentFilterFunc)
KernelUpdatePolicy implements the update policy for kernel asset updates.
This is called when there is a kernel->kernel refresh for kernels that contain bootloader assets. In this case all bootloader assets that are marked as "update: true" in the kernel.yaml need updating.
But any non-kernel assets need to be ignored, they will be handled by the regular gadget->gadget update mechanism and policy.
func RemodelUpdatePolicy ¶
func RemodelUpdatePolicy(from, to *LaidOutStructure) (bool, ResolvedContentFilterFunc)
RemodelUpdatePolicy implements the update policy of a remodel scenario. The policy selects all non-MBR structures for the update.
type StructureEncryptionParameters ¶
type StructureEncryptionParameters struct { // Method is the method of encryption used, currently only EncryptionLUKS is // recognized. Method DiskEncryptionMethod `json:"method"` // contains filtered or unexported fields }
StructureEncryptionParameters contains information about an encrypted structure, used to match encrypted structures on disk with their abstract, laid out counterparts in the gadget.yaml.
func (*StructureEncryptionParameters) UnmarshalJSON ¶
func (s *StructureEncryptionParameters) UnmarshalJSON(b []byte) error
type StructureLocation ¶
type StructureLocation struct { // Device is the kernel device node path such as /dev/vda1 for the // structure's backing physical disk. Device string // Offset is the offset from 0 for the physical disk that this structure // starts at. Offset quantity.Offset // RootMountPoint is the directory where the root directory of the structure // is mounted read/write. There may be other mount points for this structure // on the system, but this one is guaranteed to be writable and thus // suitable for gadget asset updates. RootMountPoint string }
StructureLocation represents the location of a structure for updating purposes. Either Device + Offset must be set for a raw structure without a filesystem, or RootMountPoint must be set for structures with a filesystem.
type UpdatePolicyFunc ¶
type UpdatePolicyFunc func(from, to *LaidOutStructure) (bool, ResolvedContentFilterFunc)
UpdatePolicyFunc is a callback that evaluates the provided pair of (potentially not yet resolved) structures and returns true when the pair should be part of an update. It may also return a filter function for the resolved content when not all of the content should be applied as part of the update (e.g. when updating assets from the kernel snap).
type Updater ¶
type Updater interface { // Update applies the update or errors out on failures. When no actual // update was applied because the new content is identical a special // ErrNoUpdate is returned. Update() error // Backup prepares a backup copy of data that will be modified by // Update() Backup() error // Rollback restores data modified by update Rollback() error }
type ValidationConstraints ¶
type ValidationConstraints struct { // EncryptedData when true indicates that the gadget will be used on a // device where the data partition will be encrypted. EncryptedData bool }
ValidationConstraints carries extra constraints on top of those implied by the model to use for gadget validation. They might be constraints that are determined only at runtime.
type Volume ¶
type Volume struct { // Partial is a list of properties that are only only partially // described in the gadget and that need to be filled by an // installer. Partial []PartialProperty `yaml:"partial,omitempty" json:"partial,omitempty"` // Schema for the volume can be either gpt or mbr. Schema string `yaml:"schema" json:"schema"` // Bootloader names the bootloader used by the volume Bootloader string `yaml:"bootloader" json:"bootloader"` // ID is a 2-hex digit disk ID or GPT GUID ID string `yaml:"id" json:"id"` // Structure describes the structures that are part of the volume Structure []VolumeStructure `yaml:"structure" json:"structure"` // Name is the name of the volume from the gadget.yaml Name string `json:"-"` // AssignedDevice is set during runtime to assign a specific gadget // volume to a device, eg. /dev/disk/by-path/pci-42:0. This is only // set optionally if matched against the volume-assignments. AssignedDevice string `json:"-"` }
Volume defines the structure and content for the image to be written into a block device.
func FindBootVolume ¶
FindBootVolume returns the volume that contains the system-boot partition.
func (*Volume) HasPartial ¶
func (v *Volume) HasPartial(pp PartialProperty) bool
HasPartial checks if the volume has a partially defined part.
func (*Volume) StructFromYamlIndex ¶
func (v *Volume) StructFromYamlIndex(yamlIdx int) *VolumeStructure
StructFromYamlIndex returns the structure defined at a given yaml index from the original yaml file.
type VolumeAssignment ¶
type VolumeAssignment struct { // Name is the assignment variant name Name string `yaml:"assignment-name"` // Assignments maps a volume name to an actual device assignment Assignments map[string]*DeviceAssignment `yaml:"assignment"` }
VolumeAssignment is an optional set of volume-to-disk assignments that can be specified. This is a nice way of reusing the same gadget for multiple devices, or a way to map multiple volumes to the same disk for cases like eMMC. Each assignment in this structure refers to a volume and a device path (/dev/disk/** for now).
type VolumeCompatibilityOptions ¶
type VolumeCompatibilityOptions struct { // AssumeCreatablePartitionsCreated will assume that all partitions such as // ubuntu-data, ubuntu-save, etc. that are creatable in install mode have // already been created and thus must be already exactly matching that which // is in the gadget.yaml. AssumeCreatablePartitionsCreated bool // AllowImplicitSystemData allows the system-data role to be missing from // the gadget volume as was allowed in UC18 and UC16 where the system-data // partition would be dynamically inserted into the image at image build // time by ubuntu-image without being mentioned in the gadget.yaml. AllowImplicitSystemData bool // ExpectedStructureEncryption is a map of the structure name to information // about the encrypted partitions that can be used to validate whether a // given structure should be accepted as an encrypted partition. ExpectedStructureEncryption map[string]StructureEncryptionParameters }
VolumeCompatibilityOptions is a set of options for determining how strict to be when evaluating whether an on-disk structure matches a laid out structure.
type VolumeContent ¶
type VolumeContent struct { // UnresovedSource is the data of the partition relative to // the gadget base directory UnresolvedSource string `yaml:"source" json:"source"` // Target is the location of the data inside the root filesystem Target string `yaml:"target" json:"target"` // Image names the image, relative to gadget base directory, to be used // for a 'bare' type structure Image string `yaml:"image" json:"image"` // Offset the image is written at Offset *quantity.Offset `yaml:"offset" json:"offset"` // Size of the image, when empty size is calculated by looking at the // image Size quantity.Size `yaml:"size" json:"size"` Unpack bool `yaml:"unpack" json:"unpack"` }
VolumeContent defines the contents of the structure. The content can be either files within a filesystem described by the structure or raw images written into the area of a bare structure.
func (VolumeContent) String ¶
func (vc VolumeContent) String() string
type VolumeStructure ¶
type VolumeStructure struct { // VolumeName is the name of the volume that this structure belongs to. VolumeName string `json:"-"` // Name, when non empty, provides the name of the structure Name string `yaml:"name" json:"name"` // Label provides the filesystem label Label string `yaml:"filesystem-label" json:"filesystem-label"` // Offset defines a starting offset of the structure Offset *quantity.Offset `yaml:"offset" json:"offset"` // OffsetWrite describes a 32-bit address, within the volume, at which // the offset of the current structure will be written. Initially, the // position could be specified as a byte offset relative to the start // of any named structure in the volume, but now the scope has been // limited and the only accepted structure would be one with offset // 0. Which implies that actually this offset will be always absolute, // which should be fine as the only known use case for this is to set // an address in an MBR. Furthermore, writes outside of the first // structure are now not allowed. OffsetWrite *RelativeOffset `yaml:"offset-write" json:"offset-write"` // Minimum size of the structure (optional) MinSize quantity.Size `yaml:"min-size" json:"min-size"` // Size of the structure Size quantity.Size `yaml:"size" json:"size"` // Type of the structure, which can be 2-hex digit MBR partition, // 36-char GUID partition, comma separated <mbr>,<guid> for hybrid // partitioning schemes, or 'bare' when the structure is not considered // a partition. // // For backwards compatibility type 'mbr' is also accepted, and the // structure is treated as if it is of role 'mbr'. Type string `yaml:"type" json:"type"` // Role describes the role of given structure, can be one of // 'mbr', 'system-data', 'system-boot', 'system-boot-image', // 'system-boot-select' or 'system-recovery-select'. Structures of type 'mbr', must have a // size of 446 bytes and must start at 0 offset. Role string `yaml:"role" json:"role"` // ID is the GPT partition ID, this should always be made upper case for // comparison purposes. ID string `yaml:"id" json:"id"` // Filesystem used for the partition, 'vfat', 'vfat-{16,32}', 'ext4' or 'none' for // structures of type 'bare'. 'vfat' is a synonymous for 'vfat-32'. Filesystem string `yaml:"filesystem" json:"filesystem"` // Content of the structure Content []VolumeContent `yaml:"content" json:"content"` Update VolumeUpdate `yaml:"update" json:"update"` // Note that the Device field will never be part of the yaml // and just used as part of the POST /systems/<label> API that // is used by an installer. Device string `yaml:"-" json:"device,omitempty"` // Index of the structure definition in gadget YAML, note this starts at 0. YamlIndex int `yaml:"-" json:"-"` // EnclosingVolume is a pointer to the enclosing Volume, and should be used // exclusively to check for partial information that affects the // structure properties. EnclosingVolume *Volume `yaml:"-" json:"-"` }
VolumeStructure describes a single structure inside a volume. A structure can represent a partition, Master Boot Record, or any other contiguous range within the volume.
func (*VolumeStructure) Copy ¶
func (vs *VolumeStructure) Copy() *VolumeStructure
Copy makes a deep copy of the volume structure.
func (*VolumeStructure) HasFilesystem ¶
func (vs *VolumeStructure) HasFilesystem() bool
HasFilesystem tells us if the structure definition expects a filesystem.
func (*VolumeStructure) HasLabel ¶
func (vs *VolumeStructure) HasLabel(label string) bool
HasLabel checks if label matches the VolumeStructure label. It ignores capitals if the structure has a fat filesystem.
func (*VolumeStructure) IsPartition ¶
func (vs *VolumeStructure) IsPartition() bool
IsPartition returns true when the structure describes a partition in a block device.
func (*VolumeStructure) IsRoleMBR ¶
func (v *VolumeStructure) IsRoleMBR() bool
IsRoleMBR tells us if v has MBR role or not.
func (*VolumeStructure) LinuxFilesystem ¶
func (vs *VolumeStructure) LinuxFilesystem() string
LinuxFilesystem returns the linux filesystem that corresponds to the one specified in the gadget.