diff --git a/Makefile b/Makefile index c73978b..697c895 100644 --- a/Makefile +++ b/Makefile @@ -25,12 +25,11 @@ test: build = $(race_detector) all: clean release -release: +releases: + @echo "Building Wigo releases" @mkdir -p release - @cp $(BASE_DIR)/src/wigo/global.go $(BASE_DIR)/src/wigo/global.go.bkp @cd release && for target in $(RELEASE_TARGETS) ; do \ RELEASE_DIR=$(BASE_DIR)/release/$$target; \ - sed -i "s/##VERSION##/Wigo v$(RELEASE_VERSION)/" $(BASE_DIR)/src/wigo/global.go;\ export CGO_ENABLED=1; \ export GOPATH=`echo "$(GOPATH):$(BASE_DIR)"`; \ export GOOS=`echo $$target | cut -d "-" -f 1`; \ @@ -43,15 +42,23 @@ release: export CC=; \ fi ; \ mkdir $$RELEASE_DIR; \ - echo "Building Wigo for $$target to $$RELEASE_DIR"; \ - $(build) -o $$RELEASE_DIR/wigo $(BASE_DIR)/src/wigo.go; \ - $(build) -o $$RELEASE_DIR/wigocli $(BASE_DIR)/src/wigocli.go; \ - $(build) -o $$RELEASE_DIR/generate_cert $(BASE_DIR)/src/generate_cert.go; \ - cp $(BASE_DIR)/src/wigo/global.go.bkp $(BASE_DIR)/src/wigo/global.go; \ + echo "Building Wigo release for $$target to $$RELEASE_DIR"; \ + $(build) -ldflags "-X wigo.Version=$(RELEASE_VERSION)" -o $$RELEASE_DIR/wigo $(BASE_DIR)/src/wigo.go; \ + $(build) -ldflags "-X wigo.Version=$(RELEASE_VERSION)" -o $$RELEASE_DIR/wigocli $(BASE_DIR)/src/wigocli.go; \ + $(build) -o $$RELEASE_DIR/generate_cert $(BASE_DIR)/src/generate_cert.go; \ done - @rm $(BASE_DIR)/src/wigo/global.go.bkp + +release: + @echo "Building Wigo release for current OS" + @mkdir -p release + @cd release; \ + export GOPATH=`echo "$(GOPATH):$(BASE_DIR)"`; \ + $(build) -ldflags "-X wigo.Version=$(RELEASE_VERSION)" -o current/wigo $(BASE_DIR)/src/wigo.go; \ + $(build) -ldflags "-X wigo.Version=$(RELEASE_VERSION)" -o current/wigocli $(BASE_DIR)/src/wigocli.go; \ + $(build) -o current/generate_cert $(BASE_DIR)/src/generate_cert.go debs: + @echo "Building Wigo Debian packages" @mkdir -p $(DEBROOT) @mkdir -p $(DEBROOT)/etc/wigo/conf.d @mkdir -p $(DEBROOT)/etc/logrotate.d @@ -75,6 +82,7 @@ debs: @cp -R public $(DEBROOT)/usr/local/wigo @sed -i "s/##VERSION##/Wigo v$(RELEASE_VERSION)/" $(DEBROOT)/usr/local/wigo/public/index.html @for arch in amd64 armhf ; do \ + echo "Building Wigo Debian package for $$arch to $(DEBROOT)"; \ cp -R build/deb/DEBIAN/control $(DEBROOT)/DEBIAN/control ; \ sed -i "s/^Version:.*/Version: $(RELEASE_VERSION)/" $(DEBROOT)/DEBIAN/control ; \ sed -i "s/^Architecture:.*/Architecture: $$arch/" $(DEBROOT)/DEBIAN/control ; \ @@ -87,9 +95,10 @@ debs: done publish-debs: + @echo "Publishing Wigo Debian packages to repo" @for arch in amd64 armhf ; do \ for release in stretch buster ; do \ - echo "Adding package with arch $$arch and release $$release to repo" ; \ + echo "Adding package with arch $$arch and release $$release to repo $(REPOROOT)" ; \ reprepro --ask-passphrase -b $(REPOROOT) includedeb $$release $(DEBROOT)/wigo-$(RELEASE_VERSION)-$$arch.deb ; \ done \ done @@ -104,9 +113,11 @@ lint: test $$FAIL -eq 0 clean: + @echo "Cleaning all files" @rm -rf release @rm -rf $(DEBROOT) deps: + @echo "Installing dependencies" @export GOPATH=`echo "$(GOPATH):$(BASE_DIR)"`; \ go get -d ./... diff --git a/src/wigo.go b/src/wigo.go index 5367a47..2d21457 100644 --- a/src/wigo.go +++ b/src/wigo.go @@ -177,8 +177,8 @@ func threadLocalChecks() { // Delete probes results of this directory for c := currentProbesList.Front(); c != nil; c = c.Next() { probeName := c.Value.(string) - if _, ok := wigo.GetLocalWigo().GetLocalHost().Probes[probeName]; ok { - delete(wigo.GetLocalWigo().GetLocalHost().Probes, probeName) + if _, ok := wigo.GetLocalWigo().GetLocalHost().Probes.Get(probeName); ok { + wigo.GetLocalWigo().GetLocalHost().Probes.Remove(probeName) } } @@ -461,7 +461,7 @@ func launchRemoteHostCheckRoutine(Hostname wigo.AdvancedRemoteWigoConfig) { if Hostname.Port != 0 { host = Hostname.Hostname + ":" + strconv.Itoa(Hostname.Port) } else { - host = Hostname.Hostname + ":" + strconv.Itoa(wigo.GetLocalWigo().GetConfig().Global.ListenPort) + host = Hostname.Hostname + ":" + strconv.Itoa(wigo.GetLocalWigo().GetConfig().Http.Port) } // Create vars diff --git a/src/wigo/authority.go b/src/wigo/authority.go index 1898b5c..2c7a179 100644 --- a/src/wigo/authority.go +++ b/src/wigo/authority.go @@ -219,8 +219,9 @@ func (this *Authority) RevokeClient(uuid string) (err error) { log.Println("Authority : token " + token + " revoked") } } - if wigo, ok := LocalWigo.RemoteWigos[uuid]; ok { - delete(LocalWigo.RemoteWigos, uuid) + if tmp, ok := LocalWigo.RemoteWigos.Get(uuid); ok { + wigo := tmp.(*Wigo) + LocalWigo.RemoteWigos.Remove(uuid) log.Println("Authority : " + wigo.Hostname + " removed") } return diff --git a/src/wigo/config.go b/src/wigo/config.go index 115525b..e88f73a 100644 --- a/src/wigo/config.go +++ b/src/wigo/config.go @@ -55,6 +55,7 @@ func NewConfig(configFile string) (this *Config) { this.Global.AliveTimeout = 60 this.Global.ConfigFile = configFile this.Global.Debug = false + this.Global.Trace = false // Http server this.Http.Enabled = true @@ -116,6 +117,8 @@ func NewConfig(configFile string) (this *Config) { this.OpenTSDB.BufferSize = 10000 this.OpenTSDB.Tags = make(map[string]string) + log.Printf("Loading configuration file %s\n", this.Global.ConfigFile) + // Override with config file if _, err := toml.DecodeFile(this.Global.ConfigFile, &this); err != nil { log.Printf("Failed to load configuration file %s : %s\n", this.Global.ConfigFile, err) @@ -135,7 +138,7 @@ func NewConfig(configFile string) (this *Config) { } if port == 0 { - port = this.Global.ListenPort + port = this.Http.Port } // Create new RemoteWigoConfig @@ -162,13 +165,13 @@ func NewConfig(configFile string) (this *Config) { type GeneralConfig struct { Hostname string - ListenPort int ListenAddress string ProbesDirectory string ProbesConfigDirectory string UuidFile string LogFile string Debug bool + Trace bool ConfigFile string Group string Database string diff --git a/src/wigo/global.go b/src/wigo/global.go index f48ae8b..f8247ea 100644 --- a/src/wigo/global.go +++ b/src/wigo/global.go @@ -36,7 +36,7 @@ type Wigo struct { GlobalMessage string LocalHost *Host - RemoteWigos map[string]*Wigo + RemoteWigos *concurrentMapWigos Hostname string config *Config @@ -63,6 +63,7 @@ func NewWigo(config *Config) (this *Wigo, err error) { this.Version = Version this.GlobalStatus = 100 this.GlobalMessage = "OK" + log.Printf("Wigo version is : %s", this.Version) // Load uuid if _, err = os.Stat(this.config.Global.UuidFile); err == nil { @@ -116,7 +117,7 @@ func NewWigo(config *Config) (this *Wigo, err error) { this.LocalHost.parentWigo = this // Init RemoteWigos list - this.RemoteWigos = make(map[string]*Wigo) + this.RemoteWigos = NewConcurrentMapWigos() // Private vars this.locker = new(sync.RWMutex) @@ -231,7 +232,8 @@ Options: go func() { for { now := time.Now().Unix() - for _, host := range LocalWigo.RemoteWigos { + for item := range LocalWigo.RemoteWigos.IterBuffered() { + host := item.Val.(*Wigo) if host.LastUpdate < now-int64(config.Global.AliveTimeout) { if host.IsAlive { host.Down() @@ -261,6 +263,7 @@ func GetLocalWigo() *Wigo { func NewWigoFromJson(ba []byte, checkRemotesDepth int) (this *Wigo, e error) { this = new(Wigo) + this.RemoteWigos = NewConcurrentMapWigos() err := json.Unmarshal(ba, this) if err != nil { @@ -313,9 +316,11 @@ func (this *Wigo) RecomputeGlobalStatus() { this.GlobalStatus = 0 // Local probes - for probeName := range this.LocalHost.Probes { - if this.LocalHost.Probes[probeName].Status > this.GlobalStatus { - this.GlobalStatus = this.LocalHost.Probes[probeName].Status + for item := range this.LocalHost.Probes.IterBuffered() { + probe := item.Val.(*ProbeResult) + + if probe.Status > this.GlobalStatus { + this.GlobalStatus = probe.Status } } @@ -340,17 +345,20 @@ func (this *Wigo) GetOpenTsdb() *gopentsdb.OpenTsdb { } func (this *Wigo) Deduplicate(remoteWigo *Wigo) (err error) { - for uuid, wigo := range remoteWigo.RemoteWigos { + + for item := range remoteWigo.RemoteWigos.IterBuffered() { + uuid := item.Key + wigo := item.Val.(*Wigo) if uuid != wigo.Uuid { return errors.New(fmt.Sprintf("Remote wigo %s uuid mismatch ...", wigo.GetHostname())) } if wigo.Uuid != "" && this.Uuid == wigo.Uuid { log.Printf("Try to add a remote wigo %s with same uuid as me, Discarding.", wigo.GetHostname()) - delete(remoteWigo.RemoteWigos, uuid) + remoteWigo.RemoteWigos.Remove(uuid) } - if _, ok := this.RemoteWigos[uuid]; ok { + if _, ok := this.RemoteWigos.Get(uuid); ok { log.Printf("Found a duplicate wigo %s, Discarding.", wigo.GetHostname()) - delete(remoteWigo.RemoteWigos, uuid) + remoteWigo.RemoteWigos.Remove(uuid) } if err := this.Deduplicate(wigo); err != nil { return err @@ -374,15 +382,17 @@ func (this *Wigo) AddOrUpdateRemoteWigo(remoteWigo *Wigo) { return } - if oldWigo, ok := this.RemoteWigos[remoteWigo.Uuid]; ok { + if tmp, ok := this.RemoteWigos.Get(remoteWigo.Uuid); ok { + oldWigo := tmp.(*Wigo) if !oldWigo.IsAlive { remoteWigo.IsAlive = false } this.CompareTwoWigosAndRaiseNotifications(oldWigo, remoteWigo) } - this.RemoteWigos[remoteWigo.Uuid] = remoteWigo - this.RemoteWigos[remoteWigo.Uuid].LastUpdate = time.Now().Unix() + _remoteWigo := remoteWigo + _remoteWigo.LastUpdate = time.Now().Unix() + this.RemoteWigos.Set(remoteWigo.Uuid, _remoteWigo) this.RecomputeGlobalStatus() } @@ -390,10 +400,12 @@ func (this *Wigo) CompareTwoWigosAndRaiseNotifications(oldWigo *Wigo, newWigo *W // Detect changes and deleted probes if oldWigo.LocalHost != nil { - for probeName := range oldWigo.LocalHost.Probes { - oldProbe := oldWigo.LocalHost.Probes[probeName] + for item := range oldWigo.LocalHost.Probes.IterBuffered() { + probeName := item.Key + oldProbe := item.Val.(*ProbeResult) - if probeWhichStillExistInNew, ok := newWigo.LocalHost.Probes[probeName]; ok { + if tmp, ok := newWigo.LocalHost.Probes.Get(probeName); ok { + probeWhichStillExistInNew := tmp.(*ProbeResult) // Probe still exist in new newWigo.LocalHost.SetParentWigo(newWigo) @@ -417,19 +429,23 @@ func (this *Wigo) CompareTwoWigosAndRaiseNotifications(oldWigo *Wigo, newWigo *W // Detect new probes (only if new wigo is up) if newWigo.IsAlive && oldWigo.IsAlive { - for probeName := range newWigo.LocalHost.Probes { - if _, ok := oldWigo.LocalHost.Probes[probeName]; !ok { - NewNotificationProbe(nil, newWigo.LocalHost.Probes[probeName]) + for item := range newWigo.LocalHost.Probes.IterBuffered() { + probeName := item.Key + newProbe := item.Val.(*ProbeResult) + + if _, ok := oldWigo.LocalHost.Probes.Get(probeName); ok { + NewNotificationProbe(nil, newProbe) } } } // Remote Wigos - for wigoName := range oldWigo.RemoteWigos { + for item := range oldWigo.RemoteWigos.IterBuffered() { + wigoName := item.Key + oldWigo := item.Val.(*Wigo) - oldWigo := oldWigo.RemoteWigos[wigoName] - - if wigoStillExistInNew, ok := newWigo.RemoteWigos[wigoName]; ok { + if tmp, ok := newWigo.RemoteWigos.Get(wigoName); ok { + wigoStillExistInNew := tmp.(*Wigo) // Recursion this.CompareTwoWigosAndRaiseNotifications(oldWigo, wigoStillExistInNew) } @@ -437,12 +453,14 @@ func (this *Wigo) CompareTwoWigosAndRaiseNotifications(oldWigo *Wigo, newWigo *W } func (this *Wigo) SetParentHostsInProbes() { - for localProbeName := range this.GetLocalHost().Probes { - this.LocalHost.Probes[localProbeName].SetHost(this.LocalHost) + for item := range this.GetLocalHost().Probes.IterBuffered() { + localProbe := item.Val.(*ProbeResult) + localProbe.SetHost(this.LocalHost) } - for remoteWigo := range this.RemoteWigos { - this.RemoteWigos[remoteWigo].SetParentHostsInProbes() + for item := range this.RemoteWigos.IterBuffered() { + wigo := item.Val.(*Wigo) + wigo.SetParentHostsInProbes() } } @@ -652,20 +670,22 @@ func (this *Wigo) GenerateSummary(showOnlyErrors bool) (summary string) { if this.LocalHost.Status != 100 || !showOnlyErrors { summary += "Local probes : \n\n" - for probeName := range this.LocalHost.Probes { - if this.LocalHost.Probes[probeName].Status > 100 && this.LocalHost.Probes[probeName].Status < 300 { - summary += yellow("\t%-25s : %d %s\n", this.LocalHost.Probes[probeName].Name, this.LocalHost.Probes[probeName].Status, strings.Replace(this.LocalHost.Probes[probeName].Message, "%", "%%", -1)) - } else if this.LocalHost.Probes[probeName].Status >= 300 { - summary += red("\t%-25s : %d %s\n", this.LocalHost.Probes[probeName].Name, this.LocalHost.Probes[probeName].Status, strings.Replace(this.LocalHost.Probes[probeName].Message, "%", "%%", -1)) + for item := range this.LocalHost.Probes.IterBuffered() { + probe := item.Val.(*ProbeResult) + + if probe.Status > 100 && probe.Status < 300 { + summary += yellow("\t%-25s : %d %s\n", probe.Name, probe.Status, strings.Replace(probe.Message, "%", "%%", -1)) + } else if probe.Status >= 300 { + summary += red("\t%-25s : %d %s\n", probe.Name, probe.Status, strings.Replace(probe.Message, "%", "%%", -1)) } else { - summary += fmt.Sprintf("\t%-25s : %d %s\n", this.LocalHost.Probes[probeName].Name, this.LocalHost.Probes[probeName].Status, strings.Replace(this.LocalHost.Probes[probeName].Message, "%", "%%", -1)) + summary += fmt.Sprintf("\t%-25s : %d %s\n", probe.Name, probe.Status, strings.Replace(probe.Message, "%", "%%", -1)) } } summary += "\n" } - if this.GlobalStatus >= 200 && len(this.RemoteWigos) > 0 { + if this.GlobalStatus >= 200 && len(this.RemoteWigos.Items()) > 0 { summary += "Remote Wigos : \n\n" } @@ -679,9 +699,10 @@ func (this *Wigo) GenerateRemoteWigosSummary(level int, showOnlyErrors bool, ver red := color.New(color.FgRed).SprintfFunc() yellow := color.New(color.FgYellow).SprintfFunc() - for remoteWigo := range this.RemoteWigos { + for item := range this.RemoteWigos.IterBuffered() { + remoteWigo := item.Val.(*Wigo) - if showOnlyErrors && this.RemoteWigos[remoteWigo].GlobalStatus < 200 { + if showOnlyErrors && remoteWigo.GlobalStatus < 200 { continue } @@ -692,22 +713,22 @@ func (this *Wigo) GenerateRemoteWigosSummary(level int, showOnlyErrors bool, ver } // Host down ? - if !this.RemoteWigos[remoteWigo].IsAlive { - summary += tabs + red(this.RemoteWigos[remoteWigo].GetHostname()+" DOWN : \n") - summary += tabs + red("\t"+this.RemoteWigos[remoteWigo].GlobalMessage+"\n") + if !remoteWigo.IsAlive { + summary += tabs + red(remoteWigo.GetHostname()+" DOWN : \n") + summary += tabs + red("\t"+remoteWigo.GlobalMessage+"\n") } else { - if this.RemoteWigos[remoteWigo].Version != version { - summary += tabs + this.RemoteWigos[remoteWigo].GetHostname() + " ( " + this.RemoteWigos[remoteWigo].LocalHost.Name + " ) - " + red(this.RemoteWigos[remoteWigo].Version) + ": \n" + if remoteWigo.Version != version { + summary += tabs + remoteWigo.GetHostname() + " ( " + remoteWigo.LocalHost.Name + " ) - " + red(remoteWigo.Version) + ": \n" } else { - summary += tabs + this.RemoteWigos[remoteWigo].GetHostname() + " ( " + this.RemoteWigos[remoteWigo].LocalHost.Name + " ) - " + this.RemoteWigos[remoteWigo].Version + ": \n" + summary += tabs + remoteWigo.GetHostname() + " ( " + remoteWigo.LocalHost.Name + " ) - " + remoteWigo.Version + ": \n" } } // Iterate on probes - for probeName := range this.RemoteWigos[remoteWigo].GetLocalHost().Probes { + for item := range remoteWigo.GetLocalHost().Probes.IterBuffered() { + currentProbe := item.Val.(*ProbeResult) - currentProbe := this.RemoteWigos[remoteWigo].GetLocalHost().Probes[probeName] summary += tabs if currentProbe.Status > 100 && currentProbe.Status < 300 { @@ -721,7 +742,7 @@ func (this *Wigo) GenerateRemoteWigosSummary(level int, showOnlyErrors bool, ver nextLevel := level + 1 summary += "\n" - summary += this.RemoteWigos[remoteWigo].GenerateRemoteWigosSummary(nextLevel, showOnlyErrors, version) + summary += remoteWigo.GenerateRemoteWigosSummary(nextLevel, showOnlyErrors, version) } return @@ -734,14 +755,15 @@ func (this *Wigo) FindRemoteWigoByHostname(hostname string) *Wigo { return this } - for name := range this.RemoteWigos { + for item := range this.RemoteWigos.IterBuffered() { + name := item.Key + remoteWigo := item.Val.(*Wigo) if name == hostname { - foundWigo = this.RemoteWigos[name] - return foundWigo + return remoteWigo } - foundWigo = this.RemoteWigos[name].FindRemoteWigoByHostname(hostname) + foundWigo = remoteWigo.FindRemoteWigoByHostname(hostname) if foundWigo != nil { return foundWigo } @@ -751,11 +773,16 @@ func (this *Wigo) FindRemoteWigoByHostname(hostname string) *Wigo { } func (this *Wigo) FindRemoteWigoByUuid(uuid string) (*Wigo, bool) { - if wigo, ok := LocalWigo.RemoteWigos[uuid]; ok { + if tmp, ok := this.RemoteWigos.Get(LocalWigo.Uuid); ok { + wigo := tmp.(*Wigo) return wigo, true } else { - for _, w := range this.RemoteWigos { - w.FindRemoteWigoByUuid(uuid) + for item := range this.RemoteWigos.IterBuffered() { + uuid := item.Key + wigo := item.Val.(*Wigo) + if remoteWigo, ok := wigo.FindRemoteWigoByUuid(uuid); ok { + return remoteWigo, true + } } } return nil, false @@ -767,10 +794,10 @@ func (this *Wigo) ListRemoteWigosNames() []string { if this.Uuid == LocalWigo.Uuid { list = append(list, this.GetHostname()) } - - for wigoName := range this.RemoteWigos { - list = append(list, this.RemoteWigos[wigoName].GetHostname()) - remoteList := this.RemoteWigos[wigoName].ListRemoteWigosNames() + for item := range this.RemoteWigos.IterBuffered() { + wigo := item.Val.(*Wigo) + list = append(list, wigo.GetHostname()) + remoteList := wigo.ListRemoteWigosNames() list = append(list, remoteList...) } @@ -780,8 +807,10 @@ func (this *Wigo) ListRemoteWigosNames() []string { func (this *Wigo) ListProbes() []string { list := make([]string, 0) - for probe := range this.LocalHost.Probes { - list = append(list, probe) + for item := range this.LocalHost.Probes.IterBuffered() { + probeName := item.Key + + list = append(list, probeName) } return list @@ -794,13 +823,14 @@ func (this *Wigo) EraseRemoteWigos(depth int) *Wigo { depth = depth - 1 if depth == 0 { - this.RemoteWigos = make(map[string]*Wigo) + this.RemoteWigos = NewConcurrentMapWigos() this.RecomputeGlobalStatus() return this } else { - for remoteWigo := range this.RemoteWigos { - this.RemoteWigos[remoteWigo].EraseRemoteWigos(depth) - this.RemoteWigos[remoteWigo].RecomputeGlobalStatus() + for item := range this.RemoteWigos.IterBuffered() { + remoteWigo := item.Val.(*Wigo) + remoteWigo.EraseRemoteWigos(depth) + remoteWigo.RecomputeGlobalStatus() } } @@ -816,14 +846,16 @@ func (this *Wigo) ListGroupsNames() []string { list = append(list, this.GetLocalHost().Group) } - for wigoName := range this.RemoteWigos { - group := this.RemoteWigos[wigoName].GetLocalHost().Group + for item := range this.RemoteWigos.IterBuffered() { + wigo := item.Val.(*Wigo) + + group := wigo.GetLocalHost().Group if !IsStringInArray(group, list) && group != "" { - list = append(list, this.RemoteWigos[wigoName].GetLocalHost().Group) + list = append(list, wigo.GetLocalHost().Group) } - remoteList := this.RemoteWigos[wigoName].ListGroupsNames() + remoteList := wigo.ListGroupsNames() for i := range remoteList { if !IsStringInArray(remoteList[i], list) { @@ -858,8 +890,10 @@ func (this *Wigo) GroupSummary(groupName string) (hs []*HostSummary, status int) } } - for remoteWigoName := range this.RemoteWigos { - subSummaries, subStatus := this.RemoteWigos[remoteWigoName].GroupSummary(groupName) + for item := range this.RemoteWigos.IterBuffered() { + wigo := item.Val.(*Wigo) + + subSummaries, subStatus := wigo.GroupSummary(groupName) if len(subSummaries) > 0 { hs = append(hs, subSummaries...) diff --git a/src/wigo/host.go b/src/wigo/host.go index e53c9f7..1891e1e 100644 --- a/src/wigo/host.go +++ b/src/wigo/host.go @@ -6,7 +6,7 @@ type Host struct { Name string Group string Status int - Probes map[string]*ProbeResult + Probes *concurrentMapProbes parentWigo *Wigo } @@ -23,7 +23,7 @@ func NewHost() (this *Host) { this = new(Host) this.Status = 100 - this.Probes = make(map[string]*ProbeResult) + this.Probes = NewConcurrentMapProbes() return } @@ -34,9 +34,11 @@ func (this *Host) RecomputeStatus() { this.Status = 0 - for probeName := range this.Probes { - if this.Probes[probeName].Status > this.Status { - this.Status = this.Probes[probeName].Status + for item := range this.Probes.IterBuffered() { + probe := item.Val.(*ProbeResult) + + if probe.Status > this.Status { + this.Status = probe.Status } } @@ -46,7 +48,8 @@ func (this *Host) RecomputeStatus() { func (this *Host) AddOrUpdateProbe(probe *ProbeResult) { // If old probe, test if status is different - if oldProbe, ok := GetLocalWigo().GetLocalHost().Probes[probe.Name]; ok { + if tmp, ok := GetLocalWigo().GetLocalHost().Probes.Get(probe.Name); ok { + oldProbe := tmp.(*ProbeResult) // Notification if oldProbe.Status != probe.Status { @@ -59,7 +62,7 @@ func (this *Host) AddOrUpdateProbe(probe *ProbeResult) { } // Update - GetLocalWigo().LocalHost.Probes[probe.Name] = probe + GetLocalWigo().LocalHost.Probes.Set(probe.Name, probe) GetLocalWigo().LocalHost.RecomputeStatus() // Graph @@ -72,9 +75,10 @@ func (this *Host) AddOrUpdateProbe(probe *ProbeResult) { } func (this *Host) DeleteProbeByName(probeName string) { - if probeToDelete, ok := this.Probes[probeName]; ok { + if tmp, ok := this.Probes.Get(probeName); ok { + probeToDelete := tmp.(*ProbeResult) NewNotificationProbe(probeToDelete, nil) - delete(this.Probes, probeName) + this.Probes.Remove(probeName) } } @@ -82,8 +86,11 @@ func (this *Host) GetErrorsProbesList() (list []string) { list = make([]string, 0) - for probeName := range this.Probes { - if this.Probes[probeName].Status > 100 { + for item := range this.Probes.IterBuffered() { + probeName := item.Key + probe := item.Val.(*ProbeResult) + + if probe.Status > 100 { list = append(list, probeName) } } @@ -104,12 +111,13 @@ func (this *Host) GetSummary() (hs *HostSummary) { hs.Status = this.Status hs.Probes = make([]map[string]interface{}, 0) - for probeName := range this.Probes { + for item := range this.Probes.IterBuffered() { + _probe := item.Val.(*ProbeResult) probe := make(map[string]interface{}) - probe["Name"] = this.Probes[probeName].Name - probe["Status"] = this.Probes[probeName].Status - probe["Message"] = this.Probes[probeName].Message + probe["Name"] = _probe.Name + probe["Status"] = _probe.Status + probe["Message"] = _probe.Message hs.Probes = append(hs.Probes, probe) } diff --git a/src/wigo/http.go b/src/wigo/http.go index 3b7b8b2..3897f02 100644 --- a/src/wigo/http.go +++ b/src/wigo/http.go @@ -40,7 +40,7 @@ func HttpRemotesHandler(params martini.Params) (int, string) { func HttpRemotesProbesHandler(params martini.Params) (int, string) { hostname := params["hostname"] - probe := params["probe"] + probeName := params["probe"] if hostname == "" { return 404, "No wigo name set in url" @@ -53,9 +53,11 @@ func HttpRemotesProbesHandler(params martini.Params) (int, string) { } // Get probe or probes - if probe != "" { - if remoteWigo.LocalHost.Probes[probe] != nil { - json, err := json.Marshal(remoteWigo.LocalHost.Probes[probe]) + if probeName != "" { + if tmp, ok := remoteWigo.LocalHost.Probes.Get(probeName); ok { + probe := tmp.(*ProbeResult) + + json, err := json.Marshal(probe) if err != nil { return 500, "" } else { @@ -94,12 +96,12 @@ func HttpRemotesStatusHandler(params martini.Params) (int, string) { func HttpRemotesProbesStatusHandler(params martini.Params) (int, string) { hostname := params["hostname"] - probe := params["probe"] + probeName := params["probe"] if hostname == "" { return 404, "No wigo name set in url" } - if probe == "" { + if probeName == "" { return 404, "No probe name set in url" } @@ -110,11 +112,13 @@ func HttpRemotesProbesStatusHandler(params martini.Params) (int, string) { } // Get probe - if remoteWigo.LocalHost.Probes[probe] == nil { - return 404, "Probe " + probe + " not found in remote wigo " + hostname + if tmp, ok := remoteWigo.LocalHost.Probes.Get(probeName); ok { + probe := tmp.(*ProbeResult) + return 200, strconv.Itoa(probe.Status) + } else { + return 404, "Probe " + probeName + " not found in remote wigo " + hostname } - return 200, strconv.Itoa(remoteWigo.LocalHost.Probes[probe].Status) } func HttpLogsHandler(params martini.Params, r *http.Request) (int, string) { @@ -134,9 +138,9 @@ func HttpLogsHandler(params martini.Params, r *http.Request) (int, string) { if len(pq["hostname"]) > 0 { hostname = pq["hostname"][0] } - probe := "" + probeName := "" if len(pq["probe"]) > 0 { - probe = pq["probe"][0] + probeName = pq["probe"][0] } group := "" if len(pq["group"]) > 0 { @@ -167,17 +171,18 @@ func HttpLogsHandler(params martini.Params, r *http.Request) (int, string) { } // Test probe - if probe != "" { + if probeName != "" { if hostname != "" { // Get probe - if remoteWigo.LocalHost.Probes[probe] == nil { - return 404, "Probe " + probe + " not found in remote wigo " + hostname + if _, ok := remoteWigo.LocalHost.Probes.Get(probeName); ok { + } else { + return 404, "Probe " + probeName + " not found in remote wigo " + hostname } } } // Get logs - logs := LocalWigo.SearchLogs(probe, hostname, group, uint64(limit), uint64(offset)) + logs := LocalWigo.SearchLogs(probeName, hostname, group, uint64(limit), uint64(offset)) // Json json, err := json.Marshal(logs) diff --git a/src/wigo/push_server.go b/src/wigo/push_server.go index 8984627..dc79aa9 100644 --- a/src/wigo/push_server.go +++ b/src/wigo/push_server.go @@ -78,9 +78,9 @@ func NewPushServer(config *PushServerConfig) (this *PushServer) { // verify the identity of the server. To avoid the small window // of MITM vulnerability you might copy the certificate by yourself. func (this *PushServer) GetServerCertificate(req HelloRequest, cert *[]byte) (err error) { - // if LocalWigo.GetConfig().Global.Debug { - // Dump(req) - // } + if LocalWigo.GetConfig().Global.Debug && LocalWigo.GetConfig().Global.Trace { + log.Printf("Push server Debug : GetServerCertificate \n%s", ToJson(req)) + } log.Printf("Push server [client %s] : sending server certificate", req.Hostname) *cert = this.authority.GetServerCertificate() return @@ -91,9 +91,9 @@ func (this *PushServer) GetServerCertificate(req HelloRequest, cert *[]byte) (er // to grant the client to the allowed list. You may accept // new clients automatically with the AutoAcceptClient setting. func (this *PushServer) Register(req HelloRequest, reply *bool) (err error) { - // if LocalWigo.GetConfig().Global.Debug { - // Dump(req) - // } + if LocalWigo.GetConfig().Global.Debug && LocalWigo.GetConfig().Global.Trace { + log.Printf("Push server Debug : Register \n%s", ToJson(req)) + } if !this.authority.IsAllowed(req.Uuid) { log.Printf("Push server [client %s] : adding client to waiting list", req.Hostname) this.authority.AddClientToWaitingList(req.Uuid, req.Hostname) @@ -109,9 +109,9 @@ func (this *PushServer) Register(req HelloRequest, reply *bool) (err error) { // The client will have to provide this as a proof of // his identity at every new connection. func (this *PushServer) GetUuidSignature(req HelloRequest, sig *[]byte) (err error) { - // if LocalWigo.GetConfig().Global.Debug { - // Dump(req) - // } + if LocalWigo.GetConfig().Global.Debug && LocalWigo.GetConfig().Global.Trace { + log.Printf("Push server Debug : GetUuidSignature \n%s", ToJson(req)) + } if this.authority.IsAllowed(req.Uuid) { log.Printf("Push server [client %s] : sending uuid signature", req.Hostname) *sig, err = this.authority.GetUuidSignature(req.Uuid, req.Hostname) @@ -130,9 +130,9 @@ func (this *PushServer) GetUuidSignature(req HelloRequest, sig *[]byte) (err err // Verify the validity of the client's uuid signature. This is done // once for every connection then a token then a token is used. func (this *PushServer) Hello(req HelloRequest, token *string) (err error) { - // if LocalWigo.GetConfig().Global.Debug { - // Dump(req) - // } + if LocalWigo.GetConfig().Global.Debug && LocalWigo.GetConfig().Global.Trace { + log.Printf("Push server Debug : Hello \n%s", ToJson(req)) + } if this.authority.IsAllowed(req.Uuid) { if err = this.authority.VerifyUuidSignature(req.Uuid, req.UuidSignature); err == nil { if *token, err = this.authority.GetToken(req.Uuid); err == nil { @@ -160,16 +160,32 @@ func (this *PushServer) Hello(req HelloRequest, token *string) (err error) { // Update a client's data func (this *PushServer) Update(req UpdateRequest, reply *bool) (err error) { - // if LocalWigo.GetConfig().Global.Debug { - // Dump(req) - // } + if LocalWigo.GetConfig().Global.Debug && LocalWigo.GetConfig().Global.Trace { + log.Printf("Push server Debug : Update \n%s", ToJson(req)) + } if err = this.auth(req.Request); err == nil { - log.Printf("Push server : Update from %s", req.Wigo.GetHostname()) - req.Wigo.SetParentHostsInProbes() - // TODO this should return an error - LocalWigo.AddOrUpdateRemoteWigo(&req.Wigo) + if req.WigoJson == "" { + wigoHostname := req.WigoHostname + if this.authority.IsAllowed(req.Uuid) { + wigoHostname = this.authority.Allowed[req.Uuid] + } + log.Printf("Push server : Legacy data format received from wigo %s with uuid %s, please update your wigo client", wigoHostname, req.Uuid) + err = errors.New("TOO OLD WIGO CLIENT") + } else { + wigoJson := []byte(req.WigoJson) + wigo, err := NewWigoFromJson(wigoJson, 1) + if err != nil { + log.Printf("Push server : Cannot decode json for wigo %s with uuid %s : %s", req.WigoHostname, req.Uuid, err.Error()) + err = errors.New("CANNOT DECODE") + } else { + log.Printf("Push server : Update from %s with uuid %s", req.WigoHostname, req.Uuid) + wigo.SetParentHostsInProbes() + // TODO this should return an error + LocalWigo.AddOrUpdateRemoteWigo(wigo) + } + } } else { - log.Printf("Push server : Update for %s refused, you're not allowed", req.Wigo.GetHostname()) + log.Printf("Push server : Update for %s with uuid %s refused, you're not allowed", req.WigoHostname, req.Uuid) err = errors.New("NOT ALLOWED") } return @@ -177,9 +193,9 @@ func (this *PushServer) Update(req UpdateRequest, reply *bool) (err error) { // Disconnect the client gracefully func (this *PushServer) Goodbye(req Request, reply *bool) (err error) { - // if LocalWigo.GetConfig().Global.Debug { - // Dump(req) - // } + if LocalWigo.GetConfig().Global.Debug && LocalWigo.GetConfig().Global.Trace { + log.Printf("Push server Debug : Goodbye \n%s", ToJson(req)) + } if err = this.auth(&req); err == nil { this.authority.RevokeToken(req.Uuid, req.Token) } @@ -222,9 +238,9 @@ func NewRequest(uuid string, token string) (this *Request) { // expire within 300 seconds hence forcing the client // to reconnect. Here we also check for flooding clients. func (this *PushServer) auth(req *Request) (err error) { - // if LocalWigo.GetConfig().Global.Debug { - // Dump(req) - // } + if LocalWigo.GetConfig().Global.Debug && LocalWigo.GetConfig().Global.Trace { + log.Printf("Push server Debug : auth \n%s", ToJson(req)) + } err = this.authority.VerifyToken(req.Uuid, req.Token) if err != nil { err = errors.New("NOT ALLOWED") @@ -236,12 +252,18 @@ func (this *PushServer) auth(req *Request) (err error) { // Request the server to update the client's data type UpdateRequest struct { *Request - Wigo Wigo + WigoJson string + WigoHostname string } func NewUpdateRequest(wigo *Wigo, token string) (this *UpdateRequest) { this = new(UpdateRequest) this.Request = NewRequest(wigo.Uuid, token) - this.Wigo = *wigo + json, err := wigo.ToJsonString() + if err != nil { + log.Println("Push server : NewUpdateRequest error : " + err.Error()) + } + this.WigoJson = json + this.WigoHostname = wigo.GetHostname() return } diff --git a/src/wigocli.go b/src/wigocli.go index 6f38a31..608835e 100644 --- a/src/wigocli.go +++ b/src/wigocli.go @@ -76,16 +76,20 @@ Options if probe != "" { if wigoHost == "localhost" { // Find probe - if p, ok := wigoObj.GetLocalHost().Probes[probe]; ok { + if tmp, ok := wigoObj.GetLocalHost().Probes.Get(probe); ok { + p := tmp.(*wigo.ProbeResult) fmt.Println(p.Summary()) } else { fmt.Printf("Probe %s not found in local wigo\n", probe) } } else { // Find wigo - if w, ok := wigoObj.RemoteWigos[wigoHost]; ok { + + if tmp, ok := wigoObj.RemoteWigos.Get(wigoHost); ok { + w := tmp.(*wigo.Wigo) // Find probe - if p, ok := w.GetLocalHost().Probes[probe]; ok { + if tmp, ok := w.GetLocalHost().Probes.Get(probe); ok { + p := tmp.(*wigo.ProbeResult) fmt.Println(p.Summary()) } else { fmt.Printf("Probe %s not found on remote wigo %s\n", probe, wigoHost) @@ -96,7 +100,8 @@ Options } } else if wigoHost != "" && wigoHost != "localhost" { // Find remote - if w, ok := wigoObj.RemoteWigos[wigoHost]; ok { + if tmp, ok := wigoObj.RemoteWigos.Get(wigoHost); ok { + w := tmp.(*wigo.Wigo) fmt.Printf(w.GenerateSummary(showOnlyErrors)) } else { fmt.Printf("Remote wigo %s not found\n", wigoHost)