feat: Plugins add storage

This commit is contained in:
zhangsetsail 2022-06-07 19:20:31 +08:00 committed by yangkaa
parent 8ec269f393
commit a09edcba31
9 changed files with 169 additions and 5 deletions

View File

@ -93,6 +93,14 @@ type ResourceSpec struct {
BaseNormal BaseEnv `json:"base_normal"`
}
//PluginStorage 插件存储结构体
type PluginStorage struct {
VolumeName string `json:"volume_name"`
VolumePath string `json:"volume_path"`
FileContent string `json:"file_content"`
AttrType string `json:"attr_type"`
}
//BasePort base of current app ports
type BasePort struct {
ServiceAlias string `json:"service_alias"`

View File

@ -440,6 +440,9 @@ var ShareFileVolumeType VolumeType = "share-file"
//LocalVolumeType 本地文件存储
var LocalVolumeType VolumeType = "local"
//PluginStorageType 插件存储
var PluginStorageType VolumeType = "plugin-storage"
//MemoryFSVolumeType 内存文件存储
var MemoryFSVolumeType VolumeType = "memoryfs"

View File

@ -32,7 +32,7 @@ var translationMetadata = map[string]string{
"save image to hub error": "保存镜像到仓库失败",
"Please try again or contact customer service": "后端服务开小差,请重试或联系客服",
"unzip metadata file error": "解压数据失败",
"start service error": "启动服务失败,请检查集服务信息或查看日志",
"start service error": "启动服务失败,请检查集服务信息或查看日志",
"start service timeout": "启动服务超时,建议观察服务实例运行状态",
"stop service error": "停止服务失败,建议观察服务实例运行状态",
"stop service timeout": "停止服务超时,建议观察服务实例运行状态",

View File

@ -21,6 +21,7 @@ package conversion
import (
"encoding/json"
"fmt"
"github.com/goodrain/rainbond/worker/appm/volume"
"os"
"strconv"
"strings"
@ -181,6 +182,31 @@ func conversionServicePlugin(as *typesv1.AppService, dbmanager db.Manager) ([]v1
}
//create plugin config to configmap
for i := range appPlugins {
config, err := dbmanager.TenantPluginVersionConfigDao().GetPluginConfig(appPlugins[i].ServiceID,
appPlugins[i].PluginID)
if err != nil && err != gorm.ErrRecordNotFound {
logrus.Errorf("get service plugin config from db failure %s", err.Error())
}
if config != nil {
configStr := config.ConfigStr
var oldConfig api_model.ResourceSpec
if err := json.Unmarshal([]byte(configStr), &oldConfig); err == nil {
for key, plugin := range oldConfig.BaseNormal.Options {
var pluginStorage api_model.PluginStorage
jsonValue, ok := plugin.(string)
if !ok {
continue
}
if err := json.Unmarshal([]byte(jsonValue), &pluginStorage); err != nil {
continue
}
if pluginStorage.VolumeName != "" || pluginStorage.VolumePath != "" {
IsContainMount(&mainContainer.VolumeMounts, as, pluginStorage, config.PluginID)
delete(oldConfig.BaseNormal.Options, key)
}
}
}
}
ApplyPluginConfig(as, appPlugins[i], dbmanager, inboundPluginConfig)
}
//if need proxy but not install net plugin
@ -199,6 +225,11 @@ func conversionServicePlugin(as *typesv1.AppService, dbmanager db.Manager) ([]v1
initContainers = append(initContainers, bootSequence)
}
as.BootSeqContainer = &bootSequence
if len(as.GetPodTemplate().Spec.Containers) != 0 {
pluginMountVolume(initContainers, as.GetPodTemplate().Spec.Containers[0].VolumeMounts)
pluginMountVolume(precontainers, as.GetPodTemplate().Spec.Containers[0].VolumeMounts)
pluginMountVolume(postcontainers, as.GetPodTemplate().Spec.Containers[0].VolumeMounts)
}
return initContainers, precontainers, postcontainers, nil
}
@ -280,7 +311,6 @@ func ApplyPluginConfig(as *typesv1.AppService, servicePluginRelation *model.Tena
}
if config != nil {
configStr := config.ConfigStr
//if have inbound plugin,will Propagate its listner port to other plug-ins
if inboundPluginConfig != nil {
var oldConfig api_model.ResourceSpec
if err := json.Unmarshal([]byte(configStr), &oldConfig); err == nil {
@ -470,3 +500,34 @@ func xdsHostIPEnv(xdsHost string) corev1.EnvVar {
}
return v1.EnvVar{Name: "XDS_HOST_IP", Value: xdsHost}
}
//IsContainMount 判断存储路径是否冲突,以及进一步实现创建存储或配置文件
func IsContainMount(volumeMounts *[]v1.VolumeMount, as *typesv1.AppService, plugin api_model.PluginStorage, pluginID string) bool {
for _, mountValue := range *volumeMounts {
if mountValue.MountPath == plugin.VolumePath {
return false
}
}
volumeMount := v1.VolumeMount{Name: plugin.VolumeName, MountPath: plugin.VolumePath}
*volumeMounts = append(*volumeMounts, volumeMount)
var define = &volume.Define{}
v := new(volume.PluginStorageVolume)
v.Plugin = plugin
v.AS = as
v.PluginID = pluginID
if err := v.CreateVolume(define); err != nil {
return false
}
as.GetPodTemplate().Spec.Volumes = append(as.GetPodTemplate().Spec.Volumes, define.GetVolumes()...)
if len(as.GetPodTemplate().Spec.Containers) != 0 {
as.GetPodTemplate().Spec.Containers[0].VolumeMounts = append(as.GetPodTemplate().Spec.Containers[0].VolumeMounts, define.GetVolumeMounts()...)
}
return true
}
func pluginMountVolume(containers []v1.Container, volumeMount []v1.VolumeMount) {
for i := range containers {
containers[i].VolumeMounts = volumeMount
}
}

View File

@ -172,7 +172,6 @@ func getMainContainer(as *v1.AppService, version *dbmodel.VersionInfo, dv *volum
logrus.Infof("service id: %s; enable privileged.", as.ServiceID)
c.SecurityContext = &corev1.SecurityContext{Privileged: util.Bool(true)}
}
return c, nil
}

View File

@ -0,0 +1,65 @@
package volume
import (
"fmt"
api_model "github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/util"
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"path"
)
//PluginStorageVolume 插件新增存储
type PluginStorageVolume struct {
Plugin api_model.PluginStorage
Base
PluginID string
AS *v1.AppService
}
//CreateVolume 创建插件存储或配置文件
func (v *PluginStorageVolume) CreateVolume(define *Define) error {
v.as = v.AS
if v.Plugin.AttrType == "config-file" {
cmap := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: util.NewUUID(),
Namespace: v.as.GetNamespace(),
Labels: v.as.GetCommonLabels(),
},
Data: make(map[string]string),
}
cmap.Data[path.Base(v.Plugin.VolumePath)] = util.ParseVariable(v.Plugin.FileContent, map[string]string{})
v.as.SetConfigMap(cmap)
mode := int32(777)
define.SetVolumeCMap(cmap, path.Base(v.Plugin.VolumePath), v.Plugin.VolumePath, false, &mode)
return nil
} else if v.Plugin.AttrType == "storage" {
volumeMountName := fmt.Sprintf("plugin-%v-%v", v.PluginID, v.Plugin.VolumeName)
volumeMountPath := v.Plugin.VolumePath
volumeReadOnly := false
var vm *corev1.VolumeMount
annotations := map[string]string{"volume_name": v.Plugin.VolumeName}
labels := v.as.GetCommonLabels(map[string]string{"volume_name": volumeMountName, "VolumeName": v.Plugin.VolumeName, "pluginID": v.PluginID})
claim := newVolumeClaim(volumeMountName, volumeMountPath, "RWX", v1.RainbondStatefuleShareStorageClass, 0, labels, annotations)
v.as.SetClaim(claim)
v.as.SetClaimManually(claim)
vo := corev1.Volume{Name: volumeMountName}
vo.PersistentVolumeClaim = &corev1.PersistentVolumeClaimVolumeSource{ClaimName: claim.GetName(), ReadOnly: volumeReadOnly}
define.volumes = append(define.volumes, vo)
vm = &corev1.VolumeMount{
Name: volumeMountName,
MountPath: volumeMountPath,
ReadOnly: volumeReadOnly,
}
define.volumeMounts = append(define.volumeMounts, *vm)
return nil
}
return nil
}
// CreateDependVolume create depend volume
func (v *PluginStorageVolume) CreateDependVolume(define *Define) error {
return nil
}

View File

@ -71,7 +71,6 @@ func (v *ShareFileVolume) CreateVolume(define *Define) error {
claim := newVolumeClaim(volumeMountName, volumeMountPath, v.svm.AccessMode, v1.RainbondStatefuleShareStorageClass, v.svm.VolumeCapacity, labels, annotations)
v.as.SetClaim(claim)
v.as.SetClaimManually(claim)
vo := corev1.Volume{Name: volumeMountName}
vo.PersistentVolumeClaim = &corev1.PersistentVolumeClaimVolumeSource{ClaimName: claim.GetName(), ReadOnly: volumeReadOnly}
define.volumes = append(define.volumes, vo)

View File

@ -72,6 +72,8 @@ func NewVolumeManager(as *v1.AppService,
v = new(MemoryFSVolume)
case dbmodel.LocalVolumeType.String():
v = new(LocalVolume)
case dbmodel.PluginStorageType.String():
v = new(PluginStorageVolume)
default:
logrus.Warnf("other volume type[%s]", volumeType)
v = new(OtherVolume)

View File

@ -19,7 +19,10 @@
package provider
import (
"encoding/json"
"fmt"
api_model "github.com/goodrain/rainbond/api/model"
"github.com/jinzhu/gorm"
"os"
"path"
"strconv"
@ -68,7 +71,7 @@ func (p *rainbondssscProvisioner) Provision(options controller.VolumeOptions) (*
_, stateless := options.PVC.Labels["stateless"]
// v5.0.4 Previous versions
hostpath := path.Join(p.pvDir, "tenant", tenantID, "service", serviceID, options.PVC.Name)
pluginID, ok := options.PVC.Labels["pluginID"]
// after v5.0.4,change host path
// Directory path has nothing to do with volume ID
// Directory path bound to volume mount path
@ -85,6 +88,30 @@ func (p *rainbondssscProvisioner) Provision(options controller.VolumeOptions) (*
if !stateless {
hostpath = path.Join(volume.HostPath, podName)
}
} else if ok {
config, err := db.GetManager().TenantPluginVersionConfigDao().GetPluginConfig(serviceID, pluginID)
if err != nil && err != gorm.ErrRecordNotFound {
logrus.Errorf("get service plugin config from db failure %s", err.Error())
}
if config == nil {
return nil, fmt.Errorf("can not parse volume id")
}
configStr := config.ConfigStr
var oldConfig api_model.ResourceSpec
if err := json.Unmarshal([]byte(configStr), &oldConfig); err == nil {
for _, plugin := range oldConfig.BaseNormal.Options {
var pluginStorage api_model.PluginStorage
jsonValue, ok := plugin.(string)
if ok {
if err := json.Unmarshal([]byte(jsonValue), &pluginStorage); err == nil {
if pluginStorage.VolumeName == options.PVC.Labels["VolumeName"] {
hostpath = path.Join("/grdata/tenant/", tenantID, "service", serviceID, pluginStorage.VolumePath, podName)
}
}
}
}
}
} else {
return nil, fmt.Errorf("can not parse volume id")
}