diff --git a/cmd/worker/worker.go b/cmd/worker/worker.go index 2288de8a3c..0ceb0e0d1e 100644 --- a/cmd/worker/worker.go +++ b/cmd/worker/worker.go @@ -47,6 +47,7 @@ func main() { Registry(component.Event()). Registry(component.K8sClient()). Registry(component.StorageClient()). + Registry(component.FilePersistenceClient()). Registry(component.HubRegistry()). Registry(component.Proxy()). Registry(component.MQ()). diff --git a/config/configs/config.go b/config/configs/config.go index 35bf20002e..cdbe300a51 100644 --- a/config/configs/config.go +++ b/config/configs/config.go @@ -10,45 +10,47 @@ type Env string func init() { defaultConfig = &Config{ - fs: pflag.CommandLine, - APIConfig: &rbdcomponent.APIConfig{}, - EventLogConfig: &rbdcomponent.EventLogConfig{}, - StorageConfig: &StorageConfig{}, - DBConfig: &DBConfig{}, - ESConfig: &ESConfig{}, - LogConfig: &LogConfig{}, - WebSocketConfig: &WebSocketConfig{}, - MQConfig: &rbdcomponent.MQConfig{}, - K8SConfig: &K8SConfig{}, - PrometheusConfig: &PrometheusConfig{}, - ServerConfig: &ServerConfig{}, - WorkerConfig: &rbdcomponent.WorkerConfig{}, - PublicConfig: &PublicConfig{}, - ChaosConfig: &rbdcomponent.ChaosConfig{}, + fs: pflag.CommandLine, + APIConfig: &rbdcomponent.APIConfig{}, + EventLogConfig: &rbdcomponent.EventLogConfig{}, + StorageConfig: &StorageConfig{}, + DBConfig: &DBConfig{}, + ESConfig: &ESConfig{}, + LogConfig: &LogConfig{}, + WebSocketConfig: &WebSocketConfig{}, + MQConfig: &rbdcomponent.MQConfig{}, + K8SConfig: &K8SConfig{}, + PrometheusConfig: &PrometheusConfig{}, + ServerConfig: &ServerConfig{}, + WorkerConfig: &rbdcomponent.WorkerConfig{}, + PublicConfig: &PublicConfig{}, + ChaosConfig: &rbdcomponent.ChaosConfig{}, + FilePersistenceConfig: &FilePersistenceConfig{}, } } // Config - type Config struct { - AppName string - Version string - Env Env - Debug bool - APIConfig *rbdcomponent.APIConfig - EventLogConfig *rbdcomponent.EventLogConfig - StorageConfig *StorageConfig - DBConfig *DBConfig - ESConfig *ESConfig - LogConfig *LogConfig - WebSocketConfig *WebSocketConfig - MQConfig *rbdcomponent.MQConfig - K8SConfig *K8SConfig - PrometheusConfig *PrometheusConfig - ServerConfig *ServerConfig - WorkerConfig *rbdcomponent.WorkerConfig - PublicConfig *PublicConfig - ChaosConfig *rbdcomponent.ChaosConfig - fs *pflag.FlagSet + AppName string + Version string + Env Env + Debug bool + APIConfig *rbdcomponent.APIConfig + EventLogConfig *rbdcomponent.EventLogConfig + StorageConfig *StorageConfig + DBConfig *DBConfig + ESConfig *ESConfig + LogConfig *LogConfig + WebSocketConfig *WebSocketConfig + MQConfig *rbdcomponent.MQConfig + K8SConfig *K8SConfig + PrometheusConfig *PrometheusConfig + ServerConfig *ServerConfig + WorkerConfig *rbdcomponent.WorkerConfig + PublicConfig *PublicConfig + ChaosConfig *rbdcomponent.ChaosConfig + fs *pflag.FlagSet + FilePersistenceConfig *FilePersistenceConfig } var defaultConfig *Config diff --git a/config/configs/filepersistence_config.go b/config/configs/filepersistence_config.go new file mode 100644 index 0000000000..8fb2ee9ff7 --- /dev/null +++ b/config/configs/filepersistence_config.go @@ -0,0 +1,27 @@ +package configs + +import "github.com/spf13/pflag" + +type FilePersistenceConfig struct { + FilePersistenceType string `json:"file_persistence_type"` + FilePersistenceAccessKeyID string `json:"file_persistence_access_key_id"` + FilePersistenceSecretAccessKey string `json:"file_persistence_secret_access_key"` + FilePersistenceRegion string `json:"file_persistence_region"` + FilePersistenceZoneID string `json:"file_persistence_zone_id"` + FilePersistenceVpcID string `json:"file_persistence_vpc_id"` + FilePersistenceSubnetID string `json:"file_persistence_subnet_id"` + FilePersistencePermissionGroupID string `json:"file_persistence_permission_group_id"` + FilePersistenceEnable string `json:"file_persistence_enable"` +} + +func AddFilePersistenceFlags(fs *pflag.FlagSet, fpc *FilePersistenceConfig) { + fs.StringVar(&fpc.FilePersistenceType, "file-persistence-type", "volcengine", "volcengine、aliyun or tencentcloud") + fs.StringVar(&fpc.FilePersistenceAccessKeyID, "file-persistence-access-key-id", "", "access key id") + fs.StringVar(&fpc.FilePersistenceSecretAccessKey, "file-persistence-secret-access-key", "", "secret access key") + fs.StringVar(&fpc.FilePersistenceRegion, "file-persistence-region", "cn-shanghai", "region") + fs.StringVar(&fpc.FilePersistenceZoneID, "file-persistence-zone-id", "cn-shanghai-b", "zone id") + fs.StringVar(&fpc.FilePersistenceVpcID, "file-persistence-vpc-id", "", "file persistence vpc id") + fs.StringVar(&fpc.FilePersistenceSubnetID, "file-persistence-subnet-id", "", "file persistence subnet id") + fs.StringVar(&fpc.FilePersistencePermissionGroupID, "file-persistence-permission-group-id", "", "file persistence permission group id") + fs.StringVar(&fpc.FilePersistenceEnable, "file-persistence-enable", "open", "open or close") +} diff --git a/config/configs/options.go b/config/configs/options.go index fba8f8ad4d..73c4e74692 100644 --- a/config/configs/options.go +++ b/config/configs/options.go @@ -41,6 +41,7 @@ func (c *Config) SetPublicFlags() *Config { AddESFlags(c.fs, c.ESConfig) AddLogFlags(c.fs, c.LogConfig) AddStorageFlags(c.fs, c.StorageConfig) + AddFilePersistenceFlags(c.fs, c.FilePersistenceConfig) AddWebSocketFlags(c.fs, c.WebSocketConfig) AddK8SFlags(c.fs, c.K8SConfig) AddPrometheusFlags(c.fs, c.PrometheusConfig) diff --git a/db/model/tenant.go b/db/model/tenant.go index 899cc6cca5..dea4d9ce87 100644 --- a/db/model/tenant.go +++ b/db/model/tenant.go @@ -496,6 +496,8 @@ var LocalVolumeType VolumeType = "local" // PluginStorageType 插件存储 var PluginStorageType VolumeType = "plugin-storage" +var VolcengineType VolumeType = "volcengine" + // MemoryFSVolumeType 内存文件存储 var MemoryFSVolumeType VolumeType = "memoryfs" diff --git a/go.mod b/go.mod index f07fd58c14..af26e5ff30 100644 --- a/go.mod +++ b/go.mod @@ -100,6 +100,7 @@ require ( ) require ( + github.com/aliyun/alibaba-cloud-sdk-go v1.63.79 github.com/apache/apisix-ingress-controller v1.7.1 github.com/coreos/etcd v3.3.13+incompatible github.com/dustin/go-humanize v1.0.0 @@ -109,6 +110,8 @@ require ( github.com/grafana/pyroscope-go v1.2.0 github.com/helm/helm v2.17.0+incompatible github.com/openkruise/kruise-api v1.4.0-rc.0 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cfs v1.0.1077 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1077 github.com/volcengine/volcengine-go-sdk v1.0.176 golang.org/x/sync v0.3.0 k8s.io/klog/v2 v2.100.1 @@ -227,6 +230,7 @@ require ( github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183 // indirect github.com/openshift/client-go v0.0.0-20210112165513-ebc401615f47 // indirect github.com/openshift/custom-resource-status v1.1.2 // indirect + github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/pelletier/go-toml v1.9.4 // indirect github.com/pelletier/go-toml/v2 v2.0.9 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect @@ -261,6 +265,7 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20230815205213-6bfd019c3878 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878 // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/go.sum b/go.sum index f88e690b1c..953a270490 100644 --- a/go.sum +++ b/go.sum @@ -128,6 +128,7 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GoogleCloudPlatform/k8s-cloud-provider v1.16.1-0.20210702024009-ea6160c1d0e3/go.mod h1:8XasY4ymP2V/tn2OOV9ZadmiTE1FIB/h3W+yNlPttKw= github.com/GoogleCloudPlatform/k8s-cloud-provider v1.18.1-0.20220218231025-f11817397a1b/go.mod h1:FNj4KYEAAHfYu68kRYolGoxkaJn+6mdEsaM12VTwuI0= +github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= @@ -198,6 +199,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alessio/shellescape v1.2.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.79 h1:8o2+c+UR+l+iqml6M7iqq3t42SVzpViZcxNXp3Lrol8= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.79/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/aliyun/aliyun-oss-go-sdk v2.1.5+incompatible h1:v5yDfjkRY/kOxu05gkh0/D/2wYxbTFCoTr3JqFI0FLE= github.com/aliyun/aliyun-oss-go-sdk v2.1.5+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= @@ -831,6 +834,7 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= @@ -1634,6 +1638,8 @@ github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKw github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= +github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= @@ -1894,6 +1900,10 @@ github.com/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cfs v1.0.1077 h1:Do6yeAmLsaE2Wxaaqjoxm4ktL+Kel1wr9lgvKlTCot4= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cfs v1.0.1077/go.mod h1:Kpj6UWtlNi4tF5JDAKufrAbSUKecG/FQur3NYwzslME= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1077 h1:ma62uyPX1M549mfkehpXq/XVNIpuJvFbtZth9/v22/w= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1077/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= @@ -1930,7 +1940,11 @@ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2 github.com/uber/jaeger-client-go v2.20.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= +github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= +github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= @@ -2105,6 +2119,8 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.2.0/go.mod h1:YfO3fm683kQpzETxlTGZhGIVmXAhaw3gxeBADbpZtnU= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= @@ -2683,6 +2699,7 @@ gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJ gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= @@ -2872,6 +2889,8 @@ gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20160818015218-f2b6f6c918c4/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= @@ -2910,6 +2929,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200603094226-e3079894b1e8/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= diff --git a/pkg/component/core.go b/pkg/component/core.go index f794a8cd09..6f61b82203 100644 --- a/pkg/component/core.go +++ b/pkg/component/core.go @@ -37,6 +37,7 @@ import ( "github.com/goodrain/rainbond/mq/mqcomponent/metrics" "github.com/goodrain/rainbond/mq/mqcomponent/mqclient" "github.com/goodrain/rainbond/pkg/component/eventlog" + "github.com/goodrain/rainbond/pkg/component/filepersistence" "github.com/goodrain/rainbond/pkg/component/grpc" "github.com/goodrain/rainbond/pkg/component/hubregistry" "github.com/goodrain/rainbond/pkg/component/k8s" @@ -75,6 +76,11 @@ func StorageClient() rainbond.Component { return storage.New() } +// FilePersistenceClient - +func FilePersistenceClient() rainbond.Component { + return filepersistence.New() +} + // HubRegistry - func HubRegistry() rainbond.Component { return hubregistry.New() diff --git a/pkg/component/filepersistence/filepersistence.go b/pkg/component/filepersistence/filepersistence.go new file mode 100644 index 0000000000..c01e0be995 --- /dev/null +++ b/pkg/component/filepersistence/filepersistence.go @@ -0,0 +1,103 @@ +package filepersistence + +import ( + "context" + "github.com/goodrain/rainbond/config/configs" + storagev1 "k8s.io/api/storage/v1" +) + +// FileSystem represents a file storage system +type FileSystem struct { + ID string + Name string + Status string + ProtocolType string + StorageType string + FileSystemType string + ZoneID string + Region string + Size int64 +} + +// CreateFileSystemOptions contains options for creating a file system +type CreateFileSystemOptions struct { + Name string + ProtocolType string + StorageType string + FileSystemType string + VpcID string + VSwitchID string + SecurityGroup string + Description string + Size int64 +} + +// CreateStorageClassOptions contains options for creating a storage class +type CreateStorageClassOptions struct { + Name string + ReclaimPolicy string + VolumeBindingMode string + Parameters map[string]string +} + +type InterfaceFilePersistence interface { + FindFileSystem(ctx context.Context, name string) (*FileSystem, error) + CreateFileSystem(ctx context.Context, opts *CreateFileSystemOptions) (string, error) + CreateStorageClass(ctx context.Context, fs *FileSystem, opts *CreateStorageClassOptions) (*storagev1.StorageClass, error) +} + +// ComponentFilePersistence - +type ComponentFilePersistence struct { + FilePersistenceCli InterfaceFilePersistence + FilePersistenceConfig *configs.FilePersistenceConfig +} + +var defaultFilePersistenceComponent *ComponentFilePersistence + +// New - +func New() *ComponentFilePersistence { + fpConfig := configs.Default().FilePersistenceConfig + defaultFilePersistenceComponent = &ComponentFilePersistence{ + FilePersistenceConfig: fpConfig, + } + return defaultFilePersistenceComponent +} + +// Start - +func (s *ComponentFilePersistence) Start(ctx context.Context) error { + var fpCli InterfaceFilePersistence + switch s.FilePersistenceConfig.FilePersistenceType { + case "volcengine": + fpCli = &VolcengineProvider{ + config: &VolcengineConfig{ + AccessKey: s.FilePersistenceConfig.FilePersistenceAccessKeyID, + SecretKey: s.FilePersistenceConfig.FilePersistenceSecretAccessKey, + Region: s.FilePersistenceConfig.FilePersistenceRegion, + ZoneID: s.FilePersistenceConfig.FilePersistenceZoneID, + VpcID: s.FilePersistenceConfig.FilePersistenceVpcID, + SubnetID: s.FilePersistenceConfig.FilePersistenceSubnetID, + PermissionGroupID: s.FilePersistenceConfig.FilePersistencePermissionGroupID, + }, + } + } + s.FilePersistenceCli = fpCli + return nil +} + +// CloseHandle - +func (s *ComponentFilePersistence) CloseHandle() { +} + +// Default - +func Default() *ComponentFilePersistence { + return defaultFilePersistenceComponent +} + +type SrcFile interface { + Read([]byte) (int, error) +} + +// DstFile 目标文件接口 +type DstFile interface { + Write([]byte) (int, error) +} diff --git a/pkg/component/filepersistence/volcengine.go b/pkg/component/filepersistence/volcengine.go new file mode 100644 index 0000000000..07bc007a8a --- /dev/null +++ b/pkg/component/filepersistence/volcengine.go @@ -0,0 +1,187 @@ +package filepersistence + +import ( + "context" + "fmt" + "time" + + "github.com/volcengine/volcengine-go-sdk/service/filenas" + "github.com/volcengine/volcengine-go-sdk/volcengine" + "github.com/volcengine/volcengine-go-sdk/volcengine/credentials" + "github.com/volcengine/volcengine-go-sdk/volcengine/session" + v1 "k8s.io/api/core/v1" + storagev1 "k8s.io/api/storage/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// VolcengineProvider implements the Provider interface for Volcengine NAS +type VolcengineProvider struct { + client *filenas.FILENAS + config *VolcengineConfig +} + +// VolcengineConfig contains configuration for Volcengine NAS +type VolcengineConfig struct { + AccessKey string + SecretKey string + Region string + ZoneID string + VpcID string + SubnetID string + PermissionGroupID string +} + +func (p *VolcengineProvider) init() error { + if p.client != nil { + return nil + } + config := volcengine.NewConfig(). + WithCredentials(credentials.NewStaticCredentials(p.config.AccessKey, p.config.SecretKey, "")). + WithRegion(p.config.Region) + + sess, err := session.NewSession(config) + if err != nil { + return fmt.Errorf("failed to create Volcengine session: %v", err) + } + + p.client = filenas.New(sess) + return nil +} + +// FindFileSystem finds a file system by ID +func (p *VolcengineProvider) FindFileSystem(ctx context.Context, name string) (*FileSystem, error) { + if err := p.init(); err != nil { + return nil, err + } + key := "FileSystemName" + input := &filenas.DescribeFileSystemsInput{ + Filters: []*filenas.FilterForDescribeFileSystemsInput{ + { + Key: &key, + Value: &name, + }, + }, + } + + output, err := p.client.DescribeFileSystems(input) + if err != nil { + return nil, fmt.Errorf("failed to describe file system: %v", err) + } + + if len(output.FileSystems) == 0 { + return nil, fmt.Errorf("file system %s not found", name) + } + + fs := output.FileSystems[0] + var size int64 + if fs.Capacity != nil && fs.Capacity.Total != nil { + size = *fs.Capacity.Total + } + + return &FileSystem{ + ID: *fs.FileSystemId, + Name: *fs.FileSystemName, + Status: *fs.Status, + ProtocolType: *fs.ProtocolType, + StorageType: *fs.StorageType, + FileSystemType: *fs.FileSystemType, + ZoneID: *fs.ZoneId, + Region: p.config.Region, + Size: size, + }, nil +} + +// CreateFileSystem creates a new file system +func (p *VolcengineProvider) CreateFileSystem(ctx context.Context, opts *CreateFileSystemOptions) (string, error) { + if err := p.init(); err != nil { + return "", err + } + + capacityGB := int32(opts.Size / (1024 * 1024 * 1024)) // Convert bytes to GB + chargeType := "PayAsYouGo" + input := &filenas.CreateFileSystemInput{ + ZoneId: &p.config.ZoneID, + FileSystemName: &opts.Name, + FileSystemType: &opts.FileSystemType, + ProtocolType: &opts.ProtocolType, + ChargeType: &chargeType, + Description: &opts.Description, + Capacity: &capacityGB, + } + output, err := p.client.CreateFileSystem(input) + if err != nil { + return "", fmt.Errorf("failed to create file system: %v", err) + } + if output.Metadata.Error != nil { + return "", fmt.Errorf("failed to create file system: %v", output.Metadata.Error) + } + for i := 0; i < 60; i++ { + mpInput := &filenas.CreateMountPointInput{ + FileSystemId: output.FileSystemId, + MountPointName: &opts.Name, + PermissionGroupId: &p.config.PermissionGroupID, + SubnetId: &p.config.SubnetID, + VpcId: &p.config.VpcID, + } + mpOutput, _ := p.client.CreateMountPoint(mpInput) + if mpOutput.Metadata.Error != nil { + if mpOutput.Metadata.Error.Message != "The specified FileSystem is unhealthy." { + return "", fmt.Errorf("failed to create mount point: %v", mpOutput.Metadata.Error) + } + } else { + break + } + time.Sleep(time.Second) + } + for t := 0; t < 600; t++ { + mpInput := &filenas.DescribeMountPointsInput{ + FileSystemId: output.FileSystemId, + MountPointName: &opts.Name, + } + mpi, err := p.client.DescribeMountPoints(mpInput) + if err != nil { + return "", err + } + if mpi.MountPoints != nil && len(mpi.MountPoints) > 0 { + if *mpi.MountPoints[0].Domain != "" { + return *mpi.MountPoints[0].Domain, nil + } + } + } + return "", fmt.Errorf("failed to describe mount point: %v", opts.Name) +} + +// CreateStorageClass creates a storage class for the file system +func (p *VolcengineProvider) CreateStorageClass(ctx context.Context, fs *FileSystem, opts *CreateStorageClassOptions) (*storagev1.StorageClass, error) { + if opts.Parameters == nil { + opts.Parameters = make(map[string]string) + } + + // Set required parameters for Volcengine NAS + opts.Parameters["fileSystemId"] = fs.ID + opts.Parameters["server"] = fmt.Sprintf("%s.%s.nas.volces.com", fs.ID, fs.Region) + opts.Parameters["protocolType"] = fs.ProtocolType + opts.Parameters["storageType"] = fs.StorageType + + var reclaimPolicy v1.PersistentVolumeReclaimPolicy + if opts.ReclaimPolicy == "" { + reclaimPolicy = v1.PersistentVolumeReclaimDelete + } else { + reclaimPolicy = v1.PersistentVolumeReclaimPolicy(opts.ReclaimPolicy) + } + + volumeBindingMode := storagev1.VolumeBindingImmediate + if opts.VolumeBindingMode == "WaitForFirstConsumer" { + volumeBindingMode = storagev1.VolumeBindingWaitForFirstConsumer + } + + return &storagev1.StorageClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: opts.Name, + }, + Provisioner: "nas.csi.volcengine.com", + Parameters: opts.Parameters, + ReclaimPolicy: &reclaimPolicy, + VolumeBindingMode: &volumeBindingMode, + }, nil +} diff --git a/worker/appm/volume/volcengine.go b/worker/appm/volume/volcengine.go new file mode 100644 index 0000000000..1f4bdb4c1a --- /dev/null +++ b/worker/appm/volume/volcengine.go @@ -0,0 +1,126 @@ +package volume + +import ( + "context" + "fmt" + "time" + + "github.com/goodrain/rainbond/db" + dbmodel "github.com/goodrain/rainbond/db/model" + "github.com/goodrain/rainbond/pkg/component/filepersistence" + "github.com/goodrain/rainbond/pkg/component/k8s" + workerutil "github.com/goodrain/rainbond/worker/util" + "github.com/sirupsen/logrus" + corev1 "k8s.io/api/core/v1" + storagev1 "k8s.io/api/storage/v1" + k8serror "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// VolcengineVolume VolcengineVolume +type VolcengineVolume struct { + Base +} + +// CreateVolume ceph rbd volume create volume +func (v *VolcengineVolume) CreateVolume(define *Define) error { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + sc, err := k8s.Default().Clientset.StorageV1().StorageClasses().Get(ctx, define.as.K8sComponentName, metav1.GetOptions{}) + if err != nil { + if k8serror.IsNotFound(err) { + fileDomain, err := filepersistence.Default().FilePersistenceCli.CreateFileSystem( + ctx, + &filepersistence.CreateFileSystemOptions{ + Name: define.as.K8sComponentName, + ProtocolType: "NFS", + StorageType: "Standard", + Size: 100 * 1024 * 1024 * 1024, + FileSystemType: "Capacity", + }, + ) + if err != nil { + return fmt.Errorf("create file system failure:%v", err) + } + + reclaimPolicy := corev1.PersistentVolumeReclaimDelete + volumeBindingMode := storagev1.VolumeBindingImmediate + sc = &storagev1.StorageClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: define.as.K8sComponentName, + }, + Provisioner: "nas.csi.volcengine.com", + Parameters: map[string]string{ + "ChargeType": "PostPaid", + "archiveOnDelete": "false", + "fsType": "Capacity", + "server": fileDomain, + "subPath": "/", + "volumeAs": "subpath", + }, + MountOptions: []string{ + "nolock,proto=tcp,noresvport", + "vers=3", + }, + ReclaimPolicy: &reclaimPolicy, + VolumeBindingMode: &volumeBindingMode, + } + + sc, err = k8s.Default().Clientset.StorageV1().StorageClasses().Create(ctx, sc, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("create storage class failure: %v", err) + } + } else { + return fmt.Errorf("get storage class failure: %v", err) + } + } + v.as.SharedStorageClass = sc.Name + + statefulset := v.as.GetStatefulSet() //有状态组件 + if v.svm.VolumeType == dbmodel.ShareFileVolumeType.String() { + v.svm.VolumeType = v.as.SharedStorageClass + } + volumeType, err := db.GetManager().VolumeTypeDao().GetVolumeTypeByType(v.svm.VolumeType) + if err != nil { + logrus.Errorf("get volume type by type error: %s", err.Error()) + return fmt.Errorf("validate volume capacity error") + } + if err := workerutil.ValidateVolumeCapacity(volumeType.CapacityValidation, v.svm.VolumeCapacity); err != nil { + logrus.Errorf("validate volume capacity[%v] error: %s", v.svm.VolumeCapacity, err.Error()) + return err + } + v.svm.VolumeProviderName = volumeType.Provisioner + volumeMountName := fmt.Sprintf("manual%d", v.svm.ID) + volumeMountPath := v.svm.VolumePath + volumeReadOnly := v.svm.IsReadOnly + labels := v.as.GetCommonLabels(map[string]string{"volume_name": v.svm.VolumeName, "version": v.as.DeployVersion, "reclaim_policy": v.svm.ReclaimPolicy}) + annotations := map[string]string{"volume_name": v.svm.VolumeName} + if statefulset == nil { + v.svm.AccessMode = "RWX" + } + claim := newVolumeClaim(volumeMountName, volumeMountPath, v.svm.AccessMode, v.svm.VolumeType, v.svm.VolumeCapacity, labels, annotations) + logrus.Debugf("storage class is : %s, claim value is : %s", v.svm.VolumeType, claim.GetName()) + v.as.SetClaim(claim) // store claim to appService + vo := corev1.Volume{Name: volumeMountName} + vo.PersistentVolumeClaim = &corev1.PersistentVolumeClaimVolumeSource{ClaimName: claim.GetName(), ReadOnly: volumeReadOnly} + if statefulset != nil { + statefulset.Spec.VolumeClaimTemplates = append(statefulset.Spec.VolumeClaimTemplates, *claim) + logrus.Debugf("stateset.Spec.VolumeClaimTemplates: %+v", statefulset.Spec.VolumeClaimTemplates) + } else { + v.as.SetClaimManually(claim) + define.volumes = append(define.volumes, vo) + } + + vm := corev1.VolumeMount{ + Name: volumeMountName, + MountPath: volumeMountPath, + ReadOnly: volumeReadOnly, + } + define.volumeMounts = append(define.volumeMounts, vm) + return nil +} + +// CreateDependVolume create depend volume +func (v *VolcengineVolume) CreateDependVolume(define *Define) error { + return nil +} diff --git a/worker/appm/volume/volume.go b/worker/appm/volume/volume.go index 5aada785ef..0989ed1be9 100644 --- a/worker/appm/volume/volume.go +++ b/worker/appm/volume/volume.go @@ -82,6 +82,8 @@ func NewVolumeManager(as *v1.AppService, v = new(LocalVolume) case dbmodel.PluginStorageType.String(): v = new(PluginStorageVolume) + case dbmodel.VolcengineType.String(): + v = new(VolcengineVolume) default: logrus.Warnf("other volume type[%s]", volumeType) if serviceMountR != nil { diff --git a/worker/master/master.go b/worker/master/master.go index fccef511f5..aadd2054f1 100644 --- a/worker/master/master.go +++ b/worker/master/master.go @@ -92,11 +92,14 @@ func NewMasterController(store store.Storer) (*Controller, error) { rainbondssscProvisioner := provider.NewRainbondssscProvisioner() //statefulset local controller rainbondsslcProvisioner := provider.NewRainbondsslcProvisioner(k8s.Default().Clientset, store) + //volcengine nas controller + //volcengineNasProvisioner := provider.NewVolcengineNasProvisioner() // Start the provision controller which will dynamically provision hostPath // PVs pc := controller.NewProvisionController(map[string]controller.Provisioner{ rainbondssscProvisioner.Name(): rainbondssscProvisioner, rainbondsslcProvisioner.Name(): rainbondsslcProvisioner, + //volcengineNasProvisioner.Name(): volcengineNasProvisioner, }, serverVersion.GitVersion) stopCh := make(chan struct{}) diff --git a/worker/master/volumes/provider/rainbondsssc.go b/worker/master/volumes/provider/rainbondsssc.go index a76088324a..bc01927938 100644 --- a/worker/master/volumes/provider/rainbondsssc.go +++ b/worker/master/volumes/provider/rainbondsssc.go @@ -203,6 +203,14 @@ func updatePathForPersistentVolumeSource(persistentVolumeSource *v1.PersistentVo Path: newPath(persistentVolumeSource.CSI.VolumeAttributes["path"]), } } + case persistentVolumeSource.CSI != nil && persistentVolumeSource.CSI.Driver == "nas.csi.volcengine.com": + // convert volcengine nas to nfs + if persistentVolumeSource.CSI.VolumeAttributes != nil { + source.NFS = &v1.NFSVolumeSource{ + Server: persistentVolumeSource.CSI.VolumeAttributes["server"], + Path: newPath(persistentVolumeSource.CSI.VolumeAttributes["path"]), + } + } case persistentVolumeSource.Glusterfs != nil: //glusterfs: // endpoints: glusterfs-cluster diff --git a/worker/master/volumes/provider/volcenginenas.go b/worker/master/volumes/provider/volcenginenas.go new file mode 100644 index 0000000000..28f54865fe --- /dev/null +++ b/worker/master/volumes/provider/volcenginenas.go @@ -0,0 +1,193 @@ +package provider + +// +//import ( +// "fmt" +// "os" +// "path" +// "strconv" +// +// "github.com/goodrain/rainbond/util" +// "github.com/goodrain/rainbond/worker/master/volumes/provider/lib/controller" +// "github.com/sirupsen/logrus" +// "github.com/volcengine/volcengine-go-sdk/service/filenas" +// "github.com/volcengine/volcengine-go-sdk/volcengine" +// "github.com/volcengine/volcengine-go-sdk/volcengine/credentials" +// v1 "k8s.io/api/core/v1" +// "k8s.io/apimachinery/pkg/api/resource" +// metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +//) +// +//type volcengineNasProvisioner struct { +// client *filenas.FILENAS +// region string +// zoneID string +// pvDir string +// name string +//} +// +//// NewVolcengineNasProvisioner creates a new volcengine nas provisioner +//func NewVolcengineNasProvisioner() controller.Provisioner { +// accessKey := os.Getenv("VOLCENGINE_ACCESS_KEY") +// secretKey := os.Getenv("VOLCENGINE_SECRET_KEY") +// region := os.Getenv("VOLCENGINE_REGION") +// zoneID := os.Getenv("VOLCENGINE_ZONE_ID") +// if accessKey == "" || secretKey == "" || region == "" || zoneID == "" { +// logrus.Error("volcengine credentials not found") +// return nil +// } +// +// creds := credentials.NewStaticCredentials(accessKey, secretKey, "") +// config := volcengine.NewConfig(). +// WithCredentials(creds). +// WithRegion(region) +// +// client := filenas.New(config) +// +// sharePath := os.Getenv("SHARE_DATA_PATH") +// if sharePath == "" { +// sharePath = "/grdata" +// } +// +// return &volcengineNasProvisioner{ +// client: client, +// region: region, +// zoneID: zoneID, +// pvDir: sharePath, +// name: "nas.csi.volcengine.com", +// } +//} +// +//func (p *volcengineNasProvisioner) Provision(options controller.VolumeOptions) (*v1.PersistentVolume, error) { +// logrus.Debugf("[volcengineNasProvisioner] start creating PV object. parameters: %+v", options.Parameters) +// +// capacity := options.PVC.Spec.Resources.Requests[v1.ResourceStorage] +// capacityGB := int32(capacity.Value() / (1024 * 1024 * 1024)) // convert to GB +// if capacityGB < 100 { +// capacityGB = 100 // minimum size is 100GB for Volcengine NAS +// } +// +// fileSystemName := fmt.Sprintf("rainbond-%s", options.PVName) +// fileSystemType := "Extreme" // 可以从 options.Parameters 中获取,这里使用默认值 +// protocolType := "NFS" +// chargeType := "PayAsYouGo" +// +// // 创建文件系统 +// createResp, err := p.client.CreateFileSystem(&filenas.CreateFileSystemInput{ +// ZoneId: &p.zoneID, +// FileSystemName: &fileSystemName, +// FileSystemType: &fileSystemType, +// ProtocolType: &protocolType, +// ChargeType: &chargeType, +// Capacity: &capacityGB, +// }) +// if err != nil { +// logrus.Errorf("create volcengine nas filesystem error: %v", err) +// return nil, err +// } +// +// // 等待文件系统创建完成 +// fileSystemID := createResp.FileSystem.FileSystemId +// err = p.waitForFileSystemReady(fileSystemID) +// if err != nil { +// return nil, err +// } +// +// // 获取挂载点 +// descResp, err := p.client.DescribeFileSystems(&filenas.DescribeFileSystemsInput{ +// FileSystemIds: []string{fileSystemID}, +// }) +// if err != nil { +// return nil, err +// } +// if len(descResp.FileSystems) == 0 { +// return nil, fmt.Errorf("file system %s not found", fileSystemID) +// } +// +// mountPoint := descResp.FileSystems[0].MountPoint +// if mountPoint == "" { +// return nil, fmt.Errorf("mount point is empty for file system %s", fileSystemID) +// } +// +// // 创建 PV +// pv := &v1.PersistentVolume{ +// ObjectMeta: metav1.ObjectMeta{ +// Name: options.PVName, +// Labels: options.PVC.Labels, +// }, +// Spec: v1.PersistentVolumeSpec{ +// PersistentVolumeReclaimPolicy: options.PersistentVolumeReclaimPolicy, +// AccessModes: options.PVC.Spec.AccessModes, +// Capacity: v1.ResourceList{ +// v1.ResourceStorage: options.PVC.Spec.Resources.Requests[v1.ResourceStorage], +// }, +// PersistentVolumeSource: v1.PersistentVolumeSource{ +// CSI: &v1.CSIPersistentVolumeSource{ +// Driver: p.name, +// VolumeAttributes: map[string]string{ +// "server": mountPoint, +// "fileSystemId": fileSystemID, +// "path": "/", +// }, +// }, +// }, +// }, +// } +// +// logrus.Infof("created volcengine nas pv %s for pvc %s", pv.Name, options.PVC.Name) +// return pv, nil +//} +// +//func (p *volcengineNasProvisioner) Delete(volume *v1.PersistentVolume) error { +// if volume.Spec.CSI == nil { +// return fmt.Errorf("volume %s is not a CSI volume", volume.Name) +// } +// +// fileSystemID := volume.Spec.CSI.VolumeAttributes["fileSystemId"] +// if fileSystemID == "" { +// return fmt.Errorf("fileSystemId not found in volume %s", volume.Name) +// } +// +// // 删除文件系统 +// _, err := p.client.DeleteFileSystem(&filenas.DeleteFileSystemInput{ +// FileSystemId: &fileSystemID, +// }) +// if err != nil { +// return fmt.Errorf("delete file system %s error: %v", fileSystemID, err) +// } +// +// logrus.Infof("deleted volcengine nas filesystem %s for volume %s", fileSystemID, volume.Name) +// return nil +//} +// +//func (p *volcengineNasProvisioner) waitForFileSystemReady(fileSystemID string) error { +// for i := 0; i < 60; i++ { // 最多等待 5 分钟 +// resp, err := p.client.DescribeFileSystems(&filenas.DescribeFileSystemsInput{ +// FileSystemIds: []string{fileSystemID}, +// }) +// if err != nil { +// return err +// } +// if len(resp.FileSystems) == 0 { +// return fmt.Errorf("file system %s not found", fileSystemID) +// } +// +// status := resp.FileSystems[0].Status +// if status == "Running" { +// return nil +// } +// +// if status == "Error" { +// return fmt.Errorf("file system %s creation failed", fileSystemID) +// } +// +// // 等待 5 秒后重试 +// time.Sleep(5 * time.Second) +// } +// +// return fmt.Errorf("timeout waiting for file system %s to be ready", fileSystemID) +//} +// +//func (p *volcengineNasProvisioner) Name() string { +// return p.name +//}