1
2
3
4
19
20 package winkernel
21
22 import (
23 "encoding/json"
24
25 "github.com/Microsoft/hcsshim/hcn"
26 "github.com/stretchr/testify/assert"
27
28 "strings"
29 "testing"
30
31 "github.com/google/go-cmp/cmp"
32 )
33
34 const (
35 sourceVip = "192.168.1.2"
36 serviceVip = "11.0.0.1"
37 addressPrefix = "192.168.1.0/24"
38 gatewayAddress = "192.168.1.1"
39 epMacAddress = "00-11-22-33-44-55"
40 epIpAddress = "192.168.1.3"
41 epIpv6Address = "192::3"
42 epIpAddressB = "192.168.1.4"
43 epIpAddressRemote = "192.168.2.3"
44 epPaAddress = "10.0.0.3"
45 protocol = 6
46 internalPort = 80
47 externalPort = 32440
48 )
49
50 func TestGetNetworkByName(t *testing.T) {
51 hns := hns{hcn: newHcnImpl()}
52 Network := mustTestNetwork(t)
53
54 network, err := hns.getNetworkByName(Network.Name)
55 if err != nil {
56 t.Error(err)
57 }
58
59 if !strings.EqualFold(network.id, Network.Id) {
60 t.Errorf("%v does not match %v", network.id, Network.Id)
61 }
62 err = Network.Delete()
63 if err != nil {
64 t.Error(err)
65 }
66 }
67
68 func TestGetAllEndpointsByNetwork(t *testing.T) {
69 hns := hns{hcn: newHcnImpl()}
70 Network := mustTestNetwork(t)
71
72 ipv4Config := &hcn.IpConfig{
73 IpAddress: epIpAddress,
74 }
75 ipv6Config := &hcn.IpConfig{
76 IpAddress: epIpv6Address,
77 }
78 Endpoint := &hcn.HostComputeEndpoint{
79 IpConfigurations: []hcn.IpConfig{*ipv4Config, *ipv6Config},
80 MacAddress: epMacAddress,
81 SchemaVersion: hcn.SchemaVersion{
82 Major: 2,
83 Minor: 0,
84 },
85 }
86 Endpoint, err := Network.CreateEndpoint(Endpoint)
87 if err != nil {
88 t.Error(err)
89 }
90
91 mapEndpointsInfo, err := hns.getAllEndpointsByNetwork(Network.Name)
92 if err != nil {
93 t.Error(err)
94 }
95 endpointIpv4, ipv4EpPresent := mapEndpointsInfo[ipv4Config.IpAddress]
96 assert.True(t, ipv4EpPresent, "IPV4 endpoint is missing in Dualstack mode")
97 assert.Equal(t, endpointIpv4.ip, epIpAddress, "IPV4 IP is missing in Dualstack mode")
98
99 endpointIpv6, ipv6EpPresent := mapEndpointsInfo[ipv6Config.IpAddress]
100 assert.True(t, ipv6EpPresent, "IPV6 endpoint is missing in Dualstack mode")
101 assert.Equal(t, endpointIpv6.ip, epIpv6Address, "IPV6 IP is missing in Dualstack mode")
102
103 err = Endpoint.Delete()
104 if err != nil {
105 t.Error(err)
106 }
107 err = Network.Delete()
108 if err != nil {
109 t.Error(err)
110 }
111 }
112
113 func TestGetEndpointByID(t *testing.T) {
114 hns := hns{hcn: newHcnImpl()}
115 Network := mustTestNetwork(t)
116
117 ipConfig := &hcn.IpConfig{
118 IpAddress: epIpAddress,
119 }
120 Endpoint := &hcn.HostComputeEndpoint{
121 IpConfigurations: []hcn.IpConfig{*ipConfig},
122 MacAddress: epMacAddress,
123 SchemaVersion: hcn.SchemaVersion{
124 Major: 2,
125 Minor: 0,
126 },
127 }
128
129 Endpoint, err := Network.CreateEndpoint(Endpoint)
130 if err != nil {
131 t.Error(err)
132 }
133
134 endpoint, err := hns.getEndpointByID(Endpoint.Id)
135 if err != nil {
136 t.Error(err)
137 }
138 if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
139 t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
140 }
141
142 err = Endpoint.Delete()
143 if err != nil {
144 t.Error(err)
145 }
146 err = Network.Delete()
147 if err != nil {
148 t.Error(err)
149 }
150 }
151
152 func TestGetEndpointByIpAddressAndName(t *testing.T) {
153 hns := hns{hcn: newHcnImpl()}
154 Network := mustTestNetwork(t)
155
156 ipConfig := &hcn.IpConfig{
157 IpAddress: epIpAddress,
158 }
159 Endpoint := &hcn.HostComputeEndpoint{
160 IpConfigurations: []hcn.IpConfig{*ipConfig},
161 MacAddress: epMacAddress,
162 SchemaVersion: hcn.SchemaVersion{
163 Major: 2,
164 Minor: 0,
165 },
166 }
167 Endpoint, err := Network.CreateEndpoint(Endpoint)
168 if err != nil {
169 t.Error(err)
170 }
171
172 endpoint, err := hns.getEndpointByIpAddress(Endpoint.IpConfigurations[0].IpAddress, Network.Name)
173 if err != nil {
174 t.Error(err)
175 }
176 if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
177 t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
178 }
179 if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress {
180 t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress)
181 }
182
183 endpoint2, err := hns.getEndpointByName(Endpoint.Name)
184 if err != nil {
185 t.Error(err)
186 }
187 diff := cmp.Diff(endpoint, endpoint2)
188 if diff != "" {
189 t.Errorf("getEndpointByName(%s) returned a different endpoint. Diff: %s ", Endpoint.Name, diff)
190 }
191
192 err = Endpoint.Delete()
193 if err != nil {
194 t.Error(err)
195 }
196 err = Network.Delete()
197 if err != nil {
198 t.Error(err)
199 }
200 }
201
202 func TestCreateEndpointLocal(t *testing.T) {
203 hns := hns{hcn: newHcnImpl()}
204 Network := mustTestNetwork(t)
205
206 endpoint := &endpointInfo{
207 ip: epIpAddress,
208 macAddress: epMacAddress,
209 isLocal: true,
210 }
211
212 endpoint, err := hns.createEndpoint(endpoint, Network.Name)
213 if err != nil {
214 t.Error(err)
215 }
216 Endpoint, err := hcn.GetEndpointByID(endpoint.hnsID)
217 if err != nil {
218 t.Error(err)
219 }
220 if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
221 t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
222 }
223 if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress {
224 t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress)
225 }
226 if endpoint.macAddress != Endpoint.MacAddress {
227 t.Errorf("%v does not match %v", endpoint.macAddress, Endpoint.MacAddress)
228 }
229
230 err = Endpoint.Delete()
231 if err != nil {
232 t.Error(err)
233 }
234 err = Network.Delete()
235 if err != nil {
236 t.Error(err)
237 }
238 }
239
240 func TestCreateEndpointRemote(t *testing.T) {
241 hns := hns{hcn: newHcnImpl()}
242 Network := mustTestNetwork(t)
243 providerAddress := epPaAddress
244
245 endpoint := &endpointInfo{
246 ip: epIpAddressRemote,
247 macAddress: epMacAddress,
248 isLocal: false,
249 providerAddress: providerAddress,
250 }
251
252 endpoint, err := hns.createEndpoint(endpoint, Network.Name)
253 if err != nil {
254 t.Error(err)
255 }
256 Endpoint, err := hcn.GetEndpointByID(endpoint.hnsID)
257 if err != nil {
258 t.Error(err)
259 }
260 if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
261 t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
262 }
263 if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress {
264 t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress)
265 }
266 if endpoint.macAddress != Endpoint.MacAddress {
267 t.Errorf("%v does not match %v", endpoint.macAddress, Endpoint.MacAddress)
268 }
269 if len(providerAddress) != 0 && endpoint.providerAddress != epPaAddress {
270 t.Errorf("%v does not match %v", endpoint.providerAddress, providerAddress)
271 }
272
273 err = Endpoint.Delete()
274 if err != nil {
275 t.Error(err)
276 }
277 err = Network.Delete()
278 if err != nil {
279 t.Error(err)
280 }
281 }
282
283 func TestDeleteEndpoint(t *testing.T) {
284 hns := hns{hcn: newHcnImpl()}
285 Network := mustTestNetwork(t)
286
287 ipConfig := &hcn.IpConfig{
288 IpAddress: epIpAddress,
289 }
290 Endpoint := &hcn.HostComputeEndpoint{
291 IpConfigurations: []hcn.IpConfig{*ipConfig},
292 MacAddress: epMacAddress,
293 SchemaVersion: hcn.SchemaVersion{
294 Major: 2,
295 Minor: 0,
296 },
297 }
298 Endpoint, err := Network.CreateEndpoint(Endpoint)
299 if err != nil {
300 t.Error(err)
301 }
302 err = hns.deleteEndpoint(Endpoint.Id)
303 if err != nil {
304 t.Error(err)
305 }
306
307 Endpoint, err = hcn.GetEndpointByID(Endpoint.Id)
308 if err == nil {
309 t.Error(err)
310 }
311
312 err = Network.Delete()
313 if err != nil {
314 t.Error(err)
315 }
316 }
317
318 func TestGetLoadBalancerExisting(t *testing.T) {
319 hns := hns{hcn: newHcnImpl()}
320 Network := mustTestNetwork(t)
321 lbs := make(map[loadBalancerIdentifier]*(loadBalancerInfo))
322
323 ipConfig := &hcn.IpConfig{
324 IpAddress: epIpAddress,
325 }
326 Endpoint := &hcn.HostComputeEndpoint{
327 IpConfigurations: []hcn.IpConfig{*ipConfig},
328 MacAddress: epMacAddress,
329 SchemaVersion: hcn.SchemaVersion{
330 Major: 2,
331 Minor: 0,
332 },
333 }
334 Endpoint, err := Network.CreateEndpoint(Endpoint)
335 if err != nil {
336 t.Error(err)
337 }
338
339 Endpoints := []hcn.HostComputeEndpoint{*Endpoint}
340 LoadBalancer, err := hcn.AddLoadBalancer(
341 Endpoints,
342 hcn.LoadBalancerFlagsNone,
343 hcn.LoadBalancerPortMappingFlagsNone,
344 sourceVip,
345 []string{serviceVip},
346 protocol,
347 internalPort,
348 externalPort,
349 )
350 if err != nil {
351 t.Error(err)
352 }
353 endpoint := &endpointInfo{
354 ip: Endpoint.IpConfigurations[0].IpAddress,
355 hnsID: Endpoint.Id,
356 }
357 endpoints := []endpointInfo{*endpoint}
358 hash, err := hashEndpoints(endpoints)
359 if err != nil {
360 t.Error(err)
361 }
362
363
364 id := loadBalancerIdentifier{protocol: protocol, internalPort: internalPort, externalPort: externalPort, vip: serviceVip, endpointsHash: hash}
365 lbs[id] = &loadBalancerInfo{hnsID: LoadBalancer.Id}
366
367 lb, err := hns.getLoadBalancer(endpoints, loadBalancerFlags{}, sourceVip, serviceVip, protocol, internalPort, externalPort, lbs)
368
369 if err != nil {
370 t.Error(err)
371 }
372
373 if !strings.EqualFold(lb.hnsID, LoadBalancer.Id) {
374 t.Errorf("%v does not match %v", lb.hnsID, LoadBalancer.Id)
375 }
376
377 err = LoadBalancer.Delete()
378 if err != nil {
379 t.Error(err)
380 }
381 err = Endpoint.Delete()
382 if err != nil {
383 t.Error(err)
384 }
385 err = Network.Delete()
386 if err != nil {
387 t.Error(err)
388 }
389 }
390
391 func TestGetLoadBalancerNew(t *testing.T) {
392 hns := hns{hcn: newHcnImpl()}
393 Network := mustTestNetwork(t)
394
395 lbs := make(map[loadBalancerIdentifier]*(loadBalancerInfo))
396
397 ipConfig := &hcn.IpConfig{
398 IpAddress: epIpAddress,
399 }
400 Endpoint := &hcn.HostComputeEndpoint{
401 IpConfigurations: []hcn.IpConfig{*ipConfig},
402 MacAddress: epMacAddress,
403 SchemaVersion: hcn.SchemaVersion{
404 Major: 2,
405 Minor: 0,
406 },
407 }
408 Endpoint, err := Network.CreateEndpoint(Endpoint)
409 if err != nil {
410 t.Error(err)
411 }
412 endpoint := &endpointInfo{
413 ip: Endpoint.IpConfigurations[0].IpAddress,
414 hnsID: Endpoint.Id,
415 }
416 endpoints := []endpointInfo{*endpoint}
417 lb, err := hns.getLoadBalancer(endpoints, loadBalancerFlags{}, sourceVip, serviceVip, protocol, internalPort, externalPort, lbs)
418 if err != nil {
419 t.Error(err)
420 }
421 LoadBalancer, err := hcn.GetLoadBalancerByID(lb.hnsID)
422 if err != nil {
423 t.Error(err)
424 }
425 if !strings.EqualFold(lb.hnsID, LoadBalancer.Id) {
426 t.Errorf("%v does not match %v", lb.hnsID, LoadBalancer.Id)
427 }
428 err = LoadBalancer.Delete()
429 if err != nil {
430 t.Error(err)
431 }
432
433 err = Endpoint.Delete()
434 if err != nil {
435 t.Error(err)
436 }
437 err = Network.Delete()
438 if err != nil {
439 t.Error(err)
440 }
441 }
442
443 func TestDeleteLoadBalancer(t *testing.T) {
444 hns := hns{hcn: newHcnImpl()}
445 Network := mustTestNetwork(t)
446
447 ipConfig := &hcn.IpConfig{
448 IpAddress: epIpAddress,
449 }
450 Endpoint := &hcn.HostComputeEndpoint{
451 IpConfigurations: []hcn.IpConfig{*ipConfig},
452 MacAddress: epMacAddress,
453 SchemaVersion: hcn.SchemaVersion{
454 Major: 2,
455 Minor: 0,
456 },
457 }
458 Endpoint, err := Network.CreateEndpoint(Endpoint)
459 if err != nil {
460 t.Error(err)
461 }
462
463 Endpoints := []hcn.HostComputeEndpoint{*Endpoint}
464 LoadBalancer, err := hcn.AddLoadBalancer(
465 Endpoints,
466 hcn.LoadBalancerFlagsNone,
467 hcn.LoadBalancerPortMappingFlagsNone,
468 sourceVip,
469 []string{serviceVip},
470 protocol,
471 internalPort,
472 externalPort,
473 )
474 if err != nil {
475 t.Error(err)
476 }
477 err = hns.deleteLoadBalancer(LoadBalancer.Id)
478 if err != nil {
479 t.Error(err)
480 }
481
482 LoadBalancer, err = hcn.GetLoadBalancerByID(LoadBalancer.Id)
483 if err == nil {
484 t.Error(err)
485 }
486
487 err = Endpoint.Delete()
488 if err != nil {
489 t.Error(err)
490 }
491 err = Network.Delete()
492 if err != nil {
493 t.Error(err)
494 }
495 }
496
497 func mustTestNetwork(t *testing.T) *hcn.HostComputeNetwork {
498 network, err := createTestNetwork()
499 if err != nil {
500 t.Fatalf("cannot create test network: %v", err)
501 }
502 if network == nil {
503 t.Fatal("test network was nil without error")
504 }
505 return network
506 }
507
508 func TestHashEndpoints(t *testing.T) {
509 Network := mustTestNetwork(t)
510
511 ipConfigA := &hcn.IpConfig{
512 IpAddress: epIpAddress,
513 }
514 endpointASpec := &hcn.HostComputeEndpoint{
515 IpConfigurations: []hcn.IpConfig{*ipConfigA},
516 MacAddress: epMacAddress,
517 SchemaVersion: hcn.SchemaVersion{
518 Major: 2,
519 Minor: 0,
520 },
521 }
522 endpointA, err := Network.CreateEndpoint(endpointASpec)
523 if err != nil {
524 t.Error(err)
525 }
526 endpointInfoA := &endpointInfo{
527 ip: endpointA.IpConfigurations[0].IpAddress,
528 hnsID: endpointA.Id,
529 }
530
531 ipConfigB := &hcn.IpConfig{
532 IpAddress: epIpAddressB,
533 }
534 endpointBSpec := &hcn.HostComputeEndpoint{
535 IpConfigurations: []hcn.IpConfig{*ipConfigB},
536 MacAddress: epMacAddress,
537 SchemaVersion: hcn.SchemaVersion{
538 Major: 2,
539 Minor: 0,
540 },
541 }
542 endpointB, err := Network.CreateEndpoint(endpointBSpec)
543 if err != nil {
544 t.Error(err)
545 }
546 endpointInfoB := &endpointInfo{
547 ip: endpointB.IpConfigurations[0].IpAddress,
548 hnsID: endpointB.Id,
549 }
550 endpoints := []endpointInfo{*endpointInfoA, *endpointInfoB}
551 endpointsReverse := []endpointInfo{*endpointInfoB, *endpointInfoA}
552 h1, err := hashEndpoints(endpoints)
553 if err != nil {
554 t.Error(err)
555 } else if len(h1) < 1 {
556 t.Error("HashEndpoints failed for endpoints", endpoints)
557 }
558
559 h2, err := hashEndpoints(endpointsReverse)
560 if err != nil {
561 t.Error(err)
562 }
563 if h1 != h2 {
564 t.Errorf("%x does not match %x", h1, h2)
565 }
566
567
568 err = endpointA.Delete()
569 if err != nil {
570 t.Error(err)
571 }
572 err = endpointB.Delete()
573 if err != nil {
574 t.Error(err)
575 }
576 err = Network.Delete()
577 if err != nil {
578 t.Error(err)
579 }
580 }
581
582 func createTestNetwork() (*hcn.HostComputeNetwork, error) {
583 network := &hcn.HostComputeNetwork{
584 Type: NETWORK_TYPE_OVERLAY,
585 Name: "TestOverlay",
586 MacPool: hcn.MacPool{
587 Ranges: []hcn.MacRange{
588 {
589 StartMacAddress: "00-15-5D-52-C0-00",
590 EndMacAddress: "00-15-5D-52-CF-FF",
591 },
592 },
593 },
594 Ipams: []hcn.Ipam{
595 {
596 Type: "Static",
597 Subnets: []hcn.Subnet{
598 {
599 IpAddressPrefix: addressPrefix,
600 Routes: []hcn.Route{
601 {
602 NextHop: gatewayAddress,
603 DestinationPrefix: "0.0.0.0/0",
604 },
605 },
606 },
607 },
608 },
609 },
610 SchemaVersion: hcn.SchemaVersion{
611 Major: 2,
612 Minor: 0,
613 },
614 }
615
616 vsid := &hcn.VsidPolicySetting{
617 IsolationId: 5000,
618 }
619 vsidJson, err := json.Marshal(vsid)
620 if err != nil {
621 return nil, err
622 }
623
624 sp := &hcn.SubnetPolicy{
625 Type: hcn.VSID,
626 }
627 sp.Settings = vsidJson
628
629 spJson, err := json.Marshal(sp)
630 if err != nil {
631 return nil, err
632 }
633
634 network.Ipams[0].Subnets[0].Policies = append(network.Ipams[0].Subnets[0].Policies, spJson)
635
636 return network.Create()
637 }
638
View as plain text