fix(esxi-agent): support esxi vm forder name same with vm name (#24663)

This commit is contained in:
屈轩
2026-04-13 09:50:44 +08:00
committed by GitHub
parent 448bae5037
commit af2d09a0d7
7 changed files with 106 additions and 63 deletions

2
go.mod
View File

@@ -108,7 +108,7 @@ require (
k8s.io/cri-api v0.28.15
k8s.io/klog/v2 v2.90.1
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260409123844-2f5e06efeade
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260411042903-0d42d35416dc
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91

4
go.sum
View File

@@ -1785,8 +1785,8 @@ sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260409123844-2f5e06efeade h1:8DBeLhYpDrOW7oP5s/mGlc458zAN0mZq8ZMbH5b+JTA=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260409123844-2f5e06efeade/go.mod h1:TbMuTWxcTdyL2Usn+WQdIw0jdlBYO66SzPRY8LZ3Wj0=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260411042903-0d42d35416dc h1:r5S/o/GA4FczSmHM/DqKi3IzN+Mxl6C34vFFsMUFRcc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260411042903-0d42d35416dc/go.mod h1:TbMuTWxcTdyL2Usn+WQdIw0jdlBYO66SzPRY8LZ3Wj0=
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005 h1:3sWwcjGXGjG9mLBWa7AyLq+QSi0udTAx21pfVQRFMBE=
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=

View File

@@ -36,6 +36,7 @@ type EsxiOptions struct {
Zone string `help:"Zone where the agent locates"`
DeployServerSocketPath string `help:"Deploy server listen socket path" default:"/var/run/onecloud/deploy.sock"`
HostDelayTaskWorkerCount int `default:"8" help:"Host delay worker thread count, default is 8"`
EnableFolderNameUUID bool `default:"false" help:"Enable folder name uuid"`
esxi.EsxiOptions
}

View File

@@ -34,6 +34,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/agent/iagent"
esxi_options "yunion.io/x/onecloud/pkg/esxi/options"
"yunion.io/x/onecloud/pkg/hostman/guestman/desc"
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
"yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
@@ -148,7 +149,7 @@ func (as *SAgentStorage) agentRebuildRoot(ctx context.Context, data jsonutils.JS
return vm.DoRebuildRoot(ctx, newPath, diskId, uefi)
}
func (as *SAgentStorage) agentCreateGuest(ctx context.Context, data *jsonutils.JSONDict) (bool, error) {
func (as *SAgentStorage) agentCreateGuest(ctx context.Context, data jsonutils.JSONObject) (bool, error) {
hd := SHostDatastore{}
err := data.Unmarshal(&hd)
if err != nil {
@@ -168,6 +169,9 @@ func (as *SAgentStorage) agentCreateGuest(ctx context.Context, data *jsonutils.J
if err != nil {
return false, errors.Wrapf(err, "%s: fail to unmarshal to esxi.SCreateVMParam", hostutils.ParamsError)
}
if !esxi_options.Options.EnableFolderNameUUID {
createParam.Uuid = ""
}
needDeploy, vm, err := host.CreateVM2(ctx, ds, createParam)
if err != nil {
return false, errors.Wrap(err, "SHost.CreateVM2")
@@ -180,10 +184,11 @@ func (as *SAgentStorage) agentCreateGuest(ctx context.Context, data *jsonutils.J
log.Warningf("set tags for vm %s error: %v", createParam.Name, err)
}
}
name, _ := descDict.GetString("name")
err = as.tryRenameVm(ctx, vm, name)
if err != nil {
return false, errors.Wrapf(err, "RenameVm name '%s'", name)
if esxi_options.Options.EnableFolderNameUUID && len(createParam.Uuid) > 0 {
err = as.tryRenameVm(ctx, vm, createParam.Name)
if err != nil {
return false, errors.Wrapf(err, "RenameVm name '%s'", createParam.Name)
}
}
return needDeploy, nil
}
@@ -229,22 +234,55 @@ func (self esxiVm) GetName() string {
return self.Name
}
type SHostDatastore struct {
HostIp string
Datastore vcenter.SVCenterAccessInfo
}
type SDeployInfo struct {
Action string
SHostDatastore
Desc desc.SGuestDesc
PublicKey string
DeletePublicKey string
AdminPublicKey string
ProjectPublicKey string
GuestExtId string
GuestId string
ResetPassword bool
Password string
EnableCloudInit bool
LoginAccount string
DeployTelegraf bool
TelegrafConf string
Deploys []struct {
Path string
Content string
Action string
}
}
func (as *SAgentStorage) AgentDeployGuest(ctx context.Context, data interface{}) (jsonutils.JSONObject, error) {
init := false
dataDict := data.(*jsonutils.JSONDict)
log.Debugf("dataDict: %s", dataDict)
action, _ := dataDict.GetString("action")
var (
needDeploy = true
err error
)
if action == "create" {
deployInfo := SDeployInfo{}
err := dataDict.Unmarshal(&deployInfo)
if err != nil {
return nil, errors.Wrap(err, "Unmarshal DeployInfo")
}
var needDeploy = true
switch deployInfo.Action {
case "create":
needDeploy, err = as.agentCreateGuest(ctx, dataDict)
if err != nil {
return nil, errors.Wrap(err, "agentCreateGuest")
}
init = true
} else if action == "rebuild" {
case "rebuild":
err := as.agentRebuildRoot(ctx, dataDict)
if err != nil {
return nil, errors.Wrap(err, "agentRebuildRoot")
@@ -252,26 +290,25 @@ func (as *SAgentStorage) AgentDeployGuest(ctx context.Context, data interface{})
init = true
}
var (
hostIp, _ = dataDict.GetString("host_ip")
dsInfo, _ = dataDict.Get("datastore")
)
dc, info, err := esxi.NewESXiClientFromJson(ctx, dsInfo)
dc, info, err := esxi.NewESXiClientFromJson(ctx, jsonutils.Marshal(deployInfo.Datastore))
if err != nil {
return nil, errors.Wrap(err, "esxi.NewESXiClientFromJson")
}
host, err := dc.FindHostByIp(hostIp)
host, err := dc.FindHostByIp(deployInfo.HostIp)
if err != nil {
return nil, errors.Wrap(err, "SDatacenter.FindHostByIp")
}
vmId, _ := dataDict.GetString("guest_ext_id")
vmId := deployInfo.GuestExtId
if !esxi_options.Options.EnableFolderNameUUID && deployInfo.Action == "create" {
vmId = deployInfo.Desc.Name
}
realHost := host
ivm, err := host.GetIVMById(vmId)
if err == cloudprovider.ErrNotFound {
// reschedule by DRS, migrate to other host
siblingHosts, err := host.GetSiblingHosts()
if err != nil {
return nil, errors.Wrap(err, "SHost.GetSiblingHosts")
return nil, errors.Wrap(err, "GetSiblingHosts")
}
for _, sh := range siblingHosts {
ivm, err = host.GetIVMById(vmId)
@@ -314,48 +351,40 @@ func (as *SAgentStorage) AgentDeployGuest(ctx context.Context, data interface{})
return nil, errors.Wrapf(err, "%s: unmarshal to guestDesc", hostutils.ParamsError.Error())
}
var desc = new(desc.SGuestDesc)
err := dataDict.Unmarshal(desc, "desc")
if err != nil {
return nil, errors.Wrap(err, "Unmarshal Guest Desc")
}
// desc, _ := dataDict.Get("desc")
guestDesc.Hypervisor = api.HYPERVISOR_ESXI
key := deployapi.SSHKeys{}
err = dataDict.Unmarshal(&key)
if err != nil {
return nil, errors.Wrapf(err, "%s: unmarshal to deployapi.SSHKeys", hostutils.ParamsError.Error())
key := deployapi.SSHKeys{
PublicKey: deployInfo.PublicKey,
DeletePublicKey: deployInfo.DeletePublicKey,
AdminPublicKey: deployInfo.AdminPublicKey,
ProjectPublicKey: deployInfo.ProjectPublicKey,
}
deployArray := make([]*deployapi.DeployContent, 0)
if dataDict.Contains("deploys") {
err = dataDict.Unmarshal(&deployArray, "deploys")
if err != nil {
return nil, errors.Wrapf(err, "%s: unmarshal to array of deployapi.DeployContent", hostutils.ParamsError.Error())
}
for _, deploy := range deployInfo.Deploys {
deployArray = append(deployArray, &deployapi.DeployContent{
Path: deploy.Path,
Content: deploy.Content,
Action: deploy.Action,
})
}
isRandomPassword := false
passwd, _ := dataDict.GetString("password")
resetPassword := jsonutils.QueryBoolean(dataDict, "reset_password", false)
passwd := deployInfo.Password
resetPassword := deployInfo.ResetPassword
if resetPassword && len(passwd) == 0 {
passwd = seclib.RandomPassword(12)
isRandomPassword = true
}
enableCloudInit := jsonutils.QueryBoolean(dataDict, "enable_cloud_init", false)
loginAccount, _ := dataDict.GetString("login_account")
deployTelegraf := jsonutils.QueryBoolean(dataDict, "deploy_telegraf", false)
telegrafConfig, _ := dataDict.GetString("telegraf_conf")
if deployTelegraf && telegrafConfig == "" {
if deployInfo.DeployTelegraf && deployInfo.TelegrafConf == "" {
return nil, errors.Errorf("missing telegraf_conf")
}
deployInfo := deployapi.NewDeployInfo(&key, deployArray, passwd, isRandomPassword, init, false,
deployInformation := deployapi.NewDeployInfo(&key, deployArray, passwd, isRandomPassword, init, false,
options.HostOptions.LinuxDefaultRootUser, options.HostOptions.WindowsDefaultAdminUser,
enableCloudInit, loginAccount, deployTelegraf, telegrafConfig,
desc.UserData,
deployInfo.EnableCloudInit, deployInfo.LoginAccount, deployInfo.DeployTelegraf, deployInfo.TelegrafConf,
deployInfo.Desc.UserData,
)
log.Debugf("deployInfo: %s", jsonutils.Marshal(deployInfo))
deploy, err = deployclient.GetDeployClient().DeployGuestFs(ctx, &deployapi.DeployParams{
@@ -363,7 +392,7 @@ func (as *SAgentStorage) AgentDeployGuest(ctx context.Context, data interface{})
Path: rootPath,
},
GuestDesc: &guestDesc,
DeployInfo: deployInfo,
DeployInfo: deployInformation,
VddkInfo: &vddkInfo,
})
customize := false
@@ -382,7 +411,7 @@ func (as *SAgentStorage) AgentDeployGuest(ctx context.Context, data interface{})
}
if customize {
as.waitVmToolsVersion(ctx, vm)
err = vm.DoCustomize(ctx, jsonutils.Marshal(desc))
err = vm.DoCustomize(ctx, jsonutils.Marshal(deployInfo.Desc))
if err != nil {
log.Errorf("unable to DoCustomize for vm %s: %v", vm.GetId(), err)
}
@@ -438,11 +467,6 @@ func (as *SAgentStorage) waitVmToolsVersion(ctx context.Context, vm *esxi.SVirtu
return
}
type SHostDatastore struct {
HostIp string
Datastore vcenter.SVCenterAccessInfo
}
func (as *SAgentStorage) getHostAndDatastore(ctx context.Context, data SHostDatastore) (*esxi.SHost, *esxi.SDatastore, error) {
client, err := esxi.NewESXiClientFromAccessInfo(ctx, &data.Datastore)
if err != nil {

2
vendor/modules.txt vendored
View File

@@ -2603,7 +2603,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
# sigs.k8s.io/yaml v1.3.0
## explicit; go 1.12
sigs.k8s.io/yaml
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260409123844-2f5e06efeade
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260411042903-0d42d35416dc
## explicit; go 1.24
yunion.io/x/cloudmux/pkg/apis
yunion.io/x/cloudmux/pkg/apis/billing

View File

@@ -466,10 +466,25 @@ func (dc *SDatacenter) FetchVMById(id string) (*SVirtualMachine, error) {
if err != nil {
return nil, err
}
if len(vms) == 0 {
return nil, errors.ErrNotFound
for i := range vms {
return vms[i], nil
}
return vms[0], nil
return dc.FetchVMByName(id)
}
func (dc *SDatacenter) FetchVMByName(name string) (*SVirtualMachine, error) {
filter := property.Match{}
filter["name"] = name
vms, err := dc.fetchVMsWithFilter(filter)
if err != nil {
return nil, err
}
for i := range vms {
if vms[i].GetName() == name {
return vms[i], nil
}
}
return nil, errors.Wrapf(errors.ErrNotFound, "FetchVMByName %s", name)
}
func (dc *SDatacenter) fetchDatastores(datastoreRefs []types.ManagedObjectReference) ([]cloudprovider.ICloudStorage, error) {

View File

@@ -335,7 +335,7 @@ func (host *SHost) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
return nil, err
}
for i := 0; i < len(vms); i += 1 {
if vms[i].GetGlobalId() == id {
if vms[i].GetGlobalId() == id || vms[i].GetName() == id {
return vms[i], nil
}
}
@@ -1089,9 +1089,8 @@ func (host *SHost) DoCreateVM(ctx context.Context, ds *SDatastore, params SCreat
needDeploy = true
deviceChange := make([]types.BaseVirtualDeviceConfigSpec, 0, 5)
// uuid first
name := params.Name
if len(params.Uuid) != 0 {
if len(params.Uuid) > 0 {
name = params.Uuid
}
datastorePath := fmt.Sprintf("[%s] ", ds.GetRelName())
@@ -1228,7 +1227,11 @@ func (host *SHost) DoCreateVM(ctx context.Context, ds *SDatastore, params SCreat
}
vmRef := info.Result.(types.ManagedObjectReference)
objectVM := object.NewVirtualMachine(host.manager.client.Client, vmRef)
vm, err = host.addDisks(ctx, ds, params.Disks, params.Uuid, objectVM)
uuid := params.Uuid
if len(uuid) == 0 {
uuid = params.Name
}
vm, err = host.addDisks(ctx, ds, params.Disks, uuid, objectVM)
return
}