yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/ctyun/host.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 ctyun
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  	"time"
    21  
    22  	"yunion.io/x/jsonutils"
    23  	"yunion.io/x/pkg/errors"
    24  
    25  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    26  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    27  	"yunion.io/x/cloudmux/pkg/multicloud"
    28  )
    29  
    30  type SHost struct {
    31  	multicloud.SHostBase
    32  	zone *SZone
    33  
    34  	projectId string
    35  }
    36  
    37  func (self *SHost) GetId() string {
    38  	return fmt.Sprintf("%s-%s", self.zone.region.client.cpcfg.Id, self.zone.GetId())
    39  }
    40  
    41  func (self *SHost) GetName() string {
    42  	return fmt.Sprintf("%s-%s", self.zone.region.client.cpcfg.Name, self.zone.GetId())
    43  }
    44  
    45  func (self *SHost) GetGlobalId() string {
    46  	return self.GetId()
    47  }
    48  
    49  func (self *SHost) GetStatus() string {
    50  	return api.HOST_STATUS_RUNNING
    51  }
    52  
    53  func (self *SHost) Refresh() error {
    54  	return nil
    55  }
    56  
    57  func (self *SHost) IsEmulated() bool {
    58  	return true
    59  }
    60  
    61  // http://ctyun-api-url/apiproxy/v3/ondemand/queryVMs
    62  func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
    63  	vms, err := self.zone.region.GetVMs()
    64  	if err != nil {
    65  		return nil, errors.Wrap(err, "SHost.GetVMs")
    66  	}
    67  
    68  	ivms := make([]cloudprovider.ICloudVM, len(vms))
    69  	for i := range vms {
    70  		ivms[i] = &vms[i]
    71  	}
    72  
    73  	return ivms, nil
    74  }
    75  
    76  // http://ctyun-api-url/apiproxy/v3/ondemand/queryVMDetail
    77  //  http://ctyun-api-url/apiproxy/v3/queryVMDetail
    78  func (self *SHost) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
    79  	return self.zone.region.GetIVMById(id)
    80  }
    81  
    82  func (self *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) {
    83  	return self.zone.GetIWires()
    84  }
    85  
    86  func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
    87  	return self.zone.GetIStorages()
    88  }
    89  
    90  func (self *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
    91  	return self.zone.GetIStorageById(id)
    92  }
    93  
    94  func (self *SHost) GetEnabled() bool {
    95  	return true
    96  }
    97  
    98  func (self *SHost) GetHostStatus() string {
    99  	return api.HOST_ONLINE
   100  }
   101  
   102  func (self *SHost) GetAccessIp() string {
   103  	return ""
   104  }
   105  
   106  func (self *SHost) GetAccessMac() string {
   107  	return ""
   108  }
   109  
   110  func (self *SHost) GetSysInfo() jsonutils.JSONObject {
   111  	info := jsonutils.NewDict()
   112  	info.Add(jsonutils.NewString(api.CLOUD_PROVIDER_CTYUN), "manufacture")
   113  	return info
   114  }
   115  
   116  func (self *SHost) GetSN() string {
   117  	return ""
   118  }
   119  
   120  func (self *SHost) GetCpuCount() int {
   121  	return 0
   122  }
   123  
   124  func (self *SHost) GetNodeCount() int8 {
   125  	return 0
   126  }
   127  
   128  func (self *SHost) GetCpuDesc() string {
   129  	return ""
   130  }
   131  
   132  func (self *SHost) GetCpuMhz() int {
   133  	return 0
   134  }
   135  
   136  func (self *SHost) GetMemSizeMB() int {
   137  	return 0
   138  }
   139  
   140  func (self *SHost) GetStorageSizeMB() int {
   141  	return 0
   142  }
   143  
   144  func (self *SHost) GetStorageType() string {
   145  	return api.DISK_TYPE_HYBRID
   146  }
   147  
   148  func (self *SHost) GetHostType() string {
   149  	return api.HOST_TYPE_CTYUN
   150  }
   151  
   152  func (self *SHost) GetIsMaintenance() bool {
   153  	return false
   154  }
   155  
   156  func (self *SHost) GetVersion() string {
   157  	return CTYUN_API_VERSION
   158  }
   159  
   160  func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
   161  	network, err := self.zone.region.GetNetwork(desc.ExternalNetworkId)
   162  	if err != nil {
   163  		return nil, errors.Wrap(err, "Host.CreateVM.GetNetwork")
   164  	}
   165  
   166  	//  镜像及硬盘配置
   167  	img, err := self.zone.region.GetImage(desc.ExternalImageId)
   168  	if err != nil {
   169  		return nil, errors.Wrap(err, "SHost.CreateVM.GetImage")
   170  	}
   171  
   172  	rootDiskSize := int(img.MinDisk)
   173  	if desc.SysDisk.SizeGB > rootDiskSize {
   174  		rootDiskSize = desc.SysDisk.SizeGB
   175  	}
   176  
   177  	jobId, err := self.zone.region.CreateInstance(self.zone.GetId(), desc.Name, desc.ExternalImageId, desc.OsType, desc.InstanceType, network.VpcID, desc.ExternalNetworkId, desc.ExternalSecgroupId, desc.Password, desc.SysDisk.StorageType, rootDiskSize, desc.DataDisks)
   178  	if err != nil {
   179  		return nil, errors.Wrap(err, "Host.CreateVM.CreateInstance")
   180  	}
   181  
   182  	vmId := ""
   183  	err = cloudprovider.Wait(10*time.Second, 600*time.Second, func() (b bool, err error) {
   184  		statusJson, err := self.zone.region.GetJob(jobId)
   185  		if err != nil {
   186  			if strings.Contains(err.Error(), "job fail") {
   187  				return false, err
   188  			}
   189  
   190  			return false, nil
   191  		}
   192  
   193  		if status, _ := statusJson.GetString("status"); status == "SUCCESS" {
   194  			jobs, err := statusJson.GetArray("entities", "sub_jobs")
   195  			if err != nil {
   196  				return false, err
   197  			}
   198  
   199  			if len(jobs) > 0 {
   200  				vmId, err = jobs[0].GetString("entities", "server_id")
   201  				if err != nil {
   202  					return false, err
   203  				}
   204  			} else {
   205  				return false, fmt.Errorf("CreateVM empty sub jobs")
   206  			}
   207  			return true, nil
   208  		} else if status == "FAILED" {
   209  			return false, fmt.Errorf("CreateVM job %s failed", jobId)
   210  		} else {
   211  			return false, nil
   212  		}
   213  	})
   214  	if err != nil {
   215  		return nil, errors.Wrap(err, "SHost.CreateVM.Wait")
   216  	}
   217  
   218  	return self.zone.region.GetVMById(vmId)
   219  }
   220  
   221  func (self *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) {
   222  	return nil, cloudprovider.ErrNotSupported
   223  }
   224  
   225  func (self *SRegion) getVMs(vmId string) ([]SInstance, error) {
   226  	params := map[string]string{
   227  		"regionId": self.GetId(),
   228  	}
   229  
   230  	if len(vmId) > 0 {
   231  		params["vmId"] = vmId
   232  	}
   233  
   234  	resp, err := self.client.DoGet("/apiproxy/v3/ondemand/queryVMs", params)
   235  	if err != nil {
   236  		return nil, errors.Wrap(err, "SRegion.getVMs.DoGet")
   237  	}
   238  
   239  	ret := make([]SInstance, 0)
   240  	err = resp.Unmarshal(&ret, "returnObj", "servers")
   241  	if err != nil {
   242  		return nil, errors.Wrap(err, "SRegion.getVMs.Unmarshal")
   243  	}
   244  
   245  	for i := range ret {
   246  		izone, err := self.GetIZoneById(getZoneGlobalId(self, ret[i].OSEXTAZAvailabilityZone))
   247  		if err != nil {
   248  			return nil, errors.Wrap(err, "SRegion.getVMs.GetIZoneById")
   249  		}
   250  
   251  		ret[i].host = &SHost{
   252  			zone: izone.(*SZone),
   253  		}
   254  	}
   255  
   256  	return ret, nil
   257  }
   258  
   259  func (self *SRegion) GetVMs() ([]SInstance, error) {
   260  	return self.getVMs("")
   261  }
   262  
   263  func (self *SRegion) GetVMById(vmId string) (*SInstance, error) {
   264  	if len(vmId) == 0 {
   265  		return nil, errors.Wrap(cloudprovider.ErrNotFound, "SRegion.GetVMById.EmptyVmID")
   266  	}
   267  
   268  	vms, err := self.getVMs(vmId)
   269  	if err != nil {
   270  		return nil, errors.Wrap(err, "SRegion.GetVMById")
   271  	}
   272  
   273  	if len(vms) == 0 {
   274  		return nil, errors.Wrap(cloudprovider.ErrNotFound, "SRegion.GetVMById")
   275  	} else if len(vms) == 1 {
   276  		izone, err := self.GetIZoneById(getZoneGlobalId(self, vms[0].OSEXTAZAvailabilityZone))
   277  		if err != nil {
   278  			return nil, errors.Wrap(err, "SRegion.GetVMById.GetIZoneById")
   279  		}
   280  
   281  		vms[0].host = &SHost{
   282  			zone: izone.(*SZone),
   283  		}
   284  		return &vms[0], nil
   285  	} else {
   286  		return nil, errors.Wrap(cloudprovider.ErrDuplicateId, "SRegion.GetVMById")
   287  	}
   288  }