mirror of https://github.com/chaos-mesh/chaosd.git
parent
7103539ffe
commit
d50e985cbc
|
|
@ -0,0 +1,155 @@
|
|||
// Copyright 2020 Chaos Mesh Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package attack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"go.uber.org/fx"
|
||||
|
||||
"github.com/chaos-mesh/chaosd/cmd/server"
|
||||
"github.com/chaos-mesh/chaosd/pkg/core"
|
||||
"github.com/chaos-mesh/chaosd/pkg/server/chaosd"
|
||||
"github.com/chaos-mesh/chaosd/pkg/utils"
|
||||
)
|
||||
|
||||
func NewFileAttackCommand() *cobra.Command {
|
||||
options := core.NewFileCommand()
|
||||
dep := fx.Options(
|
||||
server.Module,
|
||||
fx.Provide(func() *core.FileCommand {
|
||||
return options
|
||||
}),
|
||||
)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "file <subcommand>",
|
||||
Short: "File attack related commands",
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
NewFileCreateCommand(dep, options),
|
||||
NewFileModifyPrivilegeCommand(dep, options),
|
||||
NewFileDeleteCommand(dep, options),
|
||||
NewFileRenameCommand(dep, options),
|
||||
NewFileAppendCommand(dep, options),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func NewFileCreateCommand(dep fx.Option, options *core.FileCommand) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "create file",
|
||||
|
||||
Run: func(*cobra.Command, []string) {
|
||||
options.Action = core.FileCreateAction
|
||||
options.CompleteDefaults()
|
||||
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonFileAttackFunc)).Run()
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&options.FileName, "filename", "f", "", "create file based on filename")
|
||||
cmd.Flags().StringVarP(&options.DirName, "dirname", "d", "", "create directory based on dirname")
|
||||
cmd.Flags().StringVarP(&options.DestDir, "destdir", "", "", "create a file or directory to the specified destdir")
|
||||
// owner TODO
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func NewFileModifyPrivilegeCommand(dep fx.Option, options *core.FileCommand) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "modify",
|
||||
Short: "modify file privilege",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Action = core.FileModifyPrivilegeAction
|
||||
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonFileAttackFunc)).Run()
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&options.FileName, "filename", "f", "", "file to be change privilege")
|
||||
cmd.Flags().Uint32VarP(&options.Privilege, "privilege", "p", 0, "privilege to be update")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func NewFileDeleteCommand(dep fx.Option, options *core.FileCommand) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "delete file",
|
||||
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Action = core.FileDeleteAction
|
||||
options.CompleteDefaults()
|
||||
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonFileAttackFunc)).Run()
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&options.FileName, "filename", "f", "", "delete file based on filename")
|
||||
cmd.Flags().StringVarP(&options.DirName, "dirname", "d", "", "delete directory based on dirname")
|
||||
cmd.Flags().StringVarP(&options.DestDir, "destdir", "", "", "delete a file or directory to the specified destdir")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func NewFileRenameCommand(dep fx.Option, options *core.FileCommand) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "rename",
|
||||
Short: "rename file",
|
||||
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Action = core.FileRenameAction
|
||||
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonFileAttackFunc)).Run()
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&options.SourceFile, "source-file", "s", "", "the source file/dir of rename")
|
||||
cmd.Flags().StringVarP(&options.DstFile, "dst-file", "d", "", "the destination file/dir of rename")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func NewFileAppendCommand(dep fx.Option, options *core.FileCommand) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "append",
|
||||
Short: "append file",
|
||||
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Action = core.FileAppendAction
|
||||
utils.FxNewAppWithoutLog(dep, fx.Invoke(commonFileAttackFunc)).Run()
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&options.FileName, "filename", "f", "", "append data to the file")
|
||||
cmd.Flags().StringVarP(&options.Data, "data", "d", "", "append data")
|
||||
cmd.Flags().IntVarP(&options.Count, "count", "c", 1, "append count with default value is 1")
|
||||
cmd.Flags().IntVarP(&options.LineNo, "line", "l", 0, "the start line to append with default value is 1")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func commonFileAttackFunc(options *core.FileCommand, chaos *chaosd.Server) {
|
||||
if err := options.Validate(); err != nil {
|
||||
utils.ExitWithError(utils.ExitBadArgs, err)
|
||||
}
|
||||
|
||||
uid, err := chaos.ExecuteAttack(chaosd.FileAttack, options, core.CommandMode)
|
||||
if err != nil {
|
||||
utils.ExitWithError(utils.ExitError, err)
|
||||
}
|
||||
|
||||
utils.NormalExit(fmt.Sprintf("Attack file successfully, uid: %s", uid))
|
||||
}
|
||||
|
|
@ -38,6 +38,7 @@ const (
|
|||
ClockAttack = "clock"
|
||||
HostAttack = "host"
|
||||
JVMAttack = "jvm"
|
||||
FileAttack = "file"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
|||
|
|
@ -0,0 +1,185 @@
|
|||
// Copyright 2020 Chaos Mesh Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"github.com/pingcap/errors"
|
||||
"github.com/pingcap/log"
|
||||
"go.uber.org/zap"
|
||||
"os"
|
||||
)
|
||||
|
||||
type FileCommand struct {
|
||||
CommonAttackConfig
|
||||
|
||||
FileName string
|
||||
DirName string
|
||||
DestDir string
|
||||
Privilege uint32
|
||||
SourceFile string
|
||||
DstFile string
|
||||
Data string
|
||||
Count int
|
||||
LineNo int
|
||||
FileMode int
|
||||
}
|
||||
|
||||
var _ AttackConfig = &FileCommand{}
|
||||
|
||||
const (
|
||||
FileCreateAction = "create"
|
||||
FileModifyPrivilegeAction = "modify"
|
||||
FileDeleteAction = "delete"
|
||||
FileRenameAction = "rename"
|
||||
FileAppendAction = "append"
|
||||
)
|
||||
|
||||
func (n *FileCommand) Validate() error {
|
||||
if err := n.CommonAttackConfig.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
switch n.Action {
|
||||
case FileCreateAction:
|
||||
return n.validFileCreate()
|
||||
case FileModifyPrivilegeAction:
|
||||
return n.validFileModify()
|
||||
case FileDeleteAction:
|
||||
return n.validFileDelete()
|
||||
case FileRenameAction:
|
||||
return n.validFileRename()
|
||||
case FileAppendAction:
|
||||
return n.valieFileAppend()
|
||||
default:
|
||||
return errors.Errorf("file action %s not supported", n.Action)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *FileCommand) validFileCreate() error {
|
||||
if len(n.FileName) == 0 && len(n.DirName) == 0 {
|
||||
return errors.New("filename and dirname can not all null")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *FileCommand) validFileModify() error {
|
||||
if len(n.FileName) == 0 {
|
||||
return errors.New("filename can not null")
|
||||
}
|
||||
|
||||
if n.Privilege == 0 {
|
||||
return errors.New("file privilege can not null")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *FileCommand) validFileDelete() error {
|
||||
if len(n.FileName) == 0 && len(n.DirName) == 0 {
|
||||
return errors.New("filename and dirname can not all null")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *FileCommand) validFileRename() error {
|
||||
if len(n.SourceFile) == 0 || len(n.DstFile) == 0 {
|
||||
return errors.New("source file and destination file must have value")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *FileCommand) valieFileAppend() error {
|
||||
if len(n.FileName) == 0 {
|
||||
return errors.New("filename can not null")
|
||||
}
|
||||
|
||||
if len(n.Data) == 0 {
|
||||
return errors.New("append data can not null")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *FileCommand) CompleteDefaults() {
|
||||
switch n.Action {
|
||||
case FileCreateAction:
|
||||
n.setDefaultForFileCreate()
|
||||
case FileDeleteAction:
|
||||
n.setDefaultForFileDelete()
|
||||
case FileAppendAction:
|
||||
n.setDefaultForFileAppend()
|
||||
}
|
||||
}
|
||||
|
||||
func (n *FileCommand) setDefaultForFileCreate() {
|
||||
if len(n.FileName) == 0 && len(n.DirName) == 0 {
|
||||
n.FileName = "chaosd.file"
|
||||
}
|
||||
if len(n.DestDir) > 0 {
|
||||
n.DestDir = n.DestDir + "/"
|
||||
}
|
||||
}
|
||||
|
||||
func (n *FileCommand) setDefaultForFileDelete() {
|
||||
if len(n.DestDir) > 0 {
|
||||
n.DestDir = n.DestDir + "/"
|
||||
}
|
||||
}
|
||||
|
||||
func (n *FileCommand) setDefaultForFileAppend() {
|
||||
if n.Count == 0 {
|
||||
n.Count = 1
|
||||
}
|
||||
|
||||
fileNumber := GetFileNumber(n.FileName)
|
||||
if n.LineNo == 0 {
|
||||
n.LineNo = fileNumber + 1
|
||||
}
|
||||
}
|
||||
|
||||
func GetFileNumber(fileName string) int {
|
||||
file, err := os.Open(fileName)
|
||||
if err != nil{
|
||||
log.Error("open file error", zap.Error(err))
|
||||
}
|
||||
defer file.Close()
|
||||
fd := bufio.NewReader(file)
|
||||
count := 0
|
||||
for {
|
||||
_, err := fd.ReadString('\n')
|
||||
if err!= nil{
|
||||
break
|
||||
}
|
||||
count++
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func (n FileCommand) RecoverData() string {
|
||||
data, _ := json.Marshal(n)
|
||||
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func NewFileCommand() *FileCommand {
|
||||
return &FileCommand{
|
||||
CommonAttackConfig: CommonAttackConfig{
|
||||
Kind: FileAttack,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,373 @@
|
|||
// Copyright 2020 Chaos Mesh Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chaosd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/chaos-mesh/chaosd/pkg/core"
|
||||
"github.com/pingcap/errors"
|
||||
"github.com/pingcap/log"
|
||||
"go.uber.org/zap"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type fileAttack struct{}
|
||||
|
||||
var FileAttack AttackType = fileAttack{}
|
||||
|
||||
func (fileAttack) Attack(options core.AttackConfig, env Environment) (err error) {
|
||||
attack := options.(*core.FileCommand)
|
||||
|
||||
switch attack.Action {
|
||||
case core.FileCreateAction:
|
||||
if err = env.Chaos.createFile(attack, env.AttackUid); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
case core.FileModifyPrivilegeAction:
|
||||
if err = env.Chaos.modifyFilePrivilege(attack, env.AttackUid); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
case core.FileDeleteAction:
|
||||
if err = env.Chaos.deleteFile(attack, env.AttackUid); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
case core.FileRenameAction:
|
||||
if err = env.Chaos.renameFile(attack, env.AttackUid); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
case core.FileAppendAction:
|
||||
if err = env.Chaos.appendFile(attack, env.AttackUid); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) createFile(attack *core.FileCommand, uid string) error {
|
||||
|
||||
var err error
|
||||
if len(attack.FileName) > 0 {
|
||||
_, err = os.Create(attack.DestDir + attack.FileName)
|
||||
} else if len(attack.DirName) > 0 {
|
||||
err = os.Mkdir(attack.DestDir+attack.DirName, os.ModePerm)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Error("create file/dir failed", zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) modifyFilePrivilege(attack *core.FileCommand, uid string) error {
|
||||
|
||||
cmdStr := "stat -c %a" + " "+ attack.FileName
|
||||
cmd := exec.Command("bash", "-c", cmdStr)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Error(string(output), zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
str1 := strings.Replace(string(output), "\n", "", -1)
|
||||
attack.FileMode, err = strconv.Atoi(string(str1))
|
||||
if err != nil {
|
||||
log.Error(str1, zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
cmdStr = fmt.Sprintf("chmod %d %s", attack.Privilege, attack.FileName)
|
||||
|
||||
cmd = exec.Command("bash", "-c", cmdStr)
|
||||
output, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Error(string(output), zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
log.Info(string(output))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) deleteFile(attack *core.FileCommand, uid string) error {
|
||||
|
||||
var err error
|
||||
if len(attack.FileName) > 0 {
|
||||
backFile := attack.DestDir + attack.FileName + "." + uid
|
||||
err = os.Rename(attack.DestDir+attack.FileName, backFile)
|
||||
} else if len(attack.DirName) > 0 {
|
||||
backDir := attack.DestDir + attack.DirName + "." + uid
|
||||
err = os.Rename(attack.DestDir+attack.DirName, backDir)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Error("create file/dir faild", zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) renameFile(attack *core.FileCommand, uid string) error {
|
||||
|
||||
err := os.Rename(attack.SourceFile, attack.DstFile)
|
||||
|
||||
if err != nil {
|
||||
log.Error("create file/dir faild", zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//while the input content has many lines, "\n" is the line break
|
||||
func (s *Server) appendFile(attack *core.FileCommand, uid string) error {
|
||||
|
||||
if fileEmpty(attack.FileName) {
|
||||
|
||||
for i := 0; i < attack.Count; i++ {
|
||||
cmdStr := fmt.Sprintf("echo -e '%s' >> %s", attack.Data, attack.FileName)
|
||||
cmd := exec.Command("bash", "-c", cmdStr)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
println("append data exec echo error")
|
||||
log.Error(cmd.String()+string(output), zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
log.Info(string(output))
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if attack.LineNo == 0 {
|
||||
//在文件头部,第一行插入
|
||||
cmdStr := fmt.Sprintf("sed -i '1i %s' %s", attack.Data, attack.FileName)
|
||||
for i := 0; i < attack.Count; i++ {
|
||||
cmd := exec.Command("bash", "-c", cmdStr)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Error(cmd.String()+string(output), zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
log.Info(string(output))
|
||||
}
|
||||
|
||||
} else {
|
||||
//这种方式只能在第一行之后插入
|
||||
//实验开始前,检测test.dat文件是否存在,如果存在,删除
|
||||
if fileExist("test.dat") {
|
||||
if err := deleteTestFile("test.dat"); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
println("fileExist has run success")
|
||||
|
||||
//1. 插入的字符串转为文件
|
||||
file, err := generateFile(attack.Data)
|
||||
if err != nil {
|
||||
println("generate file error")
|
||||
log.Error("generate file from input data err", zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
println("generate file success")
|
||||
|
||||
//2. 生成的文件插入指定的行 利用sed -i
|
||||
c := fmt.Sprintf("%d r %s", attack.LineNo, file.Name())
|
||||
cmdStr := fmt.Sprintf("sed -i '%s' %s", c, attack.FileName)
|
||||
fmt.Println("cmd str is %s", cmdStr)
|
||||
|
||||
for i := 0; i < attack.Count; i++ {
|
||||
|
||||
cmd := exec.Command("bash", "-c", cmdStr)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
println("append data exec cat error")
|
||||
log.Error(cmd.String()+string(output), zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
log.Info(string(output))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteTestFile(file string) error {
|
||||
|
||||
cmdStr := fmt.Sprintf("rm -rf %s", file)
|
||||
cmd := exec.Command("bash", "-c", cmdStr)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
fmt.Print("delete test file error")
|
||||
log.Error(string(output), zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
log.Info(string(output))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func fileExist(fileName string) bool {
|
||||
_, err := os.Lstat(fileName)
|
||||
return !os.IsNotExist(err)
|
||||
}
|
||||
|
||||
func fileEmpty(fileName string) bool {
|
||||
file, err := os.Stat(fileName)
|
||||
if err != nil {
|
||||
log.Error("get file is empty err", zap.Error(err))
|
||||
}
|
||||
if file.Size() ==0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func generateFile(s string) (*os.File, error) {
|
||||
fileName := "test.dat"
|
||||
dstFile,err := os.Create(fileName)
|
||||
if err!=nil{
|
||||
fmt.Println(err.Error())
|
||||
return dstFile, err
|
||||
}
|
||||
defer dstFile.Close()
|
||||
strNew := strings.Replace(s, `\n`, "\n", -1)
|
||||
dstFile.WriteString(strNew)
|
||||
return dstFile, nil
|
||||
}
|
||||
|
||||
func (fileAttack) Recover(exp core.Experiment, env Environment) error {
|
||||
config, err := exp.GetRequestCommand()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
attack := config.(*core.FileCommand)
|
||||
|
||||
switch attack.Action {
|
||||
case core.FileCreateAction:
|
||||
if err = env.Chaos.recoverCreateFile(attack); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
case core.FileModifyPrivilegeAction:
|
||||
if err = env.Chaos.recoverModifyPrivilege(attack); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
case core.FileDeleteAction:
|
||||
if err = env.Chaos.recoverDeleteFile(attack, env.AttackUid); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
case core.FileRenameAction:
|
||||
if err = env.Chaos.recoverRenameFile(attack); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
case core.FileAppendAction:
|
||||
if err = env.Chaos.recoverAppendFile(attack); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) recoverCreateFile(attack *core.FileCommand) error {
|
||||
|
||||
var err error
|
||||
if len(attack.FileName) > 0 {
|
||||
err = os.Remove(attack.DestDir + attack.FileName)
|
||||
} else if len(attack.DirName) > 0 {
|
||||
err = os.RemoveAll(attack.DestDir + attack.DirName)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Error("delete file/dir faild", zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) recoverModifyPrivilege(attack *core.FileCommand) error {
|
||||
|
||||
cmdStr := fmt.Sprintf("chmod %d %s", attack.FileMode, attack.FileName)
|
||||
cmd := exec.Command("bash", "-c", cmdStr)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Error(string(output), zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) recoverDeleteFile(attack *core.FileCommand, uid string) error {
|
||||
var err error
|
||||
if len(attack.FileName) > 0 {
|
||||
backFile := attack.DestDir + attack.FileName + "." + uid
|
||||
err = os.Rename(backFile, attack.DestDir+attack.FileName)
|
||||
} else if len(attack.DirName) > 0 {
|
||||
backDir := attack.DestDir + attack.DirName + "." + uid
|
||||
err = os.Rename(backDir, attack.DestDir+attack.DirName)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Error("recover delete file/dir faild", zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) recoverRenameFile(attack *core.FileCommand) error {
|
||||
err := os.Rename(attack.DstFile, attack.SourceFile)
|
||||
|
||||
if err != nil {
|
||||
log.Error("recover rename file/dir faild", zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) recoverAppendFile(attack *core.FileCommand) error {
|
||||
|
||||
//实验结束的时候,将生成的临时文件test.dat删除
|
||||
if fileExist("test.dat") {
|
||||
if err := deleteTestFile("test.dat"); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
//计算插入的行数
|
||||
linesByInput := attack.Count * core.GetFileNumber(attack.FileName)
|
||||
|
||||
//从插入的行开始删除,这么多行
|
||||
c := fmt.Sprintf("%d,%dd", attack.LineNo+1, attack.LineNo+linesByInput)
|
||||
cmdStr := fmt.Sprintf("sed -i '%s' %s", c, attack.FileName)
|
||||
|
||||
cmd := exec.Command("bash", "-c", cmdStr)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Error(string(output), zap.Error(err))
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Loading…
Reference in New Issue