| package actions | |
| import ( | |
| goflag "flag" | |
| "strings" | |
| "cos.googlesource.com/cos/tools.git/src/pkg/dkms" | |
| "cos.googlesource.com/cos/tools.git/src/pkg/gcs" | |
| "cos.googlesource.com/cos/tools.git/src/pkg/modules" | |
| "github.com/golang/glog" | |
| "github.com/spf13/cobra" | |
| flag "github.com/spf13/pflag" | |
| ) | |
| var RootTrees = &dkms.Trees{} | |
| var RootModuleParams = modules.NewModuleParameters() | |
| var RootPackage = &dkms.Package{Trees: RootTrees, ModuleParams: RootModuleParams} | |
| var RootGCSBucket *gcs.GCSBucket = nil | |
| var RootOptions = &dkms.Options{} | |
| // resetState resets all of the global state back to defaults so the root | |
| // command can be run again and re-populate the global state correctly. | |
| // | |
| // This is intended to be used for tests. | |
| func resetState() { | |
| // We have to be very careful not to change any addresses here; otherwise, | |
| // we'll break the root command's flag bindings. | |
| *RootTrees = dkms.Trees{} | |
| RootModuleParams = modules.NewModuleParameters() | |
| *RootPackage = dkms.Package{Trees: RootTrees, ModuleParams: RootModuleParams} | |
| RootGCSBucket = nil | |
| *RootOptions = dkms.Options{} | |
| } | |
| var rootCmd = &cobra.Command{ | |
| Use: "cos-dkms [action] [options] [module/module-version] [/path/to/source-tree]", | |
| Short: "cos-dkms - Dynamic Kernel Module Support for COS", | |
| Long: strings.TrimSpace(` | |
| cos-dkms can be used to dynamically build kernel modules for COS, download | |
| precompiled modules, and upload compiled modules to a GCS bucket. | |
| A directory containing sources for one or more kernel modules is referred to | |
| as a package. A package may contain a dkms.conf file, which specifies how the | |
| package should be built and installed. If no dkms.conf is present in the | |
| package, default values will be used for all settings. The dkms.conf format | |
| is based on the format used by Dell DKMS (github.com/dell/dkms) and supports | |
| the following directives: | |
| PACKAGE_NAME (defaults to --package) | |
| PACKAGE_VERSION (defaults to --package-version) | |
| -- Per-module settings | |
| BUILT_MODULE_NAME[#] (defaults to --package) | |
| BUILT_MODULE_LOCATION[#] (relative to build directory; defaults to empty path) | |
| DEST_MODULE_NAME[#] (defaults to BUILT_MODULE_NAME[#]) | |
| DEST_MODULE_LOCATION[#] (relative to install directory; | |
| if # is 0, defaults to /kernel/updates; | |
| otherwise, defaults to DEST_MODULE_LOCATION[0]) | |
| STRIP[#] (if # is 0, defaults to 'yes'; | |
| otherwise, defaults to STRIP[0]) | |
| -- Command(s) for building the package | |
| MAKE[#] (defaults to 'make -C ${kernel_source_dir} M=${build_dir}') | |
| MAKE_MATCH[#] (defaults to '.*') | |
| -- Command to run when unbuilding the package | |
| CLEAN (defaults to 'make -C ${kernel_source_dir} M=${build_dir} clean') | |
| -- Patches to apply before building the package | |
| PATCH[#] (defaults to empty array) | |
| PATCH_MATCH[#] (defaults to empty array) | |
| -- List of packages which should be built before this one | |
| BUILD_DEPENDS[#] (defaults to empty array) | |
| -- Regexes to specify kernel and arch for which this package can be built | |
| BUILD_EXCLUSIVE_KERNEL (defaults to '.*') | |
| BUILD_EXCLUSIVE_ARCH (defaults to '.*') | |
| More directives may be added in the future. | |
| In many cases, packages can be managed using only the install and remove | |
| subcommands. Internally, install will call the add and build commands to | |
| add a package to the DKMS source tree and compile its modules, then | |
| install them to a target install tree; and remove will uninstall and unbuild | |
| a package, then remove it from the DKMS source tree. See the --help for each | |
| subcommand for more details. | |
| `), | |
| SilenceUsage: true, | |
| } | |
| func init() { | |
| flag.CommandLine.AddGoFlagSet(goflag.CommandLine) | |
| pflags := rootCmd.PersistentFlags() | |
| pflags.StringVarP(&RootPackage.Name, "package", "p", "", | |
| "the name of the package") | |
| pflags.StringVarP(&RootPackage.Name, "module", "m", "", | |
| "the name of the module/package (alias of --package for compatibility with dkms)") | |
| pflags.StringVar(&RootPackage.Version, "package-version", "", | |
| "the version of the package") | |
| pflags.StringVar(&RootPackage.Version, "module-version", "", | |
| "the version of the module/package (alias of --package-version for compatibility with dkms)") | |
| pflags.StringVarP(&RootPackage.KernelVersion, "kernel-version", "k", "", | |
| "the kernel version (defaults to the kernel version of the running kernel)") | |
| pflags.StringVarP(&RootPackage.Arch, "arch", "a", "", | |
| "the compiler architecture (e.g., x86_64, aarch64; defaults to the arch of the running kernel)") | |
| pflags.StringVar(&RootPackage.Trees.Kernel, "kernelsourcedir", "", | |
| "the directory where the kernel sources are located (defaults to /lib/modules/${kernel-version}/build)") | |
| pflags.StringVarP(&RootPackage.Trees.Dkms, "dkmstree", "d", "/var/lib/dkms", | |
| "the directory where the dkms tree is located") | |
| pflags.StringVarP(&RootPackage.Trees.Source, "sourcetree", "s", "", | |
| "the directory where the module source tree is located (defaults to /usr/src)") | |
| pflags.StringVarP(&RootPackage.Trees.Install, "installtree", "i", "", | |
| "the directory where the modules will be installed (defaults to /lib/modules/${kernel-version})") | |
| pflags.StringVarP(&RootPackage.Trees.KernelModules, "kernelmodulestree", "b", "", | |
| "the directory where in-tree kernel modules are installed (defaults to ${installtree}") | |
| pflags.StringVar(&RootPackage.BuildId, "build-id", "", | |
| "the kernel build id") | |
| pflags.StringVar(&RootPackage.Board, "board", "", | |
| "the kernel board") | |
| pflags.Var(&RootPackage.ModuleParams, "module-arg", | |
| "parameters to be passed to kernel modules, in the form module1.param1=value1,module2.param2=value2, etc.") | |
| pflags.BoolVar(&RootOptions.Latest, "latest", false, | |
| "use the latest compatible version of the package which is available") | |
| pflags.StringVar(&RootOptions.MinVersion, "min-version", "", | |
| "only install versions of the package greater than or equal to this version; implies --latest") | |
| pflags.StringVar(&RootOptions.MaxVersion, "max-version", "", | |
| "only install versions of the package less than or equal to this version; implies --latest") | |
| pflags.BoolVarP(&RootOptions.Force, "force", "f", false, | |
| "whether to force an action even if it has already happened") | |
| pflags.BoolVar(&RootOptions.ForceVersionOverride, "force-version-override", false, | |
| "skip any version checks when using a module which has an earlier version than one which is already present") | |
| pflags.BoolVar(&RootOptions.InstallBuildDependencies, "install-build-dependencies", false, | |
| "install build dependencies before running build if they are not installed") | |
| pflags.BoolVarP(&RootOptions.InsertOnInstall, "insert-on-install", "I", false, | |
| "insert installed modules and their dependencies into the running kernel on install") | |
| pflags.BoolVarP(&RootOptions.ModprobeOnInstall, "modprobe-on-install", "M", false, | |
| "run modprobe on install, inserting installed modules and their dependencies into the running kernel") | |
| pflags.BoolVar(&RootOptions.NoDepmod, "no-depmod", false, | |
| "do not run depmod before modprobe on install when --modprobe-on-install is specified") | |
| pflags.IntVarP(&RootOptions.Jobs, "jobs", "j", 1, | |
| "the maximum number of jobs to use when compiling modules") | |
| pflags.StringVar(&RootOptions.GCSBucket, "gcs-bucket", "", | |
| "a GCS bucket path to use as a cache for builds and source files") | |
| pflags.BoolVar(&RootOptions.Upload, "upload", false, | |
| "whether or not to upload files to the GCS bucket after a build or install") | |
| pflags.IntVarP(&RootOptions.DownloadWorkers, "download-workers", "w", 1, | |
| "the maximum number of workers to use when downloading from a GCS bucket; if the number of workers is negative or 0, one download worker will be created per object to be downloaded") | |
| pflags.StringVar(&RootOptions.MakeVariables, "make-variables", "", | |
| "variables to be passed to the make command, such as CC. If set to 'cos-default', the variables for compiling the COS kernel will be used.") | |
| pflags.StringVar(&RootOptions.LSBReleasePath, "lsb-release-path", "/etc/lsb-release", | |
| "path to the LSB Release file which will be used to populate default values for --build-id and --board if they are not supplied") | |
| pflags.StringVar(&RootOptions.Hash, "hash-algorithm", "sha256", | |
| "the hash algorithm used during signing of modules. Currently, only SHA-2 and SHA-3 families are supported. (e.g. 'sha256')") | |
| pflags.StringVar(&RootOptions.CloudKMSKey, "cloud-kms-key", "", | |
| "the resource name for a Cloud KMS key used to sign modules. If provided, this key would be used instead of a local private key. (e.g. projects/my-project/locations/global/keyRings/my-keyring/cryptoKeys/my-key/cryptoKeyVersions/1)") | |
| pflags.BoolVar(&RootOptions.UseRegionalBucket, "use-regional-bucket", true, | |
| "use regional GCS buckets (e.g. cos-tools-us-central1) for downloading artifacts") | |
| } | |
| func Execute() { | |
| if err := rootCmd.Execute(); err != nil { | |
| glog.Exitf("%v", err) | |
| } | |
| } |