github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/plugin/manager_linux.go (about)

     1  // +build linux
     2  
     3  package plugin
     4  
     5  import (
     6  	"fmt"
     7  	"path/filepath"
     8  	"syscall"
     9  	"time"
    10  
    11  	"github.com/Sirupsen/logrus"
    12  	"github.com/docker/docker/libcontainerd"
    13  	"github.com/docker/docker/oci"
    14  	"github.com/docker/docker/pkg/plugins"
    15  	"github.com/docker/docker/plugin/v2"
    16  	specs "github.com/opencontainers/runtime-spec/specs-go"
    17  )
    18  
    19  func (pm *Manager) enable(p *v2.Plugin, force bool) error {
    20  	if p.IsEnabled() && !force {
    21  		return fmt.Errorf("plugin %s is already enabled", p.Name())
    22  	}
    23  	spec, err := p.InitSpec(oci.DefaultSpec(), pm.libRoot)
    24  	if err != nil {
    25  		return err
    26  	}
    27  	p.Lock()
    28  	p.Restart = true
    29  	p.ExitChan = make(chan bool)
    30  	p.Unlock()
    31  	if err := pm.containerdClient.Create(p.GetID(), "", "", specs.Spec(*spec), attachToLog(p.GetID())); err != nil {
    32  		return err
    33  	}
    34  
    35  	p.PClient, err = plugins.NewClientWithTimeout("unix://"+filepath.Join(p.RuntimeSourcePath, p.GetSocket()), nil, p.TimeoutInSecs)
    36  	if err != nil {
    37  		p.Lock()
    38  		p.Restart = false
    39  		p.Unlock()
    40  		shutdownPlugin(p, pm.containerdClient)
    41  		return err
    42  	}
    43  
    44  	pm.pluginStore.SetState(p, true)
    45  	pm.pluginStore.CallHandler(p)
    46  
    47  	return nil
    48  }
    49  
    50  func (pm *Manager) restore(p *v2.Plugin) error {
    51  	return pm.containerdClient.Restore(p.GetID(), attachToLog(p.GetID()))
    52  }
    53  
    54  func shutdownPlugin(p *v2.Plugin, containerdClient libcontainerd.Client) {
    55  	pluginID := p.GetID()
    56  
    57  	err := containerdClient.Signal(pluginID, int(syscall.SIGTERM))
    58  	if err != nil {
    59  		logrus.Errorf("Sending SIGTERM to plugin failed with error: %v", err)
    60  	} else {
    61  		select {
    62  		case <-p.ExitChan:
    63  			logrus.Debug("Clean shutdown of plugin")
    64  		case <-time.After(time.Second * 10):
    65  			logrus.Debug("Force shutdown plugin")
    66  			if err := containerdClient.Signal(pluginID, int(syscall.SIGKILL)); err != nil {
    67  				logrus.Errorf("Sending SIGKILL to plugin failed with error: %v", err)
    68  			}
    69  		}
    70  	}
    71  }
    72  
    73  func (pm *Manager) disable(p *v2.Plugin) error {
    74  	if !p.IsEnabled() {
    75  		return fmt.Errorf("plugin %s is already disabled", p.Name())
    76  	}
    77  	p.Lock()
    78  	p.Restart = false
    79  	p.Unlock()
    80  
    81  	shutdownPlugin(p, pm.containerdClient)
    82  	pm.pluginStore.SetState(p, false)
    83  	return nil
    84  }
    85  
    86  // Shutdown stops all plugins and called during daemon shutdown.
    87  func (pm *Manager) Shutdown() {
    88  	plugins := pm.pluginStore.GetAll()
    89  	for _, p := range plugins {
    90  		if pm.liveRestore && p.IsEnabled() {
    91  			logrus.Debug("Plugin active when liveRestore is set, skipping shutdown")
    92  			continue
    93  		}
    94  		if pm.containerdClient != nil && p.IsEnabled() {
    95  			p.Lock()
    96  			p.Restart = false
    97  			p.Unlock()
    98  			shutdownPlugin(p, pm.containerdClient)
    99  		}
   100  	}
   101  }