Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance Host Identification and Metadata Fetching in MachineInfoUtil #1989

Merged
merged 48 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
4c599e2
fix
quzard Dec 23, 2024
495a985
LOG_RESERVED_KEY_HOSTID
quzard Dec 23, 2024
ce56c21
fix
quzard Dec 23, 2024
7936468
fix
quzard Dec 23, 2024
ef22eb0
fix
quzard Dec 23, 2024
a3eb415
fix
quzard Dec 24, 2024
6a3c808
fix
quzard Dec 29, 2024
8a30856
ToLowerCaseString
quzard Dec 30, 2024
50b956e
add GetAgentGoCheckpointDir
quzard Dec 31, 2024
242cd2a
fix
quzard Dec 31, 2024
641cbf6
fix
quzard Dec 31, 2024
cd6a331
fix
SteveYitao Dec 31, 2024
1031f5c
fix
quzard Dec 31, 2024
bcd27c8
fix
quzard Dec 31, 2024
b0f04a8
fix
quzard Dec 31, 2024
e8255db
fix
quzard Dec 31, 2024
ce75c09
fix
quzard Dec 31, 2024
3685523
fix
quzard Dec 31, 2024
58fb27f
fix
quzard Dec 31, 2024
7f28d11
LoongcollectorLogConfDir
quzard Dec 31, 2024
3a54691
LOG_INFO
quzard Dec 31, 2024
8e86294
LOG_ERROR
quzard Dec 31, 2024
f2de2d9
defined(_MSC_VER)
quzard Dec 31, 2024
d711a65
add isValid
quzard Dec 31, 2024
98c02d7
add UpdateHostId
quzard Dec 31, 2024
b710760
fix
quzard Dec 31, 2024
0f04cac
rm log
quzard Dec 31, 2024
98e20eb
fix
quzard Dec 31, 2024
b8ffcdf
fix GetRunningEnvironment
quzard Dec 31, 2024
66c6b9e
Merge remote-tracking branch 'github/main' into feat/host-id
quzard Dec 31, 2024
81a3c2a
解决冲突
quzard Dec 31, 2024
7da2a0b
fix
quzard Dec 31, 2024
c0cec39
modify
quzard Dec 31, 2024
94cd582
add GetAgentPrometheusAuthorizationPath
quzard Dec 31, 2024
4ed0702
LoongcollectorPrometheusAuthorizationPath
quzard Dec 31, 2024
2328f23
回退
quzard Dec 31, 2024
efc6e66
fix
quzard Jan 1, 2025
166503d
rm
quzard Jan 1, 2025
654a7bb
fix RebuildExecutionDir
quzard Jan 1, 2025
8087fe1
fix
quzard Jan 1, 2025
9270f66
rm
quzard Jan 1, 2025
5e1ba57
fix
quzard Jan 1, 2025
c19dbec
fix
quzard Jan 1, 2025
bdd3455
fix
quzard Jan 1, 2025
92029d6
fix
quzard Jan 1, 2025
cdb572b
fix
quzard Jan 1, 2025
c14ce0e
fix
quzard Jan 1, 2025
3b0c418
fix
quzard Jan 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions core/app_config/AppConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,57 @@ std::string GetAgentLogDir() {
return dir;
}

std::string GetAgentPrometheusAuthorizationPath() {
quzard marked this conversation as resolved.
Show resolved Hide resolved
static std::string dir;
if (!dir.empty()) {
return dir;
}
#if defined(APSARA_UNIT_TEST_MAIN)
dir = GetProcessExecutionDir();
#else
if (BOOL_FLAG(logtail_mode)) {
dir = GetProcessExecutionDir();
} else {
return AppConfig::GetInstance()->GetLoongcollectorConfDir();
}
#endif
return dir;
}

std::string GetAgentGoLogConfDir() {
static std::string dir;
if (!dir.empty()) {
return dir;
}
#if defined(APSARA_UNIT_TEST_MAIN)
dir = GetProcessExecutionDir();
#else
if (BOOL_FLAG(logtail_mode)) {
dir = GetProcessExecutionDir();
} else {
return AppConfig::GetInstance()->GetLoongcollectorConfDir();
}
#endif
return dir;
}

