Exemplo n.º 1
0
// Write a full nodes.json style document based on the current
// database contents.
func (db *NodeDB) GenerateNodesJSON(w io.Writer, offlineDuration time.Duration) {
	data := db.cacheExportNodes.get(func() []byte {
		nodejs := NodesJSON{
			Nodes:     make(map[string]*NodesJSONData),
			Timestamp: NodesJSONTime(time.Now()),
			Version:   1,
		}
		db.Main.View(func(tx *bolt.Tx) error {
			nodeinfo := &NodeInfo{}
			nmeta := store.NewMeta(nodeinfo)
			return db.Main.ForEach(tx, nmeta, func(cursor *bolt.Cursor) (bool, error) {
				data, err := db.getNodesJSONData(tx, nmeta, offlineDuration)
				if err == nil {
					nodejs.Nodes[data.NodeInfo.NodeID] = data
				} else {
					log.Printf("NodeDB: can not generate node info JSON for %v: %v", alfred.HardwareAddr(nmeta.Key()), err)
				}
				return false, nil
			})
		})
		buf := new(bytes.Buffer)
		enc := json.NewEncoder(buf)
		if err := enc.Encode(&nodejs); err != nil {
			return []byte{}
		}
		return buf.Bytes()
	})
	w.Write(data)
}
Exemplo n.º 2
0
// read structured information from A.L.F.R.E.D. packet
func (ni *NodeInfo) ReadAlfred(data alfred.Data) error {
	ni.Source = alfred.HardwareAddr(data.Source)
	ni.Data = &NodeInfoData{}
	return readJSON(data, NODEINFO_PACKETTYPE, NODEINFO_PACKETVERSION, ni.Data)
}
Exemplo n.º 3
0
// Assemble data elements for a mesh node from database.
// This operation assumes the database is already locked by the caller.
func (db *NodeDB) getNodesJSONData(tx *bolt.Tx, nmeta *store.Meta, offlineDuration time.Duration) (*NodesJSONData, error) {
	data := &NodesJSONData{}

	nodeinfo := &NodeInfo{}
	if err := nmeta.GetItem(nodeinfo); err != nil {
		return data, err
	}

	data.NodeInfo = *nodeinfo.Data // make a copy

	// earliest datestamp is the "first seen" time,
	// latest datestamp is the "last seen" time
	firstseen := nmeta.Created
	lastseen := nmeta.Updated

	statistics := &Statistics{}
	smeta := store.NewMeta(statistics)
	if db.Main.Get(tx, nmeta.Key(), smeta) == nil {
		if smeta.Created.Before(firstseen) {
			firstseen = smeta.Created
		}
		if lastseen.Before(smeta.Updated) {
			lastseen = smeta.Updated
		}

		if smeta.GetItem(statistics) == nil {
			statdata := statistics.Data
			if statdata.Memory != nil {
				if statdata.Memory.Total != 0 {
					// this calculation is a bit stupid, but compatible with ffmap-backend:
					data.Statistics.MemoryUsage = 1.0 - (float64(statdata.Memory.Free) / float64(statdata.Memory.Total))
				} else {
					data.Statistics.MemoryUsage = 1
				}
			}
			data.Statistics.Uptime = statdata.Uptime
			if statdata.Clients != nil {
				data.Statistics.Clients = statdata.Clients.Total
			}
			if statdata.Gateway != nil {
				data.Statistics.Gateway = statdata.Gateway
			}
			data.Statistics.LoadAvg = statdata.LoadAvg
			data.Statistics.RootFSUsage = statdata.RootFSUsage
		}
	}

	vis := &VisData{}
	vmeta := store.NewMeta(vis)
	if db.Main.Get(tx, nmeta.Key(), vmeta) == nil {
		if vmeta.Created.Before(firstseen) {
			firstseen = vmeta.Created
		}
		if lastseen.Before(vmeta.Updated) {
			lastseen = vmeta.Updated
		}
	}

	data.FirstSeen = NodesJSONTime(firstseen)
	data.LastSeen = NodesJSONTime(lastseen)

	// set gateway flag when we have the node's address in
	// our list of gateways
	nodeid, _ := db.ResolveNodeID(tx, alfred.HardwareAddr(nmeta.Key()))
	data.Flags.Gateway = db.Main.Exists(tx, []byte(nodeid), &Gateway{})

	// online state is determined by the time we have last
	// seen a mesh node
	offline := time.Now().Sub(time.Time(data.LastSeen))
	if offline < offlineDuration {
		data.Flags.Online = true
	} else {
		data.Flags.Online = false
	}

	return data, nil
}