github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/gadget/ondisk_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2019-2020 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package gadget_test
    21  
    22  import (
    23  	"io/ioutil"
    24  	"os"
    25  	"path/filepath"
    26  
    27  	. "gopkg.in/check.v1"
    28  
    29  	"github.com/snapcore/snapd/gadget"
    30  	"github.com/snapcore/snapd/testutil"
    31  )
    32  
    33  type ondiskTestSuite struct {
    34  	testutil.BaseTest
    35  
    36  	dir string
    37  
    38  	gadgetRoot string
    39  }
    40  
    41  var _ = Suite(&ondiskTestSuite{})
    42  
    43  func (s *ondiskTestSuite) SetUpTest(c *C) {
    44  	s.BaseTest.SetUpTest(c)
    45  
    46  	s.dir = c.MkDir()
    47  
    48  	s.gadgetRoot = c.MkDir()
    49  	err := makeMockGadget(s.gadgetRoot, gadgetContent)
    50  	c.Assert(err, IsNil)
    51  }
    52  
    53  const mockSfdiskScriptBiosSeed = `
    54  >&2 echo "Some warning from sfdisk"
    55  echo '{
    56    "partitiontable": {
    57      "label": "gpt",
    58      "id": "9151F25B-CDF0-48F1-9EDE-68CBD616E2CA",
    59      "device": "/dev/node",
    60      "unit": "sectors",
    61      "firstlba": 34,
    62      "lastlba": 8388574,
    63      "partitions": [
    64        {
    65          "node": "/dev/node1",
    66          "start": 2048,
    67          "size": 2048,
    68          "type": "21686148-6449-6E6F-744E-656564454649",
    69          "uuid": "2E59D969-52AB-430B-88AC-F83873519F6F",
    70          "name": "BIOS Boot"
    71        },
    72        {
    73          "node": "/dev/node2",
    74          "start": 4096,
    75          "size": 2457600,
    76          "type": "C12A7328-F81F-11D2-BA4B-00A0C93EC93B",
    77          "uuid": "44C3D5C3-CAE1-4306-83E8-DF437ACDB32F",
    78          "name": "Recovery",
    79          "attrs": "GUID:59"
    80        }
    81      ]
    82    }
    83  }'`
    84  
    85  const mockLsblkScriptBiosSeed = `
    86  [ "$3" == "/dev/node1" ] && echo '{
    87      "blockdevices": [ {"name": "node1", "fstype": null, "label": null, "uuid": null, "mountpoint": null} ]
    88  }'
    89  [ "$3" == "/dev/node2" ] && echo '{
    90      "blockdevices": [ {"name": "node2", "fstype": "vfat", "label": "ubuntu-seed", "uuid": "A644-B807", "mountpoint": null} ]
    91  }'
    92  exit 0`
    93  
    94  func makeMockGadget(gadgetRoot, gadgetContent string) error {
    95  	if err := os.MkdirAll(filepath.Join(gadgetRoot, "meta"), 0755); err != nil {
    96  		return err
    97  	}
    98  	if err := ioutil.WriteFile(filepath.Join(gadgetRoot, "meta", "gadget.yaml"), []byte(gadgetContent), 0644); err != nil {
    99  		return err
   100  	}
   101  	if err := ioutil.WriteFile(filepath.Join(gadgetRoot, "pc-boot.img"), []byte("pc-boot.img content"), 0644); err != nil {
   102  		return err
   103  	}
   104  	if err := ioutil.WriteFile(filepath.Join(gadgetRoot, "pc-core.img"), []byte("pc-core.img content"), 0644); err != nil {
   105  		return err
   106  	}
   107  	if err := ioutil.WriteFile(filepath.Join(gadgetRoot, "grubx64.efi"), []byte("grubx64.efi content"), 0644); err != nil {
   108  		return err
   109  	}
   110  
   111  	return nil
   112  }
   113  
   114  const gadgetContent = `volumes:
   115    pc:
   116      bootloader: grub
   117      structure:
   118        - name: mbr
   119          type: mbr
   120          size: 440
   121          content:
   122            - image: pc-boot.img
   123        - name: BIOS Boot
   124          type: DA,21686148-6449-6E6F-744E-656564454649
   125          size: 1M
   126          offset: 1M
   127          offset-write: mbr+92
   128          content:
   129            - image: pc-core.img
   130        - name: Recovery
   131          role: system-seed
   132          filesystem: vfat
   133          # UEFI will boot the ESP partition by default first
   134          type: EF,C12A7328-F81F-11D2-BA4B-00A0C93EC93B
   135          size: 1200M
   136          content:
   137            - source: grubx64.efi
   138              target: EFI/boot/grubx64.efi
   139        - name: Writable
   140          role: system-data
   141          filesystem: ext4
   142          type: 83,0FC63DAF-8483-4772-8E79-3D69D8477DE4
   143          size: 1200M
   144  `
   145  
   146  var mockOnDiskStructureWritable = gadget.OnDiskStructure{
   147  	Node:                 "/dev/node3",
   148  	CreatedDuringInstall: true,
   149  	LaidOutStructure: gadget.LaidOutStructure{
   150  		VolumeStructure: &gadget.VolumeStructure{
   151  			Name:       "Writable",
   152  			Size:       1258291200,
   153  			Type:       "83,0FC63DAF-8483-4772-8E79-3D69D8477DE4",
   154  			Role:       "system-data",
   155  			Label:      "ubuntu-data",
   156  			Filesystem: "ext4",
   157  		},
   158  		StartOffset: 1260388352,
   159  		Index:       3,
   160  	},
   161  }
   162  
   163  func (s *ondiskTestSuite) TestDeviceInfoGPT(c *C) {
   164  	cmdSfdisk := testutil.MockCommand(c, "sfdisk", mockSfdiskScriptBiosSeed)
   165  	defer cmdSfdisk.Restore()
   166  
   167  	cmdLsblk := testutil.MockCommand(c, "lsblk", mockLsblkScriptBiosSeed)
   168  	defer cmdLsblk.Restore()
   169  
   170  	dl, err := gadget.OnDiskVolumeFromDevice("/dev/node")
   171  	c.Assert(err, IsNil)
   172  	c.Assert(cmdSfdisk.Calls(), DeepEquals, [][]string{
   173  		{"sfdisk", "--json", "-d", "/dev/node"},
   174  	})
   175  	c.Assert(cmdLsblk.Calls(), DeepEquals, [][]string{
   176  		{"lsblk", "--fs", "--json", "/dev/node1"},
   177  		{"lsblk", "--fs", "--json", "/dev/node2"},
   178  	})
   179  	c.Assert(err, IsNil)
   180  	c.Assert(dl.Schema, Equals, "gpt")
   181  	c.Assert(dl.ID, Equals, "9151F25B-CDF0-48F1-9EDE-68CBD616E2CA")
   182  	c.Assert(dl.Device, Equals, "/dev/node")
   183  	c.Assert(dl.SectorSize, Equals, gadget.Size(512))
   184  	c.Assert(dl.Size, Equals, gadget.Size(8388575*512))
   185  	c.Assert(len(dl.Structure), Equals, 2)
   186  
   187  	c.Assert(dl.Structure, DeepEquals, []gadget.OnDiskStructure{
   188  		{
   189  			LaidOutStructure: gadget.LaidOutStructure{
   190  				VolumeStructure: &gadget.VolumeStructure{
   191  					Name:       "BIOS Boot",
   192  					Size:       0x100000,
   193  					Label:      "",
   194  					Type:       "21686148-6449-6E6F-744E-656564454649",
   195  					Filesystem: "",
   196  				},
   197  				StartOffset: 0x100000,
   198  				Index:       1,
   199  			},
   200  			Node: "/dev/node1",
   201  		},
   202  		{
   203  			LaidOutStructure: gadget.LaidOutStructure{
   204  				VolumeStructure: &gadget.VolumeStructure{
   205  					Name:       "Recovery",
   206  					Size:       0x4b000000,
   207  					Label:      "ubuntu-seed",
   208  					Type:       "C12A7328-F81F-11D2-BA4B-00A0C93EC93B",
   209  					Filesystem: "vfat",
   210  				},
   211  				StartOffset: 0x200000,
   212  				Index:       2,
   213  			},
   214  			Node: "/dev/node2",
   215  		},
   216  	})
   217  }
   218  
   219  func (s *ondiskTestSuite) TestDeviceInfoMBR(c *C) {
   220  	const mockSfdiskWithMBR = `
   221  >&2 echo "Some warning from sfdisk"
   222  echo '{
   223     "partitiontable": {
   224        "label": "dos",
   225        "device": "/dev/node",
   226        "unit": "sectors",
   227        "partitions": [
   228           {"node": "/dev/node1", "start": 4096, "size": 2457600, "type": "c"},
   229           {"node": "/dev/node2", "start": 2461696, "size": 1048576, "type": "d"},
   230           {"node": "/dev/node3", "start": 3510272, "size": 1048576, "type": "d"}
   231        ]
   232     }
   233  }'`
   234  	const mockLsblkForMBR = `
   235  [ "$3" == "/dev/node1" ] && echo '{
   236      "blockdevices": [ {"name": "node1", "fstype": "vfat", "label": "ubuntu-seed", "uuid": "A644-B807", "mountpoint": null} ]
   237  }'
   238  [ "$3" == "/dev/node2" ] && echo '{
   239      "blockdevices": [ {"name": "node2", "fstype": "vfat", "label": "ubuntu-boot", "uuid": "A644-B808", "mountpoint": null} ]
   240  }'
   241  [ "$3" == "/dev/node3" ] && echo '{
   242      "blockdevices": [ {"name": "node3", "fstype": "ext4", "label": "ubuntu-data", "mountpoint": null} ]
   243  }'
   244  exit 0`
   245  
   246  	cmdSfdisk := testutil.MockCommand(c, "sfdisk", mockSfdiskWithMBR)
   247  	defer cmdSfdisk.Restore()
   248  
   249  	cmdLsblk := testutil.MockCommand(c, "lsblk", mockLsblkForMBR)
   250  	defer cmdLsblk.Restore()
   251  
   252  	cmdBlockdev := testutil.MockCommand(c, "blockdev", "echo 12345670")
   253  	defer cmdBlockdev.Restore()
   254  
   255  	dl, err := gadget.OnDiskVolumeFromDevice("/dev/node")
   256  	c.Assert(err, IsNil)
   257  	c.Assert(cmdSfdisk.Calls(), DeepEquals, [][]string{
   258  		{"sfdisk", "--json", "-d", "/dev/node"},
   259  	})
   260  	c.Assert(cmdLsblk.Calls(), DeepEquals, [][]string{
   261  		{"lsblk", "--fs", "--json", "/dev/node1"},
   262  		{"lsblk", "--fs", "--json", "/dev/node2"},
   263  		{"lsblk", "--fs", "--json", "/dev/node3"},
   264  	})
   265  	c.Assert(cmdBlockdev.Calls(), DeepEquals, [][]string{
   266  		{"blockdev", "--getsz", "/dev/node"},
   267  	})
   268  	c.Assert(err, IsNil)
   269  	c.Assert(dl.ID, Equals, "")
   270  	c.Assert(dl.Schema, Equals, "dos")
   271  	c.Assert(dl.Device, Equals, "/dev/node")
   272  	c.Assert(dl.SectorSize, Equals, gadget.Size(512))
   273  	c.Assert(dl.Size, Equals, gadget.Size(12345670*512))
   274  	c.Assert(len(dl.Structure), Equals, 3)
   275  
   276  	c.Assert(dl.Structure, DeepEquals, []gadget.OnDiskStructure{
   277  		{
   278  			LaidOutStructure: gadget.LaidOutStructure{
   279  				VolumeStructure: &gadget.VolumeStructure{
   280  					Size:       0x4b000000,
   281  					Label:      "ubuntu-seed",
   282  					Type:       "0C",
   283  					Filesystem: "vfat",
   284  				},
   285  				StartOffset: 0x200000,
   286  				Index:       1,
   287  			},
   288  			Node:                 "/dev/node1",
   289  			CreatedDuringInstall: false,
   290  		},
   291  		{
   292  			LaidOutStructure: gadget.LaidOutStructure{
   293  				VolumeStructure: &gadget.VolumeStructure{
   294  					Size:       0x20000000,
   295  					Label:      "ubuntu-boot",
   296  					Type:       "0D",
   297  					Filesystem: "vfat",
   298  				},
   299  				StartOffset: 0x4b200000,
   300  				Index:       2,
   301  			},
   302  			Node:                 "/dev/node2",
   303  			CreatedDuringInstall: true,
   304  		},
   305  		{
   306  			LaidOutStructure: gadget.LaidOutStructure{
   307  				VolumeStructure: &gadget.VolumeStructure{
   308  					Size:       0x20000000,
   309  					Label:      "ubuntu-data",
   310  					Type:       "0D",
   311  					Filesystem: "ext4",
   312  				},
   313  				StartOffset: 0x6b200000,
   314  				Index:       3,
   315  			},
   316  			Node:                 "/dev/node3",
   317  			CreatedDuringInstall: true,
   318  		},
   319  	})
   320  }
   321  
   322  func (s *ondiskTestSuite) TestDeviceInfoNotSectors(c *C) {
   323  	cmdSfdisk := testutil.MockCommand(c, "sfdisk", `echo '{
   324     "partitiontable": {
   325        "label": "gpt",
   326        "id": "9151F25B-CDF0-48F1-9EDE-68CBD616E2CA",
   327        "device": "/dev/node",
   328        "unit": "not_sectors",
   329        "firstlba": 34,
   330        "lastlba": 8388574,
   331        "partitions": [
   332           {"node": "/dev/node1", "start": 2048, "size": 2048, "type": "21686148-6449-6E6F-744E-656564454649", "uuid": "2E59D969-52AB-430B-88AC-F83873519F6F", "name": "BIOS Boot"}
   333        ]
   334     }
   335  }'`)
   336  	defer cmdSfdisk.Restore()
   337  
   338  	_, err := gadget.OnDiskVolumeFromDevice("/dev/node")
   339  	c.Assert(err, ErrorMatches, "cannot position partitions: unknown unit .*")
   340  }
   341  
   342  func (s *ondiskTestSuite) TestDeviceInfoFilesystemInfoError(c *C) {
   343  	cmdSfdisk := testutil.MockCommand(c, "sfdisk", `echo '{
   344     "partitiontable": {
   345        "label": "gpt",
   346        "id": "9151F25B-CDF0-48F1-9EDE-68CBD616E2CA",
   347        "device": "/dev/node",
   348        "unit": "sectors",
   349        "firstlba": 34,
   350        "lastlba": 8388574,
   351        "partitions": [
   352           {"node": "/dev/node1", "start": 2048, "size": 2048, "type": "21686148-6449-6E6F-744E-656564454649", "uuid": "2E59D969-52AB-430B-88AC-F83873519F6F", "name": "BIOS Boot"}
   353        ]
   354     }
   355  }'`)
   356  	defer cmdSfdisk.Restore()
   357  
   358  	cmdLsblk := testutil.MockCommand(c, "lsblk", "echo lsblk error; exit 1")
   359  	defer cmdLsblk.Restore()
   360  
   361  	_, err := gadget.OnDiskVolumeFromDevice("/dev/node")
   362  	c.Assert(err, ErrorMatches, "cannot obtain filesystem information: lsblk error")
   363  }
   364  
   365  func (s *ondiskTestSuite) TestDeviceInfoJsonError(c *C) {
   366  	cmd := testutil.MockCommand(c, "sfdisk", `echo 'This is not a json'`)
   367  	defer cmd.Restore()
   368  
   369  	dl, err := gadget.OnDiskVolumeFromDevice("/dev/node")
   370  	c.Assert(err, ErrorMatches, "cannot parse sfdisk output: invalid .*")
   371  	c.Assert(dl, IsNil)
   372  }
   373  
   374  func (s *ondiskTestSuite) TestDeviceInfoError(c *C) {
   375  	cmd := testutil.MockCommand(c, "sfdisk", "echo 'sfdisk: not found'; exit 127")
   376  	defer cmd.Restore()
   377  
   378  	dl, err := gadget.OnDiskVolumeFromDevice("/dev/node")
   379  	c.Assert(err, ErrorMatches, "sfdisk: not found")
   380  	c.Assert(dl, IsNil)
   381  }
   382  
   383  func (s *ondiskTestSuite) TestBuildPartitionList(c *C) {
   384  	cmdSfdisk := testutil.MockCommand(c, "sfdisk", mockSfdiskScriptBiosSeed)
   385  	defer cmdSfdisk.Restore()
   386  
   387  	cmdLsblk := testutil.MockCommand(c, "lsblk", mockLsblkScriptBiosSeed)
   388  	defer cmdLsblk.Restore()
   389  
   390  	ptable := gadget.SFDiskPartitionTable{
   391  		Label:    "gpt",
   392  		ID:       "9151F25B-CDF0-48F1-9EDE-68CBD616E2CA",
   393  		Device:   "/dev/node",
   394  		Unit:     "sectors",
   395  		FirstLBA: 34,
   396  		LastLBA:  8388574,
   397  		Partitions: []gadget.SFDiskPartition{
   398  			{
   399  				Node:  "/dev/node1",
   400  				Start: 2048,
   401  				Size:  2048,
   402  				Type:  "21686148-6449-6E6F-744E-656564454649",
   403  				UUID:  "2E59D969-52AB-430B-88AC-F83873519F6F",
   404  				Name:  "BIOS Boot",
   405  			},
   406  			{
   407  				Node:  "/dev/node2",
   408  				Start: 4096,
   409  				Size:  2457600,
   410  				Type:  "EF,C12A7328-F81F-11D2-BA4B-00A0C93EC93B",
   411  				UUID:  "216c34ff-9be6-4787-9ab3-a4c1429c3e73",
   412  				Name:  "Recovery",
   413  			},
   414  		},
   415  	}
   416  
   417  	pv, err := gadget.PositionedVolumeFromGadget(s.gadgetRoot)
   418  	c.Assert(err, IsNil)
   419  
   420  	dl, err := gadget.OnDiskVolumeFromPartitionTable(ptable)
   421  	c.Assert(err, IsNil)
   422  
   423  	// the expected expanded writable partition size is:
   424  	// start offset = (2M + 1200M), expanded size in sectors = (8388575*512 - start offset)/512
   425  	sfdiskInput, create := gadget.BuildPartitionList(dl, pv)
   426  	c.Assert(sfdiskInput.String(), Equals, `/dev/node3 : start=     2461696, size=     5926879, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, name="Writable", attrs="GUID:59"
   427  `)
   428  	c.Assert(create, DeepEquals, []gadget.OnDiskStructure{mockOnDiskStructureWritable})
   429  }
   430  
   431  func (s *ondiskTestSuite) TestUpdatePartitionList(c *C) {
   432  	const mockSfdiskScriptBios = `
   433  >&2 echo "Some warning from sfdisk"
   434  echo '{
   435    "partitiontable": {
   436      "label": "gpt",
   437      "id": "9151F25B-CDF0-48F1-9EDE-68CBD616E2CA",
   438      "device": "/dev/node",
   439      "unit": "sectors",
   440      "firstlba": 34,
   441      "lastlba": 8388574,
   442      "partitions": [
   443        {
   444          "node": "/dev/node1",
   445          "start": 2048,
   446          "size": 2048,
   447          "type": "21686148-6449-6E6F-744E-656564454649",
   448          "uuid": "2E59D969-52AB-430B-88AC-F83873519F6F",
   449          "name": "BIOS Boot"
   450        }
   451      ]
   452    }
   453  }'`
   454  
   455  	const mockLsblkScriptBios = `
   456  [ "$3" == "/dev/node1" ] && echo '{
   457      "blockdevices": [ {"name": "node1", "fstype": null, "label": null, "uuid": null, "mountpoint": null} ]
   458  }'
   459  exit 0`
   460  
   461  	// start with a single partition
   462  	cmdSfdisk := testutil.MockCommand(c, "sfdisk", mockSfdiskScriptBios)
   463  	defer cmdSfdisk.Restore()
   464  
   465  	cmdLsblk := testutil.MockCommand(c, "lsblk", mockLsblkScriptBios)
   466  	defer cmdLsblk.Restore()
   467  
   468  	dl, err := gadget.OnDiskVolumeFromDevice("/dev/node")
   469  	c.Assert(err, IsNil)
   470  	c.Assert(len(dl.Structure), Equals, 1)
   471  	c.Assert(dl.Structure[0].Node, Equals, "/dev/node1")
   472  
   473  	// add a partition
   474  	cmdSfdisk = testutil.MockCommand(c, "sfdisk", mockSfdiskScriptBiosSeed)
   475  	defer cmdSfdisk.Restore()
   476  
   477  	cmdLsblk = testutil.MockCommand(c, "lsblk", mockLsblkScriptBiosSeed)
   478  	defer cmdLsblk.Restore()
   479  
   480  	// update the partition list
   481  	err = gadget.UpdatePartitionList(dl)
   482  	c.Assert(err, IsNil)
   483  
   484  	// check if the partition list was updated
   485  	c.Assert(len(dl.Structure), Equals, 2)
   486  	c.Assert(dl.Structure[0].Node, Equals, "/dev/node1")
   487  	c.Assert(dl.Structure[1].Node, Equals, "/dev/node2")
   488  }
   489  
   490  func (s *ondiskTestSuite) TestCreatedDuringInstallGPT(c *C) {
   491  	cmdLsblk := testutil.MockCommand(c, "lsblk", `echo '{ "blockdevices": [ {"fstype":"ext4", "label":null} ] }'`)
   492  	defer cmdLsblk.Restore()
   493  
   494  	ptable := gadget.SFDiskPartitionTable{
   495  		Label:    "gpt",
   496  		ID:       "9151F25B-CDF0-48F1-9EDE-68CBD616E2CA",
   497  		Device:   "/dev/node",
   498  		Unit:     "sectors",
   499  		FirstLBA: 34,
   500  		LastLBA:  8388574,
   501  		Partitions: []gadget.SFDiskPartition{
   502  			{
   503  				Node:  "/dev/node1",
   504  				Start: 1024,
   505  				Size:  1024,
   506  				Type:  "0fc63daf-8483-4772-8e79-3d69d8477de4",
   507  				UUID:  "641764aa-a680-4d36-a7ad-f7bd01fd8d12",
   508  				Name:  "Linux filesystem",
   509  			},
   510  			{
   511  				Node:  "/dev/node2",
   512  				Start: 2048,
   513  				Size:  2048,
   514  				Type:  "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F",
   515  				UUID:  "7ea3a75a-3f6d-4647-8134-89ae61fe88d5",
   516  				Name:  "Linux swap",
   517  			},
   518  			{
   519  				Node:  "/dev/node3",
   520  				Start: 8192,
   521  				Size:  8192,
   522  				Type:  "21686148-6449-6E6F-744E-656564454649",
   523  				UUID:  "30a26851-4b08-4b8d-8aea-f686e723ed8c",
   524  				Name:  "BIOS boot partition",
   525  			},
   526  			{
   527  				Node:  "/dev/node4",
   528  				Start: 16384,
   529  				Size:  16384,
   530  				Type:  "0fc63daf-8483-4772-8e79-3d69d8477de4",
   531  				UUID:  "8ab3e8fd-d53d-4d72-9c5e-56146915fd07",
   532  				Name:  "Another Linux filesystem",
   533  			},
   534  		},
   535  	}
   536  	dl, err := gadget.OnDiskVolumeFromPartitionTable(ptable)
   537  	c.Assert(err, IsNil)
   538  	list := gadget.CreatedDuringInstall(dl)
   539  	c.Assert(list, HasLen, 0)
   540  
   541  	// Set attribute bit for all partitions except the last one
   542  	for i := 0; i < len(ptable.Partitions)-1; i++ {
   543  		ptable.Partitions[i].Attrs = "RequiredPartition LegacyBIOSBootable GUID:58,59"
   544  	}
   545  
   546  	dl, err = gadget.OnDiskVolumeFromPartitionTable(ptable)
   547  	c.Assert(err, IsNil)
   548  	list = gadget.CreatedDuringInstall(dl)
   549  	c.Assert(list, DeepEquals, []string{"/dev/node1", "/dev/node2"})
   550  }
   551  
   552  func (s *ondiskTestSuite) TestCreatedDuringInstallMBR(c *C) {
   553  	cmdLsblk := testutil.MockCommand(c, "lsblk", `
   554  what=
   555  shift 2
   556  case "$1" in
   557     /dev/node1)
   558        what='{"name": "node1", "fstype":"ext4", "label":"ubuntu-seed"}'
   559        ;;
   560     /dev/node2)
   561        what='{"name": "node2", "fstype":"vfat", "label":"ubuntu-boot"}'
   562        ;;
   563     /dev/node3)
   564        what='{"name": "node3", "fstype":null, "label":null}'
   565        ;;
   566     /dev/node4)
   567        what='{"name": "node4", "fstype":"ext4", "label":"ubuntu-data"}'
   568        ;;
   569    *)
   570      echo "unexpected call"
   571      exit 1
   572  esac
   573  
   574  cat <<EOF
   575  {
   576  "blockdevices": [
   577     $what
   578    ]
   579  }
   580  EOF`)
   581  	defer cmdLsblk.Restore()
   582  	cmdBlockdev := testutil.MockCommand(c, "blockdev", `echo '1234567'`)
   583  	defer cmdBlockdev.Restore()
   584  
   585  	ptable := gadget.SFDiskPartitionTable{
   586  		Label:  "dos",
   587  		Device: "/dev/node",
   588  		Unit:   "sectors",
   589  		Partitions: []gadget.SFDiskPartition{
   590  			{
   591  				// ubuntu-seed
   592  				Node:  "/dev/node1",
   593  				Start: 1024,
   594  				Size:  1024,
   595  				Type:  "0a",
   596  			},
   597  			{
   598  				// ubuntu-boot
   599  				Node:  "/dev/node2",
   600  				Start: 2048,
   601  				Size:  2048,
   602  				Type:  "b",
   603  			},
   604  			{
   605  				// unlabeled
   606  				Node:  "/dev/node3",
   607  				Start: 8192,
   608  				Size:  8192,
   609  				Type:  "c",
   610  			},
   611  			{
   612  				// ubuntu-data
   613  				Node:  "/dev/node4",
   614  				Start: 16384,
   615  				Size:  16384,
   616  				Type:  "0d",
   617  			},
   618  		},
   619  	}
   620  	dl, err := gadget.OnDiskVolumeFromPartitionTable(ptable)
   621  	c.Assert(err, IsNil)
   622  	list := gadget.CreatedDuringInstall(dl)
   623  	c.Assert(list, DeepEquals, []string{"/dev/node2", "/dev/node4"})
   624  }
   625  
   626  func (s *ondiskTestSuite) TestFilesystemInfo(c *C) {
   627  	cmd := testutil.MockCommand(c, "lsblk", `echo '{
   628     "blockdevices": [
   629        {"name": "loop8p2", "fstype": "vfat", "label": "ubuntu-seed", "uuid": "C1F4-CE43", "mountpoint": null}
   630     ]
   631  }'`)
   632  	defer cmd.Restore()
   633  
   634  	info, err := gadget.FilesystemInfo("/dev/node")
   635  	c.Assert(cmd.Calls(), DeepEquals, [][]string{
   636  		{"lsblk", "--fs", "--json", "/dev/node"},
   637  	})
   638  	c.Assert(err, IsNil)
   639  	c.Assert(len(info.BlockDevices), Equals, 1)
   640  	bd := info.BlockDevices[0]
   641  	c.Assert(bd.Name, Equals, "loop8p2")
   642  	c.Assert(bd.FSType, Equals, "vfat")
   643  	c.Assert(bd.Label, Equals, "ubuntu-seed")
   644  	c.Assert(bd.UUID, Equals, "C1F4-CE43")
   645  }
   646  
   647  func (s *ondiskTestSuite) TestFilesystemInfoJsonError(c *C) {
   648  	cmd := testutil.MockCommand(c, "lsblk", `echo 'This is not a json'`)
   649  	defer cmd.Restore()
   650  
   651  	info, err := gadget.FilesystemInfo("/dev/node")
   652  	c.Assert(err, ErrorMatches, "cannot parse lsblk output: invalid .*")
   653  	c.Assert(info, IsNil)
   654  }
   655  
   656  func (s *ondiskTestSuite) TestFilesystemInfoError(c *C) {
   657  	cmd := testutil.MockCommand(c, "lsblk", "echo 'lsblk: not found'; exit 127")
   658  	defer cmd.Restore()
   659  
   660  	info, err := gadget.FilesystemInfo("/dev/node")
   661  	c.Assert(err, ErrorMatches, "lsblk: not found")
   662  	c.Assert(info, IsNil)
   663  }