yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/apsara/natstable.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 apsara
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"yunion.io/x/jsonutils"
    21  	"yunion.io/x/log"
    22  
    23  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    24  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    25  	"yunion.io/x/cloudmux/pkg/multicloud"
    26  )
    27  
    28  type SSNATTableEntry struct {
    29  	multicloud.SResourceBase
    30  	ApsaraTags
    31  	nat *SNatGetway
    32  
    33  	SnatEntryId     string
    34  	SnatEntryName   string
    35  	SnatIp          string
    36  	SnatTableId     string `json:"snat_table_id"`
    37  	SourceCIDR      string `json:"source_cidr"`
    38  	SourceVSwitchId string `json:"source_vswitch_id"`
    39  	Status          string
    40  }
    41  
    42  func (stable *SSNATTableEntry) GetName() string {
    43  	if len(stable.SnatEntryName) > 0 {
    44  		return stable.SnatEntryName
    45  	}
    46  	return stable.SnatEntryId
    47  }
    48  
    49  func (stable *SSNATTableEntry) GetId() string {
    50  	return stable.SnatEntryId
    51  }
    52  
    53  func (stable *SSNATTableEntry) GetGlobalId() string {
    54  	return stable.SnatEntryId
    55  }
    56  
    57  func (stable *SSNATTableEntry) GetStatus() string {
    58  	switch stable.Status {
    59  	case "Available":
    60  		return api.NAT_STAUTS_AVAILABLE
    61  	default:
    62  		return api.NAT_STATUS_UNKNOWN
    63  	}
    64  }
    65  
    66  func (stable *SSNATTableEntry) GetIP() string {
    67  	return stable.SnatIp
    68  }
    69  
    70  func (stable *SSNATTableEntry) GetSourceCIDR() string {
    71  	return stable.SourceCIDR
    72  }
    73  
    74  func (stable *SSNATTableEntry) GetNetworkId() string {
    75  	return stable.SourceVSwitchId
    76  }
    77  
    78  func (stable *SSNATTableEntry) Delete() error {
    79  	return stable.nat.vpc.region.DeleteSnatEntry(stable.SnatTableId, stable.GetId())
    80  }
    81  
    82  func (self *SRegion) GetSNATEntries(tableId string, offset, limit int) ([]SSNATTableEntry, int, error) {
    83  	if limit > 50 || limit <= 0 {
    84  		limit = 50
    85  	}
    86  	params := make(map[string]string)
    87  	params["RegionId"] = self.RegionId
    88  	params["PageSize"] = fmt.Sprintf("%d", limit)
    89  	params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
    90  	params["SnatTableId"] = tableId
    91  
    92  	body, err := self.vpcRequest("DescribeSnatTableEntries", params)
    93  	if err != nil {
    94  		log.Errorf("DescribeSnatTableEntries fail %s", err)
    95  		return nil, 0, err
    96  	}
    97  
    98  	if self.client.debug {
    99  		log.Debugf("%s", body.PrettyString())
   100  	}
   101  
   102  	entries := make([]SSNATTableEntry, 0)
   103  	err = body.Unmarshal(&entries, "SnatTableEntries", "SnatTableEntry")
   104  	if err != nil {
   105  		log.Errorf("Unmarshal entries fail %s", err)
   106  		return nil, 0, err
   107  	}
   108  	total, _ := body.Int("TotalCount")
   109  	return entries, int(total), nil
   110  }
   111  
   112  func (self *SRegion) GetSNATEntry(tableID, SNATEntryID string) (SSNATTableEntry, error) {
   113  	params := make(map[string]string)
   114  	params["RegionId"] = self.RegionId
   115  	params["SnatTableId"] = tableID
   116  	params["SnatEntryId"] = SNATEntryID
   117  
   118  	body, err := self.vpcRequest("DescribeSnatTableEntries", params)
   119  	if err != nil {
   120  		log.Errorf("DescribeSnatTableEntries fail %s", err)
   121  		return SSNATTableEntry{}, err
   122  	}
   123  
   124  	if self.client.debug {
   125  		log.Debugf("%s", body.PrettyString())
   126  	}
   127  
   128  	entries := make([]SSNATTableEntry, 0)
   129  	err = body.Unmarshal(&entries, "SnatTableEntries", "SnatTableEntry")
   130  	if err != nil {
   131  		log.Errorf("Unmarshal entries fail %s", err)
   132  		return SSNATTableEntry{}, err
   133  	}
   134  	if len(entries) == 0 {
   135  		return SSNATTableEntry{}, cloudprovider.ErrNotFound
   136  	}
   137  	return entries[0], nil
   138  
   139  }
   140  
   141  func (region *SRegion) CreateSNATTableEntry(rule cloudprovider.SNatSRule, tableID string) (string, error) {
   142  	params := make(map[string]string)
   143  	params["RegionId"] = region.RegionId
   144  	params["SnatTableId"] = tableID
   145  	params["SnatIp"] = rule.ExternalIP
   146  	if len(rule.NetworkID) != 0 {
   147  		params["SourceVSwitchId"] = rule.NetworkID
   148  	}
   149  	if len(rule.SourceCIDR) != 0 {
   150  		params["SourceCIDR"] = rule.SourceCIDR
   151  	}
   152  	body, err := region.vpcRequest("CreateSnatEntry", params)
   153  	if err != nil {
   154  		return "", err
   155  	}
   156  
   157  	entryID, _ := body.GetString("SnatEntryId")
   158  	return entryID, nil
   159  }
   160  
   161  func (region *SRegion) DeleteSnatEntry(tableId string, entryId string) error {
   162  	params := make(map[string]string)
   163  	params["RegionId"] = region.RegionId
   164  	params["SnatTableId"] = tableId
   165  	params["SnatEntryId"] = entryId
   166  	_, err := region.vpcRequest("DeleteSnatEntry", params)
   167  	return err
   168  }
   169  
   170  func (nat *SNatGetway) getSnatEntriesForTable(tblId string) ([]SSNATTableEntry, error) {
   171  	entries := make([]SSNATTableEntry, 0)
   172  	entryTotal := -1
   173  	for entryTotal < 0 || len(entries) < entryTotal {
   174  		parts, total, err := nat.vpc.region.GetSNATEntries(tblId, len(entries), 50)
   175  		if err != nil {
   176  			return nil, err
   177  		}
   178  		if len(parts) > 0 {
   179  			entries = append(entries, parts...)
   180  		}
   181  		entryTotal = total
   182  	}
   183  	return entries, nil
   184  }
   185  
   186  func (nat *SNatGetway) getSnatEntries() ([]SSNATTableEntry, error) {
   187  	entries := make([]SSNATTableEntry, 0)
   188  	for i := range nat.SnatTableIds.SnatTableId {
   189  		sentries, err := nat.getSnatEntriesForTable(nat.SnatTableIds.SnatTableId[i])
   190  		if err != nil {
   191  			return nil, err
   192  		}
   193  		entries = append(entries, sentries...)
   194  	}
   195  	return entries, nil
   196  }
   197  
   198  func (nat *SNatGetway) dissociateWithVswitch(vswitchId string) error {
   199  	entries, err := nat.getSnatEntries()
   200  	if err != nil {
   201  		return err
   202  	}
   203  	for i := range entries {
   204  		log.Debugf("%v", entries[i])
   205  		if entries[i].SourceVSwitchId == vswitchId {
   206  			err := nat.vpc.region.DeleteSnatEntry(entries[i].SnatTableId, entries[i].SnatEntryId)
   207  			if err != nil {
   208  				return err
   209  			}
   210  		}
   211  	}
   212  	return nil
   213  }
   214  
   215  func (stable *SSNATTableEntry) Refresh() error {
   216  	new, err := stable.nat.vpc.region.GetSNATEntry(stable.SnatTableId, stable.SnatEntryId)
   217  	if err != nil {
   218  		return err
   219  	}
   220  	return jsonutils.Update(stable, new)
   221  }