diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | configure.ac | 9 | ||||
-rw-r--r-- | man/machinectl.xml | 70 | ||||
-rw-r--r-- | shell-completion/bash/machinectl | 2 | ||||
-rw-r--r-- | shell-completion/zsh/_machinectl | 4 | ||||
-rw-r--r-- | src/import/importd.c | 123 | ||||
-rw-r--r-- | src/import/org.freedesktop.import1.conf | 4 | ||||
-rw-r--r-- | src/import/pull-dkr.c | 1346 | ||||
-rw-r--r-- | src/import/pull-dkr.h | 38 | ||||
-rw-r--r-- | src/import/pull.c | 128 | ||||
-rw-r--r-- | src/machine/machinectl.c | 90 | ||||
-rw-r--r-- | src/shared/import-util.c | 52 | ||||
-rw-r--r-- | src/shared/import-util.h | 6 |
14 files changed, 16 insertions, 1862 deletions
diff --git a/Makefile.am b/Makefile.am index f20e555d5b..f552f7a60b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5021,8 +5021,6 @@ systemd_pull_SOURCES = \ src/import/pull-raw.h \ src/import/pull-tar.c \ src/import/pull-tar.h \ - src/import/pull-dkr.c \ - src/import/pull-dkr.h \ src/import/pull-job.c \ src/import/pull-job.h \ src/import/pull-common.c \ @@ -600,8 +600,6 @@ Features: removed or added to an existing machine - "machinectl migrate" or similar to copy a container from or to a difference host, via ssh - - man: document how update dkr images works with machinectl - http://lists.freedesktop.org/archives/systemd-devel/2015-February/028630.html - introduce systemd-nspawn-ephemeral@.service, and hook it into "machinectl start" with a new --ephemeral switch - "machinectl status" should also show internal logs of the container in @@ -614,8 +612,6 @@ Features: shell in it, and marks it read-only after use * importd: - - dkr: support tarsum checksum verification, if it becomes reality one day... - - dkr: convert json bits to nspawn configuration - generate a nice warning if mkfs.btrfs is missing * cryptsetup: diff --git a/configure.ac b/configure.ac index f4b188aaab..c2222c376c 100644 --- a/configure.ac +++ b/configure.ac @@ -1440,14 +1440,6 @@ AC_ARG_ENABLE([split-usr], enable_split_usr=no ])]) -AC_ARG_WITH([dkr-index-url], - [AS_HELP_STRING([--dkr-index-url=URL], [Specify the default index URL to use for image downloads])], - [DEFAULT_DKR_INDEX_URL="\"$withval\""], - [DEFAULT_DKR_INDEX_URL="NULL"]) - -AC_DEFINE_UNQUOTED(DEFAULT_DKR_INDEX_URL, [$DEFAULT_DKR_INDEX_URL], [Default index URL to use for image downloads]) -AC_SUBST(DEFAULT_DKR_INDEX_URL) - AS_IF([test "x${enable_split_usr}" = "xyes"], [ AC_DEFINE(HAVE_SPLIT_USR, 1, [Define if /bin, /sbin aren't symlinks into /usr]) ]) @@ -1616,7 +1608,6 @@ AC_MSG_RESULT([ Maximum System UID: ${SYSTEM_UID_MAX} Maximum System GID: ${SYSTEM_GID_MAX} Certificate root: ${CERTIFICATEROOT} - Default dkr Index ${DEFAULT_DKR_INDEX_URL} CFLAGS: ${OUR_CFLAGS} ${CFLAGS} CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS} diff --git a/man/machinectl.xml b/man/machinectl.xml index 0e18953700..a7288c249b 100644 --- a/man/machinectl.xml +++ b/man/machinectl.xml @@ -265,16 +265,6 @@ </varlistentry> <varlistentry> - <term><option>--dkr-index-url</option></term> - - <listitem><para>Specifies the index server to use for - downloading <literal>dkr</literal> images with the - <command>pull-dkr</command>. Takes a - <literal>http://</literal>, <literal>https://</literal> - URL.</para></listitem> - </varlistentry> - - <varlistentry> <term><option>--format=</option></term> <listitem><para>When used with the <option>export-tar</option> @@ -761,42 +751,6 @@ </varlistentry> <varlistentry> - <term><command>pull-dkr</command> <replaceable>REMOTE</replaceable> [<replaceable>NAME</replaceable>]</term> - - <listitem><para>Downloads a <literal>dkr</literal> container - image and makes it available locally. The remote name refers - to a <literal>dkr</literal> container name. If omitted, the - local machine name is derived from the <literal>dkr</literal> - container name.</para> - - <para>Image verification is not available for - <literal>dkr</literal> containers, and thus - <option>--verify=no</option> must always be specified with - this command.</para> - - <para>This command downloads all (missing) layers for the - specified container and places them in read-only subvolumes in - <filename>/var/lib/machines/</filename>. A writable snapshot - of the newest layer is then created under the specified local - machine name. To omit creation of this writable snapshot, pass - <literal>-</literal> as local machine name.</para> - - <para>The read-only layer subvolumes are prefixed with - <filename>.dkr-</filename>, and thus not shown by - <command>list-images</command>, unless <option>--all</option> - is passed.</para> - - <para>To specify the <literal>dkr</literal> index server to - use for looking up the specified container, use - <option>--dkr-index-url=</option>.</para> - - <para>Note that pressing C-c during execution of this command - will not abort the download. Use - <command>cancel-transfer</command>, described - below.</para></listitem> - </varlistentry> - - <varlistentry> <term><command>import-tar</command> <replaceable>FILE</replaceable> [<replaceable>NAME</replaceable>]</term> <term><command>import-raw</command> <replaceable>FILE</replaceable> [<replaceable>NAME</replaceable>]</term> <listitem><para>Imports a TAR or RAW container or VM image, @@ -926,12 +880,12 @@ <para>Note that many image operations are only supported, efficient or atomic on btrfs file systems. Due to this, if the <command>pull-tar</command>, <command>pull-raw</command>, - <command>pull-dkr</command>, <command>import-tar</command>, - <command>import-raw</command> and <command>set-limit</command> - commands notice that <filename>/var/lib/machines</filename> is - empty and not located on btrfs, they will implicitly set up a - loopback file <filename>/var/lib/machines.raw</filename> - containing a btrfs file system that is mounted to + <command>import-tar</command>, <command>import-raw</command> and + <command>set-limit</command> commands notice that + <filename>/var/lib/machines</filename> is empty and not located on + btrfs, they will implicitly set up a loopback file + <filename>/var/lib/machines.raw</filename> containing a btrfs file + system that is mounted to <filename>/var/lib/machines</filename>. The size of this loopback file may be controlled dynamically with <command>set-limit</command>.</para> @@ -995,18 +949,6 @@ </example> <example> - <title>Download a Fedora <literal>dkr</literal> image</title> - - <programlisting># machinectl pull-dkr --verify=no mattdm/fedora -# systemd-nspawn -M fedora</programlisting> - - <para>Downloads a <literal>dkr</literal> image and opens a shell - in it. Note that the specified download command might require an - index server to be specified with the - <literal>--dkr-index-url=</literal>.</para> - </example> - - <example> <title>Exports a container image as tar file</title> <programlisting># machinectl export-tar fedora myfedora.tar.xz</programlisting> diff --git a/shell-completion/bash/machinectl b/shell-completion/bash/machinectl index 61c5402786..e7829ca968 100644 --- a/shell-completion/bash/machinectl +++ b/shell-completion/bash/machinectl @@ -40,7 +40,7 @@ _machinectl() { ) local -A VERBS=( - [STANDALONE]='list list-images pull-tar pull-raw pull-dkr import-tar import-raw export-tar export-raw list-transfers cancel-transfer' + [STANDALONE]='list list-images pull-tar pull-raw import-tar import-raw export-tar export-raw list-transfers cancel-transfer' [MACHINES]='status show start login shell enable disable poweroff reboot terminate kill copy-to copy-from image-status show-image clone rename read-only remove set-limit' ) diff --git a/shell-completion/zsh/_machinectl b/shell-completion/zsh/_machinectl index 7898d7c05b..198fa28f7b 100644 --- a/shell-completion/zsh/_machinectl +++ b/shell-completion/zsh/_machinectl @@ -44,7 +44,6 @@ _available_machines() { "pull-tar:Download a TAR container image" "pull-raw:Download a RAW container or VM image" - "pull-dkr:Download a DKR container image" "list-transfers:Show list of downloads in progress" "cancel-transfer:Cancel a download" ) @@ -57,7 +56,7 @@ _available_machines() { if (( $#cmd )); then if (( CURRENT == 2 )); then case $cmd in - list*|cancel-transfer|pull-tar|pull-raw|pull-dkr) + list*|cancel-transfer|pull-tar|pull-raw) msg="no options" ;; start) _available_machines ;; @@ -97,5 +96,4 @@ _arguments \ {-o+,--output=}'[Change journal output mode.]:output modes:_sd_outputmodes' \ '--verify=[Verification mode for downloaded images.]:verify:(no checksum signature)' \ '--force[Download image even if already exists.]' \ - '--dkr-index-url=[Specify the index URL to use for DKR image downloads.]' \ '*::machinectl command:_machinectl_command' diff --git a/src/import/importd.c b/src/import/importd.c index 1f308b36b3..1b777c32b6 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -55,7 +55,6 @@ typedef enum TransferType { TRANSFER_EXPORT_RAW, TRANSFER_PULL_TAR, TRANSFER_PULL_RAW, - TRANSFER_PULL_DKR, _TRANSFER_TYPE_MAX, _TRANSFER_TYPE_INVALID = -1, } TransferType; @@ -74,7 +73,6 @@ struct Transfer { bool force_local; bool read_only; - char *dkr_index_url; char *format; pid_t pid; @@ -117,7 +115,6 @@ static const char* const transfer_type_table[_TRANSFER_TYPE_MAX] = { [TRANSFER_EXPORT_RAW] = "export-raw", [TRANSFER_PULL_TAR] = "pull-tar", [TRANSFER_PULL_RAW] = "pull-raw", - [TRANSFER_PULL_DKR] = "pull-dkr", }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(transfer_type, TransferType); @@ -134,7 +131,6 @@ static Transfer *transfer_unref(Transfer *t) { free(t->remote); free(t->local); - free(t->dkr_index_url); free(t->format); free(t->object_path); @@ -383,12 +379,11 @@ static int transfer_start(Transfer *t) { if (t->pid == 0) { const char *cmd[] = { NULL, /* systemd-import, systemd-export or systemd-pull */ - NULL, /* tar, raw, dkr */ + NULL, /* tar, raw */ NULL, /* --verify= */ NULL, /* verify argument */ NULL, /* maybe --force */ NULL, /* maybe --read-only */ - NULL, /* maybe --dkr-index-url */ NULL, /* if so: the actual URL */ NULL, /* maybe --format= */ NULL, /* if so: the actual format */ @@ -471,10 +466,8 @@ static int transfer_start(Transfer *t) { if (IN_SET(t->type, TRANSFER_IMPORT_TAR, TRANSFER_EXPORT_TAR, TRANSFER_PULL_TAR)) cmd[k++] = "tar"; - else if (IN_SET(t->type, TRANSFER_IMPORT_RAW, TRANSFER_EXPORT_RAW, TRANSFER_PULL_RAW)) - cmd[k++] = "raw"; else - cmd[k++] = "dkr"; + cmd[k++] = "raw"; if (t->verify != _IMPORT_VERIFY_INVALID) { cmd[k++] = "--verify"; @@ -486,11 +479,6 @@ static int transfer_start(Transfer *t) { if (t->read_only) cmd[k++] = "--read-only"; - if (t->dkr_index_url) { - cmd[k++] = "--dkr-index-url"; - cmd[k++] = t->dkr_index_url; - } - if (t->format) { cmd[k++] = "--format"; cmd[k++] = t->format; @@ -707,7 +695,7 @@ static int manager_new(Manager **ret) { return 0; } -static Transfer *manager_find(Manager *m, TransferType type, const char *dkr_index_url, const char *remote) { +static Transfer *manager_find(Manager *m, TransferType type, const char *remote) { Transfer *t; Iterator i; @@ -718,8 +706,7 @@ static Transfer *manager_find(Manager *m, TransferType type, const char *dkr_ind HASHMAP_FOREACH(t, m->transfers, i) { if (t->type == type && - streq_ptr(t->remote, remote) && - streq_ptr(t->dkr_index_url, dkr_index_url)) + streq_ptr(t->remote, remote)) return t; } @@ -907,7 +894,7 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ? TRANSFER_PULL_TAR : TRANSFER_PULL_RAW; - if (manager_find(m, type, NULL, remote)) + if (manager_find(m, type, remote)) return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, "Transfer for %s already in progress.", remote); r = transfer_new(m, &t); @@ -939,105 +926,6 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er return sd_bus_reply_method_return(msg, "uo", id, object); } -static int method_pull_dkr(sd_bus_message *msg, void *userdata, sd_bus_error *error) { - _cleanup_(transfer_unrefp) Transfer *t = NULL; - const char *index_url, *remote, *tag, *local, *verify, *object; - Manager *m = userdata; - ImportVerify v; - int force, r; - uint32_t id; - - assert(msg); - assert(m); - - r = bus_verify_polkit_async( - msg, - CAP_SYS_ADMIN, - "org.freedesktop.import1.pull", - NULL, - false, - UID_INVALID, - &m->polkit_registry, - error); - if (r < 0) - return r; - if (r == 0) - return 1; /* Will call us back */ - - r = sd_bus_message_read(msg, "sssssb", &index_url, &remote, &tag, &local, &verify, &force); - if (r < 0) - return r; - - if (isempty(index_url)) - index_url = DEFAULT_DKR_INDEX_URL; - if (!index_url) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Index URL must be specified."); - if (!http_url_is_valid(index_url)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Index URL %s is invalid", index_url); - - if (!dkr_name_is_valid(remote)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Remote name %s is not valid", remote); - - if (isempty(tag)) - tag = "latest"; - else if (!dkr_tag_is_valid(tag)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Tag %s is not valid", tag); - - if (isempty(local)) - local = NULL; - else if (!machine_name_is_valid(local)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); - - if (isempty(verify)) - v = IMPORT_VERIFY_SIGNATURE; - else - v = import_verify_from_string(verify); - if (v < 0) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown verification mode %s", verify); - - if (v != IMPORT_VERIFY_NO) - return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "DKR does not support verification."); - - r = setup_machine_directory((uint64_t) -1, error); - if (r < 0) - return r; - - if (manager_find(m, TRANSFER_PULL_DKR, index_url, remote)) - return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, "Transfer for %s already in progress.", remote); - - r = transfer_new(m, &t); - if (r < 0) - return r; - - t->type = TRANSFER_PULL_DKR; - t->verify = v; - t->force_local = force; - - t->dkr_index_url = strdup(index_url); - if (!t->dkr_index_url) - return -ENOMEM; - - t->remote = strjoin(remote, ":", tag, NULL); - if (!t->remote) - return -ENOMEM; - - if (local) { - t->local = strdup(local); - if (!t->local) - return -ENOMEM; - } - - r = transfer_start(t); - if (r < 0) - return r; - - object = t->object_path; - id = t->id; - t = NULL; - - return sd_bus_reply_method_return(msg, "uo", id, object); -} - static int method_list_transfers(sd_bus_message *msg, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; @@ -1188,7 +1076,6 @@ static const sd_bus_vtable manager_vtable[] = { SD_BUS_METHOD("ExportRaw", "shs", "uo", method_export_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PullTar", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PullRaw", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("PullDkr", "sssssb", "uo", method_pull_dkr, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListTransfers", NULL, "a(usssdo)", method_list_transfers, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CancelTransfer", "u", NULL, method_cancel_transfer, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("TransferNew", "uo", 0), diff --git a/src/import/org.freedesktop.import1.conf b/src/import/org.freedesktop.import1.conf index ae36af422f..ed2539a03b 100644 --- a/src/import/org.freedesktop.import1.conf +++ b/src/import/org.freedesktop.import1.conf @@ -53,10 +53,6 @@ send_member="PullRaw"/> <allow send_destination="org.freedesktop.import1" - send_interface="org.freedesktop.import1.Manager" - send_member="PullDkr"/> - - <allow send_destination="org.freedesktop.import1" send_interface="org.freedesktop.import1.Transfer" send_member="Cancel"/> diff --git a/src/import/pull-dkr.c b/src/import/pull-dkr.c deleted file mode 100644 index 831470ff13..0000000000 --- a/src/import/pull-dkr.c +++ /dev/null @@ -1,1346 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <curl/curl.h> -#include <sys/prctl.h> - -#include "sd-daemon.h" - -#include "alloc-util.h" -#include "aufs-util.h" -#include "btrfs-util.h" -#include "curl-util.h" -#include "fd-util.h" -#include "fileio.h" -#include "fs-util.h" -#include "hostname-util.h" -#include "import-common.h" -#include "import-util.h" -#include "json.h" -#include "mkdir.h" -#include "path-util.h" -#include "process-util.h" -#include "pull-common.h" -#include "pull-dkr.h" -#include "pull-job.h" -#include "rm-rf.h" -#include "string-util.h" -#include "strv.h" -#include "utf8.h" -#include "web-util.h" - -typedef enum DkrProgress { - DKR_SEARCHING, - DKR_RESOLVING, - DKR_METADATA, - DKR_DOWNLOADING, - DKR_COPYING, -} DkrProgress; - -struct DkrPull { - sd_event *event; - CurlGlue *glue; - - char *index_protocol; - char *index_address; - - char *index_url; - char *image_root; - - PullJob *images_job; - PullJob *tags_job; - PullJob *ancestry_job; - PullJob *json_job; - PullJob *layer_job; - - char *name; - char *reference; - char *id; - - char *response_digest; - char *response_token; - char **response_registries; - - char **ancestry; - unsigned n_ancestry; - unsigned current_ancestry; - - DkrPullFinished on_finished; - void *userdata; - - char *local; - bool force_local; - bool grow_machine_directory; - - char *temp_path; - char *final_path; - - pid_t tar_pid; -}; - -#define PROTOCOL_PREFIX "https://" - -#define HEADER_TOKEN "X-Do" /* the HTTP header for the auth token */ "cker-Token:" -#define HEADER_REGISTRY "X-Do" /* the HTTP header for the registry */ "cker-Endpoints:" -#define HEADER_DIGEST "Do" /* the HTTP header for the manifest digest */ "cker-Content-Digest:" -#define LAYERS_MAX 127 - -static void dkr_pull_job_on_finished(PullJob *j); - -DkrPull* dkr_pull_unref(DkrPull *i) { - if (!i) - return NULL; - - if (i->tar_pid > 1) { - (void) kill_and_sigcont(i->tar_pid, SIGKILL); - (void) wait_for_terminate(i->tar_pid, NULL); - } - - pull_job_unref(i->images_job); - pull_job_unref(i->tags_job); - pull_job_unref(i->ancestry_job); - pull_job_unref(i->json_job); - pull_job_unref(i->layer_job); - - curl_glue_unref(i->glue); - sd_event_unref(i->event); - - if (i->temp_path) { - (void) rm_rf(i->temp_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); - free(i->temp_path); - } - - free(i->name); - free(i->reference); - free(i->id); - free(i->response_token); - strv_free(i->ancestry); - free(i->final_path); - free(i->index_address); - free(i->index_protocol); - free(i->index_url); - free(i->image_root); - free(i->local); - free(i); - - return NULL; -} - -int dkr_pull_new( - DkrPull **ret, - sd_event *event, - const char *index_url, - const char *image_root, - DkrPullFinished on_finished, - void *userdata) { - - _cleanup_(dkr_pull_unrefp) DkrPull *i = NULL; - char *e; - int r; - - assert(ret); - assert(index_url); - - if (!http_url_is_valid(index_url)) - return -EINVAL; - - i = new0(DkrPull, 1); - if (!i) - return -ENOMEM; - - i->on_finished = on_finished; - i->userdata = userdata; - - i->image_root = strdup(image_root ?: "/var/lib/machines"); - if (!i->image_root) - return -ENOMEM; - - i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines"); - - i->index_url = strdup(index_url); - if (!i->index_url) - return -ENOMEM; - - e = endswith(i->index_url, "/"); - if (e) - *e = 0; - - if (event) - i->event = sd_event_ref(event); - else { - r = sd_event_default(&i->event); - if (r < 0) - return r; - } - - r = curl_glue_new(&i->glue, i->event); - if (r < 0) - return r; - - i->glue->on_finished = pull_job_curl_on_finished; - i->glue->userdata = i; - - *ret = i; - i = NULL; - - return 0; -} - -static void dkr_pull_report_progress(DkrPull *i, DkrProgress p) { - unsigned percent; - - assert(i); - - switch (p) { - - case DKR_SEARCHING: - percent = 0; - if (i->images_job) - percent += i->images_job->progress_percent * 5 / 100; - break; - - case DKR_RESOLVING: - percent = 5; - if (i->tags_job) - percent += i->tags_job->progress_percent * 5 / 100; - break; - - case DKR_METADATA: - percent = 10; - if (i->ancestry_job) - percent += i->ancestry_job->progress_percent * 5 / 100; - if (i->json_job) - percent += i->json_job->progress_percent * 5 / 100; - break; - - case DKR_DOWNLOADING: - percent = 20; - percent += 75 * i->current_ancestry / MAX(1U, i->n_ancestry); - if (i->layer_job) - percent += i->layer_job->progress_percent * 75 / MAX(1U, i->n_ancestry) / 100; - - break; - - case DKR_COPYING: - percent = 95; - break; - - default: - assert_not_reached("Unknown progress state"); - } - - sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); - log_debug("Combined progress %u%%", percent); -} - -static int parse_id(const void *payload, size_t size, char **ret) { - _cleanup_free_ char *buf = NULL, *id = NULL, *other = NULL; - union json_value v = {}; - void *json_state = NULL; - const char *p; - int t; - - assert(payload); - assert(ret); - - if (size <= 0) - return -EBADMSG; - - if (memchr(payload, 0, size)) - return -EBADMSG; - - buf = strndup(payload, size); - if (!buf) - return -ENOMEM; - - p = buf; - t = json_tokenize(&p, &id, &v, &json_state, NULL); - if (t < 0) - return t; - if (t != JSON_STRING) - return -EBADMSG; - - t = json_tokenize(&p, &other, &v, &json_state, NULL); - if (t < 0) - return t; - if (t != JSON_END) - return -EBADMSG; - - if (!dkr_id_is_valid(id)) - return -EBADMSG; - - *ret = id; - id = NULL; - - return 0; -} - -static int parse_ancestry(const void *payload, size_t size, char ***ret) { - _cleanup_free_ char *buf = NULL; - void *json_state = NULL; - const char *p; - enum { - STATE_BEGIN, - STATE_ITEM, - STATE_COMMA, - STATE_END, - } state = STATE_BEGIN; - _cleanup_strv_free_ char **l = NULL; - size_t n = 0, allocated = 0; - - if (size <= 0) - return -EBADMSG; - - if (memchr(payload, 0, size)) - return -EBADMSG; - - buf = strndup(payload, size); - if (!buf) - return -ENOMEM; - - p = buf; - for (;;) { - _cleanup_free_ char *str; - union json_value v = {}; - int t; - - t = json_tokenize(&p, &str, &v, &json_state, NULL); - if (t < 0) - return t; - - switch (state) { - - case STATE_BEGIN: - if (t == JSON_ARRAY_OPEN) - state = STATE_ITEM; - else - return -EBADMSG; - - break; - - case STATE_ITEM: - if (t == JSON_STRING) { - if (!dkr_id_is_valid(str)) - return -EBADMSG; - - if (n+1 > LAYERS_MAX) - return -EFBIG; - - if (!GREEDY_REALLOC(l, allocated, n + 2)) - return -ENOMEM; - - l[n++] = str; - str = NULL; - l[n] = NULL; - - state = STATE_COMMA; - - } else if (t == JSON_ARRAY_CLOSE) - state = STATE_END; - else - return -EBADMSG; - - break; - - case STATE_COMMA: - if (t == JSON_COMMA) - state = STATE_ITEM; - else if (t == JSON_ARRAY_CLOSE) - state = STATE_END; - else - return -EBADMSG; - break; - - case STATE_END: - if (t == JSON_END) { - - if (strv_isempty(l)) - return -EBADMSG; - - if (!strv_is_uniq(l)) - return -EBADMSG; - - l = strv_reverse(l); - - *ret = l; - l = NULL; - return 0; - } else - return -EBADMSG; - } - - } -} - -static const char *dkr_pull_current_layer(DkrPull *i) { - assert(i); - - if (strv_isempty(i->ancestry)) - return NULL; - - return i->ancestry[i->current_ancestry]; -} - -static const char *dkr_pull_current_base_layer(DkrPull *i) { - assert(i); - - if (strv_isempty(i->ancestry)) - return NULL; - - if (i->current_ancestry <= 0) - return NULL; - - return i->ancestry[i->current_ancestry-1]; -} - -static int dkr_pull_add_token(DkrPull *i, PullJob *j) { - const char *t; - - assert(i); - assert(j); - - if (i->response_token) - t = strjoina("Authorization: Token ", i->response_token); - else - t = HEADER_TOKEN " true"; - - j->request_header = curl_slist_new("Accept: application/json", t, NULL); - if (!j->request_header) - return -ENOMEM; - - return 0; -} - -static int dkr_pull_add_bearer_token(DkrPull *i, PullJob *j) { - const char *t = NULL; - - assert(i); - assert(j); - - if (i->response_token) - t = strjoina("Authorization: Bearer ", i->response_token); - else - return -EINVAL; - - j->request_header = curl_slist_new("Accept: application/json", t, NULL); - if (!j->request_header) - return -ENOMEM; - - return 0; -} - -static bool dkr_pull_is_done(DkrPull *i) { - assert(i); - assert(i->images_job); - if (i->images_job->state != PULL_JOB_DONE) - return false; - - if (!i->tags_job || i->tags_job->state != PULL_JOB_DONE) - return false; - - if (!i->ancestry_job || i->ancestry_job->state != PULL_JOB_DONE) - return false; - - if (i->json_job && i->json_job->state != PULL_JOB_DONE) - return false; - - if (i->layer_job && i->layer_job->state != PULL_JOB_DONE) - return false; - - if (dkr_pull_current_layer(i)) - return false; - - return true; -} - -static int dkr_pull_make_local_copy(DkrPull *i, DkrPullVersion version) { - int r; - _cleanup_free_ char *p = NULL; - - assert(i); - - if (!i->local) - return 0; - - if (!i->final_path) { - i->final_path = strjoin(i->image_root, "/.dkr-", i->id, NULL); - if (!i->final_path) - return -ENOMEM; - } - - if (version == DKR_PULL_V2) { - p = dirname_malloc(i->image_root); - if (!p) - return -ENOMEM; - } - - r = pull_make_local_copy(i->final_path, p ?: i->image_root, i->local, i->force_local); - if (r < 0) - return r; - - if (version == DKR_PULL_V2) { - char **k; - - STRV_FOREACH(k, i->ancestry) { - _cleanup_free_ char *d; - - d = strjoin(i->image_root, "/.dkr-", *k, NULL); - if (!d) - return -ENOMEM; - - r = btrfs_subvol_remove(d, BTRFS_REMOVE_QUOTA); - if (r < 0) - return r; - } - - r = rmdir(i->image_root); - if (r < 0) - return r; - } - - return 0; -} - -static int dkr_pull_job_on_open_disk(PullJob *j) { - const char *base; - DkrPull *i; - int r; - - assert(j); - assert(j->userdata); - - i = j->userdata; - assert(i->layer_job == j); - assert(i->final_path); - assert(!i->temp_path); - assert(i->tar_pid <= 0); - - r = tempfn_random(i->final_path, NULL, &i->temp_path); - if (r < 0) - return log_oom(); - - mkdir_parents_label(i->temp_path, 0700); - - base = dkr_pull_current_base_layer(i); - if (base) { - const char *base_path; - - base_path = strjoina(i->image_root, "/.dkr-", base); - r = btrfs_subvol_snapshot(base_path, i->temp_path, BTRFS_SNAPSHOT_FALLBACK_COPY|BTRFS_SNAPSHOT_QUOTA); - } else - r = btrfs_subvol_make(i->temp_path); - if (r < 0) - return log_error_errno(r, "Failed to make btrfs subvolume %s: %m", i->temp_path); - - (void) import_assign_pool_quota_and_warn(i->temp_path); - - j->disk_fd = import_fork_tar_x(i->temp_path, &i->tar_pid); - if (j->disk_fd < 0) - return j->disk_fd; - - return 0; -} - -static void dkr_pull_job_on_progress(PullJob *j) { - DkrPull *i; - - assert(j); - assert(j->userdata); - - i = j->userdata; - - dkr_pull_report_progress( - i, - j == i->images_job ? DKR_SEARCHING : - j == i->tags_job ? DKR_RESOLVING : - j == i->ancestry_job || j == i->json_job ? DKR_METADATA : - DKR_DOWNLOADING); -} - -static void dkr_pull_job_on_finished_v2(PullJob *j); - -static int dkr_pull_pull_layer_v2(DkrPull *i) { - _cleanup_free_ char *path = NULL; - const char *url, *layer = NULL; - int r; - - assert(i); - assert(!i->layer_job); - assert(!i->temp_path); - assert(!i->final_path); - - for (;;) { - layer = dkr_pull_current_layer(i); - if (!layer) - return 0; /* no more layers */ - - path = strjoin(i->image_root, "/.dkr-", layer, NULL); - if (!path) - return log_oom(); - - if (laccess(path, F_OK) < 0) { - if (errno == ENOENT) - break; - - return log_error_errno(errno, "Failed to check for container: %m"); - } - - log_info("Layer %s already exists, skipping.", layer); - - i->current_ancestry++; - - path = mfree(path); - } - - log_info("Pulling layer %s...", layer); - - i->final_path = path; - path = NULL; - - url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v2/", i->name, "/blobs/", layer); - r = pull_job_new(&i->layer_job, url, i->glue, i); - if (r < 0) - return log_error_errno(r, "Failed to allocate layer job: %m"); - - r = dkr_pull_add_bearer_token(i, i->layer_job); - if (r < 0) - return log_oom(); - - i->layer_job->on_finished = dkr_pull_job_on_finished_v2; - i->layer_job->on_open_disk = dkr_pull_job_on_open_disk; - i->layer_job->on_progress = dkr_pull_job_on_progress; - i->layer_job->grow_machine_directory = i->grow_machine_directory; - - r = pull_job_begin(i->layer_job); - if (r < 0) - return log_error_errno(r, "Failed to start layer job: %m"); - - return 0; -} - -static int dkr_pull_pull_layer(DkrPull *i) { - _cleanup_free_ char *path = NULL; - const char *url, *layer = NULL; - int r; - - assert(i); - assert(!i->layer_job); - assert(!i->temp_path); - assert(!i->final_path); - - for (;;) { - layer = dkr_pull_current_layer(i); - if (!layer) - return 0; /* no more layers */ - - path = strjoin(i->image_root, "/.dkr-", layer, NULL); - if (!path) - return log_oom(); - - if (laccess(path, F_OK) < 0) { - if (errno == ENOENT) - break; - - return log_error_errno(errno, "Failed to check for container: %m"); - } - - log_info("Layer %s already exists, skipping.", layer); - - i->current_ancestry++; - - path = mfree(path); - } - - log_info("Pulling layer %s...", layer); - - i->final_path = path; - path = NULL; - - url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", layer, "/layer"); - r = pull_job_new(&i->layer_job, url, i->glue, i); - if (r < 0) - return log_error_errno(r, "Failed to allocate layer job: %m"); - - r = dkr_pull_add_token(i, i->layer_job); - if (r < 0) - return log_oom(); - - i->layer_job->on_finished = dkr_pull_job_on_finished; - i->layer_job->on_open_disk = dkr_pull_job_on_open_disk; - i->layer_job->on_progress = dkr_pull_job_on_progress; - i->layer_job->grow_machine_directory = i->grow_machine_directory; - - r = pull_job_begin(i->layer_job); - if (r < 0) - return log_error_errno(r, "Failed to start layer job: %m"); - - return 0; -} - -static int dkr_pull_job_on_header(PullJob *j, const char *header, size_t sz) { - _cleanup_free_ char *registry = NULL; - char *token, *digest; - DkrPull *i; - int r; - - assert(j); - assert(j->userdata); - - i = j->userdata; - r = curl_header_strdup(header, sz, HEADER_TOKEN, &token); - if (r < 0) - return log_oom(); - if (r > 0) { - free(i->response_token); - i->response_token = token; - return 0; - } - - r = curl_header_strdup(header, sz, HEADER_DIGEST, &digest); - if (r < 0) - return log_oom(); - if (r > 0) { - free(i->response_digest); - i->response_digest = digest; - return 0; - } - - r = curl_header_strdup(header, sz, HEADER_REGISTRY, ®istry); - if (r < 0) - return log_oom(); - if (r > 0) { - char **l, **k; - - l = strv_split(registry, ","); - if (!l) - return log_oom(); - - STRV_FOREACH(k, l) { - if (!hostname_is_valid(*k, false)) { - log_error("Registry hostname is not valid."); - strv_free(l); - return -EBADMSG; - } - } - - strv_free(i->response_registries); - i->response_registries = l; - } - - return 0; -} - -static void dkr_pull_job_on_finished_v2(PullJob *j) { - DkrPull *i; - int r; - - assert(j); - assert(j->userdata); - - i = j->userdata; - if (j->error != 0) { - if (j == i->images_job) - log_error_errno(j->error, "Failed to retrieve images list. (Wrong index URL?)"); - else if (j == i->ancestry_job) - log_error_errno(j->error, "Failed to retrieve manifest."); - else if (j == i->json_job) - log_error_errno(j->error, "Failed to retrieve json data."); - else - log_error_errno(j->error, "Failed to retrieve layer data."); - - r = j->error; - goto finish; - } - - if (i->images_job == j) { - const char *url; - - assert(!i->tags_job); - assert(!i->ancestry_job); - assert(!i->json_job); - assert(!i->layer_job); - - if (strv_isempty(i->response_registries)) { - r = -EBADMSG; - log_error("Didn't get registry information."); - goto finish; - } - - log_info("Index lookup succeeded, directed to registry %s.", i->response_registries[0]); - dkr_pull_report_progress(i, DKR_RESOLVING); - - url = strjoina(i->index_protocol, "auth.", i->index_address, "/v2/token/?scope=repository:", - i->name, ":pull&service=registry.", i->index_address); - r = pull_job_new(&i->tags_job, url, i->glue, i); - if (r < 0) { - log_error_errno(r, "Failed to allocate tags job: %m"); - goto finish; - } - - i->tags_job->on_finished = dkr_pull_job_on_finished_v2; - i->tags_job->on_progress = dkr_pull_job_on_progress; - - r = pull_job_begin(i->tags_job); - if (r < 0) { - log_error_errno(r, "Failed to start tags job: %m"); - goto finish; - } - - } else if (i->tags_job == j) { - const char *url; - _cleanup_free_ char *buf; - _cleanup_json_variant_unref_ JsonVariant *doc = NULL; - JsonVariant *e = NULL; - - assert(!i->ancestry_job); - assert(!i->json_job); - assert(!i->layer_job); - - buf = strndup((const char *)j->payload, j->payload_size); - if (!buf) { - r = -ENOMEM; - log_oom(); - goto finish; - } - - r = json_parse(buf, &doc); - if (r < 0) { - log_error("Unable to parse bearer token\n%s", j->payload); - goto finish; - } - - e = json_variant_value(doc, "token"); - if (!e || e->type != JSON_VARIANT_STRING) { - r = -EBADMSG; - log_error("Invalid JSON format for Bearer token"); - goto finish; - } - - r = free_and_strdup(&i->response_token, json_variant_string(e)); - if (r < 0) { - log_oom(); - goto finish; - } - - url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v2/", i->name, "/manifests/", i->reference); - r = pull_job_new(&i->ancestry_job, url, i->glue, i); - if (r < 0) { - log_error_errno(r, "Failed to allocate ancestry job: %m"); - goto finish; - } - - r = dkr_pull_add_bearer_token(i, i->ancestry_job); - if (r < 0) - goto finish; - - i->ancestry_job->on_finished = dkr_pull_job_on_finished_v2; - i->ancestry_job->on_progress = dkr_pull_job_on_progress; - i->ancestry_job->on_header = dkr_pull_job_on_header; - - - r = pull_job_begin(i->ancestry_job); - if (r < 0) { - log_error_errno(r, "Failed to start ancestry job: %m"); - goto finish; - } - - } else if (i->ancestry_job == j) { - - _cleanup_json_variant_unref_ JsonVariant *doc = NULL, *compat = NULL; - JsonVariant *e = NULL; - _cleanup_strv_free_ char **ancestry = NULL; - size_t allocated = 0, size = 0; - char *path = NULL, **k = NULL; - - r = json_parse((const char *)j->payload, &doc); - if (r < 0) { - log_error("Invalid JSON Manifest"); - goto finish; - } - - e = json_variant_value(doc, "fsLayers"); - if (!e || e->type != JSON_VARIANT_ARRAY || e->size == 0) { - r = -EBADMSG; - goto finish; - } - - log_info("JSON manifest with schema v%"PRIi64" for %s parsed!", - json_variant_integer(json_variant_value(doc, "schemaVersion")), - json_variant_string(json_variant_value(doc, "name"))); - - for (unsigned z = 0; z < e->size; z++) { - JsonVariant *f = json_variant_element(e, z), *g = NULL; - const char *layer; - if (f->type != JSON_VARIANT_OBJECT) { - r = -EBADMSG; - goto finish; - } - - g = json_variant_value(f, "blobSum"); - - layer = json_variant_string(g); - if (!dkr_digest_is_valid(layer)) { - r = -EBADMSG; - goto finish; - } - - if (!GREEDY_REALLOC(ancestry, allocated, size + 2)) { - r = -ENOMEM; - log_oom(); - goto finish; - } - - ancestry[size] = strdup(layer); - if (!ancestry[size]) { - r = -ENOMEM; - log_oom(); - goto finish; - } - - ancestry[size+1] = NULL; - size += 1; - } - - e = json_variant_value(doc, "history"); - if (!e || e->type != JSON_VARIANT_ARRAY) { - r = -EBADMSG; - goto finish; - } - - e = json_variant_element(e, 0); - e = json_variant_value(e, "v1Compatibility"); - r = json_parse(json_variant_string(e), &compat); - if (r < 0) { - log_error("Invalid v1Compatibility JSON"); - goto finish; - } - - e = json_variant_value(compat, "id"); - - strv_free(i->ancestry); - i->ancestry = strv_reverse(strv_uniq(ancestry)); - i->n_ancestry = strv_length(i->ancestry); - i->current_ancestry = 0; - i->id = strdup(i->ancestry[i->n_ancestry - 1]); - if (!i->id) { - r = -ENOMEM; - log_oom(); - goto finish; - } - path = strjoin(i->image_root, "/.dkr-", json_variant_string(e), NULL); - if (!path) { - r = -ENOMEM; - log_oom(); - goto finish; - } - free(i->image_root); - i->image_root = path; - ancestry = NULL; - - log_info("Required layers:\n"); - STRV_FOREACH(k, i->ancestry) - log_info("\t%s", *k); - log_info("\nProvenance:\n\tImageID: %s\n\tDigest: %s", json_variant_string(e), i->response_digest); - - dkr_pull_report_progress(i, DKR_DOWNLOADING); - - r = dkr_pull_pull_layer_v2(i); - if (r < 0) - goto finish; - - } else if (i->layer_job == j) { - assert(i->temp_path); - assert(i->final_path); - - j->disk_fd = safe_close(j->disk_fd); - - if (i->tar_pid > 0) { - r = wait_for_terminate_and_warn("tar", i->tar_pid, true); - i->tar_pid = 0; - if (r < 0) - goto finish; - } - - r = aufs_resolve(i->temp_path); - if (r < 0) { - log_error_errno(r, "Failed to resolve aufs whiteouts: %m"); - goto finish; - } - - r = btrfs_subvol_set_read_only(i->temp_path, true); - if (r < 0) { - log_error_errno(r, "Failed to mark snapshot read-only: %m"); - goto finish; - } - - if (rename(i->temp_path, i->final_path) < 0) { - log_error_errno(errno, "Failed to rename snaphsot: %m"); - goto finish; - } - - log_info("Completed writing to layer %s.", i->final_path); - - i->layer_job = pull_job_unref(i->layer_job); - free(i->temp_path); - i->temp_path = NULL; - free(i->final_path); - i->final_path = NULL; - - i->current_ancestry ++; - r = dkr_pull_pull_layer_v2(i); - if (r < 0) - goto finish; - - } else if (i->json_job != j) - assert_not_reached("Got finished event for unknown curl object"); - - if (!dkr_pull_is_done(i)) - return; - - dkr_pull_report_progress(i, DKR_COPYING); - - r = dkr_pull_make_local_copy(i, DKR_PULL_V2); - if (r < 0) - goto finish; - - r = 0; - -finish: - if (i->on_finished) - i->on_finished(i, r, i->userdata); - else - sd_event_exit(i->event, r); - -} - -static void dkr_pull_job_on_finished(PullJob *j) { - DkrPull *i; - int r; - - assert(j); - assert(j->userdata); - - i = j->userdata; - if (j->error != 0) { - if (j == i->images_job) - log_error_errno(j->error, "Failed to retrieve images list. (Wrong index URL?)"); - else if (j == i->tags_job) - log_error_errno(j->error, "Failed to retrieve tags list."); - else if (j == i->ancestry_job) - log_error_errno(j->error, "Failed to retrieve ancestry list."); - else if (j == i->json_job) - log_error_errno(j->error, "Failed to retrieve json data."); - else - log_error_errno(j->error, "Failed to retrieve layer data."); - - r = j->error; - goto finish; - } - - if (i->images_job == j) { - const char *url; - - assert(!i->tags_job); - assert(!i->ancestry_job); - assert(!i->json_job); - assert(!i->layer_job); - - if (strv_isempty(i->response_registries)) { - r = -EBADMSG; - log_error("Didn't get registry information."); - goto finish; - } - - log_info("Index lookup succeeded, directed to registry %s.", i->response_registries[0]); - dkr_pull_report_progress(i, DKR_RESOLVING); - - url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/repositories/", i->name, "/tags/", i->reference); - r = pull_job_new(&i->tags_job, url, i->glue, i); - if (r < 0) { - log_error_errno(r, "Failed to allocate tags job: %m"); - goto finish; - } - - r = dkr_pull_add_token(i, i->tags_job); - if (r < 0) { - log_oom(); - goto finish; - } - - i->tags_job->on_finished = dkr_pull_job_on_finished; - i->tags_job->on_progress = dkr_pull_job_on_progress; - - r = pull_job_begin(i->tags_job); - if (r < 0) { - log_error_errno(r, "Failed to start tags job: %m"); - goto finish; - } - - } else if (i->tags_job == j) { - const char *url; - char *id = NULL; - - assert(!i->ancestry_job); - assert(!i->json_job); - assert(!i->layer_job); - - r = parse_id(j->payload, j->payload_size, &id); - if (r < 0) { - log_error_errno(r, "Failed to parse JSON id."); - goto finish; - } - - free(i->id); - i->id = id; - - log_info("Tag lookup succeeded, resolved to layer %s.", i->id); - dkr_pull_report_progress(i, DKR_METADATA); - - url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/ancestry"); - r = pull_job_new(&i->ancestry_job, url, i->glue, i); - if (r < 0) { - log_error_errno(r, "Failed to allocate ancestry job: %m"); - goto finish; - } - - r = dkr_pull_add_token(i, i->ancestry_job); - if (r < 0) { - log_oom(); - goto finish; - } - - i->ancestry_job->on_finished = dkr_pull_job_on_finished; - i->ancestry_job->on_progress = dkr_pull_job_on_progress; - - url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/json"); - r = pull_job_new(&i->json_job, url, i->glue, i); - if (r < 0) { - log_error_errno(r, "Failed to allocate json job: %m"); - goto finish; - } - - r = dkr_pull_add_token(i, i->json_job); - if (r < 0) { - log_oom(); - goto finish; - } - - i->json_job->on_finished = dkr_pull_job_on_finished; - i->json_job->on_progress = dkr_pull_job_on_progress; - - r = pull_job_begin(i->ancestry_job); - if (r < 0) { - log_error_errno(r, "Failed to start ancestry job: %m"); - goto finish; - } - - r = pull_job_begin(i->json_job); - if (r < 0) { - log_error_errno(r, "Failed to start json job: %m"); - goto finish; - } - - } else if (i->ancestry_job == j) { - char **ancestry = NULL, **k; - unsigned n; - - assert(!i->layer_job); - - r = parse_ancestry(j->payload, j->payload_size, &ancestry); - if (r < 0) { - log_error_errno(r, "Failed to parse JSON id."); - goto finish; - } - - n = strv_length(ancestry); - if (n <= 0 || !streq(ancestry[n-1], i->id)) { - log_error("Ancestry doesn't end in main layer."); - strv_free(ancestry); - r = -EBADMSG; - goto finish; - } - - log_info("Ancestor lookup succeeded, requires layers:\n"); - STRV_FOREACH(k, ancestry) - log_info("\t%s", *k); - - strv_free(i->ancestry); - i->ancestry = ancestry; - i->n_ancestry = n; - i->current_ancestry = 0; - - dkr_pull_report_progress(i, DKR_DOWNLOADING); - - r = dkr_pull_pull_layer(i); - if (r < 0) - goto finish; - - } else if (i->layer_job == j) { - assert(i->temp_path); - assert(i->final_path); - - j->disk_fd = safe_close(j->disk_fd); - - if (i->tar_pid > 0) { - r = wait_for_terminate_and_warn("tar", i->tar_pid, true); - i->tar_pid = 0; - if (r < 0) - goto finish; - } - - r = aufs_resolve(i->temp_path); - if (r < 0) { - log_error_errno(r, "Failed to resolve aufs whiteouts: %m"); - goto finish; - } - - r = btrfs_subvol_set_read_only(i->temp_path, true); - if (r < 0) { - log_error_errno(r, "Failed to mark snapshot read-only: %m"); - goto finish; - } - - if (rename(i->temp_path, i->final_path) < 0) { - log_error_errno(errno, "Failed to rename snaphsot: %m"); - goto finish; - } - - log_info("Completed writing to layer %s.", i->final_path); - - i->layer_job = pull_job_unref(i->layer_job); - i->temp_path = mfree(i->temp_path); - i->final_path = mfree(i->final_path); - - i->current_ancestry ++; - r = dkr_pull_pull_layer(i); - if (r < 0) - goto finish; - - } else if (i->json_job != j) - assert_not_reached("Got finished event for unknown curl object"); - - if (!dkr_pull_is_done(i)) - return; - - dkr_pull_report_progress(i, DKR_COPYING); - - r = dkr_pull_make_local_copy(i, DKR_PULL_V1); - if (r < 0) - goto finish; - - r = 0; -finish: - if (i->on_finished) - i->on_finished(i, r, i->userdata); - else - sd_event_exit(i->event, r); -} - -static int get_protocol_address(char **protocol, char **address, const char *url) { - const char *sep, *dot; - _cleanup_free_ char *a = NULL, *p = NULL; - - sep = strstr(url, "://"); - if (!sep) - return -EINVAL; - - dot = strrchr(url, '.'); - if (!dot) - return -EINVAL; - dot--; - - p = strndup(url, (sep - url) + 3); - if (!p) - return log_oom(); - - while (dot > (sep + 3) && *dot != '.') - dot--; - - a = strdup(dot + 1); - if (!a) - return log_oom(); - - *address = a; - *protocol = p; - a = p = NULL; - - return 0; -} - -int dkr_pull_start(DkrPull *i, const char *name, const char *reference, const char *local, bool force_local, DkrPullVersion version) { - const char *url; - int r; - - assert(i); - - if (!dkr_name_is_valid(name)) - return -EINVAL; - - if (reference && !dkr_ref_is_valid(reference)) - return -EINVAL; - - if (local && !machine_name_is_valid(local)) - return -EINVAL; - - if (i->images_job) - return -EBUSY; - - if (!reference) - reference = "latest"; - - free(i->index_protocol); - free(i->index_address); - r = get_protocol_address(&i->index_protocol, &i->index_address, i->index_url); - if (r < 0) - return r; - - r = free_and_strdup(&i->local, local); - if (r < 0) - return r; - i->force_local = force_local; - - r = free_and_strdup(&i->name, name); - if (r < 0) - return r; - r = free_and_strdup(&i->reference, reference); - if (r < 0) - return r; - - url = strjoina(i->index_url, "/v1/repositories/", name, "/images"); - - r = pull_job_new(&i->images_job, url, i->glue, i); - if (r < 0) - return r; - - r = dkr_pull_add_token(i, i->images_job); - if (r < 0) - return r; - - if (version == DKR_PULL_V1) - i->images_job->on_finished = dkr_pull_job_on_finished; - else - i->images_job->on_finished = dkr_pull_job_on_finished_v2; - - i->images_job->on_header = dkr_pull_job_on_header; - i->images_job->on_progress = dkr_pull_job_on_progress; - - return pull_job_begin(i->images_job); -} diff --git a/src/import/pull-dkr.h b/src/import/pull-dkr.h deleted file mode 100644 index a95d91205b..0000000000 --- a/src/import/pull-dkr.h +++ /dev/null @@ -1,38 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#pragma once - -#include "sd-event.h" - -#include "util.h" - -typedef enum { DKR_PULL_V1, DKR_PULL_V2 } DkrPullVersion; -typedef struct DkrPull DkrPull; - -typedef void (*DkrPullFinished)(DkrPull *pull, int error, void *userdata); - -int dkr_pull_new(DkrPull **pull, sd_event *event, const char *index_url, const char *image_root, DkrPullFinished on_finished, void *userdata); -DkrPull* dkr_pull_unref(DkrPull *pull); - -DEFINE_TRIVIAL_CLEANUP_FUNC(DkrPull*, dkr_pull_unref); - -int dkr_pull_start(DkrPull *pull, const char *name, const char *tag, const char *local, bool force_local, DkrPullVersion version); diff --git a/src/import/pull.c b/src/import/pull.c index fc93228a0b..e0631bdeaf 100644 --- a/src/import/pull.c +++ b/src/import/pull.c @@ -28,7 +28,6 @@ #include "import-util.h" #include "machine-image.h" #include "parse-util.h" -#include "pull-dkr.h" #include "pull-raw.h" #include "pull-tar.h" #include "signal-util.h" @@ -39,7 +38,6 @@ static bool arg_force = false; static const char *arg_image_root = "/var/lib/machines"; static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE; -static const char* arg_dkr_index_url = DEFAULT_DKR_INDEX_URL; static bool arg_settings = true; static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { @@ -220,114 +218,6 @@ static int pull_raw(int argc, char *argv[], void *userdata) { return -r; } -static void on_dkr_finished(DkrPull *pull, int error, void *userdata) { - sd_event *event = userdata; - assert(pull); - - if (error == 0) - log_info("Operation completed successfully."); - - sd_event_exit(event, abs(error)); -} - -static int pull_dkr(int argc, char *argv[], void *userdata) { - _cleanup_(dkr_pull_unrefp) DkrPull *pull = NULL; - _cleanup_(sd_event_unrefp) sd_event *event = NULL; - const char *name, *reference, *local, *digest; - int r; - - if (!arg_dkr_index_url) { - log_error("Please specify an index URL with --dkr-index-url="); - return -EINVAL; - } - - if (arg_verify != IMPORT_VERIFY_NO) { - log_error("Pulls from dkr do not support image verification, please pass --verify=no."); - return -EINVAL; - } - - digest = strchr(argv[1], '@'); - if (digest) { - reference = digest + 1; - name = strndupa(argv[1], digest - argv[1]); - } else { - reference = strchr(argv[1], ':'); - if (reference) { - name = strndupa(argv[1], reference - argv[1]); - reference++; - } else { - name = argv[1]; - reference = "latest"; - } - } - - if (!dkr_name_is_valid(name)) { - log_error("Remote name '%s' is not valid.", name); - return -EINVAL; - } - - if (!dkr_ref_is_valid(reference)) { - log_error("Tag name '%s' is not valid.", reference); - return -EINVAL; - } - - if (argc >= 3) - local = argv[2]; - else { - local = strchr(name, '/'); - if (local) - local++; - else - local = name; - } - - if (isempty(local) || streq(local, "-")) - local = NULL; - - if (local) { - if (!machine_name_is_valid(local)) { - log_error("Local image name '%s' is not valid.", local); - return -EINVAL; - } - - if (!arg_force) { - r = image_find(local, NULL); - if (r < 0) - return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); - else if (r > 0) { - log_error_errno(EEXIST, "Image '%s' already exists.", local); - return -EEXIST; - } - } - - log_info("Pulling '%s' with reference '%s', saving as '%s'.", name, reference, local); - } else - log_info("Pulling '%s' with reference '%s'.", name, reference); - - r = sd_event_default(&event); - if (r < 0) - return log_error_errno(r, "Failed to allocate event loop: %m"); - - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); - (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); - (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); - - r = dkr_pull_new(&pull, event, arg_dkr_index_url, arg_image_root, on_dkr_finished, event); - if (r < 0) - return log_error_errno(r, "Failed to allocate puller: %m"); - - r = dkr_pull_start(pull, name, reference, local, arg_force, DKR_PULL_V2); - if (r < 0) - return log_error_errno(r, "Failed to pull image: %m"); - - r = sd_event_loop(event); - if (r < 0) - return log_error_errno(r, "Failed to run event loop: %m"); - - log_info("Exiting."); - return -r; -} - static int help(int argc, char *argv[], void *userdata) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" @@ -338,12 +228,10 @@ static int help(int argc, char *argv[], void *userdata) { " --verify=MODE Verify downloaded image, one of: 'no',\n" " 'checksum', 'signature'\n" " --settings=BOOL Download settings file with image\n" - " --image-root=PATH Image root directory\n" - " --dkr-index-url=URL Specify index URL to use for downloads\n\n" + " --image-root=PATH Image root directory\n\n" "Commands:\n" " tar URL [NAME] Download a TAR image\n" - " raw URL [NAME] Download a RAW image\n" - " dkr REMOTE [NAME] Download a DKR image\n", + " raw URL [NAME] Download a RAW image\n", program_invocation_short_name); return 0; @@ -354,7 +242,6 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_FORCE, - ARG_DKR_INDEX_URL, ARG_IMAGE_ROOT, ARG_VERIFY, ARG_SETTINGS, @@ -364,7 +251,6 @@ static int parse_argv(int argc, char *argv[]) { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "force", no_argument, NULL, ARG_FORCE }, - { "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL }, { "image-root", required_argument, NULL, ARG_IMAGE_ROOT }, { "verify", required_argument, NULL, ARG_VERIFY }, { "settings", required_argument, NULL, ARG_SETTINGS }, @@ -390,15 +276,6 @@ static int parse_argv(int argc, char *argv[]) { arg_force = true; break; - case ARG_DKR_INDEX_URL: - if (!http_url_is_valid(optarg)) { - log_error("Index URL is not valid: %s", optarg); - return -EINVAL; - } - - arg_dkr_index_url = optarg; - break; - case ARG_IMAGE_ROOT: arg_image_root = optarg; break; @@ -436,7 +313,6 @@ static int pull_main(int argc, char *argv[]) { { "help", VERB_ANY, VERB_ANY, 0, help }, { "tar", 2, 3, 0, pull_tar }, { "raw", 2, 3, 0, pull_raw }, - { "dkr", 2, 3, 0, pull_dkr }, {} }; diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 0a01bd3e20..685bbafdf1 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -78,7 +78,6 @@ static unsigned arg_lines = 10; 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 const char *arg_uid = NULL; static char **arg_setenv = NULL; @@ -2166,78 +2165,6 @@ static int pull_raw(int argc, char *argv[], void *userdata) { return transfer_image_common(bus, m); } -static int pull_dkr(int argc, char *argv[], void *userdata) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; - const char *local, *remote, *tag; - sd_bus *bus = userdata; - int r; - - if (arg_verify != IMPORT_VERIFY_NO) { - log_error("Imports from DKR do not support image verification, please pass --verify=no."); - return -EINVAL; - } - - remote = argv[1]; - tag = strchr(remote, ':'); - if (tag) { - remote = strndupa(remote, tag - remote); - tag++; - } - - if (!dkr_name_is_valid(remote)) { - log_error("DKR name '%s' is invalid.", remote); - return -EINVAL; - } - if (tag && !dkr_tag_is_valid(tag)) { - log_error("DKR tag '%s' is invalid.", remote); - return -EINVAL; - } - - if (argc >= 3) - local = argv[2]; - else { - local = strchr(remote, '/'); - if (local) - local++; - else - local = remote; - } - - if (isempty(local) || streq(local, "-")) - local = NULL; - - if (local) { - if (!machine_name_is_valid(local)) { - log_error("Local name %s is not a suitable machine name.", local); - return -EINVAL; - } - } - - r = sd_bus_message_new_method_call( - bus, - &m, - "org.freedesktop.import1", - "/org/freedesktop/import1", - "org.freedesktop.import1.Manager", - "PullDkr"); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append( - m, - "sssssb", - arg_dkr_index_url, - remote, - tag, - local, - import_verify_to_string(arg_verify), - arg_force); - if (r < 0) - return bus_log_create_error(r); - - return transfer_image_common(bus, m); -} - typedef struct TransferInfo { uint32_t id; const char *type; @@ -2452,9 +2379,7 @@ static int help(int argc, char *argv[], void *userdata) { " json-pretty, json-sse, cat)\n" " --verify=MODE Verification mode for downloaded images (no,\n" " checksum, signature)\n" - " --force Download image even if already exists\n" - " --dkr-index-url=URL Specify the index URL to use for DKR image\n" - " downloads\n\n" + " --force Download image even if already exists\n\n" "Machine Commands:\n" " list List running VMs and containers\n" " status NAME... Show VM/container details\n" @@ -2486,7 +2411,6 @@ static int help(int argc, char *argv[], void *userdata) { "Image Transfer Commands:\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 NAME [FILE] Export a TAR container image locally\n" @@ -2510,7 +2434,6 @@ static int parse_argv(int argc, char *argv[]) { ARG_NO_ASK_PASSWORD, ARG_VERIFY, ARG_FORCE, - ARG_DKR_INDEX_URL, ARG_FORMAT, ARG_UID, ARG_SETENV, @@ -2536,7 +2459,6 @@ static int parse_argv(int argc, char *argv[]) { { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, { "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 }, { "uid", required_argument, NULL, ARG_UID }, { "setenv", required_argument, NULL, ARG_SETENV }, @@ -2650,15 +2572,6 @@ static int parse_argv(int argc, char *argv[]) { arg_force = true; break; - case ARG_DKR_INDEX_URL: - if (!http_url_is_valid(optarg)) { - log_error("Index URL is invalid: %s", optarg); - return -EINVAL; - } - - arg_dkr_index_url = optarg; - break; - case ARG_FORMAT: if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2")) { log_error("Unknown format: %s", optarg); @@ -2725,7 +2638,6 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) { { "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 }, { "list-transfers", VERB_ANY, 1, 0, list_transfers }, { "cancel-transfer", 2, VERB_ANY, 0, cancel_transfer }, { "set-limit", 2, 3, 0, set_limit }, diff --git a/src/shared/import-util.c b/src/shared/import-util.c index 29ce732b56..ad400e8693 100644 --- a/src/shared/import-util.c +++ b/src/shared/import-util.c @@ -160,58 +160,6 @@ int raw_strip_suffixes(const char *p, char **ret) { return 0; } -bool dkr_digest_is_valid(const char *digest) { - /* 7 chars for prefix, 64 chars for the digest itself */ - if (strlen(digest) != 71) - return false; - - return startswith(digest, "sha256:") && in_charset(digest + 7, "0123456789abcdef"); -} - -bool dkr_ref_is_valid(const char *ref) { - const char *colon; - - if (isempty(ref)) - return false; - - colon = strchr(ref, ':'); - if (!colon) - return filename_is_valid(ref); - - return dkr_digest_is_valid(ref); -} - -bool dkr_name_is_valid(const char *name) { - const char *slash, *p; - - if (isempty(name)) - return false; - - slash = strchr(name, '/'); - if (!slash) - return false; - - if (!filename_is_valid(slash + 1)) - return false; - - p = strndupa(name, slash - name); - if (!filename_is_valid(p)) - return false; - - return true; -} - -bool dkr_id_is_valid(const char *id) { - - if (!filename_is_valid(id)) - return false; - - if (!in_charset(id, "0123456789abcdef")) - return false; - - return true; -} - int import_assign_pool_quota_and_warn(const char *path) { int r; diff --git a/src/shared/import-util.h b/src/shared/import-util.h index 9120a5119f..4bfa2d9aae 100644 --- a/src/shared/import-util.h +++ b/src/shared/import-util.h @@ -42,10 +42,4 @@ ImportVerify import_verify_from_string(const char *s) _pure_; int tar_strip_suffixes(const char *name, char **ret); int raw_strip_suffixes(const char *name, char **ret); -bool dkr_name_is_valid(const char *name); -bool dkr_id_is_valid(const char *id); -bool dkr_ref_is_valid(const char *ref); -bool dkr_digest_is_valid(const char *digest); -#define dkr_tag_is_valid(tag) filename_is_valid(tag) - int import_assign_pool_quota_and_warn(const char *path); |