Skip to content

feat(storage): Add HDFS support via opendal services-hdfs-native - #3111

Open
mixermt wants to merge 9 commits into
apache:mainfrom
mixermt:feat-storage-hdfs-native
Open

feat(storage): Add HDFS support via opendal services-hdfs-native#3111
mixermt wants to merge 9 commits into
apache:mainfrom
mixermt:feat-storage-hdfs-native

Conversation

@mixermt

@mixermt mixermt commented Aug 30, 2026

Copy link
Copy Markdown

Which issue does this PR close?

This revives #1131's successor #2441 by @jordepic (closed by the stale bot after a first review round), rebased onto the current Storage-trait layout and updated for opendal 0.58, where services-hdfs-native changed behavior in ways that required design changes (details below).

What changes are included in this PR?

Adds an opendal-hdfs-native cargo feature to iceberg-storage-opendal, with OpenDalStorageFactory::HdfsNative / OpenDalStorage::HdfsNative variants and hdfs:// routing in OpenDalResolvingStorage. The backend uses OpenDAL's services-hdfs-native (pure-Rust HDFS RPC via hdfs-native — no JNI/libhdfs). The feature is experimental and not part of opendal-all, matching opendal-oss/opendal-azdls.

NameNode resolution (differs from #2441, forced by opendal 0.58 where name_node is mandatory and its comma-split list is the HA mechanism):

  1. hdfs.name-node property when set — a single endpoint or a comma-separated list for HA failover (new HDFS_NAME_NODE / HDFS_HADOOP_CONF_PREFIX constants in iceberg::io).
  2. Otherwise the path authority (hdfs://host:port/path).
  3. Authority-less paths without the property are rejected with a pointed error (opendal 0.58 can no longer defer to fs.defaultFS).

hadoop.-prefixed properties pass through to the HDFS client config, overriding $HADOOP_CONF_DIR values (mirroring the hadoop. catalog-property convention of the Java integrations); hdfs-native still loads core-site.xml/hdfs-site.xml from $HADOOP_CONF_DIR/$HADOOP_HOME for everything else, and Kerberos works via libgssapi_krb5 (runtime dlopen). Operators are cached per effective NameNode since each holds live RPC connections.

Relative paths are returned opendal-style without a leading /opendal::Deleter::delete (used by delete_stream) rejects leading slashes, which an integration test caught.

Test infrastructure: single-node HDFS docker fixture (apache/hadoop:3.5.0, host networking — required because hdfs-native dials DataNodes by their registered IP, unroutable on a bridge). The DataNode healthcheck gates on NameNode registration so --wait means writable. Tests are #[ignore]d (host networking is Linux-only); CI opts in via cargo nextest --run-ignored=only -E 'test(file_io_hdfs)'.

Are these changes tested?

  • 24 unit tests across config parsing, path parsing (authority/port/authority-less/wrong-scheme), NameNode precedence, operator caching, relativize, and scheme resolution; 3 config tests in iceberg::io.
  • 12 integration tests against the docker fixture covering exists/read/write/overwrite/metadata/range reads/streaming writes/delete/delete_prefix/delete_stream (+empty), resolving storage over hdfs://, and the HA flow (logical authority in the path + hdfs.name-node property). All 12 verified green from a cold cluster locally; the suite runs in CI on Linux.
  • make check, full-workspace --all-features lib tests, and the existing s3/gcs/resolving integration suites pass; public-api.txt regenerated for both crates.

AI Disclosure

Developed with AI assistance (Claude Code): drafting code/tests/fixtures starting from #2441, and cross-checking the design against the vendored opendal 0.58.1 / hdfs-native 0.14.5 sources. I reviewed the implementation and ran all verification locally. Areas worth reviewer attention: the NameNode-resolution semantics above (opendal's synthetic-nameservice behavior constrains what hdfs://<nameservice> paths can do without the property), and the Windows --all-features build of hdfs-native, which I could only verify via CI.

🤖 Generated with Claude Code

mixermt and others added 2 commits August 29, 2026 18:57
Adds an opendal-hdfs-native cargo feature plus OpenDalStorageFactory::Hdfs
and OpenDalStorage::Hdfs variants in iceberg-storage-opendal, using
OpenDAL's services-hdfs-native (pure-Rust HDFS RPC, no JNI/libhdfs).

The NameNode for a path resolves as: the hdfs.name-node property when set
(comma-separated endpoints enable HA failover), otherwise the path
authority. hadoop.-prefixed properties are forwarded to the HDFS client
configuration, overriding values loaded from $HADOOP_CONF_DIR. Operators
are cached per effective NameNode since each holds live RPC connections.

Revives and updates PR apache#2441 (by @jordepic) against the current storage
layer and opendal 0.58, where name_node became mandatory and the comma
list is the HA mechanism.

Closes apache#2440

Co-authored-by: Jordan Epstein <jordepic@users.noreply.github.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comment thread .github/workflows/ci.yml Outdated
Comment thread crates/iceberg/src/io/storage/config/hdfs.rs Outdated

@blackmwk blackmwk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found two correctness issues that need to be addressed before merge: malformed hdfs: URLs can panic, and bulk deletion can conflate NameNodes running on different ports. Details and suggested regression coverage are inline. Please also resolve the two existing review threads.


This review was drafted by an AI-assisted tool and confirmed by an Apache Iceberg Rust maintainer. After you've addressed the points above and pushed an update, an Apache Iceberg Rust maintainer — a real person — will take the next look at the PR. The findings cite the project's review criteria; if you think one of them is mis-applied, please reply on the PR and a maintainer will weigh in.

More on how Apache Iceberg Rust handles maintainer review: CONTRIBUTING.md.

Comment thread crates/storage/opendal/src/hdfs.rs Outdated
Comment thread crates/storage/opendal/src/lib.rs Outdated
mixermt and others added 4 commits August 31, 2026 12:17
…S CI special-casing

- HdfsConfig is now pub(crate) and parsed via #[derive(Properties)]
  (key/prefix attributes) instead of hand-written TryFrom + TypedBuilder.
- HDFS integration tests are no longer #[ignore]d and the dedicated CI
  step is gone; they run under the default nextest invocation since
  make docker-up already starts the fixture and the Tests job is
  Linux-only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…effective NameNode

- Url::parse accepts non-hierarchical forms like `hdfs:x`; the byte-7
  slice then panicked. Require the literal `hdfs://` prefix instead.
- batch_key_for_path grouped by URL host only, so NameNodes differing
  by port shared one deleter; key by the effective NameNode (configured
  hdfs.name-node, else authority incl. port), matching the operator cache.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mixermt
mixermt requested a review from blackmwk September 1, 2026 12:05

@blackmwk blackmwk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mixermt for this pr. I think the variant should be named to Hdfs-native rather than hdfs. Hdfs should be reserved for non native hdfs support.

Comment thread crates/iceberg/src/io/storage/config/hdfs.rs Outdated
Comment thread crates/storage/opendal/src/hdfs_native.rs
Comment thread crates/storage/opendal/src/hdfs.rs Outdated
mixermt and others added 2 commits September 5, 2026 12:11
…sConfig

Per review: the opendal module, its functions and the storage/factory
variants are now hdfs_native-prefixed (leaving room for a libhdfs-backed
variant, see apache#1130), and the never-consumed HdfsConfig struct is removed
from the core crate — config/hdfs.rs keeps only the property constants
that iceberg-storage-opendal uses.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support tables which live on HDFS

2 participants