HADOOP-14518. Customize User-Agent header sent in HTTP/HTTPS requests by WASB. Contributed by Georgi Chalakov.
This commit is contained in:
parent
9fe5dd098d
commit
ab95086ed1
|
@ -508,7 +508,15 @@
|
||||||
name to use for the service when the client wishes to make an RPC call.
|
name to use for the service when the client wishes to make an RPC call.
|
||||||
</description>
|
</description>
|
||||||
</property>
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>fs.azure.user.agent.prefix</name>
|
||||||
|
<value>unknown</value>
|
||||||
|
<description>
|
||||||
|
WASB passes User-Agent header to the Azure back-end. The default value
|
||||||
|
contains WASB version, Java Runtime version, Azure Client library version,
|
||||||
|
and the value of the configuration option fs.azure.user.agent.prefix.
|
||||||
|
</description>
|
||||||
|
</property>
|
||||||
|
|
||||||
<property>
|
<property>
|
||||||
<name>hadoop.security.uid.cache.secs</name>
|
<name>hadoop.security.uid.cache.secs</name>
|
||||||
|
|
|
@ -112,6 +112,7 @@ public class TestCommonConfigurationFields extends TestConfigurationFieldsBase {
|
||||||
xmlPropsToSkipCompare.add("fs.azure.secure.mode");
|
xmlPropsToSkipCompare.add("fs.azure.secure.mode");
|
||||||
xmlPropsToSkipCompare.add("fs.azure.authorization");
|
xmlPropsToSkipCompare.add("fs.azure.authorization");
|
||||||
xmlPropsToSkipCompare.add("fs.azure.authorization.caching.enable");
|
xmlPropsToSkipCompare.add("fs.azure.authorization.caching.enable");
|
||||||
|
xmlPropsToSkipCompare.add("fs.azure.user.agent.prefix");
|
||||||
|
|
||||||
// ADL properties are in a different subtree
|
// ADL properties are in a different subtree
|
||||||
// - org.apache.hadoop.hdfs.web.ADLConfKeys
|
// - org.apache.hadoop.hdfs.web.ADLConfKeys
|
||||||
|
|
|
@ -58,6 +58,7 @@ import org.apache.hadoop.fs.permission.FsPermission;
|
||||||
import org.apache.hadoop.fs.permission.PermissionStatus;
|
import org.apache.hadoop.fs.permission.PermissionStatus;
|
||||||
import org.apache.hadoop.io.IOUtils;
|
import org.apache.hadoop.io.IOUtils;
|
||||||
import org.mortbay.util.ajax.JSON;
|
import org.mortbay.util.ajax.JSON;
|
||||||
|
import org.apache.hadoop.util.VersionInfo;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -71,6 +72,10 @@ import com.microsoft.azure.storage.StorageCredentialsAccountAndKey;
|
||||||
import com.microsoft.azure.storage.StorageCredentialsSharedAccessSignature;
|
import com.microsoft.azure.storage.StorageCredentialsSharedAccessSignature;
|
||||||
import com.microsoft.azure.storage.StorageErrorCode;
|
import com.microsoft.azure.storage.StorageErrorCode;
|
||||||
import com.microsoft.azure.storage.StorageException;
|
import com.microsoft.azure.storage.StorageException;
|
||||||
|
import com.microsoft.azure.storage.Constants;
|
||||||
|
import com.microsoft.azure.storage.StorageEvent;
|
||||||
|
import com.microsoft.azure.storage.core.BaseRequest;
|
||||||
|
import com.microsoft.azure.storage.SendingRequestEvent;
|
||||||
import com.microsoft.azure.storage.blob.BlobListingDetails;
|
import com.microsoft.azure.storage.blob.BlobListingDetails;
|
||||||
import com.microsoft.azure.storage.blob.BlobProperties;
|
import com.microsoft.azure.storage.blob.BlobProperties;
|
||||||
import com.microsoft.azure.storage.blob.BlobRequestOptions;
|
import com.microsoft.azure.storage.blob.BlobRequestOptions;
|
||||||
|
@ -102,6 +107,12 @@ public class AzureNativeFileSystemStore implements NativeFileSystemStore {
|
||||||
static final String DEFAULT_STORAGE_EMULATOR_ACCOUNT_NAME = "storageemulator";
|
static final String DEFAULT_STORAGE_EMULATOR_ACCOUNT_NAME = "storageemulator";
|
||||||
static final String STORAGE_EMULATOR_ACCOUNT_NAME_PROPERTY_NAME = "fs.azure.storage.emulator.account.name";
|
static final String STORAGE_EMULATOR_ACCOUNT_NAME_PROPERTY_NAME = "fs.azure.storage.emulator.account.name";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for User-Agent field.
|
||||||
|
*/
|
||||||
|
static final String USER_AGENT_ID_KEY = "fs.azure.user.agent.prefix";
|
||||||
|
static final String USER_AGENT_ID_DEFAULT = "unknown";
|
||||||
|
|
||||||
public static final Logger LOG = LoggerFactory.getLogger(AzureNativeFileSystemStore.class);
|
public static final Logger LOG = LoggerFactory.getLogger(AzureNativeFileSystemStore.class);
|
||||||
|
|
||||||
private StorageInterface storageInteractionLayer;
|
private StorageInterface storageInteractionLayer;
|
||||||
|
@ -306,6 +317,9 @@ public class AzureNativeFileSystemStore implements NativeFileSystemStore {
|
||||||
private boolean useSecureMode = false;
|
private boolean useSecureMode = false;
|
||||||
private boolean useLocalSasKeyMode = false;
|
private boolean useLocalSasKeyMode = false;
|
||||||
|
|
||||||
|
// User-Agent
|
||||||
|
private String userAgentId;
|
||||||
|
|
||||||
private String delegationToken;
|
private String delegationToken;
|
||||||
|
|
||||||
/** The error message template when container is not accessible. */
|
/** The error message template when container is not accessible. */
|
||||||
|
@ -504,6 +518,9 @@ public class AzureNativeFileSystemStore implements NativeFileSystemStore {
|
||||||
pageBlobDirs = getDirectorySet(KEY_PAGE_BLOB_DIRECTORIES);
|
pageBlobDirs = getDirectorySet(KEY_PAGE_BLOB_DIRECTORIES);
|
||||||
LOG.debug("Page blob directories: {}", setToString(pageBlobDirs));
|
LOG.debug("Page blob directories: {}", setToString(pageBlobDirs));
|
||||||
|
|
||||||
|
// User-agent
|
||||||
|
userAgentId = conf.get(USER_AGENT_ID_KEY, USER_AGENT_ID_DEFAULT);
|
||||||
|
|
||||||
// Extract directories that should have atomic rename applied.
|
// Extract directories that should have atomic rename applied.
|
||||||
atomicRenameDirs = getDirectorySet(KEY_ATOMIC_RENAME_DIRECTORIES);
|
atomicRenameDirs = getDirectorySet(KEY_ATOMIC_RENAME_DIRECTORIES);
|
||||||
String hbaseRoot;
|
String hbaseRoot;
|
||||||
|
@ -1910,6 +1927,17 @@ public class AzureNativeFileSystemStore implements NativeFileSystemStore {
|
||||||
|
|
||||||
OperationContext operationContext = new OperationContext();
|
OperationContext operationContext = new OperationContext();
|
||||||
|
|
||||||
|
// Set User-Agent
|
||||||
|
operationContext.getSendingRequestEventHandler().addListener(new StorageEvent<SendingRequestEvent>() {
|
||||||
|
@Override
|
||||||
|
public void eventOccurred(SendingRequestEvent eventArg) {
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) eventArg.getConnectionObject();
|
||||||
|
String userAgentInfo = String.format(Utility.LOCALE_US, "WASB/%s (%s) %s",
|
||||||
|
VersionInfo.getVersion(), userAgentId, BaseRequest.getUserAgent());
|
||||||
|
connection.setRequestProperty(Constants.HeaderConstants.USER_AGENT, userAgentInfo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (selfThrottlingEnabled) {
|
if (selfThrottlingEnabled) {
|
||||||
SelfThrottlingIntercept.hook(operationContext, selfThrottlingReadFactor,
|
SelfThrottlingIntercept.hook(operationContext, selfThrottlingReadFactor,
|
||||||
selfThrottlingWriteFactor);
|
selfThrottlingWriteFactor);
|
||||||
|
|
|
@ -189,6 +189,19 @@ The configuration option `fs.azure.page.blob.extension.size` is the page blob
|
||||||
extension size. This defines the amount to extend a page blob if it starts to
|
extension size. This defines the amount to extend a page blob if it starts to
|
||||||
get full. It must be 128MB or greater, specified as an integer number of bytes.
|
get full. It must be 128MB or greater, specified as an integer number of bytes.
|
||||||
|
|
||||||
|
### Custom User-Agent
|
||||||
|
WASB passes User-Agent header to the Azure back-end. The default value
|
||||||
|
contains WASB version, Java Runtime version, Azure Client library version, and the
|
||||||
|
value of the configuration option `fs.azure.user.agent.prefix`. Customized User-Agent
|
||||||
|
header enables better troubleshooting and analysis by Azure service.
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<property>
|
||||||
|
<name>fs.azure.user.agent.prefix</name>
|
||||||
|
<value>Identifier</value>
|
||||||
|
</property>
|
||||||
|
```
|
||||||
|
|
||||||
### Atomic Folder Rename
|
### Atomic Folder Rename
|
||||||
|
|
||||||
Azure storage stores files as a flat key/value store without formal support
|
Azure storage stores files as a flat key/value store without formal support
|
||||||
|
|
|
@ -566,4 +566,52 @@ public class TestWasbUriAndConfiguration {
|
||||||
CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, null);
|
CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, null);
|
||||||
assertEquals(newPath, effectivePath);
|
assertEquals(newPath, effectivePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUserAgentConfig() throws Exception {
|
||||||
|
// Set the user agent
|
||||||
|
try {
|
||||||
|
testAccount = AzureBlobStorageTestAccount.createMock();
|
||||||
|
Configuration conf = testAccount.getFileSystem().getConf();
|
||||||
|
String authority = testAccount.getFileSystem().getUri().getAuthority();
|
||||||
|
URI defaultUri = new URI("wasbs", authority, null, null, null);
|
||||||
|
conf.set(FS_DEFAULT_NAME_KEY, defaultUri.toString());
|
||||||
|
conf.set("fs.AbstractFileSystem.wasbs.impl", "org.apache.hadoop.fs.azure.Wasbs");
|
||||||
|
|
||||||
|
conf.set(AzureNativeFileSystemStore.USER_AGENT_ID_KEY, "TestClient");
|
||||||
|
|
||||||
|
FileSystem fs = FileSystem.get(conf);
|
||||||
|
AbstractFileSystem afs = FileContext.getFileContext(conf).getDefaultFileSystem();
|
||||||
|
|
||||||
|
assertTrue(afs instanceof Wasbs);
|
||||||
|
assertEquals(-1, afs.getUri().getPort());
|
||||||
|
assertEquals("wasbs", afs.getUri().getScheme());
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
testAccount.cleanup();
|
||||||
|
FileSystem.closeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset the user agent
|
||||||
|
try {
|
||||||
|
testAccount = AzureBlobStorageTestAccount.createMock();
|
||||||
|
Configuration conf = testAccount.getFileSystem().getConf();
|
||||||
|
String authority = testAccount.getFileSystem().getUri().getAuthority();
|
||||||
|
URI defaultUri = new URI("wasbs", authority, null, null, null);
|
||||||
|
conf.set(FS_DEFAULT_NAME_KEY, defaultUri.toString());
|
||||||
|
conf.set("fs.AbstractFileSystem.wasbs.impl", "org.apache.hadoop.fs.azure.Wasbs");
|
||||||
|
|
||||||
|
conf.unset(AzureNativeFileSystemStore.USER_AGENT_ID_KEY);
|
||||||
|
|
||||||
|
FileSystem fs = FileSystem.get(conf);
|
||||||
|
AbstractFileSystem afs = FileContext.getFileContext(conf).getDefaultFileSystem();
|
||||||
|
assertTrue(afs instanceof Wasbs);
|
||||||
|
assertEquals(-1, afs.getUri().getPort());
|
||||||
|
assertEquals("wasbs", afs.getUri().getScheme());
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
testAccount.cleanup();
|
||||||
|
FileSystem.closeAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,11 @@
|
||||||
<value>true</value>
|
<value>true</value>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<property>
|
||||||
|
<name>fs.azure.user.agent.prefix</name>
|
||||||
|
<value>MSFT</value>
|
||||||
|
</property>
|
||||||
|
|
||||||
<!-- Save the above configuration properties in a separate file named -->
|
<!-- Save the above configuration properties in a separate file named -->
|
||||||
<!-- azure-auth-keys.xml in the same directory as this file. -->
|
<!-- azure-auth-keys.xml in the same directory as this file. -->
|
||||||
<!-- DO NOT ADD azure-auth-keys.xml TO REVISION CONTROL. The keys to your -->
|
<!-- DO NOT ADD azure-auth-keys.xml TO REVISION CONTROL. The keys to your -->
|
||||||
|
|
Loading…
Reference in New Issue