Merge pull request #67 from arroyc/local-build-successfull

Added validation check for resource group name and other fields in Azure VM Agent Cloud
This commit is contained in:
Claudiu Guiman 2016-11-23 10:17:53 -08:00 committed by GitHub
commit 1eca498d10
10 changed files with 293 additions and 226 deletions

View File

@ -642,6 +642,8 @@ public class AzureVMAgentTemplate implements Describable<AzureVMAgentTemplate> {
public FormValidation doVerifyConfiguration(
@RelativePath("..") @QueryParameter String azureCredentialsId,
@RelativePath("..") @QueryParameter String resourceGroupName,
@RelativePath("..") @QueryParameter String maxVirtualMachinesLimit,
@RelativePath("..") @QueryParameter String deploymentTimeout,
@QueryParameter String templateName,
@QueryParameter String labels,
@QueryParameter String location,
@ -717,7 +719,8 @@ public class AzureVMAgentTemplate implements Describable<AzureVMAgentTemplate> {
// First validate the subscription info. If it is not correct,
// then we can't validate the
String result = AzureVMManagementServiceDelegate.verifyConfiguration(servicePrincipal, resourceGroupName);
String result = AzureVMManagementServiceDelegate.verifyConfiguration(servicePrincipal, resourceGroupName,
maxVirtualMachinesLimit, deploymentTimeout);
if (!result.equals(Constants.OP_SUCCESS)) {
return FormValidation.error(result);
}

View File

@ -691,15 +691,16 @@ public class AzureVMCloud extends Cloud {
public FormValidation doVerifyConfiguration(
@QueryParameter String azureCredentialsId,
@QueryParameter String maxVirtualMachinesLimit,
@QueryParameter String deploymentTimeout,
@QueryParameter String resourceGroupName) {
if (StringUtils.isBlank(resourceGroupName)) {
resourceGroupName = Constants.DEFAULT_RESOURCE_GROUP_NAME;
}
}
AzureCredentials.ServicePrincipal credentials = AzureCredentials.getServicePrincipal(azureCredentialsId);
try {
credentials.Validate(resourceGroupName);
boolean validationResult = credentials.Validate(resourceGroupName, maxVirtualMachinesLimit, deploymentTimeout);
} catch (AzureCredentialsValidationException e) {
return FormValidation.error(e.getMessage());
}

View File

@ -36,15 +36,15 @@ import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
/**
* Performs a few types of verification:
* 1. Overall subscription verification.
2. Approximate VM count verification
3. Template verification.
When a new AzureVMCloud is constructed or a new template is added via CLI interface, then we will
manually trigger this workload.
This thread serves as a gate for whether we can create VMs from a certain template
* Performs a few types of verification: 1. Overall subscription verification.
* 2. Approximate VM count verification 3. Template verification.
*
* When a new AzureVMCloud is constructed or a new template is added via CLI
* interface, then we will manually trigger this workload.
*
* This thread serves as a gate for whether we can create VMs from a certain
* template
*
* @author mmitche
*/
@Extension
@ -54,21 +54,21 @@ public final class AzureVMCloudVerificationTask extends AsyncPeriodicWork {
// Templates that need verification
private static Map<String, String> cloudTemplates;
// Set of clouds that need verification.
private static Set<String> cloudNames;
public AzureVMCloudVerificationTask() {
super("AzureVMCloudVerificationTask");
}
private static final Object cloudNamesLock = new Object();
private static final Object templatesLock = new Object();
@Override
public void execute(final TaskListener arg0) throws IOException, InterruptedException {
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: execute: start");
if (cloudNames != null && !cloudNames.isEmpty()) {
// Walk the list of clouds and verify the configuration. If an element
// is not found (perhaps a removed cloud, removes from the list)
@ -116,7 +116,7 @@ public final class AzureVMCloudVerificationTask extends AsyncPeriodicWork {
}
}
}
if (cloudTemplates != null && !cloudTemplates.isEmpty()) {
// Now walk the templates and verify.
// Unlike the clouds, verified templates are removed from the list upon
@ -128,15 +128,15 @@ public final class AzureVMCloudVerificationTask extends AsyncPeriodicWork {
for (Map.Entry<String, String> entry : cloudTemplates.entrySet()) {
String templateName = entry.getKey();
String cloudName = entry.getValue();
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: execute: verifying {0} in {1}",
new Object[] { templateName, cloudName });
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: execute: verifying {0} in {1}",
new Object[]{templateName, cloudName});
AzureVMCloud cloud = getCloud(cloudName);
// If the cloud is null, could mean that the cloud details changed
// between the last time we ran this task
if (cloud == null) {
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: execute: parent cloud not found for {0} in {1}",
new Object[] { templateName, cloudName });
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: execute: parent cloud not found for {0} in {1}",
new Object[]{templateName, cloudName});
toRemove.add(templateName);
continue;
}
@ -144,16 +144,16 @@ public final class AzureVMCloudVerificationTask extends AsyncPeriodicWork {
AzureVMAgentTemplate agentTemplate = cloud.getAzureAgentTemplate(templateName);
// Template could have been removed since the last time we ran verification
if (agentTemplate == null) {
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: execute: could not retrieve agent template named {0} in {1}",
new Object[] { templateName, cloudName });
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: execute: could not retrieve agent template named {0} in {1}",
new Object[]{templateName, cloudName});
toRemove.add(templateName);
continue;
}
// Determine whether we need to verify the template
if (agentTemplate.isTemplateVerified()) {
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: execute: template {0} in {1} already verified",
new Object[] { templateName, cloudName });
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: execute: template {0} in {1} already verified",
new Object[]{templateName, cloudName});
// Good to go, nothing more to check here. Add to removal list.
toRemove.add(templateName);
continue;
@ -171,15 +171,14 @@ public final class AzureVMCloudVerificationTask extends AsyncPeriodicWork {
else {
String details = StringUtils.join(errors, "\n");
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: execute: {0} could not be verified:\n{1}",
new Object [] { templateName, details });
new Object[]{templateName, details});
// Set the status details to the set of messages
agentTemplate.setTemplateStatusDetails(details);
}
}
catch (Exception e) {
} catch (Exception e) {
// Log, but ignore overall
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: execute: got exception while verifying {0}:\n{1}",
new Object [] { templateName, e.toString() });
new Object[]{templateName, e.toString()});
}
}
@ -189,35 +188,36 @@ public final class AzureVMCloudVerificationTask extends AsyncPeriodicWork {
}
}
}
LOGGER.info("AzureVMCloudVerificationTask: execute: end");
}
/**
* Checks the subscription for validity if needed
* @param cloud
* @return True if the subscription is valid, false otherwise.
* Updates the cloud state if it is. If subscription is
* not valid, then we can just return
* @return True if the subscription is valid, false otherwise. Updates the
* cloud state if it is. If subscription is not valid, then we can just
* return
*/
public boolean verifyConfiguration(AzureVMCloud cloud) {
LOGGER.info("AzureVMCloudVerificationTask: verifyConfiguration: start");
// Check the sub and off we go
String result = AzureVMManagementServiceDelegate.verifyConfiguration(cloud.getServicePrincipal(), cloud.getResourceGroupName());
String result = AzureVMManagementServiceDelegate.verifyConfiguration(cloud.getServicePrincipal(), cloud.getResourceGroupName(),
Integer.toString(cloud.getMaxVirtualMachinesLimit()), Integer.toString(cloud.getDeploymentTimeout()));
if (result != Constants.OP_SUCCESS) {
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: verifyConfiguration: {0}", result);
cloud.setConfigurationValid(false);
return false;
}
return true;
}
/**
* Retrieve the current VM count.
* @param cloud
* @return
* @param cloud
* @return
*/
public int getVirtualMachineCount(AzureVMCloud cloud) {
LOGGER.info("AzureVMCloudVerificationTask: getVirtualMachineCount: start");
@ -226,22 +226,21 @@ public final class AzureVMCloudVerificationTask extends AsyncPeriodicWork {
int vmCount = AzureVMManagementServiceDelegate.getVirtualMachineCount(config, cloud.getResourceGroupName());
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: getVirtualMachineCount: end, currently {0} vms", vmCount);
return vmCount;
}
catch(Exception e) {
} catch (Exception e) {
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: getVirtualMachineCount: failed to retrieve vm count:\n{0}",
e.toString());
e.toString());
// We could have failed for any number of reasons. Just return the current
// number of virtual machines.
return cloud.getApproximateVirtualMachineCount();
}
}
/**
* Register more than one template at once
* @param templatesToRegister List of templates to register
*/
public static void registerTemplates(final List<AzureVMAgentTemplate> templatesToRegister) {
synchronized(templatesLock) {
synchronized (templatesLock) {
for (AzureVMAgentTemplate template : templatesToRegister) {
registerTemplateHelper(template);
}
@ -253,13 +252,15 @@ public final class AzureVMCloudVerificationTask extends AsyncPeriodicWork {
* @param template Template to register
*/
public static void registerTemplate(final AzureVMAgentTemplate template) {
synchronized(templatesLock) {
synchronized (templatesLock) {
registerTemplateHelper(template);
}
}
/**
* Registers a single template. The lock should be held while calling this method
* Registers a single template. The lock should be held while calling this
* method
*
* @param template Template to register
*/
private static void registerTemplateHelper(final AzureVMAgentTemplate template) {
@ -268,21 +269,21 @@ public final class AzureVMCloudVerificationTask extends AsyncPeriodicWork {
if(sp != null)
cloudName = AzureUtil.getCloudName(sp.subscriptionId.getPlainText());
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: registerTemplateHelper: Registering template {0} on {1} for verification",
new Object [] { template.getTemplateName(), cloudName });
new Object[]{template.getTemplateName(), cloudName});
if (cloudTemplates == null) {
cloudTemplates = new HashMap<String, String>();
}
cloudTemplates.put(template.getTemplateName(), cloudName);
}
/**
* Register a cloud for verification
* @param cloudName
* @param cloudName
*/
public static void registerCloud(final String cloudName) {
LOGGER.log(Level.INFO, "AzureVMCloudVerificationTask: registerCloud: Registering cloud {0} for verification",
cloudName);
synchronized(cloudNamesLock) {
cloudName);
synchronized (cloudNamesLock) {
if (cloudNames == null) {
cloudNames = new HashSet<String>();
}
@ -299,9 +300,10 @@ public final class AzureVMCloudVerificationTask extends AsyncPeriodicWork {
public AzureVMCloud getCloud(final String cloudName) {
return Jenkins.getInstance() == null ? null : (AzureVMCloud) Jenkins.getInstance().getCloud(cloudName);
}
/**
* Retrieve the verification task worker. Can be used to force work
* Retrieve the verification task worker. Can be used to force work
*
* @return The AzureVMCloudVerificationTask worker class
*/
public static AzureVMCloudVerificationTask get() {

View File

@ -69,8 +69,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Logger;
import com.microsoft.windowsazure.Configuration;
import com.microsoft.windowsazure.exception.ServiceException;
import com.microsoft.azure.exceptions.AzureCloudException;
@ -111,13 +109,13 @@ public class AzureVMManagementServiceDelegate {
private static final Logger LOGGER = Logger.getLogger(AzureVMManagementServiceDelegate.class.getName());
private static final String EMBEDDED_TEMPLATE_FILENAME = "/referenceImageTemplate.json";
private static final String EMBEDDED_TEMPLATE_WITH_SCRIPT_FILENAME = "/referenceImageTemplateWithScript.json";
private static final String EMBEDDED_TEMPLATE_IMAGE_FILENAME = "/customImageTemplate.json";
private static final String EMBEDDED_TEMPLATE_IMAGE_WITH_SCRIPT_FILENAME = "/customImageTemplateWithScript.json";
private static final String VIRTUAL_NETWORK_TEMPLATE_FRAGMENT_FILENAME = "/virtualNetworkFragment.json";
private static final String IMAGE_CUSTOM_REFERENCE = "custom";
@ -127,15 +125,16 @@ public class AzureVMManagementServiceDelegate {
private static final Map<String, String> AVAILABLE_LOCATIONS_STD = getAvailableLocationsStandard();
private static final Map<String, String> AVAILABLE_LOCATIONS_CHINA = getAvailableLocationsChina();
private static final Map<String, String> AVAILABLE_LOCATIONS_ALL = getAvailableLocationsAll();
/**
* Creates a new deployment of VMs based on the provided template
*
* @param template Template to deploy
* @param numberOfAgents Number of agents to create
* @return The base name for the VMs that were created
* @throws AzureCloudException
* @throws AzureCloudException
*/
public static AzureVMDeploymentInfo createDeployment(final AzureVMAgentTemplate template, final int numberOfAgents)
throws AzureCloudException {
@ -151,47 +150,50 @@ public class AzureVMManagementServiceDelegate {
final String deploymentName = AzureUtil.getDeploymentName(template.getTemplateName(), timestamp);
final String vmBaseName = AzureUtil.getVMBaseName(template.getTemplateName(), deploymentName, template.getOsType(), numberOfAgents);
final String locationName = getLocationName(template.getLocation());
if (!template.getResourceGroupName().matches(Constants.DEFAULT_RESOURCE_GROUP_PATTERN)) {
LOGGER.log(Level.SEVERE,
"AzureVMManagementServiceDelegate: createDeployment: ResourceGroup Name {0} is invalid. It should be 1-64 alphanumeric characters",
new Object[]{template.getResourceGroupName()});
throw new Exception("ResourceGroup Name is invalid");
}
final String resourceGroupName = template.getResourceGroupName();
LOGGER.log(Level.INFO,
"AzureVMManagementServiceDelegate: createDeployment: Creating a new deployment {0} with VM base name {1}",
new Object[] { deploymentName, vmBaseName} );
new Object[]{deploymentName, vmBaseName});
client.getResourceGroupsOperations().createOrUpdate(
resourceGroupName,
new ResourceGroup(locationName));
final Deployment deployment = new Deployment();
final DeploymentProperties properties = new DeploymentProperties();
deployment.setProperties(properties);
final InputStream embeddedTemplate;
final boolean useCustomScriptExtension =
template.getOsType().equals(Constants.OS_TYPE_WINDOWS) && !StringUtils.isBlank(template.getInitScript()) &&
template.getAgentLaunchMethod().equals(Constants.LAUNCH_METHOD_JNLP);
final boolean useCustomScriptExtension
= template.getOsType().equals(Constants.OS_TYPE_WINDOWS) && !StringUtils.isBlank(template.getInitScript())
&& template.getAgentLaunchMethod().equals(Constants.LAUNCH_METHOD_JNLP);
// check if a custom image id has been provided otherwise work with publisher and offer
if (template.getImageReferenceType().equals(IMAGE_CUSTOM_REFERENCE)) {
if (useCustomScriptExtension) {
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: createDeployment: Use embedded deployment template {0}", EMBEDDED_TEMPLATE_IMAGE_WITH_SCRIPT_FILENAME);
embeddedTemplate
= AzureVMManagementServiceDelegate.class.getResourceAsStream(EMBEDDED_TEMPLATE_IMAGE_WITH_SCRIPT_FILENAME);
}
else {
= AzureVMManagementServiceDelegate.class.getResourceAsStream(EMBEDDED_TEMPLATE_IMAGE_WITH_SCRIPT_FILENAME);
} else {
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: createDeployment: Use embedded deployment template (with script) {0}", EMBEDDED_TEMPLATE_IMAGE_FILENAME);
embeddedTemplate
= AzureVMManagementServiceDelegate.class.getResourceAsStream(EMBEDDED_TEMPLATE_IMAGE_FILENAME);
= AzureVMManagementServiceDelegate.class.getResourceAsStream(EMBEDDED_TEMPLATE_IMAGE_FILENAME);
}
} else {
if (useCustomScriptExtension) {
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: createDeployment: Use embedded deployment template (with script) {0}", EMBEDDED_TEMPLATE_WITH_SCRIPT_FILENAME);
embeddedTemplate
= AzureVMManagementServiceDelegate.class.getResourceAsStream(EMBEDDED_TEMPLATE_WITH_SCRIPT_FILENAME);
}
else {
= AzureVMManagementServiceDelegate.class.getResourceAsStream(EMBEDDED_TEMPLATE_WITH_SCRIPT_FILENAME);
} else {
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: createDeployment: Use embedded deployment template {0}", EMBEDDED_TEMPLATE_FILENAME);
embeddedTemplate
= AzureVMManagementServiceDelegate.class.getResourceAsStream(EMBEDDED_TEMPLATE_FILENAME);
= AzureVMManagementServiceDelegate.class.getResourceAsStream(EMBEDDED_TEMPLATE_FILENAME);
}
}
@ -203,7 +205,7 @@ public class AzureVMManagementServiceDelegate {
count.put("type", "int");
count.put("defaultValue", numberOfAgents);
ObjectNode.class.cast(tmp.get("parameters")).replace("count", count);
ObjectNode.class.cast(tmp.get("variables")).put("vmName", vmBaseName);
ObjectNode.class.cast(tmp.get("variables")).put("location", locationName);
@ -226,7 +228,7 @@ public class AzureVMManagementServiceDelegate {
if (StringUtils.isNotBlank(template.getImage())) {
ObjectNode.class.cast(tmp.get("variables")).put("image", template.getImage());
}
// If using the custom script extension (vs. SSH) to startup the powershell scripts,
// add variables for that and upload the init script to the storage account
if (useCustomScriptExtension) {
@ -235,14 +237,14 @@ public class AzureVMManagementServiceDelegate {
ArrayNode clientSecretsNode = ObjectNode.class.cast(tmp.get("variables")).putArray("clientSecrets");
for (int i = 0; i < numberOfAgents; i++) {
clientSecretsNode.add(
JnlpSlaveAgentProtocol.SLAVE_SECRET.mac(String.format("%s%d", vmBaseName, i)));
JnlpSlaveAgentProtocol.SLAVE_SECRET.mac(String.format("%s%d", vmBaseName, i)));
}
// Upload the startup script to blob storage
String scriptName = String.format("%s%s", deploymentName, "init.ps1");
String scriptUri = uploadCustomScript(template, scriptName);
ObjectNode.class.cast(tmp.get("variables")).put("startupScriptURI", scriptUri);
ObjectNode.class.cast(tmp.get("variables")).put("startupScriptName", scriptName);
String storageAccountKey = ServiceDelegateHelper.getStorageManagementClient(config).getStorageAccountsOperations().listKeys(
template.getResourceGroupName(), template.getStorageAccountName())
.getStorageAccountKeys().getKey1();
@ -250,7 +252,7 @@ public class AzureVMManagementServiceDelegate {
final ObjectNode storageAccountKeyNode = mapper.createObjectNode();
storageAccountKeyNode.put("type", "secureString");
storageAccountKeyNode.put("defaultValue", storageAccountKey);
// Add the storage account key
ObjectNode.class.cast(tmp.get("parameters")).replace("storageAccountKey", storageAccountKeyNode);
}
@ -258,7 +260,7 @@ public class AzureVMManagementServiceDelegate {
ObjectNode.class.cast(tmp.get("variables")).put("vmSize", template.getVirtualMachineSize());
// Grab the username/pass
StandardUsernamePasswordCredentials creds = AzureUtil.getCredentials(template.getCredentialsId());
ObjectNode.class.cast(tmp.get("variables")).put("adminUsername", creds.getUsername());
ObjectNode.class.cast(tmp.get("variables")).put("adminPassword", creds.getPassword().getPlainText());
@ -271,29 +273,28 @@ public class AzureVMManagementServiceDelegate {
if (StringUtils.isNotBlank(template.getVirtualNetworkName())) {
ObjectNode.class.cast(tmp.get("variables")).put("virtualNetworkName", template.getVirtualNetworkName());
ObjectNode.class.cast(tmp.get("variables")).put("subnetName", template.getSubnetName());
}
else {
} else {
// Add the definition of the vnet and subnet into the template
final String virtualNetworkName = Constants.DEFAULT_VNET_NAME;
final String subnetName = Constants.DEFAULT_SUBNET_NAME;
ObjectNode.class.cast(tmp.get("variables")).put("virtualNetworkName", virtualNetworkName);
ObjectNode.class.cast(tmp.get("variables")).put("subnetName", subnetName);
// Read the vnet fragment
InputStream fragmentStream =
AzureVMManagementServiceDelegate.class.getResourceAsStream(VIRTUAL_NETWORK_TEMPLATE_FRAGMENT_FILENAME);
InputStream fragmentStream
= AzureVMManagementServiceDelegate.class.getResourceAsStream(VIRTUAL_NETWORK_TEMPLATE_FRAGMENT_FILENAME);
final JsonNode virtualNetworkFragment = mapper.readTree(fragmentStream);
// Add the virtual network fragment
ArrayNode.class.cast(tmp.get("resources")).add(virtualNetworkFragment);
// Because we created/updated this in the template, we need to add the appropriate
// dependsOn node to the networkInterface
// Microsoft.Network/virtualNetworks/<vnet name>
// Find the network interfaces node
ArrayNode resourcesNodes = ArrayNode.class.cast(tmp.get("resources"));
Iterator<JsonNode> resourcesNodesIter = resourcesNodes.elements();
while(resourcesNodesIter.hasNext()) {
while (resourcesNodesIter.hasNext()) {
JsonNode resourcesNode = resourcesNodesIter.next();
JsonNode typeNode = resourcesNode.get("type");
if (typeNode == null || !typeNode.asText().equals("Microsoft.Network/networkInterfaces")) {
@ -315,7 +316,7 @@ public class AzureVMManagementServiceDelegate {
AzureVMAgentCleanUpTask.registerDeployment(template.getAzureCloud().name, template.getResourceGroupName(), deploymentName);
// Create the deployment
client.getDeploymentsOperations().createOrUpdate(template.getResourceGroupName(), deploymentName, deployment);
return new AzureVMDeploymentInfo(deploymentName, vmBaseName, numberOfAgents);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "AzureVMManagementServiceDelegate: deployment: Unable to deploy", e);
@ -324,9 +325,10 @@ public class AzureVMManagementServiceDelegate {
throw new AzureCloudException(e);
}
}
/**
* Uploads the custom script for a template to blob storage
*
* @param template Template containing script to upload
* @return URI of script
*/
@ -342,7 +344,7 @@ public class AzureVMManagementServiceDelegate {
final StorageManagementClient storageClient = ServiceDelegateHelper.getStorageManagementClient(config);
rmClient.getResourceGroupsOperations().createOrUpdate(resourceGroupName, new ResourceGroup(location));
StorageAccountCreateParameters createParams = new StorageAccountCreateParameters();
createParams.setLocation(location);
createParams.setAccountType(AccountType.StandardLRS);
@ -352,10 +354,10 @@ public class AzureVMManagementServiceDelegate {
String storageAccountKey = storageClient.getStorageAccountsOperations().listKeys(resourceGroupName, targetStorageAccount)
.getStorageAccountKeys().getKey1();
String scriptText = template.getInitScript();
String blobURL = StorageServiceDelegate.uploadFileToStorage(
config, targetStorageAccount, storageAccountKey,
storageClient.getBaseUri().toString(), resourceGroupName, Constants.CONFIG_CONTAINER_NAME,
storageClient.getBaseUri().toString(), resourceGroupName, Constants.CONFIG_CONTAINER_NAME,
targetScriptName, scriptText.getBytes("UTF-8"));
return blobURL;
}
@ -399,17 +401,18 @@ public class AzureVMManagementServiceDelegate {
azureAgent.setPublicDNSName(pubIP.getDnsSettings().getFqdn());
azureAgent.setSshPort(Constants.DEFAULT_SSH_PORT);
LOGGER.log(Level.INFO, "Azure agent details:\nnodeName{0}\nadminUserName={1}\nshutdownOnIdle={2}\nretentionTimeInMin={3}\nlabels={4}",
new Object[] { azureAgent.getNodeName(), azureAgent.getVMCredentialsId(), azureAgent.isShutdownOnIdle(),
azureAgent.getRetentionTimeInMin(), azureAgent.getLabelString()});
LOGGER.log(Level.INFO, "Azure agent details:\nnodeName{0}\nadminUserName={1}\nshutdownOnIdle={2}\nretentionTimeInMin={3}\nlabels={4}",
new Object[]{azureAgent.getNodeName(), azureAgent.getVMCredentialsId(), azureAgent.isShutdownOnIdle(),
azureAgent.getRetentionTimeInMin(), azureAgent.getLabelString()});
}
/**
* Determines whether a virtual machine exists.
*
* @param configuration Configuration for the subscription
* @param vmName Name of the VM.
* @param resourceGroupName Resource group of the VM.
* @return
* @return
*/
private static boolean virtualMachineExists(final Configuration config, final String vmName, final String resourceGroupName) {
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: virtualMachineExists: check for {0}", vmName);
@ -434,6 +437,7 @@ public class AzureVMManagementServiceDelegate {
/**
* Determines whether a given agent exists.
*
* @param agent to check
* @return True if the agent exists, false otherwise
*/
@ -441,10 +445,9 @@ public class AzureVMManagementServiceDelegate {
try {
Configuration config = ServiceDelegateHelper.getConfiguration(agent);
return virtualMachineExists(config, agent.getNodeName(), agent.getResourceGroupName());
}
catch (Exception e) {
LOGGER.log(Level.INFO,
"AzureVMManagementServiceDelegate: virtualMachineExists: error while determining whether vm exists", e);
} catch (Exception e) {
LOGGER.log(Level.INFO,
"AzureVMManagementServiceDelegate: virtualMachineExists: error while determining whether vm exists", e);
return false;
}
}
@ -470,7 +473,7 @@ public class AzureVMManagementServiceDelegate {
+ "\tfound agent {0}\n"
+ "\tOS type {1}\n"
+ "\tnumber of executors {2}",
new Object[] { vmname, osType, template.getNoOfParallelJobs() });
new Object[]{vmname, osType, template.getNoOfParallelJobs()});
AzureVMCloud azureCloud = template.getAzureCloud();
@ -523,8 +526,10 @@ public class AzureVMManagementServiceDelegate {
}
/**
* Gets a map of available locations mapping display name -> name (usable in template)
* @return
* Gets a map of available locations mapping display name -> name (usable in
* template)
*
* @return
*/
private static Map<String, String> getAvailableLocationsStandard() {
final Map<String, String> locations = new HashMap<String, String>();
@ -547,55 +552,56 @@ public class AzureVMManagementServiceDelegate {
locations.put("West India", "westindia");
return locations;
}
private static Map<String, String> getAvailableLocationsChina() {
final Map<String, String> locations = new HashMap<String, String>();
locations.put("China North", "chinanorth");
locations.put("China East", "chinaeast");
return locations;
}
private static Map<String, String> getAvailableLocationsAll() {
final Map<String, String> locations = new HashMap<String, String>();
locations.putAll(getAvailableLocationsStandard());
locations.putAll(getAvailableLocationsChina());
return locations;
}
/**
* Creates a map containing location -> vm role size list.
* This is hard coded and should be removed eventually once a transition to
* the 1.0.0 SDK is made
* @return New map
* Creates a map containing location -> vm role size list. This is hard
* coded and should be removed eventually once a transition to the 1.0.0 SDK
* is made
*
* @return New map
*/
private static Map<String, List<String>> getAvailableRoleSizes() {
final Map<String, List<String>> sizes = new HashMap<String, List<String>>();
sizes.put("East US", Arrays.asList(new String[] {"A10","A11","A5","A6","A7","A8","A9","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s"}));
sizes.put("West US", Arrays.asList(new String[] {"A10","A11","A5","A6","A7","A8","A9","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s","Standard_G1","Standard_G2","Standard_G3","Standard_G4","Standard_G5","Standard_GS1","Standard_GS2","Standard_GS3","Standard_GS4","Standard_GS5"}));
sizes.put("South Central US", Arrays.asList(new String[] {"A10","A11","A5","A6","A7","A8","A9","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s"}));
sizes.put("Central US", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s"}));
sizes.put("North Central US", Arrays.asList(new String[] {"A10","A11","A5","A6","A7","A8","A9","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1_v2","Standard_DS11_v2","Standard_DS12_v2","Standard_DS13_v2","Standard_DS14_v2","Standard_DS2_v2","Standard_DS3_v2","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s"}));
sizes.put("East US 2", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s","Standard_G1","Standard_G2","Standard_G3","Standard_G4","Standard_G5","Standard_GS1","Standard_GS2","Standard_GS3","Standard_GS4","Standard_GS5"}));
sizes.put("North Europe", Arrays.asList(new String[] {"A10","A11","A5","A6","A7","A8","A9","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s"}));
sizes.put("West Europe", Arrays.asList(new String[] {"A10","A11","A5","A6","A7","A8","A9","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s","Standard_G1","Standard_G2","Standard_G3","Standard_G4","Standard_G5","Standard_GS1","Standard_GS2","Standard_GS3","Standard_GS4","Standard_GS5"}));
sizes.put("Southeast Asia", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s","Standard_G1","Standard_G2","Standard_G3","Standard_G4","Standard_G5","Standard_GS1","Standard_GS2","Standard_GS3","Standard_GS4","Standard_GS5"}));
sizes.put("East Asia", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS11","Standard_DS12","Standard_DS13","Standard_DS14","Standard_DS2","Standard_DS3","Standard_DS4","Standard_F1","Standard_F16","Standard_F2","Standard_F4","Standard_F8"}));
sizes.put("Japan West", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s"}));
sizes.put("Japan East", Arrays.asList(new String[] {"A10","A11","A5","A6","A7","A8","A9","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s"}));
sizes.put("Brazil South", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1_v2","Standard_DS11_v2","Standard_DS12_v2","Standard_DS13_v2","Standard_DS14_v2","Standard_DS2_v2","Standard_DS3_v2","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s"}));
sizes.put("Australia Southeast", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s"}));
sizes.put("Australia East", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s","Standard_G1","Standard_G2","Standard_G3","Standard_G4","Standard_G5","Standard_GS1","Standard_GS2","Standard_GS3","Standard_GS4","Standard_GS5"}));
sizes.put("Central India", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1_v2","Standard_D11_v2","Standard_D12_v2","Standard_D13_v2","Standard_D14_v2","Standard_D2_v2","Standard_D3_v2","Standard_D4_v2","Standard_D5_v2","Standard_DS1_v2","Standard_DS11_v2","Standard_DS12_v2","Standard_DS13_v2","Standard_DS14_v2","Standard_DS2_v2","Standard_DS3_v2","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s"}));
sizes.put("South India", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1_v2","Standard_D11_v2","Standard_D12_v2","Standard_D13_v2","Standard_D14_v2","Standard_D2_v2","Standard_D3_v2","Standard_D4_v2","Standard_D5_v2","Standard_DS1_v2","Standard_DS11_v2","Standard_DS12_v2","Standard_DS13_v2","Standard_DS14_v2","Standard_DS2_v2","Standard_DS3_v2","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s"}));
sizes.put("West India", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1_v2","Standard_D11_v2","Standard_D12_v2","Standard_D13_v2","Standard_D14_v2","Standard_D2_v2","Standard_D3_v2","Standard_D4_v2","Standard_D5_v2","Standard_F1","Standard_F16","Standard_F2","Standard_F4","Standard_F8"}));
sizes.put("East US", Arrays.asList(new String[]{"A10", "A11", "A5", "A6", "A7", "A8", "A9", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s"}));
sizes.put("West US", Arrays.asList(new String[]{"A10", "A11", "A5", "A6", "A7", "A8", "A9", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s", "Standard_G1", "Standard_G2", "Standard_G3", "Standard_G4", "Standard_G5", "Standard_GS1", "Standard_GS2", "Standard_GS3", "Standard_GS4", "Standard_GS5"}));
sizes.put("South Central US", Arrays.asList(new String[]{"A10", "A11", "A5", "A6", "A7", "A8", "A9", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s"}));
sizes.put("Central US", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s"}));
sizes.put("North Central US", Arrays.asList(new String[]{"A10", "A11", "A5", "A6", "A7", "A8", "A9", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1_v2", "Standard_DS11_v2", "Standard_DS12_v2", "Standard_DS13_v2", "Standard_DS14_v2", "Standard_DS2_v2", "Standard_DS3_v2", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s"}));
sizes.put("East US 2", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s", "Standard_G1", "Standard_G2", "Standard_G3", "Standard_G4", "Standard_G5", "Standard_GS1", "Standard_GS2", "Standard_GS3", "Standard_GS4", "Standard_GS5"}));
sizes.put("North Europe", Arrays.asList(new String[]{"A10", "A11", "A5", "A6", "A7", "A8", "A9", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s"}));
sizes.put("West Europe", Arrays.asList(new String[]{"A10", "A11", "A5", "A6", "A7", "A8", "A9", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s", "Standard_G1", "Standard_G2", "Standard_G3", "Standard_G4", "Standard_G5", "Standard_GS1", "Standard_GS2", "Standard_GS3", "Standard_GS4", "Standard_GS5"}));
sizes.put("Southeast Asia", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s", "Standard_G1", "Standard_G2", "Standard_G3", "Standard_G4", "Standard_G5", "Standard_GS1", "Standard_GS2", "Standard_GS3", "Standard_GS4", "Standard_GS5"}));
sizes.put("East Asia", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS11", "Standard_DS12", "Standard_DS13", "Standard_DS14", "Standard_DS2", "Standard_DS3", "Standard_DS4", "Standard_F1", "Standard_F16", "Standard_F2", "Standard_F4", "Standard_F8"}));
sizes.put("Japan West", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s"}));
sizes.put("Japan East", Arrays.asList(new String[]{"A10", "A11", "A5", "A6", "A7", "A8", "A9", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s"}));
sizes.put("Brazil South", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1_v2", "Standard_DS11_v2", "Standard_DS12_v2", "Standard_DS13_v2", "Standard_DS14_v2", "Standard_DS2_v2", "Standard_DS3_v2", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s"}));
sizes.put("Australia Southeast", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s"}));
sizes.put("Australia East", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s", "Standard_G1", "Standard_G2", "Standard_G3", "Standard_G4", "Standard_G5", "Standard_GS1", "Standard_GS2", "Standard_GS3", "Standard_GS4", "Standard_GS5"}));
sizes.put("Central India", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1_v2", "Standard_D11_v2", "Standard_D12_v2", "Standard_D13_v2", "Standard_D14_v2", "Standard_D2_v2", "Standard_D3_v2", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1_v2", "Standard_DS11_v2", "Standard_DS12_v2", "Standard_DS13_v2", "Standard_DS14_v2", "Standard_DS2_v2", "Standard_DS3_v2", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s"}));
sizes.put("South India", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1_v2", "Standard_D11_v2", "Standard_D12_v2", "Standard_D13_v2", "Standard_D14_v2", "Standard_D2_v2", "Standard_D3_v2", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1_v2", "Standard_DS11_v2", "Standard_DS12_v2", "Standard_DS13_v2", "Standard_DS14_v2", "Standard_DS2_v2", "Standard_DS3_v2", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s"}));
sizes.put("West India", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1_v2", "Standard_D11_v2", "Standard_D12_v2", "Standard_D13_v2", "Standard_D14_v2", "Standard_D2_v2", "Standard_D3_v2", "Standard_D4_v2", "Standard_D5_v2", "Standard_F1", "Standard_F16", "Standard_F2", "Standard_F4", "Standard_F8"}));
// China sizes, may not be exact
sizes.put("China North", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS1_v2","Standard_DS11","Standard_DS11_v2","Standard_DS12","Standard_DS12_v2","Standard_DS13","Standard_DS13_v2","Standard_DS14","Standard_DS14_v2","Standard_DS2","Standard_DS2_v2","Standard_DS3","Standard_DS3_v2","Standard_DS4","Standard_DS4_v2","Standard_DS5_v2","Standard_F1","Standard_F16","Standard_F16s","Standard_F1s","Standard_F2","Standard_F2s","Standard_F4","Standard_F4s","Standard_F8","Standard_F8s","Standard_G1","Standard_G2","Standard_G3","Standard_G4","Standard_G5","Standard_GS1","Standard_GS2","Standard_GS3","Standard_GS4","Standard_GS5"}));
sizes.put("China East", Arrays.asList(new String[] {"A5","A6","A7","Basic_A0","Basic_A1","Basic_A2","Basic_A3","Basic_A4","ExtraLarge","ExtraSmall","Large","Medium","Small","Standard_D1","Standard_D1_v2","Standard_D11","Standard_D11_v2","Standard_D12","Standard_D12_v2","Standard_D13","Standard_D13_v2","Standard_D14","Standard_D14_v2","Standard_D2","Standard_D2_v2","Standard_D3","Standard_D3_v2","Standard_D4","Standard_D4_v2","Standard_D5_v2","Standard_DS1","Standard_DS11","Standard_DS12","Standard_DS13","Standard_DS14","Standard_DS2","Standard_DS3","Standard_DS4","Standard_F1","Standard_F16","Standard_F2","Standard_F4","Standard_F8"}));
sizes.put("China North", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS1_v2", "Standard_DS11", "Standard_DS11_v2", "Standard_DS12", "Standard_DS12_v2", "Standard_DS13", "Standard_DS13_v2", "Standard_DS14", "Standard_DS14_v2", "Standard_DS2", "Standard_DS2_v2", "Standard_DS3", "Standard_DS3_v2", "Standard_DS4", "Standard_DS4_v2", "Standard_DS5_v2", "Standard_F1", "Standard_F16", "Standard_F16s", "Standard_F1s", "Standard_F2", "Standard_F2s", "Standard_F4", "Standard_F4s", "Standard_F8", "Standard_F8s", "Standard_G1", "Standard_G2", "Standard_G3", "Standard_G4", "Standard_G5", "Standard_GS1", "Standard_GS2", "Standard_GS3", "Standard_GS4", "Standard_GS5"}));
sizes.put("China East", Arrays.asList(new String[]{"A5", "A6", "A7", "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", "ExtraLarge", "ExtraSmall", "Large", "Medium", "Small", "Standard_D1", "Standard_D1_v2", "Standard_D11", "Standard_D11_v2", "Standard_D12", "Standard_D12_v2", "Standard_D13", "Standard_D13_v2", "Standard_D14", "Standard_D14_v2", "Standard_D2", "Standard_D2_v2", "Standard_D3", "Standard_D3_v2", "Standard_D4", "Standard_D4_v2", "Standard_D5_v2", "Standard_DS1", "Standard_DS11", "Standard_DS12", "Standard_DS13", "Standard_DS14", "Standard_DS2", "Standard_DS3", "Standard_DS4", "Standard_F1", "Standard_F16", "Standard_F2", "Standard_F4", "Standard_F8"}));
return sizes;
}
/**
* Gets map of Azure datacenter locations which supports Persistent VM role.
* Today this is hardcoded pulling from the array, because the old form of
@ -607,11 +613,11 @@ public class AzureVMManagementServiceDelegate {
}
return AVAILABLE_LOCATIONS_STD;
}
/**
* Gets list of virtual machine sizes.
* Currently hardcoded because the old vm size API does not support
* the new method of authentication
* Gets list of virtual machine sizes. Currently hardcoded because the old
* vm size API does not support the new method of authentication
*
* @param location Location to obtain VM sizes for
*/
public static List<String> getVMSizes(final String location) {
@ -623,38 +629,47 @@ public class AzureVMManagementServiceDelegate {
*
* @param servicePrincipal
* @param resourceGroupName
* @param maxVMLimit
* @param timeout
* @return
*/
public static String verifyConfiguration(
final AzureCredentials.ServicePrincipal servicePrincipal,
final String resourceGroupName) {
if (servicePrincipal.isBlank() || StringUtils.isBlank(resourceGroupName)) {
return Messages.Azure_GC_Template_Val_Profile_Missing();
} else {
try {
// Load up the configuration now and do a live verification
Configuration config = ServiceDelegateHelper.loadConfiguration(servicePrincipal);
if (!verifyConfiguration(config, resourceGroupName).equals(Constants.OP_SUCCESS)) {
final String resourceGroupName, final String maxVMLimit, final String timeOut) {
try {
Configuration config = ServiceDelegateHelper.loadConfiguration(servicePrincipal);
if(!AzureUtil.isValidTimeOut(timeOut))
return "Invalid Timeout, Should be a positive number, minimum value "+Constants.DEFAULT_DEPLOYMENT_TIMEOUT_SEC;
if(!AzureUtil.isValidResourceGroupName(resourceGroupName))
return "Error: "+Messages.Azure_GC_Template_ResourceGroupName_Err();
if(!AzureUtil.isValidMAxVMLimit(maxVMLimit))
return "Invalid Limit, Should be a positive number, e.g. "+Constants.DEFAULT_MAX_VM_LIMIT;
if (AzureUtil.isValidTimeOut(timeOut) && AzureUtil.isValidMAxVMLimit(maxVMLimit)
&& AzureUtil.isValidResourceGroupName(resourceGroupName)) {
String result = verifyConfiguration(config, resourceGroupName);
if (!result.matches(Constants.OP_SUCCESS))
return Messages.Azure_GC_Template_Val_Profile_Err();
}
}
catch (Exception e) {
LOGGER.log(Level.SEVERE, "Error validating profile", e);
return Messages.Azure_GC_Template_Val_Profile_Err();
}
}catch (Exception e) {
LOGGER.log(Level.SEVERE, "Error validating profile", e);
return Messages.Azure_GC_Template_Val_Profile_Err();
}
return Constants.OP_SUCCESS;
}
public static String verifyConfiguration(final Configuration config, final String resourceGroupName) {
Callable<String> task = new Callable<String>() {
@Override
public String call() throws Exception {
ServiceDelegateHelper.getStorageManagementClient(config).getStorageAccountsOperations().
checkNameAvailability("CI_SYSTEM");
checkNameAvailability("CI_SYSTEM");
return Constants.OP_SUCCESS;
}
};
@ -697,14 +712,15 @@ public class AzureVMManagementServiceDelegate {
}
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: getVirtualMachineStatus:\n\tPowerState: {0}\n\tProvisioning: {1}",
new Object[] { powerstatus, provisioning });
new Object[]{powerstatus, provisioning});
return "succeeded".equalsIgnoreCase(provisioning)
? powerstatus.toUpperCase() : Constants.PROVISIONING_OR_DEPROVISIONING_VM_STATUS;
}
/**
* Checks if VM is reachable and in a valid state to connect (or getting ready to do so).
* Checks if VM is reachable and in a valid state to connect (or getting
* ready to do so).
*
* @param agent
* @return
@ -715,16 +731,16 @@ public class AzureVMManagementServiceDelegate {
String status = getVirtualMachineStatus(config, agent.getNodeName(), agent.getResourceGroupName());
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: isVMAliveOrHealthy: status {0}", status);
return !(Constants.PROVISIONING_OR_DEPROVISIONING_VM_STATUS.equalsIgnoreCase(status)
|| Constants.STOPPING_VM_STATUS.equalsIgnoreCase(status)
|| Constants.STOPPED_VM_STATUS.equalsIgnoreCase(status)
|| Constants.DEALLOCATED_VM_STATUS.equalsIgnoreCase(status));
|| Constants.STOPPING_VM_STATUS.equalsIgnoreCase(status)
|| Constants.STOPPED_VM_STATUS.equalsIgnoreCase(status)
|| Constants.DEALLOCATED_VM_STATUS.equalsIgnoreCase(status));
}
/**
* Retrieves count of virtual machine in a azure subscription. This count
* is based off of the VMs that the current credential set has access to. It also
* does not deal with the classic, model. So keep this in mind.
*
* Retrieves count of virtual machine in a azure subscription. This count is
* based off of the VMs that the current credential set has access to. It
* also does not deal with the classic, model. So keep this in mind.
*
* @param config Subscription configuration
* @return Total VM count
* @throws Exception
@ -758,15 +774,14 @@ public class AzureVMManagementServiceDelegate {
*/
public static void shutdownVirtualMachine(final AzureVMAgent agent) {
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: shutdownVirtualMachine: called for {0}",
agent.getNodeName() );
agent.getNodeName());
try {
ServiceDelegateHelper.getComputeManagementClient(agent).
getVirtualMachinesOperations().powerOff(agent.getResourceGroupName(), agent.getNodeName());
}
catch (Exception e) {
getVirtualMachinesOperations().powerOff(agent.getResourceGroupName(), agent.getNodeName());
} catch (Exception e) {
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: provision: could not terminate or shutdown {0}, {1}",
new Object[] {agent.getNodeName(), e});
new Object[]{agent.getNodeName(), e});
}
}
@ -784,12 +799,13 @@ public class AzureVMManagementServiceDelegate {
/**
* Terminates a virtual machine
*
* @param config Azure configuration
* @param vmName VM name
* @param resourceGroupName Resource group containing the VM
* @throws Exception
* @throws Exception
*/
public static void terminateVirtualMachine(final Configuration config, final String vmName,
public static void terminateVirtualMachine(final Configuration config, final String vmName,
final String resourceGroupName) throws Exception {
try {
try {
@ -797,34 +813,34 @@ public class AzureVMManagementServiceDelegate {
final ComputeManagementClient client = ServiceDelegateHelper.getComputeManagementClient(config);
List<URI> diskUrisToRemove = new ArrayList<URI>();
StorageProfile storageProfile =
client.getVirtualMachinesOperations().get(resourceGroupName, vmName).getVirtualMachine().getStorageProfile();
StorageProfile storageProfile
= client.getVirtualMachinesOperations().get(resourceGroupName, vmName).getVirtualMachine().getStorageProfile();
// Remove the OS disks
diskUrisToRemove.add(new URI(storageProfile.getOSDisk().getVirtualHardDisk().getUri()));
// TODO: Remove data disks or add option to do so?
// Remove the VM
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: terminateVirtualMachine: Removing virtual machine {0}", vmName);
client.getVirtualMachinesOperations().delete(resourceGroupName, vmName);
// Now remove the disks
for (URI diskUri : diskUrisToRemove) {
// Obtain container, storage account, and blob name
String storageAccountName = diskUri.getHost().split("\\.")[0];
String containerName = PathUtility.getContainerNameFromUri(diskUri, false);
String blobName = PathUtility.getBlobNameFromURI(diskUri, false);
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: terminateVirtualMachine: Removing disk blob {0}, in container {1} of storage account {2}",
new Object [] { blobName, containerName, storageAccountName } );
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: terminateVirtualMachine: Removing disk blob {0}, in container {1} of storage account {2}",
new Object[]{blobName, containerName, storageAccountName});
final StorageManagementClient storageClient = ServiceDelegateHelper.getStorageManagementClient(config);
StorageAccountKeys storageKeys =
storageClient.getStorageAccountsOperations().listKeys(resourceGroupName, storageAccountName).getStorageAccountKeys();
StorageAccountKeys storageKeys
= storageClient.getStorageAccountsOperations().listKeys(resourceGroupName, storageAccountName).getStorageAccountKeys();
URI blobURI = storageClient.getStorageAccountsOperations().getProperties(resourceGroupName, storageAccountName).getStorageAccount().getPrimaryEndpoints().getBlob();
CloudBlobContainer container = StorageServiceDelegate.getBlobContainerReference(
storageAccountName, storageKeys.getKey1(), blobURI.toString(), containerName);
storageAccountName, storageKeys.getKey1(), blobURI.toString(), containerName);
container.getBlockBlobReference(blobName).deleteIfExists();
}
// Also remove the init script (if it exists)
}
} catch (ExecutionException ee) {
@ -863,16 +879,17 @@ public class AzureVMManagementServiceDelegate {
}
/**
* Remove the IP name
* Remove the IP name
*
* @param config
* @param resourceGroupName
* @param vmName
* @throws AzureCloudException
* We probably should record and pass in NIC/IP names.
* Also, if we go away from 1 public IP address per system, then we will need to update this.
*
* @throws AzureCloudException We probably should record and pass in NIC/IP
* names. Also, if we go away from 1 public IP address per system, then we
* will need to update this.
*
*/
private static void removeIPName(final Configuration config,
private static void removeIPName(final Configuration config,
final String resourceGroupName, final String vmName) throws AzureCloudException {
final NetworkResourceProviderClient client = ServiceDelegateHelper.getNetworkManagementClient(config);
@ -937,7 +954,7 @@ public class AzureVMManagementServiceDelegate {
} catch (Exception e) {
LOGGER.log(Level.INFO, "AzureVMManagementServiceDelegate: startVirtualMachine: got exception while "
+ "starting VM {0}. Will retry again after 30 seconds. Current retry count {1} / {2}\n",
new Object[] { agent.getNodeName(), retryCount, Constants.MAX_PROV_RETRIES });
new Object[]{agent.getNodeName(), retryCount, Constants.MAX_PROV_RETRIES});
if (retryCount > Constants.MAX_PROV_RETRIES) {
throw e;
} else {
@ -976,17 +993,18 @@ public class AzureVMManagementServiceDelegate {
}
return null;
}
/**
* Gets a final location name from a display name location.
*
* @param location
* @return
* @return
*/
private static String getLocationName(String location) {
if (AVAILABLE_LOCATIONS_ALL.containsKey(location)) {
return AVAILABLE_LOCATIONS_ALL.get(location);
}
return null;
}
@ -1043,21 +1061,20 @@ public class AzureVMManagementServiceDelegate {
List<String> errors = new ArrayList<String>();
Configuration config = null;
// Load configuration
try {
config = ServiceDelegateHelper.loadConfiguration(servicePrincipal);
String validationResult;
// Verify basic info about the template
//Verify number of parallel jobs
validationResult = verifyNoOfExecutors(noOfParallelJobs);
addValidationResultIfFailed(validationResult, errors);
if (returnOnSingleError && errors.size() > 0) {
return errors;
}
validationResult = verifyRetentionTime(retentionTimeInMin);
addValidationResultIfFailed(validationResult, errors);
if (returnOnSingleError && errors.size() > 0) {
@ -1065,14 +1082,14 @@ public class AzureVMManagementServiceDelegate {
}
//verify password
String adminPassword="";
String adminPassword = "";
try {
StandardUsernamePasswordCredentials creds = AzureUtil.getCredentials(credentialsId);
adminPassword = creds.getPassword().getPlainText();
} catch(AzureCloudException e) {
} catch (AzureCloudException e) {
LOGGER.log(Level.SEVERE, "Could not load the VM credentials", e);
}
validationResult = verifyAdminPassword(adminPassword);
addValidationResultIfFailed(validationResult, errors);
if (returnOnSingleError && errors.size() > 0) {
@ -1091,7 +1108,7 @@ public class AzureVMManagementServiceDelegate {
if (returnOnSingleError && errors.size() > 0) {
return errors;
}
validationResult = verifyLocation(location, servicePrincipal.serviceManagementURL);
addValidationResultIfFailed(validationResult, errors);
if (returnOnSingleError && errors.size() > 0) {
@ -1170,6 +1187,8 @@ public class AzureVMManagementServiceDelegate {
errors.add("Exception occured while validating temaplate " + executionException);
} catch (TimeoutException timeoutException) {
errors.add("Exception occured while validating temaplate " + timeoutException);
} catch (Exception others) {
errors.add(others.getMessage() + others);
}
}
} catch (InterruptedException interruptedException) {
@ -1258,7 +1277,7 @@ public class AzureVMManagementServiceDelegate {
// storage account is the same as the target storage account.
// The URI for he storage account should be https://<storageaccountname>.
// Parse that out and verify agaisnt the image storageAccountName
// Check that the image string is a URI by attempting to create
// a URI
final URI u;
@ -1279,8 +1298,7 @@ public class AzureVMManagementServiceDelegate {
return Messages.Azure_GC_Template_ImageURI_Not_Valid();
}
return Constants.OP_SUCCESS;
}
catch (Exception e) {
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Invalid virtual machine image", e);
return Messages.Azure_GC_Template_ImageURI_Not_Valid();
}
@ -1300,14 +1318,12 @@ public class AzureVMManagementServiceDelegate {
// to the empty string
if (imageVersion.equalsIgnoreCase("latest")) {
params.setVersion("");
}
else {
} else {
params.setVersion(imageVersion);
}
client.get(params);
}
catch (Exception e) {
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Invalid virtual machine image", e);
return Messages.Azure_GC_Template_ImageReference_Not_Valid(e.getMessage());
}
@ -1334,11 +1350,12 @@ public class AzureVMManagementServiceDelegate {
return Messages.Azure_GC_JVM_Option_Err();
}
}
/**
* Check the location. This location is the display name.
* @param location
* @return
*
* @param location
* @return
*/
private static String verifyLocation(final String location, final String serviceManagementURL) {
String locationName = getLocationName(location);
@ -1350,14 +1367,16 @@ public class AzureVMManagementServiceDelegate {
}
/**
* Verify the validity of the image parameters (does not verify actual values)
* Verify the validity of the image parameters (does not verify actual
* values)
*
* @param image
* @param osType
* @param imagePublisher
* @param imageOffer
* @param imageSku
* @param imageVersion
* @return
* @return
*/
private static String verifyImageParameters(
final String image,
@ -1376,8 +1395,7 @@ public class AzureVMManagementServiceDelegate {
Messages.Azure_GC_Template_ImageURI_Not_Valid();
}
return Constants.OP_SUCCESS;
}
else if (StringUtils.isNotBlank(imagePublisher)
} else if (StringUtils.isNotBlank(imagePublisher)
&& StringUtils.isNotBlank(imageOffer)
&& StringUtils.isNotBlank(imageSku)
&& StringUtils.isNotBlank(imageVersion)) {

View File

@ -76,8 +76,8 @@ public class AzureCredentials extends BaseStandardCredentials {
|| StringUtils.isBlank(oauth2TokenEndpoint.getPlainText())
|| StringUtils.isBlank(clientSecret.getPlainText());
}
public void Validate(String resourceGroupName) throws AzureCredentialsValidationException {
public boolean Validate(String resourceGroupName, String maxVMLimit, String deploymentTimeout) throws AzureCredentialsValidationException {
if (StringUtils.isBlank(subscriptionId.getPlainText())) {
throw new AzureCredentialsValidationException("Error: Subscription ID is missing");
}
@ -91,9 +91,12 @@ public class AzureCredentials extends BaseStandardCredentials {
throw new AzureCredentialsValidationException("Error: OAuth 2.0 Token Endpoint is missing");
}
String response = AzureVMManagementServiceDelegate.verifyConfiguration(this,resourceGroupName);
if (!Constants.OP_SUCCESS.equalsIgnoreCase(response))
String response = AzureVMManagementServiceDelegate.verifyConfiguration(this, resourceGroupName, maxVMLimit, deploymentTimeout);
if (!Constants.OP_SUCCESS.equalsIgnoreCase(response)) {
throw new AzureCredentialsValidationException(response);
}
return true;
}
}
@ -163,9 +166,11 @@ public class AzureCredentials extends BaseStandardCredentials {
@QueryParameter String oauth2TokenEndpoint,
@QueryParameter String serviceManagementURL) {
AzureCredentials.ServicePrincipal servicePrincipal = new AzureCredentials.ServicePrincipal(subscriptionId, clientId, clientSecret, oauth2TokenEndpoint, serviceManagementURL);
AzureCredentials.ServicePrincipal servicePrincipal = new AzureCredentials.ServicePrincipal(subscriptionId, clientId, clientSecret, oauth2TokenEndpoint,
serviceManagementURL);
try {
servicePrincipal.Validate(Constants.DEFAULT_RESOURCE_GROUP_NAME);
boolean result = servicePrincipal.Validate(Constants.DEFAULT_RESOURCE_GROUP_NAME, Integer.toString(Constants.DEFAULT_MAX_VM_LIMIT),
Integer.toString(Constants.DEFAULT_DEPLOYMENT_TIMEOUT_SEC));
} catch (AzureCredentialsValidationException e) {
return FormValidation.error(e.getMessage());
}

View File

@ -364,4 +364,36 @@ public class AzureUtil {
return creds;
}
/**
* Checks if the ResourceGroup Name is valid with Azure Standards
* @param resourceGroupName Resource Group Name
* @return true if the name is valid else return false
*/
public static boolean isValidResourceGroupName(String resourceGroupName) {
if (resourceGroupName.matches(Constants.DEFAULT_RESOURCE_GROUP_PATTERN))
return true;
return false;
}
/**
* Checks if the maximum virtual machines limit is valid
* @param maxVMLimit Maximum Virtual Limit
* @return true if it is valid else return false
*/
public static boolean isValidMAxVMLimit(String maxVMLimit) {
if (StringUtils.isBlank(maxVMLimit) || !maxVMLimit.matches(Constants.REG_EX_DIGIT))
return false;
return true;
}
/**
* Checks if the deployment Timeout is valid
* @param deploymentTimeout Deployment Timeout
* @return true if it is valid else return false
*/
public static boolean isValidTimeOut(String deploymentTimeout) {
if ((StringUtils.isBlank(deploymentTimeout) || !deploymentTimeout.matches(Constants.REG_EX_DIGIT)
|| Integer.parseInt(deploymentTimeout) < Constants.DEFAULT_DEPLOYMENT_TIMEOUT_SEC))
return false;
return true;
}
}

View File

@ -136,4 +136,6 @@ public class Constants {
public static final String DEFAULT_VNET_NAME = "jenkinsarm-vnet";
public static final String DEFAULT_SUBNET_NAME = "jenkinsarm-snet";
public static final String DEFAULT_RESOURCE_GROUP_PATTERN = "^[a-zA-Z0-9][a-zA-Z\\-_0-9]{0,62}[a-zA-Z0-9]$";
}

View File

@ -121,6 +121,6 @@
</div>
</f:entry>
<f:validateButton title="${%Verify_Template}" progress="${%Verifying_Template_MSG}" method="verifyConfiguration"
with="azureCredentialsId,resourceGroupName,templateName,labels,location,virtualMachineSize,storageAccountName,noOfParallelJobs,image,osType,imagePublisher,imageOffer,imageSku,imageVersion,agentLaunchMethod,initScript,credentialsId,virtualNetworkName,subnetName,retentionTimeInMin,jvmOptions" />
with="azureCredentialsId,resourceGroupName,maxVirtualMachinesLimit,deploymentTimeout,templateName,labels,location,virtualMachineSize,storageAccountName,noOfParallelJobs,image,osType,imagePublisher,imageOffer,imageSku,imageVersion,agentLaunchMethod,initScript,credentialsId,virtualNetworkName,subnetName,retentionTimeInMin,jvmOptions" />
</table>
</j:jelly>

View File

@ -18,7 +18,7 @@
<f:textbox default="${descriptor.getDefaultResourceGroupName()}" />
</f:entry>
<f:validateButton title="${%Verify_Configuration}" progress="${%Verifying}" method="verifyConfiguration"
with="azureCredentialsId,resourceGroupName" />
with="azureCredentialsId,maxVirtualMachinesLimit,deploymentTimeout,resourceGroupName" />
</f:section>
<f:entry title="${%Azure_Virtual_Machine_Template}" description="${%Azure_Virtual_Machine_Template_desc}">

View File

@ -13,6 +13,10 @@ Azure_GC_JVM_Option_Err=Error: Not a valid JVM Option. JVM options should start
Azure_GC_Template_Error_List=The following errors occurred while validating the template.
Azure_GC_Template_Val_Profile_Missing=The profile configuration is missing. Configure an Azure profile first.
Azure_GC_Template_ResourceGroupName_Err=Resource Group Name is invalid. Valid characters are Alphanumeric, underscore(_) and hyphen(-), length 2-64 \
\nAvoid having - or _ as the first or last character in name.
Azure_GC_Template_Deployment_Timeout_Err=Deployment Timeout value is invalid. Should be a positive integer and more than 1200 seconds.
Azure_GC_Template_Val_Profile_Err=Failed to validate the Azure profile. Verify the subscription Id, client Id and secret, OAUth 2.0 Token Endpoint and the URL information.
Azure_GC_Template_max_VM_Err=The current number of virtual machines in this Azure subscription is {0}, which is more than or equal to the default value {1} \
\n.Consider increasing Max Virtual Machines Limit value or delete existing virtual machines from your subscription.