From 33f8463292735b2e9c7c06d29457cb01b156c9bf Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Tue, 27 Oct 2026 08:50:32 +0000 Subject: [PATCH] Replace Travis CI with GitHub Actions and refresh packaging and docs - Add a GitHub Actions workflow: a build job (JDK 17 and 21) that runs the cluster-free unit tests and Javadoc, and an integration job that bootstraps a single-node MicroCeph cluster and runs the whole suite. - Remove .travis.yml (travis-ci.org is gone) and the src/test/docker harness, which was based on a Ceph Jewel / Ubuntu 16.04 image that is no longer available. src/test/scripts/microceph-setup.sh replaces it and works on any Ubuntu machine with snapd. - debian/: move to debhelper-compat 13 with short-form dh rules, build with JDK 17 and Maven 3.6+, depend on Nautilus-or-newer client libraries including libradosstriper1, drop the committed debhelper.log and the stale compat/install files. The changelog gains a 1:0.7.0-1 entry; the epoch is required because the previous entry was 1.0. - README: document the Java 17 and Nautilus requirements, the Maven coordinates, try-with-resources usage, how to run the unit tests without a cluster, and the MicroCeph script. Drop the obsolete note about copying jars into /usr/share/java. --- .github/workflows/ci.yml | 50 +++++ .travis.yml | 18 -- README.md | 92 ++++++--- debian/changelog | 10 + debian/compat | 1 - debian/control | 20 +- debian/debhelper.log | 1 - debian/librados-java.docs | 4 +- debian/librados-java.install | 1 - debian/rules | 56 ++---- src/test/docker/Dockerfile | 25 --- src/test/docker/entrypoint.sh | 291 ---------------------------- src/test/docker/run-test.sh | 11 -- src/test/docker/validate-cluster.sh | 57 ------ src/test/scripts/microceph-setup.sh | 51 +++++ 15 files changed, 203 insertions(+), 485 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml delete mode 100644 debian/compat delete mode 100644 debian/debhelper.log delete mode 100644 debian/librados-java.install delete mode 100644 src/test/docker/Dockerfile delete mode 100755 src/test/docker/entrypoint.sh delete mode 100755 src/test/docker/run-test.sh delete mode 100755 src/test/docker/validate-cluster.sh create mode 100755 src/test/scripts/microceph-setup.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..4fd8841 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,50 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + +jobs: + build: + name: Build and unit tests (JDK ${{ matrix.java }}) + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + java: [17, 21] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: ${{ matrix.java }} + cache: maven + - name: Build, run the cluster-free unit tests and generate Javadoc + run: >- + ./mvnw -B -ntp + -Dtest='RadosBaseTest,ErrorCodeTest' + -Dsurefire.failIfNoSpecifiedTests=false + verify javadoc:javadoc + + integration: + name: Integration tests against a MicroCeph cluster + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: maven + - name: Install librados, librbd and libradosstriper + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends librados2 librbd1 libradosstriper1 + - name: Bootstrap a single-node Ceph cluster + run: sudo src/test/scripts/microceph-setup.sh + - name: Run all tests + run: ./mvnw -B -ntp test + - name: Cluster status on failure + if: failure() + run: sudo microceph.ceph -s || true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 264f640..0000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ - -sudo: required - -services: - - docker - -before_install: - - docker build -t rados-java-test src/test/docker - -script: - - docker run -d --name rados-java-test --net=host -v $(pwd):/build -e MON_IP=$(ip -4 -o a | awk '/eth|ens|eno|enp/ { sub ("/..", "", $4); print $4 }') -e CEPH_PUBLIC_NETWORK=$(grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/[0-9]\{1,2\}' /proc/net/fib_trie | grep -vE "^127|0$" | head -1) rados-java-test - - sudo ./src/test/docker/validate-cluster.sh - - docker exec -it rados-java-test /build/src/test/docker/run-test.sh - - - - - diff --git a/README.md b/README.md index 135dd30..b58bff6 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,87 @@ # RADOS Java -These are Java bindings for [librados](https://docs.ceph.com/en/latest/rados/api/librados/) (C) which use JNA. -Both RADOS and RBD are implemented in these bindings. +[![CI](https://github.com/ceph/rados-java/actions/workflows/ci.yml/badge.svg)](https://github.com/ceph/rados-java/actions/workflows/ci.yml) -By using JNA there is no need for building the bindings against any header -you can use them on any system where JNA and librados are present. +Java bindings for [librados](https://docs.ceph.com/en/latest/rados/api/librados/), +[librbd](https://docs.ceph.com/en/latest/rbd/api/librbdpy/) and libradosstriper +from the [Ceph](https://ceph.io/) project, implemented with +[JNA](https://github.com/java-native-access/jna). -The bindings follow the current librados C API and require Ceph Nautilus (14.2) -or newer: the `rados_pool_stat_t` struct layout and the deprecated auid calls -changed in Nautilus. +Because JNA binds at runtime there is no native build against the Ceph +headers: the bindings work on any system where JNA and the Ceph client +libraries are present. -# Maven -## Building +## Requirements -Building requires JDK 17 or newer and Maven 3.6+ (or use the bundled `./mvnw`). +* Java 17 or newer +* librados2, librbd1 and libradosstriper1 from Ceph **Nautilus (14.2) or + newer**. The `rados_pool_stat_t` struct layout and the deprecated auid calls + changed in Nautilus, older versions are not supported. -```bash -$ mvn clean install (-Dcom.ceph.rados.skipTests) +## Using the library + +```xml + + com.ceph + rados + 0.7.0 + ``` -## Tests +```java +import com.ceph.rados.IoCTX; +import com.ceph.rados.Rados; -```bash -$ mvn test +try (Rados rados = new Rados("admin")) { + rados.confReadFile(new File("/etc/ceph/ceph.conf")); + rados.connect(); + + try (IoCTX io = rados.ioCtxCreate("data")) { + io.write("hello", "world".getBytes(StandardCharsets.UTF_8)); + System.out.println(io.stat("hello").getSize()); + } +} ``` -You can also run specific tests: +`Rados`, `IoCTX`, `IoCTXStriper`, `RbdImage`, `Completion`, `ReadOp` and +`ListCtx` are `AutoCloseable` and release their native handles on `close()`. + +## Building + +Building requires JDK 17 or newer. The Maven wrapper downloads a suitable +Maven version. ```bash -mvn -Dtest=com.ceph.rados.TestRados +./mvnw clean install -Dcom.ceph.rados.skipTests=true ``` +## Tests + +The unit tests that do not need a cluster can always be run: + ```bash -mvn -Dtest=com.ceph.rbd.TestRbd +./mvnw test -Dtest='RadosBaseTest,ErrorCodeTest' -Dsurefire.failIfNoSpecifiedTests=false ``` -# Unit Tests -The tests require a running Ceph cluster. By default it will read /etc/ceph/ceph.conf -and use "admin" as a cephx id. +The remaining tests are integration tests that require a running Ceph cluster. +By default they read `/etc/ceph/ceph.conf`, authenticate as `admin` and use +the pools `data` (RADOS and striper) and `rbd` (RBD). These pools have to +EXIST prior to running the tests and should be EMPTY. -All tests will be performed on the pools "data" (RADOS) and "rbd" (RBD). +**DO NOT RUN THESE TESTS AGAINST A PRODUCTION CLUSTER.** -These pools have to EXIST prior to running the tests and should be EMPTY! +The defaults can be overridden with environment variables: -DO NOT RUN THESE TESTS ON A PRODUCTION PLATFORM. +* `RADOS_JAVA_ID` +* `RADOS_JAVA_CONFIG_FILE` +* `RADOS_JAVA_POOL` -You can overrride this by setting these environment variables: -* RADOS_JAVA_ID -* RADOS_JAVA_CONFIG_FILE -* RADOS_JAVA_POOL +```bash +./mvnw test +./mvnw test -Dtest=com.ceph.rados.TestRados +./mvnw test -Dtest=com.ceph.rbd.TestRbd +``` -N.B.: You need to make sure jna.jar and junit.jar are present in /usr/share/java +`src/test/scripts/microceph-setup.sh` bootstraps a throw-away single-node +cluster with [MicroCeph](https://canonical-microceph.readthedocs-hosted.com/) +and creates the pools, which is what the GitHub Actions workflow uses. diff --git a/debian/changelog b/debian/changelog index ece6b0b..eaf8929 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +librados-java (1:0.7.0-1) unstable; urgency=medium + + * New upstream release 0.7.0 (the pom.xml version); an epoch is needed + because the previous Debian version was 1.0. + * Bindings fixed against the current librados C API (Nautilus+). + * Java 17 baseline, JNA 5.17, JUnit 5. + * Modern debhelper (compat 13) packaging. + + -- Wido den Hollander Tue, 27 Oct 2026 08:50:07 +0000 + librados-java (1.0) unstable; urgency=low * Release of version 1.0 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index ec63514..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/debian/control b/debian/control index 056c887..1f652a0 100644 --- a/debian/control +++ b/debian/control @@ -1,12 +1,16 @@ Source: librados-java -Section: libs -Priority: extra -Maintainer: Wido den Hollander -Build-Depends: debhelper (>= 7), openjdk-7-jdk | openjdk-8-jdk, maven (>= 3) -Standards-Version: 3.8.1 -Homepage: http://www.github.com/ceph/rados-java +Section: java +Priority: optional +Maintainer: Wido den Hollander +Build-Depends: debhelper-compat (= 13), default-jdk (>= 2:1.17) | openjdk-17-jdk, maven (>= 3.6) +Standards-Version: 4.7.0 +Homepage: https://github.com/ceph/rados-java +Rules-Requires-Root: no Package: librados-java Architecture: all -Depends: librados2 (>= 0.80), librbd1 (>= 0.80) -Description: Java JNA bindings for librados and librbd +Depends: ${misc:Depends}, default-jre-headless (>= 2:1.17) | java17-runtime-headless, librados2 (>= 14.2), librbd1 (>= 14.2), libradosstriper1 (>= 14.2) +Description: Java JNA bindings for librados, librbd and libradosstriper + Java bindings for the Ceph RADOS object store client library (librados), + the RADOS block device library (librbd) and libradosstriper, implemented + with JNA so no native build against the Ceph headers is required. diff --git a/debian/debhelper.log b/debian/debhelper.log deleted file mode 100644 index 1d1d0b2..0000000 --- a/debian/debhelper.log +++ /dev/null @@ -1 +0,0 @@ -dh_installdirs diff --git a/debian/librados-java.docs b/debian/librados-java.docs index fa471a8..95db102 100644 --- a/debian/librados-java.docs +++ b/debian/librados-java.docs @@ -1,2 +1,2 @@ -README -LICENSE \ No newline at end of file +README.md +LICENSE diff --git a/debian/librados-java.install b/debian/librados-java.install deleted file mode 100644 index c68d582..0000000 --- a/debian/librados-java.install +++ /dev/null @@ -1 +0,0 @@ -/usr/share/java/rados-*.jar \ No newline at end of file diff --git a/debian/rules b/debian/rules index 520c93a..9c72a15 100755 --- a/debian/rules +++ b/debian/rules @@ -1,50 +1,24 @@ #!/usr/bin/make -f export DH_VERBOSE=1 -export DH_OPTIONS -VERSION := $(shell grep '^ ' pom.xml| cut -d'>' -f2 |cut -d'<' -f1) +VERSION := $(shell grep '^ ' pom.xml | cut -d'>' -f2 | cut -d'<' -f1) +JAVADIR := debian/librados-java/usr/share/java -configure: configure-stamp -configure-stamp: - dh_testdir - touch configure-stamp +%: + dh $@ -build: build-indep +override_dh_auto_build: + mvn -B -ntp -Dcom.ceph.rados.skipTests=true clean package -build-indep: build-indep-stamp +override_dh_auto_test: + # The tests need a running Ceph cluster, see README.md -build-indep-stamp: configure - mvn clean - mvn -DskipTests install - touch $@ +override_dh_auto_install: + install -D -m 0644 target/rados-$(VERSION).jar $(JAVADIR)/rados-$(VERSION).jar + dh_link usr/share/java/rados-$(VERSION).jar usr/share/java/rados.jar + install -m 0644 target/dependencies/jna*.jar $(JAVADIR)/ -clean: - dh_testdir - dh_testroot - rm -f build-arch-stamp build-indep-stamp configure-stamp - dh_clean - -install: - dh_testdir - dh_testroot - dh_prep -s - - mkdir -p debian/tmp/usr/share/java - cp target/rados-${VERSION}.jar debian/tmp/usr/share/java - dh_link usr/share/java/rados-${VERSION}.jar usr/share/java/rados.jar - cp target/dependencies/jna*.jar debian/tmp/usr/share/java - - dh_installdirs - dh_install - -binary: install - dh_install - dh_installchangelogs - dh_link - dh_compress - dh_fixperms - dh_installdeb - dh_gencontrol - dh_md5sums - dh_builddeb +override_dh_auto_clean: + mvn -B -ntp -q clean || true + dh_auto_clean diff --git a/src/test/docker/Dockerfile b/src/test/docker/Dockerfile deleted file mode 100644 index ff84684..0000000 --- a/src/test/docker/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# DOCKER-VERSION 1.0.0 -# -# Ceph docker image for testing rados-java -# based on the Demo Image by Sébastien Han "seb@redhat.com" -# -# VERSION 0.0.1 - -FROM ceph/base:tag-build-master-jewel-ubuntu-16.04 -MAINTAINER Arno Broekhof "arnobroekhof@gmail.com" - -# Add bootstrap script -ADD entrypoint.sh /entrypoint.sh - -# Add OpenJDK 8 -RUN apt-get update && \ - apt-get -y --no-install-recommends install openjdk-8-jdk libjna-java - -# Add volumes for Ceph config and data -VOLUME ["/etc/ceph","/var/lib/ceph"] - -# Expose the Ceph ports -EXPOSE 6789 6800 6801 6802 6803 6804 6805 80 5000 - -# Execute the entrypoint -ENTRYPOINT ["/entrypoint.sh"] diff --git a/src/test/docker/entrypoint.sh b/src/test/docker/entrypoint.sh deleted file mode 100755 index 4f0c7ed..0000000 --- a/src/test/docker/entrypoint.sh +++ /dev/null @@ -1,291 +0,0 @@ -#!/bin/bash -set -e - -: ${CLUSTER:=ceph} -: ${RGW_NAME:=$(hostname -s)} -: ${MON_NAME:=$(hostname -s)} -: ${RGW_CIVETWEB_PORT:=80} -: ${NETWORK_AUTO_DETECT:=1} -: ${RESTAPI_IP:=0.0.0.0} -: ${RESTAPI_PORT:=5000} -: ${RESTAPI_BASE_URL:=/api/v0.1} -: ${RESTAPI_LOG_LEVEL:=warning} -: ${RESTAPI_LOG_FILE:=/var/log/ceph/ceph-restapi.log} - -CEPH_OPTS="--cluster ${CLUSTER}" - - -# FUNCTIONS -# Log arguments with timestamp -function log { - if [ -z "$*" ]; then - return 1 - fi - - TIMESTAMP=$(date '+%F %T') - echo "${TIMESTAMP} $0: $*" - return 0 -} - -function create_socket_dir { - mkdir -p /var/run/ceph - chown ceph. /var/run/ceph -} - -####### -# MON # -####### - -function bootstrap_mon { - if [[ ! -n "$CEPH_PUBLIC_NETWORK" && ${NETWORK_AUTO_DETECT} -eq 0 ]]; then - log "ERROR- CEPH_PUBLIC_NETWORK must be defined as the name of the network for the OSDs" - exit 1 - fi - - if [[ ! -n "$MON_IP" && ${NETWORK_AUTO_DETECT} -eq 0 ]]; then - log "ERROR- MON_IP must be defined as the IP address of the monitor" - exit 1 - fi - - if [ ${NETWORK_AUTO_DETECT} -ne 0 ]; then - NIC_MORE_TRAFFIC=$(grep -vE "lo:|face|Inter" /proc/net/dev | sort -n -k 2 | tail -1 | awk '{ sub (":", "", $1); print $1 }') - if command -v ip; then - if [ ${NETWORK_AUTO_DETECT} -eq 1 ]; then - MON_IP=$(ip -6 -o a s $NIC_MORE_TRAFFIC | awk '{ sub ("/..", "", $4); print $4 }') - if [ -z "$MON_IP" ]; then - MON_IP=$(ip -4 -o a s $NIC_MORE_TRAFFIC | awk '{ sub ("/..", "", $4); print $4 }') - CEPH_PUBLIC_NETWORK=$(ip r | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/[0-9]\{1,2\}' | head -1) - fi - elif [ ${NETWORK_AUTO_DETECT} -eq 4 ]; then - MON_IP=$(ip -4 -o a s $NIC_MORE_TRAFFIC | awk '{ sub ("/..", "", $4); print $4 }') - CEPH_PUBLIC_NETWORK=$(ip r | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/[0-9]\{1,2\}' | head -1) - elif [ ${NETWORK_AUTO_DETECT} -eq 6 ]; then - MON_IP=$(ip -6 -o a s $NIC_MORE_TRAFFIC | awk '{ sub ("/..", "", $4); print $4 }') - CEPH_PUBLIC_NETWORK=$(ip r | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/[0-9]\{1,2\}' | head -1) - fi - # best effort, only works with ipv4 - # it is tough to find the ip from the nic only using /proc - # so we just take on of the addresses available - # which is fairely safe given that containers usually have a single nic - else - MON_IP=$(grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' /proc/net/fib_trie | grep -vEw "^127|255$|0$" | head -1) - CEPH_PUBLIC_NETWORK=$(grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/[0-9]\{1,2\}' /proc/net/fib_trie | grep -vE "^127|^0" | head -1) - fi - fi - - if [[ -z "$MON_IP" || -z "$CEPH_PUBLIC_NETWORK" ]]; then - log "ERROR- it looks like we have not been able to discover the network settings" - exit 1 - fi - - # bootstrap MON - if [ ! -e /etc/ceph/${CLUSTER}.conf ]; then - fsid=$(uuidgen) - cat </etc/ceph/${CLUSTER}.conf -[global] -fsid = $fsid -mon initial members = ${MON_NAME} -mon host = ${MON_IP} -auth cluster required = cephx -auth service required = cephx -auth client required = cephx -osd crush chooseleaf type = 0 -osd journal size = 100 -osd pool default pg num = 8 -osd pool default pgp num = 8 -osd pool default size = 1 -public network = ${CEPH_PUBLIC_NETWORK} -cluster network = ${CEPH_PUBLIC_NETWORK} -ENDHERE - - # For ext4 - if [ "$(findmnt -n -o FSTYPE -T /var/lib/ceph)" = "ext4" ]; then - cat <> /etc/ceph/${CLUSTER}.conf -osd max object name len = 256 -osd max object namespace len = 64 -ENDHERE - fi - - # Generate administrator key - ceph-authtool /etc/ceph/${CLUSTER}.client.admin.keyring --create-keyring --gen-key -n client.admin --set-uid=0 --cap mon 'allow *' --cap osd 'allow *' --cap mds 'allow' - - # Generate the mon. key - ceph-authtool /etc/ceph/${CLUSTER}.mon.keyring --create-keyring --gen-key -n mon. --cap mon 'allow *' - - # Generate initial monitor map - monmaptool --create --add ${MON_NAME} ${MON_IP} --fsid ${fsid} /etc/ceph/monmap-${CLUSTER} - fi - - # If we don't have a monitor keyring, this is a new monitor - if [ ! -e /var/lib/ceph/mon/${CLUSTER}-${MON_NAME}/keyring ]; then - - if [ ! -e /etc/ceph/${CLUSTER}.client.admin.keyring ]; then - log "ERROR- /etc/ceph/${CLUSTER}.client.admin.keyring must exist; get it from your existing mon" - exit 2 - fi - - if [ ! -e /etc/ceph/${CLUSTER}.mon.keyring ]; then - log "ERROR- /etc/ceph/${CLUSTER}.mon.keyring must exist. You can extract it from your current monitor by running 'ceph ${CEPH_OPTS} auth get mon. -o /tmp/${CLUSTER}.mon.keyring'" - exit 3 - fi - - if [ ! -e /etc/ceph/monmap-${CLUSTER} ]; then - log "ERROR- /etc/ceph/monmap-${CLUSTER} must exist. You can extract it from your current monitor by running 'ceph ${CEPH_OPTS} mon getmap -o /tmp/monmap-${CLUSTER}'" - exit 4 - fi - - # Import the client.admin keyring and the monitor keyring into a new, temporary one - ceph-authtool /tmp/${CLUSTER}.mon.keyring --create-keyring --import-keyring /etc/ceph/${CLUSTER}.client.admin.keyring - ceph-authtool /tmp/${CLUSTER}.mon.keyring --import-keyring /etc/ceph/${CLUSTER}.mon.keyring - - # Make the monitor directory - mkdir -p /var/lib/ceph/mon/${CLUSTER}-${MON_NAME} - - # Make user 'ceph' the owner of all the tree - chown ceph. /var/lib/ceph/bootstrap-{osd,mds,rgw} - - # Prepare the monitor daemon's directory with the map and keyring - chown -R ceph. /var/lib/ceph/mon - ceph-mon ${CEPH_OPTS} --mkfs -i ${MON_NAME} --monmap /etc/ceph/monmap-${CLUSTER} --keyring /tmp/${CLUSTER}.mon.keyring - ceph-mon ${CEPH_OPTS} --setuser ceph --setgroup ceph --mkfs -i ${MON_NAME} --monmap /etc/ceph/monmap-${CLUSTER} --keyring /tmp/${CLUSTER}.mon.keyring --mon-data /var/lib/ceph/mon/${CLUSTER}-${MON_NAME} - - # Clean up the temporary key - rm /tmp/${CLUSTER}.mon.keyring - fi - - # start MON - create_socket_dir - chown -R ceph. /var/lib/ceph/mon - ceph-mon ${CEPH_OPTS} -i ${MON_NAME} --public-addr "${MON_IP}:6789" --setuser ceph --setgroup ceph - - # change replica size - ceph ${CEPH_OPTS} osd pool set rbd size 1 -} - - -####### -# OSD # -####### - -function bootstrap_osd { - if [ ! -e /var/lib/ceph/osd/${CLUSTER}-0/keyring ]; then - # bootstrap OSD - mkdir -p /var/lib/ceph/osd/${CLUSTER}-0 - ceph ${CEPH_OPTS} osd create - chown -R ceph. /var/lib/ceph/osd/${CLUSTER}-0 - ceph-osd ${CEPH_OPTS} -i 0 --mkfs --setuser ceph --setgroup ceph - ceph ${CEPH_OPTS} auth get-or-create osd.0 osd 'allow *' mon 'allow profile osd' -o /var/lib/ceph/osd/${CLUSTER}-0/keyring - ceph ${CEPH_OPTS} osd crush add 0 1 root=default host=localhost - fi - - # start OSD - chown -R ceph. /var/lib/ceph/osd/${CLUSTER}-0 - ceph-osd ${CEPH_OPTS} -i 0 --setuser ceph --setgroup ceph -} - - -####### -# MDS # -####### - -function bootstrap_mds { - if [ ! -e /var/lib/ceph/mds/${CLUSTER}-0/keyring ]; then - # create ceph filesystem - ceph ${CEPH_OPTS} osd pool create cephfs_data 8 - ceph ${CEPH_OPTS} osd pool create cephfs_metadata 8 - ceph ${CEPH_OPTS} fs new cephfs cephfs_metadata cephfs_data - - # bootstrap MDS - mkdir -p /var/lib/ceph/mds/${CLUSTER}-0 - ceph ${CEPH_OPTS} auth get-or-create mds.0 mds 'allow' osd 'allow *' mon 'allow profile mds' > /var/lib/ceph/mds/${CLUSTER}-0/keyring - chown -R ceph. /var/lib/ceph/mds/${CLUSTER}-0 - fi - - # start MDS - ceph-mds ${CEPH_OPTS} -i 0 --setuser ceph --setgroup ceph -} - -####### -# RGW # -####### - -function bootstrap_rgw { - if [ ! -e /var/lib/ceph/radosgw/${RGW_NAME}/keyring ]; then - # bootstrap RGW - mkdir -p /var/lib/ceph/radosgw/${RGW_NAME} - ceph ${CEPH_OPTS} auth get-or-create client.radosgw.gateway osd 'allow rwx' mon 'allow rw' -o /var/lib/ceph/radosgw/${RGW_NAME}/keyring - chown -R ceph. /var/lib/ceph/radosgw/${RGW_NAME} - fi - - # start RGW - radosgw ${CEPH_OPTS} -c /etc/ceph/${CLUSTER}.conf -n client.radosgw.gateway -k /var/lib/ceph/radosgw/${RGW_NAME}/keyring --rgw-socket-path="" --rgw-frontends="civetweb port=${RGW_CIVETWEB_PORT}" --setuser ceph --setgroup ceph -} - -function bootstrap_demo_user { - if [ -n "$CEPH_DEMO_UID" ] && [ -n "$CEPH_DEMO_ACCESS_KEY" ] && [ -n "$CEPH_DEMO_SECRET_KEY" ]; then - if [ -f /ceph-demo-user ]; then - log "Demo user already exists with credentials:" - cat /ceph-demo-user - else - log "Setting up a demo user..." - radosgw-admin user create --uid=$CEPH_DEMO_UID --display-name="Ceph demo user" --access-key=$CEPH_DEMO_ACCESS_KEY --secret-key=$CEPH_DEMO_SECRET_KEY - sed -i s/AWS_ACCESS_KEY_PLACEHOLDER/$CEPH_DEMO_ACCESS_KEY/ /root/.s3cfg - sed -i s/AWS_SECRET_KEY_PLACEHOLDER/$CEPH_DEMO_SECRET_KEY/ /root/.s3cfg - echo "Access key: $CEPH_DEMO_ACCESS_KEY" > /ceph-demo-user - echo "Secret key: $CEPH_DEMO_SECRET_KEY" >> /ceph-demo-user - - if [ -n "$CEPH_DEMO_BUCKET" ]; then - log "Creating bucket..." - s3cmd mb s3://$CEPH_DEMO_BUCKET - fi - fi - fi -} - -####### -# NFS # -####### - -function bootstrap_nfs { - # Init RPC - rpcbind || return 0 - rpc.statd -L || return 0 - rpc.idmapd || return 0 - - # start ganesha - exec /usr/bin/ganesha.nfsd -F ${GANESHA_OPTIONS} ${GANESHA_EPOCH} -} - -####### -# API # -####### - -function bootstrap_rest_api { - if [[ ! "$(egrep "\[client.restapi\]" /etc/ceph/${CLUSTER}.conf)" ]]; then - cat <>/etc/ceph/${CLUSTER}.conf -[client.restapi] - public addr = ${RESTAPI_IP}:${RESTAPI_PORT} - restapi base url = ${RESTAPI_BASE_URL} - restapi log level = ${RESTAPI_LOG_LEVEL} - log file = ${RESTAPI_LOG_FILE} -ENDHERE - fi - - # start ceph-rest-api - ceph-rest-api ${CEPH_OPTS} -n client.admin & -} - -######### -# WATCH # -######### - -mkdir -p /var/lib/ceph/bootstrap-{osd,mds,rgw} -bootstrap_mon -bootstrap_osd -bootstrap_mds -bootstrap_rgw -bootstrap_demo_user -bootstrap_rest_api -bootstrap_nfs -log "SUCCESS" -exec ceph ${CEPH_OPTS} -w diff --git a/src/test/docker/run-test.sh b/src/test/docker/run-test.sh deleted file mode 100755 index f0812f8..0000000 --- a/src/test/docker/run-test.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -set -xe - -# create data pool for testing -ceph osd pool create data 128 128 - -# sleep for 2 seconds to ensure the pool is created -sleep 2 - -cd /build -./mvnw clean test diff --git a/src/test/docker/validate-cluster.sh b/src/test/docker/validate-cluster.sh deleted file mode 100755 index 7558afe..0000000 --- a/src/test/docker/validate-cluster.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash -set -xe - -container_name=rados-java-test - - -# FUNCTIONS -function wait_for_daemon () { - timeout=20 - daemon_to_test=$1 - while [ $timeout -ne 0 ]; do - if eval $daemon_to_test; then - return 0 - fi - sleep 1 - let timeout=timeout-1 - done - return 1 -} - -function ceph_status { - echo "Waiting for Ceph to be ready" - return $(wait_for_daemon "docker exec $container_name ceph health | grep -sq HEALTH_OK") -} - -function test_demo_mon { - return $(wait_for_daemon "docker exec $container_name ceph -s | grep -sq quorum") -} - -function test_demo_osd { - return $(wait_for_daemon "docker exec $container_name ceph -s | grep -sq '1 osds: 1 up, 1 in'") -} - -function test_demo_rgw { - return $(wait_for_daemon "docker exec $container_name ceph osd dump | grep -sq rgw") -} - -function test_demo_mds { - echo "Waiting for the MDS to be ready" - # NOTE(leseb): metadata server always takes up to 5 sec to run - # so we first check if the pools exit, from that we assume that - # the process will start. We stop waiting after 10 seconds. - return $(wait_for_daemon "docker exec $container_name ceph osd dump | grep -sq cephfs && docker exec $container_name ceph -s | grep -sq 'up:active'") -} - -# MAIN -ceph_status # wait for the cluster to stabilize -test_demo_mon -test_demo_osd -test_demo_rgw -test_demo_mds -ceph_status # wait again for the cluster to stabilize (mds pools) - -if ! docker ps | grep $container_name; then - echo "looks like $container_name container died :(" - exit 1 -fi diff --git a/src/test/scripts/microceph-setup.sh b/src/test/scripts/microceph-setup.sh new file mode 100755 index 0000000..8c794be --- /dev/null +++ b/src/test/scripts/microceph-setup.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# +# Bootstrap a throw-away single-node Ceph cluster with MicroCeph and create +# the pools the rados-java tests expect ("data" for RADOS and the striper, +# "rbd" for RBD). Used by the GitHub Actions workflow, but also works on any +# Ubuntu machine with snapd. Must run as root. +# +# DO NOT run this on a machine that already runs Ceph. +# +set -euo pipefail + +if [ "$(id -u)" -ne 0 ]; then + echo "This script must run as root" >&2 + exit 1 +fi + +OSD_COUNT=${OSD_COUNT:-3} +OSD_SIZE=${OSD_SIZE:-4G} +POOLS=(data rbd) + +snap install microceph +snap refresh --hold microceph + +microceph cluster bootstrap +microceph disk add "loop,${OSD_SIZE},${OSD_COUNT}" + +# Expose the configuration and admin keyring to librados outside the snap. +mkdir -p /etc/ceph +cp /var/snap/microceph/current/conf/ceph.conf /etc/ceph/ceph.conf +for keyring in ceph.keyring ceph.client.admin.keyring; do + if [ -f "/var/snap/microceph/current/conf/${keyring}" ]; then + cp "/var/snap/microceph/current/conf/${keyring}" "/etc/ceph/${keyring}" + chmod 0644 "/etc/ceph/${keyring}" + fi +done + +# Wait for all OSDs to come up before creating pools. +for _ in $(seq 1 60); do + if microceph.ceph osd stat | grep -q "${OSD_COUNT} up"; then + break + fi + sleep 5 +done + +for pool in "${POOLS[@]}"; do + microceph.ceph osd pool create "${pool}" 8 +done +microceph.ceph osd pool application enable data rados +microceph.ceph osd pool application enable rbd rbd + +microceph.ceph -s