github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/pkg/katautils/config.go (about) 1 // Copyright (c) 2018 Intel Corporation 2 // Copyright (c) 2018 HyperHQ Inc. 3 // 4 // SPDX-License-Identifier: Apache-2.0 5 // 6 7 package katautils 8 9 import ( 10 "errors" 11 "fmt" 12 "io/ioutil" 13 goruntime "runtime" 14 "strings" 15 16 "github.com/BurntSushi/toml" 17 govmmQemu "github.com/kata-containers/govmm/qemu" 18 vc "github.com/kata-containers/runtime/virtcontainers" 19 "github.com/kata-containers/runtime/virtcontainers/device/config" 20 exp "github.com/kata-containers/runtime/virtcontainers/experimental" 21 "github.com/kata-containers/runtime/virtcontainers/pkg/oci" 22 "github.com/kata-containers/runtime/virtcontainers/utils" 23 "github.com/sirupsen/logrus" 24 ) 25 26 const ( 27 defaultHypervisor = vc.QemuHypervisor 28 defaultAgent = vc.KataContainersAgent 29 ) 30 31 var ( 32 defaultProxy = vc.KataProxyType 33 defaultShim = vc.KataShimType 34 35 // if true, enable opentracing support. 36 tracing = false 37 ) 38 39 // The TOML configuration file contains a number of sections (or 40 // tables). The names of these tables are in dotted ("nested table") 41 // form: 42 // 43 // [<component>.<type>] 44 // 45 // The components are hypervisor, proxy, shim and agent. For example, 46 // 47 // [proxy.kata] 48 // 49 // The currently supported types are listed below: 50 const ( 51 // supported hypervisor component types 52 firecrackerHypervisorTableType = "firecracker" 53 clhHypervisorTableType = "clh" 54 qemuHypervisorTableType = "qemu" 55 acrnHypervisorTableType = "acrn" 56 57 // supported proxy component types 58 kataProxyTableType = "kata" 59 60 // supported shim component types 61 kataShimTableType = "kata" 62 63 // supported agent component types 64 kataAgentTableType = "kata" 65 66 // the maximum amount of PCI bridges that can be cold plugged in a VM 67 maxPCIBridges uint32 = 5 68 ) 69 70 type tomlConfig struct { 71 Hypervisor map[string]hypervisor 72 Proxy map[string]proxy 73 Shim map[string]shim 74 Agent map[string]agent 75 Runtime runtime 76 Factory factory 77 Netmon netmon 78 } 79 80 type factory struct { 81 Template bool `toml:"enable_template"` 82 TemplatePath string `toml:"template_path"` 83 VMCacheNumber uint `toml:"vm_cache_number"` 84 VMCacheEndpoint string `toml:"vm_cache_endpoint"` 85 } 86 87 type hypervisor struct { 88 Path string `toml:"path"` 89 HypervisorPathList []string `toml:"valid_hypervisor_paths"` 90 JailerPath string `toml:"jailer_path"` 91 JailerPathList []string `toml:"valid_jailer_paths"` 92 Kernel string `toml:"kernel"` 93 CtlPath string `toml:"ctlpath"` 94 CtlPathList []string `toml:"valid_ctlpaths"` 95 Initrd string `toml:"initrd"` 96 Image string `toml:"image"` 97 Firmware string `toml:"firmware"` 98 MachineAccelerators string `toml:"machine_accelerators"` 99 CPUFeatures string `toml:"cpu_features"` 100 KernelParams string `toml:"kernel_params"` 101 MachineType string `toml:"machine_type"` 102 BlockDeviceDriver string `toml:"block_device_driver"` 103 EntropySource string `toml:"entropy_source"` 104 SharedFS string `toml:"shared_fs"` 105 VirtioFSDaemon string `toml:"virtio_fs_daemon"` 106 VirtioFSDaemonList []string `toml:"valid_virtio_fs_daemon_paths"` 107 VirtioFSCache string `toml:"virtio_fs_cache"` 108 VirtioFSExtraArgs []string `toml:"virtio_fs_extra_args"` 109 PFlashList []string `toml:"pflashes"` 110 VirtioFSCacheSize uint32 `toml:"virtio_fs_cache_size"` 111 BlockDeviceCacheSet bool `toml:"block_device_cache_set"` 112 BlockDeviceCacheDirect bool `toml:"block_device_cache_direct"` 113 BlockDeviceCacheNoflush bool `toml:"block_device_cache_noflush"` 114 EnableVhostUserStore bool `toml:"enable_vhost_user_store"` 115 VhostUserStorePath string `toml:"vhost_user_store_path"` 116 VhostUserStorePathList []string `toml:"valid_vhost_user_store_paths"` 117 NumVCPUs int32 `toml:"default_vcpus"` 118 DefaultMaxVCPUs uint32 `toml:"default_maxvcpus"` 119 MemorySize uint32 `toml:"default_memory"` 120 MemSlots uint32 `toml:"memory_slots"` 121 MemOffset uint32 `toml:"memory_offset"` 122 DefaultBridges uint32 `toml:"default_bridges"` 123 Msize9p uint32 `toml:"msize_9p"` 124 PCIeRootPort uint32 `toml:"pcie_root_port"` 125 DisableBlockDeviceUse bool `toml:"disable_block_device_use"` 126 MemPrealloc bool `toml:"enable_mem_prealloc"` 127 HugePages bool `toml:"enable_hugepages"` 128 VirtioMem bool `toml:"enable_virtio_mem"` 129 IOMMU bool `toml:"enable_iommu"` 130 IOMMUPlatform bool `toml:"enable_iommu_platform"` 131 FileBackedMemRootDir string `toml:"file_mem_backend"` 132 FileBackedMemRootList []string `toml:"valid_file_mem_backends"` 133 Swap bool `toml:"enable_swap"` 134 Debug bool `toml:"enable_debug"` 135 DisableNestingChecks bool `toml:"disable_nesting_checks"` 136 EnableIOThreads bool `toml:"enable_iothreads"` 137 UseVSock bool `toml:"use_vsock"` 138 DisableImageNvdimm bool `toml:"disable_image_nvdimm"` 139 HotplugVFIOOnRootBus bool `toml:"hotplug_vfio_on_root_bus"` 140 DisableVhostNet bool `toml:"disable_vhost_net"` 141 GuestHookPath string `toml:"guest_hook_path"` 142 EnableAnnotations []string `toml:"enable_annotations"` 143 } 144 145 type proxy struct { 146 Path string `toml:"path"` 147 Debug bool `toml:"enable_debug"` 148 } 149 150 type runtime struct { 151 Debug bool `toml:"enable_debug"` 152 Tracing bool `toml:"enable_tracing"` 153 DisableNewNetNs bool `toml:"disable_new_netns"` 154 DisableGuestSeccomp bool `toml:"disable_guest_seccomp"` 155 SandboxCgroupOnly bool `toml:"sandbox_cgroup_only"` 156 EnableAgentPidNs bool `toml:"enable_agent_pidns"` 157 Experimental []string `toml:"experimental"` 158 InterNetworkModel string `toml:"internetworking_model"` 159 } 160 161 type shim struct { 162 Path string `toml:"path"` 163 Debug bool `toml:"enable_debug"` 164 Tracing bool `toml:"enable_tracing"` 165 } 166 167 type agent struct { 168 Debug bool `toml:"enable_debug"` 169 Tracing bool `toml:"enable_tracing"` 170 TraceMode string `toml:"trace_mode"` 171 TraceType string `toml:"trace_type"` 172 KernelModules []string `toml:"kernel_modules"` 173 } 174 175 type netmon struct { 176 Path string `toml:"path"` 177 Debug bool `toml:"enable_debug"` 178 Enable bool `toml:"enable_netmon"` 179 } 180 181 func (h hypervisor) path() (string, error) { 182 p := h.Path 183 184 if h.Path == "" { 185 p = defaultHypervisorPath 186 } 187 188 return ResolvePath(p) 189 } 190 191 func (h hypervisor) ctlpath() (string, error) { 192 p := h.CtlPath 193 194 if h.CtlPath == "" { 195 p = defaultHypervisorCtlPath 196 } 197 198 return ResolvePath(p) 199 } 200 201 func (h hypervisor) jailerPath() (string, error) { 202 p := h.JailerPath 203 204 if h.JailerPath == "" { 205 return "", nil 206 } 207 208 return ResolvePath(p) 209 } 210 211 func (h hypervisor) kernel() (string, error) { 212 p := h.Kernel 213 214 if p == "" { 215 p = defaultKernelPath 216 } 217 218 return ResolvePath(p) 219 } 220 221 func (h hypervisor) initrd() (string, error) { 222 p := h.Initrd 223 224 if p == "" { 225 return "", errors.New("initrd is not set") 226 } 227 228 return ResolvePath(p) 229 } 230 231 func (h hypervisor) image() (string, error) { 232 p := h.Image 233 234 if p == "" { 235 return "", errors.New("image is not set") 236 } 237 238 return ResolvePath(p) 239 } 240 241 func (h hypervisor) firmware() (string, error) { 242 p := h.Firmware 243 244 if p == "" { 245 if defaultFirmwarePath == "" { 246 return "", nil 247 } 248 p = defaultFirmwarePath 249 } 250 251 return ResolvePath(p) 252 } 253 254 func (h hypervisor) PFlash() ([]string, error) { 255 pflashes := h.PFlashList 256 257 if len(pflashes) == 0 { 258 return []string(nil), nil 259 } 260 261 for _, pflash := range pflashes { 262 _, err := ResolvePath(pflash) 263 if err != nil { 264 return []string{}, fmt.Errorf("pflash path doesn't exist: %s", pflash) 265 } 266 } 267 268 return pflashes, nil 269 } 270 271 func (h hypervisor) machineAccelerators() string { 272 var machineAccelerators string 273 for _, accelerator := range strings.Split(h.MachineAccelerators, ",") { 274 if accelerator != "" { 275 machineAccelerators += strings.TrimSpace(accelerator) + "," 276 } 277 } 278 279 machineAccelerators = strings.Trim(machineAccelerators, ",") 280 281 return machineAccelerators 282 } 283 284 func (h hypervisor) cpuFeatures() string { 285 var cpuFeatures string 286 for _, feature := range strings.Split(h.CPUFeatures, ",") { 287 if feature != "" { 288 cpuFeatures += strings.TrimSpace(feature) + "," 289 } 290 } 291 292 cpuFeatures = strings.Trim(cpuFeatures, ",") 293 294 return cpuFeatures 295 } 296 297 func (h hypervisor) kernelParams() string { 298 if h.KernelParams == "" { 299 return defaultKernelParams 300 } 301 302 return h.KernelParams 303 } 304 305 func (h hypervisor) machineType() string { 306 if h.MachineType == "" { 307 return defaultMachineType 308 } 309 310 return h.MachineType 311 } 312 313 func (h hypervisor) GetEntropySource() string { 314 if h.EntropySource == "" { 315 return defaultEntropySource 316 } 317 318 return h.EntropySource 319 } 320 321 func (h hypervisor) defaultVCPUs() uint32 { 322 numCPUs := goruntime.NumCPU() 323 324 if h.NumVCPUs < 0 || h.NumVCPUs > int32(numCPUs) { 325 return uint32(numCPUs) 326 } 327 if h.NumVCPUs == 0 { // or unspecified 328 return defaultVCPUCount 329 } 330 331 return uint32(h.NumVCPUs) 332 } 333 334 func (h hypervisor) defaultMaxVCPUs() uint32 { 335 numcpus := uint32(goruntime.NumCPU()) 336 maxvcpus := vc.MaxQemuVCPUs() 337 reqVCPUs := h.DefaultMaxVCPUs 338 339 //don't exceed the number of physical CPUs. If a default is not provided, use the 340 // numbers of physical CPUs 341 if reqVCPUs >= numcpus || reqVCPUs == 0 { 342 reqVCPUs = numcpus 343 } 344 345 // Don't exceed the maximum number of vCPUs supported by hypervisor 346 if reqVCPUs > maxvcpus { 347 return maxvcpus 348 } 349 350 return reqVCPUs 351 } 352 353 func (h hypervisor) defaultMemSz() uint32 { 354 if h.MemorySize > 0 { 355 return h.MemorySize 356 } 357 358 return defaultMemSize 359 } 360 361 func (h hypervisor) defaultMemSlots() uint32 { 362 slots := h.MemSlots 363 if slots == 0 { 364 slots = defaultMemSlots 365 } 366 367 return slots 368 } 369 370 func (h hypervisor) defaultMemOffset() uint32 { 371 offset := h.MemOffset 372 if offset == 0 { 373 offset = defaultMemOffset 374 } 375 376 return offset 377 } 378 379 func (h hypervisor) defaultBridges() uint32 { 380 if h.DefaultBridges == 0 { 381 return defaultBridgesCount 382 } 383 384 if h.DefaultBridges > maxPCIBridges { 385 return maxPCIBridges 386 } 387 388 return h.DefaultBridges 389 } 390 391 func (h hypervisor) defaultVirtioFSCache() string { 392 if h.VirtioFSCache == "" { 393 return defaultVirtioFSCacheMode 394 } 395 396 return h.VirtioFSCache 397 } 398 399 func (h hypervisor) blockDeviceDriver() (string, error) { 400 supportedBlockDrivers := []string{config.VirtioSCSI, config.VirtioBlock, config.VirtioMmio, config.Nvdimm, config.VirtioBlockCCW} 401 402 if h.BlockDeviceDriver == "" { 403 return defaultBlockDeviceDriver, nil 404 } 405 406 for _, b := range supportedBlockDrivers { 407 if b == h.BlockDeviceDriver { 408 return h.BlockDeviceDriver, nil 409 } 410 } 411 412 return "", fmt.Errorf("Invalid hypervisor block storage driver %v specified (supported drivers: %v)", h.BlockDeviceDriver, supportedBlockDrivers) 413 } 414 415 func (h hypervisor) sharedFS() (string, error) { 416 supportedSharedFS := []string{config.Virtio9P, config.VirtioFS} 417 418 if h.SharedFS == "" { 419 return config.Virtio9P, nil 420 } 421 422 for _, fs := range supportedSharedFS { 423 if fs == h.SharedFS { 424 return h.SharedFS, nil 425 } 426 } 427 428 return "", fmt.Errorf("Invalid hypervisor shared file system %v specified (supported file systems: %v)", h.SharedFS, supportedSharedFS) 429 } 430 431 func (h hypervisor) msize9p() uint32 { 432 if h.Msize9p == 0 { 433 return defaultMsize9p 434 } 435 436 return h.Msize9p 437 } 438 439 func (h hypervisor) useVSock() bool { 440 return h.UseVSock 441 } 442 443 func (h hypervisor) guestHookPath() string { 444 if h.GuestHookPath == "" { 445 return defaultGuestHookPath 446 } 447 return h.GuestHookPath 448 } 449 450 func (h hypervisor) vhostUserStorePath() string { 451 if h.VhostUserStorePath == "" { 452 return defaultVhostUserStorePath 453 } 454 return h.VhostUserStorePath 455 } 456 457 func (h hypervisor) getInitrdAndImage() (initrd string, image string, err error) { 458 initrd, errInitrd := h.initrd() 459 460 image, errImage := h.image() 461 462 if image != "" && initrd != "" { 463 return "", "", errors.New("having both an image and an initrd defined in the configuration file is not supported") 464 } 465 466 if errInitrd != nil && errImage != nil { 467 return "", "", fmt.Errorf("Either initrd or image must be set to a valid path (initrd: %v) (image: %v)", errInitrd, errImage) 468 } 469 470 return 471 } 472 473 func (h hypervisor) getIOMMUPlatform() bool { 474 if h.IOMMUPlatform { 475 kataUtilsLogger.Info("IOMMUPlatform is enabled by default.") 476 } else { 477 kataUtilsLogger.Info("IOMMUPlatform is disabled by default.") 478 } 479 return h.IOMMUPlatform 480 } 481 482 func (p proxy) path() (string, error) { 483 path := p.Path 484 if path == "" { 485 path = defaultProxyPath 486 } 487 488 return ResolvePath(path) 489 } 490 491 func (p proxy) debug() bool { 492 return p.Debug 493 } 494 495 func (s shim) path() (string, error) { 496 p := s.Path 497 498 if p == "" { 499 p = defaultShimPath 500 } 501 502 return ResolvePath(p) 503 } 504 505 func (s shim) debug() bool { 506 return s.Debug 507 } 508 509 func (s shim) trace() bool { 510 return s.Tracing 511 } 512 513 func (a agent) debug() bool { 514 return a.Debug 515 } 516 517 func (a agent) trace() bool { 518 return a.Tracing 519 } 520 521 func (a agent) traceMode() string { 522 return a.TraceMode 523 } 524 525 func (a agent) traceType() string { 526 return a.TraceType 527 } 528 529 func (a agent) kernelModules() []string { 530 return a.KernelModules 531 } 532 533 func (n netmon) enable() bool { 534 return n.Enable 535 } 536 537 func (n netmon) path() string { 538 if n.Path == "" { 539 return defaultNetmonPath 540 } 541 542 return n.Path 543 } 544 545 func (n netmon) debug() bool { 546 return n.Debug 547 } 548 549 func newFirecrackerHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { 550 hypervisor, err := h.path() 551 if err != nil { 552 return vc.HypervisorConfig{}, err 553 } 554 555 jailer, err := h.jailerPath() 556 if err != nil { 557 return vc.HypervisorConfig{}, err 558 } 559 560 kernel, err := h.kernel() 561 if err != nil { 562 return vc.HypervisorConfig{}, err 563 } 564 565 initrd, image, err := h.getInitrdAndImage() 566 if err != nil { 567 return vc.HypervisorConfig{}, err 568 } 569 570 firmware, err := h.firmware() 571 if err != nil { 572 return vc.HypervisorConfig{}, err 573 } 574 575 kernelParams := h.kernelParams() 576 577 blockDriver, err := h.blockDeviceDriver() 578 if err != nil { 579 return vc.HypervisorConfig{}, err 580 } 581 582 if !utils.SupportsVsocks() { 583 return vc.HypervisorConfig{}, errors.New("No vsock support, firecracker cannot be used") 584 } 585 586 return vc.HypervisorConfig{ 587 HypervisorPath: hypervisor, 588 HypervisorPathList: h.HypervisorPathList, 589 JailerPath: jailer, 590 JailerPathList: h.JailerPathList, 591 KernelPath: kernel, 592 InitrdPath: initrd, 593 ImagePath: image, 594 FirmwarePath: firmware, 595 KernelParams: vc.DeserializeParams(strings.Fields(kernelParams)), 596 NumVCPUs: h.defaultVCPUs(), 597 DefaultMaxVCPUs: h.defaultMaxVCPUs(), 598 MemorySize: h.defaultMemSz(), 599 MemSlots: h.defaultMemSlots(), 600 EntropySource: h.GetEntropySource(), 601 DefaultBridges: h.defaultBridges(), 602 DisableBlockDeviceUse: h.DisableBlockDeviceUse, 603 HugePages: h.HugePages, 604 Mlock: !h.Swap, 605 Debug: h.Debug, 606 DisableNestingChecks: h.DisableNestingChecks, 607 BlockDeviceDriver: blockDriver, 608 EnableIOThreads: h.EnableIOThreads, 609 DisableVhostNet: true, // vhost-net backend is not supported in Firecracker 610 UseVSock: true, 611 GuestHookPath: h.guestHookPath(), 612 EnableAnnotations: h.EnableAnnotations, 613 }, nil 614 } 615 616 func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { 617 hypervisor, err := h.path() 618 if err != nil { 619 return vc.HypervisorConfig{}, err 620 } 621 622 kernel, err := h.kernel() 623 if err != nil { 624 return vc.HypervisorConfig{}, err 625 } 626 627 initrd, image, err := h.getInitrdAndImage() 628 if err != nil { 629 return vc.HypervisorConfig{}, err 630 } 631 632 if image != "" && initrd != "" { 633 return vc.HypervisorConfig{}, 634 errors.New("having both an image and an initrd defined in the configuration file is not supported") 635 } 636 637 if image == "" && initrd == "" { 638 return vc.HypervisorConfig{}, 639 errors.New("either image or initrd must be defined in the configuration file") 640 } 641 642 firmware, err := h.firmware() 643 if err != nil { 644 return vc.HypervisorConfig{}, err 645 } 646 647 pflashes, err := h.PFlash() 648 if err != nil { 649 return vc.HypervisorConfig{}, err 650 } 651 652 machineAccelerators := h.machineAccelerators() 653 cpuFeatures := h.cpuFeatures() 654 kernelParams := h.kernelParams() 655 machineType := h.machineType() 656 657 // The "microvm" machine type doesn't support NVDIMM so override the 658 // config setting to explicitly disable it (i.e. don't require the 659 // user to add 'disable_image_nvdimm = true' in the .toml file). 660 if machineType == govmmQemu.MachineTypeMicrovm && !h.DisableImageNvdimm { 661 h.DisableImageNvdimm = true 662 kataUtilsLogger.Info("Setting 'disable_image_nvdimm = true' as microvm does not support NVDIMM") 663 } 664 665 blockDriver, err := h.blockDeviceDriver() 666 if err != nil { 667 return vc.HypervisorConfig{}, err 668 } 669 670 sharedFS, err := h.sharedFS() 671 if err != nil { 672 return vc.HypervisorConfig{}, err 673 } 674 675 if sharedFS == config.VirtioFS && h.VirtioFSDaemon == "" { 676 return vc.HypervisorConfig{}, 677 errors.New("cannot enable virtio-fs without daemon path in configuration file") 678 } 679 680 useVSock := false 681 if h.useVSock() { 682 if utils.SupportsVsocks() { 683 kataUtilsLogger.Info("vsock supported") 684 useVSock = true 685 } else { 686 kataUtilsLogger.Warn("No vsock support, falling back to legacy serial port") 687 } 688 } 689 690 return vc.HypervisorConfig{ 691 HypervisorPath: hypervisor, 692 HypervisorPathList: h.HypervisorPathList, 693 KernelPath: kernel, 694 InitrdPath: initrd, 695 ImagePath: image, 696 FirmwarePath: firmware, 697 MachineAccelerators: machineAccelerators, 698 CPUFeatures: cpuFeatures, 699 KernelParams: vc.DeserializeParams(strings.Fields(kernelParams)), 700 HypervisorMachineType: machineType, 701 NumVCPUs: h.defaultVCPUs(), 702 DefaultMaxVCPUs: h.defaultMaxVCPUs(), 703 MemorySize: h.defaultMemSz(), 704 MemSlots: h.defaultMemSlots(), 705 MemOffset: h.defaultMemOffset(), 706 VirtioMem: h.VirtioMem, 707 EntropySource: h.GetEntropySource(), 708 DefaultBridges: h.defaultBridges(), 709 DisableBlockDeviceUse: h.DisableBlockDeviceUse, 710 SharedFS: sharedFS, 711 VirtioFSDaemon: h.VirtioFSDaemon, 712 VirtioFSDaemonList: h.VirtioFSDaemonList, 713 VirtioFSCacheSize: h.VirtioFSCacheSize, 714 VirtioFSCache: h.defaultVirtioFSCache(), 715 VirtioFSExtraArgs: h.VirtioFSExtraArgs, 716 PFlash: pflashes, 717 MemPrealloc: h.MemPrealloc, 718 HugePages: h.HugePages, 719 IOMMU: h.IOMMU, 720 IOMMUPlatform: h.getIOMMUPlatform(), 721 FileBackedMemRootDir: h.FileBackedMemRootDir, 722 FileBackedMemRootList: h.FileBackedMemRootList, 723 Mlock: !h.Swap, 724 Debug: h.Debug, 725 DisableNestingChecks: h.DisableNestingChecks, 726 BlockDeviceDriver: blockDriver, 727 BlockDeviceCacheSet: h.BlockDeviceCacheSet, 728 BlockDeviceCacheDirect: h.BlockDeviceCacheDirect, 729 BlockDeviceCacheNoflush: h.BlockDeviceCacheNoflush, 730 EnableIOThreads: h.EnableIOThreads, 731 Msize9p: h.msize9p(), 732 UseVSock: useVSock, 733 DisableImageNvdimm: h.DisableImageNvdimm, 734 HotplugVFIOOnRootBus: h.HotplugVFIOOnRootBus, 735 PCIeRootPort: h.PCIeRootPort, 736 DisableVhostNet: h.DisableVhostNet, 737 EnableVhostUserStore: h.EnableVhostUserStore, 738 VhostUserStorePath: h.vhostUserStorePath(), 739 VhostUserStorePathList: h.VhostUserStorePathList, 740 GuestHookPath: h.guestHookPath(), 741 EnableAnnotations: h.EnableAnnotations, 742 }, nil 743 } 744 745 func newAcrnHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { 746 hypervisor, err := h.path() 747 if err != nil { 748 return vc.HypervisorConfig{}, err 749 } 750 751 hypervisorctl, err := h.ctlpath() 752 if err != nil { 753 return vc.HypervisorConfig{}, err 754 } 755 756 kernel, err := h.kernel() 757 if err != nil { 758 return vc.HypervisorConfig{}, err 759 } 760 761 image, err := h.image() 762 if err != nil { 763 return vc.HypervisorConfig{}, err 764 } 765 766 if image == "" { 767 return vc.HypervisorConfig{}, 768 errors.New("image must be defined in the configuration file") 769 } 770 771 firmware, err := h.firmware() 772 if err != nil { 773 return vc.HypervisorConfig{}, err 774 } 775 776 kernelParams := h.kernelParams() 777 778 blockDriver, err := h.blockDeviceDriver() 779 if err != nil { 780 return vc.HypervisorConfig{}, err 781 } 782 783 return vc.HypervisorConfig{ 784 HypervisorPath: hypervisor, 785 HypervisorPathList: h.HypervisorPathList, 786 KernelPath: kernel, 787 ImagePath: image, 788 HypervisorCtlPath: hypervisorctl, 789 HypervisorCtlPathList: h.CtlPathList, 790 FirmwarePath: firmware, 791 KernelParams: vc.DeserializeParams(strings.Fields(kernelParams)), 792 NumVCPUs: h.defaultVCPUs(), 793 DefaultMaxVCPUs: h.defaultMaxVCPUs(), 794 MemorySize: h.defaultMemSz(), 795 MemSlots: h.defaultMemSlots(), 796 EntropySource: h.GetEntropySource(), 797 DefaultBridges: h.defaultBridges(), 798 HugePages: h.HugePages, 799 Mlock: !h.Swap, 800 Debug: h.Debug, 801 DisableNestingChecks: h.DisableNestingChecks, 802 BlockDeviceDriver: blockDriver, 803 DisableVhostNet: h.DisableVhostNet, 804 GuestHookPath: h.guestHookPath(), 805 EnableAnnotations: h.EnableAnnotations, 806 }, nil 807 } 808 809 func newClhHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { 810 hypervisor, err := h.path() 811 if err != nil { 812 return vc.HypervisorConfig{}, err 813 } 814 815 kernel, err := h.kernel() 816 if err != nil { 817 return vc.HypervisorConfig{}, err 818 } 819 820 initrd, image, err := h.getInitrdAndImage() 821 if err != nil { 822 return vc.HypervisorConfig{}, err 823 } 824 825 if initrd != "" { 826 return vc.HypervisorConfig{}, 827 errors.New("having an initrd defined in the configuration file is not supported") 828 } 829 830 if image == "" { 831 return vc.HypervisorConfig{}, 832 errors.New("image must be defined in the configuration file") 833 } 834 835 firmware, err := h.firmware() 836 if err != nil { 837 return vc.HypervisorConfig{}, err 838 } 839 840 machineAccelerators := h.machineAccelerators() 841 kernelParams := h.kernelParams() 842 machineType := h.machineType() 843 844 blockDriver, err := h.blockDeviceDriver() 845 if err != nil { 846 return vc.HypervisorConfig{}, err 847 } 848 849 sharedFS := config.VirtioFS 850 851 if h.VirtioFSDaemon == "" { 852 return vc.HypervisorConfig{}, 853 errors.New("virtio-fs daemon path is missing in configuration file") 854 } 855 856 return vc.HypervisorConfig{ 857 HypervisorPath: hypervisor, 858 HypervisorPathList: h.HypervisorPathList, 859 KernelPath: kernel, 860 InitrdPath: initrd, 861 ImagePath: image, 862 FirmwarePath: firmware, 863 MachineAccelerators: machineAccelerators, 864 KernelParams: vc.DeserializeParams(strings.Fields(kernelParams)), 865 HypervisorMachineType: machineType, 866 NumVCPUs: h.defaultVCPUs(), 867 DefaultMaxVCPUs: h.defaultMaxVCPUs(), 868 MemorySize: h.defaultMemSz(), 869 MemSlots: h.defaultMemSlots(), 870 MemOffset: h.defaultMemOffset(), 871 VirtioMem: h.VirtioMem, 872 EntropySource: h.GetEntropySource(), 873 DefaultBridges: h.defaultBridges(), 874 DisableBlockDeviceUse: h.DisableBlockDeviceUse, 875 SharedFS: sharedFS, 876 VirtioFSDaemon: h.VirtioFSDaemon, 877 VirtioFSDaemonList: h.VirtioFSDaemonList, 878 VirtioFSCacheSize: h.VirtioFSCacheSize, 879 VirtioFSCache: h.VirtioFSCache, 880 MemPrealloc: h.MemPrealloc, 881 HugePages: h.HugePages, 882 FileBackedMemRootDir: h.FileBackedMemRootDir, 883 FileBackedMemRootList: h.FileBackedMemRootList, 884 Mlock: !h.Swap, 885 Debug: h.Debug, 886 DisableNestingChecks: h.DisableNestingChecks, 887 BlockDeviceDriver: blockDriver, 888 BlockDeviceCacheSet: h.BlockDeviceCacheSet, 889 BlockDeviceCacheDirect: h.BlockDeviceCacheDirect, 890 BlockDeviceCacheNoflush: h.BlockDeviceCacheNoflush, 891 EnableIOThreads: h.EnableIOThreads, 892 Msize9p: h.msize9p(), 893 HotplugVFIOOnRootBus: h.HotplugVFIOOnRootBus, 894 PCIeRootPort: h.PCIeRootPort, 895 DisableVhostNet: true, 896 UseVSock: true, 897 VirtioFSExtraArgs: h.VirtioFSExtraArgs, 898 EnableAnnotations: h.EnableAnnotations, 899 }, nil 900 } 901 902 func newFactoryConfig(f factory) (oci.FactoryConfig, error) { 903 if f.TemplatePath == "" { 904 f.TemplatePath = defaultTemplatePath 905 } 906 if f.VMCacheEndpoint == "" { 907 f.VMCacheEndpoint = defaultVMCacheEndpoint 908 } 909 return oci.FactoryConfig{ 910 Template: f.Template, 911 TemplatePath: f.TemplatePath, 912 VMCacheNumber: f.VMCacheNumber, 913 VMCacheEndpoint: f.VMCacheEndpoint, 914 }, nil 915 } 916 917 func newShimConfig(s shim) (vc.ShimConfig, error) { 918 path, err := s.path() 919 if err != nil { 920 return vc.ShimConfig{}, err 921 } 922 923 return vc.ShimConfig{ 924 Path: path, 925 Debug: s.debug(), 926 Trace: s.trace(), 927 }, nil 928 } 929 930 func updateRuntimeConfigHypervisor(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig) error { 931 for k, hypervisor := range tomlConf.Hypervisor { 932 var err error 933 var hConfig vc.HypervisorConfig 934 935 switch k { 936 case firecrackerHypervisorTableType: 937 config.HypervisorType = vc.FirecrackerHypervisor 938 hConfig, err = newFirecrackerHypervisorConfig(hypervisor) 939 case qemuHypervisorTableType: 940 config.HypervisorType = vc.QemuHypervisor 941 hConfig, err = newQemuHypervisorConfig(hypervisor) 942 case acrnHypervisorTableType: 943 config.HypervisorType = vc.AcrnHypervisor 944 hConfig, err = newAcrnHypervisorConfig(hypervisor) 945 case clhHypervisorTableType: 946 config.HypervisorType = vc.ClhHypervisor 947 hConfig, err = newClhHypervisorConfig(hypervisor) 948 } 949 950 if err != nil { 951 return fmt.Errorf("%v: %v", configPath, err) 952 } 953 954 config.HypervisorConfig = hConfig 955 } 956 957 return nil 958 } 959 960 func updateRuntimeConfigProxy(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig, builtIn bool) error { 961 if builtIn { 962 config.ProxyType = vc.KataBuiltInProxyType 963 config.ProxyConfig = vc.ProxyConfig{ 964 Debug: config.Debug, 965 } 966 return nil 967 } 968 969 for k, proxy := range tomlConf.Proxy { 970 switch k { 971 case kataProxyTableType: 972 config.ProxyType = vc.KataProxyType 973 default: 974 return fmt.Errorf("%s proxy type not supported", k) 975 } 976 977 path, err := proxy.path() 978 if err != nil { 979 return err 980 } 981 982 config.ProxyConfig = vc.ProxyConfig{ 983 Path: path, 984 Debug: proxy.debug(), 985 } 986 } 987 988 return nil 989 } 990 991 func updateRuntimeConfigAgent(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig, builtIn bool) error { 992 if builtIn { 993 var agentConfig vc.KataAgentConfig 994 995 // If the agent config section isn't a Kata one, just default 996 // to everything being disabled. 997 agentConfig, _ = config.AgentConfig.(vc.KataAgentConfig) 998 999 config.AgentType = vc.KataContainersAgent 1000 config.AgentConfig = vc.KataAgentConfig{ 1001 LongLiveConn: true, 1002 UseVSock: config.HypervisorConfig.UseVSock, 1003 Debug: agentConfig.Debug, 1004 KernelModules: agentConfig.KernelModules, 1005 } 1006 1007 return nil 1008 } 1009 1010 for k, agent := range tomlConf.Agent { 1011 switch k { 1012 case kataAgentTableType: 1013 config.AgentType = vc.KataContainersAgent 1014 config.AgentConfig = vc.KataAgentConfig{ 1015 UseVSock: config.HypervisorConfig.UseVSock, 1016 Debug: agent.debug(), 1017 Trace: agent.trace(), 1018 TraceMode: agent.traceMode(), 1019 TraceType: agent.traceType(), 1020 KernelModules: agent.kernelModules(), 1021 } 1022 default: 1023 return fmt.Errorf("%s agent type is not supported", k) 1024 } 1025 } 1026 1027 return nil 1028 } 1029 1030 func updateRuntimeConfigShim(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig, builtIn bool) error { 1031 if builtIn { 1032 config.ShimType = vc.KataBuiltInShimType 1033 config.ShimConfig = vc.ShimConfig{} 1034 return nil 1035 } 1036 1037 for k, shim := range tomlConf.Shim { 1038 switch k { 1039 case kataShimTableType: 1040 config.ShimType = vc.KataShimType 1041 default: 1042 return fmt.Errorf("%s shim is not supported", k) 1043 } 1044 1045 shConfig, err := newShimConfig(shim) 1046 if err != nil { 1047 return fmt.Errorf("%v: %v", configPath, err) 1048 } 1049 1050 config.ShimConfig = shConfig 1051 } 1052 1053 return nil 1054 } 1055 1056 // SetKernelParams adds the user-specified kernel parameters (from the 1057 // configuration file) to the defaults so that the former take priority. 1058 func SetKernelParams(runtimeConfig *oci.RuntimeConfig) error { 1059 defaultKernelParams := GetKernelParamsFunc(needSystemd(runtimeConfig.HypervisorConfig), runtimeConfig.Trace) 1060 1061 if runtimeConfig.HypervisorConfig.Debug { 1062 strParams := vc.SerializeParams(defaultKernelParams, "=") 1063 formatted := strings.Join(strParams, " ") 1064 kataUtilsLogger.WithField("default-kernel-parameters", formatted).Debug() 1065 } 1066 1067 // retrieve the parameters specified in the config file 1068 userKernelParams := runtimeConfig.HypervisorConfig.KernelParams 1069 1070 // reset 1071 runtimeConfig.HypervisorConfig.KernelParams = []vc.Param{} 1072 1073 // first, add default values 1074 for _, p := range defaultKernelParams { 1075 if err := runtimeConfig.AddKernelParam(p); err != nil { 1076 return err 1077 } 1078 } 1079 1080 // set the scsi scan mode to none for virtio-scsi 1081 if runtimeConfig.HypervisorConfig.BlockDeviceDriver == config.VirtioSCSI { 1082 p := vc.Param{ 1083 Key: "scsi_mod.scan", 1084 Value: "none", 1085 } 1086 if err := runtimeConfig.AddKernelParam(p); err != nil { 1087 return err 1088 } 1089 } 1090 1091 // next, check for agent specific kernel params 1092 if agentConfig, ok := runtimeConfig.AgentConfig.(vc.KataAgentConfig); ok { 1093 err := vc.KataAgentSetDefaultTraceConfigOptions(&agentConfig) 1094 if err != nil { 1095 return err 1096 } 1097 1098 params := vc.KataAgentKernelParams(agentConfig) 1099 1100 for _, p := range params { 1101 if err := runtimeConfig.AddKernelParam(p); err != nil { 1102 return err 1103 } 1104 } 1105 } 1106 1107 // now re-add the user-specified values so that they take priority. 1108 for _, p := range userKernelParams { 1109 if err := runtimeConfig.AddKernelParam(p); err != nil { 1110 return err 1111 } 1112 } 1113 1114 return nil 1115 } 1116 1117 func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig, builtIn bool) error { 1118 if err := updateRuntimeConfigHypervisor(configPath, tomlConf, config); err != nil { 1119 return err 1120 } 1121 1122 if err := updateRuntimeConfigProxy(configPath, tomlConf, config, builtIn); err != nil { 1123 return err 1124 } 1125 1126 if err := updateRuntimeConfigAgent(configPath, tomlConf, config, builtIn); err != nil { 1127 return err 1128 } 1129 1130 if err := updateRuntimeConfigShim(configPath, tomlConf, config, builtIn); err != nil { 1131 return err 1132 } 1133 1134 fConfig, err := newFactoryConfig(tomlConf.Factory) 1135 if err != nil { 1136 return fmt.Errorf("%v: %v", configPath, err) 1137 } 1138 config.FactoryConfig = fConfig 1139 1140 config.NetmonConfig = vc.NetmonConfig{ 1141 Path: tomlConf.Netmon.path(), 1142 Debug: tomlConf.Netmon.debug(), 1143 Enable: tomlConf.Netmon.enable(), 1144 } 1145 1146 err = SetKernelParams(config) 1147 if err != nil { 1148 return err 1149 } 1150 1151 return nil 1152 } 1153 1154 func GetDefaultHypervisorConfig() vc.HypervisorConfig { 1155 return vc.HypervisorConfig{ 1156 HypervisorPath: defaultHypervisorPath, 1157 JailerPath: defaultJailerPath, 1158 KernelPath: defaultKernelPath, 1159 ImagePath: defaultImagePath, 1160 InitrdPath: defaultInitrdPath, 1161 FirmwarePath: defaultFirmwarePath, 1162 MachineAccelerators: defaultMachineAccelerators, 1163 CPUFeatures: defaultCPUFeatures, 1164 HypervisorMachineType: defaultMachineType, 1165 NumVCPUs: defaultVCPUCount, 1166 DefaultMaxVCPUs: defaultMaxVCPUCount, 1167 MemorySize: defaultMemSize, 1168 MemOffset: defaultMemOffset, 1169 VirtioMem: defaultVirtioMem, 1170 DisableBlockDeviceUse: defaultDisableBlockDeviceUse, 1171 DefaultBridges: defaultBridgesCount, 1172 MemPrealloc: defaultEnableMemPrealloc, 1173 HugePages: defaultEnableHugePages, 1174 IOMMU: defaultEnableIOMMU, 1175 IOMMUPlatform: defaultEnableIOMMUPlatform, 1176 FileBackedMemRootDir: defaultFileBackedMemRootDir, 1177 Mlock: !defaultEnableSwap, 1178 Debug: defaultEnableDebug, 1179 DisableNestingChecks: defaultDisableNestingChecks, 1180 BlockDeviceDriver: defaultBlockDeviceDriver, 1181 BlockDeviceCacheSet: defaultBlockDeviceCacheSet, 1182 BlockDeviceCacheDirect: defaultBlockDeviceCacheDirect, 1183 BlockDeviceCacheNoflush: defaultBlockDeviceCacheNoflush, 1184 EnableIOThreads: defaultEnableIOThreads, 1185 Msize9p: defaultMsize9p, 1186 HotplugVFIOOnRootBus: defaultHotplugVFIOOnRootBus, 1187 PCIeRootPort: defaultPCIeRootPort, 1188 GuestHookPath: defaultGuestHookPath, 1189 VhostUserStorePath: defaultVhostUserStorePath, 1190 VirtioFSCache: defaultVirtioFSCacheMode, 1191 DisableImageNvdimm: defaultDisableImageNvdimm, 1192 } 1193 } 1194 1195 func initConfig() (config oci.RuntimeConfig, err error) { 1196 var defaultAgentConfig interface{} 1197 1198 err = config.InterNetworkModel.SetModel(defaultInterNetworkingModel) 1199 if err != nil { 1200 return oci.RuntimeConfig{}, err 1201 } 1202 1203 defaultAgentConfig = vc.KataAgentConfig{} 1204 1205 config = oci.RuntimeConfig{ 1206 HypervisorType: defaultHypervisor, 1207 HypervisorConfig: GetDefaultHypervisorConfig(), 1208 AgentType: defaultAgent, 1209 AgentConfig: defaultAgentConfig, 1210 ProxyType: defaultProxy, 1211 ShimType: defaultShim, 1212 } 1213 1214 return config, nil 1215 } 1216 1217 // LoadConfiguration loads the configuration file and converts it into a 1218 // runtime configuration. 1219 // 1220 // If ignoreLogging is true, the system logger will not be initialised nor 1221 // will this function make any log calls. 1222 // 1223 // All paths are resolved fully meaning if this function does not return an 1224 // error, all paths are valid at the time of the call. 1225 func LoadConfiguration(configPath string, ignoreLogging, builtIn bool) (resolvedConfigPath string, config oci.RuntimeConfig, err error) { 1226 1227 config, err = initConfig() 1228 if err != nil { 1229 return "", oci.RuntimeConfig{}, err 1230 } 1231 1232 tomlConf, resolved, err := decodeConfig(configPath) 1233 if err != nil { 1234 return "", oci.RuntimeConfig{}, err 1235 } 1236 1237 config.Debug = tomlConf.Runtime.Debug 1238 if !tomlConf.Runtime.Debug { 1239 // If debug is not required, switch back to the original 1240 // default log priority, otherwise continue in debug mode. 1241 kataUtilsLogger.Logger.Level = originalLoggerLevel 1242 } 1243 1244 config.Trace = tomlConf.Runtime.Tracing 1245 tracing = config.Trace 1246 1247 if tomlConf.Runtime.InterNetworkModel != "" { 1248 err = config.InterNetworkModel.SetModel(tomlConf.Runtime.InterNetworkModel) 1249 if err != nil { 1250 return "", config, err 1251 } 1252 } 1253 1254 if !ignoreLogging { 1255 err := handleSystemLog("", "") 1256 if err != nil { 1257 return "", config, err 1258 } 1259 1260 kataUtilsLogger.WithFields( 1261 logrus.Fields{ 1262 "format": "TOML", 1263 "file": resolved, 1264 }).Info("loaded configuration") 1265 } 1266 1267 if err := updateRuntimeConfig(resolved, tomlConf, &config, builtIn); err != nil { 1268 return "", config, err 1269 } 1270 1271 config.DisableGuestSeccomp = tomlConf.Runtime.DisableGuestSeccomp 1272 1273 // use no proxy if HypervisorConfig.UseVSock is true 1274 if config.HypervisorConfig.UseVSock { 1275 kataUtilsLogger.Info("VSOCK supported, configure to not use proxy") 1276 config.ProxyType = vc.NoProxyType 1277 config.ProxyConfig = vc.ProxyConfig{Debug: config.Debug} 1278 } 1279 1280 config.SandboxCgroupOnly = tomlConf.Runtime.SandboxCgroupOnly 1281 config.DisableNewNetNs = tomlConf.Runtime.DisableNewNetNs 1282 config.EnableAgentPidNs = tomlConf.Runtime.EnableAgentPidNs 1283 if config.EnableAgentPidNs { 1284 kataUtilsLogger.Warn("Feature to allow containers to share PID namespace with the agent has been enabled. Please understand this has security implications and should only be used for debug purposes") 1285 } 1286 1287 for _, f := range tomlConf.Runtime.Experimental { 1288 feature := exp.Get(f) 1289 if feature == nil { 1290 return "", config, fmt.Errorf("Unsupported experimental feature %q", f) 1291 } 1292 config.Experimental = append(config.Experimental, *feature) 1293 } 1294 1295 if err := checkConfig(config); err != nil { 1296 return "", config, err 1297 } 1298 1299 return resolved, config, nil 1300 } 1301 1302 func decodeConfig(configPath string) (tomlConfig, string, error) { 1303 var ( 1304 resolved string 1305 tomlConf tomlConfig 1306 err error 1307 ) 1308 1309 if configPath == "" { 1310 resolved, err = getDefaultConfigFile() 1311 } else { 1312 resolved, err = ResolvePath(configPath) 1313 } 1314 1315 if err != nil { 1316 return tomlConf, "", fmt.Errorf("Cannot find usable config file (%v)", err) 1317 } 1318 1319 configData, err := ioutil.ReadFile(resolved) 1320 if err != nil { 1321 return tomlConf, resolved, err 1322 } 1323 1324 _, err = toml.Decode(string(configData), &tomlConf) 1325 if err != nil { 1326 return tomlConf, resolved, err 1327 } 1328 1329 return tomlConf, resolved, nil 1330 } 1331 1332 // checkConfig checks the validity of the specified config. 1333 func checkConfig(config oci.RuntimeConfig) error { 1334 if err := checkNetNsConfig(config); err != nil { 1335 return err 1336 } 1337 1338 if err := checkHypervisorConfig(config.HypervisorConfig); err != nil { 1339 return err 1340 } 1341 1342 if err := checkFactoryConfig(config); err != nil { 1343 return err 1344 } 1345 1346 return nil 1347 } 1348 1349 // checkNetNsConfig performs sanity checks on disable_new_netns config. 1350 // Because it is an expert option and conflicts with some other common configs. 1351 func checkNetNsConfig(config oci.RuntimeConfig) error { 1352 if config.DisableNewNetNs { 1353 if config.NetmonConfig.Enable { 1354 return fmt.Errorf("config disable_new_netns conflicts with enable_netmon") 1355 } 1356 if config.InterNetworkModel != vc.NetXConnectNoneModel { 1357 return fmt.Errorf("config disable_new_netns only works with 'none' internetworking_model") 1358 } 1359 } else if shim, ok := config.ShimConfig.(vc.ShimConfig); ok && shim.Trace { 1360 // Normally, the shim runs in a separate network namespace. 1361 // But when tracing, the shim process needs to be able to talk 1362 // to the Jaeger agent running in the host network namespace. 1363 return errors.New("Shim tracing requires disable_new_netns for Jaeger agent communication") 1364 } 1365 1366 return nil 1367 } 1368 1369 // checkFactoryConfig ensures the VM factory configuration is valid. 1370 func checkFactoryConfig(config oci.RuntimeConfig) error { 1371 if config.FactoryConfig.Template { 1372 if config.HypervisorConfig.InitrdPath == "" { 1373 return errors.New("Factory option enable_template requires an initrd image") 1374 } 1375 } 1376 1377 if config.FactoryConfig.VMCacheNumber > 0 { 1378 if config.HypervisorType != vc.QemuHypervisor { 1379 return errors.New("VM cache just support qemu") 1380 } 1381 if config.AgentType != vc.KataContainersAgent { 1382 return errors.New("VM cache just support kata agent") 1383 } 1384 } 1385 1386 return nil 1387 } 1388 1389 // checkHypervisorConfig performs basic "sanity checks" on the hypervisor 1390 // config. 1391 func checkHypervisorConfig(config vc.HypervisorConfig) error { 1392 type image struct { 1393 path string 1394 initrd bool 1395 } 1396 1397 images := []image{ 1398 { 1399 path: config.ImagePath, 1400 initrd: false, 1401 }, 1402 { 1403 path: config.InitrdPath, 1404 initrd: true, 1405 }, 1406 } 1407 1408 memSizeMB := int64(config.MemorySize) 1409 1410 if memSizeMB == 0 { 1411 return errors.New("VM memory cannot be zero") 1412 } 1413 1414 mb := int64(1024 * 1024) 1415 1416 for _, image := range images { 1417 if image.path == "" { 1418 continue 1419 } 1420 1421 imageSizeBytes, err := fileSize(image.path) 1422 if err != nil { 1423 return err 1424 } 1425 1426 if imageSizeBytes == 0 { 1427 return fmt.Errorf("image %q is empty", image.path) 1428 } 1429 1430 if imageSizeBytes > mb { 1431 imageSizeMB := imageSizeBytes / mb 1432 1433 msg := fmt.Sprintf("VM memory (%dMB) smaller than image %q size (%dMB)", 1434 memSizeMB, image.path, imageSizeMB) 1435 if imageSizeMB >= memSizeMB { 1436 if image.initrd { 1437 // Initrd's need to be fully read into memory 1438 return errors.New(msg) 1439 } 1440 1441 // Images do not need to be fully read 1442 // into memory, but it would be highly 1443 // unusual to have an image larger 1444 // than the amount of memory assigned 1445 // to the VM. 1446 kataUtilsLogger.Warn(msg) 1447 } 1448 } 1449 } 1450 1451 return nil 1452 } 1453 1454 // GetDefaultConfigFilePaths returns a list of paths that will be 1455 // considered as configuration files in priority order. 1456 func GetDefaultConfigFilePaths() []string { 1457 return []string{ 1458 // normally below "/etc" 1459 defaultSysConfRuntimeConfiguration, 1460 1461 // normally below "/usr/share" 1462 defaultRuntimeConfiguration, 1463 } 1464 } 1465 1466 // getDefaultConfigFile looks in multiple default locations for a 1467 // configuration file and returns the resolved path for the first file 1468 // found, or an error if no config files can be found. 1469 func getDefaultConfigFile() (string, error) { 1470 var errs []string 1471 1472 for _, file := range GetDefaultConfigFilePaths() { 1473 resolved, err := ResolvePath(file) 1474 if err == nil { 1475 return resolved, nil 1476 } 1477 s := fmt.Sprintf("config file %q unresolvable: %v", file, err) 1478 errs = append(errs, s) 1479 } 1480 1481 return "", errors.New(strings.Join(errs, ", ")) 1482 } 1483 1484 // SetConfigOptions will override some of the defaults settings. 1485 func SetConfigOptions(n, runtimeConfig, sysRuntimeConfig string) { 1486 if n != "" { 1487 name = n 1488 } 1489 1490 if runtimeConfig != "" { 1491 defaultRuntimeConfiguration = runtimeConfig 1492 } 1493 1494 if sysRuntimeConfig != "" { 1495 defaultSysConfRuntimeConfiguration = sysRuntimeConfig 1496 } 1497 }