Files
llmgw/internal/control/agentsvc/firewall.go
T
Ilker ManapandClaude Opus 5.5 7245dbe1dd llmgw stop, start and restart act on the whole system
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>
2026-10-07 18:01:45 +02:00

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
}