org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.java Source code

Java tutorial

Introduction

Here is the source code for org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jclouds.azurecompute.arm.compute;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.builder;
import static com.google.common.collect.ImmutableList.of;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import static org.jclouds.azurecompute.arm.compute.domain.LocationAndName.fromSlashEncoded;
import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractName;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.PublicIpAvailablePredicateFactory;
import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.compute.options.IpOptions;
import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources;
import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
import org.jclouds.azurecompute.arm.domain.CreationData;
import org.jclouds.azurecompute.arm.domain.DataDisk;
import org.jclouds.azurecompute.arm.domain.HardwareProfile;
import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.ImageReference;
import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
import org.jclouds.azurecompute.arm.domain.Location;
import org.jclouds.azurecompute.arm.domain.ManagedDiskParameters;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.domain.NetworkProfile;
import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;
import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface.NetworkInterfaceProperties;
import org.jclouds.azurecompute.arm.domain.OSDisk;
import org.jclouds.azurecompute.arm.domain.OSProfile;
import org.jclouds.azurecompute.arm.domain.Offer;
import org.jclouds.azurecompute.arm.domain.Plan;
import org.jclouds.azurecompute.arm.domain.Provisionable;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
import org.jclouds.azurecompute.arm.domain.SKU;
import org.jclouds.azurecompute.arm.domain.StorageAccountType;
import org.jclouds.azurecompute.arm.domain.StorageProfile;
import org.jclouds.azurecompute.arm.domain.VMHardware;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VMSize;
import org.jclouds.azurecompute.arm.domain.Version;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
import org.jclouds.azurecompute.arm.features.OSImageApi;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.location.Region;
import org.jclouds.logging.Logger;

import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

/**
 * Defines the connection between the {@link AzureComputeApi} implementation and
 * the jclouds {@link org.jclouds.compute.ComputeService}.
 */
