Fix detection of devmapper metadata reservation

Because new versions of devicemapper may add additional fields to the output of 'dmsetup status',
change the check to use SplitN to get the minimum fields required, and ignore any additional fields
after the one we care about.
This commit is contained in:
Andy Goldstein 2016-06-23 11:24:10 -04:00
parent 6351fbfc84
commit f014860332
2 changed files with 19 additions and 12 deletions

View File

@ -150,8 +150,8 @@ func (w *ThinPoolWatcher) Refresh() error {
}
const (
thinPoolDmsetupStatusTokens = 11
thinPoolDmsetupStatusHeldMetadataRoot = 6
thinPoolDmsetupStatusMinFields = thinPoolDmsetupStatusHeldMetadataRoot + 1
)
// checkReservation checks to see whether the thin device is currently holding
@ -163,14 +163,14 @@ func (w *ThinPoolWatcher) checkReservation(poolName string) (bool, error) {
return false, err
}
tokens := strings.Split(string(output), " ")
// Split returns the input as the last item in the result, adjust the
// number of tokens by one
if len(tokens) != thinPoolDmsetupStatusTokens+1 {
return false, fmt.Errorf("unexpected output of dmsetup status command; expected 11 fields, got %v; output: %v", len(tokens), string(output))
// we care about the field at fields[thinPoolDmsetupStatusHeldMetadataRoot],
// so make sure we get enough fields
fields := strings.Fields(string(output))
if len(fields) < thinPoolDmsetupStatusMinFields {
return false, fmt.Errorf("unexpected output of dmsetup status command; expected at least %d fields, got %v; output: %v", thinPoolDmsetupStatusMinFields, len(fields), string(output))
}
heldMetadataRoot := tokens[thinPoolDmsetupStatusHeldMetadataRoot]
heldMetadataRoot := fields[thinPoolDmsetupStatusHeldMetadataRoot]
currentlyReserved := heldMetadataRoot != "-"
return currentlyReserved, nil
}

View File

@ -45,6 +45,18 @@ func TestRefresh(t *testing.T) {
},
expectedError: true,
},
{
name: "no existing reservation - ok with minimum # of fields",
dmsetupCommands: []fake.DmsetupCommand{
{"status", "0 75497472 thin-pool 65 327/524288 14092/589824 -", nil}, // status check
{"message", "", nil}, // make reservation
{"message", "", nil}, // release reservation
},
thinLsOutput: usage,
expectedError: false,
deviceId: "2",
expectedUsage: 23456,
},
{
name: "no existing reservation - ok",
dmsetupCommands: []fake.DmsetupCommand{
@ -182,11 +194,6 @@ func TestCheckReservation(t *testing.T) {
statusResult: "0 75 thin-pool 65 327/12345 14092/589824 - rw no_discard_passdown queue_if_no_space - ",
expectedResult: false,
},
{
name: "malformed input",
statusResult: "0 12345 14092/45678 36 rw discard_passdown error_if_no_space needs_check ",
expectedErr: fmt.Errorf("not gonna work"),
},
}
for _, tc := range cases {