// setNextBoot will schedule the given os or kernel snap to be used in // the next boot func setNextBoot(s *snap.Info) error { if s.Type != snap.TypeOS && s.Type != snap.TypeKernel { return nil } bootloader, err := findBootloader() if err != nil { return fmt.Errorf("can not set next boot: %s", err) } var bootvar string switch s.Type { case snap.TypeOS: bootvar = "snappy_os" case snap.TypeKernel: bootvar = "snappy_kernel" } blobName := filepath.Base(s.MountFile()) if err := bootloader.SetBootVar(bootvar, blobName); err != nil { return err } if err := bootloader.SetBootVar("snappy_mode", "try"); err != nil { return err } return nil }
// extractKernelAssets extracts kernel/initrd/dtb data from the given // Snap to a versionized bootloader directory so that the bootloader // can use it. func extractKernelAssets(s *snap.Info, snapf snap.File, flags InstallFlags, inter progress.Meter) error { if s.Type != snap.TypeKernel { return fmt.Errorf("can not extract kernel assets from snap type %q", s.Type) } bootloader, err := findBootloader() if err != nil { return fmt.Errorf("can not extract kernel assets: %s", err) } // check if we are on a "grub" system. if so, no need to unpack // the kernel if oem, err := getGadget(); err == nil { if oem.Legacy.Gadget.Hardware.Bootloader == "grub" { return nil } } // now do the kernel specific bits blobName := filepath.Base(s.MountFile()) dstDir := filepath.Join(bootloader.Dir(), blobName) if err := os.MkdirAll(dstDir, 0755); err != nil { return err } dir, err := os.Open(dstDir) if err != nil { return err } defer dir.Close() for _, src := range []string{s.Legacy.Kernel, s.Legacy.Initrd} { if src == "" { continue } if err := snapf.Unpack(src, dstDir); err != nil { return err } src = filepath.Join(dstDir, src) dst := filepath.Join(dstDir, dropVersionSuffix(src)) if err := os.Rename(src, dst); err != nil { return err } if err := dir.Sync(); err != nil { return err } } if s.Legacy.Dtbs != "" { src := filepath.Join(s.Legacy.Dtbs, "*") dst := dstDir if err := snapf.Unpack(src, dst); err != nil { return err } } return dir.Sync() }
func addSquashfsMount(s *snap.Info, inhibitHooks bool, inter interacter) error { squashfsPath := stripGlobalRootDir(s.MountFile()) whereDir := stripGlobalRootDir(s.MountDir()) sysd := systemd.New(dirs.GlobalRootDir, inter) mountUnitName, err := sysd.WriteMountUnitFile(s.Name(), squashfsPath, whereDir) if err != nil { return err } // we always enable the mount unit even in inhibit hooks if err := sysd.Enable(mountUnitName); err != nil { return err } if !inhibitHooks { return sysd.Start(mountUnitName) } return nil }
func kernelOrOsRebootRequired(s *snap.Info) bool { if s.Type != snap.TypeKernel && s.Type != snap.TypeOS { return false } bootloader, err := findBootloader() if err != nil { logger.Noticef("can not get boot settings: %s", err) return false } var nextBoot, goodBoot string switch s.Type { case snap.TypeKernel: nextBoot = "snappy_kernel" goodBoot = "snappy_good_kernel" case snap.TypeOS: nextBoot = "snappy_os" goodBoot = "snappy_good_os" } nextBootVer, err := bootloader.GetBootVar(nextBoot) if err != nil { return false } goodBootVer, err := bootloader.GetBootVar(goodBoot) if err != nil { return false } squashfsName := filepath.Base(s.MountFile()) if nextBootVer == squashfsName && goodBootVer != nextBootVer { return true } return false }