Browse Source

*: add client.defrag and defrag cmd for etcdctl

Xiang Li 9 years ago
parent
commit
7c377fa703
4 changed files with 99 additions and 0 deletions
  1. 2 0
      clientv3/client.go
  2. 52 0
      clientv3/maintenance.go
  3. 44 0
      etcdctlv3/command/defrag_command.go
  4. 1 0
      etcdctlv3/main.go

+ 2 - 0
clientv3/client.go

@@ -39,6 +39,7 @@ type Client struct {
 	Lease
 	Watcher
 	Auth
+	Maintenance
 
 	conn   *grpc.ClientConn
 	cfg    Config
@@ -178,6 +179,7 @@ func newClient(cfg *Config) (*Client, error) {
 	client.Lease = NewLease(client)
 	client.Watcher = NewWatcher(client)
 	client.Auth = NewAuth(client)
+	client.Maintenance = &maintenance{c: client}
 
 	return client, nil
 }

+ 52 - 0
clientv3/maintenance.go

@@ -0,0 +1,52 @@
+// Copyright 2016 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+	"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
+	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+)
+
+type (
+	DefragmentResponse pb.DefragmentResponse
+)
+
+type Maintenance interface {
+	// Defragment defragments storage backend of the etcd member with given endpoint.
+	// Defragment is only needed when deleting a large number of keys and want to reclaim
+	// the resources.
+	// Defragment is an expensive operation. User should avoid defragmenting multiple members
+	// at the same time.
+	// To defragment multiple members in the cluster, user need to call defragment multiple
+	// times with different endpoints.
+	Defragment(ctx context.Context, endpoint string) (*DefragmentResponse, error)
+}
+
+type maintenance struct {
+	c *Client
+}
+
+func (m *maintenance) Defragment(ctx context.Context, endpoint string) (*DefragmentResponse, error) {
+	conn, err := m.c.Dial(endpoint)
+	if err != nil {
+		return nil, err
+	}
+	remote := pb.NewMaintenanceClient(conn)
+	resp, err := remote.Defragment(ctx, &pb.DefragmentRequest{})
+	if err != nil {
+		return nil, err
+	}
+	return (*DefragmentResponse)(resp), nil
+}

+ 44 - 0
etcdctlv3/command/defrag_command.go

@@ -0,0 +1,44 @@
+// Copyright 2016 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package command
+
+import (
+	"fmt"
+	"os"
+
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/spf13/cobra"
+	"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
+)
+
+// NewDefragCommand returns the cobra command for "Defrag".
+func NewDefragCommand() *cobra.Command {
+	return &cobra.Command{
+		Use:   "defrag",
+		Short: "defrag defragments the storage of the etcd members with given endpoints.",
+		Run:   defragCommandFunc,
+	}
+}
+
+func defragCommandFunc(cmd *cobra.Command, args []string) {
+	c := mustClientFromCmd(cmd)
+	for _, ep := range c.Endpoints() {
+		_, err := c.Defragment(context.TODO(), ep)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Failed to defragment etcd member[%s] (%v)\n", ep, err)
+		} else {
+			fmt.Printf("Finished defragmenting etcd member[%s]\n", ep)
+		}
+	}
+}

+ 1 - 0
etcdctlv3/main.go

@@ -56,6 +56,7 @@ func init() {
 		command.NewDelCommand(),
 		command.NewTxnCommand(),
 		command.NewCompactionCommand(),
+		command.NewDefragCommand(),
 		command.NewWatchCommand(),
 		command.NewVersionCommand(),
 		command.NewLeaseCommand(),