diff --git a/cmd/storagenode/gracefulexit.go b/cmd/storagenode/gracefulexit.go new file mode 100644 index 000000000..03fc47620 --- /dev/null +++ b/cmd/storagenode/gracefulexit.go @@ -0,0 +1,141 @@ +// Copyright (C) 2019 Storj Labs, Inc. +// See LICENSE for copying information. + +package main + +import ( + "bufio" + "context" + "fmt" + "os" + "strings" + "text/tabwriter" + + "github.com/segmentio/go-prompt" + "github.com/spf13/cobra" + "github.com/zeebo/errs" + "go.uber.org/zap" + + "storj.io/storj/internal/memory" + "storj.io/storj/pkg/pb" + "storj.io/storj/pkg/process" + "storj.io/storj/pkg/rpc" + "storj.io/storj/pkg/storj" +) + +type gracefulExitClient struct { + conn *rpc.Conn +} + +func dialGracefulExitClient(ctx context.Context, address string) (*gracefulExitClient, error) { + conn, err := rpc.NewDefaultDialer(nil).DialAddressUnencrypted(ctx, address) + if err != nil { + return nil, errs.Wrap(err) + } + return &gracefulExitClient{conn: conn}, nil +} + +func (client *gracefulExitClient) getNonExitingSatellites(ctx context.Context) (*pb.GetNonExitingSatellitesResponse, error) { + return client.conn.NodeGracefulExitClient().GetNonExitingSatellites(ctx, &pb.GetNonExitingSatellitesRequest{}) +} + +func (client *gracefulExitClient) initGracefulExit(ctx context.Context, req *pb.StartExitRequest) (*pb.StartExitResponse, error) { + return client.conn.NodeGracefulExitClient().StartExit(ctx, req) +} + +func (client *gracefulExitClient) close() error { + return client.conn.Close() +} + +func cmdGracefulExitInit(cmd *cobra.Command, args []string) error { + ctx, _ := process.Ctx(cmd) + + ident, err := runCfg.Identity.Load() + if err != nil { + zap.S().Fatal(err) + } else { + zap.S().Info("Node ID: ", ident.ID) + } + + // display warning message + if !prompt.Confirm("Please be aware that by starting a graceful exit on a satellite, you will no longer be allowed to participate in repairs or uploads from that satellite. This action can not be undone. Are you sure you want to continue? y/n\n") { + return nil + } + + client, err := dialGracefulExitClient(ctx, diagCfg.Server.PrivateAddress) + if err != nil { + return errs.Wrap(err) + } + defer func() { + if err := client.close(); err != nil { + zap.S().Debug("closing graceful exit client failed", err) + } + }() + + // get list of satellites + satelliteList, err := client.getNonExitingSatellites(ctx) + if err != nil { + fmt.Println("Can't find any non-existing satellites.") + return errs.Wrap(err) + } + + // display satellite options + w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + + fmt.Fprintln(w, "Domain Name\tNode ID\tSpace Used\t") + + for _, satellite := range satelliteList.GetSatellites() { + fmt.Fprintln(w, satellite.GetDomainName()+"\t"+satellite.NodeId.String()+"\t"+memory.Size(satellite.GetSpaceUsed()).Base10String()+"\t\n") + } + fmt.Fprintln(w, "Please enter the domain name for each satellite you would like to start graceful exit on with a space in between each domain name and hit enter once you are done:") + err = w.Flush() + if err != nil { + return errs.Wrap(err) + } + + var selectedSatellite []string + + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + input := scanner.Text() + // parse selected satellite from user input + inputs := strings.Split(input, " ") + selectedSatellite = append(selectedSatellite, inputs...) + break + } + if err != scanner.Err() || err != nil { + return errs.Wrap(err) + } + + // validate user input + satelliteIDs := make([]storj.NodeID, 0, len(satelliteList.GetSatellites())) + for _, selected := range selectedSatellite { + for _, satellite := range satelliteList.GetSatellites() { + if satellite.GetDomainName() == selected { + satelliteIDs = append(satelliteIDs, satellite.NodeId) + } + } + } + + if len(satelliteIDs) < 1 { + fmt.Println("Invalid input. Please use valid satellite domian names.") + return errs.New("Invalid satellite domain names") + } + + // save satellites for graceful exit into the db + req := &pb.StartExitRequest{ + NodeIds: satelliteIDs, + } + resp, err := client.initGracefulExit(ctx, req) + if err != nil { + return errs.Wrap(err) + } + for _, status := range resp.Statuses { + if !status.GetSuccess() { + fmt.Printf("Failed to start graceful exit on satellite: %s\n", status.GetDomainName()) + continue + } + fmt.Printf("Started graceful exit on satellite: %s\n", status.GetDomainName()) + } + return nil +} diff --git a/cmd/storagenode/main.go b/cmd/storagenode/main.go index 052ba0295..a96975bb1 100644 --- a/cmd/storagenode/main.go +++ b/cmd/storagenode/main.go @@ -69,6 +69,12 @@ var ( RunE: cmdDashboard, Annotations: map[string]string{"type": "helper"}, } + gracefulExitInitCmd = &cobra.Command{ + Use: "exit-satellite", + Short: "Initiate graceful exit", + RunE: cmdGracefulExitInit, + Annotations: map[string]string{"type": "helper"}, + } runCfg StorageNodeFlags setupCfg StorageNodeFlags @@ -100,11 +106,13 @@ func init() { rootCmd.AddCommand(configCmd) rootCmd.AddCommand(diagCmd) rootCmd.AddCommand(dashboardCmd) + rootCmd.AddCommand(gracefulExitInitCmd) process.Bind(runCmd, &runCfg, defaults, cfgstruct.ConfDir(confDir), cfgstruct.IdentityDir(identityDir)) process.Bind(setupCmd, &setupCfg, defaults, cfgstruct.ConfDir(confDir), cfgstruct.IdentityDir(identityDir), cfgstruct.SetupMode()) process.Bind(configCmd, &setupCfg, defaults, cfgstruct.ConfDir(confDir), cfgstruct.IdentityDir(identityDir), cfgstruct.SetupMode()) process.Bind(diagCmd, &diagCfg, defaults, cfgstruct.ConfDir(confDir), cfgstruct.IdentityDir(identityDir)) process.Bind(dashboardCmd, &dashboardCfg, defaults, cfgstruct.ConfDir(defaultDiagDir)) + process.Bind(gracefulExitInitCmd, &diagCfg, defaults, cfgstruct.ConfDir(defaultDiagDir)) } func databaseConfig(config storagenode.Config) storagenodedb.Config { diff --git a/go.mod b/go.mod index 038b6ea6f..dbb320e51 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a github.com/garyburd/redigo v1.0.1-0.20170216214944-0d253a66e6e1 // indirect github.com/graphql-go/graphql v0.7.9-0.20190403165646-199d20bbfed7 - github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/minio/minio v0.0.0-20180508161510-54cd29b51c38 github.com/segmentio/go-prompt v1.2.1-0.20161017233205-f0d19b6901ad @@ -74,7 +73,6 @@ require ( github.com/minio/minio-go v6.0.3+incompatible github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 github.com/minio/sio v0.0.0-20180327104954-6a41828a60f0 // indirect - github.com/mitchellh/go-homedir v0.0.0-20180801233206-58046073cbff // indirect github.com/nats-io/gnatsd v1.3.0 // indirect github.com/nats-io/go-nats v1.6.0 // indirect github.com/nats-io/go-nats-streaming v0.4.2 // indirect @@ -96,7 +94,7 @@ require ( github.com/skyrings/skyring-common v0.0.0-20160929130248-d1c0bb1cbd5e github.com/spacemonkeygo/errors v0.0.0-20171212215202-9064522e9fd1 // indirect github.com/spf13/cast v1.3.0 - github.com/spf13/cobra v0.0.3 + github.com/spf13/cobra v0.0.5 github.com/spf13/pflag v1.0.3 github.com/spf13/viper v1.4.0 github.com/streadway/amqp v0.0.0-20180806233856-70e15c650864 // indirect diff --git a/go.sum b/go.sum index c27c131ea..13924644b 100644 --- a/go.sum +++ b/go.sum @@ -49,9 +49,11 @@ github.com/cloudfoundry/gosigar v1.1.0/go.mod h1:3qLfc2GlfmwOx2+ZDaRGH3Y9fwQ0sQe github.com/cockroachdb/cockroach-go v0.0.0-20180212155653-59c0560478b7/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= @@ -266,8 +268,8 @@ github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 h1:l16XLUUJ34wIz github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sio v0.0.0-20180327104954-6a41828a60f0 h1:ys4bbOlPvaUBlA0byjm6TqydsXZu614ZIUTfF+4MRY0= github.com/minio/sio v0.0.0-20180327104954-6a41828a60f0/go.mod h1:PDJGYr8GXjiOTIst0hQMOSK5FdXLwObr2cGbiMddDPc= -github.com/mitchellh/go-homedir v0.0.0-20180801233206-58046073cbff h1:jM4Eo4qMmmcqePS3u6X2lcEELtVuXWkWJIS/pRI3oSk= -github.com/mitchellh/go-homedir v0.0.0-20180801233206-58046073cbff/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -339,6 +341,7 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rs/cors v1.5.0 h1:dgSHE6+ia18arGOTIYQKKGWLvEbGvmbNE6NfxhoNHUY= github.com/rs/cors v1.5.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/segmentio/go-prompt v1.2.1-0.20161017233205-f0d19b6901ad h1:EqOdoSJGI7CsBQczPcIgmpm3hJE7X8Hj3jrgI002whs= github.com/segmentio/go-prompt v1.2.1-0.20161017233205-f0d19b6901ad/go.mod h1:B3ehdD1xPoWDKgrQgUaGk+m8H1xb1J5TyYDfKpKNeEE= github.com/sirupsen/logrus v1.0.6 h1:hcP1GmhGigz/O7h1WVUM5KklBp1JoNS9FggWKdj/j3s= @@ -365,12 +368,13 @@ github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/storj/grpc-go v1.23.1-0.20190918084400-1c4561bf5127 h1:sJtPW3g23UOuV+b5o3ARQ7467NzjjacUoBBPTyvIP9c= @@ -392,6 +396,7 @@ github.com/tidwall/match v0.0.0-20171002075945-1731857f09b1 h1:pWIN9LOlFRCJFqWIO github.com/tidwall/match v0.0.0-20171002075945-1731857f09b1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/vivint/infectious v0.0.0-20190108171102-2455b059135b h1:dLkqBELopfQNhe8S9ucnSf+HhiUCgK/hPIjVG0f9GlY= github.com/vivint/infectious v0.0.0-20190108171102-2455b059135b/go.mod h1:5oyMAv4hrBEKqBwORFsiqIrCNCmL2qcZLQTdJLYeYIc= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -426,6 +431,7 @@ go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -463,6 +469,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/pkg/pb/gracefulexit.pb.go b/pkg/pb/gracefulexit.pb.go index 04528a01d..035ee18e6 100644 --- a/pkg/pb/gracefulexit.pb.go +++ b/pkg/pb/gracefulexit.pb.go @@ -49,7 +49,7 @@ func (x TransferFailed_Error) String() string { } func (TransferFailed_Error) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_8f0acbf2ce5fa631, []int{1, 0} + return fileDescriptor_8f0acbf2ce5fa631, []int{7, 0} } type ExitFailed_Reason int32 @@ -71,7 +71,238 @@ func (x ExitFailed_Reason) String() string { } func (ExitFailed_Reason) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_8f0acbf2ce5fa631, []int{7, 0} + return fileDescriptor_8f0acbf2ce5fa631, []int{13, 0} +} + +type GetNonExitingSatellitesRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetNonExitingSatellitesRequest) Reset() { *m = GetNonExitingSatellitesRequest{} } +func (m *GetNonExitingSatellitesRequest) String() string { return proto.CompactTextString(m) } +func (*GetNonExitingSatellitesRequest) ProtoMessage() {} +func (*GetNonExitingSatellitesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_8f0acbf2ce5fa631, []int{0} +} +func (m *GetNonExitingSatellitesRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetNonExitingSatellitesRequest.Unmarshal(m, b) +} +func (m *GetNonExitingSatellitesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetNonExitingSatellitesRequest.Marshal(b, m, deterministic) +} +func (m *GetNonExitingSatellitesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetNonExitingSatellitesRequest.Merge(m, src) +} +func (m *GetNonExitingSatellitesRequest) XXX_Size() int { + return xxx_messageInfo_GetNonExitingSatellitesRequest.Size(m) +} +func (m *GetNonExitingSatellitesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetNonExitingSatellitesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetNonExitingSatellitesRequest proto.InternalMessageInfo + +// StartExitRequest +type StartExitRequest struct { + NodeIds []NodeID `protobuf:"bytes,1,rep,name=node_ids,json=nodeIds,proto3,customtype=NodeID" json:"node_ids"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StartExitRequest) Reset() { *m = StartExitRequest{} } +func (m *StartExitRequest) String() string { return proto.CompactTextString(m) } +func (*StartExitRequest) ProtoMessage() {} +func (*StartExitRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_8f0acbf2ce5fa631, []int{1} +} +func (m *StartExitRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StartExitRequest.Unmarshal(m, b) +} +func (m *StartExitRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StartExitRequest.Marshal(b, m, deterministic) +} +func (m *StartExitRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_StartExitRequest.Merge(m, src) +} +func (m *StartExitRequest) XXX_Size() int { + return xxx_messageInfo_StartExitRequest.Size(m) +} +func (m *StartExitRequest) XXX_DiscardUnknown() { + xxx_messageInfo_StartExitRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_StartExitRequest proto.InternalMessageInfo + +type NonExitingSatellite struct { + NodeId NodeID `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3,customtype=NodeID" json:"node_id"` + DomainName string `protobuf:"bytes,2,opt,name=domain_name,json=domainName,proto3" json:"domain_name,omitempty"` + SpaceUsed float64 `protobuf:"fixed64,3,opt,name=space_used,json=spaceUsed,proto3" json:"space_used,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NonExitingSatellite) Reset() { *m = NonExitingSatellite{} } +func (m *NonExitingSatellite) String() string { return proto.CompactTextString(m) } +func (*NonExitingSatellite) ProtoMessage() {} +func (*NonExitingSatellite) Descriptor() ([]byte, []int) { + return fileDescriptor_8f0acbf2ce5fa631, []int{2} +} +func (m *NonExitingSatellite) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NonExitingSatellite.Unmarshal(m, b) +} +func (m *NonExitingSatellite) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NonExitingSatellite.Marshal(b, m, deterministic) +} +func (m *NonExitingSatellite) XXX_Merge(src proto.Message) { + xxx_messageInfo_NonExitingSatellite.Merge(m, src) +} +func (m *NonExitingSatellite) XXX_Size() int { + return xxx_messageInfo_NonExitingSatellite.Size(m) +} +func (m *NonExitingSatellite) XXX_DiscardUnknown() { + xxx_messageInfo_NonExitingSatellite.DiscardUnknown(m) +} + +var xxx_messageInfo_NonExitingSatellite proto.InternalMessageInfo + +func (m *NonExitingSatellite) GetDomainName() string { + if m != nil { + return m.DomainName + } + return "" +} + +func (m *NonExitingSatellite) GetSpaceUsed() float64 { + if m != nil { + return m.SpaceUsed + } + return 0 +} + +type GetNonExitingSatellitesResponse struct { + Satellites []*NonExitingSatellite `protobuf:"bytes,1,rep,name=satellites,proto3" json:"satellites,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetNonExitingSatellitesResponse) Reset() { *m = GetNonExitingSatellitesResponse{} } +func (m *GetNonExitingSatellitesResponse) String() string { return proto.CompactTextString(m) } +func (*GetNonExitingSatellitesResponse) ProtoMessage() {} +func (*GetNonExitingSatellitesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_8f0acbf2ce5fa631, []int{3} +} +func (m *GetNonExitingSatellitesResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetNonExitingSatellitesResponse.Unmarshal(m, b) +} +func (m *GetNonExitingSatellitesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetNonExitingSatellitesResponse.Marshal(b, m, deterministic) +} +func (m *GetNonExitingSatellitesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetNonExitingSatellitesResponse.Merge(m, src) +} +func (m *GetNonExitingSatellitesResponse) XXX_Size() int { + return xxx_messageInfo_GetNonExitingSatellitesResponse.Size(m) +} +func (m *GetNonExitingSatellitesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetNonExitingSatellitesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetNonExitingSatellitesResponse proto.InternalMessageInfo + +func (m *GetNonExitingSatellitesResponse) GetSatellites() []*NonExitingSatellite { + if m != nil { + return m.Satellites + } + return nil +} + +type StartExitStatus struct { + DomainName string `protobuf:"bytes,1,opt,name=domain_name,json=domainName,proto3" json:"domain_name,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StartExitStatus) Reset() { *m = StartExitStatus{} } +func (m *StartExitStatus) String() string { return proto.CompactTextString(m) } +func (*StartExitStatus) ProtoMessage() {} +func (*StartExitStatus) Descriptor() ([]byte, []int) { + return fileDescriptor_8f0acbf2ce5fa631, []int{4} +} +func (m *StartExitStatus) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StartExitStatus.Unmarshal(m, b) +} +func (m *StartExitStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StartExitStatus.Marshal(b, m, deterministic) +} +func (m *StartExitStatus) XXX_Merge(src proto.Message) { + xxx_messageInfo_StartExitStatus.Merge(m, src) +} +func (m *StartExitStatus) XXX_Size() int { + return xxx_messageInfo_StartExitStatus.Size(m) +} +func (m *StartExitStatus) XXX_DiscardUnknown() { + xxx_messageInfo_StartExitStatus.DiscardUnknown(m) +} + +var xxx_messageInfo_StartExitStatus proto.InternalMessageInfo + +func (m *StartExitStatus) GetDomainName() string { + if m != nil { + return m.DomainName + } + return "" +} + +func (m *StartExitStatus) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +type StartExitResponse struct { + Statuses []*StartExitStatus `protobuf:"bytes,1,rep,name=statuses,proto3" json:"statuses,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StartExitResponse) Reset() { *m = StartExitResponse{} } +func (m *StartExitResponse) String() string { return proto.CompactTextString(m) } +func (*StartExitResponse) ProtoMessage() {} +func (*StartExitResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_8f0acbf2ce5fa631, []int{5} +} +func (m *StartExitResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StartExitResponse.Unmarshal(m, b) +} +func (m *StartExitResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StartExitResponse.Marshal(b, m, deterministic) +} +func (m *StartExitResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_StartExitResponse.Merge(m, src) +} +func (m *StartExitResponse) XXX_Size() int { + return xxx_messageInfo_StartExitResponse.Size(m) +} +func (m *StartExitResponse) XXX_DiscardUnknown() { + xxx_messageInfo_StartExitResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_StartExitResponse proto.InternalMessageInfo + +func (m *StartExitResponse) GetStatuses() []*StartExitStatus { + if m != nil { + return m.Statuses + } + return nil } type TransferSucceeded struct { @@ -87,7 +318,7 @@ func (m *TransferSucceeded) Reset() { *m = TransferSucceeded{} } func (m *TransferSucceeded) String() string { return proto.CompactTextString(m) } func (*TransferSucceeded) ProtoMessage() {} func (*TransferSucceeded) Descriptor() ([]byte, []int) { - return fileDescriptor_8f0acbf2ce5fa631, []int{0} + return fileDescriptor_8f0acbf2ce5fa631, []int{6} } func (m *TransferSucceeded) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TransferSucceeded.Unmarshal(m, b) @@ -140,7 +371,7 @@ func (m *TransferFailed) Reset() { *m = TransferFailed{} } func (m *TransferFailed) String() string { return proto.CompactTextString(m) } func (*TransferFailed) ProtoMessage() {} func (*TransferFailed) Descriptor() ([]byte, []int) { - return fileDescriptor_8f0acbf2ce5fa631, []int{1} + return fileDescriptor_8f0acbf2ce5fa631, []int{7} } func (m *TransferFailed) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TransferFailed.Unmarshal(m, b) @@ -181,7 +412,7 @@ func (m *StorageNodeMessage) Reset() { *m = StorageNodeMessage{} } func (m *StorageNodeMessage) String() string { return proto.CompactTextString(m) } func (*StorageNodeMessage) ProtoMessage() {} func (*StorageNodeMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_8f0acbf2ce5fa631, []int{2} + return fileDescriptor_8f0acbf2ce5fa631, []int{8} } func (m *StorageNodeMessage) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StorageNodeMessage.Unmarshal(m, b) @@ -320,7 +551,7 @@ func (m *NotReady) Reset() { *m = NotReady{} } func (m *NotReady) String() string { return proto.CompactTextString(m) } func (*NotReady) ProtoMessage() {} func (*NotReady) Descriptor() ([]byte, []int) { - return fileDescriptor_8f0acbf2ce5fa631, []int{3} + return fileDescriptor_8f0acbf2ce5fa631, []int{9} } func (m *NotReady) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NotReady.Unmarshal(m, b) @@ -354,7 +585,7 @@ func (m *TransferPiece) Reset() { *m = TransferPiece{} } func (m *TransferPiece) String() string { return proto.CompactTextString(m) } func (*TransferPiece) ProtoMessage() {} func (*TransferPiece) Descriptor() ([]byte, []int) { - return fileDescriptor_8f0acbf2ce5fa631, []int{4} + return fileDescriptor_8f0acbf2ce5fa631, []int{10} } func (m *TransferPiece) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TransferPiece.Unmarshal(m, b) @@ -392,7 +623,7 @@ func (m *DeletePiece) Reset() { *m = DeletePiece{} } func (m *DeletePiece) String() string { return proto.CompactTextString(m) } func (*DeletePiece) ProtoMessage() {} func (*DeletePiece) Descriptor() ([]byte, []int) { - return fileDescriptor_8f0acbf2ce5fa631, []int{5} + return fileDescriptor_8f0acbf2ce5fa631, []int{11} } func (m *DeletePiece) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DeletePiece.Unmarshal(m, b) @@ -424,7 +655,7 @@ func (m *ExitCompleted) Reset() { *m = ExitCompleted{} } func (m *ExitCompleted) String() string { return proto.CompactTextString(m) } func (*ExitCompleted) ProtoMessage() {} func (*ExitCompleted) Descriptor() ([]byte, []int) { - return fileDescriptor_8f0acbf2ce5fa631, []int{6} + return fileDescriptor_8f0acbf2ce5fa631, []int{12} } func (m *ExitCompleted) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExitCompleted.Unmarshal(m, b) @@ -464,7 +695,7 @@ func (m *ExitFailed) Reset() { *m = ExitFailed{} } func (m *ExitFailed) String() string { return proto.CompactTextString(m) } func (*ExitFailed) ProtoMessage() {} func (*ExitFailed) Descriptor() ([]byte, []int) { - return fileDescriptor_8f0acbf2ce5fa631, []int{7} + return fileDescriptor_8f0acbf2ce5fa631, []int{13} } func (m *ExitFailed) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ExitFailed.Unmarshal(m, b) @@ -515,7 +746,7 @@ func (m *SatelliteMessage) Reset() { *m = SatelliteMessage{} } func (m *SatelliteMessage) String() string { return proto.CompactTextString(m) } func (*SatelliteMessage) ProtoMessage() {} func (*SatelliteMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_8f0acbf2ce5fa631, []int{8} + return fileDescriptor_8f0acbf2ce5fa631, []int{14} } func (m *SatelliteMessage) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SatelliteMessage.Unmarshal(m, b) @@ -737,6 +968,12 @@ func _SatelliteMessage_OneofSizer(msg proto.Message) (n int) { func init() { proto.RegisterEnum("gracefulexit.TransferFailed_Error", TransferFailed_Error_name, TransferFailed_Error_value) proto.RegisterEnum("gracefulexit.ExitFailed_Reason", ExitFailed_Reason_name, ExitFailed_Reason_value) + proto.RegisterType((*GetNonExitingSatellitesRequest)(nil), "gracefulexit.GetNonExitingSatellitesRequest") + proto.RegisterType((*StartExitRequest)(nil), "gracefulexit.StartExitRequest") + proto.RegisterType((*NonExitingSatellite)(nil), "gracefulexit.NonExitingSatellite") + proto.RegisterType((*GetNonExitingSatellitesResponse)(nil), "gracefulexit.GetNonExitingSatellitesResponse") + proto.RegisterType((*StartExitStatus)(nil), "gracefulexit.StartExitStatus") + proto.RegisterType((*StartExitResponse)(nil), "gracefulexit.StartExitResponse") proto.RegisterType((*TransferSucceeded)(nil), "gracefulexit.TransferSucceeded") proto.RegisterType((*TransferFailed)(nil), "gracefulexit.TransferFailed") proto.RegisterType((*StorageNodeMessage)(nil), "gracefulexit.StorageNodeMessage") @@ -751,54 +988,178 @@ func init() { func init() { proto.RegisterFile("gracefulexit.proto", fileDescriptor_8f0acbf2ce5fa631) } var fileDescriptor_8f0acbf2ce5fa631 = []byte{ - // 742 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xdb, 0x6e, 0xeb, 0x44, - 0x14, 0xb5, 0x73, 0x4e, 0x93, 0x66, 0xe7, 0x72, 0xd2, 0xe9, 0x69, 0x1b, 0xca, 0x81, 0x1e, 0xfc, - 0x54, 0xf1, 0x10, 0xa1, 0x72, 0x17, 0x12, 0xc8, 0x69, 0xae, 0x6a, 0xb0, 0xcb, 0x24, 0x2d, 0x12, - 0x2f, 0xd6, 0x34, 0xde, 0x49, 0x2c, 0x1c, 0x3b, 0x1a, 0x4f, 0x50, 0xfb, 0x27, 0x3c, 0xf1, 0x1f, - 0xfc, 0x41, 0xbf, 0x01, 0x89, 0x7e, 0x04, 0x5f, 0x80, 0x3c, 0x1e, 0xbb, 0x71, 0x2f, 0x48, 0xe5, - 0x6d, 0x66, 0xcf, 0xda, 0x2b, 0x6b, 0xf6, 0x5a, 0x13, 0x03, 0x99, 0x73, 0x36, 0xc5, 0xd9, 0xda, - 0xc7, 0x6b, 0x4f, 0xb4, 0x56, 0x3c, 0x14, 0x21, 0xa9, 0x6e, 0xd6, 0x0e, 0x61, 0x1e, 0xce, 0xc3, - 0xe4, 0xe4, 0xb0, 0xbe, 0x44, 0xc1, 0xbc, 0x60, 0x96, 0xee, 0xab, 0x21, 0x77, 0x91, 0x47, 0xc9, - 0xce, 0xf8, 0x47, 0x87, 0x9d, 0x09, 0x67, 0x41, 0x34, 0x43, 0x3e, 0x5e, 0x4f, 0xa7, 0x88, 0x2e, - 0xba, 0xe4, 0x27, 0xd8, 0x63, 0xae, 0xcb, 0x31, 0x8a, 0xd0, 0x75, 0x24, 0xde, 0xf1, 0xbd, 0xa5, - 0x27, 0x9a, 0xfa, 0x7b, 0xfd, 0xb8, 0x72, 0xf2, 0x51, 0x2b, 0xe3, 0x34, 0x53, 0x98, 0x1d, 0xa3, - 0x46, 0x31, 0x88, 0xee, 0xb2, 0xc7, 0x45, 0x62, 0xc2, 0x6e, 0xc8, 0xbd, 0xb9, 0x17, 0x30, 0xdf, - 0x59, 0x79, 0x38, 0x45, 0x67, 0xc1, 0xa2, 0x45, 0xb3, 0x20, 0x09, 0x77, 0x5a, 0x4a, 0xd4, 0x79, - 0x7c, 0x32, 0x60, 0xd1, 0x82, 0xee, 0xa4, 0xe8, 0xac, 0x44, 0xfa, 0xb0, 0xcf, 0x71, 0xe5, 0xb3, - 0x29, 0x2e, 0x31, 0x10, 0x9b, 0x2c, 0xaf, 0x9e, 0x63, 0x79, 0xbb, 0xd1, 0x90, 0x55, 0x8d, 0x3f, - 0x75, 0xa8, 0xa7, 0x97, 0xee, 0x31, 0xcf, 0x47, 0x97, 0x7c, 0x0a, 0xdb, 0x09, 0x9f, 0xe7, 0xca, - 0x4b, 0x56, 0xdb, 0x6f, 0x6e, 0xef, 0x8e, 0xb4, 0xbf, 0xee, 0x8e, 0x4a, 0xb2, 0x6f, 0xd8, 0xa1, - 0x25, 0x09, 0x18, 0xba, 0xe4, 0x1b, 0xd8, 0x42, 0xce, 0x43, 0x2e, 0xc5, 0xd7, 0x4f, 0x8c, 0x56, - 0xce, 0x8f, 0x3c, 0x71, 0xab, 0x1b, 0x23, 0x69, 0xd2, 0x60, 0x98, 0xb0, 0x25, 0xf7, 0xa4, 0x06, - 0x65, 0xcb, 0x9e, 0x38, 0x3d, 0xfb, 0xc2, 0xea, 0x34, 0x34, 0xf2, 0x0e, 0x9a, 0xe3, 0x89, 0x4d, - 0xcd, 0x7e, 0xd7, 0xb1, 0xec, 0x4e, 0xd7, 0xb9, 0xb0, 0xcc, 0x4b, 0x73, 0x38, 0x32, 0xdb, 0xa3, - 0x6e, 0x43, 0x27, 0x15, 0x28, 0x5d, 0x58, 0x67, 0x96, 0xfd, 0xb3, 0xd5, 0x28, 0x18, 0xbf, 0xeb, - 0x40, 0xc6, 0x22, 0xe4, 0x6c, 0x8e, 0x56, 0xe8, 0xe2, 0x8f, 0x18, 0x45, 0x6c, 0x8e, 0xe4, 0x07, - 0x28, 0x47, 0xa9, 0x7d, 0xca, 0xa5, 0xa3, 0xa7, 0x75, 0x65, 0x2e, 0x0f, 0x34, 0x7a, 0xdf, 0x43, - 0xbe, 0x82, 0xe2, 0x4c, 0x2a, 0x56, 0x96, 0xbc, 0xfb, 0xaf, 0x5b, 0x0d, 0x34, 0xaa, 0xd0, 0xed, - 0x32, 0x94, 0x94, 0x06, 0x03, 0x60, 0xdb, 0x0a, 0x05, 0x45, 0xe6, 0xde, 0x18, 0xb7, 0x3a, 0xd4, - 0xd2, 0x1e, 0x39, 0xc0, 0x17, 0x4e, 0xb8, 0xb2, 0xe2, 0xde, 0x6f, 0x4c, 0xa0, 0xf3, 0x2b, 0xde, - 0x48, 0x45, 0xd5, 0xf6, 0x81, 0x82, 0xbf, 0x91, 0xf0, 0xf3, 0xe4, 0xfc, 0x0c, 0x6f, 0x28, 0xac, - 0xb2, 0xf5, 0xf3, 0xc9, 0x7d, 0xf5, 0x7f, 0x93, 0x6b, 0x7c, 0x0b, 0x95, 0x0e, 0xfa, 0x28, 0xf0, - 0xc5, 0xf7, 0x30, 0xfa, 0x50, 0xeb, 0x5e, 0x7b, 0xe2, 0x34, 0x5c, 0xae, 0x62, 0x82, 0x78, 0xca, - 0x07, 0xf1, 0x38, 0x9d, 0xa9, 0xaa, 0x38, 0x91, 0x37, 0x0f, 0x98, 0x58, 0x73, 0x4c, 0xb8, 0xe8, - 0x1e, 0x6e, 0xe0, 0xc7, 0xe9, 0xa1, 0xf1, 0x87, 0x0e, 0x10, 0x33, 0xa9, 0xb4, 0x7e, 0x01, 0xfb, - 0x92, 0x26, 0xf6, 0x60, 0xcd, 0x1f, 0xb3, 0xbc, 0x45, 0x85, 0x5d, 0xf3, 0x7b, 0x12, 0xf2, 0x35, - 0x14, 0x39, 0xb2, 0x28, 0x0c, 0x54, 0x70, 0x1f, 0x04, 0xe4, 0x9e, 0xbf, 0x45, 0x25, 0x8c, 0x2a, - 0xb8, 0xf1, 0x09, 0x14, 0x93, 0x0a, 0x39, 0x80, 0xdd, 0xcb, 0x2e, 0x1d, 0xf6, 0x86, 0xa7, 0xe6, - 0x64, 0x68, 0x5b, 0x4e, 0xcf, 0x1c, 0x8e, 0xba, 0x9d, 0x86, 0x66, 0xfc, 0x5d, 0x80, 0xc6, 0x98, - 0x09, 0xf4, 0x7d, 0x4f, 0x64, 0xa1, 0xfc, 0x12, 0xca, 0x41, 0x28, 0x1c, 0x1e, 0x27, 0x42, 0x85, - 0x72, 0x3f, 0xff, 0x9b, 0x69, 0x5e, 0x06, 0x1a, 0xdd, 0x0e, 0xd4, 0x9a, 0x74, 0xa0, 0x2e, 0x54, - 0x74, 0x92, 0x47, 0xae, 0x22, 0xf9, 0xe1, 0xd3, 0x91, 0x4c, 0xde, 0xb5, 0x46, 0x6b, 0x22, 0x97, - 0xb7, 0xef, 0xa1, 0xea, 0x4a, 0xdb, 0x14, 0x47, 0x12, 0x80, 0x0f, 0xf2, 0x1c, 0x1b, 0xc6, 0x0e, - 0x34, 0x5a, 0x71, 0x37, 0x7c, 0xee, 0x40, 0x3d, 0x67, 0x95, 0xdb, 0x7c, 0xfd, 0x94, 0x8a, 0x9c, - 0xbf, 0xb1, 0x0a, 0xcc, 0x19, 0xfe, 0x1d, 0x54, 0x32, 0xa7, 0xd0, 0x6d, 0x6e, 0x49, 0x8a, 0xe6, - 0x73, 0x83, 0x1f, 0x68, 0x14, 0x30, 0xdb, 0x6d, 0xbc, 0xad, 0x93, 0x05, 0xec, 0x65, 0xe3, 0xed, - 0xab, 0xe6, 0xb8, 0x8f, 0xd8, 0x50, 0x3a, 0xe7, 0xe1, 0x14, 0xa3, 0x88, 0xbc, 0xcf, 0xd3, 0x3e, - 0xfe, 0x97, 0x38, 0xfc, 0xf8, 0x01, 0xe2, 0x81, 0x61, 0xc7, 0xfa, 0x67, 0x7a, 0xfb, 0xf5, 0x2f, - 0x85, 0xd5, 0xd5, 0x55, 0x51, 0x7e, 0x1e, 0x3e, 0xff, 0x37, 0x00, 0x00, 0xff, 0xff, 0x43, 0x36, - 0xf6, 0x79, 0x6c, 0x06, 0x00, 0x00, + // 984 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xdf, 0x6e, 0x1a, 0xc7, + 0x17, 0x66, 0xed, 0x98, 0x3f, 0x07, 0x8c, 0xf1, 0x38, 0xb6, 0xf9, 0xf9, 0x97, 0x04, 0xb2, 0x37, + 0x75, 0xab, 0xd6, 0xaa, 0xdc, 0xbf, 0x51, 0xd5, 0x56, 0x38, 0x60, 0x83, 0x42, 0x17, 0x77, 0xb0, + 0x53, 0xa9, 0x37, 0xab, 0x09, 0x73, 0x8c, 0x57, 0x85, 0x5d, 0x3a, 0x33, 0x44, 0xf1, 0x4d, 0x9f, + 0xa3, 0x57, 0x7d, 0x8f, 0xbe, 0x41, 0x1e, 0xa1, 0xaa, 0xd4, 0x3c, 0x44, 0x9f, 0xa0, 0x9a, 0xd9, + 0x61, 0xcd, 0x62, 0x88, 0x9a, 0xde, 0x31, 0x67, 0xbe, 0xf3, 0xed, 0x77, 0xce, 0xf9, 0x66, 0x06, + 0x20, 0x43, 0xc1, 0x06, 0x78, 0x35, 0x1d, 0xe1, 0xab, 0x40, 0x1d, 0x4d, 0x44, 0xa4, 0x22, 0x52, + 0x9a, 0x8f, 0x1d, 0xc0, 0x30, 0x1a, 0x46, 0xf1, 0xce, 0x41, 0x79, 0x8c, 0x8a, 0x05, 0xe1, 0xd5, + 0x6c, 0x5d, 0x8a, 0x04, 0x47, 0x21, 0xe3, 0x95, 0x5b, 0x87, 0x47, 0x67, 0xa8, 0xbc, 0x28, 0x6c, + 0xbd, 0x0a, 0x54, 0x10, 0x0e, 0xfb, 0x4c, 0xe1, 0x68, 0x14, 0x28, 0x94, 0x14, 0x7f, 0x9e, 0xa2, + 0x54, 0xee, 0xd7, 0x50, 0xe9, 0x2b, 0x26, 0x94, 0x06, 0xd8, 0x18, 0x79, 0x1f, 0xf2, 0x61, 0xc4, + 0xd1, 0x0f, 0xb8, 0xac, 0x3a, 0xf5, 0xf5, 0xc3, 0xd2, 0x49, 0xf9, 0xf5, 0x9b, 0x5a, 0xe6, 0xcf, + 0x37, 0xb5, 0xac, 0x17, 0x71, 0xec, 0x34, 0x69, 0x4e, 0xef, 0x77, 0xb8, 0x74, 0x7f, 0x81, 0x9d, + 0x25, 0xec, 0xe4, 0x3d, 0xc8, 0x59, 0x86, 0xaa, 0x53, 0x77, 0x96, 0x10, 0x64, 0x63, 0x02, 0x52, + 0x83, 0x22, 0x8f, 0xc6, 0x2c, 0x08, 0xfd, 0x90, 0x8d, 0xb1, 0xba, 0x56, 0x77, 0x0e, 0x0b, 0x14, + 0xe2, 0x90, 0xc7, 0xc6, 0x48, 0x1e, 0x02, 0xc8, 0x09, 0x1b, 0xa0, 0x3f, 0x95, 0xc8, 0xab, 0xeb, + 0x75, 0xe7, 0xd0, 0xa1, 0x05, 0x13, 0xb9, 0x94, 0xc8, 0x5d, 0x0e, 0xb5, 0x95, 0x05, 0xca, 0x49, + 0x14, 0x4a, 0x24, 0x0d, 0x00, 0x99, 0x44, 0x4d, 0x3d, 0xc5, 0xe3, 0xc7, 0x47, 0xa9, 0x26, 0x2f, + 0xc9, 0xa7, 0x73, 0x49, 0x6e, 0x17, 0xb6, 0x92, 0x26, 0xf5, 0x15, 0x53, 0x53, 0xb9, 0x28, 0xdc, + 0xb9, 0x23, 0xbc, 0x0a, 0x39, 0x39, 0x1d, 0x0c, 0x50, 0x4a, 0x53, 0x55, 0x9e, 0xce, 0x96, 0xae, + 0x07, 0xdb, 0x73, 0x2d, 0xb7, 0x2a, 0x9f, 0x40, 0x5e, 0x1a, 0xe6, 0x44, 0xe3, 0xc3, 0xb4, 0xc6, + 0x05, 0x01, 0x34, 0x81, 0xbb, 0x7f, 0x3b, 0xb0, 0x7d, 0x21, 0x58, 0x28, 0xaf, 0x50, 0xf4, 0xf5, + 0x37, 0x90, 0x23, 0x27, 0xdf, 0xc3, 0x2e, 0xe3, 0x5c, 0xa0, 0x94, 0xc8, 0x7d, 0x63, 0x0a, 0x7f, + 0x14, 0x8c, 0x03, 0x65, 0xa4, 0x6a, 0xf6, 0xc4, 0x38, 0x8d, 0x19, 0xac, 0xa7, 0x51, 0x5d, 0x0d, + 0xa2, 0x3b, 0xec, 0x6e, 0x90, 0x34, 0x60, 0x27, 0x12, 0xc1, 0x30, 0x08, 0xd9, 0xc8, 0x9f, 0x04, + 0x38, 0x40, 0xff, 0x9a, 0xc9, 0x6b, 0x53, 0x5e, 0xf1, 0x78, 0xfb, 0xc8, 0x3a, 0xef, 0x5c, 0xef, + 0xb4, 0x99, 0xbc, 0xa6, 0xdb, 0x33, 0x74, 0x12, 0x22, 0x67, 0xb0, 0x27, 0x70, 0x32, 0x62, 0x03, + 0x1c, 0x63, 0xa8, 0xe6, 0x59, 0xd6, 0x57, 0xb1, 0xdc, 0x9f, 0x4b, 0x48, 0xa2, 0xee, 0xef, 0x0e, + 0x94, 0x67, 0x45, 0x9f, 0xb2, 0x60, 0x84, 0x9c, 0x7c, 0x00, 0xf9, 0x98, 0x2f, 0x71, 0xdd, 0x96, + 0x75, 0x5d, 0xce, 0xe4, 0x69, 0xdf, 0x1a, 0x40, 0x87, 0x93, 0x2f, 0x61, 0x03, 0x85, 0x88, 0x84, + 0x11, 0x5f, 0x3e, 0x76, 0xd3, 0xbd, 0x4e, 0x13, 0x1f, 0xb5, 0x34, 0x92, 0xc6, 0x09, 0x6e, 0x03, + 0x36, 0xcc, 0x9a, 0x6c, 0x42, 0xc1, 0xeb, 0x5d, 0xf8, 0xa7, 0xbd, 0x4b, 0xaf, 0x59, 0xc9, 0x90, + 0x07, 0x50, 0xed, 0x5f, 0xf4, 0x68, 0xe3, 0xac, 0xe5, 0x7b, 0xbd, 0x66, 0xcb, 0xbf, 0xf4, 0x1a, + 0xcf, 0x1b, 0x9d, 0x6e, 0xe3, 0xa4, 0xdb, 0xaa, 0x38, 0xa4, 0x08, 0xb9, 0x4b, 0xef, 0x99, 0xd7, + 0xfb, 0xc1, 0xab, 0xac, 0xb9, 0xbf, 0x3a, 0x40, 0xfa, 0x2a, 0x12, 0x6c, 0x88, 0xfa, 0x38, 0x7c, + 0x87, 0x52, 0xb2, 0x21, 0x92, 0x6f, 0xa1, 0x20, 0x67, 0xe3, 0xb3, 0x53, 0xaa, 0x2d, 0xd7, 0x95, + 0x4c, 0xb9, 0x9d, 0xa1, 0xb7, 0x39, 0xe4, 0x73, 0xc8, 0x5e, 0x19, 0xc5, 0x76, 0x24, 0x0f, 0xde, + 0x56, 0x55, 0x3b, 0x43, 0x2d, 0xfa, 0xa4, 0x00, 0x39, 0xab, 0xc1, 0x05, 0xc8, 0x7b, 0x91, 0xa2, + 0xc8, 0xf8, 0x8d, 0xfb, 0xda, 0x81, 0xcd, 0x59, 0x8e, 0x69, 0xe0, 0x3b, 0x76, 0xb8, 0x38, 0x11, + 0xc1, 0x4b, 0xa6, 0xd0, 0xff, 0x09, 0x6f, 0x8c, 0xa2, 0xd2, 0xc9, 0xbe, 0x85, 0x6f, 0x19, 0xf8, + 0x79, 0xbc, 0xff, 0x0c, 0x6f, 0x28, 0x4c, 0x92, 0xdf, 0xab, 0x9d, 0xbb, 0xfe, 0x5f, 0x9d, 0xeb, + 0x3e, 0x81, 0x62, 0x13, 0x47, 0xa8, 0xf0, 0x9d, 0xeb, 0x70, 0xcf, 0x60, 0x53, 0x9f, 0xba, 0xa7, + 0xd1, 0x78, 0xa2, 0x09, 0x74, 0x97, 0xf7, 0x75, 0x3b, 0xfd, 0x81, 0x8d, 0xf8, 0x32, 0x18, 0x86, + 0x4c, 0x4d, 0x45, 0x7c, 0x0b, 0x94, 0xe8, 0x2e, 0xce, 0xe1, 0xfb, 0xb3, 0x4d, 0xf7, 0x37, 0x07, + 0x40, 0x33, 0x59, 0xb7, 0x7e, 0x0a, 0x7b, 0x86, 0x46, 0xcf, 0x60, 0x2a, 0xee, 0xb2, 0xdc, 0x47, + 0x8b, 0x9d, 0x8a, 0x5b, 0x12, 0xf2, 0x05, 0x64, 0x05, 0x32, 0x19, 0x85, 0xd6, 0xb8, 0x0b, 0x06, + 0xb9, 0xe5, 0x3f, 0xa2, 0x06, 0x46, 0x2d, 0xdc, 0x7d, 0x0c, 0xd9, 0x38, 0x42, 0xf6, 0x61, 0xe7, + 0x79, 0x8b, 0x76, 0x4e, 0x3b, 0x4f, 0x1b, 0x17, 0x9d, 0x9e, 0xe7, 0x9f, 0x36, 0x3a, 0xdd, 0x56, + 0xb3, 0x92, 0x71, 0xff, 0x5a, 0x83, 0x4a, 0x72, 0xff, 0xcd, 0x4c, 0xf9, 0x19, 0x14, 0xc2, 0x48, + 0xf9, 0x42, 0x3b, 0xc2, 0x9a, 0x72, 0x6f, 0xf1, 0xf2, 0x8c, 0xfd, 0xd2, 0xce, 0xd0, 0x7c, 0x68, + 0x7f, 0x93, 0x26, 0x94, 0x95, 0xb5, 0x4e, 0x7c, 0xc8, 0xad, 0x25, 0xff, 0xbf, 0xdc, 0x92, 0xf1, + 0xb9, 0xce, 0xd0, 0x4d, 0x95, 0xf2, 0xdb, 0x37, 0x50, 0xe2, 0x66, 0x6c, 0x96, 0x23, 0x36, 0xc0, + 0xff, 0xd2, 0x1c, 0x73, 0x83, 0x6d, 0x67, 0x68, 0x91, 0xcf, 0xcd, 0xb9, 0x09, 0xe5, 0xd4, 0xa8, + 0x78, 0xf5, 0xde, 0x32, 0x15, 0xa9, 0xf9, 0x6a, 0x15, 0x98, 0x1a, 0xf8, 0x57, 0x50, 0x4c, 0x26, + 0x85, 0xbc, 0xba, 0x61, 0x28, 0xaa, 0xab, 0x1a, 0xdf, 0xce, 0x50, 0xc0, 0x64, 0x35, 0x77, 0xb6, + 0x8e, 0xff, 0x70, 0xa0, 0xa2, 0xcf, 0xfb, 0x99, 0x4d, 0xd4, 0x39, 0xe4, 0x25, 0xec, 0xaf, 0x78, + 0xc0, 0xc8, 0x87, 0xe9, 0x4f, 0xbc, 0xfd, 0x21, 0x3f, 0xf8, 0xe8, 0x5f, 0xa2, 0xed, 0x7b, 0xd3, + 0x85, 0x42, 0xf2, 0xa2, 0x90, 0x47, 0x2b, 0x9e, 0x9a, 0x19, 0x77, 0x6d, 0xe5, 0x7e, 0xcc, 0x76, + 0x7c, 0x0d, 0xbb, 0xc9, 0x37, 0x52, 0xe5, 0xf5, 0x20, 0x77, 0x2e, 0x22, 0xfd, 0xec, 0x91, 0xfa, + 0x22, 0xc9, 0xe2, 0x05, 0x78, 0xb0, 0x28, 0x63, 0xc1, 0x8b, 0x87, 0xce, 0xc7, 0xce, 0xc9, 0xbd, + 0x1f, 0xd7, 0x26, 0x2f, 0x5e, 0x64, 0xcd, 0xdf, 0x9b, 0x4f, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, + 0xe0, 0x3d, 0x33, 0xc3, 0x2c, 0x09, 0x00, 0x00, +} + +type DRPCNodeGracefulExitClient interface { + DRPCConn() drpc.Conn + + // GetSatellitesList returns a list of satellites that the storagenode has not begun a graceful exit for. + GetNonExitingSatellites(ctx context.Context, in *GetNonExitingSatellitesRequest) (*GetNonExitingSatellitesResponse, error) + // StartExit updates one or more satellites in the storagenode's database to be gracefully exiting. + StartExit(ctx context.Context, in *StartExitRequest) (*StartExitResponse, error) +} + +type drpcNodeGracefulExitClient struct { + cc drpc.Conn +} + +func NewDRPCNodeGracefulExitClient(cc drpc.Conn) DRPCNodeGracefulExitClient { + return &drpcNodeGracefulExitClient{cc} +} + +func (c *drpcNodeGracefulExitClient) DRPCConn() drpc.Conn { return c.cc } + +func (c *drpcNodeGracefulExitClient) GetNonExitingSatellites(ctx context.Context, in *GetNonExitingSatellitesRequest) (*GetNonExitingSatellitesResponse, error) { + out := new(GetNonExitingSatellitesResponse) + err := c.cc.Invoke(ctx, "/gracefulexit.NodeGracefulExit/GetNonExitingSatellites", in, out) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *drpcNodeGracefulExitClient) StartExit(ctx context.Context, in *StartExitRequest) (*StartExitResponse, error) { + out := new(StartExitResponse) + err := c.cc.Invoke(ctx, "/gracefulexit.NodeGracefulExit/StartExit", in, out) + if err != nil { + return nil, err + } + return out, nil +} + +type DRPCNodeGracefulExitServer interface { + // GetSatellitesList returns a list of satellites that the storagenode has not begun a graceful exit for. + GetNonExitingSatellites(context.Context, *GetNonExitingSatellitesRequest) (*GetNonExitingSatellitesResponse, error) + // StartExit updates one or more satellites in the storagenode's database to be gracefully exiting. + StartExit(context.Context, *StartExitRequest) (*StartExitResponse, error) +} + +type DRPCNodeGracefulExitDescription struct{} + +func (DRPCNodeGracefulExitDescription) NumMethods() int { return 2 } + +func (DRPCNodeGracefulExitDescription) Method(n int) (string, drpc.Handler, interface{}, bool) { + switch n { + case 0: + return "/gracefulexit.NodeGracefulExit/GetNonExitingSatellites", + func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) { + return srv.(DRPCNodeGracefulExitServer). + GetNonExitingSatellites( + ctx, + in1.(*GetNonExitingSatellitesRequest), + ) + }, DRPCNodeGracefulExitServer.GetNonExitingSatellites, true + case 1: + return "/gracefulexit.NodeGracefulExit/StartExit", + func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) { + return srv.(DRPCNodeGracefulExitServer). + StartExit( + ctx, + in1.(*StartExitRequest), + ) + }, DRPCNodeGracefulExitServer.StartExit, true + default: + return "", nil, nil, false + } +} + +func DRPCRegisterNodeGracefulExit(srv drpc.Server, impl DRPCNodeGracefulExitServer) { + srv.Register(impl, DRPCNodeGracefulExitDescription{}) +} + +type DRPCNodeGracefulExit_GetNonExitingSatellitesStream interface { + drpc.Stream + SendAndClose(*GetNonExitingSatellitesResponse) error +} + +type drpcNodeGracefulExitGetNonExitingSatellitesStream struct { + drpc.Stream +} + +func (x *drpcNodeGracefulExitGetNonExitingSatellitesStream) SendAndClose(m *GetNonExitingSatellitesResponse) error { + if err := x.MsgSend(m); err != nil { + return err + } + return x.CloseSend() +} + +type DRPCNodeGracefulExit_StartExitStream interface { + drpc.Stream + SendAndClose(*StartExitResponse) error +} + +type drpcNodeGracefulExitStartExitStream struct { + drpc.Stream +} + +func (x *drpcNodeGracefulExitStartExitStream) SendAndClose(m *StartExitResponse) error { + if err := x.MsgSend(m); err != nil { + return err + } + return x.CloseSend() } type DRPCSatelliteGracefulExitClient interface { @@ -907,6 +1268,107 @@ var _ grpc.ClientConn // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion4 +// NodeGracefulExitClient is the client API for NodeGracefulExit service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type NodeGracefulExitClient interface { + // GetSatellitesList returns a list of satellites that the storagenode has not begun a graceful exit for. + GetNonExitingSatellites(ctx context.Context, in *GetNonExitingSatellitesRequest, opts ...grpc.CallOption) (*GetNonExitingSatellitesResponse, error) + // StartExit updates one or more satellites in the storagenode's database to be gracefully exiting. + StartExit(ctx context.Context, in *StartExitRequest, opts ...grpc.CallOption) (*StartExitResponse, error) +} + +type nodeGracefulExitClient struct { + cc *grpc.ClientConn +} + +func NewNodeGracefulExitClient(cc *grpc.ClientConn) NodeGracefulExitClient { + return &nodeGracefulExitClient{cc} +} + +func (c *nodeGracefulExitClient) GetNonExitingSatellites(ctx context.Context, in *GetNonExitingSatellitesRequest, opts ...grpc.CallOption) (*GetNonExitingSatellitesResponse, error) { + out := new(GetNonExitingSatellitesResponse) + err := c.cc.Invoke(ctx, "/gracefulexit.NodeGracefulExit/GetNonExitingSatellites", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeGracefulExitClient) StartExit(ctx context.Context, in *StartExitRequest, opts ...grpc.CallOption) (*StartExitResponse, error) { + out := new(StartExitResponse) + err := c.cc.Invoke(ctx, "/gracefulexit.NodeGracefulExit/StartExit", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// NodeGracefulExitServer is the server API for NodeGracefulExit service. +type NodeGracefulExitServer interface { + // GetSatellitesList returns a list of satellites that the storagenode has not begun a graceful exit for. + GetNonExitingSatellites(context.Context, *GetNonExitingSatellitesRequest) (*GetNonExitingSatellitesResponse, error) + // StartExit updates one or more satellites in the storagenode's database to be gracefully exiting. + StartExit(context.Context, *StartExitRequest) (*StartExitResponse, error) +} + +func RegisterNodeGracefulExitServer(s *grpc.Server, srv NodeGracefulExitServer) { + s.RegisterService(&_NodeGracefulExit_serviceDesc, srv) +} + +func _NodeGracefulExit_GetNonExitingSatellites_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNonExitingSatellitesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeGracefulExitServer).GetNonExitingSatellites(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gracefulexit.NodeGracefulExit/GetNonExitingSatellites", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeGracefulExitServer).GetNonExitingSatellites(ctx, req.(*GetNonExitingSatellitesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NodeGracefulExit_StartExit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StartExitRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeGracefulExitServer).StartExit(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gracefulexit.NodeGracefulExit/StartExit", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeGracefulExitServer).StartExit(ctx, req.(*StartExitRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _NodeGracefulExit_serviceDesc = grpc.ServiceDesc{ + ServiceName: "gracefulexit.NodeGracefulExit", + HandlerType: (*NodeGracefulExitServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetNonExitingSatellites", + Handler: _NodeGracefulExit_GetNonExitingSatellites_Handler, + }, + { + MethodName: "StartExit", + Handler: _NodeGracefulExit_StartExit_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "gracefulexit.proto", +} + // SatelliteGracefulExitClient is the client API for SatelliteGracefulExit service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. diff --git a/pkg/pb/gracefulexit.proto b/pkg/pb/gracefulexit.proto index ec086bb2e..dd444e614 100644 --- a/pkg/pb/gracefulexit.proto +++ b/pkg/pb/gracefulexit.proto @@ -10,8 +10,44 @@ import "orders.proto"; package gracefulexit; +// NodeGracefulExit is a private service on storagenodes +service NodeGracefulExit { + // GetSatellitesList returns a list of satellites that the storagenode has not begun a graceful exit for. + rpc GetNonExitingSatellites(GetNonExitingSatellitesRequest) returns (GetNonExitingSatellitesResponse); + // StartExit updates one or more satellites in the storagenode's database to be gracefully exiting. + rpc StartExit(StartExitRequest) returns (StartExitResponse); + +} + +message GetNonExitingSatellitesRequest{} + +message StartExitRequest { + repeated bytes node_ids = 1 [(gogoproto.customtype) = "NodeID", (gogoproto.nullable) = false]; +} + +// NonExitingSatellite contains information that's needed for a storagenode to start graceful exit +message NonExitingSatellite { + bytes node_id = 1 [(gogoproto.customtype) = "NodeID", (gogoproto.nullable) = false]; + string domain_name = 2; + double space_used = 3; +} + +message GetNonExitingSatellitesResponse { + repeated NonExitingSatellite satellites = 1; +} + +// StartExitStatus indicates the result of graceful exit initialization from a storagenode +message StartExitStatus { + string domain_name = 1; + bool success = 2; +} + +message StartExitResponse { + repeated StartExitStatus statuses = 1; +} + service SatelliteGracefulExit { - // Process is called by storage nodes to initiate the graceful exit, get pieces to transfer, and receive exit status. + // Process is called by storage nodes to initiate the graceful exit, get pieces to transfer, and receive exit status. rpc Process(stream StorageNodeMessage) returns (stream SatelliteMessage); } @@ -74,4 +110,5 @@ message SatelliteMessage { ExitCompleted exit_completed = 4; ExitFailed exit_failed = 5; } -} \ No newline at end of file +} + diff --git a/pkg/rpc/compat_drpc.go b/pkg/rpc/compat_drpc.go index 96dc84784..aa16f62eb 100644 --- a/pkg/rpc/compat_drpc.go +++ b/pkg/rpc/compat_drpc.go @@ -32,6 +32,9 @@ type ( // NodeClient is an alias to the drpc client interface NodeClient = pb.DRPCNodeClient + // NodeGracefulExitClient is an alias to the drpc client interface + NodeGracefulExitClient = pb.DRPCNodeGracefulExitClient + // NodeStatsClient is an alias to the drpc client interface NodeStatsClient = pb.DRPCNodeStatsClient @@ -117,6 +120,16 @@ func (c *Conn) NodeClient() NodeClient { return NewNodeClient(c.raw) } +// NewNodeGracefulExitClient returns the drpc version of a NodeGracefulExitClient +func NewNodeGracefulExitClient(rc *RawConn) NodeGracefulExitClient { + return pb.NewDRPCNodeGracefulExitClient(rc) +} + +// NodeGracefulExitClient returns a NodeGracefulExitClient for this connection +func (c *Conn) NodeGracefulExitClient() NodeGracefulExitClient { + return NewNodeGracefulExitClient(c.raw) +} + // NewNodeStatsClient returns the drpc version of a NodeStatsClient func NewNodeStatsClient(rc *RawConn) NodeStatsClient { return pb.NewDRPCNodeStatsClient(rc) diff --git a/pkg/rpc/compat_grpc.go b/pkg/rpc/compat_grpc.go index 89fb4e477..32103311e 100644 --- a/pkg/rpc/compat_grpc.go +++ b/pkg/rpc/compat_grpc.go @@ -33,6 +33,9 @@ type ( // NodeClient is an alias to the grpc client interface NodeClient = pb.NodeClient + // NodeGracefulExitClient is an alias to the grpc client interface + NodeGracefulExitClient = pb.NodeGracefulExitClient + // NodeStatsClient is an alias to the grpc client interface NodeStatsClient = pb.NodeStatsClient @@ -118,6 +121,16 @@ func (c *Conn) NodeClient() NodeClient { return NewNodeClient(c.raw) } +// NewNodeGracefulExitClient returns the grpc version of a NodeGracefulExitClient +func NewNodeGracefulExitClient(rc *RawConn) NodeGracefulExitClient { + return pb.NewNodeGracefulExitClient(rc) +} + +// NodeGracefulExitClient returns a NodeGracefulExitClient for this connection +func (c *Conn) NodeGracefulExitClient() NodeGracefulExitClient { + return NewNodeGracefulExitClient(c.raw) +} + // NewNodeStatsClient returns the grpc version of a NodeStatsClient func NewNodeStatsClient(rc *RawConn) NodeStatsClient { return pb.NewNodeStatsClient(rc) diff --git a/proto.lock b/proto.lock index f943381b4..7271e4517 100644 --- a/proto.lock +++ b/proto.lock @@ -877,6 +877,97 @@ } ], "messages": [ + { + "name": "GetNonExitingSatellitesRequest" + }, + { + "name": "StartExitRequest", + "fields": [ + { + "id": 1, + "name": "node_ids", + "type": "bytes", + "is_repeated": true, + "options": [ + { + "name": "(gogoproto.customtype)", + "value": "NodeID" + }, + { + "name": "(gogoproto.nullable)", + "value": "false" + } + ] + } + ] + }, + { + "name": "NonExitingSatellite", + "fields": [ + { + "id": 1, + "name": "node_id", + "type": "bytes", + "options": [ + { + "name": "(gogoproto.customtype)", + "value": "NodeID" + }, + { + "name": "(gogoproto.nullable)", + "value": "false" + } + ] + }, + { + "id": 2, + "name": "domain_name", + "type": "string" + }, + { + "id": 3, + "name": "space_used", + "type": "double" + } + ] + }, + { + "name": "GetNonExitingSatellitesResponse", + "fields": [ + { + "id": 1, + "name": "satellites", + "type": "NonExitingSatellite", + "is_repeated": true + } + ] + }, + { + "name": "StartExitStatus", + "fields": [ + { + "id": 1, + "name": "domain_name", + "type": "string" + }, + { + "id": 2, + "name": "success", + "type": "bool" + } + ] + }, + { + "name": "StartExitResponse", + "fields": [ + { + "id": 1, + "name": "statuses", + "type": "StartExitStatus", + "is_repeated": true + } + ] + }, { "name": "TransferSucceeded", "fields": [ @@ -1057,6 +1148,21 @@ } ], "services": [ + { + "name": "NodeGracefulExit", + "rpcs": [ + { + "name": "GetNonExitingSatellites", + "in_type": "GetNonExitingSatellitesRequest", + "out_type": "GetNonExitingSatellitesResponse" + }, + { + "name": "StartExit", + "in_type": "StartExitRequest", + "out_type": "StartExitResponse" + } + ] + }, { "name": "SatelliteGracefulExit", "rpcs": [ diff --git a/storagenode/gracefulexit/endpoint.go b/storagenode/gracefulexit/endpoint.go new file mode 100644 index 000000000..6a4ce936a --- /dev/null +++ b/storagenode/gracefulexit/endpoint.go @@ -0,0 +1,128 @@ +// Copyright (C) 2019 Storj Labs, Inc. +// See LICENSE for copying information. + +package gracefulexit + +import ( + "context" + "time" + + "github.com/zeebo/errs" + "go.uber.org/zap" + + "storj.io/storj/pkg/pb" + "storj.io/storj/storagenode/pieces" + "storj.io/storj/storagenode/satellites" + "storj.io/storj/storagenode/trust" +) + +// Error is the default error class for graceful exit package. +var Error = errs.Class("gracefulexit") + +// Endpoint is +type Endpoint struct { + log *zap.Logger + usageCache *pieces.BlobsUsageCache + trust *trust.Pool + satellites satellites.DB +} + +// NewEndpoint creates a new graceful exit endpoint. +func NewEndpoint(log *zap.Logger, trust *trust.Pool, satellites satellites.DB, usageCache *pieces.BlobsUsageCache) *Endpoint { + return &Endpoint{ + log: log, + usageCache: usageCache, + trust: trust, + satellites: satellites, + } +} + +// GetNonExitingSatellites returns a list of satellites that the storagenode has not begun a graceful exit for. +func (e *Endpoint) GetNonExitingSatellites(ctx context.Context, req *pb.GetNonExitingSatellitesRequest) (*pb.GetNonExitingSatellitesResponse, error) { + e.log.Debug("initialize graceful exit: GetSatellitesList") + // get all trusted satellites + trustedSatellites := e.trust.GetSatellites(ctx) + + availableSatellites := make([]*pb.NonExitingSatellite, 0, len(trustedSatellites)) + + // filter out satellites that are already exiting + exitingSatellites, err := e.satellites.ListGracefulExits(ctx) + if err != nil { + return nil, Error.Wrap(err) + } + + for _, trusted := range trustedSatellites { + var isExiting bool + for _, exiting := range exitingSatellites { + if trusted == exiting.SatelliteID { + isExiting = true + break + } + } + + if isExiting { + continue + } + + // get domain name + domain, err := e.trust.GetAddress(ctx, trusted) + if err != nil { + e.log.Debug("graceful exit: get satellite domian name", zap.String("satelliteID", trusted.String()), zap.Error(err)) + continue + } + // get space usage by satellites + spaceUsed, err := e.usageCache.SpaceUsedBySatellite(ctx, trusted) + if err != nil { + e.log.Debug("graceful exit: get space used by satellite", zap.String("satelliteID", trusted.String()), zap.Error(err)) + continue + } + availableSatellites = append(availableSatellites, &pb.NonExitingSatellite{ + DomainName: domain, + NodeId: trusted, + SpaceUsed: float64(spaceUsed), + }) + } + + return &pb.GetNonExitingSatellitesResponse{ + Satellites: availableSatellites, + }, nil +} + +// StartExit updates one or more satellites in the storagenode's database to be gracefully exiting. +func (e *Endpoint) StartExit(ctx context.Context, req *pb.StartExitRequest) (*pb.StartExitResponse, error) { + e.log.Debug("initialize graceful exit: StartExit", zap.Int("satellite count", len(req.NodeIds))) + // save satellites info into db + resp := &pb.StartExitResponse{} + for _, satelliteID := range req.NodeIds { + e.log.Debug("initialize graceful exit: StartExit", zap.String("satellite ID", satelliteID.String())) + + status := &pb.StartExitStatus{ + Success: false, + } + domain, err := e.trust.GetAddress(ctx, satelliteID) + if err != nil { + e.log.Debug("initialize graceful exit: StartExit", zap.Error(err)) + resp.Statuses = append(resp.Statuses, status) + continue + } + status.DomainName = domain + + // get space usage by satellites + spaceUsed, err := e.usageCache.SpaceUsedBySatellite(ctx, satelliteID) + if err != nil { + e.log.Debug("initialize graceful exit: StartExit", zap.Error(err)) + resp.Statuses = append(resp.Statuses, status) + continue + } + err = e.satellites.InitiateGracefulExit(ctx, satelliteID, time.Now().UTC(), spaceUsed) + if err != nil { + e.log.Debug("initialize graceful exit: StartExit", zap.Error(err)) + resp.Statuses = append(resp.Statuses, status) + continue + } + status.Success = true + resp.Statuses = append(resp.Statuses, status) + } + + return resp, nil +} diff --git a/storagenode/gracefulexit/endpoint_test.go b/storagenode/gracefulexit/endpoint_test.go new file mode 100644 index 000000000..5057c5cfa --- /dev/null +++ b/storagenode/gracefulexit/endpoint_test.go @@ -0,0 +1,78 @@ +// Copyright (C) 2019 Storj Labs, Inc. +// See LICENSE for copying information. + +package gracefulexit_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + "storj.io/storj/internal/testcontext" + "storj.io/storj/internal/testplanet" + "storj.io/storj/pkg/pb" + "storj.io/storj/pkg/storj" +) + +func TestGetNonExitingSatellites(t *testing.T) { + ctx := testcontext.New(t) + defer ctx.Cleanup() + + totalSatelliteCount := 3 + exitingSatelliteCount := 1 + planet, err := testplanet.New(t, totalSatelliteCount, 1, 1) + require.NoError(t, err) + defer ctx.Check(planet.Shutdown) + + planet.Start(ctx) + exitingSatellite := planet.Satellites[0] + storagenode := planet.StorageNodes[0] + + // set a satellite to already be exiting + err = storagenode.DB.Satellites().InitiateGracefulExit(ctx, exitingSatellite.ID(), time.Now().UTC(), 0) + require.NoError(t, err) + + nonExitingSatellites, err := storagenode.GracefulExit.Endpoint.GetNonExitingSatellites(ctx, &pb.GetNonExitingSatellitesRequest{}) + require.NoError(t, err) + require.Len(t, nonExitingSatellites.GetSatellites(), totalSatelliteCount-exitingSatelliteCount) + + for _, satellite := range nonExitingSatellites.GetSatellites() { + require.NotEqual(t, exitingSatellite.ID(), satellite.NodeId) + } +} + +func TestStartExiting(t *testing.T) { + ctx := testcontext.New(t) + defer ctx.Cleanup() + + totalSatelliteCount := 3 + const exitingSatelliteCount = 2 + planet, err := testplanet.New(t, totalSatelliteCount, 1, 1) + require.NoError(t, err) + defer ctx.Check(planet.Shutdown) + + planet.Start(ctx) + storagenode := planet.StorageNodes[0] + + exitingSatelliteIDs := []storj.NodeID{ + planet.Satellites[0].ID(), + planet.Satellites[1].ID(), + } + req := &pb.StartExitRequest{ + NodeIds: exitingSatelliteIDs, + } + + resp, err := storagenode.GracefulExit.Endpoint.StartExit(ctx, req) + require.NoError(t, err) + for _, status := range resp.GetStatuses() { + require.True(t, status.GetSuccess()) + } + + exitStatuses, err := storagenode.DB.Satellites().ListGracefulExits(ctx) + require.NoError(t, err) + require.Len(t, exitStatuses, exitingSatelliteCount) + for _, status := range exitStatuses { + require.Contains(t, exitingSatelliteIDs, status.SatelliteID) + } +} diff --git a/storagenode/peer.go b/storagenode/peer.go index cd4669c0c..def958e0b 100644 --- a/storagenode/peer.go +++ b/storagenode/peer.go @@ -31,6 +31,7 @@ import ( "storj.io/storj/storagenode/console/consoleassets" "storj.io/storj/storagenode/console/consoleserver" "storj.io/storj/storagenode/contact" + "storj.io/storj/storagenode/gracefulexit" "storj.io/storj/storagenode/inspector" "storj.io/storj/storagenode/monitor" "storj.io/storj/storagenode/nodestats" @@ -153,6 +154,10 @@ type Peer struct { Endpoint *consoleserver.Server } + GracefulExit struct { + Endpoint *gracefulexit.Endpoint + } + Bandwidth *bandwidth.Service } @@ -380,6 +385,17 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, revocationDB exten pb.DRPCRegisterPieceStoreInspector(peer.Server.PrivateDRPC(), peer.Storage2.Inspector) } + { // setup graceful exit service + peer.GracefulExit.Endpoint = gracefulexit.NewEndpoint( + peer.Log.Named("gracefulexit:endpoint"), + peer.Storage2.Trust, + peer.DB.Satellites(), + peer.Storage2.BlobsCache, + ) + pb.RegisterNodeGracefulExitServer(peer.Server.PrivateGRPC(), peer.GracefulExit.Endpoint) + pb.DRPCRegisterNodeGracefulExit(peer.Server.PrivateDRPC(), peer.GracefulExit.Endpoint) + } + peer.Collector = collector.NewService(peer.Log.Named("collector"), peer.Storage2.Store, peer.DB.UsedSerials(), config.Collector) peer.Bandwidth = bandwidth.NewService(peer.Log.Named("bandwidth"), peer.DB.Bandwidth(), config.Bandwidth)