apiVersion: v1
kind: ConfigMap
metadata:
  namespace: ${ cr.namespace() }
  name: ${ cr.name() }
  labels:
    app.kubernetes.io/name: ${ constants.APP_NAME }
    app.kubernetes.io/instance: ${ cr.name() }
    app.kubernetes.io/managed-by: ${ constants.VM_OP_NAME }
  annotations:
    vmoperator.jdrupes.org/version: ${ managerVersion }
  ownerReferences:
  - apiVersion: ${ cr.apiVersion() }
    kind: ${ constants.Crd.KIND_VM }
    name: ${ cr.name() }
    uid: ${ cr.metadata().getUid() }
    controller: false

data:
  config.yaml: |
    "/Runner":
      # The directory used to store data files. Defaults to (depending on 
      # values available):
      #  * $XDG_DATA_HOME/vmrunner/${ cr.name() }
      #  * $HOME/.local/share/vmrunner/${ cr.name() }
      #  * ./${ cr.name() }
      dataDir: /var/local/vm-data
      
      # The directory used to store runtime files. Defaults to (depending on 
      # values available):
      #  * $XDG_RUNTIME_DIR/vmrunner/${ cr.name() }
      #  * /tmp/$USER/vmrunner/${ cr.name() }
      #  * /tmp/vmrunner/${ cr.name() }
      # runtimeDir: "$XDG_RUNTIME_DIR/vmrunner/${ cr.name() }"
      
      <#assign spec = cr.spec() />
      # The template to use. Resolved relative to /usr/share/vmrunner/templates.
      # template: "Standard-VM-latest.ftl.yaml"
      <#if spec.runnerTemplate?? && spec.runnerTemplate.source?? >
      template: ${ cm.spec().runnerTemplate.source }
      </#if>
    
      # The template is copied to the data diretory when the VM starts for
      # the first time. Subsequent starts use the copy unless this option is set.
      <#if spec.runnerTemplate?? && spec.runnerTemplate.update?? >
      updateTemplate: ${ spec.runnerTemplate.update?c }
      </#if>

      # Whether a shutdown initiated by the guest stops the pod deployment
      guestShutdownStops: ${ (spec.guestShutdownStops!false)?c }
      
      # When incremented, the VM is reset. The value has no default value,
      # i.e. if you start the VM without a value for this property, and
      # decide to trigger a reset later, you have to first set the value
      # and then inrement it.
      resetCounter: ${ cr.extra().get().resetCount()?c }

      # Forward the cloud-init data if provided
      <#if spec.cloudInit??>    
      cloudInit:
        metaData: ${ toJson(adjustCloudInitMeta(spec.cloudInit.metaData!{}, cr.metadata())) }
        <#if spec.cloudInit.userData??>
        userData: ${ toJson(spec.cloudInit.userData) }
        <#else>
        userData: {}
        </#if>
        <#if spec.cloudInit.networkConfig??>
        networkConfig: ${ toJson(spec.cloudInit.networkConfig) }
        </#if>
      </#if>
      
      # Define the VM (required)
      vm:
        # The VM's name (required)
        name: ${ cr.name() }
        
        # The machine's uuid. If none is specified, a uuid is generated
        # and stored in the data directory. If the uuid is important
        # (e.g. because licenses depend on it) it is recommaned to specify
        # it here explicitly or to carefully backup the data directory.
        # uuid: "generated uuid"
        <#if spec.vm.machineUuid??>
        uuid: "${ spec.vm.machineUuid }"
        </#if>

        # Whether to provide a software TPM (defaults to false)
        # useTpm: false
        useTpm: ${ spec.vm.useTpm?c }
        
        # How to boot (see https://github.com/mnlipp/VM-Operator/blob/main/org.jdrupes.vmoperator.runner.qemu/resources/org/jdrupes/vmoperator/runner/qemu/defaults.yaml):
        #  * bios
        #  * uefi[-4m]
        #  * secure[-4m]
        firmware: ${ spec.vm.firmware }
        
        # Whether to show a boot menu.
        # bootMenu: false
        bootMenu: ${ spec.vm.bootMenu?c }
    
        # When terminating, a graceful powerdown is attempted. If it
        # doesn't succeed within the given timeout (seconds) SIGTERM
        # is sent to Qemu.
        # powerdownTimeout: 900
        powerdownTimeout: ${ spec.vm.powerdownTimeout?c }
        
        # CPU settings
        cpuModel: ${ spec.vm.cpuModel }
        # Setting maximumCpus to 1 omits the "-smp" options. The defaults (0)
        # cause the corresponding property to be omitted from the "-smp" option.
        # If currentCpus is greater than maximumCpus, the latter is adjusted.
        <#if spec.vm.maximumCpus?? >
        maximumCpus: ${ parseQuantity(spec.vm.maximumCpus)?c }
        </#if>
        <#if spec.vm.cpuTopology?? >
        sockets: ${ spec.vm.cpuTopology.sockets?c }
        diesPerSocket: ${ spec.vm.cpuTopology.diesPerSocket?c }
        coresPerDie: ${ spec.vm.cpuTopology.coresPerDie?c }
        threadsPerCore: ${ spec.vm.cpuTopology.threadsPerCore?c }
        </#if>
        <#if spec.vm.currentCpus?? >
        currentCpus: ${ parseQuantity(spec.vm.currentCpus)?c }
        </#if>
        
        # RAM settings
        # Maximum defaults to 1G
        maximumRam: "${ formatMemory(parseQuantity(spec.vm.maximumRam)) }"
        <#if spec.vm.currentRam?? >
        currentRam: "${ formatMemory(parseQuantity(spec.vm.currentRam)) }"
        </#if>
        
        # RTC settings.
        # rtcBase: utc
        # rtcClock: rt
        rtcBase: ${ spec.vm.rtcBase }
        rtcClock: ${ spec.vm.rtcClock }
        
        # Network settings
        # Supported types are "tap" and "user" (for debugging). Type "user"
        # supports only the property "net".
        # network:
        # - type: tap
        #   bridge: br0
        #   device: virtio-net
        #   mac: (undefined)
        network:
        <#assign nwCounter = 0/>
        <#list spec.vm.networks as itf>
        <#if itf.tap??>
        - type: tap
          device: ${ itf.tap.device }
          bridge: ${ itf.tap.bridge }
          <#if itf.tap.mac??>
          mac: "${ itf.tap.mac }"
          </#if>
        <#elseif itf.user??>
        - type: user
          device: ${ itf.user.device }
          <#if itf.user.net??>
          net: "${ itf.user.net }"
          </#if>
        </#if>
        <#assign nwCounter += 1/>
        </#list>

        # There are no default drives. The supported types are "ide-cd"
        # and "raw". All types support a "bootindex" property.
        # Type "raw" can have a property "file" (if backed by a file on
        # the host) or a property "device" (if backed by a device).    
        # drives:
        # - type: ide-cd
        #   bootindex: (undefined)
        #   file: (undefined)
        drives:
        <#assign drvCounter = 0/>
        <#list spec.vm.disks as disk>
        <#if disk.volumeClaimTemplate?? 
          && disk.volumeClaimTemplate.metadata??
          && disk.volumeClaimTemplate.metadata.name??>
          <#assign diskName = disk.volumeClaimTemplate.metadata.name + "-disk">
        <#else>
          <#assign diskName = "disk-" + drvCounter>
        </#if>
        <#if disk.volumeClaimTemplate??> 
        - type: raw
          resource: /dev/${ diskName }
          <#if disk.bootindex??>
          bootindex: ${ disk.bootindex?c }
          </#if>
          <#assign drvCounter = drvCounter + 1/>
        </#if>
        <#if disk.cdrom??> 
        - type: ide-cd
          file: "${ imageLocation(disk.cdrom.image) }"
          <#if disk.bootindex??>
          bootindex: ${ disk.bootindex?c }
          </#if>
        </#if>
        </#list>
        
        display:
          <#if spec.vm.display.outputs?? >
          outputs: ${ spec.vm.display.outputs?c }
          </#if>
          <#if loginRequestedFor?? >
          loggedInUser: "${ loginRequestedFor }"
          </#if>
          <#if spec.vm.display.spice??>
          spice:
            port: ${ spec.vm.display.spice.port?c }
            <#if spec.vm.display.spice.ticket??>
            ticket: "${ spec.vm.display.spice.ticket }"
            </#if>
            <#if spec.vm.display.spice.streamingVideo??>
            streaming-video: "${ spec.vm.display.spice.streamingVideo }"
            </#if>
            usbRedirects: ${ spec.vm.display.spice.usbRedirects?c }
          </#if>

  logging.properties: |
    handlers=java.util.logging.ConsoleHandler
    
    #org.jgrapes.level=FINE
    #org.jgrapes.core.handlerTracking.level=FINER
    
    org.jdrupes.vmoperator.runner.qemu.level=FINE
    
    java.util.logging.ConsoleHandler.level=ALL
    java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
    java.util.logging.SimpleFormatter.format=%1$tb %1$td %1$tT %4$s %5$s%6$s%n
