disk/lvm: generate logical volume name
When creating a new logical volume via the `CreateVolume` method, the logical volume name was left blank. Generate an name based on the mountpoint. We will detect collisions for names and will try to correct them by attaching a suffix. We do give up after 100 attempts though. Add a simple test for it.
This commit is contained in:
parent
9b89df57b6
commit
a9ef16a95e
2 changed files with 80 additions and 1 deletions
|
|
@ -1,6 +1,9 @@
|
|||
package disk
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type LVMVolumeGroup struct {
|
||||
Name string
|
||||
|
|
@ -66,7 +69,33 @@ func (vg *LVMVolumeGroup) CreateVolume(mountpoint string, size uint64) (Entity,
|
|||
FSTabPassNo: 0,
|
||||
}
|
||||
|
||||
names := make(map[string]bool, len(vg.LogicalVolumes))
|
||||
for _, lv := range vg.LogicalVolumes {
|
||||
names[lv.Name] = true
|
||||
}
|
||||
|
||||
base := lvname(mountpoint)
|
||||
var exists bool
|
||||
name := base
|
||||
|
||||
// Make sure that we don't collide with an existing volume, e.g. 'home/test'
|
||||
// and /home/test_test would collide. We try 100 times and then give up. This
|
||||
// is mimicking what blivet does. See blivet/blivet.py#L1060 commit 2eb4bd4
|
||||
for i := 0; i < 100; i++ {
|
||||
exists = names[name]
|
||||
if !exists {
|
||||
break
|
||||
}
|
||||
|
||||
name = fmt.Sprintf("%s%02d", base, i)
|
||||
}
|
||||
|
||||
if exists {
|
||||
return nil, fmt.Errorf("could not create logical volume: name collision")
|
||||
}
|
||||
|
||||
lv := LVMLogicalVolume{
|
||||
Name: name,
|
||||
Size: size,
|
||||
Payload: &filesystem,
|
||||
}
|
||||
|
|
@ -128,3 +157,13 @@ func (lv *LVMLogicalVolume) EnsureSize(s uint64) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// lvname returns a name for a logical volume based on the mountpoint.
|
||||
func lvname(path string) string {
|
||||
if path == "/" {
|
||||
return "rootlv"
|
||||
}
|
||||
|
||||
path = strings.TrimLeft(path, "/")
|
||||
return strings.ReplaceAll(path, "/", "_") + "lv"
|
||||
}
|
||||
|
|
|
|||
40
internal/disk/lvm_test.go
Normal file
40
internal/disk/lvm_test.go
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package disk
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLVMVGCreateVolume(t *testing.T) {
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
vg := &LVMVolumeGroup{
|
||||
Name: "root",
|
||||
Description: "root volume group",
|
||||
}
|
||||
|
||||
entity, err := vg.CreateVolume("/", 0)
|
||||
assert.NoError(err)
|
||||
rootlv := entity.(*LVMLogicalVolume)
|
||||
assert.Equal("rootlv", rootlv.Name)
|
||||
|
||||
_, err = vg.CreateVolume("/home_test", 0)
|
||||
assert.NoError(err)
|
||||
|
||||
entity, err = vg.CreateVolume("/home/test", 0)
|
||||
assert.NoError(err)
|
||||
|
||||
dedup := entity.(*LVMLogicalVolume)
|
||||
assert.Equal("home_testlv00", dedup.Name)
|
||||
|
||||
// Lets collide it
|
||||
for i := 0; i < 98; i++ {
|
||||
_, err = vg.CreateVolume("/home/test", 0)
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
||||
_, err = vg.CreateVolume("/home/test", 0)
|
||||
assert.Error(err)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue