compute/pkg/api/raft/node.go

123 lines
3.0 KiB
Go

package raft
import (
"encoding/json"
"fmt"
"log"
"time"
raft_hashicorp "github.com/hashicorp/raft"
"libvirt.org/go/libvirt"
etcd_client "deevirt.fr/compute/pkg/etcd"
//"deevirt.fr/compute/pkg/scheduler"
)
type RaftNode struct {
Bootstrap bool
Raft *raft_hashicorp.Raft
Store *Store
NodeID string
StateCh chan raft_hashicorp.Observation
}
func (n *RaftNode) init() {
println("bootstrap :")
nodes := make(NodeStore)
// Récupération des Noeuds ID
etcd, _ := etcd_client.New(n.Store.conf.EtcdURI)
defer etcd.Close()
for key, value := range etcd_client.GetNodes(etcd, n.Store.conf.ClusterID) {
nodes[key] = &NodeStoreInfo{
IpManagement: value.IpManagement,
Scoring: 0,
}
println(key)
println(value.IpManagement)
var libvirt_uri string
if n.Store.conf.LibvirtTLS {
libvirt_uri = fmt.Sprintf("qemu+tls://%s/system", value.IpManagement)
} else {
libvirt_uri = fmt.Sprintf("qemu+tcp://%s/system", value.IpManagement)
}
c, err := libvirt.NewConnect(libvirt_uri)
if err != nil {
log.Fatalf("Erreur %v", err)
}
defer c.Close()
getDomains, _ := c.ListAllDomains(libvirt.CONNECT_LIST_DOMAINS_PERSISTENT)
for _, domain := range getDomains {
conf, _ := domain.GetXMLDesc(libvirt.DOMAIN_XML_INACTIVE)
uuid, _ := domain.GetUUIDString()
state, _, _ := domain.GetState()
d, _ := json.Marshal(struct {
Config string `json:"config"`
State int `json:"state"`
Migrate bool `json:"Migrate"`
}{
conf, int(state), false,
})
n.Store.Set(fmt.Sprintf("/etc/libvirt/qemu/%s/%s", key, uuid), d)
}
}
jNodes, _ := json.Marshal(nodes)
n.Store.Set("/etc/libvirt/cluster", jNodes)
}
// Fonction pour surveiller et afficher les changements d'état
func (n *RaftNode) WatchStateChanges() {
worker, _ := NewWorker(n.Store)
for obs := range n.StateCh {
switch evt := obs.Data.(type) {
case raft_hashicorp.RaftState:
if evt == raft_hashicorp.Leader {
log.Println("[ÉVÉNEMENT] Changement d'état Raft :", evt)
if n.Bootstrap {
n.init()
}
// On attend une seconde avant de démarrer le worker
time.Sleep(1 * time.Second)
worker.Start()
} else {
worker.Stop()
}
log.Println("[ÉVÉNEMENT] Changement d'état Raft :", evt)
case raft_hashicorp.LeaderObservation:
log.Println("[ÉVÉNEMENT] Le leader est", evt.LeaderID)
case raft_hashicorp.PeerObservation:
if n.Raft.State() == raft_hashicorp.Leader {
peerID := evt.Peer.ID
peerAddr := evt.Peer.Address
log.Println("[NOUVEAU NŒUD] Détection de", peerID, "à", peerAddr)
log.Println("[ACTION] Ajout automatique en tant que voter...")
future := n.Raft.AddVoter(peerID, peerAddr, 0, 0)
if err := future.Error(); err != nil {
log.Println("[ERREUR] Impossible d'ajouter", peerID, ":", err)
} else {
log.Println("[SUCCÈS] Voter ajouté :", peerID)
}
}
case raft_hashicorp.FailedHeartbeatObservation:
log.Println("[ÉVÉNEMENT] Perte de connexion avec un nœud :", evt.PeerID)
default:
log.Println("[ÉVÉNEMENT] Autre événement :", evt)
}
}
}