fix(region): esxi vm folder (#23751)

This commit is contained in:
屈轩
2025-11-17 18:10:02 +08:00
committed by GitHub
parent 1875cf7bd6
commit 9e72da7b1e
11 changed files with 195 additions and 60 deletions
+3 -3
View File
@@ -88,14 +88,14 @@ require (
k8s.io/client-go v0.19.3
k8s.io/cluster-bootstrap v0.19.3
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251105060653-4f6e3fb8ad84
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251117093447-50d652c04675
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900
yunion.io/x/pkg v1.10.4-0.20251029085629-5e6cd5e0d3ad
yunion.io/x/pkg v1.10.4-0.20251114095758-2a2f105d9712
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
yunion.io/x/sqlchemy v1.1.3-0.20250925091009-4ca0766fc8f0
yunion.io/x/sqlchemy v1.1.3-0.20251114094729-b018084e8ec7
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c
)
+6 -6
View File
@@ -1279,8 +1279,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251105060653-4f6e3fb8ad84 h1:PDR7KimPiyiIrtC6K1glMgyi80/OHx6l8nB0LCyWFqI=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251105060653-4f6e3fb8ad84/go.mod h1:S9o/TRZsnYWGaGe7o3PpeOv6CgMY8ZJwITYsEnGfOgQ=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251117093447-50d652c04675 h1:d5Lc5K/Zp91IXXMY6Xoplx85dZhCCwRbTyGngwsoXN0=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251117093447-50d652c04675/go.mod h1:S9o/TRZsnYWGaGe7o3PpeOv6CgMY8ZJwITYsEnGfOgQ=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
@@ -1294,11 +1294,11 @@ yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 h1:Hu/4ERvoWaN6aiFs4h4/yvVB
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v1.10.4-0.20251029085629-5e6cd5e0d3ad h1:rvh05lRDppYWzVyIjU/y/vzXUvfQ8Oi47vioL+zGayA=
yunion.io/x/pkg v1.10.4-0.20251029085629-5e6cd5e0d3ad/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
yunion.io/x/pkg v1.10.4-0.20251114095758-2a2f105d9712 h1:LUYhaE2PbRrlO2dJTII3K5L62wYlwDet2drziGv6yLY=
yunion.io/x/pkg v1.10.4-0.20251114095758-2a2f105d9712/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 h1:1KJ3YYinydPHpDEQRXdr/T8SYcKZ5Er+m489H+PnaQ4=
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
yunion.io/x/sqlchemy v1.1.3-0.20250925091009-4ca0766fc8f0 h1:L4zE6kTD1PEki1jQnLLBiYnEYFKWa/weoful0Sl4tKw=
yunion.io/x/sqlchemy v1.1.3-0.20250925091009-4ca0766fc8f0/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
yunion.io/x/sqlchemy v1.1.3-0.20251114094729-b018084e8ec7 h1:C26+f+xEzgxnfp4N1+M6hRc1hIvV4cFCzZxJH7o06xM=
yunion.io/x/sqlchemy v1.1.3-0.20251114094729-b018084e8ec7/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c h1:QuLab2kSRECZRxo4Lo2KcYn6XjQFDGaZ1+x0pYDVVwQ=
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
+3 -15
View File
@@ -447,21 +447,9 @@ func (self *SESXiGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gues
action, _ := config.GetString("action")
if action == "create" {
project, err := db.TenantCacheManager.FetchTenantById(ctx, guest.ProjectId)
if err != nil {
return errors.Wrapf(err, "FetchTenantById(%s)", guest.ProjectId)
}
projects, err := account.GetExternalProjectsByProjectIdOrName(project.Id, project.Name)
if err != nil {
return errors.Wrapf(err, "GetExternalProjectsByProjectIdOrName(%s,%s)", project.Id, project.Name)
}
extProj := models.GetAvailableExternalProject(project, projects)
if extProj != nil {
config.Add(jsonutils.NewString(extProj.Name), "desc", "resource_pool")
} else {
config.Add(jsonutils.NewString(project.Name), "desc", "resource_pool")
projectId, _ := account.SyncProject(ctx, task.GetUserCred(), guest.ProjectId)
if len(projectId) > 0 {
config.Add(jsonutils.NewString(projectId), "desc", "project_id")
}
}
+3 -3
View File
@@ -1605,7 +1605,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
# sigs.k8s.io/yaml v1.2.0
## explicit; go 1.12
sigs.k8s.io/yaml
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251105060653-4f6e3fb8ad84
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251117093447-50d652c04675
## explicit; go 1.21
yunion.io/x/cloudmux/pkg/apis
yunion.io/x/cloudmux/pkg/apis/billing
@@ -1700,7 +1700,7 @@ yunion.io/x/log/hooks
yunion.io/x/ovsdb/cli_util
yunion.io/x/ovsdb/schema/ovn_nb
yunion.io/x/ovsdb/types
# yunion.io/x/pkg v1.10.4-0.20251029085629-5e6cd5e0d3ad
# yunion.io/x/pkg v1.10.4-0.20251114095758-2a2f105d9712
## explicit; go 1.18
yunion.io/x/pkg/appctx
yunion.io/x/pkg/errors
@@ -1754,7 +1754,7 @@ yunion.io/x/pkg/utils
# yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
## explicit; go 1.12
yunion.io/x/s3cli
# yunion.io/x/sqlchemy v1.1.3-0.20250925091009-4ca0766fc8f0
# yunion.io/x/sqlchemy v1.1.3-0.20251114094729-b018084e8ec7
## explicit; go 1.17
yunion.io/x/sqlchemy
yunion.io/x/sqlchemy/backends
+16 -16
View File
@@ -786,7 +786,7 @@ type SCreateVMParam struct {
Cdrom SCdromInfo
Disks []SDiskInfo
Nics []jsonutils.JSONObject
ResourcePool string
ProjectId string
InstanceSnapshotInfo SEsxiInstanceSnapshotInfo
EnableEsxiSwap bool
}
@@ -1161,19 +1161,19 @@ func (host *SHost) DoCreateVM(ctx context.Context, ds *SDatastore, params SCreat
err = errors.Wrapf(err, "SHost.GetDatacenter for host '%s'", host.GetId())
return
}
// get vmFloder
folders, err := dc.getObjectDatacenter().Folders(ctx)
vmFolder, err := dc.GetFolder(params.ProjectId)
if err != nil {
err = errors.Wrap(err, "object.DataCenter.Folders")
err = errors.Wrap(err, "GetFolder")
return
}
vmFolder := folders.VmFolder
resourcePool, err := host.SyncResourcePool(params.ResourcePool)
pool, err := host.GetResourcePool()
if err != nil {
err = errors.Wrap(err, "SyncResourcePool")
err = errors.Wrap(err, "GetResourcePool")
return
}
task, err := vmFolder.CreateVM(ctx, spec, resourcePool, host.GetHostSystem())
task, err := vmFolder.CreateVM(ctx, spec, pool, host.GetHostSystem())
if err != nil {
err = errors.Wrap(err, "VmFolder.Create")
return
@@ -1286,17 +1286,16 @@ func (host *SHost) CloneVM(ctx context.Context, from *SVirtualMachine, snapshot
if err != nil {
return nil, errors.Wrapf(err, "SHost.GetDatacenter for host '%s'", host.GetId())
}
// get vmFloder
folders, err := dc.getObjectDatacenter().Folders(ctx)
vmFolder, err := dc.GetFolder(params.ProjectId)
if err != nil {
return nil, errors.Wrap(err, "object.DataCenter.Folders")
return nil, errors.Wrap(err, "GetFolder")
}
resourcePool, err := host.SyncResourcePool(params.ResourcePool)
resourcePool, err := host.GetResourcePool()
if err != nil {
return nil, errors.Wrap(err, "SyncResourcePool")
return nil, errors.Wrap(err, "GetResourcePool")
}
folderref := folders.VmFolder.Reference()
poolref := resourcePool.Reference()
hostref := host.GetHostSystem().Reference()
tds, err := ds.getDatastoreObj(ctx)
@@ -1304,8 +1303,9 @@ func (host *SHost) CloneVM(ctx context.Context, from *SVirtualMachine, snapshot
return nil, errors.Wrapf(err, "getDatastoreObj")
}
dsref := tds.Reference()
vmFolderRef := vmFolder.Reference()
relocateSpec := types.VirtualMachineRelocateSpec{
Folder: &folderref,
Folder: &vmFolderRef,
Pool: &poolref,
Host: &hostref,
Datastore: &dsref,
@@ -1355,7 +1355,7 @@ func (host *SHost) CloneVM(ctx context.Context, from *SVirtualMachine, snapshot
})
}
cloneSpec.Config = &spec
task, err := ovm.Clone(ctx, folders.VmFolder, name, *cloneSpec)
task, err := ovm.Clone(ctx, vmFolder, name, *cloneSpec)
if err != nil {
return nil, errors.Wrap(err, "object.VirtualMachine.Clone")
}
-16
View File
@@ -586,22 +586,6 @@ func findDatacenterByMoId(dcs []*SDatacenter, dcId string) (*SDatacenter, error)
return nil, cloudprovider.ErrNotFound
}
func (cli *SESXiClient) GetIProjects() ([]cloudprovider.ICloudProject, error) {
dcs, err := cli.GetDatacenters()
if err != nil {
return nil, errors.Wrap(err, "GetDatacenters")
}
ret := []cloudprovider.ICloudProject{}
for i := 0; i < len(dcs); i++ {
iprojects, err := dcs[i].GetResourcePools()
if err != nil {
return nil, errors.Wrap(err, "GetResourcePools")
}
ret = append(ret, iprojects...)
}
return ret, nil
}
func (cli *SESXiClient) FindHostByMoId(moId string) (cloudprovider.ICloudHost, error) {
dcs, err := cli.GetDatacenters()
if err != nil {
+142
View File
@@ -0,0 +1,142 @@
// Copyright 2019 Yunion
//
// 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 esxi
import (
"context"
"github.com/vmware/govmomi/object"
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud"
"yunion.io/x/pkg/errors"
)
type SProject struct {
multicloud.SProjectBase
multicloud.STagBase
client *SESXiClient
folder *object.Folder
Name string
Id string
}
func (project *SProject) GetId() string {
return project.Id
}
func (project *SProject) GetGlobalId() string {
return project.Id
}
func (project *SProject) GetName() string {
return project.Name
}
func (project *SProject) GetStatus() string {
return api.EXTERNAL_PROJECT_STATUS_AVAILABLE
}
func (cli *SESXiClient) listAllFolders(ctx context.Context, folder *object.Folder, prefix string) ([]SProject, error) {
ret := []SProject{}
name, err := folder.ObjectName(ctx)
if err != nil {
return nil, errors.Wrap(err, "ObjectName")
}
if len(prefix) > 0 {
name = prefix + name
}
ret = append(ret, SProject{
folder: folder,
Id: folder.Reference().Value,
Name: name,
})
children, err := folder.Children(ctx)
if err != nil {
return nil, errors.Wrap(err, "Children")
}
for _, child := range children {
if subFolder, ok := child.(*object.Folder); ok {
folders, err := cli.listAllFolders(ctx, subFolder, name+"|")
if err != nil {
return nil, errors.Wrap(err, "listAllFolders")
}
ret = append(ret, folders...)
}
}
return ret, nil
}
func (dc *SDatacenter) GetVMFolders() ([]SProject, error) {
vmFolders, err := dc.getObjectDatacenter().Folders(dc.manager.context)
if err != nil {
return nil, errors.Wrap(err, "Folders")
}
ret, err := dc.manager.listAllFolders(dc.manager.context, vmFolders.VmFolder, "")
if err != nil {
return nil, errors.Wrap(err, "listAllFolders")
}
return ret, nil
}
func (dc *SDatacenter) GetFolder(folderId string) (*object.Folder, error) {
vmFolders, err := dc.getObjectDatacenter().Folders(dc.manager.context)
if err != nil {
return nil, errors.Wrap(err, "Folders")
}
ret, err := dc.manager.listAllFolders(dc.manager.context, vmFolders.VmFolder, "")
if err != nil {
return nil, errors.Wrap(err, "listAllFolders")
}
for i := range ret {
if ret[i].Id == folderId {
return ret[i].folder, nil
}
}
return vmFolders.VmFolder, nil
}
func (cli *SESXiClient) GetVMFolders() ([]SProject, error) {
dcs, err := cli.GetDatacenters()
if err != nil {
return nil, errors.Wrap(err, "GetDatacenters")
}
ret := make([]SProject, 0)
for i := range dcs {
folders, err := dcs[i].GetVMFolders()
if err != nil {
return nil, errors.Wrap(err, "GetVMFolders")
}
ret = append(ret, folders...)
}
return ret, nil
}
func (cli *SESXiClient) GetIProjects() ([]cloudprovider.ICloudProject, error) {
projects, err := cli.GetVMFolders()
if err != nil {
return nil, errors.Wrap(err, "GetVMFolders")
}
ret := make([]cloudprovider.ICloudProject, 0)
for i := range projects {
projects[i].client = cli
ret = append(ret, &projects[i])
}
return ret, nil
}
+10
View File
@@ -47,6 +47,8 @@ type SStructFieldInfo struct {
kebabFieldName string
ForceString bool
Tags map[string]string
Aliases []string
}
func (s *SStructFieldInfo) updateTags(k, v string) {
@@ -69,6 +71,9 @@ func (s SStructFieldInfo) deepCopy() *SStructFieldInfo {
tags[k] = v
}
scopy.Tags = tags
aliases := make([]string, len(s.Aliases))
copy(aliases, s.Aliases)
scopy.Aliases = aliases
return &scopy
}
@@ -125,6 +130,9 @@ func ParseFieldJsonInfo(name string, tag reflect.StructTag) SStructFieldInfo {
if !info.Ignore && len(info.Name) == 0 {
info.Name = info.kebabFieldName
}
if val, ok := info.Tags["alias"]; !info.Ignore && ok {
info.Aliases = strings.Split(val, ",")
}
return info
}
@@ -336,6 +344,8 @@ func (fields SStructFieldValueSet) GetStructFieldIndexes2(name string, strictMod
ret = append(ret, i)
} else if info.FieldName == capName {
ret = append(ret, i)
} else if len(info.Aliases) > 0 && utils.IsInArray(name, info.Aliases) {
ret = append(ret, i)
}
}
}
+5
View File
@@ -61,6 +61,11 @@ func CamelSplitTokens(str string) []string {
} else {
upperCount = 0
split = true
// For non-alphanumeric characters at the end of the string,
// include them in the current buffer before splitting to preserve them
if i == len(str)-1 && len(buf) > 0 {
buf = append(buf, c)
}
inc = false
}
if split && len(buf) > 0 {
+4
View File
@@ -319,6 +319,10 @@ func NewBaseColumn(name string, sqltype string, tagmap map[string]string, isPoin
if ok {
dbName = val
}
tagmap, val, ok = utils.TagPop(tagmap, TAG_SQL_NAME)
if ok {
dbName = val
}
oldName := ""
tagmap, val, ok = utils.TagPop(tagmap, TAG_OLD_NAME)
if ok {
+3 -1
View File
@@ -48,8 +48,10 @@ const (
const (
// TAG_IGNORE is a field tag that indicates the field is ignored, not represents a table column
TAG_IGNORE = "ignore"
// TAG_NAME is a field tag that indicates the column name of this field
// TAG_NAME is a field tag that indicates the column name of this field, obsolete, use TAG_SQL_NAME instead!
TAG_NAME = "name"
// TAG_SQL_NAME is a field tag that indicates the column name of this field, superceeds TAG_NAME!
TAG_SQL_NAME = "sql_name"
// TAG_WIDTH is a field tag that indicates the width of the column, like VARCHAR(15)
// Supported by: mysql
TAG_WIDTH = "width"