github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/legacy_ipaddresses_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "fmt" 8 9 "github.com/juju/errors" 10 "github.com/juju/names" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/instance" 15 "github.com/juju/juju/network" 16 "github.com/juju/juju/state" 17 ) 18 19 type IPAddressSuite struct { 20 ConnSuite 21 } 22 23 var _ = gc.Suite(&IPAddressSuite{}) 24 25 func (s *IPAddressSuite) assertAddress( 26 c *gc.C, 27 ipAddr *state.IPAddress, 28 addr network.Address, 29 ipState state.AddressState, 30 machineId, ifaceId, subnetId string, 31 ) { 32 c.Assert(ipAddr, gc.NotNil) 33 c.Assert(ipAddr.MachineId(), gc.Equals, machineId) 34 c.Assert(ipAddr.InterfaceId(), gc.Equals, ifaceId) 35 c.Assert(ipAddr.SubnetId(), gc.Equals, subnetId) 36 c.Assert(ipAddr.Value(), gc.Equals, addr.Value) 37 c.Assert(ipAddr.Type(), gc.Equals, addr.Type) 38 c.Assert(ipAddr.Scope(), gc.Equals, addr.Scope) 39 c.Assert(ipAddr.State(), gc.Equals, ipState) 40 c.Assert(ipAddr.Address(), jc.DeepEquals, addr) 41 c.Assert(ipAddr.String(), gc.Equals, addr.String()) 42 c.Assert(ipAddr.Id(), gc.Equals, s.State.ModelUUID()+":"+addr.Value) 43 c.Assert(ipAddr.InstanceId(), gc.Equals, instance.UnknownId) 44 c.Assert(ipAddr.MACAddress(), gc.Equals, "") 45 } 46 47 func (s *IPAddressSuite) createMachine(c *gc.C) *state.Machine { 48 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 49 c.Assert(err, jc.ErrorIsNil) 50 err = machine.SetProvisioned("foo", "fake_nonce", nil) 51 c.Assert(err, jc.ErrorIsNil) 52 return machine 53 } 54 55 func (s *IPAddressSuite) TestAddIPAddress(c *gc.C) { 56 for i, test := range []string{"0.1.2.3", "2001:db8::1"} { 57 c.Logf("test %d: %q", i, test) 58 addr := network.NewScopedAddress(test, network.ScopePublic) 59 ipAddr, err := s.State.AddIPAddress(addr, "foobar") 60 c.Assert(err, jc.ErrorIsNil) 61 s.assertAddress(c, ipAddr, addr, state.AddressStateUnknown, "", "", "foobar") 62 c.Assert(ipAddr.Life(), gc.Equals, state.Alive) 63 64 // verify the address was stored in the state 65 ipAddr, err = s.State.IPAddress(test) 66 c.Assert(err, jc.ErrorIsNil) 67 s.assertAddress(c, ipAddr, addr, state.AddressStateUnknown, "", "", "foobar") 68 } 69 } 70 71 func (s *IPAddressSuite) TestAddIPAddressInvalid(c *gc.C) { 72 addr := network.Address{Value: "foo"} 73 _, err := s.State.AddIPAddress(addr, "foobar") 74 c.Assert(err, jc.Satisfies, errors.IsNotValid) 75 c.Assert(err, gc.ErrorMatches, `cannot add IP address "foo": address not valid`) 76 } 77 78 func (s *IPAddressSuite) TestAddIPAddressAlreadyExists(c *gc.C) { 79 addr := network.NewScopedAddress("0.1.2.3", network.ScopePublic) 80 _, err := s.State.AddIPAddress(addr, "foobar") 81 c.Assert(err, jc.ErrorIsNil) 82 _, err = s.State.AddIPAddress(addr, "foobar") 83 c.Assert(err, jc.Satisfies, errors.IsAlreadyExists) 84 c.Assert(err, gc.ErrorMatches, 85 `cannot add IP address "public:0.1.2.3": address already exists`, 86 ) 87 } 88 89 func (s *IPAddressSuite) TestIPAddressNotFound(c *gc.C) { 90 _, err := s.State.IPAddress("0.1.2.3") 91 c.Assert(err, jc.Satisfies, errors.IsNotFound) 92 c.Assert(err, gc.ErrorMatches, `IP address "0.1.2.3" not found`) 93 } 94 95 func (s *IPAddressSuite) TestIPAddressByTag(c *gc.C) { 96 addr := network.NewScopedAddress("0.1.2.3", network.ScopePublic) 97 added, err := s.State.AddIPAddress(addr, "foobar") 98 c.Assert(err, jc.ErrorIsNil) 99 100 uuid, err := added.UUID() 101 c.Assert(err, jc.ErrorIsNil) 102 tag := names.NewIPAddressTag(uuid.String()) 103 found, err := s.State.IPAddressByTag(tag) 104 c.Assert(err, jc.ErrorIsNil) 105 c.Assert(found.Id(), gc.Equals, added.Id()) 106 } 107 108 func (s *IPAddressSuite) TestIPAddressFindEntity(c *gc.C) { 109 addr := network.NewScopedAddress("0.1.2.3", network.ScopePublic) 110 added, err := s.State.AddIPAddress(addr, "foobar") 111 c.Assert(err, jc.ErrorIsNil) 112 113 uuid, err := added.UUID() 114 c.Assert(err, jc.ErrorIsNil) 115 tag := names.NewIPAddressTag(uuid.String()) 116 found, err := s.State.FindEntity(tag) 117 c.Assert(err, jc.ErrorIsNil) 118 c.Assert(found.Tag(), gc.Equals, tag) 119 } 120 121 func (s *IPAddressSuite) TestIPAddressByTagNotFound(c *gc.C) { 122 tag := names.NewIPAddressTag("42424242-1111-2222-3333-0123456789ab") 123 _, err := s.State.IPAddressByTag(tag) 124 c.Assert(err, gc.ErrorMatches, `IP address "ipaddress-42424242-1111-2222-3333-0123456789ab" not found`) 125 } 126 127 func (s *IPAddressSuite) TestEnsureDeadRemove(c *gc.C) { 128 addr := network.NewScopedAddress("0.1.2.3", network.ScopePublic) 129 ipAddr, err := s.State.AddIPAddress(addr, "foobar") 130 c.Assert(err, jc.ErrorIsNil) 131 132 // Should not be able to remove an Alive IP address. 133 c.Assert(ipAddr.Life(), gc.Equals, state.Alive) 134 err = ipAddr.Remove() 135 msg := fmt.Sprintf("cannot remove IP address %q: IP address is not dead", ipAddr.String()) 136 c.Assert(err, gc.ErrorMatches, msg) 137 138 err = ipAddr.EnsureDead() 139 c.Assert(err, jc.ErrorIsNil) 140 141 // EnsureDead twice should not be an error 142 err = ipAddr.EnsureDead() 143 c.Assert(err, jc.ErrorIsNil) 144 145 err = ipAddr.Remove() 146 c.Assert(err, jc.ErrorIsNil) 147 148 // Remove twice is also fine. 149 err = ipAddr.Remove() 150 c.Assert(err, jc.ErrorIsNil) 151 152 _, err = s.State.IPAddress("0.1.2.3") 153 c.Assert(err, jc.Satisfies, errors.IsNotFound) 154 c.Assert(err, gc.ErrorMatches, `IP address "0.1.2.3" not found`) 155 } 156 157 func (s *IPAddressSuite) TestSetStateDead(c *gc.C) { 158 addr := network.NewScopedAddress("0.1.2.3", network.ScopePublic) 159 ipAddr, err := s.State.AddIPAddress(addr, "foobar") 160 c.Assert(err, jc.ErrorIsNil) 161 162 copyIPAddr, err := s.State.IPAddress("0.1.2.3") 163 c.Assert(err, jc.ErrorIsNil) 164 err = copyIPAddr.EnsureDead() 165 c.Assert(err, jc.ErrorIsNil) 166 167 err = ipAddr.SetState(state.AddressStateAllocated) 168 msg := fmt.Sprintf(`cannot set IP address %q to state "allocated": address is dead`, ipAddr.String()) 169 c.Assert(err, gc.ErrorMatches, msg) 170 } 171 172 func (s *IPAddressSuite) TestAllocateToDead(c *gc.C) { 173 machine := s.createMachine(c) 174 addr := network.NewScopedAddress("0.1.2.3", network.ScopePublic) 175 ipAddr, err := s.State.AddIPAddress(addr, "foobar") 176 c.Assert(err, jc.ErrorIsNil) 177 178 copyIPAddr, err := s.State.IPAddress("0.1.2.3") 179 c.Assert(err, jc.ErrorIsNil) 180 err = copyIPAddr.EnsureDead() 181 c.Assert(err, jc.ErrorIsNil) 182 183 msg := fmt.Sprintf(`cannot allocate IP address %q to machine %q, interface "frogger": address is dead`, ipAddr.String(), machine.Id()) 184 err = ipAddr.AllocateTo(machine.Id(), "frogger", "01:23:45:67:89:ab") 185 c.Assert(err, gc.ErrorMatches, msg) 186 } 187 188 func (s *IPAddressSuite) TestAllocateToProvisionedMachine(c *gc.C) { 189 machine := s.createMachine(c) 190 191 addr := network.NewAddress("0.1.2.3") 192 ipAddr, err := s.State.AddIPAddress(addr, "foobar") 193 c.Assert(err, jc.ErrorIsNil) 194 195 err = ipAddr.AllocateTo(machine.Id(), "fake", "01:23:45:67:89:ab") 196 c.Assert(err, jc.ErrorIsNil) 197 198 c.Assert(ipAddr.InstanceId(), gc.Equals, instance.Id("foo")) 199 c.Assert(ipAddr.MACAddress(), gc.Equals, "01:23:45:67:89:ab") 200 } 201 202 func (s *IPAddressSuite) TestAddressStateString(c *gc.C) { 203 for i, test := range []struct { 204 ipState state.AddressState 205 expect string 206 }{{ 207 state.AddressStateUnknown, 208 "<unknown>", 209 }, { 210 state.AddressStateAllocated, 211 "allocated", 212 }, { 213 state.AddressStateUnavailable, 214 "unavailable", 215 }} { 216 c.Logf("test %d: %q -> %q", i, test.ipState, test.expect) 217 c.Check(test.ipState.String(), gc.Equals, test.expect) 218 } 219 } 220 221 func (s *IPAddressSuite) TestSetState(c *gc.C) { 222 addr := network.NewScopedAddress("0.1.2.3", network.ScopePublic) 223 224 for i, test := range []struct { 225 initial, changeTo state.AddressState 226 err string 227 }{{ 228 initial: state.AddressStateUnknown, 229 changeTo: state.AddressStateUnknown, 230 }, { 231 initial: state.AddressStateUnknown, 232 changeTo: state.AddressStateAllocated, 233 }, { 234 initial: state.AddressStateUnknown, 235 changeTo: state.AddressStateUnavailable, 236 }, { 237 initial: state.AddressStateAllocated, 238 changeTo: state.AddressStateAllocated, 239 }, { 240 initial: state.AddressStateUnavailable, 241 changeTo: state.AddressStateUnavailable, 242 }, { 243 initial: state.AddressStateAllocated, 244 changeTo: state.AddressStateUnknown, 245 err: `cannot set IP address "public:0.1.2.3" to state "<unknown>": ` + 246 `transition from "allocated" not valid`, 247 }, { 248 initial: state.AddressStateUnavailable, 249 changeTo: state.AddressStateUnknown, 250 err: `cannot set IP address "public:0.1.2.3" to state "<unknown>": ` + 251 `transition from "unavailable" not valid`, 252 }, { 253 initial: state.AddressStateAllocated, 254 changeTo: state.AddressStateUnavailable, 255 err: `cannot set IP address "public:0.1.2.3" to state "unavailable": ` + 256 `transition from "allocated" not valid`, 257 }, { 258 initial: state.AddressStateUnavailable, 259 changeTo: state.AddressStateAllocated, 260 err: `cannot set IP address "public:0.1.2.3" to state "allocated": ` + 261 `transition from "unavailable" not valid`, 262 }} { 263 c.Logf("test %d: %q -> %q ok:%v", i, test.initial, test.changeTo, test.err == "") 264 ipAddr, err := s.State.AddIPAddress(addr, "foobar") 265 c.Check(err, jc.ErrorIsNil) 266 267 // Initially, all addresses have AddressStateUnknown. 268 c.Assert(ipAddr.State(), gc.Equals, state.AddressStateUnknown) 269 270 if test.initial != state.AddressStateUnknown { 271 err = ipAddr.SetState(test.initial) 272 c.Check(err, jc.ErrorIsNil) 273 } 274 err = ipAddr.SetState(test.changeTo) 275 if test.err != "" { 276 c.Check(err, gc.ErrorMatches, test.err) 277 c.Check(err, jc.Satisfies, errors.IsNotValid) 278 c.Check(ipAddr.EnsureDead(), jc.ErrorIsNil) 279 c.Check(ipAddr.Remove(), jc.ErrorIsNil) 280 continue 281 } 282 c.Check(err, jc.ErrorIsNil) 283 c.Check(ipAddr.State(), gc.Equals, test.changeTo) 284 c.Check(ipAddr.EnsureDead(), jc.ErrorIsNil) 285 c.Check(ipAddr.Remove(), jc.ErrorIsNil) 286 } 287 } 288 289 func (s *IPAddressSuite) TestAllocateTo(c *gc.C) { 290 machine := s.createMachine(c) 291 292 addr := network.NewScopedAddress("0.1.2.3", network.ScopePublic) 293 ipAddr, err := s.State.AddIPAddress(addr, "foobar") 294 c.Assert(err, jc.ErrorIsNil) 295 c.Assert(ipAddr.State(), gc.Equals, state.AddressStateUnknown) 296 c.Assert(ipAddr.MachineId(), gc.Equals, "") 297 c.Assert(ipAddr.InterfaceId(), gc.Equals, "") 298 c.Assert(ipAddr.InstanceId(), gc.Equals, instance.UnknownId) 299 300 err = ipAddr.AllocateTo(machine.Id(), "wobble", "01:23:45:67:89:ab") 301 c.Assert(err, jc.ErrorIsNil) 302 c.Assert(ipAddr.State(), gc.Equals, state.AddressStateAllocated) 303 c.Assert(ipAddr.MachineId(), gc.Equals, machine.Id()) 304 c.Assert(ipAddr.InterfaceId(), gc.Equals, "wobble") 305 c.Assert(ipAddr.InstanceId(), gc.Equals, instance.Id("foo")) 306 c.Assert(ipAddr.MACAddress(), gc.Equals, "01:23:45:67:89:ab") 307 308 freshCopy, err := s.State.IPAddress("0.1.2.3") 309 c.Assert(err, jc.ErrorIsNil) 310 c.Assert(freshCopy.State(), gc.Equals, state.AddressStateAllocated) 311 c.Assert(freshCopy.MachineId(), gc.Equals, machine.Id()) 312 c.Assert(freshCopy.InterfaceId(), gc.Equals, "wobble") 313 c.Assert(freshCopy.InstanceId(), gc.Equals, instance.Id("foo")) 314 c.Assert(freshCopy.MACAddress(), gc.Equals, "01:23:45:67:89:ab") 315 316 // allocating twice should fail. 317 machine2 := s.createMachine(c) 318 err = ipAddr.AllocateTo(machine2.Id(), "i", "01:23:45:67:89:ac") 319 320 msg := fmt.Sprintf( 321 `cannot allocate IP address "public:0.1.2.3" to machine %q, interface "i": `+ 322 `already allocated or unavailable`, machine2.Id()) 323 c.Assert(err, gc.ErrorMatches, msg) 324 } 325 326 func (s *IPAddressSuite) TestAddress(c *gc.C) { 327 addr := network.NewScopedAddress("0.1.2.3", network.ScopePublic) 328 ipAddr, err := s.State.AddIPAddress(addr, "foobar") 329 c.Assert(err, jc.ErrorIsNil) 330 c.Assert(ipAddr.Address(), jc.DeepEquals, addr) 331 } 332 333 func (s *IPAddressSuite) TestAllocatedIPAddresses(c *gc.C) { 334 machine := s.createMachine(c) 335 machine2 := s.createMachine(c) 336 addresses := [][]string{ 337 {"0.1.2.3", machine.Id()}, 338 {"0.1.2.4", machine.Id()}, 339 {"0.1.2.5", machine2.Id()}, 340 } 341 for _, details := range addresses { 342 addr := network.NewScopedAddress(details[0], network.ScopePublic) 343 ipAddr, err := s.State.AddIPAddress(addr, "foobar") 344 c.Assert(err, jc.ErrorIsNil) 345 err = ipAddr.AllocateTo(details[1], "wobble", "01:23:45:67:89:ab") 346 c.Assert(err, jc.ErrorIsNil) 347 } 348 result, err := s.State.AllocatedIPAddresses(machine.Id()) 349 c.Assert(err, jc.ErrorIsNil) 350 addr1, err := s.State.IPAddress("0.1.2.3") 351 c.Assert(err, jc.ErrorIsNil) 352 addr2, err := s.State.IPAddress("0.1.2.4") 353 c.Assert(err, jc.ErrorIsNil) 354 expected := []*state.IPAddress{addr1, addr2} 355 c.Assert(result, jc.SameContents, expected) 356 } 357 358 func (s *IPAddressSuite) TestDeadIPAddresses(c *gc.C) { 359 machine := s.createMachine(c) 360 361 addresses := []string{ 362 "0.1.2.3", 363 "0.1.2.4", 364 "0.1.2.5", 365 "0.1.2.6", 366 } 367 for i, details := range addresses { 368 addr := network.NewAddress(details) 369 ipAddr, err := s.State.AddIPAddress(addr, "foobar") 370 c.Assert(err, jc.ErrorIsNil) 371 err = ipAddr.AllocateTo(machine.Id(), "wobble", "01:23:45:67:89:ab") 372 c.Assert(err, jc.ErrorIsNil) 373 if i%2 == 0 { 374 err := ipAddr.EnsureDead() 375 c.Assert(err, jc.ErrorIsNil) 376 } else { 377 c.Assert(ipAddr.Life(), gc.Equals, state.Alive) 378 } 379 } 380 381 ipAddresses, err := s.State.DeadIPAddresses() 382 c.Assert(err, jc.ErrorIsNil) 383 addr1, err := s.State.IPAddress("0.1.2.3") 384 c.Assert(err, jc.ErrorIsNil) 385 addr3, err := s.State.IPAddress("0.1.2.5") 386 c.Assert(err, jc.ErrorIsNil) 387 c.Assert(ipAddresses, jc.SameContents, []*state.IPAddress{addr1, addr3}) 388 } 389 390 func (s *IPAddressSuite) TestRefresh(c *gc.C) { 391 rawAddr := network.NewAddress("0.1.2.3") 392 addr, err := s.State.AddIPAddress(rawAddr, "foobar") 393 c.Assert(err, jc.ErrorIsNil) 394 395 addrCopy, err := s.State.IPAddress(rawAddr.Value) 396 c.Assert(err, jc.ErrorIsNil) 397 398 err = addr.EnsureDead() 399 c.Assert(err, jc.ErrorIsNil) 400 401 c.Assert(addrCopy.Life(), gc.Equals, state.Alive) 402 err = addrCopy.Refresh() 403 c.Assert(err, jc.ErrorIsNil) 404 c.Assert(addrCopy.Life(), gc.Equals, state.Dead) 405 }