| Serge Bazanski | 516d300 | 2021-10-01 00:05:41 +0200 | [diff] [blame] | 1 | package curator |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "crypto/rand" |
| 6 | |
| Lorenz Brun | d13c1c6 | 2022-03-30 19:58:58 +0200 | [diff] [blame] | 7 | clientv3 "go.etcd.io/etcd/client/v3" |
| Serge Bazanski | 516d300 | 2021-10-01 00:05:41 +0200 | [diff] [blame] | 8 | "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 Bazanski | 5a637b0 | 2022-02-18 12:18:04 +0100 | [diff] [blame] | 13 | "source.monogon.dev/metropolis/node/core/rpc" |
| Serge Bazanski | 516d300 | 2021-10-01 00:05:41 +0200 | [diff] [blame] | 14 | ) |
| 15 | |
| 16 | // ensureRegisterTicket returns the cluster's current RegisterTicket, creating |
| 17 | // one if not yet present in the cluster state. |
| 18 | func (l *leadership) ensureRegisterTicket(ctx context.Context) ([]byte, error) { |
| 19 | l.muRegisterTicket.Lock() |
| 20 | defer l.muRegisterTicket.Unlock() |
| 21 | |
| Serge Bazanski | 5a637b0 | 2022-02-18 12:18:04 +0100 | [diff] [blame] | 22 | rpc.Trace(ctx).Printf("ensureRegisterTicket()...") |
| 23 | |
| Serge Bazanski | 516d300 | 2021-10-01 00:05:41 +0200 | [diff] [blame] | 24 | // 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 Bazanski | 5a637b0 | 2022-02-18 12:18:04 +0100 | [diff] [blame] | 32 | rpc.Trace(ctx).Printf("ensureRegisterTicket(): ticket already exists") |
| Serge Bazanski | 516d300 | 2021-10-01 00:05:41 +0200 | [diff] [blame] | 33 | 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 Bazanski | 5a637b0 | 2022-02-18 12:18:04 +0100 | [diff] [blame] | 55 | rpc.Trace(ctx).Printf("ensureRegisterTicket(): generated and saved new ticket") |
| 56 | |
| Serge Bazanski | 516d300 | 2021-10-01 00:05:41 +0200 | [diff] [blame] | 57 | return ticketBytes, nil |
| 58 | } |