Skip to content
Open
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
57 changes: 31 additions & 26 deletions package/harvester-os/files/usr/bin/setup-installer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,47 +36,52 @@ EOF

}

is_virtual_tty()
{
local tty_name=$1
local tty_num=${tty_name#tty}
[[ ${tty_num} =~ ^[1-9][0-9]*$ ]]
}

is_serial_tty()
{
local tty_name=$1
local tty_type

tty_type=$(cat "/sys/class/tty/${tty_name}/type")
[ "x${tty_type}" != "x0" ]
}


echo "Remove the getty service..."
rm -rf "/etc/systemd/system/getty*"

echo "Remove the serial-getty service..."
rm -rf "/etc/systemd/system/serial-getty*"

# reverse the ttys to start from the last one
read -r -a tty_list < /sys/class/tty/console/active
preferred_virtual_tty=""

for TTY in "${tty_list[@]}"; do
tty_num=${TTY#tty}

#for arm64 the terminals are named /dev/ttyAMA*
#skip /dev/ttyAMA* if an additional tty is present
#on equinix metal /dev/ttyAMA is the only terminal available
#so needs to be used as default option
PLATFORM=$(uname -m)
if [[ $PLATFORM == "aarch64" && ${#tty_list[@]} > 1 ]]
then
if [[ $tty_num =~ ^AMA[0-9]+$ ]]; then
continue
fi
fi

# tty1 ~ tty64
if [[ $tty_num =~ ^[0-9]+$ ]]; then
if [[ ${TTY} == "tty1" ]]; then
create_drop_in "/etc/systemd/system/getty@${TTY}.service.d"

break
exit 0
fi
if [[ -z ${preferred_virtual_tty} ]] && is_virtual_tty "${TTY}"; then
preferred_virtual_tty=${TTY}
fi
done


# might be serial console
if [[ -n ${preferred_virtual_tty} ]]; then
create_drop_in "/etc/systemd/system/getty@${preferred_virtual_tty}.service.d"
exit 0
fi

# check type is not 0
tty_type=$(cat "/sys/class/tty/${TTY}/type")
if [ "x${tty_type}" = "x0" ]; then
for TTY in "${tty_list[@]}"; do
if ! is_serial_tty "${TTY}"; then
continue
fi

create_drop_in "/etc/systemd/system/serial-getty@${TTY}.service.d"
break
exit 0
done
34 changes: 33 additions & 1 deletion package/harvester-os/files/usr/sbin/harv-restart-services
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
#!/bin/bash -ex

restart_console_getty()
{
read -r -a tty_list < /sys/class/tty/console/active
local preferred_virtual_tty=""

for TTY in "${tty_list[@]}"; do
if [[ ${TTY} == "tty1" ]]; then
systemctl restart "getty@${TTY}.service"
return 0
fi
tty_num=${TTY#tty}
if [[ -z ${preferred_virtual_tty} ]] && [[ ${tty_num} =~ ^[1-9][0-9]*$ ]]; then
preferred_virtual_tty=${TTY}
fi
done

if [[ -n ${preferred_virtual_tty} ]]; then
systemctl restart "getty@${preferred_virtual_tty}.service"
return 0
fi

for TTY in "${tty_list[@]}"; do
tty_type=$(cat "/sys/class/tty/${TTY}/type")
if [ "x${tty_type}" = "x0" ]; then
continue
fi
systemctl restart "serial-getty@${TTY}.service"
return 0
done
}

systemctl restart --no-block rancherd
systemctl restart getty@tty1.service
restart_console_getty
46 changes: 35 additions & 11 deletions pkg/console/tty.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,45 @@ package console

import (
"os"
goruntime "runtime"
"strconv"
"strings"

"github.com/sirupsen/logrus"
)

func isVirtualTTY(tty string) bool {
if !strings.HasPrefix(tty, "tty") {
return false
}

ttyNum, err := strconv.Atoi(strings.TrimPrefix(tty, "tty"))
return err == nil && ttyNum > 0
}

func getPreferredConsoleTTY(ttys []string) string {
preferredVirtualTTY := ""

for _, tty := range ttys {
if tty == "tty1" {
return tty
}
if preferredVirtualTTY == "" && isVirtualTTY(tty) {
preferredVirtualTTY = tty
}
}

if preferredVirtualTTY != "" {
return preferredVirtualTTY
}

for _, tty := range ttys {
if tty != "tty0" {
return tty
}
}
return ttys[0]
}

func getFirstConsoleTTY() string {
b, err := os.ReadFile("/sys/class/tty/console/active")
if err != nil {
Expand All @@ -17,16 +50,7 @@ func getFirstConsoleTTY() string {

ttys := strings.Split(strings.TrimRight(string(b), "\n"), " ")
if len(ttys) > 0 {
// arm devices generally have first console as /dev/ttyAMA0
// this console is skipped in iso based installs due to display resolution issues
// as a result of this automatic install via ipxe fails since installer runs in
// say /dev/tty1 but first console returned by this method is ttyAMA0
// we are currently adding a check to skip AMA0 if it is the first console and return
// the second item in the list
if goruntime.GOARCH == "arm64" && strings.Contains(ttys[0], "AMA0") && len(ttys) > 1 {
return ttys[1]
}
return ttys[0]
return getPreferredConsoleTTY(ttys)
}
return ""
}
Expand Down
46 changes: 46 additions & 0 deletions pkg/console/tty_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package console

import "testing"

func TestGetPreferredConsoleTTY(t *testing.T) {
tests := []struct {
name string
ttys []string
want string
}{
{
name: "prefer tty1 over serial",
ttys: []string{"ttyS0", "tty1"},
want: "tty1",
},
{
name: "prefer tty1 over earlier virtual tty",
ttys: []string{"tty2", "tty1"},
want: "tty1",
},
{
name: "skip tty0 when serial is available",
ttys: []string{"tty0", "ttyS0"},
want: "ttyS0",
},
{
name: "prefer first usable virtual tty",
ttys: []string{"ttyS0", "tty2"},
want: "tty2",
},
{
name: "keep ama console when it is the only usable option",
ttys: []string{"ttyAMA0"},
want: "ttyAMA0",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := getPreferredConsoleTTY(tt.ttys)
if got != tt.want {
t.Fatalf("getPreferredConsoleTTY(%v) = %q, want %q", tt.ttys, got, tt.want)
}
})
}
}
30 changes: 15 additions & 15 deletions pkg/console/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1120,56 +1120,56 @@ func Test_getAllValidDiskOptions(t *testing.T) {
expectedAllValidDiskOptions []widgets.Option
}{
{
name: "Disks with serial number",
name: "Disks with serial number",
mockedRunCommandOutput: []byte(sampleSerialDiskOutput),
expectedAllValidDiskOptions: []widgets.Option{
{
Value: "/dev/sda",
Text: "sda 250G",
Text: "sda 250G",
},
},
},
{
name: "Disks with existing data",
name: "Disks with existing data",
mockedRunCommandOutput: []byte(reinstallDisks),
expectedAllValidDiskOptions: []widgets.Option{
{
Value: "/dev/sda",
Text: "sda 10G",
Text: "sda 10G",
},
{
Value: "/dev/vda",
Text: "vda 250G",
Text: "vda 250G",
},
},
},
{
name: "Disks on existing installs",
name: "Disks on existing installs",
mockedRunCommandOutput: []byte(preInstalledMultiPath),
expectedAllValidDiskOptions: []widgets.Option{
{
Value: "/dev/sda",
Text: "sda 250G",
Text: "sda 250G",
},
},
},
{
name: "RAID disks",
name: "RAID disks",
mockedRunCommandOutput: []byte(raidDisks),
expectedAllValidDiskOptions: []widgets.Option{
{
Value: "/dev/sda",
Text: "sda 447.1G",
Text: "sda 447.1G",
},
{
Value: "/dev/sdb",
Text: "sdb 447.1G",
Text: "sdb 447.1G",
},
},
},
{
name: "No Valid Disks",
mockedRunCommandOutput: []byte(noValidDisks),
name: "No Valid Disks",
mockedRunCommandOutput: []byte(noValidDisks),
expectedAllValidDiskOptions: []widgets.Option(nil),
},
}
Expand Down Expand Up @@ -1213,7 +1213,7 @@ func Test_getDataDisksOptions(t *testing.T) {
widgets.Option{Value: "/dev/sdb", Text: "sdb 447.1G"},
},
doc.getDataDiskOptions(hvstConfig),
)
)

// Change the installation disk to the second disk option
hvstConfig.Install.Device = doc.getAllValidDiskOptions()[1].Value
Expand All @@ -1223,7 +1223,7 @@ func Test_getDataDisksOptions(t *testing.T) {
widgets.Option{Value: "/dev/sda", Text: "sda 447.1G"},
},
doc.getDataDiskOptions(hvstConfig),
)
)
}

func Test_getWipeDisksOptions(t *testing.T) {
Expand All @@ -1244,7 +1244,7 @@ func Test_getWipeDisksOptions(t *testing.T) {
widgets.Option{Value: "/dev/sdc", Text: "sdc 250G"},
},
doc.getWipeDisksOptions(hvstConfig),
)
)

hvstConfig.Install.Device = "/dev/sdc"
hvstConfig.Install.DataDisk = ""
Expand Down