yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/qcloud/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 qcloud 16 17 import ( 18 "fmt" 19 "strings" 20 21 "yunion.io/x/jsonutils" 22 "yunion.io/x/log" 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 "yunion.io/x/onecloud/pkg/util/billing" 29 ) 30 31 type SHost struct { 32 multicloud.SHostBase 33 zone *SZone 34 } 35 36 func (self *SHost) GetId() string { 37 return fmt.Sprintf("%s-%s", self.zone.region.client.cpcfg.Id, self.zone.GetId()) 38 } 39 40 func (self *SHost) GetName() string { 41 return fmt.Sprintf("%s-%s", self.zone.region.client.cpcfg.Name, self.zone.GetId()) 42 } 43 44 func (self *SHost) GetGlobalId() string { 45 return fmt.Sprintf("%s-%s", self.zone.region.client.cpcfg.Id, self.zone.GetId()) 46 } 47 48 func (self *SHost) GetInstanceById(instanceId string) (*SInstance, error) { 49 inst, err := self.zone.region.GetInstance(instanceId) 50 if err != nil { 51 return nil, err 52 } 53 inst.host = self 54 return inst, nil 55 } 56 57 func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) { 58 vmId, err := self._createVM(desc.Name, desc.Hostname, desc.ExternalImageId, 59 desc.SysDisk, desc.Cpu, desc.MemoryMB, 60 desc.InstanceType, desc.ExternalNetworkId, 61 desc.IpAddr, desc.Description, desc.Password, 62 desc.DataDisks, desc.PublicKey, desc.ExternalSecgroupId, 63 desc.UserData, desc.BillingCycle, desc.ProjectId, desc.PublicIpBw, desc.PublicIpChargeType, desc.Tags, desc.OsType) 64 if err != nil { 65 return nil, err 66 } 67 vm, err := self.GetInstanceById(vmId) 68 if err != nil { 69 return nil, err 70 } 71 return vm, err 72 } 73 74 func (self *SHost) _createVM(name, hostname string, imgId string, sysDisk cloudprovider.SDiskInfo, cpu int, memMB int, instanceType string, 75 networkId string, ipAddr string, desc string, passwd string, 76 diskSizes []cloudprovider.SDiskInfo, publicKey string, secgroupId string, userData string, bc *billing.SBillingCycle, projectId string, 77 publicIpBw int, publicIpChargeType cloudprovider.TElasticipChargeType, 78 tags map[string]string, osType string, 79 ) (string, error) { 80 net := self.zone.getNetworkById(networkId) 81 if net == nil { 82 return "", fmt.Errorf("invalid network ID %s", networkId) 83 } 84 85 var err error 86 87 keypair := "" 88 if len(publicKey) > 0 { 89 keypair, err = self.zone.region.syncKeypair(publicKey) 90 if err != nil { 91 return "", err 92 } 93 } 94 95 img, err := self.zone.region.GetImage(imgId) 96 if err != nil { 97 return "", errors.Wrapf(err, "GetImage(%s)", imgId) 98 } 99 if img.ImageState != ImageStatusNormal && img.ImageState != ImageStatusUsing { 100 return "", fmt.Errorf("image %s not ready status is %s", imgId, img.ImageState) 101 } 102 103 err = self.zone.validateStorageType(sysDisk.StorageType) 104 if err != nil { 105 return "", fmt.Errorf("Storage %s not avaiable: %s", sysDisk.StorageType, err) 106 } 107 108 disks := make([]SDisk, len(diskSizes)+1) 109 disks[0].DiskSize = img.ImageSize 110 if sysDisk.SizeGB > 0 && sysDisk.SizeGB > img.ImageSize { 111 disks[0].DiskSize = sysDisk.SizeGB 112 } 113 if disks[0].DiskSize < 50 { 114 disks[0].DiskSize = 50 115 } 116 disks[0].DiskType = strings.ToUpper(sysDisk.StorageType) 117 118 for i, dataDisk := range diskSizes { 119 disks[i+1].DiskSize = dataDisk.SizeGB 120 err = self.zone.validateStorageType(dataDisk.StorageType) 121 if err != nil { 122 return "", fmt.Errorf("Storage %s not avaiable: %s", dataDisk.StorageType, err) 123 } 124 disks[i+1].DiskType = strings.ToUpper(dataDisk.StorageType) 125 } 126 127 if len(instanceType) > 0 { 128 log.Debugf("Try instancetype : %s", instanceType) 129 vmId, err := self.zone.region.CreateInstance(name, hostname, imgId, instanceType, secgroupId, self.zone.Zone, desc, passwd, disks, networkId, ipAddr, keypair, userData, bc, projectId, publicIpBw, publicIpChargeType, tags, osType) 130 if err != nil { 131 return "", errors.Wrapf(err, "Failed to create specification %s", instanceType) 132 } 133 return vmId, nil 134 } 135 136 instanceTypes, err := self.zone.region.GetMatchInstanceTypes(cpu, memMB, 0, self.zone.Zone) 137 if err != nil { 138 return "", err 139 } 140 if len(instanceTypes) == 0 { 141 return "", fmt.Errorf("instance type %dC%dMB not avaiable", cpu, memMB) 142 } 143 144 var vmId string 145 for _, instType := range instanceTypes { 146 instanceTypeId := instType.InstanceType 147 log.Debugf("Try instancetype : %s", instanceTypeId) 148 vmId, err = self.zone.region.CreateInstance(name, hostname, imgId, instanceTypeId, secgroupId, self.zone.Zone, desc, passwd, disks, networkId, ipAddr, keypair, userData, bc, projectId, publicIpBw, publicIpChargeType, tags, osType) 149 if err != nil { 150 log.Errorf("Failed for %s: %s", instanceTypeId, err) 151 } else { 152 return vmId, nil 153 } 154 } 155 156 return "", fmt.Errorf("Failed to create, %s", err.Error()) 157 } 158 159 func (self *SHost) Refresh() error { 160 return nil 161 } 162 163 func (self *SHost) GetAccessIp() string { 164 return "" 165 } 166 167 func (self *SHost) GetAccessMac() string { 168 return "" 169 } 170 171 func (self *SHost) GetSN() string { 172 return "" 173 } 174 175 func (self *SHost) GetCpuCount() int { 176 return 0 177 } 178 179 func (self *SHost) GetNodeCount() int8 { 180 return 0 181 } 182 183 func (self *SHost) GetCpuDesc() string { 184 return "" 185 } 186 187 func (self *SHost) GetCpuMhz() int { 188 return 0 189 } 190 191 func (self *SHost) GetMemSizeMB() int { 192 return 0 193 } 194 195 func (self *SHost) GetStorageSizeMB() int { 196 return 0 197 } 198 199 func (self *SHost) GetEnabled() bool { 200 return true 201 } 202 203 func (self *SHost) GetStatus() string { 204 return api.HOST_STATUS_RUNNING 205 } 206 207 func (self *SHost) GetHostStatus() string { 208 return api.HOST_ONLINE 209 } 210 211 func (self *SHost) GetHostType() string { 212 return api.HOST_TYPE_QCLOUD 213 } 214 215 func (self *SHost) GetStorageType() string { 216 return api.DISK_TYPE_HYBRID 217 } 218 219 func (self *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { 220 return self.zone.GetIStorageById(id) 221 } 222 223 func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) { 224 return self.zone.GetIStorages() 225 } 226 227 func (self *SHost) GetIVMById(gid string) (cloudprovider.ICloudVM, error) { 228 if len(gid) == 0 { 229 return nil, cloudprovider.ErrNotFound 230 } 231 parts, _, err := self.zone.region.GetInstances(self.zone.Zone, []string{gid}, 0, 1) 232 if err != nil { 233 return nil, err 234 } 235 if len(parts) == 0 { 236 return nil, cloudprovider.ErrNotFound 237 } 238 if len(parts) > 1 { 239 return nil, cloudprovider.ErrDuplicateId 240 } 241 parts[0].host = self 242 return &parts[0], nil 243 } 244 245 func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) { 246 vms := make([]SInstance, 0) 247 for { 248 parts, total, err := self.zone.region.GetInstances(self.zone.Zone, nil, len(vms), 50) 249 if err != nil { 250 return nil, err 251 } 252 vms = append(vms, parts...) 253 if len(vms) >= total { 254 break 255 } 256 } 257 ivms := make([]cloudprovider.ICloudVM, len(vms)) 258 for i := 0; i < len(vms); i++ { 259 vms[i].host = self 260 ivms[i] = &vms[i] 261 } 262 return ivms, nil 263 } 264 265 func (self *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) { 266 return self.zone.GetIWires() 267 } 268 269 func (self *SHost) GetSysInfo() jsonutils.JSONObject { 270 info := jsonutils.NewDict() 271 info.Add(jsonutils.NewString(CLOUD_PROVIDER_QCLOUD), "manufacture") 272 return info 273 } 274 275 func (self *SHost) IsEmulated() bool { 276 return true 277 } 278 279 func (host *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) { 280 return nil, cloudprovider.ErrNotSupported 281 } 282 283 func (host *SHost) GetIsMaintenance() bool { 284 return false 285 } 286 287 func (host *SHost) GetVersion() string { 288 return QCLOUD_API_VERSION 289 }