kata-containers/runtime/patches/0039-storage-add-storage-common-functions-and-structs.patch
jiangpengfei 9a08f603ad kata-containers: move all kata related source repo into one repo kata-containers
reason: in order to make manage kata-containers related source code more easy,
we decide to move all kata related source repo into kata-containers repo.

Signed-off-by: jiangpengfei <jiangpengfei9@huawei.com>
2020-12-31 17:34:19 +08:00

246 lines
7.0 KiB
Diff

From a36c9857447aaf22628af1ef01406a916436133b Mon Sep 17 00:00:00 2001
From: jiangpengfei <jiangpengfei9@huawei.com>
Date: Tue, 18 Aug 2020 22:00:04 +0800
Subject: [PATCH 39/50] storage: add storage common functions and structs
reason:
1. add storage.go and storage_spec.go
2. provide funcs for mount nfs and gpath
Signed-off-by: jiangpengfei <jiangpengfei9@huawei.com>
---
virtcontainers/storage/storage.go | 115 +++++++++++++++++++++++++++++++++
virtcontainers/storage/storage_spec.go | 98 ++++++++++++++++++++++++++++
2 files changed, 213 insertions(+)
create mode 100644 virtcontainers/storage/storage.go
create mode 100644 virtcontainers/storage/storage_spec.go
diff --git a/virtcontainers/storage/storage.go b/virtcontainers/storage/storage.go
new file mode 100644
index 00000000..77ef994f
--- /dev/null
+++ b/virtcontainers/storage/storage.go
@@ -0,0 +1,115 @@
+// Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+// Description: common functions
+// Author: licuifang
+// Create: 2019-07-14
+
+// Package storage provides functions for mounting
+package storage
+
+import (
+ "fmt"
+ "path/filepath"
+ "regexp"
+ "strings"
+
+ "github.com/kata-containers/agent/protocols/grpc"
+ "github.com/opencontainers/runtime-spec/specs-go"
+)
+
+var (
+ // simple regular expressions for "nfs-server.com:/aaa/bbb/ccc/" or "192.168.1.1:/remote/path"
+ regUrl = regexp.MustCompile(`^((([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6})|((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))):/[A-Za-z0-9_./-]{0,1000}$`)
+
+ defaultMountOption = "nolock"
+ storageMountOptionKey = "mount_op"
+ storageCustomOptionKey = "custom_op"
+)
+
+type RemoteStorage struct {
+ Source string
+ Dest string
+ Options map[string][]string
+}
+
+func (n *RemoteStorage) Validate(volumeType string) error {
+ if n.Source == "" || n.Dest == "" {
+ return fmt.Errorf("the source and dest of storage cannot be empty")
+ }
+ switch volumeType {
+ case NFS:
+ chk := regUrl.FindAllString(n.Source, -1)
+ if chk == nil {
+ return fmt.Errorf("invalid url for nfs")
+ }
+ case GPATHFS:
+ if !filepath.IsAbs(n.Source) {
+ return fmt.Errorf("invalid gpath")
+ }
+ }
+
+ return nil
+}
+
+func (n *RemoteStorage) GetGrpcStorageAndAppendMount(volumeType string, vmBasePath string, spec *specs.Spec, sandboxId string) *grpc.Storage {
+ var (
+ grpcStorag *grpc.Storage
+ vmPath string
+ )
+ switch volumeType {
+ case NFS:
+ // source of sfs like remote-nfs.com:/share-53ee51a1
+ // source of sfs with subpath like remote-nfs.com:/share-53ee51a1/aaa/bbb
+ // source of sfs-turbo like ip:/
+ // source of sfs-turbo with subpath like ip://aaa or ip://aaa/bbb
+ // here we only get the origin source such as remote-nfs.com:/share-53ee51a1 or ip:/ as the Source of grpcStorage
+ item := strings.Split(n.Source, ":")
+ if len(item) != 2 {
+ return nil
+ }
+ vmPath = filepath.Join(vmBasePath, sandboxId, item[0], item[1])
+ parts := strings.SplitAfter(item[1], "/")
+ if len(parts) > 2 {
+ n.Source = item[0] + ":" + parts[0] + parts[1]
+ }
+
+ grpcStorag = &grpc.Storage{
+ Driver: NFS,
+ Source: n.Source,
+ MountPoint: vmPath,
+ }
+ grpcStorag.Options = append(grpcStorag.Options, defaultMountOption)
+ case GPATHFS:
+ vmPath = n.Source
+ grpcStorag = &grpc.Storage{
+ Driver: GPATHFS,
+ Source: vmPath,
+ MountPoint: n.Dest,
+ }
+ }
+ if custumOpts, ok := n.Options[storageCustomOptionKey]; ok {
+ for _, custumOpt := range custumOpts {
+ grpcStorag.Options = append(grpcStorag.Options, custumOpt)
+ }
+ }
+
+ mnt := specs.Mount{
+ Source: vmPath,
+ Destination: n.Dest,
+ }
+ if mountOpts, ok := n.Options[storageMountOptionKey]; ok {
+ for _, mountOpt := range mountOpts {
+ if mountOpt == "shared" {
+ // in order to support "shared" propagation for guestpath mounting to container directory
+ // we should set rootfspropagation shared
+ spec.Linux.RootfsPropagation = "shared"
+ }
+ mnt.Options = append(mnt.Options, mountOpt)
+ }
+ }
+ mnt.Options = append(mnt.Options, "rbind")
+ mnt.Type = "bind"
+ spec.Mounts = append(spec.Mounts, mnt)
+
+ return grpcStorag
+}
diff --git a/virtcontainers/storage/storage_spec.go b/virtcontainers/storage/storage_spec.go
new file mode 100644
index 00000000..8e866b8d
--- /dev/null
+++ b/virtcontainers/storage/storage_spec.go
@@ -0,0 +1,98 @@
+// Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
+// Description: common functions
+// Author: caihaomin c00416947
+// Create: 2019-05-05
+
+package storage
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/kata-containers/agent/protocols/grpc"
+ "github.com/opencontainers/runtime-spec/specs-go"
+)
+
+const (
+ NFS = "nfs"
+ GPATHFS = "gpath"
+)
+
+// STORAGES specifies the storage type and is supported
+var STORAGES = map[string]bool{
+ NFS: true,
+ GPATHFS: true,
+}
+
+type StorageSpec struct {
+ // StorageType specifies the type of storage passing down
+ StorageType string `json:"storage_type,omitempty"`
+
+ Source string `json:"source,omitempty"`
+ Destination string `json:"dest,omitempty"`
+
+ // Options specifies the options of storage type
+ Options map[string][]string `json:"options,omitempty"`
+}
+
+func (s *StorageSpec) generateInstances() StorageOperation {
+ var storageOpt StorageOperation
+ storageOpt = &RemoteStorage{
+ Source: s.Source,
+ Dest: s.Destination,
+ Options: s.Options,
+ }
+
+ return storageOpt
+}
+
+func ValidateStorageValue(value string) error {
+ var storageSpecs []StorageSpec
+ if err := json.Unmarshal([]byte(value), &storageSpecs); err != nil {
+ return err
+ }
+
+ var storageOpt []StorageOperation
+ for _, item := range storageSpecs {
+ if supported, ok := STORAGES[item.StorageType]; !ok || !supported {
+ return fmt.Errorf("type %s of storage is not supported", item.StorageType)
+ }
+ storageItem := item.generateInstances()
+ if err := storageItem.Validate(item.StorageType); err != nil {
+ return err
+ }
+ storageOpt = append(storageOpt, storageItem)
+ }
+
+ return nil
+}
+
+func GetGrpcStorageAndAppendMount(vmBasePath, value string, spec *specs.Spec, sandboxId string) []*grpc.Storage {
+ var (
+ grpcStorages []*grpc.Storage
+ storageSpec []StorageSpec
+ )
+
+ // the value has been validated before, and there is no need to judge the return value here
+ json.Unmarshal([]byte(value), &storageSpec)
+ for _, item := range storageSpec {
+ storageItem := item.generateInstances()
+ grpcStorages = append(grpcStorages, storageItem.GetGrpcStorageAndAppendMount(item.StorageType, vmBasePath, spec, sandboxId))
+ }
+ return grpcStorages
+}
+
+type StorageOperation interface {
+ Validate(volumeType string) error
+ GetGrpcStorageAndAppendMount(volumeType string, vmBasePath string, spec *specs.Spec, sandboxId string) *grpc.Storage
+}
+
+type FakeStorage struct{}
+
+func (f *FakeStorage) Validate() error {
+ return nil
+}
+
+func (f *FakeStorage) GetGrpcStorageAndAppendMount(vmBasePath string, spec *specs.Spec) *grpc.Storage {
+ return &grpc.Storage{}
+}
--
2.14.3 (Apple Git-98)