yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/cloudprovider/instance.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cloudprovider 16 17 import ( 18 "encoding/base64" 19 "strings" 20 21 "yunion.io/x/jsonutils" 22 "yunion.io/x/pkg/errors" 23 "yunion.io/x/pkg/util/osprofile" 24 25 "yunion.io/x/onecloud/pkg/util/ansible" 26 "yunion.io/x/onecloud/pkg/util/billing" 27 "yunion.io/x/onecloud/pkg/util/cloudinit" 28 "yunion.io/x/onecloud/pkg/util/seclib2" 29 ) 30 31 type TOsType string 32 33 var ( 34 OsTypeLinux = TOsType(osprofile.OS_TYPE_LINUX) 35 OsTypeWindows = TOsType(osprofile.OS_TYPE_WINDOWS) 36 ) 37 38 type TBiosType string 39 40 var ( 41 BIOS = TBiosType("BIOS") 42 UEFI = TBiosType("UEFI") 43 ) 44 45 func ToBiosType(bios string) TBiosType { 46 switch strings.ToLower(bios) { 47 case "uefi", "efi": 48 return UEFI 49 default: 50 return BIOS 51 } 52 } 53 54 type SDistDefaultAccount struct { 55 // 操作系统发行版 56 OsDistribution string 57 // 默认用户名 58 DefaultAccount string 59 // 是否可更改 60 Changeable bool 61 } 62 63 type SOsDefaultAccount struct { 64 // 默认用户名 65 DefaultAccount string 66 // 是否可更改用户名 67 Changeable bool 68 // 禁止使用的账号 69 DisabledAccounts []string 70 // 各操作系统发行版的默认用户名信息 71 DistAccounts []SDistDefaultAccount 72 } 73 74 type SDefaultAccount struct { 75 Linux SOsDefaultAccount 76 Windows SOsDefaultAccount 77 } 78 79 type StorageInfo struct { 80 StorageType string 81 MaxSizeGb int 82 MinSizeGb int 83 Resizable bool 84 StepSizeGb int 85 } 86 87 type Storage struct { 88 DataDisk []StorageInfo 89 SysDisk []StorageInfo 90 } 91 92 type SInstanceCapability struct { 93 Provider string 94 Hypervisor string 95 Storages Storage 96 97 DefaultAccount SDefaultAccount 98 } 99 100 type SDiskInfo struct { 101 StorageExternalId string 102 StorageType string 103 SizeGB int 104 Name string 105 } 106 107 type GuestDiskCreateOptions struct { 108 SizeMb int 109 UUID string 110 Driver string 111 StorageId string 112 } 113 114 const ( 115 CLOUD_SHELL = "cloud-shell" 116 CLOUD_SHELL_WITHOUT_ENCRYPT = "cloud-shell-without-encrypt" 117 CLOUD_CONFIG = "cloud-config" 118 CLOUD_POWER_SHELL = "powershell" 119 CLOUD_EC2 = "ec2" 120 ) 121 122 type SPublicIpInfo struct { 123 PublicIpBw int 124 PublicIpChargeType TElasticipChargeType 125 } 126 127 type ServerStopOptions struct { 128 IsForce bool 129 StopCharging bool 130 } 131 132 type SManagedVMCreateConfig struct { 133 Name string 134 NameEn string 135 Hostname string 136 ExternalImageId string 137 ImageType string 138 OsType string 139 OsDistribution string 140 OsVersion string 141 InstanceType string // InstanceType 不为空时,直接采用InstanceType创建机器。 142 Cpu int 143 MemoryMB int 144 ExternalNetworkId string 145 ExternalVpcId string 146 IpAddr string 147 Description string 148 SysDisk SDiskInfo 149 DataDisks []SDiskInfo 150 PublicKey string 151 ExternalSecgroupId string 152 ExternalSecgroupIds []string 153 Account string 154 Password string 155 UserData string 156 ProjectId string 157 158 SPublicIpInfo 159 160 Tags map[string]string 161 162 BillingCycle *billing.SBillingCycle 163 164 IsNeedInjectPasswordByCloudInit bool 165 UserDataType string 166 WindowsUserDataType string 167 IsWindowsUserDataTypeNeedEncode bool 168 } 169 170 type SManagedVMChangeConfig struct { 171 Cpu int 172 MemoryMB int 173 InstanceType string 174 } 175 176 type SManagedVMRebuildRootConfig struct { 177 Account string 178 Password string 179 ImageId string 180 PublicKey string 181 SysSizeGB int 182 OsType string 183 } 184 185 func (vmConfig *SManagedVMCreateConfig) GetConfig(config *jsonutils.JSONDict) error { 186 err := config.Unmarshal(vmConfig, "desc") 187 if err != nil { 188 return errors.Wrapf(err, "config.Unmarshal") 189 } 190 if !vmConfig.IsNeedInjectPasswordByCloudInit { 191 if len(vmConfig.UserData) > 0 { 192 _, err := cloudinit.ParseUserData(vmConfig.UserData) 193 if err != nil { 194 return err 195 } 196 } 197 } 198 if publicKey, _ := config.GetString("public_key"); len(publicKey) > 0 { 199 vmConfig.PublicKey = publicKey 200 } 201 //目前所写的userData格式仅支持Linux 202 if strings.ToLower(vmConfig.OsType) == strings.ToLower(osprofile.OS_TYPE_LINUX) { 203 adminPublicKey, _ := config.GetString("admin_public_key") 204 projectPublicKey, _ := config.GetString("project_public_key") 205 vmConfig.UserData = generateUserData(adminPublicKey, projectPublicKey, vmConfig.UserData) 206 } 207 208 resetPassword := jsonutils.QueryBoolean(config, "reset_password", false) 209 vmConfig.Password, _ = config.GetString("password") 210 if resetPassword && len(vmConfig.Password) == 0 { 211 vmConfig.Password = seclib2.RandomPassword2(12) 212 } 213 if vmConfig.IsNeedInjectPasswordByCloudInit { 214 err = vmConfig.InjectPasswordByCloudInit() 215 if err != nil { 216 return errors.Wrapf(err, "InjectPasswordByCloudInit") 217 } 218 } 219 return nil 220 } 221 222 func generateUserData(adminPublicKey, projectPublicKey, oUserData string) string { 223 var oCloudConfig *cloudinit.SCloudConfig 224 225 if len(oUserData) > 0 { 226 oCloudConfig, _ = cloudinit.ParseUserData(oUserData) 227 } 228 229 ansibleUser := cloudinit.NewUser(ansible.PUBLIC_CLOUD_ANSIBLE_USER) 230 ansibleUser.SshKey(adminPublicKey).SshKey(projectPublicKey).SudoPolicy(cloudinit.USER_SUDO_NOPASSWD) 231 232 cloudConfig := cloudinit.SCloudConfig{ 233 DisableRoot: 0, 234 SshPwauth: cloudinit.SSH_PASSWORD_AUTH_ON, 235 236 Users: []cloudinit.SUser{ 237 ansibleUser, 238 }, 239 } 240 241 if oCloudConfig != nil { 242 cloudConfig.Merge(oCloudConfig) 243 } 244 245 return cloudConfig.UserData() 246 } 247 248 func (vmConfig *SManagedVMCreateConfig) GetUserData() (string, error) { 249 if len(vmConfig.UserData) == 0 { 250 return "", nil 251 } 252 oUserData, err := cloudinit.ParseUserData(vmConfig.UserData) 253 if err != nil { 254 // 用户输入非标准cloud-init数据 255 if !vmConfig.IsNeedInjectPasswordByCloudInit { 256 return base64.StdEncoding.EncodeToString([]byte(vmConfig.UserData)), nil 257 } 258 return "", err 259 } 260 if strings.ToLower(vmConfig.OsType) == strings.ToLower(osprofile.OS_TYPE_LINUX) { 261 switch vmConfig.UserDataType { 262 case CLOUD_SHELL: 263 return oUserData.UserDataScriptBase64(), nil 264 case CLOUD_SHELL_WITHOUT_ENCRYPT: 265 return oUserData.UserDataScript(), nil 266 default: 267 return oUserData.UserDataBase64(), nil 268 } 269 } else { 270 userData := "" 271 switch vmConfig.WindowsUserDataType { 272 case CLOUD_EC2: 273 userData = oUserData.UserDataEc2() 274 default: 275 userData = oUserData.UserDataPowerShell() 276 } 277 if vmConfig.IsWindowsUserDataTypeNeedEncode { 278 userData = base64.StdEncoding.EncodeToString([]byte(userData)) 279 } 280 return userData, nil 281 } 282 } 283 284 func (vmConfig *SManagedVMCreateConfig) InjectPasswordByCloudInit() error { 285 loginUser := cloudinit.NewUser(vmConfig.Account) 286 loginUser.SudoPolicy(cloudinit.USER_SUDO_NOPASSWD) 287 if len(vmConfig.PublicKey) > 0 { 288 loginUser.SshKey(vmConfig.PublicKey) 289 } 290 if len(vmConfig.Password) > 0 { 291 loginUser.Password(vmConfig.Password) 292 } 293 294 cloudconfig := cloudinit.SCloudConfig{ 295 DisableRoot: 0, 296 SshPwauth: cloudinit.SSH_PASSWORD_AUTH_ON, 297 Users: []cloudinit.SUser{ 298 loginUser, 299 }, 300 } 301 302 if len(vmConfig.UserData) > 0 { 303 oCloudConfig, err := cloudinit.ParseUserData(vmConfig.UserData) 304 if err != nil { 305 return err 306 } 307 cloudconfig.Merge(oCloudConfig) 308 } 309 vmConfig.UserData = cloudconfig.UserData() 310 return nil 311 } 312 313 // +onecloud:model-api-gen 314 type ServerVncInput struct { 315 // 是否使用原生vnc控制台,此选项仅对openstack有效 316 // default: false 317 Origin bool `json:"origin"` 318 } 319 320 // +onecloud:model-api-gen 321 type ServerVncOutput struct { 322 Id string `json:"id"` 323 324 // baremetal 325 HostId string `json:"host_id"` 326 Zone string `json:"zone"` 327 328 // kvm host ip 329 Host string `json:"host"` 330 Protocol string `json:"protocol"` 331 Port int64 `json:"port"` 332 333 Url string `json:"url"` 334 InstanceId string `json:"instance_id"` 335 InstanceName string `json:"instance_name"` 336 Password string `json:"password"` 337 VncPassword string `json:"vnc_password"` 338 339 OsName string `json:"os_name"` 340 341 // cloudpods 342 ApiServer string `json:"api_server"` 343 ConnectParams string `json:"connect_params"` 344 Session string `json:"session"` 345 346 Hypervisor string `json:"hypervisor"` 347 }