in internal/system/appsdiscovery/apps_discovery.go [1525:1654]
func findDisksForHANABasePath(ctx context.Context, pathName string, globalINIPath string, exec commandlineexecutor.Execute) ([]string, error) {
// Get paths for desired mounts from global.ini
p := commandlineexecutor.Params{
Executable: "grep",
Args: []string{pathName, globalINIPath},
}
res := exec(ctx, p)
if res.Error != nil {
log.CtxLogger(ctx).Infow("Error executing grep", "error", res.Error, "stdOut", res.StdOut, "stdErr", res.StdErr, "exitcode", res.ExitCode)
return nil, res.Error
}
if res.StdOut == "" {
return nil, errors.New("path not found in global.ini " + pathName)
}
// Expected output should be like:
// basepath_datavolumes = /path/to/mount
parts := strings.Split(res.StdOut, "=")
if len(parts) < 2 {
return nil, errors.New("unable to find path for mount")
}
mount := strings.TrimSpace(parts[1])
// Remove trailing slash if present
mount = strings.TrimSuffix(mount, "/")
log.CtxLogger(ctx).Debugw("Found mount", "mount", mount)
// Find what is mounted to that path.
p = commandlineexecutor.Params{
Executable: "lsblk",
Args: []string{"--output=NAME,MOUNTPOINTS", "--json"},
}
res = exec(ctx, p)
if res.Error != nil {
log.CtxLogger(ctx).Infow("Error executing lsblk", "error", res.Error, "stdOut", res.StdOut, "stdErr", res.StdErr, "exitcode", res.ExitCode)
return nil, res.Error
}
// Output is json
var result lsblk
err := json.Unmarshal([]byte(res.StdOut), &result)
if err != nil {
log.CtxLogger(ctx).Infow("Error unmarshalling lsblk output", "error", err, "stdOut", res.StdOut)
return nil, err
}
var deviceNames []string
bestMatchLength := 0
// Find the block device with the best match to mount
for _, blockDevice := range result.BlockDevices {
log.CtxLogger(ctx).Debugw("Block device", "blockDevice", blockDevice)
blockDeviceName, blockMatchLen, err := findMountPointInBlockDevice(ctx, mount, blockDevice)
if err != nil {
return nil, err
}
if blockDeviceName == "" {
continue
}
if blockMatchLen > bestMatchLength {
log.CtxLogger(ctx).Debugw("Found better match", "blockDeviceName", blockDeviceName, "blockMatchLen", blockMatchLen, "bestMatchLength", bestMatchLength)
bestMatchLength = blockMatchLen
deviceNames = []string{blockDeviceName}
} else if blockMatchLen == bestMatchLength {
log.CtxLogger(ctx).Debugw("Found match with same length", "blockDeviceName", blockDeviceName, "blockMatchLen", blockMatchLen, "bestMatchLength", bestMatchLength)
deviceNames = append(deviceNames, blockDeviceName)
}
}
if len(deviceNames) == 0 {
return nil, errors.New("unable to find disk for mount")
}
log.CtxLogger(ctx).Debugw("Found device name", "deviceName", deviceNames)
// Find disk name for that device.
p = commandlineexecutor.Params{
Executable: "ls",
Args: []string{"-lart", "/dev/disk/by-id/"},
}
res = exec(ctx, p)
if res.Error != nil {
log.CtxLogger(ctx).Infow("Error executing ls", "error", res.Error, "stdOut", res.StdOut, "stdErr", res.StdErr, "exitcode", res.ExitCode)
return nil, res.Error
}
// Output will look like:
// lrwxrwxrwx 1 root root 9 Feb 5 07:32 /dev/disk/by-id/google-persistent-disk-0 -> ../../sda
// lrwxrwxrwx 1 root root 9 Feb 5 07:32 /dev/disk/by-id/google-sap-posdb00-hana-shared -> ../../sdf
// lrwxrwxrwx 1 root root 9 Feb 5 07:32 /dev/disk/by-id/google-sap-posdb00-hana-data-0 -> ../../sdc
// lrwxrwxrwx 1 root root 9 Feb 5 07:32 /dev/disk/by-id/google-sap-posdb00-usr-sap -> ../../sdb
devicePaths := []string{}
for _, deviceName := range deviceNames {
log.CtxLogger(ctx).Debugw("deviceName", "deviceName", deviceName)
for _, line := range strings.Split(res.StdOut, "\n") {
parts := strings.Fields(line)
// Expected parts:
// 0: permissions
// 1: links
// 2: owner
// 3: group
// 4: size
// 5: month
// 6: day
// 7: time
// 8: path
// 9: ->
// 10: device
log.CtxLogger(ctx).Debugw("parts", "parts", parts)
if len(parts) < 11 {
continue
}
device := parts[10]
if strings.HasSuffix(device, deviceName) {
log.CtxLogger(ctx).Debugw("ls output", "line", line)
log.CtxLogger(ctx).Debugw("Found device name in ls output")
devicePath := parts[8]
// Strip up up to the end of /google-
devicePath = strings.TrimPrefix(devicePath, "/dev/disk/by-id/")
devicePath = strings.TrimPrefix(devicePath, "google-")
devicePath = strings.TrimPrefix(devicePath, "scsi-0Google_PersistentDisk_")
// Maybe need to handle disk partitions
if !slices.Contains(devicePaths, devicePath) {
devicePaths = append(devicePaths, devicePath)
}
}
}
}
return devicePaths, nil
}