summaryrefslogtreecommitdiff
path: root/src/machine
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-03-09 17:55:07 +0100
committerLennart Poettering <lennart@poettering.net>2015-03-09 18:02:23 +0100
commit587fec427c80b6c34dcf1d7570f891fcb652a7c5 (patch)
tree0b8f6e748ac8ecc34cbe6d03327532fb52a0e85b /src/machine
parentea79e73b8a8fa72fb959a0604f642f97e200a803 (diff)
importd: add API for exporting container/VM images
Also, expose it in machinectl.
Diffstat (limited to 'src/machine')
-rw-r--r--src/machine/machinectl.c151
1 files changed, 142 insertions, 9 deletions
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index afc4fd640c..8856040206 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -71,6 +71,7 @@ static OutputMode arg_output = OUTPUT_SHORT;
static bool arg_force = false;
static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
static const char* arg_dkr_index_url = NULL;
+static const char* arg_format = NULL;
static void pager_open_if_enabled(void) {
@@ -1551,7 +1552,7 @@ static int transfer_signal_handler(sd_event_source *s, const struct signalfd_sig
return 0;
}
-static int pull_image_common(sd_bus *bus, sd_bus_message *m) {
+static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
_cleanup_bus_slot_unref_ sd_bus_slot *slot_job_removed = NULL, *slot_log_message = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
@@ -1598,7 +1599,7 @@ static int pull_image_common(sd_bus *bus, sd_bus_message *m) {
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
- log_error("Failed acquire image: %s", bus_error_message(&error, -r));
+ log_error("Failed transfer image: %s", bus_error_message(&error, -r));
return r;
}
@@ -1685,7 +1686,7 @@ static int import_tar(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_create_error(r);
- return pull_image_common(bus, m);
+ return transfer_image_common(bus, m);
}
static int import_raw(int argc, char *argv[], void *userdata) {
@@ -1752,7 +1753,124 @@ static int import_raw(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_create_error(r);
- return pull_image_common(bus, m);
+ return transfer_image_common(bus, m);
+}
+
+static void determine_compression_from_filename(const char *p) {
+ if (arg_format)
+ return;
+
+ if (!p)
+ return;
+
+ if (endswith(p, ".xz"))
+ arg_format = "xz";
+ else if (endswith(p, ".gz"))
+ arg_format = "gzip";
+ else if (endswith(p, ".bz2"))
+ arg_format = "bzip2";
+}
+
+static int export_tar(int argc, char *argv[], void *userdata) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_free_ char *ll = NULL;
+ _cleanup_close_ int fd = -1;
+ const char *local = NULL, *path = NULL;
+ sd_bus *bus = userdata;
+ int r;
+
+ assert(bus);
+
+ local = argv[1];
+ if (!machine_name_is_valid(local)) {
+ log_error("Machine name %s is not valid.", local);
+ return -EINVAL;
+ }
+
+ if (argc >= 3)
+ path = argv[2];
+ if (isempty(path) || streq(path, "-"))
+ path = NULL;
+
+ if (path) {
+ determine_compression_from_filename(path);
+
+ fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666);
+ if (fd < 0)
+ return log_error_errno(errno, "Failed to open %s: %m", path);
+ }
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ &m,
+ "org.freedesktop.import1",
+ "/org/freedesktop/import1",
+ "org.freedesktop.import1.Manager",
+ "ExportTar");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "shs",
+ local,
+ fd >= 0 ? fd : STDOUT_FILENO,
+ arg_format);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return transfer_image_common(bus, m);
+}
+
+static int export_raw(int argc, char *argv[], void *userdata) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_free_ char *ll = NULL;
+ _cleanup_close_ int fd = -1;
+ const char *local = NULL, *path = NULL;
+ sd_bus *bus = userdata;
+ int r;
+
+ assert(bus);
+
+ local = argv[1];
+ if (!machine_name_is_valid(local)) {
+ log_error("Machine name %s is not valid.", local);
+ return -EINVAL;
+ }
+
+ if (argc >= 3)
+ path = argv[2];
+ if (isempty(path) || streq(path, "-"))
+ path = NULL;
+
+ if (path) {
+ determine_compression_from_filename(path);
+
+ fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666);
+ if (fd < 0)
+ return log_error_errno(errno, "Failed to open %s: %m", path);
+ }
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ &m,
+ "org.freedesktop.import1",
+ "/org/freedesktop/import1",
+ "org.freedesktop.import1.Manager",
+ "ExportRaw");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "shs",
+ local,
+ fd >= 0 ? fd : STDOUT_FILENO,
+ arg_format);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return transfer_image_common(bus, m);
}
static int pull_tar(int argc, char *argv[], void *userdata) {
@@ -1816,7 +1934,7 @@ static int pull_tar(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_create_error(r);
- return pull_image_common(bus, m);
+ return transfer_image_common(bus, m);
}
static int pull_raw(int argc, char *argv[], void *userdata) {
@@ -1880,7 +1998,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_create_error(r);
- return pull_image_common(bus, m);
+ return transfer_image_common(bus, m);
}
static int pull_dkr(int argc, char *argv[], void *userdata) {
@@ -1952,7 +2070,7 @@ static int pull_dkr(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_create_error(r);
- return pull_image_common(bus, m);
+ return transfer_image_common(bus, m);
}
typedef struct TransferInfo {
@@ -2199,11 +2317,13 @@ static int help(int argc, char *argv[], void *userdata) {
" remove NAME... Remove an image\n"
" set-limit [NAME] BYTES Set image or pool size limit (disk quota)\n\n"
"Image Transfer Commands:\n"
- " import-tar FILE [NAME] Import a local TAR container image\n"
- " import-raw FILE [NAME] Import a local RAW container or VM image\n"
" pull-tar URL [NAME] Download a TAR container image\n"
" pull-raw URL [NAME] Download a RAW container or VM image\n"
" pull-dkr REMOTE [NAME] Download a DKR container image\n"
+ " import-tar FILE [NAME] Import a local TAR container image\n"
+ " import-raw FILE [NAME] Import a local RAW container or VM image\n"
+ " export-tar FILE [NAME] Export a TAR container image locally\n"
+ " export-raw FILE [NAME] Export a RAW container or VM image locally\n"
" list-transfers Show list of downloads in progress\n"
" cancel-transfer Cancel a download\n"
, program_invocation_short_name);
@@ -2224,6 +2344,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_VERIFY,
ARG_FORCE,
ARG_DKR_INDEX_URL,
+ ARG_FORMAT,
};
static const struct option options[] = {
@@ -2247,6 +2368,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "verify", required_argument, NULL, ARG_VERIFY },
{ "force", no_argument, NULL, ARG_FORCE },
{ "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL },
+ { "format", required_argument, NULL, ARG_FORMAT },
{}
};
@@ -2368,6 +2490,15 @@ static int parse_argv(int argc, char *argv[]) {
arg_dkr_index_url = optarg;
break;
+ case ARG_FORMAT:
+ if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2")) {
+ log_error("Unknown format: %s", optarg);
+ return -EINVAL;
+ }
+
+ arg_format = optarg;
+ break;
+
case '?':
return -EINVAL;
@@ -2405,6 +2536,8 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) {
{ "disable", 2, VERB_ANY, 0, enable_machine },
{ "import-tar", 2, 3, 0, import_tar },
{ "import-raw", 2, 3, 0, import_raw },
+ { "export-tar", 2, 3, 0, export_tar },
+ { "export-raw", 2, 3, 0, export_raw },
{ "pull-tar", 2, 3, 0, pull_tar },
{ "pull-raw", 2, 3, 0, pull_raw },
{ "pull-dkr", 2, 3, 0, pull_dkr },