mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 02:15:43 +03:00
Drivers log during fingerprinting
This PR fixes a regression in which some drivers did not log during fingerprinting.
This commit is contained in:
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/hashicorp/nomad/client/driver/executor"
|
||||
dstructs "github.com/hashicorp/nomad/client/driver/structs"
|
||||
cstructs "github.com/hashicorp/nomad/client/structs"
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
"github.com/hashicorp/nomad/helper/fields"
|
||||
shelpers "github.com/hashicorp/nomad/helper/stats"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
@@ -108,6 +109,10 @@ type DockerDriver struct {
|
||||
|
||||
driverConfig *DockerDriverConfig
|
||||
imageID string
|
||||
|
||||
// A tri-state boolean to know if the fingerprinting has happened and
|
||||
// whether it has been successful
|
||||
fingerprintSuccess *bool
|
||||
}
|
||||
|
||||
type DockerDriverAuth struct {
|
||||
@@ -262,6 +267,48 @@ func NewDockerDriver(ctx *DriverContext) Driver {
|
||||
return &DockerDriver{DriverContext: *ctx}
|
||||
}
|
||||
|
||||
func (d *DockerDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
// Initialize docker API clients
|
||||
client, _, err := d.dockerClients()
|
||||
if err != nil {
|
||||
if d.fingerprintSuccess == nil || *d.fingerprintSuccess {
|
||||
d.logger.Printf("[INFO] driver.docker: failed to initialize client: %s", err)
|
||||
}
|
||||
delete(node.Attributes, dockerDriverAttr)
|
||||
d.fingerprintSuccess = helper.BoolToPtr(false)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// This is the first operation taken on the client so we'll try to
|
||||
// establish a connection to the Docker daemon. If this fails it means
|
||||
// Docker isn't available so we'll simply disable the docker driver.
|
||||
env, err := client.Version()
|
||||
if err != nil {
|
||||
delete(node.Attributes, dockerDriverAttr)
|
||||
if d.fingerprintSuccess == nil || *d.fingerprintSuccess {
|
||||
d.logger.Printf("[DEBUG] driver.docker: could not connect to docker daemon at %s: %s", client.Endpoint(), err)
|
||||
}
|
||||
d.fingerprintSuccess = helper.BoolToPtr(false)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
node.Attributes[dockerDriverAttr] = "1"
|
||||
node.Attributes["driver.docker.version"] = env.Get("Version")
|
||||
|
||||
privileged := d.config.ReadBoolDefault(dockerPrivilegedConfigOption, false)
|
||||
if privileged {
|
||||
node.Attributes[dockerPrivilegedConfigOption] = "1"
|
||||
}
|
||||
|
||||
// Advertise if this node supports Docker volumes
|
||||
if d.config.ReadBoolDefault(dockerVolumesConfigOption, dockerVolumesConfigDefault) {
|
||||
node.Attributes["driver."+dockerVolumesConfigOption] = "1"
|
||||
}
|
||||
|
||||
d.fingerprintSuccess = helper.BoolToPtr(true)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Validate is used to validate the driver configuration
|
||||
func (d *DockerDriver) Validate(config map[string]interface{}) error {
|
||||
fd := &fields.FieldData{
|
||||
@@ -618,49 +665,6 @@ func (d *DockerDriver) dockerClients() (*docker.Client, *docker.Client, error) {
|
||||
return client, waitClient, merr.ErrorOrNil()
|
||||
}
|
||||
|
||||
func (d *DockerDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
// Get the current status so that we can log any debug messages only if the
|
||||
// state changes
|
||||
_, currentlyEnabled := node.Attributes[dockerDriverAttr]
|
||||
|
||||
// Initialize docker API clients
|
||||
client, _, err := d.dockerClients()
|
||||
if err != nil {
|
||||
delete(node.Attributes, dockerDriverAttr)
|
||||
if currentlyEnabled {
|
||||
d.logger.Printf("[INFO] driver.docker: failed to initialize client: %s", err)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
privileged := d.config.ReadBoolDefault(dockerPrivilegedConfigOption, false)
|
||||
if privileged {
|
||||
node.Attributes[dockerPrivilegedConfigOption] = "1"
|
||||
}
|
||||
|
||||
// This is the first operation taken on the client so we'll try to
|
||||
// establish a connection to the Docker daemon. If this fails it means
|
||||
// Docker isn't available so we'll simply disable the docker driver.
|
||||
env, err := client.Version()
|
||||
if err != nil {
|
||||
if currentlyEnabled {
|
||||
d.logger.Printf("[DEBUG] driver.docker: could not connect to docker daemon at %s: %s", client.Endpoint(), err)
|
||||
}
|
||||
delete(node.Attributes, dockerDriverAttr)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
node.Attributes[dockerDriverAttr] = "1"
|
||||
node.Attributes["driver.docker.version"] = env.Get("Version")
|
||||
|
||||
// Advertise if this node supports Docker volumes
|
||||
if d.config.ReadBoolDefault(dockerVolumesConfigOption, dockerVolumesConfigDefault) {
|
||||
node.Attributes["driver."+dockerVolumesConfigOption] = "1"
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (d *DockerDriver) containerBinds(driverConfig *DockerDriverConfig, taskDir *allocdir.TaskDir,
|
||||
task *structs.Task) ([]string, error) {
|
||||
|
||||
|
||||
@@ -29,6 +29,10 @@ const (
|
||||
// features.
|
||||
type ExecDriver struct {
|
||||
DriverContext
|
||||
|
||||
// A tri-state boolean to know if the fingerprinting has happened and
|
||||
// whether it has been successful
|
||||
fingerprintSuccess *bool
|
||||
}
|
||||
|
||||
type ExecDriverConfig struct {
|
||||
|
||||
@@ -4,9 +4,11 @@ package driver
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/nomad/client/config"
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
)
|
||||
|
||||
func (d *ExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
d.fingerprintSuccess = helper.BoolToPtr(false)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -2,33 +2,33 @@ package driver
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/nomad/client/config"
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func (d *ExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
// Get the current status so that we can log any debug messages only if the
|
||||
// state changes
|
||||
_, currentlyEnabled := node.Attributes[execDriverAttr]
|
||||
|
||||
// Only enable if cgroups are available and we are root
|
||||
if _, ok := node.Attributes["unique.cgroup.mountpoint"]; !ok {
|
||||
if currentlyEnabled {
|
||||
if !cgroupsMounted(node) {
|
||||
if d.fingerprintSuccess == nil || *d.fingerprintSuccess {
|
||||
d.logger.Printf("[DEBUG] driver.exec: cgroups unavailable, disabling")
|
||||
}
|
||||
d.fingerprintSuccess = helper.BoolToPtr(false)
|
||||
delete(node.Attributes, execDriverAttr)
|
||||
return false, nil
|
||||
} else if unix.Geteuid() != 0 {
|
||||
if currentlyEnabled {
|
||||
if d.fingerprintSuccess == nil || *d.fingerprintSuccess {
|
||||
d.logger.Printf("[DEBUG] driver.exec: must run as root user, disabling")
|
||||
}
|
||||
delete(node.Attributes, execDriverAttr)
|
||||
d.fingerprintSuccess = helper.BoolToPtr(false)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if !currentlyEnabled {
|
||||
if d.fingerprintSuccess == nil || *d.fingerprintSuccess {
|
||||
d.logger.Printf("[DEBUG] driver.exec: exec driver is enabled")
|
||||
}
|
||||
node.Attributes[execDriverAttr] = "1"
|
||||
d.fingerprintSuccess = helper.BoolToPtr(true)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
dstructs "github.com/hashicorp/nomad/client/driver/structs"
|
||||
"github.com/hashicorp/nomad/client/fingerprint"
|
||||
cstructs "github.com/hashicorp/nomad/client/structs"
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
"github.com/hashicorp/nomad/helper/fields"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
)
|
||||
@@ -38,6 +39,10 @@ const (
|
||||
type JavaDriver struct {
|
||||
DriverContext
|
||||
fingerprint.StaticFingerprinter
|
||||
|
||||
// A tri-state boolean to know if the fingerprinting has happened and
|
||||
// whether it has been successful
|
||||
fingerprintSuccess *bool
|
||||
}
|
||||
|
||||
type JavaDriverConfig struct {
|
||||
@@ -105,16 +110,13 @@ func (d *JavaDriver) Abilities() DriverAbilities {
|
||||
}
|
||||
|
||||
func (d *JavaDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
// Get the current status so that we can log any debug messages only if the
|
||||
// state changes
|
||||
_, currentlyEnabled := node.Attributes[javaDriverAttr]
|
||||
|
||||
// Only enable if we are root and cgroups are mounted when running on linux systems.
|
||||
if runtime.GOOS == "linux" && (syscall.Geteuid() != 0 || !d.cgroupsMounted(node)) {
|
||||
if currentlyEnabled {
|
||||
if runtime.GOOS == "linux" && (syscall.Geteuid() != 0 || !cgroupsMounted(node)) {
|
||||
if d.fingerprintSuccess == nil || *d.fingerprintSuccess {
|
||||
d.logger.Printf("[DEBUG] driver.java: root priviledges and mounted cgroups required on linux, disabling")
|
||||
}
|
||||
delete(node.Attributes, "driver.java")
|
||||
d.fingerprintSuccess = helper.BoolToPtr(false)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -128,6 +130,7 @@ func (d *JavaDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool,
|
||||
if err != nil {
|
||||
// assume Java wasn't found
|
||||
delete(node.Attributes, javaDriverAttr)
|
||||
d.fingerprintSuccess = helper.BoolToPtr(false)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -143,10 +146,11 @@ func (d *JavaDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool,
|
||||
}
|
||||
|
||||
if infoString == "" {
|
||||
if currentlyEnabled {
|
||||
if d.fingerprintSuccess == nil || *d.fingerprintSuccess {
|
||||
d.logger.Println("[WARN] driver.java: error parsing Java version information, aborting")
|
||||
}
|
||||
delete(node.Attributes, javaDriverAttr)
|
||||
d.fingerprintSuccess = helper.BoolToPtr(false)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -163,6 +167,7 @@ func (d *JavaDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool,
|
||||
node.Attributes["driver.java.version"] = versionString
|
||||
node.Attributes["driver.java.runtime"] = info[1]
|
||||
node.Attributes["driver.java.vm"] = info[2]
|
||||
d.fingerprintSuccess = helper.BoolToPtr(true)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
@@ -295,13 +300,6 @@ func (d *JavaDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle,
|
||||
|
||||
func (d *JavaDriver) Cleanup(*ExecContext, *CreatedResources) error { return nil }
|
||||
|
||||
// cgroupsMounted returns true if the cgroups are mounted on a system otherwise
|
||||
// returns false
|
||||
func (d *JavaDriver) cgroupsMounted(node *structs.Node) bool {
|
||||
_, ok := node.Attributes["unique.cgroup.mountpoint"]
|
||||
return ok
|
||||
}
|
||||
|
||||
type javaId struct {
|
||||
Version string
|
||||
KillTimeout time.Duration
|
||||
|
||||
@@ -105,10 +105,6 @@ func (d *QemuDriver) FSIsolation() cstructs.FSIsolation {
|
||||
}
|
||||
|
||||
func (d *QemuDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
// Get the current status so that we can log any debug messages only if the
|
||||
// state changes
|
||||
_, currentlyEnabled := node.Attributes[qemuDriverAttr]
|
||||
|
||||
bin := "qemu-system-x86_64"
|
||||
if runtime.GOOS == "windows" {
|
||||
// On windows, the "qemu-system-x86_64" command does not respond to the
|
||||
@@ -128,9 +124,6 @@ func (d *QemuDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool,
|
||||
return false, fmt.Errorf("Unable to parse Qemu version string: %#v", matches)
|
||||
}
|
||||
|
||||
if !currentlyEnabled {
|
||||
d.logger.Printf("[DEBUG] driver.qemu: enabling driver")
|
||||
}
|
||||
node.Attributes[qemuDriverAttr] = "1"
|
||||
node.Attributes["driver.qemu.version"] = matches[1]
|
||||
return true, nil
|
||||
|
||||
@@ -87,17 +87,11 @@ func (d *RawExecDriver) FSIsolation() cstructs.FSIsolation {
|
||||
}
|
||||
|
||||
func (d *RawExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
// Get the current status so that we can log any debug messages only if the
|
||||
// state changes
|
||||
_, currentlyEnabled := node.Attributes[rawExecDriverAttr]
|
||||
|
||||
// Check that the user has explicitly enabled this executor.
|
||||
enabled := cfg.ReadBoolDefault(rawExecConfigOption, false)
|
||||
|
||||
if enabled || cfg.DevMode {
|
||||
if currentlyEnabled {
|
||||
d.logger.Printf("[WARN] driver.raw_exec: raw exec is enabled. Only enable if needed")
|
||||
}
|
||||
d.logger.Printf("[WARN] driver.raw_exec: raw exec is enabled. Only enable if needed")
|
||||
node.Attributes[rawExecDriverAttr] = "1"
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/hashicorp/nomad/client/driver/executor"
|
||||
dstructs "github.com/hashicorp/nomad/client/driver/structs"
|
||||
cstructs "github.com/hashicorp/nomad/client/structs"
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
"github.com/hashicorp/nomad/helper/fields"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
@@ -57,6 +58,10 @@ const (
|
||||
// planned in the future
|
||||
type RktDriver struct {
|
||||
DriverContext
|
||||
|
||||
// A tri-state boolean to know if the fingerprinting has happened and
|
||||
// whether it has been successful
|
||||
fingerprintSuccess *bool
|
||||
}
|
||||
|
||||
type RktDriverConfig struct {
|
||||
@@ -157,22 +162,20 @@ func (d *RktDriver) Abilities() DriverAbilities {
|
||||
}
|
||||
|
||||
func (d *RktDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
|
||||
// Get the current status so that we can log any debug messages only if the
|
||||
// state changes
|
||||
_, currentlyEnabled := node.Attributes[rktDriverAttr]
|
||||
|
||||
// Only enable if we are root when running on non-windows systems.
|
||||
if runtime.GOOS != "windows" && syscall.Geteuid() != 0 {
|
||||
if currentlyEnabled {
|
||||
if d.fingerprintSuccess == nil || *d.fingerprintSuccess {
|
||||
d.logger.Printf("[DEBUG] driver.rkt: must run as root user, disabling")
|
||||
}
|
||||
delete(node.Attributes, rktDriverAttr)
|
||||
d.fingerprintSuccess = helper.BoolToPtr(false)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
outBytes, err := exec.Command(rktCmd, "version").Output()
|
||||
if err != nil {
|
||||
delete(node.Attributes, rktDriverAttr)
|
||||
d.fingerprintSuccess = helper.BoolToPtr(false)
|
||||
return false, nil
|
||||
}
|
||||
out := strings.TrimSpace(string(outBytes))
|
||||
@@ -181,6 +184,7 @@ func (d *RktDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, e
|
||||
appcMatches := reAppcVersion.FindStringSubmatch(out)
|
||||
if len(rktMatches) != 2 || len(appcMatches) != 2 {
|
||||
delete(node.Attributes, rktDriverAttr)
|
||||
d.fingerprintSuccess = helper.BoolToPtr(false)
|
||||
return false, fmt.Errorf("Unable to parse Rkt version string: %#v", rktMatches)
|
||||
}
|
||||
|
||||
@@ -200,6 +204,7 @@ func (d *RktDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, e
|
||||
if d.config.ReadBoolDefault(rktVolumesConfigOption, rktVolumesConfigDefault) {
|
||||
node.Attributes["driver."+rktVolumesConfigOption] = "1"
|
||||
}
|
||||
d.fingerprintSuccess = helper.BoolToPtr(true)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,13 @@ import (
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
)
|
||||
|
||||
// cgroupsMounted returns true if the cgroups are mounted on a system otherwise
|
||||
// returns false
|
||||
func cgroupsMounted(node *structs.Node) bool {
|
||||
_, ok := node.Attributes["unique.cgroup.mountpoint"]
|
||||
return ok
|
||||
}
|
||||
|
||||
// createExecutor launches an executor plugin and returns an instance of the
|
||||
// Executor interface
|
||||
func createExecutor(w io.Writer, clientConfig *config.Config,
|
||||
|
||||
Reference in New Issue
Block a user