gadget

package
v0.0.0-...-1a99902 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2020 License: GPL-3.0 Imports: 28 Imported by: 0

Documentation

Index

Constants

View Source
const (
	SystemBoot = "system-boot"
	SystemData = "system-data"
	SystemSeed = "system-seed"
)
View Source
const (
	SizeKiB = Size(1 << 10)
	SizeMiB = Size(1 << 20)
	SizeGiB = Size(1 << 30)

	// SizeMBR is the maximum byte size of a structure of role 'mbr'
	SizeMBR = Size(446)
	// SizeLBA48Pointer is the byte size of a pointer value written at the
	// location described by 'offset-write'
	SizeLBA48Pointer = Size(4)
)

Variables

View Source
var ErrDeviceNotFound = errors.New("device not found")
View Source
var ErrMountNotFound = errors.New("mount point not found")
View Source
var ErrNoFilesystemDefined = errors.New("no filesystem defined")
View Source
var (
	ErrNoUpdate = errors.New("nothing to update")
)

Functions

func CreatedDuringInstall

func CreatedDuringInstall(layout *OnDiskVolume) (created []string)

CreatedDuringInstall returns a list of partitions created during the install process.

func FindDeviceForStructure

func FindDeviceForStructure(ps *LaidOutStructure) (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 IsCompatible

func IsCompatible(current, new *Info) error

IsCompatible checks whether the current and an update are compatible. Returns nil or an error describing the incompatibility.

func MockUpdaterForStructure

func MockUpdaterForStructure(mock func(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 ParentDiskFromPartition

func ParentDiskFromPartition(partition string) (string, error)

ParentDiskFromPartition will find the parent disk device for the given partition. E.g. /dev/nvmen0n1p5 -> /dev/nvme0n1

Note that this does not work for anything using device mapper (like LUKS/LVM) yet.

func RemodelUpdatePolicy

func RemodelUpdatePolicy(from, _ *LaidOutStructure) bool

RemodelUpdatePolicy implements the update policy of a remodel scenario. The policy selects all non-MBR structures for the update.

func SystemDefaults

func SystemDefaults(gadgetDefaults map[string]map[string]interface{}) map[string]interface{}

SystemDefaults returns default system configuration from gadget defaults.

func Update

func Update(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 tructures 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.

func UpdatePartitionList

func UpdatePartitionList(dl *OnDiskVolume) error

UpdatePartitionList re-reads the partitioning data from the device and updates the partition list in the specified volume.

func Validate

func Validate(gadgetSnapRootDir string, model Model) error

Validate checks whether the given directory contains valid gadget snap metadata and a matching content, under the provided model constraints, which are handled identically to ReadInfo().

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

type ConnectionPlug struct {
	SnapID string
	Plug   string
}

func (*ConnectionPlug) Empty

func (gcplug *ConnectionPlug) Empty() bool

func (*ConnectionPlug) UnmarshalYAML

func (gcplug *ConnectionPlug) UnmarshalYAML(unmarshal func(interface{}) error) error

type ConnectionSlot

type ConnectionSlot struct {
	SnapID string
	Slot   string
}

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 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.
	//
	// 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.
	Observe(op ContentOperation, sourceStruct *LaidOutStructure,
		targetRootDir, relativeTargetPath string, dataChange *ContentChange) (bool, error)
}

ContentObserver allows for observing operations on the content of the gadget structures.

type ContentOperation

type ContentOperation int
const (
	ContentWrite ContentOperation = iota
	ContentUpdate
	ContentRollback
)

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 GadgetData

type GadgetData struct {
	// Info is the gadget metadata
	Info *Info
	// RootDir is the root directory of gadget snap data
	RootDir string
}

GadgetData holds references to a gadget revision metadata and its data directory.

type Info

type Info struct {
	Volumes map[string]Volume `yaml:"volumes,omitempty"`

	// Default configuration for snaps (snap-id => key => value).
	Defaults map[string]map[string]interface{} `yaml:"defaults,omitempty"`

	Connections []Connection `yaml:"connections"`
}

func InfoFromGadgetYaml

func InfoFromGadgetYaml(gadgetYaml []byte, model Model) (*Info, error)

InfoFromGadgetYaml reads the provided gadget metadata. If constraints is nil, only the self-consistency checks are performed, otherwise rules for the classic or system seed cases are enforced.

func ReadInfo

func ReadInfo(gadgetSnapRootDir string, model Model) (*Info, error)

ReadInfo reads the gadget specific metadata from meta/gadget.yaml in the snap root directory. If constraints is nil, ReadInfo will just check for self-consistency, otherwise rules for the classic or system seed cases are enforced.

func ReadInfoFromSnapFile

func ReadInfoFromSnapFile(snapf snap.Container, model Model) (*Info, error)

ReadInfoFromSnapFile reads the gadget specific metadata from meta/gadget.yaml in the given snap container. If constraints is nil, ReadInfo will just check for self-consistency, otherwise rules for the classic or system seed cases are enforced.

type LaidOutContent

type LaidOutContent struct {
	*VolumeContent

	// StartOffset defines the start offset of this content image
	StartOffset Size
	// AbsoluteOffsetWrite is the resolved absolute position of offset-write
	// for this content element within the enclosing volume
	AbsoluteOffsetWrite *Size
	// Size is the maximum size occupied by this image
	Size 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

func (LaidOutContent) String

func (p LaidOutContent) String() string

type LaidOutStructure

type LaidOutStructure struct {
	*VolumeStructure
	// StartOffset defines the start offset of the structure within the
	// enclosing volume
	StartOffset Size
	// AbsoluteOffsetWrite is the resolved absolute position of offset-write
	// for this structure element within the enclosing volume
	AbsoluteOffsetWrite *Size
	// Index of the structure definition in gadget YAML
	Index int
	// LaidOutContent is a list of raw content inside the structure
	LaidOutContent []LaidOutContent
}

LaidOutStructure describes a VolumeStructure that has been placed within the volume

func ShiftStructureTo

func ShiftStructureTo(ps LaidOutStructure, offset Size) LaidOutStructure

ShiftStructureTo translates the starting offset of a laid out structure and its content to the provided offset.

func (LaidOutStructure) String

func (p LaidOutStructure) String() string

type LaidOutVolume

type LaidOutVolume struct {
	*Volume
	// Size is the total size of the volume
	Size Size
	// SectorSize sector size of the volume
	SectorSize Size
	// LaidOutStructure is a list of structures within the volume, sorted
	// by their start offsets
	LaidOutStructure []LaidOutStructure
	// RootDir is the root directory for volume data
	RootDir string
}

LaidOutVolume defines the size of a volume and arrangement of all the structures within it

func LayoutVolume

func LayoutVolume(gadgetRootDir string, volume *Volume, constraints LayoutConstraints) (*LaidOutVolume, error)

LayoutVolume attempts to completely lay out the volume, that is the structures and their content, using provided constraints

func PositionedVolumeFromGadget

func PositionedVolumeFromGadget(gadgetRoot string) (*LaidOutVolume, error)

PositionedVolumeFromGadget takes a gadget rootdir and positions the partitions as specified.

type LayoutConstraints

type LayoutConstraints struct {
	// NonMBRStartOffset is the default start offset of non-MBR structure in
	// the volume.
	NonMBRStartOffset Size
	// SectorSize is the size of the sector to be used for calculations
	SectorSize Size
}

LayoutConstraints defines the constraints for arranging structures within a volume

type Model

type Model interface {
	Classic() bool
	Grade() asserts.ModelGrade
}

Model carries information about the model that is 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(contentDir string, 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 OnDiskStructure

type OnDiskStructure struct {
	LaidOutStructure

	// Node identifies the device node of the block device.
	Node string
	// CreatedDuringInstall is true when the structure has properties indicating
	// it was created based on the gadget description during installation.
	CreatedDuringInstall bool
}

OnDiskStructure represents a gadget structure laid on a block device.

func BuildPartitionList

func BuildPartitionList(dl *OnDiskVolume, pv *LaidOutVolume) (sfdiskInput *bytes.Buffer, toBeCreated []OnDiskStructure)

BuildPartitionList builds a list of partitions based on the current device contents and gadget structure list, in sfdisk dump format, and returns a partitioning description suitable for sfdisk input and a list of the partitions to be created.

type OnDiskVolume

type OnDiskVolume struct {
	Structure []OnDiskStructure
	ID        string
	Device    string
	Schema    string
	// size in bytes
	Size Size
	// sector size in bytes
	SectorSize Size
	// contains filtered or unexported fields
}

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.

type PartiallyLaidOutVolume

type PartiallyLaidOutVolume struct {
	*Volume
	// SectorSize sector size of the volume
	SectorSize Size
	// 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.

func LayoutVolumePartially

func LayoutVolumePartially(volume *Volume, constraints LayoutConstraints) (*PartiallyLaidOutVolume, error)

LayoutVolumePartially attempts to lay out only the structures in the volume using provided constraints

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
	// Offset is a 32-bit value
	Offset Size
}

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 Size

type Size uint64

Size describes the size of a structure item or an offset within the structure.

func (*Size) IECString

func (s *Size) IECString() string

IECString formats the size using multiples from IEC units (i.e. kibibytes, mebibytes), that is as multiples of 1024. Printed values are truncated to 2 decimal points.

func (*Size) String

func (s *Size) String() string

func (*Size) UnmarshalYAML

func (s *Size) UnmarshalYAML(unmarshal func(interface{}) error) error

type UpdatePolicyFunc

type UpdatePolicyFunc func(from, to *LaidOutStructure) bool

UpdatePolicyFunc is a callback that evaluates the provided pair of structures and returns true when the pair should be part of an update.

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 Volume

type Volume struct {
	// Schema describes the schema used for the volume
	Schema string `yaml:"schema"`
	// Bootloader names the bootloader used by the volume
	Bootloader string `yaml:"bootloader"`
	//  ID is a 2-hex digit disk ID or GPT GUID
	ID string `yaml:"id"`
	// Structure describes the structures that are part of the volume
	Structure []VolumeStructure `yaml:"structure"`
}

Volume defines the structure and content for the image to be written into a block device.

func (*Volume) EffectiveSchema

func (v *Volume) EffectiveSchema() string

type VolumeContent

type VolumeContent struct {
	// Source is the data of the partition relative to the gadget base
	// directory
	Source string `yaml:"source"`
	// Target is the location of the data inside the root filesystem
	Target string `yaml:"target"`

	// Image names the image, relative to gadget base directory, to be used
	// for a 'bare' type structure
	Image string `yaml:"image"`
	// Offset the image is written at
	Offset *Size `yaml:"offset"`
	// OffsetWrite describes a 32-bit address, within the volume, at which
	// the offset of current image will be written. The position may be
	// specified as a byte offset relative to the start of a named structure
	OffsetWrite *RelativeOffset `yaml:"offset-write"`
	// Size of the image, when empty size is calculated by looking at the
	// image
	Size Size `yaml:"size"`

	Unpack bool `yaml:"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 {
	// Name, when non empty, provides the name of the structure
	Name string `yaml:"name"`
	// Label provides the filesystem label
	Label string `yaml:"filesystem-label"`
	// Offset defines a starting offset of the structure
	Offset *Size `yaml:"offset"`
	// OffsetWrite describes a 32-bit address, within the volume, at which
	// the offset of current structure will be written. The position may be
	// specified as a byte offset relative to the start of a named structure
	OffsetWrite *RelativeOffset `yaml:"offset-write"`
	// Size of the structure
	Size Size `yaml:"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"`
	// Role describes the role of given structure, can be one of
	// 'mbr', 'system-data', 'system-boot', 'system-boot-image',
	// 'system-boot-select'. Structures of type 'mbr', must have a
	// size of 446 bytes and must start at 0 offset.
	Role string `yaml:"role"`
	// ID is the GPT partition ID
	ID string `yaml:"id"`
	// Filesystem used for the partition, 'vfat', 'ext4' or 'none' for
	// structures of type 'bare'
	Filesystem string `yaml:"filesystem"`
	// Content of the structure
	Content []VolumeContent `yaml:"content"`
	Update  VolumeUpdate    `yaml:"update"`
}

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) EffectiveFilesystemLabel

func (vs *VolumeStructure) EffectiveFilesystemLabel() string

EffectiveFilesystemLabel returns the effective filesystem label, either explicitly provided or implied by the structure's role

func (*VolumeStructure) EffectiveRole

func (vs *VolumeStructure) EffectiveRole() string

EffectiveRole returns the role of given structure

func (*VolumeStructure) HasFilesystem

func (vs *VolumeStructure) HasFilesystem() bool

HasFilesystem returns true if the structure is using a filesystem.

func (*VolumeStructure) IsPartition

func (vs *VolumeStructure) IsPartition() bool

IsPartition returns true when the structure describes a partition in a block device.

type VolumeUpdate

type VolumeUpdate struct {
	Edition  edition.Number `yaml:"edition"`
	Preserve []string       `yaml:"preserve"`
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL