kubesphere.io/api@v0.0.0-20231107125330-c9a03957060c/network/v1alpha1/ippool_types.go (about)

     1  /*
     2  Copyright 2020 The KubeSphere authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1alpha1
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  
    23  	cnet "github.com/projectcalico/calico/libcalico-go/lib/net"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  )
    26  
    27  const (
    28  	ResourceKindIPPool     = "IPPool"
    29  	ResourceSingularIPPool = "ippool"
    30  	ResourcePluralIPPool   = "ippools"
    31  
    32  	// scope type > id > name
    33  	// id used to detect cidr overlap
    34  	IPPoolTypeLabel    = "ippool.network.kubesphere.io/type"
    35  	IPPoolNameLabel    = "ippool.network.kubesphere.io/name"
    36  	IPPoolIDLabel      = "ippool.network.kubesphere.io/id"
    37  	IPPoolDefaultLabel = "ippool.network.kubesphere.io/default"
    38  
    39  	IPPoolTypeNone   = "none"
    40  	IPPoolTypeLocal  = "local"
    41  	IPPoolTypeCalico = "calico"
    42  )
    43  
    44  // +genclient
    45  // +genclient:nonNamespaced
    46  // +kubebuilder:object:root=true
    47  // +k8s:openapi-gen=true
    48  // +kubebuilder:subresource:status
    49  // +kubebuilder:resource:scope=Cluster
    50  type IPPool struct {
    51  	metav1.TypeMeta   `json:",inline"`
    52  	metav1.ObjectMeta `json:"metadata,omitempty"`
    53  
    54  	// +optional
    55  	Spec IPPoolSpec `json:"spec,omitempty"`
    56  	// +optional
    57  	Status IPPoolStatus `json:"status,omitempty"`
    58  }
    59  
    60  type VLANConfig struct {
    61  	VlanId uint32 `json:"vlanId"`
    62  	Master string `json:"master"`
    63  }
    64  
    65  type Route struct {
    66  	Dst string `json:"dst,omitempty"`
    67  	GW  string `json:"gateway,omitempty"`
    68  }
    69  
    70  // DNS contains values interesting for DNS resolvers
    71  type DNS struct {
    72  	Nameservers []string `json:"nameservers,omitempty"`
    73  	Domain      string   `json:"domain,omitempty"`
    74  	Search      []string `json:"search,omitempty"`
    75  	Options     []string `json:"options,omitempty"`
    76  }
    77  
    78  type WorkspaceStatus struct {
    79  	Allocations int `json:"allocations"`
    80  }
    81  
    82  type IPPoolStatus struct {
    83  	Unallocated int                        `json:"unallocated"`
    84  	Allocations int                        `json:"allocations"`
    85  	Capacity    int                        `json:"capacity"`
    86  	Reserved    int                        `json:"reserved,omitempty"`
    87  	Synced      bool                       `json:"synced,omitempty"`
    88  	Workspaces  map[string]WorkspaceStatus `json:"workspaces,omitempty"`
    89  }
    90  
    91  type IPPoolSpec struct {
    92  	Type string `json:"type"`
    93  
    94  	// The pool CIDR.
    95  	CIDR string `json:"cidr"`
    96  
    97  	// The first ip, inclusive
    98  	RangeStart string `json:"rangeStart,omitempty"`
    99  
   100  	// The last ip, inclusive
   101  	RangeEnd string `json:"rangeEnd,omitempty"`
   102  
   103  	// When disabled is true, IPAM will not assign addresses from this pool.
   104  	Disabled bool `json:"disabled,omitempty"`
   105  
   106  	// The block size to use for IP address assignments from this pool. Defaults to 26 for IPv4 and 112 for IPv6.
   107  	BlockSize int `json:"blockSize,omitempty"`
   108  
   109  	VLAN VLANConfig `json:"vlanConfig,omitempty"`
   110  
   111  	Gateway string  `json:"gateway,omitempty"`
   112  	Routes  []Route `json:"routes,omitempty"`
   113  	DNS     DNS     `json:"dns,omitempty"`
   114  }
   115  
   116  // +kubebuilder:object:root=true
   117  // +genclient:nonNamespaced
   118  type IPPoolList struct {
   119  	metav1.TypeMeta `json:",inline"`
   120  	metav1.ListMeta `json:"metadata,omitempty"`
   121  	Items           []IPPool `json:"items"`
   122  }
   123  
   124  const (
   125  	VLAN        = "vlan"
   126  	Calico      = "calico"
   127  	Porter      = "porter"
   128  	Pod         = "pod"
   129  	VLANIDStart = 1
   130  	VLANIDEnd   = 4097
   131  	PorterID    = 4098
   132  	CalicoID    = 4099
   133  	PodID       = 0
   134  )
   135  
   136  // Find the ordinal (i.e. how far into the block) a given IP lies.  Returns an error if the IP is outside the block.
   137  func (b IPPool) IPToOrdinal(ip cnet.IP) (int, error) {
   138  	_, cidr, _ := cnet.ParseCIDR(b.Spec.CIDR)
   139  	ipAsInt := cnet.IPToBigInt(ip)
   140  	baseInt := cnet.IPToBigInt(cnet.IP{IP: cidr.IP})
   141  	ord := big.NewInt(0).Sub(ipAsInt, baseInt).Int64()
   142  	if ord < 0 || ord >= int64(b.NumAddresses()) {
   143  		return 0, fmt.Errorf("IP %s not in pool %s", ip, b.Spec.CIDR)
   144  	}
   145  	return int(ord), nil
   146  }
   147  
   148  // Get number of addresses covered by the block
   149  func (b IPPool) NumAddresses() int {
   150  	_, cidr, _ := cnet.ParseCIDR(b.Spec.CIDR)
   151  	ones, size := cidr.Mask.Size()
   152  	numAddresses := 1 << uint(size-ones)
   153  	return numAddresses
   154  }
   155  
   156  func (b IPPool) Type() string {
   157  	if b.Spec.Type == VLAN {
   158  		return IPPoolTypeLocal
   159  	}
   160  
   161  	return b.Spec.Type
   162  }
   163  
   164  func (b IPPool) NumReservedAddresses() int {
   165  	return b.StartReservedAddressed() + b.EndReservedAddressed()
   166  }
   167  
   168  func (b IPPool) StartReservedAddressed() int {
   169  	if b.Spec.RangeStart == "" {
   170  		return 0
   171  	}
   172  	start, _ := b.IPToOrdinal(*cnet.ParseIP(b.Spec.RangeStart))
   173  	return start
   174  }
   175  
   176  func (b IPPool) EndReservedAddressed() int {
   177  	if b.Spec.RangeEnd == "" {
   178  		return 0
   179  	}
   180  	total := b.NumAddresses()
   181  	end, _ := b.IPToOrdinal(*cnet.ParseIP(b.Spec.RangeEnd))
   182  	return total - end - 1
   183  }
   184  
   185  func (b IPPool) Overlapped(dst IPPool) bool {
   186  	if b.ID() != dst.ID() {
   187  		return false
   188  	}
   189  
   190  	_, cidr, _ := cnet.ParseCIDR(b.Spec.CIDR)
   191  	_, cidrDst, _ := cnet.ParseCIDR(dst.Spec.CIDR)
   192  
   193  	return cidr.IsNetOverlap(cidrDst.IPNet)
   194  }
   195  
   196  func (pool IPPool) ID() uint32 {
   197  	switch pool.Spec.Type {
   198  	case VLAN:
   199  		return pool.Spec.VLAN.VlanId + VLANIDStart
   200  	case Porter:
   201  		return PorterID
   202  	case Calico:
   203  		return CalicoID
   204  	}
   205  
   206  	return PodID
   207  }
   208  
   209  func (p IPPool) TypeInvalid() bool {
   210  	typeStr := p.Spec.Type
   211  	if typeStr == VLAN || typeStr == Porter || typeStr == Pod {
   212  		return false
   213  	}
   214  
   215  	return true
   216  }
   217  
   218  func (p IPPool) Disabled() bool {
   219  	return p.Spec.Disabled
   220  }
   221  
   222  func (p IPPool) V4() bool {
   223  	ip, _, _ := cnet.ParseCIDR(p.Spec.CIDR)
   224  	if ip.To4() != nil {
   225  		return true
   226  	}
   227  	return false
   228  }
   229  
   230  const IPPoolFinalizer = "finalizers.network.kubesphere.io/ippool"