Skip to content

Commit e52c457

Browse files
authored
OSModifier: Refactor boot customization to handle both GRUB and UKI scenarios (#269)
<!-- Description: Please provide a summary of the changes and the motivation behind them. --> a follow up for #266 Enhance boot customization logic to distinguish GRUB and UKI scenarios - Introduce explicit checks for /boot/grub2/grub.cfg and /etc/default/grub to determine if GRUB is in use. - Conditionally apply GRUB-specific logic (e.g., kernel command line updates, SELinux boot parameters) only when GRUB is present. - Refactor SELinux handling into updateSELinuxForGrubBasedBoot and updateSELinuxForUkiBoot for clarity and separation of concerns. --- ### **Checklist** - [ ] Tests added/updated - [ ] Documentation updated (if needed) - [ ] Code conforms to style guidelines
1 parent 3d0e175 commit e52c457

1 file changed

Lines changed: 76 additions & 45 deletions

File tree

toolkit/tools/pkg/osmodifierlib/modifierutils.go

Lines changed: 76 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ package osmodifierlib
55

66
import (
77
"fmt"
8+
"os"
9+
"path/filepath"
810
"strings"
911

1012
"github.com/microsoft/azurelinux/toolkit/tools/imagecustomizerapi"
13+
"github.com/microsoft/azurelinux/toolkit/tools/imagegen/installutils"
1114
"github.com/microsoft/azurelinux/toolkit/tools/internal/logger"
1215
"github.com/microsoft/azurelinux/toolkit/tools/internal/safechroot"
1316
"github.com/microsoft/azurelinux/toolkit/tools/osmodifierapi"
@@ -37,66 +40,65 @@ func doModifications(baseConfigPath string, osConfig *osmodifierapi.OS) error {
3740
return err
3841
}
3942

40-
// Only initialize BootCustomizer if any GRUB-related settings are present
41-
needsBootCustomizer := osConfig.KernelCommandLine.ExtraCommandLine != nil ||
43+
// Add a check to make sure BootCustomizer can be initialized
44+
grubExists := grubConfigSupportExists(dummyChroot)
45+
46+
needsBootCustomizer := grubExists && (osConfig.KernelCommandLine.ExtraCommandLine != nil ||
4247
osConfig.Overlays != nil ||
4348
osConfig.SELinux.Mode != "" ||
4449
osConfig.Verity != nil ||
45-
osConfig.RootDevice != ""
50+
osConfig.RootDevice != "")
4651

4752
var bootCustomizer *imagecustomizerlib.BootCustomizer
4853
if needsBootCustomizer {
4954
bootCustomizer, err = imagecustomizerlib.NewBootCustomizer(dummyChroot)
5055
if err != nil {
5156
return err
5257
}
53-
}
5458

55-
updateGrubRequired := false
59+
if osConfig.KernelCommandLine.ExtraCommandLine != nil {
60+
err = bootCustomizer.AddKernelCommandLine(osConfig.KernelCommandLine.ExtraCommandLine)
61+
if err != nil {
62+
return fmt.Errorf("failed to add extra kernel command line:\n%w", err)
63+
}
64+
}
5665

57-
if osConfig.KernelCommandLine.ExtraCommandLine != nil {
58-
err = bootCustomizer.AddKernelCommandLine(osConfig.KernelCommandLine.ExtraCommandLine)
59-
if err != nil {
60-
return fmt.Errorf("failed to add extra kernel command line:\n%w", err)
66+
if osConfig.Overlays != nil {
67+
err = updateGrubConfigForOverlay(*osConfig.Overlays, bootCustomizer)
68+
if err != nil {
69+
return err
70+
}
6171
}
62-
updateGrubRequired = true
63-
}
6472

65-
if osConfig.Overlays != nil {
66-
err = updateGrubConfigForOverlay(*osConfig.Overlays, bootCustomizer)
67-
if err != nil {
68-
return err
73+
if osConfig.Verity != nil {
74+
err = updateDefaultGrubForVerity(osConfig.Verity, bootCustomizer)
75+
if err != nil {
76+
return err
77+
}
6978
}
70-
updateGrubRequired = true
71-
}
7279

73-
if osConfig.SELinux.Mode != "" {
74-
err = handleSELinux(osConfig.SELinux.Mode, bootCustomizer, dummyChroot)
75-
if err != nil {
76-
return err
80+
if osConfig.RootDevice != "" {
81+
err = bootCustomizer.SetRootDevice(osConfig.RootDevice)
82+
if err != nil {
83+
return err
84+
}
7785
}
78-
updateGrubRequired = true
79-
}
8086

81-
if osConfig.Verity != nil {
82-
err = updateDefaultGrubForVerity(osConfig.Verity, bootCustomizer)
83-
if err != nil {
84-
return err
87+
if osConfig.SELinux.Mode != "" {
88+
err = updateSELinuxForGrubBasedBoot(osConfig.SELinux.Mode, bootCustomizer, dummyChroot)
89+
if err != nil {
90+
return err
91+
}
8592
}
86-
updateGrubRequired = true
87-
}
8893

89-
if osConfig.RootDevice != "" {
90-
err = bootCustomizer.SetRootDevice(osConfig.RootDevice)
94+
err = bootCustomizer.WriteToFile(dummyChroot)
9195
if err != nil {
9296
return err
9397
}
94-
updateGrubRequired = true
9598
}
9699

97-
// Write changes to file only if GRUB needs updating
98-
if updateGrubRequired {
99-
err = bootCustomizer.WriteToFile(dummyChroot)
100+
if osConfig.SELinux.Mode != "" && !grubExists {
101+
err = updateSELinuxForUkiBoot(osConfig.SELinux.Mode, dummyChroot)
100102
if err != nil {
101103
return err
102104
}
@@ -160,30 +162,59 @@ func updateGrubConfigForOverlay(overlays []osmodifierapi.Overlay, bootCustomizer
160162
return nil
161163
}
162164

163-
func handleSELinux(selinuxMode imagecustomizerapi.SELinuxMode, bootCustomizer *imagecustomizerlib.BootCustomizer, dummyChroot safechroot.ChrootInterface) error {
164-
var err error
165-
currentSELinuxMode, err := bootCustomizer.GetSELinuxMode(dummyChroot)
165+
func updateSELinuxForUkiBoot(selinuxMode imagecustomizerapi.SELinuxMode, installChroot safechroot.ChrootInterface) error {
166+
if selinuxMode == imagecustomizerapi.SELinuxModeDefault {
167+
return nil
168+
}
169+
170+
logger.Log.Infof("Applying SELinux mode ('%s') for UKI-based system", selinuxMode)
171+
172+
err := imagecustomizerlib.UpdateSELinuxModeInConfigFile(selinuxMode, installChroot)
173+
if err != nil {
174+
return fmt.Errorf("failed to update SELinux mode in config file: %w", err)
175+
}
176+
177+
return nil
178+
}
179+
180+
func updateSELinuxForGrubBasedBoot(selinuxMode imagecustomizerapi.SELinuxMode, bootCustomizer *imagecustomizerlib.BootCustomizer, installChroot safechroot.ChrootInterface) error {
181+
currentSELinuxMode, err := bootCustomizer.GetSELinuxMode(installChroot)
166182
if err != nil {
167-
return fmt.Errorf("failed to get current SELinux mode:\n%w", err)
183+
return fmt.Errorf("failed to get current SELinux mode: %w", err)
168184
}
169185

170186
if selinuxMode == imagecustomizerapi.SELinuxModeDefault || selinuxMode == currentSELinuxMode {
171-
// Don't need to change the configured SELinux mode.
172187
return nil
173188
}
174189

175-
logger.Log.Infof("Configuring SELinux mode")
190+
logger.Log.Infof("Updating SELinux mode from ('%s') to ('%s') for GRUB-based system", currentSELinuxMode, selinuxMode)
176191

177192
err = bootCustomizer.UpdateSELinuxCommandLineForEMU(selinuxMode)
178193
if err != nil {
179-
return err
194+
return fmt.Errorf("failed to update SELinux kernel cmdline: %w", err)
180195
}
181196

182-
err = imagecustomizerlib.UpdateSELinuxModeInConfigFile(selinuxMode, dummyChroot)
197+
err = imagecustomizerlib.UpdateSELinuxModeInConfigFile(selinuxMode, installChroot)
183198
if err != nil {
184-
return fmt.Errorf("failed to update /etc/selinux/config:\n%w", err)
199+
return fmt.Errorf("failed to update SELinux mode in config file: %w", err)
185200
}
186201

187-
// No need to set SELinux labels here as in trident there is reset labels at the end
188202
return nil
189203
}
204+
205+
func grubConfigSupportExists(installChroot safechroot.ChrootInterface) bool {
206+
cfgPath := filepath.Join(installChroot.RootDir(), installutils.GrubCfgFile)
207+
defPath := filepath.Join(installChroot.RootDir(), installutils.GrubDefFile)
208+
209+
cfgExists := false
210+
if _, err := os.Stat(cfgPath); err == nil {
211+
cfgExists = true
212+
}
213+
214+
defExists := false
215+
if _, err := os.Stat(defPath); err == nil {
216+
defExists = true
217+
}
218+
219+
return cfgExists && defExists
220+
}

0 commit comments

Comments
 (0)