Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public class AbfsConfiguration{
private final String accountName;
private final boolean isSecure;
private static final Logger LOG = LoggerFactory.getLogger(AbfsConfiguration.class);
private Trilean isNamespaceEnabled = null;

@StringConfigurationValidatorAnnotation(ConfigurationKey = FS_AZURE_ACCOUNT_IS_HNS_ENABLED,
DefaultValue = DEFAULT_FS_AZURE_ACCOUNT_IS_HNS_ENABLED)
Expand Down Expand Up @@ -332,8 +333,19 @@ public AbfsConfiguration(final Configuration rawConfig, String accountName)
}
}

/**
* Returns the account type as per the user configuration. Gets the account
* specific value if it exists, then looks for an account agnostic value.
* If not configured driver makes additional getAcl call to determine
* the account type during file system initialization.
* @return TRUE/FALSE value if configured, UNKNOWN if not configured.
*/
public Trilean getIsNamespaceEnabledAccount() {
return Trilean.getTrilean(isNamespaceEnabledAccount);
if (isNamespaceEnabled == null) {
isNamespaceEnabled = Trilean.getTrilean(
getString(FS_AZURE_ACCOUNT_IS_HNS_ENABLED, isNamespaceEnabledAccount));
}
return isNamespaceEnabled;
}

/**
Expand Down Expand Up @@ -1048,9 +1060,23 @@ void setMaxBackoffIntervalMilliseconds(int maxBackoffInterval) {
this.maxBackoffInterval = maxBackoffInterval;
}

/**
* Sets the namespace enabled account flag.
*
* @param isNamespaceEnabledAccount boolean value indicating if the account is namespace enabled.
*/
void setIsNamespaceEnabledAccount(boolean isNamespaceEnabledAccount) {
this.isNamespaceEnabled = Trilean.getTrilean(isNamespaceEnabledAccount);
}

