Files
llmgw/internal/cli/serverinit_standby.go
T
Ilker ManapandClaude Opus 5.5 94401e21e6 Setup lets every part be chosen, each with its settings; three machines each run the gateway
The setup screens list the parts of an install: control plane, store, model
mirror, this machine as a node, starter model, pictures and 3D, the judge,
firewall, notifications, limits, on-demand turns and an offline bundle. Each
says what it is or what is missing without it. Space turns a part on or off;
Enter opens its settings in a dialog that explains it. A plan page lists what
is installed and what is left out, and the same install as a command. Every
setting is a server init flag too, written into server.yaml when init writes
it.

With three machines, the two database machines become control planes too,
standing by (server add's steps), with an optional floating address. The
mirror's management API answers all three control planes, so a standby that
comes to lead can still fetch models.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 11:22:36 +02:00

40 lines
1.3 KiB
Go

package cli
import (
"context"
"errors"
"fmt"
"net"
)
// Three machines, each able to take over: the store's two machines are made
// control planes too, standing by while this one leads, as 'llmgw server add'
// makes any machine one. With the store replicated across them and etcd's
// three votes on the three, losing any one machine loses neither the store
// nor the gateway. With a floating address, clients keep the one address.
// ensureStandbys makes each machine of the replicated store a control plane,
// one after the other.
func (in *serverInit) ensureStandbys(ctx context.Context) error {
if len(in.patroniNodes) == 0 {
return errors.New("the standbys go on the store's machines: give them with --patroni")
}
var hosts []string
if ip, _, err := net.ParseCIDR(in.vip); err == nil {
hosts = []string{ip.String()}
}
for i, n := range in.patroniNodes {
fmt.Fprintf(in.out, " .. making %s a control plane too\n", n.Name)
sa := serverAdd{
etcDir: in.etcDir, pkiDir: in.pkiDir, hosts: hosts, vip: in.vip,
remote: n.Remote, noFirewall: in.noFirewall, addr: n.IP, ip: n.IP,
out: in.out, priority: 100 - 10*i, quiet: true,
}
if err := sa.run(ctx); err != nil {
return fmt.Errorf("%s: %w", n.Name, err)
}
in.done("%s (%s) is a control plane too, standing by while this one leads", n.Name, n.IP)
}
return nil
}