yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/openstack/region.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 openstack 16 17 import ( 18 "fmt" 19 "io" 20 "net/url" 21 "time" 22 23 "yunion.io/x/jsonutils" 24 "yunion.io/x/pkg/errors" 25 26 api "yunion.io/x/cloudmux/pkg/apis/compute" 27 "yunion.io/x/cloudmux/pkg/cloudprovider" 28 "yunion.io/x/cloudmux/pkg/multicloud" 29 "yunion.io/x/onecloud/pkg/util/httputils" 30 ) 31 32 type SRegion struct { 33 multicloud.SRegion 34 35 client *SOpenStackClient 36 37 Name string 38 39 vpcs []SVpc 40 41 storageCache *SStoragecache 42 routers []SRouter 43 } 44 45 func (region *SRegion) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) { 46 backendGroups := []cloudprovider.ICloudLoadbalancerBackendGroup{} 47 pools, err := region.GetLoadbalancerPools() 48 if err != nil { 49 return backendGroups, errors.Wrap(err, "region.GetLoadbalancerPools()") 50 } 51 for i := 0; i < len(pools); i++ { 52 backendGroups = append(backendGroups, &pools[i]) 53 } 54 return backendGroups, nil 55 } 56 57 func (region *SRegion) GetClient() *SOpenStackClient { 58 return region.client 59 } 60 61 func (region *SRegion) GetId() string { 62 return region.Name 63 } 64 65 func (region *SRegion) GetName() string { 66 return fmt.Sprintf("%s-%s", region.client.cpcfg.Name, region.Name) 67 } 68 69 func (region *SRegion) GetI18n() cloudprovider.SModelI18nTable { 70 table := cloudprovider.SModelI18nTable{} 71 table["name"] = cloudprovider.NewSModelI18nEntry(region.GetName()).CN(region.GetName()) 72 return table 73 } 74 75 func (region *SRegion) GetGlobalId() string { 76 return fmt.Sprintf("%s/%s/%s", CLOUD_PROVIDER_OPENSTACK, region.client.cpcfg.Id, region.Name) 77 } 78 79 func (region *SRegion) IsEmulated() bool { 80 return false 81 } 82 83 func (region *SRegion) GetProvider() string { 84 return CLOUD_PROVIDER_OPENSTACK 85 } 86 87 func (region *SRegion) GetCloudEnv() string { 88 return "" 89 } 90 91 func (region *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo { 92 return cloudprovider.SGeographicInfo{} 93 } 94 95 func (region *SRegion) GetStatus() string { 96 return api.CLOUD_REGION_STATUS_INSERVER 97 } 98 99 func (region *SRegion) Refresh() error { 100 // do nothing 101 return nil 102 } 103 104 func (region *SRegion) GetMaxVersion(service string) (string, error) { 105 return region.client.GetMaxVersion(region.Name, service) 106 } 107 108 func (region *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) { 109 vpc, err := region.CreateVpc(opts.NAME, opts.Desc) 110 if err != nil { 111 return nil, errors.Wrap(err, "CreateVp") 112 } 113 return vpc, nil 114 } 115 116 func (region *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) { 117 izones, err := region.GetIZones() 118 if err != nil { 119 return nil, err 120 } 121 for i := 0; i < len(izones); i++ { 122 ihost, err := izones[i].GetIHostById(id) 123 if err == nil { 124 return ihost, nil 125 } else if errors.Cause(err) != cloudprovider.ErrNotFound { 126 return nil, err 127 } 128 } 129 return nil, cloudprovider.ErrNotFound 130 } 131 132 func (region *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { 133 izones, err := region.GetIZones() 134 if err != nil { 135 return nil, err 136 } 137 for i := 0; i < len(izones); i++ { 138 istore, err := izones[i].GetIStorageById(id) 139 if err == nil { 140 return istore, nil 141 } else if errors.Cause(err) != cloudprovider.ErrNotFound { 142 return nil, err 143 } 144 } 145 return nil, cloudprovider.ErrNotFound 146 } 147 148 func (region *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) { 149 iHosts := []cloudprovider.ICloudHost{} 150 izones, err := region.GetIZones() 151 if err != nil { 152 return nil, err 153 } 154 for i := 0; i < len(izones); i++ { 155 iZoneHost, err := izones[i].GetIHosts() 156 if err != nil { 157 return nil, err 158 } 159 iHosts = append(iHosts, iZoneHost...) 160 } 161 return iHosts, nil 162 } 163 164 func (region *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) { 165 izones, err := region.GetIZones() 166 if err != nil { 167 return nil, err 168 } 169 iStorages := []cloudprovider.ICloudStorage{} 170 for i := 0; i < len(izones); i++ { 171 iZoneStores, err := izones[i].GetIStorages() 172 if err != nil { 173 return nil, err 174 } 175 iStorages = append(iStorages, iZoneStores...) 176 } 177 return iStorages, nil 178 } 179 180 func (region *SRegion) getStoragecache() *SStoragecache { 181 if region.storageCache == nil { 182 region.storageCache = &SStoragecache{region: region} 183 } 184 return region.storageCache 185 } 186 187 func (region *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) { 188 storageCache := region.getStoragecache() 189 if storageCache.GetGlobalId() == id { 190 return region.storageCache, nil 191 } 192 return nil, cloudprovider.ErrNotFound 193 } 194 195 func (region *SRegion) GetIStoragecaches() ([]cloudprovider.ICloudStoragecache, error) { 196 storageCache := region.getStoragecache() 197 return []cloudprovider.ICloudStoragecache{storageCache}, nil 198 } 199 200 func (region *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) { 201 instance, err := region.GetInstance(id) 202 if err != nil { 203 return nil, errors.Wrapf(err, "GetInstance(%s)", id) 204 } 205 hosts, err := region.GetIHosts() 206 if err != nil { 207 return nil, err 208 } 209 for i := range hosts { 210 host := hosts[i].(*SHypervisor) 211 if instance.HypervisorHostname == host.HypervisorHostname { 212 instance.host = host 213 } 214 } 215 return instance, nil 216 } 217 218 func (region *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) { 219 disk, err := region.GetDisk(id) 220 if err != nil { 221 _, err := region.GetInstance(id) 222 if err == nil { 223 return &SNovaDisk{region: region, instanceId: id}, nil 224 } 225 return nil, errors.Wrapf(err, "GetDisk(%s)", id) 226 } 227 return disk, nil 228 } 229 230 func (region *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) { 231 vpc, err := region.GetVpc(id) 232 if err != nil { 233 return nil, errors.Wrapf(err, "GetVpc(%s)", id) 234 } 235 return vpc, nil 236 } 237 238 func (region *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) { 239 izones, err := region.GetIZones() 240 if err != nil { 241 return nil, errors.Wrap(err, "GetIZones") 242 } 243 for i := 0; i < len(izones); i++ { 244 if izones[i].GetGlobalId() == id { 245 return izones[i], nil 246 } 247 } 248 return nil, cloudprovider.ErrNotFound 249 } 250 251 func (region *SRegion) GetZones() ([]SZone, error) { 252 zones, err := region.getZones() 253 if err != nil { 254 return nil, errors.Wrap(err, "getZones") 255 } 256 ret := []SZone{} 257 for i := 0; i < len(zones); i++ { 258 if zones[i].ZoneName == "internal" { 259 continue 260 } 261 zones[i].region = region 262 ret = append(ret, zones[i]) 263 } 264 return ret, nil 265 } 266 267 func (region *SRegion) fetchVpcs() error { 268 if len(region.vpcs) > 0 { 269 return nil 270 } 271 var err error 272 region.vpcs, err = region.GetVpcs("") 273 if err != nil { 274 return errors.Wrap(err, "GetVpcs") 275 } 276 return nil 277 } 278 279 func (region *SRegion) ecsList(resource string, query url.Values) (jsonutils.JSONObject, error) { 280 return region.client.ecsRequest(region.Name, httputils.GET, resource, query, nil) 281 } 282 283 func (region *SRegion) ecsGet(resource string) (jsonutils.JSONObject, error) { 284 return region.client.ecsRequest(region.Name, httputils.GET, resource, nil, nil) 285 } 286 287 func (region *SRegion) ecsUpdate(resource string, params interface{}) (jsonutils.JSONObject, error) { 288 return region.client.ecsRequest(region.Name, httputils.PUT, resource, nil, params) 289 } 290 291 func (region *SRegion) ecsPost(resource string, params interface{}) (jsonutils.JSONObject, error) { 292 return region.client.ecsRequest(region.Name, httputils.POST, resource, nil, params) 293 } 294 295 func (region *SRegion) ecsDo(projectId, resource string, params interface{}) (jsonutils.JSONObject, error) { 296 return region.client.ecsDo(projectId, region.Name, resource, params) 297 } 298 299 func (region *SRegion) ecsDelete(resource string) (jsonutils.JSONObject, error) { 300 return region.client.ecsRequest(region.Name, httputils.DELETE, resource, nil, nil) 301 } 302 303 func (region *SRegion) ecsCreate(projectId, resource string, params interface{}) (jsonutils.JSONObject, error) { 304 return region.client.ecsCreate(projectId, region.Name, resource, params) 305 } 306 307 func (region *SRegion) vpcList(resource string, query url.Values) (jsonutils.JSONObject, error) { 308 return region.client.vpcRequest(region.Name, httputils.GET, resource, query, nil) 309 } 310 311 func (region *SRegion) vpcGet(resource string) (jsonutils.JSONObject, error) { 312 return region.client.vpcRequest(region.Name, httputils.GET, resource, nil, nil) 313 } 314 315 func (region *SRegion) vpcUpdate(resource string, params interface{}) (jsonutils.JSONObject, error) { 316 return region.client.vpcRequest(region.Name, httputils.PUT, resource, nil, params) 317 } 318 319 func (region *SRegion) vpcPost(resource string, params interface{}) (jsonutils.JSONObject, error) { 320 return region.client.vpcRequest(region.Name, httputils.POST, resource, nil, params) 321 } 322 323 func (region *SRegion) vpcDelete(resource string) (jsonutils.JSONObject, error) { 324 return region.client.vpcRequest(region.Name, httputils.DELETE, resource, nil, nil) 325 } 326 327 func (region *SRegion) imageList(resource string, query url.Values) (jsonutils.JSONObject, error) { 328 return region.client.imageRequest(region.Name, httputils.GET, resource, query, nil) 329 } 330 331 func (region *SRegion) imageGet(resource string) (jsonutils.JSONObject, error) { 332 return region.client.imageRequest(region.Name, httputils.GET, resource, nil, nil) 333 } 334 335 func (region *SRegion) imagePost(resource string, params interface{}) (jsonutils.JSONObject, error) { 336 return region.client.imageRequest(region.Name, httputils.POST, resource, nil, params) 337 } 338 339 func (region *SRegion) imageDelete(resource string) (jsonutils.JSONObject, error) { 340 return region.client.imageRequest(region.Name, httputils.DELETE, resource, nil, nil) 341 } 342 343 func (region *SRegion) imageUpload(url string, size int64, body io.Reader, callback func(progress float32)) error { 344 resp, err := region.client.imageUpload(region.Name, url, size, body, callback) 345 _, _, err = httputils.ParseResponse("", resp, err, region.client.debug) 346 return err 347 } 348 349 // Block Storage 350 func (region *SRegion) bsList(resource string, query url.Values) (jsonutils.JSONObject, error) { 351 return region.client.bsRequest(region.Name, httputils.GET, resource, query, nil) 352 } 353 354 func (region *SRegion) bsGet(resource string) (jsonutils.JSONObject, error) { 355 return region.client.bsRequest(region.Name, httputils.GET, resource, nil, nil) 356 } 357 358 func (region *SRegion) bsUpdate(resource string, params interface{}) (jsonutils.JSONObject, error) { 359 return region.client.bsRequest(region.Name, httputils.PUT, resource, nil, params) 360 } 361 362 func (region *SRegion) bsPost(resource string, params interface{}) (jsonutils.JSONObject, error) { 363 return region.client.bsRequest(region.Name, httputils.POST, resource, nil, params) 364 } 365 366 func (region *SRegion) bsDelete(resource string) (jsonutils.JSONObject, error) { 367 return region.client.bsRequest(region.Name, httputils.DELETE, resource, nil, nil) 368 } 369 370 func (region *SRegion) bsCreate(projectId, resource string, params interface{}) (jsonutils.JSONObject, error) { 371 return region.client.bsCreate(projectId, region.Name, resource, params) 372 } 373 374 //loadbalancer 375 376 func (region *SRegion) lbList(resource string, query url.Values) (jsonutils.JSONObject, error) { 377 return region.client.lbRequest(region.Name, httputils.GET, resource, query, nil) 378 } 379 380 func (region *SRegion) lbGet(resource string) (jsonutils.JSONObject, error) { 381 return region.client.lbRequest(region.Name, httputils.GET, resource, nil, nil) 382 } 383 384 func (region *SRegion) lbUpdate(resource string, params interface{}) (jsonutils.JSONObject, error) { 385 return region.client.lbRequest(region.Name, httputils.PUT, resource, nil, params) 386 } 387 388 func (region *SRegion) lbPost(resource string, params interface{}) (jsonutils.JSONObject, error) { 389 return region.client.lbRequest(region.Name, httputils.POST, resource, nil, params) 390 } 391 392 func (region *SRegion) lbDelete(resource string) (jsonutils.JSONObject, error) { 393 return region.client.lbRequest(region.Name, httputils.DELETE, resource, nil, nil) 394 } 395 396 func (region *SRegion) ProjectId() string { 397 return region.client.tokenCredential.GetProjectId() 398 } 399 400 func (region *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) { 401 zones, err := region.GetZones() 402 if err != nil { 403 return nil, errors.Wrapf(err, "GetZones") 404 } 405 ret := []cloudprovider.ICloudZone{} 406 for i := range zones { 407 ret = append(ret, &zones[i]) 408 } 409 return ret, nil 410 } 411 412 func (region *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) { 413 err := region.fetchVpcs() 414 if err != nil { 415 return nil, errors.Wrap(err, "fetchVpcs") 416 } 417 ivpcs := []cloudprovider.ICloudVpc{} 418 for i := range region.vpcs { 419 region.vpcs[i].region = region 420 ivpcs = append(ivpcs, ®ion.vpcs[i]) 421 } 422 return ivpcs, nil 423 } 424 425 func (region *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) { 426 eips, err := region.GetEips("") 427 if err != nil { 428 return nil, err 429 } 430 ieips := []cloudprovider.ICloudEIP{} 431 for i := 0; i < len(eips); i++ { 432 eips[i].region = region 433 ieips = append(ieips, &eips[i]) 434 } 435 return ieips, nil 436 } 437 438 func (region *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) { 439 network, err := region.GetNetwork(eip.NetworkExternalId) 440 if err != nil { 441 return nil, errors.Wrapf(err, "GetNetwork(%s)", eip.NetworkExternalId) 442 } 443 ieip, err := region.CreateEip(network.NetworkId, eip.NetworkExternalId, eip.IP, eip.ProjectId) 444 if err != nil { 445 return nil, errors.Wrap(err, "CreateEip") 446 } 447 return ieip, nil 448 } 449 450 func (region *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) { 451 return region.GetEip(eipId) 452 } 453 454 func (region *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) { 455 loadbalancers := []cloudprovider.ICloudLoadbalancer{} 456 sloadbalancers, err := region.GetLoadbalancers() 457 if err != nil { 458 return nil, errors.Wrap(err, "region.GetLoadbalancers()") 459 } 460 for i := 0; i < len(sloadbalancers); i++ { 461 loadbalancers = append(loadbalancers, &sloadbalancers[i]) 462 } 463 return loadbalancers, nil 464 } 465 466 func (region *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) { 467 sloadbalancer, err := region.GetLoadbalancerbyId(loadbalancerId) 468 if err != nil { 469 return nil, errors.Wrapf(err, "region.GetLoadbalancerbyId(%s)", loadbalancerId) 470 } 471 return sloadbalancer, nil 472 } 473 474 func (region *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) { 475 return region.GetLoadbalancerAclDetail(aclId) 476 } 477 478 func (region *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) { 479 return nil, cloudprovider.ErrNotImplemented 480 } 481 482 func (region *SRegion) CreateILoadBalancerCertificate(cert *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) { 483 return nil, cloudprovider.ErrNotImplemented 484 } 485 486 func (region *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) { 487 iloadbalancerAcls := []cloudprovider.ICloudLoadbalancerAcl{} 488 acls, err := region.GetLoadBalancerAcls() 489 if err != nil { 490 return nil, errors.Wrap(err, "region.GetLoadBalancerAcls") 491 } 492 for i := 0; i < len(acls); i++ { 493 iloadbalancerAcls = append(iloadbalancerAcls, &acls[i]) 494 } 495 return iloadbalancerAcls, nil 496 } 497 498 func (region *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) { 499 return nil, cloudprovider.ErrNotImplemented 500 } 501 502 func (region *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancer) (cloudprovider.ICloudLoadbalancer, error) { 503 sloadbalancer, err := region.CreateLoadBalancer(loadbalancer) 504 if err != nil { 505 return nil, errors.Wrap(err, "region.CreateLoadBalancer") 506 } 507 return sloadbalancer, nil 508 } 509 510 func (region *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) { 511 sacl, err := region.CreateLoadBalancerAcl(acl) 512 if err != nil { 513 return nil, errors.Wrap(err, "region.CreateLoadBalancerAcl(acl)") 514 } 515 err = cloudprovider.WaitMultiStatus(sacl.listener, []string{api.LB_STATUS_ENABLED, api.LB_STATUS_UNKNOWN}, 10*time.Second, 8*time.Minute) 516 if err != nil { 517 return nil, errors.Wrap(err, "cloudprovider.WaitMultiStatus") 518 } 519 if sacl.listener.GetStatus() == api.LB_STATUS_UNKNOWN { 520 return nil, errors.Wrap(fmt.Errorf("status error"), "check status") 521 } 522 return sacl, nil 523 } 524 525 func (region *SRegion) GetISkus() ([]cloudprovider.ICloudSku, error) { 526 flavors, err := region.GetFlavors() 527 if err != nil { 528 return nil, err 529 } 530 iskus := make([]cloudprovider.ICloudSku, len(flavors)) 531 for i := 0; i < len(flavors); i++ { 532 flavors[i].region = region 533 iskus[i] = &flavors[i] 534 } 535 return iskus, nil 536 } 537 538 func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) { 539 return nil, cloudprovider.ErrNotImplemented 540 } 541 542 func (region *SRegion) CreateIBucket(name string, storageClassStr string, acl string) error { 543 return cloudprovider.ErrNotImplemented 544 } 545 546 func (region *SRegion) DeleteIBucket(name string) error { 547 return cloudprovider.ErrNotImplemented 548 } 549 550 func (region *SRegion) IBucketExist(name string) (bool, error) { 551 return false, cloudprovider.ErrNotImplemented 552 } 553 554 func (region *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket, error) { 555 return nil, cloudprovider.ErrNotImplemented 556 } 557 558 func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) { 559 return nil, cloudprovider.ErrNotImplemented 560 } 561 562 func (region *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) { 563 return region.GetSecurityGroup(secgroupId) 564 } 565 566 func (region *SRegion) GetISecurityGroupByName(opts *cloudprovider.SecurityGroupFilterOptions) (cloudprovider.ICloudSecurityGroup, error) { 567 secgroups, err := region.GetSecurityGroups(opts.ProjectId, opts.Name) 568 if err != nil { 569 return nil, err 570 } 571 if len(secgroups) == 0 { 572 return nil, cloudprovider.ErrNotFound 573 } 574 if len(secgroups) > 1 { 575 return nil, cloudprovider.ErrDuplicateId 576 } 577 secgroups[0].region = region 578 return &secgroups[0], nil 579 } 580 581 func (region *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) { 582 return region.CreateSecurityGroup(conf.ProjectId, conf.Name, conf.Desc) 583 } 584 585 func (region *SRegion) GetCapabilities() []string { 586 return region.client.GetCapabilities() 587 } 588 589 func (region *SRegion) GetRouters() ([]SRouter, error) { 590 resource := "/v2.0/routers" 591 resp, err := region.vpcList(resource, nil) 592 if err != nil { 593 return nil, errors.Wrap(err, "vpcList.routes") 594 } 595 routers := []SRouter{} 596 err = resp.Unmarshal(&routers, "routers") 597 if err != nil { 598 return nil, errors.Wrap(err, "resp.Unmarshal") 599 } 600 for i := 0; i < len(routers); i++ { 601 ports, err := region.GetPorts("", routers[i].Id) 602 if err != nil { 603 return nil, errors.Wrap(err, "vpc.region.GetPortsByDeviceId") 604 } 605 routers[i].ports = ports 606 } 607 return routers, nil 608 } 609 610 func (region *SRegion) fetchrouters() error { 611 if len(region.routers) > 0 { 612 return nil 613 } 614 routers, err := region.GetRouters() 615 if err != nil { 616 return errors.Wrap(err, "region.GetRouters()") 617 } 618 region.routers = routers 619 return nil 620 }