Skip to content

Commit

Permalink
fix mount and umount bug
Browse files Browse the repository at this point in the history
  • Loading branch information
Stevent-fei committed Mar 1, 2023
1 parent f983d9b commit bd2d1c4
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 169 deletions.
201 changes: 140 additions & 61 deletions cmd/sealer/cmd/alpha/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,121 +16,200 @@ 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 my-image my-image1 my-image2
sealer alpha mount imageID
sealer alpha mount imageID1 imageID2 imageID3
`

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",
Short: "mount cluster image",
Long: longMountCmdDescription,
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,
})
if err != nil {
if err := mountInfo.Mount(args); 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 := imagebuildah.OpenBuilders(store)
if err != nil {
return MountService{}, err
}

table := tablewriter.NewWriter(common.StdOut)
table.SetHeader([]string{imageName, tableHeaderContainerID, tableHeaderMountPath})

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

// 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)
func (m MountService) getMountedImageName(container storage.Container) string {
for _, image := range m.images {
for _, name := range image.Names {
if container.ImageID == image.ID {
return name
}
}
}
return ""
}

mountPoint := mounts[0].MountPoint
if err := os.Symlink(mountPoint, path); err != nil {
return err
func (m MountService) Show() error {
clients, err := imagebuildah.OpenBuilders(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 {
name := m.getMountedImageName(container)
containerID := imagebuildah.TruncateID(client.ContainerID, true)
m.table.Append([]string{name, 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
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
}
}
}
return ""
}

func (m MountService) Mount(imageNameOrID []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)
}
}
}

for _, name := range imageNameOrID {
imageID := m.getImageID(name)
ok := utilsstrings.IsInSlice(imageID, imageIDList)
if ok {
logrus.Infof("this image has already been mounted, please do not repeat the operation")
} else {
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", name, mountPoint)
}
}
table.Render()
return nil
}
Loading

0 comments on commit bd2d1c4

Please sign in to comment.