Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add systemd stop feature #90

Merged
merged 1 commit into from
Jun 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,14 @@ pre_build:
build_yaml: build/spec.go
$(GO) run $< $(OS_YAML_FILE_PATH)

build_osbin: build_burncpu build_burnmem build_burnio build_killprocess build_stopprocess build_changedns build_tcnetwork build_dropnetwork build_filldisk build_occupynetwork build_appendfile build_chmodfile build_addfile build_deletefile build_movefile build_kernel_delay build_kernel_error cp_strace
build_osbin: build_stopsystemd build_burncpu build_burnmem build_burnio build_killprocess build_stopprocess build_changedns build_tcnetwork build_dropnetwork build_filldisk build_occupynetwork build_appendfile build_chmodfile build_addfile build_deletefile build_movefile build_kernel_delay build_kernel_error cp_strace

build_osbin_darwin: build_burncpu build_killprocess build_stopprocess build_changedns build_occupynetwork build_appendfile build_chmodfile build_addfile build_deletefile build_movefile

# build stop-systemd chaos tools
build_stopsystemd: exec/bin/stopsystemd/stopsystemd.go
$(GO) build $(GO_FLAGS) -o $(BUILD_TARGET_BIN)/chaos_stopsystemd $<

# build burn-cpu chaos tools
build_burncpu: exec/bin/burncpu/burncpu.go
$(GO) build $(GO_FLAGS) -o $(BUILD_TARGET_BIN)/chaos_burncpu $<
Expand Down
1 change: 1 addition & 0 deletions build/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func getModels() *spec.Models {
exec.NewScriptCommandModelSpec(),
exec.NewFileCommandSpec(),
exec.NewKernelInjectCommandSpec(),
exec.NewSystemdCommandModelSpec(),
}
specModels := make([]*spec.Models, 0)
for _, modeSpec := range modelCommandSpecs {
Expand Down
48 changes: 48 additions & 0 deletions exec/bin/stopsystemd/stopsystemd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* 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,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package main

import (
"flag"
"fmt"
"context"

"github.com/chaosblade-io/chaosblade-spec-go/channel"
"github.com/chaosblade-io/chaosblade-exec-os/exec/bin"
)

var service string

func main() {
flag.StringVar(&service, "service", "", "service name")
bin.ParseFlagAndInitLog()

stopSystemd(service)
}

var cl = channel.NewLocalChannel()

func stopSystemd(service string) {
var ctx = context.Background()
response := cl.Run(ctx, "systemctl", fmt.Sprintf("stop %s", service))
if !response.Success {
bin.PrintErrAndExit(response.Err)
return
}
bin.PrintOutputAndExit(response.Result.(string))
}

1 change: 1 addition & 0 deletions exec/category/category.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ const (
SystemScript = "system_script"
SystemFile = "system_file"
SystemKernel = "system_kernel"
SystemSystemd = "system_systemd"
)
1 change: 1 addition & 0 deletions exec/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func GetAllExpModels() []spec.ExpModelCommandSpec {
exec.NewScriptCommandModelSpec(),
exec.NewFileCommandSpec(),
exec.NewKernelInjectCommandSpec(),
exec.NewSystemdCommandModelSpec(),
}
}

Expand Down
55 changes: 55 additions & 0 deletions exec/systemd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* 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,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package exec

import (
"github.com/chaosblade-io/chaosblade-spec-go/spec"
)

type SystemdCommandModelSpec struct {
spec.BaseExpModelCommandSpec
}

func NewSystemdCommandModelSpec() spec.ExpModelCommandSpec {
return &SystemdCommandModelSpec{
spec.BaseExpModelCommandSpec{
ExpFlags: []spec.ExpFlagSpec{
&spec.ExpFlag{
Name: "ignore-not-found",
Desc: "Ignore systemd that cannot be found",
NoArgs: true,
},
},
ExpActions: []spec.ExpActionCommandSpec{
NewStopSystemdActionCommandSpec(),
},
},
}
}

func (*SystemdCommandModelSpec) Name() string {
return "systemd"
}

func (*SystemdCommandModelSpec) ShortDesc() string {
return "Systemd experiment"
}

func (*SystemdCommandModelSpec) LongDesc() string {
return "Systemd experiment, for example, stop systemd"
}

134 changes: 134 additions & 0 deletions exec/systemd_stop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* 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,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package exec

