volcano.sh/volcano@v1.9.0/pkg/scheduler/framework/plugins.go (about)

     1  /*
     2  Copyright 2018 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package framework
    18  
    19  import (
    20  	"fmt"
    21  	"path/filepath"
    22  	"plugin"
    23  	"strings"
    24  	"sync"
    25  
    26  	"k8s.io/klog/v2"
    27  )
    28  
    29  var pluginMutex sync.RWMutex
    30  
    31  // PluginBuilder plugin management
    32  type PluginBuilder = func(Arguments) Plugin
    33  
    34  // Plugin management
    35  var pluginBuilders = map[string]PluginBuilder{}
    36  
    37  // RegisterPluginBuilder register the plugin
    38  func RegisterPluginBuilder(name string, pc PluginBuilder) {
    39  	pluginMutex.Lock()
    40  	defer pluginMutex.Unlock()
    41  
    42  	pluginBuilders[name] = pc
    43  }
    44  
    45  // CleanupPluginBuilders cleans up all the plugin
    46  func CleanupPluginBuilders() {
    47  	pluginMutex.Lock()
    48  	defer pluginMutex.Unlock()
    49  
    50  	pluginBuilders = map[string]PluginBuilder{}
    51  }
    52  
    53  // GetPluginBuilder get the pluginbuilder by name
    54  func GetPluginBuilder(name string) (PluginBuilder, bool) {
    55  	pluginMutex.RLock()
    56  	defer pluginMutex.RUnlock()
    57  
    58  	pb, found := pluginBuilders[name]
    59  	return pb, found
    60  }
    61  
    62  // LoadCustomPlugins loads custom implement plugins
    63  func LoadCustomPlugins(pluginsDir string) error {
    64  	pluginPaths, _ := filepath.Glob(fmt.Sprintf("%s/*.so", pluginsDir))
    65  	for _, pluginPath := range pluginPaths {
    66  		pluginBuilder, err := loadPluginBuilder(pluginPath)
    67  		if err != nil {
    68  			return err
    69  		}
    70  		pluginName := getPluginName(pluginPath)
    71  		RegisterPluginBuilder(pluginName, pluginBuilder)
    72  		klog.V(4).Infof("Custom plugin %s loaded", pluginName)
    73  	}
    74  
    75  	return nil
    76  }
    77  
    78  func getPluginName(pluginPath string) string {
    79  	return strings.TrimSuffix(filepath.Base(pluginPath), filepath.Ext(pluginPath))
    80  }
    81  
    82  func loadPluginBuilder(pluginPath string) (PluginBuilder, error) {
    83  	plug, err := plugin.Open(pluginPath)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	symBuilder, err := plug.Lookup("New")
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	builder, ok := symBuilder.(PluginBuilder)
    94  	if !ok {
    95  		return nil, fmt.Errorf("unexpected plugin: %s, failed to convert PluginBuilder `New`", pluginPath)
    96  	}
    97  
    98  	return builder, nil
    99  }
   100  
   101  // Action management
   102  var actionMap = map[string]Action{}
   103  
   104  // RegisterAction register action
   105  func RegisterAction(act Action) {
   106  	pluginMutex.Lock()
   107  	defer pluginMutex.Unlock()
   108  
   109  	actionMap[act.Name()] = act
   110  }
   111  
   112  // GetAction get the action by name
   113  func GetAction(name string) (Action, bool) {
   114  	pluginMutex.RLock()
   115  	defer pluginMutex.RUnlock()
   116  
   117  	act, found := actionMap[name]
   118  	return act, found
   119  }