Changed logs to errors; added data to node.Resources.DiskMB
This commit is contained in:
parent
cd5cd7efc2
commit
d17c6128c8
|
@ -11,7 +11,6 @@ import (
|
|||
// fork/execs tasks. It should probably not be used for most things,
|
||||
// but is useful for testing purposes or for very simple tasks.
|
||||
type ExecDriver struct {
|
||||
id string
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
|
@ -23,16 +22,11 @@ type execHandle struct {
|
|||
// NewExecDriver is used to create a new exec driver
|
||||
func NewExecDriver(logger *log.Logger) Driver {
|
||||
d := &ExecDriver{
|
||||
id: "driver.exec",
|
||||
logger: logger,
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *ExecDriver) ID() string {
|
||||
return d.id
|
||||
}
|
||||
|
||||
func (d *ExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
// We can always do a fork/exec
|
||||
node.Attributes["driver.exec"] = "1"
|
||||
|
|
|
@ -10,23 +10,15 @@ import (
|
|||
|
||||
// ArchFingerprint is used to fingerprint the architecture
|
||||
type ArchFingerprint struct {
|
||||
id string
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
// NewArchFingerprint is used to create an OS fingerprint
|
||||
func NewArchFingerprint(logger *log.Logger) Fingerprint {
|
||||
f := &ArchFingerprint{
|
||||
id: "fingerprint.arch",
|
||||
logger: logger,
|
||||
}
|
||||
f := &ArchFingerprint{logger: logger}
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *ArchFingerprint) ID() string {
|
||||
return f.id
|
||||
}
|
||||
|
||||
func (f *ArchFingerprint) Fingerprint(config *client.Config, node *structs.Node) (bool, error) {
|
||||
node.Attributes["arch"] = runtime.GOARCH
|
||||
f.logger.Printf("[DEBUG] fingerprint.arch: detected '%s'", runtime.GOARCH)
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
package fingerprint
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func testLogger() *log.Logger {
|
||||
return log.New(os.Stderr, "", log.LstdFlags)
|
||||
}
|
|
@ -16,7 +16,7 @@ type CPUFingerprint struct {
|
|||
|
||||
// NewCPUFingerprint is used to create a CPU fingerprint
|
||||
func NewCPUFingerprint(logger *log.Logger) Fingerprint {
|
||||
f := &CPUFingerprint{logger}
|
||||
f := &CPUFingerprint{logger: logger}
|
||||
return f
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,5 @@ type Factory func(*log.Logger) Fingerprint
|
|||
type Fingerprint interface {
|
||||
// Fingerprint is used to update properties of the Node,
|
||||
// and returns if the fingerprint was applicable and a potential error.
|
||||
ID() string
|
||||
Fingerprint(*config.Config, *structs.Node) (bool, error)
|
||||
}
|
||||
|
|
|
@ -18,10 +18,10 @@ func testLogger() *log.Logger {
|
|||
func assertFingerprintOK(t *testing.T, fp Fingerprint, node *structs.Node) {
|
||||
ok, err := fp.Fingerprint(new(config.Config), node)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to fingerprint `%s`: `%s`", fp.ID, err)
|
||||
t.Fatalf("Failed to fingerprint: %s", err)
|
||||
}
|
||||
if !ok {
|
||||
t.Fatalf("Failed to apply node attributes for `%s`", fp.ID)
|
||||
t.Fatalf("Failed to apply node attributes")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ type HostFingerprint struct {
|
|||
|
||||
// NewHostFingerprint is used to create a Host fingerprint
|
||||
func NewHostFingerprint(logger *log.Logger) Fingerprint {
|
||||
f := &HostFingerprint{logger}
|
||||
f := &HostFingerprint{logger: logger}
|
||||
return f
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@ func TestHostFingerprint(t *testing.T) {
|
|||
|
||||
// Host info
|
||||
for _, key := range []string{"os.name", "os.version", "hostname", "kernel.name"} {
|
||||
if node.Attributes[key] == "" {
|
||||
t.Fatalf("Missing (%s) in Host Info attribute check", key)
|
||||
}
|
||||
assertNodeAttributeContains(t, node, key)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,23 +10,15 @@ import (
|
|||
|
||||
// OSFingerprint is used to fingerprint the operating system
|
||||
type OSFingerprint struct {
|
||||
id string
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
// NewOSFingerprint is used to create an OS fingerprint
|
||||
func NewOSFingerprint(logger *log.Logger) Fingerprint {
|
||||
f := &OSFingerprint{
|
||||
id: "fingerprint.os",
|
||||
logger: logger,
|
||||
}
|
||||
f := &OSFingerprint{logger: logger}
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *OSFingerprint) ID() string {
|
||||
return f.id
|
||||
}
|
||||
|
||||
func (f *OSFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
node.Attributes["os"] = runtime.GOOS
|
||||
f.logger.Printf("[DEBUG] fingerprint.os: detected '%s'", runtime.GOOS)
|
||||
|
|
|
@ -17,7 +17,6 @@ import (
|
|||
// StorageFingerprint is used to measure the amount of storage available for
|
||||
// applications that the Nomad agent will run on this machine.
|
||||
type StorageFingerprint struct {
|
||||
id string
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
|
@ -27,18 +26,10 @@ var (
|
|||
)
|
||||
|
||||
func NewStorageFingerprint(logger *log.Logger) Fingerprint {
|
||||
fp := &StorageFingerprint{
|
||||
id: "fingerprint.storage",
|
||||
logger: logger,
|
||||
}
|
||||
fp.logger.SetPrefix(fmt.Sprintf("%s ", fp.id))
|
||||
fp := &StorageFingerprint{logger: logger}
|
||||
return fp
|
||||
}
|
||||
|
||||
func (f *StorageFingerprint) ID() string {
|
||||
return f.id
|
||||
}
|
||||
|
||||
func (f *StorageFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
|
||||
// Initialize these to empty defaults
|
||||
|
@ -49,13 +40,13 @@ func (f *StorageFingerprint) Fingerprint(cfg *config.Config, node *structs.Node)
|
|||
if runtime.GOOS == "windows" {
|
||||
path, err := filepath.Abs(cfg.AllocDir)
|
||||
if err != nil {
|
||||
f.logger.Printf("[ERROR] Failed to detect volume for storage directory %s: %s", cfg.AllocDir, err)
|
||||
return false, fmt.Errorf("Failed to detect volume for storage directory %s: %s", cfg.AllocDir, err)
|
||||
}
|
||||
volume := filepath.VolumeName(path)
|
||||
node.Attributes["storage.volume"] = volume
|
||||
out, err := exec.Command("fsutil", "volume", "diskfree", volume).Output()
|
||||
if err != nil {
|
||||
f.logger.Printf("[ERROR] Failed to inspect free space from volume %s: %s", volume, err)
|
||||
return false, fmt.Errorf("Failed to inspect free space from volume %s: %s", volume, err)
|
||||
}
|
||||
|
||||
outstring := string(out)
|
||||
|
@ -64,24 +55,30 @@ func (f *StorageFingerprint) Fingerprint(cfg *config.Config, node *structs.Node)
|
|||
if len(totalMatches) == 2 {
|
||||
node.Attributes["storage.bytestotal"] = totalMatches[1]
|
||||
} else {
|
||||
f.logger.Printf("[WARN] Failed to determine storage.bytestotal")
|
||||
return false, fmt.Errorf("Failed to determine storage.bytestotal")
|
||||
}
|
||||
freeMatches := reWindowsFreeSpace.FindStringSubmatch(outstring)
|
||||
if len(freeMatches) == 2 {
|
||||
node.Attributes["storage.bytesavailable"] = freeMatches[1]
|
||||
available, err := strconv.ParseInt(freeMatches[1], 10, 64)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Failed to parse storage.bytesavailable in bytes: %s", err)
|
||||
}
|
||||
// Convert from bytes to to MB
|
||||
node.Resources.DiskMB = int(available / 1024 / 1024)
|
||||
} else {
|
||||
f.logger.Printf("[WARN] Failed to determine storage.bytesavailable")
|
||||
return false, fmt.Errorf("Failed to determine storage.bytesavailable")
|
||||
}
|
||||
} else {
|
||||
path, err := filepath.Abs(cfg.AllocDir)
|
||||
if err != nil {
|
||||
f.logger.Printf("[ERROR] Failed to determine absolute path for %s", cfg.AllocDir)
|
||||
return false, fmt.Errorf("Failed to determine absolute path for %s", cfg.AllocDir)
|
||||
}
|
||||
|
||||
// Use -k to standardize the output values between darwin and linux
|
||||
mountOutput, err := exec.Command("df", "-k", path).Output()
|
||||
if err != nil {
|
||||
f.logger.Printf("[ERROR] Failed to determine mount point for %s", path)
|
||||
return false, fmt.Errorf("Failed to determine mount point for %s", path)
|
||||
}
|
||||
// Output looks something like:
|
||||
// Filesystem 1024-blocks Used Available Capacity iused ifree %iused Mounted on
|
||||
|
@ -93,14 +90,17 @@ func (f *StorageFingerprint) Fingerprint(cfg *config.Config, node *structs.Node)
|
|||
|
||||
total, err := strconv.ParseInt(fields[1], 10, 64)
|
||||
if err != nil {
|
||||
f.logger.Printf("[WARN] Failed to parse storage.bytestotal size in kilobytes")
|
||||
return false, fmt.Errorf("Failed to parse storage.bytestotal size in kilobytes")
|
||||
}
|
||||
node.Attributes["storage.bytestotal"] = strconv.FormatInt(total*1024, 10)
|
||||
|
||||
available, err := strconv.ParseInt(fields[3], 10, 64)
|
||||
if err != nil {
|
||||
f.logger.Printf("[WARN] Failed to parse storage.bytesavailable size in kilobytes")
|
||||
return false, fmt.Errorf("Failed to parse storage.bytesavailable size in kilobytes")
|
||||
}
|
||||
// Convert from KB to MB
|
||||
node.Resources.DiskMB = int(available / 1024)
|
||||
// Convert from KB to bytes
|
||||
node.Attributes["storage.bytesavailable"] = strconv.FormatInt(available*1024, 10)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,55 @@
|
|||
package fingerprint
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/nomad/client/config"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
)
|
||||
|
||||
func TestStorageFingerprint(t *testing.T) {
|
||||
f := NewStorageFingerprint(testLogger())
|
||||
fp := NewStorageFingerprint(testLogger())
|
||||
node := &structs.Node{
|
||||
Attributes: make(map[string]string),
|
||||
Resources: &structs.Resources{},
|
||||
}
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get test working directory: %s", err)
|
||||
}
|
||||
cfg := &config.Config{
|
||||
AllocDir: cwd,
|
||||
}
|
||||
|
||||
ok, err := fp.Fingerprint(cfg, node)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to fingerprint: `%s`", err)
|
||||
}
|
||||
if !ok {
|
||||
t.Fatal("Failed to apply node attributes")
|
||||
}
|
||||
|
||||
assertFingerprintOK(t, f, node)
|
||||
assertNodeAttributeContains(t, node, "storage.volume")
|
||||
assertNodeAttributeContains(t, node, "storage.bytestotal")
|
||||
assertNodeAttributeContains(t, node, "storage.bytesavailable")
|
||||
|
||||
total, err := strconv.ParseInt(node.Attributes["storage.bytestotal"], 10, 64)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse storage.bytestotal: %s", err)
|
||||
}
|
||||
available, err := strconv.ParseInt(node.Attributes["storage.bytesavailable"], 10, 64)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse storage.bytesavailable: %s", err)
|
||||
}
|
||||
|
||||
if available > total {
|
||||
t.Errorf("storage.bytesavailable %d is larger than storage.bytestotal %d", available, total)
|
||||
}
|
||||
|
||||
if node.Resources.DiskMB == 0 {
|
||||
t.Errorf("Expected node.Resources.DiskMB to be non-zero")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue