mirror of
				https://github.com/NVIDIA/nvidia-container-toolkit
				synced 2025-06-26 18:18:24 +00:00 
			
		
		
		
	Add --watch option to create-dev-char-symlinks
This change adds a --watch option to the create-dev-char-symlinks hook. This installs an fsnotify watcher that creates symlinks for ADDED device nodes under /dev/char. Signed-off-by: Evan Lezar <elezar@nvidia.com>
This commit is contained in:
		
							parent
							
								
									be0e4667a5
								
							
						
					
					
						commit
						f9330a4c2c
					
				| @ -19,8 +19,12 @@ package devchar | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/signal" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"github.com/fsnotify/fsnotify" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/urfave/cli/v2" | ||||
| ) | ||||
| @ -37,6 +41,7 @@ type config struct { | ||||
| 	devCharPath string | ||||
| 	driverRoot  string | ||||
| 	dryRun      bool | ||||
| 	watch       bool | ||||
| } | ||||
| 
 | ||||
| // NewCommand constructs a hook sub-command with the specified logger
 | ||||
| @ -75,6 +80,13 @@ func (m command) build() *cli.Command { | ||||
| 			Destination: &cfg.driverRoot, | ||||
| 			EnvVars:     []string{"DRIVER_ROOT"}, | ||||
| 		}, | ||||
| 		&cli.BoolFlag{ | ||||
| 			Name:        "watch", | ||||
| 			Usage:       "If set, the command will watch for changes to the driver root and recreate the symlinks when changes are detected.", | ||||
| 			Value:       false, | ||||
| 			Destination: &cfg.watch, | ||||
| 			EnvVars:     []string{"WATCH"}, | ||||
| 		}, | ||||
| 		&cli.BoolFlag{ | ||||
| 			Name:        "dry-run", | ||||
| 			Usage:       "If set, the command will not create any symlinks.", | ||||
| @ -88,17 +100,67 @@ func (m command) build() *cli.Command { | ||||
| } | ||||
| 
 | ||||
| func (m command) run(c *cli.Context, cfg *config) error { | ||||
| 
 | ||||
| 	var watcher *fsnotify.Watcher | ||||
| 	var sigs chan os.Signal | ||||
| 
 | ||||
| 	if cfg.watch { | ||||
| 		watcher, err := newFSWatcher(filepath.Join(cfg.driverRoot, "dev")) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("failed to create FS watcher: %v", err) | ||||
| 		} | ||||
| 		defer watcher.Close() | ||||
| 
 | ||||
| 		sigs = newOSWatcher(syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) | ||||
| 	} | ||||
| 
 | ||||
| 	l := NewSymlinkCreator( | ||||
| 		WithLogger(m.logger), | ||||
| 		WithDevCharPath(cfg.devCharPath), | ||||
| 		WithDriverRoot(cfg.driverRoot), | ||||
| 		WithDryRun(cfg.dryRun), | ||||
| 	) | ||||
| create: | ||||
| 	err := l.CreateLinks() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to create links: %v", err) | ||||
| 	} | ||||
| 	return nil | ||||
| 	if !cfg.watch { | ||||
| 		return nil | ||||
| 	} | ||||
| 	for { | ||||
| 		select { | ||||
| 
 | ||||
| 		case event := <-watcher.Events: | ||||
| 			deviceNode := filepath.Base(event.Name) | ||||
| 			if !strings.HasPrefix(deviceNode, "nvidia") { | ||||
| 				continue | ||||
| 			} | ||||
| 			if event.Op&fsnotify.Create == fsnotify.Create { | ||||
| 				m.logger.Infof("%s created, restarting.", event.Name) | ||||
| 				goto create | ||||
| 			} | ||||
| 			if event.Op&fsnotify.Create == fsnotify.Remove { | ||||
| 				m.logger.Infof("%s removed. Ignoring", event.Name) | ||||
| 
 | ||||
| 			} | ||||
| 
 | ||||
| 		// Watch for any other fs errors and log them.
 | ||||
| 		case err := <-watcher.Errors: | ||||
| 			m.logger.Errorf("inotify: %s", err) | ||||
| 
 | ||||
| 		// React to signals
 | ||||
| 		case s := <-sigs: | ||||
| 			switch s { | ||||
| 			case syscall.SIGHUP: | ||||
| 				m.logger.Infof("Received SIGHUP, recreating symlinks.") | ||||
| 				goto create | ||||
| 			default: | ||||
| 				m.logger.Infof("Received signal %q, shutting down.", s) | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type linkCreator struct { | ||||
| @ -207,3 +269,27 @@ type deviceNode struct { | ||||
| func (d deviceNode) devCharName() string { | ||||
| 	return fmt.Sprintf("%d:%d", d.major, d.minor) | ||||
| } | ||||
| 
 | ||||
| func newFSWatcher(files ...string) (*fsnotify.Watcher, error) { | ||||
| 	watcher, err := fsnotify.NewWatcher() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	for _, f := range files { | ||||
| 		err = watcher.Add(f) | ||||
| 		if err != nil { | ||||
| 			watcher.Close() | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return watcher, nil | ||||
| } | ||||
| 
 | ||||
| func newOSWatcher(sigs ...os.Signal) chan os.Signal { | ||||
| 	sigChan := make(chan os.Signal, 1) | ||||
| 	signal.Notify(sigChan, sigs...) | ||||
| 
 | ||||
| 	return sigChan | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user