Skip to content

Commit

Permalink
*: enforce max lease TTL with 9,000,000,000 seconds
Browse files Browse the repository at this point in the history
math.MaxInt64 / time.Second is 9,223,372,036. 9,000,000,000 is easier to
remember/document.

Closes #9374.
  • Loading branch information
Iwasaki Yudai committed Mar 8, 2018
1 parent 211523f commit 1910096
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG-3.4.md
Expand Up @@ -124,3 +124,5 @@ See [code changes](https://github.com/coreos/etcd/compare/v3.3.0...v3.4.0) and [
- Previously, `etcd --auto-compaction-mode revision --auto-compaction-retention 1` was [translated to revision retention 3600000000000](https://github.com/coreos/etcd/issues/9337).
- Now, `etcd --auto-compaction-mode revision --auto-compaction-retention 1` is correctly parsed as revision retention 1.
- Enable etcd server [`raft.Config.CheckQuorum` when starting with `ForceNewCluster`](https://github.com/coreos/etcd/pull/9347).
- Fix [overflow by large TTL values for lease `Grant`](https://github.com/coreos/etcd/pull/9399)
- The endpoint now returns ErrLeaseTTLTooLarge when a requested TTL is larger than 9,000,000,000.
3 changes: 3 additions & 0 deletions clientv3/grpc_options.go → clientv3/options.go
Expand Up @@ -44,3 +44,6 @@ var (
// Some options are exposed to "clientv3.Config".
// Defaults will be overridden by the settings in "clientv3.Config".
var defaultCallOpts = []grpc.CallOption{defaultFailFast, defaultMaxCallSendMsgSize, defaultMaxCallRecvMsgSize}

// MaxLeaseTTL is the maximum lease TTL value
const MaxLeaseTTL = 9000000000
15 changes: 9 additions & 6 deletions etcdserver/api/v3rpc/rpctypes/error.go
Expand Up @@ -31,8 +31,9 @@ var (
ErrGRPCFutureRev = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision").Err()
ErrGRPCNoSpace = status.New(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded").Err()

ErrGRPCLeaseNotFound = status.New(codes.NotFound, "etcdserver: requested lease not found").Err()
ErrGRPCLeaseExist = status.New(codes.FailedPrecondition, "etcdserver: lease already exists").Err()
ErrGRPCLeaseNotFound = status.New(codes.NotFound, "etcdserver: requested lease not found").Err()
ErrGRPCLeaseExist = status.New(codes.FailedPrecondition, "etcdserver: lease already exists").Err()
ErrGRPCLeaseTTLTooLarge = status.New(codes.OutOfRange, "etcdserver: too large lease TTL").Err()

ErrGRPCMemberExist = status.New(codes.FailedPrecondition, "etcdserver: member ID already exist").Err()
ErrGRPCPeerURLExist = status.New(codes.FailedPrecondition, "etcdserver: Peer URLs already exists").Err()
Expand Down Expand Up @@ -80,8 +81,9 @@ var (
ErrorDesc(ErrGRPCFutureRev): ErrGRPCFutureRev,
ErrorDesc(ErrGRPCNoSpace): ErrGRPCNoSpace,

ErrorDesc(ErrGRPCLeaseNotFound): ErrGRPCLeaseNotFound,
ErrorDesc(ErrGRPCLeaseExist): ErrGRPCLeaseExist,
ErrorDesc(ErrGRPCLeaseNotFound): ErrGRPCLeaseNotFound,
ErrorDesc(ErrGRPCLeaseExist): ErrGRPCLeaseExist,
ErrorDesc(ErrGRPCLeaseTTLTooLarge): ErrGRPCLeaseTTLTooLarge,

ErrorDesc(ErrGRPCMemberExist): ErrGRPCMemberExist,
ErrorDesc(ErrGRPCPeerURLExist): ErrGRPCPeerURLExist,
Expand Down Expand Up @@ -131,8 +133,9 @@ var (
ErrFutureRev = Error(ErrGRPCFutureRev)
ErrNoSpace = Error(ErrGRPCNoSpace)

ErrLeaseNotFound = Error(ErrGRPCLeaseNotFound)
ErrLeaseExist = Error(ErrGRPCLeaseExist)
ErrLeaseNotFound = Error(ErrGRPCLeaseNotFound)
ErrLeaseExist = Error(ErrGRPCLeaseExist)
ErrLeaseTTLTooLarge = Error(ErrGRPCLeaseTTLTooLarge)

ErrMemberExist = Error(ErrGRPCMemberExist)
ErrPeerURLExist = Error(ErrGRPCPeerURLExist)
Expand Down
5 changes: 3 additions & 2 deletions etcdserver/api/v3rpc/util.go
Expand Up @@ -52,8 +52,9 @@ var toGRPCErrorMap = map[error]error{
etcdserver.ErrKeyNotFound: rpctypes.ErrGRPCKeyNotFound,
etcdserver.ErrCorrupt: rpctypes.ErrGRPCCorrupt,

lease.ErrLeaseNotFound: rpctypes.ErrGRPCLeaseNotFound,
lease.ErrLeaseExists: rpctypes.ErrGRPCLeaseExist,
lease.ErrLeaseNotFound: rpctypes.ErrGRPCLeaseNotFound,
lease.ErrLeaseExists: rpctypes.ErrGRPCLeaseExist,
lease.ErrLeaseTTLTooLarge: rpctypes.ErrGRPCLeaseTTLTooLarge,

auth.ErrRootUserNotExist: rpctypes.ErrGRPCRootUserNotExist,
auth.ErrRootRoleNotExist: rpctypes.ErrGRPCRootRoleNotExist,
Expand Down
14 changes: 11 additions & 3 deletions lease/lessor.go
Expand Up @@ -29,6 +29,9 @@ import (
// NoLease is a special LeaseID representing the absence of a lease.
const NoLease = LeaseID(0)

// MaxLeaseTTL is the maximum lease TTL value
const MaxLeaseTTL = 9000000000

var (
forever = time.Time{}

Expand All @@ -37,9 +40,10 @@ var (
// maximum number of leases to revoke per second; configurable for tests
leaseRevokeRate = 1000

ErrNotPrimary = errors.New("not a primary lessor")
ErrLeaseNotFound = errors.New("lease not found")
ErrLeaseExists = errors.New("lease already exists")
ErrNotPrimary = errors.New("not a primary lessor")
ErrLeaseNotFound = errors.New("lease not found")
ErrLeaseExists = errors.New("lease already exists")
ErrLeaseTTLTooLarge = errors.New("too large lease TTL")
)

// TxnDelete is a TxnWrite that only permits deletes. Defined here
Expand Down Expand Up @@ -198,6 +202,10 @@ func (le *lessor) Grant(id LeaseID, ttl int64) (*Lease, error) {
return nil, ErrLeaseNotFound
}

if ttl > MaxLeaseTTL {
return nil, ErrLeaseTTLTooLarge
}

// TODO: when lessor is under high load, it should give out lease
// with longer TTL to reduce renew load.
l := &Lease{
Expand Down
14 changes: 14 additions & 0 deletions lease/lessor_test.go
Expand Up @@ -451,6 +451,20 @@ func TestLessorExpireAndDemote(t *testing.T) {
}
}

func TestLessorMaxTTL(t *testing.T) {
dir, be := NewTestBackend(t)
defer os.RemoveAll(dir)
defer be.Close()

le := newLessor(be, minLeaseTTL)
defer le.Stop()

_, err := le.Grant(1, MaxLeaseTTL+1)
if err != ErrLeaseTTLTooLarge {
t.Fatalf("grant unexpectedly succeeded")
}
}

type fakeDeleter struct {
deleted []string
tx backend.BatchTx
Expand Down

0 comments on commit 1910096

Please sign in to comment.