blob: 8b8ea152ff3edff042f8196cf882c71129082b35 [file] [log] [blame]
Serge Bazanski516d3002021-10-01 00:05:41 +02001package curator
2
3import (
4 "context"
5 "crypto/rand"
6
Lorenz Brund13c1c62022-03-30 19:58:58 +02007 clientv3 "go.etcd.io/etcd/client/v3"
Serge Bazanski516d3002021-10-01 00:05:41 +02008 "google.golang.org/grpc/codes"
9 "google.golang.org/grpc/status"
10 "google.golang.org/protobuf/proto"
11
12 ppb "source.monogon.dev/metropolis/node/core/curator/proto/private"
Serge Bazanski5a637b02022-02-18 12:18:04 +010013 "source.monogon.dev/metropolis/node/core/rpc"
Serge Bazanski516d3002021-10-01 00:05:41 +020014)
15
16// ensureRegisterTicket returns the cluster's current RegisterTicket, creating
17// one if not yet present in the cluster state.
18func (l *leadership) ensureRegisterTicket(ctx context.Context) ([]byte, error) {
19 l.muRegisterTicket.Lock()
20 defer l.muRegisterTicket.Unlock()
21
Serge Bazanski5a637b02022-02-18 12:18:04 +010022 rpc.Trace(ctx).Printf("ensureRegisterTicket()...")
23
Serge Bazanski516d3002021-10-01 00:05:41 +020024 // Retrieve existing ticket, if any.
25 res, err := l.txnAsLeader(ctx, clientv3.OpGet(registerTicketEtcdPath))
26 if err != nil {
27 return nil, status.Errorf(codes.Unavailable, "could not retrieve register ticket: %v", err)
28 }
29 kvs := res.Responses[0].GetResponseRange().Kvs
30 if len(kvs) > 0 {
31 // Ticket already generated, return.
Serge Bazanski5a637b02022-02-18 12:18:04 +010032 rpc.Trace(ctx).Printf("ensureRegisterTicket(): ticket already exists")
Serge Bazanski516d3002021-10-01 00:05:41 +020033 return kvs[0].Value, nil
34 }
35
36 // No ticket, generate one.
37 ticket := &ppb.RegisterTicket{
38 Opaque: make([]byte, registerTicketSize),
39 }
40 _, err = rand.Read(ticket.Opaque)
41 if err != nil {
42 return nil, status.Errorf(codes.Unavailable, "could not generate new ticket: %v", err)
43 }
44 ticketBytes, err := proto.Marshal(ticket)
45 if err != nil {
46 return nil, status.Errorf(codes.Unavailable, "could not marshal new ticket: %v", err)
47 }
48
49 // Commit new ticket to etcd.
50 _, err = l.txnAsLeader(ctx, clientv3.OpPut(registerTicketEtcdPath, string(ticketBytes)))
51 if err != nil {
52 return nil, status.Errorf(codes.Unavailable, "could not save new ticket: %v", err)
53 }
54
Serge Bazanski5a637b02022-02-18 12:18:04 +010055 rpc.Trace(ctx).Printf("ensureRegisterTicket(): generated and saved new ticket")
56
Serge Bazanski516d3002021-10-01 00:05:41 +020057 return ticketBytes, nil
58}