Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wipe Disks Improvements (backport #885) #956

Merged
merged 2 commits into from
Feb 18, 2025
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
31 changes: 11 additions & 20 deletions package/harvester-os/files/usr/sbin/harv-install
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,17 @@ clear_disk_label()
# }
# ]
# }
if [ "$HARVESTER_WIPE_DISKS" == "true" ]; then
echo "wiping all disks"
for disk in $(lsblk -d -n -J -o NAME,TYPE | jq -r '.blockdevices[] | select(.type == "disk") | .name')
do
sgdisk -Z /dev/$disk
partprobe -s /dev/$disk
done
else
# Clear the label of partitions that has $DATA_DISK_FSLABEL to prevent misidentification
# Also, while yip is partitioning the disk, if it sees the LABEL to be used exists,
# it won't create the partition. So it's necessary to clear the label
for part in $(blkid -t LABEL="$DATA_DISK_FSLABEL" -o device); do
echo "Remove filesystem label from $part"
# Run this tune2fs twice because sometimes the first run would show "Recovering journal"
# and label is not modified
tune2fs -L "" $part > /dev/null
tune2fs -L "" $part > /dev/null
done
udevadm settle
fi
# Clear the label of partitions that has $DATA_DISK_FSLABEL to prevent misidentification
# Also, while yip is partitioning the disk, if it sees the LABEL to be used exists,
# it won't create the partition. So it's necessary to clear the label
for part in $(blkid -t LABEL="$DATA_DISK_FSLABEL" -o device); do
echo "Remove filesystem label from $part"
# Run this tune2fs twice because sometimes the first run would show "Recovering journal"
# and label is not modified
tune2fs -L "" $part > /dev/null
tune2fs -L "" $part > /dev/null
done
udevadm settle
}

