From 1268b710c7f0528d971d9c0e54429d3f4e48c372 Mon Sep 17 00:00:00 2001 From: holyfei Date: Tue, 18 Aug 2020 16:45:29 +0800 Subject: [PATCH 09/16] storage: add pkg/storage for mount reason: add gpath.go and nfs.go, provide mount functions and structs Signed-off-by: yangfeiyu --- pkg/storage/gpath.go | 64 ++++++++++++++++++++++++++++++++++++ pkg/storage/nfs.go | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 pkg/storage/gpath.go create mode 100644 pkg/storage/nfs.go diff --git a/pkg/storage/gpath.go b/pkg/storage/gpath.go new file mode 100644 index 0000000..5cb951f --- /dev/null +++ b/pkg/storage/gpath.go @@ -0,0 +1,64 @@ +// Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// Description: common functions +// Author: licuifang +// Create: 2019-06-24 + +package storage + +import ( + "fmt" + "os" + "syscall" + + "github.com/opencontainers/runc/libcontainer/mount" +) + +func ValidateGpath(guestPath string, opts []string) error { + for _, opt := range opts { + switch opt { + case "shared": + flag := syscall.MS_SHARED + if err := ensureMountedAs(guestPath, flag); err != nil { + return err + } + return nil + case "mounted": + // if mounted in option, the guestpath must exist and must be a mountpoint + _, err := os.Stat(guestPath) + if err != nil { + return err + } + mountpoint, err := mount.Mounted(guestPath) + if err != nil { + return err + } + if mountpoint == false { + return fmt.Errorf("the guespath:%s is not a mountpoint while mounted was set", guestPath) + } + return nil + } + } + if err := os.MkdirAll(guestPath, 0750); err != nil { + return err + } + return nil +} + +func ensureMountedAs(mountPoint string, flag int) error { + if err := os.MkdirAll(mountPoint, 0750); err != nil { + return err + } + mounted, err := mount.Mounted(mountPoint) + if err != nil { + return err + } + + if !mounted { + if err := syscall.Mount(mountPoint, mountPoint, "bind", uintptr(syscall.MS_BIND), ""); err != nil { + return err + } + } + + return syscall.Mount("", mountPoint, "", uintptr(flag), "") +} diff --git a/pkg/storage/nfs.go b/pkg/storage/nfs.go new file mode 100644 index 0000000..44bc85d --- /dev/null +++ b/pkg/storage/nfs.go @@ -0,0 +1,93 @@ +// Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// Description: common functions +// Author: leizhongkai +// Create: 2019-03-10 + +package storage + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "time" + + "github.com/opencontainers/runc/libcontainer/mount" + "github.com/sirupsen/logrus" +) + +const ( + NFS = "nfs" + + MAX_MOUNT_ATTEMPTS = 100 + MAX_MOUTN_TIMEOUT = 90 // seconds + + // ignored errors + PERMISSION_DENY = "Permission denied" + kataGuestStorageDir = "/run/kata-containers/storage/containers/" +) + +func nfsMount(source, dest string, opt string) error { + cmd := exec.Command("/bin/mount", "-t", "nfs", "-o", opt, source, dest) + res, err := cmd.Output() + logrus.Debugf("mount %s to %s, and get res %s", source, dest, string(res)) + return err +} + +func nfsMountWithAttempt(source, dest string, opt string) (err error) { + timeStart := time.Now().Unix() + for i := 0; i < MAX_MOUNT_ATTEMPTS; i++ { + logrus.Infof("this is the %d times to mount %s to %s", i, source, dest) + err = nfsMount(source, dest, opt) + if err != nil { + ee, ok := err.(*exec.ExitError) + if ok { + if strings.Contains(string(ee.Stderr), PERMISSION_DENY) { + logrus.Errorf("mounting nfs:%s to %s, get error: %s,should break", source, dest, string(ee.Stderr)) + // We do not retry when the error type is PERMISSION_DENY. + // The reason for the retry is that when you do a SFS mount, + // the network may not have been created yet, because + // creating the network and startup container is asynchronous + break + } + logrus.Infof("mounting nfs:%s to %s, get error: %s,will retry", source, dest, string(ee.Stderr)) + } + + elapsed := time.Now().Unix() - timeStart + if elapsed < MAX_MOUTN_TIMEOUT { + time.Sleep(50 * time.Microsecond) + continue + } + } + break + } + + return err +} + +func MountRemoteNfs(source string, opt []string, sandboxId string) error { + item := strings.Split(source, ":") + if len(item) != 2 { + return fmt.Errorf("the nfs of %s format is error", source) + } + tmpDes := filepath.Join(kataGuestStorageDir, sandboxId, item[0],item[1]) + if mounted, err := mount.Mounted(tmpDes); err == nil && mounted == true { + return nil + } + err := os.MkdirAll(tmpDes, 0750) + if err != nil { + logrus.Infof("mkdir %s failed before mount remote nfs server", tmpDes) + return err + } + defer func() { + if err != nil { + os.RemoveAll(tmpDes) + } + }() + + err = nfsMountWithAttempt(source, tmpDes, strings.Join(opt, ",")) + + return err +} -- 2.14.3 (Apple Git-98)