Repository: jclouds-labs Updated Branches: refs/heads/fix/AzureTemplateBuilderLiveTest 9456ad146 -> 84ed11fce
refactor from Deployment to VirtualMachine Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/21403be0 Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/21403be0 Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/21403be0 Branch: refs/heads/fix/AzureTemplateBuilderLiveTest Commit: 21403be0b6bd89f6a1301ca8db8ff6700623e631 Parents: 9456ad1 Author: Andrea Turli <[email protected]> Authored: Sat Oct 1 18:42:26 2016 +0200 Committer: Andrea Turli <[email protected]> Committed: Sat Oct 1 18:42:26 2016 +0200 ---------------------------------------------------------------------- .../arm/compute/AzureComputeServiceAdapter.java | 164 +++++++++++++-- .../AzureComputeServiceContextModule.java | 14 +- .../functions/DeploymentToNodeMetadata.java | 2 +- .../functions/VirtualMachineToNodeMetadata.java | 206 +++++++++++++++++++ .../azurecompute/arm/domain/VirtualMachine.java | 7 +- .../arm/domain/VirtualMachineProperties.java | 26 ++- .../arm/functions/CleanupResources.java | 52 +++-- .../arm/util/DeploymentTemplateBuilder.java | 10 +- .../compute/AzureComputeServiceLiveTest.java | 10 + .../arm/features/VirtualMachineApiLiveTest.java | 4 +- .../arm/features/VirtualMachineApiMockTest.java | 31 +-- 11 files changed, 457 insertions(+), 69 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/21403be0/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java index 6023eee..36534ae 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java @@ -16,6 +16,8 @@ */ package org.jclouds.azurecompute.arm.compute; +import java.net.URI; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Set; @@ -29,23 +31,38 @@ import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; import org.jclouds.azurecompute.arm.compute.functions.DeploymentToVMDeployment; import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; +import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.compute.predicates.IsDeploymentInRegions; -import org.jclouds.azurecompute.arm.domain.Deployment; -import org.jclouds.azurecompute.arm.domain.DeploymentBody; -import org.jclouds.azurecompute.arm.domain.DeploymentProperties; +import org.jclouds.azurecompute.arm.domain.DataDisk; +import org.jclouds.azurecompute.arm.domain.HardwareProfile; +import org.jclouds.azurecompute.arm.domain.IdReference; +import org.jclouds.azurecompute.arm.domain.ImageReference; +import org.jclouds.azurecompute.arm.domain.IpConfiguration; +import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties; import org.jclouds.azurecompute.arm.domain.Location; +import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; +import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties; +import org.jclouds.azurecompute.arm.domain.NetworkProfile; +import org.jclouds.azurecompute.arm.domain.OSDisk; +import org.jclouds.azurecompute.arm.domain.OSProfile; import org.jclouds.azurecompute.arm.domain.Offer; +import org.jclouds.azurecompute.arm.domain.PublicIPAddress; +import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties; import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData; import org.jclouds.azurecompute.arm.domain.SKU; +import org.jclouds.azurecompute.arm.domain.StorageProfile; import org.jclouds.azurecompute.arm.domain.StorageService; -import org.jclouds.azurecompute.arm.domain.VMDeployment; +import org.jclouds.azurecompute.arm.domain.VHD; import org.jclouds.azurecompute.arm.domain.VMHardware; import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VMSize; -import org.jclouds.azurecompute.arm.domain.Value; import org.jclouds.azurecompute.arm.domain.Version; +import org.jclouds.azurecompute.arm.domain.VirtualMachine; +import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties; import org.jclouds.azurecompute.arm.features.OSImageApi; +import org.jclouds.azurecompute.arm.features.PublicIPAddressApi; import org.jclouds.azurecompute.arm.functions.CleanupResources; +import org.jclouds.azurecompute.arm.functions.ParseJobStatus; import org.jclouds.azurecompute.arm.util.BlobHelper; import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder; import org.jclouds.compute.ComputeServiceAdapter; @@ -55,20 +72,22 @@ import org.jclouds.location.Region; import org.jclouds.logging.Logger; import com.google.common.base.Function; +import com.google.common.base.Objects; import com.google.common.base.Predicate; import com.google.common.base.Splitter; +import com.google.common.base.Strings; import com.google.common.base.Supplier; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; -import com.google.common.net.UrlEscapers; import static com.google.common.base.Preconditions.checkState; -import static java.lang.String.format; -import static java.util.concurrent.TimeUnit.SECONDS; +import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_PREFIX; import static org.jclouds.util.Predicates2.retry; /** @@ -76,7 +95,7 @@ import static org.jclouds.util.Predicates2.retry; * {@link org.jclouds.compute.ComputeService}. */ @Singleton -public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeployment, VMHardware, VMImage, Location> { +public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location> { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) @@ -107,9 +126,116 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo } @Override - public NodeAndInitialCredentials<VMDeployment> createNodeWithGroupEncodedIntoName( + public NodeAndInitialCredentials<VirtualMachine> createNodeWithGroupEncodedIntoName( final String group, final String name, final Template template) { + AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class); + + // TODO ARM specific options + + String adminUsername = Objects.firstNonNull(templateOptions.getLoginUser(), "jclouds"); + OSProfile.LinuxConfiguration linuxConfiguration = OSProfile.LinuxConfiguration.create("true", + OSProfile.LinuxConfiguration.SSH.create(Arrays.asList( + OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create( + String.format("/home/%s/.ssh/authorized_keys", adminUsername), + templateOptions.getPublicKey()) + )) + ); + + String locationName = template.getLocation().getId(); + + final PublicIPAddressApi ipApi = api.getPublicIPAddressApi(azureGroup); + + PublicIPAddressProperties properties = + PublicIPAddressProperties.builder() + .publicIPAllocationMethod("Static") + .idleTimeoutInMinutes(4) + .build(); + + String publicIpAddressName = "public-address-" + name; + PublicIPAddress ip = ipApi.createOrUpdate(publicIpAddressName, locationName, ImmutableMap.of("testkey", "testvalue"), properties); + retry(new Predicate<String>() { + @Override public boolean apply(String name) { + return api.getPublicIPAddressApi(azureGroup).get(name).properties().provisioningState().equals("Succeeded"); + } + }, 10 * 1000).apply(publicIpAddressName); + + String subnetId = templateOptions.getSubnetId(); + final NetworkInterfaceCardProperties networkInterfaceCardProperties = + NetworkInterfaceCardProperties.builder() + .ipConfigurations(ImmutableList.of( + IpConfiguration.builder() + .name("ipConfig-" + name) + .properties(IpConfigurationProperties.builder() + .privateIPAllocationMethod("Dynamic") + .publicIPAddress(IdReference.create(ip.id())) + .subnet(IdReference.create(subnetId)) + .build()) + .build())) + .build(); + + String networkInterfaceCardName = "jc-nic-" + name; + NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(azureGroup).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, ImmutableMap.of("jclouds", "livetest")); + + // StorageAccount + String storageAccountName = null; + String imageName = template.getImage().getName(); + if (imageName.startsWith(CUSTOM_IMAGE_PREFIX)) { + storageAccountName = template.getImage().getVersion(); + } + + if (Strings.isNullOrEmpty(storageAccountName)) { + storageAccountName = DeploymentTemplateBuilder.generateStorageAccountName(name); + } + + URI uri = api.getStorageAccountApi(azureGroup).create(storageAccountName, locationName, ImmutableMap.of("property_name", + "property_value"), ImmutableMap.of("accountType", StorageService.AccountType.Standard_LRS.toString())); + retry(new Predicate<URI>() { + @Override + public boolean apply(URI uri) { + return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri); + } + }, 60 * 1 * 1000 /* 1 minute timeout */).apply(uri); + StorageService storageService = api.getStorageAccountApi(azureGroup).get(storageAccountName); + String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob"); + + ImageReference imageReference = ImageReference.builder() + .publisher(template.getImage().getProviderId()) + .offer(template.getImage().getName()) + .sku(template.getImage().getVersion()) + .version("latest") + .build(); + VHD vhd = VHD.create(blob + "vhds/" + name + ".vhd"); + OSDisk osDisk = OSDisk.create(null, name, vhd, "ReadWrite", "FromImage", null); + StorageProfile storageProfile = StorageProfile.create(imageReference, osDisk, ImmutableList.<DataDisk>of()); + + VirtualMachineProperties virtualMachineProperties = VirtualMachineProperties.builder() + .licenseType(null) // TODO + .availabilitySet(null) + .hardwareProfile(HardwareProfile.builder().vmSize(template.getHardware().getId()).build()) + .storageProfile(storageProfile) + .osProfile(OSProfile.builder() + .adminUsername(adminUsername) + .linuxConfiguration(linuxConfiguration) + .computerName(name) + .build()) + .networkProfile(NetworkProfile.builder() + .networkInterfaces(ImmutableList.of(IdReference.create(nic.id()))) + .build()) + .build(); + + VirtualMachine virtualMachine = api.getVirtualMachineApi(azureGroup).create(name, template.getLocation().getId(), virtualMachineProperties); + + //Poll until resource is ready to be used + retry(new Predicate<String>() { + @Override + public boolean apply(String name) { + return api.getVirtualMachineApi(azureGroup).get(name).properties().provisioningState() != VirtualMachineProperties.ProvisioningState.SUCCEEDED; + } + }, 60 * 20 * 1000).apply(name); + + VirtualMachineProperties.ProvisioningState status = api.getVirtualMachineApi(azureGroup).get(name).properties().provisioningState(); + /* DeploymentTemplateBuilder deploymentTemplateBuilder = api.deploymentTemplateFactory().create(group, name, template); DeploymentBody deploymentTemplateBody = deploymentTemplateBuilder.getDeploymentTemplate(); DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody); @@ -140,8 +266,9 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo } VMDeployment vmDeployment = deploymentToVMDeployment.apply(api.getDeploymentApi(azureGroup).get(name)); +*/ // Safe to pass null credentials here, as jclouds will default populate the node with the default credentials from the image, or the ones in the options, if provided. - return new NodeAndInitialCredentials<VMDeployment>(vmDeployment, name, null); + return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, name, null); } @Override @@ -294,9 +421,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo } @Override - public VMDeployment getNode(final String id) { - Deployment deployment = api.getDeploymentApi(azureGroup).get(id); - return deploymentToVMDeployment.apply(deployment); + public VirtualMachine getNode(final String id) { + return api.getVirtualMachineApi(azureGroup).get(id); } @Override @@ -320,7 +446,9 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo } @Override - public Iterable<VMDeployment> listNodes() { + public Iterable<VirtualMachine> listNodes() { + return api.getVirtualMachineApi(azureGroup).list(); + /* return FluentIterable.from(api.getDeploymentApi(azureGroup).list()) .filter(isDeploymentInRegions) .filter(new Predicate<Deployment>() { @@ -334,15 +462,19 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo }) .transform(deploymentToVMDeployment) .toList(); + */ } @Override - public Iterable<VMDeployment> listNodesByIds(final Iterable<String> ids) { + public Iterable<VirtualMachine> listNodesByIds(final Iterable<String> ids) { + return null; // TODO + /* return Iterables.filter(listNodes(), new Predicate<VMDeployment>() { @Override public boolean apply(final VMDeployment input) { return Iterables.contains(ids, input.virtualMachine().name()); } }); + */ } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/21403be0/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java index 8e0d118..21d5062 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java @@ -27,17 +27,17 @@ import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.compute.AzureComputeService; import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter; import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension; -import org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata; import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation; import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware; import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; +import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes; import org.jclouds.azurecompute.arm.domain.Location; import org.jclouds.azurecompute.arm.domain.ResourceDefinition; -import org.jclouds.azurecompute.arm.domain.VMDeployment; import org.jclouds.azurecompute.arm.domain.VMHardware; import org.jclouds.azurecompute.arm.domain.VMImage; +import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance; import org.jclouds.azurecompute.arm.functions.ParseJobStatus; import org.jclouds.compute.ComputeService; @@ -80,7 +80,7 @@ import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_T import static org.jclouds.util.Predicates2.retry; public class AzureComputeServiceContextModule - extends ComputeServiceAdapterContextModule<VMDeployment, VMHardware, VMImage, Location> { + extends ComputeServiceAdapterContextModule<VirtualMachine, VMHardware, VMImage, Location> { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) @@ -89,18 +89,22 @@ public class AzureComputeServiceContextModule @Override protected void configure() { super.configure(); - bind(new TypeLiteral<ComputeServiceAdapter<VMDeployment, VMHardware, VMImage, Location>>() { + bind(new TypeLiteral<ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location>>() { }).to(AzureComputeServiceAdapter.class); bind(new TypeLiteral<Function<VMImage, org.jclouds.compute.domain.Image>>() { }).to(VMImageToImage.class); bind(new TypeLiteral<Function<VMHardware, Hardware>>() { }).to(VMHardwareToHardware.class); + /* bind(new TypeLiteral<Function<VMDeployment, NodeMetadata>>() { }).to(DeploymentToNodeMetadata.class); + */ + bind(new TypeLiteral<Function<VirtualMachine, NodeMetadata>>() { + }).to(VirtualMachineToNodeMetadata.class); bind(new TypeLiteral<Function<Location, org.jclouds.domain.Location>>() { }).to(LocationToLocation.class); bind(ComputeService.class).to(AzureComputeService.class); - install(new LocationsFromComputeServiceAdapterModule<VMDeployment, VMHardware, VMImage, Location>() { + install(new LocationsFromComputeServiceAdapterModule<VirtualMachine, VMHardware, VMImage, Location>() { }); bind(TemplateOptions.class).to(AzureTemplateOptions.class); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/21403be0/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java index e125a53..f7e3b5b 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java @@ -117,7 +117,7 @@ public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMeta //builder.hostname(deployment.name() + "pc"); String group = this.nodeNamingConvention.extractGroup(virtualMachine.name()); builder.group(group); - builder.status(getStatus(virtualMachine.properties().provisioningState())); + //builder.status(getStatus(virtualMachine.properties().provisioningState())); Credentials credentials = credentialStore.get("node#" + virtualMachine.name()); builder.credentials(LoginCredentials.fromCredentials(credentials)); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/21403be0/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java new file mode 100644 index 0000000..8075f02 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java @@ -0,0 +1,206 @@ +/* + * 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.arm.compute.functions; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; + +import org.jclouds.azurecompute.arm.AzureComputeApi; +import org.jclouds.azurecompute.arm.domain.IdReference; +import org.jclouds.azurecompute.arm.domain.ImageReference; +import org.jclouds.azurecompute.arm.domain.IpConfiguration; +import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; +import org.jclouds.azurecompute.arm.domain.VirtualMachine; +import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.functions.GroupNamingConvention; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.Location; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.logging.Logger; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Splitter; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.find; + +public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + // When using the Deployment API to deploy an ARM template, the deployment goes through + // stages. Accepted -> Running -> Succeeded. Only when the deployment has SUCCEEDED is + // the resource deployed using the template actually ready. + // + // To get details about the resource(s) deployed via template, one needs to query the + // various resources after the deployment has "SUCCEEDED". + private static final Map<VirtualMachineProperties.ProvisioningState, NodeMetadata.Status> STATUS_TO_NODESTATUS = + ImmutableMap.<VirtualMachineProperties.ProvisioningState, NodeMetadata.Status>builder(). + put(VirtualMachineProperties.ProvisioningState.ACCEPTED, NodeMetadata.Status.PENDING). + put(VirtualMachineProperties.ProvisioningState.READY, NodeMetadata.Status.PENDING). + put(VirtualMachineProperties.ProvisioningState.CREATING, NodeMetadata.Status.PENDING). + put(VirtualMachineProperties.ProvisioningState.RUNNING, NodeMetadata.Status.PENDING). + put(VirtualMachineProperties.ProvisioningState.CANCELED, NodeMetadata.Status.TERMINATED). + put(VirtualMachineProperties.ProvisioningState.FAILED, NodeMetadata.Status.ERROR). + put(VirtualMachineProperties.ProvisioningState.DELETED, NodeMetadata.Status.TERMINATED). + put(VirtualMachineProperties.ProvisioningState.SUCCEEDED, NodeMetadata.Status.RUNNING). + put(VirtualMachineProperties.ProvisioningState.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED). + build(); + + private final AzureComputeApi api; + private final GroupNamingConvention nodeNamingConvention; + private final Supplier<Map<String, ? extends Image>> images; + private final Supplier<Set<? extends Location>> locations; + private final Supplier<Map<String, ? extends Hardware>> hardwares; + private final Map<String, Credentials> credentialStore; + + @Inject + VirtualMachineToNodeMetadata( + AzureComputeApi api, + GroupNamingConvention.Factory namingConvention, + Supplier<Map<String, ? extends Image>> images, + Supplier<Map<String, ? extends Hardware>> hardwares, + @Memoized Supplier<Set<? extends Location>> locations, Map<String, Credentials> credentialStore) { + this.api = api; + this.nodeNamingConvention = namingConvention.createWithoutPrefix(); + this.images = checkNotNull(images, "images cannot be null"); + this.locations = checkNotNull(locations, "locations cannot be null"); + this.hardwares = checkNotNull(hardwares, "hardwares cannot be null"); + this.credentialStore = credentialStore; + } + @Override + public NodeMetadata apply(VirtualMachine virtualMachine) { + NodeMetadataBuilder builder = new NodeMetadataBuilder(); + builder.id(virtualMachine.name()); + builder.providerId(virtualMachine.id()); + builder.name(virtualMachine.name()); + builder.hostname(virtualMachine.name()); + String group = this.nodeNamingConvention.extractGroup(virtualMachine.name()); + builder.group(group); + builder.status(getStatus(virtualMachine.properties().provisioningState())); + + Credentials credentials = credentialStore.get("node#" + virtualMachine.name()); + builder.credentials(LoginCredentials.fromCredentials(credentials)); + + builder.publicAddresses(getPublicIpAddresses(virtualMachine.properties().networkProfile().networkInterfaces())); + builder.privateAddresses(getPrivateIpAddresses(virtualMachine.properties().networkProfile().networkInterfaces())); + + if (virtualMachine.tags() != null) { + Map<String, String> userMetaData = virtualMachine.tags(); + builder.userMetadata(userMetaData); + builder.tags(Splitter.on(",").split(userMetaData.get("tags"))); + } + String locationName = virtualMachine.location(); + builder.location(getLocation(locationName)); + + ImageReference imageReference = virtualMachine.properties().storageProfile().imageReference(); + Optional<? extends Image> image = findImage(imageReference, locationName); + if (image.isPresent()) { + builder.imageId(image.get().getId()); + builder.operatingSystem(image.get().getOperatingSystem()); + } else { + logger.info(">> image with id %s for virtualmachine %s was not found. " + + "This might be because the image that was used to create the virtualmachine has a new id.", + virtualMachine.id(), virtualMachine.id()); + } + + builder.hardware(getHardware(virtualMachine.properties().hardwareProfile().vmSize())); + + return builder.build(); + } + + private Iterable<String> getPrivateIpAddresses(List<IdReference> idReferences) { + List<String> privateIpAddresses = Lists.newArrayList(); + for (IdReference networkInterfaceCardIdReference : idReferences) { + NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference); + for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) { + privateIpAddresses.add(ipConfiguration.properties().privateIPAddress()); + } + } + return privateIpAddresses; + } + + private NetworkInterfaceCard getNetworkInterfaceCard(IdReference networkInterfaceCardIdReference) { + Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 2); + String resourceGroup = Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 4); + String nicName = Iterables.getLast(Splitter.on("/").split(networkInterfaceCardIdReference.id())); + return api.getNetworkInterfaceCardApi(resourceGroup).get(nicName); + } + + private Iterable<String> getPublicIpAddresses(List<IdReference> idReferences) { + List<String> publicIpAddresses = Lists.newArrayList(); + for (IdReference networkInterfaceCardIdReference : idReferences) { + Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 2); + String resourceGroup = Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 4); + String nicName = Iterables.getLast(Splitter.on("/").split(networkInterfaceCardIdReference.id())); + NetworkInterfaceCard networkInterfaceCard = api.getNetworkInterfaceCardApi(resourceGroup).get(nicName); + for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) { + if (ipConfiguration.properties().publicIPAddress() != null) { + String publicIpId = ipConfiguration.properties().publicIPAddress().id(); + publicIpAddresses.add(api.getPublicIPAddressApi(resourceGroup).get(Iterables.getLast(Splitter.on("/").split(publicIpId))).properties().ipAddress()); + } + } + } + return publicIpAddresses; + } + + private NodeMetadata.Status getStatus(VirtualMachineProperties.ProvisioningState provisioningState) { + return STATUS_TO_NODESTATUS.get(provisioningState); + } + + protected Location getLocation(final String locationName) { + return find(locations.get(), new Predicate<Location>() { + @Override + public boolean apply(Location location) { + return locationName != null && locationName.equals(location.getId()); + } + }, null); + } + + protected Optional<? extends Image> findImage(ImageReference imageReference, String locatioName) { + return Optional.fromNullable(images.get().get(VMImageToImage.encodeFieldsToUniqueId(false, locatioName, imageReference))); + } + + protected Hardware getHardware(final String vmSize) { + return Iterables.find(hardwares.get().values(), new Predicate<Hardware>() { + @Override + public boolean apply(Hardware input) { + return input.getId().equals(vmSize); + } + }); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/21403be0/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java index 3013543..10fa231 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachine.java @@ -16,12 +16,13 @@ */ package org.jclouds.azurecompute.arm.domain; -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableMap; +import java.util.Map; + import org.jclouds.javax.annotation.Nullable; import org.jclouds.json.SerializedNames; -import java.util.Map; +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableMap; /** * A virtual machine that is valid for your subscription. http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/21403be0/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineProperties.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineProperties.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineProperties.java index 73afd14..e59f7c1 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineProperties.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VirtualMachineProperties.java @@ -16,16 +16,34 @@ */ package org.jclouds.azurecompute.arm.domain; -import com.google.auto.value.AutoValue; +import org.jclouds.azurecompute.arm.util.GetEnumValue; import org.jclouds.javax.annotation.Nullable; import org.jclouds.json.SerializedNames; +import com.google.auto.value.AutoValue; + /** * A virtual machine properties for the virtual machine. */ @AutoValue public abstract class VirtualMachineProperties { + public enum ProvisioningState { + ACCEPTED, + CREATING, + READY, + CANCELED, + FAILED, + DELETED, + SUCCEEDED, + RUNNING, + UNRECOGNIZED; + + public static ProvisioningState fromValue(final String text) { + return (ProvisioningState) GetEnumValue.fromValueOrDefault(text, ProvisioningState.UNRECOGNIZED); + } + } + /** * The id of the virtual machine. */ @@ -78,7 +96,7 @@ public abstract class VirtualMachineProperties { * The provisioning state of the VM */ @Nullable - public abstract String provisioningState(); + public abstract ProvisioningState provisioningState(); @SerializedNames({"vmId", "licenseType", "availabilitySet", "hardwareProfile", "storageProfile", "osProfile", "networkProfile", "diagnosticsProfile", "provisioningState"}) @@ -90,7 +108,7 @@ public abstract class VirtualMachineProperties { final OSProfile osProfile, final NetworkProfile networkProfile, final DiagnosticsProfile diagnosticsProfile, - final String provisioningState) { + final ProvisioningState provisioningState) { return builder() .vmId(vmId) .licenseType(licenseType) @@ -126,7 +144,7 @@ public abstract class VirtualMachineProperties { public abstract Builder diagnosticsProfile(DiagnosticsProfile diagnosticsProfile); - public abstract Builder provisioningState(String provisioningState); + public abstract Builder provisioningState(ProvisioningState provisioningState); public abstract VirtualMachineProperties build(); } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/21403be0/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java index 6970887..7290f8d 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java @@ -16,28 +16,29 @@ */ package org.jclouds.azurecompute.arm.functions; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; +import java.net.URI; import javax.annotation.Resource; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import com.google.common.base.Predicate; import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule; -import org.jclouds.azurecompute.arm.domain.Deployment; +import org.jclouds.azurecompute.arm.domain.IdReference; +import org.jclouds.azurecompute.arm.domain.IpConfiguration; import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; -import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; -import org.jclouds.azurecompute.arm.domain.PublicIPAddress; import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.logging.Logger; import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; -import java.net.URI; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; @Singleton public class CleanupResources implements Function<String, Boolean> { @@ -70,8 +71,33 @@ public class CleanupResources implements Function<String, Boolean> { String group = azureComputeConstants.azureResourceGroup(); VirtualMachine vm = api.getVirtualMachineApi(group).get(id); + if (vm != null) { URI uri = api.getVirtualMachineApi(group).delete(id); + nodeTerminated.apply(uri); + + for (IdReference idReference : vm.properties().networkProfile().networkInterfaces()) { + String nicName = Iterables.getLast(Splitter.on("/").split(idReference.id())); + NetworkInterfaceCard networkInterfaceCard = api.getNetworkInterfaceCardApi(group).get(nicName); + + api.getNetworkInterfaceCardApi(group).delete(nicName); + // TODO waitForJob + + for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) { + if (ipConfiguration.properties().publicIPAddress() != null) { + String publicIpId = ipConfiguration.properties().publicIPAddress().id(); + String publicIpAddressName = Iterables.getLast(Splitter.on("/").split(publicIpId)); + // TODO deallocate first? + api.getPublicIPAddressApi(group).delete(publicIpAddressName); + // TODO waitForJob + } + } + } + } + return true; + } +} + /* if (uri != null) { boolean jobDone = nodeTerminated.apply(uri); boolean storageAcctDeleteStatus = false; @@ -127,14 +153,4 @@ public class CleanupResources implements Function<String, Boolean> { } else { return false; } - } else { - return false; - } - } else { - return false; - } - } else { - return false; - } - } -} + */ http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/21403be0/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java index 0f94379..08f3a87 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java @@ -16,10 +16,6 @@ */ package org.jclouds.azurecompute.arm.util; -import static com.google.common.io.BaseEncoding.base64; -import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_PREFIX; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION; - import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -70,6 +66,10 @@ import com.google.common.collect.Lists; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; +import static com.google.common.io.BaseEncoding.base64; +import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_PREFIX; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION; + public class DeploymentTemplateBuilder { public interface Factory { DeploymentTemplateBuilder create(@Assisted("group") String group, @Assisted("name") String name, Template template); @@ -522,7 +522,7 @@ public class DeploymentTemplateBuilder { * If sanitized name is less than 3 characters, storage account is sanitized name plus 4 random chars. * If sanitized name is more than 24 characters, storage account is first 10 chars of sanitized name plus 4 random chars plus last 10 chars of sanitized name. */ - private static String generateStorageAccountName(String name) { + public static String generateStorageAccountName(String name) { String storageAccountName = name.replaceAll("[^a-z0-9]", ""); int nameLength = storageAccountName.length(); if (nameLength >= 3 && nameLength <= 24) { http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/21403be0/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java index 15ca7c9..6629360 100644 --- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java @@ -22,12 +22,14 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata; +import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils; import org.jclouds.compute.RunScriptOnNodesException; import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.internal.BaseComputeServiceLiveTest; import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.domain.LoginCredentials; @@ -102,6 +104,14 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest { } @Override + protected Template buildTemplate(TemplateBuilder templateBuilder) { + Template template = templateBuilder.build(); + AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class); + options.authorizePublicKey("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNnvPZ25wZK19grrbal6R5JP1hLRBUuNh86KxZVMAFkGd5ouVSgO9dFajHZ45Q4mbaTkdOiqf7otMLDzkaztEa7oLK7Jso0Y0LOi+nT4gf38rvbEF5mq069G9b9XqlNleaGnpLuTN54iEK8c4TWZxIJqgelHEHhjp7V1asmilBbpZDmwA5cTt9vGJIhqA/BptKH3folZKeAQjRa1ZRSwSQUnk9rBKn4PKSRDojVa9A9jKt4qboJh5q7ZjtE8z+665F/4TgLzElTXUA8+uUFGpuynMSmQEt301e18dXAl+vBr8fMiThcoVVbdVdqdjXsw75fMXPAgqhjrw8k3+0/4P9 [email protected]"); + return template; + } + + @Override protected Template refreshTemplate() { return this.template = addRunScriptToTemplate(this.buildTemplate(this.client.templateBuilder())); } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/21403be0/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java index 2702370..d759760 100644 --- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java @@ -125,7 +125,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest { }, 60 * 20 * 1000).apply(vmName); assertTrue(jobDone, "create operation did not complete in the configured timeout"); - String status = api().get(vmName).properties().provisioningState(); + VirtualMachineProperties.ProvisioningState status = api().get(vmName).properties().provisioningState(); // Cannot be creating anymore. Should be succeeded or running but not failed. assertTrue(!status.equals("Creating")); assertTrue(!status.equals("Failed")); @@ -245,7 +245,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest { DiagnosticsProfile.BootDiagnostics.create(true, blob); DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics); VirtualMachineProperties properties = VirtualMachineProperties.create(null, - null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, "Creating"); + null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, VirtualMachineProperties.ProvisioningState.CREATING); return properties; } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/21403be0/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java index f6583c8..9e1bd7a 100644 --- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java @@ -16,35 +16,36 @@ */ package org.jclouds.azurecompute.arm.features; -import com.google.common.collect.ImmutableList; -import com.squareup.okhttp.mockwebserver.MockResponse; +import java.net.URI; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.jclouds.azurecompute.arm.domain.DataDisk; +import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile; import org.jclouds.azurecompute.arm.domain.HardwareProfile; import org.jclouds.azurecompute.arm.domain.IdReference; import org.jclouds.azurecompute.arm.domain.ImageReference; -import org.jclouds.azurecompute.arm.domain.VirtualMachine; -import org.jclouds.azurecompute.arm.domain.VHD; +import org.jclouds.azurecompute.arm.domain.NetworkProfile; import org.jclouds.azurecompute.arm.domain.OSDisk; import org.jclouds.azurecompute.arm.domain.OSProfile; -import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile; -import org.jclouds.azurecompute.arm.domain.NetworkProfile; import org.jclouds.azurecompute.arm.domain.StorageProfile; -import org.jclouds.azurecompute.arm.domain.DataDisk; +import org.jclouds.azurecompute.arm.domain.VHD; +import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance; import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties; import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest; import org.testng.annotations.Test; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Date; -import java.text.SimpleDateFormat; -import java.text.DateFormat; +import com.google.common.collect.ImmutableList; +import com.squareup.okhttp.mockwebserver.MockResponse; import static com.google.common.collect.Iterables.isEmpty; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; @Test(groups = "unit", testName = "VirtualMachineApiMockTest", singleThreaded = true) @@ -231,7 +232,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest { "https://groupname2760.blob.core.windows.net/"); DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics); VirtualMachineProperties properties = VirtualMachineProperties.create("27ee085b-d707-xxxx-yyyy-2370e2eb1cc1", - null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, "Creating"); + null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, VirtualMachineProperties.ProvisioningState.CREATING); return properties; }