std::string GetAgentGoCheckpointDir() {
static std::string dir;
if (!dir.empty()) {
return dir;
}
#if defined(APSARA_UNIT_TEST_MAIN)
dir = GetProcessExecutionDir();
#else
if (BOOL_FLAG(logtail_mode)) {
dir = AppConfig::GetInstance()->GetLoongcollectorConfDir();
} else {
return GetAgentDataDir();
}
#endif
return dir;
}

std::string GetAgentDataDir() {
static std::string dir;
if (!dir.empty()) {
Expand Down
3 changes: 3 additions & 0 deletions core/app_config/AppConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ std::string GetAgentConfDir();
std::string GetAgentRunDir();
std::string GetAgentThirdPartyDir();

std::string GetAgentGoCheckpointDir();
std::string GetAgentGoLogConfDir();
std::string GetAgentPrometheusAuthorizationPath();
std::string GetAgentConfigFile();
std::string GetAgentAppInfoFile();
std::string GetAdhocCheckpointDirPath();
Expand Down
2 changes: 1 addition & 1 deletion core/application/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ void Application::Init() {
appInfoJson["UUID"] = Json::Value(Application::GetInstance()->GetUUID());
appInfoJson["instance_id"] = Json::Value(Application::GetInstance()->GetInstanceId());
#ifdef __ENTERPRISE__
appInfoJson["host_id"] = Json::Value(FetchHostId());
appInfoJson["host_id"] = Json::Value(HostIdentifier::Instance()->GetHostId().id);
appInfoJson[GetVersionTag()] = Json::Value(ILOGTAIL_VERSION);
#else
appInfoJson[GetVersionTag()] = Json::Value(string(ILOGTAIL_VERSION) + " Community Edition");
Expand Down
243 changes: 212 additions & 31 deletions core/common/MachineInfoUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@

#include "MachineInfoUtil.h"

#include <rapidjson/document.h>
#include <rapidjson/rapidjson.h>
#include <string.h>

#include "AppConfig.h"

#if defined(__linux__)
#include <arpa/inet.h>
#include <ifaddrs.h>
Expand All @@ -40,8 +45,11 @@

#include "FileSystemUtil.h"
#include "StringTools.h"
#include "common/FileSystemUtil.h"
#include "common/UUIDUtil.h"
#include "logger/Logger.h"

DEFINE_FLAG_STRING(agent_host_id, "", "");

#if defined(_MSC_VER)
typedef LONG NTSTATUS, *PNTSTATUS;
Expand Down Expand Up @@ -496,59 +504,232 @@ size_t FetchECSMetaCallback(char* buffer, size_t size, size_t nmemb, std::string
return sizes;
}

quzard marked this conversation as resolved.
Show resolved Hide resolved
ECSMeta FetchECSMeta() {
CURL* curl;
HostIdentifier::HostIdentifier() {
#ifdef __ENTERPRISE__
getECSMetaFromFile();
updateHostId();
#else
ECSMeta ecsMeta;
if (FetchECSMeta(ecsMeta)) {
UpdateECSMetaAndHostid(ecsMeta);
}
#endif
}

bool HostIdentifier::UpdateECSMetaAndHostid(const ECSMeta& meta) {
// 如果 instanceID 发生变化,则更新ecs元数据
if (mMetadata.instanceID != meta.instanceID) {
LOG_INFO(sLogger,
("ecs instanceID changed, old instanceID", mMetadata.instanceID)("new instanceID", meta.instanceID));
{
std::unique_lock<std::shared_mutex> lock(mMutex); // 写锁
mMetadata = meta;
}
updateHostId();
return true;
}
return false;
}

void HostIdentifier::DumpECSMeta() {
std::string fileName = AppConfig::GetInstance()->GetLoongcollectorConfDir() + PATH_SEPARATOR + "instance_identity";
std::string errMsg;
if (!WriteFile(fileName, mMetadataStr, errMsg)) {
LOG_WARNING(sLogger, ("failed to write ecs meta to file", fileName)("error", errMsg));
} else {
LOG_INFO(sLogger, ("write ecs meta to file success, fileName", fileName)("mMetadataStr", mMetadataStr));
}
}

void HostIdentifier::updateHostId() {
if (!STRING_FLAG(agent_host_id).empty()) {
setHostId(Hostid{STRING_FLAG(agent_host_id), Type::CUSTOM});
return;
}
if (mMetadata.isValid && !mMetadata.instanceID.empty()) {
setHostId(Hostid{mMetadata.instanceID, Type::ECS});
return;
}
getSerialNumberFromEcsAssist();
if (!mSerialNumber.empty()) {
setHostId(Hostid{mSerialNumber, Type::ECS_ASSIST});
return;
}
getLocalHostId();
setHostId(Hostid{mLocalHostId, Type::LOCAL});
}

void HostIdentifier::setHostId(const Hostid& hostid) {
if (mHostid.id == hostid.id && mHostid.type == hostid.type) {
return;
}
LOG_INFO(sLogger,
("change hostId, id from", mHostid.id)("to", hostid.id)("type from", mHostid.type)("to", hostid.type));
std::unique_lock<std::shared_mutex> lock(mMutex); // 写锁
mHostid = hostid;
}

bool ParseECSMeta(const std::string& meta, ECSMeta& metaObj) {
rapidjson::Document doc;
doc.Parse(meta.c_str());
if (doc.HasParseError() || !doc.IsObject()) {
LOG_WARNING(sLogger, ("fetch ecs meta fail", meta));
return false;
}

if (const auto instanceItr = doc.FindMember("instance-id");
instanceItr != doc.MemberEnd() && instanceItr->value.IsString()) {
metaObj.instanceID = instanceItr->value.GetString();
}

if (const auto userItr = doc.FindMember("owner-account-id");
userItr != doc.MemberEnd() && userItr->value.IsString()) {
metaObj.userID = userItr->value.GetString();
}

if (const auto regionItr = doc.FindMember("region-id");
regionItr != doc.MemberEnd() && regionItr->value.IsString()) {
metaObj.regionID = regionItr->value.GetString();
}
if (!metaObj.instanceID.empty() && !metaObj.userID.empty() && !metaObj.regionID.empty()) {
metaObj.isValid = true;
}
return true;
}

void HostIdentifier::getECSMetaFromFile() {
std::string fileName = AppConfig::GetInstance()->GetLoongcollectorConfDir() + PATH_SEPARATOR + "instance_identity";
if (!CheckExistance(fileName)) {
return;
}
std::string ecsMetaStr;
if (ReadFileContent(fileName, ecsMetaStr) && ParseECSMeta(ecsMetaStr, mMetadata)) {
return;
} else {
LOG_ERROR(sLogger, ("read ecs meta from file fail", fileName)("ecs meta", ecsMetaStr));
}
}

bool HostIdentifier::FetchECSMeta(ECSMeta& metaObj) {
metaObj.isValid = false;
CURL* curl = nullptr;
for (size_t retryTimes = 1; retryTimes <= 5; retryTimes++) {
curl = curl_easy_init();
if (curl) {
break;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
ECSMeta metaObj;
metaObj.instanceID = "";
metaObj.userID = "";
metaObj.regionID = "";
if (curl) {
std::string token;
auto* tokenHeaders = curl_slist_append(nullptr, "X-aliyun-ecs-metadata-token-ttl-seconds:3600");
if (!tokenHeaders) {
curl_easy_cleanup(curl);
return false;
}
curl_easy_setopt(curl, CURLOPT_URL, "http://100.100.100.200/latest/api/token");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, tokenHeaders);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &token);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FetchECSMetaCallback);

CURLcode res = curl_easy_perform(curl);
curl_slist_free_all(tokenHeaders);

if (res != CURLE_OK) {
LOG_INFO(sLogger, ("fetch ecs token fail", curl_easy_strerror(res)));
curl_easy_cleanup(curl);
return false;
}

// Get metadata with token
std::string meta;
auto* metaHeaders = curl_slist_append(nullptr, ("X-aliyun-ecs-metadata-token: " + token).c_str());
if (!metaHeaders) {
curl_easy_cleanup(curl);
return false;
}

curl_easy_reset(curl);
curl_easy_setopt(curl, CURLOPT_URL, "http://100.100.100.200/latest/dynamic/instance-identity/document");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, metaHeaders);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &meta);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FetchECSMetaCallback);
CURLcode res = curl_easy_perform(curl);

res = curl_easy_perform(curl);
curl_slist_free_all(metaHeaders);

if (res != CURLE_OK) {
LOG_DEBUG(sLogger, ("fetch ecs meta fail", curl_easy_strerror(res)));
} else {
rapidjson::Document doc;
doc.Parse(meta.c_str());
if (doc.HasParseError() || !doc.IsObject()) {
LOG_DEBUG(sLogger, ("fetch ecs meta fail", meta));
} else {
rapidjson::Value::ConstMemberIterator instanceItr = doc.FindMember("instance-id");
if (instanceItr != doc.MemberEnd() && (instanceItr->value.IsString())) {
metaObj.instanceID = instanceItr->value.GetString();
}

rapidjson::Value::ConstMemberIterator userItr = doc.FindMember("owner-account-id");
if (userItr != doc.MemberEnd() && userItr->value.IsString()) {
metaObj.userID = userItr->value.GetString();
}

rapidjson::Value::ConstMemberIterator regionItr = doc.FindMember("region-id");
if (regionItr != doc.MemberEnd() && regionItr->value.IsString()) {
metaObj.regionID = regionItr->value.GetString();
}
}
LOG_INFO(sLogger, ("fetch ecs meta fail", curl_easy_strerror(res)));
curl_easy_cleanup(curl);
return false;
}
if (!ParseECSMeta(meta, metaObj)) {
curl_easy_cleanup(curl);
return false;
}
mMetadataStr = meta;
curl_easy_cleanup(curl);
return metaObj;
return metaObj.isValid;
}
LOG_WARNING(
sLogger,
("curl handler cannot be initialized during user environment identification", "ecs meta may be mislabeled"));
return metaObj;
return false;
}

