drivermanager: attempt to reattach and shutdown driver plugin if blocked by allow/block lists

This commit is contained in:
Nick Ethier 2018-12-17 22:54:25 -05:00
parent ce1a5cba0e
commit a02308ee6a
No known key found for this signature in database
GPG Key ID: 07C1A3ECED90D24A
5 changed files with 52 additions and 17 deletions

View File

@ -911,7 +911,7 @@ func (c *Client) restoreState() error {
arConf := &allocrunner.Config{ arConf := &allocrunner.Config{
Alloc: alloc, Alloc: alloc,
Logger: c.logger, Logger: c.logger,
ClientConfig: c.config, ClientConfig: c.configCopy,
StateDB: c.stateDB, StateDB: c.stateDB,
StateUpdater: c, StateUpdater: c,
DeviceStatsReporter: c, DeviceStatsReporter: c,
@ -2009,7 +2009,7 @@ func (c *Client) addAlloc(alloc *structs.Allocation, migrateToken string) error
arConf := &allocrunner.Config{ arConf := &allocrunner.Config{
Alloc: alloc, Alloc: alloc,
Logger: c.logger, Logger: c.logger,
ClientConfig: c.config, ClientConfig: c.configCopy,
StateDB: c.stateDB, StateDB: c.stateDB,
Consul: c.consulService, Consul: c.consulService,
Vault: c.vaultClient, Vault: c.vaultClient,

View File

@ -1199,7 +1199,8 @@ func TestClient_updateNodeFromDriverUpdatesAll(t *testing.T) {
"node.mock.testattr1": "val1", "node.mock.testattr1": "val1",
}, },
} }
n := client.updateNodeFromDriver("mock", info) client.updateNodeFromDriver("mock", info)
n := client.config.Node
updatedInfo := *n.Drivers["mock"] updatedInfo := *n.Drivers["mock"]
// compare without update time // compare without update time
@ -1220,7 +1221,8 @@ func TestClient_updateNodeFromDriverUpdatesAll(t *testing.T) {
"node.mock.testattr1": "val2", "node.mock.testattr1": "val2",
}, },
} }
n := client.updateNodeFromDriver("mock", info) client.updateNodeFromDriver("mock", info)
n := client.Node()
updatedInfo := *n.Drivers["mock"] updatedInfo := *n.Drivers["mock"]
// compare without update time // compare without update time
@ -1231,7 +1233,8 @@ func TestClient_updateNodeFromDriverUpdatesAll(t *testing.T) {
assert.Equal(t, "val2", n.Attributes["node.mock.testattr1"]) assert.Equal(t, "val2", n.Attributes["node.mock.testattr1"])
// update once more with the same info, updateTime shouldn't change // update once more with the same info, updateTime shouldn't change
un := client.updateNodeFromDriver("mock", info) client.updateNodeFromDriver("mock", info)
un := client.Node()
assert.EqualValues(t, n, un) assert.EqualValues(t, n, un)
} }
@ -1245,7 +1248,8 @@ func TestClient_updateNodeFromDriverUpdatesAll(t *testing.T) {
"node.mock.testattr1": "", "node.mock.testattr1": "",
}, },
} }
n := client.updateNodeFromDriver("mock", info) client.updateNodeFromDriver("mock", info)
n := client.Node()
updatedInfo := *n.Drivers["mock"] updatedInfo := *n.Drivers["mock"]
// compare without update time // compare without update time
@ -1256,7 +1260,8 @@ func TestClient_updateNodeFromDriverUpdatesAll(t *testing.T) {
assert.Equal(t, "", n.Attributes["node.mock.testattr1"]) assert.Equal(t, "", n.Attributes["node.mock.testattr1"])
// update once more with the same info, updateTime shouldn't change // update once more with the same info, updateTime shouldn't change
un := client.updateNodeFromDriver("mock", info) client.updateNodeFromDriver("mock", info)
un := client.Node()
assert.EqualValues(t, n, un) assert.EqualValues(t, n, un)
} }
} }

View File

