Skip to content

Commit 727f94e

Browse files
authored
Merge pull request #109 from bbockelm/posc
Create a "Persist on Successful Close" plugin
2 parents d213b45 + cab29a3 commit 727f94e

File tree

16 files changed

+1726
-65
lines changed

16 files changed

+1726
-65
lines changed

.github/workflows/test.yml

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,29 +33,31 @@ jobs:
3333
with:
3434
go-version: '1.23.5'
3535
- name: install deps
36+
working-directory: ${{runner.workspace}}
3637
run: |
37-
sudo curl -L https://xrootd.web.cern.ch/repo/RPM-GPG-KEY.txt -o /etc/apt/trusted.gpg.d/xrootd.asc
38-
sudo /bin/sh -c 'echo "deb https://xrootd.web.cern.ch/ubuntu noble stable" >> /etc/apt/sources.list.d/xrootd.list'
39-
sudo apt update && sudo apt-get install -y cmake libcurl4-openssl-dev libcurl4 pkg-config libssl-dev xrootd-server libxrootd-dev libxrootd-server-dev libgtest-dev
40-
sudo curl -L https://dl.min.io/server/minio/release/linux-amd64/minio -o /usr/local/bin/minio
41-
sudo chmod +x /usr/local/bin/minio
42-
sudo curl -L https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc
43-
sudo chmod +x /usr/local/bin/mc
38+
# Build deps
39+
sudo apt update && sudo apt-get install -y cmake libz-dev uuid-dev libcurl4-openssl-dev libcurl4 pkg-config libssl-dev g++ libscitokens-dev libgtest-dev
40+
41+
# Build our preferred set of patches on xrootd
42+
git clone https://github.com/xrootd/xrootd.git
43+
cd xrootd
44+
git remote add github_pelican https://github.com/PelicanPlatform/xrootd.git
45+
git fetch github_pelican
46+
git checkout -b v5.8.4-pelican -t github_pelican/v5.8.4-pelican
47+
mkdir -p build/release_dir
48+
cd build
49+
cmake .. -DCMAKE_INSTALL_PREFIX=$PWD/release_dir -DENABLE_ASAN=TRUE
50+
make -j $(($(nproc) + 2)) install
4451
4552
- name: Create Build Environment
4653
# Some projects don't allow in-source building, so create a separate build directory
4754
# We'll use this as our working directory for all subsequent commands
4855
run: cmake -E make_directory ${{runner.workspace}}/build
4956

5057
- name: Configure CMake
51-
# Use a bash shell so we can use the same syntax for environment variable
52-
# access regardless of the host operating system
5358
shell: bash
5459
working-directory: ${{runner.workspace}}/build
55-
# Note the current convention is to use the -S and -B options here to specify source
56-
# and build directories, but this is only available with CMake 3.13 and higher.
57-
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
58-
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_TESTING=yes -DXROOTD_PLUGINS_EXTERNAL_GTEST=${{ matrix.external-gtest }}
60+
run: CMAKE_PREFIX_PATH=$PWD/../xrootd/build/release_dir/lib/cmake/XRootD cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_TESTS=yes -DENABLE_ASAN=true -DXROOTD_PLUGINS_EXTERNAL_GTEST=${{ matrix.external-gtest }}
5961

6062
- name: Build
6163
working-directory: ${{runner.workspace}}/build
@@ -73,7 +75,7 @@ jobs:
7375
- name: Start xrootd
7476
working-directory: ${{runner.workspace}}/build
7577
shell: bash
76-
run: xrootd -c ${{runner.workspace}}/xrootd-s3-http/test/s3-xrootd-test.cfg &
78+
run: ASAN_OPTIONS=detect_odr_violation=0 LD_LIBRARY_PATH=$PWD/../xrootd/build/release_dir/lib $PWD/../xrootd/build/release_dir/bin/xrootd -c ${{runner.workspace}}/xrootd-s3-http/test/s3-xrootd-test.cfg &
7779

7880
- name: Get a file
7981
working-directory: ${{runner.workspace}}/build

CMakeLists.txt

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ project( xrootd-http/s3 )
44