// 从云助手获取序列号
void HostIdentifier::getSerialNumberFromEcsAssist() {
if (mHasTriedToGetSerialNumber) {
return;
}
if (CheckExistance(mEcsAssistMachineIdFile)) {
if (!ReadFileContent(mEcsAssistMachineIdFile, mSerialNumber)) {
mSerialNumber = "";
}
}
mHasTriedToGetSerialNumber = true;
}

void HostIdentifier::getLocalHostId() {
std::string fileName = AppConfig::GetInstance()->GetLoongcollectorConfDir() + PATH_SEPARATOR + "host_id";
if (!mLocalHostId.empty()) {
return;
}
if (CheckExistance(fileName)) {
if (!ReadFileContent(fileName, mLocalHostId)) {
mLocalHostId = "";
}
}
if (mLocalHostId.empty()) {
// 随机生成hostid
mLocalHostId = CalculateRandomUUID();

LOG_INFO(sLogger, ("save hostId file to local file system, hostId", mLocalHostId));
int fd = open(fileName.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0755);
if (fd == -1) {
int savedErrno = errno;
if (savedErrno != EEXIST) {
LOG_ERROR(sLogger, ("save hostId file fail", fileName)("errno", strerror(savedErrno)));
}
} else {
// 文件成功创建,现在写入hostId
ssize_t written = write(fd, mLocalHostId.c_str(), mLocalHostId.length());
if (written == static_cast<ssize_t>(mLocalHostId.length())) {
LOG_INFO(sLogger, ("hostId saved successfully to", fileName));
} else {
int writeErrno = errno;
LOG_ERROR(sLogger, ("Failed to write hostId to file", fileName)("errno", strerror(writeErrno)));
}
close(fd);
}
}
}

} // namespace logtail
Loading
Loading