mirror of
https://github.com/SCST-project/scst.git
synced 2026-10-22 14:12:33 +00:00
Add shared sg3_utils scenarios for scst_local and iSCSI exports: inquiry and VPD identity, capacity, LUN visibility, write protection and invalid LBA handling. Require the expected SCSI status and raw sense for rejected commands, then verify that valid reads still work. Use temporary fileio backends with 512-byte sectors. Keep fixture identifiers within vdisk's 20-character USN limit. Match each exported device to its fixture by identity and geometry before submitting commands. Carry binary responses over the existing supervised command transports and retain fixture ownership through successful cleanup. Add framework checks for response parsing, device selection and command interruption. Document tool prerequisites and the scsi label for both transports through the common Make targets.
69 lines
1.8 KiB
Go
69 lines
1.8 KiB
Go
// SPDX-License-Identifier: GPL-2.0-only
|
|
package dataio
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
"scst-component-tests/internal/admin"
|
|
)
|
|
|
|
type RunFunc func(context.Context, time.Duration, ...string) (admin.Result, error)
|
|
|
|
//go:embed command.py
|
|
var binaryCommand string
|
|
|
|
type Reply struct {
|
|
ExitCode int `json:"exit_code"`
|
|
Data []byte `json:"data"`
|
|
Stderr string `json:"stderr"`
|
|
}
|
|
|
|
func invoke(ctx context.Context, run RunFunc, timeout time.Duration, request any) (Reply, error) {
|
|
var response Reply
|
|
data, err := json.Marshal(request)
|
|
if err != nil {
|
|
return response, err
|
|
}
|
|
r, err := run(ctx, timeout, "python3", "-c", binaryCommand, string(data))
|
|
if err != nil {
|
|
return response, fmt.Errorf("data command execution: %w\n%s", err, r.String())
|
|
}
|
|
if r.ExitCode != 0 {
|
|
return response, fmt.Errorf("data command helper: %s", r.String())
|
|
}
|
|
var wire struct {
|
|
ExitCode *int `json:"exit_code"`
|
|
Data *[]byte `json:"data"`
|
|
Stderr *string `json:"stderr"`
|
|
}
|
|
if err := json.Unmarshal([]byte(r.Stdout), &wire); err != nil {
|
|
return response, fmt.Errorf("data command response: %w", err)
|
|
}
|
|
if wire.ExitCode == nil || wire.Data == nil || wire.Stderr == nil {
|
|
return response, fmt.Errorf("incomplete data command response")
|
|
}
|
|
response = Reply{*wire.ExitCode, *wire.Data, *wire.Stderr}
|
|
return response, nil
|
|
}
|
|
|
|
func command(ctx context.Context, run RunFunc, timeout time.Duration, input []byte, argv ...string) (Reply, error) {
|
|
return invoke(ctx, run, timeout, struct {
|
|
Args []string `json:"argv"`
|
|
Input []byte `json:"input,omitempty"`
|
|
}{argv, input})
|
|
}
|
|
|
|
func success(r Reply, err error) ([]byte, error) {
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if r.ExitCode != 0 {
|
|
return nil, fmt.Errorf("data command exit %d: %s", r.ExitCode, r.Stderr)
|
|
}
|
|
return r.Data, nil
|
|
}
|