Merge pull request #35919 from yongtang/35333-carry

Carry #35333: Devicemapper: ignore Nodata errors when delete thin device
This commit is contained in:
Sebastiaan van Stijn 2018-01-20 18:47:16 +01:00 committed by GitHub
commit db5c006bc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 3 deletions

View File

@ -0,0 +1,74 @@
package container
import (
"context"
"fmt"
"strings"
"testing"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
"github.com/docker/docker/integration/util/request"
"github.com/gotestyourself/gotestyourself/icmd"
"github.com/gotestyourself/gotestyourself/poll"
"github.com/gotestyourself/gotestyourself/skip"
"github.com/stretchr/testify/require"
)
func TestDeleteDevicemapper(t *testing.T) {
skip.IfCondition(t, testEnv.DaemonInfo.Driver != "devicemapper")
defer setupTest(t)()
client := request.NewAPIClient(t)
ctx := context.Background()
foo, err := client.ContainerCreate(ctx,
&container.Config{
Cmd: []string{"echo"},
Image: "busybox",
},
&container.HostConfig{},
&network.NetworkingConfig{},
"foo",
)
require.NoError(t, err)
err = client.ContainerStart(ctx, foo.ID, types.ContainerStartOptions{})
require.NoError(t, err)
inspect, err := client.ContainerInspect(ctx, foo.ID)
require.NoError(t, err)
poll.WaitOn(t, containerIsStopped(ctx, client, foo.ID), poll.WithDelay(100*time.Millisecond))
deviceID := inspect.GraphDriver.Data["DeviceId"]
// Find pool name from device name
deviceName := inspect.GraphDriver.Data["DeviceName"]
devicePrefix := deviceName[:strings.LastIndex(deviceName, "-")]
devicePool := fmt.Sprintf("/dev/mapper/%s-pool", devicePrefix)
result := icmd.RunCommand("dmsetup", "message", devicePool, "0", fmt.Sprintf("delete %s", deviceID))
result.Assert(t, icmd.Success)
err = client.ContainerRemove(ctx, foo.ID, types.ContainerRemoveOptions{})
require.NoError(t, err)
}
func containerIsStopped(ctx context.Context, client client.APIClient, containerID string) func(log poll.LogT) poll.Result {
return func(log poll.LogT) poll.Result {
inspect, err := client.ContainerInspect(ctx, containerID)
switch {
case err != nil:
return poll.Error(err)
case !inspect.State.Running:
return poll.Success()
default:
return poll.Continue("waiting for container to be stopped")
}
}
}

View File

@ -67,12 +67,14 @@ var (
ErrBusy = errors.New("Device is Busy") ErrBusy = errors.New("Device is Busy")
ErrDeviceIDExists = errors.New("Device Id Exists") ErrDeviceIDExists = errors.New("Device Id Exists")
ErrEnxio = errors.New("No such device or address") ErrEnxio = errors.New("No such device or address")
ErrEnoData = errors.New("No data available")
) )
var ( var (
dmSawBusy bool dmSawBusy bool
dmSawExist bool dmSawExist bool
dmSawEnxio bool // No Such Device or Address dmSawEnxio bool // No Such Device or Address
dmSawEnoData bool // No data available
) )
type ( type (
@ -708,10 +710,15 @@ func DeleteDevice(poolName string, deviceID int) error {
} }
dmSawBusy = false dmSawBusy = false
dmSawEnoData = false
if err := task.run(); err != nil { if err := task.run(); err != nil {
if dmSawBusy { if dmSawBusy {
return ErrBusy return ErrBusy
} }
if dmSawEnoData {
logrus.Debugf("devicemapper: Device(id: %d) from pool(%s) does not exist", deviceID, poolName)
return nil
}
return fmt.Errorf("devicemapper: Error running DeleteDevice %s", err) return fmt.Errorf("devicemapper: Error running DeleteDevice %s", err)
} }
return nil return nil

View File

@ -55,6 +55,9 @@ func DevmapperLogCallback(level C.int, file *C.char, line, dmErrnoOrClass C.int,
if strings.Contains(msg, "No such device or address") { if strings.Contains(msg, "No such device or address") {
dmSawEnxio = true dmSawEnxio = true
} }
if strings.Contains(msg, "No data available") {
dmSawEnoData = true
}
} }
if dmLogger != nil { if dmLogger != nil {