mirror of https://github.com/apache/cloudstack.git
api: Change GET/POST request max length of VM user data to 4K/1M (#4737)
Currently we can send a default value of 4K/32K for GET/POST request of user data field. Most new browsers and also nginx support till 1MB of post data. Added a new global setting `vm.userdata.max.length` with default value of 32KB which can be increased till 1MB.
This commit is contained in:
parent
95de82750e
commit
2f8d557f58
|
|
@ -150,7 +150,9 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
|
|||
+ "The parameter is required and respected only when hypervisor info is not set on the ISO/Template passed to the call")
|
||||
private String hypervisor;
|
||||
|
||||
@Parameter(name = ApiConstants.USER_DATA, type = CommandType.STRING, description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. This binary data must be base64 encoded before adding it to the request. Using HTTP GET (via querystring), you can send up to 2KB of data after base64 encoding. Using HTTP POST(via POST body), you can send up to 32K of data after base64 encoding.", length = 32768)
|
||||
@Parameter(name = ApiConstants.USER_DATA, type = CommandType.STRING,
|
||||
description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. This binary data must be base64 encoded before adding it to the request. Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. Using HTTP POST(via POST body), you can send up to 1MB of data after base64 encoding.",
|
||||
length = 1048576)
|
||||
private String userData;
|
||||
|
||||
@Parameter(name = ApiConstants.SSH_KEYPAIR, type = CommandType.STRING, description = "name of the ssh key pair used to login to the virtual machine")
|
||||
|
|
|
|||
|
|
@ -80,8 +80,13 @@ public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction,
|
|||
|
||||
@Parameter(name = ApiConstants.USER_DATA,
|
||||
type = CommandType.STRING,
|
||||
description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. This binary data must be base64 encoded before adding it to the request. Using HTTP GET (via querystring), you can send up to 2KB of data after base64 encoding. Using HTTP POST(via POST body), you can send up to 32K of data after base64 encoding.",
|
||||
length = 32768)
|
||||
description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. " +
|
||||
"This binary data must be base64 encoded before adding it to the request. " +
|
||||
"Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. " +
|
||||
"Using HTTP POST(via POST body), you can send up to 1MB of data after base64 encoding." +
|
||||
"You also need to change vm.userdata.max.length value",
|
||||
length = 1048576,
|
||||
since = "4.16.0")
|
||||
private String userData;
|
||||
|
||||
@Parameter(name = ApiConstants.DISPLAY_VM, type = CommandType.BOOLEAN, description = "an optional field, whether to the display the vm to the end user or not.", authorized = {RoleType.Admin})
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public class UserVmVO extends VMInstanceVO implements UserVm {
|
|||
@Column(name = "iso_id", nullable = true, length = 17)
|
||||
private Long isoId = null;
|
||||
|
||||
@Column(name = "user_data", updatable = true, nullable = true, length = 32768)
|
||||
@Column(name = "user_data", updatable = true, nullable = true, length = 1048576)
|
||||
@Basic(fetch = FetchType.LAZY)
|
||||
private String userData;
|
||||
|
||||
|
|
|
|||
|
|
@ -411,6 +411,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
protected Set<String> configValuesForValidation;
|
||||
private Set<String> weightBasedParametersForValidation;
|
||||
private Set<String> overprovisioningFactorsForValidation;
|
||||
public static final String VM_USERDATA_MAX_LENGTH_STRING = "vm.userdata.max.length";
|
||||
|
||||
public static final ConfigKey<Boolean> SystemVMUseLocalStorage = new ConfigKey<Boolean>(Boolean.class, "system.vm.use.local.storage", "Advanced", "false",
|
||||
"Indicates whether to use local storage pools or shared storage pools for system VMs.", false, ConfigKey.Scope.Zone, null);
|
||||
|
|
@ -430,6 +431,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
"Indicates whether the host in down state can be put into maintenance state so thats its not enabled after it comes back.",
|
||||
true, ConfigKey.Scope.Zone, null);
|
||||
|
||||
public static final ConfigKey<Integer> VM_USERDATA_MAX_LENGTH = new ConfigKey<Integer>("Advanced", Integer.class, VM_USERDATA_MAX_LENGTH_STRING, "32768",
|
||||
"Max length of vm userdata after base64 decoding. Default is 32768 and maximum is 1048576", true);
|
||||
|
||||
private static final String IOPS_READ_RATE = "IOPS Read";
|
||||
private static final String IOPS_WRITE_RATE = "IOPS Write";
|
||||
private static final String BYTES_READ_RATE = "Bytes Read";
|
||||
|
|
@ -484,6 +488,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
configValuesForValidation.add(StorageManager.STORAGE_POOL_DISK_WAIT.key());
|
||||
configValuesForValidation.add(StorageManager.STORAGE_POOL_CLIENT_TIMEOUT.key());
|
||||
configValuesForValidation.add(StorageManager.STORAGE_POOL_CLIENT_MAX_CONNECTIONS.key());
|
||||
configValuesForValidation.add(VM_USERDATA_MAX_LENGTH_STRING);
|
||||
}
|
||||
|
||||
private void weightBasedParametersForValidation() {
|
||||
|
|
@ -958,6 +963,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
throw new InvalidParameterValueException("Please enter a value less than 257 for the configuration parameter:" + name);
|
||||
}
|
||||
}
|
||||
if (VM_USERDATA_MAX_LENGTH_STRING.equalsIgnoreCase(name)) {
|
||||
if (val > 1048576) {
|
||||
throw new InvalidParameterValueException("Please enter a value less than 1048576 for the configuration parameter:" + name);
|
||||
}
|
||||
}
|
||||
} catch (final NumberFormatException e) {
|
||||
s_logger.error("There was an error trying to parse the integer value for:" + name);
|
||||
throw new InvalidParameterValueException("There was an error trying to parse the integer value for:" + name);
|
||||
|
|
@ -6519,6 +6529,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] {SystemVMUseLocalStorage, IOPS_MAX_READ_LENGTH, IOPS_MAX_WRITE_LENGTH,
|
||||
BYTES_MAX_READ_LENGTH, BYTES_MAX_WRITE_LENGTH, ADD_HOST_ON_SERVICE_RESTART_KVM, SET_HOST_DOWN_TO_MAINTENANCE};
|
||||
BYTES_MAX_READ_LENGTH, BYTES_MAX_WRITE_LENGTH, ADD_HOST_ON_SERVICE_RESTART_KVM, SET_HOST_DOWN_TO_MAINTENANCE,
|
||||
VM_USERDATA_MAX_LENGTH};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -341,6 +341,8 @@ import com.cloud.vm.snapshot.VMSnapshotManager;
|
|||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||
|
||||
import static com.cloud.configuration.ConfigurationManagerImpl.VM_USERDATA_MAX_LENGTH;
|
||||
|
||||
public class UserVmManagerImpl extends ManagerBase implements UserVmManager, VirtualMachineGuru, UserVmService, Configurable {
|
||||
private static final Logger s_logger = Logger.getLogger(UserVmManagerImpl.class);
|
||||
|
||||
|
|
@ -541,7 +543,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
private Map<Long, VmAndCountDetails> vmIdCountMap = new ConcurrentHashMap<>();
|
||||
|
||||
private static final int MAX_HTTP_GET_LENGTH = 2 * MAX_USER_DATA_LENGTH_BYTES;
|
||||
private static final int MAX_HTTP_POST_LENGTH = 16 * MAX_USER_DATA_LENGTH_BYTES;
|
||||
private static final int NUM_OF_2K_BLOCKS = 512;
|
||||
private static final int MAX_HTTP_POST_LENGTH = NUM_OF_2K_BLOCKS * MAX_USER_DATA_LENGTH_BYTES;
|
||||
|
||||
@Inject
|
||||
private OrchestrationService _orchSrvc;
|
||||
|
|
@ -4471,11 +4474,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (!Base64.isBase64(userData)) {
|
||||
throw new InvalidParameterValueException("User data is not base64 encoded");
|
||||
}
|
||||
// If GET, use 4K. If POST, support upto 32K.
|
||||
// If GET, use 4K. If POST, support up to 1M.
|
||||
if (httpmethod.equals(HTTPMethod.GET)) {
|
||||
if (userData.length() >= MAX_HTTP_GET_LENGTH) {
|
||||
throw new InvalidParameterValueException("User data is too long for an http GET request");
|
||||
}
|
||||
if (userData.length() > VM_USERDATA_MAX_LENGTH.value()) {
|
||||
throw new InvalidParameterValueException("User data has exceeded configurable max length : " + VM_USERDATA_MAX_LENGTH.value());
|
||||
}
|
||||
decodedUserData = Base64.decodeBase64(userData.getBytes());
|
||||
if (decodedUserData.length > MAX_HTTP_GET_LENGTH) {
|
||||
throw new InvalidParameterValueException("User data is too long for GET request");
|
||||
|
|
@ -4484,6 +4490,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (userData.length() >= MAX_HTTP_POST_LENGTH) {
|
||||
throw new InvalidParameterValueException("User data is too long for an http POST request");
|
||||
}
|
||||
if (userData.length() > VM_USERDATA_MAX_LENGTH.value()) {
|
||||
throw new InvalidParameterValueException("User data has exceeded configurable max length : " + VM_USERDATA_MAX_LENGTH.value());
|
||||
}
|
||||
decodedUserData = Base64.decodeBase64(userData.getBytes());
|
||||
if (decodedUserData.length > MAX_HTTP_POST_LENGTH) {
|
||||
throw new InvalidParameterValueException("User data is too long for POST request");
|
||||
|
|
|
|||
Loading…
Reference in New Issue