subnet_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. // Copyright 2015 flannel 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. package etcdv2
  15. import (
  16. "encoding/json"
  17. "reflect"
  18. "testing"
  19. "time"
  20. etcd "github.com/coreos/etcd/client"
  21. "github.com/coreos/flannel/pkg/ip"
  22. . "github.com/coreos/flannel/subnet"
  23. "github.com/jonboulle/clockwork"
  24. "golang.org/x/net/context"
  25. )
  26. func newDummyRegistry() *MockSubnetRegistry {
  27. attrs := LeaseAttrs{
  28. PublicIP: ip.MustParseIP4("1.1.1.1"),
  29. }
  30. exp := time.Time{}
  31. subnets := []Lease{
  32. // leases within SubnetMin-SubnetMax range
  33. {ip.IP4Net{ip.MustParseIP4("10.3.1.0"), 24}, attrs, exp, 10},
  34. {ip.IP4Net{ip.MustParseIP4("10.3.2.0"), 24}, attrs, exp, 11},
  35. {ip.IP4Net{ip.MustParseIP4("10.3.4.0"), 24}, attrs, exp, 12},
  36. {ip.IP4Net{ip.MustParseIP4("10.3.5.0"), 24}, attrs, exp, 13},
  37. // hand created lease outside the range of subnetMin-SubnetMax for testing removal
  38. {ip.IP4Net{ip.MustParseIP4("10.3.31.0"), 24}, attrs, exp, 13},
  39. }
  40. config := `{ "Network": "10.3.0.0/16", "SubnetMin": "10.3.1.0", "SubnetMax": "10.3.25.0" }`
  41. return NewMockRegistry(config, subnets)
  42. }
  43. func TestAcquireLease(t *testing.T) {
  44. msr := newDummyRegistry()
  45. sm := NewMockManager(msr)
  46. extIaddr, _ := ip.ParseIP4("1.2.3.4")
  47. attrs := LeaseAttrs{
  48. PublicIP: extIaddr,
  49. }
  50. l, err := sm.AcquireLease(context.Background(), &attrs)
  51. if err != nil {
  52. t.Fatal("AcquireLease failed: ", err)
  53. }
  54. if !inAllocatableRange(context.Background(), sm, l.Subnet) {
  55. t.Fatal("Subnet mismatch: expected 10.3.3.0/24, got: ", l.Subnet)
  56. }
  57. // Acquire again, should reuse
  58. l2, err := sm.AcquireLease(context.Background(), &attrs)
  59. if err != nil {
  60. t.Fatal("AcquireLease failed: ", err)
  61. }
  62. if !l.Subnet.Equal(l2.Subnet) {
  63. t.Fatalf("AcquireLease did not reuse subnet; expected %v, got %v", l.Subnet, l2.Subnet)
  64. }
  65. // Test if a previous subnet will be used
  66. msr2 := newDummyRegistry()
  67. prevSubnet := ip.IP4Net{ip.MustParseIP4("10.3.6.0"), 24}
  68. sm2 := NewMockManagerWithSubnet(msr2, prevSubnet)
  69. prev, err := sm2.AcquireLease(context.Background(), &attrs)
  70. if err != nil {
  71. t.Fatal("AcquireLease failed: ", err)
  72. }
  73. if !prev.Subnet.Equal(prevSubnet) {
  74. t.Fatalf("AcquireLease did not reuse subnet from previous run; expected %v, got %v", prevSubnet, prev.Subnet)
  75. }
  76. // Test that a previous subnet will not be used if it does not match the registry config
  77. msr3 := newDummyRegistry()
  78. invalidSubnet := ip.IP4Net{ip.MustParseIP4("10.4.1.0"), 24}
  79. sm3 := NewMockManagerWithSubnet(msr3, invalidSubnet)
  80. l3, err := sm3.AcquireLease(context.Background(), &attrs)
  81. if err != nil {
  82. t.Fatal("AcquireLease failed: ", err)
  83. }
  84. if l3.Subnet.Equal(invalidSubnet) {
  85. t.Fatalf("AcquireLease reused invalid subnet from previous run; reused %v", l3.Subnet)
  86. }
  87. }
  88. func TestConfigChanged(t *testing.T) {
  89. msr := newDummyRegistry()
  90. sm := NewMockManager(msr)
  91. extIaddr, _ := ip.ParseIP4("1.2.3.4")
  92. attrs := LeaseAttrs{
  93. PublicIP: extIaddr,
  94. }
  95. l, err := sm.AcquireLease(context.Background(), &attrs)
  96. if err != nil {
  97. t.Fatal("AcquireLease failed: ", err)
  98. }
  99. if !inAllocatableRange(context.Background(), sm, l.Subnet) {
  100. t.Fatal("Acquired subnet outside of valid range: ", l.Subnet)
  101. }
  102. // Change config
  103. config := `{ "Network": "10.4.0.0/16" }`
  104. msr.setConfig(config)
  105. // Acquire again, should not reuse
  106. if l, err = sm.AcquireLease(context.Background(), &attrs); err != nil {
  107. t.Fatal("AcquireLease failed: ", err)
  108. }
  109. if !inAllocatableRange(context.Background(), sm, l.Subnet) {
  110. t.Fatal("Acquired subnet outside of valid range: ", l.Subnet)
  111. }
  112. }
  113. func newIP4Net(ipaddr string, prefix uint) ip.IP4Net {
  114. a, err := ip.ParseIP4(ipaddr)
  115. if err != nil {
  116. panic("failed to parse ipaddr")
  117. }
  118. return ip.IP4Net{
  119. IP: a,
  120. PrefixLen: prefix,
  121. }
  122. }
  123. func acquireLease(ctx context.Context, t *testing.T, sm Manager) *Lease {
  124. extIaddr, _ := ip.ParseIP4("1.2.3.4")
  125. attrs := LeaseAttrs{
  126. PublicIP: extIaddr,
  127. }
  128. l, err := sm.AcquireLease(ctx, &attrs)
  129. if err != nil {
  130. t.Fatal("AcquireLease failed: ", err)
  131. }
  132. return l
  133. }
  134. func TestWatchLeaseAdded(t *testing.T) {
  135. msr := newDummyRegistry()
  136. sm := NewMockManager(msr)
  137. ctx, cancel := context.WithCancel(context.Background())
  138. defer cancel()
  139. l := acquireLease(ctx, t, sm)
  140. events := make(chan []Event)
  141. go WatchLeases(ctx, sm, l, events)
  142. evtBatch := <-events
  143. for _, evt := range evtBatch {
  144. if evt.Lease.Key() == l.Key() {
  145. t.Errorf("WatchLeases returned our own lease")
  146. }
  147. }
  148. expected := ip.IP4Net{
  149. IP: ip.MustParseIP4("10.3.30.0"),
  150. PrefixLen: 24,
  151. }
  152. // Sanity check to make sure acquired lease is not this.
  153. // It shouldn't be as SubnetMin/SubnetMax in config is [10.3.1.0/24 to 10.3.25.0/24]
  154. if l.Subnet.Equal(expected) {
  155. t.Fatalf("Acquired lease conflicts with one about to create")
  156. }
  157. attrs := &LeaseAttrs{
  158. PublicIP: ip.MustParseIP4("1.1.1.1"),
  159. }
  160. _, err := msr.createSubnet(ctx, expected, attrs, 0)
  161. if err != nil {
  162. t.Fatalf("createSubnet filed: %v", err)
  163. }
  164. evtBatch = <-events
  165. if len(evtBatch) != 1 {
  166. t.Fatalf("WatchLeases produced wrong sized event batch: got %v, expected 1", len(evtBatch))
  167. }
  168. evt := evtBatch[0]
  169. if evt.Type != EventAdded {
  170. t.Fatalf("WatchLeases produced wrong event type")
  171. }
  172. actual := evt.Lease.Subnet
  173. if !actual.Equal(expected) {
  174. t.Errorf("WatchSubnet produced wrong subnet: expected %s, got %s", expected, actual)
  175. }
  176. }
  177. func TestWatchLeaseRemoved(t *testing.T) {
  178. msr := newDummyRegistry()
  179. sm := NewMockManager(msr)
  180. ctx, cancel := context.WithCancel(context.Background())
  181. defer cancel()
  182. l := acquireLease(ctx, t, sm)
  183. events := make(chan []Event)
  184. go WatchLeases(ctx, sm, l, events)
  185. evtBatch := <-events
  186. for _, evt := range evtBatch {
  187. if evt.Lease.Key() == l.Key() {
  188. t.Errorf("WatchLeases returned our own lease")
  189. }
  190. }
  191. expected := ip.IP4Net{ip.MustParseIP4("10.3.31.0"), 24}
  192. // Sanity check to make sure acquired lease is not this.
  193. // It shouldn't be as SubnetMin/SubnetMax in config is [10.3.1.0/24 to 10.3.25.0/24]
  194. if l.Subnet.Equal(expected) {
  195. t.Fatalf("Acquired lease conflicts with one about to create")
  196. }
  197. msr.expireSubnet("_", expected)
  198. evtBatch = <-events
  199. if len(evtBatch) != 1 {
  200. t.Fatalf("WatchLeases produced wrong sized event batch: %#v", evtBatch)
  201. }
  202. evt := evtBatch[0]
  203. if evt.Type != EventRemoved {
  204. t.Fatalf("WatchLeases produced wrong event type")
  205. }
  206. actual := evt.Lease.Subnet
  207. if !actual.Equal(expected) {
  208. t.Errorf("WatchSubnet produced wrong subnet: expected %s, got %s", expected, actual)
  209. }
  210. }
  211. type leaseData struct {
  212. Dummy string
  213. }
  214. func TestRenewLease(t *testing.T) {
  215. msr := newDummyRegistry()
  216. sm := NewMockManager(msr)
  217. now := time.Now()
  218. fakeClock := clockwork.NewFakeClockAt(now)
  219. clock = fakeClock
  220. // Create LeaseAttrs
  221. extIaddr, _ := ip.ParseIP4("1.2.3.4")
  222. attrs := LeaseAttrs{
  223. PublicIP: extIaddr,
  224. BackendType: "vxlan",
  225. }
  226. ld, err := json.Marshal(&leaseData{Dummy: "test string"})
  227. if err != nil {
  228. t.Fatalf("Failed to marshal leaseData: %v", err)
  229. }
  230. attrs.BackendData = json.RawMessage(ld)
  231. // Acquire lease
  232. ctx, cancel := context.WithCancel(context.Background())
  233. defer cancel()
  234. l, err := sm.AcquireLease(ctx, &attrs)
  235. if err != nil {
  236. t.Fatal("AcquireLease failed: ", err)
  237. }
  238. now = now.Add(subnetTTL)
  239. fakeClock.Advance(24 * time.Hour)
  240. if err := sm.RenewLease(ctx, l); err != nil {
  241. t.Fatal("RenewLease failed: ", err)
  242. }
  243. // check that it's still good
  244. n, err := msr.getNetwork(ctx)
  245. if err != nil {
  246. t.Errorf("Failed to renew lease: could not get networks: %v", err)
  247. }
  248. for _, sn := range n.subnets {
  249. if sn.Subnet.Equal(l.Subnet) {
  250. expected := now.Add(subnetTTL)
  251. if !sn.Expiration.Equal(expected) {
  252. t.Errorf("Failed to renew lease: bad expiration; expected %v, got %v", expected, sn.Expiration)
  253. }
  254. if !reflect.DeepEqual(sn.Attrs, attrs) {
  255. t.Errorf("LeaseAttrs changed: was %#v, now %#v", attrs, sn.Attrs)
  256. }
  257. return
  258. }
  259. }
  260. t.Fatal("Failed to find acquired lease")
  261. }
  262. func TestLeaseRevoked(t *testing.T) {
  263. msr := newDummyRegistry()
  264. sm := NewMockManager(msr)
  265. ctx, cancel := context.WithCancel(context.Background())
  266. defer cancel()
  267. l := acquireLease(ctx, t, sm)
  268. if err := sm.RevokeLease(ctx, l.Subnet); err != nil {
  269. t.Fatalf("RevokeLease failed: %v", err)
  270. }
  271. _, _, err := msr.getSubnet(ctx, l.Subnet)
  272. if err == nil {
  273. t.Fatalf("Revoked lease still exists")
  274. }
  275. if etcdErr, ok := err.(etcd.Error); ok && etcdErr.Code != etcd.ErrorCodeKeyNotFound {
  276. t.Fatalf("getSubnets after revoked lease returned unexpected error: %v", err)
  277. }
  278. }
  279. func TestAddReservation(t *testing.T) {
  280. msr := newDummyRegistry()
  281. sm := NewMockManager(msr)
  282. ctx, cancel := context.WithCancel(context.Background())
  283. defer cancel()
  284. r := Reservation{
  285. Subnet: newIP4Net("10.4.3.0", 24),
  286. PublicIP: ip.MustParseIP4("52.195.12.13"),
  287. }
  288. if err := sm.AddReservation(ctx, &r); err == nil {
  289. t.Fatalf("unexpectedly added a reservation outside of configured network")
  290. }
  291. r.Subnet = newIP4Net("10.3.10.0", 24)
  292. if err := sm.AddReservation(ctx, &r); err != nil {
  293. t.Fatalf("failed to add reservation: %v", err)
  294. }
  295. // Add the same reservation -- should succeed
  296. if err := sm.AddReservation(ctx, &r); err != nil {
  297. t.Fatalf("failed to add reservation: %v", err)
  298. }
  299. // Add a reservation with a different public IP -- should fail
  300. r2 := r
  301. r2.PublicIP = ip.MustParseIP4("52.195.12.17")
  302. if err := sm.AddReservation(ctx, &r2); err != ErrLeaseTaken {
  303. t.Fatalf("taken add reservation returned: %v", err)
  304. }
  305. attrs := &LeaseAttrs{
  306. PublicIP: r.PublicIP,
  307. }
  308. l, err := sm.AcquireLease(ctx, attrs)
  309. if err != nil {
  310. t.Fatalf("failed to acquire subnet: %v", err)
  311. }
  312. if !l.Subnet.Equal(r.Subnet) {
  313. t.Fatalf("acquired subnet is not the reserved one: expected %v, got %v", r.Subnet, l.Subnet)
  314. }
  315. if !l.Expiration.IsZero() {
  316. t.Fatalf("acquired lease (prev reserved) has expiration set")
  317. }
  318. }
  319. func TestRemoveReservation(t *testing.T) {
  320. msr := newDummyRegistry()
  321. sm := NewMockManager(msr)
  322. ctx, cancel := context.WithCancel(context.Background())
  323. defer cancel()
  324. r := Reservation{
  325. Subnet: newIP4Net("10.3.10.0", 24),
  326. PublicIP: ip.MustParseIP4("52.195.12.13"),
  327. }
  328. if err := sm.AddReservation(ctx, &r); err != nil {
  329. t.Fatalf("failed to add reservation: %v", err)
  330. }
  331. if err := sm.RemoveReservation(ctx, r.Subnet); err != nil {
  332. t.Fatalf("failed to remove reservation: %v", err)
  333. }
  334. // The node should have a TTL
  335. sub, _, err := msr.getSubnet(ctx, r.Subnet)
  336. if err != nil {
  337. t.Fatalf("getSubnet failed: %v", err)
  338. }
  339. if sub.Expiration.IsZero() {
  340. t.Fatalf("removed reservation resulted in no TTL")
  341. }
  342. }
  343. func TestListReservations(t *testing.T) {
  344. msr := newDummyRegistry()
  345. sm := NewMockManager(msr)
  346. ctx, cancel := context.WithCancel(context.Background())
  347. defer cancel()
  348. r1 := Reservation{
  349. Subnet: newIP4Net("10.3.10.0", 24),
  350. PublicIP: ip.MustParseIP4("52.195.12.13"),
  351. }
  352. if err := sm.AddReservation(ctx, &r1); err != nil {
  353. t.Fatalf("failed to add reservation: %v", err)
  354. }
  355. r2 := Reservation{
  356. Subnet: newIP4Net("10.3.20.0", 24),
  357. PublicIP: ip.MustParseIP4("52.195.12.14"),
  358. }
  359. if err := sm.AddReservation(ctx, &r2); err != nil {
  360. t.Fatalf("failed to add reservation: %v", err)
  361. }
  362. rs, err := sm.ListReservations(ctx)
  363. if err != nil {
  364. if len(rs) != 2 {
  365. t.Fatalf("unexpected number of reservations, expected 2, got %v", len(rs))
  366. }
  367. if !resvEqual(rs[0], r1) && !resvEqual(rs[1], r1) {
  368. t.Fatalf("reservation not found")
  369. }
  370. if !resvEqual(rs[0], r2) && !resvEqual(rs[1], r2) {
  371. t.Fatalf("reservation not found")
  372. }
  373. }
  374. }
  375. func inAllocatableRange(ctx context.Context, sm Manager, ipn ip.IP4Net) bool {
  376. cfg, err := sm.GetNetworkConfig(ctx)
  377. if err != nil {
  378. panic(err)
  379. }
  380. return ipn.IP >= cfg.SubnetMin || ipn.IP <= cfg.SubnetMax
  381. }
  382. func resvEqual(r1, r2 Reservation) bool {
  383. return r1.Subnet.Equal(r2.Subnet) && r1.PublicIP == r2.PublicIP
  384. }