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 }