@ -13,7 +13,7 @@ import (
var ( var (
// batchFirstFingerprintsTimeout is the maximum amount of time to wait for // batchFirstFingerprintsTimeout is the maximum amount of time to wait for
// intial fingerprinting to complete before sending a batched Node update // initial fingerprinting to complete before sending a batched Node update
batchFirstFingerprintsTimeout = 5 * time.Second batchFirstFingerprintsTimeout = 5 * time.Second
) )
@ -43,7 +43,10 @@ SEND_BATCH:
var driverChanged bool var driverChanged bool
c.batchNodeUpdates.batchDriverUpdates(func(driver string, info *structs.DriverInfo) { c.batchNodeUpdates.batchDriverUpdates(func(driver string, info *structs.DriverInfo) {
if c.updateNodeFromDriverLocked(driver, info) { if c.updateNodeFromDriverLocked(driver, info) {
c.config.Node.Drivers[driver].UpdateTime = time.Now() c.config.Node.Drivers[driver] = info
if c.config.Node.Drivers[driver].UpdateTime.IsZero() {
c.config.Node.Drivers[driver].UpdateTime = time.Now()
}
driverChanged = true driverChanged = true
} }
}) })
@ -56,7 +59,7 @@ SEND_BATCH:
} }
}) })
// only update the node if changes occured // only update the node if changes occurred
if driverChanged || devicesChanged { if driverChanged || devicesChanged {
c.updateNodeLocked() c.updateNodeLocked()
} }
@ -69,7 +72,10 @@ func (c *Client) updateNodeFromDriver(name string, info *structs.DriverInfo) {
defer c.configLock.Unlock() defer c.configLock.Unlock()
if c.updateNodeFromDriverLocked(name, info) { if c.updateNodeFromDriverLocked(name, info) {
c.config.Node.Drivers[name].UpdateTime = time.Now() c.config.Node.Drivers[name] = info
if c.config.Node.Drivers[name].UpdateTime.IsZero() {
c.config.Node.Drivers[name].UpdateTime = time.Now()
}
c.updateNodeLocked() c.updateNodeLocked()
} }
} }
@ -84,7 +90,6 @@ func (c *Client) updateNodeFromDriverLocked(name string, info *structs.DriverInf
if !hadDriver { if !hadDriver {
// If the driver info has not yet been set, do that here // If the driver info has not yet been set, do that here
hasChanged = true hasChanged = true
c.config.Node.Drivers[name] = info
for attrName, newVal := range info.Attributes { for attrName, newVal := range info.Attributes {
c.config.Node.Attributes[attrName] = newVal c.config.Node.Attributes[attrName] = newVal
} }
@ -93,9 +98,9 @@ func (c *Client) updateNodeFromDriverLocked(name string, info *structs.DriverInf
// The driver info has already been set, fix it up // The driver info has already been set, fix it up
if oldVal.Detected != info.Detected { if oldVal.Detected != info.Detected {
hasChanged = true hasChanged = true
c.config.Node.Drivers[name].Detected = info.Detected
} }
// If health state has change, trigger node event
if oldVal.Healthy != info.Healthy || oldVal.HealthDescription != info.HealthDescription { if oldVal.Healthy != info.Healthy || oldVal.HealthDescription != info.HealthDescription {
hasChanged = true hasChanged = true
if info.HealthDescription != "" { if info.HealthDescription != "" {
@ -107,8 +112,6 @@ func (c *Client) updateNodeFromDriverLocked(name string, info *structs.DriverInf
} }
c.triggerNodeEvent(event) c.triggerNodeEvent(event)
} }
// Update the node with the latest information
c.config.Node.Drivers[name].MergeHealthCheck(info)
} }
for attrName, newVal := range info.Attributes { for attrName, newVal := range info.Attributes {
@ -225,7 +228,7 @@ func (b *batchNodeUpdates) batchDriverUpdates(f drivermanager.UpdateNodeDriverIn
} }
// updateNodeFromDevices implements devicemanager.UpdateNodeDevicesFn and is // updateNodeFromDevices implements devicemanager.UpdateNodeDevicesFn and is
// used in teh device manager to send device fingerprints to // used in the device manager to send device fingerprints to
func (b *batchNodeUpdates) updateNodeFromDevices(devices []*structs.NodeDeviceResource) { func (b *batchNodeUpdates) updateNodeFromDevices(devices []*structs.NodeDeviceResource) {
b.devicesMu.Lock() b.devicesMu.Lock()
defer b.devicesMu.Unlock() defer b.devicesMu.Unlock()

View File

@ -274,6 +274,9 @@ func (m *manager) loadReattachConfigs() error {
if s != nil { if s != nil {
for name, c := range s.ReattachConfigs { for name, c := range s.ReattachConfigs {
if m.isDriverBlocked(name) { if m.isDriverBlocked(name) {
m.logger.Warn("reattach config for driver plugin found but driver is blocked due to allow/block list, killing plugin",
"driver", name)
m.shutdownBlockedDriver(name, c)
continue continue
} }
@ -288,6 +291,28 @@ func (m *manager) loadReattachConfigs() error {
return nil return nil
} }
// shutdownBlockedDriver is used to forcefully shutdown a running driver plugin
// when it has been blocked due to allow/block lists
func (m *manager) shutdownBlockedDriver(name string, reattach *shared.ReattachConfig) {
c, err := shared.ReattachConfigToGoPlugin(reattach)
if err != nil {
m.logger.Warn("failed to reattach and kill blocked driver plugin",
"driver", name, "error", err)
return
}
pluginInstance, err := m.loader.Reattach(name, base.PluginTypeDriver, c)
if err != nil {
m.logger.Warn("failed to reattach and kill blocked driver plugin",
"driver", name, "error", err)
return
}
if !pluginInstance.Exited() {
pluginInstance.Kill()
}
}
// storePluginReattachConfig is used as a callback to the instance managers and // storePluginReattachConfig is used as a callback to the instance managers and
// persists thhe plugin reattach configurations. // persists thhe plugin reattach configurations.
func (m *manager) storePluginReattachConfig(id loader.PluginID, c *plugin.ReattachConfig) error { func (m *manager) storePluginReattachConfig(id loader.PluginID, c *plugin.ReattachConfig) error {

View File

@ -185,12 +185,14 @@ func TestMananger_TaskEvents(t *testing.T) {
event1 := mockTaskEvent("abc1") event1 := mockTaskEvent("abc1")
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(1) wg.Add(1)
mgr.eventHandlerFactory = func(string, string) EventHandler { mgr.instancesMu.Lock()
mgr.instances["mock"].eventHandlerFactory = func(string, string) EventHandler {
return func(ev *drivers.TaskEvent) { return func(ev *drivers.TaskEvent) {
defer wg.Done() defer wg.Done()
assert.Exactly(t, event1, ev) assert.Exactly(t, event1, ev)
} }
} }
mgr.instancesMu.Unlock()
evChan <- event1 evChan <- event1
wg.Wait() wg.Wait()