136 lines
3.4 KiB
Go
136 lines
3.4 KiB
Go
// Copyright 2018 Intel Corporation. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package deviceplugin
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"reflect"
|
|
|
|
pluginapi "isolcpu_plugin/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1"
|
|
|
|
"isolcpu_plugin/intel/intel-device-plugins-for-kubernetes/pkg/debug"
|
|
)
|
|
|
|
// updateInfo contains info for added, updated and deleted devices.
|
|
type updateInfo struct {
|
|
Added DeviceTree
|
|
Updated DeviceTree
|
|
Removed DeviceTree
|
|
}
|
|
|
|
// notifier implements Notifier interface.
|
|
type notifier struct {
|
|
deviceTree DeviceTree
|
|
updatesCh chan<- updateInfo
|
|
}
|
|
|
|
func newNotifier(updatesCh chan<- updateInfo) *notifier {
|
|
return ¬ifier{
|
|
updatesCh: updatesCh,
|
|
}
|
|
}
|
|
|
|
func (n *notifier) Notify(newDeviceTree DeviceTree) {
|
|
added := NewDeviceTree()
|
|
updated := NewDeviceTree()
|
|
|
|
for devType, new := range newDeviceTree {
|
|
if old, ok := n.deviceTree[devType]; ok {
|
|
if !reflect.DeepEqual(old, new) {
|
|
updated[devType] = new
|
|
}
|
|
delete(n.deviceTree, devType)
|
|
} else {
|
|
added[devType] = new
|
|
}
|
|
}
|
|
|
|
if len(added) > 0 || len(updated) > 0 || len(n.deviceTree) > 0 {
|
|
n.updatesCh <- updateInfo{
|
|
Added: added,
|
|
Updated: updated,
|
|
Removed: n.deviceTree,
|
|
}
|
|
}
|
|
|
|
n.deviceTree = newDeviceTree
|
|
}
|
|
|
|
// Manager manages life cycle of device plugins and handles the scan results
|
|
// received from them.
|
|
type Manager struct {
|
|
devicePlugin Scanner
|
|
namespace string
|
|
servers map[string]devicePluginServer
|
|
createServer func(string, func(*pluginapi.AllocateResponse) error) devicePluginServer
|
|
}
|
|
|
|
// NewManager creates a new instance of Manager
|
|
func NewManager(namespace string, devicePlugin Scanner) *Manager {
|
|
return &Manager{
|
|
devicePlugin: devicePlugin,
|
|
namespace: namespace,
|
|
servers: make(map[string]devicePluginServer),
|
|
createServer: newServer,
|
|
}
|
|
}
|
|
|
|
// Run prepares and launches event loop for updates from Scanner
|
|
func (m *Manager) Run() {
|
|
updatesCh := make(chan updateInfo)
|
|
|
|
go func() {
|
|
err := m.devicePlugin.Scan(newNotifier(updatesCh))
|
|
if err != nil {
|
|
fmt.Printf("Device scan failed: %+v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
close(updatesCh)
|
|
}()
|
|
|
|
for update := range updatesCh {
|
|
m.handleUpdate(update)
|
|
}
|
|
}
|
|
|
|
func (m *Manager) handleUpdate(update updateInfo) {
|
|
debug.Print("Received dev updates:", update)
|
|
for devType, devices := range update.Added {
|
|
var postAllocate func(*pluginapi.AllocateResponse) error
|
|
|
|
if postAllocator, ok := m.devicePlugin.(PostAllocator); ok {
|
|
postAllocate = postAllocator.PostAllocate
|
|
}
|
|
|
|
m.servers[devType] = m.createServer(devType, postAllocate)
|
|
go func(dt string) {
|
|
err := m.servers[dt].Serve(m.namespace)
|
|
if err != nil {
|
|
fmt.Printf("Failed to serve %s/%s: %+v\n", m.namespace, dt, err)
|
|
os.Exit(1)
|
|
}
|
|
}(devType)
|
|
m.servers[devType].Update(devices)
|
|
}
|
|
for devType, devices := range update.Updated {
|
|
m.servers[devType].Update(devices)
|
|
}
|
|
for devType := range update.Removed {
|
|
m.servers[devType].Stop()
|
|
delete(m.servers, devType)
|
|
}
|
|
}
|