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

Bug 1861026: daemon: perform other rpm-ostree operations after OS rebase #2029

Merged
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
28 changes: 3 additions & 25 deletions cmd/machine-config-daemon/pivot.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ import (

// flag storage
var keep bool
var reboot bool
var fromEtcPullSpec bool

const (
etcPivotFile = "/etc/pivot/image-pullspec"
runPivotRebootFile = "/run/pivot/reboot-needed"
// etcPivotFile is used for 4.1 bootimages and is how the MCD
// currently communicated with this service.
Copy link
Member

Choose a reason for hiding this comment

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

nit: Unclear as to if this means now or previously. Currently would indicate it's in use now while communicated would indicate the past.

Copy link
Member

Choose a reason for hiding this comment

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

etcPivotFile = "/etc/pivot/image-pullspec"
// File containing kernel arg changes for tuning
kernelTuningFile = "/etc/pivot/kernel-args"
cmdLineFile = "/proc/cmdline"
Expand All @@ -51,7 +51,6 @@ var pivotCmd = &cobra.Command{
func init() {
rootCmd.AddCommand(pivotCmd)
pivotCmd.PersistentFlags().BoolVarP(&keep, "keep", "k", false, "Do not remove container image")
pivotCmd.PersistentFlags().BoolVarP(&reboot, "reboot", "r", false, "Reboot if changed")
pivotCmd.PersistentFlags().BoolVarP(&fromEtcPullSpec, "from-etc-pullspec", "P", false, "Parse /etc/pivot/image-pullspec")
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
}
Expand Down Expand Up @@ -232,29 +231,8 @@ func run(_ *cobra.Command, args []string) error {

if !changed {
glog.Info("No changes; already at target oscontainer, no kernel args provided")
return nil
}

if reboot {
glog.Infof("Rebooting as requested by cmdline flag")
} else {
// Otherwise see if it's specified by the file
_, err = os.Stat(runPivotRebootFile)
if err != nil && !os.IsNotExist(err) {
return errors.Wrapf(err, "Checking %s", runPivotRebootFile)
}
if err == nil {
glog.Infof("Rebooting due to %s", runPivotRebootFile)
reboot = true
}
}
if reboot {
// Reboot the machine if asked to do so
err := exec.Command("systemctl", "reboot").Run()
if err != nil {
return errors.Wrapf(err, "rebooting")
}
}
return nil
}

Expand Down
6 changes: 5 additions & 1 deletion pkg/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,11 @@ func (dn *Daemon) checkStateOnFirstRun() error {
if !osMatch {
glog.Infof("Bootstrap pivot required to: %s", targetOSImageURL)
// This only returns on error
return dn.updateOSAndReboot(state.currentConfig)
if err := dn.updateOS(state.currentConfig); err != nil {
return err
}

return dn.finalizeAndReboot(state.currentConfig)
}
glog.Info("No bootstrap pivot required; unlinking bootstrap node annotations")

Expand Down
3 changes: 2 additions & 1 deletion pkg/daemon/rpm-ostree.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,8 @@ func (r *RpmOstreeClient) RunPivot(osImageURL string) error {
defer close(journalStopCh)
go followPivotJournalLogs(journalStopCh)

// This is written by code injected by the MCS, but we always want the MCD to be in control of reboots
// This is written by code injected by the MCS for compatibility with 4.1 bootimages,
// remove it to clean things up.
if err := os.Remove("/run/pivot/reboot-needed"); err != nil && !os.IsNotExist(err) {
return errors.Wrap(err, "deleting pivot reboot-needed file")
}
Expand Down
59 changes: 37 additions & 22 deletions pkg/daemon/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,42 @@ func getNodeRef(node *corev1.Node) *corev1.ObjectReference {
}
}

// updateOSAndReboot is the last step in an update(), and it can also
// be called as a special case for the "bootstrap pivot".
func (dn *Daemon) updateOSAndReboot(newConfig *mcfgv1.MachineConfig) (retErr error) {
// Remove pending deployment on OSTree based system
func removePendingDeployment() error {
_, err := runGetOut("rpm-ostree", "cleanup", "-p")
return err
}

func (dn *Daemon) applyOSChanges(oldConfig, newConfig *mcfgv1.MachineConfig) (retErr error) {
if err := dn.updateOS(newConfig); err != nil {
return err
}
return dn.finalizeAndReboot(newConfig)

defer func() {
// Operations performed by rpm-ostree on the booted system are available
// as staged deployment. It gets applied only when we reboot the system.
// In case of an error during any rpm-ostree transaction, removing pending deployment
// should be sufficient to discard any applied changes.
if retErr != nil {
glog.Infof("Rolling back applied changes to OS")
if err := removePendingDeployment(); err != nil {
retErr = errors.Wrapf(retErr, "error removing staged deployment: %v", err)
return
}
}
}()

// kargs
if err := dn.updateKernelArguments(oldConfig, newConfig); err != nil {
return err
}

// Switch to real time kernel
if err := dn.switchKernel(oldConfig, newConfig); err != nil {
return err
}

return nil
}

func (dn *Daemon) finalizeAndReboot(newConfig *mcfgv1.MachineConfig) (retErr error) {
Expand Down Expand Up @@ -353,34 +382,20 @@ func (dn *Daemon) update(oldConfig, newConfig *mcfgv1.MachineConfig) (retErr err
}
}()

// kargs
if err := dn.updateKernelArguments(oldConfig, newConfig); err != nil {
return err
}
defer func() {
if retErr != nil {
if err := dn.updateKernelArguments(newConfig, oldConfig); err != nil {
retErr = errors.Wrapf(retErr, "error rolling back kernel arguments %v", err)
return
}
}
}()

// Switch to real time kernel
if err := dn.switchKernel(oldConfig, newConfig); err != nil {
if err := dn.applyOSChanges(oldConfig, newConfig); err != nil {
return err
}

defer func() {
if retErr != nil {
if err := dn.switchKernel(newConfig, oldConfig); err != nil {
retErr = errors.Wrapf(retErr, "error rolling back Real time Kernel %v", err)
if err := dn.applyOSChanges(newConfig, oldConfig); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Not strictly related to this change but we're now grouping the "defer rollback" of the kargs/kernel type switch - I was going to comment about how this might cause us to incorrectly roll kargs back if we failed at the kernel type switch but then I realized:

The only defer rollback we need is the removePendingDeployment() - that reverts everything.

(I think that defer will run last and hence win, so this code is fine as is)

retErr = errors.Wrapf(retErr, "error rolling back changes to OS %v", err)
return
}
}
}()

return dn.updateOSAndReboot(newConfig)
return dn.finalizeAndReboot(newConfig)
}

// MachineConfigDiff represents an ad-hoc difference between two MachineConfig objects.
Expand Down