import (
"context"
"fmt"
"path"

"github.com/chaosblade-io/chaosblade-spec-go/channel"
"github.com/chaosblade-io/chaosblade-spec-go/spec"
"github.com/chaosblade-io/chaosblade-spec-go/util"
"github.com/chaosblade-io/chaosblade-exec-os/exec/category"
)

const StopSystemdBin = "chaos_stopsystemd"

type StopSystemdActionCommandSpec struct {
spec.BaseExpActionCommandSpec
}

func NewStopSystemdActionCommandSpec() spec.ExpActionCommandSpec {
return &StopSystemdActionCommandSpec{
spec.BaseExpActionCommandSpec{
ActionMatchers: []spec.ExpFlagSpec{
&spec.ExpFlag{
Name: "service",
Desc: "Service name",
},
},
ActionFlags: []spec.ExpFlagSpec{},
ActionExecutor: &StopSystemdExecutor{},
ActionExample: `
# Stop the service test
blade create systemd stop --service test`,
ActionPrograms: []string{StopSystemdBin},
ActionCategories: []string{category.SystemSystemd},
},
}
}

func (*StopSystemdActionCommandSpec) Name() string {
return "stop"
}

func (*StopSystemdActionCommandSpec) Aliases() []string {
return []string{"s"}
}

func (*StopSystemdActionCommandSpec) ShortDesc() string {
return "Stop systemd"
}

func (k *StopSystemdActionCommandSpec) LongDesc() string {
if k.ActionLongDesc != "" {
return k.ActionLongDesc
}
return "Stop system by service name"
}

func (*StopSystemdActionCommandSpec) Categories() []string {
return []string{category.SystemSystemd}
}

type StopSystemdExecutor struct {
channel spec.Channel
}

func (sse *StopSystemdExecutor) Name() string {
return "stop"
}

func (sse *StopSystemdExecutor) Exec(uid string, ctx context.Context, model *spec.ExpModel) *spec.Response {
if sse.channel == nil {
util.Errorf(uid, util.GetRunFuncName(), spec.ResponseErr[spec.ChannelNil].ErrInfo)
return spec.ResponseFail(spec.ChannelNil, spec.ResponseErr[spec.ChannelNil].ErrInfo)
}
service := model.ActionFlags["service"]
if service == "" {
util.Errorf(uid, util.GetRunFuncName(), "service name is mandantory")
return spec.ResponseFailWaitResult(spec.ParameterLess, fmt.Sprintf(spec.ResponseErr[spec.ParameterLess].Err, "service"),
fmt.Sprintf(spec.ResponseErr[spec.ParameterLess].ErrInfo, "service"))
}


flags := fmt.Sprintf("--service %s", service)
if _, ok := spec.IsDestroy(ctx); ok {
return sse.startService(service, ctx)
} else {
if response := checkServiceInvalid(uid, service, ctx); response != nil {
return response
}
return sse.channel.Run(ctx, path.Join(sse.channel.GetScriptPath(), StopSystemdBin), flags)
}
}

func checkServiceInvalid(uid, service string, ctx context.Context) *spec.Response {
cl := channel.NewLocalChannel()
if !cl.IsCommandAvailable("systemctl") {
util.Errorf(uid, util.GetRunFuncName(), spec.ResponseErr[spec.CommandSystemctlNotFound].Err)
return spec.ResponseFail(spec.CommandSystemctlNotFound, spec.ResponseErr[spec.SystemdNotFound].Err,
spec.ResponseErr[spec.SystemdNotFound].ErrInfo)
}
response := cl.Run(ctx, "systemctl", fmt.Sprintf(`status "%s" | grep 'Active' | grep 'running'`, service))
if !response.Success {
util.Errorf(uid, util.GetRunFuncName(), fmt.Sprintf(spec.ResponseErr[spec.SystemdNotFound].Err, service))
return spec.ResponseFail(spec.SystemdNotFound, fmt.Sprintf(spec.ResponseErr[spec.SystemdNotFound].Err, service),
fmt.Sprintf(spec.ResponseErr[spec.SystemdNotFound].ErrInfo, service, response.Err))
}
return nil
}

func (sse *StopSystemdExecutor) startService(service string, ctx context.Context) *spec.Response {
return sse.channel.Run(ctx, "systemctl", fmt.Sprintf("start %s", service))
}

func (sse *StopSystemdExecutor) SetChannel(channel spec.Channel) {
sse.channel = channel
}