Skip to content

Commit 9e0ac5b

Browse files
authored
refactor(lvm): continue refactoring of lvm command calling convention (#261)
* refactor(ci): rename env variables and update vgcreate command Env vars LVM_SYSTEMID and LVM_CONFIG are used to describe a potentially foreign lvm system on the kubernetes host. The lvm system is only meant to be foreign to the lvm-localpv containers. Due to the way the ci tests are written, the kubernetes host and the lvm-localpv conatiners must have identical lvm configurations or ci tests might fail. The variables LVM_SYSTEMID and LVM_CONFIG have been renamed to FOREIGN_LVM_SYSTEMID and FOREIGN_LVM_CONFIG, respectively. This is helpful when determining their roles at a glance. A secondary change was made to the foreign pv creation: the lvm option `--config` has been used in place of `--systemid` to hopefully minimize unintended side effects of using the same lvm config (with the exception of the system id) during volume group creation. Signed-off-by: kro <[email protected]> * refactor(lvm): update all lvm commands to use split output The LVM system may sometimes produce non-critical warnings which are written to STDERR without formatting. Combining STDERR with STDIN may cause failures when the output is being formatted or otherwise interpreted. Following pull #250, it's been requested that all lvm commands be refactored to use a split output in order to resolve this issue under non-tested scenarios. See issue #247. The definition for RunCommandSplit has been moved above all uses of the function, and any Command using CombinedOutput and an lvm command (s.a.: lvs, vgs, lvcreate, &c.) has been refactored to instead use RunCommandSplit to obtain the command's output. If anything is written to STDERR by the lvm commands, RunCommandSplit prints the message to the log as a warning. Signed-off-by: kro <[email protected]> --------- Signed-off-by: kro <[email protected]>
1 parent 9a7388f commit 9e0ac5b

File tree

2 files changed

+42
-50
lines changed

2 files changed

+42
-50
lines changed

ci/ci-test.sh

+5-5
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ then
2929
export KUBECONFIG="${HOME}/.kube/config"
3030
fi
3131

32-
# systemid for the testing environment. The kubernetes host machine will serve as the foreign lvm system.
33-
LVM_SYSTEMID="openebs-ci-test-system"
34-
LVM_CONFIG="global{system_id_source=lvmlocal}local{system_id=${LVM_SYSTEMID}}"
32+
# foreign systemid for the testing environment.
33+
FOREIGN_LVM_SYSTEMID="openebs-ci-test-system"
34+
FOREIGN_LVM_CONFIG="global{system_id_source=lvmlocal}local{system_id=${FOREIGN_LVM_SYSTEMID}}"
3535

3636
# Clean up generated resources for successive tests.
3737
cleanup_loopdev() {
@@ -54,7 +54,7 @@ cleanup_lvmvg() {
5454
cleanup_foreign_lvmvg() {
5555
if [ -f /tmp/openebs_ci_foreign_disk.img ]
5656
then
57-
sudo vgremove foreign_lvmvg --config="${LVM_CONFIG}" -y || true
57+
sudo vgremove foreign_lvmvg --config="${FOREIGN_LVM_CONFIG}" -y || true
5858
rm /tmp/openebs_ci_foreign_disk.img
5959
fi
6060
cleanup_loopdev
@@ -91,7 +91,7 @@ cleanup_foreign_lvmvg
9191
truncate -s 1024G /tmp/openebs_ci_foreign_disk.img
9292
foreign_disk="$(sudo losetup -f /tmp/openebs_ci_foreign_disk.img --show)"
9393
sudo pvcreate "${foreign_disk}"
94-
sudo vgcreate foreign_lvmvg "${foreign_disk}" --systemid="${LVM_SYSTEMID}"
94+
sudo vgcreate foreign_lvmvg "${foreign_disk}" --config="${FOREIGN_LVM_CONFIG}"
9595

9696
# install snapshot and thin volume module for lvm
9797
sudo modprobe dm-snapshot

pkg/lvm/lvm_util.go

+37-45
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,27 @@ func buildLVMDestroyArgs(vol *apis.LVMVolume) []string {
261261
return LVMVolArg
262262
}
263263

264+
// RunCommandSplit is a wrapper function to run a command and receive its
265+
// STDERR and STDOUT streams in separate []byte vars.
266+
func RunCommandSplit(command string, args ...string) ([]byte, []byte, error) {
267+
var cmdStdout bytes.Buffer
268+
var cmdStderr bytes.Buffer
269+
270+
cmd := exec.Command(command, args...)
271+
cmd.Stdout = &cmdStdout
272+
cmd.Stderr = &cmdStderr
273+
err := cmd.Run()
274+
275+
output := cmdStdout.Bytes()
276+
error_output := cmdStderr.Bytes()
277+
278+
if len(error_output) > 0 {
279+
klog.Warningf("lvm: said into stderr: %s", error_output)
280+
}
281+
282+
return output, error_output, err
283+
}
284+
264285
// CreateVolume creates the lvm volume
265286
func CreateVolume(vol *apis.LVMVolume) error {
266287
volume := vol.Spec.VolGroup + "/" + vol.Name
@@ -275,8 +296,7 @@ func CreateVolume(vol *apis.LVMVolume) error {
275296
}
276297

277298
args := buildLVMCreateArgs(vol)
278-
cmd := exec.Command(LVCreate, args...)
279-
out, err := cmd.CombinedOutput()
299+
out, _, err := RunCommandSplit(LVCreate, args...)
280300

281301
if err != nil {
282302
err = newExecError(out, err)
@@ -314,8 +334,7 @@ func DestroyVolume(vol *apis.LVMVolume) error {
314334
}
315335

316336
args := buildLVMDestroyArgs(vol)
317-
cmd := exec.Command(LVRemove, args...)
318-
out, err := cmd.CombinedOutput()
337+
out, _, err := RunCommandSplit(LVRemove, args...)
319338

320339
if err != nil {
321340
klog.Errorf(
@@ -406,8 +425,7 @@ func ResizeLVMVolume(vol *apis.LVMVolume, resizefs bool) error {
406425
volume := vol.Spec.VolGroup + "/" + vol.Name
407426

408427
args := buildVolumeResizeArgs(vol, resizefs)
409-
cmd := exec.Command(LVExtend, args...)
410-
out, err := cmd.CombinedOutput()
428+
out, _, err := RunCommandSplit(LVExtend, args...)
411429

412430
if err != nil {
413431
klog.Errorf(
@@ -430,8 +448,7 @@ func getLVSize(vol *apis.LVMVolume) (uint64, error) {
430448
"--nosuffix",
431449
}
432450

433-
cmd := exec.Command(LVList, args...)
434-
raw, err := cmd.CombinedOutput()
451+
raw, _, err := RunCommandSplit(LVList, args...)
435452
if err != nil {
436453
return 0, errors.Wrapf(
437454
err,
@@ -495,8 +512,7 @@ func CreateSnapshot(snap *apis.LVMSnapshot) error {
495512
snapVolume := snap.Spec.VolGroup + "/" + getLVMSnapName(snap.Name)
496513

497514
args := buildLVMSnapCreateArgs(snap)
498-
cmd := exec.Command(LVCreate, args...)
499-
out, err := cmd.CombinedOutput()
515+
out, _, err := RunCommandSplit(LVCreate, args...)
500516

501517
if err != nil {
502518
klog.Errorf("lvm: could not create snapshot %s cmd %v error: %s", snapVolume, args, string(out))
@@ -524,8 +540,7 @@ func DestroySnapshot(snap *apis.LVMSnapshot) error {
524540
}
525541

526542
args := buildLVMSnapDestroyArgs(snap)
527-
cmd := exec.Command(LVRemove, args...)
528-
out, err := cmd.CombinedOutput()
543+
out, _, err := RunCommandSplit(LVRemove, args...)
529544

530545
if err != nil {
531546
klog.Errorf("lvm: could not remove snapshot %s cmd %v error: %s", snapVolume, args, string(out))
@@ -639,34 +654,13 @@ func getIntFieldValue(fieldName, fieldValue string) int {
639654
// serving vgs or other lvm utility.
640655
func ReloadLVMMetadataCache() error {
641656
args := []string{"--cache"}
642-
cmd := exec.Command(PVScan, args...)
643-
output, err := cmd.CombinedOutput()
657+
output, _, err := RunCommandSplit(PVScan, args...)
644658
if err != nil {
645659
klog.Errorf("lvm: reload lvm metadata cache: %v - %v", string(output), err)
646660
return err
647661
}
648-
return nil
649-
}
650-
651-
// RunCommandSplit is a wrapper function to run a command and receive its
652-
// STDERR and STDOUT streams in separate []byte vars.
653-
func RunCommandSplit(command string, args ...string) ([]byte, []byte, error) {
654-
var cmdStdout bytes.Buffer
655-
var cmdStderr bytes.Buffer
656-
657-
cmd := exec.Command(command, args...)
658-
cmd.Stdout = &cmdStdout
659-
cmd.Stderr = &cmdStderr
660-
err := cmd.Run()
661-
662-
output := cmdStdout.Bytes()
663-
error_output := cmdStderr.Bytes()
664-
665-
if len(error_output) > 0 {
666-
klog.Warningf("lvm: said into stderr: %s", error_output)
667-
}
668662

669-
return output, error_output, err
663+
return nil
670664
}
671665

672666
// ListLVMVolumeGroup invokes `vgs` to list all the available volume
@@ -880,12 +874,12 @@ func ListLVMLogicalVolume() ([]LogicalVolume, error) {
880874
"--reportformat", "json",
881875
"--units", "b",
882876
}
883-
cmd := exec.Command(LVList, args...)
884-
output, err := cmd.CombinedOutput()
877+
output, _, err := RunCommandSplit(LVList, args...)
885878
if err != nil {
886879
klog.Errorf("lvm: error while running command %s %v: %v", LVList, args, err)
887880
return nil, err
888881
}
882+
889883
return decodeLvsJSON(output)
890884
}
891885

@@ -902,12 +896,12 @@ func ListLVMPhysicalVolume() ([]PhysicalVolume, error) {
902896
"--reportformat", "json",
903897
"--units", "b",
904898
}
905-
cmd := exec.Command(PVList, args...)
906-
output, err := cmd.CombinedOutput()
899+
output, _, err := RunCommandSplit(PVList, args...)
907900
if err != nil {
908901
klog.Errorf("lvm: error while running command %s %v: %v", PVList, args, err)
909902
return nil, err
910903
}
904+
911905
return decodePvsJSON(output)
912906
}
913907

@@ -1029,20 +1023,19 @@ func decodePvsJSON(raw []byte) ([]PhysicalVolume, error) {
10291023

10301024
// lvThinExists verifies if thin pool/volume already exists for given volumegroup
10311025
func lvThinExists(vg string, name string) bool {
1032-
cmd := exec.Command("lvs", vg+"/"+name, "--noheadings", "-o", "lv_name")
1033-
out, err := cmd.CombinedOutput()
1026+
out, _, err := RunCommandSplit("lvs", vg+"/"+name, "--noheadings", "-o", "lv_name")
10341027
if err != nil {
10351028
klog.Errorf("failed to list existing volumes:%v", err)
10361029
return false
10371030
}
1031+
10381032
return name == strings.TrimSpace(string(out))
10391033
}
10401034

10411035
// snapshotExists checks if a snapshot volume exists for the given volumegroup
10421036
// and snapshot name.
10431037
func isSnapshotExists(vg, snapVolumeName string) (bool, error) {
1044-
cmd := exec.Command("lvs", vg+"/"+snapVolumeName, "--noheadings", "-o", "lv_name")
1045-
out, err := cmd.CombinedOutput()
1038+
out, _, err := RunCommandSplit("lvs", vg+"/"+snapVolumeName, "--noheadings", "-o", "lv_name")
10461039
if err != nil {
10471040
return false, err
10481041
}
@@ -1051,8 +1044,7 @@ func isSnapshotExists(vg, snapVolumeName string) (bool, error) {
10511044

10521045
// getVGSize get the size in bytes for given volumegroup name
10531046
func getVGSize(vgname string) string {
1054-
cmd := exec.Command("vgs", vgname, "--noheadings", "-o", "vg_free", "--units", "b", "--nosuffix")
1055-
out, err := cmd.CombinedOutput()
1047+
out, _, err := RunCommandSplit("vgs", vgname, "--noheadings", "-o", "vg_free", "--units", "b", "--nosuffix")
10561048
if err != nil {
10571049
klog.Errorf("failed to list existing volumegroup:%v , %v", vgname, err)
10581050
return ""

0 commit comments

Comments
 (0)