X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fimport%2Fimport-dkr.c;h=a4ff6f43f0f45c4b13451bb35261fe9ef737ca82;hb=4d858e7d9f39038713f760d7acc64acf7bba2aa7;hp=cebec28144f4851278baa5c1082af636847f588a;hpb=ff2670ad11a1a29d483b7a246c95b159ddc1137c;p=elogind.git diff --git a/src/import/import-dkr.c b/src/import/import-dkr.c index cebec2814..a4ff6f43f 100644 --- a/src/import/import-dkr.c +++ b/src/import/import-dkr.c @@ -22,18 +22,27 @@ #include #include -#include "set.h" +#include "sd-daemon.h" #include "json.h" #include "strv.h" #include "btrfs-util.h" #include "utf8.h" #include "mkdir.h" +#include "import-util.h" #include "curl-util.h" #include "aufs-util.h" -#include "import-util.h" #include "import-job.h" +#include "import-common.h" #include "import-dkr.h" +typedef enum DkrProgress { + DKR_SEARCHING, + DKR_RESOLVING, + DKR_METADATA, + DKR_DOWNLOADING, + DKR_COPYING, +} DkrProgress; + struct DkrImport { sd_event *event; CurlGlue *glue; @@ -55,6 +64,7 @@ struct DkrImport { char **response_registries; char **ancestry; + unsigned n_ancestry; unsigned current_ancestry; DkrImportFinished on_finished; @@ -175,6 +185,53 @@ int dkr_import_new( return 0; } +static void dkr_import_report_progress(DkrImport *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 = {}; @@ -400,7 +457,6 @@ static int dkr_import_make_local_copy(DkrImport *i) { } static int dkr_import_job_on_open_disk(ImportJob *j) { - _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; const char *base; DkrImport *i; int r; @@ -431,56 +487,27 @@ static int dkr_import_job_on_open_disk(ImportJob *j) { if (r < 0) return log_error_errno(r, "Failed to make btrfs subvolume %s: %m", i->temp_path); - if (pipe2(pipefd, O_CLOEXEC) < 0) - return log_error_errno(errno, "Failed to create pipe for tar: %m"); - - i->tar_pid = fork(); - if (i->tar_pid < 0) - return log_error_errno(errno, "Failed to fork off tar: %m"); - if (i->tar_pid == 0) { - int null_fd; - - /* Child */ - - reset_all_signal_handlers(); - reset_signal_mask(); - assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); - - pipefd[1] = safe_close(pipefd[1]); + j->disk_fd = import_fork_tar(i->temp_path, &i->tar_pid); + if (j->disk_fd < 0) + return j->disk_fd; - if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); - _exit(EXIT_FAILURE); - } - - if (pipefd[0] != STDIN_FILENO) - safe_close(pipefd[0]); - - null_fd = open("/dev/null", O_WRONLY|O_NOCTTY); - if (null_fd < 0) { - log_error_errno(errno, "Failed to open /dev/null: %m"); - _exit(EXIT_FAILURE); - } - - if (dup2(null_fd, STDOUT_FILENO) != STDOUT_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); - _exit(EXIT_FAILURE); - } - - if (null_fd != STDOUT_FILENO) - safe_close(null_fd); + return 0; +} - execlp("tar", "tar", "--numeric-owner", "-C", i->temp_path, "-px", NULL); - log_error_errno(errno, "Failed to execute tar: %m"); - _exit(EXIT_FAILURE); - } +static void dkr_import_job_on_progress(ImportJob *j) { + DkrImport *i; - pipefd[0] = safe_close(pipefd[0]); + assert(j); + assert(j->userdata); - j->disk_fd = pipefd[1]; - pipefd[1] = -1; + i = j->userdata; - return 0; + dkr_import_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 int dkr_import_pull_layer(DkrImport *i) { @@ -533,6 +560,7 @@ static int dkr_import_pull_layer(DkrImport *i) { i->layer_job->on_finished = dkr_import_job_on_finished; i->layer_job->on_open_disk = dkr_import_job_on_open_disk; + i->layer_job->on_progress = dkr_import_job_on_progress; r = import_job_begin(i->layer_job); if (r < 0) @@ -580,6 +608,7 @@ static void dkr_import_job_on_finished(ImportJob *j) { } log_info("Index lookup succeeded, directed to registry %s.", i->response_registries[0]); + dkr_import_report_progress(i, DKR_RESOLVING); url = strappenda(PROTOCOL_PREFIX, i->response_registries[0], "/v1/repositories/", i->name, "/tags/", i->tag); r = import_job_new(&i->tags_job, url, i->glue, i); @@ -595,6 +624,7 @@ static void dkr_import_job_on_finished(ImportJob *j) { } i->tags_job->on_finished = dkr_import_job_on_finished; + i->tags_job->on_progress = dkr_import_job_on_progress; r = import_job_begin(i->tags_job); if (r < 0) { @@ -620,6 +650,7 @@ static void dkr_import_job_on_finished(ImportJob *j) { i->id = id; log_info("Tag lookup succeeded, resolved to layer %s.", i->id); + dkr_import_report_progress(i, DKR_METADATA); url = strappenda(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/ancestry"); r = import_job_new(&i->ancestry_job, url, i->glue, i); @@ -635,6 +666,7 @@ static void dkr_import_job_on_finished(ImportJob *j) { } i->ancestry_job->on_finished = dkr_import_job_on_finished; + i->ancestry_job->on_progress = dkr_import_job_on_progress; url = strappenda(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/json"); r = import_job_new(&i->json_job, url, i->glue, i); @@ -650,6 +682,7 @@ static void dkr_import_job_on_finished(ImportJob *j) { } i->json_job->on_finished = dkr_import_job_on_finished; + i->json_job->on_progress = dkr_import_job_on_progress; r = import_job_begin(i->ancestry_job); if (r < 0) { @@ -689,8 +722,11 @@ static void dkr_import_job_on_finished(ImportJob *j) { strv_free(i->ancestry); i->ancestry = ancestry; - + i->n_ancestry = n; i->current_ancestry = 0; + + dkr_import_report_progress(i, DKR_DOWNLOADING); + r = dkr_import_pull_layer(i); if (r < 0) goto finish; @@ -716,7 +752,7 @@ static void dkr_import_job_on_finished(ImportJob *j) { r = btrfs_subvol_set_read_only(i->temp_path, true); if (r < 0) { - log_error_errno(r, "Failed to mark snapshort read-only: %m"); + log_error_errno(r, "Failed to mark snapshot read-only: %m"); goto finish; } @@ -744,6 +780,8 @@ static void dkr_import_job_on_finished(ImportJob *j) { if (!dkr_import_is_done(i)) return; + dkr_import_report_progress(i, DKR_COPYING); + r = dkr_import_make_local_copy(i); if (r < 0) goto finish; @@ -847,37 +885,7 @@ int dkr_import_pull(DkrImport *i, const char *name, const char *tag, const char i->images_job->on_finished = dkr_import_job_on_finished; i->images_job->on_header = dkr_import_job_on_header; + i->images_job->on_progress = dkr_import_job_on_progress; return import_job_begin(i->images_job); } - -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; -}