123 lines
3.0 KiB
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)
|
|
}
|
|
}
|
|
}
|