Skip to content

HDDS-16139. Define and enforce OFS and O3FS IPv6 authority contracts - #11108

Open
echonesis wants to merge 2 commits into
apache:masterfrom
echonesis:HDDS-16139
Open

HDDS-16139. Define and enforce OFS and O3FS IPv6 authority contracts#11108
echonesis wants to merge 2 commits into
apache:masterfrom
echonesis:HDDS-16139

Conversation

@echonesis

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

This PR defines and enforces the supported IPv6 authority forms for OFS and O3FS following the URI parser changes in HDDS-15775.

  • Allow OFS authorities containing bracketed IPv6 literals, with or without an explicit port, such as ofs://[2001:db8::10]:9862/.
  • Reject all unbracketed IPv6 authorities in OFS with an error explaining that IPv6 literals must be enclosed in brackets.
  • Reject raw IPv6 literals in O3FS authorities with an error recommending an OM service ID or DNS name.
  • Preserve existing O3FS forms using bucket.volume, DNS names, IPv4 addresses, and OM service IDs.
  • Preserve support for o3fs://bucket.volume/ when the OM endpoint is supplied through configuration, including a configured bracketed IPv6 address.
  • Construct OM RPC addresses through the existing bracket-aware host-and-port helper so configured IPv6 addresses retain the required brackets.
  • Add coverage for URI construction, filesystem initialization, authority parsing, rejection behavior, configured IPv6 endpoints, and qualified-path round trips.

A dotted O3FS authority cannot contain a bracketed IPv6 literal such as bucket.volume.[2001:db8::10], because java.net.URI rejects that form before O3FS initialization. Therefore, O3FS requires a DNS name or OM service ID when an IPv6 endpoint must be represented in the dotted authority.

What is the link to the Apache JIRA

https://issues.apache.org/jira/browse/HDDS-16139

How was this patch tested?

Local Test

mvn -pl :ozone-filesystem-common -am test \
  -Dtest=TestBasicOzoneFileSystems,TestOmUtils,TestOMFailoverProxyProvider \
  -Dsurefire.failIfNoSpecifiedTests=false \
  -DskipShade -DskipRecon -DskipDocs

GitHub Actions CI: https://github.com/echonesis/ozone/actions/runs/32799667939

Generated-by: Codex (GPT-5)

@echonesis
echonesis marked this pull request as ready for review August 25, 2026 18:12

@chihsuan chihsuan 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 @echonesis Overall, this looks good. I left a few inline comments, mostly around error classification and test scope.

I also noticed other related IPv6 issues (getHttpAddressForOMPeerNode and getHttpsAddressForOMPeerNode) in the same file. The fix would be the same approach used elsewhere in this PR.

Would it make sense to fold those in here, or should they go on a separate Jira under the epic?

String hostName = bindHost.orElse(addressHost.orElse(omNodeHostAddr));
return hostName + ":" + addressPort.orElse(OZONE_OM_HTTP_BIND_PORT_DEFAULT);

hostCaptor.capture(), anyInt());
assertNull(hostCaptor.getValue());
assertEquals("[2001:db8::10]:9862",
OmUtils.getOmRpcAddress(confCaptor.getValue()));

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.

This assertion tests OmUtils, which TestOmUtils already covers. I wonder if we should instead assert what createAdapter receives to keep this test focused on O3FS behavior?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed. I removed the OmUtils assertion and now verify directly that createAdapter receives the original configuration, the expected bucket and volume, a null OM host, and port -1. The IPv6 formatting behavior remains covered by TestOmUtils.

public void testO3fsConfiguredIpv6Endpoint() throws Exception {
OzoneConfiguration conf = new OzoneConfiguration();
conf.set(OMConfigKeys.OZONE_OM_ADDRESS_KEY,
"[2001:db8::10]:9862");

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.

nit: these lines fit within the 120-character limit. Could remain on one line, consistent with the test above?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed. I kept the affected statements on one line since they fit within the 120-character limit and match the surrounding tests.

throw new IllegalArgumentException(URI_EXCEPTION_TEXT);
}

if (authority.indexOf(':') != authority.lastIndexOf(':')) {

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.

This treats any authority with multiple colons as IPv6, so malformed non-IPv6 authorities now get the IPv6-specific error. Could we classify it as IPv6 only after validating the authority shape?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point. I moved the IPv6 classification after the O3FS authority shape parsing and now validate the OM endpoint with InetAddresses.isInetAddress. Valid raw IPv6 literals still receive the targeted IPv6 error, while malformed multi-colon authorities receive the general O3FS URI error. I added regression coverage for both cases.

@echonesis

echonesis commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @echonesis Overall, this looks good. I left a few inline comments, mostly around error classification and test scope.

I also noticed other related IPv6 issues (getHttpAddressForOMPeerNode and getHttpsAddressForOMPeerNode) in the same file. The fix would be the same approach used elsewhere in this PR.

Would it make sense to fold those in here, or should they go on a separate Jira under the epic?

String hostName = bindHost.orElse(addressHost.orElse(omNodeHostAddr));
return hostName + ":" + addressPort.orElse(OZONE_OM_HTTP_BIND_PORT_DEFAULT);

Thanks @chihsuan
Good catch. I folded both methods into HDDS-16139 because they have the same root cause and can use the same existing getHostPortString helper. I also added IPv6 coverage for both peer HTTP and HTTPS addresses in TestOmUtils.

@echonesis
echonesis requested a review from chihsuan August 26, 2026 23:54
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.

2 participants