1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
|
// Copyright (c) 2022-2023, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.
package launcher
import (
"fmt"
"github.com/sylabs/singularity/v4/internal/pkg/ociimage"
"github.com/sylabs/singularity/v4/internal/pkg/util/fs/overlay"
"github.com/sylabs/singularity/v4/pkg/util/cryptkey"
)
// Namespaces holds flags for the optional (non-mount) namespaces that can be
// requested for a container launch.
type Namespaces struct {
User bool
UTS bool
PID bool
IPC bool
Net bool
// NoPID will force the PID namespace not to be used, even if set by default / other flags.
NoPID bool
}
// Options accumulates launch configuration from passed functional options. Note
// that the Options is modified heavily by logic during the Exec function call.
type Options struct {
// Writable marks the container image itself as writable.
Writable bool
// WritableTmpfs applies an ephemeral writable overlay to the container.
WritableTmpfs bool
// OverlayPaths holds paths to image or directory overlays to be applied.
OverlayPaths []string
// Scratchdir lists paths into the container to be mounted from a temporary location on the host.
ScratchDirs []string
// WorkDir is the parent path for scratch directories, and contained home/tmp on the host.
WorkDir string
// HomeDir is the home directory to mount into the container, or a src:dst pair.
HomeDir string
// CustomHome is a marker that HomeDir is user-supplied, and should not be
// modified by the logic used for fakeroot execution.
CustomHome bool
// NoHome disables automatic mounting of the home directory into the container.
NoHome bool
// BindPaths lists paths to bind from host to container, which may be <src>:<dest> pairs.
BindPaths []string
// FuseMount lists paths to be mounted into the container using a FUSE binary, and their options.
FuseMount []string
// Mounts lists paths to bind from host to container, from the docker compatible `--mount` flag (CSV format).
Mounts []string
// NoMount is a list of automatic / configured mounts to disable.
NoMount []string
// Nvidia enables NVIDIA GPU support.
Nvidia bool
// NcCCLI sets NVIDIA GPU support to use the nvidia-container-cli.
NvCCLI bool
// NoNvidia disables NVIDIA GPU support when set default in singularity.conf.
NoNvidia bool
// Rocm enables Rocm GPU support.
Rocm bool
// NoRocm disable Rocm GPU support when set default in singularity.conf.
NoRocm bool
// ContainLibs lists paths of libraries to bind mount into the container .singularity.d/libs dir.
ContainLibs []string
// Proot is the path to a proot binary to bind mount into the container .singularity.d/libs dir.
Proot string
// Env is a map of name=value env vars to set in the container.
Env map[string]string
// EnvFile is a file to read container env vars from.
EnvFile string
// CleanEnv starts the container with a clean environment, excluding host env vars.
CleanEnv bool
// NoEval instructs Singularity not to shell evaluate args and env vars.
NoEval bool
// Namespaces is the list of optional Namespaces requested for the container.
Namespaces Namespaces
// Network is the name of an optional CNI networking configuration to apply.
Network string
// NetworkArgs are argument to pass to the CNI plugin that will configure networking when Network is set.
NetworkArgs []string
// Hostname is the hostname to set in the container (infers/requires UTS namespace).
Hostname string
// DNS is the comma separated list of DNS servers to be set in the container's resolv.conf.
DNS string
// AddCaps is the list of capabilities to Add to the container process.
AddCaps string
// DropCaps is the list of capabilities to drop from the container process.
DropCaps string
// AllowSUID permits setuid executables inside a container started by the root user.
AllowSUID bool
// KeepPrivs keeps all privileges inside a container started by the root user.
KeepPrivs bool
// NoPrivs drops all privileges inside a container.
NoPrivs bool
// SecurityOpts is the list of security options (selinux, apparmor, seccomp) to apply.
SecurityOpts []string
// NoUmask disables propagation of the host umask into the container, using a default 0022.
NoUmask bool
// CGroupsJSON is a JSON format cgroups resource limit specification to apply.
CGroupsJSON string
// ConfigFile is an alternate singularity.conf that will be used by unprivileged installations only.
ConfigFile string
// ShellPath is a custom shell executable to be launched in the container.
ShellPath string
// CwdPath is the initial working directory in the container.
CwdPath string
// Fakeroot enables the fake root mode, using user namespaces and subuid / subgid mapping.
Fakeroot bool
// NoSetgroups disables calling setgroups for the fakeroot user namespace.
NoSetgroups bool
// Boot enables execution of /sbin/init on startup of an instance container.
Boot bool
// NoInit disables shim process when PID namespace is used.
NoInit bool
// Contain starts the container with minimal /dev and empty home/tmp mounts.
Contain bool
// ContainAll infers Contain, and adds PID, IPC namespaces, and CleanEnv.
ContainAll bool
// AppName sets a SCIF application name to run.
AppName string
// KeyInfo holds encryption key information for accessing encrypted containers.
KeyInfo *cryptkey.KeyInfo
// SIFFUSE enables mounting SIF container images using FUSE.
SIFFUSE bool
// CacheDisabled indicates caching of images was disabled in the CLI, as in
// userns flows we will need to delete the redundant temporary pulled image after
// conversion to sandbox.
CacheDisabled bool
// TransportOptions holds Docker/OCI image transport configuration (auth etc.)
// This will be used by a launcher handling OCI images directly.
TransportOptions *ociimage.TransportOptions
// TmpSandbox forces unpacking of images into temporary sandbox dirs when a
// kernel or FUSE mount would otherwise be used.
TmpSandbox bool
// NoTmpSandbox prohibits unpacking of images into temporary sandbox dirs.
NoTmpSandbox bool
// Devices contains the list of device mappings (if any), e.g. CDI mappings.
Devices []string
// CdiDirs contains the list of directories in which CDI should look for device definition JSON files
CdiDirs []string
// NoCompat indicates the container should be run in non-OCI compatible
// mode, i.e. with default mounts etc. as native mode. Effective for the OCI
// launcher only.
NoCompat bool
}
type Option func(co *Options) error
// OptWritable sets the container image to be writable.
func OptWritable(b bool) Option {
return func(lo *Options) error {
lo.Writable = b
return nil
}
}
// OptWritableTmpFs applies an ephemeral writable overlay to the container.
func OptWritableTmpfs(b bool) Option {
return func(lo *Options) error {
lo.WritableTmpfs = b
return nil
}
}
// OptOverlayPaths sets overlay images and directories to apply to the container.
// Relative paths are resolved to absolute paths at this point.
func OptOverlayPaths(op []string) Option {
return func(lo *Options) error {
var err error
for i, p := range op {
op[i], err = overlay.AbsOverlay(p)
if err != nil {
return fmt.Errorf("could not convert %q to absolute path: %w", p, err)
}
}
lo.OverlayPaths = op
return nil
}
}
// OptScratchDirs sets temporary host directories to create and bind into the container.
func OptScratchDirs(sd []string) Option {
return func(lo *Options) error {
lo.ScratchDirs = sd
return nil
}
}
// OptWorkDir sets the parent path for scratch directories, and contained home/tmp on the host.
func OptWorkDir(wd string) Option {
return func(lo *Options) error {
lo.WorkDir = wd
return nil
}
}
// OptHome sets the home directory configuration for the container.
//
// homeDir is the path or src:dst to bind mount.
// custom is a marker that this is user supplied, and must not be overridden.
// disable will disable the home mount entirely, ignoring other options.
func OptHome(homeDir string, custom bool, disable bool) Option {
return func(lo *Options) error {
lo.HomeDir = homeDir
lo.CustomHome = custom
lo.NoHome = disable
return nil
}
}
// OptMounts sets user-requested mounts to propagate into the container.
//
// binds lists bind mount specifications in Singularity's <src>:<dst>[:<opts>] format.
// mounts lists bind mount specifications in Docker CSV processed format.
// fuseMounts list FUSE mounts in <type>:<fuse command> <mountpoint> format.
func OptMounts(binds []string, mounts []string, fuseMounts []string) Option {
return func(lo *Options) error {
lo.BindPaths = binds
lo.Mounts = mounts
lo.FuseMount = fuseMounts
return nil
}
}
// OptNoMount disables the specified bind mounts.
func OptNoMount(nm []string) Option {
return func(lo *Options) error {
lo.NoMount = nm
return nil
}
}
// OptNvidia enables NVIDIA GPU support.
//
// nvccli sets whether to use the nvidia-container-runtime (true), or legacy bind mounts (false).
func OptNvidia(nv bool, nvccli bool) Option {
return func(lo *Options) error {
lo.Nvidia = nv || nvccli
lo.NvCCLI = nvccli
return nil
}
}
// OptNoNvidia disables NVIDIA GPU support, even if enabled via singularity.conf.
func OptNoNvidia(b bool) Option {
return func(lo *Options) error {
lo.NoNvidia = b
return nil
}
}
// OptRocm enable Rocm GPU support.
func OptRocm(b bool) Option {
return func(lo *Options) error {
lo.Rocm = b
return nil
}
}
// OptNoRocm disables Rocm GPU support, even if enabled via singularity.conf.
func OptNoRocm(b bool) Option {
return func(lo *Options) error {
lo.NoRocm = b
return nil
}
}
// OptContainLibs mounts specified libraries into the container .singularity.d/libs dir.
func OptContainLibs(cl []string) Option {
return func(lo *Options) error {
lo.ContainLibs = cl
return nil
}
}
// OptProot mounts specified proot executable into the container .singularity.d/libs dir.
func OptProot(p string) Option {
return func(lo *Options) error {
lo.Proot = p
return nil
}
}
// OptEnv sets container environment
//
// envFile is a path to a file container environment variables to set.
// env is a map of name=value env vars to set.
// clean removes host variables from the container environment.
func OptEnv(env map[string]string, envFile string, clean bool) Option {
return func(lo *Options) error {
lo.Env = env
lo.EnvFile = envFile
lo.CleanEnv = clean
return nil
}
}
// OptNoEval disables shell evaluation of args and env vars.
func OptNoEval(b bool) Option {
return func(lo *Options) error {
lo.NoEval = b
return nil
}
}
// OptNamespaces enable the individual kernel-support namespaces for the container.
func OptNamespaces(n Namespaces) Option {
return func(lo *Options) error {
lo.Namespaces = n
return nil
}
}
// OptNetwork enables CNI networking.
//
// network is the name of the CNI configuration to enable.
// args are arguments to pass to the CNI plugin.
func OptNetwork(network string, args []string) Option {
return func(lo *Options) error {
lo.Network = network
lo.NetworkArgs = args
return nil
}
}
// OptHostname sets a hostname for the container (infers/requires UTS namespace).
func OptHostname(h string) Option {
return func(lo *Options) error {
lo.Hostname = h
return nil
}
}
// OptDNS sets a DNS entry for the container resolv.conf.
func OptDNS(d string) Option {
return func(lo *Options) error {
lo.DNS = d
return nil
}
}
// OptCaps sets capabilities to add and drop.
func OptCaps(add, drop string) Option {
return func(lo *Options) error {
lo.AddCaps = add
lo.DropCaps = drop
return nil
}
}
// OptAllowSUID permits setuid executables inside a container started by the root user.
func OptAllowSUID(b bool) Option {
return func(lo *Options) error {
lo.AllowSUID = b
return nil
}
}
// OptKeepPrivs keeps all privileges inside a container started by the root user.
func OptKeepPrivs(b bool) Option {
return func(lo *Options) error {
lo.KeepPrivs = b
return nil
}
}
// OptNoPrivs drops all privileges inside a container.
func OptNoPrivs(b bool) Option {
return func(lo *Options) error {
lo.NoPrivs = b
return nil
}
}
// OptSecurity supplies a list of security options (selinux, apparmor, seccomp) to apply.
func OptSecurity(s []string) Option {
return func(lo *Options) error {
lo.SecurityOpts = s
return nil
}
}
// OptNoUmask disables propagation of the host umask into the container, using a default 0022.
func OptNoUmask(b bool) Option {
return func(lo *Options) error {
lo.NoUmask = b
return nil
}
}
// OptCgroupsJSON sets a Cgroups resource limit configuration to apply to the container.
func OptCgroupsJSON(cj string) Option {
return func(lo *Options) error {
lo.CGroupsJSON = cj
return nil
}
}
// OptConfigFile specifies an alternate singularity.conf that will be used by unprivileged installations only.
func OptConfigFile(c string) Option {
return func(lo *Options) error {
lo.ConfigFile = c
return nil
}
}
// OptShellPath specifies a custom shell executable to be launched in the container.
func OptShellPath(s string) Option {
return func(lo *Options) error {
lo.ShellPath = s
return nil
}
}
// OptCwdPath specifies the initial working directory in the container.
func OptCwdPath(p string) Option {
return func(lo *Options) error {
lo.CwdPath = p
return nil
}
}
// OptFakeroot enables the fake root mode, using user namespaces and subuid / subgid mapping.
func OptFakeroot(b bool) Option {
return func(lo *Options) error {
lo.Fakeroot = b
return nil
}
}
// OptNoSetgroups disables calling setgroups for the fakeroot user namespace.
func OptNoSetgroups(b bool) Option {
return func(lo *Options) error {
lo.NoSetgroups = b
return nil
}
}
// OptBoot enables execution of /sbin/init on startup of an instance container.
func OptBoot(b bool) Option {
return func(lo *Options) error {
lo.Boot = b
return nil
}
}
// OptNoInit disables shim process when PID namespace is used.
func OptNoInit(b bool) Option {
return func(lo *Options) error {
lo.NoInit = b
return nil
}
}
// OptContain starts the container with minimal /dev and empty home/tmp mounts.
func OptContain(b bool) Option {
return func(lo *Options) error {
lo.Contain = b
return nil
}
}
// OptContainAll infers Contain, and adds PID, IPC namespaces, and CleanEnv.
func OptContainAll(b bool) Option {
return func(lo *Options) error {
lo.ContainAll = b
return nil
}
}
// OptAppName sets a SCIF application name to run.
func OptAppName(a string) Option {
return func(lo *Options) error {
lo.AppName = a
return nil
}
}
// OptKeyInfo sets encryption key material to use when accessing an encrypted container image.
func OptKeyInfo(ki *cryptkey.KeyInfo) Option {
return func(lo *Options) error {
lo.KeyInfo = ki
return nil
}
}
// OptSIFFuse enables FUSE mounting of a SIF image, if possible.
func OptSIFFuse(b bool) Option {
return func(lo *Options) error {
lo.SIFFUSE = b
return nil
}
}
// TmpSandbox forces unpacking of images into temporary sandbox dirs when a
// kernel or FUSE mount would otherwise be used.
func OptTmpSandbox(b bool) Option {
return func(lo *Options) error {
lo.TmpSandbox = b
return nil
}
}
// OptNoTmpSandbox prohibits unpacking of images into temporary sandbox dirs.
func OptNoTmpSandbox(b bool) Option {
return func(lo *Options) error {
lo.NoTmpSandbox = b
return nil
}
}
// OptCacheDisabled indicates caching of images was disabled in the CLI.
func OptCacheDisabled(b bool) Option {
return func(lo *Options) error {
lo.CacheDisabled = b
return nil
}
}
// OptTransportOptions sets Docker/OCI image transport options (auth etc.)
func OptTransportOptions(tOpts *ociimage.TransportOptions) Option {
return func(lo *Options) error {
lo.TransportOptions = tOpts
return nil
}
}
// OptDevice sets CDI device mappings to apply.
func OptDevice(op []string) Option {
return func(lo *Options) error {
lo.Devices = op
return nil
}
}
// OptCdiDirs sets CDI spec search-directories to apply.
func OptCdiDirs(op []string) Option {
return func(lo *Options) error {
lo.CdiDirs = op
return nil
}
}
// OptNoCompat disable OCI compatible mode, for singularity native mode default behaviors.
func OptNoCompat(b bool) Option {
return func(lo *Options) error {
lo.NoCompat = b
return nil
}
}
|