@Singleton
public class AzureComputeServiceAdapter
        implements ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location> {

    public static final String GROUP_KEY = "jclouds_group";
    public static final String AUTOGENERATED_IP_KEY = "jclouds-autogenerated";

    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;

    private final CleanupResources cleanupResources;
    private final AzureComputeApi api;
    private final List<String> imagePublishers;
    private final Supplier<Set<String>> regionIds;
    private final PublicIpAvailablePredicateFactory publicIpAvailable;
    private final CustomImageToVMImage customImagetoVmImage;
    private final GroupNamingConvention namingConvention;
    private Predicate<Supplier<Provisionable>> resourceAvailable;

    @Inject
    AzureComputeServiceAdapter(final AzureComputeApi api, @Named(IMAGE_PUBLISHERS) String imagePublishers,
            CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
            PublicIpAvailablePredicateFactory publicIpAvailable, CustomImageToVMImage customImagetoVmImage,
            GroupNamingConvention.Factory namingConvention, Predicate<Supplier<Provisionable>> resourceAvailable) {
        this.api = api;
        this.imagePublishers = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(imagePublishers);
        this.cleanupResources = cleanupResources;
        this.regionIds = regionIds;
        this.publicIpAvailable = publicIpAvailable;
        this.customImagetoVmImage = customImagetoVmImage;
        this.namingConvention = namingConvention.create();
        this.resourceAvailable = resourceAvailable;
    }

    @Override
    public NodeAndInitialCredentials<VirtualMachine> createNodeWithGroupEncodedIntoName(final String group,
            final String name, final Template template) {
        String locationName = template.getLocation().getId();
        Image image = template.getImage();
        String hardwareId = fromSlashEncoded(template.getHardware().getId()).name();
        AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class);
        String resourceGroupName = templateOptions.getResourceGroup();

        IdReference availabilitySet = getAvailabilitySetIdReference(templateOptions.getAvailabilitySet());
        NetworkProfile networkProfile = createNetworkProfile(
                createNetworkInterfaceCards(name, locationName, templateOptions));
        StorageProfile storageProfile = createStorageProfile(image, templateOptions.getDataDisks());
        HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(hardwareId).build();
        OSProfile osProfile = createOsProfile(name, template);

        VirtualMachineProperties virtualMachineProperties = VirtualMachineProperties.builder()
                .availabilitySet(availabilitySet).hardwareProfile(hardwareProfile).storageProfile(storageProfile)
                .osProfile(osProfile).networkProfile(networkProfile).build();

        // Store group apart from the name to be able to identify nodes with
        // custom names in the configured group
        templateOptions.getUserMetadata().put(GROUP_KEY, group);
        Map<String, String> metadataAndTags = metadataAndTagsAsCommaDelimitedValue(templateOptions);
        Plan plan = getMarketplacePlanFromImageMetadata(image);

        VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).createOrUpdate(name,
                locationName, virtualMachineProperties, metadataAndTags, plan);

        // Safe to pass null credentials here, as jclouds will default populate
        // the node with the default credentials from the image, or the ones in
        // the options, if provided.
        ResourceGroupAndName resourceGroupAndName = fromResourceGroupAndName(resourceGroupName, name);
        return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, resourceGroupAndName.slashEncode(),
                null);
    }

    @Override
    public Iterable<VMHardware> listHardwareProfiles() {
        final List<VMHardware> hwProfiles = Lists.newArrayList();
        for (Location location : listLocations()) {
            Iterable<VMSize> vmSizes = api.getVMSizeApi(location.name()).list();
            for (VMSize vmSize : vmSizes) {
                VMHardware hwProfile = VMHardware.create(vmSize.name(), vmSize.numberOfCores(),
                        vmSize.osDiskSizeInMB(), vmSize.resourceDiskSizeInMB(), vmSize.memoryInMB(),
                        vmSize.maxDataDiskCount(), location.name());
                hwProfiles.add(hwProfile);
            }
        }
        return hwProfiles;
    }

    private List<VMImage> getImagesFromPublisher(String publisherName, String location) {
        List<VMImage> osImagesRef = Lists.newArrayList();
        OSImageApi osImageApi = api.getOSImageApi(location);
        Iterable<Offer> offerList = osImageApi.listOffers(publisherName);

        for (Offer offer : offerList) {
            Iterable<SKU> skuList = osImageApi.listSKUs(publisherName, offer.name());

            for (SKU sku : skuList) {
                Iterable<Version> versionList = osImageApi.listVersions(publisherName, offer.name(), sku.name());
                for (Version version : versionList) {
                    Version versionDetails = osImageApi.getVersion(publisherName, offer.name(), sku.name(),
                            version.name());
                    VMImage vmImage = VMImage.azureImage().publisher(publisherName).offer(offer.name())
                            .sku(sku.name()).version(versionDetails.name()).location(location)
                            .versionProperties(versionDetails.properties()).build();
                    osImagesRef.add(vmImage);
                }
            }
        }
        return osImagesRef;
    }

    private List<VMImage> listImagesByLocation(String location) {
        final List<VMImage> osImages = Lists.newArrayList();
        for (String publisher : imagePublishers) {
            osImages.addAll(getImagesFromPublisher(publisher, location));
        }
        return osImages;
    }

    private List<VMImage> listCustomImagesByResourceGroup(String resourceGroup) {
        List<org.jclouds.azurecompute.arm.domain.Image> customImgs = api.getVirtualMachineImageApi(resourceGroup)
                .list();
        return ImmutableList
                .copyOf(transform(filter(customImgs, new Predicate<org.jclouds.azurecompute.arm.domain.Image>() {
                    @Override
                    public boolean apply(org.jclouds.azurecompute.arm.domain.Image input) {
                        return regionIds.get().contains(input.location());
                    }
                }), customImagetoVmImage));
    }

    @Override
    public Iterable<VMImage> listImages() {
        final ImmutableList.Builder<VMImage> osImages = ImmutableList.builder();

        final List<String> availableLocationNames = newArrayList(
                transform(listLocations(), new Function<Location, String>() {
                    @Override
                    public String apply(Location location) {
                        return location.name();
                    }
                }));

        for (String locationName : availableLocationNames) {
            osImages.addAll(listImagesByLocation(locationName));
        }

        // We need to look for custom images in all resource groups
        for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
            osImages.addAll(listCustomImagesByResourceGroup(resourceGroup.name()));
        }

        return osImages.build();
    }

    @Override
    public VMImage getImage(final String id) {
        VMImage image = VMImage.decodeFieldsFromUniqueId(id);

        if (image.custom()) {
            org.jclouds.azurecompute.arm.domain.Image vmImage = api.getVirtualMachineImageApi(image.resourceGroup())
                    .get(image.name());
            return vmImage == null ? null : customImagetoVmImage.apply(vmImage);
        }

        String location = image.location();
        String publisher = image.publisher();
        String offer = image.offer();
        String sku = image.sku();

        OSImageApi osImageApi = api.getOSImageApi(location);
        List<Version> versions = osImageApi.listVersions(publisher, offer, sku);
        if (!versions.isEmpty()) {
            Version version = osImageApi.getVersion(publisher, offer, sku, versions.get(0).name());
            return VMImage.azureImage().publisher(publisher).offer(offer).sku(sku).version(version.name())
                    .location(location).versionProperties(version.properties()).build();
        }

        return null;
    }

    @Override
    public Iterable<Location> listLocations() {
        final Iterable<String> vmLocations = FluentIterable
                .from(api.getResourceProviderApi().get("Microsoft.Compute"))
                .filter(new Predicate<ResourceProviderMetaData>() {
                    @Override
                    public boolean apply(ResourceProviderMetaData input) {
                        return input.resourceType().equals("virtualMachines");
                    }
                }).transformAndConcat(new Function<ResourceProviderMetaData, Iterable<String>>() {
                    @Override
                    public Iterable<String> apply(ResourceProviderMetaData resourceProviderMetaData) {
                        return resourceProviderMetaData.locations();
                    }
                });

        List<Location> locations = FluentIterable.from(api.getLocationApi().list())
                .filter(new Predicate<Location>() {
                    @Override
                    public boolean apply(Location location) {
                        return Iterables.contains(vmLocations, location.displayName());
                    }
                }).filter(new Predicate<Location>() {
                    @Override
                    public boolean apply(Location location) {
                        return regionIds.get().isEmpty() ? true : regionIds.get().contains(location.name());
                    }
                }).toList();

        return locations;
    }

    @Override
    public VirtualMachine getNode(final String id) {
        ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
        return api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).get(resourceGroupAndName.name());
    }

    @Override
    public void destroyNode(final String id) {
        checkState(cleanupResources.cleanupNode(id), "server(%s) and its resources still there after deleting!?",
                id);
    }

    @Override
    public void rebootNode(final String id) {
        ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
        api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).restart(resourceGroupAndName.name());
    }

    @Override
    public void resumeNode(final String id) {
        ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
        api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).start(resourceGroupAndName.name());
    }

    @Override
    public void suspendNode(final String id) {
        ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
        api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).stop(resourceGroupAndName.name());
    }

    @Override
    public Iterable<VirtualMachine> listNodes() {
        ImmutableList.Builder<VirtualMachine> nodes = builder();
        for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
            List<VirtualMachine> vms = api.getVirtualMachineApi(resourceGroup.name()).list();
            nodes.addAll(filter(vms, new Predicate<VirtualMachine>() {
                @Override
                public boolean apply(VirtualMachine input) {
                    return regionIds.get().contains(input.location());
                }
            }));
        }
        return nodes.build();
    }

    @Override
    public Iterable<VirtualMachine> listNodesByIds(final Iterable<String> ids) {
        return transform(ids, new Function<String, VirtualMachine>() {
            @Override
            public VirtualMachine apply(String input) {
                return getNode(input);
            }
        });
    }

    private OSProfile createOsProfile(String computerName, Template template) {
        String defaultLoginUser = template.getImage().getDefaultCredentials().getUser();
        String adminUsername = MoreObjects.firstNonNull(template.getOptions().getLoginUser(), defaultLoginUser);
        // Password already generated in CreateResourcesThenCreateNodes (if not set by user)
        String adminPassword = template.getOptions().getLoginPassword();
        OSProfile.Builder builder = OSProfile.builder().adminUsername(adminUsername).adminPassword(adminPassword)
                .computerName(computerName);

        if (!Strings.isNullOrEmpty(template.getOptions().getPublicKey())
                && OsFamily.WINDOWS != template.getImage().getOperatingSystem().getFamily()) {
            OSProfile.LinuxConfiguration linuxConfiguration = OSProfile.LinuxConfiguration.create("true",
                    OSProfile.LinuxConfiguration.SSH.create(of(OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create(
                            String.format("/home/%s/.ssh/authorized_keys", adminUsername),
                            template.getOptions().getPublicKey()))));
            builder.linuxConfiguration(linuxConfiguration);
        }

        AzureTemplateOptions azureTemplateOptions = template.getOptions().as(AzureTemplateOptions.class);

        if (azureTemplateOptions.getWindowsConfiguration() != null) {
            builder.windowsConfiguration(azureTemplateOptions.getWindowsConfiguration());
        }

        if (azureTemplateOptions.getSecrets() != null) {
            builder.secrets(azureTemplateOptions.getSecrets());
        }

        if (!Strings.isNullOrEmpty(azureTemplateOptions.getCustomData())) {
            builder.customData(azureTemplateOptions.getCustomData());
        }

        return builder.build();
    }

    private List<NetworkInterfaceCard> createNetworkInterfaceCards(final String nodeName, final String location,
            AzureTemplateOptions options) {
        // Prefer a sorted list of NICs with the ones with public IPs first, to
        // make sure the primary NIC is the public one
        final String securityGroup = getOnlyElement(options.getGroups(), null);
        return Lists.transform(publicIpsFirst(options.getIpOptions()),
                new Function<IpOptions, NetworkInterfaceCard>() {
                    @Override
                    public NetworkInterfaceCard apply(IpOptions input) {
                        return createNetworkInterfaceCard(input, nodeName, location, securityGroup);
                    }
                });
    }

    private NetworkInterfaceCard createNetworkInterfaceCard(IpOptions ipConfig, String nodeName, String location,
            String securityGroup) {
        String resourceGroup = extractResourceGroup(ipConfig.subnet());
        String subnetName = extractName(ipConfig.subnet());

        IpConfigurationProperties.Builder ipProperties = IpConfigurationProperties.builder()
                .subnet(IdReference.create(ipConfig.subnet()))
                .privateIPAllocationMethod(ipConfig.address().isPresent() ? "Static" : "Dynamic")
                .privateIPAddress(ipConfig.address().orNull());

        configurePublicIP(ipConfig, ipProperties, resourceGroup, location, nodeName);

        String ipName = namingConvention.uniqueNameForGroup(subnetName);
        final String nicName = namingConvention.uniqueNameForGroup(subnetName);

        IpConfiguration config = IpConfiguration.builder().name(ipName).properties(ipProperties.build()).build();

        NetworkInterfaceCardProperties.Builder nicProperties = NetworkInterfaceCardProperties.builder()
                .ipConfigurations(ImmutableList.of(config));

        if (securityGroup != null) {
            nicProperties.networkSecurityGroup(IdReference.create(securityGroup));
        }

        logger.debug(">> creating nic %s(%s) with security groups (%s)", nicName, config,
                securityGroup != null ? securityGroup : "");

        final NetworkInterfaceCardApi nicApi = api.getNetworkInterfaceCardApi(resourceGroup);
        NetworkInterfaceCard nic = nicApi.createOrUpdate(nicName, location, nicProperties.build(),
                ImmutableMap.of("jclouds", nodeName));

        resourceAvailable.apply(new Supplier<Provisionable>() {
            @Override
            public Provisionable get() {
                NetworkInterfaceCard updated = nicApi.get(nicName);
                return updated == null ? null : updated.properties();
            }
        });

        return nic;
    }

    private void configurePublicIP(IpOptions ipConfig, IpConfigurationProperties.Builder ipProperties,
            String resourceGroup, String location, String nodeName) {
        if (ipConfig.publicIpId() != null) {
            logger.debug(">> configuring public ip: %s", extractName(ipConfig.publicIpId()));
            PublicIPAddress publicIp = api.getPublicIPAddressApi(extractResourceGroup(ipConfig.publicIpId()))
                    .get(extractName(ipConfig.publicIpId()));
            ipProperties.publicIPAddress(IdReference.create(publicIp.id()));
        } else if (ipConfig.allocateNewPublicIp()) {
            PublicIPAddress publicIp = createPublicIp(resourceGroup, location, nodeName);
            ipProperties.publicIPAddress(IdReference.create(publicIp.id()));
        }
    }

    /**
     * Create the network profile and configure the first NIC as primary.
     */
    private NetworkProfile createNetworkProfile(List<NetworkInterfaceCard> nics) {
        List<NetworkInterface> nicAttachments = new ArrayList<NetworkInterface>(nics.size());
        for (int i = 0; i < nics.size(); i++) {
            nicAttachments
                    .add(NetworkInterface.create(nics.get(i).id(), NetworkInterfaceProperties.create(i == 0)));
        }
        return NetworkProfile.create(nicAttachments);
    }

    private static List<IpOptions> publicIpsFirst(List<IpOptions> ipOptions) {
        List<IpOptions> sorted = new ArrayList<IpOptions>(ipOptions);
        Collections.sort(sorted, new Comparator<IpOptions>() {
            @Override
            public int compare(IpOptions o1, IpOptions o2) {
                return o1.allocateNewPublicIp() == o2.allocateNewPublicIp() ? 0 : o1.allocateNewPublicIp() ? -1 : 1;
            }
        });
        return sorted;
    }

    private PublicIPAddress createPublicIp(String resourceGroup, String location, String nodeName) {
        String name = namingConvention.uniqueNameForGroup(nodeName);

        PublicIPAddressProperties properties = PublicIPAddressProperties.builder()
                .publicIPAllocationMethod("Static").idleTimeoutInMinutes(4).build();

        logger.debug(">> allocating new public ip address: %s", name);

        PublicIPAddress ip = api.getPublicIPAddressApi(resourceGroup).createOrUpdate(name, location,
                ImmutableMap.of("jclouds", nodeName, AUTOGENERATED_IP_KEY, "true"), properties);

        checkState(publicIpAvailable.create(resourceGroup).apply(name),
                "Public IP was not provisioned in the configured timeout");

        return ip;
    }

    private StorageProfile createStorageProfile(Image image, List<DataDisk> dataDisks) {
        return StorageProfile.create(createImageReference(image), createOSDisk(image), dataDisks);
    }

    private ImageReference createImageReference(Image image) {
        return isCustom(image.getId()) ? ImageReference.builder().customImageId(image.getProviderId()).build()
                : ImageReference.builder().publisher(image.getProviderId()).offer(image.getName())
                        .sku(image.getVersion()).version("latest").build();
    }

    private OSDisk createOSDisk(Image image) {
        OsFamily osFamily = image.getOperatingSystem().getFamily();
        String osType = osFamily == OsFamily.WINDOWS ? "Windows" : "Linux";
        return OSDisk.builder().osType(osType).caching(DataDisk.CachingTypes.READ_WRITE.toString())
                .createOption(CreationData.CreateOptions.FROM_IMAGE.toString()).managedDiskParameters(
                        ManagedDiskParameters.create(null, StorageAccountType.STANDARD_LRS.toString()))
                .build();
    }

    private IdReference getAvailabilitySetIdReference(AvailabilitySet availabilitySet) {
        return availabilitySet != null ? IdReference.create(availabilitySet.id()) : null;
    }
}