Browse Source

Get node OS/Arch info into the CV2 db

Grant Limberg 2 months ago
parent
commit
1ffadf31de

+ 19 - 11
controller/CV1.cpp

@@ -286,14 +286,20 @@ void CV1::eraseMember(const uint64_t networkId, const uint64_t memberId)
 	_memberChanged(tmp.first, nullJson, true);
 }
 
-void CV1::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress)
+void CV1::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress, const char *osArch)
 {
 	std::lock_guard<std::mutex> l(_lastOnline_l);
-	std::pair<int64_t, InetAddress> &i = _lastOnline[std::pair<uint64_t,uint64_t>(networkId, memberId)];
-	i.first = OSUtils::now();
+	NodeOnlineRecord &i = _lastOnline[std::pair<uint64_t,uint64_t>(networkId, memberId)];
+	i.lastSeen = OSUtils::now();
 	if (physicalAddress) {
-		i.second = physicalAddress;
+		i.physicalAddress = physicalAddress;
 	}
+	i.osArch = std::string(osArch);
+}
+
+void CV1::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress)
+{
+	this->nodeIsOnline(networkId, memberId, physicalAddress, "unknown/unknown");
 }
 
 AuthInfo CV1::getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL)
@@ -1643,7 +1649,7 @@ void CV1::onlineNotification_Postgres()
 		auto c2 = _pool->borrow();
 		try {
 			fprintf(stderr, "%s onlineNotification_Postgres\n", _myAddressStr.c_str());
-			std::unordered_map< std::pair<uint64_t,uint64_t>,std::pair<int64_t,InetAddress>,_PairHasher > lastOnline;
+			std::unordered_map< std::pair<uint64_t,uint64_t>,NodeOnlineRecord,_PairHasher > lastOnline;
 			{
 				std::lock_guard<std::mutex> l(_lastOnline_l);
 				lastOnline.swap(_lastOnline);
@@ -1684,9 +1690,10 @@ void CV1::onlineNotification_Postgres()
 					continue;
 				}
 
-				int64_t ts = i->second.first;
-				std::string ipAddr = i->second.second.toIpString(ipTmp);
+				int64_t ts = i->second.lastSeen;
+				std::string ipAddr = i->second.physicalAddress.toIpString(ipTmp);
 				std::string timestamp = std::to_string(ts);
+				std::string osArch = i->second.osArch;
 
 				std::stringstream memberUpdate;
 				memberUpdate << "INSERT INTO ztc_member_status (network_id, member_id, address, last_updated) VALUES "
@@ -1741,7 +1748,7 @@ void CV1::onlineNotification_Redis()
 		auto start = std::chrono::high_resolution_clock::now();
 		uint64_t count = 0;
 
-		std::unordered_map< std::pair<uint64_t,uint64_t>,std::pair<int64_t,InetAddress>,_PairHasher > lastOnline;
+		std::unordered_map< std::pair<uint64_t,uint64_t>,NodeOnlineRecord,_PairHasher > lastOnline;
 		{
 			std::lock_guard<std::mutex> l(_lastOnline_l);
 			lastOnline.swap(_lastOnline);
@@ -1771,7 +1778,7 @@ void CV1::onlineNotification_Redis()
 }
 
 uint64_t CV1::_doRedisUpdate(sw::redis::Transaction &tx, std::string &controllerId,
-	std::unordered_map< std::pair<uint64_t,uint64_t>,std::pair<int64_t,InetAddress>,_PairHasher > &lastOnline) 
+	std::unordered_map< std::pair<uint64_t,uint64_t>,NodeOnlineRecord,_PairHasher > &lastOnline) 
 
 {
 	nlohmann::json jtmp1, jtmp2;
@@ -1792,9 +1799,10 @@ uint64_t CV1::_doRedisUpdate(sw::redis::Transaction &tx, std::string &controller
 		std::string networkId(nwidTmp);
 		std::string memberId(memTmp);
 
-		int64_t ts = i->second.first;
-		std::string ipAddr = i->second.second.toIpString(ipTmp);
+		int64_t ts = i->second.lastSeen;
+		std::string ipAddr = i->second.physicalAddress.toIpString(ipTmp);
 		std::string timestamp = std::to_string(ts);
+		std::string osArch = i->second.osArch;
 
 		std::unordered_map<std::string, std::string> record = {
 			{"id", memberId},

+ 3 - 2
controller/CV1.hpp

@@ -57,6 +57,7 @@ public:
 	virtual void eraseNetwork(const uint64_t networkId);
 	virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
 	virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress);
+	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress, const char *osArch);
 	virtual AuthInfo getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL);
 
 	virtual bool ready() {
@@ -93,7 +94,7 @@ private:
 	void onlineNotification_Postgres();
 	void onlineNotification_Redis();
 	uint64_t _doRedisUpdate(sw::redis::Transaction &tx, std::string &controllerId,
-		std::unordered_map< std::pair<uint64_t,uint64_t>,std::pair<int64_t,InetAddress>,_PairHasher > &lastOnline);
+		std::unordered_map< std::pair<uint64_t,uint64_t>,NodeOnlineRecord,_PairHasher > &lastOnline);
 
 	void configureSmee();
 	void notifyNewMember(const std::string &networkID, const std::string &memberID);
