yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/openstack/port.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 openstack
    16  
    17  import (
    18  	"net/url"
    19  	"strings"
    20  	"time"
    21  
    22  	"yunion.io/x/pkg/errors"
    23  
    24  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    25  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    26  	"yunion.io/x/cloudmux/pkg/multicloud"
    27  )
    28  
    29  type DnsAssignment struct {
    30  	Hostname  string
    31  	IpAddress string
    32  	Fqdn      string
    33  }
    34  
    35  type ExtraDhcpOpt struct {
    36  	OptValue  string
    37  	IpVersion int
    38  	OptName   string
    39  }
    40  
    41  type SFixedIP struct {
    42  	port *SPort
    43  
    44  	IpAddress string
    45  	SubnetID  string
    46  }
    47  
    48  func (fixip *SFixedIP) GetGlobalId() string {
    49  	return fixip.IpAddress
    50  }
    51  
    52  func (fixip *SFixedIP) GetIP() string {
    53  	return fixip.IpAddress
    54  }
    55  
    56  func (fixip *SFixedIP) GetINetworkId() string {
    57  	network, err := fixip.port.region.GetNetwork(fixip.SubnetID)
    58  	if err != nil {
    59  		return ""
    60  	}
    61  	for _, pool := range network.AllocationPools {
    62  		if pool.Contains(fixip.IpAddress) {
    63  			network.AllocationPools = []AllocationPool{pool}
    64  			return network.GetGlobalId()
    65  		}
    66  	}
    67  	return ""
    68  }
    69  
    70  func (fixip *SFixedIP) IsPrimary() bool {
    71  	return true
    72  }
    73  
    74  type SPort struct {
    75  	multicloud.SNetworkInterfaceBase
    76  	OpenStackTags
    77  	region                  *SRegion
    78  	AdminStateUp            bool
    79  	AllowedAddressPairs     []string
    80  	CreatedAt               time.Time
    81  	DataPlaneStatus         string
    82  	Description             string
    83  	DeviceID                string
    84  	DeviceOwner             string
    85  	DnsAssignment           []DnsAssignment
    86  	DnsDomain               string
    87  	DnsName                 string
    88  	ExtraDhcpOpts           []ExtraDhcpOpt
    89  	FixedIps                []SFixedIP
    90  	ID                      string
    91  	IpAllocation            string
    92  	MacAddress              string
    93  	Name                    string
    94  	NetworkID               string
    95  	ProjectID               string
    96  	RevisionNumber          int
    97  	SecurityGroups          []string
    98  	Status                  string
    99  	Tags                    []string
   100  	TenantID                string
   101  	UpdatedAt               time.Time
   102  	QosPolicyID             string
   103  	PortSecurityEnabled     bool
   104  	UplinkStatusPropagation bool
   105  }
   106  
   107  func (port *SPort) GetName() string {
   108  	if len(port.Name) > 0 {
   109  		return port.Name
   110  	}
   111  	return port.ID
   112  }
   113  
   114  func (port *SPort) GetId() string {
   115  	return port.ID
   116  }
   117  
   118  func (port *SPort) GetGlobalId() string {
   119  	return port.ID
   120  }
   121  
   122  func (port *SPort) GetMacAddress() string {
   123  	return port.MacAddress
   124  }
   125  
   126  func (port *SPort) GetAssociateType() string {
   127  	switch port.DeviceOwner {
   128  	case "compute:nova":
   129  		return api.NETWORK_INTERFACE_ASSOCIATE_TYPE_SERVER
   130  	case "network:router_gateway", "network:dhcp", "network:router_interface":
   131  		return api.NETWORK_INTERFACE_ASSOCIATE_TYPE_RESERVED
   132  	}
   133  	return port.DeviceOwner
   134  }
   135  
   136  func (port *SPort) GetAssociateId() string {
   137  	return port.DeviceID
   138  }
   139  
   140  func (port *SPort) GetStatus() string {
   141  	switch port.Status {
   142  	case "ACTIVE", "DOWN":
   143  		return api.NETWORK_INTERFACE_STATUS_AVAILABLE
   144  	case "BUILD":
   145  		return api.NETWORK_INTERFACE_STATUS_CREATING
   146  	}
   147  	return port.Status
   148  }
   149  
   150  func (port *SPort) GetICloudInterfaceAddresses() ([]cloudprovider.ICloudInterfaceAddress, error) {
   151  	address := []cloudprovider.ICloudInterfaceAddress{}
   152  	for i := 0; i < len(port.FixedIps); i++ {
   153  		port.FixedIps[i].port = port
   154  		address = append(address, &port.FixedIps[i])
   155  	}
   156  	return address, nil
   157  }
   158  
   159  func (region *SRegion) GetINetworkInterfaces() ([]cloudprovider.ICloudNetworkInterface, error) {
   160  	ports, err := region.GetPorts("", "")
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  	ret := []cloudprovider.ICloudNetworkInterface{}
   165  	for i := 0; i < len(ports); i++ {
   166  		if strings.HasPrefix(ports[i].DeviceOwner, "compute:") || ports[i].DeviceOwner == "network:floatingip" {
   167  			continue
   168  		}
   169  		ports[i].region = region
   170  		ret = append(ret, &ports[i])
   171  	}
   172  	return ret, nil
   173  }
   174  
   175  func (region *SRegion) GetPort(portId string) (*SPort, error) {
   176  	resource := "/v2.0/ports/" + portId
   177  	resp, err := region.vpcGet(resource)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  	port := &SPort{}
   182  	err = resp.Unmarshal(port, "port")
   183  	if err != nil {
   184  		return nil, errors.Wrap(err, "resp.Unmarshal")
   185  	}
   186  	return port, nil
   187  }
   188  
   189  func (region *SRegion) GetPorts(macAddress, deviceId string) ([]SPort, error) {
   190  	resource, ports := "/v2.0/ports", []SPort{}
   191  	query := url.Values{}
   192  	if len(macAddress) > 0 {
   193  		query.Set("mac_address", macAddress)
   194  	}
   195  	if len(deviceId) > 0 {
   196  		query.Set("device_id", deviceId)
   197  	}
   198  	for {
   199  		resp, err := region.vpcList(resource, query)
   200  		if err != nil {
   201  			return nil, errors.Wrap(err, "vpcList")
   202  		}
   203  		part := struct {
   204  			Ports      []SPort
   205  			PortsLinks SNextLinks
   206  		}{}
   207  		err = resp.Unmarshal(&part)
   208  		if err != nil {
   209  			return nil, errors.Wrap(err, "resp.Unmarshal")
   210  		}
   211  		ports = append(ports, part.Ports...)
   212  		marker := part.PortsLinks.GetNextMark()
   213  		if len(marker) == 0 {
   214  			break
   215  		}
   216  		query.Set("marker", marker)
   217  	}
   218  	return ports, nil
   219  }