instancenic.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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. package aliyun
  15. import (
  16. "fmt"
  17. "time"
  18. alierr "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
  19. "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/util/netutils"
  22. "yunion.io/x/cloudmux/pkg/cloudprovider"
  23. )
  24. type SInstanceNic struct {
  25. instance *SInstance
  26. id string
  27. ipAddr string
  28. ip6Addr string
  29. macAddr string
  30. classic bool
  31. cloudprovider.DummyICloudNic
  32. }
  33. func (self *SInstanceNic) GetId() string {
  34. return self.id
  35. }
  36. func (self *SInstanceNic) mustGetId() string {
  37. if self.id == "" {
  38. panic("empty network interface id")
  39. }
  40. return self.id
  41. }
  42. func (self *SInstanceNic) GetIP() string {
  43. return self.ipAddr
  44. }
  45. func (self *SInstanceNic) GetIP6() string {
  46. return self.ip6Addr
  47. }
  48. func (self *SInstanceNic) GetMAC() string {
  49. if len(self.macAddr) > 0 {
  50. return self.macAddr
  51. }
  52. ip, _ := netutils.NewIPV4Addr(self.GetIP())
  53. return ip.ToMac("00:16:")
  54. }
  55. func (self *SInstanceNic) InClassicNetwork() bool {
  56. return self.classic == true
  57. }
  58. func (self *SInstanceNic) GetDriver() string {
  59. return "virtio"
  60. }
  61. func (self *SInstanceNic) GetINetworkId() string {
  62. return self.instance.VpcAttributes.VSwitchId
  63. }
  64. func (self *SInstanceNic) GetSubAddress() ([]string, error) {
  65. selfId := self.mustGetId()
  66. region := self.instance.host.zone.region
  67. params := map[string]string{
  68. "RegionId": region.GetId(),
  69. "NetworkInterfaceId.1": selfId,
  70. }
  71. body, err := region.ecsRequest("DescribeNetworkInterfaces", params)
  72. if err != nil {
  73. return nil, err
  74. }
  75. type DescribeNetworkInterfacesResponse struct {
  76. TotalCount int `json:"TotalCount"`
  77. RequestID string `json:"RequestId"`
  78. PageSize int `json:"PageSize"`
  79. NextToken string `json:"NextToken"`
  80. PageNumber int `json:"PageNumber"`
  81. NetworkInterfaceSets struct {
  82. NetworkInterfaceSet []struct {
  83. Status string `json:"Status"`
  84. PrivateIPAddress string `json:"PrivateIpAddress"`
  85. ZoneID string `json:"ZoneId"`
  86. ResourceGroupID string `json:"ResourceGroupId"`
  87. InstanceID string `json:"InstanceId"`
  88. VSwitchID string `json:"VSwitchId"`
  89. NetworkInterfaceID string `json:"NetworkInterfaceId"`
  90. MacAddress string `json:"MacAddress"`
  91. SecurityGroupIds struct {
  92. SecurityGroupID []string `json:"SecurityGroupId"`
  93. } `json:"SecurityGroupIds"`
  94. Type string `json:"Type"`
  95. Ipv6Sets struct {
  96. Ipv6Set []struct {
  97. Ipv6Address string `json:"Ipv6Address"`
  98. } `json:"Ipv6Set"`
  99. } `json:"Ipv6Sets"`
  100. VpcID string `json:"VpcId"`
  101. OwnerID string `json:"OwnerId"`
  102. AssociatedPublicIP struct {
  103. } `json:"AssociatedPublicIp"`
  104. CreationTime time.Time `json:"CreationTime"`
  105. Tags struct {
  106. Tag []struct {
  107. TagKey string `json:"TagKey"`
  108. TagValue string `json:"TagValue"`
  109. } `json:"Tag"`
  110. } `json:"Tags"`
  111. PrivateIPSets struct {
  112. PrivateIPSet []struct {
  113. PrivateIPAddress string `json:"PrivateIpAddress"`
  114. AssociatedPublicIP struct {
  115. } `json:"AssociatedPublicIp"`
  116. Primary bool `json:"Primary"`
  117. } `json:"PrivateIpSet"`
  118. } `json:"PrivateIpSets"`
  119. } `json:"NetworkInterfaceSet"`
  120. } `json:"NetworkInterfaceSets"`
  121. }
  122. var resp DescribeNetworkInterfacesResponse
  123. if err := body.Unmarshal(&resp); err != nil {
  124. return nil, errors.Wrapf(err, "unmarshal DescribeNetworkInterfacesResponse: %s", body)
  125. }
  126. if got := len(resp.NetworkInterfaceSets.NetworkInterfaceSet); got != 1 {
  127. return nil, errors.Errorf("got %d element(s) in interface set, expect 1", got)
  128. }
  129. var (
  130. ipAddrs []string
  131. networkInterface = resp.NetworkInterfaceSets.NetworkInterfaceSet[0]
  132. )
  133. if got := networkInterface.NetworkInterfaceID; got != selfId {
  134. return nil, errors.Errorf("got interface data for %s, expect %s", got, selfId)
  135. }
  136. for _, privateIP := range networkInterface.PrivateIPSets.PrivateIPSet {
  137. if !privateIP.Primary {
  138. ipAddrs = append(ipAddrs, privateIP.PrivateIPAddress)
  139. }
  140. }
  141. return ipAddrs, nil
  142. }
  143. func (self *SInstanceNic) ipAddrsParams(ipAddrs []string) map[string]string {
  144. region := self.instance.host.zone.region
  145. params := map[string]string{
  146. "RegionId": region.GetId(),
  147. "NetworkInterfaceId": self.mustGetId(),
  148. }
  149. for i, ipAddr := range ipAddrs {
  150. k := fmt.Sprintf("PrivateIpAddress.%d", i+1)
  151. params[k] = ipAddr
  152. }
  153. return params
  154. }
  155. func (self *SInstanceNic) AssignAddress(ipAddrs []string) error {
  156. var (
  157. selfId = self.mustGetId()
  158. instance = self.instance
  159. zone = instance.host.zone
  160. region = zone.region
  161. )
  162. ecsClient, err := region.getEcsClient()
  163. if err != nil {
  164. return err
  165. }
  166. request := ecs.CreateAssignPrivateIpAddressesRequest()
  167. request.Scheme = "https"
  168. request.NetworkInterfaceId = selfId
  169. request.PrivateIpAddress = &ipAddrs
  170. resp, err := ecsClient.AssignPrivateIpAddresses(request)
  171. if err != nil {
  172. if aerr, ok := err.(*alierr.ServerError); ok {
  173. if aerr.ErrorCode() == "InvalidOperation.Ipv4CountExceeded" {
  174. return errors.Wrap(cloudprovider.ErrAddressCountExceed, aerr.Message())
  175. }
  176. }
  177. return errors.Wrapf(err, "AssignPrivateIpAddresses")
  178. }
  179. allocated := resp.AssignedPrivateIpAddressesSet.PrivateIpSet.PrivateIpAddress
  180. if len(allocated) != len(ipAddrs) {
  181. return errors.Errorf("AssignAddress want %d addresses, got %d", len(ipAddrs), len(allocated))
  182. }
  183. for i := 0; i < len(ipAddrs); i++ {
  184. ip0 := ipAddrs[i]
  185. ip1 := allocated[i]
  186. if ip0 != ip1 {
  187. return errors.Errorf("AssignAddress address %d does not match: want %s, got %s", i, ip0, ip1)
  188. }
  189. }
  190. return nil
  191. }
  192. func (self *SInstanceNic) UnassignAddress(ipAddrs []string) error {
  193. var (
  194. selfId = self.mustGetId()
  195. instance = self.instance
  196. zone = instance.host.zone
  197. region = zone.region
  198. )
  199. ecsClient, err := region.getEcsClient()
  200. if err != nil {
  201. return err
  202. }
  203. request := ecs.CreateUnassignPrivateIpAddressesRequest()
  204. request.Scheme = "https"
  205. request.NetworkInterfaceId = selfId
  206. request.PrivateIpAddress = &ipAddrs
  207. resp, err := ecsClient.UnassignPrivateIpAddresses(request)
  208. if err != nil {
  209. if resp.GetHttpStatus() == 404 {
  210. return nil
  211. }
  212. return err
  213. }
  214. return nil
  215. }