55
option( XROOTD_PLUGINS_EXTERNAL_GTEST "Use an external/pre-installed copy of GTest" OFF )
66
option( VALGRIND "Run select unit tests under valgrind" OFF )
7-
option( ASAN "Build the plugin with the address sanitizer" OFF )
7+
option( ENABLE_ASAN "Build the plugin with the address sanitizer" OFF )
88

99
set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake )
1010
if( "${CMAKE_BUILD_TYPE}" STREQUAL "" )
@@ -20,7 +20,7 @@ if(VALGRIND)
2020
find_program(VALGRIND_BIN valgrind REQUIRED)
2121
endif()
2222

23-
if(ASAN)
23+
if( ENABLE_ASAN )
2424
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
2525
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
2626
set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -fsanitize=address")
@@ -146,6 +146,16 @@ target_link_libraries(XrdOssGlobusObj ${XRootD_UTILS_LIBRARIES} ${XRootD_SERVER_
146146
add_library(XrdOssGlobus MODULE "$<TARGET_OBJECTS:XrdOssGlobusObj>")
147147
target_link_libraries(XrdOssGlobus XrdOssGlobusObj)
148148

149+
#######################
150+
## libXrdOssPosc ##
151+
#######################
152+
add_library( XrdOssPoscObj OBJECT src/Posc.cc )
153+
set_target_properties( XrdOssPoscObj PROPERTIES POSITION_INDEPENDENT_CODE ON )
154+
target_link_libraries( XrdOssPoscObj XRootD::XrdServer XRootD::XrdUtils )
155+
156+
add_library( XrdOssPosc MODULE "$<TARGET_OBJECTS:XrdOssPoscObj>" )
157+
target_link_libraries( XrdOssPosc XrdOssPoscObj )
158+
149159
# Customize module's suffix and, on Linux, hide unnecessary symbols
150160
if( APPLE )
151161
set_target_properties( XrdS3 PROPERTIES OUTPUT_NAME "XrdS3-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" )
@@ -154,23 +164,25 @@ if( APPLE )
154164
set_target_properties( XrdOssHttp PROPERTIES OUTPUT_NAME "XrdOssHttp-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" )
155165
set_target_properties( XrdOssFilter PROPERTIES OUTPUT_NAME "XrdOssFilter-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" )
156166
set_target_properties( XrdOssGlobus PROPERTIES OUTPUT_NAME "XrdOssGlobus-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" )
167+
set_target_properties( XrdOssPosc PROPERTIES OUTPUT_NAME "XrdOssPosc-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" )
157168
else()
158169
set_target_properties( XrdS3 PROPERTIES OUTPUT_NAME "XrdS3-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/configs/export-lib-symbols" )
159170
set_target_properties( XrdHTTPServer PROPERTIES OUTPUT_NAME "XrdHTTPServer-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/configs/export-lib-symbols" )
160171
set_target_properties( XrdOssS3 PROPERTIES OUTPUT_NAME "XrdOssS3-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/configs/export-lib-symbols" )
161172
set_target_properties( XrdOssHttp PROPERTIES OUTPUT_NAME "XrdOssHttp-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/configs/export-lib-symbols" )
162173
set_target_properties( XrdOssFilter PROPERTIES OUTPUT_NAME "XrdOssFilter-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/configs/export-lib-symbols" )
163174
set_target_properties( XrdOssGlobus PROPERTIES OUTPUT_NAME "XrdOssGlobus-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/configs/export-lib-symbols" )
175+
set_target_properties( XrdOssPosc PROPERTIES OUTPUT_NAME "XrdOssPosc-${XRootD_PLUGIN_VERSION}" SUFFIX ".so" LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/configs/export-lib-symbols" )
164176
endif()
165177

166178
include(GNUInstallDirs)
167179

168180
install(
169-
TARGETS XrdS3 XrdHTTPServer XrdOssS3 XrdOssHttp XrdOssFilter XrdOssGlobus
181+
TARGETS XrdS3 XrdHTTPServer XrdOssS3 XrdOssHttp XrdOssFilter XrdOssGlobus XrdOssPosc
170182
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
171183
)
172184

173-
if( BUILD_TESTING )
185+
if( ENABLE_TESTS )
174186
# Create shared libraries for testing from the existing objects
175187
add_library(XrdS3Testing SHARED "$<TARGET_OBJECTS:XrdS3Obj>")
176188
target_link_libraries(XrdS3Testing XrdS3Obj)
@@ -188,6 +200,10 @@ if( BUILD_TESTING )
188200
target_link_libraries(XrdOssGlobusTesting XrdOssGlobusObj)
189201
target_include_directories(XrdOssGlobusTesting INTERFACE ${XRootD_INCLUDE_DIRS})
190202

203+
add_library( XrdOssPoscTesting SHARED "$<TARGET_OBJECTS:XrdOssPoscObj>" )
204+
target_link_libraries( XrdOssPoscTesting XrdOssPoscObj )
205+
target_include_directories( XrdOssPoscTesting INTERFACE ${XRootD_INCLUDE_DIRS} )
206+
191207
find_program(GoWrk go-wrk HINTS "$ENV{HOME}/go/bin")
192208
if( NOT GoWrk )
193209
# Try installing the go-wrk variable to generate a reasonable stress test

README.md

Lines changed: 151 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
1+
# Pelican filesystem plugins for XRootD
2+
This repository contains various plugins for [XRootD](https://github.com/xrootd/xrootd)'s "Open Storage System" (OSS) layer,
3+
which affects how XRootD serves objects from storage.
4+
5+
The plugins in the repository include:
6+
- `XrdOssHttp`: Exposes a backend HTTP(S) server as a backend storage.
7+
- `XrdOssS3`: Exposes a backend S3-compatible interface as a backend storage.
8+
- `XrdOssFilter`: A "stacking" plugin (meant to be loaded on top of another OSS plugin)
9+
that exports only files/directories matching a given list of Unix globs.
10+
- `XrdOssPosc`: A "stacking" plugin that causes in-progress files being written from being
11+
visible to the filesystem and to be deleted if not successfully closed. Here, "POSC"
12+
stands for "Persist on Successful Close" and is similar in spirit to the POSC functionality
13+
in the core XRootD (with the addition of making in-progress files not-visible in the namespace).
114

2-
# S3/HTTP filesystem plugins for XRootD
3-
These filesystem plugins for [XRootD](https://github.com/xrootd/xrootd) allow you to serve objects from S3 and HTTP backends through an XRootD server.
415

516
## Building and Installing
617
Assuming XRootD, CMake>=3.13 and gcc>=8 are already installed, run:
@@ -18,28 +29,25 @@ make
1829
If building XRootD from source instead, add `-DXROOTD_DIR` to the CMake command line
1930
to point it at the installed directory.
2031

32+
Dependency packages (tinyxml, gtest, and minio/mc for tests) are automatically downloaded
33+
if they are not present in the build environment.
34+
2135
### Building with Tests
2236

2337
Unit tests for this repository require `gtest`, which is included as a submodule of this repo. The tests can be compiled with a slight modification to your build command:
2438

2539
```
2640
mkdir build
2741
cd build
28-
cmake -DXROOTD_PLUGINS_BUILD_UNITTESTS=ON ..
42+
cmake -DBUILD_TESTING=ON ..
2943
make
3044
```
3145

32-
This creates the directory `build/test` with two unit test executables that can be run:
33-
- `build/test/s3-gtest`
34-
- `build/test/http-gtest`
46+
To run the test framework, execute `ctest` from the build directory:
3547

36-
Alternatively, `gtest` can be installed externally. For example, on RHEL-based linux distributions:
37-
38-
```bash
39-
dnf install gtest
4048
```
41-
42-
Add `-DXROOTD_PLUGINS_EXTERNAL_GTEST=ON` to your `cmake` command if you're using an external installation.
49+
ctest
50+
```
4351

4452
## Configuration
4553

@@ -48,7 +56,7 @@ Add `-DXROOTD_PLUGINS_EXTERNAL_GTEST=ON` to your `cmake` command if you're using
4856
To configure the HTTP server plugin, add the following line to the Xrootd configuration file:
4957

5058
```
51-
ofs.osslib </path/to/libXrdHTTPServer.so>
59+
ofs.osslib libXrdOssHttp.so
5260
```
5361

5462
Here's a minimal config file
@@ -64,9 +72,9 @@ xrd.protocol http:1094 libXrdHttp.so
6472
all.export </exported/server/prefix>
6573
6674
# Setting up HTTP plugin
67-
ofs.osslib libXrdHTTPServer.so
68-
# Use this if libXrdHTTPServer.so is in a development directory
69-
# ofs.osslib /path/to/libXrdHTTPServer.so
75+
ofs.osslib libXrdOssHttp.so
76+
# Use this if libXrdOssHttp.so is in a development directory
77+
# ofs.osslib /path/to/libXrdOssHttp.so
7078
7179
# Upon last testing, the plugin did not yet work in async mode
7280
xrootd.async off
@@ -81,7 +89,7 @@ httpserver.host_url <host url>
8189
To configure the S3 plugin, add the following line to the Xrootd configuration file:
8290

8391
```
84-
ofs.osslib </path/to/libXrdS3.so>
92+
ofs.osslib libXrdOssS3.so
8593
```
8694

8795
Here's a minimal config file
@@ -96,11 +104,11 @@ xrd.protocol http:1094 libXrdHttp.so
96104
all.export </exported/server/prefix>
97105
98106
# Setting up S3 plugin
99-
ofs.osslib libXrdS3.so
100-
# Use this if libXrdS3.so is in a development directory
101-
# ofs.osslib /path/to/libXrdS3.so
107+
ofs.osslib libXrdOssS3.so
108+
# Use this if libXrdOssS3.so is in a development directory
109+
# ofs.osslib /path/to/libXrdOssS3.so
102110
103-
# Upon last testing, the plugin did not yet work in async mode
111+
# The plugin does not support plugin mode
104112
xrootd.async off
105113
106114
#example url
@@ -148,34 +156,145 @@ s3.trace debug
148156
149157
```
150158

159+
### Configure the filter plugin
151160

152-
## Startup and Testing
161+
The filter plugin allows you to provide multiple globs to export specific
162+
files and directories inside a filesystem (allowing some to be made inaccessible).
153163

154-
### HTTP Server Backend
164+
Note this only affects the namespace seen by XRootD. A user that can create symlinks
165+
on the filesystem outside XRootD can expose hidden parts of the namespace via a specially
166+
crafted symlink.
155167

156-
Assuming you named the config file `xrootd-http.cfg`, as a non-rootly user run:
168+
To load, invoke `ofs.osslib` in "stacking" mode:
157169

158170
```
159-
xrootd -d -c xrootd-http.cfg
171+
ofs.osslib ++ libXrdOssFilter.so
160172
```
161173

162-
In a separate terminal, run
174+
(an absolute path may be given if `libXrdOssFilter-5.so` does not reside in a system directory)
175+
176+
There are three configuration commands for the filter module:
163177

164178
```
165-
curl -v http://localhost:1094/<host name>/<URL path to object>
179+
filter.trace [all|error|warning|info|debug|none]
180+
filter.glob [-a] glob1 [glob2] [...]
181+
filter.prefix prefix1 [prefix2] [...]
166182
```
167183

168-
### S3 Server Backend
169-
Startup and Testing
184+
- `filter.trace`: Controls the logging verbosity of the module. Can be specified multiple times
185+
(values are additive) and multiple values can be given per line. Example:
186+
187+
```
188+
filter.trace info
189+
```
190+
191+
The default level is `warning`.
192+
- `filter.glob`: Controls the visibility of files in the storage; only files matching one of the
193+
configured globs or prefixes can be accessed. Can be specified multiple times (values are additive)
194+
and multiple globs can be given per line.
170195

171-
Assuming you named the config file `xrootd-s3.cfg`, as a non-rootly user run:
196+
The `-a` flag indicates that a wildcard should match all filenames, including those prefixed with a
197+
`.` character. Otherwise, such "dotfiles" are not visible.
198+
199+
The glob language supported by the platform's `fnmatch` C runtime function is used; additionally, the
200+
globstar operator (`**`) matches any names in zero-or-more directory hierarchies
201+
202+
Example:
203+
204+
```
205+
filter.glob /foo/*/*.txt /bar/**/*.csv
206+
```
207+
208+
With the above configuration, the files `/foo/1/test.txt` and `/bar/2/3/data.csv` would be visible
209+
but the files `/foo/4/5/test.txt` and `/bar/test.txt` would not.
210+
- `filter.prefix`: Controls the prefixes exported. Every file or directory under the provided prefix
211+
will be visible. Can be specified multiple times (values are additive) and multiple globs can be
212+
given per line.
213+
214+
Example:
215+
216+
```
217+
filter.prefix /foo /bar
218+
```
219+
220+
The above example would be equivalent to setting:
221+
222+
```
223+
filter.glob -a /foo/** /bar/**
224+
```
225+
226+
### Configure the POSC (Persist on Successful Close) plugin
227+
228+
The POSC plugin allows you to make files being uploaded into the storage invisible
229+
from readers until they have been successfully closed. If the writer never calls
230+
`close()` or the server crashes mid-transfer, the files will be deleted.
231+
232+
Note the visibility only affects the namespace seen by XRootD. A user that can create symlinks
233+
on the filesystem outside XRootD can expose the in-progress files if desired (but may not be
234+
able to read them, depending on the filesystem permissions set).
235+
236+
To load, invoke `ofs.osslib` in "stacking" mode:
172237

173238
```
174-
xrootd -d -c xrootd-s3.cfg
239+
ofs.osslib ++ libXrdOssPosc.so
240+
```
241+
242+
(an absolute path may be given if `libXrdOssPosc-5.so` does not reside in a system directory)
243+
244+
There are three configuration commands for the POSC module:
245+
246+
```
247+
posc.trace [all|error|warning|info|debug|none]
248+
posc.prefix posc_directory
249+
```
250+
251+
- `posc.trace`: Controls the logging verbosity of the module. Can be specified multiple times
252+
(values are additive) and multiple values can be given per line. Example:
253+
254+
```
255+
filter.trace info
256+
```
257+
258+
The default level is `warning`.
259+
260+
- `posc.prefix`: Controls the directory where in-progress files will be written. Once completed,
261+
they will be renamed into the final location. If this is not specified, the module will fail
262+
to start; if specified multiple times, the last value wins. Example:
263+
264+
```
265+
posc.prefix /in-progress
266+
```
267+
268+
The `posc.prefix` directory is not exported into the namespace; users will not be able to list
269+
its contents.
270+
271+
Files in the `posc.prefix` directory will have the following structure:
272+
273+
```
274+
/$(posc.prefix)/$(username)/in-progress.$(timestamp).$(random)
275+
```
276+
277+
where `$(username)` is the username as determined by the security framework (`anonymous` if unset).
278+
The user directory and files will be created with the user's credential as possible. If using
279+
the multi-user plugin, this the `posc.prefix` directory should be world writable with the "sticky bit"
280+
set to allow any user to create a subdirectory (but not allow users to delete other directories).
281+
282+
XRootD will never perform filesystem operations as root; it will not create as root and "chown" to the
283+
user.
284+
285+
World-writable directories are difficult to manage. Another option would be for the filesystem owner
286+
to pre-create all the potential user temporary directories.
287+
288+
## Startup and Testing
289+
290+
Assuming you named the config file `xrootd-http.cfg`, as a non-rootly user run:
291+
292+
```
293+
xrootd -d -c xrootd-http.cfg
175294
```
176295

177296
In a separate terminal, run
178297

179298
```
180-
curl -v http://localhost:1094/<path name>/<object name>
299+
curl -v http://localhost:1094/<host name>/<URL path to object>
181300
```

rpm/xrootd-s3-http.spec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ cmake --build redhat-linux-build --verbose
4545
%{_libdir}/libXrdOssGlobus-5.so
4646
%{_libdir}/libXrdOssS3-5.so
4747
%{_libdir}/libXrdOssFilter-5.so
48+
%{_libdir}/libXrdOssPosc-5.so
4849
%doc README.md
4950
%license LICENSE
5051

0 commit comments

Comments
 (0)