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 ¶ms.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 }