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 }