diff --git a/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/AvailabilitySetImpl.java b/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/AvailabilitySetImpl.java index b71f30a0bd38..460165bfcea3 100644 --- a/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/AvailabilitySetImpl.java +++ b/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/AvailabilitySetImpl.java @@ -11,6 +11,9 @@ import com.microsoft.azure.management.compute.implementation.api.AvailabilitySetsInner; import com.microsoft.azure.management.compute.implementation.api.InstanceViewStatus; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; +import com.microsoft.azure.management.resources.fluentcore.utils.Utils; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; import com.microsoft.azure.management.resources.implementation.ResourceManager; import com.microsoft.rest.ServiceResponse; import java.util.ArrayList; @@ -90,6 +93,11 @@ public AvailabilitySetImpl apply() throws Exception { return this.create(); } + @Override + public ServiceCall applyAsync(ServiceCallback callback) { + return this.createAsync(callback); + } + @Override protected void createResource() throws Exception { ServiceResponse response = this.client.createOrUpdate(this.resourceGroupName(), this.name(), this.inner()); @@ -97,4 +105,21 @@ protected void createResource() throws Exception { this.setInner(availabilitySetInner); this.idOfVMsInSet = null; } + + @Override + protected ServiceCall createResourceAsync(final ServiceCallback callback) { + return this.client.createOrUpdateAsync(this.resourceGroupName(), this.name(), this.inner(), + Utils.fromVoidCallback(this, new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + idOfVMsInSet = null; + callback.success(result); + } + })); + } } diff --git a/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/VirtualMachineImpl.java b/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/VirtualMachineImpl.java index c3802aaca8dd..811ec8f5999c 100644 --- a/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/VirtualMachineImpl.java +++ b/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/VirtualMachineImpl.java @@ -48,11 +48,14 @@ import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; import com.microsoft.azure.management.resources.fluentcore.utils.PagedListConverter; import com.microsoft.azure.management.resources.fluentcore.utils.ResourceNamer; +import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.azure.management.resources.implementation.ResourceManager; import com.microsoft.azure.management.resources.implementation.api.PageImpl; import com.microsoft.azure.management.storage.StorageAccount; import com.microsoft.azure.management.storage.implementation.StorageManager; import com.microsoft.rest.RestException; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceResponse; import java.io.IOException; @@ -156,6 +159,11 @@ public VirtualMachineImpl apply() throws Exception { return this.create(); } + @Override + public ServiceCall applyAsync(ServiceCallback callback) { + return this.createAsync(callback); + } + @Override public void deallocate() throws CloudException, IOException, InterruptedException { this.client.deallocate(this.resourceGroupName(), this.name()); @@ -850,6 +858,43 @@ protected void createResource() throws Exception { initializeDataDisks(); } + @Override + protected ServiceCall createResourceAsync(final ServiceCallback callback) { + if (isInCreateMode()) { + setOSDiskAndOSProfileDefaults(); + setHardwareProfileDefaults(); + } + DataDiskImpl.setDataDisksDefaults(this.dataDisks, this.vmName); + final VirtualMachineImpl self = this; + final ServiceCall call = new ServiceCall(null); + handleStorageSettingsAsync(new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + handleNetworkSettings(); + handleAvailabilitySettings(); + call.newCall(client.createOrUpdateAsync(resourceGroupName(), vmName, inner(), + Utils.fromVoidCallback(self, new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + initializeDataDisks(); + callback.success(result); + } + })).getCall()); + } + }); + return call; + } + /**************************************************. * Helper methods **************************************************/ @@ -927,6 +972,61 @@ private void handleStorageSettings() throws Exception { } } + private void handleStorageSettingsAsync(final ServiceCallback callback) { + final ServiceCallback storageAccountServiceCallback = new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + if (isInCreateMode()) { + if (isOSDiskFromImage(inner().storageProfile().osDisk())) { + String uri = inner() + .storageProfile() + .osDisk().vhd().uri() + .replaceFirst("\\{storage-base-url}", result.getBody().endPoints().primary().blob()); + inner().storageProfile().osDisk().vhd().withUri(uri); + } + DataDiskImpl.ensureDisksVhdUri(dataDisks, result.getBody(), vmName); + } else { + if (result.getBody() != null) { + DataDiskImpl.ensureDisksVhdUri(dataDisks, result.getBody(), vmName); + } else { + DataDiskImpl.ensureDisksVhdUri(dataDisks, vmName); + } + } + callback.success(new ServiceResponse(result.getHeadResponse())); + } + }; + if (this.creatableStorageAccountKey != null) { + storageAccountServiceCallback.success(new ServiceResponse<>( + (StorageAccount) this.createdResource(this.creatableStorageAccountKey), null)); + } else if (this.existingStorageAccountToAssociate != null) { + storageAccountServiceCallback.success(new ServiceResponse<>( + this.existingStorageAccountToAssociate, null)); + } else if (osDiskRequiresImplicitStorageAccountCreation() + || dataDisksRequiresImplicitStorageAccountCreation()) { + this.storageManager.storageAccounts() + .define(this.namer.randomName("stg", 24)) + .withRegion(this.region()) + .withExistingGroup(this.resourceGroupName()) + .createAsync(new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + storageAccountServiceCallback.success(result); + } + }); + } + + } + private void handleNetworkSettings() { if (isInCreateMode()) { NetworkInterface primaryNetworkInterface = null; diff --git a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkImpl.java b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkImpl.java index e1f0f7a5a455..1c7f2caff718 100644 --- a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkImpl.java +++ b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkImpl.java @@ -5,21 +5,24 @@ */ package com.microsoft.azure.management.network.implementation; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - import com.microsoft.azure.management.network.Network; import com.microsoft.azure.management.network.Subnet; import com.microsoft.azure.management.network.implementation.api.SubnetInner; import com.microsoft.azure.management.network.implementation.api.VirtualNetworkInner; import com.microsoft.azure.management.network.implementation.api.VirtualNetworksInner; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; +import com.microsoft.azure.management.resources.fluentcore.utils.Utils; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; import com.microsoft.azure.management.resources.implementation.ResourceManager; import com.microsoft.rest.ServiceResponse; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + /** * Internal virtual network implementation of the fluent interface. * (Internal use only) @@ -67,6 +70,11 @@ public NetworkImpl apply() throws Exception { return this.create(); } + @Override + public ServiceCall applyAsync(ServiceCallback callback) { + return createAsync(callback); + } + // Setters (fluent) @Override @@ -165,4 +173,33 @@ protected void createResource() throws Exception { this.setInner(response.getBody()); initializeSubnetsFromInner(); } + + @Override + protected ServiceCall createResourceAsync(final ServiceCallback callback) { + // Ensure address spaces + if (this.addressSpaces().size() == 0) { + this.withAddressSpace("10.0.0.0/16"); + } + + if (isInCreateMode()) { + // Create a subnet as needed, covering the entire first address space + if (this.inner().subnets().size() == 0) { + this.withSubnet("subnet1", this.addressSpaces().get(0)); + } + } + + return this.client.createOrUpdateAsync(this.resourceGroupName(), this.name(), this.inner(), + Utils.fromVoidCallback(this, new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + initializeSubnetsFromInner(); + callback.success(result); + } + })); + } } \ No newline at end of file diff --git a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkInterfaceImpl.java b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkInterfaceImpl.java index 7bf48fd7f4d3..8712fec4724a 100644 --- a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkInterfaceImpl.java +++ b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkInterfaceImpl.java @@ -23,6 +23,8 @@ import com.microsoft.azure.management.resources.fluentcore.model.Creatable; import com.microsoft.azure.management.resources.fluentcore.utils.ResourceNamer; import com.microsoft.azure.management.resources.fluentcore.utils.Utils; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; import com.microsoft.azure.management.resources.implementation.ResourceManager; import com.microsoft.rest.ServiceResponse; @@ -91,6 +93,11 @@ public NetworkInterfaceImpl apply() throws Exception { return this.create(); } + @Override + public ServiceCall applyAsync(ServiceCallback callback) { + return createAsync(callback); + } + /**************************************************. * Setters **************************************************/ @@ -352,6 +359,26 @@ protected void createResource() throws Exception { initializeNicIpConfigurations(); } + @Override + protected ServiceCall createResourceAsync(final ServiceCallback callback) { + NicIpConfigurationImpl.ensureConfigurations(this.nicIpConfigurations); + return this.client.createOrUpdateAsync(this.resourceGroupName(), + this.nicName, + this.inner(), + Utils.fromVoidCallback(this, new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + initializeNicIpConfigurations(); + callback.success(result); + } + })); + } + /**************************************************. * Helper methods **************************************************/ diff --git a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkSecurityGroupImpl.java b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkSecurityGroupImpl.java index bd880e5c9723..746d414561e4 100644 --- a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkSecurityGroupImpl.java +++ b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkSecurityGroupImpl.java @@ -5,10 +5,6 @@ */ package com.microsoft.azure.management.network.implementation; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import com.microsoft.azure.management.network.NetworkSecurityGroup; import com.microsoft.azure.management.network.NetworkSecurityRule; import com.microsoft.azure.management.network.implementation.api.NetworkInterfaceInner; @@ -16,9 +12,16 @@ import com.microsoft.azure.management.network.implementation.api.NetworkSecurityGroupsInner; import com.microsoft.azure.management.network.implementation.api.SecurityRuleInner; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; +import com.microsoft.azure.management.resources.fluentcore.utils.Utils; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; import com.microsoft.azure.management.resources.implementation.ResourceManager; import com.microsoft.rest.ServiceResponse; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * Implementation of the NetworkSecurityGroup interface. * (Internal use only) @@ -75,6 +78,11 @@ public NetworkSecurityGroupImpl apply() throws Exception { return this.create(); } + @Override + public ServiceCall applyAsync(ServiceCallback callback) { + return createAsync(callback); + } + @Override protected void createResource() throws Exception { ServiceResponse response = @@ -83,6 +91,23 @@ protected void createResource() throws Exception { initializeRulesFromInner(); } + @Override + protected ServiceCall createResourceAsync(final ServiceCallback callback) { + return this.client.createOrUpdateAsync(this.resourceGroupName(), this.name(), this.inner(), + Utils.fromVoidCallback(this, new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + initializeRulesFromInner(); + callback.success(result); + } + })); + } + // Setters (fluent) diff --git a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/PublicIpAddressImpl.java b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/PublicIpAddressImpl.java index a4a68fd1a733..7281e4cc52c8 100644 --- a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/PublicIpAddressImpl.java +++ b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/PublicIpAddressImpl.java @@ -11,6 +11,9 @@ import com.microsoft.azure.management.network.implementation.api.PublicIPAddressInner; import com.microsoft.azure.management.network.implementation.api.PublicIPAddressesInner; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; +import com.microsoft.azure.management.resources.fluentcore.utils.Utils; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; import com.microsoft.azure.management.resources.implementation.ResourceManager; import com.microsoft.rest.ServiceResponse; @@ -42,6 +45,11 @@ public PublicIpAddressImpl apply() throws Exception { return this.create(); } + @Override + public ServiceCall applyAsync(ServiceCallback callback) { + return this.createAsync(callback); + } + @Override public PublicIpAddress refresh() throws Exception { ServiceResponse response = @@ -146,4 +154,20 @@ protected void createResource() throws Exception { this.client.createOrUpdate(this.resourceGroupName(), this.name(), this.inner()); this.setInner(response.getBody()); } + + @Override + protected ServiceCall createResourceAsync(ServiceCallback callback) { + // Clean up empty DNS settings + final PublicIPAddressDnsSettings dnsSettings = this.inner().dnsSettings(); + if (dnsSettings != null) { + if ((dnsSettings.domainNameLabel() == null || dnsSettings.domainNameLabel().isEmpty()) + && (dnsSettings.fqdn() == null || dnsSettings.fqdn().isEmpty()) + && (dnsSettings.reverseFqdn() == null || dnsSettings.reverseFqdn().isEmpty())) { + this.inner().withDnsSettings(null); + } + } + + return this.client.createOrUpdateAsync(this.resourceGroupName(), this.name(), this.inner(), + Utils.fromVoidCallback(this, callback)); + } } \ No newline at end of file diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/Appliable.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/Appliable.java index 8866b469e712..bc26b679f8df 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/Appliable.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/Appliable.java @@ -6,6 +6,9 @@ package com.microsoft.azure.management.resources.fluentcore.model; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; + /** * The base interface for all template interfaces that support update operations. * @@ -19,4 +22,12 @@ public interface Appliable extends Indexable { * @throws Exception exceptions from Azure */ T apply() throws Exception; + + /** + * Execute the update request asynchronously. + * + * @param callback the callback for success and failure + * @return the handle to the REST call + */ + ServiceCall applyAsync(ServiceCallback callback); } diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/Creatable.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/Creatable.java index e73bf420f1de..b690ed3c1d58 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/Creatable.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/Creatable.java @@ -6,6 +6,9 @@ package com.microsoft.azure.management.resources.fluentcore.model; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; + /** * The final stage of the resource definition, at which it can be create, using {@link #create()}. * @@ -19,4 +22,13 @@ public interface Creatable extends Indexable { * @throws Exception exceptions from Azure */ T create() throws Exception; + + /** + * Puts the request into the queue and allow the HTTP client to execute + * it when system resources are available. + * + * @param callback the callback to handle success and failure + * @return a handle to cancel the request + */ + ServiceCall createAsync(ServiceCallback callback); } \ No newline at end of file diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableImpl.java index 3386870db264..f897367d19d6 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableImpl.java @@ -8,6 +8,9 @@ import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.management.resources.fluentcore.model.Creatable; +import com.microsoft.azure.management.resources.fluentcore.utils.Utils; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; /** * The base class for all creatable resource. @@ -26,7 +29,33 @@ public abstract class CreatableImpl protected CreatableImpl(String name, InnerModelT innerObject) { super(name, innerObject); - creatableTaskGroup = new CreatableTaskGroup(name, (Creatable) this, this); + creatableTaskGroup = new CreatableTaskGroup(name, (Creatable) this, this); + } + + /** + * create this resource and creatable resources it depends on. + *

