2016-01-27 06:22:25 +00:00
|
|
|
package fingerprint
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
client "github.com/hashicorp/nomad/client/config"
|
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
cgroupAvailable = "available"
|
|
|
|
cgroupUnavailable = "unavailable"
|
2016-01-29 13:34:29 +00:00
|
|
|
interval = 15
|
2016-01-27 06:22:25 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type CGroupFingerprint struct {
|
|
|
|
logger *log.Logger
|
|
|
|
lastState string
|
|
|
|
mountPointDetector MountPointDetector
|
|
|
|
}
|
|
|
|
|
|
|
|
// An interface to isolate calls to the cgroup library
|
|
|
|
// This facilitates testing where we can implement
|
2016-01-27 06:36:58 +00:00
|
|
|
// fake mount points to test various code paths
|
2016-01-27 06:22:25 +00:00
|
|
|
type MountPointDetector interface {
|
|
|
|
MountPoint() (string, error)
|
|
|
|
}
|
|
|
|
|
2016-01-27 06:36:58 +00:00
|
|
|
// Implements the interface detector which calls the cgroups library directly
|
2016-01-27 06:22:25 +00:00
|
|
|
type DefaultMountPointDetector struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call out to the default cgroup library
|
|
|
|
func (b *DefaultMountPointDetector) MountPoint() (string, error) {
|
|
|
|
return FindCgroupMountpointDir()
|
|
|
|
}
|
|
|
|
|
2016-01-29 13:34:29 +00:00
|
|
|
// NewCGroupFingerprint returns a new cgroup fingerprinter
|
2016-01-27 06:22:25 +00:00
|
|
|
func NewCGroupFingerprint(logger *log.Logger) Fingerprint {
|
|
|
|
f := &CGroupFingerprint{
|
|
|
|
logger: logger,
|
|
|
|
lastState: cgroupUnavailable,
|
|
|
|
mountPointDetector: &DefaultMountPointDetector{},
|
|
|
|
}
|
|
|
|
return f
|
|
|
|
}
|
|
|
|
|
2016-01-29 13:34:29 +00:00
|
|
|
// Fingerprint tries to find a valid cgroup moint point
|
2016-01-27 06:22:25 +00:00
|
|
|
func (f *CGroupFingerprint) Fingerprint(cfg *client.Config, node *structs.Node) (bool, error) {
|
|
|
|
mount, err := f.mountPointDetector.MountPoint()
|
|
|
|
if err != nil {
|
2016-01-29 13:34:29 +00:00
|
|
|
f.clearCGroupAttributes(node)
|
2016-01-27 06:22:25 +00:00
|
|
|
return false, fmt.Errorf("Failed to discover cgroup mount point: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if a cgroup mount point was found
|
|
|
|
if mount == "" {
|
|
|
|
// Clear any attributes from the previous fingerprint.
|
|
|
|
f.clearCGroupAttributes(node)
|
|
|
|
|
|
|
|
if f.lastState == cgroupAvailable {
|
|
|
|
f.logger.Printf("[INFO] fingerprint.cgroups: cgroups are unavailable")
|
|
|
|
}
|
|
|
|
f.lastState = cgroupUnavailable
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2016-01-29 13:34:29 +00:00
|
|
|
node.Attributes["unique.cgroup.mountpoint"] = mount
|
2016-01-27 06:22:25 +00:00
|
|
|
|
|
|
|
if f.lastState == cgroupUnavailable {
|
|
|
|
f.logger.Printf("[INFO] fingerprint.cgroups: cgroups are available")
|
|
|
|
}
|
|
|
|
f.lastState = cgroupAvailable
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2016-01-29 13:34:29 +00:00
|
|
|
// clearCGroupAttributes clears any node attributes related to cgroups that might
|
|
|
|
// have been set in a previous fingerprint run.
|
2016-01-27 06:22:25 +00:00
|
|
|
func (f *CGroupFingerprint) clearCGroupAttributes(n *structs.Node) {
|
2016-01-29 13:34:29 +00:00
|
|
|
delete(n.Attributes, "unique.cgroup.mountpoint")
|
2016-01-27 06:22:25 +00:00
|
|
|
}
|
|
|
|
|
2016-01-29 13:34:29 +00:00
|
|
|
// Periodic determines the interval at which the periodic fingerprinter will run.
|
2016-01-27 06:22:25 +00:00
|
|
|
func (f *CGroupFingerprint) Periodic() (bool, time.Duration) {
|
2016-01-29 13:34:29 +00:00
|
|
|
return true, interval * time.Second
|
2016-01-27 06:22:25 +00:00
|
|
|
}
|