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) } } }