instance.go 9.2 KB

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