Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
107
plugins/inputs/lvm/README.md
Normal file
107
plugins/inputs/lvm/README.md
Normal file
|
@ -0,0 +1,107 @@
|
|||
# Logical Volume Manager Input Plugin
|
||||
|
||||
This plugin collects information about physical volumes, volume groups and
|
||||
logical volumes from the Logical Volume Management (LVM) of the
|
||||
[Linux kernel][kernel].
|
||||
|
||||
⭐ Telegraf v1.21.0
|
||||
🏷️ system
|
||||
💻 linux
|
||||
|
||||
[kernel]: https://www.kernel.org/
|
||||
|
||||
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||
|
||||
In addition to the plugin-specific configuration settings, plugins support
|
||||
additional global and plugin configuration settings. These settings are used to
|
||||
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||
|
||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
# Read metrics about LVM physical volumes, volume groups, logical volumes.
|
||||
[[inputs.lvm]]
|
||||
## Use sudo to run LVM commands
|
||||
use_sudo = false
|
||||
|
||||
## The default location of the pvs binary can be overridden with:
|
||||
#pvs_binary = "/usr/sbin/pvs"
|
||||
|
||||
## The default location of the vgs binary can be overridden with:
|
||||
#vgs_binary = "/usr/sbin/vgs"
|
||||
|
||||
## The default location of the lvs binary can be overridden with:
|
||||
#lvs_binary = "/usr/sbin/lvs"
|
||||
```
|
||||
|
||||
The LVM commands requires elevated permissions. If the user has configured sudo
|
||||
with the ability to run these commands, then set the `use_sudo` to true.
|
||||
|
||||
### Using sudo
|
||||
|
||||
If your account does not already have the ability to run commands
|
||||
with passwordless sudo then updates to the sudoers file are required. Below
|
||||
is an example to allow the requires LVM commands:
|
||||
|
||||
First, use the `visudo` command to start editing the sudoers file. Then add
|
||||
the following content, where `<username>` is the username of the user that
|
||||
needs this access:
|
||||
|
||||
```text
|
||||
Cmnd_Alias LVM = /usr/sbin/pvs *, /usr/sbin/vgs *, /usr/sbin/lvs *
|
||||
<username> ALL=(root) NOPASSWD: LVM
|
||||
Defaults!LVM !logfile, !syslog, !pam_session
|
||||
```
|
||||
|
||||
Path to binaries must match those from config file (pvs_binary, vgs_binary and
|
||||
lvs_binary)
|
||||
|
||||
## Metrics
|
||||
|
||||
Metrics are broken out by physical volume (pv), volume group (vg), and logical
|
||||
volume (lv):
|
||||
|
||||
- lvm_physical_vol
|
||||
- tags
|
||||
- path
|
||||
- vol_group
|
||||
- fields
|
||||
- size
|
||||
- free
|
||||
- used
|
||||
- used_percent
|
||||
- lvm_vol_group
|
||||
- tags
|
||||
- name
|
||||
- fields
|
||||
- size
|
||||
- free
|
||||
- used_percent
|
||||
- physical_volume_count
|
||||
- logical_volume_count
|
||||
- snapshot_count
|
||||
- lvm_logical_vol
|
||||
- tags
|
||||
- name
|
||||
- vol_group
|
||||
- fields
|
||||
- size
|
||||
- data_percent
|
||||
- meta_percent
|
||||
|
||||
## Example Output
|
||||
|
||||
The following example shows a system with the root partition on an LVM group
|
||||
as well as with a Docker thin-provisioned LVM group on a second drive:
|
||||
|
||||
```text
|
||||
lvm_physical_vol,path=/dev/sda2,vol_group=vgroot free=0i,size=249510756352i,used=249510756352i,used_percent=100 1631823026000000000
|
||||
lvm_physical_vol,path=/dev/sdb,vol_group=docker free=3858759680i,size=128316342272i,used=124457582592i,used_percent=96.99277612525741 1631823026000000000
|
||||
lvm_vol_group,name=vgroot free=0i,logical_volume_count=1i,physical_volume_count=1i,size=249510756352i,snapshot_count=0i,used_percent=100 1631823026000000000
|
||||
lvm_vol_group,name=docker free=3858759680i,logical_volume_count=1i,physical_volume_count=1i,size=128316342272i,snapshot_count=0i,used_percent=96.99277612525741 1631823026000000000
|
||||
lvm_logical_vol,name=lvroot,vol_group=vgroot data_percent=0,metadata_percent=0,size=249510756352i 1631823026000000000
|
||||
lvm_logical_vol,name=thinpool,vol_group=docker data_percent=0.36000001430511475,metadata_percent=1.3300000429153442,size=121899057152i 1631823026000000000
|
||||
```
|
288
plugins/inputs/lvm/lvm.go
Normal file
288
plugins/inputs/lvm/lvm.go
Normal file
|
@ -0,0 +1,288 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package lvm
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
var (
|
||||
execCommand = exec.Command
|
||||
)
|
||||
|
||||
type LVM struct {
|
||||
UseSudo bool `toml:"use_sudo"`
|
||||
PVSBinary string `toml:"pvs_binary"`
|
||||
VGSBinary string `toml:"vgs_binary"`
|
||||
LVSBinary string `toml:"lvs_binary"`
|
||||
}
|
||||
|
||||
func (*LVM) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (lvm *LVM) Gather(acc telegraf.Accumulator) error {
|
||||
if err := lvm.gatherPhysicalVolumes(acc); err != nil {
|
||||
return err
|
||||
} else if err := lvm.gatherVolumeGroups(acc); err != nil {
|
||||
return err
|
||||
} else if err := lvm.gatherLogicalVolumes(acc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lvm *LVM) gatherPhysicalVolumes(acc telegraf.Accumulator) error {
|
||||
args := []string{
|
||||
"--reportformat", "json", "--units", "b", "--nosuffix",
|
||||
"-o", "pv_name,vg_name,pv_size,pv_free,pv_used",
|
||||
}
|
||||
out, err := lvm.runCmd(lvm.PVSBinary, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var report pvsReport
|
||||
err = json.Unmarshal(out, &report)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal physical volume JSON: %w", err)
|
||||
}
|
||||
|
||||
if len(report.Report) > 0 {
|
||||
for _, pv := range report.Report[0].Pv {
|
||||
tags := map[string]string{
|
||||
"path": pv.Name,
|
||||
"vol_group": pv.VolGroup,
|
||||
}
|
||||
|
||||
size, err := strconv.ParseUint(pv.Size, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
free, err := strconv.ParseUint(pv.Free, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
used, err := strconv.ParseUint(pv.Used, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
usedPercent := float64(used) / float64(size) * 100
|
||||
|
||||
fields := map[string]interface{}{
|
||||
"size": size,
|
||||
"free": free,
|
||||
"used": used,
|
||||
"used_percent": usedPercent,
|
||||
}
|
||||
|
||||
acc.AddFields("lvm_physical_vol", fields, tags)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lvm *LVM) gatherVolumeGroups(acc telegraf.Accumulator) error {
|
||||
args := []string{
|
||||
"--reportformat", "json", "--units", "b", "--nosuffix",
|
||||
"-o", "vg_name,pv_count,lv_count,snap_count,vg_size,vg_free",
|
||||
}
|
||||
out, err := lvm.runCmd(lvm.VGSBinary, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var report vgsReport
|
||||
err = json.Unmarshal(out, &report)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal vol group JSON: %w", err)
|
||||
}
|
||||
|
||||
if len(report.Report) > 0 {
|
||||
for _, vg := range report.Report[0].Vg {
|
||||
tags := map[string]string{
|
||||
"name": vg.Name,
|
||||
}
|
||||
|
||||
size, err := strconv.ParseUint(vg.Size, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
free, err := strconv.ParseUint(vg.Free, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pvCount, err := strconv.ParseUint(vg.PvCount, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lvCount, err := strconv.ParseUint(vg.LvCount, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
snapCount, err := strconv.ParseUint(vg.SnapCount, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
usedPercent := (float64(size) - float64(free)) / float64(size) * 100
|
||||
|
||||
fields := map[string]interface{}{
|
||||
"size": size,
|
||||
"free": free,
|
||||
"used_percent": usedPercent,
|
||||
"physical_volume_count": pvCount,
|
||||
"logical_volume_count": lvCount,
|
||||
"snapshot_count": snapCount,
|
||||
}
|
||||
|
||||
acc.AddFields("lvm_vol_group", fields, tags)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lvm *LVM) gatherLogicalVolumes(acc telegraf.Accumulator) error {
|
||||
args := []string{
|
||||
"--reportformat", "json", "--units", "b", "--nosuffix",
|
||||
"-o", "lv_name,vg_name,lv_size,data_percent,metadata_percent",
|
||||
}
|
||||
out, err := lvm.runCmd(lvm.LVSBinary, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var report lvsReport
|
||||
err = json.Unmarshal(out, &report)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal logical vol JSON: %w", err)
|
||||
}
|
||||
|
||||
if len(report.Report) > 0 {
|
||||
for _, lv := range report.Report[0].Lv {
|
||||
tags := map[string]string{
|
||||
"name": lv.Name,
|
||||
"vol_group": lv.VolGroup,
|
||||
}
|
||||
|
||||
size, err := strconv.ParseUint(lv.Size, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Does not apply to all logical volumes, set default value
|
||||
if lv.DataPercent == "" {
|
||||
lv.DataPercent = "0.0"
|
||||
}
|
||||
dataPercent, err := strconv.ParseFloat(lv.DataPercent, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Does not apply to all logical volumes, set default value
|
||||
if lv.MetadataPercent == "" {
|
||||
lv.MetadataPercent = "0.0"
|
||||
}
|
||||
metadataPercent, err := strconv.ParseFloat(lv.MetadataPercent, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fields := map[string]interface{}{
|
||||
"size": size,
|
||||
"data_percent": dataPercent,
|
||||
"metadata_percent": metadataPercent,
|
||||
}
|
||||
|
||||
acc.AddFields("lvm_logical_vol", fields, tags)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lvm *LVM) runCmd(cmd string, args []string) ([]byte, error) {
|
||||
execCmd := execCommand(cmd, args...)
|
||||
if lvm.UseSudo {
|
||||
execCmd = execCommand("sudo", append([]string{"-n", cmd}, args...)...)
|
||||
}
|
||||
|
||||
out, err := internal.StdOutputTimeout(execCmd, 5*time.Second)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"failed to run command %s: %w - %s", strings.Join(execCmd.Args, " "), err, string(out),
|
||||
)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Represents info about physical volume command, pvs, output
|
||||
type pvsReport struct {
|
||||
Report []struct {
|
||||
Pv []struct {
|
||||
Name string `json:"pv_name"`
|
||||
VolGroup string `json:"vg_name"`
|
||||
Size string `json:"pv_size"`
|
||||
Free string `json:"pv_free"`
|
||||
Used string `json:"pv_used"`
|
||||
} `json:"pv"`
|
||||
} `json:"report"`
|
||||
}
|
||||
|
||||
// Represents info about volume group command, vgs, output
|
||||
type vgsReport struct {
|
||||
Report []struct {
|
||||
Vg []struct {
|
||||
Name string `json:"vg_name"`
|
||||
Size string `json:"vg_size"`
|
||||
Free string `json:"vg_free"`
|
||||
LvCount string `json:"lv_count"`
|
||||
PvCount string `json:"pv_count"`
|
||||
SnapCount string `json:"snap_count"`
|
||||
} `json:"vg"`
|
||||
} `json:"report"`
|
||||
}
|
||||
|
||||
// Represents info about logical volume command, lvs, output
|
||||
type lvsReport struct {
|
||||
Report []struct {
|
||||
Lv []struct {
|
||||
Name string `json:"lv_name"`
|
||||
VolGroup string `json:"vg_name"`
|
||||
Size string `json:"lv_size"`
|
||||
DataPercent string `json:"data_percent"`
|
||||
MetadataPercent string `json:"metadata_percent"`
|
||||
} `json:"lv"`
|
||||
} `json:"report"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("lvm", func() telegraf.Input {
|
||||
return &LVM{
|
||||
PVSBinary: "/usr/sbin/pvs",
|
||||
VGSBinary: "/usr/sbin/vgs",
|
||||
LVSBinary: "/usr/sbin/lvs",
|
||||
}
|
||||
})
|
||||
}
|
214
plugins/inputs/lvm/lvm_test.go
Normal file
214
plugins/inputs/lvm/lvm_test.go
Normal file
|
@ -0,0 +1,214 @@
|
|||
package lvm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
func TestGather(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
|
||||
lvm := LVM{
|
||||
PVSBinary: "/usr/sbin/pvs",
|
||||
VGSBinary: "/usr/sbin/vgs",
|
||||
LVSBinary: "/usr/sbin/lvs",
|
||||
}
|
||||
|
||||
// overwriting exec commands with mock commands
|
||||
execCommand = fakeExecCommand
|
||||
err := lvm.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
pvsTags := map[string]string{
|
||||
"path": "/dev/sdb",
|
||||
"vol_group": "docker",
|
||||
}
|
||||
pvsFields := map[string]interface{}{
|
||||
"size": uint64(128316342272),
|
||||
"free": uint64(3858759680),
|
||||
"used": uint64(124457582592),
|
||||
"used_percent": 96.99277612525741,
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "lvm_physical_vol", pvsFields, pvsTags)
|
||||
|
||||
vgsTags := map[string]string{
|
||||
"name": "docker",
|
||||
}
|
||||
vgsFields := map[string]interface{}{
|
||||
"size": uint64(128316342272),
|
||||
"free": uint64(3858759680),
|
||||
"used_percent": 96.99277612525741,
|
||||
"physical_volume_count": uint64(1),
|
||||
"logical_volume_count": uint64(1),
|
||||
"snapshot_count": uint64(0),
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "lvm_vol_group", vgsFields, vgsTags)
|
||||
|
||||
lvsTags := map[string]string{
|
||||
"name": "thinpool",
|
||||
"vol_group": "docker",
|
||||
}
|
||||
lvsFields := map[string]interface{}{
|
||||
"size": uint64(121899057152),
|
||||
"data_percent": 0.36000001430511475,
|
||||
"metadata_percent": 1.3300000429153442,
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "lvm_logical_vol", lvsFields, lvsTags)
|
||||
}
|
||||
|
||||
// Used as a helper function that mock the exec.Command call
|
||||
func fakeExecCommand(command string, args ...string) *exec.Cmd {
|
||||
cs := []string{"-test.run=TestHelperProcess", "--", command}
|
||||
cs = append(cs, args...)
|
||||
cmd := exec.Command(os.Args[0], cs...)
|
||||
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Used to mock exec.Command output
|
||||
func TestHelperProcess(_ *testing.T) {
|
||||
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
|
||||
return
|
||||
}
|
||||
|
||||
mockPVSData := `{
|
||||
"report": [
|
||||
{
|
||||
"pv": [
|
||||
{"pv_name":"/dev/sdb", "vg_name":"docker", "pv_size":"128316342272", "pv_free":"3858759680", "pv_used":"124457582592"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
mockVGSData := `{
|
||||
"report": [
|
||||
{
|
||||
"vg": [
|
||||
{"vg_name":"docker", "pv_count":"1", "lv_count":"1", "snap_count":"0", "vg_size":"128316342272", "vg_free":"3858759680"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
mockLVSData := `{
|
||||
"report": [
|
||||
{
|
||||
"lv": [
|
||||
{"lv_name":"thinpool", "vg_name":"docker", "lv_size":"121899057152", "data_percent":"0.36", "metadata_percent":"1.33"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
// Previous arguments are tests stuff, that looks like :
|
||||
// /tmp/go-build970079519/…/_test/integration.test -test.run=TestHelperProcess --
|
||||
args := os.Args
|
||||
cmd := args[3]
|
||||
if cmd == "/usr/sbin/pvs" {
|
||||
fmt.Fprint(os.Stdout, mockPVSData)
|
||||
} else if cmd == "/usr/sbin/vgs" {
|
||||
fmt.Fprint(os.Stdout, mockVGSData)
|
||||
} else if cmd == "/usr/sbin/lvs" {
|
||||
fmt.Fprint(os.Stdout, mockLVSData)
|
||||
} else {
|
||||
fmt.Fprint(os.Stdout, "command not found")
|
||||
//nolint:revive // error code is important for this "test"
|
||||
os.Exit(1)
|
||||
}
|
||||
//nolint:revive // error code is important for this "test"
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// test when no lvm devices exist
|
||||
func TestGatherNoLVM(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
|
||||
noLVM := LVM{
|
||||
PVSBinary: "/usr/sbin/pvs",
|
||||
VGSBinary: "/usr/sbin/vgs",
|
||||
LVSBinary: "/usr/sbin/lvs",
|
||||
}
|
||||
|
||||
// overwriting exec commands with mock commands
|
||||
execCommand = fakeExecCommandNoLVM
|
||||
err := noLVM.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
acc.AssertDoesNotContainMeasurement(t, "lvm_physical_vol")
|
||||
acc.AssertDoesNotContainMeasurement(t, "lvm_vol_group")
|
||||
acc.AssertDoesNotContainMeasurement(t, "lvm_logical_vol")
|
||||
}
|
||||
|
||||
// Used as a helper function that mock the exec.Command call
|
||||
func fakeExecCommandNoLVM(command string, args ...string) *exec.Cmd {
|
||||
cs := []string{"-test.run=TestHelperProcessNoLVM", "--", command}
|
||||
cs = append(cs, args...)
|
||||
cmd := exec.Command(os.Args[0], cs...)
|
||||
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Used to mock exec.Command output
|
||||
func TestHelperProcessNoLVM(_ *testing.T) {
|
||||
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
|
||||
return
|
||||
}
|
||||
|
||||
mockPVSData := `{
|
||||
"report": [
|
||||
{
|
||||
"pv": [
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
mockVGSData := `{
|
||||
"report": [
|
||||
{
|
||||
"vg": [
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
mockLVSData := `{
|
||||
"report": [
|
||||
{
|
||||
"lv": [
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
// Previous arguments are tests stuff, that looks like :
|
||||
// /tmp/go-build970079519/…/_test/integration.test -test.run=TestHelperProcess --
|
||||
args := os.Args
|
||||
cmd := args[3]
|
||||
if cmd == "/usr/sbin/pvs" {
|
||||
fmt.Fprint(os.Stdout, mockPVSData)
|
||||
} else if cmd == "/usr/sbin/vgs" {
|
||||
fmt.Fprint(os.Stdout, mockVGSData)
|
||||
} else if cmd == "/usr/sbin/lvs" {
|
||||
fmt.Fprint(os.Stdout, mockLVSData)
|
||||
} else {
|
||||
fmt.Fprint(os.Stdout, "command not found")
|
||||
//nolint:revive // error code is important for this "test"
|
||||
os.Exit(1)
|
||||
}
|
||||
//nolint:revive // error code is important for this "test"
|
||||
os.Exit(0)
|
||||
}
|
13
plugins/inputs/lvm/sample.conf
Normal file
13
plugins/inputs/lvm/sample.conf
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Read metrics about LVM physical volumes, volume groups, logical volumes.
|
||||
[[inputs.lvm]]
|
||||
## Use sudo to run LVM commands
|
||||
use_sudo = false
|
||||
|
||||
## The default location of the pvs binary can be overridden with:
|
||||
#pvs_binary = "/usr/sbin/pvs"
|
||||
|
||||
## The default location of the vgs binary can be overridden with:
|
||||
#vgs_binary = "/usr/sbin/vgs"
|
||||
|
||||
## The default location of the lvs binary can be overridden with:
|
||||
#lvs_binary = "/usr/sbin/lvs"
|
Loading…
Add table
Add a link
Reference in a new issue