Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed lp:1574844: juju2 gives ipv6 address for one lxd, rabbit doesn't appreciate it. #5435

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9cd8891
go rename machineDoc.PreferredPublicAddress -> PreferredPublicIPv4Add…
May 16, 2016
78fe6aa
go rename machineDoc.PreferredPrivateAddress -> PreferredPrivateIPv4A…
May 16, 2016
93f01f7
core/description: Updated public/private addresses fields to include …
May 16, 2016
ed690b5
state: Fix upgrade step to include ipv4 for preferredprivate|publicad…
May 16, 2016
48b34bd
state: Migrations updated similarly to use IPv4 for public/private addrs
May 16, 2016
f7ac9f5
state: Updated field names used for private|public machine addresses
May 16, 2016
fa7af32
Initial attempt at refactoring preferred addresses handling
May 19, 2016
c2893e2
Reverted most of the refactoring to network and state/machine
May 19, 2016
05d5524
core/description: Added PreferredPublic|PrivateIPv6Address and setter
May 19, 2016
5f87296
core/description: Implementations for preferred IPv6 addresses handling
May 19, 2016
811ad35
state: Updated upgrade steps to handle IPv6 as well as IPv4 addresses
May 19, 2016
09f132f
state: Migration export sets IPv6 preferred addresses
May 19, 2016
84e2be0
state: Migration import sets preferred IPv6 addresses
May 19, 2016
07a1ed0
state: Updated migration internal tests for IPv6 addresses
May 19, 2016
4cc7aba
state: machineDocFromTemplate handles both IPv4 and IPv6 preferred addrs
May 19, 2016
44634ad
network: Allow selecting internal/public addresses by type as well as…
May 19, 2016
4d3f6f0
state: Proper handling of preferred machine IPv4 / IPv6 addresses
May 19, 2016
f5fe59b
state: Fixed upgrade steps around preferred addresses to handle IPv6 …
May 19, 2016
069b124
TODO for extra test
May 20, 2016
acedf41
cmd/jujud/agent: Disabled flaky test MachineSuite.TestDyingModelCleanup
May 23, 2016
a165f97
core/description: added AddressType mirroring network.AddressType
May 23, 2016
88e1706
core/description: Refactored preferred addresses methods
May 23, 2016
e72b4cd
core/description: Implemented refactored preferred addresses methods
May 23, 2016
9f98dd6
core/description: Updated preferred addresses tests
May 23, 2016
8febf28
state: Fixed migration export/import after preferred addresses refact…
May 23, 2016
2b63028
storage/looputil: Handle loop devs with 0 inode (fixed provisioner te…
May 23, 2016
a1f508f
network: Refactored address selection to minimize duplication and imp…
May 23, 2016
ee07624
state: Use network.AddressType.IsConsistentWith vs IsSameTypeOrHostName
May 23, 2016
806a3f4
state: Removed TODO for already covered test case
May 23, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/jujud/agent/machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1588,6 +1588,8 @@ func (s *MachineSuite) TestHostedModelWorkers(c *gc.C) {
}

func (s *MachineSuite) TestDyingModelCleanedUp(c *gc.C) {
c.Skip("test disabled as flaky, see lp:1584626")

tracker := newModelTracker(c)
check := modelMatchFunc(c, tracker, append(
alwaysModelWorkers, deadModelWorkers...,
Expand Down
9 changes: 9 additions & 0 deletions core/description/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ import (
"github.com/juju/schema"
)

// AddressType shadows the equivalent type in the network package.
type AddressType string

const (
HostName AddressType = "hostname"
IPv4Address AddressType = "ipv4"
IPv6Address AddressType = "ipv6"
)

// AddressArgs is an argument struct used to create a new internal address
// type that supports the Address interface.
type AddressArgs struct {
Expand Down
6 changes: 3 additions & 3 deletions core/description/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ type Machine interface {
MachineAddresses() []Address
SetAddresses(machine []AddressArgs, provider []AddressArgs)

PreferredPublicAddress() Address
PreferredPrivateAddress() Address
SetPreferredAddresses(public AddressArgs, private AddressArgs)
PreferredPublicAddress(addressType AddressType) Address
PreferredPrivateAddress(addressType AddressType) Address
SetPreferredAddresses(publicIPv4, publicIPv6, privateIPv4, privateIPv6 AddressArgs)

Tools() AgentTools
SetTools(AgentToolsArgs)
Expand Down
112 changes: 80 additions & 32 deletions core/description/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ type machine struct {
ProviderAddresses_ []*address `yaml:"provider-addresses,omitempty"`
MachineAddresses_ []*address `yaml:"machine-addresses,omitempty"`

PreferredPublicAddress_ *address `yaml:"preferred-public-address,omitempty"`
PreferredPrivateAddress_ *address `yaml:"preferred-private-address,omitempty"`
PreferredPublicIPv4Address_ *address `yaml:"preferred-public-ipv4-address,omitempty"`
PreferredPrivateIPv4Address_ *address `yaml:"preferred-private-ipv4-address,omitempty"`
PreferredPublicIPv6Address_ *address `yaml:"preferred-public-ipv6-address,omitempty"`
PreferredPrivateIPv6Address_ *address `yaml:"preferred-private-ipv6-address,omitempty"`

Tools_ *agentTools `yaml:"tools"`
Jobs_ []string `yaml:"jobs"`
Expand Down Expand Up @@ -183,30 +185,56 @@ func (m *machine) SetAddresses(margs []AddressArgs, pargs []AddressArgs) {
}

// PreferredPublicAddress implements Machine.
func (m *machine) PreferredPublicAddress() Address {
// To avoid typed nils check nil here.
if m.PreferredPublicAddress_ == nil {
func (m *machine) PreferredPublicAddress(addressType AddressType) Address {
switch addressType {
case IPv4Address, HostName:
// To avoid typed nils check nil here.
if m.PreferredPublicIPv4Address_ != nil {
return m.PreferredPublicIPv4Address_
}
return nil
case IPv6Address:
// To avoid typed nils check nil here.
if m.PreferredPublicIPv6Address_ != nil {
return m.PreferredPublicIPv6Address_
}
return nil
}
return m.PreferredPublicAddress_
return nil
}

// PreferredPrivateAddress implements Machine.
func (m *machine) PreferredPrivateAddress() Address {
// To avoid typed nils check nil here.
if m.PreferredPrivateAddress_ == nil {
func (m *machine) PreferredPrivateAddress(addressType AddressType) Address {
switch addressType {
case IPv4Address, HostName:
// To avoid typed nils check nil here.
if m.PreferredPrivateIPv4Address_ != nil {
return m.PreferredPrivateIPv4Address_
}
return nil
case IPv6Address:
// To avoid typed nils check nil here.
if m.PreferredPrivateIPv6Address_ != nil {
return m.PreferredPrivateIPv6Address_
}
return nil
}
return m.PreferredPrivateAddress_
return nil
}

// SetPreferredAddresses implements Machine.
func (m *machine) SetPreferredAddresses(public AddressArgs, private AddressArgs) {
if public.Value != "" {
m.PreferredPublicAddress_ = newAddress(public)
func (m *machine) SetPreferredAddresses(publicIPv4, publicIPv6, privateIPv4, privateIPv6 AddressArgs) {
if publicIPv4.Value != "" {
m.PreferredPublicIPv4Address_ = newAddress(publicIPv4)
}
if publicIPv6.Value != "" {
m.PreferredPublicIPv6Address_ = newAddress(publicIPv6)
}
if private.Value != "" {
m.PreferredPrivateAddress_ = newAddress(private)
if privateIPv4.Value != "" {
m.PreferredPrivateIPv4Address_ = newAddress(privateIPv4)
}
if privateIPv6.Value != "" {
m.PreferredPrivateIPv6Address_ = newAddress(privateIPv6)
}
}

Expand Down Expand Up @@ -375,24 +403,28 @@ func importMachineV1(source map[string]interface{}) (*machine, error) {
"containers": schema.List(schema.StringMap(schema.Any())),
"opened-ports": schema.StringMap(schema.Any()),

"provider-addresses": schema.List(schema.StringMap(schema.Any())),
"machine-addresses": schema.List(schema.StringMap(schema.Any())),
"preferred-public-address": schema.StringMap(schema.Any()),
"preferred-private-address": schema.StringMap(schema.Any()),
"provider-addresses": schema.List(schema.StringMap(schema.Any())),
"machine-addresses": schema.List(schema.StringMap(schema.Any())),
"preferred-public-ipv4-address": schema.StringMap(schema.Any()),
"preferred-private-ipv4-address": schema.StringMap(schema.Any()),
"preferred-public-ipv6-address": schema.StringMap(schema.Any()),
"preferred-private-ipv6-address": schema.StringMap(schema.Any()),
}

defaults := schema.Defaults{
"placement": "",
"container-type": "",
// Even though we are expecting instance data for every machine,
// it isn't strictly necessary, so we allow it to not exist here.
"instance": schema.Omit,
"supported-containers": schema.Omit,
"opened-ports": schema.Omit,
"provider-addresses": schema.Omit,
"machine-addresses": schema.Omit,
"preferred-public-address": schema.Omit,
"preferred-private-address": schema.Omit,
"instance": schema.Omit,
"supported-containers": schema.Omit,
"opened-ports": schema.Omit,
"provider-addresses": schema.Omit,
"machine-addresses": schema.Omit,
"preferred-public-ipv4-address": schema.Omit,
"preferred-private-ipv4-address": schema.Omit,
"preferred-public-ipv6-address": schema.Omit,
"preferred-private-ipv6-address": schema.Omit,
}
addAnnotationSchema(fields, defaults)
addConstraintsSchema(fields, defaults)
Expand Down Expand Up @@ -479,20 +511,36 @@ func importMachineV1(source map[string]interface{}) (*machine, error) {
result.MachineAddresses_ = machineAddresses
}

if address, ok := valid["preferred-public-address"]; ok {
publicAddress, err := importAddress(address.(map[string]interface{}))
if address, ok := valid["preferred-public-ipv4-address"]; ok {
publicIPv4Address, err := importAddress(address.(map[string]interface{}))
if err != nil {
return nil, errors.Trace(err)
}
result.PreferredPublicIPv4Address_ = publicIPv4Address
}

if address, ok := valid["preferred-private-ipv4-address"]; ok {
privateIPv4Address, err := importAddress(address.(map[string]interface{}))
if err != nil {
return nil, errors.Trace(err)
}
result.PreferredPrivateIPv4Address_ = privateIPv4Address
}

if address, ok := valid["preferred-public-ipv6-address"]; ok {
publicIPv6Address, err := importAddress(address.(map[string]interface{}))
if err != nil {
return nil, errors.Trace(err)
}
result.PreferredPublicAddress_ = publicAddress
result.PreferredPublicIPv6Address_ = publicIPv6Address
}

if address, ok := valid["preferred-private-address"]; ok {
privateAddress, err := importAddress(address.(map[string]interface{}))
if address, ok := valid["preferred-private-ipv6-address"]; ok {
privateIPv6Address, err := importAddress(address.(map[string]interface{}))
if err != nil {
return nil, errors.Trace(err)
}
result.PreferredPrivateAddress_ = privateAddress
result.PreferredPrivateIPv6Address_ = privateIPv6Address
}

machineList := valid["containers"].([]interface{})
Expand Down
24 changes: 14 additions & 10 deletions core/description/machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,17 +286,21 @@ func (s *MachineSerializationSuite) TestParsingSerializedData(c *gc.C) {
s.addOpenedPorts(m)

// Just use one set of address args for both machine and provider.
addrArgs := []AddressArgs{
{
Value: "10.0.0.10",
Type: "special",
}, {
Value: "10.1.2.3",
Type: "other",
},
}
addrArgs := []AddressArgs{{
Value: "10.0.0.10",
Type: "special",
}, {
Value: "2001:db8::/64",
Type: "special",
}, {
Value: "10.1.2.3",
Type: "other",
}, {
Value: "fc00:123::/64",
Type: "other",
}}
m.SetAddresses(addrArgs, addrArgs)
m.SetPreferredAddresses(addrArgs[0], addrArgs[1])
m.SetPreferredAddresses(addrArgs[0], addrArgs[1], addrArgs[2], addrArgs[3])

// Make sure the machine is valid.
c.Assert(m.Validate(), jc.ErrorIsNil)
Expand Down
65 changes: 63 additions & 2 deletions network/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ const (
IPv6Address AddressType = "ipv6"
)

// IsConsistentWith returns whether current is the same as other, or either of
// the types is a HostHame. Hostnames potentially resolve to one or more IPv4,
// IPv6 or even both address types, so without actually resolving them we can
// reasonably treat them as IPv4 or IPv6, depending on context.
func (current AddressType) IsConsistentWith(other AddressType) bool {
return current == other || current == HostName || other == HostName
}

// Scope denotes the context a location may apply to. If a name or
// address can be reached from the wider internet, it is considered
// public. A private network address is either specific to the cloud
Expand Down Expand Up @@ -351,9 +359,25 @@ func SelectMongoHostPortsByScope(hostPorts []HostPort, machineLocal bool) []stri
// are no suitable addresses, then ok is false (and an empty address is
// returned). If a suitable address is then ok is true.
func SelectPublicAddress(addresses []Address) (Address, bool) {
return selectPublicAddressOptionallyWithType(addresses, "")
}

// SelectPublicAddressWithType works like SelectPublicAddress, but only
// considers addresses with the given addrType
func SelectPublicAddressWithType(addresses []Address, addrType AddressType) (Address, bool) {
return selectPublicAddressOptionallyWithType(addresses, addrType)
}

func selectPublicAddressOptionallyWithType(addresses []Address, addrType AddressType) (Address, bool) {
matcher := publicMatch
if addrType != "" {
matcher = publicTypedMatcher(addrType)
}

index := bestAddressIndex(len(addresses), func(i int) Address {
return addresses[i]
}, publicMatch)
}, matcher)

if index < 0 {
return Address{}, false
}
Expand All @@ -378,12 +402,29 @@ func SelectPublicHostPort(hps []HostPort) string {
// are no suitable addresses, then ok is false (and an empty address is
// returned). If a suitable address was found then ok is true.
func SelectInternalAddress(addresses []Address, machineLocal bool) (Address, bool) {
return selectInternalAddressOptionallyWithType(addresses, "", machineLocal)
}

// SelectInternalAddressWithType works like SelectInternalAddress, but only
// considers addresses with the given addrType
func SelectInternalAddressWithType(addresses []Address, addrType AddressType, machineLocal bool) (Address, bool) {
return selectInternalAddressOptionallyWithType(addresses, addrType, machineLocal)
}

func selectInternalAddressOptionallyWithType(addresses []Address, addrType AddressType, machineLocal bool) (Address, bool) {
matcher := internalAddressMatcher(machineLocal)
if addrType != "" {
matcher = internalTypedAddressMatcher(machineLocal, addrType)
}

index := bestAddressIndex(len(addresses), func(i int) Address {
return addresses[i]
}, internalAddressMatcher(machineLocal))
}, matcher)

if index < 0 {
return Address{}, false
}

return addresses[index], true
}

Expand Down Expand Up @@ -443,13 +484,33 @@ func publicMatch(addr Address) scopeMatch {
return invalidScope
}

func publicTypedMatcher(addrType AddressType) scopeMatchFunc {
return func(addr Address) scopeMatch {
if !addr.Type.IsConsistentWith(addrType) {
return invalidScope
}

return publicMatch(addr)
}
}

func internalAddressMatcher(machineLocal bool) scopeMatchFunc {
if machineLocal {
return cloudOrMachineLocalMatch
}
return cloudLocalMatch
}

func internalTypedAddressMatcher(machineLocal bool, addrType AddressType) scopeMatchFunc {
return func(addr Address) scopeMatch {
if !addr.Type.IsConsistentWith(addrType) {
return invalidScope
}

return internalAddressMatcher(machineLocal)(addr)
}
}

func cloudLocalMatch(addr Address) scopeMatch {
switch addr.Scope {
case ScopeCloudLocal:
Expand Down
36 changes: 20 additions & 16 deletions state/addmachine.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,23 +449,27 @@ func (st *State) machineDocForTemplate(template MachineTemplate, id string) *mac
// no address is available, in which case the empty address is returned
// and setting the preferred address to an empty one is the correct
// thing to do when none is available.
privateAddr, _ := network.SelectInternalAddress(template.Addresses, false)
publicAddr, _ := network.SelectPublicAddress(template.Addresses)
privateIPv4Addr, _ := network.SelectInternalAddressWithType(template.Addresses, network.IPv4Address, false)
privateIPv6Addr, _ := network.SelectInternalAddressWithType(template.Addresses, network.IPv6Address, false)
publicIPv4Addr, _ := network.SelectPublicAddressWithType(template.Addresses, network.IPv4Address)
publicIPv6Addr, _ := network.SelectPublicAddressWithType(template.Addresses, network.IPv6Address)
return &machineDoc{
DocID: st.docID(id),
Id: id,
ModelUUID: st.ModelUUID(),
Series: template.Series,
Jobs: template.Jobs,
Clean: !template.Dirty,
Principals: template.principals,
Life: Alive,
Nonce: template.Nonce,
Addresses: fromNetworkAddresses(template.Addresses, OriginMachine),
PreferredPrivateAddress: fromNetworkAddress(privateAddr, OriginMachine),
PreferredPublicAddress: fromNetworkAddress(publicAddr, OriginMachine),
NoVote: template.NoVote,
Placement: template.Placement,
DocID: st.docID(id),
Id: id,
ModelUUID: st.ModelUUID(),
Series: template.Series,
Jobs: template.Jobs,
Clean: !template.Dirty,
Principals: template.principals,
Life: Alive,
Nonce: template.Nonce,
Addresses: fromNetworkAddresses(template.Addresses, OriginMachine),
PreferredPrivateIPv4Address: fromNetworkAddress(privateIPv4Addr, OriginMachine),
PreferredPublicIPv4Address: fromNetworkAddress(publicIPv4Addr, OriginMachine),
PreferredPrivateIPv6Address: fromNetworkAddress(privateIPv6Addr, OriginMachine),
PreferredPublicIPv6Address: fromNetworkAddress(publicIPv6Addr, OriginMachine),
NoVote: template.NoVote,
Placement: template.Placement,
}
}

Expand Down