yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aliyun/dbinstance.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 aliyun 16 17 import ( 18 "context" 19 "fmt" 20 "strings" 21 "time" 22 23 "yunion.io/x/jsonutils" 24 "yunion.io/x/log" 25 "yunion.io/x/pkg/errors" 26 "yunion.io/x/pkg/utils" 27 28 api "yunion.io/x/cloudmux/pkg/apis/compute" 29 "yunion.io/x/cloudmux/pkg/cloudprovider" 30 "yunion.io/x/cloudmux/pkg/multicloud" 31 "yunion.io/x/onecloud/pkg/util/billing" 32 "yunion.io/x/onecloud/pkg/util/rand" 33 ) 34 35 type SReadOnlyDBInstanceIds struct { 36 ReadOnlyDBInstanceId []string 37 } 38 39 type SDBInstanceId struct { 40 DBInstanceId []string 41 } 42 43 type SDBInstanceExtra struct { 44 DBInstanceId SDBInstanceId 45 } 46 47 type SDBInstance struct { 48 multicloud.SDBInstanceBase 49 50 netInfo []SDBInstanceNetwork 51 52 region *SRegion 53 54 AccountMaxQuantity int 55 AccountType string 56 CanTempUpgrade bool 57 Category string 58 AvailabilityValue string 59 DBInstanceDescription string 60 DBInstanceId string 61 ConnectionMode string 62 ConnectionString string 63 ConnectionDomain string 64 CurrentKernelVersion string 65 DBInstanceCPU int 66 CreateTime time.Time 67 DBInstanceClass string 68 DBInstanceClassType string 69 DBInstanceNetType string 70 DBInstanceStatus string 71 DBInstanceType string 72 DBInstanceDiskUsed int64 73 DBInstanceStorage int 74 DBInstanceStorageType string 75 MasterInstanceId string 76 DBInstanceMemory int 77 DBMaxQuantity int 78 IPType string 79 LatestKernelVersion string 80 DispenseMode string 81 Engine string 82 EngineVersion string 83 ExpireTime time.Time 84 InstanceNetworkType string 85 LockMode string 86 LockReason string 87 MutriORsignle bool 88 MaintainTime string 89 MaxConnections int 90 MaxIOPS int 91 Port int 92 PayType TChargeType 93 ReadOnlyDBInstanceIds SReadOnlyDBInstanceIds 94 RegionId string 95 ResourceGroupId string 96 VSwitchId string 97 VpcCloudInstanceId string 98 VpcId string 99 ZoneId string 100 Extra SDBInstanceExtra 101 SecurityIPList string 102 SecurityIPMode string 103 SupportCreateSuperAccount string 104 SupportUpgradeAccountType string 105 TempUpgradeTimeEnd time.Time 106 TempUpgradeTimeStart time.Time 107 } 108 109 func (rds *SDBInstance) GetName() string { 110 if len(rds.DBInstanceDescription) > 0 { 111 return rds.DBInstanceDescription 112 } 113 return rds.DBInstanceId 114 } 115 116 func (rds *SDBInstance) GetId() string { 117 return rds.DBInstanceId 118 } 119 120 func (rds *SDBInstance) GetGlobalId() string { 121 return rds.GetId() 122 } 123 124 // Creating 创建中 125 // Running 使用中 126 // Deleting 删除中 127 // Rebooting 重启中 128 // DBInstanceClassChanging 升降级中 129 // TRANSING 迁移中 130 // EngineVersionUpgrading 迁移版本中 131 // TransingToOthers 迁移数据到其他RDS中 132 // GuardDBInstanceCreating 生产灾备实例中 133 // Restoring 备份恢复中 134 // Importing 数据导入中 135 // ImportingFromOthers 从其他RDS实例导入数据中 136 // DBInstanceNetTypeChanging 内外网切换中 137 // GuardSwitching 容灾切换中 138 // INS_CLONING 实例克隆中 139 func (rds *SDBInstance) GetStatus() string { 140 switch rds.DBInstanceStatus { 141 case "Creating", "GuardDBInstanceCreating", "DBInstanceNetTypeChanging", "GuardSwitching", "NET_CREATING", "NET_DELETING": 142 return api.DBINSTANCE_DEPLOYING 143 case "DBInstanceClassChanging": 144 return api.DBINSTANCE_CHANGE_CONFIG 145 case "Running": 146 return api.DBINSTANCE_RUNNING 147 case "Deleting": 148 return api.DBINSTANCE_DELETING 149 case "Rebooting": 150 return api.DBINSTANCE_REBOOTING 151 case "TRANSING", "EngineVersionUpgrading", "TransingToOthers": 152 return api.DBINSTANCE_MIGRATING 153 case "Restoring": 154 return api.DBINSTANCE_RESTORING 155 case "Importing", "ImportingFromOthers": 156 return api.DBINSTANCE_IMPORTING 157 case "INS_CLONING": 158 return api.DBINSTANCE_CLONING 159 default: 160 log.Errorf("Unknown dbinstance status %s", rds.DBInstanceStatus) 161 return api.DBINSTANCE_UNKNOWN 162 } 163 } 164 165 func (rds *SDBInstance) GetBillingType() string { 166 return convertChargeType(rds.PayType) 167 } 168 169 func (rds *SDBInstance) GetExpiredAt() time.Time { 170 return rds.ExpireTime 171 } 172 173 func (rds *SDBInstance) GetCreatedAt() time.Time { 174 return rds.CreateTime 175 } 176 177 func (rds *SDBInstance) GetStorageType() string { 178 return rds.DBInstanceStorageType 179 } 180 181 func (rds *SDBInstance) GetEngine() string { 182 switch rds.Engine { 183 case "MySQL": 184 return api.DBINSTANCE_TYPE_MYSQL 185 case "SQLServer": 186 return api.DBINSTANCE_TYPE_SQLSERVER 187 case "PostgreSQL": 188 return api.DBINSTANCE_TYPE_POSTGRESQL 189 case "PPAS": 190 return api.DBINSTANCE_TYPE_PPAS 191 case "MariaDB": 192 return api.DBINSTANCE_TYPE_MARIADB 193 } 194 return rds.Engine 195 } 196 197 func (rds *SDBInstance) GetEngineVersion() string { 198 return rds.EngineVersion 199 } 200 201 func (rds *SDBInstance) GetInstanceType() string { 202 return rds.DBInstanceClass 203 } 204 205 func (rds *SDBInstance) GetCategory() string { 206 switch rds.Category { 207 case "Basic": 208 return api.ALIYUN_DBINSTANCE_CATEGORY_BASIC 209 case "HighAvailability": 210 return api.ALIYUN_DBINSTANCE_CATEGORY_HA 211 case "AlwaysOn": 212 return api.ALIYUN_DBINSTANCE_CATEGORY_ALWAYSON 213 case "Finance": 214 return api.ALIYUN_DBINSTANCE_CATEGORY_FINANCE 215 } 216 return rds.Category 217 } 218 219 func (rds *SDBInstance) GetVcpuCount() int { 220 if rds.DBInstanceCPU == 0 { 221 rds.Refresh() 222 } 223 return rds.DBInstanceCPU 224 } 225 226 func (rds *SDBInstance) GetVmemSizeMB() int { 227 if rds.DBInstanceMemory == 0 { 228 rds.Refresh() 229 } 230 return rds.DBInstanceMemory 231 } 232 233 func (rds *SDBInstance) GetDiskSizeGB() int { 234 if rds.DBInstanceStorage == 0 { 235 rds.Refresh() 236 } 237 return rds.DBInstanceStorage 238 } 239 240 func (rds *SDBInstance) GetDiskSizeUsedMB() int { 241 if rds.DBInstanceDiskUsed == 0 { 242 rds.Refresh() 243 } 244 return int(rds.DBInstanceDiskUsed / 1024 / 1024) 245 } 246 247 func (rds *SDBInstance) GetPort() int { 248 if rds.Port == 0 { 249 rds.Refresh() 250 } 251 return rds.Port 252 } 253 254 func (rds *SDBInstance) GetMaintainTime() string { 255 return rds.MaintainTime 256 } 257 258 func (rds *SDBInstance) GetIVpcId() string { 259 return rds.VpcId 260 } 261 262 func (rds *SDBInstance) Refresh() error { 263 instance, err := rds.region.GetDBInstanceDetail(rds.DBInstanceId) 264 if err != nil { 265 return err 266 } 267 return jsonutils.Update(rds, instance) 268 } 269 270 func (rds *SDBInstance) getZoneId(index int) string { 271 zoneId := rds.getZone(index) 272 if len(zoneId) > 0 { 273 zone, err := rds.region.getZoneById(zoneId) 274 if err != nil { 275 log.Errorf("failed to found zone %s for rds %s", zoneId, rds.GetName()) 276 return "" 277 } 278 return zone.GetGlobalId() 279 } 280 return "" 281 } 282 283 func (rds *SDBInstance) GetZone1Id() string { 284 return rds.getZoneId(1) 285 } 286 287 func (rds *SDBInstance) GetZone2Id() string { 288 return rds.getZoneId(2) 289 } 290 291 func (rds *SDBInstance) GetZone3Id() string { 292 return rds.getZoneId(3) 293 } 294 295 func (rds *SDBInstance) GetIOPS() int { 296 if rds.MaxIOPS == 0 { 297 rds.Refresh() 298 } 299 return rds.MaxIOPS 300 } 301 302 func (rds *SDBInstance) GetNetworkAddress() string { 303 return rds.ConnectionDomain 304 } 305 306 func (rds *SDBInstance) getZone(index int) string { 307 zoneStr := strings.Replace(rds.ZoneId, ")", "", -1) 308 zoneInfo := strings.Split(zoneStr, ",") 309 if len(zoneInfo) < index { 310 return "" 311 } 312 zone := zoneInfo[index-1] 313 zoneCode := zone[len(zone)-1] 314 if strings.HasPrefix(rds.ZoneId, fmt.Sprintf("%s-", rds.RegionId)) { 315 return fmt.Sprintf("%s-%s", rds.RegionId, string(zoneCode)) 316 } 317 return fmt.Sprintf("%s%s", rds.RegionId, string(zoneCode)) 318 } 319 320 func (rds *SDBInstance) GetDBNetworks() ([]cloudprovider.SDBInstanceNetwork, error) { 321 netInfo, err := rds.region.GetDBInstanceNetInfo(rds.DBInstanceId) 322 if err != nil { 323 return nil, errors.Wrapf(err, "GetDBInstanceNetInfo") 324 } 325 networks := []cloudprovider.SDBInstanceNetwork{} 326 for _, net := range netInfo { 327 if net.IPType == "Private" { 328 network := cloudprovider.SDBInstanceNetwork{} 329 network.IP = net.IPAddress 330 network.NetworkId = net.VSwitchId 331 networks = append(networks, network) 332 } 333 } 334 return networks, nil 335 } 336 337 func (rds *SDBInstance) fetchNetInfo() error { 338 if len(rds.netInfo) > 0 { 339 return nil 340 } 341 netInfo, err := rds.region.GetDBInstanceNetInfo(rds.DBInstanceId) 342 if err != nil { 343 return errors.Wrap(err, "GetDBInstanceNetInfo") 344 } 345 rds.netInfo = netInfo 346 return nil 347 } 348 349 func (rds *SDBInstance) GetInternalConnectionStr() string { 350 err := rds.fetchNetInfo() 351 if err != nil { 352 log.Errorf("failed to fetch netInfo error: %v", err) 353 return "" 354 } 355 356 str := "" 357 for _, net := range rds.netInfo { 358 if net.IPType != "Public" { 359 if net.IPType == "Private" { 360 return net.ConnectionString 361 } else if net.IPType == "Inner" { 362 str = net.ConnectionString 363 } 364 } 365 } 366 return str 367 } 368 369 func (rds *SDBInstance) GetConnectionStr() string { 370 err := rds.fetchNetInfo() 371 if err != nil { 372 log.Errorf("failed to fetch netInfo error: %v", err) 373 return "" 374 } 375 376 for _, net := range rds.netInfo { 377 if net.IPType == "Public" { 378 return net.ConnectionString 379 } 380 } 381 return "" 382 } 383 384 func (region *SRegion) GetDBInstances(ids []string, offset int, limit int) ([]SDBInstance, int, error) { 385 if limit > 50 || limit <= 0 { 386 limit = 50 387 } 388 params := make(map[string]string) 389 params["RegionId"] = region.RegionId 390 params["PageSize"] = fmt.Sprintf("%d", limit) 391 params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1) 392 393 body, err := region.rdsRequest("DescribeDBInstances", params) 394 if err != nil { 395 return nil, 0, errors.Wrapf(err, "GetDBInstances") 396 } 397 instances := []SDBInstance{} 398 err = body.Unmarshal(&instances, "Items", "DBInstance") 399 if err != nil { 400 return nil, 0, errors.Wrapf(err, "GetDBInstances.Unmarshal") 401 } 402 total, _ := body.Int("TotalRecordCount") 403 return instances, int(total), nil 404 } 405 406 func (region *SRegion) GetIDBInstanceById(instanceId string) (cloudprovider.ICloudDBInstance, error) { 407 rds, err := region.GetDBInstanceDetail(instanceId) 408 if err != nil { 409 return nil, err 410 } 411 rds.region = region 412 return rds, nil 413 } 414 415 func (region *SRegion) GetIDBInstances() ([]cloudprovider.ICloudDBInstance, error) { 416 instances := []SDBInstance{} 417 for { 418 part, total, err := region.GetDBInstances([]string{}, len(instances), 50) 419 if err != nil { 420 return nil, err 421 } 422 instances = append(instances, part...) 423 if len(instances) >= total { 424 break 425 } 426 } 427 idbinstances := []cloudprovider.ICloudDBInstance{} 428 for i := 0; i < len(instances); i++ { 429 instances[i].region = region 430 idbinstances = append(idbinstances, &instances[i]) 431 } 432 return idbinstances, nil 433 } 434 435 func (region *SRegion) GetDBInstanceDetail(instanceId string) (*SDBInstance, error) { 436 if len(instanceId) == 0 { 437 return nil, cloudprovider.ErrNotFound 438 } 439 params := map[string]string{} 440 params["RegionId"] = region.RegionId 441 params["DBInstanceId"] = instanceId 442 body, err := region.rdsRequest("DescribeDBInstanceAttribute", params) 443 if err != nil { 444 return nil, errors.Wrapf(err, "GetDBInstanceDetail") 445 } 446 instances := []SDBInstance{} 447 err = body.Unmarshal(&instances, "Items", "DBInstanceAttribute") 448 if err != nil { 449 return nil, errors.Wrapf(err, "GetDBInstanceDetail.Unmarshal") 450 } 451 if len(instances) == 1 { 452 instances[0].region = region 453 return &instances[0], nil 454 } 455 if len(instances) == 0 { 456 return nil, cloudprovider.ErrNotFound 457 } 458 return nil, cloudprovider.ErrDuplicateId 459 } 460 461 func (region *SRegion) DeleteDBInstance(instanceId string) error { 462 params := map[string]string{} 463 params["RegionId"] = region.RegionId 464 params["DBInstanceId"] = instanceId 465 _, err := region.rdsRequest("DeleteDBInstance", params) 466 return err 467 } 468 469 type SDBInstanceWeight struct { 470 } 471 472 type SDBInstanceWeights struct { 473 DBInstanceWeight []SDBInstanceWeight 474 } 475 476 type SsecurityIPGroup struct { 477 } 478 479 type SSecurityIPGroups struct { 480 securityIPGroup []SsecurityIPGroup 481 } 482 483 type SDBInstanceNetwork struct { 484 ConnectionString string 485 ConnectionStringType string 486 DBInstanceWeights SDBInstanceWeights 487 IPAddress string 488 IPType string 489 Port int 490 SecurityIPGroups SSecurityIPGroups 491 Upgradeable string 492 VPCId string 493 VSwitchId string 494 } 495 496 func (network *SDBInstanceNetwork) GetGlobalId() string { 497 return network.IPAddress 498 } 499 500 func (network *SDBInstanceNetwork) GetINetworkId() string { 501 return network.VSwitchId 502 } 503 504 func (network *SDBInstanceNetwork) GetIP() string { 505 return network.IPAddress 506 } 507 508 func (region *SRegion) GetDBInstanceNetInfo(instanceId string) ([]SDBInstanceNetwork, error) { 509 params := map[string]string{} 510 params["RegionId"] = region.RegionId 511 params["DBInstanceId"] = instanceId 512 body, err := region.rdsRequest("DescribeDBInstanceNetInfo", params) 513 if err != nil { 514 return nil, errors.Wrapf(err, "GetDBInstanceNetwork") 515 } 516 networks := []SDBInstanceNetwork{} 517 err = body.Unmarshal(&networks, "DBInstanceNetInfos", "DBInstanceNetInfo") 518 if err != nil { 519 return nil, err 520 } 521 return networks, nil 522 } 523 524 func (rds *SDBInstance) GetIDBInstanceParameters() ([]cloudprovider.ICloudDBInstanceParameter, error) { 525 parameters, err := rds.region.GetDBInstanceParameters(rds.DBInstanceId) 526 if err != nil { 527 return nil, err 528 } 529 iparameters := []cloudprovider.ICloudDBInstanceParameter{} 530 for i := 0; i < len(parameters); i++ { 531 iparameters = append(iparameters, ¶meters[i]) 532 } 533 return iparameters, nil 534 } 535 536 func (self *SDBInstance) GetSecurityGroupIds() ([]string, error) { 537 return self.region.GetRdsSecgroupIds(self.DBInstanceId) 538 } 539 540 func (self *SDBInstance) SetSecurityGroups(ids []string) error { 541 return self.region.SetRdsSecgroups(self.DBInstanceId, ids) 542 } 543 544 func (self *SRegion) SetRdsSecgroups(rdsId string, secIds []string) error { 545 params := map[string]string{ 546 "DBInstanceId": rdsId, 547 "SecurityGroupId": strings.Join(secIds, ","), 548 } 549 _, err := self.rdsRequest("ModifySecurityGroupConfiguration", params) 550 if err != nil { 551 return errors.Wrapf(err, "ModifySecurityGroupConfiguration") 552 } 553 return nil 554 } 555 556 func (self *SRegion) GetRdsSecgroupIds(rdsId string) ([]string, error) { 557 params := map[string]string{ 558 "DBInstanceId": rdsId, 559 } 560 resp, err := self.rdsRequest("DescribeSecurityGroupConfiguration", params) 561 if err != nil { 562 return nil, errors.Wrapf(err, "DescribeSecurityGroupConfiguration") 563 } 564 items := []struct { 565 NetworkType string 566 SecurityGroupId string 567 RegionId string 568 }{} 569 err = resp.Unmarshal(&items, "Items", "EcsSecurityGroupRelation") 570 if err != nil { 571 return nil, errors.Wrapf(err, "resp.Unmarshal") 572 } 573 ids := []string{} 574 for _, item := range items { 575 ids = append(ids, item.SecurityGroupId) 576 } 577 return ids, nil 578 } 579 580 func (region *SRegion) GetIDBInstanceBackupById(backupId string) (cloudprovider.ICloudDBInstanceBackup, error) { 581 backups, err := region.GetIDBInstanceBackups() 582 if err != nil { 583 return nil, errors.Wrap(err, "region.GetIDBInstanceBackups") 584 } 585 for _, backup := range backups { 586 if backup.GetGlobalId() == backupId { 587 return backup, nil 588 } 589 } 590 return nil, cloudprovider.ErrNotFound 591 } 592 593 func (rds *SDBInstance) Reboot() error { 594 return rds.region.RebootDBInstance(rds.DBInstanceId) 595 } 596 597 func (rds *SDBInstance) Delete() error { 598 return rds.region.DeleteDBInstance(rds.DBInstanceId) 599 } 600 601 func (region *SRegion) RebootDBInstance(instanceId string) error { 602 params := map[string]string{} 603 params["RegionId"] = region.RegionId 604 params["DBInstanceId"] = instanceId 605 _, err := region.rdsRequest("RestartDBInstance", params) 606 return err 607 } 608 609 func (rds *SDBInstance) GetIDBInstanceDatabases() ([]cloudprovider.ICloudDBInstanceDatabase, error) { 610 databases := []SDBInstanceDatabase{} 611 for { 612 parts, total, err := rds.region.GetDBInstanceDatabases(rds.DBInstanceId, "", len(databases), 500) 613 if err != nil { 614 return nil, err 615 } 616 databases = append(databases, parts...) 617 if len(databases) >= total { 618 break 619 } 620 } 621 622 idatabase := []cloudprovider.ICloudDBInstanceDatabase{} 623 for i := 0; i < len(databases); i++ { 624 databases[i].instance = rds 625 idatabase = append(idatabase, &databases[i]) 626 } 627 return idatabase, nil 628 } 629 630 func (rds *SDBInstance) GetIDBInstanceAccounts() ([]cloudprovider.ICloudDBInstanceAccount, error) { 631 accounts := []SDBInstanceAccount{} 632 for { 633 parts, total, err := rds.region.GetDBInstanceAccounts(rds.DBInstanceId, len(accounts), 50) 634 if err != nil { 635 return nil, err 636 } 637 accounts = append(accounts, parts...) 638 if len(accounts) >= total { 639 break 640 } 641 } 642 643 iaccounts := []cloudprovider.ICloudDBInstanceAccount{} 644 for i := 0; i < len(accounts); i++ { 645 accounts[i].instance = rds 646 iaccounts = append(iaccounts, &accounts[i]) 647 } 648 return iaccounts, nil 649 } 650 651 func (rds *SDBInstance) ChangeConfig(cxt context.Context, desc *cloudprovider.SManagedDBInstanceChangeConfig) error { 652 return rds.region.ChangeDBInstanceConfig(rds.DBInstanceId, string(rds.PayType), desc) 653 } 654 655 func (region *SRegion) ChangeDBInstanceConfig(instanceId, payType string, desc *cloudprovider.SManagedDBInstanceChangeConfig) error { 656 params := map[string]string{ 657 "RegionId": region.RegionId, 658 "DBInstanceId": instanceId, 659 "PayType": payType, 660 } 661 if len(desc.InstanceType) > 0 { 662 params["DBInstanceClass"] = desc.InstanceType 663 } 664 if desc.DiskSizeGB > 0 { 665 params["DBInstanceStorage"] = fmt.Sprintf("%d", desc.DiskSizeGB) 666 } 667 668 _, err := region.rdsRequest("ModifyDBInstanceSpec", params) 669 if err != nil { 670 return errors.Wrap(err, "region.rdsRequest.ModifyDBInstanceSpec") 671 } 672 return nil 673 } 674 675 func (region *SRegion) CreateIDBInstance(desc *cloudprovider.SManagedDBInstanceCreateConfig) (cloudprovider.ICloudDBInstance, error) { 676 params := map[string]string{ 677 "RegionId": region.RegionId, 678 "Engine": desc.Engine, 679 "EngineVersion": desc.EngineVersion, 680 "DBInstanceStorage": fmt.Sprintf("%d", desc.DiskSizeGB), 681 "DBInstanceNetType": "Intranet", 682 "PayType": "Postpaid", 683 "SecurityIPList": "0.0.0.0/0", 684 "DBInstanceDescription": desc.Name, 685 "InstanceNetworkType": "VPC", 686 "VPCId": desc.VpcId, 687 "VSwitchId": desc.NetworkId, 688 "DBInstanceStorageType": desc.StorageType, 689 "DBInstanceClass": desc.InstanceType, 690 "ZoneId": desc.ZoneId, 691 "ClientToken": utils.GenRequestId(20), 692 } 693 switch desc.Category { 694 case api.ALIYUN_DBINSTANCE_CATEGORY_HA: 695 params["Category"] = "HighAvailability" 696 case api.ALIYUN_DBINSTANCE_CATEGORY_BASIC: 697 params["Category"] = "Basic" 698 case api.ALIYUN_DBINSTANCE_CATEGORY_ALWAYSON: 699 params["Category"] = "AlwaysOn" 700 case api.ALIYUN_DBINSTANCE_CATEGORY_FINANCE: 701 params["Category"] = "Finance" 702 } 703 704 if len(desc.Address) > 0 { 705 params["PrivateIpAddress"] = desc.Address 706 } 707 if len(desc.ProjectId) > 0 { 708 params["ResourceGroupId"] = desc.ProjectId 709 } 710 if desc.BillingCycle != nil { 711 params["PayType"] = "Prepaid" 712 if desc.BillingCycle.GetYears() > 0 { 713 params["Period"] = "Year" 714 params["UsedTime"] = fmt.Sprintf("%d", desc.BillingCycle.GetYears()) 715 } else { 716 params["Period"] = "Month" 717 params["UsedTime"] = fmt.Sprintf("%d", desc.BillingCycle.GetMonths()) 718 } 719 params["AutoRenew"] = "False" 720 if desc.BillingCycle.AutoRenew { 721 params["AutoRenew"] = "True" 722 } 723 } 724 725 action := "CreateDBInstance" 726 if len(desc.MasterInstanceId) > 0 { 727 action = "CreateReadOnlyDBInstance" 728 params["DBInstanceId"] = desc.MasterInstanceId 729 } 730 731 resp, err := region.rdsRequest(action, params) 732 if err != nil { 733 return nil, errors.Wrapf(err, "rdsRequest") 734 } 735 instanceId, err := resp.GetString("DBInstanceId") 736 if err != nil { 737 return nil, errors.Wrap(err, `resp.GetString("DBInstanceId")`) 738 } 739 region.SetResourceTags(ALIYUN_SERVICE_RDS, "INSTANCE", instanceId, desc.Tags, false) 740 return region.GetIDBInstanceById(instanceId) 741 } 742 743 func (rds *SDBInstance) GetMasterInstanceId() string { 744 if len(rds.MasterInstanceId) > 0 { 745 return rds.MasterInstanceId 746 } 747 rds.Refresh() 748 return rds.MasterInstanceId 749 } 750 751 func (region *SRegion) OpenPublicConnection(instanceId string) error { 752 rds, err := region.GetDBInstanceDetail(instanceId) 753 if err != nil { 754 return err 755 } 756 params := map[string]string{ 757 "RegionId": region.RegionId, 758 "ConnectionStringPrefix": rds.DBInstanceId + rand.String(3), 759 "DBInstanceId": rds.DBInstanceId, 760 "Port": fmt.Sprintf("%d", rds.Port), 761 } 762 _, err = rds.region.rdsRequest("AllocateInstancePublicConnection", params) 763 if err != nil { 764 return errors.Wrap(err, "rdsRequest(AllocateInstancePublicConnection)") 765 } 766 return nil 767 } 768 769 func (rds *SDBInstance) OpenPublicConnection() error { 770 if url := rds.GetConnectionStr(); len(url) == 0 { 771 err := rds.region.OpenPublicConnection(rds.DBInstanceId) 772 if err != nil { 773 return err 774 } 775 rds.netInfo = []SDBInstanceNetwork{} 776 } 777 return nil 778 } 779 780 func (region *SRegion) ClosePublicConnection(instanceId string) error { 781 netInfo, err := region.GetDBInstanceNetInfo(instanceId) 782 if err != nil { 783 return errors.Wrap(err, "GetDBInstanceNetInfo") 784 } 785 786 for _, net := range netInfo { 787 if net.IPType == "Public" { 788 params := map[string]string{ 789 "RegionId": region.RegionId, 790 "CurrentConnectionString": net.ConnectionString, 791 "DBInstanceId": instanceId, 792 } 793 _, err = region.rdsRequest("ReleaseInstancePublicConnection", params) 794 if err != nil { 795 return errors.Wrap(err, "rdsRequest(ReleaseInstancePublicConnection)") 796 } 797 798 } 799 } 800 return nil 801 802 } 803 804 func (rds *SDBInstance) ClosePublicConnection() error { 805 return rds.region.ClosePublicConnection(rds.DBInstanceId) 806 } 807 808 func (rds *SDBInstance) RecoveryFromBackup(conf *cloudprovider.SDBInstanceRecoveryConfig) error { 809 if len(conf.OriginDBInstanceExternalId) == 0 { 810 conf.OriginDBInstanceExternalId = rds.DBInstanceId 811 } 812 return rds.region.RecoveryDBInstanceFromBackup(conf.OriginDBInstanceExternalId, rds.DBInstanceId, conf.BackupId, conf.Databases) 813 } 814 815 func (region *SRegion) RecoveryDBInstanceFromBackup(srcId, destId string, backupId string, databases map[string]string) error { 816 params := map[string]string{ 817 "RegionId": region.RegionId, 818 "DBInstanceId": srcId, 819 "TargetDBInstanceId": destId, 820 "BackupId": backupId, 821 "DbNames": jsonutils.Marshal(databases).String(), 822 } 823 _, err := region.rdsRequest("RecoveryDBInstance", params) 824 if err != nil { 825 return errors.Wrap(err, "rdsRequest.RecoveryDBInstance") 826 } 827 return nil 828 } 829 830 func (rds *SDBInstance) GetProjectId() string { 831 return rds.ResourceGroupId 832 } 833 834 func (rds *SDBInstance) CreateDatabase(conf *cloudprovider.SDBInstanceDatabaseCreateConfig) error { 835 return rds.region.CreateDBInstanceDatabae(rds.DBInstanceId, conf.CharacterSet, conf.Name, conf.Description) 836 } 837 838 func (rds *SDBInstance) CreateAccount(conf *cloudprovider.SDBInstanceAccountCreateConfig) error { 839 return rds.region.CreateDBInstanceAccount(rds.DBInstanceId, conf.Name, conf.Password, conf.Description) 840 } 841 842 func (rds *SDBInstance) Renew(bc billing.SBillingCycle) error { 843 return rds.region.RenewInstance(rds.DBInstanceId, bc) 844 } 845 846 func (rds *SDBInstance) SetAutoRenew(bc billing.SBillingCycle) error { 847 month := 1 848 if bc.GetMonths() > 0 { 849 month = bc.GetMonths() 850 } 851 return rds.region.ModifyInstanceAutoRenewalAttribute(rds.DBInstanceId, month, bc.AutoRenew) 852 } 853 854 func (region *SRegion) ModifyInstanceAutoRenewalAttribute(rdsId string, month int, autoRenew bool) error { 855 params := map[string]string{ 856 "RegionId": region.RegionId, 857 "DBInstanceId": rdsId, 858 "AutoRenew": "False", 859 "ClientToken": utils.GenRequestId(20), 860 } 861 if autoRenew { 862 params["AutoRenew"] = "True" 863 params["Duration"] = fmt.Sprintf("%d", month) 864 } 865 _, err := region.rdsRequest("ModifyInstanceAutoRenewalAttribute", params) 866 if err != nil { 867 return errors.Wrap(err, "ModifyInstanceAutoRenewalAttribute") 868 } 869 return nil 870 } 871 872 func (region *SRegion) RenewDBInstance(instanceId string, bc billing.SBillingCycle) error { 873 params := map[string]string{ 874 "DBInstanceId": instanceId, 875 "Period": fmt.Sprintf("%d", bc.GetMonths()), 876 "ClientToken": utils.GenRequestId(20), 877 } 878 _, err := region.rdsRequest("RenewInstance", params) 879 return err 880 } 881 882 func (self *SDBInstance) GetTags() (map[string]string, error) { 883 _, tags, err := self.region.ListSysAndUserTags(ALIYUN_SERVICE_RDS, "INSTANCE", self.DBInstanceId) 884 if err != nil { 885 return nil, errors.Wrapf(err, "ListTags") 886 } 887 tagMaps := map[string]string{} 888 for k, v := range tags { 889 tagMaps[strings.ToLower(k)] = v 890 } 891 return tagMaps, nil 892 } 893 894 func (self *SDBInstance) GetSysTags() map[string]string { 895 tags, _, err := self.region.ListSysAndUserTags(ALIYUN_SERVICE_RDS, "INSTANCE", self.DBInstanceId) 896 if err != nil { 897 return nil 898 } 899 tagMaps := map[string]string{} 900 for k, v := range tags { 901 tagMaps[strings.ToLower(k)] = v 902 } 903 return tagMaps 904 } 905 906 func (rds *SDBInstance) SetTags(tags map[string]string, replace bool) error { 907 return rds.region.SetResourceTags(ALIYUN_SERVICE_RDS, "INSTANCE", rds.GetId(), tags, replace) 908 }