You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2015/04/13 11:32:28 UTC
[2/2] jclouds-labs git commit: [JCLOUDS-873] Provided network
security group operations + some important fixes around live test execution
[JCLOUDS-873] Provided network security group operations + some important fixes around live test execution
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/29435e1c
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/29435e1c
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/29435e1c
Branch: refs/heads/master
Commit: 29435e1c35609fc2d1ae0878243c3af56a8297cc
Parents: eae8910
Author: fmartelli <fa...@gmail.com>
Authored: Mon Mar 30 17:51:04 2015 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon Apr 13 11:28:18 2015 +0200
----------------------------------------------------------------------
.../AzureManagementApiMetadata.java | 2 +-
.../jclouds/azurecompute/binders/RuleToXML.java | 6 +-
.../compute/AzureComputeServiceAdapter.java | 74 ++++-
.../AzureComputeServiceContextModule.java | 45 +--
.../AzureComputeSecurityGroupExtension.java | 126 +++++----
...ServiceAndVirtualNetworkThenCreateNodes.java | 2 +-
.../domain/NetworkSecurityGroup.java | 39 ++-
.../org/jclouds/azurecompute/domain/Rule.java | 96 ++++++-
.../features/NetworkSecurityGroupApi.java | 95 +++++--
.../util/ConflictManagementPredicate.java | 185 +++++++++----
.../xml/NetworkSecurityGroupHandler.java | 7 +-
.../jclouds/azurecompute/xml/RuleHandler.java | 20 +-
.../AzureComputeServiceAdapterLiveTest.java | 30 +-
.../AzureComputeServiceContextLiveTest.java | 25 +-
.../features/AffinityGroupApiLiveTest.java | 4 +-
.../features/DeploymentApiLiveTest.java | 12 +-
.../NetworkSecurityGroupApiLiveTest.java | 226 +++++++++++++++
.../NetworkSecurityGroupApiMockTest.java | 277 +++++++++++++++++++
.../features/TrafficManagerApiLiveTest.java | 10 +-
.../features/VirtualMachineApiLiveTest.java | 46 +--
.../features/VirtualNetworkApiLiveTest.java | 15 +-
.../AbstractAzureComputeApiLiveTest.java | 9 +-
.../internal/BaseAzureComputeApiLiveTest.java | 31 ++-
.../ListNetworkSecurityGroupsHandlerTest.java | 47 ++++
.../xml/NetworkSecurityGroupHandlerTest.java | 68 +++--
.../src/test/resources/networksecuritygroup.xml | 98 +------
.../resources/networksecuritygroupforsubnet.xml | 4 +
.../networksecuritygroupfulldetails.xml | 97 +++++++
.../test/resources/networksecuritygroups.xml | 12 +
29 files changed, 1307 insertions(+), 401 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
index ebd0c74..406b029 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
@@ -51,7 +51,7 @@ public class AzureManagementApiMetadata extends BaseHttpApiMetadata<AzureCompute
public static Properties defaultProperties() {
final Properties properties = BaseHttpApiMetadata.defaultProperties();
// Sometimes SSH Authentication failure happens in Azure.
- // It seems that the authorized key is injected after ssh has been started.
+ // It seems that the authorized key is injected after ssh has been started.
properties.setProperty("jclouds.ssh.max-retries", "15");
properties.setProperty("jclouds.ssh.retry-auth", "true");
return properties;
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RuleToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RuleToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RuleToXML.java
index 6822728..bcb1b3a 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RuleToXML.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RuleToXML.java
@@ -32,14 +32,14 @@ public final class RuleToXML implements Binder {
Rule rule = Rule.class.cast(input);
try {
String xml = XMLBuilder.create("Rule", "http://schemas.microsoft.com/windowsazure")
- .e("Type").t(rule.type()).up()
+ .e("Type").t(rule.type().name()).up()
.e("Priority").t(rule.priority()).up()
- .e("Action").t(rule.action()).up()
+ .e("Action").t(rule.action().name()).up()
.e("SourceAddressPrefix").t(rule.sourceAddressPrefix()).up()
.e("SourcePortRange").t(rule.sourcePortRange()).up()
.e("DestinationAddressPrefix").t(rule.destinationAddressPrefix()).up()
.e("DestinationPortRange").t(rule.destinationPortRange()).up()
- .e("Protocol").t(rule.protocol()).up().asString();
+ .e("Protocol").t(rule.protocol().getValue()).up().asString();
return (R) request.toBuilder().payload(xml).build();
} catch (Exception e) {
throw propagate(e);
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
index 30f2ca6..a045674 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
@@ -44,7 +44,6 @@ import org.jclouds.azurecompute.domain.Deployment.RoleInstance;
import org.jclouds.azurecompute.domain.Role;
import org.jclouds.azurecompute.compute.functions.OSImageToImage;
import org.jclouds.azurecompute.options.AzureComputeTemplateOptions;
-import org.jclouds.azurecompute.util.ConflictManagementPredicate;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
@@ -60,6 +59,7 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import org.jclouds.azurecompute.util.ConflictManagementPredicate;
/**
* Defines the connection between the {@link AzureComputeApi} implementation and the jclouds
@@ -111,8 +111,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
final String subnetName = templateOptions.getSubnetName().get();
logger.debug("Creating a cloud service with name '%s', label '%s' in location '%s'", name, name, location);
- final String createCloudServiceRequestId =
- api.getCloudServiceApi().createWithLabelInLocation(name, name, location);
+ final String createCloudServiceRequestId
+ = api.getCloudServiceApi().createWithLabelInLocation(name, name, location);
if (!operationSucceededPredicate.apply(createCloudServiceRequestId)) {
final String message = generateIllegalStateExceptionMessage(
createCloudServiceRequestId, azureComputeConstants.operationTimeout());
@@ -142,13 +142,23 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
.build();
logger.debug("Creating a deployment with params '%s' ...", params);
- retry(new ConflictManagementPredicate() {
+ if (!new ConflictManagementPredicate(api) {
@Override
protected String operation() {
return api.getDeploymentApiForService(name).create(params);
}
- }, 30 * 60, 1, SECONDS).apply(name);
+ }.apply(name)) {
+ final String message = generateIllegalStateExceptionMessage(
+ createCloudServiceRequestId, azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ logger.debug("Deleting cloud service (%s) ...", name);
+ deleteCloudService(name);
+ logger.debug("Cloud service (%s) deleted.", name);
+ throw new IllegalStateException(message);
+ }
+
+ logger.info("Deployment created with name: %s", name);
final Set<Deployment> deployments = Sets.newHashSet();
if (!retry(new Predicate<String>() {
@@ -300,8 +310,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
@Override
public boolean apply(final CloudService input) {
- final Deployment deployment =
- input.status() == CloudService.Status.DELETING || input.status() == CloudService.Status.DELETED
+ final Deployment deployment
+ = input.status() == CloudService.Status.DELETING || input.status() == CloudService.Status.DELETED
? null
: api.getDeploymentApiForService(input.name()).get(id);
return deployment != null && deployment.status() != Deployment.Status.DELETING;
@@ -331,13 +341,19 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
final String cloudServiceName = cloudService.name();
logger.debug("Deleting deployment(%s) of cloud service (%s)", id, cloudServiceName);
- retry(new ConflictManagementPredicate(operationSucceededPredicate) {
+
+ if (!new ConflictManagementPredicate(api, operationSucceededPredicate) {
@Override
protected String operation() {
return api.getDeploymentApiForService(cloudServiceName).delete(id);
}
- }, 30 * 60, 1, SECONDS).apply(id);
+ }.apply(id)) {
+ final String message = generateIllegalStateExceptionMessage(
+ "Delete deployment", azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ throw new IllegalStateException(message);
+ }
logger.debug("Deleting cloud service (%s) ...", cloudServiceName);
trackRequest(api.getCloudServiceApi().delete(cloudServiceName));
@@ -347,13 +363,17 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
for (Role role : deployment.roleList()) {
final Role.OSVirtualHardDisk disk = role.osVirtualHardDisk();
if (disk != null) {
- retry(new ConflictManagementPredicate(operationSucceededPredicate) {
+ if (!new ConflictManagementPredicate(api, operationSucceededPredicate) {
@Override
protected String operation() {
return api.getDiskApi().delete(disk.diskName());
}
- }, 30 * 60, 1, SECONDS).apply(id);
+ }.apply(id)) {
+ final String message = generateIllegalStateExceptionMessage(
+ "Delete disk", azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ }
}
}
}
@@ -425,4 +445,36 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
return URI.create(
String.format("https://%s.blob.core.windows.net/vhds/disk-%s.vhd", storageServiceName, diskName));
}
+
+ private void deleteCloudService(final String name) {
+ if (!new ConflictManagementPredicate(api) {
+
+ @Override
+ protected String operation() {
+ return api.getCloudServiceApi().delete(name);
+ }
+
+ }.apply(name)) {
+ final String deleteMessage = generateIllegalStateExceptionMessage(
+ "CloudService delete", azureComputeConstants.operationTimeout());
+ logger.warn(deleteMessage);
+ throw new IllegalStateException(deleteMessage);
+ }
+ }
+
+ private void deleteDeployment(final String id, final String cloudServiceName) {
+ if (!new ConflictManagementPredicate(api) {
+
+ @Override
+ protected String operation() {
+ return api.getDeploymentApiForService(cloudServiceName).delete(id);
+ }
+
+ }.apply(id)) {
+ final String deleteMessage = generateIllegalStateExceptionMessage(
+ "Deployment delete", azureComputeConstants.operationTimeout());
+ logger.warn(deleteMessage);
+ throw new IllegalStateException(deleteMessage);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java
index e129ada..1e07798 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java
@@ -16,7 +16,6 @@
*/
package org.jclouds.azurecompute.compute.config;
-import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD;
import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_TIMEOUT;
@@ -39,7 +38,6 @@ import org.jclouds.azurecompute.compute.strategy.impl.AzureAdaptingComputeServic
import org.jclouds.azurecompute.domain.Deployment;
import org.jclouds.azurecompute.domain.Location;
import org.jclouds.azurecompute.domain.OSImage;
-import org.jclouds.azurecompute.domain.Operation;
import org.jclouds.azurecompute.domain.RoleSize;
import org.jclouds.azurecompute.options.AzureComputeTemplateOptions;
import org.jclouds.compute.ComputeServiceAdapter;
@@ -49,9 +47,8 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
-import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
import org.jclouds.compute.strategy.impl.AdaptingComputeServiceStrategies;
-import org.jclouds.util.Predicates2;
+import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
import com.google.common.base.Function;
import com.google.common.base.Optional;
@@ -61,6 +58,9 @@ import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
+import java.util.concurrent.TimeUnit;
+import org.jclouds.azurecompute.util.ConflictManagementPredicate;
+
public class AzureComputeServiceContextModule
extends ComputeServiceAdapterContextModule<Deployment, RoleSize, OSImage, Location> {
@@ -103,37 +103,12 @@ public class AzureComputeServiceContextModule
@Singleton
protected Predicate<String> provideOperationSucceededPredicate(
final AzureComputeApi api, final AzureComputeConstants azureComputeConstants) {
-
- return Predicates2.retry(new OperationSucceededPredicate(api),
- azureComputeConstants.operationTimeout(), azureComputeConstants.operationPollInitialPeriod(),
- azureComputeConstants.operationPollMaxPeriod());
- }
-
- public static class OperationSucceededPredicate implements Predicate<String> {
-
- private final AzureComputeApi api;
-
- public OperationSucceededPredicate(final AzureComputeApi api) {
- this.api = checkNotNull(api, "api must not be null");
- }
-
- @Override
- public boolean apply(final String input) {
- final Operation operation = api.getOperationApi().get(input);
- switch (operation.status()) {
- case SUCCEEDED:
- return true;
-
- case IN_PROGRESS:
- case FAILED:
- case UNRECOGNIZED:
- return false;
-
- default:
- throw new IllegalStateException("Operation is in invalid status: " + operation.status().name());
- }
- }
-
+ return new ConflictManagementPredicate(
+ api,
+ azureComputeConstants.operationTimeout(),
+ azureComputeConstants.operationPollInitialPeriod(),
+ azureComputeConstants.operationPollMaxPeriod(),
+ TimeUnit.MILLISECONDS);
}
@Singleton
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java
index f6bab8f..8848127 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java
@@ -17,9 +17,6 @@
package org.jclouds.azurecompute.compute.extensions;
import static com.google.common.base.Preconditions.checkNotNull;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.jclouds.azurecompute.compute.AzureComputeServiceAdapter.generateIllegalStateExceptionMessage;
-import static org.jclouds.util.Predicates2.retry;
import java.util.List;
import java.util.Set;
@@ -56,6 +53,7 @@ import com.google.common.base.Splitter;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
+import static org.jclouds.azurecompute.compute.AzureComputeServiceAdapter.generateIllegalStateExceptionMessage;
/**
* An extension to compute service to allow for the manipulation of {@link org.jclouds.compute.domain.SecurityGroup}s.
@@ -100,7 +98,7 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
/**
* @param name it represents both cloudservice and deployment name
- * @return Set<SecurityGroup>
+ * @return Set<SecurityGroup>
*/
@Override
public Set<SecurityGroup> listSecurityGroupsForNode(final String name) {
@@ -152,7 +150,8 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
checkNotNull(name, "name");
checkNotNull(location, "location");
- final NetworkSecurityGroup networkSecurityGroup = NetworkSecurityGroup.create(name, name, location.getId(), null);
+ final NetworkSecurityGroup networkSecurityGroup = NetworkSecurityGroup.create(
+ name, name, location.getId(), null, null);
final String createNSGRequestId = api.getNetworkSecurityGroupApi().create(networkSecurityGroup);
if (!operationSucceededPredicate.apply(createNSGRequestId)) {
final String message = generateIllegalStateExceptionMessage(
@@ -183,19 +182,23 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
if (virtualNetworkName != null && subnetName != null) {
final NetworkSecurityGroup networkSecurityGroupAppliedToSubnet = api.getNetworkSecurityGroupApi()
.getNetworkSecurityGroupAppliedToSubnet(virtualNetworkName, subnetName);
- if (networkSecurityGroupAppliedToSubnet != null) {
- if (!networkSecurityGroupAppliedToSubnet.name().equals(id)) {
- logger.debug("Removing a networkSecurityGroup %s is already applied to subnet '%s' ...",
- id, subnetName);
- // remove existing nsg from subnet
- String removeFromSubnetRequestId = api.getNetworkSecurityGroupApi().removeFromSubnet(
- virtualNetworkName, subnetName, networkSecurityGroupAppliedToSubnet.name());
- if (!operationSucceededPredicate.apply(removeFromSubnetRequestId)) {
- final String message = generateIllegalStateExceptionMessage(
- removeFromSubnetRequestId, azureComputeConstants.operationTimeout());
- logger.warn(message);
- throw new IllegalStateException(message);
+ if (networkSecurityGroupAppliedToSubnet != null
+ && networkSecurityGroupAppliedToSubnet.name().equals(id)) {
+ logger.debug("Removing a networkSecurityGroup %s is already applied to subnet '%s' ...",
+ id, subnetName);
+
+ // remove existing nsg from subnet
+ if (!new ConflictManagementPredicate(api, operationSucceededPredicate) {
+ @Override
+ protected String operation() {
+ return api.getNetworkSecurityGroupApi().removeFromSubnet(
+ virtualNetworkName, subnetName, id);
}
+ }.apply(id)) {
+ final String message = generateIllegalStateExceptionMessage(
+ "Remove security group from subnet", azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ throw new IllegalStateException(message);
}
}
}
@@ -249,24 +252,27 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
}
}
- retry(new ConflictManagementPredicate(
- operationSucceededPredicate,
- azureComputeConstants.operationTimeout()) {
-
- @Override
- protected String operation() {
- // Check for deployment validity
- final Deployment deployment = api.getDeploymentApiForService(
- service.name()).get(service.name());
- if (deployment == null || deployment.status() == Status.DELETING) {
- return null;
- } else {
- return api.getVirtualMachineApiForDeploymentInService(
- deployment.name(), deployment.name()).
+ if (!new ConflictManagementPredicate(api, operationSucceededPredicate) {
+
+ @Override
+ protected String operation() {
+ // Check for deployment validity
+ final Deployment deployment = api.getDeploymentApiForService(
+ service.name()).get(service.name());
+ if (deployment == null || deployment.status() == Status.DELETING) {
+ return null;
+ } else {
+ return api.getVirtualMachineApiForDeploymentInService(
+ deployment.name(), deployment.name()).
updateRole(role.roleName(), role);
- }
- }
- }, 600, 30, 30, SECONDS).apply(role.roleName());
+ }
+ }
+ }.apply(role.roleName())) {
+ final String message = generateIllegalStateExceptionMessage(
+ "Operation", azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ throw new IllegalStateException(message);
+ }
}
}
}
@@ -329,24 +335,25 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
}
}
- retry(new ConflictManagementPredicate(
- operationSucceededPredicate,
- azureComputeConstants.operationTimeout()) {
-
- @Override
- protected String operation() {
- // Check for deployment validity
- final Deployment deployment = api.getDeploymentApiForService(
- service.name()).get(service.name());
- if (deployment == null || deployment.status() == Status.DELETING) {
- return null;
- } else {
- return api.getVirtualMachineApiForDeploymentInService(
- deployment.name(), deployment.name()).
- updateRole(role.roleName(), role);
- }
- }
- }, 600, 30, 30, SECONDS).apply(role.roleName());
+ if (!new ConflictManagementPredicate(api, operationSucceededPredicate) {
+ @Override
+ protected String operation() {
+ // Check for deployment validity
+ final Deployment deployment = api.getDeploymentApiForService(
+ service.name()).get(service.name());
+ if (deployment == null || deployment.status() == Status.DELETING) {
+ return null;
+ } else {
+ return api.getVirtualMachineApiForDeploymentInService(
+ deployment.name(), deployment.name()).updateRole(role.roleName(), role);
+ }
+ }
+ }.apply(role.roleName())) {
+ final String message = generateIllegalStateExceptionMessage(
+ "Operation", azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ throw new IllegalStateException(message);
+ }
}
}
}
@@ -410,7 +417,8 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
builder.fromPort(extractPort(rule.name(), 0))
.toPort(extractPort(rule.name(), 1));
}
- builder.ipProtocol(rule.protocol().equals("*") ? IpProtocol.ALL : IpProtocol.valueOf(rule.protocol()));
+ builder.ipProtocol(rule.protocol().equals(Rule.Protocol.ALL)
+ ? IpProtocol.ALL : IpProtocol.valueOf(rule.protocol().getValue()));
if (rule.destinationAddressPrefix().equals("*")) {
builder.cidrBlock("0.0.0.0/0");
} else {
@@ -450,24 +458,20 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
final String destinationPortRange = ipPermission.getFromPort() == ipPermission.getToPort()
? String.valueOf(ipPermission.getToPort())
: String.format("%s-%s", ipPermission.getFromPort(), ipPermission.getToPort());
- final String destinationAddressPrefix =
- ipPermission.getCidrBlocks().isEmpty()
+ final String destinationAddressPrefix = ipPermission.getCidrBlocks().isEmpty()
|| Iterables.get(ipPermission.getCidrBlocks(), 0).equals("0.0.0.0/0")
? "*"
: Iterables.get(ipPermission.getCidrBlocks(), 0);
final String setRuleToNSGRequestId = api.getNetworkSecurityGroupApi().
setRule(networkSecurityGroupId, ruleName, Rule.create(ruleName, // name
- "Inbound", // type
+ Rule.Type.Inbound, // type
String.valueOf(priority), // priority
- "Allow", // action
+ Rule.Action.Allow, // action
"INTERNET", // sourceAddressPrefix
"*", // sourcePortRange
destinationAddressPrefix, // destinationAddressPrefix
destinationPortRange, // destinationPortRange
- protocol, // protocol
- "Active", // state
- true // isDefault
- ));
+ Rule.Protocol.fromString(protocol)));
if (!operationSucceededPredicate.apply(setRuleToNSGRequestId)) {
final String message = generateIllegalStateExceptionMessage(
setRuleToNSGRequestId, azureComputeConstants.operationTimeout());
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java
index 5a8c681..b2301b6 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java
@@ -166,7 +166,7 @@ public class GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes
logger.debug("Adding a networkSecurityGroup %s is already applied to subnet '%s' of virtual network %s ...",
networkSecurityGroupName, subnetName, virtualNetworkName);
final String addToSubnetId = api.getNetworkSecurityGroupApi().addToSubnet(virtualNetworkName, subnetName,
- NetworkSecurityGroup.create(networkSecurityGroupName, null, null, null));
+ networkSecurityGroupName);
if (!operationSucceededPredicate.apply(addToSubnetId)) {
final String warnMessage = format("Add networkSecurityGroup(%s) to subnet(%s) has not been completed "
+ "within %sms.", networkSecurityGroupName, subnetName, azureComputeConstants.operationTimeout());
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/domain/NetworkSecurityGroup.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/NetworkSecurityGroup.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/NetworkSecurityGroup.java
index 41e0193..1d490a7 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/NetworkSecurityGroup.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/NetworkSecurityGroup.java
@@ -16,16 +16,37 @@
*/
package org.jclouds.azurecompute.domain;
-import static com.google.common.collect.ImmutableList.copyOf;
import java.util.List;
import org.jclouds.javax.annotation.Nullable;
import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
@AutoValue
public abstract class NetworkSecurityGroup {
+ public enum State {
+
+ CREATED,
+ CREATING,
+ UPDATING,
+ DELETING,
+ UNAVAILABLE,
+ UNRECOGNIZED;
+
+ public static State fromString(final String text) {
+ if (text != null) {
+ for (State status : State.values()) {
+ if (text.equalsIgnoreCase(status.name())) {
+ return status;
+ }
+ }
+ }
+ return UNRECOGNIZED;
+ }
+ }
+
NetworkSecurityGroup() {
} // For AutoValue only!
@@ -38,11 +59,23 @@ public abstract class NetworkSecurityGroup {
public abstract String location();
@Nullable
+ public abstract State state();
+
+ @Nullable
public abstract List<Rule> rules();
+ public static NetworkSecurityGroup create(final String name) {
+ return new AutoValue_NetworkSecurityGroup(name, null, null, null, null);
+ }
+
public static NetworkSecurityGroup create(
- final String name, final String label, String location, final List<Rule> rules) {
+ final String name, final String label, String location, final State state, final List<Rule> rules) {
- return new AutoValue_NetworkSecurityGroup(name, label, location, rules == null ? null : copyOf(rules));
+ return new AutoValue_NetworkSecurityGroup(
+ name,
+ label,
+ location,
+ state,
+ rules == null ? ImmutableList.<Rule>of() : ImmutableList.copyOf(rules));
}
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Rule.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Rule.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Rule.java
index 1d81c14..a58cb3b 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Rule.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Rule.java
@@ -23,13 +23,78 @@ import com.google.auto.value.AutoValue;
@AutoValue
public abstract class Rule {
+ public enum Action {
+
+ Allow,
+ Deny,
+ UNRECOGNIZED;
+
+ public static Action fromString(final String text) {
+ if (text != null) {
+ for (Action action : Action.values()) {
+ if (text.equalsIgnoreCase(action.name())) {
+ return action;
+ }
+ }
+ }
+ return UNRECOGNIZED;
+ }
+ }
+
+ public enum Type {
+
+ Inbound,
+ Outbound,
+ UNRECOGNIZED;
+
+ public static Type fromString(final String text) {
+ if (text != null) {
+ for (Type type : Type.values()) {
+ if (text.equalsIgnoreCase(type.name())) {
+ return type;
+ }
+ }
+ }
+ return UNRECOGNIZED;
+ }
+ }
+
+ public enum Protocol {
+
+ TCP("TCP"),
+ UDP("UDP"),
+ ALL("*"),
+ UNRECOGNIZED("");
+
+ private final String value;
+
+ Protocol(final String value) {
+ this.value = value;
+ }
+
+ public static Protocol fromString(final String text) {
+ if (text != null) {
+ for (Protocol protocol : Protocol.values()) {
+ if (text.equalsIgnoreCase(protocol.value)) {
+ return protocol;
+ }
+ }
+ }
+ return UNRECOGNIZED;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
public abstract String name();
- public abstract String type();
+ public abstract Type type();
public abstract String priority();
- public abstract String action();
+ public abstract Action action();
public abstract String sourceAddressPrefix();
@@ -39,7 +104,7 @@ public abstract class Rule {
public abstract String destinationPortRange();
- public abstract String protocol();
+ public abstract Protocol protocol();
public abstract String state();
@@ -49,9 +114,30 @@ public abstract class Rule {
Rule() {
} // For AutoValue only!
- public static Rule create(final String name, final String type, final String priority, final String action,
+ /**
+ * Use this method to create a new rule to be added to a network security group.
+ * @param name
+ * @param type
+ * @param priority
+ * @param action
+ * @param sourceAddressPrefix
+ * @param sourcePortRange
+ * @param destinationAddressPrefix
+ * @param destinationPortRange
+ * @param protocol
+ * @return
+ */
+ public static Rule create(final String name, final Type type, final String priority, final Action action,
+ final String sourceAddressPrefix, final String sourcePortRange, final String destinationAddressPrefix,
+ final String destinationPortRange, final Protocol protocol) {
+
+ return new AutoValue_Rule(name, type, priority, action, sourceAddressPrefix, sourcePortRange,
+ destinationAddressPrefix, destinationPortRange, protocol, "Active", null);
+ }
+
+ public static Rule create(final String name, final Type type, final String priority, final Action action,
final String sourceAddressPrefix, final String sourcePortRange, final String destinationAddressPrefix,
- final String destinationPortRange, final String protocol, final String state, final Boolean isDefault) {
+ final String destinationPortRange, final Protocol protocol, final String state, final Boolean isDefault) {
return new AutoValue_Rule(name, type, priority, action, sourceAddressPrefix, sourcePortRange,
destinationAddressPrefix, destinationPortRange, protocol, state, isDefault);
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/features/NetworkSecurityGroupApi.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/features/NetworkSecurityGroupApi.java b/azurecompute/src/main/java/org/jclouds/azurecompute/features/NetworkSecurityGroupApi.java
index 4eede4b..aa50bf2 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/features/NetworkSecurityGroupApi.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/features/NetworkSecurityGroupApi.java
@@ -41,18 +41,28 @@ import org.jclouds.azurecompute.xml.NetworkSecurityGroupHandler;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.XMLResponseParser;
+/**
+ * The Service Management API includes operations for managing the network security groups in your subscription.
+ *
+ * @see https://msdn.microsoft.com/en-us/library/azure/dn913824.aspx.
+ */
@Path("/services/networking")
-@Headers(keys = "x-ms-version", values = "{jclouds.api-version}")
+@Produces(MediaType.APPLICATION_XML)
@Consumes(MediaType.APPLICATION_XML)
+@Headers(keys = "x-ms-version", values = "{jclouds.api-version}")
public interface NetworkSecurityGroupApi {
/**
- * Lists all of the Network Security Groups for the subscription.
+ * The List Network Security Groups operation returns a list of the network security groups in the specified
+ * subscription.
*
+ * @return network security group list.
*/
@Named("ListNetworkSecurityGroups")
@Path("/networksecuritygroups")
@@ -61,10 +71,17 @@ public interface NetworkSecurityGroupApi {
@Fallback(EmptyListOnNotFoundOr404.class)
List<NetworkSecurityGroup> list();
+ /**
+ * The Create Network Security Group operation creates a new network security group within the context of the
+ * specified subscription. For more information, see
+ * <a href="https://msdn.microsoft.com/en-us/library/azure/dn848316.aspx">About Network Security Groups</a>.
+ *
+ * @param networkSecurityGroup network security group.
+ * @return request id.
+ */
@Named("CreateNetworkSecurityGroup")
@Path("/networksecuritygroups")
@POST
- @Produces(MediaType.APPLICATION_XML)
@ResponseParser(ParseRequestIdHeader.class)
String create(@BinderParam(NetworkSecurityGroupToXML.class) NetworkSecurityGroup networkSecurityGroup);
@@ -78,17 +95,18 @@ public interface NetworkSecurityGroupApi {
*/
@Named("CreateNetworkSecurityGroup")
@Path("/networksecuritygroups/{networkSecurityGroupName}")
+ @Fallback(NullOnNotFoundOr404.class)
@DELETE
- @Produces(MediaType.APPLICATION_XML)
@ResponseParser(ParseRequestIdHeader.class)
String delete(@PathParam("networkSecurityGroupName") String networkSecurityGroupName);
/**
- * Gets the Network Security Group applied to a specific subnet.
+ * The Get Network Security Group for Subnet operation returns information about the network security group
+ * associated with a subnet.
*
- * @param virtualNetworkName
- * @param subnetName
- * @return
+ * @param virtualNetworkName virtual network name.
+ * @param subnetName subnet name.
+ * @return network security group.
*/
@Named("GetsNetworkSecurityGroupAppliedToSubnet")
@Path("/virtualnetwork/{virtualNetworkName}/subnets/{subnetName}/networksecuritygroups")
@@ -99,10 +117,10 @@ public interface NetworkSecurityGroupApi {
@PathParam("virtualNetworkName") String virtualNetworkName, @PathParam("subnetName") String subnetName);
/**
- * Gets the details for the specified Network Security Group in the subscription
+ * The Get Network Security Group operation returns information about the specified network security group and rules.
*
- * @param networkSecurityGroupName
- * @return
+ * @param networkSecurityGroupName network security group name.
+ * @return network security group.
*/
@Named("GetDetailsNetworkSecurityGroup")
@Path("/networksecuritygroups/{networkSecurityGroupName}")
@@ -113,53 +131,84 @@ public interface NetworkSecurityGroupApi {
NetworkSecurityGroup getFullDetails(@PathParam("networkSecurityGroupName") String networkSecurityGroupName);
/**
- * Adds a Network Security Group to a subnet.
+ * The Get Network Security Group operation returns information about the specified network security group.
+ *
+ * @param networkSecurityGroupName network security group name.
+ * @return network security group.
+ */
+ @Named("GetDetailsNetworkSecurityGroup")
+ @Path("/networksecuritygroups/{networkSecurityGroupName}")
+ @GET
+ @XMLResponseParser(NetworkSecurityGroupHandler.class)
+ @Fallback(NullOnNotFoundOr404.class)
+ NetworkSecurityGroup get(@PathParam("networkSecurityGroupName") String networkSecurityGroupName);
+
+ /**
+ * The Add Network Security Group to Subnet operation associates the network security group with specified subnet in
+ * a virtual network. For more information, see
+ * <a href="https://msdn.microsoft.com/en-us/library/azure/dn848316.aspx">About Network Security Groups</a>.
*
- * @param virtualNetworkName
- * @return
+ * @param virtualNetworkName virtual network name.
+ * @param subnetName subnet name.
+ * @param networkSecurityGroupName network security group name.
+ * @return request id.
*/
@Named("AddNetworkSecurityGroupToSubnet")
@Path("/virtualnetwork/{virtualNetworkName}/subnets/{subnetName}/networksecuritygroups")
+ @Payload("<NetworkSecurityGroup xmlns=\"http://schemas.microsoft.com/windowsazure\">"
+ + "<Name>{networkSecurityGroupName}</Name></NetworkSecurityGroup>")
@POST
- @Produces(MediaType.APPLICATION_XML)
@ResponseParser(ParseRequestIdHeader.class)
String addToSubnet(@PathParam("virtualNetworkName") String virtualNetworkName,
@PathParam("subnetName") String subnetName,
- @BinderParam(NetworkSecurityGroupToXML.class) NetworkSecurityGroup networkSecurityGroup);
+ @PayloadParam("networkSecurityGroupName") String networkSecurityGroupName);
/**
- * Removes a Network Security Group from a subnet
+ * The Remove Network Security Group from Subnet operation removes the association of the specified network security
+ * group from the specified subnet.
+ *
+ * @param virtualNetworkName virtual network name.
+ * @param subnetName subnet name.
+ * @param networkSecurityGroupName network security group name.
+ * @return request id.
*/
@Named("RemoveNetworkSecurityGroupToSubnet")
@Path("/virtualnetwork/{virtualNetworkName}/subnets/{subnetName}/networksecuritygroups/{networkSecurityGroupName}")
+ @Fallback(NullOnNotFoundOr404.class)
@DELETE
- @Produces(MediaType.APPLICATION_XML)
@ResponseParser(ParseRequestIdHeader.class)
String removeFromSubnet(@PathParam("virtualNetworkName") String virtualNetworkName,
@PathParam("subnetName") String subnetName,
@PathParam("networkSecurityGroupName") String networkSecurityGroupName);
/**
- * Sets a new Network Security Rule to existing Network Security Group
- *
+ * The Set Network Security Rule operation adds or updates a network security rule that is associated with the
+ * specified network security group.
*
+ * @param networkSecurityGroupName network security group name.
+ * @param ruleName rule name.
+ * @param rule rule.
+ * @return request id.
*/
@Named("SetNetworkSecurityRuleToNetworkSecurityGroup")
@Path("/networksecuritygroups/{networkSecurityGroupName}/rules/{ruleName}")
@PUT
- @Produces(MediaType.APPLICATION_XML)
@ResponseParser(ParseRequestIdHeader.class)
String setRule(@PathParam("networkSecurityGroupName") String networkSecurityGroupName,
@PathParam("ruleName") String ruleName, @BinderParam(RuleToXML.class) Rule rule);
/**
- * Deletes a rule from the specified Network Security Group.
+ * The Delete Network Security Rule operation deletes a network security group rule from the specified network
+ * security group.
*
+ * @param networkSecurityGroupName network security group name.
+ * @param ruleName name of the rule to be deleted.
+ * @return request id.
*/
@Named("SetNetworkSecurityRuleToNetworkSecurityGroup")
@Path("/networksecuritygroups/{networkSecurityGroupName}/rules/{ruleName}")
+ @Fallback(NullOnNotFoundOr404.class)
@DELETE
- @Produces(MediaType.APPLICATION_XML)
@ResponseParser(ParseRequestIdHeader.class)
String deleteRule(@PathParam("networkSecurityGroupName") String networkSecurityGroupName,
@PathParam("ruleName") String ruleName);
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/util/ConflictManagementPredicate.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/util/ConflictManagementPredicate.java b/azurecompute/src/main/java/org/jclouds/azurecompute/util/ConflictManagementPredicate.java
index 4949130..c859c50 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/util/ConflictManagementPredicate.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/util/ConflictManagementPredicate.java
@@ -16,30 +16,42 @@
*/
package org.jclouds.azurecompute.util;
-import static org.jclouds.azurecompute.compute.AzureComputeServiceAdapter.generateIllegalStateExceptionMessage;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.azurecompute.domain.Operation.Status.FAILED;
import com.google.common.base.Predicate;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
import javax.annotation.Resource;
import javax.inject.Named;
+
+import org.jclouds.azurecompute.AzureComputeApi;
+import org.jclouds.azurecompute.domain.Operation;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
+import org.jclouds.util.Predicates2;
/**
* Conflict errors (409 response status code) management predicate.
*/
-public abstract class ConflictManagementPredicate implements Predicate<String> {
-
- protected final Predicate<String> operationSucceeded;
-
- private Long timeout = null;
+public class ConflictManagementPredicate implements Predicate<String> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
- private boolean raiseException = false;
+ private AzureComputeApi api;
+
+ private Predicate<String> operationSucceeded;
+
+ private final long timeout = 600000;
+ private final long interval = 15000;
public ConflictManagementPredicate() {
this(null);
@@ -48,25 +60,35 @@ public abstract class ConflictManagementPredicate implements Predicate<String> {
/**
* Constructor.
*
- * @param operationSucceeded predicate to be applied to the requestId.
+ * @param api azure api.
*/
- public ConflictManagementPredicate(final Predicate<String> operationSucceeded) {
- this.operationSucceeded = operationSucceeded;
+ public ConflictManagementPredicate(final AzureComputeApi api) {
+ this(api, Predicates2.retry(new OperationSucceededPredicate(api), 600, 5, 5, SECONDS));
}
/**
- * Constructor to be used to raise an IllegalStateException in case of the given predicate evaluation is false.
+ * Constructor.
*
- * @param operationSucceeded predicate to be applied to the requestId.
- * @param timeout timeout of the predicate.
+ * @param api azure api.
+ * @param timeout predicate timeout.
+ * @param period predicate period.
+ * @param maxPeriod max period
+ * @param unit timeout and period time unit.
*/
public ConflictManagementPredicate(
- final Predicate<String> operationSucceeded,
- final Long timeout) {
+ final AzureComputeApi api, long timeout, long period, long maxPeriod, TimeUnit unit) {
+ this(api, Predicates2.retry(new OperationSucceededPredicate(api), timeout, period, maxPeriod, unit));
+ }
+ /**
+ * Constructor.
+ *
+ * @param api azure api.
+ * @param operationSucceeded predicate to be applied to the requestId.
+ */
+ public ConflictManagementPredicate(final AzureComputeApi api, final Predicate<String> operationSucceeded) {
+ this.api = api;
this.operationSucceeded = operationSucceeded;
- this.timeout = timeout;
- this.raiseException = true;
}
/**
@@ -74,49 +96,116 @@ public abstract class ConflictManagementPredicate implements Predicate<String> {
*
* @return requestId.
*/
- protected abstract String operation();
+ protected String operation() {
+ throw new UnsupportedOperationException();
+ }
/**
* {@inheritDoc }
*
- * @param name interested object/operaton descripton.
+ * @param input interested object/operaton descripton or requestId.
* @return predicate evaluation.
*/
@Override
- public final boolean apply(final String name) {
- try {
- final String requestId = operation();
- logger.info("Executed operation on {0}", name);
+ public final boolean apply(final String input) {
+ Operation operation = null;
+ String requestId = null;
+
+ boolean retry = true;
+
+ long now = System.currentTimeMillis();
+ long end = now + timeout;
+
+ while (retry && now < end) {
+ try {
+ requestId = operation();
+ logger.debug("Executed operation on %s", input);
+
+ // If request id is not available let's assume operation succeeded.
+ if (requestId == null) {
+ logger.debug("No request id available. Assume operation succeeded.");
+ return true;
+ }
- if (requestId == null) {
- return true;
+ operation = api.getOperationApi().get(requestId);
+ logger.debug("Operation %s status: %s", operation.id(), operation.status().name());
+
+ if (operation.status() == FAILED) {
+ // rise an exception based on HTTP status code
+ if (operation.httpStatusCode() == 409 || operation.httpStatusCode() == 500) {
+ logger.info("Retry operation %s with (code %d)", operation.id(), operation.httpStatusCode());
+ } else {
+ logger.info("Not retriable operation %s (code %d)", operation.id(), operation.httpStatusCode());
+ retry = false;
+ }
+ } else {
+ logger.debug("Tracking for operation %s ...", operation.id());
+ retry = false;
+ }
+ } catch (UnsupportedOperationException e) {
+ requestId = input;
+ retry = false;
+ logger.debug("Tracking for operation %s ...", input);
+ } catch (RuntimeException e) {
+ final HttpResponseException re = (e instanceof HttpResponseException)
+ ? HttpResponseException.class.cast(e) : (e.getCause() instanceof HttpResponseException)
+ ? HttpResponseException.class.cast(e.getCause())
+ : null;
+ if (re == null) {
+ throw e;
+ } else {
+ final HttpResponse res = re.getResponse();
+ logger.info("[%s (%d)] Performing operation on %s", res.getStatusLine(), res.getStatusCode(), input);
+ if (res.getStatusCode() == 409 || res.getStatusCode() == 500) {
+ logger.info("Retry operation %s", operation == null ? "" : operation.id(), res.getStatusCode());
+ } else {
+ throw re;
+ }
+ }
}
- final boolean res = operationSucceeded == null ? true : operationSucceeded.apply(requestId);
- if (!res && raiseException) {
- final String message = generateIllegalStateExceptionMessage(requestId, timeout);
- logger.warn(message);
- throw new IllegalStateException(message);
- } else {
- return res;
+ if (retry) {
+ try {
+ Thread.sleep(interval);
+ } catch (InterruptedException ex) {
+ // ignore
+ }
+
+ now = System.currentTimeMillis();
}
- } catch (RuntimeException e) {
- final HttpResponseException re = (e instanceof HttpResponseException)
- ? HttpResponseException.class.cast(e) : (e.getCause() instanceof HttpResponseException)
- ? HttpResponseException.class.cast(e.getCause())
- : null;
- if (re == null) {
- throw e;
- } else {
- final HttpResponse res = re.getResponse();
- logger.info("[{0} (core: {1})] while performing operation on {2}",
- new Object[]{res.getStatusLine(), res.getStatusCode(), name});
- if (res.getStatusCode() == 409) {
- logger.info("[{0}] Retry operation on {1}", new Object[]{e.getMessage(), name});
+ }
+
+ if (now >= end) {
+ throw new RuntimeException(new TimeoutException(requestId));
+ }
+
+ return operationSucceeded.apply(requestId);
+ }
+
+ private static class OperationSucceededPredicate implements Predicate<String> {
+
+ private final AzureComputeApi api;
+
+ public OperationSucceededPredicate(final AzureComputeApi api) {
+ this.api = checkNotNull(api, "api must not be null");
+ }
+
+ @Override
+ public boolean apply(final String input) {
+ final Operation operation = api.getOperationApi().get(input);
+ switch (operation.status()) {
+ case SUCCEEDED:
+ return true;
+
+ case IN_PROGRESS:
+ case UNRECOGNIZED:
return false;
- } else {
- throw re;
- }
+
+ case FAILED:
+ throw new RuntimeException(new CancellationException(input));
+
+ default:
+ throw new IllegalStateException("Operation is in invalid status: " + operation.status().name());
}
}
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/xml/NetworkSecurityGroupHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/NetworkSecurityGroupHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/NetworkSecurityGroupHandler.java
index f893ac5..421bde2 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/NetworkSecurityGroupHandler.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/NetworkSecurityGroupHandler.java
@@ -34,6 +34,8 @@ public class NetworkSecurityGroupHandler extends ParseSax.HandlerForGeneratedReq
private String location;
+ private NetworkSecurityGroup.State state;
+
private List<Rule> rules = Lists.newArrayList();
private boolean inRule;
@@ -51,8 +53,9 @@ public class NetworkSecurityGroupHandler extends ParseSax.HandlerForGeneratedReq
@Override
public NetworkSecurityGroup getResult() {
- NetworkSecurityGroup result = NetworkSecurityGroup.create(name, label, location, rules);
+ NetworkSecurityGroup result = NetworkSecurityGroup.create(name, label, location, state, rules);
name = label = location = null; // handler is called in a loop.
+ this.state = null;
rules = Lists.newArrayList();
return result;
}
@@ -70,6 +73,8 @@ public class NetworkSecurityGroupHandler extends ParseSax.HandlerForGeneratedReq
label = currentOrNull(currentText);
} else if (qName.equals("Location")) {
location = currentOrNull(currentText);
+ } else if (qName.equals("State")) {
+ state = NetworkSecurityGroup.State.fromString(currentOrNull(currentText));
}
currentText.setLength(0);
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/main/java/org/jclouds/azurecompute/xml/RuleHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/RuleHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/RuleHandler.java
index 7dc43f6..758b8d1 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/RuleHandler.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/RuleHandler.java
@@ -25,11 +25,11 @@ final class RuleHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Ru
private String name;
- private String type;
+ private Rule.Type type;
private String priority;
- private String action;
+ private Rule.Action action;
private String sourceAddressPrefix;
@@ -39,7 +39,7 @@ final class RuleHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Ru
private String destinationPortRange;
- private String protocol;
+ private Rule.Protocol protocol;
private String state;
@@ -51,8 +51,12 @@ final class RuleHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Ru
public Rule getResult() {
Rule result = Rule.create(name, type, priority, action, sourceAddressPrefix, sourcePortRange,
destinationAddressPrefix, destinationPortRange, protocol, state, isDefault);
- name = type = priority = action = sourceAddressPrefix = sourcePortRange = destinationAddressPrefix
- = destinationPortRange = protocol = state = null; // handler is called in a loop.
+
+ name = priority = sourceAddressPrefix = sourcePortRange = destinationAddressPrefix
+ = destinationPortRange = state = null; // handler is called in a loop.
+ protocol = null;
+ action = null;
+ type = null;
isDefault = false;
return result;
}
@@ -62,11 +66,11 @@ final class RuleHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Ru
if (qName.equals("Name")) {
name = currentOrNull(currentText);
} else if (qName.equals("Type")) {
- type = currentOrNull(currentText);
+ type = Rule.Type.fromString(currentOrNull(currentText));
} else if (qName.equals("Priority")) {
priority = currentOrNull(currentText);
} else if (qName.equals("Action")) {
- action = currentOrNull(currentText);
+ action = Rule.Action.fromString(currentOrNull(currentText));
} else if (qName.equals("SourceAddressPrefix")) {
sourceAddressPrefix = currentOrNull(currentText);
} else if (qName.equals("SourcePortRange")) {
@@ -76,7 +80,7 @@ final class RuleHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Ru
} else if (qName.equals("DestinationPortRange")) {
destinationPortRange = currentOrNull(currentText);
} else if (qName.equals("Protocol")) {
- protocol = currentOrNull(currentText);
+ protocol = Rule.Protocol.fromString(currentOrNull(currentText));
} else if (qName.equals("State")) {
state = currentOrNull(currentText);
} else if (qName.equals("IsDefault")) {
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapterLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapterLiveTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapterLiveTest.java
index fcdf2bc..f4b6f56 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapterLiveTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapterLiveTest.java
@@ -16,22 +16,12 @@
*/
package org.jclouds.azurecompute.compute;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
-import com.google.common.net.HostAndPort;
-import com.google.common.net.InetAddresses;
-import com.google.inject.Injector;
-import com.google.inject.Module;
-
-import java.util.Arrays;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
@@ -52,6 +42,16 @@ import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import org.testng.annotations.AfterGroups;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.net.HostAndPort;
+import com.google.common.net.InetAddresses;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import java.util.Arrays;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.util.Predicates2.retry;
+
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeServiceAdapterLiveTest")
public class AzureComputeServiceAdapterLiveTest extends BaseAzureComputeApiLiveTest {
@@ -61,6 +61,16 @@ public class AzureComputeServiceAdapterLiveTest extends BaseAzureComputeApiLiveT
private Factory sshFactory;
+ private String storageServiceName = null;
+
+ @Override
+ protected String getStorageServiceName() {
+ if (storageServiceName == null) {
+ storageServiceName = String.format("%3.20sacsa", System.getProperty("user.name") + RAND).toLowerCase();
+ }
+ return storageServiceName;
+ }
+
@Override
protected AzureComputeApi create(final Properties props, final Iterable<Module> modules) {
final Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceContextLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceContextLiveTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceContextLiveTest.java
index f73fd2b..0e204ba 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceContextLiveTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceContextLiveTest.java
@@ -16,14 +16,8 @@
*/
package org.jclouds.azurecompute.compute;
-import static java.util.concurrent.TimeUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.jclouds.util.Predicates2.retry;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import com.google.common.reflect.TypeToken;
-import com.google.inject.Module;
+import static org.testng.Assert.assertTrue;
import java.util.Arrays;
import java.util.Random;
@@ -31,7 +25,6 @@ import java.util.Set;
import org.jclouds.azurecompute.options.AzureComputeTemplateOptions;
import org.jclouds.azurecompute.AzureComputeApi;
-import org.jclouds.azurecompute.compute.config.AzureComputeServiceContextModule;
import org.jclouds.azurecompute.internal.BaseAzureComputeApiLiveTest;
import org.jclouds.azurecompute.util.ConflictManagementPredicate;
import org.jclouds.compute.RunNodesException;
@@ -43,6 +36,10 @@ import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.ssh.SshClient;
import org.jclouds.sshj.config.SshjSshClientModule;
+import com.google.common.collect.Iterables;
+import com.google.common.reflect.TypeToken;
+import com.google.inject.Module;
+
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -54,14 +51,11 @@ public class AzureComputeServiceContextLiveTest extends BaseComputeServiceContex
private AzureComputeApi api;
- private Predicate<String> operationSucceeded;
-
private String storageServiceName = null;
protected String getStorageServiceName() {
if (storageServiceName == null) {
- storageServiceName = String.format("%3.24s",
- System.getProperty("user.name") + RAND + this.getClass().getSimpleName()).toLowerCase();
+ storageServiceName = String.format("%3.20sacsc", System.getProperty("user.name") + RAND).toLowerCase();
}
return storageServiceName;
}
@@ -76,20 +70,17 @@ public class AzureComputeServiceContextLiveTest extends BaseComputeServiceContex
private static final long serialVersionUID = 309104475566522958L;
});
-
- operationSucceeded = retry(
- new AzureComputeServiceContextModule.OperationSucceededPredicate(api), 600, 5, 5, SECONDS);
}
@AfterClass(alwaysRun = true)
public void tearDown() {
- retry(new ConflictManagementPredicate(operationSucceeded) {
+ assertTrue(new ConflictManagementPredicate(api) {
@Override
protected String operation() {
return api.getStorageAccountApi().delete(getStorageServiceName());
}
- }, 600, 5, 5, SECONDS).apply(getStorageServiceName());
+ }.apply(getStorageServiceName()));
}
@Override
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/test/java/org/jclouds/azurecompute/features/AffinityGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/features/AffinityGroupApiLiveTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/features/AffinityGroupApiLiveTest.java
index cd677c7..62bab24 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/features/AffinityGroupApiLiveTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/features/AffinityGroupApiLiveTest.java
@@ -21,6 +21,8 @@ import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertNotNull;
+import static org.jclouds.azurecompute.internal.BaseAzureComputeApiLiveTest.LOCATION;
+
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
@@ -70,7 +72,7 @@ public class AffinityGroupApiLiveTest extends AbstractAzureComputeApiLiveTest {
final CreateAffinityGroupParams params = CreateAffinityGroupParams.builder().
name(GROUP_NAME).
label(GROUP_NAME).
- location("West Europe").
+ location(LOCATION).
build();
final String requestId = api().add(params);
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiLiveTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiLiveTest.java
index 183beda..5cbf7f5 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiLiveTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiLiveTest.java
@@ -122,35 +122,35 @@ public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
public void testDelete() {
final List<Role> roles = api.getDeploymentApiForService(cloudService.name()).get(DEPLOYMENT).roleList();
- retry(new ConflictManagementPredicate(operationSucceeded) {
+ assertTrue(new ConflictManagementPredicate(api) {
@Override
protected String operation() {
return api().delete(deployment.name());
}
- }, 600, 30, 30, SECONDS).apply(deployment.name());
+ }.apply(deployment.name()));
assertTrue(deploymentGone.apply(deployment), deployment.toString());
Logger.getAnonymousLogger().log(Level.INFO, "deployment deleted: {0}", deployment);
- retry(new ConflictManagementPredicate(operationSucceeded) {
+ assertTrue(new ConflictManagementPredicate(api) {
@Override
protected String operation() {
return api.getCloudServiceApi().delete(cloudService.name());
}
- }, 600, 30, 30, SECONDS).apply(cloudService.name());
+ }.apply(cloudService.name()));
for (Role r : roles) {
final Role.OSVirtualHardDisk disk = r.osVirtualHardDisk();
if (disk != null) {
- retry(new ConflictManagementPredicate(operationSucceeded) {
+ assertTrue(new ConflictManagementPredicate(api) {
@Override
protected String operation() {
return api.getDiskApi().delete(disk.diskName());
}
- }, 600, 30, 30, SECONDS).apply(disk.diskName());
+ }.apply(disk.diskName()));
}
}
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/29435e1c/azurecompute/src/test/java/org/jclouds/azurecompute/features/NetworkSecurityGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/features/NetworkSecurityGroupApiLiveTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/features/NetworkSecurityGroupApiLiveTest.java
new file mode 100644
index 0000000..763e1ce
--- /dev/null
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/features/NetworkSecurityGroupApiLiveTest.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+
+import org.jclouds.azurecompute.domain.NetworkSecurityGroup;
+import org.jclouds.azurecompute.domain.Rule;
+import org.jclouds.azurecompute.internal.BaseAzureComputeApiLiveTest;
+
+import static org.jclouds.azurecompute.internal.BaseAzureComputeApiLiveTest.DEFAULT_SUBNET_NAME;
+import static org.jclouds.azurecompute.internal.BaseAzureComputeApiLiveTest.LOCATION;
+import static org.jclouds.azurecompute.internal.BaseAzureComputeApiLiveTest.VIRTUAL_NETWORK_NAME;
+import org.jclouds.azurecompute.util.ConflictManagementPredicate;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "NetworkSecurityGroupApiLiveTest", singleThreaded = true)
+public class NetworkSecurityGroupApiLiveTest extends BaseAzureComputeApiLiveTest {
+
+ private static final String GROUP1 = System.getProperty("user.name") + RAND + "-1";
+
+ private static final String GROUP2 = System.getProperty("user.name") + RAND + "-2";
+
+ public static final String ADDRESS_SPACE = "10.10.0.0/20";
+
+ public static final String SUBNET_ADDRESS_SPACE = "10.10.0.0/23";
+
+ public static final String NETWORK_NAME = "secgrp-vnetsite";
+
+ public static final String SUBNET_NAME = "secgrp-subnet";
+
+ @BeforeClass
+ public void groupSetup() {
+ // ----------------------------
+ // Clean before start
+ // ----------------------------
+ try {
+ final NetworkSecurityGroup group = api().
+ getNetworkSecurityGroupAppliedToSubnet(VIRTUAL_NETWORK_NAME, DEFAULT_SUBNET_NAME);
+
+ if (group != null && (group.name().equals(GROUP1) || group.name().equals(GROUP2))) {
+ api().removeFromSubnet(VIRTUAL_NETWORK_NAME, DEFAULT_SUBNET_NAME, group.name());
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+
+ try {
+ if (api().get(GROUP1) != null) {
+ operationSucceeded.apply(api.getNetworkSecurityGroupApi().delete(GROUP1));
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+
+ try {
+ if (api().get(GROUP2) != null) {
+ operationSucceeded.apply(api.getNetworkSecurityGroupApi().delete(GROUP2));
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ // ----------------------------
+
+ String requestId = api().create(
+ NetworkSecurityGroup.create(GROUP1, GROUP1 + " security group", LOCATION, null, null));
+
+ assertTrue(operationSucceeded.apply(requestId), GROUP1);
+
+ requestId = api().create(
+ NetworkSecurityGroup.create(GROUP2, GROUP2 + " security group", LOCATION, null, null));
+
+ assertTrue(operationSucceeded.apply(requestId), GROUP2);
+ }
+
+ @Test
+ public void list() {
+ final List<NetworkSecurityGroup> groups = api().list();
+ assertFalse(groups.isEmpty());
+ }
+
+ @Test
+ public void get() {
+ final NetworkSecurityGroup group = api().get(GROUP1);
+ assertEquals(group.name(), GROUP1);
+ assertEquals(group.label(), GROUP1 + " security group");
+ assertEquals(group.location(), LOCATION);
+ assertNull(group.state());
+ assertTrue(group.rules().isEmpty());
+ }
+
+ @Test
+ public void getFullDetails() {
+ final NetworkSecurityGroup group = api().getFullDetails(GROUP2);
+ assertEquals(group.name(), GROUP2);
+ assertEquals(group.label(), GROUP2 + " security group");
+ assertEquals(group.location(), LOCATION);
+ assertNull(group.state());
+ assertFalse(group.rules().isEmpty());
+ }
+
+ @Test
+ public void setRule() {
+ final String ruleName = "newrule";
+
+ final String requestId = api().setRule(GROUP1, ruleName, Rule.create(
+ ruleName,
+ Rule.Type.Inbound,
+ "100",
+ Rule.Action.Allow,
+ "INTERNET",
+ "*",
+ "10.0.0.0/0",
+ "*",
+ Rule.Protocol.ALL));
+
+ assertTrue(operationSucceeded.apply(requestId), ruleName);
+
+ Rule newrule = null;
+
+ for (Rule rule : api().getFullDetails(GROUP1).rules()) {
+ if (ruleName.equals(rule.name())) {
+ newrule = rule;
+ }
+ }
+
+ assertNotNull(newrule);
+
+ assertNull(newrule.isDefault());
+ assertEquals(newrule.action(), Rule.Action.Allow);
+ assertEquals(newrule.type(), Rule.Type.Inbound);
+ assertEquals(newrule.protocol(), Rule.Protocol.ALL);
+ assertEquals(newrule.state(), "Active");
+ }
+
+ @Test(dependsOnMethods = {"setRule"})
+ public void removeRule() {
+ final String ruleName = "newrule";
+
+ final String requestId = api().deleteRule(GROUP1, ruleName);
+ assertTrue(operationSucceeded.apply(requestId), ruleName);
+
+ Rule newrule = null;
+
+ for (Rule rule : api().getFullDetails(GROUP1).rules()) {
+ if (ruleName.equals(rule.name())) {
+ newrule = rule;
+ }
+ }
+
+ assertNull(newrule);
+ }
+
+ @Test(dependsOnMethods = {"removeRule"})
+ public void addToSubnet() {
+ assertTrue(new ConflictManagementPredicate(api) {
+
+ @Override
+ protected String operation() {
+ return api().addToSubnet(VIRTUAL_NETWORK_NAME, DEFAULT_SUBNET_NAME, GROUP1);
+ }
+ }.apply(GROUP1));
+ }
+
+ @Test(dependsOnMethods = {"addToSubnet"})
+ public void getForSubnet() {
+ final NetworkSecurityGroup group = api().
+ getNetworkSecurityGroupAppliedToSubnet(VIRTUAL_NETWORK_NAME, DEFAULT_SUBNET_NAME);
+ assertEquals(group.state(), NetworkSecurityGroup.State.CREATED);
+ }
+
+ @Test(dependsOnMethods = {"getForSubnet"})
+ public void removeFromSubnet() {
+ assertTrue(new ConflictManagementPredicate(api) {
+
+ @Override
+ protected String operation() {
+ return api().removeFromSubnet(VIRTUAL_NETWORK_NAME, DEFAULT_SUBNET_NAME, GROUP1);
+ }
+ }.apply(GROUP1));
+ }
+
+ @AfterClass
+ public void cleanup() {
+ // no assertion is required: just to be sure to remove for subnet
+ final NetworkSecurityGroup group = api().
+ getNetworkSecurityGroupAppliedToSubnet(VIRTUAL_NETWORK_NAME, DEFAULT_SUBNET_NAME);
+
+ if (group != null) {
+ api().removeFromSubnet(VIRTUAL_NETWORK_NAME, DEFAULT_SUBNET_NAME, group.name());
+ }
+
+ String requestId = api.getNetworkSecurityGroupApi().delete(GROUP1);
+ assertTrue(operationSucceeded.apply(requestId), GROUP1);
+
+ requestId = api.getNetworkSecurityGroupApi().delete(GROUP2);
+ assertTrue(operationSucceeded.apply(requestId), GROUP2);
+ }
+
+ private NetworkSecurityGroupApi api() {
+ return api.getNetworkSecurityGroupApi();
+ }
+}