Boot from CD-ROM works.
This commit is contained in:
parent
2ed51772ed
commit
ad7e63d78c
6 changed files with 122 additions and 21 deletions
|
|
@ -12,7 +12,7 @@ dependencies {
|
||||||
implementation 'org.jgrapes:org.jgrapes.core:[1.19.0,2)'
|
implementation 'org.jgrapes:org.jgrapes.core:[1.19.0,2)'
|
||||||
implementation 'org.jgrapes:org.jgrapes.io:[2.5.0,3)'
|
implementation 'org.jgrapes:org.jgrapes.io:[2.5.0,3)'
|
||||||
implementation 'org.jgrapes:org.jgrapes.http:[3.1.0,4)'
|
implementation 'org.jgrapes:org.jgrapes.http:[3.1.0,4)'
|
||||||
implementation 'org.jgrapes:org.jgrapes.util:[1.26.0,2)'
|
implementation 'org.jgrapes:org.jgrapes.util:[1.28.0,2)'
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ dependencies {
|
||||||
implementation 'org.jgrapes:org.jgrapes.core:[1.19.0,2)'
|
implementation 'org.jgrapes:org.jgrapes.core:[1.19.0,2)'
|
||||||
implementation 'org.jgrapes:org.jgrapes.io:[2.5.0,3)'
|
implementation 'org.jgrapes:org.jgrapes.io:[2.5.0,3)'
|
||||||
implementation 'org.jgrapes:org.jgrapes.http:[3.1.0,4)'
|
implementation 'org.jgrapes:org.jgrapes.http:[3.1.0,4)'
|
||||||
implementation 'org.jgrapes:org.jgrapes.util:[1.26.0,2)'
|
implementation 'org.jgrapes:org.jgrapes.util:[1.28.0,2)'
|
||||||
|
|
||||||
implementation 'org.freemarker:freemarker:[2.3.32,2.4)'
|
implementation 'org.freemarker:freemarker:[2.3.32,2.4)'
|
||||||
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:[2.15.0,3]'
|
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:[2.15.1,3]'
|
||||||
|
|
||||||
implementation project(':org.jdrupes.vmoperator.util')
|
implementation project(':org.jdrupes.vmoperator.util')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@
|
||||||
# "bootMode": "uefi"
|
# "bootMode": "uefi"
|
||||||
|
|
||||||
# RAM settings
|
# RAM settings
|
||||||
# "maximumRam": "512M"
|
# "maximumRam": "1G"
|
||||||
# "currentRam": "512M"
|
# "currentRam": "1G"
|
||||||
|
|
||||||
# CPU settings
|
# CPU settings
|
||||||
# "cpuModel": "host"
|
# "cpuModel": "host"
|
||||||
|
|
@ -59,4 +59,12 @@
|
||||||
# "threadsPerCore": 0
|
# "threadsPerCore": 0
|
||||||
# "accelertor": "kvm"
|
# "accelertor": "kvm"
|
||||||
|
|
||||||
|
# RTC settings.
|
||||||
|
# "rtcBase": "utc"
|
||||||
|
# "rtcClock": "rt"
|
||||||
|
|
||||||
|
"drives":
|
||||||
|
- "type": "ide-cd"
|
||||||
|
"bootindex": (undefined)
|
||||||
|
"file": (undefined)
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ class Configuration implements Dto {
|
||||||
/**
|
/**
|
||||||
* Subsection "vm".
|
* Subsection "vm".
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("PMD.ShortClassName")
|
@SuppressWarnings({ "PMD.ShortClassName", "PMD.TooManyFields" })
|
||||||
public static class Vm implements Dto {
|
public static class Vm implements Dto {
|
||||||
public String name;
|
public String name;
|
||||||
public String uuid;
|
public String uuid;
|
||||||
|
|
@ -69,6 +69,18 @@ class Configuration implements Dto {
|
||||||
public int coresPerDie;
|
public int coresPerDie;
|
||||||
public int threadsPerCore;
|
public int threadsPerCore;
|
||||||
public String accelerator = "kvm";
|
public String accelerator = "kvm";
|
||||||
|
public String rtcBase = "utc";
|
||||||
|
public String rtcClock = "rt";
|
||||||
|
public Drive[] drives;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subsection "drive".
|
||||||
|
*/
|
||||||
|
public static class Drive implements Dto {
|
||||||
|
public String type;
|
||||||
|
public Integer bootindex;
|
||||||
|
public String file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -76,9 +88,6 @@ class Configuration implements Dto {
|
||||||
*
|
*
|
||||||
* @return true, if successful
|
* @return true, if successful
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "PMD.AvoidDeeplyNestedIfStmts",
|
|
||||||
"PMD.CognitiveComplexity", "PMD.CyclomaticComplexity",
|
|
||||||
"PMD.NPathComplexity" })
|
|
||||||
public boolean check() {
|
public boolean check() {
|
||||||
if (vm == null || vm.name == null) {
|
if (vm == null || vm.name == null) {
|
||||||
logger.severe(() -> "Configuration is missing mandatory entries.");
|
logger.severe(() -> "Configuration is missing mandatory entries.");
|
||||||
|
|
@ -127,6 +136,7 @@ class Configuration implements Dto {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("PMD.AvoidDeeplyNestedIfStmts")
|
||||||
private boolean checkDataDir() {
|
private boolean checkDataDir() {
|
||||||
// Data directory
|
// Data directory
|
||||||
if (dataDir == null) {
|
if (dataDir == null) {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
package org.jdrupes.vmoperator.runner.qemu;
|
package org.jdrupes.vmoperator.runner.qemu;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
@ -143,6 +144,9 @@ public class Runner extends Component {
|
||||||
*/
|
*/
|
||||||
public Runner() throws IOException {
|
public Runner() throws IOException {
|
||||||
super(new Context());
|
super(new Context());
|
||||||
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
|
||||||
|
false);
|
||||||
|
|
||||||
// Get defaults
|
// Get defaults
|
||||||
defaults = mapper.readValue(
|
defaults = mapper.readValue(
|
||||||
Runner.class.getResourceAsStream("defaults.yaml"), JsonNode.class);
|
Runner.class.getResourceAsStream("defaults.yaml"), JsonNode.class);
|
||||||
|
|
@ -153,7 +157,7 @@ public class Runner extends Component {
|
||||||
fmConfig.setDirectoryForTemplateLoading(new File("/"));
|
fmConfig.setDirectoryForTemplateLoading(new File("/"));
|
||||||
fmConfig.setDefaultEncoding("utf-8");
|
fmConfig.setDefaultEncoding("utf-8");
|
||||||
fmConfig.setObjectWrapper(new ExtendedObjectWrapper(
|
fmConfig.setObjectWrapper(new ExtendedObjectWrapper(
|
||||||
fmConfig.getIncompatibleImprovements(), mapper));
|
fmConfig.getIncompatibleImprovements()));
|
||||||
fmConfig.setTemplateExceptionHandler(
|
fmConfig.setTemplateExceptionHandler(
|
||||||
TemplateExceptionHandler.RETHROW_HANDLER);
|
TemplateExceptionHandler.RETHROW_HANDLER);
|
||||||
fmConfig.setLogTemplateExceptions(false);
|
fmConfig.setLogTemplateExceptions(false);
|
||||||
|
|
|
||||||
|
|
@ -23,23 +23,38 @@
|
||||||
# Useful links:
|
# Useful links:
|
||||||
# - https://joonas.fi/2021/02/uefi-pc-boot-process-and-uefi-with-qemu/
|
# - https://joonas.fi/2021/02/uefi-pc-boot-process-and-uefi-with-qemu/
|
||||||
"arguments":
|
"arguments":
|
||||||
|
# Qemu configuration
|
||||||
- "-no-user-config"
|
- "-no-user-config"
|
||||||
|
# * https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt
|
||||||
|
- [ "-global", "kvm-pit.lost_tick_policy=delay" ]
|
||||||
|
- [ "-sandbox", "on,obsolete=deny,elevateprivileges=deny,\
|
||||||
|
spawn=allow,resourcecontrol=deny" ]
|
||||||
|
- [ "-msg", "timestamp=on" ]
|
||||||
|
# * Qemu monitor connection
|
||||||
|
- [ "-chardev", "socket,id=charmonitor,\
|
||||||
|
path=${ runtimeDir }/monitor.sock,server=on,wait=off" ]
|
||||||
|
- [ "-mon", "chardev=charmonitor,id=monitor,mode=control" ]
|
||||||
|
|
||||||
|
# VM configuration
|
||||||
- [ "-name", "guest=${ vm.name },debug-threads=on" ]
|
- [ "-name", "guest=${ vm.name },debug-threads=on" ]
|
||||||
- [ "-uuid", "${ vm.uuid }"]
|
- [ "-uuid", "${ vm.uuid }"]
|
||||||
# Configure "modern" machine (pc-q35-7.0). USB is off, because we
|
# * Configure "modern" machine (pc-q35-7.0). USB is off, because we
|
||||||
# configure (better) xhci later. No VMWare IO port (obviously).
|
# configure (better) xhci later. No VMWare IO port (obviously).
|
||||||
# For smm=on see https://scumjr.github.io/2016/01/04/playing-with-smm-and-qemu/.
|
# For smm=on see https://scumjr.github.io/2016/01/04/playing-with-smm-and-qemu/.
|
||||||
# Configure ROM/EEPROM for UEFI.
|
# Configure ROM/EEPROM for UEFI.
|
||||||
- [ "-machine", "pc-q35-7.0,usb=off,vmport=off,dump-guest-core=off\
|
- [ "-machine", "pc-q35-7.0,usb=off,vmport=off,dump-guest-core=off\
|
||||||
<#if vm.bootMode == "secure">,smm=on</#if>\
|
<#if vm.bootMode == "secure">,smm=on</#if>\
|
||||||
<#if vm.bootMode != "bios">,pflash0=fw-rom-device\
|
<#if vm.bootMode != "bios">,pflash0=fw-rom-device\
|
||||||
,pflash1=fw-eeprom-device</#if>,memory-backend=pc.ram,hpet=off" ]
|
,pflash1=fw-eeprom-device</#if>,memory-backend=pc.ram,hpet=off" ]
|
||||||
|
# * https://bugzilla.redhat.com/show_bug.cgi?id=1170533, may be unnecessary
|
||||||
|
- [ "-global", "ICH9-LPC.disable_s3=1" ]
|
||||||
|
- [ "-global", "ICH9-LPC.disable_s4=1" ]
|
||||||
# {{- if .Values.vm.secureBoot }}
|
# {{- if .Values.vm.secureBoot }}
|
||||||
# -global driver=cfi.pflash01,property=secure,value=on
|
# -global driver=cfi.pflash01,property=secure,value=on
|
||||||
# -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/local/qemu/master-key.aes"}'
|
# -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/local/qemu/master-key.aes"}'
|
||||||
# {{- end }}
|
# {{- end }}
|
||||||
<#if vm.bootMode != "bios">
|
<#if vm.bootMode != "bios">
|
||||||
# Provide ROM/EEPROM devices (instead of built-in BIOS)
|
# * Provide ROM/EEPROM devices (instead of built-in BIOS)
|
||||||
- [ "-blockdev", "node-name=fw-rom-file,driver=file,\
|
- [ "-blockdev", "node-name=fw-rom-file,driver=file,\
|
||||||
filename=${ firmwareRom },auto-read-only=true,discard=unmap" ]
|
filename=${ firmwareRom },auto-read-only=true,discard=unmap" ]
|
||||||
- [ "-blockdev", "node-name=fw-rom-device,driver=raw,\
|
- [ "-blockdev", "node-name=fw-rom-device,driver=raw,\
|
||||||
|
|
@ -49,9 +64,10 @@
|
||||||
- [ "-blockdev", "node-name=fw-eeprom-device,driver=raw,\
|
- [ "-blockdev", "node-name=fw-eeprom-device,driver=raw,\
|
||||||
read-only=false,file=fw-eeprom-file" ]
|
read-only=false,file=fw-eeprom-file" ]
|
||||||
</#if>
|
</#if>
|
||||||
# Provide RAM
|
# * Provide RAM
|
||||||
- [ "-object", "memory-backend-ram,id=pc.ram,\
|
- [ "-object", "memory-backend-ram,id=pc.ram,\
|
||||||
size=${ vm.maximumRam!"512M" }" ]
|
size=${ vm.maximumRam!"1G" }" ]
|
||||||
|
- [ "-m", "${ vm.maximumRam!"1G" }" ]
|
||||||
<#if vm.useTpm>
|
<#if vm.useTpm>
|
||||||
# Attach TPM
|
# Attach TPM
|
||||||
- [ "-chardev", "socket,id=chrtpm,path=${ runtimeDir }/swtpm-sock" ]
|
- [ "-chardev", "socket,id=chrtpm,path=${ runtimeDir }/swtpm-sock" ]
|
||||||
|
|
@ -69,10 +85,73 @@
|
||||||
<#if vm.accelerator != "none">
|
<#if vm.accelerator != "none">
|
||||||
- [ "-accel", "${ vm.accelerator }"]
|
- [ "-accel", "${ vm.accelerator }"]
|
||||||
</#if>
|
</#if>
|
||||||
|
# (More devices:)
|
||||||
|
# * RTC
|
||||||
|
- [ "-rtc", "base=${ vm.rtcBase },clock=${ vm.rtcClock },driftfix=slew" ]
|
||||||
|
# On-board serial, made available as pty on host (not used)
|
||||||
|
- [ "-chardev", "pty,id=ptyserial0" ]
|
||||||
|
- [ "-device", "isa-serial,chardev=ptyserial0,id=serial0,index=0" ]
|
||||||
|
# * PCI Serial device(s) (more in SPICE configuration below)
|
||||||
|
# Best explanation found:
|
||||||
|
# https://fedoraproject.org/wiki/Features/VirtioSerial
|
||||||
|
- [ "-device", "virtio-serial-pci,id=virtio-serial0" ]
|
||||||
|
# - Guest agent serial connection
|
||||||
|
- [ "-chardev","socket,id=guest-agent-socket,\
|
||||||
|
path=${ runtimeDir }/org.qemu.guest_agent.0,server=on,wait=off" ]
|
||||||
|
- [ "-device", "virtserialport,bus=virtio-serial0.0,nr=1,\
|
||||||
|
chardev=guest-agent-socket,id=channel0,name=org.qemu.guest_agent.0" ]
|
||||||
|
# * USB Hub and devices (more in SPICE configuration below)
|
||||||
|
# https://qemu-project.gitlab.io/qemu/system/devices/usb.html
|
||||||
|
# https://github.com/qemu/qemu/blob/master/hw/usb/hcd-xhci.c
|
||||||
|
- [ "-device", "qemu-xhci,p2=15,p3=15,id=usb" ]
|
||||||
|
- [ "-device", "usb-tablet" ]
|
||||||
|
# * Random number generator
|
||||||
|
- [ "-object", "rng-random,id=objrng0,filename=/dev/random" ]
|
||||||
|
- [ "-device", "virtio-rng-pci,rng=objrng0,id=rng0" ]
|
||||||
|
# * Graphics and Audio Card
|
||||||
|
- [ "-device", "virtio-vga,id=video0,max_outputs=1" ]
|
||||||
|
- [ "-device", "ich9-intel-hda,id=sound0" ]
|
||||||
|
# Drives
|
||||||
|
# * CD-Drives
|
||||||
|
<#assign cdCounter = 0/>
|
||||||
|
<#list vm.drives![] as drive>
|
||||||
|
<#if (drive.type!"hdd") == "ide-cd">
|
||||||
|
- [ "-drive", "id=drive-cdrom${ cdCounter },if=none,media=cdrom\
|
||||||
|
<#if drive.file??>,file=${ drive.file }</#if>" ]
|
||||||
|
# (IDE is old, but faster than usb-storage. virtio-blk-pci does not
|
||||||
|
# work without file [empty drive])
|
||||||
|
- [ "-device", "ide-cd,id=cd${ cdCounter },drive=drive-cdrom${ cdCounter }\
|
||||||
|
<#if drive.bootindex??>,bootindex=${ drive.bootindex }</#if>" ]
|
||||||
|
<#assign cdCounter += 1/>
|
||||||
|
</#if>
|
||||||
|
</#list>
|
||||||
|
|
||||||
- [ "-chardev", "socket,id=charmonitor,path=${ runtimeDir }/monitor.sock,server=on,wait=off" ]
|
# - how to access the resource on the host (a file)
|
||||||
- [ "-mon", "chardev=charmonitor,id=monitor,mode=control" ]
|
# - [ "-blockdev", "node-name=blockdev-cdrom-file,driver=file,\
|
||||||
|
# filename=/home/mnl/Downloads/archlinux-2023.05.03-x86_64.iso" ]
|
||||||
|
# - how to use the file (as sequence of literal blocks)
|
||||||
|
# - [ "-blockdev", "node-name=blockdev-cdrom-backend,driver=raw,\
|
||||||
|
# read-only=true,file=blockdev-cdrom-file" ]
|
||||||
|
# - the driver (what the guest sees)
|
||||||
|
# - [ "-device", "virtio-blk-pci,id=virtio-disk-cdrom,\
|
||||||
|
# drive=blockdev-cdrom-backend,bootindex=1" ]
|
||||||
|
|
||||||
|
|
||||||
|
# SPICE (display, channels ...)
|
||||||
# - [ "-spice", "port=5900,disable-ticketing=on" ]
|
# - [ "-spice", "port=5900,disable-ticketing=on" ]
|
||||||
|
# -chardev spicevmc,id=charchannel1,name=vdagent
|
||||||
|
# -device virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel1,id=channel1,name=com.redhat.spice.0
|
||||||
|
# -audiodev '{"id":"audio1","driver":"spice"}'
|
||||||
|
# - [ "-device", "hda-duplex,\
|
||||||
|
# id=sound0-codec0,bus=sound0.0,cad=0,audiodev=audio1" ]
|
||||||
|
# -spice port={{ .Values.vm.spicePort }},addr=0.0.0.0,disable-ticketing=on,seamless-migration=on
|
||||||
|
# -chardev spicevmc,id=charredir0,name=usbredir
|
||||||
|
# -device usb-redir,chardev=charredir0,id=redir0,bus=usb.0,port=2
|
||||||
|
# -chardev spicevmc,id=charredir1,name=usbredir
|
||||||
|
# -device usb-redir,chardev=charredir1,id=redir1,bus=usb.0,port=3
|
||||||
|
# -device virtio-balloon-pci,id=balloon0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"monitorMessages":
|
"monitorMessages":
|
||||||
"connect": '{ "execute": "qmp_capabilities" }'
|
"connect": '{ "execute": "qmp_capabilities" }'
|
||||||
Loading…
Add table
Add a link
Reference in a new issue