|
|
@@ -16,8 +16,10 @@ package command
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
+ "io"
|
|
|
"os"
|
|
|
"strconv"
|
|
|
+ "time"
|
|
|
|
|
|
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/spf13/cobra"
|
|
|
"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
|
|
|
@@ -34,6 +36,7 @@ func NewLeaseCommand() *cobra.Command {
|
|
|
|
|
|
lc.AddCommand(NewLeaseCreateCommand())
|
|
|
lc.AddCommand(NewLeaseRevokeCommand())
|
|
|
+ lc.AddCommand(NewLeaseKeepAliveCommand())
|
|
|
|
|
|
return lc
|
|
|
}
|
|
|
@@ -121,3 +124,69 @@ func leaseRevokeCommandFunc(cmd *cobra.Command, args []string) {
|
|
|
}
|
|
|
fmt.Printf("lease %016x revoked\n", id)
|
|
|
}
|
|
|
+
|
|
|
+// NewLeaseKeepAliveCommand returns the cobra command for "lease keep-alive".
|
|
|
+func NewLeaseKeepAliveCommand() *cobra.Command {
|
|
|
+ lc := &cobra.Command{
|
|
|
+ Use: "keep-alive",
|
|
|
+ Short: "keep-alive is used to keep leases alive.",
|
|
|
+
|
|
|
+ Run: leaseKeepAliveCommandFunc,
|
|
|
+ }
|
|
|
+
|
|
|
+ return lc
|
|
|
+}
|
|
|
+
|
|
|
+// leaseKeepAliveCommandFunc executes the "lease keep-alive" command.
|
|
|
+func leaseKeepAliveCommandFunc(cmd *cobra.Command, args []string) {
|
|
|
+ if len(args) != 1 {
|
|
|
+ ExitWithError(ExitBadArgs, fmt.Errorf("lease keep-alive command needs lease ID as argument"))
|
|
|
+ }
|
|
|
+
|
|
|
+ id, err := strconv.ParseInt(args[0], 16, 64)
|
|
|
+ if err != nil {
|
|
|
+ ExitWithError(ExitBadArgs, fmt.Errorf("bad lease ID arg (%v), expecting ID in Hex", err))
|
|
|
+ }
|
|
|
+
|
|
|
+ endpoint, err := cmd.Flags().GetString("endpoint")
|
|
|
+ if err != nil {
|
|
|
+ ExitWithError(ExitError, err)
|
|
|
+ }
|
|
|
+ conn, err := grpc.Dial(endpoint)
|
|
|
+ if err != nil {
|
|
|
+ ExitWithError(ExitBadConnection, err)
|
|
|
+ }
|
|
|
+ lease := pb.NewLeaseClient(conn)
|
|
|
+ kStream, err := lease.LeaseKeepAlive(context.TODO())
|
|
|
+ if err != nil {
|
|
|
+ ExitWithError(ExitBadConnection, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ nextC := make(chan int64, 1)
|
|
|
+ go leaseKeepAliveRecvLoop(kStream, nextC)
|
|
|
+
|
|
|
+ req := &pb.LeaseKeepAliveRequest{ID: id}
|
|
|
+ for {
|
|
|
+ err := kStream.Send(req)
|
|
|
+ if err != nil {
|
|
|
+ ExitWithError(ExitError, fmt.Errorf("failed to keep-alive lease (%v)", err))
|
|
|
+ }
|
|
|
+ next := <-nextC
|
|
|
+ time.Sleep(time.Duration(next/2) * time.Second)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func leaseKeepAliveRecvLoop(kStream pb.Lease_LeaseKeepAliveClient, nextC chan int64) {
|
|
|
+ for {
|
|
|
+ resp, err := kStream.Recv()
|
|
|
+ if err == io.EOF {
|
|
|
+ os.Exit(ExitSuccess)
|
|
|
+ }
|
|
|
+ if err != nil {
|
|
|
+ ExitWithError(ExitError, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ fmt.Printf("lease %016x keepalived with TTL(%d)\n", resp.ID, resp.TTL)
|
|
|
+ nextC <- resp.TTL
|
|
|
+ }
|
|
|
+}
|