Exemple #1
0
func (*AddressSuite) TestSortAddresses(c *gc.C) {
	addrs := network.NewAddresses(
		"127.0.0.1",
		"localhost",
		"example.com",
		"::1",
		"fc00::1",
		"fe80::2",
		"172.16.0.1",
		"8.8.8.8",
	)
	network.SortAddresses(addrs, false)
	c.Assert(addrs, jc.DeepEquals, network.NewAddresses(
		"example.com",
		"localhost",
		"127.0.0.1",
		"172.16.0.1",
		"8.8.8.8",
		"::1",
		"fe80::2",
		"fc00::1",
	))

	network.SortAddresses(addrs, true)
	c.Assert(addrs, jc.DeepEquals, network.NewAddresses(
		"example.com",
		"localhost",
		"fe80::2",
		"::1",
		"fc00::1",
		"127.0.0.1",
		"172.16.0.1",
		"8.8.8.8",
	))
}
Exemple #2
0
// setAddresses updates the machine's addresses (either Addresses or
// MachineAddresses, depending on the field argument). Changes are
// only predicated on the machine not being Dead; concurrent address
// changes are ignored.
func (m *Machine) setAddresses(addresses []network.Address, field *[]address, fieldName string) error {
	var addressesToSet []network.Address
	if !m.IsContainer() {
		// Check addresses first. We'll only add those addresses
		// which are not in the IP address collection.
		ipAddresses, closer := m.st.getCollection(ipaddressesC)
		defer closer()

		addressValues := make([]string, len(addresses))
		for i, address := range addresses {
			addressValues[i] = address.Value
		}
		ipDocs := []ipaddressDoc{}
		sel := bson.D{{"value", bson.D{{"$in", addressValues}}}, {"state", AddressStateAllocated}}
		err := ipAddresses.Find(sel).All(&ipDocs)
		if err != nil {
			return err
		}
		ipDocValues := set.NewStrings()
		for _, ipDoc := range ipDocs {
			ipDocValues.Add(ipDoc.Value)
		}
		for _, address := range addresses {
			if !ipDocValues.Contains(address.Value) {
				addressesToSet = append(addressesToSet, address)
			}
		}
	} else {
		// Containers will set all addresses.
		addressesToSet = make([]network.Address, len(addresses))
		copy(addressesToSet, addresses)
	}

	// Update addresses now.
	envConfig, err := m.st.EnvironConfig()
	if err != nil {
		return err
	}
	network.SortAddresses(addressesToSet, envConfig.PreferIPv6())
	stateAddresses := fromNetworkAddresses(addressesToSet)

	if addressesEqual(addressesToSet, networkAddresses(*field)) {
		return nil
	}
	if err := m.st.runTransaction([]txn.Op{{
		C:      machinesC,
		Id:     m.doc.DocID,
		Assert: notDeadDoc,
		Update: bson.D{{"$set", bson.D{{fieldName, stateAddresses}}}},
	}}); err != nil {
		if err == txn.ErrAborted {
			return ErrDead
		}
		return errors.Trace(err)
	}
	*field = stateAddresses
	return nil
}
Exemple #3
0
// addressesEqual compares the addresses of the machine and the instance information.
func addressesEqual(a0, a1 []network.Address) bool {
	if len(a0) != len(a1) {
		logger.Tracef("address lists have different lengths %d != %d for %v != %v",
			len(a0), len(a1), a0, a1)
		return false
	}

	ca0 := make([]network.Address, len(a0))
	copy(ca0, a0)
	network.SortAddresses(ca0, true)
	ca1 := make([]network.Address, len(a1))
	copy(ca1, a1)
	network.SortAddresses(ca1, true)

	for i := range ca0 {
		if ca0[i] != ca1[i] {
			logger.Tracef("address entry at offset %d has a different value for %v != %v",
				i, ca0, ca1)
			return false
		}
	}
	return true
}
Exemple #4
0
// setAddresses updates the machine's addresses (either Addresses or
// MachineAddresses, depending on the field argument).
func (m *Machine) setAddresses(addresses []network.Address, field *[]address, fieldName string) error {
	var changed bool
	envConfig, err := m.st.EnvironConfig()
	if err != nil {
		return err
	}
	network.SortAddresses(addresses, envConfig.PreferIPv6())
	stateAddresses := instanceAddressesToAddresses(addresses)
	buildTxn := func(attempt int) ([]txn.Op, error) {
		changed = false
		if attempt > 0 {
			if err := m.Refresh(); err != nil {
				return nil, err
			}
		}
		if m.doc.Life == Dead {
			return nil, ErrDead
		}
		op := txn.Op{
			C:      machinesC,
			Id:     m.doc.Id,
			Assert: append(bson.D{{fieldName, *field}}, notDeadDoc...),
		}
		if !addressesEqual(addresses, addressesToInstanceAddresses(*field)) {
			op.Update = bson.D{{"$set", bson.D{{fieldName, stateAddresses}}}}
			changed = true
		}
		return []txn.Op{op}, nil
	}
	switch err := m.st.run(buildTxn); err {
	case nil:
	case jujutxn.ErrExcessiveContention:
		return errors.Annotatef(err, "cannot set %s for machine %s", fieldName, m)
	default:
		return err
	}
	if !changed {
		return nil
	}
	*field = stateAddresses
	return nil
}
Exemple #5
0
func (*AddressSuite) TestSortAddresses(c *gc.C) {
	addrs := network.NewAddresses(
		"127.0.0.1",
		"::1",
		"fc00::1",
		"169.254.1.2",
		"localhost",
		"2001:db8::1",
		"fe80::2",
		"7.8.8.8",
		"172.16.0.1",
		"example.com",
		"8.8.8.8",
	)
	network.SortAddresses(addrs)
	c.Assert(addrs, jc.DeepEquals, network.NewAddresses(
		// Public IPv4 addresses on top.
		"7.8.8.8",
		"8.8.8.8",
		// After that public IPv6 addresses.
		"2001:db8::1",
		// Then hostnames.
		"example.com",
		"localhost",
		// Then IPv4 cloud-local addresses.
		"172.16.0.1",
		// Then IPv6 cloud-local addresses.
		"fc00::1",
		// Then machine-local IPv4 addresses.
		"127.0.0.1",
		// Then machine-local IPv6 addresses.
		"::1",
		// Then link-local IPv4 addresses.
		"169.254.1.2",
		// Finally, link-local IPv6 addresses.
		"fe80::2",
	))
}