瀏覽代碼

clientv3: AlarmList and AlarmDisarm

Anthony Romano 9 年之前
父節點
當前提交
c91b2d098d
共有 2 個文件被更改,包括 96 次插入1 次删除
  1. 1 1
      clientv3/client.go
  2. 95 0
      clientv3/maintenance.go

+ 1 - 1
clientv3/client.go

@@ -184,7 +184,7 @@ func newClient(cfg *Config) (*Client, error) {
 	client.Lease = NewLease(client)
 	client.Watcher = NewWatcher(client)
 	client.Auth = NewAuth(client)
-	client.Maintenance = &maintenance{c: client}
+	client.Maintenance = NewMaintenance(client)
 	if cfg.Logger != nil {
 		logger.Set(cfg.Logger)
 	} else {

+ 95 - 0
clientv3/maintenance.go

@@ -15,15 +15,26 @@
 package clientv3
 
 import (
+	"sync"
+
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	"golang.org/x/net/context"
+	"google.golang.org/grpc"
 )
 
 type (
 	DefragmentResponse pb.DefragmentResponse
+	AlarmResponse      pb.AlarmResponse
+	AlarmMember        pb.AlarmMember
 )
 
 type Maintenance interface {
+	// AlarmList gets all active alarms.
+	AlarmList(ctx context.Context) (*AlarmResponse, error)
+
+	// AlarmDisarm disarms a given alarm.
+	AlarmDisarm(ctx context.Context, m *AlarmMember) (*AlarmResponse, error)
+
 	// 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.
@@ -36,6 +47,72 @@ type Maintenance interface {
 
 type maintenance struct {
 	c *Client
+
+	mu     sync.Mutex
+	conn   *grpc.ClientConn // conn in-use
+	remote pb.MaintenanceClient
+}
+
+func NewMaintenance(c *Client) Maintenance {
+	conn := c.ActiveConnection()
+	return &maintenance{
+		c:      c,
+		conn:   conn,
+		remote: pb.NewMaintenanceClient(conn),
+	}
+}
+
+func (m *maintenance) AlarmList(ctx context.Context) (*AlarmResponse, error) {
+	req := &pb.AlarmRequest{
+		Action:   pb.AlarmRequest_GET,
+		MemberID: 0,                 // all
+		Alarm:    pb.AlarmType_NONE, // all
+	}
+	for {
+		resp, err := m.getRemote().Alarm(ctx, req)
+		if err == nil {
+			return (*AlarmResponse)(resp), nil
+		}
+		if isHalted(ctx, err) {
+			return nil, err
+		}
+		if err = m.switchRemote(err); err != nil {
+			return nil, err
+		}
+	}
+}
+
+func (m *maintenance) AlarmDisarm(ctx context.Context, am *AlarmMember) (*AlarmResponse, error) {
+	req := &pb.AlarmRequest{
+		Action:   pb.AlarmRequest_DEACTIVATE,
+		MemberID: am.MemberID,
+		Alarm:    am.Alarm,
+	}
+
+	if req.MemberID == 0 && req.Alarm == pb.AlarmType_NONE {
+		ar, err := m.AlarmList(ctx)
+		if err != nil {
+			return nil, err
+		}
+		ret := AlarmResponse{}
+		for _, am := range ar.Alarms {
+			dresp, derr := m.AlarmDisarm(ctx, (*AlarmMember)(am))
+			if derr != nil {
+				return nil, derr
+			}
+			ret.Alarms = append(ret.Alarms, dresp.Alarms...)
+		}
+		return &ret, nil
+	}
+
+	resp, err := m.getRemote().Alarm(ctx, req)
+	if err == nil {
+		return (*AlarmResponse)(resp), nil
+	}
+	if !isHalted(ctx, err) {
+		go m.switchRemote(err)
+	}
+	return nil, err
 }
 
 func (m *maintenance) Defragment(ctx context.Context, endpoint string) (*DefragmentResponse, error) {
@@ -50,3 +127,21 @@ func (m *maintenance) Defragment(ctx context.Context, endpoint string) (*Defragm
 	}
 	return (*DefragmentResponse)(resp), nil
 }
+
+func (m *maintenance) getRemote() pb.MaintenanceClient {
+	m.mu.Lock()
+	defer m.mu.Unlock()
+	return m.remote
+}
+
+func (m *maintenance) switchRemote(prevErr error) error {
+	m.mu.Lock()
+	defer m.mu.Unlock()
+	newConn, err := m.c.retryConnection(m.conn, prevErr)
+	if err != nil {
+		return err
+	}
+	m.conn = newConn
+	m.remote = pb.NewMaintenanceClient(m.conn)
+	return nil
+}