github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/libpod/runtime.go (about) 1 package libpod 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "strings" 9 "sync" 10 "syscall" 11 12 "github.com/containers/common/pkg/config" 13 "github.com/containers/image/v5/pkg/sysregistriesv2" 14 is "github.com/containers/image/v5/storage" 15 "github.com/containers/image/v5/types" 16 "github.com/containers/podman/v2/libpod/define" 17 "github.com/containers/podman/v2/libpod/events" 18 "github.com/containers/podman/v2/libpod/image" 19 "github.com/containers/podman/v2/libpod/lock" 20 "github.com/containers/podman/v2/libpod/shutdown" 21 "github.com/containers/podman/v2/pkg/cgroups" 22 "github.com/containers/podman/v2/pkg/registries" 23 "github.com/containers/podman/v2/pkg/rootless" 24 "github.com/containers/podman/v2/pkg/util" 25 "github.com/containers/storage" 26 "github.com/cri-o/ocicni/pkg/ocicni" 27 "github.com/docker/docker/pkg/namesgenerator" 28 "github.com/pkg/errors" 29 "github.com/sirupsen/logrus" 30 ) 31 32 // A RuntimeOption is a functional option which alters the Runtime created by 33 // NewRuntime 34 type RuntimeOption func(*Runtime) error 35 36 type storageSet struct { 37 RunRootSet bool 38 GraphRootSet bool 39 StaticDirSet bool 40 VolumePathSet bool 41 GraphDriverNameSet bool 42 TmpDirSet bool 43 } 44 45 // Runtime is the core libpod runtime 46 type Runtime struct { 47 config *config.Config 48 storageConfig storage.StoreOptions 49 storageSet storageSet 50 51 state State 52 store storage.Store 53 storageService *storageService 54 imageContext *types.SystemContext 55 defaultOCIRuntime OCIRuntime 56 ociRuntimes map[string]OCIRuntime 57 runtimeFlags []string 58 netPlugin ocicni.CNIPlugin 59 conmonPath string 60 imageRuntime *image.Runtime 61 lockManager lock.Manager 62 63 // doRenumber indicates that the runtime should perform a lock renumber 64 // during initialization. 65 // Once the runtime has been initialized and returned, this variable is 66 // unused. 67 doRenumber bool 68 69 doMigrate bool 70 // System migrate can move containers to a new runtime. 71 // We make no promises that these migrated containers work on the new 72 // runtime, though. 73 migrateRuntime string 74 75 // valid indicates whether the runtime is ready to use. 76 // valid is set to true when a runtime is returned from GetRuntime(), 77 // and remains true until the runtime is shut down (rendering its 78 // storage unusable). When valid is false, the runtime cannot be used. 79 valid bool 80 lock sync.RWMutex 81 82 // mechanism to read and write even logs 83 eventer events.Eventer 84 85 // noStore indicates whether we need to interact with a store or not 86 noStore bool 87 } 88 89 // SetXdgDirs ensures the XDG_RUNTIME_DIR env and XDG_CONFIG_HOME variables are set. 90 // containers/image uses XDG_RUNTIME_DIR to locate the auth file, XDG_CONFIG_HOME is 91 // use for the containers.conf configuration file. 92 func SetXdgDirs() error { 93 if !rootless.IsRootless() { 94 return nil 95 } 96 97 // Setup XDG_RUNTIME_DIR 98 runtimeDir := os.Getenv("XDG_RUNTIME_DIR") 99 100 if runtimeDir == "" { 101 var err error 102 runtimeDir, err = util.GetRuntimeDir() 103 if err != nil { 104 return err 105 } 106 } 107 if err := os.Setenv("XDG_RUNTIME_DIR", runtimeDir); err != nil { 108 return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR") 109 } 110 111 if rootless.IsRootless() && os.Getenv("DBUS_SESSION_BUS_ADDRESS") == "" { 112 sessionAddr := filepath.Join(runtimeDir, "bus") 113 if _, err := os.Stat(sessionAddr); err == nil { 114 os.Setenv("DBUS_SESSION_BUS_ADDRESS", fmt.Sprintf("unix:path=%s", sessionAddr)) 115 } 116 } 117 118 // Setup XDG_CONFIG_HOME 119 if cfgHomeDir := os.Getenv("XDG_CONFIG_HOME"); cfgHomeDir == "" { 120 cfgHomeDir, err := util.GetRootlessConfigHomeDir() 121 if err != nil { 122 return err 123 } 124 if err := os.Setenv("XDG_CONFIG_HOME", cfgHomeDir); err != nil { 125 return errors.Wrapf(err, "cannot set XDG_CONFIG_HOME") 126 } 127 } 128 return nil 129 } 130 131 // NewRuntime creates a new container runtime 132 // Options can be passed to override the default configuration for the runtime 133 func NewRuntime(ctx context.Context, options ...RuntimeOption) (*Runtime, error) { 134 conf, err := config.NewConfig("") 135 if err != nil { 136 return nil, err 137 } 138 conf.CheckCgroupsAndAdjustConfig() 139 return newRuntimeFromConfig(ctx, conf, options...) 140 } 141 142 // NewRuntimeFromConfig creates a new container runtime using the given 143 // configuration file for its default configuration. Passed RuntimeOption 144 // functions can be used to mutate this configuration further. 145 // An error will be returned if the configuration file at the given path does 146 // not exist or cannot be loaded 147 func NewRuntimeFromConfig(ctx context.Context, userConfig *config.Config, options ...RuntimeOption) (*Runtime, error) { 148 149 return newRuntimeFromConfig(ctx, userConfig, options...) 150 } 151 152 func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...RuntimeOption) (*Runtime, error) { 153 runtime := new(Runtime) 154 155 if conf.Engine.OCIRuntime == "" { 156 conf.Engine.OCIRuntime = "runc" 157 // If we're running on cgroups v2, default to using crun. 158 if onCgroupsv2, _ := cgroups.IsCgroup2UnifiedMode(); onCgroupsv2 { 159 conf.Engine.OCIRuntime = "crun" 160 } 161 } 162 163 runtime.config = conf 164 165 if err := SetXdgDirs(); err != nil { 166 return nil, err 167 } 168 169 storeOpts, err := storage.DefaultStoreOptions(rootless.IsRootless(), rootless.GetRootlessUID()) 170 if err != nil { 171 return nil, err 172 } 173 runtime.storageConfig = storeOpts 174 175 // Overwrite config with user-given configuration options 176 for _, opt := range options { 177 if err := opt(runtime); err != nil { 178 return nil, errors.Wrapf(err, "error configuring runtime") 179 } 180 } 181 182 if err := shutdown.Start(); err != nil { 183 return nil, errors.Wrapf(err, "error starting shutdown signal handler") 184 } 185 186 if err := makeRuntime(ctx, runtime); err != nil { 187 return nil, err 188 } 189 190 if err := shutdown.Register("libpod", func(sig os.Signal) error { 191 os.Exit(1) 192 return nil 193 }); err != nil && errors.Cause(err) != shutdown.ErrHandlerExists { 194 logrus.Errorf("Error registering shutdown handler for libpod: %v", err) 195 } 196 197 return runtime, nil 198 } 199 200 func getLockManager(runtime *Runtime) (lock.Manager, error) { 201 var err error 202 var manager lock.Manager 203 204 switch runtime.config.Engine.LockType { 205 case "file": 206 lockPath := filepath.Join(runtime.config.Engine.TmpDir, "locks") 207 manager, err = lock.OpenFileLockManager(lockPath) 208 if err != nil { 209 if os.IsNotExist(errors.Cause(err)) { 210 manager, err = lock.NewFileLockManager(lockPath) 211 if err != nil { 212 return nil, errors.Wrapf(err, "failed to get new file lock manager") 213 } 214 } else { 215 return nil, err 216 } 217 } 218 219 case "", "shm": 220 lockPath := define.DefaultSHMLockPath 221 if rootless.IsRootless() { 222 lockPath = fmt.Sprintf("%s_%d", define.DefaultRootlessSHMLockPath, rootless.GetRootlessUID()) 223 } 224 // Set up the lock manager 225 manager, err = lock.OpenSHMLockManager(lockPath, runtime.config.Engine.NumLocks) 226 if err != nil { 227 switch { 228 case os.IsNotExist(errors.Cause(err)): 229 manager, err = lock.NewSHMLockManager(lockPath, runtime.config.Engine.NumLocks) 230 if err != nil { 231 return nil, errors.Wrapf(err, "failed to get new shm lock manager") 232 } 233 case errors.Cause(err) == syscall.ERANGE && runtime.doRenumber: 234 logrus.Debugf("Number of locks does not match - removing old locks") 235 236 // ERANGE indicates a lock numbering mismatch. 237 // Since we're renumbering, this is not fatal. 238 // Remove the earlier set of locks and recreate. 239 if err := os.Remove(filepath.Join("/dev/shm", lockPath)); err != nil { 240 return nil, errors.Wrapf(err, "error removing libpod locks file %s", lockPath) 241 } 242 243 manager, err = lock.NewSHMLockManager(lockPath, runtime.config.Engine.NumLocks) 244 if err != nil { 245 return nil, err 246 } 247 default: 248 return nil, err 249 } 250 } 251 default: 252 return nil, errors.Wrapf(define.ErrInvalidArg, "unknown lock type %s", runtime.config.Engine.LockType) 253 } 254 return manager, nil 255 } 256 257 // Make a new runtime based on the given configuration 258 // Sets up containers/storage, state store, OCI runtime 259 func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { 260 // Find a working conmon binary 261 cPath, err := runtime.config.FindConmon() 262 if err != nil { 263 return err 264 } 265 runtime.conmonPath = cPath 266 267 // Make the static files directory if it does not exist 268 if err := os.MkdirAll(runtime.config.Engine.StaticDir, 0700); err != nil { 269 // The directory is allowed to exist 270 if !os.IsExist(err) { 271 return errors.Wrap(err, "error creating runtime static files directory") 272 } 273 } 274 275 // Set up the state. 276 // 277 // TODO - if we further break out the state implementation into 278 // libpod/state, the config could take care of the code below. It 279 // would further allow to move the types and consts into a coherent 280 // package. 281 switch runtime.config.Engine.StateType { 282 case config.InMemoryStateStore: 283 state, err := NewInMemoryState() 284 if err != nil { 285 return err 286 } 287 runtime.state = state 288 case config.SQLiteStateStore: 289 return errors.Wrapf(define.ErrInvalidArg, "SQLite state is currently disabled") 290 case config.BoltDBStateStore: 291 dbPath := filepath.Join(runtime.config.Engine.StaticDir, "bolt_state.db") 292 293 state, err := NewBoltState(dbPath, runtime) 294 if err != nil { 295 return err 296 } 297 runtime.state = state 298 default: 299 return errors.Wrapf(define.ErrInvalidArg, "unrecognized state type passed (%v)", runtime.config.Engine.StateType) 300 } 301 302 // Grab config from the database so we can reset some defaults 303 dbConfig, err := runtime.state.GetDBConfig() 304 if err != nil { 305 return errors.Wrapf(err, "error retrieving runtime configuration from database") 306 } 307 308 runtime.mergeDBConfig(dbConfig) 309 310 logrus.Debugf("Using graph driver %s", runtime.storageConfig.GraphDriverName) 311 logrus.Debugf("Using graph root %s", runtime.storageConfig.GraphRoot) 312 logrus.Debugf("Using run root %s", runtime.storageConfig.RunRoot) 313 logrus.Debugf("Using static dir %s", runtime.config.Engine.StaticDir) 314 logrus.Debugf("Using tmp dir %s", runtime.config.Engine.TmpDir) 315 logrus.Debugf("Using volume path %s", runtime.config.Engine.VolumePath) 316 317 // Validate our config against the database, now that we've set our 318 // final storage configuration 319 if err := runtime.state.ValidateDBConfig(runtime); err != nil { 320 return err 321 } 322 323 if err := runtime.state.SetNamespace(runtime.config.Engine.Namespace); err != nil { 324 return errors.Wrapf(err, "error setting libpod namespace in state") 325 } 326 logrus.Debugf("Set libpod namespace to %q", runtime.config.Engine.Namespace) 327 328 // Set up containers/storage 329 var store storage.Store 330 if os.Geteuid() != 0 { 331 logrus.Debug("Not configuring container store") 332 } else if runtime.noStore { 333 logrus.Debug("No store required. Not opening container store.") 334 } else if err := runtime.configureStore(); err != nil { 335 return err 336 } 337 defer func() { 338 if retErr != nil && store != nil { 339 // Don't forcibly shut down 340 // We could be opening a store in use by another libpod 341 if _, err := store.Shutdown(false); err != nil { 342 logrus.Errorf("Error removing store for partially-created runtime: %s", err) 343 } 344 } 345 }() 346 347 // Setup the eventer 348 eventer, err := runtime.newEventer() 349 if err != nil { 350 return err 351 } 352 runtime.eventer = eventer 353 if runtime.imageRuntime != nil { 354 runtime.imageRuntime.Eventer = eventer 355 } 356 357 // Set up containers/image 358 if runtime.imageContext == nil { 359 runtime.imageContext = &types.SystemContext{} 360 } 361 runtime.imageContext.SignaturePolicyPath = runtime.config.Engine.SignaturePolicyPath 362 363 // Create the tmpDir 364 if err := os.MkdirAll(runtime.config.Engine.TmpDir, 0751); err != nil { 365 // The directory is allowed to exist 366 if !os.IsExist(err) { 367 return errors.Wrap(err, "error creating tmpdir") 368 } 369 } 370 371 // Create events log dir 372 if err := os.MkdirAll(filepath.Dir(runtime.config.Engine.EventsLogFilePath), 0700); err != nil { 373 // The directory is allowed to exist 374 if !os.IsExist(err) { 375 return errors.Wrap(err, "error creating events dirs") 376 } 377 } 378 379 // Get us at least one working OCI runtime. 380 runtime.ociRuntimes = make(map[string]OCIRuntime) 381 382 // Initialize remaining OCI runtimes 383 for name, paths := range runtime.config.Engine.OCIRuntimes { 384 385 ociRuntime, err := newConmonOCIRuntime(name, paths, runtime.conmonPath, runtime.runtimeFlags, runtime.config) 386 if err != nil { 387 // Don't fatally error. 388 // This will allow us to ship configs including optional 389 // runtimes that might not be installed (crun, kata). 390 // Only a warnf so default configs don't spec errors. 391 logrus.Warnf("Error initializing configured OCI runtime %s: %v", name, err) 392 continue 393 } 394 395 runtime.ociRuntimes[name] = ociRuntime 396 } 397 398 // Do we have a default OCI runtime? 399 if runtime.config.Engine.OCIRuntime != "" { 400 // If the string starts with / it's a path to a runtime 401 // executable. 402 if strings.HasPrefix(runtime.config.Engine.OCIRuntime, "/") { 403 ociRuntime, err := newConmonOCIRuntime(runtime.config.Engine.OCIRuntime, []string{runtime.config.Engine.OCIRuntime}, runtime.conmonPath, runtime.runtimeFlags, runtime.config) 404 if err != nil { 405 return err 406 } 407 408 runtime.ociRuntimes[runtime.config.Engine.OCIRuntime] = ociRuntime 409 runtime.defaultOCIRuntime = ociRuntime 410 } else { 411 ociRuntime, ok := runtime.ociRuntimes[runtime.config.Engine.OCIRuntime] 412 if !ok { 413 return errors.Wrapf(define.ErrInvalidArg, "default OCI runtime %q not found", runtime.config.Engine.OCIRuntime) 414 } 415 runtime.defaultOCIRuntime = ociRuntime 416 } 417 } 418 419 // Do we have at least one valid OCI runtime? 420 if len(runtime.ociRuntimes) == 0 { 421 return errors.Wrapf(define.ErrInvalidArg, "no OCI runtime has been configured") 422 } 423 424 // Do we have a default runtime? 425 if runtime.defaultOCIRuntime == nil { 426 return errors.Wrapf(define.ErrInvalidArg, "no default OCI runtime was configured") 427 } 428 429 // Make the per-boot files directory if it does not exist 430 if err := os.MkdirAll(runtime.config.Engine.TmpDir, 0755); err != nil { 431 // The directory is allowed to exist 432 if !os.IsExist(err) { 433 return errors.Wrapf(err, "error creating runtime temporary files directory") 434 } 435 } 436 437 // Set up the CNI net plugin 438 if !rootless.IsRootless() { 439 440 netPlugin, err := ocicni.InitCNI(runtime.config.Network.DefaultNetwork, runtime.config.Network.NetworkConfigDir, runtime.config.Network.CNIPluginDirs...) 441 if err != nil { 442 return errors.Wrapf(err, "error configuring CNI network plugin") 443 } 444 runtime.netPlugin = netPlugin 445 } 446 447 // We now need to see if the system has restarted 448 // We check for the presence of a file in our tmp directory to verify this 449 // This check must be locked to prevent races 450 runtimeAliveLock := filepath.Join(runtime.config.Engine.TmpDir, "alive.lck") 451 runtimeAliveFile := filepath.Join(runtime.config.Engine.TmpDir, "alive") 452 aliveLock, err := storage.GetLockfile(runtimeAliveLock) 453 if err != nil { 454 return errors.Wrapf(err, "error acquiring runtime init lock") 455 } 456 // Acquire the lock and hold it until we return 457 // This ensures that no two processes will be in runtime.refresh at once 458 // TODO: we can't close the FD in this lock, so we should keep it around 459 // and use it to lock important operations 460 aliveLock.Lock() 461 doRefresh := false 462 defer func() { 463 if aliveLock.Locked() { 464 aliveLock.Unlock() 465 } 466 }() 467 468 _, err = os.Stat(runtimeAliveFile) 469 if err != nil { 470 // If we need to refresh, then it is safe to assume there are 471 // no containers running. Create immediately a namespace, as 472 // we will need to access the storage. 473 if os.Geteuid() != 0 { 474 aliveLock.Unlock() // Unlock to avoid deadlock as BecomeRootInUserNS will reexec. 475 pausePid, err := util.GetRootlessPauseProcessPidPathGivenDir(runtime.config.Engine.TmpDir) 476 if err != nil { 477 return errors.Wrapf(err, "could not get pause process pid file path") 478 } 479 became, ret, err := rootless.BecomeRootInUserNS(pausePid) 480 if err != nil { 481 return err 482 } 483 if became { 484 os.Exit(ret) 485 } 486 487 } 488 // If the file doesn't exist, we need to refresh the state 489 // This will trigger on first use as well, but refreshing an 490 // empty state only creates a single file 491 // As such, it's not really a performance concern 492 if os.IsNotExist(err) { 493 doRefresh = true 494 } else { 495 return errors.Wrapf(err, "error reading runtime status file %s", runtimeAliveFile) 496 } 497 } 498 499 runtime.lockManager, err = getLockManager(runtime) 500 if err != nil { 501 return err 502 } 503 504 // If we're renumbering locks, do it now. 505 // It breaks out of normal runtime init, and will not return a valid 506 // runtime. 507 if runtime.doRenumber { 508 if err := runtime.renumberLocks(); err != nil { 509 return err 510 } 511 } 512 513 // If we need to refresh the state, do it now - things are guaranteed to 514 // be set up by now. 515 if doRefresh { 516 // Ensure we have a store before refresh occurs 517 if runtime.store == nil { 518 if err := runtime.configureStore(); err != nil { 519 return err 520 } 521 } 522 523 if err2 := runtime.refresh(runtimeAliveFile); err2 != nil { 524 return err2 525 } 526 } 527 528 // Mark the runtime as valid - ready to be used, cannot be modified 529 // further 530 runtime.valid = true 531 532 if runtime.doMigrate { 533 if err := runtime.migrate(ctx); err != nil { 534 return err 535 } 536 } 537 538 return nil 539 } 540 541 // TmpDir gets the current Libpod temporary files directory. 542 func (r *Runtime) TmpDir() (string, error) { 543 if !r.valid { 544 return "", define.ErrRuntimeStopped 545 } 546 547 return r.config.Engine.TmpDir, nil 548 } 549 550 // GetConfig returns a copy of the configuration used by the runtime 551 func (r *Runtime) GetConfig() (*config.Config, error) { 552 r.lock.RLock() 553 defer r.lock.RUnlock() 554 555 if !r.valid { 556 return nil, define.ErrRuntimeStopped 557 } 558 559 config := new(config.Config) 560 561 // Copy so the caller won't be able to modify the actual config 562 if err := JSONDeepCopy(r.config, config); err != nil { 563 return nil, errors.Wrapf(err, "error copying config") 564 } 565 566 return config, nil 567 } 568 569 // DeferredShutdown shuts down the runtime without exposing any 570 // errors. This is only meant to be used when the runtime is being 571 // shutdown within a defer statement; else use Shutdown 572 func (r *Runtime) DeferredShutdown(force bool) { 573 _ = r.Shutdown(force) 574 } 575 576 // Shutdown shuts down the runtime and associated containers and storage 577 // If force is true, containers and mounted storage will be shut down before 578 // cleaning up; if force is false, an error will be returned if there are 579 // still containers running or mounted 580 func (r *Runtime) Shutdown(force bool) error { 581 r.lock.Lock() 582 defer r.lock.Unlock() 583 584 if !r.valid { 585 return define.ErrRuntimeStopped 586 } 587 588 r.valid = false 589 590 // Shutdown all containers if --force is given 591 if force { 592 ctrs, err := r.state.AllContainers() 593 if err != nil { 594 logrus.Errorf("Error retrieving containers from database: %v", err) 595 } else { 596 for _, ctr := range ctrs { 597 if err := ctr.StopWithTimeout(r.config.Engine.StopTimeout); err != nil { 598 logrus.Errorf("Error stopping container %s: %v", ctr.ID(), err) 599 } 600 } 601 } 602 } 603 604 var lastError error 605 // If no store was requested, it can be nil and there is no need to 606 // attempt to shut it down 607 if r.store != nil { 608 if _, err := r.store.Shutdown(force); err != nil { 609 lastError = errors.Wrapf(err, "error shutting down container storage") 610 } 611 } 612 if err := r.state.Close(); err != nil { 613 if lastError != nil { 614 logrus.Errorf("%v", lastError) 615 } 616 lastError = err 617 } 618 619 return lastError 620 } 621 622 // Reconfigures the runtime after a reboot 623 // Refreshes the state, recreating temporary files 624 // Does not check validity as the runtime is not valid until after this has run 625 func (r *Runtime) refresh(alivePath string) error { 626 logrus.Debugf("Podman detected system restart - performing state refresh") 627 628 // First clear the state in the database 629 if err := r.state.Refresh(); err != nil { 630 return err 631 } 632 633 // Next refresh the state of all containers to recreate dirs and 634 // namespaces, and all the pods to recreate cgroups. 635 // Containers, pods, and volumes must also reacquire their locks. 636 ctrs, err := r.state.AllContainers() 637 if err != nil { 638 return errors.Wrapf(err, "error retrieving all containers from state") 639 } 640 pods, err := r.state.AllPods() 641 if err != nil { 642 return errors.Wrapf(err, "error retrieving all pods from state") 643 } 644 vols, err := r.state.AllVolumes() 645 if err != nil { 646 return errors.Wrapf(err, "error retrieving all volumes from state") 647 } 648 // No locks are taken during pod, volume, and container refresh. 649 // Furthermore, the pod/volume/container refresh() functions are not 650 // allowed to take locks themselves. 651 // We cannot assume that any pod/volume/container has a valid lock until 652 // after this function has returned. 653 // The runtime alive lock should suffice to provide mutual exclusion 654 // until this has run. 655 for _, ctr := range ctrs { 656 if err := ctr.refresh(); err != nil { 657 logrus.Errorf("Error refreshing container %s: %v", ctr.ID(), err) 658 } 659 } 660 for _, pod := range pods { 661 if err := pod.refresh(); err != nil { 662 logrus.Errorf("Error refreshing pod %s: %v", pod.ID(), err) 663 } 664 } 665 for _, vol := range vols { 666 if err := vol.refresh(); err != nil { 667 logrus.Errorf("Error refreshing volume %s: %v", vol.Name(), err) 668 } 669 } 670 671 // Create a file indicating the runtime is alive and ready 672 file, err := os.OpenFile(alivePath, os.O_RDONLY|os.O_CREATE, 0644) 673 if err != nil { 674 return errors.Wrap(err, "error creating runtime status file") 675 } 676 defer file.Close() 677 678 r.newSystemEvent(events.Refresh) 679 680 return nil 681 } 682 683 // Info returns the store and host information 684 func (r *Runtime) Info() (*define.Info, error) { 685 return r.info() 686 } 687 688 // generateName generates a unique name for a container or pod. 689 func (r *Runtime) generateName() (string, error) { 690 for { 691 name := namesgenerator.GetRandomName(0) 692 // Make sure container with this name does not exist 693 if _, err := r.state.LookupContainer(name); err == nil { 694 continue 695 } else if errors.Cause(err) != define.ErrNoSuchCtr { 696 return "", err 697 } 698 // Make sure pod with this name does not exist 699 if _, err := r.state.LookupPod(name); err == nil { 700 continue 701 } else if errors.Cause(err) != define.ErrNoSuchPod { 702 return "", err 703 } 704 return name, nil 705 } 706 // The code should never reach here. 707 } 708 709 // Configure store and image runtime 710 func (r *Runtime) configureStore() error { 711 store, err := storage.GetStore(r.storageConfig) 712 if err != nil { 713 return err 714 } 715 716 r.store = store 717 is.Transport.SetStore(store) 718 719 // Set up a storage service for creating container root filesystems from 720 // images 721 r.storageService = getStorageService(r.store) 722 723 ir := image.NewImageRuntimeFromStore(r.store) 724 ir.SignaturePolicyPath = r.config.Engine.SignaturePolicyPath 725 ir.EventsLogFilePath = r.config.Engine.EventsLogFilePath 726 ir.EventsLogger = r.config.Engine.EventsLogger 727 728 r.imageRuntime = ir 729 730 return nil 731 } 732 733 // ImageRuntime returns the imageruntime for image operations. 734 // If WithNoStore() was used, no image runtime will be available, and this 735 // function will return nil. 736 func (r *Runtime) ImageRuntime() *image.Runtime { 737 return r.imageRuntime 738 } 739 740 // SystemContext returns the imagecontext 741 func (r *Runtime) SystemContext() *types.SystemContext { 742 return r.imageContext 743 } 744 745 // GetOCIRuntimePath retrieves the path of the default OCI runtime. 746 func (r *Runtime) GetOCIRuntimePath() string { 747 return r.defaultOCIRuntime.Path() 748 } 749 750 // StorageConfig retrieves the storage options for the container runtime 751 func (r *Runtime) StorageConfig() storage.StoreOptions { 752 return r.storageConfig 753 } 754 755 // GetStore returns the runtime stores 756 func (r *Runtime) GetStore() storage.Store { 757 return r.store 758 } 759 760 // GetName retrieves the name associated with a given full ID. 761 // This works for both containers and pods, and does not distinguish between the 762 // two. 763 // If the given ID does not correspond to any existing Pod or Container, 764 // ErrNoSuchCtr is returned. 765 func (r *Runtime) GetName(id string) (string, error) { 766 r.lock.RLock() 767 defer r.lock.RUnlock() 768 769 if !r.valid { 770 return "", define.ErrRuntimeStopped 771 } 772 773 return r.state.GetName(id) 774 } 775 776 // DBConfig is a set of Libpod runtime configuration settings that are saved in 777 // a State when it is first created, and can subsequently be retrieved. 778 type DBConfig struct { 779 LibpodRoot string 780 LibpodTmp string 781 StorageRoot string 782 StorageTmp string 783 GraphDriver string 784 VolumePath string 785 } 786 787 // mergeDBConfig merges the configuration from the database. 788 func (r *Runtime) mergeDBConfig(dbConfig *DBConfig) { 789 790 c := &r.config.Engine 791 if !r.storageSet.RunRootSet && dbConfig.StorageTmp != "" { 792 if r.storageConfig.RunRoot != dbConfig.StorageTmp && 793 r.storageConfig.RunRoot != "" { 794 logrus.Debugf("Overriding run root %q with %q from database", 795 r.storageConfig.RunRoot, dbConfig.StorageTmp) 796 } 797 r.storageConfig.RunRoot = dbConfig.StorageTmp 798 } 799 800 if !r.storageSet.GraphRootSet && dbConfig.StorageRoot != "" { 801 if r.storageConfig.GraphRoot != dbConfig.StorageRoot && 802 r.storageConfig.GraphRoot != "" { 803 logrus.Debugf("Overriding graph root %q with %q from database", 804 r.storageConfig.GraphRoot, dbConfig.StorageRoot) 805 } 806 r.storageConfig.GraphRoot = dbConfig.StorageRoot 807 } 808 809 if !r.storageSet.GraphDriverNameSet && dbConfig.GraphDriver != "" { 810 if r.storageConfig.GraphDriverName != dbConfig.GraphDriver && 811 r.storageConfig.GraphDriverName != "" { 812 logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve", 813 r.storageConfig.GraphDriverName, dbConfig.GraphDriver) 814 } 815 r.storageConfig.GraphDriverName = dbConfig.GraphDriver 816 } 817 818 if !r.storageSet.StaticDirSet && dbConfig.LibpodRoot != "" { 819 if c.StaticDir != dbConfig.LibpodRoot && c.StaticDir != "" { 820 logrus.Debugf("Overriding static dir %q with %q from database", c.StaticDir, dbConfig.LibpodRoot) 821 } 822 c.StaticDir = dbConfig.LibpodRoot 823 } 824 825 if !r.storageSet.TmpDirSet && dbConfig.LibpodTmp != "" { 826 if c.TmpDir != dbConfig.LibpodTmp && c.TmpDir != "" { 827 logrus.Debugf("Overriding tmp dir %q with %q from database", c.TmpDir, dbConfig.LibpodTmp) 828 } 829 c.TmpDir = dbConfig.LibpodTmp 830 c.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log") 831 } 832 833 if !r.storageSet.VolumePathSet && dbConfig.VolumePath != "" { 834 if c.VolumePath != dbConfig.VolumePath && c.VolumePath != "" { 835 logrus.Debugf("Overriding volume path %q with %q from database", c.VolumePath, dbConfig.VolumePath) 836 } 837 c.VolumePath = dbConfig.VolumePath 838 } 839 } 840 841 func (r *Runtime) EnableLabeling() bool { 842 return r.config.Containers.EnableLabeling 843 } 844 845 // Reload reloads the configurations files 846 func (r *Runtime) Reload() error { 847 if err := r.reloadContainersConf(); err != nil { 848 return err 849 } 850 if err := r.reloadStorageConf(); err != nil { 851 return err 852 } 853 if err := reloadRegistriesConf(); err != nil { 854 return err 855 } 856 return nil 857 } 858 859 // reloadContainersConf reloads the containers.conf 860 func (r *Runtime) reloadContainersConf() error { 861 config, err := config.Reload() 862 if err != nil { 863 return err 864 } 865 r.config = config 866 logrus.Infof("applied new containers configuration: %v", config) 867 return nil 868 } 869 870 // reloadRegistries reloads the registries.conf 871 func reloadRegistriesConf() error { 872 sysregistriesv2.InvalidateCache() 873 registries, err := sysregistriesv2.GetRegistries(&types.SystemContext{SystemRegistriesConfPath: registries.SystemRegistriesConfPath()}) 874 if err != nil { 875 return err 876 } 877 logrus.Infof("applied new registry configuration: %+v", registries) 878 return nil 879 } 880 881 // reloadStorageConf reloads the storage.conf 882 func (r *Runtime) reloadStorageConf() error { 883 configFile, err := storage.DefaultConfigFile(rootless.IsRootless()) 884 if err != nil { 885 return err 886 } 887 storage.ReloadConfigurationFile(configFile, &r.storageConfig) 888 logrus.Infof("applied new storage configuration: %v", r.storageConfig) 889 return nil 890 }