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/30 16:48:01 UTC
jclouds-labs git commit: JCLOUDS-852: Added VMImageOpertaions to
Azure Compute
Repository: jclouds-labs
Updated Branches:
refs/heads/1.9.x e7fb50988 -> 6b4de9e73
JCLOUDS-852: Added VMImageOpertaions to Azure Compute
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/6b4de9e7
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/6b4de9e7
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/6b4de9e7
Branch: refs/heads/1.9.x
Commit: 6b4de9e73209970cb8f678fca53a26018d9dc0b5
Parents: e7fb509
Author: hsbhathiya <hs...@gmail.com>
Authored: Sun Mar 1 17:14:49 2015 +0530
Committer: Ignasi Barrera <na...@apache.org>
Committed: Thu Apr 30 16:45:38 2015 +0200
----------------------------------------------------------------------
.../jclouds/azurecompute/AzureComputeApi.java | 6 +
.../binders/CaptureVMImageParamsToXML.java | 68 +++++
.../binders/VMImageParamsToXML.java | 97 ++++++++
.../domain/CaptureVMImageParams.java | 117 +++++++++
.../jclouds/azurecompute/domain/VMImage.java | 166 +++++++++++++
.../azurecompute/domain/VMImageParams.java | 246 +++++++++++++++++++
.../azurecompute/features/VMImageApi.java | 95 +++++++
.../features/VirtualMachineApi.java | 13 +
.../xml/DataVirtualHardDiskHandler.java | 2 +-
.../azurecompute/xml/ListVMImagesHandler.java | 70 ++++++
.../azurecompute/xml/OSConfigHandler.java | 106 ++++++++
.../azurecompute/xml/VMImageHandler.java | 207 ++++++++++++++++
.../features/VMImageApiLiveTest.java | 215 ++++++++++++++++
.../features/VMImageApiMockTest.java | 198 +++++++++++++++
.../features/VirtualMachineApiLiveTest.java | 3 +
.../features/VirtualMachineApiMockTest.java | 3 +
.../xml/ListVMImagesHandlerTest.java | 106 ++++++++
.../src/test/resources/vmimageparams.xml | 1 +
.../src/test/resources/vmimageparams_mock.xml | 1 +
azurecompute/src/test/resources/vmimages.xml | 56 +++++
20 files changed, 1775 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/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 93187c4..d7e78f2 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeApi.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeApi.java
@@ -35,6 +35,7 @@ import org.jclouds.azurecompute.features.SubscriptionApi;
import org.jclouds.azurecompute.features.TrafficManagerApi;
import org.jclouds.azurecompute.features.VirtualMachineApi;
import org.jclouds.azurecompute.features.VirtualNetworkApi;
+import org.jclouds.azurecompute.features.VMImageApi;
import org.jclouds.rest.annotations.Delegate;
/**
@@ -167,4 +168,9 @@ public interface AzureComputeApi extends Closeable {
*/
@Delegate
ReservedIPAddressApi getReservedIPAddressApi();
+ /*
+ * The Service Management API includes operations for managing the VM Images in your subscription.
+ */
+ @Delegate
+ VMImageApi getVMImageApi();
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/main/java/org/jclouds/azurecompute/binders/CaptureVMImageParamsToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/CaptureVMImageParamsToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/CaptureVMImageParamsToXML.java
new file mode 100644
index 0000000..b8ac478
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/CaptureVMImageParamsToXML.java
@@ -0,0 +1,68 @@
+/*
+ * 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 com.jamesmurty.utils.XMLBuilder;
+import org.jclouds.azurecompute.domain.CaptureVMImageParams;
+import org.jclouds.azurecompute.domain.RoleSize;
+
+import static org.jclouds.azurecompute.domain.VMImage.OSDiskConfiguration.OSState.GENERALIZED;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import static com.google.common.base.Throwables.propagate;
+
+public final class CaptureVMImageParamsToXML implements Binder {
+
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ CaptureVMImageParams params = CaptureVMImageParams.class.cast(input);
+
+ try {
+ XMLBuilder builder = XMLBuilder.create("CaptureRoleAsVMImageOperation", "http://schemas.microsoft.com/windowsazure")
+ .namespace("i", "http://www.w3.org/2001/XMLSchema-instance")
+ .e("OperationType").t("CaptureRoleAsVMImageOperation").up()
+ .e("OSState").t(params.osState() == GENERALIZED ? "Generalized" : "Specialized").up()
+ .e("VMImageName").t(params.name()).up()
+ .e("VMImageLabel").t(params.label()).up();
+ add(builder, "Description", params.description());
+ add(builder, "Language", params.language());
+ add(builder, "ImageFamily", params.imageFamily());
+
+ RoleSize.Type vmSize = params.recommendedVMSize();
+ if (vmSize != null) {
+ String vmSizeText = params.recommendedVMSize().getText();
+ builder.e("RecommendedVMSize").t(vmSizeText).up();
+ }
+
+ builder.up();
+
+ return (R) request.toBuilder().payload(builder.asString()).build();
+ } catch (Exception e) {
+ throw propagate(e);
+ }
+ }
+
+ private XMLBuilder add(XMLBuilder xmlBuilder, String entity, String text) {
+ if (text != null) {
+ return xmlBuilder.e(entity).t(text).up();
+ } else {
+ return xmlBuilder.e(entity).up();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/main/java/org/jclouds/azurecompute/binders/VMImageParamsToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/VMImageParamsToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/VMImageParamsToXML.java
new file mode 100644
index 0000000..540faa8
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/VMImageParamsToXML.java
@@ -0,0 +1,97 @@
+/*
+ * 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 com.google.common.base.CaseFormat;
+import com.jamesmurty.utils.XMLBuilder;
+import org.jclouds.azurecompute.domain.RoleSize;
+import org.jclouds.azurecompute.domain.VMImageParams;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import java.net.URI;
+
+import static com.google.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.Throwables.propagate;
+
+public final class VMImageParamsToXML implements Binder {
+
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ VMImageParams params = VMImageParams.class.cast(input);
+
+ try {
+ XMLBuilder builder = XMLBuilder.create("VMImage", "http://schemas.microsoft.com/windowsazure");
+ add(builder, "Name", params.name());
+ add(builder, "Label", params.label());
+ add(builder, "Description", params.description());
+ //OSConfig
+ VMImageParams.OSDiskConfigurationParams osDiskConfig = params.osDiskConfiguration();
+ if (osDiskConfig != null) {
+ String cache = CaseFormat.UPPER_UNDERSCORE.to(UPPER_CAMEL, osDiskConfig.hostCaching().toString());
+ XMLBuilder osConfigBuilder = builder.e("OSDiskConfiguration");
+ osConfigBuilder
+ .e("HostCaching").t(cache).up()
+ .e("OSState").t(osDiskConfig.osState().toString()).up()
+ .e("OS").t(osDiskConfig.os().toString()).up()
+ .e("MediaLink").t(osDiskConfig.mediaLink().toASCIIString()).up()
+ .up(); //OSDiskConfiguration
+ }
+ builder.up();
+ builder.e("DataDiskConfigurations").up();
+ add(builder, "Language", params.language());
+ add(builder, "ImageFamily", params.imageFamily());
+
+ RoleSize.Type vmSize = params.recommendedVMSize();
+ if (vmSize != null) {
+ String vmSizeText = params.recommendedVMSize().getText();
+ builder.e("RecommendedVMSize").t(vmSizeText).up();
+ }
+
+ add(builder, "Eula", params.eula());
+ add(builder, "IconUri", params.iconUri());
+ add(builder, "SmallIconUri", params.smallIconUri());
+ add(builder, "PrivacyUri", params.privacyUri());
+
+ if (params.showGui() != null) {
+ String showGuiText = params.showGui().toString();
+ builder.e("ShowGui").t(showGuiText).up();
+ }
+ builder.up();
+
+ return (R) request.toBuilder().payload(builder.asString()).build();
+ } catch (Exception e) {
+ throw propagate(e);
+ }
+ }
+
+ private XMLBuilder add(XMLBuilder xmlBuilder, String entity, String text) {
+ if (text != null) {
+ return xmlBuilder.e(entity).t(text).up();
+ } else {
+ return xmlBuilder.e(entity).up();
+ }
+ }
+
+ private XMLBuilder add(XMLBuilder xmlBuilder, String entity, URI text) {
+ if (text != null) {
+ return xmlBuilder.e(entity).t(text.toASCIIString()).up();
+ } else {
+ return xmlBuilder.e(entity).up();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/main/java/org/jclouds/azurecompute/domain/CaptureVMImageParams.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/CaptureVMImageParams.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/CaptureVMImageParams.java
new file mode 100644
index 0000000..a68625e
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/CaptureVMImageParams.java
@@ -0,0 +1,117 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
+
+/**
+ * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn499768.aspx" >api</a>
+ */
+@AutoValue
+public abstract class CaptureVMImageParams {
+
+ public abstract VMImage.OSDiskConfiguration.OSState osState();
+
+ public abstract String name();
+
+ public abstract String label();
+
+ @Nullable public abstract String description();
+
+ @Nullable public abstract String language();
+
+ @Nullable public abstract String imageFamily();
+
+ @Nullable public abstract RoleSize.Type recommendedVMSize();
+
+ public Builder toBuilder() {
+ return builder().fromVMImageParams(this);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+ private VMImage.OSDiskConfiguration.OSState osState;
+ private String name;
+ private String label;
+ private String description;
+ private String language;
+ private String imageFamily;
+ private RoleSize.Type recommendedVMSize;
+
+ public Builder osState(VMImage.OSDiskConfiguration.OSState osState) {
+ this.osState = osState;
+ return this;
+ }
+
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder label(String label) {
+ this.label = label;
+ return this;
+ }
+
+ public Builder description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public Builder language(String language) {
+ this.language = language;
+ return this;
+ }
+
+ public Builder imageFamily(String imageFamily) {
+ this.imageFamily = imageFamily;
+ return this;
+ }
+
+ public Builder recommendedVMSize(RoleSize.Type recommendedRoleSize) {
+ this.recommendedVMSize = recommendedRoleSize;
+ return this;
+ }
+
+ public Builder fromVMImageParams(CaptureVMImageParams in) {
+ return name(in.name())
+ .label(in.label())
+ .osState(in.osState())
+ .description(in.description())
+ .language(in.language())
+ .imageFamily(in.imageFamily())
+ .recommendedVMSize(in.recommendedVMSize());
+
+ }
+
+ public CaptureVMImageParams build() {
+ return CaptureVMImageParams.create(osState, name, label, description, language,
+ imageFamily, recommendedVMSize);
+ }
+
+ }
+
+ public static CaptureVMImageParams create(VMImage.OSDiskConfiguration.OSState osState, String name, String label,
+ String description, String language, String imageFamily, RoleSize.Type recommendedVMSize) {
+ return new AutoValue_CaptureVMImageParams(osState, name, label, description, language, imageFamily,
+ recommendedVMSize);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/main/java/org/jclouds/azurecompute/domain/VMImage.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/VMImage.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/VMImage.java
new file mode 100644
index 0000000..f7f5edf
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/VMImage.java
@@ -0,0 +1,166 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.List;
+
+import static com.google.common.collect.ImmutableList.copyOf;
+/**
+ * OS image from the image repository
+ *
+ * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn499770.aspx" >api</a>
+ */
+@AutoValue
+public abstract class VMImage {
+
+ @AutoValue
+ public abstract static class OSDiskConfiguration {
+
+ public enum Caching {
+ READ_ONLY,
+ READ_WRITE,
+ NONE
+ }
+
+ public enum OSState {
+ GENERALIZED,
+ SPECIALIZED
+ }
+
+ /**
+ * Specifies the name of the operating system disk.
+ */
+ public abstract String name();
+
+ /**
+ * Specifies the caching behavior of the operating system disk.
+ * This setting impacts the consistency and performance of the disk.
+ * The default value is ReadWrite
+ */
+ @Nullable public abstract Caching hostCaching();
+
+ /**
+ * Specifies the state of the operating system in the image.
+ * A Virtual Machine that is fully configured and running contains a Specialized operating system.
+ * A Virtual Machine on which the Sysprep command has been run with the generalize option contains
+ * a Generalized operating system.
+ */
+ @Nullable public abstract OSState osState();
+
+ /**
+ * Specifies the operating system type of the image.
+ */
+ public abstract OSImage.Type os();
+
+ /**
+ * Specifies the location of the blob in Azure storage. The blob location belongs to a storage account in the
+ * subscription specified by the <subscription-id> value in the operation call.
+ */
+ @Nullable public abstract URI mediaLink();
+
+ /**
+ * Specifies the size, in GB, of the operating system disk
+ */
+ @Nullable public abstract Integer logicalSizeInGB();
+
+ /**
+ * This property identifies the type of the storage account for the backing VHD.
+ */
+ @Nullable public abstract String ioType();
+
+ public static OSDiskConfiguration create(String name, Caching hostCaching, OSState osState, OSImage.Type os,
+ URI mediaLink, Integer logicalDiskSizeInGB, String ioType) {
+ return new AutoValue_VMImage_OSDiskConfiguration(name, hostCaching, osState, os, mediaLink,
+ logicalDiskSizeInGB, ioType);
+ }
+
+ }
+
+ public abstract String name();
+
+ /**
+ * The name can be up to 100 characters in length. The name can be used identify the storage account for your
+ * tracking purposes.
+ */
+ public abstract String label();
+
+ /**
+ * The repository classification of image. All user images have the category "User", but
+ * categories for other images could be, for example "Canonical"
+ */
+ @Nullable public abstract String category();
+
+ @Nullable public abstract String description();
+
+ @Nullable public abstract OSDiskConfiguration osDiskConfiguration();
+
+ public abstract List<DataVirtualHardDisk> dataDiskConfiguration();
+
+ @Nullable public abstract String serviceName();
+
+ @Nullable public abstract String deploymentName();
+
+ @Nullable public abstract String roleName();
+
+ /**
+ * The geo-locations of the image, if the image is not associated with an affinity group.
+ */
+ @Nullable public abstract String location();
+
+ /**
+ * The affinity group with which this image is associated, if any.
+ */
+ @Nullable public abstract String affinityGroup();
+
+ @Nullable public abstract Date createdTime();
+
+ @Nullable public abstract Date modifiedTime();
+
+ @Nullable public abstract String language();
+
+ @Nullable public abstract String imageFamily();
+
+ @Nullable public abstract RoleSize.Type recommendedVMSize();
+
+ @Nullable public abstract Boolean isPremium();
+
+ @Nullable public abstract String eula();
+
+ @Nullable public abstract URI iconUri();
+
+ @Nullable public abstract URI smallIconUri();
+
+ @Nullable public abstract URI privacyUri();
+
+ @Nullable public abstract Date publishedDate();
+
+ public static VMImage create(String name, String label, String category, String description,
+ OSDiskConfiguration osDiskConfiguration, List<DataVirtualHardDisk> dataDiskConfiguration, String serviceName,
+ String deploymentName, String roleName, String location, String affinityGroup, Date createdTime,
+ Date modifiedTime, String language, String imageFamily, RoleSize.Type recommendedVMSize, Boolean isPremium,
+ String eula, URI iconUri, URI smallIconUri,
+ URI privacyUri, Date publishedDate) {
+ return new AutoValue_VMImage(name, label, category, description, osDiskConfiguration, copyOf(dataDiskConfiguration),
+ serviceName, deploymentName, roleName, location, affinityGroup, createdTime, modifiedTime, language,
+ imageFamily, recommendedVMSize, isPremium, eula, iconUri, smallIconUri, privacyUri, publishedDate);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/main/java/org/jclouds/azurecompute/domain/VMImageParams.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/VMImageParams.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/VMImageParams.java
new file mode 100644
index 0000000..7fda79d
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/VMImageParams.java
@@ -0,0 +1,246 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.Lists;
+import org.jclouds.javax.annotation.Nullable;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * OS image from the image repository
+ *
+ * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn499770.aspx" >api</a>
+ */
+@AutoValue
+public abstract class VMImageParams {
+
+ @AutoValue
+ public abstract static class OSDiskConfigurationParams {
+
+ public enum Caching {
+ READ_ONLY,
+ READ_WRITE,
+ NONE
+ }
+
+ public enum OSState {
+ GENERALIZED,
+ SPECIALIZED
+ }
+
+ /**
+ * Specifies the name of the operating system disk.
+ */
+ @Nullable public abstract String name();
+
+ /**
+ * Specifies the caching behavior of the operating system disk.
+ * This setting impacts the consistency and performance of the disk.
+ * The default value is ReadWrite
+ */
+ @Nullable public abstract Caching hostCaching();
+
+ /**
+ * Specifies the state of the operating system in the image.
+ * A Virtual Machine that is fully configured and running contains a Specialized operating system.
+ * A Virtual Machine on which the Sysprep command has been run with the generalize option contains
+ * a Generalized operating system.
+ */
+
+ @Nullable public abstract OSState osState();
+
+ /**
+ * Specifies the operating system type of the image.
+ */
+ public abstract OSImage.Type os();
+
+ /**
+ * Specifies the location of the blob in Azure storage. The blob location belongs to a storage account in the
+ * subscription specified by the <subscription-id> value in the operation call.
+ */
+ @Nullable public abstract URI mediaLink();
+
+ /**
+ * Specifies the size, in GB, of the operating system disk
+ */
+ @Nullable public abstract Integer logicalSizeInGB();
+
+ /**
+ * This property identifies the type of the storage account for the backing VHD.
+ */
+ @Nullable public abstract String ioType();
+
+ public static OSDiskConfigurationParams OSDiskConfiguration(String name, Caching hostCaching, OSState osState,
+ OSImage.Type os, URI mediaLink, Integer logicalDiskSizeInGB, String ioType) {
+ return new AutoValue_VMImageParams_OSDiskConfigurationParams(name, hostCaching, osState, os, mediaLink,
+ logicalDiskSizeInGB, ioType);
+ }
+
+ }
+
+ @Nullable public abstract String name();
+
+ /**
+ * The name can be up to 100 characters in length. The name can be used identify the storage account for your
+ * tracking purposes.
+ */
+ @Nullable public abstract String label();
+
+ @Nullable public abstract String description();
+
+ @Nullable public abstract OSDiskConfigurationParams osDiskConfiguration();
+
+ public abstract List<DataVirtualHardDisk> dataDiskConfiguration();
+
+ @Nullable public abstract String language();
+
+ @Nullable public abstract String imageFamily();
+
+ @Nullable public abstract RoleSize.Type recommendedVMSize();
+
+ @Nullable public abstract String eula();
+
+ @Nullable public abstract URI iconUri();
+
+ @Nullable public abstract URI smallIconUri();
+
+ @Nullable public abstract URI privacyUri();
+
+ @Nullable public abstract Boolean showGui();
+
+ public Builder toBuilder() {
+ return builder().fromVMImageParams(this);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+ private String name;
+ private String label;
+ private String description;
+ private OSDiskConfigurationParams osDiskConfiguration;
+ private List<DataVirtualHardDisk> dataDiskConfiguration = Lists.newArrayList();
+ private String language;
+ private String imageFamily;
+ private RoleSize.Type recommendedVMSize;
+ private String eula;
+ private URI iconUri;
+ private URI smallIconUri;
+ private URI privacyUri;
+ private Boolean showGui;
+
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder label(String label) {
+ this.label = label;
+ return this;
+ }
+
+ public Builder description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public Builder osDiskConfiguration(OSDiskConfigurationParams osDiskConfig) {
+ this.osDiskConfiguration = osDiskConfig;
+ return this;
+ }
+
+ public Builder language(String language) {
+ this.language = language;
+ return this;
+ }
+
+ public Builder imageFamily(String imageFamily) {
+ this.imageFamily = imageFamily;
+ return this;
+ }
+
+ public Builder recommendedVMSize(RoleSize.Type recommendedRoleSize) {
+ this.recommendedVMSize = recommendedRoleSize;
+ return this;
+ }
+
+ public Builder showGui(Boolean showGui) {
+ this.showGui = showGui;
+ return this;
+ }
+
+ public Builder eula(String eula) {
+ this.eula = eula;
+ return this;
+ }
+
+ public Builder iconUri(URI iconUri) {
+ this.iconUri = iconUri;
+ return this;
+ }
+
+ public Builder smallIconUri(URI smallIconUri) {
+ this.smallIconUri = smallIconUri;
+ return this;
+ }
+
+ public Builder privacyUri(URI privacyUri) {
+ this.privacyUri = smallIconUri;
+ return this;
+ }
+
+ public Builder dataDiskConfiguration(DataVirtualHardDisk dataDiskConfiguration) {
+ this.dataDiskConfiguration.add(dataDiskConfiguration);
+ return this;
+ }
+
+ public Builder dataDiskConfigurations(Collection<DataVirtualHardDisk> dataDiskConfiguration) {
+ this.dataDiskConfiguration.addAll(dataDiskConfiguration);
+ return this;
+ }
+
+ public VMImageParams build() {
+ return VMImageParams
+ .create(name, label, description, osDiskConfiguration, dataDiskConfiguration, language,
+ imageFamily, recommendedVMSize, eula, iconUri, smallIconUri, privacyUri,
+ showGui);
+ }
+
+ public Builder fromVMImageParams(VMImageParams in) {
+ return name(in.name()).label(in.label()).description(in.description())
+ .osDiskConfiguration(in.osDiskConfiguration()).dataDiskConfigurations(in.dataDiskConfiguration())
+ .language(in.language()).imageFamily(in.imageFamily()).recommendedVMSize(in.recommendedVMSize())
+ .eula(in.eula()).iconUri(in.iconUri()).smallIconUri(in.smallIconUri()).privacyUri(in.privacyUri());
+ }
+
+ }
+
+ public static VMImageParams create(String name, String label, String description,
+ OSDiskConfigurationParams osDiskConfiguration, List<DataVirtualHardDisk> dataDiskConfiguration,
+ String language, String imageFamily, RoleSize.Type recommendedVMSize, String eula, URI iconUri,
+ URI smallIconUri, URI privacyUri, Boolean showGui) {
+ return new AutoValue_VMImageParams(name, label, description, osDiskConfiguration, dataDiskConfiguration,
+ language, imageFamily, recommendedVMSize, eula, iconUri, smallIconUri, privacyUri,
+ showGui);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/main/java/org/jclouds/azurecompute/features/VMImageApi.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/features/VMImageApi.java b/azurecompute/src/main/java/org/jclouds/azurecompute/features/VMImageApi.java
new file mode 100644
index 0000000..ecca539
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/features/VMImageApi.java
@@ -0,0 +1,95 @@
+/*
+ * 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 org.jclouds.azurecompute.binders.VMImageParamsToXML;
+import org.jclouds.azurecompute.domain.VMImage;
+import org.jclouds.azurecompute.domain.VMImageParams;
+import org.jclouds.azurecompute.functions.ParseRequestIdHeader;
+import org.jclouds.azurecompute.xml.ListVMImagesHandler;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.XMLResponseParser;
+import org.jclouds.rest.annotations.BinderParam;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import java.util.List;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_XML;
+import static org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import static org.jclouds.Fallbacks.NullOnNotFoundOr404;
+
+/**
+ * The Service Management API includes operations for managing the VM Images in your subscription.
+ *
+ * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn499771.aspx">docs</a>
+ */
+@Path("/services/vmimages")
+@Consumes(APPLICATION_XML)
+@Headers(keys = "x-ms-version", values = "{jclouds.api-version}")
+public interface VMImageApi {
+
+
+ /**
+ * The List VM Images operation retrieves a list of the VM Images from the image repository that is associated with
+ * the specified subscription.
+ */
+ @Named("ListVMImages")
+ @GET
+ @XMLResponseParser(ListVMImagesHandler.class)
+ @Fallback(EmptyListOnNotFoundOr404.class) List<VMImage> list();
+
+ /**
+ * The Create VM Image operation creates a VM Image in the image repository that is associated with the specified
+ * subscription using a specified set of virtual hard disks.
+ */
+ @Named("CreateVMImage")
+ @POST
+ @Produces(APPLICATION_XML)
+ @ResponseParser(ParseRequestIdHeader.class) String create(
+ @BinderParam(VMImageParamsToXML.class) VMImageParams params);
+
+ /**
+ * The Create VM Image operation creates a VM Image in the image repository that is associated with the specified
+ * subscription using a specified set of virtual hard disks.
+ */
+ @Named("UpdateVMImage")
+ @PUT
+ @Path("/{imageName}")
+ @Produces(APPLICATION_XML)
+ @ResponseParser(ParseRequestIdHeader.class) String update(@PathParam("imageName") String imageName,
+ @BinderParam(VMImageParamsToXML.class) VMImageParams params);
+
+ /**
+ * The Delete VM Image operation deletes the specified VM Image from the image repository that is associated with
+ * the specified subscription.
+ */
+ @Named("DeleteImage")
+ @DELETE
+ @Path("/{imageName}")
+ @Fallback(NullOnNotFoundOr404.class)
+ @ResponseParser(ParseRequestIdHeader.class) String delete(@PathParam("imageName") String imageName);
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/main/java/org/jclouds/azurecompute/features/VirtualMachineApi.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/features/VirtualMachineApi.java b/azurecompute/src/main/java/org/jclouds/azurecompute/features/VirtualMachineApi.java
index 1ee93e0..968b406 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/features/VirtualMachineApi.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/features/VirtualMachineApi.java
@@ -28,7 +28,9 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
+import org.jclouds.azurecompute.binders.CaptureVMImageParamsToXML;
import org.jclouds.azurecompute.binders.RoleToXML;
+import org.jclouds.azurecompute.domain.CaptureVMImageParams;
import org.jclouds.azurecompute.domain.Role;
import org.jclouds.azurecompute.functions.ParseRequestIdHeader;
import org.jclouds.azurecompute.xml.RoleHandler;
@@ -124,4 +126,15 @@ public interface VirtualMachineApi {
@ResponseParser(ParseRequestIdHeader.class)
String updateRole(@PathParam("roleName") String roleName, @BinderParam(RoleToXML.class) Role role);
+ /**
+ * The Capture VM Image operation creates a copy of the operating system virtual hard disk (VHD) and all of the data
+ * VHDs that are associated with the Virtual Machine, saves the VHD copies in the same storage location as the original
+ * VHDs, and registers the copies as a VM Image in the image repository that is associated with the specified subscription.
+ */
+ @Named("CaptureVMImage")
+ @POST
+ @Produces(MediaType.APPLICATION_XML)
+ @Path("/roleinstances/{name}/Operations")
+ @ResponseParser(ParseRequestIdHeader.class) String capture(@PathParam("name") String name,
+ @BinderParam(CaptureVMImageParamsToXML.class) CaptureVMImageParams params);
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DataVirtualHardDiskHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DataVirtualHardDiskHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DataVirtualHardDiskHandler.java
index 17ac28a..e6178a1 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DataVirtualHardDiskHandler.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DataVirtualHardDiskHandler.java
@@ -61,7 +61,7 @@ final class DataVirtualHardDiskHandler extends ParseSax.HandlerForGeneratedReque
if (qName.equals("HostCaching")) {
String hostCachingText = currentOrNull(currentText);
hostCaching = DataVirtualHardDisk.Caching.fromString(UPPER_CAMEL.to(UPPER_UNDERSCORE, hostCachingText));
- } else if (qName.equals("DiskName")) {
+ } else if (qName.equals("DiskName") || qName.equals("Name")) {
diskName = currentOrNull(currentText);
} else if (qName.equals("Lun")) {
String lunText = currentOrNull(currentText);
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/main/java/org/jclouds/azurecompute/xml/ListVMImagesHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/ListVMImagesHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/ListVMImagesHandler.java
new file mode 100644
index 0000000..a4e9e08
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/ListVMImagesHandler.java
@@ -0,0 +1,70 @@
+/*
+ * 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.xml;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+import com.google.inject.Inject;
+import org.jclouds.azurecompute.domain.VMImage;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import java.util.List;
+
+public final class ListVMImagesHandler extends ParseSax.HandlerForGeneratedRequestWithResult<List<VMImage>> {
+ private boolean inVMImage;
+ private final VMImageHandler VMImageHandler;
+ private final Builder<VMImage> images = ImmutableList.builder();
+
+ @Inject ListVMImagesHandler(VMImageHandler vmImageHandler) {
+ this.VMImageHandler = vmImageHandler;
+ }
+
+ @Override
+ public List<VMImage> getResult() {
+ return images.build();
+ }
+
+ @Override
+ public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
+ if (qName.equals("VMImage")) {
+ inVMImage = true;
+ }
+ if (inVMImage) {
+ VMImageHandler.startElement(url, name, qName, attributes);
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String name, String qName) {
+ if (qName.equals("VMImage")) {
+ inVMImage = false;
+ images.add(VMImageHandler.getResult());
+ }
+ if (inVMImage) {
+ VMImageHandler.endElement(uri, name, qName);
+ }
+ }
+
+ @Override
+ public void characters(char ch[], int start, int length) {
+ if (inVMImage) {
+ VMImageHandler.characters(ch, start, length);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/main/java/org/jclouds/azurecompute/xml/OSConfigHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/OSConfigHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/OSConfigHandler.java
new file mode 100644
index 0000000..8144c31
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/OSConfigHandler.java
@@ -0,0 +1,106 @@
+/*
+ * 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.xml;
+
+import org.jclouds.azurecompute.domain.OSImage;
+import org.jclouds.azurecompute.domain.VMImage;
+import org.jclouds.http.functions.ParseSax;
+
+import java.net.URI;
+
+import static com.google.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
+import static org.jclouds.util.SaxUtils.currentOrNull;
+
+/**
+ * @see <a href="https://msdn.microsoft.com/en-us/library/azure/jj157193.aspx#DataVirtualHardDisks" >api</a>
+ */
+final class OSConfigHandler extends ParseSax.HandlerForGeneratedRequestWithResult<VMImage.OSDiskConfiguration> {
+
+ private VMImage.OSDiskConfiguration.Caching hostCaching;
+ private String name;
+ private VMImage.OSDiskConfiguration.OSState osState;
+ private OSImage.Type os;
+ private Integer logicalDiskSizeInGB;
+ private URI mediaLink;
+ private String ioType;
+
+ private final StringBuilder currentText = new StringBuilder();
+
+ @Override
+ public VMImage.OSDiskConfiguration getResult() {
+ return VMImage.OSDiskConfiguration
+ .create(name, hostCaching, osState, os, mediaLink, logicalDiskSizeInGB, ioType);
+ }
+
+ @Override
+ public void endElement(String ignoredUri, String ignoredName, String qName) {
+
+ if (qName.equals("HostCaching")) {
+ String hostCachingText = currentOrNull(currentText);
+ if (hostCachingText != null) {
+ hostCaching = parseHostCache(hostCachingText);
+ }
+ } else if (qName.equals("OSState")) {
+ String osStateText = currentOrNull(currentText);
+ if (osStateText != null) {
+ osState = VMImage.OSDiskConfiguration.OSState.valueOf(osStateText.toUpperCase());
+ }
+ } else if (qName.equals("OS")) {
+ String osText = currentOrNull(currentText);
+ if (osText != null) {
+ os = OSImage.Type.valueOf(osText.toUpperCase());
+ }
+ } else if (qName.equals("Name")) {
+ name = currentOrNull(currentText);
+ } else if (qName.equals("LogicalDiskSizeInGB")) {
+ String gb = currentOrNull(currentText);
+ if (gb != null) {
+ logicalDiskSizeInGB = Integer.parseInt(gb);
+ }
+ } else if (qName.equals("MediaLink")) {
+ String link = currentOrNull(currentText);
+ if (link != null) {
+ mediaLink = URI.create(link);
+ }
+ } else if (qName.equals("IOType")) {
+ ioType = currentOrNull(currentText);
+ }
+ currentText.setLength(0);
+ }
+
+ private static VMImage.OSDiskConfiguration.Caching parseHostCache(String hostCaching) {
+ try {
+ return VMImage.OSDiskConfiguration.Caching.valueOf(UPPER_CAMEL.to(UPPER_UNDERSCORE, hostCaching));
+ } catch (IllegalArgumentException e) {
+ return VMImage.OSDiskConfiguration.Caching.NONE;
+ }
+ }
+
+ private static VMImage.OSDiskConfiguration.OSState parseOSState(String osState) {
+ try {
+ return VMImage.OSDiskConfiguration.OSState.valueOf(UPPER_CAMEL.to(UPPER_UNDERSCORE, osState));
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ @Override
+ public void characters(char ch[], int start, int length) {
+ currentText.append(ch, start, length);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/main/java/org/jclouds/azurecompute/xml/VMImageHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/VMImageHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/VMImageHandler.java
new file mode 100644
index 0000000..4c3ee57
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/VMImageHandler.java
@@ -0,0 +1,207 @@
+/*
+ * 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.xml;
+
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import org.jclouds.azurecompute.domain.DataVirtualHardDisk;
+import org.jclouds.azurecompute.domain.RoleSize;
+import org.jclouds.azurecompute.domain.VMImage;
+import org.jclouds.date.DateService;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.List;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+
+/**
+ * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn499770.aspx" >api</a>
+ */
+final class VMImageHandler extends ParseSax.HandlerForGeneratedRequestWithResult<VMImage> {
+ private String name;
+ private String label;
+ private String category;
+ private String description;
+ private VMImage.OSDiskConfiguration osDiskConfiguration;
+ private String serviceName;
+ private String deploymentName;
+ private String roleName;
+ private String location;
+ private String affinityGroup;
+ private Date createdTime;
+ private Date modifiedTime;
+ private String language;
+ private String imageFamily;
+ private RoleSize.Type recommendedVMSize;
+ private Boolean isPremium;
+ private String eula;
+ private URI iconUri;
+ private URI smallIconUri;
+ private URI privacyUri;
+ private Date publishedDate;
+
+ private final StringBuilder currentText = new StringBuilder();
+
+ private final DataVirtualHardDiskHandler dataVirtualHardDiskHandler;
+ private final OSConfigHandler osConfigHandler;
+ private List<DataVirtualHardDisk> dataDiskConfigurations = Lists.newArrayList();
+
+ private boolean inOSConfig;
+ private boolean inDataConfig;
+ private final DateService dateService = new SimpleDateFormatDateService();
+
+ @Inject VMImageHandler(DataVirtualHardDiskHandler dataVirtualHardDiskHandler, OSConfigHandler osConfigHandler) {
+ this.dataVirtualHardDiskHandler = dataVirtualHardDiskHandler;
+ this.osConfigHandler = osConfigHandler;
+ }
+
+ @Override
+ public VMImage getResult() {
+ VMImage result = VMImage
+ .create(name, label, category, description, osDiskConfiguration, dataDiskConfigurations,
+ serviceName, deploymentName, roleName, location, affinityGroup, createdTime, modifiedTime, language,
+ imageFamily, recommendedVMSize, isPremium, eula, iconUri, smallIconUri, privacyUri, publishedDate);
+ resetState(); // handler is called in a loop.
+ return result;
+ }
+
+ @Override
+ public void startElement(String ignoredUri, String ignoredLocalName, String qName,
+ Attributes ignoredAttributes) throws SAXException {
+
+ if (qName.equals("OSDiskConfiguration")) {
+ inOSConfig = true;
+ }
+ if (inOSConfig) {
+ osConfigHandler.endElement(ignoredUri, ignoredLocalName, qName);
+ }
+ if (qName.equals("DataDiskConfiguration")) {
+ inDataConfig = true;
+ }
+ if (inDataConfig) {
+ dataVirtualHardDiskHandler.startElement(ignoredUri, ignoredLocalName, qName, ignoredAttributes);
+ }
+ }
+
+ private void resetState() {
+ name = affinityGroup = label = description = category = null;
+ serviceName = deploymentName = roleName = location = affinityGroup = null;
+ createdTime = modifiedTime = null;
+ language = imageFamily = eula = null;
+ recommendedVMSize = null;
+ isPremium = Boolean.FALSE;
+ iconUri = smallIconUri = privacyUri = null;
+ publishedDate = null;
+ osDiskConfiguration = null;
+ dataDiskConfigurations = Lists.newArrayList();
+ }
+
+ @Override public void endElement(String ignoredUri, String ignoredName, String qName) {
+ if (qName.equals("Name") && !inDataConfig && !inOSConfig) {
+ name = currentOrNull(currentText);
+ } else if (qName.equals("Label")) {
+ label = currentOrNull(currentText);
+ } else if (qName.equals("Category")) {
+ category = currentOrNull(currentText);
+ } else if (qName.equals("Description")) {
+ description = currentOrNull(currentText);
+ } else if (qName.equals("OSDiskConfiguration")) {
+ osDiskConfiguration = osConfigHandler.getResult();
+ inOSConfig = false;
+ } else if (inOSConfig) {
+ osConfigHandler.endElement(ignoredUri, ignoredName, qName);
+ } else if (qName.equals("DataDiskConfiguration") && !inOSConfig) {
+ dataDiskConfigurations.add(dataVirtualHardDiskHandler.getResult());
+ inDataConfig = false;
+ } else if (inDataConfig) {
+ dataVirtualHardDiskHandler.endElement(ignoredUri, ignoredName, qName);
+ } else if (qName.equals("ServiceName")) {
+ serviceName = currentOrNull(currentText);
+ } else if (qName.equals("DeploymentName")) {
+ deploymentName = currentOrNull(currentText);
+ } else if (qName.equals("RoleName")) {
+ roleName = currentOrNull(currentText);
+ } else if (qName.equals("Location")) {
+ location = currentOrNull(currentText);
+ } else if (qName.equals("AffinityGroup")) {
+ affinityGroup = currentOrNull(currentText);
+ } else if (qName.equals("CreatedTime")) {
+ createdTime = dateService.iso8601DateOrSecondsDateParse(currentOrNull(currentText));
+ } else if (qName.equals("ModifiedTime")) {
+ modifiedTime = dateService.iso8601DateOrSecondsDateParse(currentOrNull(currentText));
+ } else if (qName.equals("Language")) {
+ language = currentOrNull(currentText);
+ } else if (qName.equals("ImageFamily")) {
+ imageFamily = currentOrNull(currentText);
+ } else if (qName.equals("Label")) {
+ label = currentOrNull(currentText);
+ } else if (qName.equals("RecommendedVMSize")) {
+ String vmSizeText = currentOrNull(currentText);
+ if (vmSizeText != null) {
+ recommendedVMSize = parseRoleSize(vmSizeText);
+ }
+ } else if (qName.equals("IconUri")) {
+ String uri = currentOrNull(currentText);
+ if (uri != null) {
+ iconUri = URI.create(uri);
+ }
+ } else if (qName.equals("SmallIconUri")) {
+ String uri = currentOrNull(currentText);
+ if (uri != null) {
+ smallIconUri = URI.create(uri);
+ }
+ } else if (qName.equals("PrivacyUri")) {
+ String uri = currentOrNull(currentText);
+ if (uri != null) {
+ privacyUri = URI.create(uri);
+ }
+ } else if (qName.equals("IsPremium")) {
+ String isPremiumText = currentOrNull(currentText);
+ if (isPremiumText != null) {
+ isPremium = Boolean.parseBoolean(isPremiumText);
+ }
+ } else if (qName.equals("Eula")) {
+ eula = currentOrNull(currentText);
+ } else if (qName.equals("PublishedDate")) {
+ publishedDate = dateService.iso8601SecondsDateParse(currentOrNull(currentText));
+ }
+ currentText.setLength(0);
+ }
+
+ @Override public void characters(char ch[], int start, int length) {
+ if (inDataConfig) {
+ dataVirtualHardDiskHandler.characters(ch, start, length);
+ } else if (inOSConfig) {
+ osConfigHandler.characters(ch, start, length);
+ } else {
+ currentText.append(ch, start, length);
+ }
+ }
+
+ private static RoleSize.Type parseRoleSize(String roleSize) {
+ try {
+ return RoleSize.Type.valueOf(roleSize.toUpperCase().replace(" ", ""));
+ } catch (IllegalArgumentException e) {
+ return RoleSize.Type.UNRECOGNIZED;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/test/java/org/jclouds/azurecompute/features/VMImageApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/features/VMImageApiLiveTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/features/VMImageApiLiveTest.java
new file mode 100644
index 0000000..2b074fd
--- /dev/null
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/features/VMImageApiLiveTest.java
@@ -0,0 +1,215 @@
+/*
+ * 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 java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.azurecompute.domain.Deployment.InstanceStatus.READY_ROLE;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+
+import com.google.common.collect.Iterables;
+import org.jclouds.azurecompute.compute.AzureComputeServiceAdapter;
+import org.jclouds.azurecompute.domain.Deployment;
+import org.jclouds.azurecompute.domain.DeploymentParams;
+import org.jclouds.azurecompute.domain.VMImage;
+import org.jclouds.azurecompute.domain.RoleSize;
+import org.jclouds.azurecompute.domain.OSImage;
+import org.jclouds.azurecompute.domain.CloudService;
+import org.jclouds.azurecompute.domain.CaptureVMImageParams;
+import org.jclouds.azurecompute.domain.VMImageParams;
+import org.jclouds.azurecompute.internal.BaseAzureComputeApiLiveTest;
+import org.jclouds.azurecompute.util.ConflictManagementPredicate;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+
+@Test(groups = "live", testName = "VMImageApiLiveTest")
+public class VMImageApiLiveTest extends BaseAzureComputeApiLiveTest {
+
+ private static final String CLOUD_SERVICE = String.format("%s%d-%s",
+ System.getProperty("user.name"), RAND, VMImageApiLiveTest.class.getSimpleName()).toLowerCase();
+
+ private static final String DEPLOYMENT = String.format("%s%d-%s",
+ System.getProperty("user.name"), RAND, VMImageApiLiveTest.class.getSimpleName()).toLowerCase();
+
+ private static final String CAPTURED_IMAGE_NAME = "captured-image";
+
+ private static final String CREATE_IMAGE_NAME = "create-image";
+
+ private String roleName;
+
+ private String diskName;
+
+ private Predicate<String> roleInstanceReady;
+
+ private CloudService cloudService;
+
+ @BeforeClass(groups = {"integration", "live"})
+ @Override
+ public void setup() {
+ super.setup();
+ cloudService = getOrCreateCloudService(CLOUD_SERVICE, LOCATION);
+
+ roleInstanceReady = retry(new Predicate<String>() {
+
+ @Override
+ public boolean apply(String input) {
+ Deployment.RoleInstance roleInstance = getFirstRoleInstanceInDeployment(input);
+ return roleInstance != null && roleInstance.instanceStatus() == READY_ROLE;
+ }
+ }, 600, 5, 5, SECONDS);
+
+ final DeploymentParams params = DeploymentParams.builder()
+ .name(DEPLOYMENT)
+ .os(OSImage.Type.LINUX)
+ .sourceImageName(BaseAzureComputeApiLiveTest.IMAGE_NAME)
+ .mediaLink(AzureComputeServiceAdapter.createMediaLink(storageService.serviceName(), DEPLOYMENT))
+ .username("test")
+ .password("supersecurePassword1!")
+ .size(RoleSize.Type.BASIC_A2)
+ .subnetName(Iterables.get(virtualNetworkSite.subnets(), 0).name())
+ .virtualNetworkName(virtualNetworkSite.name())
+ .externalEndpoint(DeploymentParams.ExternalEndpoint.inboundTcpToLocalPort(22, 22))
+ .build();
+ Deployment deployment = getOrCreateDeployment(cloudService.name(), params);
+ Deployment.RoleInstance roleInstance = getFirstRoleInstanceInDeployment(DEPLOYMENT);
+ assertTrue(roleInstanceReady.apply(DEPLOYMENT), roleInstance.toString());
+ roleName = roleInstance.roleName();
+ diskName = deployment.roleList().get(0).osVirtualHardDisk().diskName();
+ }
+
+ @Test(dependsOnMethods = "testCaptureVMImage")
+ public void testCreate() {
+ Date date = new Date();
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ VMImage image = api().list().get(5);
+ VMImageParams.OSDiskConfigurationParams osParams = VMImageParams.OSDiskConfigurationParams
+ .OSDiskConfiguration(CREATE_IMAGE_NAME + "osdisk",
+ VMImageParams.OSDiskConfigurationParams.Caching.READ_ONLY,
+ VMImageParams.OSDiskConfigurationParams.OSState.SPECIALIZED,
+ image.osDiskConfiguration().os(),
+ URI.create(
+ "https://" + storageService.serviceName()
+ + ".blob.core.windows.net/vhds/" + CAPTURED_IMAGE_NAME + "-os-" + dateFormat.format(date) + ".vhd"),
+ 30,
+ "Standard");
+ VMImageParams params = VMImageParams.builder().name(CREATE_IMAGE_NAME).label(CREATE_IMAGE_NAME)
+ .description(image.description()).recommendedVMSize(image.recommendedVMSize())
+ .osDiskConfiguration(osParams).imageFamily(image.imageFamily())
+ .build();
+
+ String requestId = api().create(params);
+ assertNotNull(requestId);
+ operationSucceeded.apply(requestId);
+ }
+
+ @Test
+ public void testCaptureVMImage() {
+ String shutdownRequest = api.getVirtualMachineApiForDeploymentInService(DEPLOYMENT, CLOUD_SERVICE).shutdown(roleName);
+ assertTrue(operationSucceeded.apply(shutdownRequest), shutdownRequest);
+
+ CaptureVMImageParams captureParams = CaptureVMImageParams.builder()
+ .osState(VMImage.OSDiskConfiguration.OSState.GENERALIZED).name(CAPTURED_IMAGE_NAME)
+ .label(CAPTURED_IMAGE_NAME).recommendedVMSize(RoleSize.Type.MEDIUM).build();
+
+ String requestId = api.getVirtualMachineApiForDeploymentInService(DEPLOYMENT, CLOUD_SERVICE)
+ .capture(roleName, captureParams);
+ assertNotNull(requestId);
+ operationSucceeded.apply(requestId);
+ }
+
+ @Test(dependsOnMethods = "testCreate")
+ public void testUpdateVMImage() {
+ VMImage image = api().list().get(5);
+ VMImageParams params = VMImageParams.builder()
+ .label("UpdatedLabel")
+ .description(image.description()).recommendedVMSize(RoleSize.Type.A7)
+ .build();
+
+ String requestId = api().update(CAPTURED_IMAGE_NAME, params);
+ assertNotNull(requestId);
+ operationSucceeded.apply(requestId);
+ }
+
+ @Test
+ public void testList() {
+ List<VMImage> vmImageList = api().list();
+ assertTrue(vmImageList.size() > 0);
+ for (VMImage VMImage : vmImageList) {
+ checkVMImage(VMImage);
+ }
+ }
+
+ @Test(dependsOnMethods = {"testList", "testUpdateVMImage"})
+ public void testDelete() {
+ String requestId = api().delete(CAPTURED_IMAGE_NAME);
+ assertNotNull(requestId);
+ assertTrue(operationSucceeded.apply(requestId), requestId);
+ }
+
+ private void checkVMImage(VMImage image) {
+ assertNotNull(image.label(), "Label cannot be null for " + image);
+ assertNotNull(image.name(), "Name cannot be null for " + image);
+ assertNotNull(image.location(), "Location cannot be null for " + image);
+
+ //OSImage
+ VMImage.OSDiskConfiguration osDiskConfiguration = image.osDiskConfiguration();
+ assertNotNull(osDiskConfiguration);
+ assertNotNull(osDiskConfiguration.name());
+ assertTrue(osDiskConfiguration.logicalSizeInGB() > 0);
+
+ if (osDiskConfiguration.mediaLink() != null) {
+ assertTrue(ImmutableSet.of("http", "https").contains(osDiskConfiguration.mediaLink().getScheme()),
+ "MediaLink should be an http(s) url" + image);
+ }
+
+ if (image.category() != null) {
+ assertNotEquals("", image.category().trim(), "Invalid Category for " + image);
+ }
+ }
+
+ @AfterClass
+ @Override
+ protected void tearDown() {
+ assertTrue(new ConflictManagementPredicate(api) {
+ @Override
+ protected String operation() {
+ return api.getDiskApi().delete(diskName);
+ }
+ }.apply(diskName));
+ super.tearDown();
+ }
+
+ private VMImageApi api() {
+ return api.getVMImageApi();
+ }
+
+ private Deployment.RoleInstance getFirstRoleInstanceInDeployment(String deployment) {
+ return Iterables.getOnlyElement(api.getDeploymentApiForService(cloudService.name()).get(deployment).
+ roleInstanceList());
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/test/java/org/jclouds/azurecompute/features/VMImageApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/features/VMImageApiMockTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/features/VMImageApiMockTest.java
new file mode 100644
index 0000000..2396bb0
--- /dev/null
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/features/VMImageApiMockTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertEquals;
+
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+import org.jclouds.azurecompute.domain.OSImage;
+import org.jclouds.azurecompute.domain.RoleSize;
+import org.jclouds.azurecompute.domain.VMImageParams;
+import org.jclouds.azurecompute.domain.CaptureVMImageParams;
+import org.jclouds.azurecompute.domain.VMImage;
+import org.jclouds.azurecompute.internal.BaseAzureComputeApiMockTest;
+import org.jclouds.azurecompute.xml.ListVMImagesHandlerTest;
+import org.testng.annotations.Test;
+
+import java.net.URI;
+
+@Test(groups = "unit", testName = "VMImageApiMockTest")
+public class VMImageApiMockTest extends BaseAzureComputeApiMockTest {
+
+ public void listWhenFound() throws Exception {
+ MockWebServer server = mockAzureManagementServer();
+ server.enqueue(xmlResponse("/vmimages.xml"));
+
+ try {
+ VMImageApi api = api(server.getUrl("/")).getVMImageApi();
+
+ assertEquals(api.list(), ListVMImagesHandlerTest.expected());
+
+ assertSent(server, "GET", "/services/vmimages");
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void listWhenNotFound() throws Exception {
+ MockWebServer server = mockAzureManagementServer();
+ server.enqueue(new MockResponse().setResponseCode(404));
+
+ try {
+ VMImageApi api = api(server.getUrl("/")).getVMImageApi();
+
+ assertTrue(api.list().isEmpty());
+
+ assertSent(server, "GET", "/services/vmimages");
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void create() throws Exception {
+ MockWebServer server = mockAzureManagementServer();
+ server.enqueue(requestIdResponse("request-1"));
+
+ try {
+ VMImageApi api = api(server.getUrl("/")).getVMImageApi();
+
+ VMImageParams.OSDiskConfigurationParams osParams = VMImageParams.OSDiskConfigurationParams
+ .OSDiskConfiguration("ClouderaGolden-os_disk",
+ VMImageParams.OSDiskConfigurationParams.Caching.READ_ONLY,
+ VMImageParams.OSDiskConfigurationParams.OSState.SPECIALIZED,
+ OSImage.Type.LINUX,
+ URI.create("http://blobs/disks/neotysss/MSFT__Win2K8R2SP1-ABCD-en-us-30GB.vhd"),
+ 30,
+ "Standard");
+ VMImageParams params = VMImageParams.builder()
+ .name("ClouderaGolden")
+ .label("CDH 5.1 Evaluation")
+ .description("Single click deployment")
+ .recommendedVMSize(RoleSize.Type.LARGE)
+ .osDiskConfiguration(osParams)
+ .imageFamily("Ubuntu")
+ .language("en")
+ .eula("http://www.gnu.org/copyleft/gpl.html")
+ .iconUri(URI.create("http://www.cloudera.com/content/cloudera/en/privacy-policy.html"))
+ .smallIconUri(URI.create("http://www.cloudera.com/content/cloudera/en/privacy-policy.html"))
+ .privacyUri(URI.create("http://www.cloudera.com/content/cloudera/en/privacy-policy.html"))
+ .showGui(Boolean.TRUE)
+ .build();
+
+ assertEquals(api.create(params), "request-1");
+
+ assertSent(server, "POST", "/services/vmimages", "/vmimageparams.xml");
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testUpdate() throws Exception {
+ MockWebServer server = mockAzureManagementServer();
+ server.enqueue(requestIdResponse("request-1"));
+
+ try {
+ VMImageApi api = api(server.getUrl("/")).getVMImageApi();
+
+ VMImageParams.OSDiskConfigurationParams osParams = VMImageParams.OSDiskConfigurationParams
+ .OSDiskConfiguration("ClouderaGolden-os_disk",
+ VMImageParams.OSDiskConfigurationParams.Caching.READ_ONLY,
+ VMImageParams.OSDiskConfigurationParams.OSState.SPECIALIZED,
+ OSImage.Type.LINUX,
+ URI.create("http://blobs/disks/neotysss/MSFT__Win2K8R2SP1-ABCD-en-us-30GB.vhd"),
+ 30,
+ "Standard");
+ VMImageParams params = VMImageParams.builder()
+ .name("ClouderaGolden")
+ .label("CDH 5.1 Evaluation")
+ .description("Single click deployment")
+ .recommendedVMSize(RoleSize.Type.LARGE)
+ .osDiskConfiguration(osParams)
+ .imageFamily("Ubuntu")
+ .language("en")
+ .eula("http://www.gnu.org/copyleft/gpl.html")
+ .iconUri(URI.create("http://www.cloudera.com/content/cloudera/en/privacy-policy.html"))
+ .smallIconUri(URI.create("http://www.cloudera.com/content/cloudera/en/privacy-policy.html"))
+ .privacyUri(URI.create("http://www.cloudera.com/content/cloudera/en/privacy-policy.html"))
+ .showGui(Boolean.TRUE)
+ .build();
+
+ assertEquals(api.update("myvmimage", params), "request-1");
+
+ assertSent(server, "PUT", "/services/vmimages/myvmimage", "/vmimageparams.xml");
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void deleteWhenFound() throws Exception {
+ MockWebServer server = mockAzureManagementServer();
+ server.enqueue(requestIdResponse("request-1"));
+
+ try {
+ VMImageApi api = api(server.getUrl("/")).getVMImageApi();
+
+ assertEquals(api.delete("myvmimage"), "request-1");
+
+ assertSent(server, "DELETE", "/services/vmimages/myvmimage");
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void deleteWhenNotFound() throws Exception {
+ MockWebServer server = mockAzureManagementServer();
+ server.enqueue(new MockResponse().setResponseCode(404));
+
+ try {
+ VMImageApi api = api(server.getUrl("/")).getVMImageApi();
+
+ assertNull(api.delete("myvmimage"));
+
+ assertSent(server, "DELETE", "/services/vmimages/myvmimage");
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ @Test
+ public void testCaptureVMImage() throws Exception {
+
+ MockWebServer server = mockAzureManagementServer();
+ server.enqueue(requestIdResponse("request-1"));
+
+ try {
+ CaptureVMImageParams captureParams = CaptureVMImageParams.builder()
+ .osState(VMImage.OSDiskConfiguration.OSState.GENERALIZED).name("capturedimage")
+ .label("CapturedImage").recommendedVMSize(RoleSize.Type.MEDIUM).build();
+
+ VirtualMachineApi api = api(server.getUrl("/")).
+ getVirtualMachineApiForDeploymentInService("mydeployment", "myservice");
+
+ assertEquals(api.capture("myvirtualmachine", captureParams), "request-1");
+ assertSent(server, "POST",
+ "/services/hostedservices/myservice/deployments/mydeployment/roleinstances/" +
+ "myvirtualmachine/Operations",
+ "/vmimageparams_mock.xml");
+ } finally {
+ server.shutdown();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/test/java/org/jclouds/azurecompute/features/VirtualMachineApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/features/VirtualMachineApiLiveTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/features/VirtualMachineApiLiveTest.java
index 1d20841..7b67b85 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/features/VirtualMachineApiLiveTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/features/VirtualMachineApiLiveTest.java
@@ -42,6 +42,9 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+/*
+ * Note: Live test for CaptureVMImage method is in VMImageApiLiveTest class
+ */
@Test(groups = "live", testName = "VirtualMachineApiLiveTest", singleThreaded = true)
public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/test/java/org/jclouds/azurecompute/features/VirtualMachineApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/features/VirtualMachineApiMockTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/features/VirtualMachineApiMockTest.java
index f6529d4..5bdd3a8 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/features/VirtualMachineApiMockTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/features/VirtualMachineApiMockTest.java
@@ -25,6 +25,9 @@ import org.testng.annotations.Test;
import com.squareup.okhttp.mockwebserver.MockWebServer;
+/*
+ * Note: Mock test for CaptureVMImage method is in VMImageApiMockTest class
+ */
@Test(groups = "unit", testName = "VirtualMachineApiMockTest")
public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListVMImagesHandlerTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListVMImagesHandlerTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListVMImagesHandlerTest.java
new file mode 100644
index 0000000..4befa28
--- /dev/null
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListVMImagesHandlerTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.xml;
+
+import static org.testng.Assert.assertEquals;
+
+import com.google.common.collect.ImmutableList;
+import org.jclouds.azurecompute.domain.DataVirtualHardDisk;
+import org.jclouds.azurecompute.domain.OSImage;
+import org.jclouds.azurecompute.domain.VMImage;
+import org.jclouds.date.DateService;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.testng.annotations.Test;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.util.List;
+
+@Test(groups = "unit", testName = "ListVMImagesHandlerTest")
+public class ListVMImagesHandlerTest extends BaseHandlerTest {
+
+ public void test() {
+ InputStream is = getClass().getResourceAsStream("/vmimages.xml");
+ List<VMImage> result = factory.create(new ListVMImagesHandler(new VMImageHandler(
+ new DataVirtualHardDiskHandler(),
+ new OSConfigHandler()
+ ))).parse(is);
+
+ assertEquals(result, expected());
+ }
+
+ public static List<VMImage> expected() {
+ DateService dateService = new SimpleDateFormatDateService();
+ return ImmutableList.of(
+ VMImage.create("1acf693f34c74e86a50be61cb631ddfe__ClouderaGolden-202406-699696",
+ "CDH 5.1 Evaluation",
+ "Public",
+ "Single click deployment of CDH 5.1 Evaluation for MR, HDFS and HIVE",
+ OSDiskConfig(),
+ dataDiskConfig(),
+ null,
+ null,
+ null,
+ "East Asia;Southeast Asia;Australia East;Australia Southeast;Brazil South;North Europe",
+ null,
+ dateService.iso8601DateOrSecondsDateParse("2014-07-05T14:55:17Z"),
+ dateService.iso8601DateOrSecondsDateParse("2014-09-06T22:58:11Z"),
+ null,
+ "CDH 5.1 Evaluation",
+ null,
+ false,
+ "http://www.gnu.org/copyleft/gpl.html",
+ null,
+ null,
+ URI.create("http://www.cloudera.com/content/cloudera/en/privacy-policy.html"),
+ dateService.iso8601DateOrSecondsDateParse("2012-07-05T14:55:17Z")
+ )
+ );
+ }
+
+ public static VMImage.OSDiskConfiguration OSDiskConfig() {
+ return VMImage.OSDiskConfiguration.create("ClouderaGolden-202406-699696-os-2014-10-06",
+ VMImage.OSDiskConfiguration.Caching.READ_WRITE,
+ VMImage.OSDiskConfiguration.OSState.SPECIALIZED,
+ OSImage.Type.LINUX,
+ null,
+ 30,
+ null);
+ }
+
+ public static List<DataVirtualHardDisk> dataDiskConfig() {
+ return ImmutableList.of(
+ DataVirtualHardDisk.create(
+ DataVirtualHardDisk.Caching.READ_ONLY,
+ "testimage1-testimage1-0-20120817095145",
+ 10,
+ 30,
+ URI.create("http://blobs/disks/neotysss/MSFT__Win2K8R2SP1-ABCD-en-us-30GB.vhd"),
+ "Standard"
+ ),
+ DataVirtualHardDisk.create(
+ DataVirtualHardDisk.Caching.READ_WRITE,
+ "testimage2-testimage2-0-20120817095145",
+ 20,
+ 30,
+ URI.create("http://blobs/disks/neotysss/MSFT__Win2K8R2SP1-ABCD-en-us-30GB.vhd"),
+ "Standard"
+ )
+ );
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/test/resources/vmimageparams.xml
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/resources/vmimageparams.xml b/azurecompute/src/test/resources/vmimageparams.xml
new file mode 100644
index 0000000..43a54bf
--- /dev/null
+++ b/azurecompute/src/test/resources/vmimageparams.xml
@@ -0,0 +1 @@
+<VMImage xmlns="http://schemas.microsoft.com/windowsazure"><Name>ClouderaGolden</Name><Label>CDH 5.1 Evaluation</Label><Description>Single click deployment</Description><OSDiskConfiguration><HostCaching>ReadOnly</HostCaching><OSState>SPECIALIZED</OSState><OS>LINUX</OS><MediaLink>http://blobs/disks/neotysss/MSFT__Win2K8R2SP1-ABCD-en-us-30GB.vhd</MediaLink></OSDiskConfiguration><DataDiskConfigurations/><Language>en</Language><ImageFamily>Ubuntu</ImageFamily><RecommendedVMSize>Large</RecommendedVMSize><Eula>http://www.gnu.org/copyleft/gpl.html</Eula><IconUri>http://www.cloudera.com/content/cloudera/en/privacy-policy.html</IconUri><SmallIconUri>http://www.cloudera.com/content/cloudera/en/privacy-policy.html</SmallIconUri><PrivacyUri>http://www.cloudera.com/content/cloudera/en/privacy-policy.html</PrivacyUri><ShowGui>true</ShowGui></VMImage>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/test/resources/vmimageparams_mock.xml
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/resources/vmimageparams_mock.xml b/azurecompute/src/test/resources/vmimageparams_mock.xml
new file mode 100644
index 0000000..bd62d9c
--- /dev/null
+++ b/azurecompute/src/test/resources/vmimageparams_mock.xml
@@ -0,0 +1 @@
+<CaptureRoleAsVMImageOperation xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><OperationType>CaptureRoleAsVMImageOperation</OperationType><OSState>Generalized</OSState><VMImageName>capturedimage</VMImageName><VMImageLabel>CapturedImage</VMImageLabel><Description/><Language/><ImageFamily/><RecommendedVMSize>Medium</RecommendedVMSize></CaptureRoleAsVMImageOperation>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/6b4de9e7/azurecompute/src/test/resources/vmimages.xml
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/resources/vmimages.xml b/azurecompute/src/test/resources/vmimages.xml
new file mode 100644
index 0000000..f92e74b
--- /dev/null
+++ b/azurecompute/src/test/resources/vmimages.xml
@@ -0,0 +1,56 @@
+<VMImages xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+ <VMImage>
+ <Name>1acf693f34c74e86a50be61cb631ddfe__ClouderaGolden-202406-699696</Name>
+ <Label>CDH 5.1 Evaluation</Label>
+ <Category>Public</Category>
+ <Description>Single click deployment of CDH 5.1 Evaluation for MR, HDFS and HIVE</Description>
+ <OSDiskConfiguration>
+ <Name>ClouderaGolden-202406-699696-os-2014-10-06</Name>
+ <HostCaching>ReadWrite</HostCaching>
+ <OSState>SPECIALIZED</OSState>
+ <OS>Linux</OS>
+ <MediaLink/>
+ <LogicalDiskSizeInGB>30</LogicalDiskSizeInGB>
+ <IOType/>
+ </OSDiskConfiguration>
+ <DataDiskConfigurations>
+ <DataDiskConfiguration>
+ <Name>testimage1-testimage1-0-20120817095145</Name>
+ <HostCaching>ReadOnly</HostCaching>
+ <Lun>10</Lun>
+ <MediaLink>http://blobs/disks/neotysss/MSFT__Win2K8R2SP1-ABCD-en-us-30GB.vhd</MediaLink>
+ <LogicalDiskSizeInGB>30</LogicalDiskSizeInGB>
+ <IOType>Standard</IOType>
+ </DataDiskConfiguration>
+ <DataDiskConfiguration>
+ <Name>testimage2-testimage2-0-20120817095145</Name>
+ <HostCaching>ReadWrite</HostCaching>
+ <Lun>20</Lun>
+ <MediaLink>http://blobs/disks/neotysss/MSFT__Win2K8R2SP1-ABCD-en-us-30GB.vhd</MediaLink>
+ <LogicalDiskSizeInGB>30</LogicalDiskSizeInGB>
+ <IOType>Standard</IOType>
+ </DataDiskConfiguration>
+ </DataDiskConfigurations>
+ <ServiceName/>
+ <DeploymentName/>
+ <RoleName/>
+ <Location>
+ East Asia;Southeast Asia;Australia East;Australia Southeast;Brazil South;North Europe
+ </Location>
+ <AffinityGroup/>
+ <CreatedTime>2014-07-05T14:55:17Z</CreatedTime>
+ <ModifiedTime>2014-09-06T22:58:11Z</ModifiedTime>
+ <Language/>
+ <ImageFamily>CDH 5.1 Evaluation</ImageFamily>
+ <RecommendedVMSize/>
+ <IsPremium>False</IsPremium>
+ <Eula>http://www.gnu.org/copyleft/gpl.html</Eula>
+ <IconUri/>
+ <SmallIconUri></SmallIconUri>
+ <PrivacyUri>http://www.cloudera.com/content/cloudera/en/privacy-policy.html</PrivacyUri>
+ <PublisherName>publisher-identifier</PublisherName>
+ <PublishedDate>2012-07-05T14:55:17Z</PublishedDate>
+ <ShowInGui>indicator-of-availability</ShowInGui>
+ <PricingDetailLink>pricing-details</PricingDetailLink>
+ </VMImage>
+</VMImages>