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

Add support for periodic fingerprints and make consul periodic #391

Merged
merged 4 commits into from
Nov 6, 2015
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,11 +443,35 @@ 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. If the
// fingerprinter returns an error, the function exits.
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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should continue fingerprinting if it returns an error since it might recover later.

c.logger.Printf("[DEBUG] client: disabling periodic fingerprinting for %v: %v", name, err)
return
}
case <-c.shutdownCh:
return
}
}
}

// setupDrivers is used to find the available drivers
func (c *Client) setupDrivers() error {
var avail []string
Expand Down
4 changes: 3 additions & 1 deletion client/driver/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
4 changes: 3 additions & 1 deletion client/driver/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -18,6 +19,7 @@ import (
// features.
type ExecDriver struct {
DriverContext
fingerprint.StaticFingerprinter
}

// execHandle is returned from Start/Open as a handle to the PID
Expand All @@ -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) {
Expand Down
4 changes: 3 additions & 1 deletion client/driver/java.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -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
Expand All @@ -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) {
Expand Down
4 changes: 3 additions & 1 deletion client/driver/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -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
Expand All @@ -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) {
Expand Down
4 changes: 3 additions & 1 deletion client/driver/raw_exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -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
Expand All @@ -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) {
Expand Down
4 changes: 3 additions & 1 deletion client/driver/rkt.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -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
Expand All @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions client/fingerprint/arch.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

// ArchFingerprint is used to fingerprint the architecture
type ArchFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

Expand Down
6 changes: 5 additions & 1 deletion client/fingerprint/consul.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
}
1 change: 1 addition & 0 deletions client/fingerprint/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

// CPUFingerprint is used to fingerprint the CPU
type CPUFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

Expand Down
1 change: 1 addition & 0 deletions client/fingerprint/env_aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ var ec2InstanceSpeedMap = map[string]int{

// EnvAWSFingerprint is used to fingerprint AWS metadata
type EnvAWSFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

Expand Down
1 change: 1 addition & 0 deletions client/fingerprint/env_gce.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 25 additions & 6 deletions client/fingerprint/fingerprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
"env_aws",
"env_gce",
"host",
"memory",
"storage",
"network",
"env_aws",
"env_gce",
"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,
"env_aws": NewEnvAWSFingerprint,
"env_gce": NewEnvGCEFingerprint,
"host": NewHostFingerprint,
"memory": NewMemoryFingerprint,
"storage": NewStorageFingerprint,
"network": NewNetworkFingerprinter,
"env_aws": NewEnvAWSFingerprint,
"env_gce": NewEnvGCEFingerprint,
"storage": NewStorageFingerprint,
}

// NewFingerprint is used to instantiate and return a new fingerprint
Expand Down Expand Up @@ -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
}
1 change: 1 addition & 0 deletions client/fingerprint/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

// HostFingerprint is used to fingerprint the host
type HostFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

Expand Down
1 change: 1 addition & 0 deletions client/fingerprint/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

// MemoryFingerprint is used to fingerprint the available memory on the node
type MemoryFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

Expand Down
1 change: 1 addition & 0 deletions client/fingerprint/network_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
1 change: 1 addition & 0 deletions client/fingerprint/network_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

// NetworkFingerprint is used to fingerprint the Network capabilities of a node
type NetworkFingerprint struct {
StaticFingerprinter
logger *log.Logger
}

Expand Down
1 change: 1 addition & 0 deletions client/fingerprint/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down