Issue #3 asked for commands to stop and start the system, and 05aa21c gave
only one machine's services. Now:
- llmgw stop sets serving.stopped in the cluster's settings, live: the
reconciler wants every model at no replicas, freeing every GPU, and the
gateway answers every POST under /v1/ with 503 system_stopped. The control
planes, agents and mirror keep running, and no model's definition changes.
- llmgw start clears it; every model is placed again as it asks.
- llmgw restart has every agent restart over its stream (RestartAgent), then
the other control planes over ssh, standbys before a leader, then this
one; engines keep serving.
- llmgw status is the cluster's summary, saying when it is stopped.
One machine's services moved to llmgw service status|start|stop|restart.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
62 lines
1.7 KiB
Go
62 lines
1.7 KiB
Go
package agentsvc
|
|
|
|
import (
|
|
"time"
|
|
|
|
llmgwv1 "gitea.mynodes.xyz/ilker/llmgw/api/gen/llmgw/v1"
|
|
)
|
|
|
|
// SetFirewall gives the service whether nodes keep llmgw's firewall, read
|
|
// at each use so a change to the cluster's settings is what is sent next.
|
|
func (s *Service) SetFirewall(f func() *llmgwv1.Firewall) {
|
|
s.mu.Lock()
|
|
s.firewall = f
|
|
s.mu.Unlock()
|
|
}
|
|
|
|
func (s *Service) firewallMsg() *llmgwv1.ControlMessage {
|
|
s.mu.RLock()
|
|
f := s.firewall
|
|
s.mu.RUnlock()
|
|
if f == nil {
|
|
return nil
|
|
}
|
|
fw := f()
|
|
if fw == nil {
|
|
return nil
|
|
}
|
|
return &llmgwv1.ControlMessage{Msg: &llmgwv1.ControlMessage_Firewall{Firewall: fw}}
|
|
}
|
|
|
|
// BroadcastFirewall tells every connected agent what the cluster's settings
|
|
// now say of the firewall. A node not connected is told when it registers.
|
|
func (s *Service) BroadcastFirewall() {
|
|
msg := s.firewallMsg()
|
|
if msg == nil {
|
|
return
|
|
}
|
|
for _, node := range s.ConnectedNodes() {
|
|
if err := s.send(node, msg); err != nil {
|
|
s.log.Warn("could not tell a node about the firewall; it is told when it next registers",
|
|
"node", node, "err", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// RestartAgents has every connected agent start again, one at a time a
|
|
// moment apart, and names those it told. Their engines keep serving.
|
|
func (s *Service) RestartAgents(reason string) []string {
|
|
msg := &llmgwv1.ControlMessage{Msg: &llmgwv1.ControlMessage_RestartAgent{
|
|
RestartAgent: &llmgwv1.RestartAgent{Reason: reason}}}
|
|
var told []string
|
|
for _, node := range s.ConnectedNodes() {
|
|
if err := s.send(node, msg); err != nil {
|
|
s.log.Warn("could not tell a node to restart its agent", "node", node, "err", err)
|
|
continue
|
|
}
|
|
told = append(told, node)
|
|
time.Sleep(time.Second)
|
|
}
|
|
return told
|
|
}
|