Skip to content

Commit

Permalink
Option to mount image for booting host machine (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
outofforest authored Aug 24, 2022
1 parent 1c6bd75 commit c321cdd
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 10 deletions.
2 changes: 1 addition & 1 deletion commands/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func NewListCommand(cmdF *CmdFactory) *cobra.Command {
}

storageF = cmdF.AddStorageFlags(cmd)
filterF = cmdF.AddFilterFlags(cmd, []string{config.BuildTypeImage, config.BuildTypeMount, config.BuildTypeVM})
filterF = cmdF.AddFilterFlags(cmd, []string{config.BuildTypeImage, config.BuildTypeMount, config.BuildTypeBoot, config.BuildTypeVM})
formatF = cmdF.AddFormatFlags(cmd)
return cmd
}
1 change: 1 addition & 0 deletions commands/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func NewMountCommand(cmdF *CmdFactory) *cobra.Command {
}
storageF = cmdF.AddStorageFlags(cmd)
formatF = cmdF.AddFormatFlags(cmd)
cmd.Flags().BoolVar(&mountF.Boot, "boot", false, "Create mount used to boot host machine")
cmd.Flags().StringVar(&mountF.LibvirtAddr, "libvirt-addr", "unix:///var/run/libvirt/libvirt-sock", "Address libvirt listens on")
cmd.Flags().StringVar(&mountF.XMLDir, "xml-dir", must.String(os.UserHomeDir())+"/osman", "Directory where VM definition is taken from if vm-file argument is not provided")
cmd.Flags().StringVar(&mountF.VMFile, "vm", "", "Defines VM for mounted image in Libvirt using provided file. If flag is provided without value or value is `auto` then file is derived as <xml-dir>/<image-name>.xml")
Expand Down
4 changes: 4 additions & 0 deletions config/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ const (
// BuildTypeMount represents mount build
BuildTypeMount = "mount"

// BuildTypeBoot represents boot build
BuildTypeBoot = "boot"

// BuildTypeVM represents vm build
BuildTypeVM = "vm"
)

var typeMapping = map[string]types.BuildType{
BuildTypeImage: types.BuildTypeImage,
BuildTypeMount: types.BuildTypeMount,
BuildTypeBoot: types.BuildTypeBoot,
BuildTypeVM: types.BuildTypeVM,
}

Expand Down
9 changes: 9 additions & 0 deletions config/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (

// MountFactory collects data for mount config
type MountFactory struct {
// Boot means that the mount is created for booting host machine
Boot bool

// XMLDir is a directory where VM definition is taken from if xml file is not provided explicitly
XMLDir string

Expand All @@ -26,7 +29,13 @@ func (f *MountFactory) Config(args Args) Mount {
LibvirtAddr: f.LibvirtAddr,
Type: types.BuildTypeMount,
}
if f.Boot {
config.Type = types.BuildTypeBoot
}
if f.VMFile != "" {
if f.Boot {
panic(errors.New("can't mount as boot and vm at the same time"))
}
config.Type = types.BuildTypeVM
if f.VMFile != "auto" {
config.VMFile = f.VMFile
Expand Down
5 changes: 4 additions & 1 deletion functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,16 @@ func vmName(doc *etree.Document) string {

func cloneForMount(ctx context.Context, image types.BuildInfo, buildKey types.BuildKey, imageType types.BuildType, s storage.Driver) (retInfo types.BuildInfo, retErr error) {
buildID := types.NewBuildID(imageType)
if _, _, err := s.Clone(ctx, image.BuildID, buildKey.Name, buildID); err != nil {
finalizeFn, _, err := s.Clone(ctx, image.BuildID, buildKey.Name, buildID)
if err != nil {
return types.BuildInfo{}, err
}
defer func() {
if retErr != nil {
_ = s.Drop(ctx, buildID)
return
}
retErr = finalizeFn()
}()

if err := s.StoreManifest(ctx, types.ImageManifest{
Expand Down
26 changes: 20 additions & 6 deletions infra/storage/zfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (d *zfsDriver) Info(ctx context.Context, buildID types.BuildID) (types.Buil
}

mounted := ""
if buildID.Type().Properties().Mountable {
if buildID.Type().Properties().Mountable && filesystem.Info.Mountpoint != "none" {
mounted = filesystem.Info.Mountpoint
}
buildInfo.Mounted = mounted
Expand Down Expand Up @@ -131,8 +131,15 @@ func (d *zfsDriver) Clone(ctx context.Context, srcBuildID types.BuildID, dstImag
return nil, "", err
}

properties := dstBuildID.Type().Properties()

mountpoint := "none"
if properties.AutoMount {
mountpoint = "/" + d.config.Root + "/" + string(dstBuildID) + "/root"
}

filesystem, err := snapshot.Clone(ctx, d.config.Root+"/"+string(dstBuildID), zfs.CloneOptions{Properties: map[string]string{
"mountpoint": "/" + d.config.Root + "/" + string(dstBuildID) + "/root",
"mountpoint": mountpoint,
propertyName: string(must.Bytes(json.Marshal(types.BuildInfo{
BuildID: dstBuildID,
BasedOn: srcBuildID,
Expand All @@ -144,16 +151,23 @@ func (d *zfsDriver) Clone(ctx context.Context, srcBuildID types.BuildID, dstImag
return nil, "", err
}
return func() error {
properties := dstBuildID.Type().Properties()
if !properties.Mountable {
if err := filesystem.Unmount(ctx); err != nil {
if !properties.Mountable || !properties.AutoMount {
value, _, err := filesystem.GetProperty(ctx, "mounted")
if err != nil {
return err
}
if value == "yes" {
if err := filesystem.Unmount(ctx); err != nil {
return err
}
}
}
if !properties.Mountable {
if err := filesystem.SetProperty(ctx, "canmount", "off"); err != nil {
return err
}
}
if properties.Cloneable {
if properties.Cloneable || properties.Revertable {
if _, err := filesystem.Snapshot(ctx, "image"); err != nil {
return err
}
Expand Down
19 changes: 17 additions & 2 deletions infra/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,15 @@ type BuildTypeProperties struct {
// Cloneable means image may be cloned
Cloneable bool

// Mountable means image stays mounted
// Revertable means image might be reverted to original state
Revertable bool

// Mountable means image can't be mounted
Mountable bool

// AutoMount means image is automatically mounted
AutoMount bool

// VM means vm in libvirt is defined for this image
VM bool
}
Expand All @@ -100,16 +106,25 @@ const (
// BuildTypeMount is the mount build type
BuildTypeMount BuildType = "mid"

// BuildTypeBoot is the boot build type
BuildTypeBoot BuildType = "bid"

// BuildTypeVM is the vm build type
BuildTypeVM BuildType = "vid"
)

var buildTypes = map[BuildType]BuildTypeProperties{
BuildTypeImage: {
Cloneable: true,
Cloneable: true,
Revertable: true,
},
BuildTypeMount: {
Mountable: true,
AutoMount: true,
},
BuildTypeBoot: {
Mountable: true,
Revertable: true,
},
BuildTypeVM: {
Mountable: true,
Expand Down

0 comments on commit c321cdd

Please sign in to comment.