github.com/sacloud/iaas-api-go@v1.12.0/fake/pool.go (about)

     1  // Copyright 2022-2023 The sacloud/iaas-api-go Authors
     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 fake
    16  
    17  import (
    18  	"math"
    19  	"net"
    20  	"sync"
    21  
    22  	"github.com/sacloud/iaas-api-go"
    23  	"github.com/sacloud/iaas-api-go/types"
    24  	"github.com/sacloud/packages-go/cidr"
    25  )
    26  
    27  const (
    28  	valuePoolMagicID     = types.ID(math.MaxInt64)
    29  	valuePoolResourceKey = "meta"
    30  )
    31  
    32  func pool() *valuePool {
    33  	InitDataStore()
    34  	return vp
    35  }
    36  
    37  var vp *valuePool
    38  
    39  type valuePool struct {
    40  	CurrentID            int64
    41  	CurrentSharedIP      net.IP
    42  	SharedNetMaskLen     int
    43  	SharedDefaultGateway net.IP
    44  	CurrentMACAddress    net.HardwareAddr
    45  	CurrentSubnets       map[int]string
    46  	dataStore            Store
    47  	mu                   sync.Mutex
    48  }
    49  
    50  var poolMu sync.Mutex
    51  
    52  func initValuePool(s Store) *valuePool {
    53  	poolMu.Lock()
    54  	defer poolMu.Unlock()
    55  
    56  	v := s.Get(valuePoolResourceKey, iaas.APIDefaultZone, valuePoolMagicID)
    57  	if v != nil {
    58  		vp = v.(*valuePool)
    59  		vp.dataStore = s
    60  		return vp
    61  	}
    62  
    63  	vp = &valuePool{
    64  		CurrentID:            int64(100000000000),
    65  		CurrentSharedIP:      net.IP{192, 0, 2, 2},
    66  		SharedNetMaskLen:     24,
    67  		SharedDefaultGateway: net.IP{192, 0, 2, 1},
    68  		CurrentMACAddress:    net.HardwareAddr{0x00, 0x00, 0x5E, 0x00, 0x53, 0x00},
    69  		CurrentSubnets: map[int]string{
    70  			24: "24.0.0.0/24",
    71  			25: "25.0.0.0/25",
    72  			26: "26.0.0.0/26",
    73  			27: "27.0.0.0/27",
    74  			28: "28.0.0.0/28",
    75  		},
    76  		dataStore: s,
    77  	}
    78  	return vp
    79  }
    80  
    81  func (p *valuePool) store() {
    82  	p.dataStore.Put(valuePoolResourceKey, iaas.APIDefaultZone, valuePoolMagicID, p)
    83  }
    84  
    85  func (p *valuePool) generateID() types.ID {
    86  	p.mu.Lock()
    87  	defer p.mu.Unlock()
    88  
    89  	p.CurrentID++
    90  
    91  	p.store()
    92  	return types.ID(p.CurrentID)
    93  }
    94  
    95  func (p *valuePool) nextSharedIP() net.IP {
    96  	p.mu.Lock()
    97  	defer p.mu.Unlock()
    98  
    99  	ip := p.CurrentSharedIP.To4()
   100  	ip[3]++
   101  	p.CurrentSharedIP = ip
   102  	p.store()
   103  
   104  	ret := net.IP{0x00, 0x00, 0x00, 0x00}
   105  	copy(ret, ip)
   106  	return ret
   107  }
   108  
   109  func (p *valuePool) nextMACAddress() net.HardwareAddr {
   110  	p.mu.Lock()
   111  	defer p.mu.Unlock()
   112  
   113  	mac := []byte(p.CurrentMACAddress)
   114  	mac[5]++
   115  	p.CurrentMACAddress = mac
   116  	p.store()
   117  
   118  	ret := net.HardwareAddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
   119  	copy(ret, mac)
   120  	return ret
   121  }
   122  
   123  func (p *valuePool) nextSubnet(maskLen int) *assignedSubnet {
   124  	p.mu.Lock()
   125  	defer p.mu.Unlock()
   126  
   127  	_, currentSubnet, _ := net.ParseCIDR(p.CurrentSubnets[maskLen])
   128  	next, _ := cidr.NextSubnet(currentSubnet, maskLen) // ignore result
   129  	p.CurrentSubnets[maskLen] = next.String()
   130  
   131  	count := cidr.AddressCount(next)
   132  	current := next.IP
   133  	var defaultGateway, networkAddr string
   134  
   135  	var addresses []string
   136  	for i := uint64(0); i < count; i++ {
   137  		// [0]: ネットワークアドレス
   138  		// [1:3]: ルータ自身が利用
   139  		// [len]: ブロードキャスト
   140  		if i < 4 || i == count-1 {
   141  			if i == 0 {
   142  				networkAddr = current.String()
   143  			}
   144  			if i == 1 {
   145  				defaultGateway = current.String()
   146  			}
   147  			current = cidr.Inc(current)
   148  			continue
   149  		}
   150  		addresses = append(addresses, current.String())
   151  		current = cidr.Inc(current)
   152  	}
   153  
   154  	p.store()
   155  	return &assignedSubnet{
   156  		defaultRoute:   defaultGateway,
   157  		networkAddress: networkAddr,
   158  		networkMaskLen: maskLen,
   159  		addresses:      addresses,
   160  	}
   161  }
   162  
   163  func (p *valuePool) nextSubnetFull(maskLen int, defaultRoute string) *assignedSubnet {
   164  	p.mu.Lock()
   165  	defer p.mu.Unlock()
   166  
   167  	_, currentSubnet, _ := net.ParseCIDR(p.CurrentSubnets[maskLen])
   168  	next, _ := cidr.NextSubnet(currentSubnet, maskLen) // ignore result
   169  	p.CurrentSubnets[maskLen] = next.String()
   170  
   171  	count := cidr.AddressCount(next)
   172  	current := next.IP
   173  	var networkAddr string
   174  
   175  	var addresses []string
   176  	for i := uint64(0); i < count; i++ {
   177  		addresses = append(addresses, current.String())
   178  		current = cidr.Inc(current)
   179  	}
   180  
   181  	p.store()
   182  	return &assignedSubnet{
   183  		defaultRoute:   defaultRoute,
   184  		networkAddress: networkAddr,
   185  		networkMaskLen: maskLen,
   186  		addresses:      addresses,
   187  	}
   188  }
   189  
   190  type assignedSubnet struct {
   191  	defaultRoute   string
   192  	networkMaskLen int
   193  	networkAddress string
   194  	addresses      []string
   195  }