Files
Memoh/internal/containerd/mount.go

109 lines
2.3 KiB
Go

package containerd
import (
"context"
"fmt"
"os"
"github.com/containerd/containerd/v2/core/mount"
)
type MountedSnapshot struct {
Dir string
Info ContainerInfo
Unmount func() error
}
// MountContainerSnapshot mounts the active snapshot for a container.
func MountContainerSnapshot(ctx context.Context, service Service, containerID string) (*MountedSnapshot, error) {
if containerID == "" {
return nil, ErrInvalidArgument
}
info, err := service.GetContainer(ctx, containerID)
if err != nil {
return nil, err
}
mountInfos, err := service.SnapshotMounts(ctx, info.Snapshotter, info.SnapshotKey)
if err != nil {
return nil, err
}
mounts := make([]mount.Mount, len(mountInfos))
for i, m := range mountInfos {
mounts[i] = mount.Mount{
Type: m.Type,
Source: m.Source,
Options: m.Options,
}
}
dir, err := os.MkdirTemp("", "memoh-snapshot-*")
if err != nil {
return nil, err
}
if err := mount.All(mounts, dir); err != nil {
_ = os.RemoveAll(dir)
return nil, err
}
return &MountedSnapshot{
Dir: dir,
Info: info,
Unmount: func() error {
if err := mount.UnmountAll(dir, 0); err != nil {
return fmt.Errorf("unmount snapshot: %w", err)
}
if err := os.RemoveAll(dir); err != nil {
return fmt.Errorf("remove snapshot dir: %w", err)
}
return nil
},
}, nil
}
// MountSnapshot mounts a snapshot by snapshotter/key without a container.
func MountSnapshot(ctx context.Context, service Service, snapshotter, key string) (string, func() error, error) {
if snapshotter == "" || key == "" {
return "", nil, ErrInvalidArgument
}
mountInfos, err := service.SnapshotMounts(ctx, snapshotter, key)
if err != nil {
return "", nil, err
}
mounts := make([]mount.Mount, len(mountInfos))
for i, m := range mountInfos {
mounts[i] = mount.Mount{
Type: m.Type,
Source: m.Source,
Options: m.Options,
}
}
dir, err := os.MkdirTemp("", "memoh-snapshot-*")
if err != nil {
return "", nil, err
}
if err := mount.All(mounts, dir); err != nil {
_ = os.RemoveAll(dir)
return "", nil, err
}
cleanup := func() error {
if err := mount.UnmountAll(dir, 0); err != nil {
return fmt.Errorf("unmount snapshot: %w", err)
}
if err := os.RemoveAll(dir); err != nil {
return fmt.Errorf("remove snapshot dir: %w", err)
}
return nil
}
return dir, cleanup, nil
}