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()