diff --git a/pkg/apis/compute/guest_const.go b/pkg/apis/compute/guest_const.go
index d88531d250..1d1d34475e 100644
--- a/pkg/apis/compute/guest_const.go
+++ b/pkg/apis/compute/guest_const.go
@@ -229,9 +229,10 @@ var HOSTTYPE_HYPERVISOR = map[string]string{
}
const (
- VM_AWS_DEFAULT_LOGIN_USER = "ec2user"
- VM_AZURE_DEFAULT_LOGIN_USER = "toor"
- VM_ZSTACK_DEFAULT_LOGIN_USER = "root"
+ VM_AWS_DEFAULT_LOGIN_USER = "ec2user"
+ VM_AWS_DEFAULT_WINDOWS_LOGIN_USER = "Administrator"
+ VM_AZURE_DEFAULT_LOGIN_USER = "toor"
+ VM_ZSTACK_DEFAULT_LOGIN_USER = "root"
VM_METADATA_APP_TAGS = "app_tags"
VM_METADATA_CREATE_PARAMS = "create_params"
diff --git a/pkg/cloudprovider/instance.go b/pkg/cloudprovider/instance.go
index 22cd39a6c7..760069ddf2 100644
--- a/pkg/cloudprovider/instance.go
+++ b/pkg/cloudprovider/instance.go
@@ -115,7 +115,7 @@ func generateUserData(adminPublicKey, projectPublicKey, oUserData string) string
cloudConfig := cloudinit.SCloudConfig{
DisableRoot: 0,
- SshPwauth: 1,
+ SshPwauth: cloudinit.SSH_PASSWORD_AUTH_ON,
Users: []cloudinit.SUser{
ansibleUser,
@@ -141,7 +141,7 @@ func (vmConfig *SManagedVMCreateConfig) InjectPasswordByCloudInit() error {
cloudconfig := cloudinit.SCloudConfig{
DisableRoot: 0,
- SshPwauth: 1,
+ SshPwauth: cloudinit.SSH_PASSWORD_AUTH_ON,
Users: []cloudinit.SUser{
loginUser,
},
diff --git a/pkg/compute/guestdrivers/aws.go b/pkg/compute/guestdrivers/aws.go
index 68a237f732..ca9ac21c72 100644
--- a/pkg/compute/guestdrivers/aws.go
+++ b/pkg/compute/guestdrivers/aws.go
@@ -81,7 +81,7 @@ func (self *SAwsGuestDriver) IsNeedInjectPasswordByCloudInit(desc *cloudprovider
func (self *SAwsGuestDriver) GetLinuxDefaultAccount(desc cloudprovider.SManagedVMCreateConfig) string {
// return fetchAwsUserName(desc)
if desc.OsType == "Windows" {
- return "Administrator"
+ return api.VM_AWS_DEFAULT_WINDOWS_LOGIN_USER
}
return api.VM_AWS_DEFAULT_LOGIN_USER
diff --git a/pkg/multicloud/aws/host.go b/pkg/multicloud/aws/host.go
index 925d17489b..4a9ef6e7ad 100644
--- a/pkg/multicloud/aws/host.go
+++ b/pkg/multicloud/aws/host.go
@@ -15,10 +15,13 @@
package aws
import (
+ "encoding/base64"
"fmt"
+ "strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
+ "yunion.io/x/pkg/util/osprofile"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
@@ -173,6 +176,12 @@ func (self *SHost) GetInstanceById(instanceId string) (*SInstance, error) {
}
func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
+ if strings.ToLower(desc.OsType) == strings.ToLower(osprofile.OS_TYPE_WINDOWS) {
+ // powershell scripts
+ data := fmt.Sprintf("%s", desc.UserData)
+ desc.UserData = base64.StdEncoding.EncodeToString([]byte(data))
+ }
+
vmId, err := self._createVM(desc.Name, desc.ExternalImageId, desc.SysDisk, desc.InstanceType, desc.ExternalNetworkId, desc.IpAddr, desc.Description, desc.Password, desc.DataDisks, desc.PublicKey, desc.ExternalSecgroupId, desc.UserData)
if err != nil {
return nil, err
diff --git a/pkg/multicloud/aws/instance.go b/pkg/multicloud/aws/instance.go
index bcb88b5428..5ce258587e 100644
--- a/pkg/multicloud/aws/instance.go
+++ b/pkg/multicloud/aws/instance.go
@@ -410,32 +410,6 @@ func (self *SInstance) RebuildRoot(ctx context.Context, desc *cloudprovider.SMan
return "", err
}
- var cloudconfig *cloudinit.SCloudConfig
- if len(udata) == 0 {
- cloudconfig = &cloudinit.SCloudConfig{}
- } else {
- cloudconfig, err = cloudinit.ParseUserDataBase64(udata)
- if err != nil {
- log.Debugf("RebuildRoot invalid instance user data %s", udata)
- return "", fmt.Errorf("RebuildRoot invalid instance user data %s", err)
- }
- }
-
- keypairName := self.KeyPairName
- loginUser := cloudinit.NewUser(api.VM_AWS_DEFAULT_LOGIN_USER)
- loginUser.SudoPolicy(cloudinit.USER_SUDO_NOPASSWD)
- if len(desc.PublicKey) > 0 {
- loginUser.SshKey(desc.PublicKey)
- cloudconfig.MergeUser(loginUser)
- keypairName, err = self.host.zone.region.syncKeypair(desc.PublicKey)
- if err != nil {
- return "", fmt.Errorf("RebuildRoot.syncKeypair %s", err)
- }
- } else if len(desc.Password) > 0 {
- loginUser.Password(desc.Password)
- cloudconfig.MergeUser(loginUser)
- }
-
// compare sysSizeGB
image, err := self.host.zone.region.GetImage(desc.ImageId)
if err != nil {
@@ -447,7 +421,65 @@ func (self *SInstance) RebuildRoot(ctx context.Context, desc *cloudprovider.SMan
}
}
- diskId, err := self.host.zone.region.ReplaceSystemDisk(ctx, self.InstanceId, desc.ImageId, desc.SysSizeGB, keypairName, cloudconfig.UserDataBase64())
+ // upload keypair
+ keypairName := self.KeyPairName
+ if len(desc.PublicKey) > 0 {
+ keypairName, err = self.host.zone.region.syncKeypair(desc.PublicKey)
+ if err != nil {
+ return "", fmt.Errorf("RebuildRoot.syncKeypair %s", err)
+ }
+ }
+
+ userdata := ""
+ srcOsType := strings.ToLower(self.GetOSType())
+ destOsType := strings.ToLower(image.GetOsType())
+ winOS := strings.ToLower(osprofile.OS_TYPE_WINDOWS)
+
+ cloudconfig := &cloudinit.SCloudConfig{}
+ if srcOsType != winOS && len(udata) > 0 {
+ _cloudconfig, err := cloudinit.ParseUserDataBase64(udata)
+ if err != nil {
+ // 忽略无效的用户数据
+ log.Debugf("RebuildRoot invalid instance user data %s", udata)
+ } else {
+ cloudconfig = _cloudconfig
+ }
+ }
+
+ if (srcOsType != winOS && destOsType != winOS) || (srcOsType == winOS && destOsType != winOS) {
+ // linux/windows to linux
+ loginUser := cloudinit.NewUser(api.VM_AWS_DEFAULT_LOGIN_USER)
+ loginUser.SudoPolicy(cloudinit.USER_SUDO_NOPASSWD)
+ if len(desc.PublicKey) > 0 {
+ loginUser.SshKey(desc.PublicKey)
+ cloudconfig.MergeUser(loginUser)
+ } else if len(desc.Password) > 0 {
+ cloudconfig.SshPwauth = cloudinit.SSH_PASSWORD_AUTH_ON
+ loginUser.Password(desc.Password)
+ cloudconfig.MergeUser(loginUser)
+ }
+
+ userdata = cloudconfig.UserDataBase64()
+ } else {
+ // linux/windows to windows
+ data := ""
+ if len(desc.Password) > 0 {
+ cloudconfig.SshPwauth = cloudinit.SSH_PASSWORD_AUTH_ON
+ loginUser := cloudinit.NewUser(api.VM_AWS_DEFAULT_WINDOWS_LOGIN_USER)
+ loginUser.SudoPolicy(cloudinit.USER_SUDO_NOPASSWD)
+ loginUser.Password(desc.Password)
+ cloudconfig.MergeUser(loginUser)
+ data = fmt.Sprintf("%s", cloudconfig.UserDataPowerShell())
+ } else {
+ if len(udata) > 0 {
+ data = fmt.Sprintf("%s", udata)
+ }
+ }
+
+ userdata = base64.StdEncoding.EncodeToString([]byte(data))
+ }
+
+ diskId, err := self.host.zone.region.ReplaceSystemDisk(ctx, self.InstanceId, desc.ImageId, desc.SysSizeGB, keypairName, userdata)
if err != nil {
return "", err
}
@@ -985,7 +1017,11 @@ func (self *SRegion) ReplaceSystemDisk(ctx context.Context, instanceId string, i
self.ec2Client.WaitUntilInstanceStopped(&ec2.DescribeInstancesInput{InstanceIds: []*string{&instanceId}})
self.ec2Client.WaitUntilVolumeInUse(&ec2.DescribeVolumesInput{VolumeIds: []*string{&tempInstance.Disks[0]}})
- err = instance.UpdateUserData(userdata)
+ userdataText, err := base64.StdEncoding.DecodeString(userdata)
+ if err != nil {
+ return "", errors.Wrap(err, "SRegion.ReplaceSystemDisk.DecodeString")
+ }
+ err = instance.UpdateUserData(string(userdataText))
if err != nil {
log.Debugf("ReplaceSystemDisk update user data %s", err)
return "", fmt.Errorf("ReplaceSystemDisk update user data failed")
diff --git a/pkg/util/cloudinit/cloudconfig.go b/pkg/util/cloudinit/cloudconfig.go
index 288776f5d4..6b7d874cab 100644
--- a/pkg/util/cloudinit/cloudconfig.go
+++ b/pkg/util/cloudinit/cloudconfig.go
@@ -34,6 +34,7 @@ import (
*/
type TSudoPolicy string
+type TSshPwauth string
const (
CLOUD_CONFIG_HEADER = "#cloud-config\n"
@@ -43,6 +44,10 @@ const (
USER_SUDO = TSudoPolicy("sudo")
USER_SUDO_DENY = TSudoPolicy("sudo_deny")
USER_SUDO_NONE = TSudoPolicy("")
+
+ SSH_PASSWORD_AUTH_ON = TSshPwauth("true")
+ SSH_PASSWORD_AUTH_OFF = TSshPwauth("false")
+ SSH_PASSWORD_AUTH_UNCHANGED = TSshPwauth("unchanged")
)
type SWriteFile struct {
@@ -74,7 +79,7 @@ type SCloudConfig struct {
Packages []string
PhoneHome *SPhoneHome
DisableRoot int
- SshPwauth int
+ SshPwauth TSshPwauth
}
func NewWriteFile(path string, content string, perm string, owner string, isBase64 bool) SWriteFile {
diff --git a/pkg/util/cloudinit/cloudconfig_test.go b/pkg/util/cloudinit/cloudconfig_test.go
index dc64571511..f751d0abdc 100644
--- a/pkg/util/cloudinit/cloudconfig_test.go
+++ b/pkg/util/cloudinit/cloudconfig_test.go
@@ -43,7 +43,7 @@ func TestSCloudConfig_UserData(t *testing.T) {
Url: "http://www.yunion.io/$INSTANCE_ID",
},
DisableRoot: 0,
- SshPwauth: 1,
+ SshPwauth: SSH_PASSWORD_AUTH_ON,
}
userData := config.UserData()