Пример #1
0
//Sync Watch Process
func startSyncWatchProcess(server *Server) {
	config := util.GetConfig()
	watch := config.GetStringList("watch/keys", nil)
	events := config.GetStringList("watch/events", nil)
	if watch == nil {
		return
	}
	extensions := map[string]extension.Environment{}
	for _, event := range events {
		path := "sync://" + event
		env, err := server.NewEnvironmentForPath("sync."+event, path)
		if err != nil {
			log.Fatal(err.Error())
		}
		extensions[event] = env
	}
	responseChan := make(chan *gohan_sync.Event)
	stopChan := make(chan bool)
	for _, path := range watch {
		go func(path string) {
			defer util.LogFatalPanic(log)
			for server.running {
				lockKey := lockPath + "watch"
				err := server.sync.Lock(lockKey, true)
				if err != nil {
					log.Warning("Can't start watch process due to lock", err)
					time.Sleep(5 * time.Second)
					continue
				}
				defer func() {
					server.sync.Unlock(lockKey)
				}()
				err = server.sync.Watch(path, responseChan, stopChan)
				if err != nil {
					log.Error(fmt.Sprintf("sync watch error: %s", err))
				}
			}
		}(path)
	}
	//main response lisnter process
	go func() {
		defer util.LogFatalPanic(log)
		for server.running {
			response := <-responseChan
			server.queue.Add(job.NewJob(
				func() {
					defer util.LogPanic(log)
					for _, event := range events {
						//match extensions
						if strings.HasPrefix(response.Key, "/"+event) {
							env := extensions[event]
							runExtensionOnSync(server, response, env.Clone())
							return
						}
					}
				}))
		}
	}()

}
Пример #2
0
//SNMP Process
//Experimental
func startSNMPProcess(server *Server) {
	config := util.GetConfig()
	enabled := config.GetParam("snmp", nil)
	if enabled == nil {
		return
	}
	host := config.GetString("snmp/address", "localhost:162")

	path := "snmp://"
	env, err := server.NewEnvironmentForPath("snmp", path)
	if err != nil {
		log.Fatal(err.Error())
	}

	addr, err := net.ResolveUDPAddr("udp", host)
	if err != nil {
		log.Fatal(err)
	}

	conn, err := net.ListenUDP("udp", addr)
	if err != nil {
		log.Fatal(err)
	}

	buf := make([]byte, 1024)
	go func() {
		defer util.LogFatalPanic(log)
		defer conn.Close()
		for server.running {
			rlen, remote, err := conn.ReadFromUDP(buf)
			if err != nil {
				log.Error(fmt.Sprintf("[SNMP] failed read bytes %s", err))
				return
			}
			decoded, err := wapsnmp.DecodeSequence(buf[:rlen])
			if err != nil {
				log.Error(fmt.Sprintf("[SNMP] failed decode bytes %s", err))
				continue
			}
			infos := decoded[3].([]interface{})[4].([]interface{})[1:]
			trap := map[string]string{}
			for _, info := range infos {
				listInfo := info.([]interface{})
				oid := listInfo[1].(wapsnmp.Oid)
				trap[oid.String()] = fmt.Sprintf("%v", listInfo[2])
			}

			context := map[string]interface{}{
				"trap":   trap,
				"remote": remote,
			}
			if err := env.HandleEvent("notification", context); err != nil {
				log.Warning(fmt.Sprintf("extension error: %s", err))
			}
		}
	}()
}
Пример #3
0
//CRON Process
func startCRONProcess(server *Server) {
	config := util.GetConfig()
	jobList := config.GetParam("cron", nil)
	if jobList == nil {
		return
	}
	if server.sync == nil {
		log.Fatalf(fmt.Sprintf("Could not start CRON process because of sync backend misconfiguration."))
		util.LogFatalPanic(log)
	}
	log.Info("Started CRON process")
	c := cron.New()
	for _, rawJob := range jobList.([]interface{}) {
		job := rawJob.(map[string]interface{})
		path := job["path"].(string)
		timing := job["timing"].(string)
		name := strings.TrimPrefix(path, "cron://")
		env, err := server.NewEnvironmentForPath(name, path)
		if err != nil {
			log.Fatal(err.Error())
		}
		log.Info("New job for %s / %s", path, timing)
		c.AddFunc(timing, func() {
			lockKey := lockPath + "/" + path
			err := server.sync.Lock(lockKey, false)
			if err != nil {
				return
			}
			defer func() {
				server.sync.Unlock(lockKey)
			}()
			context := map[string]interface{}{
				"path": path,
			}
			if err != nil {
				log.Warning(fmt.Sprintf("extension error: %s", err))
				return
			}
			if err := env.HandleEvent("notification", context); err != nil {
				log.Warning(fmt.Sprintf("extension error: %s", err))
				return
			}
			return
		})
	}
	c.Start()
}
Пример #4
0
//Start sync Process
func startSyncProcess(server *Server) {
	pollingTicker := time.Tick(eventPollingTime)
	committed := transactionCommitInformer()
	go func() {
		defer util.LogFatalPanic(log)
		recentlySynced := false
		for server.running {
			select {
			case <-pollingTicker:
				if recentlySynced {
					recentlySynced = false
					continue
				}
			case <-committed:
				recentlySynced = true
			}
			server.sync.Lock(syncPath, true)
			server.Sync()
		}
		server.sync.Unlock(syncPath)
	}()
}
Пример #5
0
//TODO(nati) integrate with watch process
func startStateUpdatingProcess(server *Server) {

	stateResponseChan := make(chan *gohan_sync.Event)
	stateStopChan := make(chan bool)

	if _, err := server.sync.Fetch(statePrefix); err != nil {
		server.sync.Update(statePrefix, "")
	}

	if _, err := server.sync.Fetch(monitoringPrefix); err != nil {
		server.sync.Update(monitoringPrefix, "")
	}

	go func() {
		defer util.LogFatalPanic(log)
		for server.running {
			lockKey := lockPath + "state"
			err := server.sync.Lock(lockKey, true)
			if err != nil {
				log.Warning("Can't start state watch process due to lock", err)
				time.Sleep(5 * time.Second)
				continue
			}
			defer func() {
				server.sync.Unlock(lockKey)
			}()

			err = server.sync.Watch(statePrefix, stateResponseChan, stateStopChan)
			if err != nil {
				log.Error(fmt.Sprintf("sync watch error: %s", err))
			}
		}
	}()
	go func() {
		defer util.LogFatalPanic(log)
		for server.running {
			response := <-stateResponseChan
			err := StateUpdate(response, server)
			if err != nil {
				log.Warning(fmt.Sprintf("error during state update: %s", err))
			}
		}
		stateStopChan <- true
	}()
	monitoringResponseChan := make(chan *gohan_sync.Event)
	monitoringStopChan := make(chan bool)
	go func() {
		defer util.LogFatalPanic(log)
		for server.running {
			lockKey := lockPath + "monitoring"
			err := server.sync.Lock(lockKey, true)
			if err != nil {
				log.Warning("Can't start state watch process due to lock", err)
				time.Sleep(5 * time.Second)
				continue
			}
			defer func() {
				server.sync.Unlock(lockKey)
			}()
			err = server.sync.Watch(monitoringPrefix, monitoringResponseChan, monitoringStopChan)
			if err != nil {
				log.Error(fmt.Sprintf("sync watch error: %s", err))
			}
		}
	}()
	go func() {
		defer util.LogFatalPanic(log)
		for server.running {
			response := <-monitoringResponseChan
			err := MonitoringUpdate(response, server)
			if err != nil {
				log.Warning(fmt.Sprintf("error during state update: %s", err))
			}
		}
		monitoringStopChan <- true
	}()
}
Пример #6
0
//TODO(nati) integrate with watch process
func startStateWatchProcess(server *Server) {
	stateResponseChan := make(chan *gohan_sync.Event)
	stateStopChan := make(chan bool)

	for _, toCreate := range []string{stateWatchPrefix, statePrefix, monitoringPrefix} {
		if _, err := server.sync.Fetch(toCreate); err != nil {
			server.sync.Update(toCreate, "")
		}
	}

	go func() {
		defer util.LogFatalPanic(log)

		for server.running {
			lockKey := lockPath + "/state_watch"
			err := server.sync.Lock(lockKey, true)
			if err != nil {
				log.Warning("Can't start state watch process due to lock", err)
				time.Sleep(5 * time.Second)
				continue
			}
			defer func() {
				server.sync.Unlock(lockKey)
			}()

			err = server.sync.Watch(stateWatchPrefix, stateResponseChan, stateStopChan)
			if err != nil {
				log.Error(fmt.Sprintf("sync state watch error: %s", err))
			}
		}
	}()

	go func() {
		defer util.LogFatalPanic(log)

		var bufferMutex sync.Mutex
		buffers := make(map[string]chan *gohan_sync.Event)

		for server.running {
			response := <-stateResponseChan

			key := stateWatchTrimmer.ReplaceAllLiteralString(response.Key, "")
			bufferMutex.Lock()
			buffer, ok := buffers[key]
			if !ok {
				buffer = make(chan *gohan_sync.Event, bufferSize)
				buffers[key] = buffer

				go func(buf chan *gohan_sync.Event, key string) {
					for {
						var resp *gohan_sync.Event

						bufferMutex.Lock()
						select {
						case resp = <-buf:
							bufferMutex.Unlock()
						default:
							close(buf)
							delete(buffers, key)
							bufferMutex.Unlock()
							return
						}

						var err error
						if strings.HasPrefix(resp.Key, statePrefix) {
							err = StateUpdate(resp, server)
							log.Info("Completed StateUpdate")
						} else if strings.HasPrefix(resp.Key, monitoringPrefix) {
							err = MonitoringUpdate(resp, server)
							log.Info("Completed MonitoringUpdate")
						}
						if err != nil {
							log.Warning(fmt.Sprintf("error during state update: %s", err))
						}
					}
				}(buffer, key)
			}

			buffer <- response
			bufferMutex.Unlock()
		}

		stateStopChan <- true
	}()

}
Пример #7
0
func listenAMQP(server *Server) {

	hostname, _ := os.Hostname()
	processID := hostname + uuid.NewV4().String()
	config := util.GetConfig()
	connection := config.GetString("amqp/connection", "amqp://*****:*****@127.0.0.1:5672/")
	queues := config.GetStringList("amqp/queues", []string{"notifications.info", "notifications.error"})
	events := config.GetStringList("amqp/events", []string{})
	extensions := map[string]extension.Environment{}
	for _, event := range events {
		path := "amqp://" + event
		env, err := server.NewEnvironmentForPath("amqp."+event, path)
		if err != nil {
			log.Fatal(err.Error())
		}
		extensions[event] = env
	}

	for _, queue := range queues {
		go func(queue string) {
			defer util.LogFatalPanic(log)
			for server.running {
				conn, err := amqp.Dial(connection)
				if err != nil {
					log.Error(fmt.Sprintf("[AMQP] connection error: %s", err))
					time.Sleep(connectionWait)
					continue
				}
				defer conn.Close()

				ch, err := conn.Channel()
				if err != nil {
					log.Error(fmt.Sprintf("[AMQP] channel: %s", err))
					return
				}
				defer ch.Close()
				q, err := ch.QueueDeclare(
					queue, // name
					false, // durable
					false, // delete when usused
					false, // exclusive
					false, // no-wait
					nil,   // arguments
				)
				if err != nil {
					log.Error(fmt.Sprintf("[AMQP] queue declare error: %s", err))
					return
				}

				for server.running {
					msgs, err := ch.Consume(
						q.Name, // queue
						"gohan-"+processID+"-"+queue, // consumer
						true,  // auto-ack
						false, // exclusive
						false, // no-local
						false, // no-wait
						nil,   // args
					)

					if err != nil {
						log.Error(fmt.Sprintf("[AMQP] consume queue error: %s", err))
						break
					}
					for d := range msgs {
						var message map[string]interface{}
						err = json.Unmarshal(d.Body, &message)
						log.Debug(fmt.Sprintf("Received a message: %s %s", queue, d.Body))
						if err != nil {
							log.Error(fmt.Sprintf("[AMQP] json decode error: %s", err))
							continue
						}
						eventType, ok := message["event_type"].(string)
						if !ok {
							log.Error("[AMQP] wrong event type")
							continue
						}
						for _, event := range events {
							if strings.HasPrefix(eventType, event) {
								env := extensions[event]

								context := map[string]interface{}{
									"event": message,
								}
								if err := env.HandleEvent("notification", context); err != nil {
									log.Warning(fmt.Sprintf("extension error: %s", err))
								}
							}
						}
					}
				}
			}
		}(queue)
	}
}