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. 解读Raft(三 安全性)

    前言 之前的两篇文章更多的是在描述Raft算法的正常流程,没有过多的去讨论异常场景. 而实际在分布式系统中,我们更多的都是在应对网络不可用.机器故障等异常场景,所以本篇来讨论一下Raft协议的安全性, ...

  2. PHP单元测试使用

    单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证.对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类, ...

  3. Eclipse RCP中超长任务单线程,异步线程处理

    转自:http://www.blogjava.net/mydearvivian/articles/246028.html 在RCP程序中,常碰到某个线程执行时间比较很长的情况,若处理不好,用户体验度是 ...

  4. IT小团队的管理者的突围之道

    笔者前几天被问到一个问题,你在团队管理方面有什么值得分享的吗?咋一听,实用千言万语,但是事后回忆说出来的东西感觉空无一物,缺少干货.故想通过写一篇随笔思考整理一下,刷新一下自己对小团队管理的认知.这里 ...

  5. Python高阶函数之 - 装饰器

    高阶函数:  1. 函数名可以作为参数传入     2. 函数名可以作为返回值. python装饰器是用于拓展原来函数功能的一种函数 , 这个函数的特殊之处在于它的返回值也是一个函数 , 使用pyth ...

  6. FFPLAY的原理(七)

    同步音频 现在我们已经有了一个比较像样的播放器.所以让我们看一下还有哪些零碎的东西没处理.上次,我们掩饰了一点同步问题,也就是同步音频到视频而不是其它的同 步方式.我们将采用和视频一样的方式:做一个内 ...

  7. Kali Linux 工具使用中文说明书

    From: https://www.hackfun.org/kali-tools/kali-tools-zh.html 英文版地址:http://tools.kali.org/ 信息收集 accche ...

  8. HTML元素的专用传参数据属性

    把参数直接放到事件定义里面,类似下面这样,也是可以,但是这样不够Nice. <a href="javascript:void(0)" onclick="clickh ...

  9. HTML5学习系列之表单与文件

    article元素 article元素代表文档.页面或应用程序中独立的.完整的.可以独自被外部引用的内容.它可以是一篇博客或报刊中的文章.一篇论坛帖子.一段用户评论或独立的插件,或者其他任何独立的内容 ...

  10. FOF 全面科普贴(转载)

    看过那么多 FOF 科普贴,这份最全面!告转之~ 来自:https://xueqiu.com/7692591808/81852994 [ 导言 ] 看过那么多FOF科普贴,这份最全面! 昨天下午,青果 ...