Skip to content

Commit

Permalink
fix mount and umount bug (#2029)
Browse files Browse the repository at this point in the history
  • Loading branch information
Stevent-fei authored Mar 7, 2023
1 parent 0b818f5 commit 3d81283
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 181 deletions.
195 changes: 131 additions & 64 deletions cmd/sealer/cmd/alpha/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,44 @@ package alpha

import (
"fmt"
"os"
"path/filepath"
"strings"
"time"

"github.com/containers/buildah"
"github.com/containers/storage"
"github.com/olekukonko/tablewriter"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"

"github.com/sealerio/sealer/common"
"github.com/sealerio/sealer/pkg/define/options"
"github.com/sealerio/sealer/pkg/imageengine/buildah"
imagebuildah "github.com/sealerio/sealer/pkg/imageengine/buildah"
utilsstrings "github.com/sealerio/sealer/utils/strings"
)

var longMountCmdDescription = `
mount the cluster image to '/var/lib/sealer/data/overlay2' the directory and check whether the contents of the build image and rootfs are consistent in advance
mount the cluster image to '/var/lib/containers/storage/overlay' the directory and check whether the contents of the build image and rootfs are consistent in advance
`

var exampleForMountCmd = `
sealer alpha mount(show mount list)
sealer alpha mount my-image
sealer alpha mount ba15e47f5969
sealer alpha mount imageID
`

const (
tableHeaderMountPath = "MOUNT PATH"
tableHeaderContainerID = "CONTAINER ID"
)

type MountService struct {
table *tablewriter.Table
engine *imagebuildah.Engine
store storage.Store
images []storage.Image
containers []storage.Container
builders []*buildah.Builder
}

func NewMountCmd() *cobra.Command {
mountCmd := &cobra.Command{
Use: "mount",
Expand All @@ -49,88 +62,142 @@ func NewMountCmd() *cobra.Command {
Example: exampleForMountCmd,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
var (
path string
imageID string
)

engine, err := buildah.NewBuildahImageEngine(options.EngineGlobalConfigurations{})
if err != nil {
return err
}

store := engine.ImageStore()
images, err := store.Images()
mountInfo, err := NewMountService()
if err != nil {
return err
}

//output mount list
if len(args) == 0 {
if err := mountList(images); err != nil {
if err := mountInfo.Show(); err != nil {
return err
}
return nil
}

for _, i := range images {
for _, name := range i.Names {
if name == args[0] || strings.Contains(i.ID, args[0]) {
imageID = i.ID
path = filepath.Join(common.DefaultLayerDir, imageID)
}
}
}

cid, err := engine.CreateContainer(&options.FromOptions{
Image: args[0],
Quiet: false,
})
_, err = mountInfo.Mount(args[0])
if err != nil {
return err
}
return nil
},
}
return mountCmd
}

//too fast to mount.
time.Sleep(time.Second * 1)
func NewMountService() (MountService, error) {
engine, err := imagebuildah.NewBuildahImageEngine(options.EngineGlobalConfigurations{})
if err != nil {
return MountService{}, err
}
store := engine.ImageStore()
containers, err := store.Containers()
if err != nil {
return MountService{}, err
}
images, err := store.Images()
if err != nil {
return MountService{}, err
}

mounts, err := engine.Mount(&options.MountOptions{Containers: []string{cid}})
if err != nil {
return err
}
builders, err := buildah.OpenAllBuilders(store)
if err != nil {
return MountService{}, err
}

// remove destination dir if it exists, otherwise the Symlink will fail.
if _, err = os.Stat(path); err == nil {
return fmt.Errorf("destination directionay %s exists, you should remove it first", path)
}
table := tablewriter.NewWriter(common.StdOut)
table.SetHeader([]string{tableHeaderContainerID, tableHeaderMountPath})

return MountService{
table: table,
engine: engine,
store: store,
images: images,
containers: containers,
builders: builders,
}, nil
}

mountPoint := mounts[0].MountPoint
if err := os.Symlink(mountPoint, path); err != nil {
return err
func (m MountService) Show() error {
clients, err := buildah.OpenAllBuilders(m.store)
if err != nil {
return fmt.Errorf("reading build Containers: %w", err)
}
for _, client := range clients {
mounted, err := client.Mounted()
if err != nil {
return err
}
for _, container := range m.containers {
if client.ContainerID == container.ID && mounted {
containerID := imagebuildah.TruncateID(client.ContainerID, true)
m.table.Append([]string{containerID, client.MountPoint})
}
}
}
m.table.Render()
return nil
}

logrus.Infof("mount cluster image %s to %s successful", args[0], path)
return nil
},
func (m MountService) getMountedImageID(container storage.Container) string {
var imageID string
for _, image := range m.images {
if container.ImageID == image.ID {
imageID = image.ID
}
}
return mountCmd
return imageID
}

func mountList(images []storage.Image) error {
table := tablewriter.NewWriter(common.StdOut)
table.SetHeader([]string{imageName, "mountpath"})
for _, i := range images {
for _, name := range i.Names {
err := filepath.Walk(common.DefaultLayerDir, func(path string, f os.FileInfo, err error) error {
if f.Name() == i.ID {
table.Append([]string{name, filepath.Join(common.DefaultLayerDir, i.ID)})
}
return nil
})
if err != nil {
return err
func (m MountService) getImageID(name string) string {
for _, image := range m.images {
if strings.HasPrefix(image.ID, name) {
return image.ID
}
for _, n := range image.Names {
if name == n {
return image.ID
}
}
}
table.Render()
return nil
return ""
}

func (m MountService) Mount(imageNameOrID string) (string, error) {
var imageIDList []string

for _, builder := range m.builders {
mounted, err := builder.Mounted()
if err != nil {
return "", err
}
for _, container := range m.containers {
if builder.ContainerID == container.ID && mounted {
imageID := m.getMountedImageID(container)
imageIDList = append(imageIDList, imageID)
}
}
}

imageID := m.getImageID(imageNameOrID)
ok := utilsstrings.IsInSlice(imageID, imageIDList)
if ok {
logrus.Warnf("this image has already been mounted, please do not repeat the operation")
return "", nil
}
cid, err := m.engine.CreateContainer(&options.FromOptions{
Image: imageID,
Quiet: false,
})
if err != nil {
return "", err
}
mounts, err := m.engine.Mount(&options.MountOptions{Containers: []string{cid}})
if err != nil {
return "", err
}
mountPoint := mounts[0].MountPoint
logrus.Infof("mount cluster image %s to %s successful", imageNameOrID, mountPoint)

return mountPoint, nil
}
Loading

0 comments on commit 3d81283

Please sign in to comment.