When running on EC2, getting the "hardware" UUID from SMBIOS won't work.
Instead, we have to grab the EC2 instance ID, which is reachable over
HTTP. This implements getting that ID using libcurl on Linux.
Signed-off-by: Russell Bryant <rbryant(a)redhat.com>
---
src/lib/host.c | 5 ++
src/lib/host_linux.c | 97 +++++++++++++++++++++++++++++++++++++++++++++--
src/lib/host_private.h | 3 +
src/lib/host_windows.c | 8 ++++
4 files changed, 108 insertions(+), 5 deletions(-)
diff --git a/src/lib/host.c b/src/lib/host.c
index 2212b6d..29cb654 100644
--- a/src/lib/host.c
+++ b/src/lib/host.c
@@ -267,8 +267,13 @@ mh_host_get_uuid(const char *lifetime)
uuid = immutable_uuid;
} else if (!strcasecmp("hardware", lifetime)) {
if (!hardware_uuid) {
+ /* Check for a UUID from SMBIOS first. */
hardware_uuid = host_os_machine_uuid();
}
+ if (!hardware_uuid) {
+ /* If SMBIOS wasn't available, then maybe we're on EC2, try that. */
+ hardware_uuid = host_os_ec2_instance_id();
+ }
uuid = hardware_uuid;
} else if (!strcasecmp("reboot", lifetime)) {
if (!reboot_uuid) {
diff --git a/src/lib/host_linux.c b/src/lib/host_linux.c
index 7e22661..304592a 100644
--- a/src/lib/host_linux.c
+++ b/src/lib/host_linux.c
@@ -34,9 +34,12 @@
#include <pcre.h>
#include <uuid/uuid.h>
+#include <curl/curl.h>
#include "matahari/logging.h"
#include "matahari/host.h"
+
+#include "utilities_private.h"
#include "host_private.h"
@@ -211,7 +214,7 @@ host_os_machine_uuid(void)
if (!output) {
mh_err("Got no output from dmidecode when trying to get UUID.\n");
- return strdup("(dmidecode-failed)");
+ return NULL;
}
lines = g_strsplit(output, "\n", max_lines);
@@ -242,10 +245,6 @@ host_os_machine_uuid(void)
}
cleanup:
- if (!uuid) {
- uuid = strdup("(not-found)");
- }
-
if (lines) {
g_strfreev(lines);
}
@@ -257,6 +256,94 @@ cleanup:
return uuid;
}
+struct curl_write_cb_data {
+ char buf[256];
+ size_t used;
+};
+
+static size_t
+curl_write_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ struct curl_write_cb_data *buf = userdata;
+ size_t len;
+
+ len = size * nmemb;
+
+ if (len >= (sizeof(buf->buf) - buf->used)) {
+ mh_err("Buffer not large enough to hold received UC2 instance ID.");
+ return 0;
+ }
+
+ memcpy(buf->buf + buf->used, ptr, len);
+
+ return len;
+}
+
+char *
+host_os_ec2_instance_id(void)
+{
+ CURL *curl;
+ CURLcode curl_res;
+ long response = 0;
+ static const char URI[] =
"http://169.254.169.254/latest/meta-data/instance-id";
+ struct curl_write_cb_data buf = {
+ .used = 0,
+ };
+
+ if (mh_curl_init() != MH_RES_SUCCESS) {
+ return NULL;
+ }
+
+ if (!(curl = curl_easy_init())) {
+ mh_warn("Failed to curl_easy_init()");
+ return NULL;
+ }
+
+ curl_res = curl_easy_setopt(curl, CURLOPT_URL, URI);
+ if (curl_res != CURLE_OK) {
+ mh_warn("curl_easy_setopt of URI '%s' failed. (%d)", URI,
curl_res);
+ goto return_cleanup;
+ }
+
+ curl_res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
+ if (curl_res != CURLE_OK) {
+ mh_warn("curl_easy_setopt of WRITEFUNCTION failed. (%d)", curl_res);
+ goto return_cleanup;
+ }
+
+ curl_res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
+ if (curl_res != CURLE_OK) {
+ mh_warn("curl_easy_setopt of WRITEDATA failed. (%d)", curl_res);
+ goto return_cleanup;
+ }
+
+ curl_res = curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long) 3);
+ if (curl_res != CURLE_OK) {
+ mh_warn("curl_easy_setopt of TIMEOUT failed. (%d)", curl_res);
+ goto return_cleanup;
+ }
+
+ curl_res = curl_easy_perform(curl);
+ if (curl_res != CURLE_OK) {
+ mh_warn("curl request for URI '%s' failed. (%d)", URI,
curl_res);
+ goto return_cleanup;
+ }
+
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
+ if (curl_res != CURLE_OK) {
+ mh_warn("curl_easy_getinfo for RESPONSE_CODE failed. (%d)", curl_res);
+ goto return_cleanup;
+ }
+ if (response < 200 || response > 299) {
+ mh_warn("curl request for URI '%s' got response %ld", URI,
response);
+ }
+
+return_cleanup:
+ curl_easy_cleanup(curl);
+
+ return mh_strlen_zero(buf.buf) ? NULL : strdup(buf.buf);
+}
+
char *
host_os_custom_uuid(void)
{
diff --git a/src/lib/host_private.h b/src/lib/host_private.h
index 119620c..c2f7a1b 100644
--- a/src/lib/host_private.h
+++ b/src/lib/host_private.h
@@ -53,6 +53,9 @@ char *
host_os_machine_uuid(void);
char *
+host_os_ec2_instance_id(void);
+
+char *
host_os_custom_uuid(void);
char *
diff --git a/src/lib/host_windows.c b/src/lib/host_windows.c
index aae2166..71c5089 100644
--- a/src/lib/host_windows.c
+++ b/src/lib/host_windows.c
@@ -153,6 +153,14 @@ host_os_machine_uuid(void)
return ret;
}
+char *
+host_os_ec2_instance_id(void)
+{
+ /* XXX */
+
+ return NULL;
+}
+
/**
* \internal
* \brief Get time of last boot.
--
1.7.6.2