From 11c7507eeddcddf142845fd3d11704e875cef85e Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Wed, 22 Jun 2016 16:53:22 +0800 Subject: [PATCH] support file destination volume If a volume source contains only one file named ".hyper_file_volume_data_do_not_create_on_your_own", bind mount it as a file to the specified mountpoint inside container's namespace, rather than mounting its parent directory. The special name .hyper_file_volume_data_do_not_create_on_your_own is agreed upon with client which would save a file as this name if it wants to bind mount a single file rather than a directory. Signed-off-by: Peng Tao --- src/container.c | 72 ++++++++++++++++++++++++++++++++++++++++++------- src/hyper.h | 1 + src/util.c | 20 ++++++++++++++ 3 files changed, 84 insertions(+), 9 deletions(-) diff --git a/src/container.c b/src/container.c index 6ef2ad1..1d780af 100644 --- a/src/container.c +++ b/src/container.c @@ -49,6 +49,42 @@ static int container_populate_volume(char *src, char *dest) return hyper_copy_dir(src, dest); } +const char *INIT_VOLUME_FILENAME = ".hyper_file_volume_data_do_not_create_on_your_own"; + +static int container_check_file_volume(char *hyper_path, const char **filename) +{ + struct dirent **list; + struct stat stbuf; + int i, num, found = 0; + char path[PATH_MAX]; + + *filename = NULL; + num = scandir(hyper_path, &list, NULL, NULL); + if (num < 0) { + perror("scan path failed"); + return -1; + } else if (num != 3) { + fprintf(stdout, "%s has %d files/dirs\n", hyper_path, num - 2); + return 0; + } + + sprintf(path, "%s/%s", hyper_path, INIT_VOLUME_FILENAME); + for (i = 0; i < num; i++) { + if (strcmp(list[i]->d_name, ".") != 0 && + strcmp(list[i]->d_name, "..") != 0 && + strcmp(list[i]->d_name, INIT_VOLUME_FILENAME) == 0 && + stat(path, &stbuf) == 0 && S_ISREG(stbuf.st_mode)) { + found++; + } + free(list[i]); + } + free(list); + + fprintf(stdout, "%s %s a file volume\n", hyper_path, found > 0?"is":"is not"); + *filename = found > 0 ? INIT_VOLUME_FILENAME : NULL; + return 0; +} + static int container_setup_volume(struct hyper_container *container) { int i; @@ -59,6 +95,7 @@ static int container_setup_volume(struct hyper_container *container) char volume[512]; char mountpoint[512]; char *options = NULL; + const char *filevolume = NULL; vol = &container->vols[i]; if (vol->scsiaddr) @@ -66,13 +103,12 @@ static int container_setup_volume(struct hyper_container *container) sprintf(dev, "/dev/%s", vol->device); sprintf(path, "/tmp/%s", vol->mountpoint); - sprintf(volume, "/%s/_data", path); sprintf(mountpoint, "./%s", vol->mountpoint); fprintf(stdout, "mount %s to %s, tmp path %s\n", dev, vol->mountpoint, path); - if (hyper_mkdir(path) < 0 || hyper_mkdir(mountpoint) < 0) { + if (hyper_mkdir(path) < 0) { perror("create volume dir failed"); return -1; } @@ -85,17 +121,35 @@ static int container_setup_volume(struct hyper_container *container) return -1; } - if (vol->docker) { - if (container->initialize && - (container_populate_volume(mountpoint, volume) < 0)) { - fprintf(stderr, "fail to populate volume %s\n", mountpoint); - return -1; - } - } else if (hyper_mkdir(volume) < 0) { + sprintf(volume, "/%s/_data", path); + if (hyper_mkdir(volume) < 0) { fprintf(stderr, "fail to create directroy %s\n", volume); return -1; } + if (container_check_file_volume(volume, &filevolume) < 0) + return -1; + + if (filevolume == NULL) { + if (hyper_mkdir(mountpoint) < 0) { + perror("create volume dir failed"); + return -1; + } + if (vol->docker) { + if (container->initialize && + (container_populate_volume(mountpoint, volume) < 0)) { + fprintf(stderr, "fail to populate volume %s\n", mountpoint); + return -1; + } + } + } else { + if (hyper_create_file(mountpoint) < 0) { + perror("create volume file failed"); + return -1; + } + sprintf(volume, "/%s/_data/%s", path, filevolume); + } + if (mount(volume, mountpoint, NULL, MS_BIND, NULL) < 0) { perror("mount volume device failed"); return -1; diff --git a/src/hyper.h b/src/hyper.h index 3210f02..8f2b066 100644 --- a/src/hyper.h +++ b/src/hyper.h @@ -124,6 +124,7 @@ static inline int hyper_create(char *hyper_path) return 0; } +int hyper_create_file(const char *hyper_path); int hyper_mkdir(char *hyper_path); int hyper_open_serial(char *tty); struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id); diff --git a/src/util.c b/src/util.c index 90acf03..c25d8c5 100644 --- a/src/util.c +++ b/src/util.c @@ -233,6 +233,26 @@ int hyper_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroup return ret; } +int hyper_create_file(const char *hyper_path) +{ + int fd; + struct stat stbuf; + + if (stat(hyper_path, &stbuf) >= 0) { + if (S_ISREG(stbuf.st_mode)) + return 0; + errno = S_ISDIR(stbuf.st_mode) ? EISDIR : EINVAL; + return -1; + } + + fd = open(hyper_path, O_CREAT|O_WRONLY, 0666); + if (fd < 0) + return -1; + close(fd); + fprintf(stdout, "created file %s\n", hyper_path); + return 0; +} + int hyper_mkdir(char *hyper_path) { struct stat st;