// KernelOrOsRebootRequired returns whether a reboot is required to swith to the given OS or kernel snap. func KernelOrOsRebootRequired(s *snap.Info) bool { if s.Type != snap.TypeKernel && s.Type != snap.TypeOS { return false } bootloader, err := partition.FindBootloader() if err != nil { logger.Noticef("cannot get boot settings: %s", err) return false } var nextBoot, goodBoot string switch s.Type { case snap.TypeKernel: nextBoot = "snap_try_kernel" goodBoot = "snap_kernel" case snap.TypeOS: nextBoot = "snap_try_core" goodBoot = "snap_core" } m, err := bootloader.GetBootVars(nextBoot, goodBoot) if err != nil { return false } squashfsName := filepath.Base(s.MountFile()) if m[nextBoot] == squashfsName && m[goodBoot] != m[nextBoot] { return true } return false }
// SetNextBoot will schedule the given OS or kernel snap to be used in // the next boot func SetNextBoot(s *snap.Info) error { if release.OnClassic { return nil } if s.Type != snap.TypeOS && s.Type != snap.TypeKernel { return nil } bootloader, err := partition.FindBootloader() if err != nil { return fmt.Errorf("cannot set next boot: %s", err) } var bootvar string switch s.Type { case snap.TypeOS: bootvar = "snap_try_core" case snap.TypeKernel: bootvar = "snap_try_kernel" } blobName := filepath.Base(s.MountFile()) if err := bootloader.SetBootVar(bootvar, blobName); err != nil { return err } if err := bootloader.SetBootVar("snap_mode", "try"); err != nil { return err } return nil }
// ExtractKernelAssets extracts kernel/initrd/dtb data from the given // kernel snap, if required, to a versioned bootloader directory so // that the bootloader can use it. func ExtractKernelAssets(s *snap.Info, snapf snap.Container) error { if s.Type != snap.TypeKernel { return fmt.Errorf("cannot extract kernel assets from snap type %q", s.Type) } bootloader, err := partition.FindBootloader() if err != nil { return fmt.Errorf("cannot extract kernel assets: %s", err) } if bootloader.Name() == "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{"kernel.img", "initrd.img"} { if err := snapf.Unpack(src, dstDir); err != nil { return err } if err := dir.Sync(); err != nil { return err } } if err := snapf.Unpack("dtbs/*", dstDir); err != nil { return err } return dir.Sync() }
// SetNextBoot will schedule the given OS or kernel snap to be used in // the next boot func SetNextBoot(s *snap.Info) error { if release.OnClassic { return nil } if s.Type != snap.TypeOS && s.Type != snap.TypeKernel { return nil } bootloader, err := partition.FindBootloader() if err != nil { return fmt.Errorf("cannot set next boot: %s", err) } var nextBoot, goodBoot string switch s.Type { case snap.TypeOS: nextBoot = "snap_try_core" goodBoot = "snap_core" case snap.TypeKernel: nextBoot = "snap_try_kernel" goodBoot = "snap_kernel" } blobName := filepath.Base(s.MountFile()) // check if we actually need to do anything, i.e. the exact same // kernel/core revision got installed again (e.g. firstboot) m, err := bootloader.GetBootVars(goodBoot) if err != nil { return err } if m[goodBoot] == blobName { return nil } return bootloader.SetBootVars(map[string]string{ nextBoot: blobName, "snap_mode": "try", }) }
func addMountUnit(s *snap.Info, meter progress.Meter) error { squashfsPath := dirs.StripRootDir(s.MountFile()) whereDir := dirs.StripRootDir(s.MountDir()) sysd := systemd.New(dirs.GlobalRootDir, meter) mountUnitName, err := sysd.WriteMountUnitFile(s.Name(), squashfsPath, whereDir, "squashfs") if err != nil { return err } // we need to do a daemon-reload here to ensure that systemd really // knows about this new mount unit file if err := sysd.DaemonReload(); err != nil { return err } if err := sysd.Enable(mountUnitName); err != nil { return err } return sysd.Start(mountUnitName) }
func copyLocalSnapFile(snapPath, targetDir string, info *snap.Info) (dstPath string, err error) { dst := filepath.Join(targetDir, filepath.Base(info.MountFile())) return dst, osutil.CopyFile(snapPath, dst, 0) }