Merge pull request #391 from hashicorp/f-periodic-fingerprint

Add support for periodic fingerprints and make consul periodic
This commit is contained in:
Alex Dadgar
2015-11-05 18:49:42 -08:00
18 changed files with 81 additions and 15 deletions

View File

@@ -443,11 +443,33 @@ func (c *Client) fingerprint() error {
if applies {
applied = append(applied, name)
}
p, period := f.Periodic()
if p {
// TODO: If more periodic fingerprinters are added, then
// fingerprintPeriodic should be used to handle all the periodic
// fingerprinters by using a priority queue.
go c.fingerprintPeriodic(name, f, period)
}
}
c.logger.Printf("[DEBUG] client: applied fingerprints %v", applied)
return nil
}
// fingerprintPeriodic runs a fingerprinter at the specified duration.
func (c *Client) fingerprintPeriodic(name string, f fingerprint.Fingerprint, d time.Duration) {
c.logger.Printf("[DEBUG] client: periodically fingerprinting %v at duration %v", name, d)
for {
select {
case <-time.After(d):
if _, err := f.Fingerprint(c.config, c.config.Node); err != nil {
c.logger.Printf("[DEBUG] client: periodic fingerprinting for %v failed: %v", name, err)
}
case <-c.shutdownCh:
return
}
}
}
// setupDrivers is used to find the available drivers
func (c *Client) setupDrivers() error {
var avail []string

View File

@@ -13,11 +13,13 @@ import (
"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/driver/args"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/nomad/structs"
)
type DockerDriver struct {
DriverContext
fingerprint.StaticFingerprinter
}
type dockerPID struct {
@@ -37,7 +39,7 @@ type dockerHandle struct {
}
func NewDockerDriver(ctx *DriverContext) Driver {
return &DockerDriver{*ctx}
return &DockerDriver{DriverContext: *ctx}
}
// dockerClient creates *docker.Client. In test / dev mode we can use ENV vars

View File

@@ -10,6 +10,7 @@ import (
"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/driver/executor"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/client/getter"
"github.com/hashicorp/nomad/nomad/structs"
)
@@ -18,6 +19,7 @@ import (
// features.
type ExecDriver struct {
DriverContext
fingerprint.StaticFingerprinter
}
// execHandle is returned from Start/Open as a handle to the PID
@@ -29,7 +31,7 @@ type execHandle struct {
// NewExecDriver is used to create a new exec driver
func NewExecDriver(ctx *DriverContext) Driver {
return &ExecDriver{*ctx}
return &ExecDriver{DriverContext: *ctx}
}
func (d *ExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {

View File

@@ -13,6 +13,7 @@ import (
"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/driver/executor"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/client/getter"
"github.com/hashicorp/nomad/nomad/structs"
)
@@ -21,6 +22,7 @@ import (
// It literally just fork/execs tasks with the java command.
type JavaDriver struct {
DriverContext
fingerprint.StaticFingerprinter
}
// javaHandle is returned from Start/Open as a handle to the PID
@@ -32,7 +34,7 @@ type javaHandle struct {
// NewJavaDriver is used to create a new exec driver
func NewJavaDriver(ctx *DriverContext) Driver {
return &JavaDriver{*ctx}
return &JavaDriver{DriverContext: *ctx}
}
func (d *JavaDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {

View File

@@ -16,6 +16,7 @@ import (
"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/client/getter"
"github.com/hashicorp/nomad/nomad/structs"
)
@@ -29,6 +30,7 @@ var (
// planned in the future
type QemuDriver struct {
DriverContext
fingerprint.StaticFingerprinter
}
// qemuHandle is returned from Start/Open as a handle to the PID
@@ -48,7 +50,7 @@ type qemuPID struct {
// NewQemuDriver is used to create a new exec driver
func NewQemuDriver(ctx *DriverContext) Driver {
return &QemuDriver{*ctx}
return &QemuDriver{DriverContext: *ctx}
}
func (d *QemuDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {

View File

@@ -13,6 +13,7 @@ import (
"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/driver/args"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/client/getter"
"github.com/hashicorp/nomad/nomad/structs"
)
@@ -31,6 +32,7 @@ const (
// and this should only be used when explicitly needed.
type RawExecDriver struct {
DriverContext
fingerprint.StaticFingerprinter
}
// rawExecHandle is returned from Start/Open as a handle to the PID
@@ -42,7 +44,7 @@ type rawExecHandle struct {
// NewRawExecDriver is used to create a new raw exec driver
func NewRawExecDriver(ctx *DriverContext) Driver {
return &RawExecDriver{*ctx}
return &RawExecDriver{DriverContext: *ctx}
}
func (d *RawExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {

View File

@@ -17,6 +17,7 @@ import (
"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/driver/args"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/nomad/structs"
)
@@ -30,6 +31,7 @@ var (
// planned in the future
type RktDriver struct {
DriverContext
fingerprint.StaticFingerprinter
}
// rktHandle is returned from Start/Open as a handle to the PID
@@ -50,7 +52,7 @@ type rktPID struct {
// NewRktDriver is used to create a new exec driver
func NewRktDriver(ctx *DriverContext) Driver {
return &RktDriver{*ctx}
return &RktDriver{DriverContext: *ctx}
}
func (d *RktDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {

View File

@@ -10,6 +10,7 @@ import (
// ArchFingerprint is used to fingerprint the architecture
type ArchFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

View File

@@ -48,7 +48,7 @@ func (f *ConsulFingerprint) Fingerprint(config *client.Config, node *structs.Nod
// If we can't hit this URL consul is probably not running on this machine.
info, err := consulClient.Agent().Self()
if err != nil {
return false, fmt.Errorf("Failed to query consul for agent status: %s", err)
return false, nil
}
node.Attributes["consul.server"] = strconv.FormatBool(info["Config"]["Server"].(bool))
@@ -63,3 +63,7 @@ func (f *ConsulFingerprint) Fingerprint(config *client.Config, node *structs.Nod
return true, nil
}
func (f *ConsulFingerprint) Periodic() (bool, time.Duration) {
return true, 15 * time.Second
}

View File

@@ -11,6 +11,7 @@ import (
// CPUFingerprint is used to fingerprint the CPU
type CPUFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

View File

@@ -69,6 +69,7 @@ var ec2InstanceSpeedMap = map[string]int{
// EnvAWSFingerprint is used to fingerprint AWS metadata
type EnvAWSFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

View File

@@ -46,6 +46,7 @@ func lastToken(s string) string {
// EnvGCEFingerprint is used to fingerprint GCE metadata
type EnvGCEFingerprint struct {
StaticFingerprinter
client *http.Client
logger *log.Logger
metadataURL string

View File

@@ -3,35 +3,41 @@ package fingerprint
import (
"fmt"
"log"
"time"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/nomad/structs"
)
// EmptyDuration is to be used by fingerprinters that are not periodic.
const EmptyDuration = time.Duration(0)
// BuiltinFingerprints is a slice containing the key names of all regestered
// fingerprints available, to provided an ordered iteration
var BuiltinFingerprints = []string{
"arch",
"consul",
"cpu",
"host",
"memory",
"storage",
"network",
"env_aws",
"env_gce",
"host",
"memory",
"network",
"storage",
}
// builtinFingerprintMap contains the built in registered fingerprints
// which are available, corresponding to a key found in BuiltinFingerprints
var builtinFingerprintMap = map[string]Factory{
"arch": NewArchFingerprint,
"consul": NewConsulFingerprint,
"cpu": NewCPUFingerprint,
"host": NewHostFingerprint,
"memory": NewMemoryFingerprint,
"storage": NewStorageFingerprint,
"network": NewNetworkFingerprinter,
"env_aws": NewEnvAWSFingerprint,
"env_gce": NewEnvGCEFingerprint,
"host": NewHostFingerprint,
"memory": NewMemoryFingerprint,
"network": NewNetworkFingerprinter,
"storage": NewStorageFingerprint,
}
// NewFingerprint is used to instantiate and return a new fingerprint
@@ -59,4 +65,17 @@ type Fingerprint interface {
// Fingerprint is used to update properties of the Node,
// and returns if the fingerprint was applicable and a potential error.
Fingerprint(*config.Config, *structs.Node) (bool, error)
// Periodic is a mechanism for the fingerprinter to indicate that it should
// be run periodically. The return value is a boolean indicating if it
// should be periodic, and if true, a duration.
Periodic() (bool, time.Duration)
}
// StaticFingerprinter can be embeded in a struct that has a Fingerprint method
// to make it non-periodic.
type StaticFingerprinter struct{}
func (s *StaticFingerprinter) Periodic() (bool, time.Duration) {
return false, EmptyDuration
}

View File

@@ -14,6 +14,7 @@ import (
// HostFingerprint is used to fingerprint the host
type HostFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

View File

@@ -11,6 +11,7 @@ import (
// MemoryFingerprint is used to fingerprint the available memory on the node
type MemoryFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

View File

@@ -19,6 +19,7 @@ import (
// NetworkFingerprint is used to fingerprint the Network capabilities of a node
type NetworkFingerprint struct {
StaticFingerprinter
logger *log.Logger
interfaceDetector NetworkInterfaceDetector
}

View File

@@ -11,6 +11,7 @@ import (
// NetworkFingerprint is used to fingerprint the Network capabilities of a node
type NetworkFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

View File

@@ -18,6 +18,7 @@ import (
// StorageFingerprint is used to measure the amount of storage free for
// applications that the Nomad agent will run on this machine.
type StorageFingerprint struct {
StaticFingerprinter
logger *log.Logger
}