mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-30 18:23:35 +08:00
fix(region): custom user data (#14449)
This commit is contained in:
@@ -368,7 +368,8 @@ type ServerCreateInput struct {
|
||||
VcpuCount int `json:"vcpu_count"`
|
||||
|
||||
// 用户自定义启动脚本
|
||||
// 公有云私有云只支持 #cloud-config yaml 格式, 且只有linux系统生效
|
||||
// 部分平台只支持 #cloud-config yaml 格式(由于部分平台密码依赖cloud-init注入密码信息,所以不支持特殊类型的user data)
|
||||
// 支持特殊user data平台: Aliyun, Qcloud, Azure, Apsara, Ucloud
|
||||
// required: false
|
||||
UserData string `json:"user_data"`
|
||||
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
package cloudprovider
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/ansible"
|
||||
@@ -142,6 +145,11 @@ type SManagedVMCreateConfig struct {
|
||||
Tags map[string]string
|
||||
|
||||
BillingCycle *billing.SBillingCycle
|
||||
|
||||
IsNeedInjectPasswordByCloudInit bool
|
||||
UserDataType string
|
||||
WindowsUserDataType string
|
||||
IsWindowsUserDataTypeNeedEncode bool
|
||||
}
|
||||
|
||||
type SManagedVMChangeConfig struct {
|
||||
@@ -160,8 +168,15 @@ type SManagedVMRebuildRootConfig struct {
|
||||
}
|
||||
|
||||
func (vmConfig *SManagedVMCreateConfig) GetConfig(config *jsonutils.JSONDict) error {
|
||||
if err := config.Unmarshal(vmConfig, "desc"); err != nil {
|
||||
return err
|
||||
err := config.Unmarshal(vmConfig, "desc")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "config.Unmarshal")
|
||||
}
|
||||
if !vmConfig.IsNeedInjectPasswordByCloudInit {
|
||||
_, err := cloudinit.ParseUserData(vmConfig.UserData)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if publicKey, _ := config.GetString("public_key"); len(publicKey) > 0 {
|
||||
vmConfig.PublicKey = publicKey
|
||||
@@ -178,6 +193,12 @@ func (vmConfig *SManagedVMCreateConfig) GetConfig(config *jsonutils.JSONDict) er
|
||||
if resetPassword && len(vmConfig.Password) == 0 {
|
||||
vmConfig.Password = seclib2.RandomPassword2(12)
|
||||
}
|
||||
if vmConfig.IsNeedInjectPasswordByCloudInit {
|
||||
err = vmConfig.InjectPasswordByCloudInit()
|
||||
if err != nil {
|
||||
log.Warningf("failed to inject password by cloud-init error: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -207,6 +228,42 @@ func generateUserData(adminPublicKey, projectPublicKey, oUserData string) string
|
||||
return cloudConfig.UserData()
|
||||
}
|
||||
|
||||
func (vmConfig *SManagedVMCreateConfig) GetUserData() (string, error) {
|
||||
if len(vmConfig.UserData) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
oUserData, err := cloudinit.ParseUserData(vmConfig.UserData)
|
||||
if err != nil {
|
||||
// 用户输入非标准cloud-init数据
|
||||
if !vmConfig.IsNeedInjectPasswordByCloudInit {
|
||||
return base64.StdEncoding.EncodeToString([]byte(vmConfig.UserData)), nil
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
if strings.ToLower(vmConfig.OsType) == strings.ToLower(osprofile.OS_TYPE_LINUX) {
|
||||
switch vmConfig.UserDataType {
|
||||
case CLOUD_SHELL:
|
||||
return oUserData.UserDataScriptBase64(), nil
|
||||
case CLOUD_SHELL_WITHOUT_ENCRYPT:
|
||||
return oUserData.UserDataScript(), nil
|
||||
default:
|
||||
return oUserData.UserDataBase64(), nil
|
||||
}
|
||||
} else {
|
||||
userData := ""
|
||||
switch vmConfig.WindowsUserDataType {
|
||||
case CLOUD_EC2:
|
||||
userData = oUserData.UserDataEc2()
|
||||
default:
|
||||
userData = oUserData.UserDataPowerShell()
|
||||
}
|
||||
if vmConfig.IsWindowsUserDataTypeNeedEncode {
|
||||
userData = base64.StdEncoding.EncodeToString([]byte(userData))
|
||||
}
|
||||
return userData, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (vmConfig *SManagedVMCreateConfig) InjectPasswordByCloudInit() error {
|
||||
loginUser := cloudinit.NewUser(vmConfig.Account)
|
||||
loginUser.SudoPolicy(cloudinit.USER_SUDO_NOPASSWD)
|
||||
|
||||
@@ -72,7 +72,7 @@ func fetchAwsUserName(desc cloudprovider.SManagedVMCreateConfig) string {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) IsNeedInjectPasswordByCloudInit(desc *cloudprovider.SManagedVMCreateConfig) bool {
|
||||
func (self *SAwsGuestDriver) IsNeedInjectPasswordByCloudInit() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -324,7 +324,7 @@ func (self *SBaseGuestDriver) GetGuestInitialStateAfterRebuild() string {
|
||||
return api.VM_READY
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) IsNeedInjectPasswordByCloudInit(desc *cloudprovider.SManagedVMCreateConfig) bool {
|
||||
func (self *SBaseGuestDriver) IsNeedInjectPasswordByCloudInit() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ func (self *SGoogleGuestDriver) GetGuestInitialStateAfterRebuild() string {
|
||||
return api.VM_READY
|
||||
}
|
||||
|
||||
func (self *SGoogleGuestDriver) IsNeedInjectPasswordByCloudInit(desc *cloudprovider.SManagedVMCreateConfig) bool {
|
||||
func (self *SGoogleGuestDriver) IsNeedInjectPasswordByCloudInit() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ func (self *SHuaweiGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SHuaweiGuestDriver) IsNeedInjectPasswordByCloudInit(desc *cloudprovider.SManagedVMCreateConfig) bool {
|
||||
func (self *SHuaweiGuestDriver) IsNeedInjectPasswordByCloudInit() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ func (self *SHCSOGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle)
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SHCSOGuestDriver) IsNeedInjectPasswordByCloudInit(desc *cloudprovider.SManagedVMCreateConfig) bool {
|
||||
func (self *SHCSOGuestDriver) IsNeedInjectPasswordByCloudInit() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -16,16 +16,13 @@ package guestdrivers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
@@ -221,7 +218,8 @@ func (self *SManagedVirtualizedGuestDriver) ValidateCreateData(ctx context.Conte
|
||||
if input.Cdrom != "" {
|
||||
return nil, httperrors.NewInputParameterError("%s not support cdrom params", input.Hypervisor)
|
||||
}
|
||||
if len(input.UserData) > 0 {
|
||||
driver := models.GetDriver(input.Hypervisor)
|
||||
if len(input.UserData) > 0 && driver != nil && driver.IsNeedInjectPasswordByCloudInit() {
|
||||
_, err := cloudinit.ParseUserData(input.UserData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -369,7 +367,12 @@ func (self *SManagedVirtualizedGuestDriver) RequestDeployGuestOnHost(ctx context
|
||||
}
|
||||
log.Debugf("RequestDeployGuestOnHost: %s", config)
|
||||
|
||||
desc := cloudprovider.SManagedVMCreateConfig{}
|
||||
desc := cloudprovider.SManagedVMCreateConfig{
|
||||
IsNeedInjectPasswordByCloudInit: guest.GetDriver().IsNeedInjectPasswordByCloudInit(),
|
||||
UserDataType: guest.GetDriver().GetUserDataType(),
|
||||
WindowsUserDataType: guest.GetDriver().GetWindowsUserDataType(),
|
||||
IsWindowsUserDataTypeNeedEncode: guest.GetDriver().IsWindowsUserDataTypeNeedEncode(),
|
||||
}
|
||||
err = desc.GetConfig(config)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "desc.GetConfig")
|
||||
@@ -411,38 +414,9 @@ func (self *SManagedVirtualizedGuestDriver) RequestDeployGuestOnHost(ctx context
|
||||
}
|
||||
|
||||
desc.Account = guest.GetDriver().GetDefaultAccount(desc)
|
||||
|
||||
if guest.GetDriver().IsNeedInjectPasswordByCloudInit(&desc) {
|
||||
err = desc.InjectPasswordByCloudInit()
|
||||
if err != nil {
|
||||
log.Warningf("failed to inject password by cloud-init error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(desc.UserData) > 0 {
|
||||
oUserData, err := cloudinit.ParseUserData(desc.UserData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch guest.GetDriver().GetUserDataType() {
|
||||
case cloudprovider.CLOUD_SHELL:
|
||||
desc.UserData = oUserData.UserDataScriptBase64()
|
||||
case cloudprovider.CLOUD_SHELL_WITHOUT_ENCRYPT:
|
||||
desc.UserData = oUserData.UserDataScript()
|
||||
default:
|
||||
desc.UserData = oUserData.UserDataBase64()
|
||||
}
|
||||
if strings.ToLower(desc.OsType) == strings.ToLower(osprofile.OS_TYPE_WINDOWS) {
|
||||
switch guest.GetDriver().GetWindowsUserDataType() {
|
||||
case cloudprovider.CLOUD_EC2:
|
||||
desc.UserData = oUserData.UserDataEc2()
|
||||
default:
|
||||
desc.UserData = oUserData.UserDataPowerShell()
|
||||
}
|
||||
if guest.GetDriver().IsWindowsUserDataTypeNeedEncode() {
|
||||
desc.UserData = base64.StdEncoding.EncodeToString([]byte(desc.UserData))
|
||||
}
|
||||
}
|
||||
desc.UserData, err = desc.GetUserData()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetUserData")
|
||||
}
|
||||
|
||||
action, err := config.GetString("action")
|
||||
|
||||
@@ -93,7 +93,7 @@ func (self *SNutanixGuestDriver) GetUserDataType() string {
|
||||
return cloudprovider.CLOUD_SHELL
|
||||
}
|
||||
|
||||
func (self *SNutanixGuestDriver) IsNeedInjectPasswordByCloudInit(desc *cloudprovider.SManagedVMCreateConfig) bool {
|
||||
func (self *SNutanixGuestDriver) IsNeedInjectPasswordByCloudInit() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ func (self *SOpenStackGuestDriver) GetChangeConfigStatus(guest *models.SGuest) (
|
||||
return []string{api.VM_READY, api.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) IsNeedInjectPasswordByCloudInit(desc *cloudprovider.SManagedVMCreateConfig) bool {
|
||||
func (self *SOpenStackGuestDriver) IsNeedInjectPasswordByCloudInit() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ func (self *SZStackGuestDriver) GetGuestInitialStateAfterRebuild() string {
|
||||
return api.VM_READY
|
||||
}
|
||||
|
||||
func (self *SZStackGuestDriver) IsNeedInjectPasswordByCloudInit(desc *cloudprovider.SManagedVMCreateConfig) bool {
|
||||
func (self *SZStackGuestDriver) IsNeedInjectPasswordByCloudInit() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ type IGuestDriver interface {
|
||||
ValidateChangeConfig(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, cpuChanged bool, memChanged bool, newDisks []*api.DiskConfig) error
|
||||
ValidateDetachDisk(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, disk *SDisk) error
|
||||
|
||||
IsNeedInjectPasswordByCloudInit(desc *cloudprovider.SManagedVMCreateConfig) bool
|
||||
IsNeedInjectPasswordByCloudInit() bool
|
||||
GetUserDataType() string
|
||||
GetWindowsUserDataType() string
|
||||
IsWindowsUserDataTypeNeedEncode() bool
|
||||
|
||||
Reference in New Issue
Block a user