/**
* Sets the namespace enabled account flag for testing purposes.
*
* @param isNamespaceEnabledAccount Trilean value indicating if the account is namespace enabled.
*/
@VisibleForTesting
void setIsNamespaceEnabledAccount(String isNamespaceEnabledAccount) {
this.isNamespaceEnabledAccount = isNamespaceEnabledAccount;
void setIsNamespaceEnabledAccountForTesting(Trilean isNamespaceEnabledAccount) {
this.isNamespaceEnabled = isNamespaceEnabledAccount;
}

private String getTrimmedPasswordString(String key, String defaultValue) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.apache.hadoop.fs.azurebfs.contracts.exceptions.InvalidConfigurationValueException;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.thirdparty.com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions;
Expand Down Expand Up @@ -106,6 +107,7 @@
import static org.apache.hadoop.fs.CommonConfigurationKeys.IOSTATISTICS_LOGGING_LEVEL_DEFAULT;
import static org.apache.hadoop.fs.azurebfs.AbfsStatistic.*;
import static org.apache.hadoop.fs.azurebfs.constants.ConfigurationKeys.DATA_BLOCKS_BUFFER;
import static org.apache.hadoop.fs.azurebfs.constants.ConfigurationKeys.FS_AZURE_ACCOUNT_IS_HNS_ENABLED;
import static org.apache.hadoop.fs.azurebfs.constants.ConfigurationKeys.FS_AZURE_BLOCK_UPLOAD_ACTIVE_BLOCKS;
import static org.apache.hadoop.fs.azurebfs.constants.ConfigurationKeys.FS_AZURE_BLOCK_UPLOAD_BUFFER_DIR;
import static org.apache.hadoop.fs.azurebfs.constants.FileSystemConfigurations.BLOCK_UPLOAD_ACTIVE_BLOCKS_DEFAULT;
Expand Down Expand Up @@ -190,6 +192,15 @@ public void initialize(URI uri, Configuration configuration)
tracingHeaderFormat = abfsConfiguration.getTracingHeaderFormat();
this.setWorkingDirectory(this.getHomeDirectory());

TracingContext initFSTracingContext = new TracingContext(clientCorrelationId,
fileSystemId, FSOperationType.INIT, tracingHeaderFormat, listener);
try {
getIsNamespaceEnabled(initFSTracingContext);
} catch (AzureBlobFileSystemException ex) {
LOG.debug("Failed to determine account type for service type validation", ex);
throw new InvalidConfigurationValueException(FS_AZURE_ACCOUNT_IS_HNS_ENABLED, ex);
}

if (abfsConfiguration.getCreateRemoteFileSystemDuringInitialization()) {
TracingContext tracingContext = new TracingContext(clientCorrelationId,
fileSystemId, FSOperationType.CREATE_FILESYSTEM, tracingHeaderFormat, listener);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ public class AzureBlobFileSystemStore implements Closeable, ListingSupport {
private final AbfsConfiguration abfsConfiguration;
private final Set<String> azureAtomicRenameDirSet;
private Set<String> azureInfiniteLeaseDirSet;
private Trilean isNamespaceEnabled;
private final AuthType authType;
private final UserGroupInformation userGroupInformation;
private final IdentityTransformerInterface identityTransformer;
Expand Down Expand Up @@ -207,8 +206,6 @@ public AzureBlobFileSystemStore(

LOG.trace("AbfsConfiguration init complete");

this.isNamespaceEnabled = abfsConfiguration.getIsNamespaceEnabledAccount();

this.userGroupInformation = UserGroupInformation.getCurrentUser();
this.userName = userGroupInformation.getShortUserName();
LOG.trace("UGI init complete");
Expand Down Expand Up @@ -342,35 +339,67 @@ private String[] authorityParts(URI uri) throws InvalidUriAuthorityException, In
return authorityParts;
}

/**
* Resolves namespace information of the filesystem from the state of {@link #isNamespaceEnabled()}.
* if the state is UNKNOWN, it will be determined by making a GET_ACL request
* to the root of the filesystem. GET_ACL call is synchronized to ensure a single
* call is made to determine the namespace information in case multiple threads are
* calling this method at the same time. The resolution of namespace information
* would be stored back as {@link #setNamespaceEnabled(boolean)}.
*
* @param tracingContext tracing context
* @return true if namespace is enabled, false otherwise.
* @throws AzureBlobFileSystemException server errors.
*/
public boolean getIsNamespaceEnabled(TracingContext tracingContext)
throws AzureBlobFileSystemException {
try {
return this.isNamespaceEnabled.toBoolean();
return isNamespaceEnabled();
} catch (TrileanConversionException e) {
LOG.debug("isNamespaceEnabled is UNKNOWN; fall back and determine through"
+ " getAcl server call", e);
}

LOG.debug("Get root ACL status");
try (AbfsPerfInfo perfInfo = startTracking("getIsNamespaceEnabled",
"getAclStatus")) {
AbfsRestOperation op = client
.getAclStatus(AbfsHttpConstants.ROOT_PATH, tracingContext);
perfInfo.registerResult(op.getResult());
isNamespaceEnabled = Trilean.getTrilean(true);
perfInfo.registerSuccess(true);
return getNamespaceEnabledInformationFromServer(tracingContext);
}

private synchronized boolean getNamespaceEnabledInformationFromServer(
final TracingContext tracingContext) throws AzureBlobFileSystemException {
if (abfsConfiguration.getIsNamespaceEnabledAccount() != Trilean.UNKNOWN) {
return isNamespaceEnabled();
}
try {
LOG.debug("Get root ACL status");
getClient().getAclStatus(AbfsHttpConstants.ROOT_PATH, tracingContext);
// If getAcl succeeds, namespace is enabled.
setNamespaceEnabled(true);
} catch (AbfsRestOperationException ex) {
// Get ACL status is a HEAD request, its response doesn't contain
// errorCode
// So can only rely on its status code to determine its account type.
// Get ACL status is a HEAD request, its response doesn't contain errorCode
// So can only rely on its status code to determine account type.
if (HttpURLConnection.HTTP_BAD_REQUEST != ex.getStatusCode()) {
// If getAcl fails with anything other than 400, namespace is enabled.
setNamespaceEnabled(true);
// Continue to throw exception as earlier.
LOG.debug("Failed to get ACL status with non 400. Inferring namespace enabled", ex);
throw ex;
}

isNamespaceEnabled = Trilean.getTrilean(false);
// If getAcl fails with 400, namespace is disabled.
LOG.debug("Failed to get ACL status with 400. "
+ "Inferring namespace disabled and ignoring error", ex);
setNamespaceEnabled(false);
} catch (AzureBlobFileSystemException ex) {
throw ex;
}
return isNamespaceEnabled();
}

return isNamespaceEnabled.toBoolean();
/**
* @return true if namespace is enabled, false otherwise.
* @throws TrileanConversionException if namespaceEnabled information is UNKNOWN
*/
@VisibleForTesting
boolean isNamespaceEnabled() throws TrileanConversionException {
return abfsConfiguration.getIsNamespaceEnabledAccount().toBoolean();
}

@VisibleForTesting
Expand Down Expand Up @@ -1869,9 +1898,8 @@ void setClient(AbfsClient client) {
this.client = client;
}

@VisibleForTesting
void setNamespaceEnabled(Trilean isNamespaceEnabled){
this.isNamespaceEnabled = isNamespaceEnabled;
void setNamespaceEnabled(boolean isNamespaceEnabled){
abfsConfiguration.setIsNamespaceEnabledAccount(isNamespaceEnabled);
}

private void updateInfiniteLeaseDirs() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ public enum FSOperationType {
SET_OWNER("SO"),
SET_ACL("SA"),
TEST_OP("TS"),
WRITE("WR");
WRITE("WR"),
INIT("IN");

private final String opCode;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import org.apache.hadoop.fs.azurebfs.contracts.exceptions.InvalidConfigurationValueException;
import org.apache.hadoop.fs.azurebfs.contracts.exceptions.TrileanConversionException;
import org.apache.hadoop.thirdparty.com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions;
import org.apache.hadoop.thirdparty.com.google.common.base.Strings;
Expand Down Expand Up @@ -1154,4 +1156,21 @@ public ListenableFuture<?> submit(Runnable runnable) {
public <V> void addCallback(ListenableFuture<V> future, FutureCallback<V> callback) {
Futures.addCallback(future, callback, executorService);
}

/**
* Checks if the namespace is enabled.
*
* @return True if the namespace is enabled, false otherwise.
* * @throws AzureBlobFileSystemException if the conversion fails.
*/
public boolean getIsNamespaceEnabled() throws AzureBlobFileSystemException {
try {
return abfsConfiguration.getIsNamespaceEnabledAccount().toBoolean();
} catch (TrileanConversionException ex) {
LOG.error(
"Failed to convert namespace enabled account property to boolean",
ex);
throw new InvalidConfigurationValueException("Failed to determine account type");
}
}
}
Loading
Loading