mirror of
https://github.com/token2/snapd.git
synced 2026-03-13 11:15:47 -07:00
Revert commit r151 and use lsblk again to find partition layout.
This commit is contained in:
@@ -34,7 +34,6 @@ import (
|
||||
"os/signal"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
@@ -64,12 +63,6 @@ const BOOT_PARTITION_LABEL = "system-boot"
|
||||
// FIXME: Should query system-image-cli (see bug LP:#1380574).
|
||||
const DEFAULT_CACHE_DIR = "/writable/cache"
|
||||
|
||||
// Directory created by udev that allows a non-priv user to list the
|
||||
// available disk partitions by partition label.
|
||||
var diskDeviceDir = "/dev/disk/by-partlabel"
|
||||
|
||||
var mountsFile = "/proc/self/mounts"
|
||||
|
||||
// Directory to mount writable root filesystem below the cache
|
||||
// diretory.
|
||||
const MOUNT_TARGET = "system"
|
||||
@@ -158,31 +151,6 @@ type blockDevice struct {
|
||||
mountpoint string
|
||||
}
|
||||
|
||||
// similar to a "struct mntent"
|
||||
type mntEnt struct {
|
||||
Device string
|
||||
MountPoint string
|
||||
Type string
|
||||
Options []string
|
||||
DumpFreq int
|
||||
FsckPassNo int
|
||||
}
|
||||
|
||||
// Return the mountpoint for the specified disk partition by inspecting the
|
||||
// provided mount entries.
|
||||
func getMountPoint(mounts []mntEnt, partition string) string {
|
||||
for _, entry := range mounts {
|
||||
// Note that we have to special-case the rootfs mount
|
||||
// since there are *two* entries in the mount table; one
|
||||
// for mountpoint "/root", the other for "/".
|
||||
if entry.Device == partition && entry.MountPoint != "/root" {
|
||||
return entry.MountPoint
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// Representation of HARDWARE_SPEC_FILE
|
||||
type hardwareSpecType struct {
|
||||
Kernel string `yaml:"kernel"`
|
||||
@@ -330,136 +298,84 @@ func stringInSlice(slice []string, value string) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
// Returns all current mounts
|
||||
var getMounts = func(mountsFile string) (mounts []mntEnt, err error) {
|
||||
lines, err := readLines(mountsFile)
|
||||
if err != nil {
|
||||
return mounts, err
|
||||
}
|
||||
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
|
||||
if len(fields) < 6 {
|
||||
// handle invalid input.
|
||||
continue
|
||||
}
|
||||
|
||||
options := strings.Split(fields[3], ",")
|
||||
|
||||
dumpFreq, err := strconv.Atoi(fields[4])
|
||||
if err != nil {
|
||||
return mounts, err
|
||||
}
|
||||
|
||||
fsckPassNo, err := strconv.Atoi(fields[5])
|
||||
if err != nil {
|
||||
return mounts, err
|
||||
}
|
||||
|
||||
m := mntEnt{
|
||||
Device: fields[0],
|
||||
MountPoint: fields[1],
|
||||
Type: fields[2],
|
||||
Options: options,
|
||||
DumpFreq: dumpFreq,
|
||||
FsckPassNo: fsckPassNo,
|
||||
}
|
||||
|
||||
mounts = append(mounts, m)
|
||||
}
|
||||
|
||||
return mounts, err
|
||||
}
|
||||
|
||||
// Returns a hash of recognised partitions in the following form:
|
||||
//
|
||||
// key: name of recognised partition.
|
||||
// value: full path to disk device for the partition.
|
||||
func getPartitions(deviceDir string) (m map[string]string, err error) {
|
||||
|
||||
recognised := allPartitionLabels()
|
||||
|
||||
m = make(map[string]string)
|
||||
|
||||
entries, err := ioutil.ReadDir(deviceDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
pos := stringInSlice(recognised, entry.Name())
|
||||
if pos < 0 {
|
||||
// ignore unrecognised partitions
|
||||
continue
|
||||
}
|
||||
isSymLink := (entry.Mode() & os.ModeSymlink) == os.ModeSymlink
|
||||
|
||||
fullPath := path.Join(deviceDir, entry.Name())
|
||||
|
||||
if isSymLink {
|
||||
dest, err := os.Readlink(fullPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var cleaned string
|
||||
|
||||
if strings.HasPrefix(dest, "..") {
|
||||
cleaned = path.Clean(path.Join(deviceDir, dest))
|
||||
} else {
|
||||
cleaned = path.Clean(dest)
|
||||
}
|
||||
|
||||
fullPath = cleaned
|
||||
}
|
||||
|
||||
m[entry.Name()] = fullPath
|
||||
}
|
||||
|
||||
return m, nil
|
||||
var runLsblk = func() (output []string, err error) {
|
||||
return runCommandWithStdout(
|
||||
"/bin/lsblk",
|
||||
"--ascii",
|
||||
"--output=NAME,LABEL,PKNAME,MOUNTPOINT",
|
||||
"--pairs")
|
||||
}
|
||||
|
||||
// Determine details of the recognised disk partitions
|
||||
// available on the system via lsblk
|
||||
func loadPartitionDetails() (partitions []blockDevice, err error) {
|
||||
var recognised []string = allPartitionLabels()
|
||||
|
||||
pm, err := getPartitions(diskDeviceDir)
|
||||
lines, err := runLsblk()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return partitions, err
|
||||
}
|
||||
pattern := regexp.MustCompile(`(?:[^\s"]|"(?:[^"])*")+`)
|
||||
|
||||
mounts, err := getMounts(mountsFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, line := range lines {
|
||||
fields := make(map[string]string)
|
||||
|
||||
// XXX: allow a prefix (".*") for test code.
|
||||
diskPattern := regexp.MustCompile(`(.*/dev/[^\d]*)\d+`)
|
||||
// split the line into 'NAME="quoted value"' fields
|
||||
matches := pattern.FindAllString(line, -1)
|
||||
|
||||
for name, device := range pm {
|
||||
// convert partition device to parent disk device by stripping
|
||||
// off the numeric partition number.
|
||||
// FIXME: this is crude and probably fragile.
|
||||
matches := diskPattern.FindAllStringSubmatch(device, -1)
|
||||
for _, match := range matches {
|
||||
tmp := strings.Split(match, "=")
|
||||
name := tmp[0]
|
||||
|
||||
if matches == nil {
|
||||
return nil,
|
||||
errors.New(fmt.Sprintf("failed to find disk associated with partition %q", device))
|
||||
// remove quotes
|
||||
value := strings.Trim(tmp[1], `"`)
|
||||
|
||||
// store
|
||||
fields[name] = value
|
||||
}
|
||||
|
||||
disk := matches[0][1]
|
||||
|
||||
if !fileExists(disk) {
|
||||
// Look for expected partition labels
|
||||
name, ok := fields["LABEL"]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
mountPoint := getMountPoint(mounts, device)
|
||||
if name == "" || name == "\"\"" {
|
||||
continue
|
||||
}
|
||||
|
||||
pos := stringInSlice(recognised, name)
|
||||
if pos < 0 {
|
||||
// ignore unrecognised partitions
|
||||
continue
|
||||
}
|
||||
|
||||
// reconstruct full path to disk partition device
|
||||
device := fmt.Sprintf("/dev/%s", fields["NAME"])
|
||||
|
||||
// FIXME: we should have a way to mock the "/dev" dir
|
||||
// or we skip this test lsblk never returns non-existing
|
||||
// devices
|
||||
/*
|
||||
if err := FileExists(device); err != nil {
|
||||
continue
|
||||
}
|
||||
*/
|
||||
// reconstruct full path to entire disk device
|
||||
disk := fmt.Sprintf("/dev/%s", fields["PKNAME"])
|
||||
|
||||
// FIXME: we should have a way to mock the "/dev" dir
|
||||
// or we skip this test lsblk never returns non-existing
|
||||
// files
|
||||
/*
|
||||
if err := FileExists(disk); err != nil {
|
||||
continue
|
||||
}
|
||||
*/
|
||||
bd := blockDevice{
|
||||
name: name,
|
||||
name: fields["LABEL"],
|
||||
device: device,
|
||||
mountpoint: mountPoint,
|
||||
mountpoint: fields["MOUNTPOINT"],
|
||||
parentName: disk,
|
||||
}
|
||||
|
||||
@@ -711,7 +627,7 @@ func (p *Partition) rootPartition() (result *blockDevice) {
|
||||
}
|
||||
|
||||
// Return pointer to blockDevice representing the "other" root
|
||||
// filesystem (which is not currently active)
|
||||
// filesystem (which is not currently mounted)
|
||||
func (p *Partition) otherRootPartition() (result *blockDevice) {
|
||||
for _, part := range p.rootPartitions() {
|
||||
if part.mountpoint != "/" {
|
||||
@@ -791,11 +707,17 @@ func (p *Partition) unmountOtherRootfs() (err error) {
|
||||
// The bootloader requires a few filesystems to be mounted when
|
||||
// run from within a chroot.
|
||||
func (p *Partition) bindmountRequiredFilesystems() (err error) {
|
||||
var boot *blockDevice
|
||||
|
||||
// Minimal list of mounts required for running grub-install
|
||||
// within a chroot.
|
||||
for _, fs := range []string{"/dev", "/proc", "/sys"} {
|
||||
// we always requires these
|
||||
requiredChrootMounts := []string{"/dev", "/proc", "/sys"}
|
||||
|
||||
// if there is a boot partition we also bind-mount it
|
||||
boot := p.bootPartition()
|
||||
if boot != nil && boot.mountpoint != "" {
|
||||
requiredChrootMounts = append(requiredChrootMounts, boot.mountpoint)
|
||||
}
|
||||
|
||||
for _, fs := range requiredChrootMounts {
|
||||
target := path.Join(p.MountTarget(), fs)
|
||||
|
||||
err := bindmountAndAddToGlobalMountList(fs, target)
|
||||
@@ -804,24 +726,7 @@ func (p *Partition) bindmountRequiredFilesystems() (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
boot = p.bootPartition()
|
||||
if boot == nil {
|
||||
// No separate boot partition
|
||||
return nil
|
||||
}
|
||||
|
||||
if boot.mountpoint == "" {
|
||||
// Impossible situation
|
||||
return nil
|
||||
}
|
||||
|
||||
target := path.Join(p.MountTarget(), boot.mountpoint)
|
||||
err = bindmountAndAddToGlobalMountList(boot.mountpoint, target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// Undo the effects of BindmountRequiredFilesystems()
|
||||
|
||||
@@ -2,11 +2,8 @@ package partition
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -22,28 +19,6 @@ type PartitionTestSuite struct {
|
||||
|
||||
var _ = Suite(&PartitionTestSuite{})
|
||||
|
||||
// Create an empty file specified by path
|
||||
func createEmptyFile(path string) (err error) {
|
||||
return ioutil.WriteFile(path, []byte(""), 0640)
|
||||
}
|
||||
|
||||
// Run specified function from directory dir
|
||||
func runChdir(dir string, f func() (err error)) (err error) {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = os.Chdir(dir); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
err = os.Chdir(cwd)
|
||||
}()
|
||||
|
||||
return f()
|
||||
}
|
||||
|
||||
func makeHardwareYaml() (tmp *os.File, err error) {
|
||||
tmp, err = ioutil.TempFile("", "hw-")
|
||||
if err != nil {
|
||||
@@ -59,130 +34,16 @@ bootloader: uboot
|
||||
return tmp, err
|
||||
}
|
||||
|
||||
// Create a fake "/proc/self/mounts"-format file containing only the entries
|
||||
// we care about.
|
||||
func makeMountsFile(replaceMap map[string]string) (filename string, err error) {
|
||||
template := []string{"/dev/sda2 /boot/efi vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 0",
|
||||
"/dev/sda2 /boot/grub vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 0",
|
||||
"/dev/sda3 /root ext4 ro,relatime,data=ordered 0 0",
|
||||
"/dev/sda3 / ext4 ro,relatime,data=ordered 0 0",
|
||||
"/dev/sda4 /writable/cache/system ext4 ro,relatime,data=ordered 0 0",
|
||||
"/dev/sda5 /writable ext4 rw,relatime,discard,data=ordered 0 0"}
|
||||
|
||||
var lines []string
|
||||
|
||||
for _, line := range template {
|
||||
for from, to := range replaceMap {
|
||||
line = strings.Replace(line, from, to, -1)
|
||||
}
|
||||
lines = append(lines, line)
|
||||
}
|
||||
|
||||
tmp, err := ioutil.TempFile("", "mounts-")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, line := range lines {
|
||||
tmp.WriteString(fmt.Sprintf("%s\n", line))
|
||||
}
|
||||
|
||||
tmp.Close()
|
||||
|
||||
return tmp.Name(), err
|
||||
}
|
||||
|
||||
// Create a fake directory tree that is similar to that created by udev
|
||||
// as /dev/disk/by-partlabel/.
|
||||
func makeDeviceDirs(disk string, deviceMap map[string]string) (parent string, linkDir string, err error) {
|
||||
|
||||
parent, err = ioutil.TempDir("", "mounts-parent-")
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
devDir := path.Join(parent, "dev")
|
||||
linkDir = path.Join(devDir, "disk", "by-partlabel")
|
||||
os.MkdirAll(linkDir, 0755)
|
||||
|
||||
// Create the fake overall disk device
|
||||
if err = createEmptyFile(path.Join(devDir, disk)); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
for name, label := range deviceMap {
|
||||
// Create the fake partition device
|
||||
if err = createEmptyFile(path.Join(devDir, name)); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
relativePath := fmt.Sprintf("../../%s", name)
|
||||
|
||||
// create the symlink pointing to the fake device
|
||||
err = runChdir(linkDir, func() (err error) {
|
||||
cmd := exec.Command("/bin/ln", "-s", relativePath, label)
|
||||
return cmd.Run()
|
||||
})
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
return parent, linkDir, nil
|
||||
}
|
||||
|
||||
func makeMountsFileAndDevices(dualRootfs bool) (mountsFile string, parentDevDir string, devDir string, err error) {
|
||||
|
||||
disk := "sda"
|
||||
devs := map[string]string{
|
||||
"sda1": "grub",
|
||||
"sda2": "system-boot",
|
||||
"sda3": "system-a",
|
||||
"sda5": "writable",
|
||||
}
|
||||
|
||||
if dualRootfs {
|
||||
devs["sda4"] = "system-b"
|
||||
}
|
||||
|
||||
parentDevDir, devDir, err = makeDeviceDirs(disk, devs)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
replacements := make(map[string]string)
|
||||
|
||||
for dev, _ := range devs {
|
||||
replacements[fmt.Sprintf("/dev/%s", dev)] =
|
||||
path.Join(parentDevDir, "/dev", dev)
|
||||
}
|
||||
|
||||
if mountsFile, err = makeMountsFile(replacements); err != nil {
|
||||
return mountsFile, parentDevDir, devDir, err
|
||||
}
|
||||
|
||||
return mountsFile, parentDevDir, devDir, err
|
||||
}
|
||||
|
||||
func (s *PartitionTestSuite) TestHardwareSpec(c *C) {
|
||||
mockMountsFile, parentDevDir, deviceDir, err := makeMountsFileAndDevices(true)
|
||||
c.Assert(err, IsNil)
|
||||
defer func() {
|
||||
os.Remove(mockMountsFile)
|
||||
os.RemoveAll(parentDevDir)
|
||||
}()
|
||||
|
||||
diskDeviceDir = deviceDir
|
||||
mountsFile = mockMountsFile
|
||||
|
||||
p := New()
|
||||
c.Assert(p, NotNil)
|
||||
|
||||
tmp2, err := makeHardwareYaml()
|
||||
tmp, err := makeHardwareYaml()
|
||||
defer func() {
|
||||
os.Remove(tmp2.Name())
|
||||
os.Remove(tmp.Name())
|
||||
}()
|
||||
|
||||
p.hardwareSpecFile = tmp2.Name()
|
||||
p.hardwareSpecFile = tmp.Name()
|
||||
hw, err := p.hardwareSpec()
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(hw.Kernel, Equals, "assets/vmlinuz")
|
||||
@@ -192,82 +53,60 @@ func (s *PartitionTestSuite) TestHardwareSpec(c *C) {
|
||||
c.Assert(hw.Bootloader, Equals, "uboot")
|
||||
}
|
||||
|
||||
func mockRunLsblkDualSnappy() (output []string, err error) {
|
||||
dualData := `
|
||||
NAME="sda" LABEL="" PKNAME="" MOUNTPOINT=""
|
||||
NAME="sda1" LABEL="" PKNAME="sda" MOUNTPOINT=""
|
||||
NAME="sda2" LABEL="system-boot" PKNAME="sda" MOUNTPOINT="/boot/efi"
|
||||
NAME="sda3" LABEL="system-a" PKNAME="sda" MOUNTPOINT="/"
|
||||
NAME="sda4" LABEL="system-b" PKNAME="sda" MOUNTPOINT=""
|
||||
NAME="sda5" LABEL="writable" PKNAME="sda" MOUNTPOINT="/writable"
|
||||
NAME="sr0" LABEL="" PKNAME="" MOUNTPOINT=""
|
||||
`
|
||||
return strings.Split(dualData, "\n"), err
|
||||
}
|
||||
|
||||
func (s *PartitionTestSuite) TestSnappyDualRoot(c *C) {
|
||||
mockMountsFile, parentDevDir, deviceDir, err := makeMountsFileAndDevices(true)
|
||||
c.Assert(err, IsNil)
|
||||
defer func() {
|
||||
os.Remove(mockMountsFile)
|
||||
os.RemoveAll(parentDevDir)
|
||||
}()
|
||||
diskDeviceDir = deviceDir
|
||||
mountsFile = mockMountsFile
|
||||
runLsblk = mockRunLsblkDualSnappy
|
||||
|
||||
p := New()
|
||||
c.Assert(p.dualRootPartitions(), Equals, true)
|
||||
c.Assert(p.singleRootPartition(), Equals, false)
|
||||
|
||||
rootPartitions := p.rootPartitions()
|
||||
|
||||
// XXX: getPartitions() returns a map, and iteration is random.
|
||||
// Hence, we cannot rely on the order of the array returned by
|
||||
// rootPartitions() so take a sniff first...
|
||||
var aIndex int
|
||||
var bIndex int
|
||||
|
||||
if rootPartitions[0].name == "system-a" {
|
||||
aIndex = 0
|
||||
bIndex = 1
|
||||
} else {
|
||||
aIndex = 1
|
||||
bIndex = 0
|
||||
}
|
||||
|
||||
c.Assert(rootPartitions[aIndex].name, Equals, "system-a")
|
||||
c.Assert(strings.HasSuffix(rootPartitions[aIndex].device, "/dev/sda3"), Equals, true)
|
||||
c.Assert(strings.HasSuffix(rootPartitions[aIndex].parentName, "/dev/sda"), Equals, true)
|
||||
|
||||
c.Assert(rootPartitions[bIndex].name, Equals, "system-b")
|
||||
c.Assert(strings.HasSuffix(rootPartitions[bIndex].device, "/dev/sda4"), Equals, true)
|
||||
c.Assert(strings.HasSuffix(rootPartitions[bIndex].parentName, "/dev/sda"), Equals, true)
|
||||
c.Assert(rootPartitions[0].name, Equals, "system-a")
|
||||
c.Assert(rootPartitions[0].device, Equals, "/dev/sda3")
|
||||
c.Assert(rootPartitions[0].parentName, Equals, "/dev/sda")
|
||||
c.Assert(rootPartitions[1].name, Equals, "system-b")
|
||||
c.Assert(rootPartitions[1].device, Equals, "/dev/sda4")
|
||||
c.Assert(rootPartitions[1].parentName, Equals, "/dev/sda")
|
||||
|
||||
wp := p.writablePartition()
|
||||
c.Assert(wp.name, Equals, "writable")
|
||||
|
||||
c.Assert(strings.HasSuffix(wp.device, "/dev/sda5"), Equals, true)
|
||||
c.Assert(strings.HasSuffix(wp.parentName, "/dev/sda"), Equals, true)
|
||||
c.Assert(wp.device, Equals, "/dev/sda5")
|
||||
c.Assert(wp.parentName, Equals, "/dev/sda")
|
||||
|
||||
boot := p.bootPartition()
|
||||
c.Assert(boot.name, Equals, "system-boot")
|
||||
|
||||
c.Assert(strings.HasSuffix(boot.device, "/dev/sda2"), Equals, true)
|
||||
c.Assert(strings.HasSuffix(boot.parentName, "/dev/sda"), Equals, true)
|
||||
c.Assert(boot.device, Equals, "/dev/sda2")
|
||||
c.Assert(boot.parentName, Equals, "/dev/sda")
|
||||
|
||||
root := p.rootPartition()
|
||||
c.Assert(root, Not(IsNil))
|
||||
c.Assert(root.name, Equals, "system-a")
|
||||
|
||||
c.Assert(strings.HasSuffix(root.device, "/dev/sda3"), Equals, true)
|
||||
c.Assert(strings.HasSuffix(root.parentName, "/dev/sda"), Equals, true)
|
||||
c.Assert(root.device, Equals, "/dev/sda3")
|
||||
c.Assert(root.parentName, Equals, "/dev/sda")
|
||||
|
||||
other := p.otherRootPartition()
|
||||
c.Assert(other.name, Equals, "system-b")
|
||||
c.Assert(strings.HasSuffix(other.device, "/dev/sda4"), Equals, true)
|
||||
c.Assert(strings.HasSuffix(other.parentName, "/dev/sda"), Equals, true)
|
||||
c.Assert(other.device, Equals, "/dev/sda4")
|
||||
c.Assert(other.parentName, Equals, "/dev/sda")
|
||||
}
|
||||
|
||||
func (s *PartitionTestSuite) TestRunWithOtherDualParitionRO(c *C) {
|
||||
mockMountsFile, parentDevDir, deviceDir, err := makeMountsFileAndDevices(true)
|
||||
c.Assert(err, IsNil)
|
||||
defer func() {
|
||||
os.Remove(mockMountsFile)
|
||||
os.RemoveAll(parentDevDir)
|
||||
}()
|
||||
diskDeviceDir = deviceDir
|
||||
mountsFile = mockMountsFile
|
||||
|
||||
runLsblk = mockRunLsblkDualSnappy
|
||||
p := New()
|
||||
reportedRoot := ""
|
||||
err = p.RunWithOther(RO, func(otherRoot string) (err error) {
|
||||
err := p.RunWithOther(RO, func(otherRoot string) (err error) {
|
||||
reportedRoot = otherRoot
|
||||
return nil
|
||||
})
|
||||
@@ -276,14 +115,7 @@ func (s *PartitionTestSuite) TestRunWithOtherDualParitionRO(c *C) {
|
||||
}
|
||||
|
||||
func (s *PartitionTestSuite) TestRunWithOtherDualParitionRWFuncErr(c *C) {
|
||||
mockMountsFile, parentDevDir, deviceDir, err := makeMountsFileAndDevices(true)
|
||||
c.Assert(err, IsNil)
|
||||
defer func() {
|
||||
os.Remove(mockMountsFile)
|
||||
os.RemoveAll(parentDevDir)
|
||||
}()
|
||||
diskDeviceDir = deviceDir
|
||||
mountsFile = mockMountsFile
|
||||
runLsblk = mockRunLsblkDualSnappy
|
||||
|
||||
savedRunCommand := runCommand
|
||||
defer func() {
|
||||
@@ -292,7 +124,7 @@ func (s *PartitionTestSuite) TestRunWithOtherDualParitionRWFuncErr(c *C) {
|
||||
runCommand = mockRunCommand
|
||||
|
||||
p := New()
|
||||
err = p.RunWithOther(RW, func(otherRoot string) (err error) {
|
||||
err := p.RunWithOther(RW, func(otherRoot string) (err error) {
|
||||
return errors.New("canary")
|
||||
})
|
||||
|
||||
@@ -307,31 +139,26 @@ func (s *PartitionTestSuite) TestRunWithOtherDualParitionRWFuncErr(c *C) {
|
||||
}
|
||||
|
||||
func (s *PartitionTestSuite) TestRunWithOtherSingleParitionRO(c *C) {
|
||||
mockMountsFile, parentDevDir, deviceDir, err := makeMountsFileAndDevices(false)
|
||||
c.Assert(err, IsNil)
|
||||
defer func() {
|
||||
os.Remove(mockMountsFile)
|
||||
os.RemoveAll(parentDevDir)
|
||||
}()
|
||||
diskDeviceDir = deviceDir
|
||||
mountsFile = mockMountsFile
|
||||
|
||||
runLsblk = mockRunLsblkSingleRootSnappy
|
||||
p := New()
|
||||
err = p.RunWithOther(RO, func(otherRoot string) (err error) {
|
||||
err := p.RunWithOther(RO, func(otherRoot string) (err error) {
|
||||
return nil
|
||||
})
|
||||
c.Assert(err, Equals, NoDualPartitionError)
|
||||
}
|
||||
|
||||
func mockRunLsblkSingleRootSnappy() (output []string, err error) {
|
||||
dualData := `
|
||||
NAME="sda" LABEL="" PKNAME="" MOUNTPOINT=""
|
||||
NAME="sda1" LABEL="" PKNAME="sda" MOUNTPOINT=""
|
||||
NAME="sda2" LABEL="system-boot" PKNAME="sda" MOUNTPOINT=""
|
||||
NAME="sda3" LABEL="system-a" PKNAME="sda" MOUNTPOINT="/"
|
||||
NAME="sda5" LABEL="writable" PKNAME="sda" MOUNTPOINT="/writable"
|
||||
`
|
||||
return strings.Split(dualData, "\n"), err
|
||||
}
|
||||
func (s *PartitionTestSuite) TestSnappySingleRoot(c *C) {
|
||||
mockMountsFile, parentDevDir, deviceDir, err := makeMountsFileAndDevices(false)
|
||||
c.Assert(err, IsNil)
|
||||
defer func() {
|
||||
os.Remove(mockMountsFile)
|
||||
os.RemoveAll(parentDevDir)
|
||||
}()
|
||||
diskDeviceDir = deviceDir
|
||||
mountsFile = mockMountsFile
|
||||
runLsblk = mockRunLsblkSingleRootSnappy
|
||||
|
||||
p := New()
|
||||
c.Assert(p.dualRootPartitions(), Equals, false)
|
||||
@@ -339,8 +166,8 @@ func (s *PartitionTestSuite) TestSnappySingleRoot(c *C) {
|
||||
|
||||
root := p.rootPartition()
|
||||
c.Assert(root.name, Equals, "system-a")
|
||||
c.Assert(strings.HasSuffix(root.device, "/dev/sda3"), Equals, true)
|
||||
c.Assert(strings.HasSuffix(root.parentName, "/dev/sda"), Equals, true)
|
||||
c.Assert(root.device, Equals, "/dev/sda3")
|
||||
c.Assert(root.parentName, Equals, "/dev/sda")
|
||||
|
||||
other := p.otherRootPartition()
|
||||
c.Assert(other, IsNil)
|
||||
@@ -354,14 +181,7 @@ func mockRunCommand(args ...string) (err error) {
|
||||
}
|
||||
|
||||
func (s *PartitionTestSuite) TestMountUnmountTracking(c *C) {
|
||||
mockMountsFile, parentDevDir, deviceDir, err := makeMountsFileAndDevices(true)
|
||||
c.Assert(err, IsNil)
|
||||
defer func() {
|
||||
os.Remove(mockMountsFile)
|
||||
os.RemoveAll(parentDevDir)
|
||||
}()
|
||||
diskDeviceDir = deviceDir
|
||||
mountsFile = mockMountsFile
|
||||
runLsblk = mockRunLsblkDualSnappy
|
||||
|
||||
// FIXME: there should be a generic
|
||||
// mockFunc(func) (restorer func())
|
||||
@@ -397,14 +217,7 @@ func (s *PartitionTestSuite) TestStringSliceRemoveNoexistingNoOp(c *C) {
|
||||
}
|
||||
|
||||
func (s *PartitionTestSuite) TestUndoMounts(c *C) {
|
||||
mockMountsFile, parentDevDir, deviceDir, err := makeMountsFileAndDevices(true)
|
||||
c.Assert(err, IsNil)
|
||||
defer func() {
|
||||
os.Remove(mockMountsFile)
|
||||
os.RemoveAll(parentDevDir)
|
||||
}()
|
||||
diskDeviceDir = deviceDir
|
||||
mountsFile = mockMountsFile
|
||||
runLsblk = mockRunLsblkDualSnappy
|
||||
|
||||
// FIXME: there should be a generic
|
||||
// mockFunc(func) (restorer func())
|
||||
@@ -419,13 +232,12 @@ func (s *PartitionTestSuite) TestUndoMounts(c *C) {
|
||||
// FIXME: mounts is global
|
||||
c.Assert(mounts, DeepEquals, []string{})
|
||||
p.bindmountRequiredFilesystems()
|
||||
|
||||
// check expected values
|
||||
c.Assert(stringInSlice(mounts, "/writable/cache/system/dev"), Not(Equals), -1)
|
||||
c.Assert(stringInSlice(mounts, "/writable/cache/system/proc"), Not(Equals), -1)
|
||||
c.Assert(stringInSlice(mounts, "/writable/cache/system/sys"), Not(Equals), -1)
|
||||
c.Assert(stringInSlice(mounts, "/writable/cache/system/boot/efi"), Not(Equals), -1)
|
||||
|
||||
c.Assert(mounts, DeepEquals, []string{
|
||||
p.MountTarget() + "/dev",
|
||||
p.MountTarget() + "/proc",
|
||||
p.MountTarget() + "/sys",
|
||||
p.MountTarget() + "/boot/efi",
|
||||
})
|
||||
p.unmountRequiredFilesystems()
|
||||
c.Assert(mounts, DeepEquals, []string{})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user