yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/google/eip.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 google 16 17 import ( 18 "fmt" 19 "time" 20 21 "yunion.io/x/jsonutils" 22 "yunion.io/x/log" 23 "yunion.io/x/pkg/errors" 24 25 billing "yunion.io/x/cloudmux/pkg/apis/billing" 26 api "yunion.io/x/cloudmux/pkg/apis/compute" 27 "yunion.io/x/cloudmux/pkg/cloudprovider" 28 "yunion.io/x/cloudmux/pkg/multicloud" 29 ) 30 31 type SAddress struct { 32 region *SRegion 33 SResourceBase 34 multicloud.SEipBase 35 GoogleTags 36 instanceId string 37 38 CreationTimestamp time.Time 39 Description string 40 Address string 41 Status string 42 Region string 43 Users []string 44 NetworkTier string 45 AddressType string 46 Kind string 47 } 48 49 func (region *SRegion) GetEips(address string, maxResults int, pageToken string) ([]SAddress, error) { 50 eips := []SAddress{} 51 params := map[string]string{} 52 if len(address) > 0 { 53 params["filter"] = fmt.Sprintf(`address="%s"`, address) 54 } 55 resource := fmt.Sprintf("regions/%s/addresses", region.Name) 56 return eips, region.List(resource, params, maxResults, pageToken, &eips) 57 } 58 59 func (region *SRegion) GetEip(id string) (*SAddress, error) { 60 eip := &SAddress{region: region} 61 return eip, region.Get("addresses", id, eip) 62 } 63 64 func (addr *SAddress) GetStatus() string { 65 switch addr.Status { 66 case "RESERVING": 67 return api.EIP_STATUS_ASSOCIATE 68 case "RESERVED": 69 return api.EIP_STATUS_READY 70 case "IN_USE": 71 return api.EIP_STATUS_READY 72 default: 73 log.Errorf("Unknown eip status: %s", addr.Status) 74 return api.EIP_STATUS_UNKNOWN 75 } 76 } 77 78 func (addr *SAddress) GetProjectId() string { 79 return addr.region.GetProjectId() 80 } 81 82 func (addr *SAddress) IsEmulated() bool { 83 return len(addr.instanceId) > 0 84 } 85 86 func (addr *SAddress) GetCreatedAt() time.Time { 87 return addr.CreationTimestamp 88 } 89 90 func (addr *SAddress) GetExpiredAt() time.Time { 91 return time.Time{} 92 } 93 94 func (addr *SAddress) GetBillingType() string { 95 return billing.BILLING_TYPE_POSTPAID 96 } 97 98 func (self *SAddress) Refresh() error { 99 if self.IsEmulated() { 100 return nil 101 } 102 addr, err := self.region.GetEip(self.Id) 103 if err != nil { 104 return err 105 } 106 return jsonutils.Update(self, addr) 107 } 108 109 func (addr *SAddress) GetIpAddr() string { 110 return addr.Address 111 } 112 113 func (addr *SAddress) GetMode() string { 114 if addr.IsEmulated() { 115 return api.EIP_MODE_INSTANCE_PUBLICIP 116 } 117 return api.EIP_MODE_STANDALONE_EIP 118 } 119 120 func (addr *SAddress) GetINetworkId() string { 121 return "" 122 } 123 124 func (addr *SAddress) GetAssociationType() string { 125 if len(addr.GetAssociationExternalId()) > 0 { 126 return api.EIP_ASSOCIATE_TYPE_SERVER 127 } 128 return "" 129 } 130 131 func (addr *SAddress) GetAssociationExternalId() string { 132 if len(addr.instanceId) > 0 { 133 return addr.instanceId 134 } 135 if len(addr.Users) > 0 { 136 res := &SResourceBase{} 137 err := addr.region.GetBySelfId(addr.Users[0], res) 138 if err != nil { 139 return "" 140 } 141 return res.GetGlobalId() 142 } 143 return "" 144 } 145 146 func (addr *SAddress) GetBandwidth() int { 147 return 0 148 } 149 150 func (addr *SAddress) GetInternetChargeType() string { 151 return api.EIP_CHARGE_TYPE_BY_TRAFFIC 152 } 153 154 func (addr *SAddress) Delete() error { 155 return addr.region.Delete(addr.SelfLink) 156 } 157 158 func (addr *SAddress) Associate(conf *cloudprovider.AssociateConfig) error { 159 return addr.region.AssociateInstanceEip(conf.InstanceId, addr.Address) 160 } 161 162 func (addr *SAddress) Dissociate() error { 163 if len(addr.Users) > 0 { 164 return addr.region.DissociateInstanceEip(addr.Users[0], addr.Address) 165 } 166 return nil 167 } 168 169 func (addr *SAddress) ChangeBandwidth(bw int) error { 170 return cloudprovider.ErrNotSupported 171 } 172 173 func (region *SRegion) CreateEip(name string, desc string) (*SAddress, error) { 174 body := map[string]string{ 175 "name": name, 176 "description": desc, 177 } 178 resource := fmt.Sprintf("regions/%s/addresses", region.Name) 179 addr := &SAddress{region: region} 180 err := region.Insert(resource, jsonutils.Marshal(body), addr) 181 if err != nil { 182 return nil, err 183 } 184 return addr, nil 185 } 186 187 func (region *SRegion) AssociateInstanceEip(instanceId string, eip string) error { 188 instance, err := region.GetInstance(instanceId) 189 if err != nil { 190 return errors.Wrap(err, "region.GetInstance") 191 } 192 for _, networkInterface := range instance.NetworkInterfaces { 193 body := map[string]interface{}{ 194 "type": "ONE_TO_ONE_NAT", 195 "name": "External NAT", 196 "natIP": eip, 197 } 198 params := map[string]string{"networkInterface": networkInterface.Name} 199 return region.Do(instance.SelfLink, "addAccessConfig", params, jsonutils.Marshal(body)) 200 } 201 return fmt.Errorf("no valid networkinterface to associate") 202 } 203 204 func (self *SRegion) DissociateInstanceEip(instanceId string, eip string) error { 205 instance := SInstance{} 206 err := self.GetBySelfId(instanceId, &instance) 207 if err != nil { 208 return errors.Wrap(err, "region.GetInstance") 209 } 210 for _, networkInterface := range instance.NetworkInterfaces { 211 for _, accessConfig := range networkInterface.AccessConfigs { 212 if accessConfig.NatIP == eip { 213 body := map[string]string{} 214 params := map[string]string{ 215 "networkInterface": networkInterface.Name, 216 "accessConfig": accessConfig.Name, 217 } 218 return self.Do(instance.SelfLink, "deleteAccessConfig", params, jsonutils.Marshal(body)) 219 } 220 } 221 } 222 return nil 223 }