+ * dependency resources will be created only if this is the root group otherwise + * it creates the main resource. + * + * @throws Exception the exception + */ + protected void creatablesCreate() throws Exception { + if (creatableTaskGroup.isRoot()) { + creatableTaskGroup.prepare(); + creatableTaskGroup.execute(); + } else { + createResource(); + } + } + + protected ServiceCall creatablesCreateAsync(ServiceCallback callback) { + if (creatableTaskGroup.isRoot()) { + creatableTaskGroup.prepare(); + return creatableTaskGroup.executeAsync(callback); + } else { + return createResourceAsync(callback); + } } /** @@ -44,6 +73,11 @@ public void createRootResource() throws Exception { this.createResource(); } + @Override + public ServiceCall createRootResourceAsync(ServiceCallback callback) { + return this.createResourceAsync(callback); + } + protected Resource createdResource(String key) { return this.creatableTaskGroup.taskResult(key); } @@ -56,6 +90,7 @@ protected Resource createdResource(String key) { @SuppressWarnings("unchecked") public FluentModelImplT create() throws Exception { if (creatableTaskGroup.isRoot()) { + creatableTaskGroup.prepare(); creatableTaskGroup.execute(); } else { createResource(); @@ -63,10 +98,28 @@ public FluentModelImplT create() throws Exception { return (FluentModelImplT) this; } + /** + * Default implementation of createAsync(). + * + * @param callback the callback to call on success or failure + * @return the handle to the create REST call + */ + @SuppressWarnings("unchecked") + public ServiceCall createAsync(ServiceCallback callback) { + if (creatableTaskGroup.isRoot()) { + creatableTaskGroup.prepare(); + return creatableTaskGroup.executeAsync(Utils.toVoidCallback((FluentModelT) this, callback)); + } else { + return createResourceAsync(Utils.toVoidCallback((FluentModelT) this, callback)); + } + } + /** * Creates this resource. * * @throws Exception the exception */ protected abstract void createResource() throws Exception; + + protected abstract ServiceCall createResourceAsync(ServiceCallback callback); } diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskGroup.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskGroup.java index 74a561d54538..bf40e4fefda0 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskGroup.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskGroup.java @@ -1,13 +1,17 @@ package com.microsoft.azure.management.resources.fluentcore.model.implementation; -import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.TaskGroupBase; +import com.microsoft.azure.TaskItem; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.management.resources.fluentcore.model.Creatable; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; /** * Type representing a group of creatable tasks and the dependency between them. */ -public class CreatableTaskGroup extends TaskGroupBase { +public class CreatableTaskGroup extends TaskGroupBase { + /** * Represents a type that know how to create the root resource in a CreatableTaskGroup. */ @@ -16,6 +20,8 @@ interface RootResourceCreator { * Creates the root resource. */ void createRootResource() throws Exception; + + ServiceCall createRootResourceAsync(ServiceCallback serviceCallback); } private final RootResourceCreator rootCreate; @@ -28,7 +34,7 @@ interface RootResourceCreator { * @param rootCreate {@link RootResourceCreator} that know how to create the rootCreatable once all the * dependencies are available */ - public CreatableTaskGroup(String rootCreatableId, Creatable rootCreatable, RootResourceCreator rootCreate) { + public CreatableTaskGroup(String rootCreatableId, Creatable rootCreatable, RootResourceCreator rootCreate) { this(rootCreatableId, new CreatableTaskItem(rootCreatable), rootCreate); } @@ -59,7 +65,12 @@ public Resource createdResource(String key) { } @Override - public void executeRootTask(CreatableTaskItem rootTaskItem) throws Exception { + public void executeRootTask(TaskItem task) throws Exception { this.rootCreate.createRootResource(); } + + @Override + public ServiceCall executeRootTaskAsync(TaskItem task, ServiceCallback callback) { + return this.rootCreate.createRootResourceAsync(callback); + } } diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskItem.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskItem.java index e86d9ff4326b..584974bf1358 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskItem.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskItem.java @@ -1,14 +1,20 @@ package com.microsoft.azure.management.resources.fluentcore.model.implementation; +import com.microsoft.azure.DAGNode; +import com.microsoft.azure.TaskGroup; import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.TaskItem; import com.microsoft.azure.management.resources.fluentcore.model.Creatable; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; +import com.microsoft.rest.ServiceResponse; /** * Represents a task that creates a resource when executed. */ public class CreatableTaskItem implements TaskItem { - private Creatable creatable; + private Creatable creatable; + private DAGNode> node; private Resource created; /** @@ -16,7 +22,7 @@ public class CreatableTaskItem implements TaskItem { * * @param creatable the creatable */ - public CreatableTaskItem(Creatable creatable) { + public CreatableTaskItem(Creatable creatable) { this.creatable = creatable; } @@ -26,7 +32,27 @@ public Resource result() { } @Override - public void execute() throws Exception { - this.created = (Resource) this.creatable.create(); + public void execute(TaskGroup> taskGroup, DAGNode> node) throws Exception { + this.created = this.creatable.create(); + taskGroup.dag().reportedCompleted(node); + taskGroup.execute(); + } + + @Override + public ServiceCall executeAsync(final TaskGroup> taskGroup, final DAGNode> node, final ServiceCallback callback) { + final CreatableTaskItem self = this; + return ((Creatable) this.creatable).createAsync(new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + self.created = result.getBody(); + taskGroup.dag().reportedCompleted(node); + taskGroup.executeAsync(callback); + } + }); } } diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/IndexableRefreshableWrapperImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/IndexableRefreshableWrapperImpl.java index 801f26ea8ba3..127b83325be6 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/IndexableRefreshableWrapperImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/IndexableRefreshableWrapperImpl.java @@ -31,7 +31,13 @@ public InnerModelT inner() { return this.innerObject; } - protected void setInner(InnerModelT inner) { + /** + * Set the wrapped inner model. + * (For internal use only) + * + * @param inner the new inner model + */ + public void setInner(InnerModelT inner) { this.innerObject = inner; } } diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/utils/Utils.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/utils/Utils.java index 49f0683f82a5..94e237b28e76 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/utils/Utils.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/utils/Utils.java @@ -6,6 +6,10 @@ package com.microsoft.azure.management.resources.fluentcore.utils; +import com.microsoft.azure.management.resources.fluentcore.model.implementation.CreatableImpl; +import com.microsoft.rest.ServiceCallback; +import com.microsoft.rest.ServiceResponse; + /** * Defines a few utilities. */ @@ -33,6 +37,57 @@ public static boolean toPrimitiveBoolean(Boolean value) { return value; } + /** + * Creates a void callback from a callback that returns another type of + * instance. This is useful for internal async handoffs where returned + * resource is stored elsewhere. + * + * @param model the fluent model + * @param callback the callback to return the fluent model + * @param the fluent model type + * @return the void callback + */ + public static ServiceCallback toVoidCallback(final T model, final ServiceCallback callback) { + return new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + callback.success(new ServiceResponse<>(model, result.getResponse())); + } + }; + } + + /** + * Creates a callback returning the inner resource from a fluent model + * and a void callback, and set the inner on the fluent model. + * + * @param modelImpl the implementation instance of the fluent resource + * @param callback the void callback + * @param the inner resource type + * @param the fluent resource type + * @param the implementation for the fuent resource type + * @return the inner callback + */ + public static > ServiceCallback + fromVoidCallback(final FluentImplT modelImpl, final ServiceCallback callback) { + return new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + modelImpl.setInner(result.getBody()); + callback.success(new ServiceResponse(result.getHeadResponse())); + } + }; + } + private Utils() { } } diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/DeploymentImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/DeploymentImpl.java index 03b7ea922c39..6295de79b2a2 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/DeploymentImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/DeploymentImpl.java @@ -29,6 +29,9 @@ import com.microsoft.azure.management.resources.implementation.api.ParametersLink; import com.microsoft.azure.management.resources.implementation.api.ProviderInner; import com.microsoft.azure.management.resources.implementation.api.TemplateLink; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; +import com.microsoft.rest.ServiceResponse; import org.joda.time.DateTime; import java.io.IOException; @@ -280,6 +283,46 @@ public DeploymentImpl create() throws Exception { // FLUENT: implementa return this; } + @Override + public ServiceCall createAsync(final ServiceCallback callback) { + final Deployment self = this; + if (this.creatableResourceGroup != null) { + return this.creatableResourceGroup.createAsync(new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + createResourceAsync(new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + callback.success(new ServiceResponse<>(self, result.getResponse())); + } + }); + } + }); + } else { + return createResourceAsync(new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + callback.success(new ServiceResponse<>(self, result.getResponse())); + } + }); + } + } + @Override public Deployment refresh() throws Exception { return null; @@ -297,6 +340,28 @@ protected void createResource() throws Exception { client.createOrUpdate(resourceGroupName(), name(), inner); } + @Override + protected ServiceCall createResourceAsync(final ServiceCallback callback) { + DeploymentInner inner = new DeploymentInner() + .withProperties(new DeploymentProperties()); + inner.properties().withMode(mode()); + inner.properties().withTemplate(template()); + inner.properties().withTemplateLink(templateLink()); + inner.properties().withParameters(parameters()); + inner.properties().withParametersLink(parametersLink()); + return client.createOrUpdateAsync(resourceGroupName(), name(), inner, new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + callback.success(new ServiceResponse(result.getHeadResponse())); + } + }); + } + @Override public DeploymentImpl apply() throws Exception { if (this.templateLink() != null && this.template() != null) { @@ -307,4 +372,19 @@ public DeploymentImpl apply() throws Exception { } return this.create(); } + + @Override + public ServiceCall applyAsync(ServiceCallback callback) { + try { + if (this.templateLink() != null && this.template() != null) { + this.withTemplate(null); + } + if (this.parametersLink() != null && this.parameters() != null) { + this.withParameters(null); + } + } catch (IOException e) { + callback.failure(e); + } + return this.createAsync(callback); + } } diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/GenericResourceImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/GenericResourceImpl.java index 757ae154a274..55b891086249 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/GenericResourceImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/GenericResourceImpl.java @@ -8,10 +8,13 @@ import com.microsoft.azure.management.resources.GenericResource; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; +import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.azure.management.resources.implementation.api.GenericResourceInner; import com.microsoft.azure.management.resources.implementation.api.Plan; import com.microsoft.azure.management.resources.implementation.api.ResourceManagementClientImpl; import com.microsoft.azure.management.resources.implementation.api.ResourcesInner; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; /** * The implementation for GenericResource and its nested interfaces. @@ -126,6 +129,11 @@ public GenericResourceImpl create() throws Exception { return this; } + @Override + public ServiceCall createAsync(final ServiceCallback callback) { + return createResourceAsync(Utils.toVoidCallback(this, callback)); + } + @Override protected void createResource() throws Exception { GenericResourceInner inner = client.createOrUpdate( @@ -140,8 +148,26 @@ protected void createResource() throws Exception { this.setInner(inner); } + @Override + protected ServiceCall createResourceAsync(final ServiceCallback callback) { + return client.createOrUpdateAsync( + resourceGroupName(), + resourceProviderNamespace, + parentResourceId, + resourceType, + key(), + apiVersion, + inner(), + Utils.fromVoidCallback(this, callback)); + } + @Override public GenericResourceImpl apply() throws Exception { return create(); } + + @Override + public ServiceCall applyAsync(ServiceCallback callback) { + return createAsync(callback); + } } diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceGroupImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceGroupImpl.java index 288e16939786..f2eb517613c9 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceGroupImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceGroupImpl.java @@ -13,11 +13,14 @@ import com.microsoft.azure.management.resources.ResourceGroupExportTemplateOptions; import com.microsoft.azure.management.resources.fluentcore.arm.Region; import com.microsoft.azure.management.resources.fluentcore.model.implementation.CreatableUpdatableImpl; +import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.azure.management.resources.implementation.api.ExportTemplateRequestInner; import com.microsoft.azure.management.resources.implementation.api.ResourceGroupExportResultInner; import com.microsoft.azure.management.resources.implementation.api.ResourceGroupInner; import com.microsoft.azure.management.resources.implementation.api.ResourceGroupsInner; import com.microsoft.azure.management.resources.implementation.api.ResourceManagementClientImpl; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; import java.io.IOException; import java.util.Arrays; @@ -123,7 +126,12 @@ public ResourceGroupImpl apply() throws Exception { } @Override - public ResourceGroupImpl refresh() throws Exception { // FLUENT: implementation of ResourceGroup.Refreshable + public ServiceCall applyAsync(ServiceCallback callback) { + return createAsync(callback); + } + + @Override + public ResourceGroupImpl refresh() throws Exception { this.setInner(client.get(this.key).getBody()); return this; } @@ -140,4 +148,12 @@ protected void createResource() throws Exception { params.withTags(this.inner().tags()); client.createOrUpdate(this.name(), params); } + + @Override + protected ServiceCall createResourceAsync(final ServiceCallback callback) { + ResourceGroupInner params = new ResourceGroupInner(); + params.withLocation(this.inner().location()); + params.withTags(this.inner().tags()); + return client.createOrUpdateAsync(this.name(), params, Utils.fromVoidCallback(this, callback)); + } } diff --git a/azure-mgmt-storage/src/main/java/com/microsoft/azure/management/storage/implementation/StorageAccountImpl.java b/azure-mgmt-storage/src/main/java/com/microsoft/azure/management/storage/implementation/StorageAccountImpl.java index 61036d6561ad..e55f42d7c3b8 100644 --- a/azure-mgmt-storage/src/main/java/com/microsoft/azure/management/storage/implementation/StorageAccountImpl.java +++ b/azure-mgmt-storage/src/main/java/com/microsoft/azure/management/storage/implementation/StorageAccountImpl.java @@ -8,6 +8,7 @@ import com.microsoft.azure.CloudException; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; +import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.azure.management.resources.implementation.ResourceManager; import com.microsoft.azure.management.storage.KeyType; import com.microsoft.azure.management.storage.StorageAccount; @@ -24,6 +25,8 @@ import com.microsoft.azure.management.storage.implementation.api.StorageAccountListKeysResultInner; import com.microsoft.azure.management.storage.implementation.api.StorageAccountUpdateParametersInner; import com.microsoft.azure.management.storage.implementation.api.StorageAccountsInner; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceResponse; import org.joda.time.DateTime; @@ -206,6 +209,27 @@ protected void createResource() throws Exception { clearWrapperProperties(); } + @Override + protected ServiceCall createResourceAsync(final ServiceCallback callback) { + createParameters.withLocation(this.region()); + createParameters.withTags(this.inner().getTags()); + final StorageAccountImpl self = this; + return this.client.createAsync(this.resourceGroupName(), this.name(), createParameters, + new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + client.getPropertiesAsync(resourceGroupName(), name(), + Utils.fromVoidCallback(self, callback)); + clearWrapperProperties(); + } + }); + } + @Override public StorageAccountImpl update() { updateParameters = new StorageAccountUpdateParametersInner(); @@ -218,6 +242,23 @@ public StorageAccountImpl apply() throws Exception { return this; } + @Override + public ServiceCall applyAsync(final ServiceCallback callback) { + final StorageAccountImpl self = this; + return client.updateAsync(resourceGroupName(), name(), updateParameters, new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + setInner(result.getBody()); + callback.success(new ServiceResponse(self, result.getResponse())); + } + }); + } + @Override public StorageAccountImpl withCustomDomain(CustomDomain customDomain) { if (isInCreateMode()) { diff --git a/azure/src/test/java/com/microsoft/azure/TestTemplate.java b/azure/src/test/java/com/microsoft/azure/TestTemplate.java index 10c22c50a57f..aae728b4c195 100644 --- a/azure/src/test/java/com/microsoft/azure/TestTemplate.java +++ b/azure/src/test/java/com/microsoft/azure/TestTemplate.java @@ -5,16 +5,14 @@ */ package com.microsoft.azure; -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - import com.microsoft.azure.management.resources.ResourceGroups; import com.microsoft.azure.management.resources.fluentcore.arm.collection.SupportsGettingByGroup; import com.microsoft.azure.management.resources.fluentcore.arm.models.GroupableResource; import com.microsoft.azure.management.resources.fluentcore.collection.SupportsDeleting; import com.microsoft.azure.management.resources.fluentcore.collection.SupportsListing; +import org.junit.Assert; + +import java.io.IOException; /** * Base class for CRUD test cases for top level Azure resource models. @@ -89,7 +87,6 @@ public void verifyDeleting() throws Exception { * @param resourceGroups the resource groups collection * @throws Exception if anything goes wrong */ - @Test public void runTest(C collection, ResourceGroups resourceGroups) throws Exception { this.collection = collection; this.resourceGroups = resourceGroups; diff --git a/azure/src/test/java/com/microsoft/azure/TestVirtualMachine.java b/azure/src/test/java/com/microsoft/azure/TestVirtualMachine.java index 1bba7748e00c..006851502dbe 100644 --- a/azure/src/test/java/com/microsoft/azure/TestVirtualMachine.java +++ b/azure/src/test/java/com/microsoft/azure/TestVirtualMachine.java @@ -1,15 +1,28 @@ package com.microsoft.azure; +import com.microsoft.azure.credentials.ApplicationTokenCredentials; import com.microsoft.azure.management.compute.KnownWindowsVirtualMachineImage; import com.microsoft.azure.management.compute.VirtualMachine; import com.microsoft.azure.management.compute.VirtualMachines; +import com.microsoft.azure.management.compute.implementation.api.VirtualMachineSizeTypes; import com.microsoft.azure.management.resources.fluentcore.arm.Region; +import com.microsoft.rest.ServiceCallback; +import com.microsoft.rest.ServiceResponse; +import okhttp3.logging.HttpLoggingInterceptor; +import org.junit.Test; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.fail; public class TestVirtualMachine extends TestTemplate { @Override public VirtualMachine createResource(VirtualMachines virtualMachines) throws Exception { final String vmName = "vm" + this.testId; - VirtualMachine vm = virtualMachines.define(vmName) + final CountDownLatch latch = new CountDownLatch(1); + final VirtualMachine[] vms = new VirtualMachine[1]; + virtualMachines.define(vmName) .withRegion(Region.US_EAST) .withNewGroup() .withNewPrimaryNetwork("10.0.0.0/28") @@ -18,8 +31,21 @@ public VirtualMachine createResource(VirtualMachines virtualMachines) throws Exc .withPopularWindowsImage(KnownWindowsVirtualMachineImage.WINDOWS_SERVER_2012_R2_DATACENTER) .withAdminUserName("testuser") .withPassword("12NewPA$$w0rd!") - .create(); - return vm; + .withSize(VirtualMachineSizeTypes.STANDARD_D1_V2) + .createAsync(new ServiceCallback() { + @Override + public void failure(Throwable t) { + fail(); + } + + @Override + public void success(ServiceResponse result) { + vms[0] = result.getBody(); + latch.countDown(); + } + }); + latch.await(12, TimeUnit.MINUTES); + return vms[0]; } @Override @@ -31,4 +57,19 @@ public VirtualMachine updateResource(VirtualMachine resource) throws Exception { public void print(VirtualMachine virtualMachine) { TestUtils.print(virtualMachine); } + + @Test + public void run() throws Exception { + ApplicationTokenCredentials credentials = new ApplicationTokenCredentials( + System.getenv("client-id"), + System.getenv("domain"), + System.getenv("secret"), + null); + + Azure azure = Azure.configure() + .withLogLevel(HttpLoggingInterceptor.Level.BODY) + .authenticate(credentials) + .withDefaultSubscription(); + runTest(azure.virtualMachines(), azure.resourceGroups()); + } } diff --git a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroup.java b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroup.java index 94b4628ff70a..29507425d443 100644 --- a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroup.java +++ b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroup.java @@ -7,6 +7,9 @@ package com.microsoft.azure; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; + /** * Represents a group of related tasks. *

@@ -39,6 +42,11 @@ public interface TaskGroup> { */ void merge(TaskGroup parentTaskGroup); + /** + * Prepare the graph for execution. + */ + void prepare(); + /** * Executes the tasks in the group. *

@@ -48,6 +56,14 @@ public interface TaskGroup> { */ void execute() throws Exception; + /** + * Executes the tasks in the group asynchronously. + * + * @param callback the callback to call on failure or success + * @return the handle to the REST call + */ + ServiceCall executeAsync(ServiceCallback callback); + /** * Gets the result of execution of a task in the group. *

diff --git a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroupBase.java b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroupBase.java index 5cf4369142ea..48978f12ca11 100644 --- a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroupBase.java +++ b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroupBase.java @@ -7,15 +7,17 @@ package com.microsoft.azure; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; + /** * The base implementation of TaskGroup interface. * * @param the result type of the tasks in the group - * @param type representing task in the group */ -public abstract class TaskGroupBase> - implements TaskGroup { - private DAGraph> dag; +public abstract class TaskGroupBase + implements TaskGroup> { + private DAGraph, DAGNode>> dag; /** * Creates TaskGroupBase. @@ -23,12 +25,12 @@ public abstract class TaskGroupBase> * @param rootTaskItemId the id of the root task in this task group * @param rootTaskItem the root task */ - public TaskGroupBase(String rootTaskItemId, U rootTaskItem) { + public TaskGroupBase(String rootTaskItemId, TaskItem rootTaskItem) { this.dag = new DAGraph<>(new DAGNode<>(rootTaskItemId, rootTaskItem)); } @Override - public DAGraph> dag() { + public DAGraph, DAGNode>> dag() { return dag; } @@ -38,27 +40,51 @@ public boolean isRoot() { } @Override - public void merge(TaskGroup parentTaskGroup) { + public void merge(TaskGroup> parentTaskGroup) { dag.merge(parentTaskGroup.dag()); } @Override - public void execute() throws Exception { + public void prepare() { if (isRoot()) { dag.prepare(); - DAGNode nextNode = dag.getNext(); - while (nextNode != null) { - if (dag.isRootNode(nextNode)) { - executeRootTask(nextNode.data()); - } else { - // TaskGroupBase::execute will be called both in update and create - // scenarios, so run the task only if it not not executed already. - if (nextNode.data().result() == null) { - nextNode.data().execute(); - } - } - dag.reportedCompleted(nextNode); - nextNode = dag.getNext(); + } + } + + @Override + public void execute() throws Exception { + DAGNode> nextNode = dag.getNext(); + if (nextNode == null) { + return; + } + + if (dag.isRootNode(nextNode)) { + executeRootTask(nextNode.data()); + } else { + // TaskGroupBase::execute will be called both in update and create + // scenarios, so run the task only if it not not executed already. + if (nextNode.data().result() == null) { + nextNode.data().execute(this, nextNode); + } + } + } + + @Override + public ServiceCall executeAsync(final ServiceCallback callback) { + final DAGNode> nextNode = dag.getNext(); + if (nextNode == null) { + return null; + } + + if (dag.isRootNode(nextNode)) { + return executeRootTaskAsync(nextNode.data(), callback); + } else { + // TaskGroupBase::execute will be called both in update and create + // scenarios, so run the task only if it not not executed already. + if (nextNode.data().result() == null) { + return nextNode.data().executeAsync(this, nextNode, callback); + } else { + return null; } } } @@ -78,5 +104,18 @@ public T taskResult(String taskId) { * @param task the root task in this group * @throws Exception the exception */ - public abstract void executeRootTask(U task) throws Exception; + public abstract void executeRootTask(TaskItem task) throws Exception; + + /** + * executes the root task in this group asynchronously. + *

+ * this method will be invoked when all the task dependencies of the root task are finished + * executing, at this point root task can be executed by consuming the result of tasks it + * depends on. + * + * @param task the root task in this group + * @param callback the callback when the task fails or succeeds + * @return the handle to the REST call + */ + public abstract ServiceCall executeRootTaskAsync(TaskItem task, ServiceCallback callback); } diff --git a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskItem.java b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskItem.java index 7df830f69bb9..fb74c23845c3 100644 --- a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskItem.java +++ b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskItem.java @@ -7,6 +7,9 @@ package com.microsoft.azure; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; + /** * Type representing a task in a task group {@link TaskGroup}. * @@ -22,7 +25,22 @@ public interface TaskItem { * Executes the task. *

* once executed the result will be available through result getter + * + * @param taskGroup the task group dispatching tasks + * @param node the node the task item is associated with * @throws Exception exception */ - void execute() throws Exception; + void execute(TaskGroup> taskGroup, DAGNode> node) throws Exception; + + /** + * Executes the task asynchronously. + *

+ * once executed the result will be available through result getter + + * @param taskGroup the task group dispatching tasks + * @param node the node the task item is associated with + * @param callback callback to call on success or failure + * @return the handle of the REST call + */ + ServiceCall executeAsync(TaskGroup> taskGroup, DAGNode> node, ServiceCallback callback); }