提交 c3371e2e 编写于 作者: W WangFengTu

resume pulling layers

Signed-off-by: NWangFengTu <wangfengtu@huawei.com>
上级 b815e33d
......@@ -689,12 +689,12 @@ static int progress(void *p, double dltotal, double dlnow, double ultotal, doubl
}
int http_request_file(pull_descriptor *desc, const char *url, const char **custom_headers, char *file,
resp_data_type type)
resp_data_type type, CURLcode *errcode)
{
int ret = 0;
struct http_get_options *options = NULL;
if (desc == NULL || url == NULL || file == NULL) {
if (desc == NULL || url == NULL || file == NULL || errcode == NULL) {
ERROR("Invalid NULL pointer");
return -1;
}
......@@ -711,6 +711,9 @@ int http_request_file(pull_descriptor *desc, const char *url, const char **custo
options->with_head = 1;
}
options->with_body = 1;
if (type == RESUME_BODY) {
options->resume = true;
}
options->outputtype = HTTP_REQUEST_FILE;
options->output = file;
options->show_progress = 1;
......@@ -733,6 +736,7 @@ int http_request_file(pull_descriptor *desc, const char *url, const char **custo
}
out:
*errcode = options->errcode;
free_http_get_options(options);
options = NULL;
......
......@@ -15,6 +15,7 @@
#ifndef DAEMON_MODULES_IMAGE_OCI_REGISTRY_HTTP_REQUEST_H
#define DAEMON_MODULES_IMAGE_OCI_REGISTRY_HTTP_REQUEST_H
#include <curl/curl.h>
#include "registry_type.h"
#ifdef __cplusplus
......@@ -25,12 +26,13 @@ typedef enum {
HEAD_ONLY = 0,
BODY_ONLY = 1,
HEAD_BODY = 2,
RESUME_BODY = 3,
} resp_data_type;
int http_request_buf(pull_descriptor *desc, const char *url, const char **custom_headers, char **output,
resp_data_type type);
int http_request_file(pull_descriptor *desc, const char *url, const char **custom_headers, char *file,
resp_data_type type);
resp_data_type type, CURLcode *errcode);
#ifdef __cplusplus
}
......
......@@ -400,7 +400,7 @@ out:
}
static int registry_request(pull_descriptor *desc, char *path, char **custom_headers, char *file, char **output_buffer,
resp_data_type type)
resp_data_type type, CURLcode *errcode)
{
int ret = 0;
int sret = 0;
......@@ -448,7 +448,7 @@ static int registry_request(pull_descriptor *desc, char *path, char **custom_hea
}
DEBUG("resp=%s", *output_buffer);
} else {
ret = http_request_file(desc, url, (const char **)headers, file, type);
ret = http_request_file(desc, url, (const char **)headers, file, type, errcode);
if (ret != 0) {
ERROR("http request file failed, url: %s", url);
goto out;
......@@ -647,6 +647,7 @@ static int fetch_manifest_list(pull_descriptor *desc, char *file, char **content
char *http_head = NULL;
char **custom_headers = NULL;
char path[PATH_MAX] = { 0 };
CURLcode errcode = CURLE_OK;
if (desc == NULL || content_type == NULL || digest == NULL) {
ERROR("Invalid NULL pointer");
......@@ -666,7 +667,7 @@ static int fetch_manifest_list(pull_descriptor *desc, char *file, char **content
goto out;
}
ret = registry_request(desc, path, custom_headers, file, NULL, HEAD_BODY);
ret = registry_request(desc, path, custom_headers, file, NULL, HEAD_BODY, &errcode);
if (ret != 0) {
ERROR("registry: Get %s failed", path);
goto out;
......@@ -694,6 +695,23 @@ out:
return ret;
}
static void try_log_resp_body(char *path, char *file)
{
char *body = NULL;
size_t size = 0;
body = util_read_text_file(file);
if (body == NULL) {
return;
}
size = strlen(body);
if (size < LXC_LOG_BUFFER_SIZE) { // Max length not exactly, just avoid too long.
ERROR("Get %s response message body: %s", path, body);
}
return;
}
static int fetch_data(pull_descriptor *desc, char *path, char *file, char *content_type, char *digest)
{
int ret = 0;
......@@ -701,6 +719,9 @@ static int fetch_data(pull_descriptor *desc, char *path, char *file, char *conte
char accept[MAX_ELEMENT_SIZE] = { 0 };
char **custom_headers = NULL;
int retry_times = RETRY_TIMES;
resp_data_type type = BODY_ONLY;
bool forbid_resume = false;
CURLcode errcode = CURLE_OK;
// digest can be NULL
if (desc == NULL || path == NULL || file == NULL || content_type == NULL) {
......@@ -723,12 +744,20 @@ static int fetch_data(pull_descriptor *desc, char *path, char *file, char *conte
while (retry_times > 0) {
retry_times--;
ret = registry_request(desc, path, custom_headers, file, NULL, BODY_ONLY);
ret = registry_request(desc, path, custom_headers, file, NULL, type, &errcode);
if (ret != 0) {
if (errcode == CURLE_RANGE_ERROR) {
forbid_resume = true;
type = BODY_ONLY;
}
if (!forbid_resume) {
type = RESUME_BODY;
}
if (retry_times > 0) {
continue;
}
ERROR("registry: Get %s failed", path);
isulad_try_set_error_message("Get %s failed", path);
desc->cancel = true;
goto out;
}
......@@ -736,11 +765,15 @@ static int fetch_data(pull_descriptor *desc, char *path, char *file, char *conte
// If content is signatured, digest is for payload but not fetched data
if (strcmp(content_type, DOCKER_MANIFEST_SCHEMA1_PRETTYJWS) && digest != NULL) {
if (!sha256_valid_digest_file(file, digest)) {
type = BODY_ONLY;
(void)util_path_remove(file); // remove the invalid file to avoid resume pulling
if (retry_times > 0) {
continue;
}
ret = -1;
try_log_resp_body(path, file);
ERROR("data from %s does not have digest %s", path, digest);
isulad_try_set_error_message("Invalid data fetched for %s, this mainly caused by server error", path);
desc->cancel = true;
goto out;
}
......@@ -1112,6 +1145,7 @@ int login_to_registry(pull_descriptor *desc)
int sret = 0;
char *resp_buffer = NULL;
char path[PATH_MAX] = { 0 };
CURLcode errcode = CURLE_OK;
if (desc == NULL) {
ERROR("Invalid NULL pointer");
......@@ -1125,7 +1159,7 @@ int login_to_registry(pull_descriptor *desc)
goto out;
}
ret = registry_request(desc, path, NULL, NULL, &resp_buffer, HEAD_BODY);
ret = registry_request(desc, path, NULL, NULL, &resp_buffer, HEAD_BODY, &errcode);
if (ret != 0) {
ERROR("registry: Get %s failed, resp: %s", path, resp_buffer);
isulad_try_set_error_message("login to registry for %s failed", desc->host);
......
......@@ -13,6 +13,8 @@
* Description: provide container http function
******************************************************************************/
#include <curl/curl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
......@@ -296,14 +298,29 @@ static void curl_getinfo_on_condition(long *response_code, CURL *curl_handle, ch
curl_easy_getinfo(curl_handle, CURLINFO_REDIRECT_URL, tmp);
}
static int ensure_path_file(char **rpath, const struct http_get_options *options, FILE **pagefile)
static int ensure_path_file(char **rpath, void *output, bool resume, FILE **pagefile, size_t *fsize)
{
if (util_ensure_path(rpath, options->output)) {
const char *mode = "w+";
struct stat st;
if (util_ensure_path(rpath, output)) {
return -1;
}
*pagefile = util_fopen(*rpath, "w+");
if (resume) {
mode = "a";
if (stat(*rpath, &st) < 0) {
ERROR("stat %s failed: %s", *rpath, strerror(errno));
return -1;
}
*fsize = (size_t)st.st_size;
} else {
*fsize = 0;
}
*pagefile = util_fopen(*rpath, mode);
if (*pagefile == NULL) {
ERROR("Failed to open file %s\n", (const char *)options->output);
ERROR("Failed to open file %s\n", (const char *)output);
return -1;
}
return 0;
......@@ -334,6 +351,7 @@ int http_request(const char *url, struct http_get_options *options, long *respon
bool file_args;
char *redir_url = NULL;
char *tmp = NULL;
size_t fsize = 0;
if (recursive_len + 1 >= MAX_REDIRCT_NUMS) {
ERROR("reach the max redirect num");
......@@ -371,9 +389,14 @@ int http_request(const char *url, struct http_get_options *options, long *respon
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, fwrite_buffer);
} else if (file_args) {
/* open the file */
if (ensure_path_file(&rpath, options, &pagefile) == -1) {
if (ensure_path_file(&rpath, options->output, options->resume, &pagefile, &fsize) != 0) {
ret = -1;
goto out;
}
if (options->resume) {
curl_easy_setopt(curl_handle, CURLOPT_RESUME_FROM_LARGE, (curl_off_t)fsize);
}
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, pagefile);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, fwrite_file);
} else {
......
......@@ -71,6 +71,7 @@ struct http_get_options {
char *errmsg;
int errcode;
bool resume;
void *progressinfo;
progress_info_func progress_info_op;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册