Skip to content

Commit

Permalink
Wipe Disks Improvements:
Browse files Browse the repository at this point in the history
PR introduces two new fields in the harvester config wipeDisksList and
wipeAllDisks and drops the old wipeDisks introduced in v1.3

There is an extra panel in disk configuration page. The extra panel
contains a drop down menu which gets rendered and populated if installer
finds additional disks with existing elemental based installations which
are not already used in install device or additional data device
  • Loading branch information
ibrokethecloud committed Jan 15, 2025
1 parent c78f37a commit 82cde1f
Show file tree
Hide file tree
Showing 7 changed files with 652 additions and 78 deletions.
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

0 comments on commit 82cde1f

Please sign in to comment.