github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/api/networker/networker_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package networker_test
     5  
     6  import (
     7  	"runtime"
     8  	"sort"
     9  
    10  	"github.com/juju/names"
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/utils"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/api"
    16  	"github.com/juju/juju/api/networker"
    17  	"github.com/juju/juju/apiserver/common"
    18  	"github.com/juju/juju/apiserver/params"
    19  	"github.com/juju/juju/instance"
    20  	"github.com/juju/juju/juju/testing"
    21  	"github.com/juju/juju/network"
    22  	"github.com/juju/juju/state"
    23  	statetesting "github.com/juju/juju/state/testing"
    24  )
    25  
    26  type networkerSuite struct {
    27  	testing.JujuConnSuite
    28  
    29  	networks []state.NetworkInfo
    30  
    31  	machine         *state.Machine
    32  	container       *state.Machine
    33  	nestedContainer *state.Machine
    34  
    35  	machineIfaces         []state.NetworkInterfaceInfo
    36  	containerIfaces       []state.NetworkInterfaceInfo
    37  	nestedContainerIfaces []state.NetworkInterfaceInfo
    38  
    39  	st        api.Connection
    40  	networker networker.State
    41  }
    42  
    43  var _ = gc.Suite(&networkerSuite{})
    44  
    45  // Create several networks.
    46  func (s *networkerSuite) setUpNetworks(c *gc.C) {
    47  	s.networks = []state.NetworkInfo{{
    48  		Name:       "net1",
    49  		ProviderId: "net1",
    50  		CIDR:       "0.1.2.0/24",
    51  		VLANTag:    0,
    52  	}, {
    53  		Name:       "vlan42",
    54  		ProviderId: "vlan42",
    55  		CIDR:       "0.2.2.0/24",
    56  		VLANTag:    42,
    57  	}, {
    58  		Name:       "vlan69",
    59  		ProviderId: "vlan69",
    60  		CIDR:       "0.3.2.0/24",
    61  		VLANTag:    69,
    62  	}, {
    63  		Name:       "vlan123",
    64  		ProviderId: "vlan123",
    65  		CIDR:       "0.4.2.0/24",
    66  		VLANTag:    123,
    67  	}, {
    68  		Name:       "net2",
    69  		ProviderId: "net2",
    70  		CIDR:       "0.5.2.0/24",
    71  		VLANTag:    0,
    72  	}}
    73  }
    74  
    75  // Create a machine and login to it.
    76  func (s *networkerSuite) setUpMachine(c *gc.C) {
    77  	var err error
    78  	s.machine, err = s.State.AddMachine("quantal", state.JobHostUnits)
    79  	c.Assert(err, jc.ErrorIsNil)
    80  	password, err := utils.RandomPassword()
    81  	c.Assert(err, jc.ErrorIsNil)
    82  	err = s.machine.SetPassword(password)
    83  	c.Assert(err, jc.ErrorIsNil)
    84  	hwChars := instance.MustParseHardware("cpu-cores=123", "mem=4G")
    85  	s.machineIfaces = []state.NetworkInterfaceInfo{{
    86  		MACAddress:    "aa:bb:cc:dd:ee:f0",
    87  		InterfaceName: "eth0",
    88  		NetworkName:   "net1",
    89  		IsVirtual:     false,
    90  	}, {
    91  		MACAddress:    "aa:bb:cc:dd:ee:f1",
    92  		InterfaceName: "eth1",
    93  		NetworkName:   "net1",
    94  		IsVirtual:     false,
    95  	}, {
    96  		MACAddress:    "aa:bb:cc:dd:ee:f1",
    97  		InterfaceName: "eth1.42",
    98  		NetworkName:   "vlan42",
    99  		IsVirtual:     true,
   100  	}, {
   101  		MACAddress:    "aa:bb:cc:dd:ee:f0",
   102  		InterfaceName: "eth0.69",
   103  		NetworkName:   "vlan69",
   104  		IsVirtual:     true,
   105  	}, {
   106  		MACAddress:    "aa:bb:cc:dd:ee:f2",
   107  		InterfaceName: "eth2",
   108  		NetworkName:   "net2",
   109  		IsVirtual:     false,
   110  		Disabled:      true,
   111  	}}
   112  	err = s.machine.SetInstanceInfo("i-am", "fake_nonce", &hwChars, s.networks, s.machineIfaces, nil, nil)
   113  	c.Assert(err, jc.ErrorIsNil)
   114  	s.st = s.OpenAPIAsMachine(c, s.machine.Tag(), password, "fake_nonce")
   115  	c.Assert(s.st, gc.NotNil)
   116  }
   117  
   118  // Create and provision a container and a nested container.
   119  func (s *networkerSuite) setUpContainers(c *gc.C) {
   120  	template := state.MachineTemplate{
   121  		Series: "quantal",
   122  		Jobs:   []state.MachineJob{state.JobHostUnits},
   123  	}
   124  	var err error
   125  	s.container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
   126  	c.Assert(err, jc.ErrorIsNil)
   127  	s.containerIfaces = []state.NetworkInterfaceInfo{{
   128  		MACAddress:    "aa:bb:cc:dd:ee:e0",
   129  		InterfaceName: "eth0",
   130  		NetworkName:   "net1",
   131  		IsVirtual:     false,
   132  	}, {
   133  		MACAddress:    "aa:bb:cc:dd:ee:e1",
   134  		InterfaceName: "eth1",
   135  		NetworkName:   "net1",
   136  		IsVirtual:     false,
   137  	}, {
   138  		MACAddress:    "aa:bb:cc:dd:ee:e1",
   139  		InterfaceName: "eth1.42",
   140  		NetworkName:   "vlan42",
   141  		IsVirtual:     true,
   142  	}}
   143  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
   144  	err = s.container.SetInstanceInfo("i-container", "fake_nonce", &hwChars, s.networks[:2],
   145  		s.containerIfaces, nil, nil)
   146  	c.Assert(err, jc.ErrorIsNil)
   147  
   148  	s.nestedContainer, err = s.State.AddMachineInsideMachine(template, s.container.Id(), instance.LXC)
   149  	c.Assert(err, jc.ErrorIsNil)
   150  	s.nestedContainerIfaces = []state.NetworkInterfaceInfo{{
   151  		MACAddress:    "aa:bb:cc:dd:ee:d0",
   152  		InterfaceName: "eth0",
   153  		NetworkName:   "net1",
   154  		IsVirtual:     false,
   155  	}}
   156  	err = s.nestedContainer.SetInstanceInfo("i-too", "fake_nonce", &hwChars, s.networks[:1],
   157  		s.nestedContainerIfaces, nil, nil)
   158  	c.Assert(err, jc.ErrorIsNil)
   159  }
   160  
   161  func (s *networkerSuite) SetUpTest(c *gc.C) {
   162  	s.JujuConnSuite.SetUpTest(c)
   163  
   164  	s.setUpNetworks(c)
   165  	s.setUpMachine(c)
   166  	s.setUpContainers(c)
   167  
   168  	// Create the networker API facade.
   169  	s.networker = s.st.Networker()
   170  	c.Assert(s.networker, gc.NotNil)
   171  }
   172  
   173  func (s *networkerSuite) TestMachineNetworkConfigPermissionDenied(c *gc.C) {
   174  	info, err := s.networker.MachineNetworkConfig(names.NewMachineTag("1"))
   175  	c.Assert(err, gc.ErrorMatches, "permission denied")
   176  	c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized)
   177  	c.Assert(info, gc.IsNil)
   178  }
   179  
   180  func (s *networkerSuite) TestMachineNetworkConfigNameChange(c *gc.C) {
   181  	var called bool
   182  	networker.PatchFacadeCall(s, s.networker, func(request string, args, response interface{}) error {
   183  		if !called {
   184  			called = true
   185  			c.Assert(request, gc.Equals, "MachineNetworkConfig")
   186  			return &params.Error{"MachineNetworkConfig", params.CodeNotImplemented}
   187  		}
   188  		c.Assert(request, gc.Equals, "MachineNetworkInfo")
   189  		expected := params.Entities{
   190  			Entities: []params.Entity{{Tag: names.NewMachineTag("42").String()}},
   191  		}
   192  		c.Assert(args, gc.DeepEquals, expected)
   193  		result := response.(*params.MachineNetworkConfigResults)
   194  		result.Results = make([]params.MachineNetworkConfigResult, 1)
   195  		result.Results[0].Error = common.ServerError(common.ErrPerm)
   196  		return nil
   197  	})
   198  	// Make a call, in this case result is "permission denied".
   199  	info, err := s.networker.MachineNetworkConfig(names.NewMachineTag("42"))
   200  	c.Assert(err, gc.ErrorMatches, "permission denied")
   201  	c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized)
   202  	c.Assert(info, gc.IsNil)
   203  }
   204  
   205  type orderedIfc []network.InterfaceInfo
   206  
   207  func (o orderedIfc) Len() int {
   208  	return len(o)
   209  }
   210  
   211  func (o orderedIfc) Less(i, j int) bool {
   212  	if o[i].MACAddress < o[j].MACAddress {
   213  		return true
   214  	}
   215  	if o[i].MACAddress > o[j].MACAddress {
   216  		return false
   217  	}
   218  	if o[i].CIDR < o[j].CIDR {
   219  		return true
   220  	}
   221  	if o[i].CIDR > o[j].CIDR {
   222  		return false
   223  	}
   224  	if o[i].NetworkName < o[j].NetworkName {
   225  		return true
   226  	}
   227  	if o[i].NetworkName > o[j].NetworkName {
   228  		return false
   229  	}
   230  	return o[i].VLANTag < o[j].VLANTag
   231  }
   232  
   233  func (o orderedIfc) Swap(i, j int) {
   234  	o[i], o[j] = o[j], o[i]
   235  }
   236  
   237  func (s *networkerSuite) TestMachineNetworkConfig(c *gc.C) {
   238  	// TODO(bogdanteleaga): Find out what's the problem with this test
   239  	// It seems to work on some machines
   240  	if runtime.GOOS == "windows" {
   241  		c.Skip("bug 1403084: currently does not work on windows")
   242  	}
   243  	// Expected results of MachineNetworkInfo for a machine and containers
   244  	expectedMachineInfo := []network.InterfaceInfo{{
   245  		MACAddress:    "aa:bb:cc:dd:ee:f0",
   246  		CIDR:          "0.1.2.0/24",
   247  		NetworkName:   "net1",
   248  		ProviderId:    "net1",
   249  		VLANTag:       0,
   250  		InterfaceName: "eth0",
   251  	}, {
   252  		MACAddress:    "aa:bb:cc:dd:ee:f1",
   253  		CIDR:          "0.1.2.0/24",
   254  		NetworkName:   "net1",
   255  		ProviderId:    "net1",
   256  		VLANTag:       0,
   257  		InterfaceName: "eth1",
   258  	}, {
   259  		MACAddress:    "aa:bb:cc:dd:ee:f1",
   260  		CIDR:          "0.2.2.0/24",
   261  		NetworkName:   "vlan42",
   262  		ProviderId:    "vlan42",
   263  		VLANTag:       42,
   264  		InterfaceName: "eth1",
   265  	}, {
   266  		MACAddress:    "aa:bb:cc:dd:ee:f0",
   267  		CIDR:          "0.3.2.0/24",
   268  		NetworkName:   "vlan69",
   269  		ProviderId:    "vlan69",
   270  		VLANTag:       69,
   271  		InterfaceName: "eth0",
   272  	}, {
   273  		MACAddress:    "aa:bb:cc:dd:ee:f2",
   274  		CIDR:          "0.5.2.0/24",
   275  		NetworkName:   "net2",
   276  		ProviderId:    "net2",
   277  		VLANTag:       0,
   278  		InterfaceName: "eth2",
   279  		Disabled:      true,
   280  	}}
   281  	sort.Sort(orderedIfc(expectedMachineInfo))
   282  
   283  	expectedContainerInfo := []network.InterfaceInfo{{
   284  		MACAddress:    "aa:bb:cc:dd:ee:e0",
   285  		CIDR:          "0.1.2.0/24",
   286  		NetworkName:   "net1",
   287  		ProviderId:    "net1",
   288  		VLANTag:       0,
   289  		InterfaceName: "eth0",
   290  	}, {
   291  		MACAddress:    "aa:bb:cc:dd:ee:e1",
   292  		CIDR:          "0.1.2.0/24",
   293  		NetworkName:   "net1",
   294  		ProviderId:    "net1",
   295  		VLANTag:       0,
   296  		InterfaceName: "eth1",
   297  	}, {
   298  		MACAddress:    "aa:bb:cc:dd:ee:e1",
   299  		CIDR:          "0.2.2.0/24",
   300  		NetworkName:   "vlan42",
   301  		ProviderId:    "vlan42",
   302  		VLANTag:       42,
   303  		InterfaceName: "eth1",
   304  	}}
   305  	sort.Sort(orderedIfc(expectedContainerInfo))
   306  
   307  	expectedNestedContainerInfo := []network.InterfaceInfo{{
   308  		MACAddress:    "aa:bb:cc:dd:ee:d0",
   309  		CIDR:          "0.1.2.0/24",
   310  		NetworkName:   "net1",
   311  		ProviderId:    "net1",
   312  		VLANTag:       0,
   313  		InterfaceName: "eth0",
   314  	}}
   315  	sort.Sort(orderedIfc(expectedNestedContainerInfo))
   316  
   317  	results, err := s.networker.MachineNetworkConfig(names.NewMachineTag("0"))
   318  	c.Assert(err, jc.ErrorIsNil)
   319  	sort.Sort(orderedIfc(results))
   320  	c.Assert(results, gc.DeepEquals, expectedMachineInfo)
   321  
   322  	results, err = s.networker.MachineNetworkConfig(names.NewMachineTag("0/lxc/0"))
   323  	c.Assert(err, jc.ErrorIsNil)
   324  	sort.Sort(orderedIfc(results))
   325  	c.Assert(results, gc.DeepEquals, expectedContainerInfo)
   326  
   327  	results, err = s.networker.MachineNetworkConfig(names.NewMachineTag("0/lxc/0/lxc/0"))
   328  	c.Assert(err, jc.ErrorIsNil)
   329  	sort.Sort(orderedIfc(results))
   330  	c.Assert(results, gc.DeepEquals, expectedNestedContainerInfo)
   331  }
   332  
   333  func (s *networkerSuite) TestWatchInterfacesPermissionDenied(c *gc.C) {
   334  	w, err := s.networker.WatchInterfaces(names.NewMachineTag("1"))
   335  	c.Assert(err, gc.ErrorMatches, "permission denied")
   336  	c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized)
   337  	c.Assert(w, gc.IsNil)
   338  }
   339  
   340  func (s *networkerSuite) TestWatchInterfaces(c *gc.C) {
   341  	// Read dynamically generated document Ids.
   342  	ifaces, err := s.machine.NetworkInterfaces()
   343  	c.Assert(err, jc.ErrorIsNil)
   344  	c.Assert(ifaces, gc.HasLen, 5)
   345  
   346  	// Start network interface watcher.
   347  	w, err := s.networker.WatchInterfaces(names.NewMachineTag("0"))
   348  	defer statetesting.AssertStop(c, w)
   349  	wc := statetesting.NewNotifyWatcherC(c, s.BackingState, w)
   350  	wc.AssertOneChange()
   351  
   352  	// Disable the first interface.
   353  	err = ifaces[0].Disable()
   354  	c.Assert(err, jc.ErrorIsNil)
   355  	wc.AssertOneChange()
   356  
   357  	// Disable the first interface again, should not report.
   358  	err = ifaces[0].Disable()
   359  	c.Assert(err, jc.ErrorIsNil)
   360  	wc.AssertNoChange()
   361  
   362  	// Enable the first interface.
   363  	err = ifaces[0].Enable()
   364  	c.Assert(err, jc.ErrorIsNil)
   365  	wc.AssertOneChange()
   366  
   367  	// Enable the first interface again, should not report.
   368  	err = ifaces[0].Enable()
   369  	c.Assert(err, jc.ErrorIsNil)
   370  	wc.AssertNoChange()
   371  
   372  	// Remove the network interface.
   373  	err = ifaces[0].Remove()
   374  	c.Assert(err, jc.ErrorIsNil)
   375  	wc.AssertOneChange()
   376  
   377  	// Add the new interface.
   378  	_, err = s.machine.AddNetworkInterface(state.NetworkInterfaceInfo{
   379  		MACAddress:    "aa:bb:cc:dd:ee:f3",
   380  		InterfaceName: "eth3",
   381  		NetworkName:   "net2",
   382  	})
   383  	c.Assert(err, jc.ErrorIsNil)
   384  	wc.AssertOneChange()
   385  
   386  	// Add the new interface on the container, should not report.
   387  	_, err = s.container.AddNetworkInterface(state.NetworkInterfaceInfo{
   388  		MACAddress:    "aa:bb:cc:dd:ee:e3",
   389  		InterfaceName: "eth3",
   390  		NetworkName:   "net2",
   391  	})
   392  	c.Assert(err, jc.ErrorIsNil)
   393  	wc.AssertNoChange()
   394  
   395  	// Read dynamically generated document Ids.
   396  	containerIfaces, err := s.container.NetworkInterfaces()
   397  	c.Assert(err, jc.ErrorIsNil)
   398  	c.Assert(containerIfaces, gc.HasLen, 4)
   399  
   400  	// Disable the first interface on the second machine, should not report.
   401  	err = containerIfaces[0].Disable()
   402  	c.Assert(err, jc.ErrorIsNil)
   403  	wc.AssertNoChange()
   404  
   405  	// Remove the network interface on the second machine, should not report.
   406  	err = containerIfaces[0].Remove()
   407  	c.Assert(err, jc.ErrorIsNil)
   408  	wc.AssertNoChange()
   409  
   410  	// Stop watcher; check Changes chan closed.
   411  	statetesting.AssertStop(c, w)
   412  	wc.AssertClosed()
   413  }