CI / test (push) Failing after 30m4s
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>
40 lines
1.3 KiB
Go
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
|
|
}
|