| package kernelmods | |
| import ( | |
| "context" | |
| "fmt" | |
| "os" | |
| "path/filepath" | |
| "cos-extensions/tools/gcs" | |
| "cos-extensions/tools/module" | |
| "github.com/golang/glog" | |
| ) | |
| var ( | |
| retrieveInstalledModules = module.RetrieveInstalledModules | |
| retrieveLocalModulesInfo = module.RetrieveLocalModulesInfo | |
| installModule = module.InstallModule | |
| ) | |
| // DownloadModules takes in a list of module file names in a gcs path and copies them to the local directory. | |
| // If recursive is set, it downloads all module files in a gcs path and its subdirectories. | |
| func DownloadModules(ctx context.Context, cfg *gcs.GCSConfig, modFiles []string, localDir string, recursive bool) ([]string, error) { | |
| var downloadedModules []string | |
| var err error | |
| if recursive { | |
| modFiles, err = cfg.ListModules(ctx, recursive) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to recursively retrieve module files: %v", err) | |
| } | |
| } | |
| for _, moduleFile := range modFiles { | |
| modLocalPath, err := cfg.DownloadKernelModule(ctx, moduleFile, localDir) | |
| if err != nil { | |
| glog.Errorf("Failed to download module (%s) [skipping]: %v", moduleFile, err) | |
| continue | |
| } | |
| downloadedModules = append(downloadedModules, modLocalPath) | |
| glog.Infof("Successfully downloaded module (%s) to file path (%s) ", moduleFile, modLocalPath) | |
| } | |
| return downloadedModules, nil | |
| } | |
| // InstallModules takes in a list of module paths in a local directory and installs them to the kernel | |
| // if they are not already installed. | |
| func InstallModules(modulePaths []string, args []string) ([]string, error) { | |
| var installedModules []string | |
| installedModuleMap, err := retrieveInstalledModules(modulePaths) | |
| if err != nil { | |
| return installedModules, fmt.Errorf("failed to retrieve installed modules: %v", err) | |
| } | |
| for _, modulePath := range modulePaths { | |
| // Skipping if module already installed | |
| if _, ok := installedModuleMap[modulePath]; ok { | |
| glog.Errorf("Failed to install module (%s) [skipping]: Module already installed.", modulePath) | |
| continue | |
| } | |
| // Skipping if failed to install | |
| err = installModule(modulePath, args) | |
| if err != nil { | |
| glog.Errorf("Failed to install module (%s) [skipping]: %v", modulePath, err) | |
| continue | |
| } | |
| installedModules = append(installedModules, modulePath) | |
| glog.Infof("Successfully installed module (%s) with args (%s) ", modulePath, args) | |
| } | |
| return installedModules, nil | |
| } | |
| // ListDownloadedModules lists all the compiled kernel module files | |
| // in a local directory. Identifies module files as files with .ko | |
| // extension. | |
| // It returns a mapping of the module file paths to their name. | |
| func ListDownloadedModules(localDir string, recursive bool) (map[string]string, error) { | |
| var modPaths []string | |
| modPaths, err := retrieveModulePaths(localDir, modPaths, recursive) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to retrieve module files from directory %s: %v", localDir, err) | |
| } | |
| modFileName := retrieveLocalModulesInfo(modPaths) | |
| return modFileName, nil | |
| } | |
| // ListInstalledModules lists all the loaded kernel modules in a local directory. | |
| // Identifies module files in the directory as files with .ko extension. | |
| // Returns a mapping of the file paths of the loaded modules in the directory to their names. | |
| func ListInstalledModules(localDir string, recursive bool) (map[string]string, error) { | |
| var modPaths []string | |
| modPaths, err := retrieveModulePaths(localDir, modPaths, recursive) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to retrieve module files from directory %s: %v", localDir, err) | |
| } | |
| installedModules, err := retrieveInstalledModules(modPaths) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to validate installation of module files %s: %v", modPaths, err) | |
| } | |
| return installedModules, nil | |
| } | |
| // retrieveModulePaths takes in a local directory and returns the | |
| // path of all the modules in that directory. Identifies module files as files with .ko extension. | |
| // If recursive is set, it returns the path of the modules in the subdirectories as well. | |
| func retrieveModulePaths(localDir string, modulePaths []string, recursive bool) ([]string, error) { | |
| if _, err := os.Stat(localDir); err != nil { | |
| return nil, fmt.Errorf("failed to validate local directory (%s): %v", localDir, err) | |
| } | |
| contents, err := os.ReadDir(localDir) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read from directory (%s): %v", localDir, err) | |
| } | |
| for _, content := range contents { | |
| contentName := content.Name() | |
| if recursive && content.IsDir() { | |
| dir := filepath.Join(localDir, contentName) | |
| modulePaths, err = retrieveModulePaths(dir, modulePaths, recursive) | |
| if err != nil { | |
| return nil, err | |
| } | |
| } | |
| modPath := filepath.Join(localDir, contentName) | |
| if filepath.Ext(contentName) == ".ko" { | |
| modulePaths = append(modulePaths, modPath) | |
| } | |
| } | |
| return modulePaths, nil | |
| } |