@@ -118,7 +119,7 @@ private:
 	std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS];
 	std::thread _onlineNotificationThread;
 
-	std::unordered_map< std::pair<uint64_t,uint64_t>,std::pair<int64_t,InetAddress>,_PairHasher > _lastOnline;
+	std::unordered_map< std::pair<uint64_t,uint64_t>,NodeOnlineRecord,_PairHasher > _lastOnline;
 
 	mutable std::mutex _lastOnline_l;
 	mutable std::mutex _readyLock;

+ 20 - 11
controller/CV2.cpp

@@ -197,14 +197,20 @@ void CV2::eraseMember(const uint64_t networkId, const uint64_t memberId)
 	_memberChanged(tmp.first, nullJson, true);
 }
 
-void CV2::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress)
+void CV2::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress, const char *osArch)
 {
 	std::lock_guard<std::mutex> l(_lastOnline_l);
-	std::pair<int64_t, InetAddress> &i = _lastOnline[std::pair<uint64_t,uint64_t>(networkId, memberId)];
-	i.first = OSUtils::now();
+	NodeOnlineRecord &i = _lastOnline[std::pair<uint64_t,uint64_t>(networkId, memberId)];
+	i.lastSeen = OSUtils::now();
 	if (physicalAddress) {
-		i.second = physicalAddress;
+		i.physicalAddress = physicalAddress;
 	}
+	i.osArch = std::string(osArch);
+}
+
+void CV2::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress)
+{
+	this->nodeIsOnline(networkId, memberId, physicalAddress, "unknown/unknown");
 }
 
 AuthInfo CV2::getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL)
@@ -940,7 +946,7 @@ void CV2::onlineNotificationThread() {
 		try {
 			fprintf(stderr, "%s onlineNotificationThread\n", _myAddressStr.c_str());
 
-			std::unordered_map<std::pair<uint64_t, uint64_t>, std::pair<int64_t, InetAddress>,_PairHasher> lastOnline;
+			std::unordered_map<std::pair<uint64_t, uint64_t>, NodeOnlineRecord,_PairHasher> lastOnline;
 			{
 				std::lock_guard<std::mutex> l(_lastOnline_l);
 				lastOnline.swap(_lastOnline);
@@ -980,18 +986,21 @@ void CV2::onlineNotificationThread() {
 					continue;
 				}
 
-				int64_t ts = i->second.first;
-				std::string ipAddr = i->second.second.toIpString(ipTmp);
+				int64_t ts = i->second.lastSeen;
+				std::string ipAddr = i->second.physicalAddress.toIpString(ipTmp);
 				std::string timestamp = std::to_string(ts);
+				std::string osArch = i->second.osArch;
+				std::vector<std::string> osArchSplit = split(osArch, '/');
 
 				json record = {
 					{ipAddr, ts},
 				};
 
-
-				std::string device_network_insert = "INSERT INTO network_memberships_ctl (device_id, network_id, last_seen) " 
-					"VALUES ('"+w2.esc(memberId)+"', '"+w2.esc(networkId)+"', '"+w2.esc(record.dump())+"'::JSONB) " 
-					"ON CONFLICT (device_id, network_id) DO UPDATE SET last_seen = last_seen || EXCLUDED.last_seen";
+				std::string device_network_insert = "INSERT INTO network_memberships_ctl (device_id, network_id, last_seen, os, arch) " 
+					"VALUES ('"+w2.esc(memberId)+"', '"+w2.esc(networkId)+"', '"+w2.esc(record.dump())+"'::JSONB, "
+					"'"+w2.esc(osArchSplit[0])+"', '"+w2.esc(osArchSplit[1])+"') " 
+					"ON CONFLICT (device_id, network_id) DO UPDATE SET last_seen = last_seen || EXCLUDED.last_seen "
+					"os = EXCLUDED.os, arch = EXCLUDED.arch";
 				pipe.insert(device_network_insert);
 
 				Metrics::pgsql_node_checkin++;

+ 2 - 1
controller/CV2.hpp

@@ -44,6 +44,7 @@ public:
 	virtual void eraseNetwork(const uint64_t networkId);
 	virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
 	virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress);
+	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress, const char *osArch);
 	virtual AuthInfo getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL);
 
 	virtual bool ready() {
@@ -95,7 +96,7 @@ private:
 	std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS];
 	std::thread _onlineNotificationThread;
 
