Skip to content

Commit

Permalink
Add sealer alpha mount and umount command (#1848)
Browse files Browse the repository at this point in the history
  • Loading branch information
Stevent-fei authored Jan 16, 2023
1 parent 3812a82 commit f816172
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 5 deletions.
2 changes: 2 additions & 0 deletions cmd/sealer/cmd/alpha/alpha.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,7 @@ func NewCmdAlpha() *cobra.Command {
cmd.AddCommand(NewSearchCmd())
cmd.AddCommand(NewManifestCmd())
cmd.AddCommand(NewHostAliasCmd())
cmd.AddCommand(NewMountCmd())
cmd.AddCommand(NewUmountCmd())
return cmd
}
119 changes: 119 additions & 0 deletions cmd/sealer/cmd/alpha/mount.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright © 2021 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package alpha

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

"github.com/containers/storage"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"

"github.com/olekukonko/tablewriter"
"github.com/sealerio/sealer/common"
"github.com/sealerio/sealer/pkg/define/options"
"github.com/sealerio/sealer/pkg/imageengine"
"github.com/sealerio/sealer/pkg/imageengine/buildah"
)

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
`

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

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()
if err != nil {
return err
}

//output mount list
if len(args) == 0 {
if err := mountList(images); 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)
}
}
}

imageEngine, err := imageengine.NewImageEngine(options.EngineGlobalConfigurations{})
if err != nil {
return err
}
if _, err := imageEngine.CreateWorkingContainer(&options.BuildRootfsOptions{
DestDir: path,
ImageNameOrID: args[0],
}); err != nil {
return err
}
logrus.Infof("mount cluster image %s to %s successful", args[0], path)
return nil
},
}
return mountCmd
}

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
}
}
}
table.Render()
return nil
}
173 changes: 173 additions & 0 deletions cmd/sealer/cmd/alpha/umount.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// Copyright © 2021 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package alpha

import (
"fmt"
"io/fs"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/sealerio/sealer/common"
imagecommon "github.com/sealerio/sealer/pkg/define/options"
"github.com/sealerio/sealer/pkg/imageengine"
"github.com/sealerio/sealer/pkg/imageengine/buildah"

"github.com/containers/storage"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

var umountAll bool

var longUmountCmdDescription = `
umount the cluster image and delete the mount directory
`

var exampleForUmountCmd = `
sealer alpha umount my-image
sealer alpha umount ba15e47f5969
sealer alpha umount --all
`

func NewUmountCmd() *cobra.Command {
umountCmd := &cobra.Command{
Use: "umount",
Short: "umount cluster image",
Long: longUmountCmdDescription,
Example: exampleForUmountCmd,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
var containerID string
var imgName string

if len(args) == 0 && !umountAll {
return fmt.Errorf("you must input imageName Or imageIp")
}

imageEngine, err := imageengine.NewImageEngine(imagecommon.EngineGlobalConfigurations{})
if err != nil {
return err
}

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

store := engine.ImageStore()
containers, err := store.Containers()
if err != nil {
return err
}

files, err := ioutil.ReadDir(common.DefaultLayerDir)
if err != nil {
return err
}

// umount all cluster image
if umountAll {
for _, c := range containers {
if err := imageEngine.RemoveContainer(&imagecommon.RemoveContainerOptions{
ContainerNamesOrIDs: []string{c.ID}},
); err != nil {
return err
}
}

for _, file := range files {
if err := os.RemoveAll(filepath.Join(common.DefaultLayerDir, file.Name())); err != nil {
return err
}
}
logrus.Infof("umount all cluster image successful")
return nil
}

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

for _, image := range images {
for _, name := range image.Names {
if strings.Contains(image.ID, args[0]) {
imgName = name
}
}
}

for _, c := range containers {
if strings.Contains(c.ImageID, args[0]) {
containerID = c.ID
break
}

id, err := getImageID(images, args[0])
if err != nil {
return err
}
if c.ImageID == id {
containerID = c.ID
imgName = args[0]
}
}

if err := imageEngine.RemoveContainer(&imagecommon.RemoveContainerOptions{
ContainerNamesOrIDs: []string{containerID}},
); err != nil {
return err
}

for _, file := range files {
for _, image := range images {
if err := removeContainerDir(image, file, imgName); err != nil {
return err
}
}
}

logrus.Infof("umount cluster image %s successful", args[0])
return nil
},
}
umountCmd.Flags().BoolVarP(&umountAll, "all", "a", false, "umount all cluster image directories")
return umountCmd
}

func getImageID(images []storage.Image, imageName string) (string, error) {
for _, image := range images {
for _, n := range image.Names {
if n == imageName {
return image.ID, nil
}
}
}
return "", fmt.Errorf("failed to get container id")
}

func removeContainerDir(image storage.Image, file fs.FileInfo, imageName string) error {
for _, n := range image.Names {
if n == imageName && file.Name() == image.ID {
if err := os.RemoveAll(filepath.Join(common.DefaultLayerDir, file.Name())); err != nil {
return err
}
}
}
return nil
}
5 changes: 3 additions & 2 deletions cmd/sealer/cmd/utils/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import (
"reflect"
"strconv"

"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"

"github.com/sealerio/sealer/cmd/sealer/cmd/types"
"github.com/sealerio/sealer/common"
"github.com/sealerio/sealer/pkg/client/k8s"
Expand All @@ -28,8 +31,6 @@ import (
v2 "github.com/sealerio/sealer/types/api/v2"
netutils "github.com/sealerio/sealer/utils/net"
strUtils "github.com/sealerio/sealer/utils/strings"
"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
)

func MergeClusterWithFlags(cluster v2.Cluster, mergeFlags *types.MergeFlags) (*v2.Cluster, error) {
Expand Down
1 change: 0 additions & 1 deletion cmd/sealer/cmd/utils/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
v1 "github.com/sealerio/sealer/types/api/v1"

"github.com/sealerio/sealer/common"

v2 "github.com/sealerio/sealer/types/api/v2"
)

Expand Down
5 changes: 3 additions & 2 deletions pkg/imageengine/buildah/from.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ import (
"os"
"strings"

"github.com/sealerio/sealer/pkg/define/options"

"github.com/containers/buildah"
"github.com/containers/buildah/define"
buildahcli "github.com/containers/buildah/pkg/cli"
"github.com/containers/buildah/pkg/parse"
"github.com/containers/common/pkg/config"
encconfig "github.com/containers/ocicrypt/config"

"github.com/pkg/errors"

"github.com/sealerio/sealer/pkg/define/options"
)

type fromFlagsWrapper struct {
Expand Down

0 comments on commit f816172

Please sign in to comment.