github.com/whamcloud/lemur@v0.0.0-20190827193804-4655df8a52af/dmplugin/plugin.go (about) 1 // Copyright (c) 2018 DDN. All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 5 package dmplugin 6 7 import ( 8 "net" 9 "path" 10 "sync" 11 "time" 12 13 "github.com/pkg/errors" 14 15 "golang.org/x/net/context" 16 17 pb "github.com/intel-hpdd/lemur/pdm" 18 "github.com/intel-hpdd/lemur/pkg/fsroot" 19 "google.golang.org/grpc" 20 ) 21 22 // Plugin manages communication between the HSM agent and the datamover 23 type Plugin struct { 24 name string 25 ctx context.Context 26 cancelContext context.CancelFunc 27 rpcConn *grpc.ClientConn 28 cli pb.DataMoverClient 29 movers []*DataMoverClient 30 fsClient fsroot.Client 31 config *pluginConfig 32 } 33 34 func unixDialer(addr string, timeout time.Duration) (net.Conn, error) { 35 return net.DialTimeout("unix", addr, timeout) 36 } 37 38 // New returns a new *Plugin, or error 39 func New(name string, initClient func(string) (fsroot.Client, error)) (*Plugin, error) { 40 config := mustInitConfig() 41 42 fsClient, err := initClient(config.ClientRoot) 43 if err != nil { 44 return nil, errors.Wrap(err, "client init failed") 45 } 46 47 ctx, cancel := context.WithCancel(context.Background()) 48 conn, err := grpc.Dial(config.AgentAddress, grpc.WithDialer(unixDialer), grpc.WithInsecure()) 49 if err != nil { 50 return nil, errors.Wrap(err, "dial gprc server failed") 51 } 52 return &Plugin{ 53 name: name, 54 rpcConn: conn, 55 ctx: ctx, 56 cancelContext: cancel, 57 cli: pb.NewDataMoverClient(conn), 58 fsClient: fsClient, 59 config: config, 60 }, nil 61 } 62 63 // FsName returns the associated Lustre filesystem name 64 func (a *Plugin) FsName() string { 65 return a.fsClient.FsName() 66 } 67 68 // Base returns the root directory for plugin. 69 func (a *Plugin) Base() string { 70 return a.fsClient.Path() 71 } 72 73 // ConfigFile returns path to the plugin config file. 74 func (a *Plugin) ConfigFile() string { 75 return path.Join(a.config.ConfigDir, a.name) 76 } 77 78 // AddMover registers a new data mover with the plugin 79 func (a *Plugin) AddMover(config *Config) { 80 dm := NewMover(a, a.cli, config) 81 a.movers = append(a.movers, dm) 82 } 83 84 // Run starts the data mover threads and blocks until they complete. 85 func (a *Plugin) Run() { 86 var wg sync.WaitGroup 87 for _, dm := range a.movers { 88 wg.Add(1) 89 go func(dm *DataMoverClient) { 90 dm.Run(a.ctx) 91 wg.Done() 92 }(dm) 93 } 94 wg.Wait() 95 } 96 97 // Stop signals to all registered data movers that they should stop processing 98 // and shut down 99 func (a *Plugin) Stop() { 100 a.cancelContext() 101 } 102 103 // Close closes the connection to the agent 104 func (a *Plugin) Close() error { 105 return errors.Wrap(a.rpcConn.Close(), "closed failed") 106 }