mirror of https://github.com/chaos-mesh/chaosd.git
add percentage of disk option in disk fill (#46)
This commit is contained in:
parent
721fc1398a
commit
618b8eaebe
|
|
@ -67,7 +67,7 @@ func NewDiskWritePayloadCommand(dep fx.Option, options *core.DiskCommand) *cobra
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().Uint64VarP(&options.Size, "size", "s", 0,
|
||||
cmd.Flags().StringVarP(&options.Size, "size", "s", "",
|
||||
"'size' specifies how many data will fill in the file path with unit MB.")
|
||||
cmd.Flags().StringVarP(&options.Path, "path", "p", "/dev/null",
|
||||
"'path' specifies the location to fill data in.\n"+
|
||||
|
|
@ -86,7 +86,7 @@ func NewDiskReadPayloadCommand(dep fx.Option, options *core.DiskCommand) *cobra.
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().Uint64VarP(&options.Size, "size", "s", 0,
|
||||
cmd.Flags().StringVarP(&options.Size, "size", "s", "",
|
||||
"'size' specifies how many data will read from the file path with unit MB.")
|
||||
cmd.Flags().StringVarP(&options.Path, "path", "p", "",
|
||||
"'path' specifies the location to read data.\n"+
|
||||
|
|
@ -105,11 +105,13 @@ func NewDiskFillCommand(dep fx.Option, options *core.DiskCommand) *cobra.Command
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().Uint64VarP(&options.Size, "size", "s", 0,
|
||||
cmd.Flags().StringVarP(&options.Size, "size", "s", "",
|
||||
"'size' specifies how many data will fill in the file path with unit MB.")
|
||||
cmd.Flags().StringVarP(&options.Path, "path", "p", "",
|
||||
"'path' specifies the location to fill data in.\n"+
|
||||
"If path not provided, a temp file will be generated and deleted immediately after data filled in or allocated")
|
||||
cmd.Flags().StringVarP(&options.Percent, "percent", "c", "",
|
||||
"'percent' how many percent data of disk will fill in the file path")
|
||||
cmd.Flags().BoolVarP(&options.FillByFallocate, "fallocate", "f", true, "fill disk by fallocate instead of dd")
|
||||
commonFlags(cmd, &options.CommonAttackConfig)
|
||||
return cmd
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ package command
|
|||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"go.uber.org/fx"
|
||||
|
|
@ -43,7 +44,7 @@ func TestServer_DiskFill(t *testing.T) {
|
|||
Action: core.DiskFillAction,
|
||||
Kind: core.DiskAttack,
|
||||
},
|
||||
Size: 1024,
|
||||
Size: "1024",
|
||||
Path: "temp",
|
||||
FillByFallocate: true,
|
||||
},
|
||||
|
|
@ -55,7 +56,7 @@ func TestServer_DiskFill(t *testing.T) {
|
|||
Action: core.DiskFillAction,
|
||||
Kind: core.DiskAttack,
|
||||
},
|
||||
Size: 24,
|
||||
Size: "24",
|
||||
Path: "temp",
|
||||
FillByFallocate: false,
|
||||
},
|
||||
|
|
@ -85,8 +86,10 @@ func TestServer_DiskFill(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
if uint64(stat.Size()) != tt.command.Size*1024*1024 {
|
||||
t.Errorf("DiskFill() size %v, expect %d", stat.Size(), tt.command.Size*1024*1024)
|
||||
size, _ := strconv.ParseUint(tt.command.Size, 10, 0)
|
||||
|
||||
if uint64(stat.Size()) != size*1024*1024 {
|
||||
t.Errorf("DiskFill() size %v, expect %d", stat.Size(), size*1024*1024)
|
||||
return
|
||||
}
|
||||
os.Remove(tt.command.Path)
|
||||
|
|
@ -109,7 +112,7 @@ func TestServer_DiskPayload(t *testing.T) {
|
|||
Action: core.DiskWritePayloadAction,
|
||||
Kind: core.DiskAttack,
|
||||
},
|
||||
Size: 24,
|
||||
Size: "24",
|
||||
Path: "temp",
|
||||
},
|
||||
wantErr: false,
|
||||
|
|
@ -120,7 +123,7 @@ func TestServer_DiskPayload(t *testing.T) {
|
|||
Action: core.DiskReadPayloadAction,
|
||||
Kind: core.DiskAttack,
|
||||
},
|
||||
Size: 24,
|
||||
Size: "24",
|
||||
Path: "temp",
|
||||
},
|
||||
wantErr: false,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ package core
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -27,18 +28,27 @@ const (
|
|||
type DiskCommand struct {
|
||||
CommonAttackConfig
|
||||
|
||||
Size uint64 `json:"size"`
|
||||
Size string `json:"size"`
|
||||
Path string `json:"path"`
|
||||
Percent string `json:"percent"`
|
||||
FillByFallocate bool `json:"fill_by_fallocate"`
|
||||
}
|
||||
|
||||
var _ AttackConfig = &DiskCommand{}
|
||||
|
||||
func (d DiskCommand) Validate() error {
|
||||
if d.Action == DiskFillAction || d.Action == DiskWritePayloadAction || d.Action == DiskReadPayloadAction {
|
||||
return nil
|
||||
func (d *DiskCommand) Validate() error {
|
||||
if d.Percent == "" && d.Size == "" {
|
||||
return fmt.Errorf("one of percent and size must not be empty, DiskCommand : %v", d)
|
||||
}
|
||||
return fmt.Errorf("invalid disk attack action %v", d.Action)
|
||||
if d.FillByFallocate && (d.Size == "0" || (d.Size == "" && d.Percent == "0")) {
|
||||
return fmt.Errorf("fallocate not suppurt 0 size or 0 percent data, "+
|
||||
"if you want allocate a 0 size file please set fallocate=false, DiskCommand : %v", d)
|
||||
}
|
||||
_, err := strconv.ParseUint(d.Percent, 10, 0)
|
||||
if d.Size == "" && err != nil {
|
||||
return fmt.Errorf("unsupport percent : %s, DiskCommand : %v", d.Percent, d)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d DiskCommand) RecoverData() string {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,10 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/pingcap/errors"
|
||||
"github.com/pingcap/log"
|
||||
|
|
@ -38,18 +41,18 @@ func (disk diskAttack) Attack(options core.AttackConfig, env Environment) (err e
|
|||
attack := options.(*core.DiskCommand)
|
||||
|
||||
if options.String() == core.DiskFillAction {
|
||||
return disk.attackDiskFill(env.AttackUid, attack)
|
||||
return disk.attackDiskFill(attack)
|
||||
}
|
||||
return disk.attackDiskPayload(env.AttackUid, attack)
|
||||
return disk.attackDiskPayload(attack)
|
||||
}
|
||||
|
||||
func (diskAttack) attackDiskPayload(uid string, payload *core.DiskCommand) error {
|
||||
func (diskAttack) attackDiskPayload(payload *core.DiskCommand) error {
|
||||
switch payload.Action {
|
||||
case core.DiskWritePayloadAction:
|
||||
if payload.Path == "" {
|
||||
payload.Path = "/dev/null"
|
||||
}
|
||||
cmd := exec.Command("bash", "-c", fmt.Sprintf(DDWritePayloadCommand, payload.Path, "1M", strconv.FormatUint(payload.Size, 10)))
|
||||
cmd := exec.Command("bash", "-c", fmt.Sprintf(DDWritePayloadCommand, payload.Path, "1M", payload.Size))
|
||||
output, err := cmd.CombinedOutput()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -64,7 +67,7 @@ func (diskAttack) attackDiskPayload(uid string, payload *core.DiskCommand) error
|
|||
log.Error(fmt.Sprintf("payload action: %s", payload.Action), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
cmd := exec.Command("bash", "-c", fmt.Sprintf(DDReadPayloadCommand, payload.Path, "1M", strconv.FormatUint(payload.Size, 10)))
|
||||
cmd := exec.Command("bash", "-c", fmt.Sprintf(DDReadPayloadCommand, payload.Path, "1M", payload.Size))
|
||||
output, err := cmd.CombinedOutput()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -83,7 +86,7 @@ func (diskAttack) attackDiskPayload(uid string, payload *core.DiskCommand) error
|
|||
const DDFillCommand = "dd if=/dev/zero of=%s bs=%s count=%s iflag=fullblock"
|
||||
const DDFallocateCommand = "fallocate -l %sM %s"
|
||||
|
||||
func (diskAttack) attackDiskFill(uid string, fill *core.DiskCommand) error {
|
||||
func (diskAttack) attackDiskFill(fill *core.DiskCommand) error {
|
||||
if fill.Path == "" {
|
||||
tempFile, err := ioutil.TempFile("", "example")
|
||||
if err != nil {
|
||||
|
|
@ -113,11 +116,32 @@ func (diskAttack) attackDiskFill(uid string, fill *core.DiskCommand) error {
|
|||
}
|
||||
|
||||
var cmd *exec.Cmd
|
||||
if fill.Size != "" {
|
||||
fill.Size = strings.Trim(fill.Size, " ")
|
||||
} else if fill.Percent != "" {
|
||||
fill.Percent = strings.Trim(fill.Percent, " ")
|
||||
percent, err := strconv.ParseUint(fill.Percent, 10, 0)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf(" unexcepted err when parsing disk percent '%s'", fill.Percent), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
dir := filepath.Dir(fill.Path)
|
||||
s := syscall.Statfs_t{}
|
||||
err = syscall.Statfs(dir, &s)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("unexpected err when using syscall.Statfs"), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
reservedBlocks := s.Bfree - s.Bavail
|
||||
totalM := uint64(s.Frsize) * (s.Blocks - reservedBlocks) / 1024 / 1024
|
||||
fill.Size = strconv.FormatUint(totalM*percent/100, 10)
|
||||
}
|
||||
|
||||
if fill.FillByFallocate {
|
||||
cmd = exec.Command("bash", "-c", fmt.Sprintf(DDFallocateCommand, strconv.FormatUint(fill.Size, 10), fill.Path))
|
||||
cmd = exec.Command("bash", "-c", fmt.Sprintf(DDFallocateCommand, fill.Size, fill.Path))
|
||||
} else {
|
||||
//1M means the block size. The bytes size dd read | write is (block size) * (size).
|
||||
cmd = exec.Command("bash", "-c", fmt.Sprintf(DDFillCommand, fill.Path, "1M", strconv.FormatUint(fill.Size, 10)))
|
||||
cmd = exec.Command("bash", "-c", fmt.Sprintf(DDFillCommand, fill.Path, "1M", fill.Size))
|
||||
}
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
|
|
|
|||
Loading…
Reference in New Issue