mirror of
https://github.com/clearlinux/micro-config-drive.git
synced 2026-09-05 13:11:46 +00:00
add command line option to process openstack config drive
add --openstack-config-drive option to process metadata and userdata using as datasource an openstack config drive (iso9660 or vfat filesystem) add type_by_device function to get the disk type
This commit is contained in:
+10
-3
@@ -59,9 +59,16 @@ service URL.
|
||||
.PP
|
||||
\fB\-\-openstack\-metadata\-file\fR FILE
|
||||
.RS 4
|
||||
Path to an openstack metadata file\&. If omitted, \fBcloud-init\fR will
|
||||
attempt to fetch metadata from the openstack link-local connected data
|
||||
service URL.
|
||||
Path to an openstack metadata file.
|
||||
more information: \%http://docs.openstack.org/user-guide/cli_config_drive.html#openstack-metadata-format
|
||||
.RE
|
||||
.PP
|
||||
\fB\-\-openstack\-config\-drive\fR PATH
|
||||
.RS 4
|
||||
Path to openstack config drive (iso9660 or vfat filesystem),
|
||||
it will be used to process metadata and userdata.
|
||||
more information:
|
||||
\%http://docs.openstack.org/user-guide/cli_config_drive.html#configuration-drive-contents
|
||||
.RE
|
||||
.PP
|
||||
\fB\-\-user\-data\fR
|
||||
|
||||
+115
-82
@@ -118,6 +118,115 @@ int openstack_main(struct datasource_options_struct* opts) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
gboolean openstack_process_config_drive(const gchar* path) {
|
||||
char mountpoint[] = "/tmp/config-2-XXXXXX";
|
||||
char userdata_file[] = "/tmp/userdata-XXXXXX";
|
||||
int fd_userdata_in = 0;
|
||||
int fd_userdata_out = 0;
|
||||
off_t bytes_copied = 0;
|
||||
ssize_t send_result = 0;
|
||||
struct stat userdata_info = { 0 };
|
||||
gchar metadata_drive_path[PATH_MAX] = { 0 };
|
||||
gchar userdata_drive_path[PATH_MAX] = { 0 };
|
||||
gchar* devtype = NULL;
|
||||
gboolean result = false;
|
||||
struct stat st;
|
||||
gchar command[PATH_MAX] = { 0 };
|
||||
|
||||
if (!type_by_device(path, &devtype)) {
|
||||
LOG("Unknown filesystem device '%s'\n", (char*)path);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mkdtemp(mountpoint)) {
|
||||
LOG(MOD "Unable to create directory '%s'\n", mountpoint);
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (stat(path, &st)) {
|
||||
LOG(MOD "stat failed\n");
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if ((st.st_mode & S_IFMT) != S_IFBLK) {
|
||||
g_snprintf(command, PATH_MAX, "mount -o loop,ro -t %s %s %s", devtype, path, mountpoint );
|
||||
if (!exec_task(command)) {
|
||||
LOG(MOD "Unable to mount config drive '%s'\n", (char*)path);
|
||||
goto fail2;
|
||||
}
|
||||
} else if (mount(path, mountpoint, devtype, MS_NODEV|MS_NOEXEC|MS_RDONLY, NULL) != 0) {
|
||||
LOG(MOD "Unable to mount config drive '%s'\n", (char*)path);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
g_snprintf(metadata_drive_path, PATH_MAX, "%s%s", mountpoint, METADATA_DRIVE_PATH);
|
||||
if (!openstack_process_metadata(metadata_drive_path)) {
|
||||
LOG(MOD "Using config drive get and process metadata failed\n");
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
result = true;
|
||||
|
||||
g_snprintf(userdata_drive_path, PATH_MAX, "%s%s", mountpoint, USERDATA_DRIVE_PATH);
|
||||
fd_userdata_in = open(userdata_drive_path, O_RDONLY);
|
||||
if (-1 == fd_userdata_in) {
|
||||
LOG(MOD "No userdata in config drive\n");
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
if (fstat(fd_userdata_in, &userdata_info) == -1) {
|
||||
LOG(MOD "Unable to get info from file '%s'\n", userdata_drive_path);
|
||||
goto fail4;
|
||||
}
|
||||
|
||||
fd_userdata_out = mkstemp(userdata_file);
|
||||
if (-1 == fd_userdata_out) {
|
||||
LOG(MOD "Unable to create a temporal file\n");
|
||||
goto fail4;
|
||||
}
|
||||
|
||||
send_result = sendfile(fd_userdata_out, fd_userdata_in, &bytes_copied, (size_t)userdata_info.st_size);
|
||||
if (-1 == send_result) {
|
||||
LOG(MOD "Unable to copy file from '%s' to '%s'\n", userdata_drive_path, userdata_file);
|
||||
goto fail5;
|
||||
}
|
||||
|
||||
close(fd_userdata_out);
|
||||
close(fd_userdata_in);
|
||||
fd_userdata_out = 0;
|
||||
fd_userdata_in = 0;
|
||||
|
||||
if (!userdata_process_file(userdata_file)) {
|
||||
LOG(MOD "Unable to process userdata\n");
|
||||
}
|
||||
|
||||
remove(userdata_file);
|
||||
|
||||
fail5:
|
||||
if (fd_userdata_out) {
|
||||
close(fd_userdata_out);
|
||||
}
|
||||
fail4:
|
||||
if (fd_userdata_in) {
|
||||
close(fd_userdata_in);
|
||||
}
|
||||
fail3:
|
||||
if ((st.st_mode & S_IFMT) != S_IFBLK) {
|
||||
g_snprintf(command, PATH_MAX, "umount %s", mountpoint );
|
||||
if (!exec_task(command)) {
|
||||
LOG(MOD "Using config drive cannot umount '%s'\n", mountpoint);
|
||||
goto fail2;
|
||||
}
|
||||
} else if (umount(mountpoint) != 0) {
|
||||
LOG(MOD "Using config drive cannot umount '%s'\n", mountpoint);
|
||||
}
|
||||
fail2:
|
||||
rmdir(mountpoint);
|
||||
fail1:
|
||||
g_free(devtype);
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean openstack_process_metadata(const gchar* filename) {
|
||||
GError* error = NULL;
|
||||
JsonParser* parser = NULL;
|
||||
@@ -187,102 +296,26 @@ cleancurl:
|
||||
}
|
||||
|
||||
static gboolean openstack_use_config_drive(void) {
|
||||
char mountpoint[] = "/tmp/config-2-XXXXXX";
|
||||
char userdata_file[] = "/tmp/userdata-XXXXXX";
|
||||
int fd_userdata_in = 0;
|
||||
int fd_userdata_out = 0;
|
||||
off_t bytes_copied = 0;
|
||||
ssize_t send_result = 0;
|
||||
struct stat userdata_info = { 0 };
|
||||
gboolean config_drive = false;
|
||||
GString* metadata_drive_path;
|
||||
GString* userdata_drive_path;
|
||||
gchar* device;
|
||||
gchar* devtype;
|
||||
gchar* device = NULL;
|
||||
gboolean result = false;
|
||||
|
||||
config_drive = disk_by_label("config-2", &device, &devtype);
|
||||
config_drive = disk_by_label("config-2", &device);
|
||||
|
||||
if (!config_drive) {
|
||||
LOG(MOD "Config drive not found\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mkdtemp(mountpoint)) {
|
||||
LOG(MOD "Cannot create directory '%s'\n", mountpoint);
|
||||
goto failcfgdrive0;
|
||||
}
|
||||
|
||||
if (mount(device, mountpoint, devtype, MS_NODEV|MS_NOEXEC|MS_RDONLY, NULL) != 0) {
|
||||
LOG(MOD "Cannot mount config drive '%s'\n", (char*)device);
|
||||
goto failcfgdrive1;
|
||||
}
|
||||
|
||||
metadata_drive_path = g_string_new(mountpoint);
|
||||
g_string_append(metadata_drive_path, METADATA_DRIVE_PATH);
|
||||
userdata_drive_path = g_string_new(mountpoint);
|
||||
g_string_append(userdata_drive_path, USERDATA_DRIVE_PATH);
|
||||
|
||||
if (!openstack_process_metadata(metadata_drive_path->str)) {
|
||||
LOG(MOD "Using config drive get and process metadata failed\n");
|
||||
goto failcfgdrive2;
|
||||
if (!openstack_process_config_drive(device)) {
|
||||
LOG(MOD "Process config drive failed\n");
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
result = true;
|
||||
|
||||
fd_userdata_in = open(userdata_drive_path->str, O_RDONLY);
|
||||
if (-1 == fd_userdata_in) {
|
||||
LOG(MOD "No userdata in config drive\n");
|
||||
goto failcfgdrive2;
|
||||
}
|
||||
|
||||
if (fstat(fd_userdata_in, &userdata_info) == -1) {
|
||||
LOG(MOD "Cannot get info from file '%s'\n", userdata_drive_path->str);
|
||||
goto failcfgdrive3;
|
||||
}
|
||||
|
||||
fd_userdata_out = mkstemp(userdata_file);
|
||||
if (-1 == fd_userdata_out) {
|
||||
LOG(MOD "Cannot create a temporal file\n");
|
||||
goto failcfgdrive3;
|
||||
}
|
||||
|
||||
send_result = sendfile(fd_userdata_out, fd_userdata_in, &bytes_copied, (size_t)userdata_info.st_size);
|
||||
if (-1 == send_result) {
|
||||
LOG(MOD "Cannot copy file from '%s' to '%s'\n", userdata_drive_path->str, userdata_file);
|
||||
goto failcfgdrive4;
|
||||
}
|
||||
|
||||
close(fd_userdata_out);
|
||||
close(fd_userdata_in);
|
||||
fd_userdata_out = 0;
|
||||
fd_userdata_in = 0;
|
||||
|
||||
if (!userdata_process_file(userdata_file)) {
|
||||
LOG(MOD "Unable to process userdata\n");
|
||||
}
|
||||
|
||||
remove(userdata_file);
|
||||
|
||||
failcfgdrive4:
|
||||
if (fd_userdata_out) {
|
||||
close(fd_userdata_out);
|
||||
}
|
||||
failcfgdrive3:
|
||||
if (fd_userdata_in) {
|
||||
close(fd_userdata_in);
|
||||
}
|
||||
failcfgdrive2:
|
||||
g_string_free(metadata_drive_path, true);
|
||||
g_string_free(userdata_drive_path, true);
|
||||
if (umount(mountpoint) != 0) {
|
||||
LOG(MOD "Using config drive cannot umount '%s'\n", mountpoint);
|
||||
}
|
||||
failcfgdrive1:
|
||||
rmdir(mountpoint);
|
||||
failcfgdrive0:
|
||||
fail1:
|
||||
g_free(device);
|
||||
g_free(devtype);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,3 +35,5 @@
|
||||
#include <glib.h>
|
||||
|
||||
gboolean openstack_process_metadata(const gchar* filename);
|
||||
|
||||
gboolean openstack_process_config_drive(const gchar* path);
|
||||
|
||||
+14
-9
@@ -194,16 +194,12 @@ fail1:
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean disk_by_label(const gchar* label, gchar** device, gchar** type) {
|
||||
gboolean result = false;
|
||||
gboolean disk_by_label(const gchar* label, gchar** device) {
|
||||
const char* devpath = NULL;
|
||||
const char *devtype = NULL;
|
||||
blkid_dev dev = NULL;
|
||||
blkid_cache cache = NULL;
|
||||
blkid_probe probe = NULL;
|
||||
|
||||
*device = NULL;
|
||||
*type = NULL;
|
||||
|
||||
if (blkid_get_cache(&cache, "/dev/null") != 0) {
|
||||
LOG(MOD "Cannot get cache!\n");
|
||||
@@ -227,7 +223,18 @@ gboolean disk_by_label(const gchar* label, gchar** device, gchar** type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
probe = blkid_new_probe_from_filename(devpath);
|
||||
*device = g_strdup(devpath);
|
||||
return true;
|
||||
}
|
||||
|
||||
gboolean type_by_device(const gchar* device, gchar** type) {
|
||||
gboolean result = false;
|
||||
const char *devtype = NULL;
|
||||
blkid_probe probe = NULL;
|
||||
|
||||
*type = NULL;
|
||||
|
||||
probe = blkid_new_probe_from_filename(device);
|
||||
if(!probe) {
|
||||
LOG(MOD "Probe from filename failed!\n");
|
||||
return false;
|
||||
@@ -245,10 +252,8 @@ gboolean disk_by_label(const gchar* label, gchar** device, gchar** type) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
result = true;
|
||||
*device = g_strdup(devpath);
|
||||
*type = g_strdup(devtype);
|
||||
|
||||
result = true;
|
||||
fail:
|
||||
blkid_free_probe(probe);
|
||||
return result;
|
||||
|
||||
+3
-1
@@ -39,4 +39,6 @@ gchar *disk_for_path(const gchar* path);
|
||||
|
||||
gboolean disk_resize_grow(const gchar* disk_path, GChildWatchFunc async_func_watcher, gpointer data);
|
||||
|
||||
gboolean disk_by_label(const gchar* label, gchar** device, gchar** type);
|
||||
gboolean disk_by_label(const gchar* label, gchar** device);
|
||||
|
||||
gboolean type_by_device(const gchar* device, gchar** type);
|
||||
|
||||
+31
@@ -59,6 +59,7 @@
|
||||
/* Long options */
|
||||
enum {
|
||||
OPT_OPENSTACK_METADATA_FILE=1001,
|
||||
OPT_OPENSTACK_CONFIG_DRIVE,
|
||||
OPT_USER_DATA,
|
||||
OPT_METADATA,
|
||||
OPT_NO_GROWPART,
|
||||
@@ -72,6 +73,7 @@ enum {
|
||||
static struct option opts[] = {
|
||||
{ "user-data-file", required_argument, NULL, 'u' },
|
||||
{ "openstack-metadata-file", required_argument, NULL, OPT_OPENSTACK_METADATA_FILE },
|
||||
{ "openstack-config-drive", required_argument, NULL, OPT_OPENSTACK_CONFIG_DRIVE },
|
||||
{ "user-data", no_argument, NULL, OPT_USER_DATA },
|
||||
{ "metadata", no_argument, NULL, OPT_METADATA },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
@@ -197,7 +199,9 @@ int main(int argc, char *argv[]) {
|
||||
struct datasource_options_struct datasource_opts = { 0 };
|
||||
char* userdata_filename = NULL;
|
||||
char* tmp_metadata_filename = NULL;
|
||||
char* tmp_data_filesystem = NULL;
|
||||
char metadata_filename[PATH_MAX] = { 0 };
|
||||
char data_filesystem_path[PATH_MAX] = { 0 };
|
||||
GError* error = NULL;
|
||||
GThread* async_tasks_thread = NULL;
|
||||
async_task_function func = NULL;
|
||||
@@ -224,6 +228,8 @@ int main(int argc, char *argv[]) {
|
||||
LOG("Usage: %s [options]\n", argv[0]);
|
||||
LOG("-u, --user-data-file [file] specify a custom user data file\n");
|
||||
LOG(" --openstack-metadata-file [file] specify an Openstack metadata file\n");
|
||||
LOG(" --openstack-config-drive [path] specify an Openstack config drive to process\n");
|
||||
LOG(" metadata and user data (iso9660 or vfat filesystem)\n");
|
||||
LOG(" --user-data get and process user data from data sources\n");
|
||||
LOG(" --metadata get and process metadata from data sources\n");
|
||||
LOG("-h, --help display this help message\n");
|
||||
@@ -252,6 +258,11 @@ int main(int argc, char *argv[]) {
|
||||
tmp_metadata_filename = strdup(optarg);
|
||||
break;
|
||||
|
||||
case OPT_OPENSTACK_CONFIG_DRIVE:
|
||||
datasource = DS_OPENSTACK;
|
||||
tmp_data_filesystem = strdup(optarg);
|
||||
break;
|
||||
|
||||
case OPT_USER_DATA:
|
||||
datasource_opts.user_data = true;
|
||||
break;
|
||||
@@ -342,6 +353,26 @@ int main(int argc, char *argv[]) {
|
||||
tmp_metadata_filename = NULL;
|
||||
}
|
||||
|
||||
/* process userdata/metadata using iso9660 or vfat filesystem */
|
||||
if (tmp_data_filesystem) {
|
||||
if (realpath(tmp_data_filesystem, data_filesystem_path)) {
|
||||
switch (datasource) {
|
||||
case DS_OPENSTACK:
|
||||
if (!openstack_process_config_drive(data_filesystem_path)) {
|
||||
result_code = EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG("Unsupported datasource '%d'\n", datasource);
|
||||
}
|
||||
} else {
|
||||
LOG("iso9660 or vfat filesystem not found '%s'\n", tmp_data_filesystem);
|
||||
}
|
||||
|
||||
free(tmp_data_filesystem);
|
||||
tmp_data_filesystem = NULL;
|
||||
}
|
||||
|
||||
/* process userdata file */
|
||||
if (userdata_filename) {
|
||||
if (!userdata_process_file(userdata_filename)) {
|
||||
|
||||
Reference in New Issue
Block a user