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  }