umount_target() {
Expand Down
27 changes: 14 additions & 13 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,19 +154,20 @@ type Install struct {
ClusterPodCIDR string `json:"clusterPodCidr,omitempty"`
ClusterServiceCIDR string `json:"clusterServiceCidr,omitempty"`

ForceEFI bool `json:"forceEfi,omitempty"`
Device string `json:"device,omitempty"`
ConfigURL string `json:"configUrl,omitempty"`
Silent bool `json:"silent,omitempty"`
ISOURL string `json:"isoUrl,omitempty"`
PowerOff bool `json:"powerOff,omitempty"`
NoFormat bool `json:"noFormat,omitempty"`
Debug bool `json:"debug,omitempty"`
TTY string `json:"tty,omitempty"`
ForceGPT bool `json:"forceGpt,omitempty"`
Role string `json:"role,omitempty"`
WithNetImages bool `json:"withNetImages,omitempty"`
WipeDisks bool `json:"wipeDisks,omitempty"`
ForceEFI bool `json:"forceEfi,omitempty"`
Device string `json:"device,omitempty"`
ConfigURL string `json:"configUrl,omitempty"`
Silent bool `json:"silent,omitempty"`
ISOURL string `json:"isoUrl,omitempty"`
PowerOff bool `json:"powerOff,omitempty"`
NoFormat bool `json:"noFormat,omitempty"`
Debug bool `json:"debug,omitempty"`
TTY string `json:"tty,omitempty"`
ForceGPT bool `json:"forceGpt,omitempty"`
Role string `json:"role,omitempty"`
WithNetImages bool `json:"withNetImages,omitempty"`
WipeAllDisks bool `json:"wipeAllDisks,omitempty"`
WipeDisksList []string `json:"wipeDisksList,omitempty"`

// Following options are not cOS installer flag
ForceMBR bool `json:"forceMbr,omitempty"`
Expand Down
3 changes: 3 additions & 0 deletions pkg/console/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ const (
vipTextPanel = "vipTextPanel"
ntpServersPanel = "ntpServersPanel"
askRolePanel = "askRolePanel"
wipeDisksPanel = "wipeDisksPanel"
wipeDisksTitlePanel = "wipeDisksTitlePanel"

hostnameTitle = "Configure hostname for this instance"
networkTitle = "Configure network"
Expand All @@ -65,6 +67,7 @@ const (
mtuLabel = "MTU (optional)"
dnsServersLabel = "DNS Servers"
ntpServersLabel = "NTP Servers"
wipeDisksLabel = "Wipe Disks"

networkMethodDHCPText = "Automatic (DHCP)"
networkMethodStaticText = "Static"
Expand Down
132 changes: 94 additions & 38 deletions pkg/console/install_panels.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"net"
"net/netip"
"os"
"os/exec"
"slices"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -290,28 +290,6 @@ func getDataDiskOptions(hvstConfig *config.HarvesterConfig) ([]widgets.Option, e
return nil, nil
}

func getDiskOptions() ([]widgets.Option, error) {
output, err := exec.Command("/bin/sh", "-c", `lsblk -J -o NAME,SIZE,TYPE,WWN,SERIAL`).CombinedOutput()
if err != nil {
return nil, err
}

lines, err := identifyUniqueDisks(output)

var options []widgets.Option
for _, line := range lines {
splits := strings.SplitN(line, " ", 2)
if len(splits) == 2 {
options = append(options, widgets.Option{
Value: "/dev/" + splits[0],
Text: line,
})
}
}

return options, nil
}

func addDiskPanel(c *Console) error {
diskConfirmed = false

Expand Down Expand Up @@ -396,6 +374,29 @@ func addDiskPanel(c *Console) error {
setLocation(persistentSizeV, 3)
c.AddElement(persistentSizePanel, persistentSizeV)

// WipeDisksPanel
wipeDisksTitlePanelV := widgets.NewPanel(c.Gui, wipeDisksTitlePanel)
wipeDisksTitlePanelV.SetContent("Additional Harvester installations detected")
wipeDisksTitlePanelV.FgColor = gocui.ColorRed
setLocation(wipeDisksTitlePanelV, 3)
c.AddElement(wipeDisksTitlePanel, wipeDisksTitlePanelV)

wipeDisksV, err := widgets.NewDropDown(c.Gui, wipeDisksPanel, wipeDisksLabel, func() ([]widgets.Option, error) {
return getWipeDisksOptions(c.config)
})
if err != nil {
return err
}
setLocation(wipeDisksV.Panel, 3)
wipeDisksV.Autoscroll = true
wipeDisksV.FgColor = gocui.ColorRed
wipeDisksV.SetMulti(true) // allow multiple disks to be selected for wipe operation
wipeDisksV.PreShow = func() error {
wipeDisksV.Focus = true
return nil
}
c.AddElement(wipeDisksPanel, wipeDisksV)

// Asking force MBR title
askForceMBRTitleV := widgets.NewPanel(c.Gui, askForceMBRTitlePanel)
askForceMBRTitleV.SetContent("Use MBR partitioning scheme")
Expand Down Expand Up @@ -478,6 +479,8 @@ func addDiskPanel(c *Console) error {
diskNotePanel,
askForceMBRTitlePanel,
persistentSizePanel,
wipeDisksTitlePanel,
wipeDisksPanel,
)
}
gotoPrevPage := func(_ *gocui.Gui, _ *gocui.View) error {
Expand Down Expand Up @@ -549,6 +552,34 @@ func addDiskPanel(c *Console) error {
}
return showNext(c, persistentSizePanel)
}

// isWipeDisksNeeded is a helper function to render the wipeDisksPanel if needed
// if there are no additional disks to wipe then it checks if MBR needs to be enabled
// else will move on to the next apge
isWipeDisksNeeded := func(g *gocui.Gui, v *gocui.View) error {
options, err := getWipeDisksOptions(c.config)
if err != nil {
return err
}
if len(options) != 0 {
if slices.Contains(c.config.WipeDisksList, c.config.Device) || slices.Contains(c.config.WipeDisksList, c.config.DataDisk) {
c.config.WipeDisksList = []string{}
wipeDisksV.Reset()
}
return showNext(c, wipeDisksTitlePanel, wipeDisksPanel)
}
// no disks left to wipe, so close the wipeDisksTitlePanel and wipeDisksPanel
c.CloseElements(wipeDisksTitlePanel, wipeDisksPanel)

if systemIsBIOS() {
if err := c.setContentByName(diskNotePanel, forceMBRNote); err != nil {
return err
}
return showNext(c, askForceMBRPanel)
}
return gotoNextPage(g, v)
}

// Keybindings
diskV.KeyBindings = map[gocui.Key]func(*gocui.Gui, *gocui.View) error{
gocui.KeyEnter: diskConfirm,
Expand Down Expand Up @@ -596,13 +627,7 @@ func addDiskPanel(c *Console) error {
// At this point the disk configuration is valid.
diskConfirmed = true

if systemIsBIOS() {
if err := c.setContentByName(diskNotePanel, forceMBRNote); err != nil {
return err
}
return showNext(c, askForceMBRPanel)
}
return gotoNextPage(g, v)
return isWipeDisksNeeded(g, v)
}
dataDiskV.KeyBindings = map[gocui.Key]func(*gocui.Gui, *gocui.View) error{
gocui.KeyEnter: dataDiskConfirm,
Expand Down Expand Up @@ -637,15 +662,9 @@ func addDiskPanel(c *Console) error {

// At this point the disk configuration is valid.
diskConfirmed = true

if systemIsBIOS() {
if err := c.setContentByName(diskNotePanel, forceMBRNote); err != nil {
return err
}
return showNext(c, askForceMBRPanel)
}
return gotoNextPage(g, v)
return isWipeDisksNeeded(g, v)
}

persistentSizeV.KeyBindings = map[gocui.Key]func(*gocui.Gui, *gocui.View) error{
gocui.KeyEnter: persistentSizeConfirm,
gocui.KeyArrowUp: func(_ *gocui.Gui, _ *gocui.View) error {
Expand All @@ -671,6 +690,43 @@ func addDiskPanel(c *Console) error {
gocui.KeyEsc: gotoPrevPage,
}

wipeDisksConfirm := func(g *gocui.Gui, v *gocui.View) error {
c.config.WipeDisksList = wipeDisksV.GetMultiData()
if systemIsBIOS() {
if err := c.setContentByName(diskNotePanel, forceMBRNote); err != nil {
return err
}
return showNext(c, askForceMBRPanel)
}
return gotoNextPage(g, v)
}

wipeDisksV.KeyBindings = map[gocui.Key]func(*gocui.Gui, *gocui.View) error{
gocui.KeyEnter: wipeDisksConfirm,
gocui.KeyArrowDown: wipeDisksConfirm,
gocui.KeyArrowUp: func(_ *gocui.Gui, _ *gocui.View) error {
diskConfirmed = false

disk, err := diskV.GetData()
if err != nil {
return err
}
dataDisk, err := dataDiskV.GetData()
if err != nil {
return err
}

if len(diskOpts) > 1 && disk != dataDisk {
return showNext(c, dataDiskPanel)
}
if err := c.setContentByName(diskNotePanel, persistentSizeNote); err != nil {
return err
}
return showNext(c, persistentSizePanel)
},
gocui.KeyEsc: gotoPrevPage,
}

mbrConfirm := func(g *gocui.Gui, v *gocui.View) error {
forceMBR, err := askForceMBRV.GetData()
if err != nil {
Expand Down
Loading
Loading