From 9e2557c53c81a8f47baaebf9604754b6a61562e2 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Wed, 1 Feb 2017 10:27:04 -0800 Subject: [PATCH] Re-cherry-pick 71d807f607589f2eb4fea4e83e3876d122c8afc0 and e2320d69b6b155d8223758415aabafc60a0e9d3b. --- command/agent/agent.go | 46 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/command/agent/agent.go b/command/agent/agent.go index 6f3171782..1d420e9ab 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -27,6 +27,7 @@ import ( "github.com/hashicorp/go-uuid" "github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/serf" + "github.com/shirou/gopsutil/host" ) const ( @@ -593,6 +594,43 @@ func (a *Agent) setupClient() error { return nil } +// makeRandomID will generate a random UUID for a node. +func (a *Agent) makeRandomID() (string, error) { + id, err := uuid.GenerateUUID() + if err != nil { + return "", err + } + + a.logger.Printf("[DEBUG] Using random ID %q as node ID", id) + return id, nil +} + +// makeNodeID will try to find a host-specific ID, or else will generate a +// random ID. The returned ID will always be formatted as a GUID. We don't tell +// the caller whether this ID is random or stable since the consequences are +// high for us if this changes, so we will persist it either way. This will let +// gopsutil change implementations without affecting in-place upgrades of nodes. +func (a *Agent) makeNodeID() (string, error) { + // Try to get a stable ID associated with the host itself. + info, err := host.Info() + if err != nil { + a.logger.Printf("[DEBUG] Couldn't get a unique ID from the host: %v", err) + return a.makeRandomID() + } + + // Make sure the host ID parses as a UUID, since we don't have complete + // control over this process. + id := strings.ToLower(info.HostID) + if _, err := uuid.ParseUUID(id); err != nil { + a.logger.Printf("[DEBUG] Unique ID %q from host isn't formatted as a UUID: %v", + id, err) + return a.makeRandomID() + } + + a.logger.Printf("[DEBUG] Using unique ID %q from host as node ID", id) + return id, nil +} + // setupNodeID will pull the persisted node ID, if any, or create a random one // and persist it. func (a *Agent) setupNodeID(config *Config) error { @@ -606,15 +644,14 @@ func (a *Agent) setupNodeID(config *Config) error { return nil } - // For dev mode we have no filesystem access so just make a GUID. + // For dev mode we have no filesystem access so just make one. if a.config.DevMode { - id, err := uuid.GenerateUUID() + id, err := a.makeNodeID() if err != nil { return err } config.NodeID = types.NodeID(id) - a.logger.Printf("[INFO] agent: Generated unique node ID %q for this agent (will not be persisted in dev mode)", config.NodeID) return nil } @@ -637,7 +674,7 @@ func (a *Agent) setupNodeID(config *Config) error { // If we still don't have a valid node ID, make one. if config.NodeID == "" { - id, err := uuid.GenerateUUID() + id, err := a.makeNodeID() if err != nil { return err } @@ -649,7 +686,6 @@ func (a *Agent) setupNodeID(config *Config) error { } config.NodeID = types.NodeID(id) - a.logger.Printf("[INFO] agent: Generated unique node ID %q for this agent (persisted)", config.NodeID) } return nil }