blob: f17f0cce5e38dd7a2e24ebab4da7b9bf7661dc01 [file] [log] [blame]
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 ${kerneltree} M=${build-dir}')
MAKE_MATCH[#] (defaults to '.*')
-- Command to run when unbuilding the package
CLEAN (defaults to 'make -C ${kerneltree} 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 compiled 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.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')")
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
glog.Exitf("%v", err)
}
}