From 3e6357b1cb3d956d854efd8b91c042dcc9568030 Mon Sep 17 00:00:00 2001 From: wangyanghack Date: Fri, 17 Feb 2023 09:17:16 +0800 Subject: [PATCH] add create volume cli --- tools-v2/internal/error/error.go | 4 +- tools-v2/internal/utils/proto.go | 12 ++ tools-v2/pkg/cli/command/curvebs/bs.go | 2 + .../pkg/cli/command/curvebs/create/create.go | 151 ++++++++++++++++++ tools-v2/pkg/config/bs.go | 24 +++ 5 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 tools-v2/pkg/cli/command/curvebs/create/create.go diff --git a/tools-v2/internal/error/error.go b/tools-v2/internal/error/error.go index 56aba2443d..9d1bc96e43 100644 --- a/tools-v2/internal/error/error.go +++ b/tools-v2/internal/error/error.go @@ -372,7 +372,9 @@ var ( ErrBsListZone = func() *CmdError { return NewInternalCmdError(39, "list zone fail. the error is %s") } - + ErrBsCreateFile = func() *CmdError { + return NewInternalCmdError(40, "create file fail. the error is %s") + } ErrBsDeleteFile = func() *CmdError { return NewInternalCmdError(40, "delete file fail. the error is %s") } diff --git a/tools-v2/internal/utils/proto.go b/tools-v2/internal/utils/proto.go index 1911f824b1..acce0c61f6 100644 --- a/tools-v2/internal/utils/proto.go +++ b/tools-v2/internal/utils/proto.go @@ -29,6 +29,7 @@ import ( cmderror "github.com/opencurve/curve/tools-v2/internal/error" "github.com/opencurve/curve/tools-v2/proto/curvefs/proto/common" "github.com/opencurve/curve/tools-v2/proto/curvefs/proto/topology" + "github.com/opencurve/curve/tools-v2/proto/proto/nameserver2" ) func TranslateFsType(fsType string) (common.FSType, *cmderror.CmdError) { @@ -42,6 +43,17 @@ func TranslateFsType(fsType string) (common.FSType, *cmderror.CmdError) { return common.FSType(value), &retErr } +func TranslateFileType(fileType string) (nameserver2.FileType, *cmderror.CmdError) { + fs := strings.ToUpper("INODE_" + fileType) + value := nameserver2.FileType_value[fs] + var retErr cmderror.CmdError + if value == 0 { + retErr = *cmderror.ErrUnknownFsType() + retErr.Format(fileType) + } + return nameserver2.FileType(value), &retErr +} + func TranslateBitmapLocation(bitmapLocation string) (common.BitmapLocation, *cmderror.CmdError) { value := common.BitmapLocation_value[bitmapLocation] var retErr cmderror.CmdError diff --git a/tools-v2/pkg/cli/command/curvebs/bs.go b/tools-v2/pkg/cli/command/curvebs/bs.go index 9919af0abc..d036f9ee50 100644 --- a/tools-v2/pkg/cli/command/curvebs/bs.go +++ b/tools-v2/pkg/cli/command/curvebs/bs.go @@ -26,6 +26,7 @@ import ( "github.com/spf13/cobra" basecmd "github.com/opencurve/curve/tools-v2/pkg/cli/command" + "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/create" "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/delete" "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/list" "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/query" @@ -43,6 +44,7 @@ func (bsCmd *CurveBsCommand) AddSubCommands() { list.NewListCommand(), query.NewQueryCommand(), status.NewStatusCommand(), + create.NewCreateCommand(), delete.NewDeleteCommand(), ) } diff --git a/tools-v2/pkg/cli/command/curvebs/create/create.go b/tools-v2/pkg/cli/command/curvebs/create/create.go new file mode 100644 index 0000000000..a6d229249d --- /dev/null +++ b/tools-v2/pkg/cli/command/curvebs/create/create.go @@ -0,0 +1,151 @@ +/* + * Project: tools-v2 + * Created Date: 2022-11-14 + * Author: shentupenghui@gmail.com + */ + +package create + +import ( + "context" + cmderror "github.com/opencurve/curve/tools-v2/internal/error" + cobrautil "github.com/opencurve/curve/tools-v2/internal/utils" + basecmd "github.com/opencurve/curve/tools-v2/pkg/cli/command" + "github.com/opencurve/curve/tools-v2/pkg/config" + "github.com/opencurve/curve/tools-v2/pkg/output" + "github.com/opencurve/curve/tools-v2/proto/proto/nameserver2" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "google.golang.org/grpc" +) + +const ( + createCliExample = `curve bs create --filename /curvebs-file-name --user username --filelength the_length_num_of_volume [--password password]` +) + +type CreateCertainFileRpc struct { + Info *basecmd.Rpc + Request *nameserver2.CreateFileRequest + mdsClient nameserver2.CurveFSServiceClient +} + +var _ basecmd.RpcFunc = (*CreateCertainFileRpc)(nil) + +// CreateCommand definition +type CreateCommand struct { + basecmd.FinalCurveCmd + Rpc *CreateCertainFileRpc + Response *nameserver2.CreateFileResponse +} + +var _ basecmd.FinalCurveCmdFunc = (*CreateCommand)(nil) + +func (gRpc *CreateCertainFileRpc) NewRpcClient(cc grpc.ClientConnInterface) { + gRpc.mdsClient = nameserver2.NewCurveFSServiceClient(cc) + +} + +func (gRpc *CreateCertainFileRpc) Stub_Func(ctx context.Context) (interface{}, error) { + return gRpc.mdsClient.CreateFile(ctx, gRpc.Request) +} + +func (createCommand *CreateCommand) Init(cmd *cobra.Command, args []string) error { + mdsAddrs, err := config.GetBsMdsAddrSlice(createCommand.Cmd) + if err.TypeCode() != cmderror.CODE_SUCCESS { + return err.ToError() + } + //get the default timeout and retrytimes + timeout := config.GetFlagDuration(createCommand.Cmd, config.RPCTIMEOUT) + retrytimes := config.GetFlagInt32(createCommand.Cmd, config.RPCRETRYTIMES) + filename := config.GetBsFlagString(createCommand.Cmd, config.CURVEBS_FILENAME) + username := config.GetBsFlagString(createCommand.Cmd, config.CURVEBS_USER) + password := config.GetBsFlagString(createCommand.Cmd, config.CURVEBS_PASSWORD) + date, errDat := cobrautil.GetTimeofDayUs() + if errDat.TypeCode() != cmderror.CODE_SUCCESS { + return errDat.ToError() + } + + fileLength := config.GetFlagUint64(createCommand.Cmd, config.CURVEBS_FILELENGTH) + fileTypeStr := config.GetBsFlagString(createCommand.Cmd, config.CURVEBS_FILETYPE) + //fileTypeStr := "directory" + fileType, errFstype := cobrautil.TranslateFileType(fileTypeStr) + if errFstype.TypeCode() != cmderror.CODE_SUCCESS { + return errFstype.ToError() + } + createRequest := nameserver2.CreateFileRequest{ + FileName: &filename, + Owner: &username, + Date: &date, + FileType: &fileType, + FileLength: &fileLength, + } + if username == viper.GetString(config.VIPER_CURVEBS_USER) && len(password) != 0 { + strSig := cobrautil.GetString2Signature(date, username) + sig := cobrautil.CalcString2Signature(strSig, password) + createRequest.Signature = &sig + } + createCommand.Rpc = &CreateCertainFileRpc{ + Info: basecmd.NewRpc(mdsAddrs, timeout, retrytimes, "CreateFile"), + Request: &createRequest, + } + header := []string{cobrautil.ROW_RESULT, cobrautil.ROW_REASON} + createCommand.SetHeader(header) + createCommand.TableNew.SetAutoMergeCellsByColumnIndex(cobrautil.GetIndexSlice( + createCommand.Header, header, + )) + return nil +} + +func (createCommand *CreateCommand) RunCommand(cmd *cobra.Command, args []string) error { + out := make(map[string]string) + result, err := basecmd.GetRpcResponse(createCommand.Rpc.Info, createCommand.Rpc) + if err.TypeCode() != cmderror.CODE_SUCCESS { + out[cobrautil.ROW_RESULT] = "failed" + out[cobrautil.ROW_REASON] = err.Message + return nil + } + createCommand.Response = result.(*nameserver2.CreateFileResponse) + if createCommand.Response.GetStatusCode() != nameserver2.StatusCode_kOK { + err = cmderror.ErrBsCreateFile() + out[cobrautil.ROW_RESULT] = "failed" + out[cobrautil.ROW_REASON] = err.Message + return nil + } + out[cobrautil.ROW_RESULT] = "success" + out[cobrautil.ROW_REASON] = "" + list := cobrautil.Map2List(out, []string{cobrautil.ROW_RESULT, cobrautil.ROW_REASON}) + createCommand.TableNew.Append(list) + return nil +} + +func (createCommand *CreateCommand) Print(cmd *cobra.Command, args []string) error { + return output.FinalCmdOutput(&createCommand.FinalCurveCmd, createCommand) +} + +func (createCommand *CreateCommand) ResultPlainOutput() error { + return output.FinalCmdOutputPlain(&createCommand.FinalCurveCmd) +} + +func (createCommand *CreateCommand) AddFlags() { + config.AddBsMdsFlagOption(createCommand.Cmd) + config.AddRpcTimeoutFlag(createCommand.Cmd) + config.AddRpcRetryTimesFlag(createCommand.Cmd) + config.AddBsFilenameRequiredFlag(createCommand.Cmd) + config.AddBsUserOptionFlag(createCommand.Cmd) + config.AddBsPasswordOptionFlag(createCommand.Cmd) + config.AddBsFileLengthOptionFlag(createCommand.Cmd) + config.AddBsFileTypeRequiredFlag(createCommand.Cmd) +} + +// NewCreateCommand return the mid cli +func NewCreateCommand() *cobra.Command { + createCommand := &CreateCommand{ + FinalCurveCmd: basecmd.FinalCurveCmd{ + Use: "create", + Short: "create certain file in curvebs", + Example: createCliExample, + }, + } + basecmd.NewFinalCurveCli(&createCommand.FinalCurveCmd, createCommand) + return createCommand.Cmd +} diff --git a/tools-v2/pkg/config/bs.go b/tools-v2/pkg/config/bs.go index 19a5bdd2b5..2c432a6d5a 100644 --- a/tools-v2/pkg/config/bs.go +++ b/tools-v2/pkg/config/bs.go @@ -50,6 +50,8 @@ const ( VIPER_CURVEBS_PASSWORD = "curvebs.root.password" CURVEBS_DEFAULT_PASSWORD = "root_password" CURVEBS_FILENAME = "filename" + CURVEBS_FILETYPE = "filetype" + CURVEBS_FILELENGTH = "filelength" VIPER_CURVEBS_FILENAME = "curvebs.filename" CURVEBS_FORCEDELETE = "forcedelete" CURVEBS_DEFAULT_FORCEDELETE = false @@ -87,6 +89,7 @@ var ( CURVEBS_USER: CURVEBS_DEFAULT_USER, CURVEBS_PASSWORD: CURVEBS_DEFAULT_PASSWORD, CURVEBS_FORCEDELETE: CURVEBS_DEFAULT_FORCEDELETE, + CURVEBS_FILELENGTH: 20, } ) @@ -113,6 +116,15 @@ func AddBsStringSliceRequiredFlag(cmd *cobra.Command, name string, usage string) } } +func AddBsFileTypeRequiredFlag(cmd *cobra.Command) { + AddBsStringRequiredFlag(cmd, CURVEBS_FILETYPE, "directory,pagefile,appendfile,appendecfile,snapshot_pagefile") +} + +// Filelength [option] +func AddBsFileLengthOptionFlag(cmd *cobra.Command) { + AddBsIntOptionFlag(cmd, CURVEBS_FILELENGTH, "curve bs file length") +} + func AddBsStringOptionFlag(cmd *cobra.Command, name string, usage string) { defaultValue := FLAG2DEFAULT[name] if defaultValue == nil { @@ -125,6 +137,18 @@ func AddBsStringOptionFlag(cmd *cobra.Command, name string, usage string) { } } +func AddBsIntOptionFlag(cmd *cobra.Command, name string, usage string) { + defaultValue := BSFLAG2DEFAULT[name] + if defaultValue == nil { + defaultValue = "" + } + cmd.Flags().Int(name, defaultValue.(int), usage) + err := viper.BindPFlag(BSFLAG2VIPER[name], cmd.Flags().Lookup(name)) + if err != nil { + cobra.CheckErr(err) + } +} + // add bs required flag func AddBsStringRequiredFlag(cmd *cobra.Command, name string, usage string) { cmd.Flags().String(name, "", usage+color.Red.Sprint("[required]"))