From 256c68fecad0625d27c8579fac274c495fc26cb3 Mon Sep 17 00:00:00 2001 From: Andrew Lavery Date: Thu, 18 Mar 2021 19:01:48 -0400 Subject: [PATCH] added two parameters to the eligible block device check whether to accept unmounted partitions (default false) and minimum acceptable device size (default 0) --- pkg/analyze/host_block_devices.go | 32 +++++-- pkg/analyze/host_block_devices_test.go | 91 +++++++++++++++++++ .../v1beta2/hostanalyzer_shared.go | 6 +- 3 files changed, 117 insertions(+), 12 deletions(-) diff --git a/pkg/analyze/host_block_devices.go b/pkg/analyze/host_block_devices.go index 099c88b2..6761d701 100644 --- a/pkg/analyze/host_block_devices.go +++ b/pkg/analyze/host_block_devices.go @@ -51,7 +51,7 @@ func (a *AnalyzeHostBlockDevices) Analyze(getCollectedFileContents func(string) return &result, nil } - isMatch, err := compareHostBlockDevicesConditionalToActual(outcome.Fail.When, devices) + isMatch, err := compareHostBlockDevicesConditionalToActual(outcome.Fail.When, hostAnalyzer.MinimumAcceptableSize, hostAnalyzer.IncludeUnmountedPartitions, devices) if err != nil { return nil, errors.Wrapf(err, "failed to compare %s", outcome.Fail.When) } @@ -72,7 +72,7 @@ func (a *AnalyzeHostBlockDevices) Analyze(getCollectedFileContents func(string) return &result, nil } - isMatch, err := compareHostBlockDevicesConditionalToActual(outcome.Warn.When, devices) + isMatch, err := compareHostBlockDevicesConditionalToActual(outcome.Warn.When, hostAnalyzer.MinimumAcceptableSize, hostAnalyzer.IncludeUnmountedPartitions, devices) if err != nil { return nil, errors.Wrapf(err, "failed to compare %s", outcome.Warn.When) } @@ -93,7 +93,7 @@ func (a *AnalyzeHostBlockDevices) Analyze(getCollectedFileContents func(string) return &result, nil } - isMatch, err := compareHostBlockDevicesConditionalToActual(outcome.Pass.When, devices) + isMatch, err := compareHostBlockDevicesConditionalToActual(outcome.Pass.When, hostAnalyzer.MinimumAcceptableSize, hostAnalyzer.IncludeUnmountedPartitions, devices) if err != nil { return nil, errors.Wrapf(err, "failed to compare %s", outcome.Pass.When) } @@ -113,7 +113,7 @@ func (a *AnalyzeHostBlockDevices) Analyze(getCollectedFileContents func(string) // // example: sdb > 0 -func compareHostBlockDevicesConditionalToActual(conditional string, devices []collect.BlockDeviceInfo) (res bool, err error) { +func compareHostBlockDevicesConditionalToActual(conditional string, minimumAcceptableSize uint64, includeUnmountedPartitions bool, devices []collect.BlockDeviceInfo) (res bool, err error) { parts := strings.Split(conditional, " ") if len(parts) != 3 { return false, fmt.Errorf("Expected exactly 3 parts, got %d", len(parts)) @@ -123,7 +123,7 @@ func compareHostBlockDevicesConditionalToActual(conditional string, devices []co if err != nil { return false, errors.Wrapf(err, "failed to compile regex %q", parts[0]) } - count := countEligibleBlockDevices(rx, devices) + count := countEligibleBlockDevices(rx, minimumAcceptableSize, includeUnmountedPartitions, devices) desiredInt, err := strconv.Atoi(parts[2]) if err != nil { @@ -146,11 +146,11 @@ func compareHostBlockDevicesConditionalToActual(conditional string, devices []co return false, fmt.Errorf("Unexpected operator %q", parts[1]) } -func countEligibleBlockDevices(rx *regexp.Regexp, devices []collect.BlockDeviceInfo) int { +func countEligibleBlockDevices(rx *regexp.Regexp, minimumAcceptableSize uint64, includeUnmountedPartitions bool, devices []collect.BlockDeviceInfo) int { count := 0 for _, device := range devices { - if isEligibleBlockDevice(rx, device, devices) { + if isEligibleBlockDevice(rx, minimumAcceptableSize, includeUnmountedPartitions, device, devices) { count++ } } @@ -158,13 +158,25 @@ func countEligibleBlockDevices(rx *regexp.Regexp, devices []collect.BlockDeviceI return count } -func isEligibleBlockDevice(rx *regexp.Regexp, device collect.BlockDeviceInfo, devices []collect.BlockDeviceInfo) bool { +func isEligibleBlockDevice(rx *regexp.Regexp, minimumAcceptableSize uint64, includeUnmountedPartitions bool, device collect.BlockDeviceInfo, devices []collect.BlockDeviceInfo) bool { if !rx.MatchString(device.Name) { return false } - if device.Type != "disk" { - return false + if includeUnmountedPartitions { + if device.Type != "disk" && device.Type != "part" { + return false + } + } else { + if device.Type != "disk" { + return false + } + } + + if minimumAcceptableSize != 0 { + if device.Size < minimumAcceptableSize { + return false + } } if device.Mountpoint != "" { diff --git a/pkg/analyze/host_block_devices_test.go b/pkg/analyze/host_block_devices_test.go index 962b96b5..fccbcdf1 100644 --- a/pkg/analyze/host_block_devices_test.go +++ b/pkg/analyze/host_block_devices_test.go @@ -149,6 +149,97 @@ func TestAnalyzeBlockDevices(t *testing.T) { Message: "No block device available", }, }, + { + name: ".* > 1, pass with unmounted partition", + devices: []collect.BlockDeviceInfo{ + { + Name: "sdb", + KernelName: "sdb", + Type: "disk", + Major: 8, + Serial: "disk1", + }, + { + Name: "sdb1", + KernelName: "sdb1", + ParentKernelName: "sdb", + Type: "part", + Major: 8, + Minor: 1, + }, + }, + hostAnalyzer: &troubleshootv1beta2.BlockDevicesAnalyze{ + IncludeUnmountedPartitions: true, + Outcomes: []*troubleshootv1beta2.Outcome{ + { + Pass: &troubleshootv1beta2.SingleOutcome{ + When: ".* >= 1", + Message: "Block device or partition available", + }, + }, + }, + }, + result: &AnalyzeResult{ + Title: "Block Devices", + IsPass: true, + Message: "Block device or partition available", + }, + }, + { + name: ".* = 2, pass with two unmounted partitions/devices of at least 10gb in size", + devices: []collect.BlockDeviceInfo{ + { + Name: "sdb", + KernelName: "sdb", + Type: "disk", + Major: 8, + Serial: "disk1", + Size: 1024 * 1024 * 1024 * 128, + }, + { + Name: "sdb1", + KernelName: "sdb1", + ParentKernelName: "sdb", + Type: "part", + Major: 8, + Minor: 1, + Size: 1024 * 1024 * 1024 * 128, + }, + { + Name: "sdc", + KernelName: "sdc", + Type: "disk", + Major: 8, + Serial: "disk2", + Size: 1024 * 1024 * 1024 * 16, + }, + { + Name: "sdd", + KernelName: "sdd", + Type: "disk", + Major: 8, + Serial: "disk3", + Size: 1024 * 1024 * 1024 * 8, + }, + }, + hostAnalyzer: &troubleshootv1beta2.BlockDevicesAnalyze{ + IncludeUnmountedPartitions: true, + MinimumAcceptableSize: 1024 * 1024 * 1024 * 10, + Outcomes: []*troubleshootv1beta2.Outcome{ + { + Pass: &troubleshootv1beta2.SingleOutcome{ + When: ".* = 2", + Message: "Two block devices or partitions of >10gb size available", + }, + }, + }, + }, + result: &AnalyzeResult{ + Title: "Block Devices", + IsPass: true, + Message: "Two block devices or partitions of >10gb size available", + }, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { diff --git a/pkg/apis/troubleshoot/v1beta2/hostanalyzer_shared.go b/pkg/apis/troubleshoot/v1beta2/hostanalyzer_shared.go index c4b06a6f..9b386afa 100644 --- a/pkg/apis/troubleshoot/v1beta2/hostanalyzer_shared.go +++ b/pkg/apis/troubleshoot/v1beta2/hostanalyzer_shared.go @@ -46,8 +46,10 @@ type TimeAnalyze struct { } type BlockDevicesAnalyze struct { - AnalyzeMeta `json:",inline" yaml:",inline"` - Outcomes []*Outcome `json:"outcomes" yaml:"outcomes"` + AnalyzeMeta `json:",inline" yaml:",inline"` + MinimumAcceptableSize uint64 `json:"minimumAcceptableSize" yaml:"minimumAcceptableSize"` + IncludeUnmountedPartitions bool `json:"includeUnmountedPartitions" yaml:"includeUnmountedPartitions"` + Outcomes []*Outcome `json:"outcomes" yaml:"outcomes"` } type TCPConnectAnalyze struct {