You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by an...@apache.org on 2015/02/27 12:31:19 UTC
[4/4] jclouds-labs git commit: AzureCompute: initial work to support
ComputeServiceAdapter
AzureCompute: initial work to support ComputeServiceAdapter
improve DeploymentToNodeMetadata
enhance Deployment value object
add support for get/set NetworkConfiguration
added AzureComputeTemplateOptions to manage networkConfigurations
add support for create/checkAvailable/list storageAccounts
add support for inboundPorts
add more RoleSize
add support for SecurityGroupExtension by using NetworkSecurityGroup
fix destroy node
fix LocationToLocation
fix OsImageToImage
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/e97ddaee
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/e97ddaee
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/e97ddaee
Branch: refs/heads/master
Commit: e97ddaeeb59acc516e3d4d8398cf2da5e5492487
Parents: c78a66c
Author: Andrea Turli <an...@gmail.com>
Authored: Tue Dec 16 09:57:04 2014 +0100
Committer: andreaturli <an...@gmail.com>
Committed: Fri Feb 27 12:30:50 2015 +0100
----------------------------------------------------------------------
azurecompute/README.md | 2 +-
azurecompute/pom.xml | 12 +
.../jclouds/azurecompute/AzureComputeApi.java | 36 ++
.../AzureComputeProviderMetadata.java | 38 +-
.../AzureManagementApiMetadata.java | 14 +-
.../binders/DeploymentParamsToXML.java | 27 +-
.../binders/NetworkConfigurationToXML.java | 62 +++
.../binders/NetworkSecurityGroupToXML.java | 45 ++
.../jclouds/azurecompute/binders/RoleToXML.java | 74 +++
.../jclouds/azurecompute/binders/RuleToXML.java | 46 ++
.../binders/StorageServiceParamsToXML.java | 49 ++
.../compute/AzureComputeServiceAdapter.java | 262 +++++++++--
.../AzureComputeServiceContextModule.java | 121 ++++-
.../AzureComputeSecurityGroupExtension.java | 449 +++++++++++++++++++
.../functions/DeploymentToNodeMetadata.java | 96 +++-
.../compute/functions/LocationToLocation.java | 56 +++
.../compute/functions/OSImageToImage.java | 23 +-
.../compute/functions/RoleSizeToHardware.java | 36 +-
.../functions/internal/OperatingSystems.java | 83 ++++
...ServiceAndVirtualNetworkThenCreateNodes.java | 270 +++++++++++
...eNodeCredentialsButOverrideFromTemplate.java | 57 +++
.../config/AzureComputeHttpApiModule.java | 24 +
.../config/AzureComputeParserModule.java | 27 ++
.../config/AzureComputeProperties.java | 21 +-
.../domain/NetworkConfiguration.java | 22 +-
.../org/jclouds/azurecompute/domain/Role.java | 9 +-
.../azurecompute/features/DeploymentApi.java | 1 +
.../features/NetworkSecurityGroupApi.java | 167 +++++++
.../features/StorageAccountApi.java | 97 ++++
.../azurecompute/features/SubscriptionApi.java | 53 +++
.../features/VirtualMachineApi.java | 40 +-
.../features/VirtualNetworkApi.java | 76 ++++
.../options/AzureComputeTemplateOptions.java | 324 +++++++++++++
.../util/NetworkSecurityGroups.java | 73 +++
.../xml/ConfigurationSetHandler.java | 8 +-
.../xml/NetworkConfigurationHandler.java | 44 +-
.../ResourceExtensionParameterValueHandler.java | 60 +++
.../xml/ResourceExtensionReferenceHandler.java | 100 +++++
.../jclouds/azurecompute/xml/RoleHandler.java | 19 +-
.../azurecompute/xml/StorageServiceHandler.java | 2 +-
.../jclouds/azurecompute/xml/SubnetHandler.java | 3 +
.../xml/VirtualNetworkConfigurationHandler.java | 73 +++
.../xml/VirtualNetworkSiteHandler.java | 5 +
.../AzureComputeServiceAdapterLiveTest.java | 130 ++++++
.../AzureComputeServiceContextLiveTest.java | 81 ++++
...reComputeSecurityGroupExtensionLiveTest.java | 45 ++
.../features/CloudServiceApiLiveTest.java | 26 +-
.../features/CloudServiceApiMockTest.java | 55 +--
.../features/DeploymentApiLiveTest.java | 132 ++++++
.../features/DeploymentApiMockTest.java | 69 +--
.../azurecompute/features/DiskApiLiveTest.java | 2 +
.../azurecompute/features/DiskApiMockTest.java | 36 +-
.../features/LocationApiMockTest.java | 17 +-
.../features/OSImageApiMockTest.java | 41 +-
.../features/OperationApiMockTest.java | 18 +-
.../features/SubscriptionApiLiveTest.java | 42 ++
.../features/VirtualMachineApiLiveTest.java | 161 +++++++
.../features/VirtualMachineApiMockTest.java | 26 +-
.../features/VirtualNetworkApiLiveTest.java | 112 +++++
.../features/VirtualNetworkApiMockTest.java | 95 ++++
.../internal/BaseAzureComputeApiLiveTest.java | 163 ++++++-
.../internal/BaseAzureComputeApiMockTest.java | 7 +-
.../azurecompute/xml/DeploymentHandlerTest.java | 6 +-
.../xml/NetworkConfigurationHandlerTest.java | 50 +++
.../azurecompute/xml/RoleHandlerTest.java | 80 ++++
.../test/resources/deploymentparams-windows.xml | 2 +-
.../src/test/resources/deploymentparams.xml | 2 +-
.../src/test/resources/networkconfiguration.xml | 18 +
azurecompute/src/test/resources/role.xml | 56 +++
docker/src/test/resources/logback.xml | 2 +-
70 files changed, 4211 insertions(+), 369 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/azurecompute/README.md
----------------------------------------------------------------------
diff --git a/azurecompute/README.md b/azurecompute/README.md
index b38c672..9e44b67 100644
--- a/azurecompute/README.md
+++ b/azurecompute/README.md
@@ -20,7 +20,7 @@ openssl x509 -inform pem -in $HOME/.jclouds/azure.pem -outform der -out $HOME/.j
Once you do this, you will set the following to run the live tests.
```bash
-mvn -Plive -Dtest.jclouds.azurecompute.subscription-id=12345678-abcd-dcba-abdc-ba0987654321
+mvn -Plive -Dtest.azurecompute.endpoint=https://management.core.windows.net/12345678-abcd-dcba-abdc-ba0987654321
-Dtest.azurecompute.credential=P12_EXPORT_PASSWORD
-Dtest.azurecompute.identity=$HOME/.jclouds/azure.p12
```
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/azurecompute/pom.xml
----------------------------------------------------------------------
diff --git a/azurecompute/pom.xml b/azurecompute/pom.xml
index 48f2a54..4231412 100644
--- a/azurecompute/pom.xml
+++ b/azurecompute/pom.xml
@@ -86,12 +86,24 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-compute</artifactId>
+ <version>${project.parent.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.apache.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.apache.jclouds.driver</groupId>
<artifactId>jclouds-sshj</artifactId>
<version>${project.parent.version}</version>
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeApi.java b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeApi.java
index 5946838..5c35a85 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeApi.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeApi.java
@@ -24,9 +24,13 @@ import org.jclouds.azurecompute.features.CloudServiceApi;
import org.jclouds.azurecompute.features.DeploymentApi;
import org.jclouds.azurecompute.features.DiskApi;
import org.jclouds.azurecompute.features.LocationApi;
+import org.jclouds.azurecompute.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.features.OSImageApi;
import org.jclouds.azurecompute.features.OperationApi;
+import org.jclouds.azurecompute.features.StorageAccountApi;
+import org.jclouds.azurecompute.features.SubscriptionApi;
import org.jclouds.azurecompute.features.VirtualMachineApi;
+import org.jclouds.azurecompute.features.VirtualNetworkApi;
import org.jclouds.rest.annotations.Delegate;
/**
@@ -100,4 +104,36 @@ public interface AzureComputeApi extends Closeable {
*/
@Delegate
DiskApi getDiskApi();
+
+ /**
+ * The Service Management API includes operations for retrieving information about a subscription.
+ *
+ * @see <a href="http://msdn.microsoft.com/en-us/library/azure/gg715315.aspx">docs</a>
+ */
+ @Delegate
+ SubscriptionApi getSubscriptionApi();
+
+ /**
+ * The Service Management API includes operations for managing the virtual networks in your subscription.
+ *
+ * @see <a href="http://msdn.microsoft.com/en-us/library/jj157182.aspx">docs</a>
+ */
+ @Delegate
+ VirtualNetworkApi getVirtualNetworkApi();
+
+ /**
+ * The Service Management API includes operations for managing the storage accounts in your subscription.
+ *
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460790.aspx">docs</a>
+ */
+ @Delegate
+ StorageAccountApi getStorageAccountApi();
+
+ /**
+ * The Service Management API includes operations for managing the Network Security Groups in your
+ * subscription.
+ *
+ */
+ @Delegate
+ NetworkSecurityGroupApi getNetworkSecurityGroupApi();
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
index e9bb875..60e00d1 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
@@ -16,11 +16,14 @@
*/
package org.jclouds.azurecompute;
-import static org.jclouds.azurecompute.config.AzureComputeProperties.SUBSCRIPTION_ID;
-
+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;
+import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
import java.net.URI;
import java.util.Properties;
+import org.jclouds.azurecompute.config.AzureComputeProperties;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadata;
@@ -42,27 +45,32 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
super(builder());
}
- public AzureComputeProviderMetadata(Builder builder) {
- super(builder);
- }
-
public static Properties defaultProperties() {
- Properties properties = new Properties();
+ Properties properties = AzureManagementApiMetadata.defaultProperties();
+ properties.setProperty(TEMPLATE, "osFamily=UBUNTU,loginUser=jclouds");
+ properties.setProperty(OPERATION_TIMEOUT, "" + 60 * 1000);
+ properties.setProperty(OPERATION_POLL_INITIAL_PERIOD, "" + 5);
+ properties.setProperty(OPERATION_POLL_MAX_PERIOD, "" + 15);
+ properties.setProperty(AzureComputeProperties.TCP_RULE_FORMAT, "tcp_%s-%s");
return properties;
}
+ public AzureComputeProviderMetadata(Builder builder) {
+ super(builder);
+ }
+
public static class Builder extends BaseProviderMetadata.Builder {
protected Builder() {
id("azurecompute")
- .name("Microsoft Azure Service Management Service")
- .apiMetadata(new AzureManagementApiMetadata())
- .endpoint("https://management.core.windows.net/${" + SUBSCRIPTION_ID + "}")
- .homepage(URI.create("https://www.windowsazure.com/"))
- .console(URI.create("https://windows.azure.com/default.aspx"))
- .linkedServices("azureblob", "azurequeue", "azuretable")
- .iso3166Codes("US-TX", "US-IL", "IE-D", "SG", "NL-NH", "HK")
- .defaultProperties(AzureComputeProviderMetadata.defaultProperties());
+ .name("Microsoft Azure Service Management Service")
+ .apiMetadata(new AzureManagementApiMetadata())
+ .endpoint("https://management.core.windows.net/SUBSCRIPTION_ID")
+ .homepage(URI.create("https://www.windowsazure.com/"))
+ .console(URI.create("https://windows.azure.com/default.aspx"))
+ .linkedServices("azureblob", "azurequeue", "azuretable")
+ .iso3166Codes("US-TX", "US-IL", "IE-D", "SG", "NL-NH", "HK")
+ .defaultProperties(AzureComputeProviderMetadata.defaultProperties());
}
@Override
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/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 0caad94..8e5fa86 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
@@ -16,14 +16,14 @@
*/
package org.jclouds.azurecompute;
-import static org.jclouds.azurecompute.config.AzureComputeProperties.SUBSCRIPTION_ID;
-
+import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.azurecompute.compute.config.AzureComputeServiceContextModule;
import org.jclouds.azurecompute.config.AzureComputeHttpApiModule;
+import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.rest.internal.BaseHttpApiMetadata;
import com.google.common.collect.ImmutableSet;
@@ -56,17 +56,17 @@ public class AzureManagementApiMetadata extends BaseHttpApiMetadata<AzureCompute
protected Builder() {
id("azurecompute")
- .name("Microsoft Azure Service Management Service API")
- .version("2014-06-01")
+ .name("Microsoft Azure Service Management Service API")
+ .version("2014-10-01")
.identityName("Path to Management Certificate .p12 file, or PEM string")
.credentialName("Password to Management Certificate")
- .defaultEndpoint("https://management.core.windows.net/${" + SUBSCRIPTION_ID + "}")
.endpointName("Service Management Endpoint ending in your Subscription Id")
.documentation(URI.create("http://msdn.microsoft.com/en-us/library/ee460799"))
.defaultProperties(AzureManagementApiMetadata.defaultProperties())
+ .view(typeToken(ComputeServiceContext.class))
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
- .add(AzureComputeServiceContextModule.class)
- .add(AzureComputeHttpApiModule.class).build());
+ .add(AzureComputeServiceContextModule.class)
+ .add(AzureComputeHttpApiModule.class).build());
}
@Override
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java
index 26301d6..bc9f657 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java
@@ -16,8 +16,6 @@
*/
package org.jclouds.azurecompute.binders;
-import static com.google.common.base.CaseFormat.UPPER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.azurecompute.domain.OSImage.Type.LINUX;
@@ -68,7 +66,9 @@ public final class DeploymentParamsToXML implements Binder {
.e("UserName").t(params.username()).up()
.e("UserPassword").t(params.password()).up()
.e("DisableSshPasswordAuthentication").t("false").up()
- .e("SSH").up()
+ .e("SSH")
+ .e("PublicKeys").up()
+ .e("KeyPairs").up()
.up(); // Linux ConfigurationSet
} else {
throw new IllegalArgumentException("Unrecognized os type " + params);
@@ -88,25 +88,34 @@ public final class DeploymentParamsToXML implements Binder {
}
inputEndpoints.up();
- configBuilder.e("SubnetNames").up()
- .up();
+ //configBuilder.e("SubnetNames").up().up();
+
+ XMLBuilder subnetNames = configBuilder.e("SubnetNames");
+ for (String subnetName : params.subnetNames()) {
+ subnetNames.e("SubnetName").t(subnetName).up()
+ .up(); //subnetName
+ }
builder.up() //ConfigurationSets
+ // TODO No Disk should be specified for a Role if using a VMImage
.e("DataVirtualHardDisks").up()
.e("OSVirtualHardDisk")
.e("HostCaching").t("ReadWrite").up()
.e("MediaLink").t(params.mediaLink().toASCIIString()).up()
+ // TODO
+ /// If you are using a VM image, it must be specified as VMImageName for the role, not as SourceImageNamefor OSVirtualHardDisk.</Message></Error>]
.e("SourceImageName").t(params.sourceImageName()).up()
.e("OS").t(params.os() == LINUX ? "Linux" : "Windows").up()
- .up() //OSVirtualHardDisk
- .e("RoleSize").t(UPPER_UNDERSCORE.to(UPPER_CAMEL, params.size().name())).up()
+ .up() //OSVirtualHardDisk
+ .e("RoleSize").t(params.size().getText()).up()
.up() //Role
- .up(); //RoleList
-
+ .up() //RoleList
+ .e("VirtualNetworkName").t(params.virtualNetworkName()).up();
// TODO: Undeprecate this method as forcing users to wrap a String in guava's ByteSource is not great.
return (R) request.toBuilder().payload(builder.asString()).build();
} catch (Exception e) {
throw propagate(e);
}
}
+
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkConfigurationToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkConfigurationToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkConfigurationToXML.java
new file mode 100644
index 0000000..87ffb5e
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkConfigurationToXML.java
@@ -0,0 +1,62 @@
+/*
+ * 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.binders;
+
+import static com.google.common.base.Throwables.propagate;
+
+import org.jclouds.azurecompute.domain.NetworkConfiguration;
+import org.jclouds.azurecompute.domain.NetworkConfiguration.Subnet;
+import org.jclouds.azurecompute.domain.NetworkConfiguration.VirtualNetworkSite;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.jamesmurty.utils.XMLBuilder;
+
+public class NetworkConfigurationToXML implements Binder {
+
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ NetworkConfiguration networkConfiguration = NetworkConfiguration.class.cast(input);
+
+ try {
+ XMLBuilder builder = XMLBuilder.create("NetworkConfiguration", "http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration")
+ .e("VirtualNetworkConfiguration");
+ if (networkConfiguration.virtualNetworkConfiguration().dns() == null) {
+ builder.e("Dns");
+ } else {
+ builder.e("Dns").t(networkConfiguration.virtualNetworkConfiguration().dns());
+ }
+ if (!networkConfiguration.virtualNetworkConfiguration().virtualNetworkSites().isEmpty()) {
+ XMLBuilder virtualNetworkSitesBuilder = builder.e("VirtualNetworkSites");
+ for (VirtualNetworkSite virtualNetworkSite : networkConfiguration.virtualNetworkConfiguration().virtualNetworkSites()) {
+ XMLBuilder virtualNetworkSiteBuilder = virtualNetworkSitesBuilder.e("VirtualNetworkSite").a("name",
+ virtualNetworkSite.name()).a("Location", virtualNetworkSite.location());
+ virtualNetworkSiteBuilder.e("AddressSpace")
+ .e("AddressPrefix").t(virtualNetworkSite.addressSpace().addressPrefix()).up();
+ XMLBuilder subnetBuilder = virtualNetworkSiteBuilder.e("Subnets");
+ for (Subnet subnet : virtualNetworkSite.subnets()) {
+ subnetBuilder.e("Subnet").a("name", subnet.name()).e("AddressPrefix").t(subnet.addressPrefix());
+ }
+ }
+ }
+ return (R) request.toBuilder().payload(builder.asString()).build();
+ } catch (Exception e) {
+ throw propagate(e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkSecurityGroupToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkSecurityGroupToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkSecurityGroupToXML.java
new file mode 100644
index 0000000..6290df6
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkSecurityGroupToXML.java
@@ -0,0 +1,45 @@
+/*
+ * 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.binders;
+
+import static com.google.common.base.Throwables.propagate;
+
+import org.jclouds.azurecompute.domain.NetworkSecurityGroup;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.jamesmurty.utils.XMLBuilder;
+
+public class NetworkSecurityGroupToXML implements Binder {
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ NetworkSecurityGroup networkSecurityGroup = NetworkSecurityGroup.class.cast(input);
+ try {
+ XMLBuilder builder = XMLBuilder.create("NetworkSecurityGroup", "http://schemas.microsoft.com/windowsazure")
+ .e("Name").t(networkSecurityGroup.name()).up();
+ if (networkSecurityGroup.label() != null) {
+ builder.e("Label").t(networkSecurityGroup.label()).up();
+ }
+ if (networkSecurityGroup.location() != null) {
+ builder.e("Location").t(networkSecurityGroup.location()).up();
+ }
+ return (R) request.toBuilder().payload(builder.asString()).build();
+ } catch (Exception e) {
+ throw propagate(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java
new file mode 100644
index 0000000..41c3a83
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java
@@ -0,0 +1,74 @@
+/*
+ * 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.binders;
+
+import static com.google.common.base.Throwables.propagate;
+
+import org.jclouds.azurecompute.domain.Role;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.jamesmurty.utils.XMLBuilder;
+
+public class RoleToXML implements Binder {
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ Role role = Role.class.cast(input);
+
+ try {
+ XMLBuilder builder = XMLBuilder.create("PersistentVMRole", "http://schemas.microsoft.com/windowsazure")
+ .e("RoleName").t(role.roleName()).up()
+ .e("RoleType").t(role.roleType()).up()
+ .e("ConfigurationSets");
+
+ if (!role.configurationSets().isEmpty()) {
+ for (Role.ConfigurationSet configurationSet : role.configurationSets()) {
+ XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Network
+ configBuilder.e("ConfigurationSetType").t(configurationSet.configurationSetType()).up();
+
+ XMLBuilder inputEndpoints = configBuilder.e("InputEndpoints");
+ for (Role.ConfigurationSet.InputEndpoint endpoint : configurationSet.inputEndpoints()) {
+ XMLBuilder inputBuilder = inputEndpoints.e("InputEndpoint");
+ inputBuilder.e("LocalPort").t(Integer.toString(endpoint.localPort())).up()
+ .e("Name").t(endpoint.name()).up()
+ .e("Port").t(Integer.toString(endpoint.port())).up()
+ .e("Protocol").t(endpoint.protocol().toLowerCase()).up()
+ .up(); //InputEndpoint
+ }
+ XMLBuilder subnetNames = configBuilder.e("SubnetNames");
+ for (Role.ConfigurationSet.SubnetName subnetName : configurationSet.subnetNames()) {
+ subnetNames.e("SubnetName").t(subnetName.name()).up();
+ }
+ configBuilder.e("NetworkSecurityGroup").t(configurationSet.networkSecurityGroup()).up();
+ }
+ }
+ builder.e("DataVirtualHardDisks").up()
+ .e("OSVirtualHardDisk")
+ .e("HostCaching").t(role.osVirtualHardDisk().hostCaching()).up()
+ .e("DiskName").t(role.osVirtualHardDisk().diskName()).up()
+ .e("MediaLink").t(role.osVirtualHardDisk().mediaLink().toString()).up()
+ .e("SourceImageName").t(role.osVirtualHardDisk().sourceImageName()).up()
+ .e("OS").t(role.osVirtualHardDisk().os().toString()).up()
+ .up() // DataVirtualHardDisks
+ .e("RoleSize").t(role.roleSize().getText());
+ return (R) request.toBuilder().payload(builder.asString()).build();
+ } catch (Exception e) {
+ throw propagate(e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/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
new file mode 100644
index 0000000..ec4a1f6
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RuleToXML.java
@@ -0,0 +1,46 @@
+/*
+ * 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.binders;
+
+import static com.google.common.base.Throwables.propagate;
+
+import org.jclouds.azurecompute.domain.Rule;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.jamesmurty.utils.XMLBuilder;
+
+public final class RuleToXML implements Binder {
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ Rule rule = Rule.class.cast(input);
+ try {
+ String xml = XMLBuilder.create("Rule", "http://schemas.microsoft.com/windowsazure")
+ .e("Type").t(rule.type()).up()
+ .e("Priority").t(rule.priority()).up()
+ .e("Action").t(rule.action()).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();
+ return (R) request.toBuilder().payload(xml).build();
+ } catch (Exception e) {
+ throw propagate(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/azurecompute/src/main/java/org/jclouds/azurecompute/binders/StorageServiceParamsToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/StorageServiceParamsToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/StorageServiceParamsToXML.java
new file mode 100644
index 0000000..f6a934e
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/StorageServiceParamsToXML.java
@@ -0,0 +1,49 @@
+/*
+ * 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.binders;
+
+import static com.google.common.base.Throwables.propagate;
+import org.jclouds.azurecompute.domain.StorageServiceParams;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.BaseEncoding;
+import com.jamesmurty.utils.XMLBuilder;
+
+public final class StorageServiceParamsToXML implements Binder {
+
+ @Override public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ StorageServiceParams params = StorageServiceParams.class.cast(input);
+
+ try {
+ XMLBuilder builder = XMLBuilder.create("CreateStorageServiceInput", "http://schemas.microsoft.com/windowsazure")
+ .e("ServiceName").t(params.name()).up()
+ //.e("Description").up()
+ .e("Label").t(BaseEncoding.base64().encode(params.label().getBytes(Charsets.UTF_16))).up()
+ .e("Location").t(params.location()).up()
+ //.e("GeoReplicationEnabled").up()
+ //.e("ExtendedProperties").up()
+ //.e("SecondaryReadEnabled").up()
+ .e("AccountType").t(params.accountType().name()).up();
+ return (R) request.toBuilder().payload(builder.asString()).build();
+ } catch (Exception e) {
+ throw propagate(e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/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 9663a75..aed8570 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
@@ -16,89 +16,293 @@
*/
package org.jclouds.azurecompute.compute;
+import static com.google.common.base.Predicates.notNull;
+import static java.lang.String.format;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.azurecompute.domain.Deployment.InstanceStatus.READY_ROLE;
+import static org.jclouds.util.Predicates2.retry;
+import java.net.URI;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.azurecompute.AzureComputeApi;
+import org.jclouds.azurecompute.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
+import org.jclouds.azurecompute.config.AzureComputeProperties;
+import org.jclouds.azurecompute.domain.CloudService;
import org.jclouds.azurecompute.domain.Deployment;
+import org.jclouds.azurecompute.domain.Deployment.RoleInstance;
+import org.jclouds.azurecompute.domain.DeploymentParams;
+import org.jclouds.azurecompute.domain.DeploymentParams.ExternalEndpoint;
+import org.jclouds.azurecompute.domain.Location;
import org.jclouds.azurecompute.domain.OSImage;
import org.jclouds.azurecompute.domain.RoleSize;
+import org.jclouds.azurecompute.options.AzureComputeTemplateOptions;
import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.logging.Logger;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
/**
* defines the connection between the {@link AzureComputeApi} implementation and the
* jclouds {@link org.jclouds.compute.ComputeService}
*/
@Singleton
-public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deployment, RoleSize, OSImage, String> {
+public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deployment, RoleSize, OSImage, Location> {
+
+ private static final String DEFAULT_LOGIN_USER = "jclouds";
+ private static final String DEFAULT_LOGIN_PASSWORD = "Azur3Compute!";
+
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ private final AzureComputeApi api;
+ private final Predicate<String> operationSucceededPredicate;
+ private final AzureComputeConstants azureComputeConstants;
+
+ @Inject
+ AzureComputeServiceAdapter(final AzureComputeApi api, Predicate<String> operationSucceededPredicate, AzureComputeConstants azureComputeConstants) {
+ this.api = api;
+ this.operationSucceededPredicate = operationSucceededPredicate;
+ this.azureComputeConstants = azureComputeConstants;
+ }
@Override
public NodeAndInitialCredentials<Deployment> createNodeWithGroupEncodedIntoName(
- String group, String name, Template template) {
- // TODO Auto-generated method stub
- return null;
+ final String group, final String name, Template template) {
+
+ // azure-specific options
+ AzureComputeTemplateOptions templateOptions = template.getOptions().as(AzureComputeTemplateOptions.class);
+
+ final String loginUser = templateOptions.getLoginUser() != null ? templateOptions.getLoginUser() : DEFAULT_LOGIN_USER;
+ final String loginPassword = templateOptions.getLoginPassword() != null ? templateOptions.getLoginPassword() : DEFAULT_LOGIN_PASSWORD;
+ final String location = template.getLocation().getId();
+ final int[] inboundPorts = template.getOptions().getInboundPorts();
+
+ final String storageAccountName = templateOptions.getStorageAccountName().get();
+ final String virtualNetworkName = templateOptions.getVirtualNetworkName().get();
+ final String subnetName = templateOptions.getSubnetName().get();
+
+ logger.debug("Creating a cloud service with name '%s', label '%s' in location '%s'", name, name, location);
+ String createCloudServiceRequestId = api.getCloudServiceApi().createWithLabelInLocation(name, name, location);
+ if (!operationSucceededPredicate.apply(createCloudServiceRequestId)) {
+ final String message = generateIllegalStateExceptionMessage(createCloudServiceRequestId, azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ throw new IllegalStateException(message);
+ }
+ logger.info("Cloud Service (%s) created with operation id: %s", name, createCloudServiceRequestId);
+
+ final OSImage.Type os = template.getImage().getOperatingSystem().getFamily().equals(OsFamily.WINDOWS) ? OSImage.Type.WINDOWS : OSImage.Type.LINUX;
+ Set<ExternalEndpoint> externalEndpoints = Sets.newHashSet();
+ for (int inboundPort : inboundPorts) {
+ externalEndpoints.add(ExternalEndpoint.inboundTcpToLocalPort(inboundPort, inboundPort));
+ }
+ final DeploymentParams params = DeploymentParams.builder()
+ .name(name)
+ .os(os)
+ .username(loginUser)
+ .password(loginPassword)
+ .sourceImageName(template.getImage().getId())
+ .mediaLink(createMediaLink(storageAccountName, name))
+ .size(RoleSize.Type.fromString(template.getHardware().getName()))
+ .externalEndpoints(externalEndpoints)
+ .subnetName(subnetName)
+ .virtualNetworkName(virtualNetworkName)
+ .build();
+
+ logger.debug("Creating a deployment with params '%s' ...", params);
+ String createDeploymentRequestId = api.getDeploymentApiForService(name).create(params);
+ if (!operationSucceededPredicate.apply(createDeploymentRequestId)) {
+ 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);
+ }
+ logger.info("Deployment created with operation id: %s", createDeploymentRequestId);
+
+ if (!retry(new Predicate<String>() {
+ public boolean apply(String name) {
+ return FluentIterable.from(api.getDeploymentApiForService(name).get(name).roleInstanceList())
+ .allMatch(new Predicate<RoleInstance>() {
+ @Override
+ public boolean apply(RoleInstance input) {
+ return input != null && input.instanceStatus() == READY_ROLE;
+ }
+ });
+ }
+ }, 30 * 60, 1, SECONDS).apply(name)) {
+ logger.warn("Instances %s of %s has not reached the status %s within %sms so it will be destroyed.",
+ Iterables.toString(api.getDeploymentApiForService(name).get(name).roleInstanceList()), name,
+ READY_ROLE, azureComputeConstants.operationTimeout());
+ api.getDeploymentApiForService(group).delete(name);
+ api.getCloudServiceApi().delete(name);
+ throw new IllegalStateException(format("Deployment %s is being destroyed as its instanceStatus didn't reach " +
+ "status %s after %ss. Please, try by increasing `jclouds.azure.operation-timeout` and " +
+ " try again", name, READY_ROLE, 30 * 60));
+ }
+
+ Deployment deployment = api.getDeploymentApiForService(name).get(name);
+
+ return new NodeAndInitialCredentials(deployment, deployment.name(),
+ LoginCredentials.builder().user(loginUser).password(loginPassword).build());
+ }
+
+ public static String generateIllegalStateExceptionMessage(String operationId, long timeout) {
+ final String warnMessage = format("%s has not been completed within %sms.", operationId, timeout);
+ return format("%s. Please, try by increasing `%s` and try again", warnMessage, AzureComputeProperties.OPERATION_TIMEOUT);
}
@Override
public Iterable<RoleSize> listHardwareProfiles() {
- // TODO Auto-generated method stub
- return null;
+ return api.getSubscriptionApi().listRoleSizes();
}
@Override
public Iterable<OSImage> listImages() {
- // TODO Auto-generated method stub
- return null;
+ List<OSImage> osImages = Lists.newArrayList();
+ for (OSImage osImage : api.getOSImageApi().list()) {
+ Iterable<String> locations = Splitter.on(";").split(osImage.location());
+ for (String location : locations) {
+ osImages.add(OSImage.create(
+ osImage.name(),
+ location,
+ osImage.affinityGroup(),
+ osImage.label(),
+ osImage.description(),
+ osImage.category(),
+ osImage.os(),
+ osImage.publisherName(),
+ osImage.mediaLink(),
+ osImage.logicalSizeInGB(),
+ osImage.eula()
+ ));
+ }
+ }
+ return osImages;
}
@Override
- public OSImage getImage(String id) {
- // TODO Auto-generated method stub
- return null;
+ public OSImage getImage(final String id) {
+ return Iterables.find(api.getOSImageApi().list(), new Predicate<OSImage>() {
+ @Override
+ public boolean apply(OSImage input) {
+ return input.name().equals(id);
+ }
+ });
}
@Override
- public Iterable<String> listLocations() {
- // TODO Auto-generated method stub
- return null;
+ public Iterable<Location> listLocations() {
+ return api.getLocationApi().list();
}
@Override
- public Deployment getNode(String id) {
- // TODO Auto-generated method stub
- return null;
+ public Deployment getNode(final String id) {
+ return FluentIterable.from(api.getCloudServiceApi().list())
+ .transform(new Function<CloudService, Deployment>() {
+ @Override
+ public Deployment apply(CloudService input) {
+ return api.getDeploymentApiForService(input.name()).get(id);
+ }
+ })
+ .firstMatch(notNull())
+ .orNull();
}
@Override
- public void destroyNode(String id) {
- // TODO Auto-generated method stub
+ public void destroyNode(final String id) {
+ CloudService cloudService = api.getCloudServiceApi().get(id);
+ if (cloudService != null) {
+ // TODO detach disk before deleting node
+ final String cloudServiceName = cloudService.name();
+ logger.debug("Deleting deployment(%s) of cloud service (%s)", id, cloudServiceName);
+ deleteDeployment(id, cloudServiceName);
+ logger.debug("Deployment (%s) deleted in cloud service (%s).", id, cloudServiceName);
+
+ logger.debug("Deleting cloud service (%s) ...", cloudServiceName);
+ deleteCloudService(cloudServiceName);
+ logger.debug("Cloud service (%s) deleted.", cloudServiceName);
+ }
}
@Override
- public void rebootNode(String id) {
- // TODO Auto-generated method stub
+ public void rebootNode(final String id) {
+ throw new UnsupportedOperationException();
}
@Override
public void resumeNode(String id) {
- // TODO Auto-generated method stub
+ throw new UnsupportedOperationException();
}
@Override
public void suspendNode(String id) {
- // TODO Auto-generated method stub
-
+ throw new UnsupportedOperationException();
}
@Override
public Iterable<Deployment> listNodes() {
- // TODO Auto-generated method stub
- return null;
+ Set<Deployment> deployments = FluentIterable.from(api.getCloudServiceApi().list())
+ .transform(new Function<CloudService, Deployment>() {
+ @Override
+ public Deployment apply(CloudService cloudService) {
+ return api.getDeploymentApiForService(cloudService.name()).get(cloudService.name());
+ }
+ })
+ .filter(notNull())
+ .toSet();
+ return deployments;
+ }
+
+ @Override
+ public Iterable<Deployment> listNodesByIds(final Iterable<String> ids) {
+ return Iterables.filter(listNodes(), new Predicate<Deployment>() {
+ @Override
+ public boolean apply(Deployment input) {
+ return Iterables.contains(ids, input.name());
+ }
+ });
+ }
+
+ @VisibleForTesting
+ public static URI createMediaLink(String storageServiceName, String diskName) {
+ return URI.create(String.format("https://%s.blob.core.windows.net/vhds/disk-%s.vhd", storageServiceName, diskName));
}
- @Override public Iterable<Deployment> listNodesByIds(Iterable<String> ids) {
- // TODO Auto-generated method stub
- return null;
+ private void deleteCloudService(String name) {
+ String deleteCloudServiceId = api.getCloudServiceApi().delete(name);
+ if (!operationSucceededPredicate.apply(deleteCloudServiceId)) {
+ final String deleteMessage = generateIllegalStateExceptionMessage(deleteCloudServiceId, azureComputeConstants.operationTimeout());
+ logger.warn(deleteMessage);
+ throw new IllegalStateException(deleteMessage);
+ }
}
+
+ private void deleteDeployment(String id, String cloudServiceName) {
+ String deleteDeploymentId = api.getDeploymentApiForService(cloudServiceName).delete(id);
+ if (!operationSucceededPredicate.apply(deleteDeploymentId)) {
+ final String deleteMessage = generateIllegalStateExceptionMessage(deleteDeploymentId, azureComputeConstants.operationTimeout());
+ logger.warn(deleteMessage);
+ throw new IllegalStateException(deleteMessage);
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/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 b09b867..30e2569 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,28 +16,56 @@
*/
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;
+import static org.jclouds.azurecompute.config.AzureComputeProperties.TCP_RULE_FORMAT;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.azurecompute.AzureComputeApi;
import org.jclouds.azurecompute.compute.AzureComputeServiceAdapter;
+import org.jclouds.azurecompute.compute.extensions.AzureComputeSecurityGroupExtension;
import org.jclouds.azurecompute.compute.functions.DeploymentToNodeMetadata;
+import org.jclouds.azurecompute.compute.functions.LocationToLocation;
import org.jclouds.azurecompute.compute.functions.OSImageToImage;
import org.jclouds.azurecompute.compute.functions.RoleSizeToHardware;
+import org.jclouds.azurecompute.compute.strategy.GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes;
+import org.jclouds.azurecompute.compute.strategy.UseNodeCredentialsButOverrideFromTemplate;
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;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.Hardware;
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.util.Predicates2;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
public class AzureComputeServiceContextModule
- extends ComputeServiceAdapterContextModule<Deployment, RoleSize, OSImage, String> {
+ extends ComputeServiceAdapterContextModule<Deployment, RoleSize, OSImage, Location> {
@Override
protected void configure() {
super.configure();
- bind(new TypeLiteral<ComputeServiceAdapter<Deployment, RoleSize, OSImage, String>>() {
+ bind(new TypeLiteral<ComputeServiceAdapter<Deployment, RoleSize, OSImage, Location>>() {
}).to(AzureComputeServiceAdapter.class);
bind(new TypeLiteral<Function<OSImage, org.jclouds.compute.domain.Image>>() {
}).to(OSImageToImage.class);
@@ -45,5 +73,94 @@ public class AzureComputeServiceContextModule
}).to(RoleSizeToHardware.class);
bind(new TypeLiteral<Function<Deployment, NodeMetadata>>() {
}).to(DeploymentToNodeMetadata.class);
+
+ bind(PrioritizeCredentialsFromTemplate.class).to(UseNodeCredentialsButOverrideFromTemplate.class);
+ bind(new TypeLiteral<Function<Location, org.jclouds.domain.Location>>() {
+ }).to(LocationToLocation.class);
+
+ bind(TemplateOptions.class).to(AzureComputeTemplateOptions.class);
+
+ bind(new TypeLiteral<SecurityGroupExtension>() {}).to(AzureComputeSecurityGroupExtension.class);
+ bind(CreateNodesInGroupThenAddToSet.class).to(GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.class);
+
+ // to have the compute service adapter override default locations
+ install(new LocationsFromComputeServiceAdapterModule<Deployment, RoleSize, OSImage, Location>(){});
+ }
+
+ @Override
+ protected Optional<SecurityGroupExtension> provideSecurityGroupExtension(Injector i) {
+ return Optional.of(i.getInstance(SecurityGroupExtension.class));
+ }
+
+ @Provides
+ @Singleton
+ protected Predicate<String> provideOperationSucceededPredicate(final AzureComputeApi api, AzureComputeConstants azureComputeConstants) {
+ return Predicates2.retry(new OperationSucceededPredicate(api),
+ azureComputeConstants.operationTimeout(), azureComputeConstants.operationPollInitialPeriod(),
+ azureComputeConstants.operationPollMaxPeriod());
}
+
+ @VisibleForTesting
+ static class OperationSucceededPredicate implements Predicate<String> {
+
+ private final AzureComputeApi api;
+
+ public OperationSucceededPredicate(AzureComputeApi api) {
+ this.api = checkNotNull(api, "api must not be null");
+ }
+
+ @Override
+ public boolean apply(String input) {
+ Operation operation = api.getOperationApi().get(input);
+ switch (operation.status()) {
+ case SUCCEEDED:
+ return true;
+ case IN_PROGRESS:
+ return false;
+ case FAILED:
+ return false;
+ case UNRECOGNIZED:
+ return false;
+ default:
+ throw new IllegalStateException("Operation is in invalid status: " + operation.status().name());
+ }
+ }
+
+ }
+
+ @Singleton
+ public static class AzureComputeConstants {
+ @Named(OPERATION_TIMEOUT)
+ @Inject
+ private String operationTimeoutProperty;
+
+ @Named(OPERATION_POLL_INITIAL_PERIOD)
+ @Inject
+ private String operationPollInitialPeriodProperty;
+
+ @Named(OPERATION_POLL_MAX_PERIOD)
+ @Inject
+ private String operationPollMaxPeriodProperty;
+
+ @Named(TCP_RULE_FORMAT)
+ @Inject
+ private String tcpRuleFormatProperty;
+
+ public Long operationTimeout() {
+ return Long.parseLong(operationTimeoutProperty);
+ }
+
+ public Integer operationPollInitialPeriod() {
+ return Integer.parseInt(operationPollInitialPeriodProperty);
+ }
+
+ public Integer operationPollMaxPeriod() {
+ return Integer.parseInt(operationPollMaxPeriodProperty);
+ }
+
+ public String tcpRuleFormat() {
+ return tcpRuleFormatProperty;
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/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
new file mode 100644
index 0000000..d5e2db1
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java
@@ -0,0 +1,449 @@
+/*
+ * 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.compute.extensions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.azurecompute.compute.AzureComputeServiceAdapter.generateIllegalStateExceptionMessage;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.azurecompute.AzureComputeApi;
+import org.jclouds.azurecompute.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
+import org.jclouds.azurecompute.config.AzureComputeProperties;
+import org.jclouds.azurecompute.domain.CloudService;
+import org.jclouds.azurecompute.domain.Deployment;
+import org.jclouds.azurecompute.domain.NetworkConfiguration;
+import org.jclouds.azurecompute.domain.NetworkConfiguration.VirtualNetworkSite;
+import org.jclouds.azurecompute.domain.NetworkSecurityGroup;
+import org.jclouds.azurecompute.domain.Role;
+import org.jclouds.azurecompute.domain.Rule;
+import org.jclouds.azurecompute.util.NetworkSecurityGroups;
+import org.jclouds.compute.domain.SecurityGroup;
+import org.jclouds.compute.domain.SecurityGroupBuilder;
+import org.jclouds.compute.extensions.SecurityGroupExtension;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
+import org.jclouds.logging.Logger;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.net.domain.IpProtocol;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Splitter;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+
+/**
+ * An extension to compute service to allow for the manipulation of {@link org.jclouds.compute.domain.SecurityGroup}s. Implementation
+ * is optional by providers.
+ *
+ * It considers only the custom rules added by the user and ignores the default rules created by Azure
+ */
+public class AzureComputeSecurityGroupExtension implements SecurityGroupExtension {
+
+ protected final AzureComputeApi api;
+ private final Predicate<String> operationSucceededPredicate;
+ private final AzureComputeConstants azureComputeConstants;
+
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ AzureComputeSecurityGroupExtension(final AzureComputeApi api, Predicate<String> operationSucceededPredicate, AzureComputeConstants azureComputeConstants) {
+ this.api = api;
+ this.operationSucceededPredicate = operationSucceededPredicate;
+ this.azureComputeConstants = azureComputeConstants;
+ }
+
+ @Override
+ public Set<SecurityGroup> listSecurityGroups() {
+ return FluentIterable.from(api.getNetworkSecurityGroupApi().list())
+ .transform(new NetworkSecurityGroupSecurityGroupFunction())
+ .toSet();
+ }
+
+ @Override
+ public Set<SecurityGroup> listSecurityGroupsInLocation(final Location location) {
+ return FluentIterable.from(api.getNetworkSecurityGroupApi().list())
+ .transform(new NetworkSecurityGroupSecurityGroupFunction())
+ .toSet();
+ }
+
+ /**
+ * @param name it represents both cloudservice and deployment name
+ * @return Set<SecurityGroup>
+ */
+ @Override
+ public Set<SecurityGroup> listSecurityGroupsForNode(String name) {
+ checkNotNull(name, "name");
+
+ Deployment deployment = api.getDeploymentApiForService(name).get(name);
+ final String virtualNetworkName = deployment.virtualNetworkName();
+
+ List<String> subnetNames = FluentIterable.from(deployment.roles())
+ .transformAndConcat(new Function<Role, Iterable<Role.ConfigurationSet>>() {
+ @Override
+ public Iterable<Role.ConfigurationSet> apply(Role input) {
+ return input.configurationSets();
+ }
+ })
+ .transformAndConcat(new Function<Role.ConfigurationSet, Iterable<Role.ConfigurationSet.SubnetName>>() {
+ @Override
+ public Iterable<Role.ConfigurationSet.SubnetName> apply(Role.ConfigurationSet input) {
+ return input.subnetNames();
+ }
+ })
+ .transform(new Function<Role.ConfigurationSet.SubnetName, String>() {
+ @Override
+ public String apply(Role.ConfigurationSet.SubnetName input) {
+ return input.name();
+ }
+ })
+ .toList();
+
+ return FluentIterable.from(subnetNames)
+ .transform(new Function<String, NetworkSecurityGroup>() {
+ @Override
+ public NetworkSecurityGroup apply(String input) {
+ return api.getNetworkSecurityGroupApi().getNetworkSecurityGroupAppliedToSubnet(virtualNetworkName, input);
+ }
+ })
+ .transform(new NetworkSecurityGroupSecurityGroupFunction())
+ .toSet();
+ }
+
+ @Override
+ public SecurityGroup getSecurityGroupById(String id) {
+ return transformNetworkSecurityGroupToSecurityGroup(id);
+ }
+
+ @Override
+ public SecurityGroup createSecurityGroup(final String name, Location location) {
+ checkNotNull(name, "name");
+ checkNotNull(location, "location");
+
+ final NetworkSecurityGroup networkSecurityGroup = NetworkSecurityGroup.create(name, name, location.getId(), null);
+ String createNSGRequestId = api.getNetworkSecurityGroupApi().create(networkSecurityGroup);
+ if (operationSucceededPredicate.apply(createNSGRequestId)) {
+ final String message = generateIllegalStateExceptionMessage(createNSGRequestId, azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ throw new IllegalStateException(message);
+ }
+ return transformNetworkSecurityGroupToSecurityGroup(name);
+ }
+
+ private SecurityGroup transformNetworkSecurityGroupToSecurityGroup(String name) {
+ final NetworkSecurityGroup fullDetails = api.getNetworkSecurityGroupApi().getFullDetails(name);
+ if (fullDetails == null) return null;
+ return new NetworkSecurityGroupSecurityGroupFunction().apply(fullDetails);
+ }
+
+ @Override
+ public boolean removeSecurityGroup(String id) {
+
+ final NetworkConfiguration networkConfiguration = api.getVirtualNetworkApi().getNetworkConfiguration();
+ if (networkConfiguration != null) {
+ for (VirtualNetworkSite virtualNetworkSite : networkConfiguration.virtualNetworkConfiguration().virtualNetworkSites()) {
+ for (NetworkConfiguration.Subnet subnet : virtualNetworkSite.subnets()) {
+ final String virtualNetworkName = virtualNetworkSite.name();
+ final String subnetName = subnet.name();
+ if (virtualNetworkName != null && subnetName != null) {
+ 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);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ String deleteRequestId = api.getNetworkSecurityGroupApi().delete(id);
+ return operationSucceededPredicate.apply(deleteRequestId);
+ }
+
+ @Override
+ public SecurityGroup addIpPermission(IpPermission ipPermission, SecurityGroup group) {
+ checkNotNull(group, "group");
+ checkNotNull(ipPermission, "ipPermission");
+ String id = checkNotNull(group.getId(), "group.getId()");
+
+ NetworkSecurityGroup networkSecurityGroup = api.getNetworkSecurityGroupApi().getFullDetails(group.getName());
+ List<Rule> filteredRules = NetworkSecurityGroups.getCustomRules(networkSecurityGroup);
+ int priority = NetworkSecurityGroups.getFirstAvailablePriority(filteredRules);
+
+ String ruleName = NetworkSecurityGroups.createRuleName(ipPermission.getFromPort(), ipPermission.getToPort());
+
+ // add rule to NSG
+ addRuleToNetworkSecurityGroup(id, ruleName, priority, ipPermission);
+
+ // add endpoint to VM
+ Set<Deployment> deployments = FluentIterable.from(api.getCloudServiceApi().list())
+ .transform(new Function<CloudService, Deployment>() {
+ @Override
+ public Deployment apply(CloudService cloudService) {
+ return api.getDeploymentApiForService(cloudService.name()).get(cloudService.name());
+ }
+ })
+ .filter(Predicates.notNull())
+ .toSet();
+ // TODO filter deployments
+ for (Deployment deployment : deployments) {
+ Deployment.VirtualIP virtualIP = Iterables.tryFind(deployment.virtualIPs(), Predicates.notNull()).orNull();
+ if (virtualIP == null) throw new IllegalStateException("Deployment doesn't contain virtual IPs");
+
+ for (Role role : deployment.roles()) {
+ for (Role.ConfigurationSet configurationSet : role.configurationSets()) {
+ if (ipPermission.getFromPort() < ipPermission.getToPort()) {
+ for (int i = ipPermission.getFromPort(); i <= ipPermission.getToPort(); i++) {
+ String name = String.format(AzureComputeProperties.TCP_RULE_FORMAT, i, i);
+ configurationSet.inputEndpoints().add(createInputEndpoint(name, ipPermission.getIpProtocol().name(),
+ virtualIP.address(), i));
+ }
+ } else {
+ configurationSet.inputEndpoints().add(createInputEndpoint(ruleName, ipPermission.getIpProtocol().name(),
+ virtualIP.address(), ipPermission.getToPort()));
+ }
+ String updateRoleRequestId = api.getVirtualMachineApiForDeploymentInService(deployment.name(), deployment.name()).updateRole(role.roleName(), role);
+ if (operationSucceededPredicate.apply(updateRoleRequestId)) {
+ final String message = generateIllegalStateExceptionMessage(updateRoleRequestId, azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ throw new IllegalStateException(message);
+ }
+ }
+ }
+
+ }
+ return transformNetworkSecurityGroupToSecurityGroup(id);
+ }
+
+ @Override
+ public SecurityGroup addIpPermission(IpProtocol protocol, int startPort, int endPort,
+ Multimap<String, String> tenantIdGroupNamePairs,
+ Iterable<String> ipRanges,
+ Iterable<String> groupIds, SecurityGroup group) {
+ IpPermission.Builder permBuilder = IpPermission.builder();
+ permBuilder.ipProtocol(protocol);
+ permBuilder.fromPort(startPort);
+ permBuilder.toPort(endPort);
+ permBuilder.tenantIdGroupNamePairs(tenantIdGroupNamePairs);
+ permBuilder.cidrBlocks(ipRanges);
+ permBuilder.groupIds(groupIds);
+
+ return addIpPermission(permBuilder.build(), group);
+ }
+
+ @Override
+ public SecurityGroup removeIpPermission(IpPermission ipPermission, SecurityGroup group) {
+ checkNotNull(group, "group");
+ checkNotNull(ipPermission, "ipPermission");
+ String id = checkNotNull(group.getId(), "group.getId()");
+
+ String ruleName = NetworkSecurityGroups.createRuleName(ipPermission.getFromPort(), ipPermission.getToPort());
+ // remove rule to NSG
+ removeRuleFromNetworkSecurityGroup(id, ruleName);
+
+ // TODO remove endpoint from VM
+ Set<Deployment> deployments = FluentIterable.from(api.getCloudServiceApi().list())
+ .transform(new Function<CloudService, Deployment>() {
+ @Override
+ public Deployment apply(CloudService cloudService) {
+ return api.getDeploymentApiForService(cloudService.name()).get(cloudService.name());
+ }
+ })
+ .filter(Predicates.notNull())
+ .toSet();
+ // TODO filter deployments
+ for (Deployment deployment : deployments) {
+ Deployment.VirtualIP virtualIP = Iterables.tryFind(deployment.virtualIPs(), Predicates.notNull()).orNull();
+ if (virtualIP == null) throw new IllegalStateException("");
+
+ for (Role role : deployment.roles()) {
+ for (Role.ConfigurationSet configurationSet : role.configurationSets()) {
+ for (int i = ipPermission.getFromPort(); i <= ipPermission.getToPort(); i++) {
+ String name = String.format(AzureComputeProperties.TCP_RULE_FORMAT, i, i);
+ configurationSet.inputEndpoints().remove(createInputEndpoint(name, ipPermission.getIpProtocol()
+ .name().toLowerCase(), virtualIP.address(), i));
+ }
+ String updateRoleRequestId = api.getVirtualMachineApiForDeploymentInService(deployment.name(), deployment.name()).updateRole(role.roleName(), role);
+ if (operationSucceededPredicate.apply(updateRoleRequestId)) {
+ final String message = generateIllegalStateExceptionMessage(updateRoleRequestId, azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ throw new IllegalStateException(message);
+ }
+ }
+ }
+ }
+ return transformNetworkSecurityGroupToSecurityGroup(id);
+ }
+
+ @Override
+ public SecurityGroup removeIpPermission(IpProtocol protocol, int startPort, int endPort,
+ Multimap<String, String> tenantIdGroupNamePairs,
+ Iterable<String> ipRanges,
+ Iterable<String> groupIds, SecurityGroup group) {
+ IpPermission.Builder permBuilder = IpPermission.builder();
+ permBuilder.ipProtocol(protocol);
+ permBuilder.fromPort(startPort);
+ permBuilder.toPort(endPort);
+ permBuilder.tenantIdGroupNamePairs(tenantIdGroupNamePairs);
+ permBuilder.cidrBlocks(ipRanges);
+ permBuilder.groupIds(groupIds);
+
+ return removeIpPermission(permBuilder.build(), group);
+ }
+
+ @Override
+ public boolean supportsTenantIdGroupNamePairs() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsTenantIdGroupIdPairs() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsGroupIds() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsPortRangesForGroups() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsExclusionCidrBlocks() {
+ return false;
+ }
+
+ public static class RuleToIpPermission implements Function<Rule, IpPermission> {
+
+ @Override
+ public IpPermission apply(Rule rule) {
+ IpPermission.Builder builder = IpPermission.builder();
+ if (rule.name().matches("tcp_\\d{1,5}-\\d{1,5}")) {
+ builder.fromPort(extractPort(rule.name(), 0))
+ .toPort(extractPort(rule.name(), 1));
+ }
+ builder.ipProtocol(rule.protocol().equals("*") ? IpProtocol.ALL : IpProtocol.valueOf(rule.protocol()));
+ if (rule.destinationAddressPrefix().equals("*")) {
+ builder.cidrBlock("0.0.0.0/0");
+ } else {
+ builder.cidrBlock(rule.destinationAddressPrefix());
+ }
+ return builder.build();
+ }
+
+ private int extractPort(String ruleName, int position) {
+ return Integer.parseInt(Iterables.get(Splitter.on("-").omitEmptyStrings().split(ruleName.substring(4, ruleName.length())),
+ position));
+ }
+ }
+
+ private static class NetworkSecurityGroupSecurityGroupFunction implements Function<NetworkSecurityGroup, SecurityGroup> {
+ @Override
+ public SecurityGroup apply(NetworkSecurityGroup networkSecurityGroup) {
+ SecurityGroupBuilder securityGroupBuilder = new SecurityGroupBuilder()
+ .id(networkSecurityGroup.name())
+ .providerId(networkSecurityGroup.label())
+ .name(networkSecurityGroup.name());
+ if (networkSecurityGroup.rules() != null) {
+
+ List<Rule> filteredRules = NetworkSecurityGroups.getCustomRules(networkSecurityGroup);
+
+ Iterable<IpPermission> permissions = Iterables.transform(filteredRules, new RuleToIpPermission());
+ securityGroupBuilder.ipPermissions(permissions);
+ }
+ return securityGroupBuilder.build();
+ }
+ }
+
+ private void addRuleToNetworkSecurityGroup(String networkSecurityGroupId, String ruleName, int
+ priority, IpPermission ipPermission) {
+
+ String protocol = ipPermission.getIpProtocol().name();
+ String destinationPortRange;
+ if (ipPermission.getFromPort() != ipPermission.getToPort()) {
+ destinationPortRange = String.format("%s-%s", ipPermission.getFromPort(), ipPermission.getToPort());
+ } else {
+ destinationPortRange = String.valueOf(ipPermission.getToPort());
+ }
+ final String destinationAddressPrefix =
+ ipPermission.getCidrBlocks().isEmpty() || Iterables.get(ipPermission.getCidrBlocks(), 0).equals("0.0.0.0/0") ?
+ "*" : Iterables.get(ipPermission.getCidrBlocks(), 0);
+ String setRuleToNSGRequestId = api.getNetworkSecurityGroupApi().setRule(networkSecurityGroupId, ruleName,
+ Rule.create(ruleName, // name
+ "Inbound", // type
+ String.valueOf(priority), // priority
+ "Allow", // action
+ "INTERNET", // sourceAddressPrefix
+ "*", // sourcePortRange
+ destinationAddressPrefix, // destinationAddressPrefix
+ destinationPortRange, // destinationPortRange
+ protocol, // protocol
+ "Active", // state
+ true // isDefault
+ ));
+ if (operationSucceededPredicate.apply(setRuleToNSGRequestId)) {
+ final String message = generateIllegalStateExceptionMessage(setRuleToNSGRequestId, azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ throw new IllegalStateException(message);
+ }
+ }
+
+ private void removeRuleFromNetworkSecurityGroup(String id, String ruleName) {
+ String setRuleToNSGRequestId = api.getNetworkSecurityGroupApi().deleteRule(id, ruleName);
+ if (operationSucceededPredicate.apply(setRuleToNSGRequestId)) {
+ final String message = generateIllegalStateExceptionMessage(setRuleToNSGRequestId, azureComputeConstants.operationTimeout());
+ logger.warn(message);
+ throw new IllegalStateException(message);
+ }
+ }
+
+ private Role.ConfigurationSet.InputEndpoint createInputEndpoint(String ruleName, String protocol, String address, int port) {
+ return Role.ConfigurationSet.InputEndpoint.create(
+ ruleName,
+ protocol,
+ port,
+ port,
+ address,
+ false, // enabledDirectServerReturn
+ null, // loadBalancerName
+ null, // loadBalancerProbe
+ null //idleTimeoutInMinutes
+ );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
index 127ea02..0d099e8 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
@@ -16,16 +16,108 @@
*/
package org.jclouds.azurecompute.compute.functions;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+
import org.jclouds.azurecompute.domain.Deployment;
+import org.jclouds.azurecompute.domain.Deployment.RoleInstance;
+import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.domain.Credentials;
+import org.jclouds.domain.Location;
import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
public class DeploymentToNodeMetadata implements Function<Deployment, NodeMetadata> {
+ private final Supplier<Set<? extends Location>> locations;
+ private final GroupNamingConvention nodeNamingConvention;
+ private final OSImageToImage osImageToImage;
+ private final RoleSizeToHardware roleSizeToHardware;
+ private final Map<String, Credentials> credentialStore;
+
+ public static final Map<Deployment.Status, NodeMetadata.Status> serverStateToNodeStatus = ImmutableMap
+ .<Deployment.Status, NodeMetadata.Status> builder()
+ .put(Deployment.Status.DELETING, NodeMetadata.Status.PENDING)
+ .put(Deployment.Status.SUSPENDED_TRANSITIONING, NodeMetadata.Status.PENDING)
+ .put(Deployment.Status.RUNNING_TRANSITIONING, NodeMetadata.Status.PENDING)
+ .put(Deployment.Status.DEPLOYING, NodeMetadata.Status.PENDING)
+ .put(Deployment.Status.STARTING, NodeMetadata.Status.PENDING)
+ .put(Deployment.Status.SUSPENDED, NodeMetadata.Status.SUSPENDED)
+ .put(Deployment.Status.RUNNING, NodeMetadata.Status.RUNNING)
+ .put(Deployment.Status.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).build();
+
+ @Inject
+ DeploymentToNodeMetadata(@Memoized Supplier<Set<? extends Location>> locations,
+ GroupNamingConvention.Factory namingConvention, OSImageToImage osImageToImage,
+ RoleSizeToHardware roleSizeToHardware, Map<String, Credentials> credentialStore) {
+ this.nodeNamingConvention = namingConvention.createWithoutPrefix();
+ this.locations = locations;
+ this.osImageToImage = osImageToImage;
+ this.roleSizeToHardware = roleSizeToHardware;
+ this.credentialStore = credentialStore;
+ }
+
@Override
- public NodeMetadata apply(Deployment input) {
- return null;
+ public NodeMetadata apply(Deployment from) {
+ NodeMetadataBuilder builder = new NodeMetadataBuilder();
+ builder.id(from.name());
+ builder.providerId(from.name());
+ builder.name(from.name());
+ builder.hostname(getHostname(from));
+ /* TODO
+ if (from.getDatacenter() != null) {
+ builder.location(from(locations.get()).firstMatch(
+ LocationPredicates.idEquals(from.getDatacenter().getId() + "")).orNull());
+ }
+ builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getHostname()));
+ builder.hardware(roleSizeToHardware.apply(from.instanceSize()));
+ Image image = osImageToImage.apply(from);
+ if (image != null) {
+ builder.imageId(image.getId());
+ builder.operatingSystem(image.getOperatingSystem());
+ }
+ */
+ if (from.status() != null) {
+ builder.status(serverStateToNodeStatus.get(from.status()));
+ }
+ Set<String> publicIpAddresses = Sets.newLinkedHashSet();
+ if (from.virtualIPs() != null) {
+ for (Deployment.VirtualIP virtualIP : from.virtualIPs()) {
+ publicIpAddresses.add(virtualIP.address());
+ }
+ builder.publicAddresses(publicIpAddresses);
+ }
+ Set<String> privateIpAddresses = Sets.newLinkedHashSet();
+ if (from.roleInstanceList() != null) {
+ for (RoleInstance roleInstance : from.roleInstanceList()) {
+ privateIpAddresses.add(roleInstance.ipAddress());
+ }
+ builder.privateAddresses(privateIpAddresses);
+ }
+ return builder.build();
}
+ private String getHostname(Deployment from) {
+ final Optional<RoleInstance> roleInstanceOptional = tryFindFirstRoleInstanceInDeployment(from);
+ if (!roleInstanceOptional.isPresent()) {
+ return from.name();
+ } else {
+ return roleInstanceOptional.get().hostname();
+ }
+ }
+
+ private Optional<RoleInstance> tryFindFirstRoleInstanceInDeployment(Deployment deployment) {
+ if (deployment.roleInstanceList() == null || deployment.roleInstanceList().isEmpty()) return Optional.absent();
+ return Optional.of(deployment.roleInstanceList().get(0));
+ }
+
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e97ddaee/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/LocationToLocation.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/LocationToLocation.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/LocationToLocation.java
new file mode 100644
index 0000000..228d875
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/LocationToLocation.java
@@ -0,0 +1,56 @@
+/*
+ * 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.compute.functions;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.azurecompute.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.location.suppliers.all.JustProvider;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Converts an Location into a Location.
+ */
+@Singleton
+public class LocationToLocation implements Function<Location, org.jclouds.domain.Location> {
+ private final JustProvider justProvider;
+
+ // allow us to lazy discover the provider of a resource
+ @Inject
+ LocationToLocation(JustProvider justProvider) {
+ this.justProvider = justProvider;
+ }
+
+ @Override
+ public org.jclouds.domain.Location apply(Location location) {
+ LocationBuilder builder = new LocationBuilder();
+ builder.id(location.name());
+ builder.description(location.displayName());
+ builder.scope(LocationScope.REGION);
+ builder.parent(getOnlyElement(justProvider.get()));
+ builder.iso3166Codes(ImmutableSet.<String> of("name", location.name()));
+ return builder.build();
+ }
+
+}