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 }