yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/jdcloud/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 jdcloud 16 17 import ( 18 "context" 19 "fmt" 20 "time" 21 22 commodels "github.com/jdcloud-api/jdcloud-sdk-go/services/common/models" 23 "github.com/jdcloud-api/jdcloud-sdk-go/services/vm/apis" 24 "github.com/jdcloud-api/jdcloud-sdk-go/services/vm/client" 25 "github.com/jdcloud-api/jdcloud-sdk-go/services/vm/models" 26 27 "yunion.io/x/log" 28 "yunion.io/x/pkg/errors" 29 "yunion.io/x/pkg/util/sets" 30 31 napis "yunion.io/x/cloudmux/pkg/apis" 32 api "yunion.io/x/cloudmux/pkg/apis/compute" 33 "yunion.io/x/cloudmux/pkg/cloudprovider" 34 "yunion.io/x/cloudmux/pkg/multicloud" 35 "yunion.io/x/onecloud/pkg/util/billing" 36 ) 37 38 type SInstance struct { 39 multicloud.SInstanceBase 40 multicloud.SBillingBase 41 JdcloudTags 42 43 host *SHost 44 image *SImage 45 46 models.Instance 47 48 instanceType *SInstanceType 49 } 50 51 func (i *SInstance) GetBillingType() string { 52 return billingType(&i.Charge) 53 } 54 55 func (i *SInstance) GetExpiredAt() time.Time { 56 return expireAt(&i.Charge) 57 } 58 59 func (i *SInstance) GetId() string { 60 return i.InstanceId 61 } 62 63 func (i *SInstance) GetName() string { 64 return i.InstanceName 65 } 66 67 func (i *SInstance) GetHostname() string { 68 return i.Hostname 69 } 70 71 func (i *SInstance) GetGlobalId() string { 72 return i.GetId() 73 } 74 75 func (i *SInstance) GetStatus() string { 76 switch i.Status { 77 case "pending": 78 return api.VM_DEPLOYING 79 case "starting": 80 return api.VM_STARTING 81 case "running": 82 return api.VM_RUNNING 83 case "stopping": 84 return api.VM_STOPPING 85 case "stopped": 86 return api.VM_READY 87 case "reboot": 88 return api.VM_STARTING 89 case "rebuilding": 90 return api.VM_REBUILD_ROOT 91 case "resizing": 92 return api.VM_CHANGE_FLAVOR 93 case "deleting": 94 return api.VM_DELETING 95 default: 96 return api.VM_UNKNOWN 97 } 98 } 99 100 func (i *SInstance) Refresh() error { 101 return nil 102 } 103 104 func (i *SInstance) IsEmulated() bool { 105 return false 106 } 107 108 func (i *SInstance) GetBootOrder() string { 109 return "dcn" 110 } 111 112 func (i *SInstance) GetVga() string { 113 return "std" 114 } 115 116 func (i *SInstance) GetVdi() string { 117 return "vnc" 118 } 119 120 func (i *SInstance) GetImage() (*SImage, error) { 121 if i.image != nil { 122 return i.image, nil 123 } 124 image, err := i.host.zone.region.GetImage(i.ImageId) 125 if err != nil { 126 return nil, err 127 } 128 i.image = image 129 return i.image, nil 130 } 131 132 func (i *SInstance) GetOsType() cloudprovider.TOsType { 133 image, err := i.GetImage() 134 if err != nil { 135 return cloudprovider.OsTypeLinux 136 } 137 return image.GetOsType() 138 } 139 140 func (i *SInstance) GetFullOsName() string { 141 image, err := i.GetImage() 142 if err != nil { 143 return "" 144 } 145 return image.GetFullOsName() 146 } 147 148 func (i *SInstance) GetBios() cloudprovider.TBiosType { 149 image, err := i.GetImage() 150 if err != nil { 151 return cloudprovider.BIOS 152 } 153 return image.GetBios() 154 } 155 156 func (i *SInstance) GetOsArch() string { 157 image, err := i.GetImage() 158 if err != nil { 159 return napis.OS_ARCH_X86_64 160 } 161 return image.GetOsArch() 162 } 163 164 func (i *SInstance) GetOsDist() string { 165 image, err := i.GetImage() 166 if err != nil { 167 return "" 168 } 169 return image.GetOsDist() 170 } 171 172 func (i *SInstance) GetOsVersion() string { 173 image, err := i.GetImage() 174 if err != nil { 175 return "" 176 } 177 return image.GetOsVersion() 178 } 179 180 func (i *SInstance) GetOsLang() string { 181 image, err := i.GetImage() 182 if err != nil { 183 return "" 184 } 185 return image.GetOsLang() 186 } 187 188 func (i *SInstance) GetMachine() string { 189 return "pc" 190 } 191 192 func (i *SInstance) GetInstanceType() string { 193 return i.InstanceType 194 } 195 196 func (in *SInstance) GetProjectId() string { 197 return "" 198 } 199 200 func (in *SInstance) GetIHost() cloudprovider.ICloudHost { 201 return in.host 202 } 203 204 func (in *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) { 205 disks := make([]cloudprovider.ICloudDisk, 0, len(in.DataDisks)+1) 206 if in.SystemDisk.DiskCategory != "local" { 207 disk := &SDisk{ 208 Disk: in.SystemDisk.CloudDisk, 209 ImageId: in.ImageId, 210 IsSystemDisk: true, 211 } 212 stroage, err := in.host.zone.getStorageByType(disk.DiskType) 213 if err != nil { 214 return nil, errors.Wrapf(err, "unable to find storage with type %s", disk.DiskType) 215 } 216 disk.storage = stroage 217 disks = append(disks, disk) 218 } 219 for i := range in.DataDisks { 220 disk := &SDisk{ 221 Disk: in.DataDisks[i].CloudDisk, 222 } 223 stroage, err := in.host.zone.getStorageByType(disk.DiskType) 224 if err != nil { 225 return nil, errors.Wrapf(err, "unable to find storage with type %s", disk.DiskType) 226 } 227 disk.storage = stroage 228 disks = append(disks, disk) 229 } 230 return disks, nil 231 } 232 233 func (in *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) { 234 nis := make([]cloudprovider.ICloudNic, 0, len(in.SecondaryNetworkInterfaces)+1) 235 nis = append(nis, &SInstanceNic{ 236 instance: in, 237 InstanceNetworkInterface: in.PrimaryNetworkInterface.NetworkInterface, 238 }) 239 for i := range in.SecondaryNetworkInterfaces { 240 nis = append(nis, &SInstanceNic{ 241 instance: in, 242 InstanceNetworkInterface: in.SecondaryNetworkInterfaces[i].NetworkInterface, 243 }) 244 } 245 return nis, nil 246 } 247 248 func (in *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) { 249 eip, err := in.host.zone.region.GetEIPById(in.ElasticIpId) 250 if err != nil { 251 return nil, err 252 } 253 return eip, nil 254 } 255 256 func (in *SInstance) GetSecurityGroupIds() ([]string, error) { 257 ids := sets.NewString() 258 for _, sg := range in.PrimaryNetworkInterface.NetworkInterface.SecurityGroups { 259 ids.Insert(sg.GroupId) 260 } 261 for i := range in.SecondaryNetworkInterfaces { 262 for _, sg := range in.SecondaryNetworkInterfaces[i].NetworkInterface.SecurityGroups { 263 ids.Insert(sg.GroupId) 264 } 265 } 266 return ids.UnsortedList(), nil 267 } 268 269 func (in *SInstance) fetchInstanceType() error { 270 its, err := in.host.zone.region.InstanceTypes(in.InstanceType) 271 if err != nil { 272 return err 273 } 274 if len(its) == 0 { 275 return cloudprovider.ErrNotFound 276 } 277 for i := range its { 278 if its[i].InstanceType.InstanceType == in.InstanceType { 279 in.instanceType = &its[i] 280 return nil 281 } 282 } 283 return cloudprovider.ErrNotFound 284 } 285 286 func (in *SInstance) GetVcpuCount() int { 287 if in.instanceType == nil { 288 err := in.fetchInstanceType() 289 if err != nil { 290 log.Errorf("unable to get instance type %s: %v", in.InstanceType, err) 291 return 0 292 } 293 } 294 return in.instanceType.GetCpu() 295 } 296 297 func (in *SInstance) GetVmemSizeMB() int { 298 if in.instanceType == nil { 299 err := in.fetchInstanceType() 300 if err != nil { 301 log.Errorf("unable to get instance type %s", in.InstanceType) 302 return 0 303 } 304 } 305 return in.instanceType.GetMemoryMB() 306 } 307 308 func (in *SInstance) AssignSecurityGroup(id string) error { 309 return cloudprovider.ErrNotImplemented 310 } 311 312 func (in *SInstance) SetSecurityGroups(ids []string) error { 313 return cloudprovider.ErrNotImplemented 314 } 315 316 func (in *SInstance) GetHypervisor() string { 317 return api.HYPERVISOR_JDCLOUD 318 } 319 320 func (in *SInstance) StartVM(ctx context.Context) error { 321 return cloudprovider.ErrNotImplemented 322 } 323 324 func (in *SInstance) StopVM(ctx context.Context, opts *cloudprovider.ServerStopOptions) error { 325 return cloudprovider.ErrNotImplemented 326 } 327 328 func (in *SInstance) DeleteVM(ctx context.Context) error { 329 return cloudprovider.ErrNotImplemented 330 } 331 332 func (in *SInstance) UpdateVM(ctx context.Context, name string) error { 333 return cloudprovider.ErrNotSupported 334 } 335 336 func (in *SInstance) UpdateUserData(userData string) error { 337 return cloudprovider.ErrNotSupported 338 } 339 340 func (self *SInstance) RebuildRoot(ctx context.Context, config *cloudprovider.SManagedVMRebuildRootConfig) (string, error) { 341 return "", cloudprovider.ErrNotImplemented 342 } 343 344 func (self *SInstance) DeployVM(ctx context.Context, name string, username string, password string, publicKey string, deleteKeypair bool, description string) error { 345 return cloudprovider.ErrNotImplemented 346 } 347 348 func (in *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.SManagedVMChangeConfig) error { 349 return cloudprovider.ErrNotImplemented 350 } 351 352 func (in *SInstance) GetVNCInfo(input *cloudprovider.ServerVncInput) (*cloudprovider.ServerVncOutput, error) { 353 region := in.host.zone.region 354 req := apis.NewDescribeInstanceVncUrlRequest(region.ID, in.InstanceId) 355 client := client.NewVmClient(region.getCredential()) 356 client.Logger = Logger{debug: region.client.debug} 357 resp, err := client.DescribeInstanceVncUrl(req) 358 if err != nil { 359 return nil, err 360 } 361 362 ret := &cloudprovider.ServerVncOutput{ 363 Url: resp.Result.VncUrl, 364 Protocol: "jdcloud", 365 InstanceId: in.GetId(), 366 Hypervisor: api.HYPERVISOR_JDCLOUD, 367 } 368 return ret, nil 369 } 370 371 func (in *SInstance) AttachDisk(ctx context.Context, diskId string) error { 372 return cloudprovider.ErrNotImplemented 373 } 374 375 func (in *SInstance) DetachDisk(ctx context.Context, diskId string) error { 376 return cloudprovider.ErrNotImplemented 377 } 378 379 func (self *SInstance) Renew(bc billing.SBillingCycle) error { 380 return cloudprovider.ErrNotImplemented 381 } 382 383 func (self *SInstance) GetError() error { 384 return nil 385 } 386 387 func (r *SRegion) GetInstances(zoneId string, ids []string, pangeNumber, pageSize int) ([]SInstance, int, error) { 388 filters := []commodels.Filter{} 389 if zoneId != "" { 390 filters = append(filters, commodels.Filter{ 391 Name: "az", 392 Values: []string{zoneId}, 393 }) 394 } 395 if len(ids) > 0 { 396 filters = append(filters, commodels.Filter{ 397 Name: "instanceId", 398 Values: ids, 399 }) 400 } 401 req := apis.NewDescribeInstancesRequestWithAllParams(r.ID, &pangeNumber, &pageSize, filters) 402 client := client.NewVmClient(r.getCredential()) 403 client.Logger = Logger{debug: r.client.debug} 404 resp, err := client.DescribeInstances(req) 405 if err != nil { 406 return nil, 0, err 407 } 408 if resp.Error.Code >= 400 { 409 return nil, 0, fmt.Errorf(resp.Error.Message) 410 } 411 ins := make([]SInstance, len(resp.Result.Instances)) 412 for i := range ins { 413 ins[i] = SInstance{ 414 Instance: resp.Result.Instances[i], 415 } 416 } 417 return ins, resp.Result.TotalCount, nil 418 } 419 420 func (r *SRegion) GetInstanceById(id string) (*SInstance, error) { 421 req := apis.NewDescribeInstanceRequest(r.ID, id) 422 client := client.NewVmClient(r.getCredential()) 423 client.Logger = Logger{debug: r.client.debug} 424 resp, err := client.DescribeInstance(req) 425 if err != nil { 426 return nil, err 427 } 428 return &SInstance{ 429 Instance: resp.Result.Instance, 430 }, nil 431 } 432 433 func (r *SRegion) FillHost(instance *SInstance) { 434 izone, err := r.getIZoneByRealId(instance.Az) 435 if err != nil { 436 log.Errorf("unable to find zone %s: %v", instance.Az, err) 437 return 438 } 439 zone := izone.(*SZone) 440 instance.host = &SHost{ 441 zone: zone, 442 } 443 }