mirror of https://github.com/chaos-mesh/chaosd.git
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:
parent
03541d3687
commit
bc4ca8cb07
|
@ -38,6 +38,7 @@ func NewAttackCommand() *cobra.Command {
|
|||
NewClockAttackCommand(&uid),
|
||||
NewRedisAttackCommand(&uid),
|
||||
NewFileAttackCommand(&uid),
|
||||
NewVMAttackCommand(&uid),
|
||||
)
|
||||
|
||||
return cmd
|
||||
|
|
|
@ -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()
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
|
@ -27,6 +27,10 @@ import (
|
|||
"github.com/chaos-mesh/chaos-mesh/pkg/time/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
ClockAction = "clock"
|
||||
)
|
||||
|
||||
type ClockOption struct {
|
||||
CommonAttackConfig
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue