fix(region): refactor huawei eip api

This commit is contained in:
ioito
2022-04-19 18:52:34 +08:00
parent 96e501b310
commit 9e76d9616f
9 changed files with 162 additions and 238 deletions
-6
View File
@@ -28,11 +28,9 @@ type Client struct {
init bool
Balances *modules.SBalanceManager
Bandwidths *modules.SBandwidthManager
Credentials *modules.SCredentialManager
Disks *modules.SDiskManager
Domains *modules.SDomainManager
Eips *modules.SEipManager
Elasticcache *modules.SElasticcacheManager
DcsAvailableZone *modules.SDcsAvailableZoneManager
Flavors *modules.SFlavorManager
@@ -125,7 +123,6 @@ func (self *Client) SetHttpClient(httpClient *http.Client) {
self.Regions.SetHttpClient(httpClient)
self.Zones.SetHttpClient(httpClient)
self.Vpcs.SetHttpClient(httpClient)
self.Eips.SetHttpClient(httpClient)
self.Elasticcache.SetHttpClient(httpClient)
self.DcsAvailableZone.SetHttpClient(httpClient)
self.Disks.SetHttpClient(httpClient)
@@ -140,7 +137,6 @@ func (self *Client) SetHttpClient(httpClient *http.Client) {
self.Interface.SetHttpClient(httpClient)
self.Jobs.SetHttpClient(httpClient)
self.Balances.SetHttpClient(httpClient)
self.Bandwidths.SetHttpClient(httpClient)
self.Port.SetHttpClient(httpClient)
self.Flavors.SetHttpClient(httpClient)
self.VpcRoutes.SetHttpClient(httpClient)
@@ -201,7 +197,6 @@ func (self *Client) initManagers() {
self.Regions = modules.NewRegionManager(self.cfg)
self.Zones = modules.NewZoneManager(self.cfg)
self.Vpcs = modules.NewVpcManager(self.cfg)
self.Eips = modules.NewEipManager(self.cfg)
self.Elasticcache = modules.NewElasticcacheManager(self.cfg)
self.DcsAvailableZone = modules.NewDcsAvailableZoneManager(self.cfg)
self.Disks = modules.NewDiskManager(self.cfg)
@@ -216,7 +211,6 @@ func (self *Client) initManagers() {
self.Interface = modules.NewInterfaceManager(self.cfg)
self.Jobs = modules.NewJobManager(self.cfg)
self.Balances = modules.NewBalanceManager(self.cfg)
self.Bandwidths = modules.NewBandwidthManager(self.cfg)
self.Credentials = modules.NewCredentialManager(self.cfg)
self.Port = modules.NewPortManager(self.cfg)
self.Flavors = modules.NewFlavorManager(self.cfg)
@@ -1,37 +0,0 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package modules
import (
"yunion.io/x/onecloud/pkg/multicloud/huawei/client/manager"
)
type SBandwidthManager struct {
SResourceManager
}
func NewBandwidthManager(cfg manager.IManagerConfig) *SBandwidthManager {
return &SBandwidthManager{SResourceManager: SResourceManager{
SBaseManager: NewBaseManager(cfg),
ServiceName: ServiceNameVPC,
Region: cfg.GetRegionId(),
ProjectId: cfg.GetProjectId(),
version: "v1",
Keyword: "bandwidth",
KeywordPlural: "bandwidths",
ResourceKeyword: "bandwidths",
}}
}
@@ -1,44 +0,0 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package modules
import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/multicloud/huawei/client/manager"
)
type SEipManager struct {
SResourceManager
}
func NewEipManager(cfg manager.IManagerConfig) *SEipManager {
return &SEipManager{SResourceManager: SResourceManager{
SBaseManager: NewBaseManager(cfg),
ServiceName: ServiceNameVPC,
Region: cfg.GetRegionId(),
ProjectId: cfg.GetProjectId(),
version: "v1",
Keyword: "publicip",
KeywordPlural: "publicips",
ResourceKeyword: "publicips",
}}
}
// https://support.huaweicloud.com/api-eip/eip_api_0005.html
func (self *SEipManager) Delete(id string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
return self.DeleteInContextWithSpec(self.ctx, id, "", nil, params, "")
}
+80 -90
View File
@@ -16,11 +16,11 @@ package huawei
import (
"fmt"
"net/url"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
@@ -69,6 +69,7 @@ type SEipAddress struct {
multicloud.SEipBase
multicloud.HuaweiTags
Alias string
ID string `json:"id"`
Status string `json:"status"`
Profile *SProfile `json:"profile,omitempty"`
@@ -92,10 +93,9 @@ func (self *SEipAddress) GetId() string {
}
func (self *SEipAddress) GetName() string {
if len(self.BandwidthName) == 0 {
return self.BandwidthName
if len(self.Alias) > 0 {
return self.Alias
}
return self.PublicIPAddress
}
@@ -208,20 +208,17 @@ func (self *SEipAddress) GetInternetChargeType() string {
if err != nil {
return api.EIP_CHARGE_TYPE_BY_TRAFFIC
}
if bandwidth.ChargeMode != "traffic" {
return api.EIP_CHARGE_TYPE_BY_BANDWIDTH
} else {
if bandwidth.ChargeMode == "traffic" {
return api.EIP_CHARGE_TYPE_BY_TRAFFIC
}
return api.EIP_CHARGE_TYPE_BY_BANDWIDTH
}
func (self *SEipAddress) GetBillingType() string {
if self.Profile == nil {
return billing_api.BILLING_TYPE_POSTPAID
} else {
return billing_api.BILLING_TYPE_PREPAID
}
return billing_api.BILLING_TYPE_PREPAID
}
func (self *SEipAddress) GetCreatedAt() time.Time {
@@ -260,20 +257,11 @@ func (self *SEipAddress) Associate(conf *cloudprovider.AssociateConfig) error {
}
func (self *SEipAddress) Dissociate() error {
if len(self.PortId) == 0 {
return nil
}
port, err := self.region.GetPort(self.PortId)
err := self.region.DissociateEip(self.ID)
if err != nil {
return errors.Wrapf(err, "GetPort(%s)", self.PortId)
return err
}
err = self.region.DissociateEip(self.ID, port.DeviceID)
if err != nil {
return errors.Wrapf(err, "DissociateEip")
}
err = cloudprovider.WaitStatus(self, api.EIP_STATUS_READY, 10*time.Second, 180*time.Second)
return err
return cloudprovider.WaitStatus(self, api.EIP_STATUS_READY, 10*time.Second, 180*time.Second)
}
func (self *SEipAddress) ChangeBandwidth(bw int) error {
@@ -297,43 +285,41 @@ func (self *SRegion) GetInstancePortId(instanceId string) (string, error) {
// https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090596.html
func (self *SRegion) AllocateEIP(name string, bwMbps int, chargeType TInternetChargeType, bgpType string, projectId string) (*SEipAddress, error) {
paramsStr := `
{
"publicip": {
"type": "%s",
"ip_version": 4
},
"bandwidth": {
"name": "%s",
"size": %d,
"share_type": "PER",
"charge_mode": "%s"
}
}
`
if len(bgpType) == 0 {
return nil, fmt.Errorf("AllocateEIP bgp type should not be empty")
params := map[string]interface{}{
"bandwidth": map[string]interface{}{
"name": name,
"size": bwMbps,
"share_type": "PER",
"charge_mode": chargeType,
},
"publicip": map[string]interface{}{
"type": bgpType,
"ip_version": 4,
"alias": name,
},
}
paramsStr = fmt.Sprintf(paramsStr, bgpType, name, bwMbps, chargeType)
_params, _ := jsonutils.ParseString(paramsStr)
params := _params.(*jsonutils.JSONDict)
if len(projectId) > 0 {
params.Set("enterprise_project_id", jsonutils.NewString(projectId))
params["enterprise_project_id"] = projectId
}
eip := SEipAddress{}
err := DoCreate(self.ecsClient.Eips.Create, params, &eip)
return &eip, err
resp, err := self.vpcCreate("publicips", params)
if err != nil {
return nil, err
}
eip := &SEipAddress{region: self}
return eip, resp.Unmarshal(eip, "publicip")
}
func (self *SRegion) GetEip(eipId string) (*SEipAddress, error) {
var eip SEipAddress
err := DoGet(self.ecsClient.Eips.Get, eipId, nil, &eip)
eip.region = self
return &eip, err
resp, err := self.vpcGet("publicips/" + eipId)
if err != nil {
return nil, err
}
eip := &SEipAddress{region: self}
return eip, resp.Unmarshal(eip, "publicip")
}
func (self *SRegion) DeallocateEIP(eipId string) error {
_, err := self.ecsClient.Eips.Delete(eipId, nil)
_, err := self.vpcDelete("publicips/" + eipId)
return err
}
@@ -346,57 +332,61 @@ func (self *SRegion) AssociateEip(eipId string, instanceId string) error {
}
func (self *SRegion) AssociateEipWithPortId(eipId string, portId string) error {
params := jsonutils.NewDict()
publicIPObj := jsonutils.NewDict()
publicIPObj.Add(jsonutils.NewString(portId), "port_id")
params.Add(publicIPObj, "publicip")
_, err := self.ecsClient.Eips.Update(eipId, params)
params := map[string]interface{}{
"publicip": map[string]interface{}{
"port_id": portId,
},
}
_, err := self.vpcUpdate("publicips/"+eipId, params)
return err
}
func (self *SRegion) DissociateEip(eipId string, instanceId string) error {
eip, err := self.GetEip(eipId)
if err != nil {
return err
}
// 已经是解绑状态
if eip.Status == "DOWN" {
return nil
}
remoteInstanceId := eip.GetAssociationExternalId()
if remoteInstanceId != instanceId {
return fmt.Errorf("eip %s associate with another instance %s", eipId, remoteInstanceId)
}
paramsStr := `{"publicip":{"port_id":null}}`
params, _ := jsonutils.ParseString(paramsStr)
_, err = self.ecsClient.Eips.Update(eipId, params)
return err
func (self *SRegion) DissociateEip(eipId string) error {
return self.AssociateEipWithPortId(eipId, "")
}
func (self *SRegion) UpdateEipBandwidth(bandwidthId string, bw int) error {
paramStr := `{
"bandwidth":
{
"size": %d
}
}`
paramStr = fmt.Sprintf(paramStr, bw)
params, _ := jsonutils.ParseString(paramStr)
_, err := self.ecsClient.Bandwidths.Update(bandwidthId, params)
params := map[string]interface{}{
"bandwidth": map[string]interface{}{
"size": bw,
},
}
_, err := self.vpcUpdate("bandwidths/"+bandwidthId, params)
return err
}
func (self *SRegion) GetEipBandwidth(bandwidthId string) (Bandwidth, error) {
bandwidth := Bandwidth{}
err := DoGet(self.ecsClient.Bandwidths.Get, bandwidthId, nil, &bandwidth)
return bandwidth, err
func (self *SRegion) GetEipBandwidth(id string) (*Bandwidth, error) {
resp, err := self.vpcGet("bandwidths/" + id)
if err != nil {
return nil, err
}
ret := &Bandwidth{}
return ret, resp.Unmarshal(ret, "bandwidth")
}
func (self *SEipAddress) GetProjectId() string {
return self.EnterpriseProjectId
}
func (self *SRegion) GetEips(portId string, addrs []string) ([]SEipAddress, error) {
query := url.Values{}
for _, addr := range addrs {
query.Add("public_ip_address", addr)
}
if len(portId) > 0 {
query.Set("port_id", portId)
}
resp, err := self.vpcList("publicips", query)
if err != nil {
return nil, err
}
eips := []SEipAddress{}
err = resp.Unmarshal(&eips, "publicips")
if err != nil {
return nil, err
}
for i := range eips {
eips[i].region = self
}
return eips, nil
}
+29 -4
View File
@@ -223,12 +223,12 @@ func (self *SHuaweiClient) lbGet(regionId, resource string) (jsonutils.JSONObjec
func (self *SHuaweiClient) lbCreate(regionId, resource string, params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://elb.%s.myhuaweicloud.com/v2/%s/%s", regionId, self.projectId, resource)
return self.request(httputils.DELETE, uri, url.Values{}, params)
return self.request(httputils.POST, uri, url.Values{}, params)
}
func (self *SHuaweiClient) lbUpdate(regionId, resource string) (jsonutils.JSONObject, error) {
func (self *SHuaweiClient) lbUpdate(regionId, resource string, params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://elb.%s.myhuaweicloud.com/v2/%s/%s", regionId, self.projectId, resource)
return self.request(httputils.PUT, uri, url.Values{}, nil)
return self.request(httputils.PUT, uri, url.Values{}, params)
}
func (self *SHuaweiClient) lbDelete(regionId, resource string) (jsonutils.JSONObject, error) {
@@ -236,6 +236,31 @@ func (self *SHuaweiClient) lbDelete(regionId, resource string) (jsonutils.JSONOb
return self.request(httputils.DELETE, uri, url.Values{}, nil)
}
func (self *SHuaweiClient) vpcList(regionId, resource string, query url.Values) (jsonutils.JSONObject, error) {
url := fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v1/%s/%s", regionId, self.projectId, resource)
return self.request(httputils.GET, url, query, nil)
}
func (self *SHuaweiClient) vpcCreate(regionId, resource string, params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v1/%s/%s", regionId, self.projectId, resource)
return self.request(httputils.POST, uri, url.Values{}, params)
}
func (self *SHuaweiClient) vpcGet(regionId, resource string) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v1/%s/%s", regionId, self.projectId, resource)
return self.request(httputils.GET, uri, url.Values{}, nil)
}
func (self *SHuaweiClient) vpcDelete(regionId, resource string) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v1/%s/%s", regionId, self.projectId, resource)
return self.request(httputils.DELETE, uri, url.Values{}, nil)
}
func (self *SHuaweiClient) vpcUpdate(regionId, resource string, params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v1/%s/%s", regionId, self.projectId, resource)
return self.request(httputils.PUT, uri, url.Values{}, params)
}
type akClient struct {
client *http.Client
aksk aksk.SignOptions
@@ -243,7 +268,7 @@ type akClient struct {
func (self *akClient) Do(req *http.Request) (*http.Response, error) {
req.Header.Del("Accept")
if req.Method == string(httputils.GET) {
if req.Method == string(httputils.GET) || req.Method == string(httputils.DELETE) {
req.Header.Del("Content-Length")
}
aksk.Sign(req, self.aksk)
+3 -7
View File
@@ -430,17 +430,13 @@ func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
return nil, nil
}
eips, err := self.host.zone.region.GetEips()
eips, err := self.host.zone.region.GetEips("", ips)
if err != nil {
return nil, err
}
for _, eip := range eips {
if eip.PublicIPAddress == ips[0] {
return &eip, nil
}
if len(eips) > 0 {
return &eips[0], nil
}
return nil, nil
}
+25 -9
View File
@@ -176,15 +176,11 @@ func (self *SLoadbalancer) GetNetwork() *SNetwork {
func (self *SLoadbalancer) GetEip() *SEipAddress {
if self.eip == nil {
eips, _ := self.region.GetEips()
eips, _ := self.region.GetEips(self.VipPortID, nil)
for i := range eips {
eip := &eips[i]
if eip.PortId == self.VipPortID {
self.eip = eip
}
self.eip = &eips[i]
}
}
return self.eip
}
@@ -536,6 +532,26 @@ func (self *SRegion) lbList(resource string, query url.Values) (jsonutils.JSONOb
return self.client.lbList(self.ID, resource, query)
}
func (self *SRegion) vpcList(resource string, query url.Values) (jsonutils.JSONObject, error) {
return self.client.vpcList(self.ID, resource, query)
}
func (self *SRegion) vpcCreate(resource string, params map[string]interface{}) (jsonutils.JSONObject, error) {
return self.client.vpcCreate(self.ID, resource, params)
}
func (self *SRegion) vpcGet(resource string) (jsonutils.JSONObject, error) {
return self.client.vpcGet(self.ID, resource)
}
func (self *SRegion) vpcDelete(resource string) (jsonutils.JSONObject, error) {
return self.client.vpcDelete(self.ID, resource)
}
func (self *SRegion) vpcUpdate(resource string, params map[string]interface{}) (jsonutils.JSONObject, error) {
return self.client.vpcUpdate(self.ID, resource, params)
}
func (self *SRegion) lbListAll(resource string, query url.Values, respKey string, retVal interface{}) error {
ret := jsonutils.NewArray()
for {
@@ -562,15 +578,15 @@ func (self *SRegion) lbGet(resource string) (jsonutils.JSONObject, error) {
}
func (self *SRegion) lbDelete(resource string) (jsonutils.JSONObject, error) {
return self.client.lbGet(self.ID, resource)
return self.client.lbDelete(self.ID, resource)
}
func (self *SRegion) lbCreate(resource string, params map[string]interface{}) (jsonutils.JSONObject, error) {
return self.client.lbGet(self.ID, resource)
return self.client.lbCreate(self.ID, resource, params)
}
func (self *SRegion) lbUpdate(resource string, params map[string]interface{}) (jsonutils.JSONObject, error) {
return self.client.lbUpdate(self.ID, resource)
return self.client.lbUpdate(self.ID, resource, params)
}
// https://support.huaweicloud.com/api-elb/zh-cn_topic_0096561535.html
+8 -30
View File
@@ -340,41 +340,16 @@ func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
return self.ivpcs, nil
}
func (self *SRegion) GetEipById(eipId string) (SEipAddress, error) {
var eip SEipAddress
err := DoGet(self.ecsClient.Eips.Get, eipId, nil, &eip)
eip.region = self
return eip, err
}
// 返回参数分别为eip 列表、列表长度、error。
// https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090598.html
func (self *SRegion) GetEips() ([]SEipAddress, error) {
querys := make(map[string]string)
eips := make([]SEipAddress, 0)
err := doListAllWithMarker(self.ecsClient.Eips.List, querys, &eips)
for i := range eips {
eips[i].region = self
}
return eips, err
}
func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
_, err := self.getECSClient()
eips, err := self.GetEips("", nil)
if err != nil {
return nil, err
}
eips, err := self.GetEips()
if err != nil {
return nil, err
}
ret := make([]cloudprovider.ICloudEIP, len(eips))
ret := []cloudprovider.ICloudEIP{}
for i := 0; i < len(eips); i += 1 {
eips[i].region = self
ret[i] = &eips[i]
ret = append(ret, &eips[i])
}
return ret, nil
}
@@ -406,8 +381,11 @@ func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
}
func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
eip, err := self.GetEipById(eipId)
return &eip, err
eip, err := self.GetEip(eipId)
if err != nil {
return nil, err
}
return eip, nil
}
// https://support.huaweicloud.com/api-vpc/zh-cn_topic_0060595555.html
+17 -11
View File
@@ -21,9 +21,11 @@ import (
func init() {
type EipListOptions struct {
PortId string
Addrs []string
}
shellutils.R(&EipListOptions{}, "eip-list", "List eips", func(cli *huawei.SRegion, args *EipListOptions) error {
eips, e := cli.GetEips()
eips, e := cli.GetEips(args.PortId, args.Addrs)
if e != nil {
return e
}
@@ -32,13 +34,14 @@ func init() {
})
type EipAllocateOptions struct {
NAME string `help:"eip name"`
BW int `help:"Bandwidth limit in Mbps"`
BGP string `help:"bgp type" choices:"5_telcom|5_union|5_bgp|5_sbgp"`
ProjectId string
NAME string `help:"eip name"`
BW int `help:"Bandwidth limit in Mbps"`
BGP string `help:"bgp type" choices:"5_telcom|5_union|5_bgp|5_sbgp"`
ChargeType string `help:"eip charge type" default:"traffic" choices:"traffic|bandwidth"`
ProjectId string
}
shellutils.R(&EipAllocateOptions{}, "eip-create", "Allocate an EIP", func(cli *huawei.SRegion, args *EipAllocateOptions) error {
eip, err := cli.AllocateEIP(args.NAME, args.BW, huawei.InternetChargeByTraffic, args.BGP, args.ProjectId)
eip, err := cli.AllocateEIP(args.NAME, args.BW, huawei.TInternetChargeType(args.ChargeType), args.BGP, args.ProjectId)
if err != nil {
return err
}
@@ -59,11 +62,14 @@ func init() {
INSTANCE string `help:"Instance ID"`
}
shellutils.R(&EipAssociateOptions{}, "eip-associate", "Associate an EIP", func(cli *huawei.SRegion, args *EipAssociateOptions) error {
err := cli.AssociateEip(args.ID, args.INSTANCE)
return err
return cli.AssociateEip(args.ID, args.INSTANCE)
})
shellutils.R(&EipAssociateOptions{}, "eip-dissociate", "Dissociate an EIP", func(cli *huawei.SRegion, args *EipAssociateOptions) error {
err := cli.DissociateEip(args.ID, args.INSTANCE)
return err
type EipDissociateOptions struct {
ID string `help:"EIP allocation ID"`
}
shellutils.R(&EipDissociateOptions{}, "eip-dissociate", "Dissociate an EIP", func(cli *huawei.SRegion, args *EipDissociateOptions) error {
return cli.DissociateEip(args.ID)
})
}