├── .github └── workflows │ └── go.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── build └── package │ └── upload.sh ├── cli ├── cli │ ├── cli.go │ └── version.go ├── command │ ├── audit.go │ ├── clean.go │ ├── client │ │ ├── cmd.go │ │ ├── enter.go │ │ ├── install.go │ │ ├── map.go │ │ ├── mount.go │ │ ├── status.go │ │ ├── umount.go │ │ ├── uninstall.go │ │ └── unmap.go │ ├── cluster │ │ ├── add.go │ │ ├── checkout.go │ │ ├── cmd.go │ │ ├── export.go │ │ ├── import.go │ │ ├── list.go │ │ └── remove.go │ ├── cmd.go │ ├── completion.go │ ├── config │ │ ├── cmd.go │ │ ├── commit.go │ │ ├── diff.go │ │ └── show.go │ ├── deploy.go │ ├── enter.go │ ├── exec.go │ ├── format.go │ ├── hosts │ │ ├── cmd.go │ │ ├── commit.go │ │ ├── list.go │ │ ├── list_test.go │ │ ├── playbook.go │ │ ├── show.go │ │ └── ssh.go │ ├── migrate.go │ ├── monitor │ │ ├── clean.go │ │ ├── cmd.go │ │ ├── deploy.go │ │ ├── reload.go │ │ ├── restart.go │ │ ├── start.go │ │ ├── status.go │ │ └── stop.go │ ├── pfs │ │ ├── cmd.go │ │ ├── install.go │ │ └── uninstall.go │ ├── playground │ │ ├── cmd.go │ │ ├── enter.go │ │ ├── list.go │ │ ├── remove.go │ │ └── run.go │ ├── precheck.go │ ├── reload.go │ ├── restart.go │ ├── scale_out.go │ ├── start.go │ ├── status.go │ ├── stop.go │ ├── support.go │ ├── target │ │ ├── add.go │ │ ├── cmd.go │ │ ├── delete.go │ │ ├── list.go │ │ ├── start.go │ │ └── stop.go │ └── upgrade.go └── curveadm.go ├── cmd └── curveadm │ └── main.go ├── configs ├── bs │ ├── cluster │ │ ├── client.yaml │ │ ├── format.yaml │ │ ├── monitor.yaml │ │ ├── scale-out.yaml │ │ └── topology.yaml │ └── stand-alone │ │ ├── client.yaml │ │ ├── format.yaml │ │ └── topology.yaml └── fs │ ├── cluster │ ├── client.yaml │ └── topology.yaml │ └── stand-alone │ ├── client.yaml │ └── topology.yaml ├── docs └── zh │ └── REMEAD.md ├── go.mod ├── go.sum ├── internal ├── build │ ├── build.go │ ├── debug.go │ └── release.go ├── common │ └── common.go ├── configure │ ├── client.go │ ├── common │ │ └── item_set.go │ ├── curveadm │ │ └── curveadm.go │ ├── format.go │ ├── hosts │ │ ├── hc_get.go │ │ ├── hc_item.go │ │ └── hosts.go │ ├── monitor.go │ ├── os.go │ ├── os │ │ └── os.go │ ├── playground.go │ ├── pool.go │ └── topology │ │ ├── context.go │ │ ├── dc.go │ │ ├── dc_get.go │ │ ├── dc_item.go │ │ ├── diff.go │ │ ├── topology.go │ │ └── variables.go ├── errno │ └── errno.go ├── playbook │ ├── config.go │ ├── configs.go │ ├── factory.go │ ├── playbook.go │ └── tasks │ │ ├── monitor.go │ │ └── tasks.go ├── storage │ ├── driver │ │ ├── driver.go │ │ ├── rqlite.go │ │ └── sqlite.go │ ├── sql.go │ └── storage.go ├── task │ ├── context │ │ ├── context.go │ │ └── register.go │ ├── scripts │ │ ├── enable_etcd_auth.go │ │ ├── monitor.go │ │ ├── script.go │ │ └── shell │ │ │ ├── create_fs.sh │ │ │ ├── create_volume.sh │ │ │ ├── format.sh │ │ │ ├── map.sh │ │ │ ├── recycle.sh │ │ │ ├── report.sh │ │ │ ├── start_nginx.sh │ │ │ ├── target.sh │ │ │ ├── wait.sh │ │ │ └── wait_chunkserver.sh │ ├── step │ │ ├── common.go │ │ ├── container.go │ │ ├── file.go │ │ └── shell.go │ ├── task │ │ ├── bs │ │ │ ├── add_target.go │ │ │ ├── balance_leader.go │ │ │ ├── check.go │ │ │ ├── create_volume.go │ │ │ ├── delete_target.go │ │ │ ├── detect_release.go │ │ │ ├── format.go │ │ │ ├── format_status.go │ │ │ ├── format_stop.go │ │ │ ├── install_polarfs.go │ │ │ ├── list_targets.go │ │ │ ├── map.go │ │ │ ├── start_nebd.go │ │ │ ├── start_tgtd.go │ │ │ ├── stop_tgtd.go │ │ │ ├── uninstall_polarfs.go │ │ │ └── unmap.go │ │ ├── checker │ │ │ ├── common.go │ │ │ ├── date.go │ │ │ ├── kernel.go │ │ │ ├── kernel_test.go │ │ │ ├── network.go │ │ │ ├── network_test.go │ │ │ ├── permission.go │ │ │ ├── service.go │ │ │ ├── ssh.go │ │ │ ├── topology.go │ │ │ └── topology.yaml.go │ │ ├── common │ │ │ ├── backup_etcd.go │ │ │ ├── clean_service.go │ │ │ ├── client_status.go │ │ │ ├── collect_client.go │ │ │ ├── collect_curveadm.go │ │ │ ├── collect_report.go │ │ │ ├── collect_service.go │ │ │ ├── create_container.go │ │ │ ├── create_pool.go │ │ │ ├── etcd_auth_enable.go │ │ │ ├── init_support.go │ │ │ ├── install_client.go │ │ │ ├── pull_image.go │ │ │ ├── restart_service.go │ │ │ ├── service_status.go │ │ │ ├── start_service.go │ │ │ ├── stop_service.go │ │ │ ├── sync_config.go │ │ │ ├── uninstall_client.go │ │ │ └── update_topology.go │ │ ├── fs │ │ │ ├── mount.go │ │ │ ├── mount_test.go │ │ │ └── umount.go │ │ ├── monitor │ │ │ ├── clean_container.go │ │ │ ├── clean_service.go │ │ │ ├── create_container.go │ │ │ ├── pull_image.go │ │ │ ├── restart_service.go │ │ │ ├── start_service.go │ │ │ ├── status_service.go │ │ │ ├── stop_service.go │ │ │ └── sync_config.go │ │ ├── playground │ │ │ ├── create.go │ │ │ ├── init.go │ │ │ ├── list.go │ │ │ ├── remove.go │ │ │ ├── script │ │ │ │ ├── client.yaml │ │ │ │ ├── entrypoint.sh │ │ │ │ ├── script.go │ │ │ │ └── topology.yaml │ │ │ └── start.go │ │ └── task.go │ └── tasks │ │ ├── monitor.go │ │ └── tasks.go ├── tasks │ ├── monitor.go │ └── tasks.go ├── tools │ ├── ssh.go │ ├── upgrade.go │ ├── upgrade │ │ └── upgrade.go │ └── upload.go ├── tui │ ├── audit.go │ ├── client │ │ └── status.go │ ├── clients.go │ ├── clusters.go │ ├── common │ │ ├── prompt.go │ │ └── tui.go │ ├── format │ │ └── status.go │ ├── hosts.go │ ├── playground.go │ ├── service │ │ └── status.go │ └── targets.go └── utils │ ├── cobra.go │ ├── common.go │ ├── file.go │ ├── file_test.go │ ├── fs.go │ └── map.go ├── pkg ├── log │ ├── glg │ │ ├── glg.go │ │ └── log.go │ ├── log.go │ └── zaplog │ │ └── log.go ├── module │ ├── docker_cli.go │ ├── file.go │ ├── module.go │ ├── shell.go │ └── ssh.go └── variable │ └── variables.go ├── playbook ├── logs │ └── scripts │ │ └── rotate.sh └── memcached │ ├── hosts.yaml │ └── scripts │ ├── clean.sh │ ├── deploy.sh │ ├── start.sh │ ├── status.sh │ └── stop.sh ├── plugins ├── README.md ├── polarfs │ ├── META │ ├── README.md │ └── main.yaml └── shell │ ├── META │ ├── README.md │ └── main.yaml ├── scripts └── install.sh └── trace ├── README.md └── curvefs-fuse-bt /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [ $default-branch, "develop" ] 6 | pull_request: 7 | branches: [ $default-branch, "develop" ] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - name: Set up Go 15 | uses: actions/setup-go@v3 16 | with: 17 | go-version: 1.18 18 | - name: Generate SSH key 19 | run: ssh-keygen -f ~/.ssh/id_rsa -P "" 20 | - name: Test 21 | run: make test 22 | 23 | build: 24 | needs: test 25 | runs-on: ubuntu-latest 26 | steps: 27 | - uses: actions/checkout@v3 28 | - name: Set up Go 29 | uses: actions/setup-go@v3 30 | with: 31 | go-version: 1.18 32 | - name: Set dependencies 33 | run: sudo apt update && sudo apt install musl-tools 34 | - name: Build 35 | run: make build 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | t/* 2 | .idea/ 3 | sbin/ 4 | bin/ 5 | PIPE/ 6 | curveadm/ 7 | T/* 8 | logs/* 9 | .playground 10 | .build/ 11 | .vscode/ 12 | .CHANGELOG 13 | vendor/ 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | v0.2.0 2 | --- 3 | * Improve: add CI (build and test action), thanks to Tsong Lew. 4 | * Improve: update go version since Go 1.18 is required to build rivo/uniseg, thanks to Tsong Lew. 5 | * Feature(exec): support execute command in specified container, thanks to Wangpan. 6 | * Feature(target): support specify target block size, thanks to mfordjody. 7 | * Feature(format): support stop formmating, thanks to DemoLiang. 8 | * Feature(mount): support setting environment variable for client container. 9 | * Feature(hosts): support setting SSH address which only for SSH connect. 10 | * Feature(playbook): add playbook which user can run any scripts in any hosts. 11 | * Feature(playbook): support deploy memcache by playbook, thanks to SiKu. 12 | * Feature(playbook): support setting host environment variable. 13 | * Feature(playbook): support pass arguments to run scripts. 14 | * Feature(playbook): support exclude and intersection pattern for playbook label. 15 | * Feature(playground): now we can run playground by specified container image. 16 | * Feature: add curvefs-fuse-bt bpftrace tool. 17 | * Fix: set environment variable failed while executing command. 18 | * Fix: its no need to become user when execute command in local. 19 | * Fix(map): map a volume which name contain underscore symbol. 20 | * Fix(format): wrong sed expression in become_user modle. 21 | 22 | v0.0.10 23 | --- 24 | * bugfix(*): fixed read & install file error 25 | 26 | v0.0.9 27 | --- 28 | * bugfix(*): fixed download and upload file conflict for deploy in local machine 29 | 30 | v0.0.6 31 | --- 32 | * feature(fs): now we will report CurveFS cluster usage to curve center (issue #18) 33 | 34 | v0.0.5 35 | --- 36 | * improve(fs): synchronize tools config to its default path 37 | * imporve(fs): trim ending slash of mountpoint when mount/umount/check 38 | * bugfix(fs): added volume for log dir and data dir for client container 39 | * bugfix(fs): specify host network for client container 40 | * bugfix(fs): create the missing configure directory when synchronize tools config 41 | * bugfix(*): use empty string for default binary option of reload command (issue #11) 42 | 43 | 44 | v0.0.4 45 | --- 46 | * feature(*): now we can get support from curve team (issue #6) 47 | * feature(*): support replace service binary without re-deploy (issue #2) 48 | 49 | v0.0.3 50 | --- 51 | * feature(*): support export and import cluster database 52 | * improve(fs): wait mds leader election success before create curvefs topology 53 | * improve(*): change the current working directory when enter service container 54 | * bugfix(fs): use fusermount to umount filesystem instead of stop fuse client (issue #3) 55 | 56 | v0.0.2 57 | --- 58 | * feature(*): support upgrade curveadm to latest version 59 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build debug install test upload lint 2 | 3 | # go env 4 | GOPROXY := "https://goproxy.cn,direct" 5 | GOOS := $(if $(GOOS),$(GOOS),$(shell go env GOOS)) 6 | GOARCH := $(if $(GOARCH),$(GOARCH),$(shell go env GOARCH)) 7 | CGO_LDFLAGS := "-static" 8 | CC := musl-gcc 9 | 10 | GOENV := GO111MODULE=on 11 | GOENV += GOPROXY=$(GOPROXY) 12 | GOENV += CC=$(CC) 13 | GOENV += CGO_ENABLED=1 CGO_LDFLAGS=$(CGO_LDFLAGS) 14 | GOENV += GOOS=$(GOOS) GOARCH=$(GOARCH) 15 | GOLANGCILINT_VERSION ?= v1.50.0 16 | GOBIN := $(shell go env GOPATH)/bin 17 | GOBIN_GOLANGCILINT := $(shell which $(GOBIN)/golangci-lint) 18 | # go 19 | GO := go 20 | 21 | # output 22 | OUTPUT := bin/curveadm 23 | 24 | # build flags 25 | LDFLAGS := -s -w 26 | LDFLAGS += -extldflags "-static -fpic" 27 | LDFLAGS += -X github.com/opencurve/curveadm/cli/cli.CommitId=$(shell git rev-parse --short HEAD) 28 | 29 | BUILD_FLAGS := -a 30 | BUILD_FLAGS += -trimpath 31 | BUILD_FLAGS += -ldflags '$(LDFLAGS)' 32 | BUILD_FLAGS += $(EXTRA_FLAGS) 33 | 34 | # debug flags 35 | GCFLAGS := "all=-N -l" 36 | 37 | DEBUG_FLAGS := -gcflags=$(GCFLAGS) 38 | 39 | # go test 40 | GO_TEST ?= $(GO) test 41 | 42 | # test flags 43 | CASE ?= "." 44 | 45 | TEST_FLAGS := -v 46 | TEST_FLAGS += -p 3 47 | TEST_FLAGS += -cover 48 | TEST_FLAGS += -count=1 49 | TEST_FLAGS += $(DEBUG_FLAGS) 50 | TEST_FLAGS += -run $(CASE) 51 | 52 | # packages 53 | PACKAGES := $(PWD)/cmd/curveadm/main.go 54 | 55 | # tar 56 | VERSION := "unknown" 57 | 58 | build: 59 | $(GOENV) $(GO) build -o $(OUTPUT) $(BUILD_FLAGS) $(PACKAGES) 60 | 61 | debug: 62 | $(GOENV) $(GO) build -o $(OUTPUT) $(DEBUG_FLAGS) $(PACKAGES) 63 | 64 | install: 65 | cp bin/curveadm ~/.curveadm/bin 66 | 67 | test: 68 | $(GO_TEST) $(TEST_FLAGS) ./... 69 | 70 | upload: 71 | @NOSCMD=$(NOSCMD) bash build/package/upload.sh $(VERSION) 72 | 73 | lint: 74 | go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCILINT_VERSION) 75 | $(GOBIN_GOLANGCILINT) run -v 76 | 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CurveAdm 2 | --- 3 | 4 | CurveAdm is a tool for deploy and manage Curve cluster, it's easy to use and with rich features. 5 | 6 | Documentation 7 | --- 8 | 9 | * [简体中文][docs] 10 | 11 | Installation 12 | --- 13 | 14 | ```shell 15 | $ bash -c "$(curl -fsSL https://curveadm.nos-eastchina1.126.net/script/install.sh)" 16 | ``` 17 | 18 | Usage 19 | --- 20 | 21 | Run `curveadm -h` for more informations. 22 | 23 | Contributing 24 | --- 25 | 26 | Contributions of code, tests, documentation and bugs are welcome, 27 | you can see [CONTRIBUTING][contributing] for details. 28 | 29 | License 30 | --- 31 | 32 | CurveAdm is under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details. 33 | 34 | [docs]: https://github.com/opencurve/curveadm/wiki 35 | [contributing]: https://github.com/opencurve/curveadm/wiki/others#参与-curveadm-的开发 -------------------------------------------------------------------------------- /build/package/upload.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | g_version=$1 4 | g_nos_cmd=${NOSCMD} 5 | g_root=$(pwd)/.build 6 | g_curveadm=${g_root}/curveadm 7 | g_curveadm_bin=${g_curveadm}/bin 8 | rm -rf ${g_root} 9 | 10 | mkdir -p ${g_curveadm_bin} 11 | cp bin/curveadm ${g_curveadm_bin} 12 | [[ -f .CHANGELOG ]] && cp .CHANGELOG ${g_curveadm}/CHANGELOG 13 | (cd ${g_curveadm} && ./bin/curveadm -v && ls -ls bin/curveadm && [[ -f CHANGELOG ]] && cat CHANGELOG) 14 | (cd ${g_root} && tar -zcf curveadm-${g_version}.tar.gz curveadm) 15 | 16 | read -p "Do you want to upload curveadm-${g_version}.tar.gz to NOS? " input 17 | case $input in 18 | [Yy]* ) 19 | if [ -z ${g_nos_cmd} ]; then 20 | echo "nos: command not found" 21 | exit 1 22 | fi 23 | ${g_nos_cmd} -putfile \ 24 | ${g_root}/curveadm-${g_version}.tar.gz \ 25 | curveadm \ 26 | -key release/curveadm-${g_version}.tar.gz \ 27 | -replace true 28 | ;; 29 | [Nn]* ) 30 | exit 31 | ;; 32 | * ) 33 | echo "Please answer yes or no." 34 | ;; 35 | esac 36 | -------------------------------------------------------------------------------- /cli/cli/version.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package cli 26 | 27 | var ( 28 | Version = "0.3.0" 29 | 30 | CommitId = "unknown" 31 | ) 32 | -------------------------------------------------------------------------------- /cli/command/audit.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-05-23 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package command 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/errno" 30 | "github.com/opencurve/curveadm/internal/tui" 31 | cliutil "github.com/opencurve/curveadm/internal/utils" 32 | "github.com/spf13/cobra" 33 | ) 34 | 35 | type auditOptions struct { 36 | tail int 37 | verbose bool 38 | } 39 | 40 | func NewAuditCommand(curveadm *cli.CurveAdm) *cobra.Command { 41 | var options auditOptions 42 | 43 | cmd := &cobra.Command{ 44 | Use: "audit [OPTIONS]", 45 | Short: "Show audit log of operation", 46 | Args: cliutil.NoArgs, 47 | RunE: func(cmd *cobra.Command, args []string) error { 48 | return runAudit(curveadm, options) 49 | }, 50 | DisableFlagsInUseLine: true, 51 | } 52 | 53 | flags := cmd.Flags() 54 | flags.IntVarP(&options.tail, "tail", "n", 20, "Number of lines to show from the end of the logs (0 means all)") 55 | flags.BoolVarP(&options.verbose, "verbose", "v", false, "Verbose output for clusters") 56 | 57 | return cmd 58 | } 59 | 60 | func runAudit(curveadm *cli.CurveAdm, options auditOptions) error { 61 | auditLogs, err := curveadm.Storage().GetAuditLogs() 62 | if err != nil { 63 | return errno.ERR_GET_AUDIT_LOGS_FAILE.E(err) 64 | } 65 | 66 | tail := options.tail 67 | if tail != 0 && tail > 0 && tail < len(auditLogs) { 68 | auditLogs = auditLogs[len(auditLogs)-tail:] 69 | } 70 | output := tui.FormatAuditLogs(auditLogs, options.verbose) 71 | curveadm.WriteOut(output) 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /cli/command/client/cmd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package client 24 | 25 | import ( 26 | "github.com/opencurve/curveadm/cli/cli" 27 | cliutil "github.com/opencurve/curveadm/internal/utils" 28 | "github.com/spf13/cobra" 29 | ) 30 | 31 | func NewClientCommand(curveadm *cli.CurveAdm) *cobra.Command { 32 | cmd := &cobra.Command{ 33 | Use: "client", 34 | Short: "Manage client", 35 | Args: cliutil.NoArgs, 36 | RunE: cliutil.ShowHelp(curveadm.Err()), 37 | } 38 | 39 | cmd.AddCommand( 40 | NewMapCommand(curveadm), 41 | NewUnmapCommand(curveadm), 42 | NewMountCommand(curveadm), 43 | NewUmountCommand(curveadm), 44 | NewStatusCommand(curveadm), 45 | NewEnterCommand(curveadm), 46 | // NewInstallCommand(curveadm), 47 | // NewUninstallCommand(curveadm), 48 | ) 49 | return cmd 50 | } 51 | -------------------------------------------------------------------------------- /cli/command/client/enter.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-08-05 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package client 24 | 25 | import ( 26 | "github.com/opencurve/curveadm/cli/cli" 27 | "github.com/opencurve/curveadm/internal/configure/topology" 28 | "github.com/opencurve/curveadm/internal/errno" 29 | "github.com/opencurve/curveadm/internal/tools" 30 | "github.com/opencurve/curveadm/internal/utils" 31 | "github.com/spf13/cobra" 32 | ) 33 | 34 | type enterOptions struct { 35 | id string 36 | } 37 | 38 | func NewEnterCommand(curveadm *cli.CurveAdm) *cobra.Command { 39 | var options enterOptions 40 | 41 | cmd := &cobra.Command{ 42 | Use: "enter ID", 43 | Short: "Enter client container", 44 | Args: utils.ExactArgs(1), 45 | RunE: func(cmd *cobra.Command, args []string) error { 46 | options.id = args[0] 47 | return runEnter(curveadm, options) 48 | }, 49 | DisableFlagsInUseLine: true, 50 | } 51 | 52 | return cmd 53 | } 54 | 55 | func runEnter(curveadm *cli.CurveAdm, options enterOptions) error { 56 | // 1) get container id 57 | clients, err := curveadm.Storage().GetClient(options.id) 58 | if err != nil { 59 | return err 60 | } else if len(clients) != 1 { 61 | return errno.ERR_NO_CLIENT_MATCHED 62 | } 63 | 64 | // 2) attch remote container 65 | client := clients[0] 66 | home := "/curvebs/nebd" 67 | if client.Kind == topology.KIND_CURVEFS { 68 | home = "/curvefs/client" 69 | } 70 | return tools.AttachRemoteContainer(curveadm, client.Host, client.ContainerId, home) 71 | } 72 | -------------------------------------------------------------------------------- /cli/command/cluster/checkout.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package cluster 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/errno" 30 | cliutil "github.com/opencurve/curveadm/internal/utils" 31 | log "github.com/opencurve/curveadm/pkg/log/glg" 32 | "github.com/spf13/cobra" 33 | ) 34 | 35 | type checkoutOptions struct { 36 | clusterName string 37 | } 38 | 39 | func NewCheckoutCommand(curveadm *cli.CurveAdm) *cobra.Command { 40 | var options checkoutOptions 41 | 42 | cmd := &cobra.Command{ 43 | Use: "checkout CLUSTER", 44 | Short: "Switch cluster", 45 | Args: cliutil.ExactArgs(1), 46 | RunE: func(cmd *cobra.Command, args []string) error { 47 | options.clusterName = args[0] 48 | return runCheckout(curveadm, options) 49 | }, 50 | DisableFlagsInUseLine: true, 51 | } 52 | 53 | return cmd 54 | } 55 | 56 | func runCheckout(curveadm *cli.CurveAdm, options checkoutOptions) error { 57 | // 1) get cluster by name 58 | clusterName := options.clusterName 59 | storage := curveadm.Storage() 60 | clusters, err := storage.GetClusters(clusterName) 61 | if err != nil { 62 | log.Error("Get clusters failed", 63 | log.Field("error", err)) 64 | return errno.ERR_GET_ALL_CLUSTERS_FAILED.E(err) 65 | } else if len(clusters) == 0 { 66 | return errno.ERR_CLUSTER_NOT_FOUND. 67 | F("cluster name: %s", clusterName) 68 | } 69 | 70 | // 2) switch current cluster in database 71 | err = storage.CheckoutCluster(clusterName) 72 | if err != nil { 73 | return errno.ERR_CHECKOUT_CLUSTER_FAILED.E(err) 74 | } 75 | 76 | // 3) print success prompt 77 | curveadm.WriteOutln("Switched to cluster '%s'", clusterName) 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /cli/command/cluster/cmd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package cluster 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | cliutil "github.com/opencurve/curveadm/internal/utils" 30 | "github.com/spf13/cobra" 31 | ) 32 | 33 | func NewClusterCommand(curveadm *cli.CurveAdm) *cobra.Command { 34 | cmd := &cobra.Command{ 35 | Use: "cluster", 36 | Short: "Manage clusters", 37 | Args: cliutil.NoArgs, 38 | RunE: cliutil.ShowHelp(curveadm.Err()), 39 | } 40 | 41 | cmd.AddCommand( 42 | NewAddCommand(curveadm), 43 | NewCheckoutCommand(curveadm), 44 | NewListCommand(curveadm), 45 | NewRemoveCommand(curveadm), 46 | // TODO(P1): enable export 47 | //NewExportCommand(curveadm), 48 | NewImportCommand(curveadm), 49 | ) 50 | return cmd 51 | } 52 | -------------------------------------------------------------------------------- /cli/command/cluster/list.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package cluster 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/errno" 30 | "github.com/opencurve/curveadm/internal/tui" 31 | cliutil "github.com/opencurve/curveadm/internal/utils" 32 | log "github.com/opencurve/curveadm/pkg/log/glg" 33 | "github.com/spf13/cobra" 34 | ) 35 | 36 | type listOptions struct { 37 | verbose bool 38 | } 39 | 40 | func NewListCommand(curveadm *cli.CurveAdm) *cobra.Command { 41 | var options listOptions 42 | 43 | cmd := &cobra.Command{ 44 | Use: "ls [OPTIONS]", 45 | Aliases: []string{"list"}, 46 | Short: "List clusters", 47 | Args: cliutil.NoArgs, 48 | RunE: func(cmd *cobra.Command, args []string) error { 49 | return runList(curveadm, options) 50 | }, 51 | DisableFlagsInUseLine: true, 52 | } 53 | 54 | flags := cmd.Flags() 55 | flags.BoolVarP(&options.verbose, "verbose", "v", false, "Verbose output for clusters") 56 | 57 | return cmd 58 | } 59 | 60 | func runList(curveadm *cli.CurveAdm, options listOptions) error { 61 | // 1) get all clusters 62 | storage := curveadm.Storage() 63 | clusters, err := storage.GetClusters("%") 64 | if err != nil { 65 | log.Error("Get clusters failed", 66 | log.Field("error", err)) 67 | return errno.ERR_GET_ALL_CLUSTERS_FAILED.E(err) 68 | } 69 | 70 | // 2) display clusters 71 | output := tui.FormatClusters(clusters, options.verbose) 72 | curveadm.WriteOut(output) 73 | return nil 74 | } 75 | -------------------------------------------------------------------------------- /cli/command/completion.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-01-07 20 | * Author: aspirer 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package command 26 | 27 | import ( 28 | "fmt" 29 | "os" 30 | 31 | "github.com/opencurve/curveadm/cli/cli" 32 | "github.com/spf13/cobra" 33 | ) 34 | 35 | func NewCompletionCommand(curveadm *cli.CurveAdm) *cobra.Command { 36 | var completionCmd = &cobra.Command{ 37 | Use: "completion [bash|zsh|fish|powershell]", 38 | Short: "Generate completion script", 39 | Long: fmt.Sprintf(`To load completions: 40 | 41 | Bash: 42 | 43 | $ source <(%[1]s completion bash) 44 | 45 | # To load completions for each session, execute once: 46 | # Linux: 47 | $ %[1]s completion bash > /etc/bash_completion.d/%[1]s 48 | # macOS: 49 | $ %[1]s completion bash > /usr/local/etc/bash_completion.d/%[1]s 50 | 51 | Zsh: 52 | 53 | # If shell completion is not already enabled in your environment, 54 | # you will need to enable it. You can execute the following once: 55 | 56 | $ echo "autoload -U compinit; compinit" >> ~/.zshrc 57 | 58 | # To load completions for each session, execute once: 59 | $ %[1]s completion zsh > "${fpath[1]}/_%[1]s" 60 | 61 | # You will need to start a new shell for this setup to take effect. 62 | 63 | fish: 64 | 65 | $ %[1]s completion fish | source 66 | 67 | # To load completions for each session, execute once: 68 | $ %[1]s completion fish > ~/.config/fish/completions/%[1]s.fish 69 | 70 | PowerShell: 71 | 72 | PS> %[1]s completion powershell | Out-String | Invoke-Expression 73 | 74 | # To load completions for every new session, run: 75 | PS> %[1]s completion powershell > %[1]s.ps1 76 | # and source this file from your PowerShell profile. 77 | `, "curveadm"), 78 | DisableFlagsInUseLine: true, 79 | ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, 80 | Args: cobra.ExactValidArgs(1), 81 | Run: func(cmd *cobra.Command, args []string) { 82 | switch args[0] { 83 | case "bash": 84 | cmd.Root().GenBashCompletion(os.Stdout) 85 | case "zsh": 86 | cmd.Root().GenZshCompletion(os.Stdout) 87 | case "fish": 88 | cmd.Root().GenFishCompletion(os.Stdout, true) 89 | case "powershell": 90 | cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout) 91 | } 92 | }, 93 | } 94 | 95 | return completionCmd 96 | } 97 | -------------------------------------------------------------------------------- /cli/command/config/cmd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package config 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | cliutil "github.com/opencurve/curveadm/internal/utils" 30 | "github.com/spf13/cobra" 31 | ) 32 | 33 | func NewConfigCommand(curveadm *cli.CurveAdm) *cobra.Command { 34 | cmd := &cobra.Command{ 35 | Use: "config", 36 | Short: "Manage cluster topology", 37 | Args: cliutil.NoArgs, 38 | RunE: cliutil.ShowHelp(curveadm.Err()), 39 | } 40 | 41 | cmd.AddCommand( 42 | NewShowCommand(curveadm), 43 | NewDiffCommand(curveadm), 44 | NewCommitCommand(curveadm), 45 | ) 46 | return cmd 47 | } 48 | -------------------------------------------------------------------------------- /cli/command/config/diff.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package config 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/errno" 30 | "github.com/opencurve/curveadm/internal/utils" 31 | "github.com/spf13/cobra" 32 | ) 33 | 34 | const ( 35 | DIFF_EXAMPLE = `Examples: 36 | $ curveadm config diff /path/to/topology.yaml # Display difference for topology` 37 | ) 38 | 39 | type diffOptions struct { 40 | filename string 41 | } 42 | 43 | func NewDiffCommand(curveadm *cli.CurveAdm) *cobra.Command { 44 | var options diffOptions 45 | 46 | cmd := &cobra.Command{ 47 | Use: "diff TOPOLOGY", 48 | Short: "Display difference for topology", 49 | Args: utils.ExactArgs(1), 50 | Example: DIFF_EXAMPLE, 51 | RunE: func(cmd *cobra.Command, args []string) error { 52 | options.filename = args[0] 53 | return runDiff(curveadm, options) 54 | }, 55 | DisableFlagsInUseLine: true, 56 | } 57 | 58 | return cmd 59 | } 60 | 61 | func runDiff(curveadm *cli.CurveAdm, options diffOptions) error { 62 | // 1) data1: current cluster topology data 63 | data1 := curveadm.ClusterTopologyData() 64 | 65 | // 2) data2: topology in file 66 | if !utils.PathExist(options.filename) { 67 | return errno.ERR_TOPOLOGY_FILE_NOT_FOUND. 68 | F("%s: no such file", utils.AbsPath(options.filename)) 69 | } 70 | data2, err := utils.ReadFile(options.filename) 71 | if err != nil { 72 | return errno.ERR_READ_TOPOLOGY_FILE_FAILED.E(err) 73 | } 74 | 75 | // 3) print difference 76 | diff := utils.Diff(data1, data2) 77 | curveadm.Out().Write([]byte(diff)) 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /cli/command/config/show.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package config 26 | 27 | import ( 28 | "encoding/json" 29 | 30 | "github.com/opencurve/curveadm/cli/cli" 31 | "github.com/opencurve/curveadm/internal/configure" 32 | "github.com/opencurve/curveadm/internal/errno" 33 | cliutil "github.com/opencurve/curveadm/internal/utils" 34 | "github.com/spf13/cobra" 35 | ) 36 | 37 | type showOptions struct { 38 | showPool bool 39 | } 40 | 41 | func NewShowCommand(curveadm *cli.CurveAdm) *cobra.Command { 42 | var options showOptions 43 | 44 | cmd := &cobra.Command{ 45 | Use: "show [OPTIONS]", 46 | Short: "Show cluster topology", 47 | Args: cliutil.NoArgs, 48 | RunE: func(cmd *cobra.Command, args []string) error { 49 | return runShow(curveadm, options) 50 | }, 51 | DisableFlagsInUseLine: true, 52 | } 53 | 54 | flags := cmd.Flags() 55 | flags.BoolVarP(&options.showPool, "pool", "p", false, "Show cluster pool information") 56 | 57 | return cmd 58 | } 59 | 60 | func decodePoolJSON(data string) (string, error) { 61 | pool := configure.CurveClusterTopo{} 62 | err := json.Unmarshal([]byte(data), &pool) 63 | if err != nil { 64 | return "", errno.ERR_DECODE_CLUSTER_POOL_JSON_FAILED.E(err) 65 | } 66 | bytes, err := json.MarshalIndent(pool, "", " ") 67 | if err != nil { 68 | return "", errno.ERR_DECODE_CLUSTER_POOL_JSON_FAILED.E(err) 69 | } 70 | return string(bytes), nil 71 | } 72 | 73 | func runShow(curveadm *cli.CurveAdm, options showOptions) error { 74 | // 1) check whether cluster exist 75 | if curveadm.ClusterId() == -1 { 76 | return errno.ERR_NO_CLUSTER_SPECIFIED 77 | } else if len(curveadm.ClusterTopologyData()) == 0 { 78 | curveadm.WriteOutln("") 79 | return nil 80 | } 81 | 82 | // 2) display cluster topology 83 | if !options.showPool { 84 | curveadm.WriteOut("%s", curveadm.ClusterTopologyData()) 85 | return nil 86 | } 87 | 88 | // 3) OR display cluster pool information 89 | if len(curveadm.ClusterPoolData()) == 0 { 90 | curveadm.WriteOutln("") 91 | return nil 92 | } 93 | data, err := decodePoolJSON(curveadm.ClusterPoolData()) 94 | if err != nil { 95 | return err 96 | } 97 | curveadm.WriteOutln(data) 98 | return nil 99 | } 100 | -------------------------------------------------------------------------------- /cli/command/enter.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package command 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/configure/topology" 30 | "github.com/opencurve/curveadm/internal/errno" 31 | "github.com/opencurve/curveadm/internal/tools" 32 | "github.com/opencurve/curveadm/internal/utils" 33 | "github.com/spf13/cobra" 34 | ) 35 | 36 | type enterOptions struct { 37 | id string 38 | } 39 | 40 | func NewEnterCommand(curveadm *cli.CurveAdm) *cobra.Command { 41 | var options enterOptions 42 | 43 | cmd := &cobra.Command{ 44 | Use: "enter ID", 45 | Short: "Enter service container", 46 | Args: utils.ExactArgs(1), 47 | PreRunE: func(cmd *cobra.Command, args []string) error { 48 | options.id = args[0] 49 | return curveadm.CheckId(options.id) 50 | }, 51 | RunE: func(cmd *cobra.Command, args []string) error { 52 | return runEnter(curveadm, options) 53 | }, 54 | DisableFlagsInUseLine: true, 55 | } 56 | 57 | return cmd 58 | } 59 | 60 | func runEnter(curveadm *cli.CurveAdm, options enterOptions) error { 61 | // 1) parse cluster topology 62 | dcs, err := curveadm.ParseTopology() 63 | if err != nil { 64 | return err 65 | } 66 | 67 | // 2) filter service 68 | dcs = curveadm.FilterDeployConfig(dcs, topology.FilterOption{ 69 | Id: options.id, 70 | Role: "*", 71 | Host: "*", 72 | }) 73 | if len(dcs) == 0 { 74 | return errno.ERR_NO_SERVICES_MATCHED 75 | } 76 | 77 | // 3) get container id 78 | dc := dcs[0] 79 | serviceId := curveadm.GetServiceId(dc.GetId()) 80 | containerId, err := curveadm.GetContainerId(serviceId) 81 | if err != nil { 82 | return err 83 | } 84 | 85 | // 4) attch remote container 86 | home := dc.GetProjectLayout().ServiceRootDir 87 | return tools.AttachRemoteContainer(curveadm, dc.GetHost(), containerId, home) 88 | } 89 | -------------------------------------------------------------------------------- /cli/command/exec.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package command 24 | 25 | import ( 26 | "strings" 27 | 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/configure/topology" 30 | "github.com/opencurve/curveadm/internal/errno" 31 | "github.com/opencurve/curveadm/internal/tools" 32 | "github.com/spf13/cobra" 33 | ) 34 | 35 | type execOptions struct { 36 | id string 37 | cmd string 38 | } 39 | 40 | func NewExecCommand(curveadm *cli.CurveAdm) *cobra.Command { 41 | var options execOptions 42 | 43 | cmd := &cobra.Command{ 44 | Use: "exec ID [OPTIONS]", 45 | Short: "Exec a cmd in service container", 46 | PreRunE: func(cmd *cobra.Command, args []string) error { 47 | options.id = args[0] 48 | options.cmd = strings.Join(args[1:], " ") 49 | args = args[:1] 50 | return curveadm.CheckId(options.id) 51 | }, 52 | RunE: func(cmd *cobra.Command, args []string) error { 53 | return runExec(curveadm, options) 54 | }, 55 | DisableFlagsInUseLine: true, 56 | } 57 | 58 | return cmd 59 | } 60 | 61 | // exec: 62 | // 1. parse cluster topology 63 | // 2. filter service 64 | // 3. get container id 65 | // 4. exec cmd in remote container 66 | func runExec(curveadm *cli.CurveAdm, options execOptions) error { 67 | // 1) parse cluster topology 68 | dcs, err := curveadm.ParseTopology() 69 | if err != nil { 70 | return err 71 | } 72 | 73 | // 2) filter service 74 | dcs = curveadm.FilterDeployConfig(dcs, topology.FilterOption{ 75 | Id: options.id, 76 | Role: "*", 77 | Host: "*", 78 | }) 79 | if len(dcs) == 0 { 80 | return errno.ERR_NO_SERVICES_MATCHED 81 | } 82 | 83 | // 3) get container id 84 | dc := dcs[0] 85 | serviceId := curveadm.GetServiceId(dc.GetId()) 86 | containerId, err := curveadm.GetContainerId(serviceId) 87 | if err != nil { 88 | return err 89 | } 90 | 91 | // 4) exec cmd in remote container 92 | return tools.ExecCmdInRemoteContainer(curveadm, dc.GetHost(), containerId, options.cmd) 93 | } 94 | -------------------------------------------------------------------------------- /cli/command/hosts/cmd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-20 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package hosts 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | cliutil "github.com/opencurve/curveadm/internal/utils" 30 | "github.com/spf13/cobra" 31 | ) 32 | 33 | func NewHostsCommand(curveadm *cli.CurveAdm) *cobra.Command { 34 | cmd := &cobra.Command{ 35 | Use: "hosts", 36 | Short: "Manage hosts", 37 | Args: cliutil.NoArgs, 38 | RunE: cliutil.ShowHelp(curveadm.Err()), 39 | } 40 | 41 | cmd.AddCommand( 42 | NewCommitCommand(curveadm), 43 | NewShowCommand(curveadm), 44 | NewListCommand(curveadm), 45 | NewSSHCommand(curveadm), 46 | NewPlaybookCommand(curveadm), 47 | ) 48 | return cmd 49 | } 50 | -------------------------------------------------------------------------------- /cli/command/hosts/show.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-24 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package hosts 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | cliutil "github.com/opencurve/curveadm/internal/utils" 30 | "github.com/spf13/cobra" 31 | ) 32 | 33 | type showOptions struct{} 34 | 35 | func NewShowCommand(curveadm *cli.CurveAdm) *cobra.Command { 36 | var options showOptions 37 | 38 | cmd := &cobra.Command{ 39 | Use: "show", 40 | Short: "Show hosts", 41 | Args: cliutil.NoArgs, 42 | RunE: func(cmd *cobra.Command, args []string) error { 43 | return runShow(curveadm, options) 44 | }, 45 | DisableFlagsInUseLine: true, 46 | } 47 | 48 | return cmd 49 | } 50 | 51 | func runShow(curveadm *cli.CurveAdm, options showOptions) error { 52 | hosts := curveadm.Hosts() 53 | if len(hosts) == 0 { 54 | curveadm.WriteOutln("") 55 | } else { 56 | curveadm.WriteOut(hosts) 57 | } 58 | return nil 59 | } 60 | -------------------------------------------------------------------------------- /cli/command/hosts/ssh.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-078-04 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package hosts 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/tools" 30 | cliutil "github.com/opencurve/curveadm/internal/utils" 31 | "github.com/spf13/cobra" 32 | ) 33 | 34 | type sshOptions struct { 35 | host string 36 | become bool 37 | } 38 | 39 | func NewSSHCommand(curveadm *cli.CurveAdm) *cobra.Command { 40 | var options sshOptions 41 | 42 | cmd := &cobra.Command{ 43 | Use: "ssh HOST [OPTIONS]", 44 | Short: "Connect remote host", 45 | Args: cliutil.ExactArgs(1), 46 | RunE: func(cmd *cobra.Command, args []string) error { 47 | options.host = args[0] 48 | return runSSH(curveadm, options) 49 | }, 50 | DisableFlagsInUseLine: true, 51 | } 52 | 53 | flags := cmd.Flags() 54 | flags.BoolVarP(&options.become, "become", "b", false, "Connect remote host with become") 55 | 56 | return cmd 57 | } 58 | 59 | func runSSH(curveadm *cli.CurveAdm, options sshOptions) error { 60 | return tools.AttachRemoteHost(curveadm, options.host, options.become) 61 | } 62 | -------------------------------------------------------------------------------- /cli/command/monitor/cmd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: Curveadm 19 | * Created Date: 2023-04-17 20 | * Author: wanghai (SeanHai) 21 | */ 22 | 23 | package monitor 24 | 25 | import ( 26 | "github.com/opencurve/curveadm/cli/cli" 27 | cliutil "github.com/opencurve/curveadm/internal/utils" 28 | "github.com/spf13/cobra" 29 | ) 30 | 31 | func NewMonitorCommand(curveadm *cli.CurveAdm) *cobra.Command { 32 | cmd := &cobra.Command{ 33 | Use: "monitor", 34 | Short: "Manage monitor", 35 | Args: cliutil.NoArgs, 36 | RunE: cliutil.ShowHelp(curveadm.Err()), 37 | } 38 | 39 | cmd.AddCommand( 40 | NewDeployCommand(curveadm), 41 | NewStartCommand(curveadm), 42 | NewStopCommand(curveadm), 43 | NewStatusCommand(curveadm), 44 | NewCleanCommand(curveadm), 45 | NewRestartCommand(curveadm), 46 | NewReloadCommand(curveadm), 47 | ) 48 | return cmd 49 | } 50 | -------------------------------------------------------------------------------- /cli/command/pfs/cmd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-08-08 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package pfs 24 | 25 | import ( 26 | "github.com/opencurve/curveadm/cli/cli" 27 | cliutil "github.com/opencurve/curveadm/internal/utils" 28 | "github.com/spf13/cobra" 29 | ) 30 | 31 | func NewPFSCommand(curveadm *cli.CurveAdm) *cobra.Command { 32 | cmd := &cobra.Command{ 33 | Use: "pfs", 34 | Short: "Manage pfs", 35 | Args: cliutil.NoArgs, 36 | RunE: cliutil.ShowHelp(curveadm.Err()), 37 | } 38 | 39 | cmd.AddCommand( 40 | NewInstallCommand(curveadm), 41 | NewUninstallCommand(curveadm), 42 | ) 43 | return cmd 44 | } 45 | -------------------------------------------------------------------------------- /cli/command/pfs/uninstall.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-08-08 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package pfs 24 | 25 | import ( 26 | "github.com/fatih/color" 27 | "github.com/opencurve/curveadm/cli/cli" 28 | comm "github.com/opencurve/curveadm/internal/common" 29 | "github.com/opencurve/curveadm/internal/playbook" 30 | cliutil "github.com/opencurve/curveadm/internal/utils" 31 | "github.com/spf13/cobra" 32 | ) 33 | 34 | var ( 35 | UNINSTALL_PFS_PLAYBOOK_STEPS = []int{ 36 | playbook.DETECT_OS_RELEASE, 37 | playbook.UNINSTALL_POLARFS, 38 | } 39 | ) 40 | 41 | type uninstallOptions struct { 42 | host string 43 | } 44 | 45 | func NewUninstallCommand(curveadm *cli.CurveAdm) *cobra.Command { 46 | var options uninstallOptions 47 | 48 | cmd := &cobra.Command{ 49 | Use: "uninstall [OPTIONS]", 50 | Short: "Uninstall PolarFS", 51 | Args: cliutil.NoArgs, 52 | RunE: func(cmd *cobra.Command, args []string) error { 53 | return runUninstall(curveadm, options) 54 | }, 55 | DisableFlagsInUseLine: true, 56 | } 57 | 58 | flags := cmd.Flags() 59 | flags.StringVar(&options.host, "host", "local", "Specify uninstall target host") 60 | 61 | return cmd 62 | } 63 | 64 | func genUninstallPlaybook(curveadm *cli.CurveAdm, 65 | v interface{}, options uninstallOptions) (*playbook.Playbook, error) { 66 | steps := UNINSTALL_PFS_PLAYBOOK_STEPS 67 | pb := playbook.NewPlaybook(curveadm) 68 | for _, step := range steps { 69 | pb.AddStep(&playbook.PlaybookStep{ 70 | Type: step, 71 | Configs: nil, 72 | Options: map[string]interface{}{ 73 | comm.KEY_POLARFS_HOST: options.host, 74 | }, 75 | }) 76 | } 77 | return pb, nil 78 | } 79 | 80 | func runUninstall(curveadm *cli.CurveAdm, options uninstallOptions) error { 81 | // 1) generate map playbook 82 | pb, err := genUninstallPlaybook(curveadm, nil, options) 83 | if err != nil { 84 | return err 85 | } 86 | 87 | // 2) run playground 88 | err = pb.Run() 89 | if err != nil { 90 | return err 91 | } 92 | 93 | // 4) print success prompt 94 | curveadm.WriteOutln("") 95 | curveadm.WriteOutln(color.GreenString("UnInstall %s polarfs success ^_^"), options.host) 96 | return nil 97 | } 98 | -------------------------------------------------------------------------------- /cli/command/playground/cmd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-06-23 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package playground 24 | 25 | import ( 26 | "github.com/opencurve/curveadm/cli/cli" 27 | cliutil "github.com/opencurve/curveadm/internal/utils" 28 | "github.com/spf13/cobra" 29 | ) 30 | 31 | func NewPlaygroundCommand(curveadm *cli.CurveAdm) *cobra.Command { 32 | cmd := &cobra.Command{ 33 | Use: "playground", 34 | Short: "Manage playground", 35 | Args: cliutil.NoArgs, 36 | RunE: cliutil.ShowHelp(curveadm.Err()), 37 | } 38 | 39 | cmd.AddCommand( 40 | NewRunCommand(curveadm), 41 | NewRemoveCommand(curveadm), 42 | NewListCommand(curveadm), 43 | NewEnterCommand(curveadm), 44 | ) 45 | return cmd 46 | } 47 | -------------------------------------------------------------------------------- /cli/command/playground/enter.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-06-24 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package playground 24 | 25 | import ( 26 | "github.com/opencurve/curveadm/cli/cli" 27 | "github.com/opencurve/curveadm/internal/errno" 28 | "github.com/opencurve/curveadm/internal/tools" 29 | "github.com/opencurve/curveadm/internal/utils" 30 | "github.com/spf13/cobra" 31 | ) 32 | 33 | type enterOptions struct { 34 | id string 35 | } 36 | 37 | func NewEnterCommand(curveadm *cli.CurveAdm) *cobra.Command { 38 | var options enterOptions 39 | 40 | cmd := &cobra.Command{ 41 | Use: "enter ID", 42 | Short: "Enter playground container", 43 | Args: utils.ExactArgs(1), 44 | RunE: func(cmd *cobra.Command, args []string) error { 45 | options.id = args[0] 46 | return runEnter(curveadm, options) 47 | }, 48 | DisableFlagsInUseLine: true, 49 | } 50 | 51 | return cmd 52 | } 53 | 54 | func runEnter(curveadm *cli.CurveAdm, options enterOptions) error { 55 | // 1) get playground 56 | id := options.id 57 | playgrounds, err := curveadm.Storage().GetPlaygroundById(id) 58 | if err != nil { 59 | return errno.ERR_GET_PLAYGROUND_BY_NAME_FAILED.E(err) 60 | } else if len(playgrounds) == 0 { 61 | return errno.ERR_PLAYGROUND_NOT_FOUND. 62 | F("id=%s", id) 63 | } 64 | 65 | // 2) attch local container 66 | return tools.AttachLocalContainer(curveadm, playgrounds[0].Name) 67 | } 68 | -------------------------------------------------------------------------------- /cli/command/target/cmd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-02-08 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package target 24 | 25 | import ( 26 | "github.com/opencurve/curveadm/cli/cli" 27 | cliutil "github.com/opencurve/curveadm/internal/utils" 28 | "github.com/spf13/cobra" 29 | ) 30 | 31 | func NewTargetCommand(curveadm *cli.CurveAdm) *cobra.Command { 32 | cmd := &cobra.Command{ 33 | Use: "target", 34 | Short: "Manage SCSI target of CurveBS", 35 | Args: cliutil.NoArgs, 36 | RunE: cliutil.ShowHelp(curveadm.Err()), 37 | } 38 | 39 | cmd.AddCommand( 40 | NewStartCommand(curveadm), 41 | NewStopCommand(curveadm), 42 | NewAddCommand(curveadm), 43 | NewDeleteCommand(curveadm), 44 | NewListCommand(curveadm), 45 | ) 46 | return cmd 47 | } 48 | -------------------------------------------------------------------------------- /cli/command/target/delete.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-02-09 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package target 24 | 25 | import ( 26 | "github.com/fatih/color" 27 | "github.com/opencurve/curveadm/cli/cli" 28 | comm "github.com/opencurve/curveadm/internal/common" 29 | "github.com/opencurve/curveadm/internal/playbook" 30 | "github.com/opencurve/curveadm/internal/task/task/bs" 31 | cliutil "github.com/opencurve/curveadm/internal/utils" 32 | "github.com/spf13/cobra" 33 | ) 34 | 35 | var ( 36 | DELETE_PLAYBOOK_STEPS = []int{ 37 | playbook.DELETE_TARGET, 38 | } 39 | ) 40 | 41 | type deleteOptions struct { 42 | host string 43 | tid string 44 | } 45 | 46 | func NewDeleteCommand(curveadm *cli.CurveAdm) *cobra.Command { 47 | var options deleteOptions 48 | 49 | cmd := &cobra.Command{ 50 | Use: "rm TID [OPTIONS]", 51 | Aliases: []string{"delete"}, 52 | Short: "Delete a target of CurveBS", 53 | Args: cliutil.ExactArgs(1), 54 | RunE: func(cmd *cobra.Command, args []string) error { 55 | options.tid = args[0] 56 | return runDelete(curveadm, options) 57 | }, 58 | DisableFlagsInUseLine: true, 59 | } 60 | 61 | flags := cmd.Flags() 62 | flags.StringVar(&options.host, "host", "localhost", "Specify target host") 63 | 64 | return cmd 65 | } 66 | 67 | func genDeletePlaybook(curveadm *cli.CurveAdm, options deleteOptions) (*playbook.Playbook, error) { 68 | steps := DELETE_PLAYBOOK_STEPS 69 | pb := playbook.NewPlaybook(curveadm) 70 | for _, step := range steps { 71 | pb.AddStep(&playbook.PlaybookStep{ 72 | Type: step, 73 | Configs: nil, 74 | Options: map[string]interface{}{ 75 | comm.KEY_TARGET_OPTIONS: bs.TargetOption{ 76 | Host: options.host, 77 | Tid: options.tid, 78 | }, 79 | }, 80 | }) 81 | } 82 | return pb, nil 83 | } 84 | 85 | func runDelete(curveadm *cli.CurveAdm, options deleteOptions) error { 86 | // 1) generate list playbook 87 | pb, err := genDeletePlaybook(curveadm, options) 88 | if err != nil { 89 | return err 90 | } 91 | 92 | // 2) run playground 93 | err = pb.Run() 94 | if err != nil { 95 | return err 96 | } 97 | 98 | // 3) print targets 99 | curveadm.WriteOutln("") 100 | curveadm.WriteOutln(color.GreenString("Delete target (tid=%s) on %s success ^_^"), 101 | options.tid, options.host) 102 | return nil 103 | } 104 | -------------------------------------------------------------------------------- /cli/command/target/stop.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-02-08 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package target 24 | 25 | import ( 26 | "github.com/fatih/color" 27 | "github.com/opencurve/curveadm/cli/cli" 28 | comm "github.com/opencurve/curveadm/internal/common" 29 | "github.com/opencurve/curveadm/internal/playbook" 30 | "github.com/opencurve/curveadm/internal/task/task/bs" 31 | cliutil "github.com/opencurve/curveadm/internal/utils" 32 | "github.com/spf13/cobra" 33 | ) 34 | 35 | var ( 36 | STOP_PLAYBOOK_STEPS = []int{ 37 | playbook.STOP_TARGET_DAEMON, 38 | } 39 | ) 40 | 41 | type stopOptions struct { 42 | host string 43 | } 44 | 45 | func NewStopCommand(curveadm *cli.CurveAdm) *cobra.Command { 46 | var options stopOptions 47 | 48 | cmd := &cobra.Command{ 49 | Use: "stop [OPTIONS]", 50 | Short: "Stop target deamon", 51 | Args: cliutil.NoArgs, 52 | RunE: func(cmd *cobra.Command, args []string) error { 53 | return runStop(curveadm, options) 54 | }, 55 | DisableFlagsInUseLine: true, 56 | } 57 | 58 | flags := cmd.Flags() 59 | flags.StringVar(&options.host, "host", "localhost", "Specify target host") 60 | 61 | return cmd 62 | } 63 | 64 | func genStopPlaybook(curveadm *cli.CurveAdm, options stopOptions) (*playbook.Playbook, error) { 65 | steps := STOP_PLAYBOOK_STEPS 66 | pb := playbook.NewPlaybook(curveadm) 67 | for _, step := range steps { 68 | pb.AddStep(&playbook.PlaybookStep{ 69 | Type: step, 70 | Configs: nil, 71 | Options: map[string]interface{}{ 72 | comm.KEY_TARGET_OPTIONS: bs.TargetOption{ 73 | Host: options.host, 74 | }, 75 | }, 76 | }) 77 | } 78 | return pb, nil 79 | } 80 | 81 | func runStop(curveadm *cli.CurveAdm, options stopOptions) error { 82 | // 1) generate stop playbook 83 | pb, err := genStopPlaybook(curveadm, options) 84 | if err != nil { 85 | return err 86 | } 87 | 88 | // 2) run playground 89 | err = pb.Run() 90 | if err != nil { 91 | return err 92 | } 93 | 94 | // 3) print success prompt 95 | curveadm.WriteOutln("") 96 | curveadm.WriteOutln(color.GreenString("Stop target daemon on %s success ^_^"), 97 | options.host) 98 | return nil 99 | } 100 | -------------------------------------------------------------------------------- /cli/curveadm.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package cli 24 | 25 | import ( 26 | "fmt" 27 | "os" 28 | "time" 29 | 30 | "github.com/opencurve/curveadm/cli/cli" 31 | "github.com/opencurve/curveadm/cli/command" 32 | ) 33 | 34 | func Execute() { 35 | curveadm, err := cli.NewCurveAdm() 36 | if err != nil { 37 | fmt.Println(err) 38 | os.Exit(1) 39 | } 40 | 41 | yes, err := curveadm.Upgrade() 42 | if err != nil { 43 | os.Exit(1) 44 | } else if yes { 45 | os.Exit(0) 46 | } 47 | 48 | id := curveadm.PreAudit(time.Now(), os.Args[1:]) 49 | cmd := command.NewCurveAdmCommand(curveadm) 50 | err = cmd.Execute() 51 | curveadm.PostAudit(id, err) 52 | if err != nil { 53 | os.Exit(1) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /cmd/curveadm/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package main 24 | 25 | import ( 26 | "github.com/opencurve/curveadm/cli" 27 | ) 28 | 29 | func main() { 30 | cli.Execute() 31 | } 32 | -------------------------------------------------------------------------------- /configs/bs/cluster/client.yaml: -------------------------------------------------------------------------------- 1 | kind: curvebs 2 | user: curve 3 | host: 10.0.1.1 4 | ssh_port: 22 5 | private_key_file: /home/curve/.ssh/id_rsa 6 | container_image: opencurvedocker/curvebs:v1.2 7 | mds.listen.addr: 10.0.1.1:6700,10.0.1.2:6700,10.0.1.3:6700 8 | log_dir: /home/curve/curvebs/logs/client 9 | -------------------------------------------------------------------------------- /configs/bs/cluster/format.yaml: -------------------------------------------------------------------------------- 1 | host: 2 | - server-host1 3 | - server-host2 4 | - server-host3 5 | disk: 6 | - /dev/sda:/data/chunkserver0:90 # device:mount_path:format_percent% 7 | - /dev/sdb:/data/chunkserver1:90 8 | - /dev/sdc:/data/chunkserver2:90 9 | -------------------------------------------------------------------------------- /configs/bs/cluster/monitor.yaml: -------------------------------------------------------------------------------- 1 | host: server-host 2 | 3 | node_exporter: 4 | container_image: prom/node-exporter:latest 5 | listen_port: 9100 6 | 7 | prometheus: 8 | container_image: prom/prometheus:latest 9 | data_dir: /tmp/monitor/prometheus 10 | listen_port: 9090 11 | retention.time: 7d 12 | retention.size: 256GB 13 | 14 | grafana: 15 | container_image: grafana/grafana:latest 16 | data_dir: /tmp/monitor/grafana 17 | listen_port: 3000 18 | username: admin 19 | password: curve 20 | -------------------------------------------------------------------------------- /configs/bs/cluster/scale-out.yaml: -------------------------------------------------------------------------------- 1 | chunkserver_services: 2 | deploy: 3 | - host: ${machine1} 4 | instances: 20 # 请注意这里的replica不代表存储池的副本数,而是节点上同类进程的数量,比如这里指的是chunkserver进程的数量,也就是配置的磁盘数,相关问题可以参考:https://github.com/opencurve/curveadm/issues/146 5 | config: 6 | - host: ${machine2} 7 | instances: 20 8 | - host: ${machine3} 9 | instances: 20 10 | 11 | -------------------------------------------------------------------------------- /configs/bs/cluster/topology.yaml: -------------------------------------------------------------------------------- 1 | kind: curvebs 2 | global: 3 | container_image: opencurvedocker/curvebs:v1.2.6 4 | log_dir: ${home}/logs/${service_role}${service_replicas_sequence} 5 | data_dir: ${home}/data/${service_role}${service_replicas_sequence} 6 | s3.nos_address: <> 7 | s3.snapshot_bucket_name: <> 8 | s3.ak: <> 9 | s3.sk: <> 10 | variable: 11 | home: /tmp 12 | machine1: server-host1 13 | machine2: server-host2 14 | machine3: server-host3 15 | 16 | etcd_services: 17 | config: 18 | listen.ip: ${service_host} 19 | listen.port: 2380 20 | listen.client_port: 2379 21 | deploy: 22 | - host: ${machine1} 23 | - host: ${machine2} 24 | - host: ${machine3} 25 | 26 | mds_services: 27 | config: 28 | listen.ip: ${service_host} 29 | listen.port: 6666 30 | listen.dummy_port: 6667 31 | deploy: 32 | - host: ${machine1} 33 | - host: ${machine2} 34 | - host: ${machine3} 35 | 36 | chunkserver_services: 37 | config: 38 | listen.ip: ${service_host} 39 | listen.port: 82${format_instances_sequence} # 8200,8201,8202 40 | data_dir: /data/chunkserver${service_instances_sequence} # /data/chunkserver0, /data/chunksever1 41 | copysets: 100 42 | deploy: 43 | - host: ${machine1} 44 | instances: 3 45 | - host: ${machine2} 46 | instances: 3 47 | - host: ${machine3} 48 | instances: 3 49 | 50 | snapshotclone_services: 51 | config: 52 | listen.ip: ${service_host} 53 | listen.port: 5555 54 | listen.dummy_port: 8081 55 | listen.proxy_port: 8080 56 | deploy: 57 | - host: ${machine1} 58 | - host: ${machine2} 59 | - host: ${machine3} 60 | -------------------------------------------------------------------------------- /configs/bs/stand-alone/client.yaml: -------------------------------------------------------------------------------- 1 | kind: curvebs 2 | user: curve 3 | host: 10.0.1.1 4 | ssh_port: 22 5 | private_key_file: /home/curve/.ssh/id_rsa 6 | container_image: opencurvedocker/curvebs:v1.2 7 | mds.listen.addr: 10.0.1.1:16700,10.0.1.1:26700,10.0.1.1:36700 8 | log_dir: /home/curve/curvebs/logs/client 9 | -------------------------------------------------------------------------------- /configs/bs/stand-alone/format.yaml: -------------------------------------------------------------------------------- 1 | host: 2 | - server-host1 3 | disk: 4 | - /dev/sda:/data/chunkserver0:90 # device:mount_path:format_percent% 5 | - /dev/sdb:/data/chunkserver1:90 6 | - /dev/sdc:/data/chunkserver2:90 7 | -------------------------------------------------------------------------------- /configs/bs/stand-alone/topology.yaml: -------------------------------------------------------------------------------- 1 | kind: curvebs 2 | global: 3 | container_image: opencurvedocker/curvebs:v1.2.7-rc1_0ff8409 4 | log_dir: ${home}/logs/${service_role}${service_host_sequence} 5 | data_dir: ${home}/data/${service_role}${service_host_sequence} 6 | s3.nos_address: <> 7 | s3.snapshot_bucket_name: <> 8 | s3.ak: <> 9 | s3.sk: <> 10 | variable: 11 | home: /tmp 12 | target: server-host 13 | 14 | etcd_services: 15 | config: 16 | listen.ip: ${service_host} 17 | listen.port: 2380${service_host_sequence} 18 | listen.client_port: 2379${service_host_sequence} 19 | deploy: 20 | - host: ${target} 21 | - host: ${target} 22 | - host: ${target} 23 | 24 | mds_services: 25 | config: 26 | listen.ip: ${service_host} 27 | listen.port: 670${service_host_sequence} 28 | listen.dummy_port: 770${service_host_sequence} 29 | deploy: 30 | - host: ${target} 31 | - host: ${target} 32 | - host: ${target} 33 | 34 | chunkserver_services: 35 | config: 36 | listen.ip: ${service_host} 37 | listen.port: 820${service_host_sequence} # 8200,8201,8202 38 | data_dir: /data/chunkserver${service_host_sequence} # /data/chunkserver0, /data/chunksever1 39 | copysets: 100 40 | deploy: 41 | - host: ${target} 42 | - host: ${target} 43 | - host: ${target} 44 | 45 | snapshotclone_services: 46 | config: 47 | listen.ip: ${service_host} 48 | listen.port: 555${service_host_sequence} 49 | listen.dummy_port: 810${service_host_sequence} 50 | listen.proxy_port: 800${service_host_sequence} 51 | deploy: 52 | - host: ${target} 53 | - host: ${target} 54 | - host: ${target} -------------------------------------------------------------------------------- /configs/fs/cluster/client.yaml: -------------------------------------------------------------------------------- 1 | kind: curvefs 2 | container_image: quay.io/opencurve/curve/curvefs:v2.7.0-rc1_d8a1137 3 | mdsOpt.rpcRetryOpt.addrs: 10.0.1.1:6700,10.0.1.2:6700,10.0.1.3:6700 4 | log_dir: /home/curve/curvefs/logs/client 5 | 6 | ### if fstype is s3 7 | s3.ak: <> 8 | s3.sk: <> 9 | s3.endpoint: nos-eastchina1.126.net 10 | s3.bucket_name: curvefs 11 | 12 | ### if fstype is volume 13 | # curvebs cluster's mds ip and port 14 | curvebs.cluster: 10.0.10.1:6700,10.0.10.2:6700,10.0.10.3:6700 15 | # volume size in bytes 16 | volumeSize: 10737418240 17 | # volume name 18 | volumeName: /volume 19 | # user of volume 20 | volumeUser: user 21 | # password of volume 22 | # if not specified when create volume then leave it empty string '' 23 | volumePassword: password 24 | -------------------------------------------------------------------------------- /configs/fs/cluster/topology.yaml: -------------------------------------------------------------------------------- 1 | kind: curvefs 2 | global: 3 | report_usage: true 4 | data_dir: ${home}/curvefs/data/${service_role} 5 | log_dir: ${home}/curvefs/logs/${service_role} 6 | container_image: quay.io/opencurve/curve/curvefs:v2.7.0-rc1_d8a1137 7 | variable: 8 | home: /tmp 9 | machine1: server-host1 10 | machine2: serevr-host2 11 | machine3: server-host3 12 | 13 | etcd_services: 14 | config: 15 | listen.ip: ${service_host} 16 | listen.port: 2380 17 | listen.client_port: 2379 18 | deploy: 19 | - host: ${machine1} 20 | - host: ${machine2} 21 | - host: ${machine3} 22 | 23 | mds_services: 24 | config: 25 | listen.ip: ${service_host} 26 | listen.port: 6700 27 | listen.dummy_port: 7700 28 | deploy: 29 | - host: ${machine1} 30 | - host: ${machine2} 31 | - host: ${machine3} 32 | 33 | metaserver_services: 34 | config: 35 | listen.ip: ${service_host} 36 | listen.port: 6800 37 | listen.external_port: 7800 38 | global.enable_external_server: true 39 | metaserver.loglevel: 0 40 | # whether commit filesystem caches of raft wal to disk. 41 | # it should be true if you wants data NEVER lost, 42 | # of course, it will leads some performance skew. 43 | braft.raft_sync: false 44 | deploy: 45 | - host: ${machine1} 46 | - host: ${machine2} 47 | - host: ${machine3} 48 | config: 49 | metaserver.loglevel: 0 50 | -------------------------------------------------------------------------------- /configs/fs/stand-alone/client.yaml: -------------------------------------------------------------------------------- 1 | kind: curvefs 2 | container_image: quay.io/opencurve/curve/curvefs:v2.7.0-rc1_d8a1137 3 | mdsOpt.rpcRetryOpt.addrs: 10.0.1.1:6700,10.0.1.2:6700,10.0.1.3:6700 4 | log_dir: /home/curve/curvefs/logs/client 5 | 6 | ### if fstype is s3 7 | s3.ak: <> 8 | s3.sk: <> 9 | s3.endpoint: nos-eastchina1.126.net 10 | s3.bucket_name: curvefs 11 | 12 | ### if fstype is volume 13 | # curvebs cluster's mds ip and port 14 | curvebs.cluster: 10.0.10.1:6700,10.0.10.2:6700,10.0.10.3:6700 15 | # volume size in bytes 16 | volumeSize: 10737418240 17 | # volume name 18 | volumeName: /volume 19 | # user of volume 20 | volumeUser: user 21 | # password of volume 22 | # if not specified when create volume then leave it empty string '' 23 | volumePassword: password 24 | -------------------------------------------------------------------------------- /configs/fs/stand-alone/topology.yaml: -------------------------------------------------------------------------------- 1 | kind: curvefs 2 | global: 3 | report_usage: true 4 | data_dir: ${home}/curvefs/data/${service_role}${service_host_sequence} 5 | log_dir: ${home}/curvefs/logs/${service_role}${service_host_sequence} 6 | container_image: quay.io/opencurve/curve/curvefs:v2.7.0-rc1_d8a1137 7 | variable: 8 | home: /tmp 9 | target: server-host 10 | 11 | etcd_services: 12 | config: 13 | listen.ip: ${service_host} 14 | listen.port: 2380${service_host_sequence} # 23800,23801,23802 15 | listen.client_port: 2379${service_host_sequence} # 23790,23791,23792 16 | deploy: 17 | - host: ${target} 18 | - host: ${target} 19 | - host: ${target} 20 | 21 | mds_services: 22 | config: 23 | listen.ip: ${service_host} 24 | listen.port: 670${service_host_sequence} # 6700,6701,6702 25 | listen.dummy_port: 770${service_host_sequence} # 7700,7701,7702 26 | deploy: 27 | - host: ${target} 28 | - host: ${target} 29 | - host: ${target} 30 | 31 | metaserver_services: 32 | config: 33 | listen.ip: ${service_host} 34 | listen.port: 680${service_host_sequence} # 6800,6801,6802 35 | listen.external_port: 780${service_host_sequence} # 7800,7801,7802 36 | global.enable_external_server: true 37 | metaserver.loglevel: 0 38 | # whether commit filesystem caches of raft wal to disk. 39 | # it should be true iff you wants data NEVER lost, 40 | # of course, it will leads some performance skew. 41 | braft.raft_sync: false 42 | deploy: 43 | - host: ${target} 44 | - host: ${target} 45 | - host: ${target} 46 | config: 47 | metaserver.loglevel: 0 48 | -------------------------------------------------------------------------------- /internal/build/build.go: -------------------------------------------------------------------------------- 1 | // +build debug 2 | 3 | package build 4 | 5 | const DEBUG_MODLE = true 6 | -------------------------------------------------------------------------------- /internal/build/debug.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-30 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package build 26 | 27 | import ( 28 | "encoding/json" 29 | "fmt" 30 | "os" 31 | ) 32 | 33 | const ( 34 | DEBUG_CURVEADM_CONFIGURE = "DEBUG_CURVEADM_CONFIGURE" 35 | DEBUG_HOSTS = "DEBUG_HOSTS" 36 | DEBUG_SMART_CONFIGS = "DEBUG_SMART_CONFIGS" 37 | DEBUG_TOPOLOGY = "DEBUG_TOPOLOGY" 38 | DEBUG_TOOL = "DEBUG_TOOL" 39 | DEBUG_CLUSTER = "DEBUG_CLUSTER" 40 | DEBUG_CREATE_POOL = "DEBUG_CREATE_POOL" 41 | DEBUG_CLIENT_CONFIGURE = "DEBUG_CLIENT_CONFIGURE" 42 | DEBUG_MONITOR_CONFIGURE = "DEBUG_MONITOR_CONFIGURE" 43 | ) 44 | 45 | type Field struct { 46 | Key string `json:"key"` 47 | Value interface{} `json:"value"` 48 | } 49 | 50 | func DEBUG(name string, a ...interface{}) { 51 | if !DEBUG_MODLE || os.Getenv(name) != "1" { 52 | return 53 | } 54 | 55 | fmt.Printf("%s:\n", name) 56 | for _, v := range a { 57 | bytes, _ := json.MarshalIndent(v, "", " ") 58 | fmt.Println(string(bytes)) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /internal/build/release.go: -------------------------------------------------------------------------------- 1 | // +build !debug 2 | 3 | package build 4 | 5 | const DEBUG_MODLE = false 6 | -------------------------------------------------------------------------------- /internal/configure/hosts/hc_item.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-08-01 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package hosts 26 | 27 | import ( 28 | "fmt" 29 | 30 | comm "github.com/opencurve/curveadm/internal/configure/common" 31 | "github.com/opencurve/curveadm/internal/utils" 32 | ) 33 | 34 | const ( 35 | DEFAULT_SSH_PORT = 22 36 | ) 37 | 38 | var ( 39 | itemset = comm.NewItemSet() 40 | 41 | CONFIG_HOST = itemset.Insert( 42 | "host", 43 | comm.REQUIRE_STRING, 44 | false, 45 | nil, 46 | ) 47 | 48 | CONFIG_HOSTNAME = itemset.Insert( 49 | "hostname", 50 | comm.REQUIRE_STRING, 51 | false, 52 | nil, 53 | ) 54 | 55 | CONFIG_SSH_HOSTNAME = itemset.Insert( 56 | "ssh_hostname", 57 | comm.REQUIRE_STRING, 58 | false, 59 | nil, 60 | ) 61 | 62 | CONFIG_USER = itemset.Insert( 63 | "user", 64 | comm.REQUIRE_STRING, 65 | false, 66 | func(hc *HostConfig) interface{} { 67 | return utils.GetCurrentUser() 68 | }, 69 | ) 70 | 71 | CONFIG_SSH_PORT = itemset.Insert( 72 | "ssh_port", 73 | comm.REQUIRE_POSITIVE_INTEGER, 74 | false, 75 | DEFAULT_SSH_PORT, 76 | ) 77 | 78 | CONFIG_PRIVATE_CONFIG_FILE = itemset.Insert( 79 | "private_key_file", 80 | comm.REQUIRE_STRING, 81 | false, 82 | func(hc *HostConfig) interface{} { 83 | return fmt.Sprintf("%s/.ssh/id_rsa", utils.GetCurrentHomeDir()) 84 | }, 85 | ) 86 | 87 | CONFIG_FORWARD_AGENT = itemset.Insert( 88 | "forward_agent", 89 | comm.REQUIRE_BOOL, 90 | false, 91 | false, 92 | ) 93 | 94 | CONFIG_BECOME_USER = itemset.Insert( 95 | "become_user", 96 | comm.REQUIRE_STRING, 97 | false, 98 | nil, 99 | ) 100 | ) 101 | -------------------------------------------------------------------------------- /internal/configure/os.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-08 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package configure 24 | 25 | import "fmt" 26 | 27 | const ( 28 | PATH_FSTAB = "/etc/fstab" 29 | 30 | FORMAT_PATH_DEVICE_SCHEDULER = "/sys/block/%s/queue/scheduler" 31 | FORMAT_PATH_DEVICE_ROTATIONAL = "/sys/block/%s/queue/rotational" 32 | ) 33 | 34 | func GetFSTabPath() string { return PATH_FSTAB } 35 | 36 | func GetDeviceShedulerPath(device string) string { 37 | return fmt.Sprintf(FORMAT_PATH_DEVICE_SCHEDULER, device) 38 | } 39 | 40 | func GetDeviceRotationalPath(device string) string { 41 | return fmt.Sprintf(FORMAT_PATH_DEVICE_ROTATIONAL, device) 42 | } 43 | -------------------------------------------------------------------------------- /internal/configure/os/os.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-08 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package os 26 | 27 | const ( 28 | PATH_FSTAB = "/etc/fstab" 29 | PATH_OS_RELEASE = "/etc/os-release" 30 | MAX_PORT = 65535 31 | ) 32 | 33 | func GetFSTabPath() string { return PATH_FSTAB } 34 | func GetMaxPortNum() int { return MAX_PORT } 35 | func GetOSReleasePath() string { return PATH_OS_RELEASE } 36 | -------------------------------------------------------------------------------- /internal/configure/playground.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-06-24 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package configure 24 | 25 | import ( 26 | "github.com/opencurve/curveadm/internal/configure/topology" 27 | ) 28 | 29 | const ( 30 | DEFAULT_CURVEBS_CONTAINER_IMAGE = "opencurvedocker/curvebs-playground:v1.2" 31 | DEFAULT_CURVEFS_CONTAINER_IMAGE = "opencurvedocker/curvefs-playground:v2.3" 32 | ) 33 | 34 | type ( 35 | PlaygroundConfig struct { 36 | Kind string 37 | Name string 38 | ContainerImage string 39 | Mountpoint string 40 | 41 | DeployConfigs []*topology.DeployConfig 42 | ClientConfig *ClientConfig 43 | } 44 | ) 45 | 46 | func (cfg *PlaygroundConfig) GetKind() string { return cfg.Kind } 47 | func (cfg *PlaygroundConfig) GetName() string { return cfg.Name } 48 | func (cfg *PlaygroundConfig) GetMointpoint() string { return cfg.Mountpoint } 49 | func (cfg *PlaygroundConfig) GetDeployConfigs() []*topology.DeployConfig { return cfg.DeployConfigs } 50 | func (cfg *PlaygroundConfig) GetClientConfig() *ClientConfig { return cfg.ClientConfig } 51 | 52 | func (cfg *PlaygroundConfig) GetContainIamge() string { 53 | if len(cfg.ContainerImage) > 0 { 54 | return cfg.ContainerImage 55 | } else if cfg.Kind == topology.KIND_CURVEBS { 56 | return DEFAULT_CURVEBS_CONTAINER_IMAGE 57 | } 58 | return DEFAULT_CURVEFS_CONTAINER_IMAGE 59 | } 60 | -------------------------------------------------------------------------------- /internal/configure/topology/context.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-08-03 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package topology 26 | 27 | type Context struct { 28 | m map[string]string 29 | } 30 | 31 | func NewContext() *Context { 32 | return &Context{m: map[string]string{}} 33 | } 34 | 35 | func (ctx *Context) Add(host, hostname string) { 36 | ctx.m[host] = hostname 37 | } 38 | 39 | func (ctx *Context) Lookup(host string) string { 40 | return ctx.m[host] 41 | } 42 | -------------------------------------------------------------------------------- /internal/playbook/config.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-27 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package playbook 24 | -------------------------------------------------------------------------------- /internal/playbook/playbook.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-27 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package playbook 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/tasks" 30 | ) 31 | 32 | /* 33 | * playbook 34 | * ├── tasks1 (e.g.: pull image) 35 | * ├── tasks2 (e.g.: create container) 36 | * ├── ... 37 | * └── tasksn (e.g.: start container) 38 | * ├── task1 (e.g.: start container in host1) 39 | * ├── task2 (e.g.: start container in host2) 40 | * ├── ... 41 | * └── taskn (e.g.: start container in host3) 42 | * ├── step1 (e.g: start container) 43 | * ├── step2 (e.g: check container status) 44 | * ├── ... 45 | * └── stepn (e.g: start crotab iff status is ok) 46 | * 47 | * tasks are made up of many same type tasks which only executed in different hosts or roles 48 | */ 49 | type ( 50 | PlaybookStep struct { 51 | Name string 52 | Type int 53 | Configs interface{} 54 | Options map[string]interface{} 55 | tasks.ExecOptions 56 | } 57 | 58 | Playbook struct { 59 | curveadm *cli.CurveAdm 60 | steps []*PlaybookStep 61 | postSteps []*PlaybookStep 62 | } 63 | 64 | ExecOptions = tasks.ExecOptions 65 | ) 66 | 67 | func NewPlaybook(curveadm *cli.CurveAdm) *Playbook { 68 | return &Playbook{ 69 | curveadm: curveadm, 70 | steps: []*PlaybookStep{}, 71 | } 72 | } 73 | 74 | func (p *Playbook) AddStep(s *PlaybookStep) { 75 | p.steps = append(p.steps, s) 76 | } 77 | 78 | func (p *Playbook) AddPostStep(s *PlaybookStep) { 79 | p.postSteps = append(p.postSteps, s) 80 | } 81 | 82 | func (p *Playbook) run(steps []*PlaybookStep) error { 83 | for i, step := range steps { 84 | tasks, err := p.createTasks(step) 85 | if err != nil { 86 | return err 87 | } 88 | 89 | err = tasks.Execute(step.ExecOptions) 90 | if err != nil { 91 | return err 92 | } 93 | 94 | isLast := (i == len(steps)-1) 95 | if !step.ExecOptions.SilentMainBar && !isLast { 96 | p.curveadm.WriteOutln("") 97 | } 98 | } 99 | return nil 100 | } 101 | 102 | func (p *Playbook) Run() error { 103 | defer func() { 104 | if len(p.postSteps) == 0 { 105 | return 106 | } 107 | p.curveadm.WriteOutln("") 108 | p.run(p.postSteps) 109 | }() 110 | 111 | return p.run(p.steps) 112 | } 113 | -------------------------------------------------------------------------------- /internal/playbook/tasks/monitor.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-01-07 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package tasks 24 | 25 | import ( 26 | "sync" 27 | 28 | "github.com/opencurve/curveadm/internal/task/task" 29 | ) 30 | 31 | 32 | const ( 33 | STATUS_OK = iota 34 | STATUS_SKIP 35 | STATUS_ERROR 36 | ) 37 | 38 | type monitor struct { 39 | err error 40 | result map[int][]error // sub task result (key: progress bar id) 41 | mutex sync.Mutex 42 | } 43 | 44 | func newMonitor() *monitor { 45 | return &monitor{ 46 | err: nil, 47 | result: map[int][]error{}, 48 | mutex: sync.Mutex{}, 49 | } 50 | } 51 | 52 | func (m *monitor) error() error { 53 | return m.err 54 | } 55 | 56 | // return number of {success, skip, error} 57 | func (m *monitor) sum(bid int) (int, int, int) { 58 | nsucc, nskip, nerr := 0, 0, 0 59 | for _, err := range m.result[bid] { 60 | if err == nil { 61 | nsucc++ 62 | } else if err == task.ERR_SKIP_TASK { 63 | nskip++ 64 | } else { 65 | nerr++ 66 | } 67 | } 68 | return nsucc, nskip, nerr 69 | } 70 | 71 | func (m *monitor) set(bid int, err error) { 72 | m.mutex.Lock() 73 | defer m.mutex.Unlock() 74 | m.result[bid] = append(m.result[bid], err) 75 | if err != nil && err != task.ERR_SKIP_TASK { 76 | m.err = err 77 | } 78 | } 79 | 80 | func (m *monitor) get(bid int) int { 81 | m.mutex.Lock() 82 | defer m.mutex.Unlock() 83 | nsucc, nskip, nerr := m.sum(bid) 84 | total := nsucc + nskip + nerr 85 | if nerr != 0 { 86 | return STATUS_ERROR 87 | } else if nskip == total { 88 | return STATUS_SKIP 89 | } 90 | // success all or part of skip 91 | return STATUS_OK 92 | } 93 | -------------------------------------------------------------------------------- /internal/storage/driver/driver.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the Licensele(). 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2023-05-24 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package driver 24 | 25 | type IQueryResult interface { 26 | Next() bool 27 | Scan(dest ...any) error 28 | Close() error 29 | } 30 | 31 | type IWriteResult interface { 32 | LastInsertId() (int64, error) 33 | } 34 | 35 | type IDataBaseDriver interface { 36 | Open(dbUrl string) error 37 | Close() error 38 | Query(query string, args ...any) (IQueryResult, error) 39 | Write(query string, args ...any) (IWriteResult, error) 40 | } 41 | -------------------------------------------------------------------------------- /internal/storage/driver/rqlite.go: -------------------------------------------------------------------------------- 1 | package driver 2 | 3 | import ( 4 | "strings" 5 | "sync" 6 | 7 | "github.com/rqlite/gorqlite" 8 | rqlite "github.com/rqlite/gorqlite" 9 | ) 10 | 11 | type RQLiteDB struct { 12 | conn *rqlite.Connection 13 | sync.Mutex 14 | } 15 | 16 | type QueryResult struct { 17 | result rqlite.QueryResult 18 | } 19 | 20 | type WriteResult struct { 21 | result rqlite.WriteResult 22 | } 23 | 24 | var ( 25 | _ IDataBaseDriver = (*RQLiteDB)(nil) 26 | _ IQueryResult = (*QueryResult)(nil) 27 | _ IWriteResult = (*WriteResult)(nil) 28 | ) 29 | 30 | func NewRQLiteDB() *RQLiteDB { 31 | return &RQLiteDB{} 32 | } 33 | 34 | func (db *RQLiteDB) Open(url string) error { 35 | connURL := "http://" + strings.TrimPrefix(url, "rqlite://") 36 | conn, err := gorqlite.Open(connURL) 37 | if err != nil { 38 | return err 39 | } 40 | db.conn = conn 41 | return nil 42 | } 43 | 44 | func (db *RQLiteDB) Close() error { 45 | return nil 46 | } 47 | 48 | func (result *QueryResult) Next() bool { 49 | return result.result.Next() 50 | } 51 | 52 | func (result *QueryResult) Scan(dest ...any) error { 53 | return result.result.Scan(dest...) 54 | } 55 | 56 | func (result *QueryResult) Close() error { 57 | return nil 58 | } 59 | 60 | func (db *RQLiteDB) Query(query string, args ...any) (IQueryResult, error) { 61 | db.Lock() 62 | defer db.Unlock() 63 | 64 | result, err := db.conn.QueryOneParameterized( 65 | rqlite.ParameterizedStatement{ 66 | Query: query, 67 | Arguments: append([]interface{}{}, args...), 68 | }, 69 | ) 70 | return &QueryResult{result: result}, err 71 | } 72 | 73 | func (result *WriteResult) LastInsertId() (int64, error) { 74 | return result.result.LastInsertID, nil 75 | } 76 | 77 | func (db *RQLiteDB) Write(query string, args ...any) (IWriteResult, error) { 78 | db.Lock() 79 | defer db.Unlock() 80 | 81 | result, err := db.conn.WriteOneParameterized( 82 | rqlite.ParameterizedStatement{ 83 | Query: query, 84 | Arguments: append([]interface{}{}, args...), 85 | }, 86 | ) 87 | return &WriteResult{result: result}, err 88 | } 89 | -------------------------------------------------------------------------------- /internal/storage/driver/sqlite.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the Licensele(). 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2023-05-24 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package driver 24 | 25 | import ( 26 | "database/sql" 27 | "strings" 28 | "sync" 29 | 30 | _ "github.com/mattn/go-sqlite3" 31 | ) 32 | 33 | type SQLiteDB struct { 34 | db *sql.DB 35 | sync.Mutex 36 | } 37 | 38 | type Rows struct { 39 | rows *sql.Rows 40 | } 41 | 42 | type Result struct { 43 | result sql.Result 44 | } 45 | 46 | var ( 47 | _ IDataBaseDriver = (*SQLiteDB)(nil) 48 | _ IQueryResult = (*Rows)(nil) 49 | _ IWriteResult = (*Result)(nil) 50 | ) 51 | 52 | func NewSQLiteDB() *SQLiteDB { 53 | return &SQLiteDB{} 54 | } 55 | 56 | func (db *SQLiteDB) Open(url string) error { 57 | var err error 58 | dataSourceName := strings.TrimPrefix(url, "sqlite://") 59 | db.db, err = sql.Open("sqlite3", dataSourceName) 60 | return err 61 | } 62 | 63 | func (db *SQLiteDB) Close() error { 64 | return db.db.Close() 65 | } 66 | 67 | func (result *Rows) Next() bool { 68 | return result.rows.Next() 69 | } 70 | 71 | func (result *Rows) Scan(dest ...any) error { 72 | return result.rows.Scan(dest...) 73 | } 74 | 75 | func (result *Rows) Close() error { 76 | return result.rows.Close() 77 | } 78 | 79 | func (db *SQLiteDB) Query(query string, args ...any) (IQueryResult, error) { 80 | db.Lock() 81 | defer db.Unlock() 82 | 83 | rows, err := db.db.Query(query, args...) 84 | if err != nil { 85 | return nil, err 86 | } 87 | return &Rows{rows: rows}, nil 88 | } 89 | 90 | func (result *Result) LastInsertId() (int64, error) { 91 | return result.result.LastInsertId() 92 | } 93 | 94 | func (db *SQLiteDB) Write(query string, args ...any) (IWriteResult, error) { 95 | db.Lock() 96 | defer db.Unlock() 97 | 98 | stmt, err := db.db.Prepare(query) 99 | if err != nil { 100 | return nil, err 101 | } 102 | 103 | result, err := stmt.Exec(args...) 104 | return &Result{result: result}, err 105 | } 106 | -------------------------------------------------------------------------------- /internal/task/context/context.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package context 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/pkg/module" 29 | ) 30 | 31 | type Context struct { 32 | sshClient *module.SSHClient 33 | module *module.Module 34 | register *Register 35 | } 36 | 37 | func NewContext(sshClient *module.SSHClient) (*Context, error) { 38 | return &Context{ 39 | sshClient: sshClient, 40 | module: module.NewModule(sshClient), 41 | register: NewRegister(), 42 | }, nil 43 | } 44 | 45 | func (ctx *Context) Close() { 46 | if ctx.sshClient != nil { 47 | ctx.sshClient.Client().Close() 48 | } 49 | } 50 | 51 | func (ctx *Context) SSHClient() *module.SSHClient { 52 | return ctx.sshClient 53 | } 54 | 55 | func (ctx *Context) Module() *module.Module { 56 | return ctx.module 57 | } 58 | 59 | func (ctx *Context) Register() *Register { 60 | return ctx.register 61 | } 62 | -------------------------------------------------------------------------------- /internal/task/context/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-12-12 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package context 26 | 27 | type Register struct { 28 | m map[string]interface{} 29 | } 30 | 31 | func NewRegister() *Register { 32 | return &Register{map[string]interface{}{}} 33 | } 34 | 35 | func (r *Register) Set(key string, value interface{}) { 36 | r.m[key] = value 37 | } 38 | 39 | func (r *Register) Get(key string) interface{} { 40 | return r.m[key] 41 | } 42 | -------------------------------------------------------------------------------- /internal/task/scripts/enable_etcd_auth.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: Curveadm 19 | * Created Date: 2023-08-02 20 | * Author: wanghai (SeanHai) 21 | */ 22 | 23 | package scripts 24 | 25 | var ENABLE_ETCD_AUTH = ` 26 | #!/usr/bin/env bash 27 | 28 | if [ $# -ne 3 ]; then 29 | echo "Usage: $0 endpoints username password" 30 | exit 1 31 | fi 32 | 33 | endpoints=$1 34 | username=$2 35 | password=$3 36 | root_user=root 37 | 38 | # create root user 39 | etcdctl --endpoints=${endpoints} user add ${root_user}:${password} && \ 40 | etcdctl --endpoints=${endpoints} user grant-role ${root_user} root || exit 1 41 | 42 | # create user if not root 43 | if [ "${username}" != "${root_user}" ]; then 44 | etcdctl --endpoints=${endpoints} user add ${username}:${password} && \ 45 | etcdctl --endpoints=${endpoints} user grant-role ${username} root || exit 1 46 | fi 47 | 48 | # enable auth 49 | etcdctl --endpoints=${endpoints} auth enable --user=${root_user}:${password} || exit 1 50 | ` 51 | -------------------------------------------------------------------------------- /internal/task/scripts/monitor.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: Curveadm 19 | * Created Date: 2023-04-23 20 | * Author: wanghai (SeanHai) 21 | */ 22 | 23 | package scripts 24 | 25 | var PROMETHEUS_YML = ` 26 | global: 27 | scrape_interval: 3s 28 | evaluation_interval: 15s 29 | 30 | scrape_configs: 31 | - job_name: 'prometheus' 32 | static_configs: 33 | - targets: ['localhost:%d'] 34 | 35 | - job_name: 'curve_metrics' 36 | file_sd_configs: 37 | - files: ['target.json'] 38 | 39 | - job_name: 'node' 40 | static_configs: 41 | - targets: %s 42 | ` 43 | 44 | var GRAFANA_DATA_SOURCE = ` 45 | datasources: 46 | - name: 'Prometheus' 47 | type: 'prometheus' 48 | access: 'proxy' 49 | org_id: 1 50 | url: 'http://%s:%d' 51 | is_default: true 52 | version: 1 53 | editable: true 54 | ` -------------------------------------------------------------------------------- /internal/task/scripts/script.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-11-25 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package scripts 24 | 25 | import ( 26 | _ "embed" 27 | ) 28 | 29 | const ( 30 | STATUS_OK = "CURVEADM_OK" 31 | STATUS_FAIL = "CURVEADM_FAIL" 32 | STATUS_TIMEOUT = "CURVEADM_TIMEOUT" 33 | ) 34 | 35 | var ( 36 | // Common 37 | 38 | //go:embed shell/wait.sh 39 | WAIT string 40 | //go:embed shell/report.sh 41 | REPORT string 42 | 43 | // CurveBS 44 | 45 | //go:embed shell/format.sh 46 | FORMAT string 47 | //go:embed shell/wait_chunkserver.sh 48 | WAIT_CHUNKSERVERS string 49 | //go:embed shell/start_nginx.sh 50 | START_NGINX string 51 | //go:embed shell/create_volume.sh 52 | CREATE_VOLUME string 53 | //go:embed shell/map.sh 54 | MAP string 55 | //go:embed shell/target.sh 56 | TARGET string 57 | //go:embed shell/recycle.sh 58 | RECYCLE string 59 | 60 | // CurveFS 61 | 62 | //go:embed shell/create_fs.sh 63 | CREATE_FS string 64 | ) 65 | -------------------------------------------------------------------------------- /internal/task/scripts/shell/create_fs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: create_fs USER VOLUME SIZE 4 | # Example: create_fs curve test 10 5 | # Created Date: 2022-01-04 6 | # Author: chengyi01 7 | 8 | 9 | g_curvefs_tool="curvefs_tool" 10 | g_curvefs_tool_operator="create-fs" 11 | g_rpc_timeout_ms="-rpcTimeoutMs=10000" 12 | g_fsname="-fsName=" 13 | g_fstype="-fsType=" 14 | g_entrypoint="/entrypoint.sh" 15 | 16 | function createfs() { 17 | g_fsname=$g_fsname$1 18 | g_fstype=$g_fstype$2 19 | 20 | $g_curvefs_tool $g_curvefs_tool_operator "$g_fsname" "$g_fstype" $g_rpc_timeout_ms 21 | } 22 | 23 | createfs "$@" 24 | 25 | ret=$? 26 | if [ $ret -eq 0 ]; then 27 | $g_entrypoint "$@" 28 | ret=$? 29 | exit $ret 30 | else 31 | echo "CREATEFS FAILED" 32 | exit 1 33 | fi 34 | -------------------------------------------------------------------------------- /internal/task/scripts/shell/create_volume.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: create_volume USER VOLUME SIZE 4 | # Example: create_volume curve test 10 5 | # Created Date: 2022-07-31 6 | # Author: Jingli Chen (Wine93) 7 | 8 | 9 | g_user=$1 10 | g_volume=$2 11 | g_size=$3 12 | g_poolset=$4 13 | g_create_opts=( 14 | "-userName=$g_user" 15 | "-fileName=$g_volume" 16 | -fileLength="$g_size" 17 | ) 18 | if [ -n "$g_poolset" ]; then 19 | g_create_opts+=("-poolset=$g_poolset") 20 | fi 21 | 22 | output=$(curve_ops_tool create "${g_create_opts[@]}") 23 | if [ "$?" -ne 0 ]; then 24 | if [ "$output" = "CreateFile fail with errCode: kFileExists" ]; then 25 | echo "EXIST" 26 | else 27 | echo "FAILED" 28 | fi 29 | else 30 | echo "SUCCESS" 31 | fi 32 | -------------------------------------------------------------------------------- /internal/task/scripts/shell/format.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Created Date: 2021-12-27 4 | # Author: Jingli Chen (Wine93) 5 | 6 | 7 | binary=$1 8 | percent=$2 9 | chunkfile_size=$3 10 | chunkfile_pool_dir=$4 11 | chunkfile_pool_meta_path=$5 12 | chunkfile_block_size=$6 13 | 14 | mkdir -p $chunkfile_pool_dir 15 | $binary \ 16 | -allocatePercent=$percent \ 17 | -fileSize=$chunkfile_size \ 18 | -filePoolDir=$chunkfile_pool_dir \ 19 | -filePoolMetaPath=$chunkfile_pool_meta_path \ 20 | -fileSystemPath=$chunkfile_pool_dir \ 21 | -blockSize=$chunkfile_block_size \ 22 | -undefok blockSize 23 | -------------------------------------------------------------------------------- /internal/task/scripts/shell/map.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: map USER VOLUME CREATE SIZE 4 | # Example: map curve test true 10 5 | # Created Date: 2022-01-10 6 | # Author: Jingli Chen (Wine93) 7 | 8 | 9 | g_user=$1 10 | g_volume=$2 11 | g_options=$3 12 | g_stderr=/tmp/__curveadm_map__ 13 | 14 | mkdir -p /curvebs/nebd/data/lock 15 | touch /etc/curve/curvetab 16 | curve-nbd map --nbds_max=16 ${g_options} cbd:pool/${g_volume}_${g_user}_ > ${g_stderr} 2>&1 17 | if [ $? -ne 0 ]; then 18 | cat ${g_stderr} 19 | exit 1 20 | else 21 | echo "SUCCESS" 22 | fi 23 | -------------------------------------------------------------------------------- /internal/task/scripts/shell/recycle.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: recycle SOURCE DESTINATION SIZE 4 | # Example: recycle '/data/chunkserver0/copysets /data/chunkserver0/recycler' /data/chunkserver0/chunkfilepool 16781312 5 | # Created Date: 2022-01-13 6 | # Author: Jingli Chen (Wine93) 7 | 8 | 9 | g_source=$1 10 | g_dest=$2 11 | g_size=$3 12 | chunkid=$(ls -vr ${g_dest} | head -n 1) 13 | chunkid=${chunkid%.clean} 14 | for file in $(find $g_source -type f -size ${g_size}c -printf '%p\n'); do 15 | chunkid=$((chunkid+1)) 16 | mv $file $g_dest/$chunkid 17 | done 18 | -------------------------------------------------------------------------------- /internal/task/scripts/shell/report.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: report KIND UUID ROLE 4 | # Example: report curvebs abcdef01234567890 metaserver 5 | # Created Date: 2021-12-06 6 | # Author: Jingli Chen (Wine93) 7 | 8 | 9 | function rematch() { 10 | local s=$1 regex=$2 11 | if [[ $s =~ $regex ]]; then 12 | echo "${BASH_REMATCH[1]}" 13 | fi 14 | } 15 | 16 | function fs_usage() { 17 | curvefs_tool usage-metadata 2>/dev/null | awk 'BEGIN { 18 | BYTES["KB"] = 1024 19 | BYTES["MB"] = BYTES["KB"] * 1024 20 | BYTES["GB"] = BYTES["MB"] * 1024 21 | BYTES["TB"] = BYTES["GB"] * 1024 22 | } 23 | { 24 | if ($0 ~ /all cluster/) { 25 | printf ("%0.f", $8 * BYTES[$9]) 26 | } 27 | }' 28 | } 29 | 30 | function bs_usage() { 31 | local message=$(curve_ops_tool space | grep physical) 32 | local used=$(rematch "$message" "used = ([0-9]+)GB") 33 | echo $(($used*1024*1024*1024)) 34 | } 35 | 36 | [[ -z $(which curl) ]] && apt-get install -y curl 37 | g_kind=$1 38 | g_uuid=$2 39 | g_role=$3 40 | g_usage=$(([[ $g_kind = "curvebs" ]] && bs_usage) || fs_usage) 41 | curl -XPOST http://curveadm.aspirer.wang:19302/ \ 42 | -d "kind=$g_kind" \ 43 | -d "uuid=$g_uuid" \ 44 | -d "role=$g_role" \ 45 | -d "usage=$g_usage" 46 | -------------------------------------------------------------------------------- /internal/task/scripts/shell/start_nginx.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Created Date: 2022-08-09 4 | # Author: Jingli Chen (Wine93) 5 | 6 | 7 | g_listen="$1" 8 | 9 | cat << __EOF__ > /etc/nginx/nginx.conf 10 | daemon off; 11 | events { 12 | worker_connections 768; 13 | } 14 | http { 15 | server { 16 | $g_listen 17 | } 18 | } 19 | __EOF__ 20 | 21 | nginx 22 | -------------------------------------------------------------------------------- /internal/task/scripts/shell/target.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: target USER VOLUME CREATE SIZE 4 | # Example: target curve test true 10 5 | # See Also: https://linux.die.net/man/8/tgtadm 6 | # Created Date: 2022-02-08 7 | # Author: Jingli Chen (Wine93) 8 | 9 | 10 | g_user=$1 11 | g_volume=$2 12 | g_create=$3 13 | g_size=$4 14 | g_blocksize=$5 15 | g_tid=1 16 | g_image=cbd:pool/${g_volume}_${g_user}_ 17 | g_image_md5=$(echo -n ${g_image} | md5sum | awk '{ print $1 }') 18 | g_targetname=iqn.$(date +"%Y-%m").com.opencurve:curve.${g_image_md5} 19 | 20 | mkdir -p /curvebs/nebd/data/lock 21 | touch /etc/curve/curvetab 22 | 23 | if [ $g_create == "true" ]; then 24 | output=$(curve_ops_tool create -userName=$g_user -fileName=$g_volume -fileLength=$g_size) 25 | if [ $? -ne 0 ]; then 26 | if [ "$output" != "CreateFile fail with errCode: 101" ]; then 27 | exit 1 28 | fi 29 | fi 30 | fi 31 | for ((i=1;;i++)); do 32 | tgtadm --lld iscsi --mode target --op show --tid $i 1>/dev/null 2>&1 33 | if [ $? -ne 0 ]; then 34 | g_tid=$i 35 | break 36 | fi 37 | done 38 | 39 | tgtadm --lld iscsi \ 40 | --mode target \ 41 | --op new \ 42 | --tid ${g_tid} \ 43 | --targetname ${g_targetname} 44 | if [ $? -ne 0 ]; then 45 | echo "tgtadm target new failed" 46 | exit 1 47 | fi 48 | 49 | tgtadm --lld iscsi \ 50 | --mode logicalunit \ 51 | --op new \ 52 | --tid ${g_tid} \ 53 | --lun 1 \ 54 | --bstype curve \ 55 | --backing-store ${g_image} \ 56 | --blocksize ${g_blocksize} 57 | if [ $? -ne 0 ]; then 58 | echo "tgtadm logicalunit new failed" 59 | exit 1 60 | fi 61 | 62 | tgtadm --lld iscsi \ 63 | --mode logicalunit \ 64 | --op update \ 65 | --tid ${g_tid} \ 66 | --lun 1 \ 67 | --params vendor_id=NetEase,product_id=CurveVolume,product_rev=2.0 68 | if [ $? -ne 0 ]; then 69 | echo "tgtadm logicalunit update failed" 70 | exit 1 71 | fi 72 | 73 | tgtadm --lld iscsi \ 74 | --mode target \ 75 | --op bind \ 76 | --tid ${g_tid} \ 77 | -I ALL 78 | if [ $? -ne 0 ]; then 79 | echo "tgtadm target bind failed" 80 | exit 1 81 | fi 82 | -------------------------------------------------------------------------------- /internal/task/scripts/shell/wait.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: wait ADDR... 4 | # Example: wait 10.0.10.1:2379 10.0.10.2:2379 5 | # Created Date: 2021-11-25 6 | # Author: Jingli Chen (Wine93) 7 | 8 | 9 | [[ -z $(which curl) ]] && apt-get install -y curl 10 | wait=0 11 | while ((wait<20)) 12 | do 13 | for addr in "$@" 14 | do 15 | curl --connect-timeout 3 --max-time 10 $addr -Iso /dev/null 16 | if [ $? == 0 ]; then 17 | exit 0 18 | fi 19 | done 20 | sleep 0.5s 21 | wait=$(expr $wait + 1) 22 | done 23 | echo "wait timeout" 24 | exit 1 25 | -------------------------------------------------------------------------------- /internal/task/scripts/shell/wait_chunkserver.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: wait_chunkserver 3 4 | # Created Date: 2022-03-09 5 | # Author: aspirer 6 | 7 | 8 | g_total="$1" 9 | 10 | wait=0 11 | while ((wait<60)) 12 | do 13 | online=$(curve_ops_tool chunkserver-status | sed -nr 's/.*online = ([0-9]+).*/\1/p') 14 | if [[ $online -eq $g_total ]]; then 15 | exit 0 16 | fi 17 | 18 | sleep 0.5s 19 | wait=$((wait+1)) 20 | done 21 | 22 | echo "wait all chunkserver online timeout, total=$g_total, online=$online" 23 | exit 1 24 | -------------------------------------------------------------------------------- /internal/task/step/common.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-26 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package step 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/internal/errno" 29 | "github.com/opencurve/curveadm/internal/task/context" 30 | "github.com/opencurve/curveadm/internal/utils" 31 | "github.com/opencurve/curveadm/pkg/module" 32 | ) 33 | 34 | type ( 35 | LambdaType func(ctx *context.Context) error 36 | 37 | Lambda struct { 38 | Lambda LambdaType 39 | } 40 | ) 41 | 42 | func (s *Lambda) Execute(ctx *context.Context) error { 43 | return s.Lambda(ctx) 44 | } 45 | 46 | func PostHandle(Success *bool, Out *string, out string, err error, ec *errno.ErrorCode) error { 47 | if Out != nil { 48 | *Out = utils.TrimSuffixRepeat(out, "\n") 49 | } 50 | 51 | if Success != nil { // handle error by user 52 | *Success = (err == nil) 53 | return nil 54 | } else if err == nil { // execute success 55 | return nil 56 | } 57 | 58 | // execute timed out 59 | if _, ok := err.(*module.TimeoutError); ok { 60 | return errno.ERR_EXECUTE_COMMAND_TIMED_OUT.S(ec.GetDescription()) 61 | } 62 | 63 | // execute failed 64 | if ec == nil { 65 | ec = errno.ERR_UNKNOWN 66 | } 67 | if len(out) > 0 { 68 | return ec.S(out) 69 | } 70 | return ec.E(err) 71 | } 72 | -------------------------------------------------------------------------------- /internal/task/task/bs/balance_leader.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-04-22 20 | * Author: Ye Tao (YhhHaa) 21 | */ 22 | 23 | package bs 24 | 25 | import ( 26 | "fmt" 27 | 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/configure/topology" 30 | "github.com/opencurve/curveadm/internal/task/step" 31 | "github.com/opencurve/curveadm/internal/task/task" 32 | tui "github.com/opencurve/curveadm/internal/tui/common" 33 | ) 34 | 35 | func NewBalanceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { 36 | serviceId := curveadm.GetServiceId(dc.GetId()) 37 | containerId, err := curveadm.GetContainerId(serviceId) 38 | if curveadm.IsSkip(dc) { 39 | return nil, nil 40 | } else if err != nil { 41 | return nil, err 42 | } 43 | 44 | hc, err := curveadm.GetHost(dc.GetHost()) 45 | if err != nil { 46 | return nil, err 47 | } 48 | 49 | subname := fmt.Sprintf("host=%s role=%s containerId=%s", 50 | dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) 51 | t := task.NewTask("Balance Leader", subname, hc.GetSSHConfig()) 52 | 53 | // add step 54 | t.AddStep(&step.ContainerExec{ 55 | ContainerId: &containerId, 56 | Command: "curve_ops_tool rapid-leader-schedule", 57 | ExecOptions: curveadm.ExecOptions(), 58 | }) 59 | 60 | return t, nil 61 | } 62 | -------------------------------------------------------------------------------- /internal/task/task/bs/check.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-12-25 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package bs 24 | -------------------------------------------------------------------------------- /internal/task/task/bs/delete_target.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-02-09 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package bs 24 | 25 | import ( 26 | "fmt" 27 | "strings" 28 | 29 | "github.com/opencurve/curveadm/cli/cli" 30 | "github.com/opencurve/curveadm/internal/common" 31 | client "github.com/opencurve/curveadm/internal/configure" 32 | "github.com/opencurve/curveadm/internal/errno" 33 | "github.com/opencurve/curveadm/internal/task/context" 34 | "github.com/opencurve/curveadm/internal/task/step" 35 | "github.com/opencurve/curveadm/internal/task/task" 36 | ) 37 | 38 | type ( 39 | step2CheckTgtdStatus struct{ output *string } 40 | ) 41 | 42 | // check target daemon status 43 | func (s *step2CheckTgtdStatus) Execute(ctx *context.Context) error { 44 | output := *s.output 45 | items := strings.Split(output, " ") 46 | if len(items) < 2 || !strings.HasPrefix(items[1], "Up") { 47 | return errno.ERR_TARGET_DAEMON_IS_ABNORMAL 48 | } 49 | 50 | return nil 51 | } 52 | 53 | func NewDeleteTargetTask(curveadm *cli.CurveAdm, cc *client.ClientConfig) (*task.Task, error) { 54 | options := curveadm.MemStorage().Get(common.KEY_TARGET_OPTIONS).(TargetOption) 55 | hc, err := curveadm.GetHost(options.Host) 56 | if err != nil { 57 | return nil, err 58 | } 59 | 60 | subname := fmt.Sprintf("hostname=%s tid=%s", hc.GetHostname(), options.Tid) 61 | t := task.NewTask("Delete Target", subname, hc.GetSSHConfig()) 62 | 63 | // add step 64 | var output string 65 | containerId := DEFAULT_TGTD_CONTAINER_NAME 66 | tid := options.Tid 67 | t.AddStep(&step.ListContainers{ 68 | ShowAll: true, 69 | Format: "'{{.ID}} {{.Status}}'", 70 | Filter: fmt.Sprintf("name=%s", DEFAULT_TGTD_CONTAINER_NAME), 71 | Out: &output, 72 | ExecOptions: curveadm.ExecOptions(), 73 | }) 74 | t.AddStep(&step2CheckTgtdStatus{ 75 | output: &output, 76 | }) 77 | t.AddStep(&step.ContainerExec{ 78 | ContainerId: &containerId, 79 | Command: fmt.Sprintf("tgtadm --lld iscsi --mode target --op delete --tid %s", tid), 80 | ExecOptions: curveadm.ExecOptions(), 81 | }) 82 | 83 | return t, nil 84 | } 85 | -------------------------------------------------------------------------------- /internal/task/task/bs/detect_release.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-08-08 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package bs 24 | 25 | import ( 26 | "fmt" 27 | "regexp" 28 | "strings" 29 | 30 | "github.com/opencurve/curveadm/cli/cli" 31 | comm "github.com/opencurve/curveadm/internal/common" 32 | "github.com/opencurve/curveadm/internal/configure/os" 33 | "github.com/opencurve/curveadm/internal/errno" 34 | "github.com/opencurve/curveadm/internal/task/context" 35 | "github.com/opencurve/curveadm/internal/task/step" 36 | "github.com/opencurve/curveadm/internal/task/task" 37 | ) 38 | 39 | const ( 40 | REGEX_OS_RELEASE = "^ID=(.*)$" 41 | ) 42 | 43 | type step2ParseOSRelease struct { 44 | host string 45 | success *bool 46 | out *string 47 | curveadm *cli.CurveAdm 48 | } 49 | 50 | func (s *step2ParseOSRelease) Execute(ctx *context.Context) error { 51 | if !*s.success { 52 | return errno.ERR_CONCATENATE_FILE_FAILED.S(*s.out) 53 | } 54 | 55 | lines := strings.Split(*s.out, "\n") 56 | pattern := regexp.MustCompile(REGEX_OS_RELEASE) 57 | for _, line := range lines { 58 | mu := pattern.FindStringSubmatch(line) 59 | if len(mu) != 0 { 60 | s.curveadm.MemStorage().Set(comm.KEY_OS_RELEASE, mu[1]) 61 | return nil 62 | } 63 | } 64 | return errno.ERR_GET_OS_REELASE_FAILED.S(*s.out) 65 | } 66 | 67 | func NewDetectOSReleaseTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) { 68 | host := curveadm.MemStorage().Get(comm.KEY_POLARFS_HOST).(string) 69 | hc, err := curveadm.GetHost(host) 70 | if err != nil { 71 | return nil, err 72 | } 73 | 74 | // new task 75 | var success bool 76 | var out string 77 | subname := fmt.Sprintf("host=%s", host) 78 | t := task.NewTask("Detect OS Release", subname, hc.GetSSHConfig()) 79 | 80 | // add step to task 81 | t.AddStep(&step.Cat{ 82 | Files: []string{os.GetOSReleasePath()}, 83 | Success: &success, 84 | Out: &out, 85 | ExecOptions: curveadm.ExecOptions(), 86 | }) 87 | t.AddStep(&step2ParseOSRelease{ 88 | host: host, 89 | success: &success, 90 | out: &out, 91 | curveadm: curveadm, 92 | }) 93 | 94 | return t, nil 95 | } 96 | -------------------------------------------------------------------------------- /internal/task/task/bs/stop_tgtd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-02-08 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package bs 24 | 25 | import ( 26 | "fmt" 27 | 28 | "github.com/opencurve/curveadm/cli/cli" 29 | comm "github.com/opencurve/curveadm/internal/common" 30 | "github.com/opencurve/curveadm/internal/task/context" 31 | "github.com/opencurve/curveadm/internal/task/step" 32 | "github.com/opencurve/curveadm/internal/task/task" 33 | ) 34 | 35 | func checkTargetDaemonExist(containerId *string) step.LambdaType { 36 | return func(ctx *context.Context) error { 37 | if len(*containerId) == 0 { 38 | return task.ERR_TASK_DONE 39 | } 40 | return nil 41 | } 42 | } 43 | 44 | func NewStopTargetDaemonTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) { 45 | options := curveadm.MemStorage().Get(comm.KEY_TARGET_OPTIONS).(TargetOption) 46 | hc, err := curveadm.GetHost(options.Host) 47 | if err != nil { 48 | return nil, err 49 | } 50 | 51 | // new task 52 | subname := fmt.Sprintf("host=%s", options.Host) 53 | t := task.NewTask("Stop Target Daemon", subname, hc.GetSSHConfig()) 54 | 55 | // add step 56 | var containerId string 57 | t.AddStep(&step.ListContainers{ 58 | ShowAll: true, 59 | Format: "'{{.ID}}'", 60 | Filter: fmt.Sprintf("name=%s", DEFAULT_TGTD_CONTAINER_NAME), 61 | Out: &containerId, 62 | ExecOptions: curveadm.ExecOptions(), 63 | }) 64 | t.AddStep(&step.Lambda{ 65 | Lambda: checkTargetDaemonExist(&containerId), 66 | }) 67 | t.AddStep(&step.StopContainer{ 68 | ContainerId: DEFAULT_TGTD_CONTAINER_NAME, 69 | ExecOptions: curveadm.ExecOptions(), 70 | }) 71 | t.AddStep(&step.RemoveContainer{ 72 | ContainerId: DEFAULT_TGTD_CONTAINER_NAME, 73 | ExecOptions: curveadm.ExecOptions(), 74 | }) 75 | 76 | return t, nil 77 | } 78 | -------------------------------------------------------------------------------- /internal/task/task/bs/uninstall_polarfs.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-08-08 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package bs 24 | 25 | import ( 26 | "fmt" 27 | 28 | "github.com/opencurve/curveadm/cli/cli" 29 | comm "github.com/opencurve/curveadm/internal/common" 30 | "github.com/opencurve/curveadm/internal/errno" 31 | "github.com/opencurve/curveadm/internal/task/context" 32 | "github.com/opencurve/curveadm/internal/task/step" 33 | "github.com/opencurve/curveadm/internal/task/task" 34 | ) 35 | 36 | type step2UninstallPackage struct { 37 | release string 38 | curveadm *cli.CurveAdm 39 | } 40 | 41 | func (s *step2UninstallPackage) Execute(ctx *context.Context) error { 42 | steps := []task.Step{} 43 | curveadm := s.curveadm 44 | release := s.release 45 | if release == comm.OS_RELEASE_DEBIAN || 46 | release == comm.OS_RELEASE_UBUNTU { 47 | steps = append(steps, &step.Dpkg{ 48 | Purge: "pfsd", 49 | ExecOptions: curveadm.ExecOptions(), 50 | }) 51 | } else if release == comm.OS_RELEASE_CENTOS { 52 | steps = append(steps, &step.Rpm{ 53 | // do something 54 | ExecOptions: curveadm.ExecOptions(), 55 | }) 56 | } else { 57 | return errno.ERR_UNSUPPORT_LINUX_OS_REELASE. 58 | F("os release: %s", release) 59 | } 60 | 61 | for _, step := range steps { 62 | err := step.Execute(ctx) 63 | if err != nil { 64 | return errno.ERR_INSTALL_PFSD_PACKAGE_FAILED.E(err) 65 | } 66 | } 67 | return nil 68 | } 69 | 70 | func NewUninstallPolarFSTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) { 71 | host := curveadm.MemStorage().Get(comm.KEY_POLARFS_HOST).(string) 72 | hc, err := curveadm.GetHost(host) 73 | if err != nil { 74 | return nil, err 75 | } 76 | 77 | // new task 78 | release := getRelease(curveadm) 79 | subname := fmt.Sprintf("host=%s release=%s", host, release) 80 | t := task.NewTask("Uninstall PolarFS", subname, hc.GetSSHConfig()) 81 | 82 | // add step to task 83 | t.AddStep(&step.RemoveFile{ 84 | Files: []string{"/etc/curve"}, 85 | ExecOptions: curveadm.ExecOptions(), 86 | }) 87 | t.AddPostStep(&step2UninstallPackage{ 88 | release: release, 89 | curveadm: curveadm, 90 | }) 91 | 92 | return t, nil 93 | } 94 | -------------------------------------------------------------------------------- /internal/task/task/checker/kernel_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-08-31 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package checker 24 | 25 | import ( 26 | "testing" 27 | 28 | "github.com/opencurve/curveadm/internal/configure/topology" 29 | "github.com/opencurve/curveadm/internal/errno" 30 | "github.com/stretchr/testify/assert" 31 | ) 32 | 33 | func TestCheckKernelVersion(t *testing.T) { 34 | assert := assert.New(t) 35 | 36 | tests := []struct { 37 | version string 38 | err error 39 | }{ 40 | {"5.12.0", nil}, 41 | {"4.9.65-netease", nil}, 42 | {"4.18.0_80.7.1.el8_0_bch_v1.0", nil}, 43 | {"4.19.0-16-amd64", nil}, 44 | {"3.15.0", nil}, 45 | {"3.15.0.0.", errno.ERR_UNRECOGNIZED_KERNEL_VERSION}, 46 | {"3.14.9", errno.ERR_RENAMEAT_NOT_SUPPORTED_IN_CURRENT_KERNEL}, 47 | } 48 | 49 | dc := topology.DeployConfig{} 50 | for _, t := range tests { 51 | lambda := checkKernelVersion(&t.version, &dc) 52 | assert.Equal(lambda(nil), t.err) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /internal/task/task/checker/network_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-09-08 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package checker 24 | 25 | import ( 26 | "testing" 27 | 28 | "github.com/golang-module/carbon/v2" 29 | "github.com/stretchr/testify/assert" 30 | ) 31 | 32 | func TestWaitNginxStart(t *testing.T) { 33 | assert := assert.New(t) 34 | 35 | seconds := []int{1, 2, 3} 36 | for _, second := range seconds { 37 | start := carbon.Now().Timestamp() 38 | err := waitNginxStarted(second)(nil) 39 | end := carbon.Now().Timestamp() 40 | elapse := (int)(end - start) 41 | assert.Nil(err) 42 | assert.GreaterOrEqual(elapse, second) 43 | assert.Less(elapse, second+1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /internal/task/task/checker/ssh.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package checker 26 | 27 | import ( 28 | "fmt" 29 | 30 | "github.com/opencurve/curveadm/cli/cli" 31 | "github.com/opencurve/curveadm/internal/configure/hosts" 32 | "github.com/opencurve/curveadm/internal/configure/topology" 33 | "github.com/opencurve/curveadm/internal/errno" 34 | "github.com/opencurve/curveadm/internal/task/context" 35 | "github.com/opencurve/curveadm/internal/task/step" 36 | "github.com/opencurve/curveadm/internal/task/task" 37 | "github.com/opencurve/curveadm/internal/utils" 38 | ) 39 | 40 | const ( 41 | PERMISSIONS_600 = 384 // -rw------- (256 + 128 = 384) 42 | ) 43 | 44 | func doNothing() step.LambdaType { 45 | return func(ctx *context.Context) error { 46 | return nil 47 | } 48 | } 49 | 50 | // we should check host again for maybe someone change the priavte key file 51 | func checkHost(hc *hosts.HostConfig) step.LambdaType { 52 | return func(ctx *context.Context) error { 53 | privateKeyFile := hc.GetPrivateKeyFile() 54 | if hc.GetForwardAgent() == false { 55 | if !utils.PathExist(privateKeyFile) { 56 | return errno.ERR_PRIVATE_KEY_FILE_NOT_EXIST. 57 | F("%s: no such file", privateKeyFile) 58 | } else if utils.GetFilePermissions(privateKeyFile) != PERMISSIONS_600 { 59 | return errno.ERR_PRIVATE_KEY_FILE_REQUIRE_600_PERMISSIONS. 60 | F("file=%s mode=%d", privateKeyFile, utils.GetFilePermissions(privateKeyFile)) 61 | } 62 | } 63 | return nil 64 | } 65 | } 66 | 67 | func NewCheckSSHConnectTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { 68 | hc, err := curveadm.GetHost(dc.GetHost()) 69 | if err != nil { 70 | return nil, err 71 | } 72 | 73 | // new task 74 | method := utils.Choose(hc.GetForwardAgent(), "forwardAgent", "privateKey") 75 | subname := fmt.Sprintf("host=%s method=%s", dc.GetHost(), method) 76 | t := task.NewTask("Check SSH Connect ", subname, hc.GetSSHConfig()) 77 | 78 | // add step to task 79 | t.AddStep(&step.Lambda{ 80 | Lambda: checkHost(hc), 81 | }) 82 | t.AddStep(&step.Lambda{ 83 | Lambda: doNothing(), 84 | }) 85 | 86 | return t, nil 87 | } 88 | -------------------------------------------------------------------------------- /internal/task/task/checker/topology.yaml.go: -------------------------------------------------------------------------------- 1 | package checker 2 | -------------------------------------------------------------------------------- /internal/task/task/common/backup_etcd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-05-21 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package common 24 | 25 | import ( 26 | "fmt" 27 | "time" 28 | 29 | "github.com/opencurve/curveadm/cli/cli" 30 | "github.com/opencurve/curveadm/internal/configure/topology" 31 | "github.com/opencurve/curveadm/internal/task/step" 32 | "github.com/opencurve/curveadm/internal/task/task" 33 | tui "github.com/opencurve/curveadm/internal/tui/common" 34 | ) 35 | 36 | func genBackupCommand(dc *topology.DeployConfig) string { 37 | layout := dc.GetProjectLayout() 38 | binaryPath := fmt.Sprintf("%s/etcdctl", layout.ServiceBinDir) 39 | endpoint := fmt.Sprintf("%s:%d", dc.GetListenIp(), dc.GetListenPort()) 40 | savePath := fmt.Sprintf("%s/snapshot.%s.db", layout.ServiceDataDir, time.Now().Format("2006-01-02-15:04:05")) 41 | command := fmt.Sprintf("%s --endpoints %s snapshot save %s", binaryPath, endpoint, savePath) 42 | return command 43 | } 44 | 45 | func NewBackupEtcdDataTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { 46 | serviceId := curveadm.GetServiceId(dc.GetId()) 47 | containerId, err := curveadm.GetContainerId(serviceId) 48 | if curveadm.IsSkip(dc) { 49 | return nil, nil 50 | } else if err != nil { 51 | return nil, err 52 | } 53 | hc, err := curveadm.GetHost(dc.GetHost()) 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | subname := fmt.Sprintf("host=%s role=%s containerId=%s", 59 | dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) 60 | t := task.NewTask("Backup Etcd Data", subname, hc.GetSSHConfig()) 61 | 62 | t.AddStep(&step.ContainerExec{ 63 | ContainerId: &containerId, 64 | Command: genBackupCommand(dc), 65 | ExecOptions: curveadm.ExecOptions(), 66 | }) 67 | return t, nil 68 | } 69 | -------------------------------------------------------------------------------- /internal/task/task/common/init_support.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-08-14 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package common 24 | 25 | import ( 26 | "fmt" 27 | "github.com/opencurve/curveadm/cli/cli" 28 | comm "github.com/opencurve/curveadm/internal/common" 29 | "github.com/opencurve/curveadm/internal/configure/topology" 30 | "github.com/opencurve/curveadm/internal/task/step" 31 | "github.com/opencurve/curveadm/internal/task/task" 32 | "path" 33 | ) 34 | 35 | func NewInitSupportTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { 36 | // new task 37 | kind := dc.GetKind() 38 | subname := fmt.Sprintf("cluster=%s kind=%s", 39 | curveadm.ClusterName(), kind) 40 | t := task.NewTask("Init Support", subname, nil) 41 | 42 | /* 43 | * 0d7a7103521da69c6331a96355142c3b 44 | * data 45 | * curveadm_db-encrypted.tar.gz 46 | * report 47 | * report-encrypted.tar.gz (curveadm hosts ls) 48 | * service 49 | * etcd 50 | * 7b510fb63730-encrypted.tar.gz 51 | * 978333085318-encrypted.tar.gz 52 | * mds 53 | * ... 54 | * client 55 | * 362d538778ad-encrypted.tar.gz 56 | * b0d56cfaad14-encrypted.tar.gz 57 | */ 58 | roles := topology.CURVEBS_ROLES 59 | if kind == topology.KIND_CURVEFS { 60 | roles = topology.CURVEFS_ROLES 61 | } 62 | secret := curveadm.MemStorage().Get(comm.KEY_SECRET).(string) 63 | urlFormat := curveadm.MemStorage().Get(comm.KEY_SUPPORT_UPLOAD_URL_FORMAT).(string) 64 | 65 | options := curveadm.ExecOptions() 66 | options.ExecInLocal = true 67 | root := encodeSecret(secret) 68 | dirs := []string{ 69 | root, 70 | path.Join(root, "data"), 71 | path.Join(root, "report"), 72 | path.Join(root, "service"), 73 | path.Join(root, "client"), 74 | } 75 | for _, role := range roles { 76 | dirs = append(dirs, path.Join(root, "service", role)) 77 | } 78 | // curl -F "mkdir=$DIR_NAME" http://localhost:8080/upload\?path=\/ 79 | for _, dir := range dirs { 80 | t.AddStep(&step.Curl{ 81 | Url: fmt.Sprintf(urlFormat, "/"), 82 | Form: fmt.Sprintf("mkdir=%s", dir), 83 | Insecure: true, 84 | Silent: true, 85 | ExecOptions: options, 86 | }) 87 | } 88 | 89 | return t, nil 90 | } 91 | -------------------------------------------------------------------------------- /internal/task/task/common/pull_image.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package common 26 | 27 | import ( 28 | "fmt" 29 | 30 | "github.com/opencurve/curveadm/cli/cli" 31 | "github.com/opencurve/curveadm/internal/configure/topology" 32 | "github.com/opencurve/curveadm/internal/task/step" 33 | "github.com/opencurve/curveadm/internal/task/task" 34 | ) 35 | 36 | func NewPullImageTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { 37 | hc, err := curveadm.GetHost(dc.GetHost()) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | // new task 43 | subname := fmt.Sprintf("host=%s image=%s", dc.GetHost(), dc.GetContainerImage()) 44 | t := task.NewTask("Pull Image", subname, hc.GetSSHConfig()) 45 | 46 | // add step to task 47 | t.AddStep(&step.PullImage{ 48 | Image: dc.GetContainerImage(), 49 | ExecOptions: curveadm.ExecOptions(), 50 | }) 51 | 52 | return t, nil 53 | } 54 | -------------------------------------------------------------------------------- /internal/task/task/common/uninstall_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-08-08 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package common 24 | 25 | import ( 26 | "fmt" 27 | 28 | "github.com/opencurve/curveadm/cli/cli" 29 | comm "github.com/opencurve/curveadm/internal/common" 30 | "github.com/opencurve/curveadm/internal/errno" 31 | "github.com/opencurve/curveadm/internal/task/context" 32 | "github.com/opencurve/curveadm/internal/task/step" 33 | "github.com/opencurve/curveadm/internal/task/task" 34 | "github.com/opencurve/curveadm/internal/utils" 35 | ) 36 | 37 | type step2UninstallPackage struct { 38 | kind string 39 | release string 40 | curveadm *cli.CurveAdm 41 | } 42 | 43 | func (s *step2UninstallPackage) Execute(ctx *context.Context) error { 44 | steps := []task.Step{} 45 | curveadm := s.curveadm 46 | release := s.release 47 | if release == comm.OS_RELEASE_DEBIAN || 48 | release == comm.OS_RELEASE_UBUNTU { 49 | steps = append(steps, &step.Dpkg{ 50 | Purge: s.kind, 51 | ExecOptions: curveadm.ExecOptions(), 52 | }) 53 | } else if release == comm.OS_RELEASE_CENTOS { 54 | steps = append(steps, &step.Rpm{ 55 | // do something 56 | ExecOptions: curveadm.ExecOptions(), 57 | }) 58 | } else { 59 | return errno.ERR_UNSUPPORT_LINUX_OS_REELASE. 60 | F("os release: %s", release) 61 | } 62 | 63 | for _, step := range steps { 64 | err := step.Execute(ctx) 65 | if err != nil { 66 | return errno.ERR_INSTALL_PFSD_PACKAGE_FAILED.E(err) 67 | } 68 | } 69 | return nil 70 | } 71 | 72 | func NewUninstallClientTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) { 73 | host := curveadm.MemStorage().Get(comm.KEY_CLIENT_HOST).(string) 74 | hc, err := curveadm.GetHost(host) 75 | if err != nil { 76 | return nil, err 77 | } 78 | 79 | // new task 80 | release := getRelease(curveadm) 81 | kind := curveadm.MemStorage().Get(comm.KEY_CLIENT_KIND).(string) 82 | subname := fmt.Sprintf("host=%s release=%s kind=%s", host, release, kind) 83 | name := utils.Choose(kind == KIND_CURVEBS, "CurveBS", "CurveFS") 84 | t := task.NewTask(fmt.Sprintf("Uninstall %s Client", name), subname, hc.GetSSHConfig()) 85 | 86 | // add step to task 87 | t.AddPostStep(&step2UninstallPackage{ 88 | kind: kind, 89 | release: release, 90 | curveadm: curveadm, 91 | }) 92 | 93 | return t, nil 94 | } 95 | -------------------------------------------------------------------------------- /internal/task/task/common/update_topology.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-08-06 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93_ 24 | 25 | package common 26 | 27 | import ( 28 | "github.com/opencurve/curveadm/cli/cli" 29 | comm "github.com/opencurve/curveadm/internal/common" 30 | "github.com/opencurve/curveadm/internal/task/context" 31 | "github.com/opencurve/curveadm/internal/task/step" 32 | "github.com/opencurve/curveadm/internal/task/task" 33 | "github.com/opencurve/curveadm/internal/errno" 34 | ) 35 | 36 | func updateTopology(curveadm *cli.CurveAdm) step.LambdaType { 37 | return func(ctx *context.Context) error { 38 | topology := curveadm.MemStorage().Get(comm.KEY_NEW_TOPOLOGY_DATA).(string) 39 | err := curveadm.Storage().SetClusterTopology(curveadm.ClusterId(), topology) 40 | if err != nil { 41 | return errno.ERR_UPDATE_CLUSTER_TOPOLOGY_FAILED.E(err) 42 | } 43 | return nil 44 | } 45 | } 46 | 47 | func NewUpdateTopologyTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) { 48 | t := task.NewTask("Update Topology", "", nil) 49 | 50 | // add step to task 51 | t.AddStep(&step.Lambda{ 52 | Lambda: updateTopology(curveadm), 53 | }) 54 | 55 | return t, nil 56 | } 57 | -------------------------------------------------------------------------------- /internal/task/task/fs/mount_test.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | "strings" 5 | "testing" 6 | 7 | "github.com/opencurve/curveadm/internal/configure" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | var ( 12 | KEY_KIND = strings.ToLower(configure.KEY_KIND) 13 | KEY_ADDRS = strings.ToLower(configure.KEY_CURVEFS_LISTEN_MDS_ADDRS) 14 | KEY_ENV = strings.ToLower(configure.KEY_ENVIRONMENT) 15 | ) 16 | 17 | func run(t *testing.T, config map[string]interface{}, envs []string) { 18 | assert := assert.New(t) 19 | cc, err := configure.NewClientConfig(config) 20 | assert.Nil(err) 21 | assert.Equal(envs, getEnvironments(cc)) 22 | } 23 | 24 | func TestConfigureEnv_Basic(t *testing.T) { 25 | run(t, map[string]interface{}{ 26 | KEY_KIND: "curvefs", 27 | KEY_ADDRS: "1.1.1.1", 28 | }, []string{ 29 | "LD_PRELOAD=/usr/local/lib/libjemalloc.so", 30 | }) 31 | 32 | run(t, map[string]interface{}{ 33 | KEY_KIND: "curvefs", 34 | KEY_ADDRS: "1.1.1.1", 35 | KEY_ENV: "MALLOC_CONF=prof:true,lg_prof_interval:26,prof_prefix:/curvefs/client/logs/jeprof.out", 36 | }, []string{ 37 | "LD_PRELOAD=/usr/local/lib/libjemalloc.so", 38 | "MALLOC_CONF=prof:true,lg_prof_interval:26,prof_prefix:/curvefs/client/logs/jeprof.out", 39 | }) 40 | 41 | run(t, map[string]interface{}{ 42 | KEY_KIND: "curvefs", 43 | KEY_ADDRS: "1.1.1.1", 44 | KEY_ENV: "NAME=jack AGE=18 FROM=china", 45 | }, []string{ 46 | "LD_PRELOAD=/usr/local/lib/libjemalloc.so", 47 | "NAME=jack", 48 | "AGE=18", 49 | "FROM=china", 50 | }) 51 | 52 | run(t, map[string]interface{}{ 53 | KEY_KIND: "curvefs", 54 | KEY_ADDRS: "1.1.1.1", 55 | KEY_ENV: "LD_PRELOAD=", 56 | }, []string{ 57 | "LD_PRELOAD=/usr/local/lib/libjemalloc.so", 58 | "LD_PRELOAD=", 59 | }) 60 | } 61 | -------------------------------------------------------------------------------- /internal/task/task/monitor/clean_container.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: Curveadm 19 | * Created Date: 2023-04-26 20 | * Author: wanghai (SeanHai) 21 | */ 22 | 23 | package monitor 24 | 25 | import ( 26 | "github.com/opencurve/curveadm/cli/cli" 27 | "github.com/opencurve/curveadm/internal/configure" 28 | "github.com/opencurve/curveadm/internal/task/task" 29 | "github.com/opencurve/curveadm/internal/task/task/common" 30 | ) 31 | 32 | func NewCleanConfigContainerTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { 33 | role := cfg.GetRole() 34 | if role != ROLE_MONITOR_CONF { 35 | return nil, nil 36 | } 37 | host := cfg.GetHost() 38 | hc, err := curveadm.GetHost(host) 39 | if err != nil { 40 | return nil, err 41 | } 42 | serviceId := curveadm.GetServiceId(cfg.GetId()) 43 | containerId, err := curveadm.GetContainerId(serviceId) 44 | if err != nil { 45 | return nil, err 46 | } 47 | t := task.NewTask("Clean Config Container", "", hc.GetSSHConfig()) 48 | t.AddStep(&common.Step2CleanContainer{ 49 | ServiceId: serviceId, 50 | ContainerId: containerId, 51 | Storage: curveadm.Storage(), 52 | ExecOptions: curveadm.ExecOptions(), 53 | }) 54 | return t, nil 55 | } 56 | -------------------------------------------------------------------------------- /internal/task/task/monitor/clean_service.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: Curveadm 19 | * Created Date: 2023-04-27 20 | * Author: wanghai (SeanHai) 21 | */ 22 | 23 | package monitor 24 | 25 | import ( 26 | "fmt" 27 | "strings" 28 | 29 | "github.com/opencurve/curveadm/cli/cli" 30 | comm "github.com/opencurve/curveadm/internal/common" 31 | "github.com/opencurve/curveadm/internal/configure" 32 | "github.com/opencurve/curveadm/internal/task/step" 33 | "github.com/opencurve/curveadm/internal/task/task" 34 | "github.com/opencurve/curveadm/internal/task/task/common" 35 | tui "github.com/opencurve/curveadm/internal/tui/common" 36 | "github.com/opencurve/curveadm/internal/utils" 37 | ) 38 | 39 | var ( 40 | ROLE_NODE_EXPORTER = configure.ROLE_NODE_EXPORTER 41 | ROLE_PROMETHEUS = configure.ROLE_PROMETHEUS 42 | ROLE_GRAFANA = configure.ROLE_GRAFANA 43 | ROLE_MONITOR_CONF = configure.ROLE_MONITOR_CONF 44 | ) 45 | 46 | func getCleanFiles(clean map[string]bool, mc *configure.MonitorConfig) []string { 47 | files := []string{} 48 | for item := range clean { 49 | switch item { 50 | case comm.CLEAN_ITEM_DATA: 51 | files = append(files, mc.GetDataDir()) 52 | } 53 | } 54 | return files 55 | } 56 | 57 | func NewCleanMonitorTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { 58 | serviceId := curveadm.GetServiceId(cfg.GetId()) 59 | containerId, err := curveadm.GetContainerId(serviceId) 60 | if err != nil { 61 | return nil, err 62 | } 63 | if cfg.GetRole() == ROLE_MONITOR_CONF && 64 | (len(containerId) == 0 || containerId == comm.CLEANED_CONTAINER_ID) { 65 | return nil, nil 66 | } 67 | hc, err := curveadm.GetHost(cfg.GetHost()) 68 | if err != nil { 69 | return nil, err 70 | } 71 | 72 | // new task 73 | only := curveadm.MemStorage().Get(comm.KEY_CLEAN_ITEMS).([]string) 74 | subname := fmt.Sprintf("host=%s role=%s containerId=%s clean=%s", 75 | cfg.GetHost(), cfg.GetRole(), tui.TrimContainerId(containerId), strings.Join(only, ",")) 76 | t := task.NewTask("Clean Monitor", subname, hc.GetSSHConfig()) 77 | 78 | // add step to task 79 | clean := utils.Slice2Map(only) 80 | files := getCleanFiles(clean, cfg) // directorys which need cleaned 81 | t.AddStep(&step.RemoveFile{ 82 | Files: files, 83 | ExecOptions: curveadm.ExecOptions(), 84 | }) 85 | if clean[comm.CLEAN_ITEM_CONTAINER] == true { 86 | t.AddStep(&common.Step2CleanContainer{ 87 | ServiceId: serviceId, 88 | ContainerId: containerId, 89 | Storage: curveadm.Storage(), 90 | ExecOptions: curveadm.ExecOptions(), 91 | }) 92 | } 93 | return t, nil 94 | } 95 | -------------------------------------------------------------------------------- /internal/task/task/monitor/pull_image.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: Curveadm 19 | * Created Date: 2023-04-19 20 | * Author: wanghai (SeanHai) 21 | */ 22 | 23 | package monitor 24 | 25 | import ( 26 | "fmt" 27 | 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/configure" 30 | "github.com/opencurve/curveadm/internal/task/step" 31 | "github.com/opencurve/curveadm/internal/task/task" 32 | ) 33 | 34 | func NewPullImageTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { 35 | image := cfg.GetImage() 36 | host := cfg.GetHost() 37 | hc, err := curveadm.GetHost(host) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | // new task 43 | subname := fmt.Sprintf("host=%s image=%s", host, image) 44 | t := task.NewTask("Pull Image", subname, hc.GetSSHConfig()) 45 | // add step to task 46 | t.AddStep(&step.PullImage{ 47 | Image: image, 48 | ExecOptions: curveadm.ExecOptions(), 49 | }) 50 | return t, nil 51 | } 52 | -------------------------------------------------------------------------------- /internal/task/task/monitor/restart_service.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: Curveadm 19 | * Created Date: 2023-04-28 20 | * Author: wanghai (SeanHai) 21 | */ 22 | 23 | package monitor 24 | 25 | import ( 26 | "fmt" 27 | 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/configure" 30 | "github.com/opencurve/curveadm/internal/task/step" 31 | "github.com/opencurve/curveadm/internal/task/task" 32 | "github.com/opencurve/curveadm/internal/task/task/common" 33 | tui "github.com/opencurve/curveadm/internal/tui/common" 34 | ) 35 | 36 | func NewRestartServiceTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { 37 | serviceId := curveadm.GetServiceId(cfg.GetId()) 38 | containerId, err := curveadm.GetContainerId(serviceId) 39 | if IsSkip(cfg, []string{ROLE_MONITOR_CONF}) { 40 | return nil, nil 41 | } else if err != nil { 42 | return nil, err 43 | } 44 | hc, err := curveadm.GetHost(cfg.GetHost()) 45 | if err != nil { 46 | return nil, err 47 | } 48 | 49 | // new task 50 | subname := fmt.Sprintf("host=%s role=%s containerId=%s", 51 | cfg.GetHost(), cfg.GetRole(), tui.TrimContainerId(containerId)) 52 | t := task.NewTask("Restart Monitor Service", subname, hc.GetSSHConfig()) 53 | 54 | // add step to task 55 | var out string 56 | var success bool 57 | host, role := cfg.GetHost(), cfg.GetRole() 58 | t.AddStep(&step.ListContainers{ 59 | ShowAll: true, 60 | Format: `"{{.ID}}"`, 61 | Filter: fmt.Sprintf("id=%s", containerId), 62 | Out: &out, 63 | ExecOptions: curveadm.ExecOptions(), 64 | }) 65 | t.AddStep(&step.Lambda{ 66 | Lambda: common.CheckContainerExist(host, role, containerId, &out), 67 | }) 68 | t.AddStep(&step.RestartContainer{ 69 | ContainerId: containerId, 70 | ExecOptions: curveadm.ExecOptions(), 71 | }) 72 | t.AddStep(&step.Lambda{ 73 | Lambda: common.WaitContainerStart(3), 74 | }) 75 | t.AddStep(&common.Step2CheckPostStart{ 76 | Host: host, 77 | ContainerId: containerId, 78 | Success: &success, 79 | Out: &out, 80 | ExecOptions: curveadm.ExecOptions(), 81 | }) 82 | 83 | return t, nil 84 | } 85 | -------------------------------------------------------------------------------- /internal/task/task/monitor/start_service.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: Curveadm 19 | * Created Date: 2023-04-24 20 | * Author: wanghai (SeanHai) 21 | */ 22 | 23 | package monitor 24 | 25 | import ( 26 | "fmt" 27 | 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/configure" 30 | "github.com/opencurve/curveadm/internal/task/step" 31 | "github.com/opencurve/curveadm/internal/task/task" 32 | "github.com/opencurve/curveadm/internal/task/task/common" 33 | tui "github.com/opencurve/curveadm/internal/tui/common" 34 | ) 35 | 36 | func IsSkip(mc *configure.MonitorConfig, roles []string) bool { 37 | role := mc.GetRole() 38 | for _, r := range roles { 39 | if role == r { 40 | return true 41 | } 42 | } 43 | return false 44 | } 45 | 46 | func NewStartServiceTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { 47 | serviceId := curveadm.GetServiceId(cfg.GetId()) 48 | containerId, err := curveadm.GetContainerId(serviceId) 49 | if IsSkip(cfg, []string{ROLE_MONITOR_CONF}) { 50 | return nil, nil 51 | } else if err != nil { 52 | return nil, err 53 | } 54 | hc, err := curveadm.GetHost(cfg.GetHost()) 55 | if err != nil { 56 | return nil, err 57 | } 58 | 59 | // new task 60 | subname := fmt.Sprintf("host=%s role=%s containerId=%s", 61 | cfg.GetHost(), cfg.GetRole(), tui.TrimContainerId(containerId)) 62 | t := task.NewTask("Start Service", subname, hc.GetSSHConfig()) 63 | 64 | // add step to task 65 | var out string 66 | var success bool 67 | role, host := cfg.GetRole(), cfg.GetHost() 68 | t.AddStep(&step.ListContainers{ 69 | ShowAll: true, 70 | Format: `"{{.ID}}"`, 71 | Filter: fmt.Sprintf("id=%s", containerId), 72 | Out: &out, 73 | ExecOptions: curveadm.ExecOptions(), 74 | }) 75 | t.AddStep(&step.Lambda{ 76 | Lambda: common.CheckContainerExist(host, role, containerId, &out), 77 | }) 78 | t.AddStep(&step.StartContainer{ 79 | ContainerId: &containerId, 80 | ExecOptions: curveadm.ExecOptions(), 81 | }) 82 | t.AddStep(&step.Lambda{ 83 | Lambda: common.WaitContainerStart(3), 84 | }) 85 | t.AddStep(&common.Step2CheckPostStart{ 86 | Host: cfg.GetHost(), 87 | Role: cfg.GetRole(), 88 | ContainerId: containerId, 89 | Success: &success, 90 | Out: &out, 91 | ExecOptions: curveadm.ExecOptions(), 92 | }) 93 | 94 | return t, nil 95 | } 96 | -------------------------------------------------------------------------------- /internal/task/task/monitor/stop_service.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: Curveadm 19 | * Created Date: 2023-04-27 20 | * Author: wanghai (SeanHai) 21 | */ 22 | 23 | package monitor 24 | 25 | import ( 26 | "fmt" 27 | 28 | "github.com/opencurve/curveadm/cli/cli" 29 | "github.com/opencurve/curveadm/internal/configure" 30 | "github.com/opencurve/curveadm/internal/task/step" 31 | "github.com/opencurve/curveadm/internal/task/task" 32 | "github.com/opencurve/curveadm/internal/task/task/common" 33 | tui "github.com/opencurve/curveadm/internal/tui/common" 34 | ) 35 | 36 | func NewStopServiceTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { 37 | serviceId := curveadm.GetServiceId(cfg.GetId()) 38 | containerId, err := curveadm.GetContainerId(serviceId) 39 | if IsSkip(cfg, []string{ROLE_MONITOR_CONF}) { 40 | return nil, nil 41 | } else if err != nil { 42 | return nil, err 43 | } 44 | hc, err := curveadm.GetHost(cfg.GetHost()) 45 | if err != nil { 46 | return nil, err 47 | } 48 | 49 | // new task 50 | subname := fmt.Sprintf("host=%s role=%s containerId=%s", 51 | cfg.GetHost(), cfg.GetRole(), tui.TrimContainerId(containerId)) 52 | t := task.NewTask("Stop Service", subname, hc.GetSSHConfig()) 53 | 54 | // add step to task 55 | var out string 56 | role, host := cfg.GetRole(), cfg.GetHost() 57 | t.AddStep(&step.ListContainers{ 58 | ShowAll: true, 59 | Format: `"{{.ID}}"`, 60 | Filter: fmt.Sprintf("id=%s", containerId), 61 | Out: &out, 62 | ExecOptions: curveadm.ExecOptions(), 63 | }) 64 | t.AddStep(&step.Lambda{ 65 | Lambda: common.CheckContainerExist(host, role, containerId, &out), 66 | }) 67 | t.AddStep(&step.StopContainer{ 68 | ContainerId: containerId, 69 | ExecOptions: curveadm.ExecOptions(), 70 | }) 71 | return t, nil 72 | } 73 | -------------------------------------------------------------------------------- /internal/task/task/playground/script/client.yaml: -------------------------------------------------------------------------------- 1 | kind: curvebs 2 | mds.listen.addr: 127.0.0.1:6700,127.0.0.1:6701,127.0.0.1:6702 -------------------------------------------------------------------------------- /internal/task/task/playground/script/script.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-11-07 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package script 24 | 25 | import ( 26 | _ "embed" 27 | ) 28 | 29 | var ( 30 | //go:embed topology.yaml 31 | TOPOLOGY string 32 | 33 | //go:embed client.yaml 34 | CLIENT string 35 | 36 | //go:embed entrypoint.sh 37 | ENTRYPOINT string 38 | ) 39 | -------------------------------------------------------------------------------- /internal/task/task/playground/script/topology.yaml: -------------------------------------------------------------------------------- 1 | kind: curvebs 2 | global: 3 | prefix: /curvebs/playground/${service_role}${service_host_sequence} 4 | log_dir: ${home}/logs/${service_role}${service_host_sequence} 5 | data_dir: ${home}/data/${service_role}${service_host_sequence} 6 | variable: 7 | home: /tmp 8 | target: localhost 9 | 10 | etcd_services: 11 | config: 12 | listen.ip: ${service_host} 13 | listen.port: 2380${service_host_sequence} 14 | listen.client_port: 2379${service_host_sequence} 15 | deploy: 16 | - host: ${target} 17 | - host: ${target} 18 | - host: ${target} 19 | 20 | mds_services: 21 | config: 22 | listen.ip: ${service_host} 23 | listen.port: 670${service_host_sequence} 24 | listen.dummy_port: 770${service_host_sequence} 25 | deploy: 26 | - host: ${target} 27 | - host: ${target} 28 | - host: ${target} 29 | 30 | chunkserver_services: 31 | config: 32 | listen.ip: ${service_host} 33 | listen.port: 820${service_host_sequence} # 8200,8201,8202 34 | data_dir: /data/chunkserver${service_host_sequence} # /data/chunkserver0, /data/chunksever1 35 | copysets: 100 36 | chunkfilepool.enable_get_chunk_from_pool: false 37 | deploy: 38 | - host: ${target} 39 | - host: ${target} 40 | - host: ${target} -------------------------------------------------------------------------------- /internal/task/task/playground/start.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-11-07 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package playground 24 | 25 | import ( 26 | "fmt" 27 | "time" 28 | 29 | "github.com/opencurve/curveadm/cli/cli" 30 | "github.com/opencurve/curveadm/internal/configure" 31 | "github.com/opencurve/curveadm/internal/task/context" 32 | "github.com/opencurve/curveadm/internal/task/step" 33 | "github.com/opencurve/curveadm/internal/task/task" 34 | ) 35 | 36 | func wait(seconds int) step.LambdaType { 37 | return func(ctx *context.Context) error { 38 | time.Sleep(time.Duration(seconds) * time.Second) 39 | return nil 40 | } 41 | } 42 | 43 | func NewStartPlaygroundTask(curveadm *cli.CurveAdm, cfg *configure.PlaygroundConfig) (*task.Task, error) { 44 | // new task 45 | subname := fmt.Sprintf("kind=%s name=%s", cfg.GetKind(), cfg.GetName()) 46 | t := task.NewTask("Start Playground", subname, nil) 47 | 48 | // add step to task 49 | containerId := cfg.GetName() 50 | t.AddStep(&step.StartContainer{ 51 | ContainerId: &containerId, 52 | ExecOptions: execOptions(curveadm), 53 | }) 54 | t.AddStep(&step.Lambda{ 55 | Lambda: wait(60), 56 | }) 57 | 58 | return t, nil 59 | } 60 | -------------------------------------------------------------------------------- /internal/task/tasks/monitor.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-01-07 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package tasks 24 | 25 | import ( 26 | "sync" 27 | 28 | "github.com/opencurve/curveadm/internal/task/task" 29 | ) 30 | 31 | const ( 32 | STATUS_OK = iota 33 | STATUS_SKIP 34 | STATUS_ERROR 35 | ) 36 | 37 | type monitor struct { 38 | err error 39 | result map[int][]error // sub task result (key: progress bar id) 40 | mutex sync.Mutex 41 | } 42 | 43 | func newMonitor() *monitor { 44 | return &monitor{ 45 | err: nil, 46 | result: map[int][]error{}, 47 | mutex: sync.Mutex{}, 48 | } 49 | } 50 | 51 | func (m *monitor) error() error { 52 | return m.err 53 | } 54 | 55 | // return number of {success, skip, error} 56 | func (m *monitor) sum(bid int) (int, int, int) { 57 | nsucc, nskip, nerr := 0, 0, 0 58 | for _, err := range m.result[bid] { 59 | if err == nil { 60 | nsucc++ 61 | } else if err == task.ERR_SKIP_TASK { 62 | nskip++ 63 | } else { 64 | nerr++ 65 | } 66 | } 67 | return nsucc, nskip, nerr 68 | } 69 | 70 | func (m *monitor) set(bid int, err error) { 71 | m.mutex.Lock() 72 | defer m.mutex.Unlock() 73 | m.result[bid] = append(m.result[bid], err) 74 | if err != nil && err != task.ERR_SKIP_TASK { 75 | m.err = err 76 | } 77 | } 78 | 79 | func (m *monitor) get(bid int) int { 80 | m.mutex.Lock() 81 | defer m.mutex.Unlock() 82 | nsucc, nskip, nerr := m.sum(bid) 83 | total := nsucc + nskip + nerr 84 | if nerr != 0 { 85 | return STATUS_ERROR 86 | } else if nskip == total { 87 | return STATUS_SKIP 88 | } 89 | // success all or part of skip 90 | return STATUS_OK 91 | } 92 | -------------------------------------------------------------------------------- /internal/tasks/monitor.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-01-07 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package tasks 26 | 27 | import ( 28 | "sync" 29 | 30 | "github.com/opencurve/curveadm/internal/task/task" 31 | ) 32 | 33 | const ( 34 | STATUS_OK = iota 35 | STATUS_SKIP 36 | STATUS_ERROR 37 | ) 38 | 39 | type monitor struct { 40 | err error 41 | result map[int][]error // sub task result (key: progress bar id) 42 | mutex sync.Mutex 43 | } 44 | 45 | func newMonitor() *monitor { 46 | return &monitor{ 47 | err: nil, 48 | result: map[int][]error{}, 49 | mutex: sync.Mutex{}, 50 | } 51 | } 52 | 53 | func (m *monitor) error() error { 54 | return m.err 55 | } 56 | 57 | // return number of {success, skip, error} 58 | func (m *monitor) sum(bid int) (int, int, int) { 59 | m.mutex.Lock() 60 | defer m.mutex.Unlock() 61 | nsucc, nskip, nerr := 0, 0, 0 62 | for _, err := range m.result[bid] { 63 | if err == nil { 64 | nsucc++ 65 | } else if err == task.ERR_SKIP_TASK { 66 | nskip++ 67 | } else { 68 | nerr++ 69 | } 70 | } 71 | return nsucc, nskip, nerr 72 | } 73 | 74 | func (m *monitor) set(bid int, err error) { 75 | m.mutex.Lock() 76 | defer m.mutex.Unlock() 77 | m.result[bid] = append(m.result[bid], err) 78 | if err != nil && err != task.ERR_SKIP_TASK { 79 | m.err = err 80 | } 81 | } 82 | 83 | func (m *monitor) get(bid int) int { 84 | nsucc, nskip, nerr := m.sum(bid) 85 | total := nsucc + nskip + nerr 86 | if nerr != 0 { 87 | return STATUS_ERROR 88 | } else if nskip == total { 89 | return STATUS_SKIP 90 | } 91 | // success all or part of skip 92 | return STATUS_OK 93 | } 94 | -------------------------------------------------------------------------------- /internal/tools/upload.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-11-26 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package tools 26 | 27 | import ( 28 | "fmt" 29 | "os" 30 | 31 | "github.com/go-resty/resty/v2" 32 | ) 33 | 34 | const ( 35 | URL_UPLOAD_SUPPORT_TARBALL = "http://curveadm.aspirer.wang:19301/upload?path=/" 36 | ) 37 | 38 | func Upload(filepath string) error { 39 | file, err := os.Open(filepath) 40 | if err != nil { 41 | return err 42 | } 43 | defer file.Close() 44 | 45 | client := resty.New() 46 | resp, err := client.R(). 47 | SetFile(filepath, filepath). 48 | Post(URL_UPLOAD_SUPPORT_TARBALL) 49 | if err != nil { 50 | return err 51 | } else if resp.StatusCode() != 200 { 52 | return fmt.Errorf("upload failed, return %d", resp.StatusCode()) 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /internal/tui/audit.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-05-23 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package tui 24 | 25 | import ( 26 | "strconv" 27 | 28 | "github.com/fatih/color" 29 | comm "github.com/opencurve/curveadm/internal/common" 30 | "github.com/opencurve/curveadm/internal/storage" 31 | tuicommon "github.com/opencurve/curveadm/internal/tui/common" 32 | "github.com/opencurve/curveadm/internal/utils" 33 | ) 34 | 35 | var ( 36 | code2str = map[int]string{ 37 | comm.AUDIT_STATUS_ABORT: "ABORT", 38 | comm.AUDIT_STATUS_SUCCESS: "SUCCESS", 39 | comm.AUDIT_STATUS_FAIL: "FAIL", 40 | comm.AUDIT_STATUS_CANCEL: "CANCEL", 41 | } 42 | ) 43 | 44 | func statusDecorate(message string) string { 45 | if message == code2str[comm.AUDIT_STATUS_ABORT] { 46 | return color.HiWhiteString(message) 47 | } else if message == code2str[comm.AUDIT_STATUS_SUCCESS] { 48 | return color.GreenString(message) 49 | } else if message == code2str[comm.AUDIT_STATUS_FAIL] { 50 | return color.RedString(message) 51 | } else if message == code2str[comm.AUDIT_STATUS_CANCEL] { 52 | return color.YellowString(message) 53 | } 54 | 55 | return message 56 | } 57 | 58 | func FormatAuditLogs(auditLogs []storage.AuditLog, verbose bool) string { 59 | lines := [][]interface{}{} 60 | title := []string{"Id", "Status", "Execute Time", "Command"} 61 | if verbose { 62 | title = append(title, "Work Directory") 63 | title = append(title, "Error Code") 64 | } 65 | first, second := tuicommon.FormatTitle(title) 66 | lines = append(lines, first) 67 | lines = append(lines, second) 68 | 69 | for i := 0; i < len(auditLogs); i++ { 70 | line := []interface{}{} 71 | auditLog := auditLogs[i] 72 | 73 | // id 74 | line = append(line, strconv.Itoa(auditLog.Id)) 75 | // status 76 | status := "UNKNOWN" 77 | if v, ok := code2str[auditLog.Status]; ok { 78 | status = v 79 | } 80 | line = append(line, tuicommon.DecorateMessage{Message: status, Decorate: statusDecorate}) 81 | // execute time 82 | line = append(line, auditLog.ExecuteTime.Format("2006-01-02 15:04:05")) 83 | // command 84 | line = append(line, auditLog.Command) 85 | 86 | if verbose { 87 | // work directory 88 | line = append(line, auditLog.WorkDirectory) 89 | // error code 90 | line = append(line, utils.Atoa(auditLog.ErrorCode)) 91 | } 92 | 93 | lines = append(lines, line) 94 | } 95 | 96 | output := tuicommon.FixedFormat(lines, 2) 97 | return output 98 | } 99 | -------------------------------------------------------------------------------- /internal/tui/client/status.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-31 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package service 24 | 25 | import ( 26 | "sort" 27 | 28 | "github.com/fatih/color" 29 | comm "github.com/opencurve/curveadm/internal/common" 30 | task "github.com/opencurve/curveadm/internal/task/task/common" 31 | tui "github.com/opencurve/curveadm/internal/tui/common" 32 | ) 33 | 34 | func statusDecorate(status string) string { 35 | switch status { 36 | case comm.CLIENT_STATUS_LOSED, comm.CLIENT_STATUS_UNKNOWN: 37 | return color.RedString(status) 38 | } 39 | return status 40 | } 41 | 42 | func sortStatues(statuses []task.ClientStatus) { 43 | sort.Slice(statuses, func(i, j int) bool { 44 | s1, s2 := statuses[i], statuses[j] 45 | if s1.Kind == s2.Kind { 46 | return s1.Host < s2.Host 47 | } 48 | return s1.Kind < s2.Kind 49 | }) 50 | } 51 | 52 | func FormatStatus(statuses []task.ClientStatus, verbose bool) string { 53 | lines := [][]interface{}{} 54 | 55 | // title 56 | title := []string{ 57 | "Id", 58 | "Kind", 59 | "Host", 60 | "Container Id", 61 | "Status", 62 | "Aux Info", 63 | } 64 | if verbose { 65 | title = append(title, "Config Dumpfile") 66 | } 67 | first, second := tui.FormatTitle(title) 68 | lines = append(lines, first) 69 | lines = append(lines, second) 70 | 71 | // status 72 | sortStatues(statuses) 73 | for _, status := range statuses { 74 | // line 75 | line := []interface{}{ 76 | status.Id, 77 | status.Kind, 78 | status.Host, 79 | tui.TrimContainerId(status.ContainerId), 80 | tui.DecorateMessage{Message: status.Status, Decorate: statusDecorate}, 81 | status.AuxInfo, 82 | } 83 | if verbose { 84 | line = append(line, status.CfgPath) 85 | } 86 | 87 | // lines 88 | lines = append(lines, line) 89 | } 90 | 91 | output := tui.FixedFormat(lines, 2) 92 | return output 93 | } 94 | -------------------------------------------------------------------------------- /internal/tui/clients.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-31 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package tui 24 | -------------------------------------------------------------------------------- /internal/tui/clusters.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package tui 26 | 27 | import ( 28 | "strconv" 29 | 30 | "github.com/fatih/color" 31 | "github.com/opencurve/curveadm/internal/storage" 32 | "github.com/opencurve/curveadm/internal/tui/common" 33 | tuicommon "github.com/opencurve/curveadm/internal/tui/common" 34 | ) 35 | 36 | func currentDecorate(message string) string { 37 | return color.GreenString(message) 38 | } 39 | 40 | func FormatClusters(clusters []storage.Cluster, verbose bool) string { 41 | lines := [][]interface{}{} 42 | if verbose { 43 | title := []string{" ", "Cluster", "Id", "UUId", "Create Time", "Description"} 44 | first, second := tuicommon.FormatTitle(title) 45 | second[0] = "" 46 | lines = append(lines, first) 47 | lines = append(lines, second) 48 | } 49 | 50 | for i := 0; i < len(clusters); i++ { 51 | line := []interface{}{} 52 | cluster := clusters[i] 53 | if cluster.Current { 54 | line = append(line, common.DecorateMessage{Message: "*", Decorate: currentDecorate}) 55 | line = append(line, common.DecorateMessage{Message: cluster.Name, Decorate: currentDecorate}) 56 | } else { 57 | line = append(line, " ") 58 | line = append(line, cluster.Name) 59 | } 60 | 61 | if verbose { 62 | line = append(line, strconv.Itoa(cluster.Id)) 63 | line = append(line, cluster.UUId) 64 | line = append(line, cluster.CreateTime.Format("2006-01-02 15:04:05")) 65 | line = append(line, cluster.Description) 66 | } 67 | 68 | lines = append(lines, line) 69 | } 70 | 71 | nspace := 1 72 | if verbose { 73 | nspace = 2 74 | } 75 | output := common.FixedFormat(lines, nspace) 76 | return output 77 | } 78 | -------------------------------------------------------------------------------- /internal/tui/format/status.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-12-29 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package format 24 | 25 | import ( 26 | "sort" 27 | 28 | "github.com/opencurve/curveadm/internal/task/task/bs" 29 | tui "github.com/opencurve/curveadm/internal/tui/common" 30 | ) 31 | 32 | func sortStatues(statuses []bs.FormatStatus) { 33 | sort.Slice(statuses, func(i, j int) bool { 34 | s1, s2 := statuses[i], statuses[j] 35 | if s1.Host == s2.Host { 36 | return s1.Device < s2.Device 37 | } 38 | return s1.Host < s2.Host 39 | }) 40 | } 41 | 42 | func FormatStatus(statuses []bs.FormatStatus) string { 43 | lines := [][]interface{}{} 44 | 45 | // title 46 | title := []string{"Host", "Device", "MountPoint", "Formatted", "Status"} 47 | first, second := tui.FormatTitle(title) 48 | lines = append(lines, first) 49 | lines = append(lines, second) 50 | 51 | // status 52 | sortStatues(statuses) 53 | for _, status := range statuses { 54 | line := []interface{}{ 55 | status.Host, 56 | status.Device, 57 | status.MountPoint, 58 | status.Formatted, 59 | status.Status, 60 | } 61 | lines = append(lines, line) 62 | } 63 | 64 | output := tui.FixedFormat(lines, 2) 65 | return output 66 | } 67 | -------------------------------------------------------------------------------- /internal/tui/hosts.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-21 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package tui 26 | 27 | import ( 28 | "strconv" 29 | "strings" 30 | 31 | configure "github.com/opencurve/curveadm/internal/configure/hosts" 32 | "github.com/opencurve/curveadm/internal/tui/common" 33 | tuicommon "github.com/opencurve/curveadm/internal/tui/common" 34 | "github.com/opencurve/curveadm/internal/utils" 35 | ) 36 | 37 | const ( 38 | FIELD_LIMIT_LENGTH = 30 39 | ) 40 | 41 | func FormatHosts(hcs []*configure.HostConfig, verbose bool) string { 42 | lines := [][]interface{}{} 43 | title := []string{ 44 | "Host", 45 | "Hostname", 46 | "User", 47 | "Port", 48 | "Private Key File", 49 | "Forward Agent", 50 | "Become User", 51 | "Labels", 52 | "Envs", 53 | } 54 | first, second := tuicommon.FormatTitle(title) 55 | lines = append(lines, first) 56 | lines = append(lines, second) 57 | 58 | for i := 0; i < len(hcs); i++ { 59 | hc := hcs[i] 60 | 61 | host := hc.GetHost() 62 | hostname := hc.GetHostname() 63 | user := hc.GetUser() 64 | port := strconv.Itoa(hc.GetSSHPort()) 65 | forwardAgent := utils.Choose(hc.GetForwardAgent(), "Y", "N") 66 | becomeUser := utils.Choose(len(hc.GetBecomeUser()) > 0, hc.GetBecomeUser(), "-") 67 | labels := utils.Choose(len(hc.GetLabels()) > 0, strings.Join(hc.GetLabels(), ","), "-") 68 | envs := utils.Choose(len(hc.GetEnvs()) > 0, strings.Join(hc.GetEnvs(), ","), "-") 69 | privateKeyFile := hc.GetPrivateKeyFile() 70 | if len(privateKeyFile) == 0 { 71 | privateKeyFile = "-" 72 | } else if !verbose && len(hc.GetPrivateKeyFile()) > FIELD_LIMIT_LENGTH { 73 | privateKeyFile = privateKeyFile[:FIELD_LIMIT_LENGTH] + "..." 74 | } 75 | 76 | lines = append(lines, []interface{}{ 77 | host, 78 | hostname, 79 | user, 80 | port, 81 | privateKeyFile, 82 | forwardAgent, 83 | becomeUser, 84 | labels, 85 | envs, 86 | }) 87 | } 88 | 89 | return common.FixedFormat(lines, 2) 90 | } 91 | -------------------------------------------------------------------------------- /internal/tui/playground.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-06-24 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package tui 24 | 25 | import ( 26 | "sort" 27 | 28 | "github.com/fatih/color" 29 | comm "github.com/opencurve/curveadm/internal/common" 30 | pg "github.com/opencurve/curveadm/internal/task/task/playground" 31 | "github.com/opencurve/curveadm/internal/tui/common" 32 | tuicommon "github.com/opencurve/curveadm/internal/tui/common" 33 | ) 34 | 35 | func playgroundStatusDecorate(status string) string { 36 | switch status { 37 | case comm.PLAYGROUDN_STATUS_LOSED: 38 | return color.RedString(status) 39 | } 40 | return status 41 | } 42 | 43 | func sortStatues(statuses []pg.PlaygroundStatus) { 44 | sort.Slice(statuses, func(i, j int) bool { 45 | s1, s2 := statuses[i], statuses[j] 46 | return s1.Id < s2.Id 47 | }) 48 | } 49 | 50 | func FormatPlayground(statuses []pg.PlaygroundStatus) string { 51 | lines := [][]interface{}{} 52 | title := []string{"Id", "Name", "Create Time", "Status"} 53 | first, second := tuicommon.FormatTitle(title) 54 | lines = append(lines, first) 55 | lines = append(lines, second) 56 | 57 | sortStatues(statuses) 58 | for _, status := range statuses { 59 | lines = append(lines, []interface{}{ 60 | status.Id, 61 | status.Name, 62 | status.CreateTime, 63 | tuicommon.DecorateMessage{Message: status.Status, Decorate: playgroundStatusDecorate}, 64 | }) 65 | } 66 | 67 | output := common.FixedFormat(lines, 2) 68 | return output 69 | } 70 | -------------------------------------------------------------------------------- /internal/tui/targets.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-02-09 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package tui 24 | 25 | import ( 26 | "sort" 27 | 28 | task "github.com/opencurve/curveadm/internal/task/task/bs" 29 | "github.com/opencurve/curveadm/internal/tui/common" 30 | tuicommon "github.com/opencurve/curveadm/internal/tui/common" 31 | ) 32 | 33 | func sortTargets(targets []task.Target) { 34 | sort.Slice(targets, func(i, j int) bool { 35 | t1, t2 := targets[i], targets[j] 36 | return t1.Tid < t2.Tid 37 | }) 38 | } 39 | 40 | func FormatTargets(targets []task.Target) string { 41 | lines := [][]interface{}{} 42 | title := []string{"Tid", "Host", "Target Name", "Store", "Portal"} 43 | first, second := tuicommon.FormatTitle(title) 44 | lines = append(lines, first) 45 | lines = append(lines, second) 46 | 47 | sortTargets(targets) 48 | for _, target := range targets { 49 | lines = append(lines, []interface{}{ 50 | target.Tid, 51 | target.Host, 52 | target.Name, 53 | target.Store, 54 | target.Portal, 55 | }) 56 | } 57 | 58 | output := common.FixedFormat(lines, 2) 59 | return output 60 | } 61 | -------------------------------------------------------------------------------- /internal/utils/file.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-12-16 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package utils 26 | 27 | import ( 28 | "fmt" 29 | "os" 30 | "path/filepath" 31 | ) 32 | 33 | type VariantName struct { 34 | Name string 35 | CompressName string 36 | LocalCompressName string 37 | EncryptCompressName string 38 | } 39 | 40 | func RandFilename(dir string) string { 41 | return fmt.Sprintf("%s/%s", dir, RandString(8)) 42 | } 43 | 44 | func NewVariantName(name string) VariantName { 45 | return VariantName{ 46 | Name: name, 47 | CompressName: fmt.Sprintf("%s.tar.gz", name), 48 | LocalCompressName: fmt.Sprintf("%s.local.tar.gz", name), 49 | EncryptCompressName: fmt.Sprintf("%s-encrypted.tar.gz", name), 50 | } 51 | } 52 | 53 | func PathExist(path string) bool { 54 | _, err := os.Stat(path) 55 | return err == nil 56 | } 57 | 58 | func AbsPath(path string) string { 59 | absPath, err := filepath.Abs(path) 60 | if err != nil { 61 | return path 62 | } 63 | return absPath 64 | } 65 | 66 | func GetFilePermissions(path string) int { 67 | info, err := os.Stat(path) 68 | if err != nil { 69 | return -1 70 | } 71 | 72 | return int(info.Mode()) 73 | } 74 | 75 | func ReadFile(filename string) (string, error) { 76 | data, err := os.ReadFile(filename) 77 | if err != nil { 78 | return "", err 79 | } 80 | return string(data), nil 81 | } 82 | 83 | func WriteFile(filename, data string, mode int) error { 84 | file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.FileMode(mode)) 85 | if err != nil { 86 | return err 87 | } 88 | defer file.Close() 89 | 90 | n, err := file.WriteString(data) 91 | if err != nil { 92 | return err 93 | } else if n != len(data) { 94 | return fmt.Errorf("write abort") 95 | } 96 | 97 | return nil 98 | } 99 | -------------------------------------------------------------------------------- /internal/utils/file_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestVariantName(t *testing.T) { 10 | assert := assert.New(t) 11 | vname := NewVariantName("test") 12 | assert.Equal("test", vname.Name) 13 | assert.Equal("test.tar.gz", vname.CompressName) 14 | assert.Equal("test.local.tar.gz", vname.LocalCompressName) 15 | assert.Equal("test-encrypted.tar.gz", vname.EncryptCompressName) 16 | } 17 | -------------------------------------------------------------------------------- /internal/utils/fs.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-12-19 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package utils 24 | 25 | import ( 26 | "fmt" 27 | "path" 28 | ) 29 | 30 | func CheckMountPoint(mountPoint string) error { 31 | if !PathExist(mountPoint) { 32 | return fmt.Errorf("%s: path not exist", mountPoint) 33 | } else if !path.IsAbs(mountPoint) { 34 | return fmt.Errorf("%s: is not an absolute path", mountPoint) 35 | } 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /internal/utils/map.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package utils 26 | 27 | import ( 28 | "sync" 29 | ) 30 | 31 | type SafeMap struct { 32 | sync.RWMutex 33 | Map map[string]interface{} 34 | transaction bool 35 | } 36 | 37 | func NewSafeMap() *SafeMap { 38 | return &SafeMap{Map: map[string]interface{}{}} 39 | } 40 | 41 | func (m *SafeMap) Get(key string) interface{} { 42 | if m.transaction { 43 | val, _ := m.Map[key] 44 | return val 45 | } 46 | m.RLock() 47 | defer m.RUnlock() 48 | val, _ := m.Map[key] 49 | return val 50 | } 51 | 52 | func (m *SafeMap) Set(key string, value interface{}) { 53 | if m.transaction { 54 | m.Map[key] = value 55 | return 56 | } 57 | m.Lock() 58 | defer m.Unlock() 59 | m.Map[key] = value 60 | } 61 | 62 | func (m *SafeMap) TX(callback func(m *SafeMap) error) error { 63 | m.Lock() 64 | m.transaction = true 65 | err := callback(m) 66 | m.transaction = false 67 | m.Unlock() 68 | return err 69 | } 70 | -------------------------------------------------------------------------------- /pkg/log/glg/glg.go: -------------------------------------------------------------------------------- 1 | package glg 2 | -------------------------------------------------------------------------------- /pkg/log/glg/log.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2022-07-22 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package glg 26 | 27 | import ( 28 | "fmt" 29 | "strconv" 30 | 31 | "github.com/kpango/glg" 32 | ) 33 | 34 | const ( 35 | INDENT_SPACE = 4 36 | SPACE = " " 37 | ) 38 | 39 | func convertLevel(level string) glg.LEVEL { 40 | switch level { 41 | case "debug": 42 | return glg.DEBG 43 | case "info": 44 | return glg.INFO 45 | case "warn": 46 | return glg.WARN 47 | case "error": 48 | return glg.ERR 49 | default: 50 | return glg.DEBG 51 | } 52 | return glg.DEBG 53 | } 54 | 55 | func Init(level, filename string) error { 56 | writer := glg.FileWriter(filename, 0666) 57 | 58 | glg.Get(). 59 | SetMode(glg.WRITER). // default is STD 60 | SetLevel(convertLevel(level)). 61 | SetLineTraceMode(glg.TraceLineShort). 62 | AddLevelWriter(glg.DEBG, writer). 63 | AddLevelWriter(glg.INFO, writer). 64 | AddLevelWriter(glg.WARN, writer). 65 | AddLevelWriter(glg.ERR, writer) 66 | 67 | return nil 68 | } 69 | 70 | func Field(key string, val interface{}) string { 71 | switch val.(type) { 72 | case bool: 73 | return fmt.Sprintf("%s: %s", key, strconv.FormatBool(val.(bool))) 74 | case string: 75 | return fmt.Sprintf("%s: %s", key, val) 76 | case []byte: 77 | return fmt.Sprintf("%s: %s", key, string(val.([]byte))) 78 | case int: 79 | case int64: 80 | return fmt.Sprintf("%s: %d", key, val) 81 | case error: 82 | return fmt.Sprintf("%s: %s", key, val.(error).Error()) 83 | } 84 | return fmt.Sprintf("%s: %v", key, val) 85 | } 86 | 87 | func format(message string, val ...string) string { 88 | output := message + "\n" 89 | for _, v := range val { 90 | output = output + fmt.Sprintf("%*s%s\n", INDENT_SPACE, SPACE, v) 91 | } 92 | 93 | return output 94 | } 95 | 96 | func Debug(message string, val ...string) error { 97 | return glg.Debug(format(message, val...)) 98 | } 99 | 100 | func Info(message string, val ...string) error { 101 | return glg.Info(format(message, val...)) 102 | } 103 | 104 | func Warn(message string, val ...string) error { 105 | return glg.Warn(format(message, val...)) 106 | } 107 | 108 | func Error(message string, val ...string) error { 109 | return glg.Error(format(message, val...)) 110 | } 111 | 112 | func SwitchLevel(err error) func(message string, val ...string) error { 113 | if err != nil { 114 | return Error 115 | } 116 | return Info 117 | } 118 | -------------------------------------------------------------------------------- /pkg/log/log.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | package log 24 | 25 | import ( 26 | zaplog "github.com/pingcap/log" 27 | "go.uber.org/zap" 28 | "go.uber.org/zap/zapcore" 29 | ) 30 | 31 | var ( 32 | Debug = zaplog.Debug 33 | Info = zaplog.Info 34 | Warn = zaplog.Warn 35 | Error = zaplog.Error 36 | ) 37 | 38 | func Init(level, filename string) error { 39 | gl, props, err := zaplog.InitLogger(&zaplog.Config{ 40 | Level: level, 41 | File: zaplog.FileLogConfig{Filename: filename}, 42 | Format: "text", 43 | DisableTimestamp: false, 44 | }, zap.AddStacktrace(zapcore.FatalLevel)) 45 | 46 | if err != nil { 47 | return err 48 | } 49 | 50 | zaplog.ReplaceGlobals(gl, props) 51 | return nil 52 | } 53 | 54 | func SwitchLevel(err error) func(msg string, fields ...zap.Field) { 55 | if err != nil { 56 | return zaplog.Error 57 | } 58 | return zaplog.Info 59 | } 60 | 61 | func Field(key string, val interface{}) zap.Field { 62 | switch val.(type) { 63 | case bool: 64 | return zap.Bool(key, val.(bool)) 65 | case string: 66 | return zap.String(key, val.(string)) 67 | case []byte: 68 | return zap.String(key, string(val.([]byte))) 69 | case int: 70 | return zap.Int(key, val.(int)) 71 | case int64: 72 | return zap.Int64(key, val.(int64)) 73 | case error: 74 | return zap.String(key, val.(error).Error()) 75 | } 76 | return zap.Skip() 77 | } 78 | -------------------------------------------------------------------------------- /pkg/log/zaplog/log.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-10-15 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package zaplog 26 | 27 | import ( 28 | zaplog "github.com/pingcap/log" 29 | "go.uber.org/zap" 30 | "go.uber.org/zap/zapcore" 31 | ) 32 | 33 | var ( 34 | Debug = zaplog.Debug 35 | Info = zaplog.Info 36 | Warn = zaplog.Warn 37 | Error = zaplog.Error 38 | ) 39 | 40 | func Init(level, filename string) error { 41 | gl, props, err := zaplog.InitLogger(&zaplog.Config{ 42 | Level: level, 43 | File: zaplog.FileLogConfig{Filename: filename}, 44 | Format: "text", 45 | DisableTimestamp: false, 46 | }, zap.AddStacktrace(zapcore.FatalLevel)) 47 | 48 | if err != nil { 49 | return err 50 | } 51 | 52 | zaplog.ReplaceGlobals(gl, props) 53 | return nil 54 | } 55 | 56 | func SwitchLevel(err error) func(msg string, fields ...zap.Field) { 57 | if err != nil { 58 | return zaplog.Error 59 | } 60 | return zaplog.Info 61 | } 62 | 63 | func Field(key string, val interface{}) zap.Field { 64 | switch val.(type) { 65 | case bool: 66 | return zap.Bool(key, val.(bool)) 67 | case string: 68 | return zap.String(key, val.(string)) 69 | case []byte: 70 | return zap.String(key, string(val.([]byte))) 71 | case int: 72 | return zap.Int(key, val.(int)) 73 | case int64: 74 | return zap.Int64(key, val.(int64)) 75 | case error: 76 | return zap.String(key, val.(error).Error()) 77 | } 78 | return zap.Skip() 79 | } 80 | -------------------------------------------------------------------------------- /pkg/module/file.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 NetEase Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Project: CurveAdm 19 | * Created Date: 2021-12-12 20 | * Author: Jingli Chen (Wine93) 21 | */ 22 | 23 | // __SIGN_BY_WINE93__ 24 | 25 | package module 26 | 27 | import ( 28 | "errors" 29 | "fmt" 30 | "os" 31 | 32 | log "github.com/opencurve/curveadm/pkg/log/glg" 33 | ) 34 | 35 | const ( 36 | TEMP_DIR = "/tmp" 37 | ) 38 | 39 | var ( 40 | ERR_UNREACHED = errors.New("remote unreached") 41 | ) 42 | 43 | type FileManager struct { 44 | sshClient *SSHClient 45 | } 46 | 47 | func NewFileManager(sshClient *SSHClient) *FileManager { 48 | return &FileManager{sshClient: sshClient} 49 | } 50 | 51 | func (f *FileManager) Upload(localPath, remotePath string) error { 52 | if f.sshClient == nil { 53 | return ERR_UNREACHED 54 | } 55 | 56 | err := f.sshClient.Client().Upload(localPath, remotePath) 57 | log.SwitchLevel(err)("UploadFile", 58 | log.Field("remoteAddress", remoteAddr(f.sshClient)), 59 | log.Field("localPath", localPath), 60 | log.Field("remotePath", remotePath), 61 | log.Field("error", err)) 62 | return err 63 | } 64 | 65 | func (f *FileManager) Download(remotePath, localPath string) error { 66 | if f.sshClient == nil { 67 | return ERR_UNREACHED 68 | } 69 | 70 | err := f.sshClient.Client().Download(remotePath, localPath) 71 | log.SwitchLevel(err)("DownloadFile", 72 | log.Field("remoteAddress", remoteAddr(f.sshClient)), 73 | log.Field("remotePath", remotePath), 74 | log.Field("localPath", localPath), 75 | log.Field("error", err)) 76 | return err 77 | } 78 | 79 | func (f *FileManager) Install(content, destPath string) error { 80 | file, err := os.CreateTemp(TEMP_DIR, "curevadm.*.install") 81 | if err != nil { 82 | return err 83 | } 84 | defer os.Remove(file.Name()) 85 | 86 | n, err := file.WriteString(content) 87 | if err != nil { 88 | return err 89 | } else if n != len(content) { 90 | return fmt.Errorf("written: expect %d bytes, actually %d bytes", len(content), n) 91 | } 92 | 93 | return os.Rename(file.Name(), destPath) 94 | } 95 | -------------------------------------------------------------------------------- /playbook/logs/scripts/rotate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: bash rotate.sh /mnt/logs/curvefs/client 86400 4 | 5 | ############################ GLOBAL VARIABLES 6 | g_log_dir="$1" 7 | g_color_yellow=$(printf '\033[33m') 8 | g_color_red=$(printf '\033[31m') 9 | g_color_normal=$(printf '\033[0m') 10 | 11 | ############################ BASIC FUNCTIONS 12 | msg() { 13 | printf '%b' "${1}" >&2 14 | } 15 | 16 | success() { 17 | msg "${g_color_yellow}[✔]${g_color_normal} ${1}${2}" 18 | } 19 | 20 | die() { 21 | msg "${g_color_red}[✘]${g_color_normal} ${1}${2}" 22 | exit 1 23 | } 24 | 25 | ############################ FUNCTIONS 26 | precheck() { 27 | local log_dir="$1" 28 | if [ ! -d "${log_dir}" ]; then 29 | die "Log directory ${log_dir} does not exist.\n" 30 | fi 31 | 32 | if [ ! -w "${log_dir}" ]; then 33 | die "Log directory ${log_dir} is not writable.\n" 34 | fi 35 | } 36 | 37 | expired() { 38 | local path="$1" 39 | local timeout="$2" 40 | local mtime=$(stat -c %Y "${path}") 41 | local now=$(date +%s) 42 | if (( now - mtime > timeout )); then 43 | return 0 44 | fi 45 | return 1 46 | } 47 | 48 | delete() { 49 | local path="$1" 50 | rm "${path}" 51 | success "Delete ${path}\n" 52 | } 53 | 54 | rotate() { 55 | local log_dir="$1" 56 | local timeout="$2" 57 | for file in $(ls "${log_dir}" | grep -E '(access|curve-fuse|aws)(.+)(\.log)?'); do 58 | local path="${log_dir}/${file}" 59 | if expired "${path}" "${timeout}"; then 60 | delete "${path}" 61 | fi 62 | done 63 | } 64 | 65 | main() { 66 | local log_dir="$1" 67 | local timeout="$2" # seconds 68 | precheck "${log_dir}" 69 | rotate "${log_dir}" "${timeout}" 70 | } 71 | 72 | ############################ MAIN() 73 | main "$@" 74 | -------------------------------------------------------------------------------- /playbook/memcached/hosts.yaml: -------------------------------------------------------------------------------- 1 | global: 2 | user: curve 3 | ssh_port: 22 4 | private_key_file: /home/curve/.ssh/id_rsa 5 | 6 | hosts: 7 | - host: server-host1 8 | hostname: 10.0.1.1 9 | labels: 10 | - memcached 11 | envs: 12 | - SUDO_ALIAS=sudo 13 | - ENGINE=docker 14 | - IMAGE=memcached:1.6.17 15 | - LISTEN=10.0.1.1 16 | - PORT=11211 17 | - USER=root 18 | - MEMORY_LIMIT=32768 # item memory in megabytes 19 | - MAX_ITEM_SIZE=8m # adjusts max item size (default: 1m, min: 1k, max: 1024m) 20 | - EXT_PATH=/mnt/memcachefile/cachefile:1024G 21 | - EXT_WBUF_SIZE=8 # size in megabytes of page write buffers. 22 | - EXT_ITEM_AGE=1 # store items idle at least this long (seconds, default: no age limit) 23 | - VERBOSE="v" # v: verbose (print errors/warnings while in event loop) 24 | # vv: very verbose (also print client commands/responses) 25 | # vvv: extremely verbose (internal state transitions) 26 | - host: server-host2 27 | hostname: 10.0.1.2 28 | labels: 29 | - memcached 30 | envs: 31 | - SUDO_ALIAS=sudo 32 | - ENGINE=docker 33 | - IMAGE=memcached:1.6.17 34 | - LISTEN=10.0.1.2 35 | - PORT=11211 36 | - USER=root 37 | - MEMORY_LIMIT=32768 # item memory in megabytes 38 | - MAX_ITEM_SIZE=8m # adjusts max item size (default: 1m, min: 1k, max: 1024m) 39 | - EXT_PATH=/mnt/memcachefile/cachefile:1024G 40 | - EXT_WBUF_SIZE=8 # size in megabytes of page write buffers. 41 | - EXT_ITEM_AGE=1 # store items idle at least this long (seconds, default: no age limit) 42 | - VERBOSE="v" # v: verbose (print errors/warnings while in event loop) 43 | # vv: very verbose (also print client commands/responses) 44 | # vvv: extremely verbose (internal state transitions) 45 | - host: server-host3 46 | hostname: 10.0.1.3 47 | labels: 48 | - memcached 49 | envs: 50 | - SUDO_ALIAS=sudo 51 | - ENGINE=docker 52 | - IMAGE=memcached:1.6.17 53 | - LISTEN=10.0.1.3 54 | - PORT=11211 55 | - USER=root 56 | - MEMORY_LIMIT=32768 # item memory in megabytes 57 | - MAX_ITEM_SIZE=8m # adjusts max item size (default: 1m, min: 1k, max: 1024m) 58 | - EXT_PATH=/mnt/memcachefile/cachefile:1024G 59 | - EXT_WBUF_SIZE=8 # size in megabytes of page write buffers. 60 | - EXT_ITEM_AGE=1 # store items idle at least this long (seconds, default: no age limit) 61 | - VERBOSE="v" # v: verbose (print errors/warnings while in event loop) 62 | # vv: very verbose (also print client commands/responses) 63 | # vvv: extremely verbose (internal state transitions) 64 | -------------------------------------------------------------------------------- /playbook/memcached/scripts/clean.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | g_container_name="memcached-"${PORT} 4 | g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" 5 | g_rm_cmd="${SUDO_ALIAS} rm -rf" 6 | 7 | function msg() { 8 | printf '%b' "$1" >&2 9 | } 10 | 11 | function success() { 12 | msg "\33[32m[✔]\33[0m ${1}${2}" 13 | } 14 | 15 | function die() { 16 | msg "\33[31m[✘]\33[0m ${1}${2}" 17 | exit 1 18 | } 19 | 20 | precheck() { 21 | container_id=`${g_docker_cmd} ps --all --format "{{.ID}}" --filter name=${g_container_name} --all` 22 | if [ -z ${container_id} ]; then 23 | die "container [${g_container_name}] not exists!!!\n" 24 | exit 1 25 | fi 26 | } 27 | 28 | stop_container() { 29 | msg=`${g_docker_cmd} rm ${g_container_name}` 30 | if [ $? -ne 0 ];then 31 | die "${msg}\n" 32 | exit 1 33 | fi 34 | success "rm container[${g_container_name}]\n" 35 | } 36 | 37 | rm_cachefile() { 38 | cachefile_path=(${EXT_PATH//:/ }) 39 | ${g_rm_cmd} ${cachefile_path} 40 | } 41 | 42 | precheck 43 | stop_container 44 | rm_cachefile 45 | -------------------------------------------------------------------------------- /playbook/memcached/scripts/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | g_container_name="memcached-"${PORT} 4 | g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" 5 | g_rm_cmd="${SUDO_ALIAS} rm -rf" 6 | g_mkdir_cmd="${SUDO_ALIAS} mkdir -p" 7 | g_touch_cmd="${SUDO_ALIAS} touch" 8 | g_status="running" 9 | 10 | function msg() { 11 | printf '%b' "$1" >&2 12 | } 13 | 14 | function success() { 15 | msg "\33[32m[✔]\33[0m ${1}${2}" 16 | } 17 | 18 | function die() { 19 | msg "\33[31m[✘]\33[0m ${1}${2}" 20 | exit 1 21 | } 22 | 23 | precheck() { 24 | # check ext path 25 | get_status_container 26 | if [ "${EXT_PATH}" ] && [ ${g_status} != "running" ]; then 27 | cachefile_path=(${EXT_PATH//:/ }) 28 | ${g_rm_cmd} ${cachefile_path} 29 | ${g_mkdir_cmd} $(dirname ${cachefile_path}) 30 | ${g_touch_cmd} ${cachefile_path} 31 | fi 32 | } 33 | 34 | start_container() { 35 | ${g_docker_cmd} start ${g_container_name} >& /dev/null 36 | success "start container[${g_container_name}]\n" 37 | } 38 | 39 | get_status_container() { 40 | g_status=`${g_docker_cmd} inspect --format='{{.State.Status}}' ${g_container_name}` 41 | } 42 | 43 | precheck 44 | start_container 45 | -------------------------------------------------------------------------------- /playbook/memcached/scripts/status.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | g_container_name="memcached-"${PORT} 4 | g_start_args="" 5 | g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" 6 | g_volume_bind="" 7 | g_container_id="" 8 | g_status="running" 9 | 10 | function msg() { 11 | printf '%b' "$1" >&2 12 | } 13 | 14 | function success() { 15 | msg "\33[32m[✔]\33[0m ${1}${2}" 16 | } 17 | 18 | function die() { 19 | msg "\33[31m[✘]\33[0m ${1}${2}" 20 | exit 1 21 | } 22 | 23 | precheck() { 24 | g_container_id=`${g_docker_cmd} ps --all --format "{{.ID}}" --filter name=${g_container_name}` 25 | if [ -z ${g_container_id} ]; then 26 | success "container [${g_container_name}] not exists!!!" 27 | exit 1 28 | fi 29 | } 30 | 31 | show_info_container() { 32 | ${g_docker_cmd} ps --all --filter "name=${g_container_name}" --format="table {{.ID}}\t{{.Names}}\t{{.Status}}" 33 | } 34 | 35 | show_ip_port() { 36 | printf "memcached addr:\t%s:%d\n" ${LISTEN} ${PORT} 37 | } 38 | 39 | get_status_container() { 40 | g_status=`${g_docker_cmd} inspect --format='{{.State.Status}}' ${g_container_name}` 41 | if [ ${g_status} != "running" ]; then 42 | exit 1 43 | fi 44 | } 45 | 46 | precheck 47 | show_ip_port 48 | show_info_container 49 | get_status_container 50 | -------------------------------------------------------------------------------- /playbook/memcached/scripts/stop.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | g_container_name="memcached-"${PORT} 4 | g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" 5 | 6 | function msg() { 7 | printf '%b' "$1" >&2 8 | } 9 | 10 | function success() { 11 | msg "\33[32m[✔]\33[0m ${1}${2}" 12 | } 13 | 14 | function die() { 15 | msg "\33[31m[✘]\33[0m ${1}${2}" 16 | exit 1 17 | } 18 | 19 | precheck() { 20 | container_id=`${g_docker_cmd} ps --all --format "{{.ID}}" --filter name=${g_container_name}` 21 | if [ -z ${container_id} ]; then 22 | die "container [${g_container_name}] not exists!!!\n" 23 | exit 1 24 | fi 25 | } 26 | 27 | stop_container() { 28 | ${g_docker_cmd} stop ${g_container_name} >& /dev/null 29 | success "stop container[${g_container_name}]\n" 30 | } 31 | 32 | precheck 33 | stop_container 34 | -------------------------------------------------------------------------------- /plugins/README.md: -------------------------------------------------------------------------------- 1 | # CurveAdm Plugin 2 | 3 | Install plugin 4 | --- 5 | 6 | ```shell 7 | $ curveadm plugin install PLUGIN-NAME 8 | ``` 9 | 10 | Run plugin 11 | --- 12 | 13 | ```shell 14 | $ curveadm plugin run PLUGUN-NAME --hosts 'HOST1:HOST2:HOST3' --arg 'ARG1=arg1' --arg 'ARG2=arg2' 15 | ``` 16 | 17 | Remove plugin 18 | --- 19 | 20 | ```shell 21 | $ curveadm plugin rm PLUGIN-NAME 22 | ``` 23 | 24 | List plugins 25 | --- 26 | 27 | ```shell 28 | $ curveadm plugin ls 29 | ``` 30 | -------------------------------------------------------------------------------- /plugins/polarfs/META: -------------------------------------------------------------------------------- 1 | Name: polarfs 2 | Version: v0.0.2 3 | Released: 2022-05-24 4 | Description: Install PolarFS on targets (Debian only) 5 | Homepage: https://github.com/opencurve/curveadm/tree/master/plugins/polarfs 6 | Copyright: Jingli Chen (Wine93), NetEase Inc. 7 | -------------------------------------------------------------------------------- /plugins/polarfs/README.md: -------------------------------------------------------------------------------- 1 | # PolarFS plugin 2 | 3 | This plugin can help you install [PolarFS](PolarFS) to multiple host machines. 4 | 5 | NOTE: now we only support deploy in debian system. 6 | 7 | ## Usage 8 | 9 | * Install PolarFS on targets 10 | 11 | ```shell 12 | $ curveadm plugin run polarfs --hosts 'host1:host2:host3' --arg mds_listen_addr='10.0.1.1:6700,10.0.1.2:6700:10.0.1.3:6700' 13 | ``` 14 | 15 | [PolarPFS]: https://github.com/opencurve/PolarDB-FileSystem 16 | -------------------------------------------------------------------------------- /plugins/polarfs/main.yaml: -------------------------------------------------------------------------------- 1 | options: 2 | - key: mds_listen_addr 3 | bind_variable: mds_listen_addr 4 | default: 127.0.0.1 5 | - key: pfs_package_url 6 | bind_variable: pfs_package_url 7 | default: https://curveadm.nos-eastchina1.126.net/plugins/package/pfs_package.tar.gz 8 | - key: package_save_dir 9 | bind_variable: package_save_dir 10 | default: /tmp 11 | 12 | task: 13 | - name: Download PFS package tarball 14 | module: shell 15 | options: 16 | command: curl -ks ${pfs_package_url} -o ${package_save_dir}/pfs_package.tar.gz 17 | 18 | - name: Decompress PFS package tarball 19 | module: shell 20 | options: 21 | command: cd ${package_save_dir} && tar -zxvf pfs_package.tar.gz 22 | 23 | - name: Install PFS 24 | module: shell 25 | options: 26 | command: sudo dpkg -i ${package_save_dir}/pfs/curvebs_pfsd.deb 27 | 28 | - name: Create Curve library and config directory 29 | module: shell 30 | options: 31 | command: sudo mkdir -p /usr/lib/curve /etc/curve/conf 32 | 33 | - name: Decompress Curve library 34 | module: shell 35 | options: 36 | command: sudo tar -zxvf ${package_save_dir}/pfs/curvelib.tar.gz -C /usr/lib/curve --strip-components=1 37 | 38 | - name: echo 39 | module: shell 40 | options: 41 | command: echo ${mds_listen_addr} > /tmp/123000 42 | 43 | - name: Modify client config file 44 | module: shell 45 | options: 46 | command: sudo sed -i 's/__MDS_LISTEN_ADDRS__/${mds_listen_addr}/g' ${package_save_dir}/pfs/client.conf 47 | 48 | - name: Copy client config file to destination directory 49 | module: shell 50 | options: 51 | command: sudo cp -r ${package_save_dir}/pfs/client.conf /etc/curve/conf/client.conf 52 | -------------------------------------------------------------------------------- /plugins/shell/META: -------------------------------------------------------------------------------- 1 | Name: shell 2 | Version: v0.0.2 3 | Released: 2022-05-24 4 | Description: Execute shell commands on targets 5 | Homepage: https://github.com/opencurve/curveadm/tree/master/plugins/polarfs 6 | Copyright: Jingli Chen (Wine93), NetEase Inc. 7 | -------------------------------------------------------------------------------- /plugins/shell/README.md: -------------------------------------------------------------------------------- 1 | # Shell plugin 2 | 3 | Execute shell commands on targets 4 | 5 | ## Usage 6 | 7 | * execute shell command in localhost 8 | 9 | ```shell 10 | $ curveadm plugin run shell --arg cmd=hostname --arg local=true 11 | ``` 12 | 13 | * execute shell command in remote host (host1, host2, host3) 14 | 15 | ```shell 16 | $ curveadm plugin run shell --hosts 'host1:host2:host3' --arg cmd=hostname 17 | ``` 18 | -------------------------------------------------------------------------------- /plugins/shell/main.yaml: -------------------------------------------------------------------------------- 1 | options: 2 | - key: cmd 3 | bind_variable: command 4 | default: 5 | - key: local 6 | bind_variable: exec_in_local 7 | default: false 8 | 9 | task: 10 | - name: execute shell command 11 | module: shell 12 | options: 13 | command: ${command} 14 | exec_in_local: ${exec_in_local} 15 | bind_variable: 16 | out: output 17 | 18 | post_task: 19 | - name: show command output 20 | module: tui 21 | options: 22 | data: ${output} 23 | max_line_length: 50 24 | -------------------------------------------------------------------------------- /trace/README.md: -------------------------------------------------------------------------------- 1 | 2 | Usage 3 | --- 4 | 5 | 6 | * [curvefs-fuse-bt](curvefs-fuse-bt) 7 | 8 | ```shell 9 | ./curvefs-fuse-bt -p 12345 10 | ``` --------------------------------------------------------------------------------