/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*/
package com.microsoft.azure.management.compute.implementation;
import com.microsoft.azure.PagedList;
import com.microsoft.azure.SubResource;
import com.microsoft.azure.management.apigeneration.LangDefinition;
import com.microsoft.azure.management.compute.ApiEntityReference;
import com.microsoft.azure.management.compute.CachingTypes;
import com.microsoft.azure.management.compute.DiskCreateOptionTypes;
import com.microsoft.azure.management.compute.ImageReference;
import com.microsoft.azure.management.compute.KnownLinuxVirtualMachineImage;
import com.microsoft.azure.management.compute.KnownWindowsVirtualMachineImage;
import com.microsoft.azure.management.compute.LinuxConfiguration;
import com.microsoft.azure.management.compute.OperatingSystemTypes;
import com.microsoft.azure.management.compute.SshConfiguration;
import com.microsoft.azure.management.compute.SshPublicKey;
import com.microsoft.azure.management.compute.StorageAccountTypes;
import com.microsoft.azure.management.compute.UpgradeMode;
import com.microsoft.azure.management.compute.UpgradePolicy;
import com.microsoft.azure.management.compute.VirtualHardDisk;
import com.microsoft.azure.management.compute.VirtualMachineScaleSet;
import com.microsoft.azure.management.compute.VirtualMachineScaleSetDataDisk;
import com.microsoft.azure.management.compute.VirtualMachineScaleSetExtension;
import com.microsoft.azure.management.compute.VirtualMachineScaleSetExtensionProfile;
import com.microsoft.azure.management.compute.VirtualMachineScaleSetManagedDiskParameters;
import com.microsoft.azure.management.compute.VirtualMachineScaleSetNetworkProfile;
import com.microsoft.azure.management.compute.VirtualMachineScaleSetOSDisk;
import com.microsoft.azure.management.compute.VirtualMachineScaleSetOSProfile;
import com.microsoft.azure.management.compute.VirtualMachineScaleSetSku;
import com.microsoft.azure.management.compute.VirtualMachineScaleSetSkuTypes;
import com.microsoft.azure.management.compute.VirtualMachineScaleSetStorageProfile;
import com.microsoft.azure.management.compute.VirtualMachineScaleSetVMs;
import com.microsoft.azure.management.compute.WinRMConfiguration;
import com.microsoft.azure.management.compute.WinRMListener;
import com.microsoft.azure.management.compute.WindowsConfiguration;
import com.microsoft.azure.management.network.LoadBalancerBackend;
import com.microsoft.azure.management.network.LoadBalancerFrontend;
import com.microsoft.azure.management.network.LoadBalancerInboundNatPool;
import com.microsoft.azure.management.network.LoadBalancer;
import com.microsoft.azure.management.network.Network;
import com.microsoft.azure.management.network.VirtualMachineScaleSetNetworkInterface;
import com.microsoft.azure.management.network.implementation.NetworkManager;
import com.microsoft.azure.management.resources.fluentcore.arm.ResourceUtils;
import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableParentResourceImpl;
import com.microsoft.azure.management.resources.fluentcore.model.Creatable;
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.SdkContext;
import com.microsoft.azure.management.resources.fluentcore.utils.Utils;
import com.microsoft.azure.management.storage.StorageAccount;
import com.microsoft.azure.management.storage.implementation.StorageManager;
import com.microsoft.rest.ServiceCallback;
import com.microsoft.rest.ServiceFuture;
import rx.Completable;
import rx.Observable;
import rx.functions.Func0;
import rx.functions.Func1;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Implementation of VirtualMachineScaleSet.
*/
@LangDefinition
public class VirtualMachineScaleSetImpl
extends GroupableParentResourceImpl<
VirtualMachineScaleSet,
VirtualMachineScaleSetInner,
VirtualMachineScaleSetImpl,
ComputeManager>
implements
VirtualMachineScaleSet,
VirtualMachineScaleSet.DefinitionManagedOrUnmanaged,
VirtualMachineScaleSet.DefinitionManaged,
VirtualMachineScaleSet.DefinitionUnmanaged,
VirtualMachineScaleSet.Update {
// Clients
private final StorageManager storageManager;
private final NetworkManager networkManager;
// used to generate unique name for any dependency resources
private final ResourceNamer namer;
private boolean isMarketplaceLinuxImage = false;
// name of an existing subnet in the primary network to use
private String existingPrimaryNetworkSubnetNameToAssociate;
// unique key of a creatable storage accounts to be used for virtual machines child resources that
// requires storage [OS disk]
private List<String> creatableStorageAccountKeys = new ArrayList<>();
// reference to an existing storage account to be used for virtual machines child resources that
// requires storage [OS disk]
private List<StorageAccount> existingStorageAccountsToAssociate = new ArrayList<>();
// Name of the container in the storage account to use to store the disks
private String vhdContainerName;
// the child resource extensions
private Map<String, VirtualMachineScaleSetExtension> extensions;
// reference to the primary and internal Internet facing load balancer
private LoadBalancer primaryInternetFacingLoadBalancer;
private LoadBalancer primaryInternalLoadBalancer;
// Load balancer specific variables used during update
private boolean removePrimaryInternetFacingLoadBalancerOnUpdate;
private boolean removePrimaryInternalLoadBalancerOnUpdate;
private LoadBalancer primaryInternetFacingLoadBalancerToAttachOnUpdate;
private LoadBalancer primaryInternalLoadBalancerToAttachOnUpdate;
private List<String> primaryInternetFacingLBBackendsToRemoveOnUpdate = new ArrayList<>();
private List<String> primaryInternetFacingLBInboundNatPoolsToRemoveOnUpdate = new ArrayList<>();
private List<String> primaryInternalLBBackendsToRemoveOnUpdate = new ArrayList<>();
private List<String> primaryInternalLBInboundNatPoolsToRemoveOnUpdate = new ArrayList<>();
private List<String> primaryInternetFacingLBBackendsToAddOnUpdate = new ArrayList<>();
private List<String> primaryInternetFacingLBInboundNatPoolsToAddOnUpdate = new ArrayList<>();
private List<String> primaryInternalLBBackendsToAddOnUpdate = new ArrayList<>();
private List<String> primaryInternalLBInboundNatPoolsToAddOnUpdate = new ArrayList<>();
// The paged converter for virtual machine scale set sku
private PagedListConverter<VirtualMachineScaleSetSkuInner, VirtualMachineScaleSetSku> skuConverter;
// Flag indicates native disk is selected for OS and Data disks
private boolean isUnmanagedDiskSelected;
// To track the managed data disks
private final ManagedDataDiskCollection managedDataDisks;
VirtualMachineScaleSetImpl(
String name,
VirtualMachineScaleSetInner innerModel,
final ComputeManager computeManager,
final StorageManager storageManager,
final NetworkManager networkManager) {
super(name, innerModel, computeManager);
this.storageManager = storageManager;
this.networkManager = networkManager;
this.namer = SdkContext.getResourceNamerFactory().createResourceNamer(this.name());
this.skuConverter = new PagedListConverter<VirtualMachineScaleSetSkuInner, VirtualMachineScaleSetSku>() {
@Override
public VirtualMachineScaleSetSku typeConvert(VirtualMachineScaleSetSkuInner inner) {
return new VirtualMachineScaleSetSkuImpl(inner);
}
};
this.managedDataDisks = new ManagedDataDiskCollection(this);
}
@Override
protected void initializeChildrenFromInner() {
this.extensions = new HashMap<>();
if (this.inner().virtualMachineProfile().extensionProfile() != null) {
if (this.inner().virtualMachineProfile().extensionProfile().extensions() != null) {
for (VirtualMachineScaleSetExtensionInner inner : this.inner().virtualMachineProfile().extensionProfile().extensions()) {
this.extensions.put(inner.name(), new VirtualMachineScaleSetExtensionImpl(inner, this));
}
}
}
}
@Override
public VirtualMachineScaleSetVMs virtualMachines() {
return new VirtualMachineScaleSetVMsImpl(this, this.manager().inner().virtualMachineScaleSetVMs(), this.myManager);
}
@Override
public PagedList<VirtualMachineScaleSetSku> listAvailableSkus() {
return this.skuConverter.convert(this.manager().inner().virtualMachineScaleSets().listSkus(this.resourceGroupName(), this.name()));
}
@Override
public void deallocate() {
this.deallocateAsync().await();
}
@Override
public Completable deallocateAsync() {
Observable<OperationStatusResponseInner> d = this.manager().inner().virtualMachineScaleSets().deallocateAsync(this.resourceGroupName(), this.name());
Observable<VirtualMachineScaleSet> r = this.refreshAsync();
return Observable.concat(d, r).toCompletable();
}
@Override
public ServiceFuture<Void> deallocateAsync(ServiceCallback<Void> callback) {
return ServiceFuture.fromBody(this.deallocateAsync().<Void>toObservable(), callback);
}
@Override
public void powerOff() {
this.powerOffAsync().await();
}
@Override
public Completable powerOffAsync() {
return this.manager().inner().virtualMachineScaleSets().powerOffAsync(this.resourceGroupName(), this.name()).toCompletable();
}
@Override
public ServiceFuture<Void> powerOffAsync(ServiceCallback<Void> callback) {
return ServiceFuture.fromBody(this.powerOffAsync().<Void>toObservable(), callback);
}
@Override
public void restart() {
this.restartAsync().await();
}
@Override
public Completable restartAsync() {
return this.manager().inner().virtualMachineScaleSets().restartAsync(this.resourceGroupName(), this.name()).toCompletable();
}
@Override
public ServiceFuture<Void> restartAsync(ServiceCallback<Void> callback) {
return ServiceFuture.fromBody(this.restartAsync().<Void>toObservable(), callback);
}
@Override
public void start() {
this.startAsync().await();
}
@Override
public Completable startAsync() {
return this.manager().inner().virtualMachineScaleSets().startAsync(this.resourceGroupName(), this.name()).toCompletable();
}
@Override
public ServiceFuture<Void> startAsync(ServiceCallback<Void> callback) {
return ServiceFuture.fromBody(this.startAsync().<Void>toObservable(), callback);
}
@Override
public void reimage() {
this.reimageAsync().await();
}
@Override
public Completable reimageAsync() {
return this.manager().inner().virtualMachineScaleSets().reimageAsync(this.resourceGroupName(), this.name()).toCompletable();
}
@Override
public ServiceFuture<Void> reimageAsync(ServiceCallback<Void> callback) {
return ServiceFuture.fromBody(this.reimageAsync().<Void>toObservable(), callback);
}
@Override
public String computerNamePrefix() {
return this.inner().virtualMachineProfile().osProfile().computerNamePrefix();
}
@Override
public OperatingSystemTypes osType() {
return this.inner().virtualMachineProfile().storageProfile().osDisk().osType();
}
@Override
public CachingTypes osDiskCachingType() {
return this.inner().virtualMachineProfile().storageProfile().osDisk().caching();
}
@Override
public String osDiskName() {
return this.inner().virtualMachineProfile().storageProfile().osDisk().name();
}
@Override
public UpgradeMode upgradeModel() {
// upgradePolicy is a required property so no null check
return this.inner().upgradePolicy().mode();
}
@Override
public boolean overProvisionEnabled() {
return this.inner().overprovision();
}
@Override
public VirtualMachineScaleSetSkuTypes sku() {
return VirtualMachineScaleSetSkuTypes.fromSku(this.inner().sku());
}
@Override
public long capacity() {
return Utils.toPrimitiveLong(this.inner().sku().capacity());
}
@Override
public Network getPrimaryNetwork() throws IOException {
String subnetId = primaryNicDefaultIPConfiguration().subnet().id();
String virtualNetworkId = ResourceUtils.parentResourceIdFromResourceId(subnetId);
return this.networkManager
.networks()
.getById(virtualNetworkId);
}
@Override
public LoadBalancer getPrimaryInternetFacingLoadBalancer() throws IOException {
if (this.primaryInternetFacingLoadBalancer == null) {
loadCurrentPrimaryLoadBalancersIfAvailable();
}
return this.primaryInternetFacingLoadBalancer;
}
@Override
public Map<String, LoadBalancerBackend> listPrimaryInternetFacingLoadBalancerBackends() throws IOException {
if (this.getPrimaryInternetFacingLoadBalancer() != null) {
return getBackendsAssociatedWithIpConfiguration(this.primaryInternetFacingLoadBalancer,
primaryNicDefaultIPConfiguration());
}
return new HashMap<>();
}
@Override
public Map<String, LoadBalancerInboundNatPool> listPrimaryInternetFacingLoadBalancerInboundNatPools() throws IOException {
if (this.getPrimaryInternetFacingLoadBalancer() != null) {
return getInboundNatPoolsAssociatedWithIpConfiguration(this.primaryInternetFacingLoadBalancer,
primaryNicDefaultIPConfiguration());
}
return new HashMap<>();
}
@Override
public LoadBalancer getPrimaryInternalLoadBalancer() throws IOException {
if (this.primaryInternalLoadBalancer == null) {
loadCurrentPrimaryLoadBalancersIfAvailable();
}
return this.primaryInternalLoadBalancer;
}
@Override
public Map<String, LoadBalancerBackend> listPrimaryInternalLoadBalancerBackends() throws IOException {
if (this.getPrimaryInternalLoadBalancer() != null) {
return getBackendsAssociatedWithIpConfiguration(this.primaryInternalLoadBalancer,
primaryNicDefaultIPConfiguration());
}
return new HashMap<>();
}
@Override
public Map<String, LoadBalancerInboundNatPool> listPrimaryInternalLoadBalancerInboundNatPools() throws IOException {
if (this.getPrimaryInternalLoadBalancer() != null) {
return getInboundNatPoolsAssociatedWithIpConfiguration(this.primaryInternalLoadBalancer,
primaryNicDefaultIPConfiguration());
}
return new HashMap<>();
}
@Override
public List<String> primaryPublicIPAddressIds() throws IOException {
LoadBalancer loadBalancer = this.getPrimaryInternetFacingLoadBalancer();
if (loadBalancer != null) {
return loadBalancer.publicIPAddressIds();
}
return new ArrayList<>();
}
@Override
public List<String> vhdContainers() {
if (this.storageProfile() != null
&& this.storageProfile().osDisk() != null
&& this.storageProfile().osDisk().vhdContainers() != null) {
return this.storageProfile().osDisk().vhdContainers();
}
return new ArrayList<>();
}
@Override
public VirtualMachineScaleSetStorageProfile storageProfile() {
return this.inner().virtualMachineProfile().storageProfile();
}
@Override
public VirtualMachineScaleSetNetworkProfile networkProfile() {
return this.inner().virtualMachineProfile().networkProfile();
}
@Override
public Map<String, VirtualMachineScaleSetExtension> extensions() {
return Collections.unmodifiableMap(this.extensions);
}
@Override
public VirtualMachineScaleSetNetworkInterface getNetworkInterfaceByInstanceId(String instanceId, String name) {
return this.networkManager.networkInterfaces().getByVirtualMachineScaleSetInstanceId(this.resourceGroupName(),
this.name(),
instanceId,
name);
}
@Override
public PagedList<VirtualMachineScaleSetNetworkInterface> listNetworkInterfaces() {
return this.networkManager.networkInterfaces()
.listByVirtualMachineScaleSet(this.resourceGroupName(), this.name());
}
@Override
public PagedList<VirtualMachineScaleSetNetworkInterface> listNetworkInterfacesByInstanceId(String virtualMachineInstanceId) {
return this.networkManager.networkInterfaces()
.listByVirtualMachineScaleSetInstanceId(this.resourceGroupName(),
this.name(),
virtualMachineInstanceId);
}
// Fluent setters
@Override
public VirtualMachineScaleSetImpl withSku(VirtualMachineScaleSetSkuTypes skuType) {
this.inner()
.withSku(skuType.sku());
return this;
}
@Override
public VirtualMachineScaleSetImpl withSku(VirtualMachineScaleSetSku sku) {
return this.withSku(sku.skuType());
}
@Override
public VirtualMachineScaleSetImpl withExistingPrimaryNetworkSubnet(Network network, String subnetName) {
this.existingPrimaryNetworkSubnetNameToAssociate = mergePath(network.id(), "subnets", subnetName);
return this;
}
@Override
public VirtualMachineScaleSetImpl withExistingPrimaryInternetFacingLoadBalancer(LoadBalancer loadBalancer) {
if (loadBalancer.publicIPAddressIds().isEmpty()) {
throw new IllegalArgumentException("Parameter loadBalancer must be an Internet facing load balancer");
}
if (isInCreateMode()) {
this.primaryInternetFacingLoadBalancer = loadBalancer;
associateLoadBalancerToIpConfiguration(this.primaryInternetFacingLoadBalancer,
this.primaryNicDefaultIPConfiguration());
} else {
this.primaryInternetFacingLoadBalancerToAttachOnUpdate = loadBalancer;
}
return this;
}
@Override
public VirtualMachineScaleSetImpl withPrimaryInternetFacingLoadBalancerBackends(String... backendNames) {
if (this.isInCreateMode()) {
VirtualMachineScaleSetIPConfigurationInner defaultPrimaryIpConfig = this.primaryNicDefaultIPConfiguration();
removeAllBackendAssociationFromIpConfiguration(this.primaryInternetFacingLoadBalancer, defaultPrimaryIpConfig);
associateBackEndsToIpConfiguration(this.primaryInternetFacingLoadBalancer.id(),
defaultPrimaryIpConfig,
backendNames);
} else {
addToList(this.primaryInternetFacingLBBackendsToAddOnUpdate, backendNames);
}
return this;
}
@Override
public VirtualMachineScaleSetImpl withPrimaryInternetFacingLoadBalancerInboundNatPools(String... natPoolNames) {
if (this.isInCreateMode()) {
VirtualMachineScaleSetIPConfigurationInner defaultPrimaryIpConfig = this.primaryNicDefaultIPConfiguration();
removeAllInboundNatPoolAssociationFromIpConfiguration(this.primaryInternetFacingLoadBalancer,
defaultPrimaryIpConfig);
associateInboundNATPoolsToIpConfiguration(this.primaryInternetFacingLoadBalancer.id(),
defaultPrimaryIpConfig,
natPoolNames);
} else {
addToList(this.primaryInternetFacingLBInboundNatPoolsToAddOnUpdate, natPoolNames);
}
return this;
}
@Override
public VirtualMachineScaleSetImpl withExistingPrimaryInternalLoadBalancer(LoadBalancer loadBalancer) {
if (!loadBalancer.publicIPAddressIds().isEmpty()) {
throw new IllegalArgumentException("Parameter loadBalancer must be an internal load balancer");
}
String lbNetworkId = null;
for (LoadBalancerFrontend frontEnd : loadBalancer.frontends().values()) {
if (frontEnd.inner().subnet().id() != null) {
lbNetworkId = ResourceUtils.parentResourceIdFromResourceId(frontEnd.inner().subnet().id());
}
}
if (isInCreateMode()) {
String vmNICNetworkId = ResourceUtils.parentResourceIdFromResourceId(this.existingPrimaryNetworkSubnetNameToAssociate);
// Azure has a really wired BUG that - it throws exception when vnet of VMSS and LB are not same
// (code: NetworkInterfaceAndInternalLoadBalancerMustUseSameVnet) but at the same time Azure update
// the VMSS's network section to refer this invalid internal LB. This makes VMSS un-usable and portal
// will show a error above VMSS profile page.
//
if (!vmNICNetworkId.equalsIgnoreCase(lbNetworkId)) {
throw new IllegalArgumentException("Virtual network associated with scale set virtual machines"
+ " and internal load balancer must be same. "
+ "'" + vmNICNetworkId + "'"
+ "'" + lbNetworkId);
}
this.primaryInternalLoadBalancer = loadBalancer;
associateLoadBalancerToIpConfiguration(this.primaryInternalLoadBalancer,
this.primaryNicDefaultIPConfiguration());
} else {
String vmNicVnetId = ResourceUtils.parentResourceIdFromResourceId(primaryNicDefaultIPConfiguration()
.subnet()
.id());
if (!vmNicVnetId.equalsIgnoreCase(lbNetworkId)) {
throw new IllegalArgumentException("Virtual network associated with scale set virtual machines"
+ " and internal load balancer must be same. "
+ "'" + vmNicVnetId + "'"
+ "'" + lbNetworkId);
}
this.primaryInternalLoadBalancerToAttachOnUpdate = loadBalancer;
}
return this;
}
@Override
public VirtualMachineScaleSetImpl withPrimaryInternalLoadBalancerBackends(String... backendNames) {
if (this.isInCreateMode()) {
VirtualMachineScaleSetIPConfigurationInner defaultPrimaryIpConfig = primaryNicDefaultIPConfiguration();
removeAllBackendAssociationFromIpConfiguration(this.primaryInternalLoadBalancer,
defaultPrimaryIpConfig);
associateBackEndsToIpConfiguration(this.primaryInternalLoadBalancer.id(),
defaultPrimaryIpConfig,
backendNames);
} else {
addToList(this.primaryInternalLBBackendsToAddOnUpdate, backendNames);
}
return this;
}
@Override
public VirtualMachineScaleSetImpl withPrimaryInternalLoadBalancerInboundNatPools(String... natPoolNames) {
if (this.isInCreateMode()) {
VirtualMachineScaleSetIPConfigurationInner defaultPrimaryIpConfig = this.primaryNicDefaultIPConfiguration();
removeAllInboundNatPoolAssociationFromIpConfiguration(this.primaryInternalLoadBalancer,
defaultPrimaryIpConfig);
associateInboundNATPoolsToIpConfiguration(this.primaryInternalLoadBalancer.id(),
defaultPrimaryIpConfig,
natPoolNames);
} else {
addToList(this.primaryInternalLBInboundNatPoolsToAddOnUpdate, natPoolNames);
}
return this;
}
@Override
public VirtualMachineScaleSetImpl withoutPrimaryInternalLoadBalancer() {
if (this.isInUpdateMode()) {
this.removePrimaryInternalLoadBalancerOnUpdate = true;
}
return this;
}
@Override
public VirtualMachineScaleSetImpl withoutPrimaryInternetFacingLoadBalancer() {
if (this.isInUpdateMode()) {
this.removePrimaryInternetFacingLoadBalancerOnUpdate = true;
}
return this;
}
@Override
public VirtualMachineScaleSetImpl withoutPrimaryInternetFacingLoadBalancerBackends(String ...backendNames) {
addToList(this.primaryInternetFacingLBBackendsToRemoveOnUpdate, backendNames);
return this;
}
@Override
public VirtualMachineScaleSetImpl withoutPrimaryInternalLoadBalancerBackends(String ...backendNames) {
addToList(this.primaryInternalLBBackendsToRemoveOnUpdate, backendNames);
return this;
}
@Override
public VirtualMachineScaleSetImpl withoutPrimaryInternetFacingLoadBalancerNatPools(String ...natPoolNames) {
addToList(this.primaryInternetFacingLBInboundNatPoolsToRemoveOnUpdate, natPoolNames);
return this;
}
@Override
public VirtualMachineScaleSetImpl withoutPrimaryInternalLoadBalancerNatPools(String ...natPoolNames) {
addToList(this.primaryInternalLBInboundNatPoolsToRemoveOnUpdate, natPoolNames);
return this;
}
@Override
public VirtualMachineScaleSetImpl withPopularWindowsImage(KnownWindowsVirtualMachineImage knownImage) {
return withSpecificWindowsImageVersion(knownImage.imageReference());
}
@Override
public VirtualMachineScaleSetImpl withLatestWindowsImage(String publisher, String offer, String sku) {
ImageReference imageReference = new ImageReference()
.withPublisher(publisher)
.withOffer(offer)
.withSku(sku)
.withVersion("latest");
return withSpecificWindowsImageVersion(imageReference);
}
@Override
public VirtualMachineScaleSetImpl withSpecificWindowsImageVersion(ImageReference imageReference) {
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withCreateOption(DiskCreateOptionTypes.FROM_IMAGE);
this.inner()
.virtualMachineProfile()
.storageProfile().withImageReference(imageReference.inner());
this.inner()
.virtualMachineProfile()
.osProfile().withWindowsConfiguration(new WindowsConfiguration());
// sets defaults for "Stored(Custom)Image" or "VM(Platform)Image"
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withProvisionVMAgent(true);
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withEnableAutomaticUpdates(true);
return this;
}
@Override
public VirtualMachineScaleSetImpl withWindowsCustomImage(String customImageId) {
ImageReferenceInner imageReferenceInner = new ImageReferenceInner();
imageReferenceInner.withId(customImageId);
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withCreateOption(DiskCreateOptionTypes.FROM_IMAGE);
this.inner()
.virtualMachineProfile()
.storageProfile().withImageReference(imageReferenceInner);
this.inner()
.virtualMachineProfile()
.osProfile().withWindowsConfiguration(new WindowsConfiguration());
// sets defaults for "Stored(Custom)Image" or "VM(Platform)Image"
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withProvisionVMAgent(true);
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withEnableAutomaticUpdates(true);
return this;
}
@Override
public VirtualMachineScaleSetImpl withStoredWindowsImage(String imageUrl) {
VirtualHardDisk userImageVhd = new VirtualHardDisk();
userImageVhd.withUri(imageUrl);
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withCreateOption(DiskCreateOptionTypes.FROM_IMAGE);
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withImage(userImageVhd);
// For platform image osType will be null, azure will pick it from the image metadata.
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withOsType(OperatingSystemTypes.WINDOWS);
this.inner()
.virtualMachineProfile()
.osProfile().withWindowsConfiguration(new WindowsConfiguration());
// sets defaults for "Stored(Custom)Image" or "VM(Platform)Image"
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withProvisionVMAgent(true);
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withEnableAutomaticUpdates(true);
return this;
}
@Override
public VirtualMachineScaleSetImpl withPopularLinuxImage(KnownLinuxVirtualMachineImage knownImage) {
return withSpecificLinuxImageVersion(knownImage.imageReference());
}
@Override
public VirtualMachineScaleSetImpl withLatestLinuxImage(String publisher, String offer, String sku) {
ImageReference imageReference = new ImageReference()
.withPublisher(publisher)
.withOffer(offer)
.withSku(sku)
.withVersion("latest");
return withSpecificLinuxImageVersion(imageReference);
}
@Override
public VirtualMachineScaleSetImpl withSpecificLinuxImageVersion(ImageReference imageReference) {
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withCreateOption(DiskCreateOptionTypes.FROM_IMAGE);
this.inner()
.virtualMachineProfile()
.storageProfile().withImageReference(imageReference.inner());
this.inner()
.virtualMachineProfile()
.osProfile().withLinuxConfiguration(new LinuxConfiguration());
this.isMarketplaceLinuxImage = true;
return this;
}
@Override
public VirtualMachineScaleSetImpl withLinuxCustomImage(String customImageId) {
ImageReferenceInner imageReferenceInner = new ImageReferenceInner();
imageReferenceInner.withId(customImageId);
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withCreateOption(DiskCreateOptionTypes.FROM_IMAGE);
this.inner()
.virtualMachineProfile()
.storageProfile().withImageReference(imageReferenceInner);
this.inner()
.virtualMachineProfile()
.osProfile().withLinuxConfiguration(new LinuxConfiguration());
this.isMarketplaceLinuxImage = true;
return this;
}
@Override
public VirtualMachineScaleSetImpl withStoredLinuxImage(String imageUrl) {
VirtualHardDisk userImageVhd = new VirtualHardDisk();
userImageVhd.withUri(imageUrl);
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withCreateOption(DiskCreateOptionTypes.FROM_IMAGE);
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withImage(userImageVhd);
// For platform image osType will be null, azure will pick it from the image metadata.
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withOsType(OperatingSystemTypes.LINUX);
this.inner()
.virtualMachineProfile()
.osProfile().withLinuxConfiguration(new LinuxConfiguration());
return this;
}
@Override
public VirtualMachineScaleSetImpl withAdminUsername(String adminUserName) {
this.inner()
.virtualMachineProfile()
.osProfile()
.withAdminUsername(adminUserName);
return this;
}
@Override
public VirtualMachineScaleSetImpl withRootUsername(String adminUserName) {
this.inner()
.virtualMachineProfile()
.osProfile()
.withAdminUsername(adminUserName);
return this;
}
@Override
public VirtualMachineScaleSetImpl withAdminPassword(String password) {
this.inner()
.virtualMachineProfile()
.osProfile()
.withAdminPassword(password);
return this;
}
@Override
public VirtualMachineScaleSetImpl withRootPassword(String password) {
this.inner()
.virtualMachineProfile()
.osProfile()
.withAdminPassword(password);
return this;
}
@Override
public VirtualMachineScaleSetImpl withSsh(String publicKeyData) {
VirtualMachineScaleSetOSProfile osProfile = this.inner()
.virtualMachineProfile()
.osProfile();
if (osProfile.linuxConfiguration().ssh() == null) {
SshConfiguration sshConfiguration = new SshConfiguration();
sshConfiguration.withPublicKeys(new ArrayList<SshPublicKey>());
osProfile.linuxConfiguration().withSsh(sshConfiguration);
}
SshPublicKey sshPublicKey = new SshPublicKey();
sshPublicKey.withKeyData(publicKeyData);
sshPublicKey.withPath("/home/" + osProfile.adminUsername() + "/.ssh/authorized_keys");
osProfile.linuxConfiguration().ssh().publicKeys().add(sshPublicKey);
return this;
}
@Override
public VirtualMachineScaleSetImpl withVMAgent() {
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withProvisionVMAgent(true);
return this;
}
@Override
public VirtualMachineScaleSetImpl withoutVMAgent() {
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withProvisionVMAgent(false);
return this;
}
@Override
public VirtualMachineScaleSetImpl withAutoUpdate() {
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withEnableAutomaticUpdates(true);
return this;
}
@Override
public VirtualMachineScaleSetImpl withoutAutoUpdate() {
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withEnableAutomaticUpdates(false);
return this;
}
@Override
public VirtualMachineScaleSetImpl withTimeZone(String timeZone) {
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withTimeZone(timeZone);
return this;
}
@Override
public VirtualMachineScaleSetImpl withWinRM(WinRMListener listener) {
if (this.inner().virtualMachineProfile().osProfile().windowsConfiguration().winRM() == null) {
WinRMConfiguration winRMConfiguration = new WinRMConfiguration();
this.inner()
.virtualMachineProfile()
.osProfile().windowsConfiguration().withWinRM(winRMConfiguration);
}
this.inner()
.virtualMachineProfile()
.osProfile()
.windowsConfiguration()
.winRM()
.listeners()
.add(listener);
return this;
}
@Override
public VirtualMachineScaleSetImpl withOSDiskCaching(CachingTypes cachingType) {
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withCaching(cachingType);
return this;
}
@Override
public VirtualMachineScaleSetImpl withOSDiskName(String name) {
this.inner()
.virtualMachineProfile()
.storageProfile().osDisk().withName(name);
return this;
}
@Override
public VirtualMachineScaleSetImpl withComputerNamePrefix(String namePrefix) {
this.inner()
.virtualMachineProfile()
.osProfile()
.withComputerNamePrefix(namePrefix);
return this;
}
@Override
public VirtualMachineScaleSetImpl withUpgradeMode(UpgradeMode upgradeMode) {
if (this.inner().upgradePolicy() == null) {
this.inner().withUpgradePolicy(new UpgradePolicy());
}
this.inner()
.upgradePolicy()
.withMode(upgradeMode);
return this;
}
@Override
public VirtualMachineScaleSetImpl withOverProvision(boolean enabled) {
this.inner()
.withOverprovision(enabled);
return this;
}
@Override
public VirtualMachineScaleSetImpl withOverProvisioning() {
return this.withOverProvision(true);
}
@Override
public VirtualMachineScaleSetImpl withoutOverProvisioning() {
return this.withOverProvision(false);
}
@Override
public VirtualMachineScaleSetImpl withCapacity(int capacity) {
this.inner()
.sku().withCapacity(new Long(capacity));
return this;
}
@Override
public VirtualMachineScaleSetImpl withNewStorageAccount(String name) {
StorageAccount.DefinitionStages.WithGroup definitionWithGroup = this.storageManager
.storageAccounts()
.define(name)
.withRegion(this.regionName());
Creatable<StorageAccount> definitionAfterGroup;
if (this.creatableGroup != null) {
definitionAfterGroup = definitionWithGroup.withNewResourceGroup(this.creatableGroup);
} else {
definitionAfterGroup = definitionWithGroup.withExistingResourceGroup(this.resourceGroupName());
}
return withNewStorageAccount(definitionAfterGroup);
}
@Override
public VirtualMachineScaleSetImpl withNewStorageAccount(Creatable<StorageAccount> creatable) {
this.creatableStorageAccountKeys.add(creatable.key());
this.addCreatableDependency(creatable);
return this;
}
@Override
public VirtualMachineScaleSetImpl withExistingStorageAccount(StorageAccount storageAccount) {
this.existingStorageAccountsToAssociate.add(storageAccount);
return this;
}
@Override
public VirtualMachineScaleSetImpl withCustomData(String base64EncodedCustomData) {
this.inner()
.virtualMachineProfile()
.osProfile()
.withCustomData(base64EncodedCustomData);
return this;
}
@Override
public VirtualMachineScaleSetExtensionImpl defineNewExtension(String name) {
return new VirtualMachineScaleSetExtensionImpl(new VirtualMachineScaleSetExtensionInner().withName(name), this);
}
protected VirtualMachineScaleSetImpl withExtension(VirtualMachineScaleSetExtensionImpl extension) {
this.extensions.put(extension.name(), extension);
return this;
}
@Override
public VirtualMachineScaleSetExtensionImpl updateExtension(String name) {
return (VirtualMachineScaleSetExtensionImpl) this.extensions.get(name);
}
@Override
public VirtualMachineScaleSetImpl withoutExtension(String name) {
if (this.extensions.containsKey(name)) {
this.extensions.remove(name);
}
return this;
}
@Override
public boolean isManagedDiskEnabled() {
VirtualMachineScaleSetStorageProfile storageProfile = this.inner().virtualMachineProfile().storageProfile();
if (isOsDiskFromCustomImage(storageProfile)) {
return true;
}
if (isOSDiskFromStoredImage(storageProfile)) {
return false;
}
if (isOSDiskFromPlatformImage(storageProfile)) {
if (this.isUnmanagedDiskSelected) {
return false;
}
}
if (isInCreateMode()) {
return true;
} else {
List<String> vhdContainers = storageProfile
.osDisk()
.vhdContainers();
return vhdContainers == null || vhdContainers.size() == 0;
}
}
@Override
public VirtualMachineScaleSetImpl withUnmanagedDisks() {
this.isUnmanagedDiskSelected = true;
return this;
}
@Override
public VirtualMachineScaleSetImpl withNewDataDisk(int sizeInGB) {
throwIfManagedDiskDisabled(ManagedUnmanagedDiskErrors.VMSS_BOTH_UNMANAGED_AND_MANAGED_DISK_NOT_ALLOWED);
this.managedDataDisks.implicitDisksToAssociate.add(new VirtualMachineScaleSetDataDisk()
.withLun(-1)
.withDiskSizeGB(sizeInGB));
return this;
}
@Override
public VirtualMachineScaleSetImpl withNewDataDisk(int sizeInGB,
int lun,
CachingTypes cachingType) {
throwIfManagedDiskDisabled(ManagedUnmanagedDiskErrors.VMSS_BOTH_UNMANAGED_AND_MANAGED_DISK_NOT_ALLOWED);
this.managedDataDisks.implicitDisksToAssociate.add(new VirtualMachineScaleSetDataDisk()
.withLun(lun)
.withDiskSizeGB(sizeInGB)
.withCaching(cachingType));
return this;
}
@Override
public VirtualMachineScaleSetImpl withNewDataDisk(int sizeInGB,
int lun,
CachingTypes cachingType,
StorageAccountTypes storageAccountType) {
throwIfManagedDiskDisabled(ManagedUnmanagedDiskErrors.VMSS_BOTH_UNMANAGED_AND_MANAGED_DISK_NOT_ALLOWED);
VirtualMachineScaleSetManagedDiskParameters managedDiskParameters = new VirtualMachineScaleSetManagedDiskParameters();
managedDiskParameters.withStorageAccountType(storageAccountType);
this.managedDataDisks.implicitDisksToAssociate.add(new VirtualMachineScaleSetDataDisk()
.withLun(lun)
.withDiskSizeGB(sizeInGB)
.withCaching(cachingType)
.withManagedDisk(managedDiskParameters));
return this;
}
@Override
public VirtualMachineScaleSetImpl withoutDataDisk(int lun) {
if (!isManagedDiskEnabled()) {
return this;
}
this.managedDataDisks.diskLunsToRemove.add(lun);
return this;
}
/* TODO: Broken by change in Azure API behavior
@Override
public VirtualMachineScaleSetImpl withDataDiskUpdated(int lun, int newSizeInGB) {
throwIfManagedDiskDisabled(ManagedUnmanagedDiskErrors.VMSS_NO_MANAGED_DISK_TO_UPDATE);
VirtualMachineScaleSetDataDisk dataDisk = getDataDiskInner(lun);
if (dataDisk == null) {
throw new RuntimeException(String.format("A data disk with lun '%d' not found", lun));
}
dataDisk
.withDiskSizeGB(newSizeInGB);
return this;
}
@Override
public VirtualMachineScaleSetImpl withDataDiskUpdated(int lun, int newSizeInGB, CachingTypes cachingType) {
throwIfManagedDiskDisabled(ManagedUnmanagedDiskErrors.VMSS_NO_MANAGED_DISK_TO_UPDATE);
VirtualMachineScaleSetDataDisk dataDisk = getDataDiskInner(lun);
if (dataDisk == null) {
throw new RuntimeException(String.format("A data disk with lun '%d' not found", lun));
}
dataDisk
.withDiskSizeGB(newSizeInGB)
.withCaching(cachingType);
return this;
}
@Override
public VirtualMachineScaleSetImpl withDataDiskUpdated(int lun, int newSizeInGB, CachingTypes cachingType, StorageAccountTypes storageAccountType) {
throwIfManagedDiskDisabled(ManagedUnmanagedDiskErrors.VMSS_NO_MANAGED_DISK_TO_UPDATE);
VirtualMachineScaleSetDataDisk dataDisk = getDataDiskInner(lun);
if (dataDisk == null) {
throw new RuntimeException(String.format("A data disk with lun '%d' not found", lun));
}
dataDisk
.withDiskSizeGB(newSizeInGB)
.withCaching(cachingType)
.managedDisk()
.withStorageAccountType(storageAccountType);
return this;
}
private VirtualMachineScaleSetDataDisk getDataDiskInner(int lun) {
VirtualMachineScaleSetStorageProfile storageProfile = this
.inner()
.virtualMachineProfile()
.storageProfile();
List<VirtualMachineScaleSetDataDisk> dataDisks = storageProfile
.dataDisks();
if (dataDisks == null) {
return null;
}
for (VirtualMachineScaleSetDataDisk dataDisk : dataDisks) {
if (dataDisk.lun() == lun) {
return dataDisk;
}
}
return null;
}
*/
@Override
public VirtualMachineScaleSetImpl withNewDataDiskFromImage(int imageLun) {
this.managedDataDisks.newDisksFromImage.add(new VirtualMachineScaleSetDataDisk()
.withLun(imageLun));
return this;
}
@Override
public VirtualMachineScaleSetImpl withNewDataDiskFromImage(int imageLun,
int newSizeInGB,
CachingTypes cachingType) {
this.managedDataDisks.newDisksFromImage.add(new VirtualMachineScaleSetDataDisk()
.withLun(imageLun)
.withDiskSizeGB(newSizeInGB)
.withCaching(cachingType));
return this;
}
@Override
public VirtualMachineScaleSetImpl withNewDataDiskFromImage(int imageLun,
int newSizeInGB,
CachingTypes cachingType,
StorageAccountTypes storageAccountType) {
VirtualMachineScaleSetManagedDiskParameters managedDiskParameters = new VirtualMachineScaleSetManagedDiskParameters();
managedDiskParameters.withStorageAccountType(storageAccountType);
this.managedDataDisks.newDisksFromImage.add(new VirtualMachineScaleSetDataDisk()
.withLun(imageLun)
.withDiskSizeGB(newSizeInGB)
.withManagedDisk(managedDiskParameters)
.withCaching(cachingType));
return this;
}
@Override
public VirtualMachineScaleSetImpl withOSDiskStorageAccountType(StorageAccountTypes accountType) {
this.managedDataDisks.setDefaultStorageAccountType(accountType);
return this;
}
@Override
public VirtualMachineScaleSetImpl withDataDiskDefaultCachingType(CachingTypes cachingType) {
this.managedDataDisks.setDefaultCachingType(cachingType);
return this;
}
@Override
public VirtualMachineScaleSetImpl withDataDiskDefaultStorageAccountType(StorageAccountTypes storageAccountType) {
this.managedDataDisks.setDefaultStorageAccountType(storageAccountType);
return this;
}
// Create Update specific methods
//
@Override
protected void beforeCreating() {
if (this.extensions.size() > 0) {
this.inner()
.virtualMachineProfile()
.withExtensionProfile(new VirtualMachineScaleSetExtensionProfile())
.extensionProfile()
.withExtensions(innersFromWrappers(this.extensions.values()));
}
}
@Override
protected Observable<VirtualMachineScaleSetInner> createInner() {
if (isInCreateMode()) {
this.setOSProfileDefaults();
this.setOSDiskDefault();
}
this.setPrimaryIpConfigurationSubnet();
this.setPrimaryIpConfigurationBackendsAndInboundNatPools();
if (isManagedDiskEnabled()) {
this.managedDataDisks.setDataDisksDefaults();
} else {
List<VirtualMachineScaleSetDataDisk> dataDisks = this.inner()
.virtualMachineProfile()
.storageProfile()
.dataDisks();
VirtualMachineScaleSetUnmanagedDataDiskImpl.setDataDisksDefaults(dataDisks, this.name());
}
final VirtualMachineScaleSetsInner client = this.manager().inner().virtualMachineScaleSets();
return this.handleOSDiskContainersAsync()
.flatMap(new Func1<Void, Observable<VirtualMachineScaleSetInner>>() {
@Override
public Observable<VirtualMachineScaleSetInner> call(Void aVoid) {
return client.createOrUpdateAsync(resourceGroupName(), name(), inner());
}
});
}
@Override
protected void afterCreating() {
this.clearCachedProperties();
this.initializeChildrenFromInner();
}
@Override
public Observable<VirtualMachineScaleSet> refreshAsync() {
return super.refreshAsync().map(new Func1<VirtualMachineScaleSet, VirtualMachineScaleSet>() {
@Override
public VirtualMachineScaleSet call(VirtualMachineScaleSet virtualMachineScaleSet) {
VirtualMachineScaleSetImpl impl = (VirtualMachineScaleSetImpl) virtualMachineScaleSet;
impl.clearCachedProperties();
impl.initializeChildrenFromInner();
return impl;
}
});
}
@Override
protected Observable<VirtualMachineScaleSetInner> getInnerAsync() {
return this.manager().inner().virtualMachineScaleSets().getByResourceGroupAsync(this.resourceGroupName(), this.name());
}
// Helpers
//
private boolean isInUpdateMode() {
return !this.isInCreateMode();
}
private void setOSProfileDefaults() {
if (isInUpdateMode()) {
return;
}
if (this.inner().sku().capacity() == null) {
this.withCapacity(2);
}
if (this.inner().upgradePolicy() == null
|| this.inner().upgradePolicy().mode() == null) {
this.inner()
.withUpgradePolicy(new UpgradePolicy()
.withMode(UpgradeMode.AUTOMATIC));
}
VirtualMachineScaleSetOSProfile osProfile = this.inner()
.virtualMachineProfile()
.osProfile();
VirtualMachineScaleSetOSDisk osDisk = this.inner().virtualMachineProfile().storageProfile().osDisk();
if (isOSDiskFromImage(osDisk)) {
// ODDisk CreateOption: FROM_IMAGE
//
if (this.osType() == OperatingSystemTypes.LINUX || this.isMarketplaceLinuxImage) {
if (osProfile.linuxConfiguration() == null) {
osProfile.withLinuxConfiguration(new LinuxConfiguration());
}
osProfile
.linuxConfiguration()
.withDisablePasswordAuthentication(osProfile.adminPassword() == null);
}
if (this.computerNamePrefix() == null) {
// VM name cannot contain only numeric values and cannot exceed 15 chars
if (this.name().matches("[0-9]+")) {
withComputerNamePrefix(this.namer.randomName("vmss-vm", 12));
} else if (this.name().length() <= 12) {
withComputerNamePrefix(this.name() + "-vm");
} else {
withComputerNamePrefix(this.namer.randomName("vmss-vm", 12));
}
}
} else {
// NOP [ODDisk CreateOption: ATTACH, ATTACH is not supported for VMSS]
this.inner()
.virtualMachineProfile()
.withOsProfile(null);
}
}
private void setOSDiskDefault() {
if (isInUpdateMode()) {
return;
}
VirtualMachineScaleSetStorageProfile storageProfile = this.inner().virtualMachineProfile().storageProfile();
VirtualMachineScaleSetOSDisk osDisk = storageProfile.osDisk();
if (isOSDiskFromImage(osDisk)) {
// ODDisk CreateOption: FROM_IMAGE
//
if (isManagedDiskEnabled()) {
// Note:
// Managed disk
// Supported: PlatformImage and CustomImage
// UnSupported: StoredImage
//
if (osDisk.managedDisk() == null) {
osDisk.withManagedDisk(new VirtualMachineScaleSetManagedDiskParameters());
}
if (osDisk.managedDisk().storageAccountType() == null) {
osDisk.managedDisk()
.withStorageAccountType(StorageAccountTypes.STANDARD_LRS);
}
osDisk.withVhdContainers(null);
// We won't set osDisk.name() explicitly for managed disk, if it is null CRP generates unique
// name for the disk resource within the resource group.
} else {
// Note:
// Native (un-managed) disk
// Supported: PlatformImage and StoredImage
// UnSupported: CustomImage
//
osDisk.withManagedDisk(null);
if (osDisk.name() == null) {
withOSDiskName(this.name() + "-os-disk");
}
}
} else {
// NOP [ODDisk CreateOption: ATTACH, ATTACH is not supported for VMSS]
}
if (this.osDiskCachingType() == null) {
withOSDiskCaching(CachingTypes.READ_WRITE);
}
}
private Observable<Void> handleOSDiskContainersAsync() {
final VirtualMachineScaleSetStorageProfile storageProfile = inner()
.virtualMachineProfile()
.storageProfile();
if (isManagedDiskEnabled()) {
storageProfile.osDisk()
.withVhdContainers(null);
return Observable.just(null);
}
if (isOSDiskFromStoredImage(storageProfile)) {
// There is a restriction currently that virtual machine's disk cannot be stored in multiple storage
// accounts if scale set is based on stored image. Remove this check once azure start supporting it.
//
storageProfile.osDisk()
.vhdContainers()
.clear();
return Observable.just(null);
}
if (this.isInCreateMode()
&& this.creatableStorageAccountKeys.isEmpty()
&& this.existingStorageAccountsToAssociate.isEmpty()) {
// If storage account(s) are not explicitly asked to create then create one implicitly
//
return Utils.<StorageAccount>rootResource(this.storageManager.storageAccounts()
.define(this.namer.randomName("stg", 24).replace("-", ""))
.withRegion(this.regionName())
.withExistingResourceGroup(this.resourceGroupName())
.createAsync())
.map(new Func1<StorageAccount, Void>() {
@Override
public Void call(StorageAccount storageAccount) {
String containerName = vhdContainerName;
if (containerName == null) {
containerName = "vhds";
}
storageProfile.osDisk()
.vhdContainers()
.add(mergePath(storageAccount.endPoints().primary().blob(), containerName));
vhdContainerName = null;
creatableStorageAccountKeys.clear();
existingStorageAccountsToAssociate.clear();
return null;
}
});
} else {
String containerName = this.vhdContainerName;
if (containerName == null) {
for (String containerUrl : storageProfile.osDisk().vhdContainers()) {
containerName = containerUrl.substring(containerUrl.lastIndexOf("/") + 1);
break;
}
}
if (containerName == null) {
containerName = "vhds";
}
for (String storageAccountKey : this.creatableStorageAccountKeys) {
StorageAccount storageAccount = (StorageAccount) createdResource(storageAccountKey);
storageProfile.osDisk()
.vhdContainers()
.add(mergePath(storageAccount.endPoints().primary().blob(), containerName));
}
for (StorageAccount storageAccount : this.existingStorageAccountsToAssociate) {
storageProfile.osDisk()
.vhdContainers()
.add(mergePath(storageAccount.endPoints().primary().blob(), containerName));
}
this.vhdContainerName = null;
this.creatableStorageAccountKeys.clear();
this.existingStorageAccountsToAssociate.clear();
return Observable.just(null);
}
}
private void setPrimaryIpConfigurationSubnet() {
if (isInUpdateMode()) {
return;
}
VirtualMachineScaleSetIPConfigurationInner ipConfig = this.primaryNicDefaultIPConfiguration();
ipConfig.withSubnet(new ApiEntityReference().withId(this.existingPrimaryNetworkSubnetNameToAssociate));
this.existingPrimaryNetworkSubnetNameToAssociate = null;
}
private void setPrimaryIpConfigurationBackendsAndInboundNatPools() {
if (isInCreateMode()) {
return;
}
try {
this.loadCurrentPrimaryLoadBalancersIfAvailable();
} catch (IOException ioException) {
throw new RuntimeException(ioException);
}
VirtualMachineScaleSetIPConfigurationInner primaryIpConfig = primaryNicDefaultIPConfiguration();
if (this.primaryInternetFacingLoadBalancer != null) {
removeBackendsFromIpConfiguration(this.primaryInternetFacingLoadBalancer.id(),
primaryIpConfig,
this.primaryInternetFacingLBBackendsToRemoveOnUpdate.toArray(new String[0]));
associateBackEndsToIpConfiguration(primaryInternetFacingLoadBalancer.id(),
primaryIpConfig,
this.primaryInternetFacingLBBackendsToAddOnUpdate.toArray(new String[0]));
removeInboundNatPoolsFromIpConfiguration(this.primaryInternetFacingLoadBalancer.id(),
primaryIpConfig,
this.primaryInternetFacingLBInboundNatPoolsToRemoveOnUpdate.toArray(new String[0]));
associateInboundNATPoolsToIpConfiguration(primaryInternetFacingLoadBalancer.id(),
primaryIpConfig,
this.primaryInternetFacingLBInboundNatPoolsToAddOnUpdate.toArray(new String[0]));
}
if (this.primaryInternalLoadBalancer != null) {
removeBackendsFromIpConfiguration(this.primaryInternalLoadBalancer.id(),
primaryIpConfig,
this.primaryInternalLBBackendsToRemoveOnUpdate.toArray(new String[0]));
associateBackEndsToIpConfiguration(primaryInternalLoadBalancer.id(),
primaryIpConfig,
this.primaryInternalLBBackendsToAddOnUpdate.toArray(new String[0]));
removeInboundNatPoolsFromIpConfiguration(this.primaryInternalLoadBalancer.id(),
primaryIpConfig,
this.primaryInternalLBInboundNatPoolsToRemoveOnUpdate.toArray(new String[0]));
associateInboundNATPoolsToIpConfiguration(primaryInternalLoadBalancer.id(),
primaryIpConfig,
this.primaryInternalLBInboundNatPoolsToAddOnUpdate.toArray(new String[0]));
}
if (this.removePrimaryInternetFacingLoadBalancerOnUpdate) {
if (this.primaryInternetFacingLoadBalancer != null) {
removeLoadBalancerAssociationFromIpConfiguration(this.primaryInternetFacingLoadBalancer, primaryIpConfig);
}
}
if (this.removePrimaryInternalLoadBalancerOnUpdate) {
if (this.primaryInternalLoadBalancer != null) {
removeLoadBalancerAssociationFromIpConfiguration(this.primaryInternalLoadBalancer, primaryIpConfig);
}
}
if (this.primaryInternetFacingLoadBalancerToAttachOnUpdate != null) {
if (this.primaryInternetFacingLoadBalancer != null) {
removeLoadBalancerAssociationFromIpConfiguration(this.primaryInternetFacingLoadBalancer, primaryIpConfig);
}
associateLoadBalancerToIpConfiguration(this.primaryInternetFacingLoadBalancerToAttachOnUpdate, primaryIpConfig);
if (!this.primaryInternetFacingLBBackendsToAddOnUpdate.isEmpty()) {
removeAllBackendAssociationFromIpConfiguration(this.primaryInternetFacingLoadBalancerToAttachOnUpdate, primaryIpConfig);
associateBackEndsToIpConfiguration(this.primaryInternetFacingLoadBalancerToAttachOnUpdate.id(),
primaryIpConfig,
this.primaryInternetFacingLBBackendsToAddOnUpdate.toArray(new String[0]));
}
if (!this.primaryInternetFacingLBInboundNatPoolsToAddOnUpdate.isEmpty()) {
removeAllInboundNatPoolAssociationFromIpConfiguration(this.primaryInternetFacingLoadBalancerToAttachOnUpdate, primaryIpConfig);
associateInboundNATPoolsToIpConfiguration(this.primaryInternetFacingLoadBalancerToAttachOnUpdate.id(),
primaryIpConfig,
this.primaryInternetFacingLBInboundNatPoolsToAddOnUpdate.toArray(new String[0]));
}
}
if (this.primaryInternalLoadBalancerToAttachOnUpdate != null) {
if (this.primaryInternalLoadBalancer != null) {
removeLoadBalancerAssociationFromIpConfiguration(this.primaryInternalLoadBalancer, primaryIpConfig);
}
associateLoadBalancerToIpConfiguration(this.primaryInternalLoadBalancerToAttachOnUpdate, primaryIpConfig);
if (!this.primaryInternalLBBackendsToAddOnUpdate.isEmpty()) {
removeAllBackendAssociationFromIpConfiguration(this.primaryInternalLoadBalancerToAttachOnUpdate, primaryIpConfig);
associateBackEndsToIpConfiguration(this.primaryInternalLoadBalancerToAttachOnUpdate.id(),
primaryIpConfig,
this.primaryInternalLBBackendsToAddOnUpdate.toArray(new String[0]));
}
if (!this.primaryInternalLBInboundNatPoolsToAddOnUpdate.isEmpty()) {
removeAllInboundNatPoolAssociationFromIpConfiguration(this.primaryInternalLoadBalancerToAttachOnUpdate, primaryIpConfig);
associateInboundNATPoolsToIpConfiguration(this.primaryInternalLoadBalancerToAttachOnUpdate.id(),
primaryIpConfig,
this.primaryInternalLBInboundNatPoolsToAddOnUpdate.toArray(new String[0]));
}
}
this.removePrimaryInternetFacingLoadBalancerOnUpdate = false;
this.removePrimaryInternalLoadBalancerOnUpdate = false;
this.primaryInternetFacingLoadBalancerToAttachOnUpdate = null;
this.primaryInternalLoadBalancerToAttachOnUpdate = null;
this.primaryInternetFacingLBBackendsToRemoveOnUpdate.clear();
this.primaryInternetFacingLBInboundNatPoolsToRemoveOnUpdate.clear();
this.primaryInternalLBBackendsToRemoveOnUpdate.clear();
this.primaryInternalLBInboundNatPoolsToRemoveOnUpdate.clear();
this.primaryInternetFacingLBBackendsToAddOnUpdate.clear();
this.primaryInternetFacingLBInboundNatPoolsToAddOnUpdate.clear();
this.primaryInternalLBBackendsToAddOnUpdate.clear();
this.primaryInternalLBInboundNatPoolsToAddOnUpdate.clear();
}
private void clearCachedProperties() {
this.primaryInternetFacingLoadBalancer = null;
this.primaryInternalLoadBalancer = null;
}
private void loadCurrentPrimaryLoadBalancersIfAvailable() throws IOException {
if (this.primaryInternetFacingLoadBalancer != null && this.primaryInternalLoadBalancer != null) {
return;
}
String firstLoadBalancerId = null;
VirtualMachineScaleSetIPConfigurationInner ipConfig = primaryNicDefaultIPConfiguration();
if (!ipConfig.loadBalancerBackendAddressPools().isEmpty()) {
firstLoadBalancerId = ResourceUtils
.parentResourceIdFromResourceId(ipConfig.loadBalancerBackendAddressPools().get(0).id());
}
if (firstLoadBalancerId == null && !ipConfig.loadBalancerInboundNatPools().isEmpty()) {
firstLoadBalancerId = ResourceUtils
.parentResourceIdFromResourceId(ipConfig.loadBalancerInboundNatPools().get(0).id());
}
if (firstLoadBalancerId == null) {
return;
}
LoadBalancer loadBalancer1 = this.networkManager
.loadBalancers()
.getById(firstLoadBalancerId);
if (loadBalancer1.publicIPAddressIds() != null && loadBalancer1.publicIPAddressIds().size() > 0) {
this.primaryInternetFacingLoadBalancer = loadBalancer1;
} else {
this.primaryInternalLoadBalancer = loadBalancer1;
}
String secondLoadBalancerId = null;
for (SubResource subResource: ipConfig.loadBalancerBackendAddressPools()) {
if (!subResource.id().toLowerCase().startsWith(firstLoadBalancerId.toLowerCase())) {
secondLoadBalancerId = ResourceUtils
.parentResourceIdFromResourceId(subResource.id());
break;
}
}
if (secondLoadBalancerId == null) {
for (SubResource subResource: ipConfig.loadBalancerInboundNatPools()) {
if (!subResource.id().toLowerCase().startsWith(firstLoadBalancerId.toLowerCase())) {
secondLoadBalancerId = ResourceUtils
.parentResourceIdFromResourceId(subResource.id());
break;
}
}
}
if (secondLoadBalancerId == null) {
return;
}
LoadBalancer loadBalancer2 = this.networkManager
.loadBalancers()
.getById(secondLoadBalancerId);
if (loadBalancer2.publicIPAddressIds() != null && loadBalancer2.publicIPAddressIds().size() > 0) {
this.primaryInternetFacingLoadBalancer = loadBalancer2;
} else {
this.primaryInternalLoadBalancer = loadBalancer2;
}
}
private VirtualMachineScaleSetIPConfigurationInner primaryNicDefaultIPConfiguration() {
List<VirtualMachineScaleSetNetworkConfigurationInner> nicConfigurations = this.inner()
.virtualMachineProfile()
.networkProfile()
.networkInterfaceConfigurations();
for (VirtualMachineScaleSetNetworkConfigurationInner nicConfiguration : nicConfigurations) {
if (nicConfiguration.primary()) {
if (nicConfiguration.ipConfigurations().size() > 0) {
VirtualMachineScaleSetIPConfigurationInner ipConfig = nicConfiguration.ipConfigurations().get(0);
if (ipConfig.loadBalancerBackendAddressPools() == null) {
ipConfig.withLoadBalancerBackendAddressPools(new ArrayList<SubResource>());
}
if (ipConfig.loadBalancerInboundNatPools() == null) {
ipConfig.withLoadBalancerInboundNatPools(new ArrayList<SubResource>());
}
return ipConfig;
}
}
}
throw new RuntimeException("Could not find the primary nic configuration or an IP configuration in it");
}
private static void associateBackEndsToIpConfiguration(String loadBalancerId,
VirtualMachineScaleSetIPConfigurationInner ipConfig,
String... backendNames) {
List<SubResource> backendSubResourcesToAssociate = new ArrayList<>();
for (String backendName : backendNames) {
String backendPoolId = mergePath(loadBalancerId, "backendAddressPools", backendName);
boolean found = false;
for (SubResource subResource : ipConfig.loadBalancerBackendAddressPools()) {
if (subResource.id().equalsIgnoreCase(backendPoolId)) {
found = true;
break;
}
}
if (!found) {
backendSubResourcesToAssociate.add(new SubResource().withId(backendPoolId));
}
}
for (SubResource backendSubResource : backendSubResourcesToAssociate) {
ipConfig.loadBalancerBackendAddressPools().add(backendSubResource);
}
}
private static void associateInboundNATPoolsToIpConfiguration(String loadBalancerId,
VirtualMachineScaleSetIPConfigurationInner ipConfig,
String... inboundNatPools) {
List<SubResource> inboundNatPoolSubResourcesToAssociate = new ArrayList<>();
for (String inboundNatPool : inboundNatPools) {
String inboundNatPoolId = mergePath(loadBalancerId, "inboundNatPools", inboundNatPool);
boolean found = false;
for (SubResource subResource : ipConfig.loadBalancerInboundNatPools()) {
if (subResource.id().equalsIgnoreCase(inboundNatPoolId)) {
found = true;
break;
}
}
if (!found) {
inboundNatPoolSubResourcesToAssociate.add(new SubResource().withId(inboundNatPoolId));
}
}
for (SubResource backendSubResource : inboundNatPoolSubResourcesToAssociate) {
ipConfig.loadBalancerInboundNatPools().add(backendSubResource);
}
}
private static Map<String, LoadBalancerBackend> getBackendsAssociatedWithIpConfiguration(LoadBalancer loadBalancer,
VirtualMachineScaleSetIPConfigurationInner ipConfig) {
String loadBalancerId = loadBalancer.id();
Map<String, LoadBalancerBackend> attachedBackends = new HashMap<>();
Map<String, LoadBalancerBackend> lbBackends = loadBalancer.backends();
for (LoadBalancerBackend lbBackend : lbBackends.values()) {
String backendId = mergePath(loadBalancerId, "backendAddressPools", lbBackend.name());
for (SubResource subResource : ipConfig.loadBalancerBackendAddressPools()) {
if (subResource.id().equalsIgnoreCase(backendId)) {
attachedBackends.put(lbBackend.name(), lbBackend);
}
}
}
return attachedBackends;
}
private static Map<String, LoadBalancerInboundNatPool> getInboundNatPoolsAssociatedWithIpConfiguration(LoadBalancer loadBalancer,
VirtualMachineScaleSetIPConfigurationInner ipConfig) {
String loadBalancerId = loadBalancer.id();
Map<String, LoadBalancerInboundNatPool> attachedInboundNatPools = new HashMap<>();
Map<String, LoadBalancerInboundNatPool> lbInboundNatPools = loadBalancer.inboundNatPools();
for (LoadBalancerInboundNatPool lbInboundNatPool : lbInboundNatPools.values()) {
String inboundNatPoolId = mergePath(loadBalancerId, "inboundNatPools", lbInboundNatPool.name());
for (SubResource subResource : ipConfig.loadBalancerInboundNatPools()) {
if (subResource.id().equalsIgnoreCase(inboundNatPoolId)) {
attachedInboundNatPools.put(lbInboundNatPool.name(), lbInboundNatPool);
}
}
}
return attachedInboundNatPools;
}
private static void associateLoadBalancerToIpConfiguration(LoadBalancer loadBalancer,
VirtualMachineScaleSetIPConfigurationInner ipConfig) {
Collection<LoadBalancerBackend> backends = loadBalancer.backends().values();
String[] backendNames = new String[backends.size()];
int i = 0;
for (LoadBalancerBackend backend : backends) {
backendNames[i] = backend.name();
i++;
}
associateBackEndsToIpConfiguration(loadBalancer.id(),
ipConfig,
backendNames);
Collection<LoadBalancerInboundNatPool> inboundNatPools = loadBalancer.inboundNatPools().values();
String[] natPoolNames = new String[inboundNatPools.size()];
i = 0;
for (LoadBalancerInboundNatPool inboundNatPool : inboundNatPools) {
natPoolNames[i] = inboundNatPool.name();
i++;
}
associateInboundNATPoolsToIpConfiguration(loadBalancer.id(),
ipConfig,
natPoolNames);
}
private static void removeLoadBalancerAssociationFromIpConfiguration(LoadBalancer loadBalancer,
VirtualMachineScaleSetIPConfigurationInner ipConfig) {
removeAllBackendAssociationFromIpConfiguration(loadBalancer, ipConfig);
removeAllInboundNatPoolAssociationFromIpConfiguration(loadBalancer, ipConfig);
}
private static void removeAllBackendAssociationFromIpConfiguration(LoadBalancer loadBalancer,
VirtualMachineScaleSetIPConfigurationInner ipConfig) {
List<SubResource> toRemove = new ArrayList<>();
for (SubResource subResource : ipConfig.loadBalancerBackendAddressPools()) {
if (subResource.id().toLowerCase().startsWith(loadBalancer.id().toLowerCase() + "/")) {
toRemove.add(subResource);
}
}
for (SubResource subResource : toRemove) {
ipConfig.loadBalancerBackendAddressPools().remove(subResource);
}
}
private static void removeAllInboundNatPoolAssociationFromIpConfiguration(LoadBalancer loadBalancer,
VirtualMachineScaleSetIPConfigurationInner ipConfig) {
List<SubResource> toRemove = new ArrayList<>();
for (SubResource subResource : ipConfig.loadBalancerInboundNatPools()) {
if (subResource.id().toLowerCase().startsWith(loadBalancer.id().toLowerCase() + "/")) {
toRemove.add(subResource);
}
}
for (SubResource subResource : toRemove) {
ipConfig.loadBalancerInboundNatPools().remove(subResource);
}
}
private static void removeBackendsFromIpConfiguration(String loadBalancerId,
VirtualMachineScaleSetIPConfigurationInner ipConfig,
String... backendNames) {
List<SubResource> toRemove = new ArrayList<>();
for (String backendName : backendNames) {
String backendPoolId = mergePath(loadBalancerId, "backendAddressPools", backendName);
for (SubResource subResource : ipConfig.loadBalancerBackendAddressPools()) {
if (subResource.id().equalsIgnoreCase(backendPoolId)) {
toRemove.add(subResource);
break;
}
}
}
for (SubResource subResource : toRemove) {
ipConfig.loadBalancerBackendAddressPools().remove(subResource);
}
}
private static void removeInboundNatPoolsFromIpConfiguration(String loadBalancerId,
VirtualMachineScaleSetIPConfigurationInner ipConfig,
String... inboundNatPoolNames) {
List<SubResource> toRemove = new ArrayList<>();
for (String natPoolName : inboundNatPoolNames) {
String inboundNatPoolId = mergePath(loadBalancerId, "inboundNatPools", natPoolName);
for (SubResource subResource : ipConfig.loadBalancerInboundNatPools()) {
if (subResource.id().equalsIgnoreCase(inboundNatPoolId)) {
toRemove.add(subResource);
break;
}
}
}
for (SubResource subResource : toRemove) {
ipConfig.loadBalancerInboundNatPools().remove(subResource);
}
}
private static <T> void addToList(List<T> list, T...items) {
for (T item : items) {
list.add(item);
}
}
private static String mergePath(String... segments) {
StringBuilder builder = new StringBuilder();
for (String segment : segments) {
while (segment.length() > 1 && segment.endsWith("/")) {
segment = segment.substring(0, segment.length() - 1);
}
if (segment.length() > 0) {
builder.append(segment);
builder.append("/");
}
}
String merged = builder.toString();
if (merged.endsWith("/")) {
merged = merged.substring(0, merged.length() - 1);
}
return merged;
}
protected VirtualMachineScaleSetImpl withUnmanagedDataDisk(VirtualMachineScaleSetUnmanagedDataDiskImpl unmanagedDisk) {
if (this.inner()
.virtualMachineProfile()
.storageProfile()
.dataDisks() == null) {
this.inner()
.virtualMachineProfile()
.storageProfile()
.withDataDisks(new ArrayList<VirtualMachineScaleSetDataDisk>());
}
List<VirtualMachineScaleSetDataDisk> dataDisks = this.inner()
.virtualMachineProfile()
.storageProfile()
.dataDisks();
dataDisks.add(unmanagedDisk.inner());
return this;
}
/**
* Checks whether the OS disk is based on an image (image from PIR or custom image [captured, bringYourOwnFeature]).
*
* @param osDisk the osDisk value in the storage profile
* @return true if the OS disk is configured to use image from PIR or custom image
*/
private boolean isOSDiskFromImage(VirtualMachineScaleSetOSDisk osDisk) {
return osDisk.createOption() == DiskCreateOptionTypes.FROM_IMAGE;
}
/**
* Checks whether the OS disk is based on a CustomImage.
* <p>
* A custom image is represented by {@link com.microsoft.azure.management.compute.VirtualMachineCustomImage}.
*
* @param storageProfile the storage profile
* @return true if the OS disk is configured to be based on custom image.
*/
private boolean isOsDiskFromCustomImage(VirtualMachineScaleSetStorageProfile storageProfile) {
ImageReferenceInner imageReference = storageProfile.imageReference();
return isOSDiskFromImage(storageProfile.osDisk())
&& imageReference != null
&& imageReference.id() != null;
}
/**
* Checks whether the OS disk is based on an platform image (image in PIR).
*
* @param storageProfile the storage profile
* @return true if the OS disk is configured to be based on platform image.
*/
private boolean isOSDiskFromPlatformImage(VirtualMachineScaleSetStorageProfile storageProfile) {
ImageReferenceInner imageReference = storageProfile.imageReference();
return isOSDiskFromImage(storageProfile.osDisk())
&& imageReference != null
&& imageReference.publisher() != null
&& imageReference.offer() != null
&& imageReference.sku() != null
&& imageReference.version() != null;
}
/**
* Checks whether the OS disk is based on a stored image ('captured' or 'bring your own feature').
*
* @param storageProfile the storage profile
* @return true if the OS disk is configured to use custom image ('captured' or 'bring your own feature')
*/
private boolean isOSDiskFromStoredImage(VirtualMachineScaleSetStorageProfile storageProfile) {
VirtualMachineScaleSetOSDisk osDisk = storageProfile.osDisk();
return isOSDiskFromImage(osDisk)
&& osDisk.image() != null
&& osDisk.image().uri() != null;
}
/* TODO Unused
private void throwIfManagedDiskEnabled(String message) {
if (this.isManagedDiskEnabled()) {
throw new UnsupportedOperationException(message);
}
}*/
private void throwIfManagedDiskDisabled(String message) {
if (!this.isManagedDiskEnabled()) {
throw new UnsupportedOperationException(message);
}
}
/**
* Class to manage Data Disk collection.
*/
private class ManagedDataDiskCollection {
private final List<VirtualMachineScaleSetDataDisk> implicitDisksToAssociate = new ArrayList<>();
private final List<Integer> diskLunsToRemove = new ArrayList<>();
private final List<VirtualMachineScaleSetDataDisk> newDisksFromImage = new ArrayList<>();
private final VirtualMachineScaleSetImpl vmss;
private CachingTypes defaultCachingType;
private StorageAccountTypes defaultStorageAccountType;
ManagedDataDiskCollection(VirtualMachineScaleSetImpl vmss) {
this.vmss = vmss;
}
void setDefaultCachingType(CachingTypes cachingType) {
this.defaultCachingType = cachingType;
}
void setDefaultStorageAccountType(StorageAccountTypes defaultStorageAccountType) {
this.defaultStorageAccountType = defaultStorageAccountType;
}
void setDataDisksDefaults() {
VirtualMachineScaleSetStorageProfile storageProfile = this.vmss
.inner()
.virtualMachineProfile()
.storageProfile();
if (isPending()) {
if (storageProfile.dataDisks() == null) {
storageProfile.withDataDisks(new ArrayList<VirtualMachineScaleSetDataDisk>());
}
List<VirtualMachineScaleSetDataDisk> dataDisks = storageProfile.dataDisks();
final List<Integer> usedLuns = new ArrayList<>();
// Get all used luns
//
for (VirtualMachineScaleSetDataDisk dataDisk : dataDisks) {
if (dataDisk.lun() != -1) {
usedLuns.add(dataDisk.lun());
}
}
for (VirtualMachineScaleSetDataDisk dataDisk : this.implicitDisksToAssociate) {
if (dataDisk.lun() != -1) {
usedLuns.add(dataDisk.lun());
}
}
for (VirtualMachineScaleSetDataDisk dataDisk : this.newDisksFromImage) {
if (dataDisk.lun() != -1) {
usedLuns.add(dataDisk.lun());
}
}
// Func to get the next available lun
//
Func0<Integer> nextLun = new Func0<Integer>() {
@Override
public Integer call() {
Integer lun = 0;
while (usedLuns.contains(lun)) {
lun++;
}
usedLuns.add(lun);
return lun;
}
};
setImplicitDataDisks(nextLun);
setImageBasedDataDisks();
removeDataDisks();
}
if (storageProfile.dataDisks() != null
&& storageProfile.dataDisks().size() == 0) {
if (vmss.isInCreateMode()) {
// If there is no data disks at all, then setting it to null rather than [] is necessary.
// This is for take advantage of CRP's implicit creation of the data disks if the image has
// more than one data disk image(s).
//
storageProfile.withDataDisks(null);
}
}
this.clear();
}
private void clear() {
implicitDisksToAssociate.clear();
diskLunsToRemove.clear();
newDisksFromImage.clear();
}
private boolean isPending() {
return implicitDisksToAssociate.size() > 0
|| diskLunsToRemove.size() > 0
|| newDisksFromImage.size() > 0;
}
private void setImplicitDataDisks(Func0<Integer> nextLun) {
VirtualMachineScaleSetStorageProfile storageProfile = this.vmss
.inner()
.virtualMachineProfile()
.storageProfile();
List<VirtualMachineScaleSetDataDisk> dataDisks = storageProfile.dataDisks();
for (VirtualMachineScaleSetDataDisk dataDisk : this.implicitDisksToAssociate) {
dataDisk.withCreateOption(DiskCreateOptionTypes.EMPTY);
if (dataDisk.lun() == -1) {
dataDisk.withLun(nextLun.call());
}
if (dataDisk.managedDisk() == null) {
dataDisk.withManagedDisk(new VirtualMachineScaleSetManagedDiskParameters());
}
if (dataDisk.caching() == null) {
dataDisk.withCaching(getDefaultCachingType());
}
if (dataDisk.managedDisk().storageAccountType() == null) {
dataDisk.managedDisk().withStorageAccountType(getDefaultStorageAccountType());
}
dataDisk.withName(null);
dataDisks.add(dataDisk);
}
}
private void setImageBasedDataDisks() {
VirtualMachineScaleSetStorageProfile storageProfile = this.vmss
.inner()
.virtualMachineProfile()
.storageProfile();
List<VirtualMachineScaleSetDataDisk> dataDisks = storageProfile.dataDisks();
for (VirtualMachineScaleSetDataDisk dataDisk : this.newDisksFromImage) {
dataDisk.withCreateOption(DiskCreateOptionTypes.FROM_IMAGE);
// Don't set default storage account type for the disk, either user has to specify it explicitly or let
// CRP pick it from the image
dataDisk.withName(null);
dataDisks.add(dataDisk);
}
}
private void removeDataDisks() {
VirtualMachineScaleSetStorageProfile storageProfile = this.vmss
.inner()
.virtualMachineProfile()
.storageProfile();
List<VirtualMachineScaleSetDataDisk> dataDisks = storageProfile.dataDisks();
for (Integer lun : this.diskLunsToRemove) {
int indexToRemove = 0;
for (VirtualMachineScaleSetDataDisk dataDisk : dataDisks) {
if (dataDisk.lun() == lun) {
dataDisks.remove(indexToRemove);
break;
}
indexToRemove++;
}
}
}
private CachingTypes getDefaultCachingType() {
if (defaultCachingType == null) {
return CachingTypes.READ_WRITE;
}
return defaultCachingType;
}
private StorageAccountTypes getDefaultStorageAccountType() {
if (defaultStorageAccountType == null) {
return StorageAccountTypes.STANDARD_LRS;
}
return defaultStorageAccountType;
}
}
}