github.com/vmware/govmomi@v0.37.2/simulator/ip_pool_manager_test.go (about)

     1  /*
     2  Copyright (c) 2017 VMware, Inc. All Rights Reserved.
     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 simulator
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"net"
    23  	"reflect"
    24  	"testing"
    25  
    26  	"github.com/vmware/govmomi"
    27  	"github.com/vmware/govmomi/vim25/methods"
    28  	"github.com/vmware/govmomi/vim25/types"
    29  )
    30  
    31  func TestIpPoolv4(t *testing.T) {
    32  	tests := []struct {
    33  		ipRange string
    34  		length  int32
    35  	}{
    36  		{"10.10.10.2#250", 250},
    37  		{"10.10.10.2#10, 10.10.10.20#20", 30},
    38  		{"10.10.10.2#10, 10.10.10.20#20, 10.10.10.50#20", 50},
    39  	}
    40  
    41  	for _, test := range tests {
    42  		var ipPool = MustNewIpPool(&types.IpPool{
    43  			Id:                     1,
    44  			Name:                   "ip-pool",
    45  			AvailableIpv4Addresses: test.length,
    46  			AvailableIpv6Addresses: 0,
    47  			AllocatedIpv6Addresses: 0,
    48  			AllocatedIpv4Addresses: 0,
    49  			Ipv4Config: &types.IpPoolIpPoolConfigInfo{
    50  				Netmask:       "10.10.10.255",
    51  				Gateway:       "10.10.10.1",
    52  				SubnetAddress: "10.10.10.0",
    53  				Range:         test.ipRange,
    54  			},
    55  		})
    56  
    57  		if len(ipPool.ipv4Pool) != int(test.length) {
    58  			t.Fatalf("expect length to be %d; got %d", test.length, len(ipPool.ipv4Pool))
    59  		}
    60  
    61  		ip, err := ipPool.AllocateIPv4("alloc")
    62  		if err != nil {
    63  			t.Fatal(err)
    64  		}
    65  
    66  		ip2, err := ipPool.AllocateIPv4("alloc")
    67  		if err != nil {
    68  			t.Fatal(err)
    69  		}
    70  		if ip != ip2 {
    71  			t.Fatalf("same allocation key should allocate the same ip; got %s, %s", ip, ip2)
    72  		}
    73  
    74  		err = ipPool.ReleaseIpv4("bad-alloc")
    75  		if err == nil {
    76  			t.Fatal("expect error to release a bad allocation")
    77  		}
    78  
    79  		if len(ipPool.ipv4Pool) != int(test.length)-1 {
    80  			t.Fatalf("expect length to be %d; got %d", test.length-1, len(ipPool.ipv4Pool))
    81  		}
    82  
    83  		err = ipPool.ReleaseIpv4("alloc")
    84  		if err != nil {
    85  			t.Fatal(err)
    86  		}
    87  
    88  		if len(ipPool.ipv4Pool) != int(test.length) {
    89  			t.Fatalf("expect length to be %d; got %d", test.length, len(ipPool.ipv4Pool))
    90  		}
    91  
    92  		allocated := map[string]bool{}
    93  		for i := 0; i < int(test.length); i++ {
    94  			ip, err := ipPool.AllocateIPv4(fmt.Sprintf("alloc-%d", i))
    95  			if err != nil {
    96  				t.Fatal(err)
    97  			}
    98  
    99  			if _, ok := allocated[ip]; ok {
   100  				t.Fatalf("duplicated allocation of ip %q", ip)
   101  			}
   102  			allocated[ip] = true
   103  		}
   104  
   105  		_, err = ipPool.AllocateIPv4("last-allocation")
   106  		if err != errNoIpAvailable {
   107  			t.Fatalf("expect errNoIpAvailable; got %s", err)
   108  		}
   109  	}
   110  }
   111  
   112  func TestIpPoolv6(t *testing.T) {
   113  	tests := []struct {
   114  		ipRange string
   115  		length  int32
   116  	}{
   117  		{"2001:4860:0:2001::2#250", 250},
   118  	}
   119  
   120  	for _, test := range tests {
   121  		var ipPool = MustNewIpPool(&types.IpPool{
   122  			Id:                     1,
   123  			Name:                   "ip-pool",
   124  			AvailableIpv4Addresses: 0,
   125  			AvailableIpv6Addresses: test.length,
   126  			AllocatedIpv6Addresses: 0,
   127  			AllocatedIpv4Addresses: 0,
   128  			Ipv6Config: &types.IpPoolIpPoolConfigInfo{
   129  				Netmask:       "2001:4860:0:2001::ff",
   130  				Gateway:       "2001:4860:0:2001::1",
   131  				SubnetAddress: "2001:4860:0:2001::0",
   132  				Range:         test.ipRange,
   133  			},
   134  		})
   135  
   136  		if len(ipPool.ipv6Pool) != int(test.length) {
   137  			t.Fatalf("expect length to be %d; got %d", test.length, len(ipPool.ipv4Pool))
   138  		}
   139  
   140  		ip, err := ipPool.AllocateIpv6("alloc")
   141  		if err != nil {
   142  			t.Fatal(err)
   143  		}
   144  
   145  		ip2, err := ipPool.AllocateIpv6("alloc")
   146  		if err != nil {
   147  			t.Fatal(err)
   148  		}
   149  		if ip != ip2 {
   150  			t.Fatalf("same allocation key should allocate the same ip; got %s, %s", ip, ip2)
   151  		}
   152  
   153  		err = ipPool.ReleaseIpv6("bad-alloc")
   154  		if err == nil {
   155  			t.Fatal("expect error to release a bad allocation")
   156  		}
   157  
   158  		if len(ipPool.ipv6Pool) != int(test.length)-1 {
   159  			t.Fatalf("expect length to be %d; got %d", test.length-1, len(ipPool.ipv4Pool))
   160  		}
   161  
   162  		err = ipPool.ReleaseIpv6("alloc")
   163  		if err != nil {
   164  			t.Fatal(err)
   165  		}
   166  
   167  		if len(ipPool.ipv6Pool) != int(test.length) {
   168  			t.Fatalf("expect length to be %d; got %d", test.length, len(ipPool.ipv4Pool))
   169  		}
   170  
   171  		allocated := map[string]bool{}
   172  		for i := 0; i < int(test.length); i++ {
   173  			ip, err := ipPool.AllocateIpv6(fmt.Sprintf("alloc-%d", i))
   174  			if err != nil {
   175  				t.Fatal(err)
   176  			}
   177  
   178  			if _, ok := allocated[ip]; ok {
   179  				t.Fatalf("duplicated allocation of ip %q", ip)
   180  			}
   181  			allocated[ip] = true
   182  		}
   183  
   184  		_, err = ipPool.AllocateIpv6("last-allocation")
   185  		if err != errNoIpAvailable {
   186  			t.Fatalf("expect errNoIpAvailable; got %s", err)
   187  		}
   188  	}
   189  }
   190  
   191  func TestIpPoolManagerLifecycle(t *testing.T) {
   192  	ctx := context.Background()
   193  	m := VPX()
   194  
   195  	defer m.Remove()
   196  
   197  	err := m.Create()
   198  	if err != nil {
   199  		t.Fatal(err)
   200  	}
   201  
   202  	s := m.Service.NewServer()
   203  	defer s.Close()
   204  
   205  	c, err := govmomi.NewClient(ctx, s.URL, true)
   206  	if err != nil {
   207  		t.Fatal(err)
   208  	}
   209  
   210  	ref := types.ManagedObjectReference{Type: "IpPoolManager", Value: "IpPoolManager"}
   211  
   212  	var ipPool = &types.IpPool{
   213  		Name:                   "ip-pool",
   214  		AvailableIpv4Addresses: 250,
   215  		AvailableIpv6Addresses: 250,
   216  		AllocatedIpv4Addresses: 0,
   217  		AllocatedIpv6Addresses: 0,
   218  		Ipv4Config: &types.IpPoolIpPoolConfigInfo{
   219  			Netmask:       "10.10.10.255",
   220  			Gateway:       "10.10.10.1",
   221  			SubnetAddress: "10.10.10.0",
   222  			Range:         "10.10.10.2#250",
   223  		},
   224  		Ipv6Config: &types.IpPoolIpPoolConfigInfo{
   225  			Netmask:       "2001:4860:0:2001::ff",
   226  			Gateway:       "2001:4860:0:2001::1",
   227  			SubnetAddress: "2001:4860:0:2001::0",
   228  			Range:         "2001:4860:0:2001::2#250",
   229  		},
   230  	}
   231  
   232  	createReq := &types.CreateIpPool{
   233  		This: ref,
   234  		Pool: *ipPool,
   235  	}
   236  
   237  	createResp, err := methods.CreateIpPool(ctx, c.Client, createReq)
   238  	if err != nil {
   239  		t.Fatal(err)
   240  	}
   241  	if createResp.Returnval != 2 {
   242  		t.Fatalf("expect pool id to be 2; got %d", createResp.Returnval)
   243  	}
   244  
   245  	ipPool.Id = 2
   246  	ipPool.Ipv4Config = &types.IpPoolIpPoolConfigInfo{
   247  		Netmask:       "10.20.10.255",
   248  		Gateway:       "10.20.10.1",
   249  		SubnetAddress: "10.20.10.0",
   250  		Range:         "10.20.10.2#250",
   251  	}
   252  
   253  	updateReq := &types.UpdateIpPool{
   254  		This: ref,
   255  		Pool: *ipPool,
   256  	}
   257  
   258  	_, err = methods.UpdateIpPool(ctx, c.Client, updateReq)
   259  	if err != nil {
   260  		t.Fatal(err)
   261  	}
   262  
   263  	queryReq := &types.QueryIpPools{
   264  		This: ref,
   265  	}
   266  
   267  	queryResp, err := methods.QueryIpPools(ctx, c.Client, queryReq)
   268  	if err != nil {
   269  		t.Fatal(err)
   270  	}
   271  
   272  	if len(queryResp.Returnval) != 2 {
   273  		t.Fatalf("expect length of ip pools is 2; got %d", len(queryResp.Returnval))
   274  	}
   275  	if !reflect.DeepEqual(queryResp.Returnval[1].Ipv4Config, ipPool.Ipv4Config) {
   276  		t.Fatalf("expect query result equal to %+v; got %+v",
   277  			ipPool.Ipv4Config, queryResp.Returnval[1].Ipv4Config)
   278  	}
   279  
   280  	destroyReq := &types.DestroyIpPool{
   281  		This: ref,
   282  		Id:   2,
   283  	}
   284  
   285  	_, err = methods.DestroyIpPool(ctx, c.Client, destroyReq)
   286  	if err != nil {
   287  		t.Fatal(err)
   288  	}
   289  
   290  	queryResp, err = methods.QueryIpPools(ctx, c.Client, queryReq)
   291  	if err != nil {
   292  		t.Fatal(err)
   293  	}
   294  	if len(queryResp.Returnval) != 1 {
   295  		t.Fatalf("expect length of ip pools is 1 (1 deleted); got %d", len(queryResp.Returnval))
   296  	}
   297  }
   298  
   299  func TestIpPoolManagerAllocate(t *testing.T) {
   300  	ctx := context.Background()
   301  	m := VPX()
   302  
   303  	defer m.Remove()
   304  
   305  	err := m.Create()
   306  	if err != nil {
   307  		t.Fatal(err)
   308  	}
   309  
   310  	s := m.Service.NewServer()
   311  	defer s.Close()
   312  
   313  	c, err := govmomi.NewClient(ctx, s.URL, true)
   314  	if err != nil {
   315  		t.Fatal(err)
   316  	}
   317  
   318  	ref := types.ManagedObjectReference{Type: "IpPoolManager", Value: "IpPoolManager"}
   319  
   320  	// Allocate IPv4
   321  	allocateReq := &types.AllocateIpv4Address{
   322  		This:         ref,
   323  		PoolId:       1,
   324  		AllocationId: "alloc",
   325  	}
   326  
   327  	allocateResp, err := methods.AllocateIpv4Address(ctx, c.Client, allocateReq)
   328  	if err != nil {
   329  		t.Fatal(err)
   330  	}
   331  	if net.ParseIP(allocateResp.Returnval) == nil {
   332  		t.Fatalf("%q is not IP address", allocateResp.Returnval)
   333  	}
   334  
   335  	releaseReq := &types.ReleaseIpAllocation{
   336  		This:         ref,
   337  		PoolId:       1,
   338  		AllocationId: "alloc",
   339  	}
   340  
   341  	queryReq := &types.QueryIPAllocations{
   342  		This:         ref,
   343  		PoolId:       1,
   344  		ExtensionKey: "alloc",
   345  	}
   346  
   347  	queryResp, err := methods.QueryIPAllocations(ctx, c.Client, queryReq)
   348  	if err != nil {
   349  		t.Fatal(err)
   350  	}
   351  	if len(queryResp.Returnval) != 1 {
   352  		t.Fatalf("expect length of result 1; got %s", queryResp.Returnval)
   353  	}
   354  	if queryResp.Returnval[0].IpAddress != allocateResp.Returnval {
   355  		t.Fatalf("expect same IP address; got %s, %s", queryResp.Returnval[0].IpAddress, allocateResp.Returnval)
   356  	}
   357  
   358  	_, err = methods.ReleaseIpAllocation(ctx, c.Client, releaseReq)
   359  	if err != nil {
   360  		t.Fatal(err)
   361  	}
   362  }