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  }