fix(region): custom user data (#14449)

This commit is contained in:
屈轩
2022-06-14 01:51:59 +08:00
committed by GitHub
parent 44a5951048
commit 01399a698e
12 changed files with 81 additions and 49 deletions
+2 -1
View File
@@ -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"`
+59 -2
View File
@@ -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)
+1 -1
View File
@@ -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
}
+1 -1
View File
@@ -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
}
+1 -1
View File
@@ -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
}
+1 -1
View File
@@ -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
}
+1 -1
View File
@@ -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
}
+11 -37
View File
@@ -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")
+1 -1
View File
@@ -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
}
+1 -1
View File
@@ -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
}
+1 -1
View File
@@ -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
}
+1 -1
View File
@@ -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