package clientv3

import (
    "io"

    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
    StatusResponse     pb.StatusResponse
)

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.
    // 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)

    // Status gets the status of the endpoint.
    Status(ctx context.Context, endpoint string) (*StatusResponse, error)

    // Snapshot provides a reader for a snapshot of a backend.
    Snapshot(ctx context.Context) (io.ReadCloser, error)
}

type maintenance struct {
    c      *Client
    remote pb.MaintenanceClient
}

func NewMaintenance(c *Client) Maintenance {
    return &maintenance{c: c, remote: pb.NewMaintenanceClient(c.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.remote.Alarm(ctx, req, grpc.FailFast(false))
        if err == nil {
            return (*AlarmResponse)(resp), nil
        }
        if isHaltErr(ctx, err) {
            return nil, toErr(ctx, 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, toErr(ctx, err)
        }
        ret := AlarmResponse{}
        for _, am := range ar.Alarms {
            dresp, derr := m.AlarmDisarm(ctx, (*AlarmMember)(am))
            if derr != nil {
                return nil, toErr(ctx, derr)
            }
            ret.Alarms = append(ret.Alarms, dresp.Alarms...)
        }
        return &ret, nil
    }

    resp, err := m.remote.Alarm(ctx, req, grpc.FailFast(false))
    if err == nil {
        return (*AlarmResponse)(resp), nil
    }
    return nil, toErr(ctx, err)
}

func (m *maintenance) Defragment(ctx context.Context, endpoint string) (*DefragmentResponse, error) {
    conn, err := m.c.Dial(endpoint)
    if err != nil {
        return nil, toErr(ctx, err)
    }
    defer conn.Close()
    remote := pb.NewMaintenanceClient(conn)
    resp, err := remote.Defragment(ctx, &pb.DefragmentRequest{}, grpc.FailFast(false))
    if err != nil {
        return nil, toErr(ctx, err)
    }
    return (*DefragmentResponse)(resp), nil
}

func (m *maintenance) Status(ctx context.Context, endpoint string) (*StatusResponse, error) {
    conn, err := m.c.Dial(endpoint)
    if err != nil {
        return nil, toErr(ctx, err)
    }
    defer conn.Close()
    remote := pb.NewMaintenanceClient(conn)
    resp, err := remote.Status(ctx, &pb.StatusRequest{}, grpc.FailFast(false))
    if err != nil {
        return nil, toErr(ctx, err)
    }
    return (*StatusResponse)(resp), nil
}

func (m *maintenance) Snapshot(ctx context.Context) (io.ReadCloser, error) {
    ss, err := m.remote.Snapshot(ctx, &pb.SnapshotRequest{}, grpc.FailFast(false))
    if err != nil {
        return nil, toErr(ctx, err)
    }

    pr, pw := io.Pipe()
    go func() {
        for {
            resp, err := ss.Recv()
            if err != nil {
                pw.CloseWithError(err)
                return
            }
            if resp == nil && err == nil {
                break
            }
            if _, werr := pw.Write(resp.Blob); werr != nil {
                pw.CloseWithError(werr)
                return
            }
        }
        pw.Close()
    }()
    return pr, nil
}

maintenance.go的更多相关文章

  1. 第24/24周 数据库维护(Database Maintenance)

    哇哦,光阴似箭!欢迎回到性能调优培训的最后一期.今天我会详细讲下SQL Server里的数据库维护,尤其是索引维护操作,还有如何进行数据库维护. 索引维护 作为一个DBA,数据库维护是你工作中非常重要 ...

  2. 玩转PowerShell第三节——【SCOM Maintenance Mode】-技术&分享

    概述 Microsoft System Center Operations Manager 2007 sp1(SCOM)是微软推出的专业系统监控软件,可以监控部署在网络中的服务器.应用系统和客户端,提 ...

  3. cloud maintenance of OpenNebula

    OpenNebula 4.4.1 maintenance release,官方建议当前的生产环境使用3.x or 4.x的其它版本; php调用curl工具伪造ip Upgrading from Op ...

  4. gdb在运行maintenance info program-spaces命令时coredump

    coredump时的信息: (gdb) maintenance info program-spaces *** Error in `gdb': free(): invalid pointer: 0x0 ...

  5. Setup SQL Server 2008 Maintenance Plan Email Notifications

    一条龙作完,如何设置EXCHANGE的操作员邮件通知.. ~~~~ http://808techblog.com/2009/07/setup-sql-server-2008-maintena.html ...

  6. The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.

    The server is temporarily unable to service your request due to maintenance downtime or capacity pro ...

  7. 产品 线上 保持 和 支持 服务 (Support and maintenance solutions)

    Maintenance and support are the key factors for the smooth functioning of ERP solutions. ERP mainten ...

  8. 一个"Median Maintenance"问题

    题目要求: Download the text file here. The goal of this problem is to implement the "Median Mainten ...

  9. Maste Note for OCR / Vote disk Maintenance Operations (ADD/REMOVE/REPLACE/MOVE)

    Doc ID 428681.1 Applies to: Oracle Database - Enterprise Edition - Version 10.2.0.1 to 11.2.0.1.0 [R ...

  10. Oracle E-Business Suite Maintenance Guide Release 12.2(Patching Procedures)

    更多内容参考: http://docs.oracle.com/cd/E51111_01/current/acrobat/122ebsmt.zip Preparing for Patching For ...

随机推荐

  1. 深入浅出web服务器与python应用程序之间的联系

    简单来说,Web服务器是在运行在物理服务器上的一个程序,它永久地等待客户端(主要是浏览器,比如Chrome,Firefox等)发送请求.Web 服务器接受 Http Request,返回 Respon ...

  2. Robot Framework + Pywinauto 框架实现Windows GUI Automation

    Robot Framework is a generic test automation framework for acceptance testing and acceptance test-dr ...

  3. Python list 两个不等长列表交叉合并

    遇到一个需求,需要对两个长度不一定相等的列表进行交叉合并.像拉拉链一样(两边的拉链不一定相等). 如: a = [1, 3, 5] b = [2, 4, 6, 8] 需将a, b 合并为 c c = ...

  4. Maximum Subarray(最大子数组)

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  5. 想要薪资20-30K,Python程序员认真敲代码就够了!

    在这个年代,互联网的飞速壮大大家有目共睹,除了表露出的公共受益,其中计算机编程者也是做出了巨大的贡献,即使外国编程语言仍旧属于领导者,但是在互联网的壮大下,我们这是"地球村",国内 ...

  6. 第三次 orm自动建表及遇到的问题

    Hibernate支持自动建表,在开发阶段很方便,可以保证hbm与数据库表结构的自动同步. 方法很简单,在hibernate.cfg.xml内加入 <property name="hi ...

  7. springboot集成rabbitmq(实战)

    RabbitMQ简介RabbitMQ使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现(AMQP的主要特征是面向消息.队列.路由.可靠性.安全).支持多种客户端,如:Python.Ru ...

  8. Python_从字符串中提取号码

    import re telNumber = '''Suppose my Phone No. is 0535-1234567,yours is 010-12345678,his is 025-87654 ...

  9. Thymeleaf中each标签遍历list如何获取index

    <tr th:each="user,userStat:${users}">userStat是状态变量,有 index,count,size,current,even,o ...

  10. angular访问后台服务及监控会话超时的封装

    angular访问后台服务及监控会话超时的封装 angular本身自带访问组件http和httpclient,组件本身都是异步模式访问.本文只列举了对http组件的封装同时也一同处理会话超时监控. 获 ...