github.com/containerd/Containerd@v1.4.13/snapshots/devmapper/dmsetup/dmsetup_test.go (about)

     1  // +build linux
     2  
     3  /*
     4     Copyright The containerd Authors.
     5  
     6     Licensed under the Apache License, Version 2.0 (the "License");
     7     you may not use this file except in compliance with the License.
     8     You may obtain a copy of the License at
     9  
    10         http://www.apache.org/licenses/LICENSE-2.0
    11  
    12     Unless required by applicable law or agreed to in writing, software
    13     distributed under the License is distributed on an "AS IS" BASIS,
    14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15     See the License for the specific language governing permissions and
    16     limitations under the License.
    17  */
    18  
    19  package dmsetup
    20  
    21  import (
    22  	"io/ioutil"
    23  	"os"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/docker/go-units"
    28  	"golang.org/x/sys/unix"
    29  	"gotest.tools/v3/assert"
    30  	is "gotest.tools/v3/assert/cmp"
    31  
    32  	"github.com/containerd/containerd/pkg/testutil"
    33  	"github.com/containerd/containerd/snapshots/devmapper/losetup"
    34  )
    35  
    36  const (
    37  	testPoolName   = "test-pool"
    38  	testDeviceName = "test-device"
    39  	deviceID       = 1
    40  	snapshotID     = 2
    41  )
    42  
    43  func TestDMSetup(t *testing.T) {
    44  	testutil.RequiresRoot(t)
    45  
    46  	tempDir, err := ioutil.TempDir("", "dmsetup-tests-")
    47  	assert.NilError(t, err, "failed to make temp dir for tests")
    48  
    49  	defer func() {
    50  		err := os.RemoveAll(tempDir)
    51  		assert.NilError(t, err)
    52  	}()
    53  
    54  	dataImage, loopDataDevice := createLoopbackDevice(t, tempDir)
    55  	metaImage, loopMetaDevice := createLoopbackDevice(t, tempDir)
    56  
    57  	defer func() {
    58  		err = losetup.RemoveLoopDevicesAssociatedWithImage(dataImage)
    59  		assert.NilError(t, err, "failed to detach loop devices for data image: %s", dataImage)
    60  
    61  		err = losetup.RemoveLoopDevicesAssociatedWithImage(metaImage)
    62  		assert.NilError(t, err, "failed to detach loop devices for meta image: %s", metaImage)
    63  	}()
    64  
    65  	t.Run("CreatePool", func(t *testing.T) {
    66  		err := CreatePool(testPoolName, loopDataDevice, loopMetaDevice, 128)
    67  		assert.NilError(t, err, "failed to create thin-pool")
    68  
    69  		table, err := Table(testPoolName)
    70  		t.Logf("table: %s", table)
    71  		assert.NilError(t, err)
    72  		assert.Assert(t, strings.HasPrefix(table, "0 32768 thin-pool"))
    73  		assert.Assert(t, strings.HasSuffix(table, "128 32768 1 skip_block_zeroing"))
    74  	})
    75  
    76  	t.Run("ReloadPool", func(t *testing.T) {
    77  		err := ReloadPool(testPoolName, loopDataDevice, loopMetaDevice, 256)
    78  		assert.NilError(t, err, "failed to reload thin-pool")
    79  	})
    80  
    81  	t.Run("CreateDevice", testCreateDevice)
    82  
    83  	t.Run("CreateSnapshot", testCreateSnapshot)
    84  	t.Run("DeleteSnapshot", testDeleteSnapshot)
    85  
    86  	t.Run("ActivateDevice", testActivateDevice)
    87  	t.Run("DeviceStatus", testDeviceStatus)
    88  	t.Run("SuspendResumeDevice", testSuspendResumeDevice)
    89  	t.Run("RemoveDevice", testRemoveDevice)
    90  
    91  	t.Run("RemovePool", func(t *testing.T) {
    92  		err = RemoveDevice(testPoolName, RemoveWithForce, RemoveWithRetries)
    93  		assert.NilError(t, err, "failed to remove thin-pool")
    94  	})
    95  
    96  	t.Run("Version", testVersion)
    97  }
    98  
    99  func testCreateDevice(t *testing.T) {
   100  	err := CreateDevice(testPoolName, deviceID)
   101  	assert.NilError(t, err, "failed to create test device")
   102  
   103  	err = CreateDevice(testPoolName, deviceID)
   104  	assert.Assert(t, err == unix.EEXIST)
   105  
   106  	infos, err := Info(testPoolName)
   107  	assert.NilError(t, err)
   108  	assert.Assert(t, is.Len(infos, 1), "got unexpected number of device infos")
   109  }
   110  
   111  func testCreateSnapshot(t *testing.T) {
   112  	err := CreateSnapshot(testPoolName, snapshotID, deviceID)
   113  	assert.NilError(t, err)
   114  }
   115  
   116  func testDeleteSnapshot(t *testing.T) {
   117  	err := DeleteDevice(testPoolName, snapshotID)
   118  	assert.NilError(t, err, "failed to send delete message")
   119  
   120  	err = DeleteDevice(testPoolName, snapshotID)
   121  	assert.Assert(t, err == unix.ENODATA)
   122  }
   123  
   124  func testActivateDevice(t *testing.T) {
   125  	err := ActivateDevice(testPoolName, testDeviceName, 1, 1024, "")
   126  	assert.NilError(t, err, "failed to activate device")
   127  
   128  	err = ActivateDevice(testPoolName, testDeviceName, 1, 1024, "")
   129  	assert.Equal(t, err, unix.EBUSY)
   130  
   131  	if _, err := os.Stat("/dev/mapper/" + testDeviceName); err != nil && !os.IsExist(err) {
   132  		assert.NilError(t, err, "failed to stat device")
   133  	}
   134  
   135  	list, err := Info(testPoolName)
   136  	assert.NilError(t, err)
   137  	assert.Assert(t, is.Len(list, 1))
   138  
   139  	info := list[0]
   140  	assert.Equal(t, testPoolName, info.Name)
   141  	assert.Assert(t, info.TableLive)
   142  }
   143  
   144  func testDeviceStatus(t *testing.T) {
   145  	status, err := Status(testDeviceName)
   146  	assert.NilError(t, err)
   147  
   148  	assert.Equal(t, int64(0), status.Offset)
   149  	assert.Equal(t, int64(2), status.Length)
   150  	assert.Equal(t, "thin", status.Target)
   151  	assert.DeepEqual(t, status.Params, []string{"0", "-"})
   152  }
   153  
   154  func testSuspendResumeDevice(t *testing.T) {
   155  	err := SuspendDevice(testDeviceName)
   156  	assert.NilError(t, err)
   157  
   158  	err = SuspendDevice(testDeviceName)
   159  	assert.NilError(t, err)
   160  
   161  	list, err := Info(testDeviceName)
   162  	assert.NilError(t, err)
   163  	assert.Assert(t, is.Len(list, 1))
   164  
   165  	info := list[0]
   166  	assert.Assert(t, info.Suspended)
   167  
   168  	err = ResumeDevice(testDeviceName)
   169  	assert.NilError(t, err)
   170  
   171  	err = ResumeDevice(testDeviceName)
   172  	assert.NilError(t, err)
   173  }
   174  
   175  func testRemoveDevice(t *testing.T) {
   176  	err := RemoveDevice(testPoolName)
   177  	assert.Assert(t, err == unix.EBUSY, "removing thin-pool with dependencies shouldn't be allowed")
   178  
   179  	err = RemoveDevice(testDeviceName, RemoveWithRetries)
   180  	assert.NilError(t, err, "failed to remove thin-device")
   181  }
   182  
   183  func testVersion(t *testing.T) {
   184  	version, err := Version()
   185  	assert.NilError(t, err)
   186  	assert.Assert(t, version != "")
   187  }
   188  
   189  func createLoopbackDevice(t *testing.T, dir string) (string, string) {
   190  	file, err := ioutil.TempFile(dir, "dmsetup-tests-")
   191  	assert.NilError(t, err)
   192  
   193  	size, err := units.RAMInBytes("16Mb")
   194  	assert.NilError(t, err)
   195  
   196  	err = file.Truncate(size)
   197  	assert.NilError(t, err)
   198  
   199  	err = file.Close()
   200  	assert.NilError(t, err)
   201  
   202  	imagePath := file.Name()
   203  
   204  	loopDevice, err := losetup.AttachLoopDevice(imagePath)
   205  	assert.NilError(t, err)
   206  
   207  	return imagePath, loopDevice
   208  }