-	std::unordered_map< std::pair<uint64_t,uint64_t>,std::pair<int64_t,InetAddress>,_PairHasher > _lastOnline;
+	std::unordered_map< std::pair<uint64_t,uint64_t>,NodeOnlineRecord,_PairHasher > _lastOnline;
 
 	mutable std::mutex _lastOnline_l;
 	mutable std::mutex _readyLock;

+ 1 - 0
controller/DB.hpp

@@ -141,6 +141,7 @@ public:
 	virtual void eraseNetwork(const uint64_t networkId) = 0;
 	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId) = 0;
 	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) = 0;
+	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress, const char *osArch) = 0;
 
 	virtual AuthInfo getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL) { return AuthInfo(); }
 

+ 6 - 2
controller/DBMirrorSet.cpp

@@ -206,14 +206,18 @@ void DBMirrorSet::eraseMember(const uint64_t networkId,const uint64_t memberId)
 	}
 }
 
-void DBMirrorSet::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress)
-{
+void DBMirrorSet::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress, const char *osArch) {
 	std::shared_lock<std::shared_mutex> l(_dbs_l);
 	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
 		(*d)->nodeIsOnline(networkId,memberId,physicalAddress);
 	}
 }
 
+void DBMirrorSet::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress)
+{
+	this->nodeIsOnline(networkId,memberId,physicalAddress,"unknown/unknown");
+}
+
 void DBMirrorSet::onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network)
 {
 	nlohmann::json record(network);

+ 2 - 1
controller/DBMirrorSet.hpp

@@ -44,7 +44,8 @@ public:
 	bool save(nlohmann::json &record,bool notifyListeners);
 	void eraseNetwork(const uint64_t networkId);
 	void eraseMember(const uint64_t networkId,const uint64_t memberId);
-	void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);
+	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);
+	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress, const char *osArch);
 
 	// These are called by various DB instances when changes occur.
 	virtual void onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network);

+ 6 - 2
controller/FileDB.cpp

@@ -155,8 +155,7 @@ void FileDB::eraseMember(const uint64_t networkId,const uint64_t memberId)
 	this->_online[networkId].erase(memberId);
 }
 
-void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress)
-{
+void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress, const char *osArch) {
 	char mid[32],atmp[64];
 	OSUtils::ztsnprintf(mid,sizeof(mid),"%.10llx",(unsigned long long)memberId);
 	physicalAddress.toString(atmp);
@@ -164,4 +163,9 @@ void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const
 	this->_online[networkId][memberId][OSUtils::now()] = physicalAddress;
 }
 
+void FileDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress)
+{
+	this->nodeIsOnline(networkId,memberId,physicalAddress,"unknown/unknown");
+}
+
 } // namespace ZeroTier

+ 2 - 1
controller/FileDB.hpp

@@ -31,7 +31,8 @@ public:
 	virtual void eraseNetwork(const uint64_t networkId);
 	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId);
 	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);
-
+	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress, const char *osArch);
+	
 protected:
 	std::string _path;
 	std::string _networksPath;

+ 6 - 1
controller/LFDB.cpp

@@ -388,7 +388,7 @@ void LFDB::eraseMember(const uint64_t networkId,const uint64_t memberId)
 	// TODO
 }
 
-void LFDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress)
+void LFDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress,const char *osArch)
 {
 	std::lock_guard<std::mutex> l(_state_l);
 	auto nw = _state.find(networkId);
@@ -403,4 +403,9 @@ void LFDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const I
 	}
 }
 
+void LFDB::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress)
+{
+	this->nodeIsOnline(networkId,memberId,physicalAddress,"unknown/unknown");
+}
+
 } // namespace ZeroTier

+ 2 - 1
controller/LFDB.hpp

@@ -47,7 +47,8 @@ public:
 	virtual void eraseNetwork(const uint64_t networkId);
 	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId);
 	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);
-
+	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress, const char *osArch);
+	
 protected:
 	const Identity _myId;
 

+ 6 - 0
controller/PostgreSQL.hpp

@@ -79,6 +79,12 @@ private:
 	DB *_psql;
 };
 
+struct NodeOnlineRecord {
+	uint64_t lastSeen;
+	InetAddress physicalAddress;
+	std::string osArch;
+};
+
 } // namespace ZeroTier
 
 #endif // ZT_CONTROLLER_POSTGRESQL_HPP

+ 3 - 0
ext/central-controller-docker/migrations/0002_os_arch.down.sql

@@ -0,0 +1,3 @@
+ALTER TABLE network_memberships_ctl
+    DROP COLUMN os,
+    DROP COLUMN arch;

+ 3 - 0
ext/central-controller-docker/migrations/0002_os_arch.up.sql

@@ -0,0 +1,3 @@
+ALTER TABLE network_memberships_ctl
+    ADD COLUMN os TEXT NOT NULL DEFAULT 'unknown',
+    ADD COLUMN arch TEXT NOT NULL DEFAULT 'unknown';