support vm attack (#158)

Signed-off-by: xiang <xiang13225080@163.com>

Co-authored-by: Ti Chi Robot <ti-community-prow-bot@tidb.io>
This commit is contained in:
WangXiang 2022-05-24 14:10:46 +08:00 committed by GitHub
parent 03541d3687
commit bc4ca8cb07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 214 additions and 1 deletions

View File

@ -38,6 +38,7 @@ func NewAttackCommand() *cobra.Command {
NewClockAttackCommand(&uid),
NewRedisAttackCommand(&uid),
NewFileAttackCommand(&uid),
NewVMAttackCommand(&uid),
)
return cmd

View File

@ -39,7 +39,7 @@ func NewClockAttackCommand(uid *string) *cobra.Command {
Use: "clock attack",
Short: "clock skew",
Run: func(*cobra.Command, []string) {
options.Action = "Attack"
options.Action = core.ClockAction
utils.FxNewAppWithoutLog(dep, fx.Invoke(processClockAttack)).Run()
},
}

58
cmd/attack/vm.go Normal file
View File

@ -0,0 +1,58 @@
// Copyright 2022 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 NewVMAttackCommand(uid *string) *cobra.Command {
options := core.NewVMOption()
dep := fx.Options(
server.Module,
fx.Provide(func() *core.VMOption {
options.UID = *uid
return options
}),
)
cmd := &cobra.Command{
Use: "vm attack",
Short: "vm attack by using virsh",
Run: func(*cobra.Command, []string) {
options.Action = core.VMAction
utils.FxNewAppWithoutLog(dep, fx.Invoke(vmAttack)).Run()
},
}
cmd.Flags().StringVarP(&options.VMName, "vm-name", "v", "", "The name of the vm to be destoryed")
return cmd
}
func vmAttack(options *core.VMOption, chaos *chaosd.Server) {
uid, err := chaos.ExecuteAttack(chaosd.VMAttack, options, core.CommandMode)
if err != nil {
utils.ExitWithError(utils.ExitError, err)
}
utils.NormalExit(fmt.Sprintf("VM attack %v successfully, uid: %s", options, uid))
}

View File

@ -27,6 +27,10 @@ import (
"github.com/chaos-mesh/chaos-mesh/pkg/time/utils"
)
const (
ClockAction = "clock"
)
type ClockOption struct {
CommonAttackConfig

View File

@ -40,6 +40,7 @@ const (
JVMAttack = "jvm"
RedisAttack = "redis"
FileAttack = "file"
VMAttack = "vm"
)
const (
@ -113,6 +114,8 @@ func GetAttackByKind(kind string) *AttackConfig {
attackConfig = &RedisCommand{}
case FileAttack:
attackConfig = &FileCommand{}
case VMAttack:
attackConfig = &VMOption{}
default:
return nil
}

46
pkg/core/vm.go Normal file
View File

@ -0,0 +1,46 @@
// Copyright 2021 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 (
"encoding/json"
)
const (
VMAction = "vm"
)
type VMOption struct {
CommonAttackConfig
VMName string `json:"vm-name,omitempty"`
}
func NewVMOption() *VMOption {
return &VMOption{
CommonAttackConfig: CommonAttackConfig{
Kind: VMAction,
},
}
}
func (opt *VMOption) CompleteDefaults() {
return
}
func (opt VMOption) RecoverData() string {
data, _ := json.Marshal(opt)
return string(data)
}

View File

@ -69,6 +69,8 @@ func (s *Server) RecoverAttack(uid string) error {
attackType = RedisAttack
case core.FileAttack:
attackType = FileAttack
case core.VMAttack:
attackType = VMAttack
default:
return perr.Errorf("chaos experiment kind %s not found", exp.Kind)
}

66
pkg/server/chaosd/vm.go Normal file
View File

@ -0,0 +1,66 @@
// Copyright 2022 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 (
"errors"
"fmt"
"os/exec"
"github.com/pingcap/log"
"go.uber.org/zap"
"github.com/chaos-mesh/chaosd/pkg/core"
)
type vmAttack struct{}
var VMAttack AttackType = vmAttack{}
func (vm vmAttack) Attack(options core.AttackConfig, env Environment) error {
vmOption, ok := options.(*core.VMOption)
if !ok {
return errors.New("the type is not VMOption")
}
cmd := exec.Command("bash", "-c", fmt.Sprintf("virsh destroy %s", vmOption.VMName))
output, err := cmd.CombinedOutput()
if err != nil {
log.Error(string(output), zap.Error(err))
return err
}
return nil
}
func (vmAttack) Recover(exp core.Experiment, _ Environment) error {
attackConfig, err := exp.GetRequestCommand()
if err != nil {
return err
}
vmOption, ok := attackConfig.(*core.VMOption)
if !ok {
return errors.New("the type is not VMOption")
}
cmd := exec.Command("bash", "-c", fmt.Sprintf("virsh start %s", vmOption.VMName))
output, err := cmd.CombinedOutput()
if err != nil {
log.Error(string(output), zap.Error(err))
return err
}
return nil
}

View File

@ -92,6 +92,7 @@ func (s *httpServer) handler(engine *gin.Engine) {
attack.POST("/disk", s.createDiskAttack)
attack.POST("/clock", s.createClockAttack)
attack.POST("/jvm", s.createJVMAttack)
attack.POST("/vm", s.createVMAttack)
attack.POST("/redis", s.createRedisAttack)
attack.DELETE("/:uid", s.recoverAttack)
@ -306,6 +307,38 @@ func (s *httpServer) createJVMAttack(c *gin.Context) {
c.JSON(http.StatusOK, utils.AttackSuccessResponse(uid))
}
// @Summary Create VM attack.
// @Description Create VM attack.
// @Tags attack
// @Produce json
// @Param request body core.VMOption true "Request body"
// @Success 200 {object} utils.Response
// @Failure 400 {object} utils.APIError
// @Failure 500 {object} utils.APIError
// @Router /api/attack/vm [post]
func (s *httpServer) createVMAttack(c *gin.Context) {
options := core.NewVMOption()
if err := c.ShouldBindJSON(options); err != nil {
c.AbortWithError(http.StatusBadRequest, utils.ErrInternalServer.WrapWithNoMessage(err))
return
}
options.CompleteDefaults()
if err := options.Validate(); err != nil {
err = core.ErrAttackConfigValidation.Wrap(err, "attack config validation failed")
handleError(c, err)
return
}
uid, err := s.chaos.ExecuteAttack(chaosd.VMAttack, options, core.ServerMode)
if err != nil {
handleError(c, err)
return
}
c.JSON(http.StatusOK, utils.AttackSuccessResponse(uid))
}
// @Summary Create redis attack.
// @Description Create redis attack.
// @Tags attack