yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/incloudsphere/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 incloudsphere 16 17 import ( 18 "context" 19 "fmt" 20 "net/url" 21 "strings" 22 23 "yunion.io/x/jsonutils" 24 "yunion.io/x/pkg/errors" 25 26 api "yunion.io/x/cloudmux/pkg/apis/compute" 27 "yunion.io/x/cloudmux/pkg/cloudprovider" 28 "yunion.io/x/cloudmux/pkg/multicloud" 29 "yunion.io/x/onecloud/pkg/util/imagetools" 30 ) 31 32 type Cdrom struct { 33 Path string `json:"path"` 34 Type string `json:"type"` 35 Connected bool `json:"connected"` 36 StartConnected bool `json:"startConnected"` 37 CifsDto string `json:"cifsDto"` 38 DataStore struct { 39 Id string `json:"id"` 40 Name string `json:"name"` 41 } `json:"dataStore"` 42 } 43 44 type Floppy struct { 45 Path string `json:"path"` 46 DataStore string `json:"dataStore"` 47 VfdType string `json:"vfdType"` 48 } 49 50 type FtpServerHost struct { 51 Id string `json:"id"` 52 Ip string `json:"ip"` 53 } 54 55 type VvSourceDto struct { 56 SourceType string `json:"sourceType"` 57 FilePath string `json:"filePath"` 58 Name string `json:"name"` 59 FtpServerHost FtpServerHost `json:"ftpServerHost"` 60 } 61 62 type Volume struct { 63 Id string `json:"id"` 64 UUID string `json:"uuid"` 65 Size float64 `json:"size"` 66 RealSize float64 `json:"realSize"` 67 Name string `json:"name"` 68 FileName string `json:"fileName"` 69 Offset int `json:"offset"` 70 Shared bool `json:"shared"` 71 DeleteModel string `json:"deleteModel"` 72 VolumePolicy string `json:"volumePolicy"` 73 Format string `json:"format"` 74 BlockDeviceId string `json:"blockDeviceId"` 75 DiskType string `json:"diskType"` 76 DataStoreId string `json:"dataStoreId"` 77 DataStoreName string `json:"dataStoreName"` 78 DataStoreSize float64 `json:"dataStoreSize"` 79 FreeStorage float64 `json:"freeStorage"` 80 DataStoreType string `json:"dataStoreType"` 81 DataStoreReplicate int `json:"dataStoreReplicate"` 82 VMName string `json:"vmName"` 83 VMStatus string `json:"vmStatus"` 84 Type string `json:"type"` 85 Description string `json:"description"` 86 Bootable bool `json:"bootable"` 87 VolumeStatus string `json:"volumeStatus"` 88 MountedHostIds string `json:"mountedHostIds"` 89 Md5 string `json:"md5"` 90 DataSize int `json:"dataSize"` 91 OpenStackId string `json:"openStackId"` 92 VvSourceDto VvSourceDto `json:"vvSourceDto"` 93 FormatDisk bool `json:"formatDisk"` 94 ToBeConverted bool `json:"toBeConverted"` 95 RelatedVms string `json:"relatedVms"` 96 XactiveDataStoreId string `json:"xactiveDataStoreId"` 97 ClusterSize int `json:"clusterSize"` 98 ScsiId string `json:"scsiId"` 99 SecondaryUUID string `json:"secondaryUuid"` 100 SecondaryVolumes []struct{} `json:"secondaryVolumes"` 101 } 102 103 type Disks struct { 104 Id string `json:"id"` 105 Label string `json:"label"` 106 ScsiId string `json:"scsiId"` 107 Enabled bool `json:"enabled"` 108 WriteBps int `json:"writeBps"` 109 ReadBps int `json:"readBps"` 110 TotalBps int `json:"totalBps"` 111 TotalIops int `json:"totalIops"` 112 WriteIops int `json:"writeIops"` 113 ReadIops int `json:"readIops"` 114 Volume Volume `json:"volume"` 115 BusModel string `json:"busModel"` 116 Usage float64 `json:"usage"` 117 MonReadIops float64 `json:"monReadIops"` 118 MonWriteIops float64 `json:"monWriteIops"` 119 ReadThroughput float64 `json:"readThroughput"` 120 WriteThroughput float64 `json:"writeThroughput"` 121 ReadWriteModel string `json:"readWriteModel"` 122 EnableNativeIO bool `json:"enableNativeIO"` 123 EnableKernelIO bool `json:"enableKernelIO"` 124 L2CacheSize int `json:"l2CacheSize"` 125 QueueNum int `json:"queueNum"` 126 } 127 128 type CdpInfo struct { 129 CdpBackupDatastoreId string `json:"cdpBackupDatastoreId"` 130 BackupDataStoreName string `json:"backupDataStoreName"` 131 StartTime string `json:"startTime"` 132 EndTime string `json:"endTime"` 133 EnableCDP bool `json:"enableCDP"` 134 CdpAvgWriteMBps int `json:"cdpAvgWriteMBps"` 135 CdpRemainTimes int `json:"cdpRemainTimes"` 136 CdpLogSpaceSize int `json:"cdpLogSpaceSize"` 137 IntervalTime int `json:"intervalTime"` 138 } 139 140 type GuestOSAuthInfo struct { 141 UserName string `json:"userName"` 142 UserPwd string `json:"userPwd"` 143 } 144 145 type SInstance struct { 146 multicloud.SInstanceBase 147 InCloudSphereTags 148 149 host *SHost 150 151 osInfo *imagetools.ImageInfo 152 153 Id string `json:"id"` 154 CustomVMId string `json:"customVmId"` 155 Name string `json:"name"` 156 State string `json:"state"` 157 Status string `json:"status"` 158 HostId string `json:"hostId"` 159 HostName string `json:"hostName"` 160 HostIP string `json:"hostIp"` 161 HostStatus string `json:"hostStatus"` 162 HostMemory int64 `json:"hostMemory"` 163 DataCenterId string `json:"dataCenterId"` 164 HaEnabled bool `json:"haEnabled"` 165 RouterFlag bool `json:"routerFlag"` 166 Migratable bool `json:"migratable"` 167 HostBinded bool `json:"hostBinded"` 168 ToolsInstalled bool `json:"toolsInstalled"` 169 ToolsVersion string `json:"toolsVersion"` 170 ToolsType string `json:"toolsType"` 171 ToolsVersionStatus string `json:"toolsVersionStatus"` 172 ToolsRunningStatus string `json:"toolsRunningStatus"` 173 ToolsNeedUpdate bool `json:"toolsNeedUpdate"` 174 Description string `json:"description"` 175 HaMaxLimit int64 `json:"haMaxLimit"` 176 Template bool `json:"template"` 177 Initialized bool `json:"initialized"` 178 GuestosLabel string `json:"guestosLabel"` 179 GuestosType string `json:"guestosType"` 180 GuestOSInfo struct { 181 Model string `json:"model"` 182 SocketLimit int `json:"socketLimit"` 183 SupportCpuHotPlug bool `json:"supportCpuHotPlug"` 184 SupportDiskHotPlug bool `json:"supportDiskHotPlug"` 185 SupportMemHotPlug bool `json:"supportMemHotPlug"` 186 SupportUefiBootMode bool `json:"supportUefiBootMode"` 187 } `json:"guestOsInfo"` 188 InnerName string `json:"innerName"` 189 UUId string `json:"uuid"` 190 MaxMemory int64 `json:"maxMemory"` 191 Memory int `json:"memory"` 192 MemoryUsage int64 `json:"memoryUsage"` 193 MemHotplugEnabled bool `json:"memHotplugEnabled"` 194 EnableHugeMemPage bool `json:"enableHugeMemPage"` 195 CPUNum int `json:"cpuNum"` 196 CPUSocket int `json:"cpuSocket"` 197 CPUCore int64 `json:"cpuCore"` 198 CPUUsage int64 `json:"cpuUsage"` 199 MaxCPUNum int64 `json:"maxCpuNum"` 200 CPUHotplugEnabled bool `json:"cpuHotplugEnabled"` 201 CPUModelType string `json:"cpuModelType"` 202 CPUModelEnabled bool `json:"cpuModelEnabled"` 203 RunningTime int64 `json:"runningTime"` 204 Boot string `json:"boot"` 205 BootMode string `json:"bootMode"` 206 SplashTime int64 `json:"splashTime"` 207 StoragePriority int64 `json:"storagePriority"` 208 USB string `json:"usb"` 209 210 //Usbs []interface{} `json:"usbs"` 211 Cdrom Cdrom `json:"cdrom"` 212 Floppy Floppy `json:"floppy"` 213 Disks []Disks `json:"disks"` 214 Nics []SInstanceNic `json:"nics"` 215 216 //Gpus []interface{} `json:"gpus"` 217 //VMPcis []interface{} `json:"vmPcis"` 218 ConfigLocation string `json:"configLocation"` 219 HotplugEnabled bool `json:"hotplugEnabled"` 220 VNCPort int64 `json:"vncPort"` 221 VNCPasswd string `json:"vncPasswd"` 222 VNCSharePolicy string `json:"vncSharePolicy"` 223 CPUBindType string `json:"cpuBindType"` 224 VcpuPin string `json:"vcpuPin"` 225 VcpuPins []string `json:"vcpuPins"` 226 CPUShares int64 `json:"cpuShares"` 227 PanickPolicy string `json:"panickPolicy"` 228 DataStoreId string `json:"dataStoreId"` 229 SdsdomainId string `json:"sdsdomainId"` 230 ClockModel string `json:"clockModel"` 231 CPULimit int64 `json:"cpuLimit"` 232 MemShares int64 `json:"memShares"` 233 CPUReservation int64 `json:"cpuReservation"` 234 MemReservation int64 `json:"memReservation"` 235 LastBackup string `json:"lastBackup"` 236 VMType string `json:"vmType"` 237 SystemVMType string `json:"systemVmType"` 238 MemBalloonEnabled bool `json:"memBalloonEnabled"` 239 Completed bool `json:"completed"` 240 GraphicsCardModel string `json:"graphicsCardModel"` 241 GraphicsCardMemory int64 `json:"graphicsCardMemory"` 242 GraphicsCards string `json:"graphicsCards"` 243 VMHostName string `json:"vmHostName"` 244 DiskTotalSize int64 `json:"diskTotalSize"` 245 DiskUsedSize float64 `json:"diskUsedSize"` 246 DiskUsage float64 `json:"diskUsage"` 247 StartPriority string `json:"startPriority"` 248 OwnerName string `json:"ownerName"` 249 Version string `json:"version"` 250 EnableReplicate bool `json:"enableReplicate"` 251 ReplicationDatastoreId string `json:"replicationDatastoreId"` 252 ReplicationDatastoreName string `json:"replicationDatastoreName"` 253 RecoveryFlag bool `json:"recoveryFlag"` 254 SpiceUSBNum int64 `json:"spiceUsbNum"` 255 CDPInfo CdpInfo `json:"cdpInfo"` 256 GuestOSAuthInfo GuestOSAuthInfo `json:"guestOSAuthInfo"` 257 AwareNUMAEnabled bool `json:"awareNumaEnabled"` 258 DrxEnabled bool `json:"drxEnabled"` 259 SecretLevel string `json:"secretLevel"` 260 //VmfpgaDevs []interface{} `json:"vmfpgaDevs"` 261 } 262 263 func (self *SInstance) GetName() string { 264 return self.Name 265 } 266 267 func (self *SInstance) GetId() string { 268 return self.Id 269 } 270 271 func (self *SInstance) GetGlobalId() string { 272 return self.GetId() 273 } 274 275 func (self *SInstance) Refresh() error { 276 ins, err := self.host.zone.region.GetInstance(self.Id) 277 if err != nil { 278 return err 279 } 280 return jsonutils.Update(self, ins) 281 } 282 283 func (self *SInstance) AssignSecurityGroup(id string) error { 284 return cloudprovider.ErrNotSupported 285 } 286 287 func (self *SInstance) AttachDisk(ctx context.Context, diskId string) error { 288 return self.host.zone.region.AttachDisk(self.Id, diskId) 289 } 290 291 func (self *SInstance) CreateDisk(ctx context.Context, opts *cloudprovider.GuestDiskCreateOptions) (string, error) { 292 return "", cloudprovider.ErrNotSupported 293 } 294 295 func (self *SInstance) ChangeConfig(ctx context.Context, opts *cloudprovider.SManagedVMChangeConfig) error { 296 return self.host.zone.region.ChangeConfig(self.Id, opts.Cpu, opts.MemoryMB) 297 } 298 299 func (self *SInstance) DeleteVM(ctx context.Context) error { 300 return self.host.zone.region.DeleteVM(self.Id) 301 } 302 303 func (self *SInstance) DeployVM(ctx context.Context, name string, username string, password string, publicKey string, deleteKeypair bool, description string) error { 304 return self.host.zone.region.ResetVmPassword(self.Id, username, password) 305 } 306 307 func (self *SInstance) DetachDisk(ctx context.Context, diskId string) error { 308 return self.host.zone.region.DetachDisk(self.Id, diskId) 309 } 310 311 func (self *SInstance) GetBios() cloudprovider.TBiosType { 312 return cloudprovider.ToBiosType(self.BootMode) 313 } 314 315 func (self *SInstance) GetBootOrder() string { 316 return strings.ToLower(self.Boot) 317 } 318 319 func (self *SInstance) GetError() error { 320 return nil 321 } 322 323 func (self *SInstance) GetHostname() string { 324 return self.HostName 325 } 326 327 func (self *SInstance) GetHypervisor() string { 328 return api.HYPERVISOR_INCLOUD_SPHERE 329 } 330 331 func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) { 332 ret := []cloudprovider.ICloudDisk{} 333 for i := range self.Disks { 334 disk, err := self.host.zone.region.GetDisk(self.Disks[i].Volume.Id) 335 if err != nil { 336 return nil, err 337 } 338 ret = append(ret, disk) 339 } 340 return ret, nil 341 } 342 343 func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) { 344 return nil, cloudprovider.ErrNotSupported 345 } 346 347 func (self *SInstance) GetIHost() cloudprovider.ICloudHost { 348 return self.host 349 } 350 351 func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) { 352 ret := []cloudprovider.ICloudNic{} 353 for i := range self.Nics { 354 self.Nics[i].ins = self 355 ret = append(ret, &self.Nics[i]) 356 } 357 return ret, nil 358 } 359 360 func (self *SInstance) GetInstanceType() string { 361 return fmt.Sprintf("ecs.g1.c%dm%d", self.GetVcpuCount(), self.GetVmemSizeMB()/1024) 362 } 363 364 func (self *SInstance) GetMachine() string { 365 return "" 366 } 367 368 /* 369 PENDING 开启准备中 370 STARTING 开启或恢复中 371 STARTED 开启的 372 PAUSING 暂停中 373 PAUSED 暂停的 374 RESTARTING 重启中 375 STOPPING 关机中 376 STOPPED 关闭的 377 HOT_SAVING 开机快照中 378 COLD_SAVING 关机快照中 379 PRE_MIGRATE 迁移准备中 380 HOT_MIGRATING 热迁移中 381 COLD_MIGRATING 冷迁移中 382 REVERTING 恢复快照中 383 EXPORTING 导出中 384 IMPORTING 导入中 385 COLD_BACKUPING 关机备份中 386 HOT_BACKUPING 开机备份中 387 COLD_MODIFYING 冷配置中 388 HOT_MODIFYING 热配置中 389 COLD_COPING 关机复制中 390 */ 391 392 func (self *SInstance) GetStatus() string { 393 switch strings.ToUpper(self.Status) { 394 case "COLD_COPING", "COLD_BACKUPING", "COLD_SAVING", "STOPPED": 395 return api.VM_READY 396 case "PENDING", "STARTING": 397 return api.VM_START_START 398 case "STARTED", "HOT_SAVING", "HOT_BACKUPING": 399 return api.VM_RUNNING 400 case "PAUSING", "RESTARTING", "STOPPING": 401 return api.VM_START_STOP 402 case "REVERTING", "EXPORTING", "IMPORTING", "COLD_MODIFYING", "HOT_MODIFYING": 403 return api.VM_RESUMING 404 case "PRE_MIGRATE", "HOT_MIGRATING", "COLD_MIGRATING": 405 return api.VM_MIGRATING 406 } 407 return strings.ToLower(self.Status) 408 } 409 410 func (i *SInstance) GetFullOsName() string { 411 return i.GuestOSInfo.Model 412 } 413 414 func (i *SInstance) GetOsType() cloudprovider.TOsType { 415 return cloudprovider.TOsType(i.GuestosType) 416 } 417 418 func (i *SInstance) GetOsArch() string { 419 return i.GetIHost().GetCpuArchitecture() 420 } 421 422 func (i *SInstance) getNormalizedOsInfo() *imagetools.ImageInfo { 423 if i.osInfo == nil { 424 osInfo := imagetools.NormalizeImageInfo(i.GuestOSInfo.Model, "", "", "", "") 425 i.osInfo = &osInfo 426 } 427 return i.osInfo 428 } 429 430 func (i *SInstance) GetOsDist() string { 431 return i.getNormalizedOsInfo().OsDistro 432 } 433 434 func (i *SInstance) GetOsVersion() string { 435 return i.getNormalizedOsInfo().OsVersion 436 } 437 438 func (i *SInstance) GetOsLang() string { 439 return i.getNormalizedOsInfo().OsLang 440 } 441 442 func (self *SInstance) GetProjectId() string { 443 return "" 444 } 445 446 func (self *SInstance) GetVNCInfo(input *cloudprovider.ServerVncInput) (*cloudprovider.ServerVncOutput, error) { 447 ret := &cloudprovider.ServerVncOutput{ 448 Protocol: "vnc", 449 Host: self.host.Name, 450 Port: self.VNCPort, 451 Id: self.Id, 452 Password: "1q@W3e$R", 453 } 454 return ret, nil 455 } 456 457 func (self *SInstance) GetVcpuCount() int { 458 return int(self.CPUNum) 459 } 460 461 func (self *SInstance) GetVmemSizeMB() int { 462 return int(self.Memory) 463 } 464 465 func (self *SInstance) GetVga() string { 466 return "std" 467 } 468 469 func (self *SInstance) GetVdi() string { 470 return "vnc" 471 } 472 473 func (self *SInstance) RebuildRoot(ctx context.Context, desc *cloudprovider.SManagedVMRebuildRootConfig) (string, error) { 474 return "", cloudprovider.ErrNotSupported 475 } 476 477 func (self *SInstance) GetSecurityGroupIds() ([]string, error) { 478 return []string{}, nil 479 } 480 481 func (self *SInstance) SetSecurityGroups(secgroupIds []string) error { 482 return cloudprovider.ErrNotSupported 483 } 484 485 func (self *SInstance) StartVM(ctx context.Context) error { 486 return self.host.zone.region.StartVm(self.Id, "", "") 487 } 488 489 func (self *SInstance) StopVM(ctx context.Context, opts *cloudprovider.ServerStopOptions) error { 490 if self.GetStatus() == api.VM_READY { 491 return nil 492 } 493 return self.host.zone.region.StopVm(self.Id) 494 } 495 496 func (self *SInstance) UpdateUserData(userData string) error { 497 return cloudprovider.ErrNotSupported 498 } 499 500 func (self *SInstance) UpdateVM(ctx context.Context, name string) error { 501 return cloudprovider.ErrNotSupported 502 } 503 504 func (self *SRegion) GetInstances(hostId string) ([]SInstance, error) { 505 ret := []SInstance{} 506 res := fmt.Sprintf("/hosts/%s/vms", hostId) 507 return ret, self.list(res, url.Values{}, &ret) 508 } 509 510 func (self *SRegion) GetInstance(id string) (*SInstance, error) { 511 ret := &SInstance{} 512 res := fmt.Sprintf("/vms/%s", id) 513 return ret, self.get(res, nil, ret) 514 } 515 516 func (self *SRegion) StartVm(id string, password, publicKey string) error { 517 res := fmt.Sprintf("/vms/%s", id) 518 params := url.Values{} 519 params.Set("action", "poweron") 520 if len(password) > 0 { 521 params.Set("os-passwd", password) 522 } 523 if len(publicKey) > 0 { 524 params.Set("publicKey", publicKey) 525 } 526 return self.put(res, params, nil, nil) 527 } 528 529 func (self *SRegion) StopVm(id string) error { 530 res := fmt.Sprintf("/vms/%s", id) 531 params := url.Values{} 532 params.Set("action", "poweroff") 533 return self.put(res, params, nil, nil) 534 } 535 536 func (self *SRegion) AttachDisk(vmId, diskId string) error { 537 disk, err := self.GetDisk(diskId) 538 if err != nil { 539 return errors.Wrapf(err, "GetDisk(%s)", diskId) 540 } 541 vm, err := self.GetInstance(vmId) 542 if err != nil { 543 return errors.Wrapf(err, "GetInstance(%s)", vmId) 544 } 545 vm.VNCPasswd = "" 546 diskInfo := Disks{ 547 BusModel: "VIRTIO", 548 ReadWriteModel: "NONE", 549 QueueNum: 1, 550 Volume: Volume{ 551 Id: disk.Id, 552 Size: disk.Size, 553 }, 554 } 555 vm.Disks = append(vm.Disks, diskInfo) 556 return self.put("/vms/"+vm.Id, nil, jsonutils.Marshal(vm), nil) 557 } 558 559 func (self *SRegion) DetachDisk(vmId, diskId string) error { 560 vm, err := self.GetInstance(vmId) 561 if err != nil { 562 return errors.Wrapf(err, "GetInstance(%s)", vmId) 563 } 564 vm.VNCPasswd = "" 565 disks := []Disks{} 566 for i := 0; i < len(vm.Disks); i++ { 567 if vm.Disks[i].Volume.Id == diskId { 568 continue 569 } 570 disks = append(disks, vm.Disks[i]) 571 } 572 vm.Disks = disks 573 return self.put("/vms/"+vm.Id, nil, jsonutils.Marshal(vm), nil) 574 } 575 576 func (self *SRegion) ChangeConfig(vmId string, cpu int, memMb int) error { 577 vm, err := self.GetInstance(vmId) 578 if err != nil { 579 return errors.Wrapf(err, "GetInstance(%s)", vmId) 580 } 581 vm.VNCPasswd = "" 582 changed := false 583 if cpu > 0 { 584 vm.CPUCore = 1 585 vm.CPUNum = cpu 586 vm.CPUSocket = cpu 587 changed = true 588 } 589 if memMb > 0 { 590 vm.Memory = memMb 591 changed = true 592 } 593 if !changed { 594 return nil 595 } 596 return self.put("/vms/"+vm.Id, nil, jsonutils.Marshal(vm), nil) 597 } 598 599 func (self *SRegion) ResetVmPassword(vmId string, username, password string) error { 600 params := url.Values{} 601 params.Set("action", "updateOsAuth") 602 body := map[string]interface{}{ 603 "userName": username, 604 "userPwd": password, 605 } 606 return self.put("/vms/"+vmId, params, jsonutils.Marshal(body), nil) 607 } 608 609 func (self *SRegion) DeleteVM(vmId string) error { 610 params := url.Values{} 611 params.Set("type", "force") 612 return self.del("/vms/"+vmId, params, nil) 613 }