Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 6 additions & 46 deletions mantle/cmd/kola/testiso.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,47 +338,7 @@ func runTestIso(cmd *cobra.Command, args []string) error {
return nil
}

// Currently effective on aarch64: switches the boot order to boot from disk on reboot. For s390x and aarch64, bootindex
// is used to boot from the network device (boot once is not supported). For s390x, the boot ordering was not a problem as it
// would always read from disk first. For aarch64, the bootindex needs to be switched to boot from disk before a reboot
func switchBootOrder(tempdir string) error {
if tempdir == "" || (system.RpmArch() != "s390x" && system.RpmArch() != "aarch64") {
//Not applicable for iso installs and other arches
return nil
}
monitor, devs, err := platform.ListQMPDevices(tempdir)
if monitor != nil {
defer monitor.Disconnect()
}
if err != nil {
return errors.Wrapf(err, "Could not list devices")
}
var blkdev string
var netdev string
for _, dev := range devs.Return {
switch dev.Type {
case "child<virtio-net-pci>", "child<virtio-net-ccw>":
netdev = filepath.Join("/machine/peripheral-anon", dev.Name)
break
case "child<virtio-blk-device>", "child<virtio-blk-pci>", "child<virtio-blk-ccw>":
blkdev = filepath.Join("/machine/peripheral-anon", dev.Name)
break
default:
break
}
}
// unset bootindex for the network device
if err := platform.SetBootIndexForDevice(monitor, netdev, -1); err != nil {
return errors.Wrapf(err, "Could not set bootindex for netdev")
}
// set bootindex to 1 to boot from disk
if err := platform.SetBootIndexForDevice(monitor, blkdev, 1); err != nil {
return errors.Wrapf(err, "Could not set bootindex for blkdev")
}
return nil
}

