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 }