From a59d96deae7aa75eaa3c92fbf4fe4ecfcae2d5a4 Mon Sep 17 00:00:00 2001 From: Mateus Melchiades Date: Wed, 20 Sep 2023 18:36:37 -0300 Subject: [PATCH] LVM thin pool commands --- RECIPE.md | 21 ++++++++++++++++++++- core/lvm/lv.go | 19 +++++++++++++++++++ core/lvm/lvm.go | 33 +++++++++++++++++++++++++++++++++ core/recipe.go | 37 ++++++++++++++++++++++++++++++++++++- 4 files changed, 108 insertions(+), 2 deletions(-) diff --git a/RECIPE.md b/RECIPE.md index 519b6558..740f05db 100644 --- a/RECIPE.md +++ b/RECIPE.md @@ -145,7 +145,7 @@ Create LVM logical volume. - *Name* (`string`): Logical volume name. - *VG* (`string`): Volume group name. - *Type* (`string`): Logical volume type. See lvcreate(8) for available types. -- *Size* (`float`): Volume group size in MiB. +- *Size* (`float`): Logical volume size in MiB. ### lvrename @@ -163,6 +163,25 @@ Deletes LVM logical volume. **Accepts**: - *Name* (`string`): The logical volume name. +### make-thin-pool + +Creates a new LVM thin pool from two LVs: one for metadata and another one for the data itself. + +**Accepts**: +- *Name* (`string`): The created thin pool name. +- *ThinDataLV* (`string`): The LV for storing data. +- *ThinMetaLV* (`string`): The LV for storing pool metadata. + +### lvcreate-thin + +Same as `lvcreate`, but creates a thin LV instead. + +**Accepts**: +- *Name* (`string`): Thin logical volume name. +- *VG* (`string`): Volume group name. +- *Size* (`float`): Volume group size in MiB. +- *Thinpool* (`string`): Name of the thin pool to create the LV from. + --- ## Post-Installation diff --git a/core/lvm/lv.go b/core/lvm/lv.go index ba637a1a..fc8d0887 100644 --- a/core/lvm/lv.go +++ b/core/lvm/lv.go @@ -282,6 +282,25 @@ func FindLv(vgName, lvName string) (Lv, error) { return lvs[0], nil } +func MakeThinPool(poolMetadata, pool interface{}) error { + poolMetadataName, err := extractNameFromLv(poolMetadata) + if err != nil { + return err + } + poolName, err := extractNameFromLv(pool) + if err != nil { + return err + } + + lvm := NewLvm() + _, err = lvm.lvm2Run("lvconvert --type thin-pool --poolmetadata %s %s", poolMetadataName, poolName) + if err != nil { + return err + } + + return nil +} + func (l *Lv) Rename(newName string) error { lvm := NewLvm() newLv, err := lvm.Lvrename(l.Name, newName, l.VgName) diff --git a/core/lvm/lvm.go b/core/lvm/lvm.go index b2a577c4..29d16900 100644 --- a/core/lvm/lvm.go +++ b/core/lvm/lvm.go @@ -337,6 +337,25 @@ func (l *Lvm) Lvcreate(name string, vg interface{}, lvType LVType, size float64) return nil } +func (l *Lvm) LvThinCreate(name string, vg, pool interface{}, size float64) error { + vgName, err := extractNameFromVg(vg) + if err != nil { + return fmt.Errorf("lvmThinCreate: %v", err) + } + + poolName, err := extractNameFromPool(pool) + if err != nil { + return fmt.Errorf("lvmThinCreate: %v", err) + } + + _, err = l.lvm2Run("lvcreate -y -n %s -V %.2fm %s %s", name, size, poolName, vgName) + if err != nil { + return fmt.Errorf("lvmThinCreate: %v", err) + } + + return nil +} + // lvs (list lvs) func (l *Lvm) Lvs(filter ...string) ([]Lv, error) { filterStr := "" @@ -480,3 +499,17 @@ func extractNameFromLv(lv interface{}) (string, error) { return lvName, nil } + +func extractNameFromPool(pool interface{}) (string, error) { + var poolName string + switch lvar := pool.(type) { + case string: + poolName = lvar + case *Lv: + poolName = lvar.Name + default: + return "", errors.New("invalid type for pool. Must be either a string with the pool's name or a pointer to a LV struct") + } + + return poolName, nil +} diff --git a/core/recipe.go b/core/recipe.go index 89b88e00..7c62dae3 100644 --- a/core/recipe.go +++ b/core/recipe.go @@ -450,7 +450,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { * - *Name* (`string`): Logical volume name. * - *VG* (`string`): Volume group name. * - *Type* (`string`): Logical volume type. See lvcreate(8) for available types. - * - *Size* (`float`): Volume group size in MiB. + * - *Size* (`float`): Logical volume size in MiB. */ case "lvcreate": name := args[0].(string) @@ -491,6 +491,41 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { if err != nil { return err } + /* !! ### make-thin-pool + * + * Creates a new LVM thin pool from two LVs: one for metadata and another one for the data itself. + * + * **Accepts**: + * - *Name* (`string`): The created thin pool name. + * - *ThinDataLV* (`string`): The LV for storing data. + * - *ThinMetaLV* (`string`): The LV for storing pool metadata. + */ + case "make-thin-pool": + thinDataLV := args[0].(string) + thinMetaLV := args[1].(string) + err := lvm.MakeThinPool(thinMetaLV, thinDataLV) + if err != nil { + return err + } + /* !! ### lvcreate-thin + * + * Same as `lvcreate`, but creates a thin LV instead. + * + * **Accepts**: + * - *Name* (`string`): Thin logical volume name. + * - *VG* (`string`): Volume group name. + * - *Size* (`float`): Volume group size in MiB. + * - *Thinpool* (`string`): Name of the thin pool to create the LV from. + */ + case "lvcreate-thin": + name := args[0].(string) + vg := args[1].(string) + vgSize := args[2].(float64) + thinPool := args[3].(string) + err := LvmInstance.LvThinCreate(name, vg, thinPool, vgSize) + if err != nil { + return err + } /* !! --- */ default: return fmt.Errorf("unrecognized operation %s", operation)