func awaitCompletion(inst *platform.QemuInstance, outdir string, tempdir string, qchan *os.File, expected []string) error {
func awaitCompletion(inst *platform.QemuInstance, outdir string, qchan *os.File, expected []string) error {
errchan := make(chan error)
go func() {
time.Sleep(installTimeout)
Expand Down Expand Up @@ -429,9 +389,9 @@ func awaitCompletion(inst *platform.QemuInstance, outdir string, tempdir string,
errchan <- fmt.Errorf("Unexpected string from completion channel: %s expected: %s", line, exp)
return
}
// switch the boot order here, we are well into the installation process. Only used for PXE test now
// switch the boot order here, we are well into the installation process - only for aarch64 and s390x
if line == liveOKSignal {
if err := switchBootOrder(tempdir); err != nil {
if err := inst.SwitchBootOrder(); err != nil {
errchan <- errors.Wrapf(err, "switching boot order failed")
return
}
Expand Down Expand Up @@ -494,7 +454,7 @@ func testPXE(inst platform.Install, outdir string, offline bool) error {
}
defer mach.Destroy()

return awaitCompletion(mach.QemuInst, outdir, mach.Tempdir, completionChannel, []string{liveOKSignal, signalCompleteString})
return awaitCompletion(mach.QemuInst, outdir, completionChannel, []string{liveOKSignal, signalCompleteString})
}

func testLiveIso(inst platform.Install, outdir string, offline bool) error {
Expand Down Expand Up @@ -535,7 +495,7 @@ func testLiveIso(inst platform.Install, outdir string, offline bool) error {
}
defer mach.Destroy()

return awaitCompletion(mach.QemuInst, outdir, "", completionChannel, []string{liveOKSignal, signalCompleteString})
return awaitCompletion(mach.QemuInst, outdir, completionChannel, []string{liveOKSignal, signalCompleteString})
}

func testLiveLogin(outdir string) error {
Expand Down Expand Up @@ -563,5 +523,5 @@ func testLiveLogin(outdir string) error {
}
defer mach.Destroy()

return awaitCompletion(mach, outdir, "", completionChannel, []string{"coreos-liveiso-success"})
return awaitCompletion(mach, outdir, completionChannel, []string{"coreos-liveiso-success"})
}
16 changes: 8 additions & 8 deletions mantle/platform/metal.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ const (
// defaultQemuHostIPv4 is documented in `man qemu-kvm`, under the `-netdev` option
defaultQemuHostIPv4 = "10.0.2.2"

targetDevice = "/dev/vda"

// rebootUnit is a copy of the system one without the ConditionPathExists
rebootUnit = `[Unit]
Description=Reboot after CoreOS Installer
Expand Down Expand Up @@ -436,12 +434,6 @@ func cat(outfile string, infiles ...string) error {

func (t *installerRun) run() (*QemuInstance, error) {
builder := t.builder
// qmp device for switching boot order (needed for aarch64)
qmpPath := filepath.Join(t.tempdir, "qmp.sock")
qmpID := "pxe-qmp"
builder.Append("-chardev", fmt.Sprintf("socket,id=%s,path=%s,server,nowait", qmpID, qmpPath))
builder.Append("-mon", fmt.Sprintf("chardev=%s,mode=control", qmpID))

netdev := fmt.Sprintf("%s,netdev=mynet0,mac=52:54:00:12:34:56", t.pxe.networkdevice)
if t.pxe.bootindex == "" {
builder.Append("-boot", "once=n", "-option-rom", "/usr/share/qemu/pxe-rtl8139.rom")
Expand Down Expand Up @@ -575,6 +567,14 @@ func (inst *Install) InstallViaISOEmbed(kargs []string, liveIgnition, targetIgni
insecureOpt = "--insecure"
}
pointerIgnitionPath := "/var/opt/pointer.ign"

targetDevice := "/dev/vda"
// For aarch64, the cdrom is a pci blk device /dev/vda
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine for now, note for future: I think we should set things up using the serial= identifer and use /dev/disk/by/id in the future, see also #1343

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noted it.

// TBD: use the serial identifier and use /dev/disk/by-id to install
if system.RpmArch() == "aarch64" {
targetDevice = "/dev/vdb"
}

installerUnit := fmt.Sprintf(`
[Unit]
After=network-online.target
Expand Down
53 changes: 48 additions & 5 deletions mantle/platform/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,47 @@ func (inst *QemuInstance) Destroy() {
}
}

// Currently effective on aarch64: switches the boot order to boot from disk on reboot. For s390x and aarch64, bootindex
// is used to boot from the network device (boot once is not supported). For s390x, the boot ordering was not a problem as it
// would always read from disk first. For aarch64, the bootindex needs to be switched to boot from disk before a reboot
func (inst *QemuInstance) SwitchBootOrder() error {
if system.RpmArch() != "s390x" && system.RpmArch() != "aarch64" {
//Not applicable for other arches
return nil
}
monitor, devs, err := listQMPDevices(inst.tempdir)
if monitor != nil {
defer monitor.Disconnect()
}
if err != nil {
return errors.Wrapf(err, "Could not list devices")
}
var blkdev string
var bootdev string
for _, dev := range devs.Return {
switch dev.Type {
// Boot device used for first boot - for aarch64 the cdrom is a pci blk device (used for ISO installs)
case "child<virtio-net-pci>", "child<virtio-blk-pci>", "child<virtio-net-ccw>":
bootdev = filepath.Join("/machine/peripheral-anon", dev.Name)
break
case "child<virtio-blk-device>", "child<virtio-blk-ccw>":
blkdev = filepath.Join("/machine/peripheral-anon", dev.Name)
break
default:
break
}
}
// unset bootindex for the network device
if err := setBootIndexForDevice(monitor, bootdev, -1); err != nil {
return errors.Wrapf(err, "Could not set bootindex for netdev")
}
// set bootindex to 1 to boot from disk
if err := setBootIndexForDevice(monitor, blkdev, 1); err != nil {
return errors.Wrapf(err, "Could not set bootindex for blkdev")
}
return nil
}

// QemuBuilder is a configurator that can then create a qemu instance
type QemuBuilder struct {
// ConfigFile is a path to Ignition configuration
Expand Down Expand Up @@ -933,12 +974,8 @@ func (builder *QemuBuilder) setupIso() error {
// primary disk is selected. This allows us to have "boot once" functionality on
// both UEFI and BIOS (`-boot once=d` OTOH doesn't work with OVMF).
switch system.RpmArch() {
case "s390x", "ppc64le":
case "s390x", "ppc64le", "aarch64":
builder.Append("-cdrom", builder.iso.path)
case "aarch64":
// TODO - can we boot from a virtual USB CDROM or a USB flash drive here?
// https://fedoraproject.org/wiki/Architectures/AArch64/Install_with_QEMU#Installing_F23_aarch64_from_CDROM seems to claim yes
return fmt.Errorf("Architecture aarch64 does not support ISO")
default:
bootindexStr := ""
if builder.iso.bootindex != "" {
Expand Down Expand Up @@ -1162,6 +1199,12 @@ func (builder *QemuBuilder) Exec() (*QemuInstance, error) {

}

// Set up QMP (currently used to switch boot order after first boot on aarch64)
qmpPath := filepath.Join(builder.tempdir, "qmp.sock")
qmpID := "qemu-qmp"
builder.Append("-chardev", fmt.Sprintf("socket,id=%s,path=%s,server,nowait", qmpID, qmpPath))
builder.Append("-mon", fmt.Sprintf("chardev=%s,mode=control", qmpID))

// Set up the virtio channel to get Ignition failures by default
journalPipeR, err := builder.VirtioChannelRead("com.coreos.ignition.journal")
inst.journalPipe = journalPipeR
Expand Down
4 changes: 2 additions & 2 deletions mantle/platform/qmp_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func newQMPMonitor(sockaddr string) (*qmp.SocketMonitor, error) {
}

// Executes a query which provides the list of devices and their names
func ListQMPDevices(sockaddr string) (*qmp.SocketMonitor, *QOMDev, error) {
func listQMPDevices(sockaddr string) (*qmp.SocketMonitor, *QOMDev, error) {
monitor, err := newQMPMonitor(sockaddr)
if err != nil {
return nil, nil, errors.Wrapf(err, "Could not open monitor")
Expand All @@ -74,7 +74,7 @@ func ListQMPDevices(sockaddr string) (*qmp.SocketMonitor, *QOMDev, error) {
}

// Set the bootindex for the particular device
func SetBootIndexForDevice(monitor *qmp.SocketMonitor, device string, bootindex int) error {
func setBootIndexForDevice(monitor *qmp.SocketMonitor, device string, bootindex int) error {
cmd := fmt.Sprintf(`{ "execute":"qom-set", "arguments": { "path":"%s", "property":"bootindex", "value":%d } }`, device, bootindex)
if _, err := monitor.Run([]byte(cmd)); err != nil {
return errors.Wrapf(err, "Running QMP command")
Expand Down