From 8c051b8c5391330f086a9d1076d3b730837cc38f Mon Sep 17 00:00:00 2001 From: Mikita Iwanowski Date: Tue, 19 Nov 2024 17:59:55 +0100 Subject: [PATCH 1/4] feat: add unpartitioned volumes support --- providers/os/connection/snapshot/blockdevices.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/providers/os/connection/snapshot/blockdevices.go b/providers/os/connection/snapshot/blockdevices.go index 5eaa96a035..8f6b05c1e2 100644 --- a/providers/os/connection/snapshot/blockdevices.go +++ b/providers/os/connection/snapshot/blockdevices.go @@ -169,6 +169,9 @@ func (device BlockDevice) GetMountablePartitions(includeAll bool) ([]*PartitionI blockDevices := &BlockDevices{ BlockDevices: device.Children, } + if len(blockDevices.BlockDevices) == 0 && device.FsType != "" { + blockDevices.BlockDevices = append(blockDevices.BlockDevices, device) + } // sort the candidates by size, so we can pick the largest one sortBlockDevicesBySize(blockDevices.BlockDevices) From ab3545c63261c835d717315c6350b47c38f4d663 Mon Sep 17 00:00:00 2001 From: Mikita Iwanowski Date: Tue, 19 Nov 2024 18:00:29 +0100 Subject: [PATCH 2/4] feat: device-names option & multiple devices support --- providers/os/config/config.go | 8 +++- .../connection/device/linux/device_manager.go | 39 +++++++++++++------ providers/os/provider/provider.go | 12 +++++- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/providers/os/config/config.go b/providers/os/config/config.go index 330e518871..907cd1d93b 100644 --- a/providers/os/config/config.go +++ b/providers/os/config/config.go @@ -279,7 +279,13 @@ var Config = plugin.Provider{ { Long: "device-name", Type: plugin.FlagType_String, - Desc: "The target device to scan, e.g. /dev/sda. Supported only for Linux scanning. Do not use together with --lun or --serial-number", + Desc: "The target device to scan, e.g. /dev/sda. Supported only for Linux scanning. Do not use together with --lun or --serial-number (Deprecated: use --device-names instead)", + Option: plugin.FlagOption_Hidden, + }, + { + Long: "device-names", + Type: plugin.FlagType_List, + Desc: "The target devices to scan, e.g. /dev/sda. Supported only for Linux scanning. Do not use together with --lun or --serial-number", Option: plugin.FlagOption_Hidden, }, { diff --git a/providers/os/connection/device/linux/device_manager.go b/providers/os/connection/device/linux/device_manager.go index 0cfb45ec7b..47c16b115f 100644 --- a/providers/os/connection/device/linux/device_manager.go +++ b/providers/os/connection/device/linux/device_manager.go @@ -5,6 +5,7 @@ package linux import ( "strconv" + "strings" "github.com/cockroachdb/errors" "github.com/rs/zerolog/log" @@ -14,6 +15,7 @@ import ( const ( LunOption = "lun" DeviceName = "device-name" + DeviceNames = "device-names" MountAllPartitions = "mount-all-partitions" ) @@ -53,11 +55,23 @@ func (d *LinuxDeviceManager) IdentifyMountTargets(opts map[string]string) ([]*sn return []*snapshot.PartitionInfo{pi}, nil } - partitions, err := d.identifyViaDeviceName(opts[DeviceName], opts[MountAllPartitions] == "true") - if err != nil { - return nil, err + deviceNames := strings.Split(opts[DeviceNames], ",") + if opts[DeviceName] != "" { + deviceNames = append(deviceNames, opts[DeviceName]) } - return partitions, nil + + var partitions []*snapshot.PartitionInfo + var errs []error + for _, deviceName := range deviceNames { + partitionsForDevice, err := d.identifyViaDeviceName(deviceName, opts[MountAllPartitions] == "true") + if err != nil { + errs = append(errs, err) + continue + } + partitions = append(partitions, partitionsForDevice...) + } + + return partitions, errors.Join(errs...) } func (d *LinuxDeviceManager) Mount(pi *snapshot.PartitionInfo) (string, error) { @@ -86,18 +100,21 @@ func (d *LinuxDeviceManager) UnmountAndClose() { // we cannot have both LUN and device name provided, those are mutually exclusive func validateOpts(opts map[string]string) error { lun := opts[LunOption] - deviceName := opts[DeviceName] + + // this is needed only for the validation purposes + deviceNames := opts[DeviceNames] + opts[DeviceName] + mountAll := opts[MountAllPartitions] == "true" - if lun != "" && deviceName != "" { - return errors.New("both lun and device name provided") + if lun != "" && deviceNames != "" { + return errors.New("both lun and device names provided") } - if lun == "" && deviceName == "" { - return errors.New("either lun or device name must be provided") + if lun == "" && deviceNames == "" { + return errors.New("either lun or device names must be provided") } - if deviceName == "" && mountAll { - return errors.New("mount-all-partitions requires a device name") + if deviceNames == "" && mountAll { + return errors.New("mount-all-partitions requires device names") } return nil diff --git a/providers/os/provider/provider.go b/providers/os/provider/provider.go index c99e5c8261..7bcfeb22ce 100644 --- a/providers/os/provider/provider.go +++ b/providers/os/provider/provider.go @@ -227,9 +227,19 @@ func (s *Service) ParseCLI(req *plugin.ParseCLIReq) (*plugin.ParseCLIRes, error) if lun, ok := flags["lun"]; ok { conf.Options["lun"] = lun.RawData().Value.(string) } + + deviceNames := []string{} if deviceName, ok := flags["device-name"]; ok { - conf.Options["device-name"] = deviceName.RawData().Value.(string) + deviceNames = append(deviceNames, deviceName.RawData().Value.(string)) + } + if deviceName, ok := flags["device-names"]; ok { + deviceNamesList := deviceName.RawData().Value.([]any) + for _, deviceName := range deviceNamesList { + deviceNames = append(deviceNames, deviceName.(string)) + } } + conf.Options["device-names"] = strings.Join(deviceNames, ",") + if serialNumber, ok := flags["serial-number"]; ok { conf.Options["serial-number"] = serialNumber.RawData().Value.(string) } From 924a6717deaca58c09c4e5f61848b5c72994e58a Mon Sep 17 00:00:00 2001 From: Mikita Iwanowski Date: Tue, 19 Nov 2024 18:04:00 +0100 Subject: [PATCH 3/4] test: TestGetMountablePartitions with unpartitioned device --- .../os/connection/snapshot/blockdevices_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/providers/os/connection/snapshot/blockdevices_test.go b/providers/os/connection/snapshot/blockdevices_test.go index 0800636b73..a42dd2a4f3 100644 --- a/providers/os/connection/snapshot/blockdevices_test.go +++ b/providers/os/connection/snapshot/blockdevices_test.go @@ -285,6 +285,21 @@ func TestGetMountablePartitions(t *testing.T) { } require.ElementsMatch(t, expected, parts) }) + + t.Run("get all non-mounted partitions (unpartitioned)", func(t *testing.T) { + block := BlockDevice{ + Name: "sda", + FsType: "xfs", + Label: "ROOT", + Uuid: "1234", + } + parts, err := block.GetMountablePartitions(true) + require.NoError(t, err) + expected := []*PartitionInfo{ + {Name: "/dev/sda", FsType: "xfs", Uuid: "1234", Label: "ROOT"}, + } + require.ElementsMatch(t, expected, parts) + }) } func TestLongestMatchingSuffix(t *testing.T) { From b740370f5d635a4a79b1a2b1dc54a1feca2c077f Mon Sep 17 00:00:00 2001 From: Mikita Iwanowski Date: Wed, 20 Nov 2024 13:16:44 +0100 Subject: [PATCH 4/4] fix: use deprecated flag option --- providers/os/config/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/providers/os/config/config.go b/providers/os/config/config.go index 907cd1d93b..bc3cc75fc6 100644 --- a/providers/os/config/config.go +++ b/providers/os/config/config.go @@ -279,8 +279,8 @@ var Config = plugin.Provider{ { Long: "device-name", Type: plugin.FlagType_String, - Desc: "The target device to scan, e.g. /dev/sda. Supported only for Linux scanning. Do not use together with --lun or --serial-number (Deprecated: use --device-names instead)", - Option: plugin.FlagOption_Hidden, + Desc: "The target device to scan, e.g. /dev/sda. Supported only for Linux scanning. Do not use together with --lun or --serial-number", + Option: plugin.FlagOption_Hidden | plugin.FlagOption_Deprecated, }, { Long: "device-names",