Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve siteFs #173

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
9 changes: 9 additions & 0 deletions doc/install/manualinstallgpu.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,17 @@ To illustrate the configuration process, consider the following parameters that
* **autoLoadKernelModule=0** Flag to determine if kernel modules will be loaded by Shifter if required. This is limited to loop, squashfs, ext4 (and dependencies). *Recommend value 0* if kernel modules (loop, squashfs, and ext4) are already loaded as part of the node boot process, otherwise use *value 1* to let Shifter load the kernel modules.
* **system=greina** The name of the computer cluster where shifter is deployed. It is **important for this to match the platform name in the json configuration file** for the Image Manager.
* **imageGateway=http://greina9:5000** Space separated URLs for where the Image Gateway can be reached.
* **siteFs=/home;/scratch** Semicolon seperated list of paths to be automatically bind-mounted from the host system into the container. This is typically used to make network filesystems accessible within the container, but could be used to allow certain other facilities.
* **siteResources=/opt/shifter/site-resources** Absolute path to where site-specific resources will be bind-mounted inside the container to enable features like native MPI or GPU support. This configuration only affects the container. The specified path will be automatically created inside the container. The specified path doesn't need to exist on the host.

.. warning::
If a path specified in ``siteFs`` contains a parent directory that also exists in
the image, mount precedence will be given to the host path, and the resources
from the image will be skipped.

For example: if ``/var/spool/alps`` is in ``siteFs``, and the image contains
``/var/spool/``, the image directory will not be mounted.


Shifter Startup
+++++++++++++++
Expand Down
75 changes: 62 additions & 13 deletions src/shifter_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,48 @@ int bindImageIntoUDI(
continue;
}

/* check to see if UDI version already exists */
/* check to see if UDI version already exists,
* skip if UDI already contains the file or folder */
snprintf(mntBuffer, PATH_MAX, "%s/%s/%s", udiRoot, relpath, itemname);
mntBuffer[PATH_MAX-1] = 0;
if (lstat(mntBuffer, &statData) == 0) {
/* exists in UDI, skip */

/* print warning if we are skipping potentially important image's data */
snprintf(srcBuffer, PATH_MAX, "%s/%s/%s", imgRoot, relpath, itemname);
srcBuffer[PATH_MAX-1] = 0;
char relBuffer[PATH_MAX];
if(strcmp(relpath, "/") == 0) {
snprintf(relBuffer, PATH_MAX, "/%s", itemname);
}
else {
snprintf(relBuffer, PATH_MAX, "%s/%s", relpath, itemname);
}
relBuffer[PATH_MAX-1] = 0;

int is_file = is_existing_file(srcBuffer) && !is_existing_directory(srcBuffer);
int is_non_empty_directory = (is_existing_directory(srcBuffer)
&& !is_empty_directory(srcBuffer));
/* We consider not important, i.e. ok to skip, the following items:
* - /etc and children: /etc is specially handled (recursive copy to merge image's /etc with site /etc)
* - /var: is specially handled (this function is also explicitely called to mount the first-level contents of /var)
* - /var/run and children: we don't care about the old container's runtime data
* - /var/spool and children: we don't care about the old container's spool data
* - /var/tmp and children: we want the site's /var/tmp so we can create/modify data (image's /var/tmp is read-only)
*/
int is_important = (strncmp(relBuffer, "/etc", 4) != 0
&& strcmp(relBuffer, "/var") != 0
&& strncmp(relBuffer, "/var/run", 8) != 0
&& strncmp(relBuffer, "/var/spool", 10) != 0
&& strncmp(relBuffer, "/var/tmp", 8) != 0);
if((is_file || is_non_empty_directory) && is_important)
{
fprintf(stderr, "WARNING: skipping mount of image's %s. The file or directory already"
" exists in the container and will not be bind mounted from the image. This"
" could happen because the system administrator configured Shifter to create"
" or mount resources in the container whose path conflicts with the contents"
" of the image.\n", relBuffer);
}

free(itemname);
itemname = NULL;
continue;
Expand Down Expand Up @@ -1717,25 +1754,37 @@ int setupVolumeMapMounts(
if (createToDev) {
int okToMkdir = 0;

/* search the first existing parent folder and check that it is on the device
where we are authorized to create stuff */
char *ptr = strrchr(to_buffer, '/');
if (ptr) {
/* get parent path of intended dir */
*ptr = '\0';

/* if parent path is on the same device as is authorized by createToDev
then ok the mkdir operation */
if (lstat(to_buffer, &statData) == 0) {
if (statData.st_dev == createToDev) {
*ptr = '\0';
while (1) {
int parent_folder_exists = (lstat(to_buffer, &statData) == 0);
if (parent_folder_exists) {
int is_parent_folder_on_authorized_device = (statData.st_dev == createToDev);
if (is_parent_folder_on_authorized_device) {
okToMkdir = 1;
}
*ptr = '/';
break;
}

/* reset to target path */
*ptr = '/';
/* move to next parent folder */
char *old_ptr = ptr;
ptr = strrchr(to_buffer, '/');
*old_ptr = '/';
*ptr = '\0';

int went_through_all_parent_folders = (ptr == to_buffer);
if(went_through_all_parent_folders)
{
*ptr = '/';
break;
}
}

if (okToMkdir) {
mkdir(to_buffer, 0755);
mkdir_p(to_buffer, 0755);
if (lstat(to_buffer, &statData) != 0) {
fprintf(stderr, "FAILED to find volume \"to\": %s\n",
to_buffer);
Expand Down
25 changes: 25 additions & 0 deletions src/utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include <stdarg.h>
#include <stdint.h>
#include <linux/limits.h>
#include <dirent.h>

#include "utility.h"

Expand Down Expand Up @@ -532,3 +533,27 @@ int is_existing_directory(const char* path) {
struct stat sb;
return stat(path, &sb) == 0 && S_ISDIR(sb.st_mode);
}

/**
* Returns 1 if the specified directory is empty.
*/
int is_empty_directory(const char* path) {
DIR *dir = opendir(path);
if(dir == NULL) {
return 1;
}

struct dirent *entry = NULL;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
{
continue;
}
closedir(dir);
return 0;
}

closedir(dir);
return 1;
}
1 change: 1 addition & 0 deletions src/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ char *userInputPathFilter(const char *input, int allowSlash);
int mkdir_p(const char* path, mode_t mode);
int is_existing_file(const char* path);
int is_existing_directory(const char* path);
int is_empty_directory(const char* path);

#ifdef __cplusplus
}
Expand Down
9 changes: 8 additions & 1 deletion udiRoot.conf.example.in
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ rootfsType=@ROOTFS_TYPE@

#siteFs
#
# Semicolon seperated list of paths to be automatically bind-mounted into the
# Semicolon separated list of paths to be automatically bind-mounted into the
# container. This is typically used to make network filesystems accessible
# within the container, but could be used to allow certain other facilities,
# like /var/run or /var/spool/alps to be accessible within the image (depending
Expand All @@ -215,6 +215,13 @@ rootfsType=@ROOTFS_TYPE@
#
# It is OK to perform this under /var or /opt or a novel path that your site
# maintains (e.g., for NERSC, /global).
#
# **WARNING**: If a path on this list contains a parent directory that also exists in
# the image, mount precedence will be given to the host path specified here, and
# the resources from the image will be skipped.
# For example: if /var/spool/alps is in siteFs, and the image contains /var/spool/,
# the image directory will not be mounted.
#
siteFs=/home:/home


Expand Down