package com.sequenceiq.cloudbreak.cloud.azure;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import javax.inject.Inject;
import org.apache.commons.lang3.text.WordUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.google.common.base.Strings;
import com.microsoft.azure.management.storage.SkuName;
import com.microsoft.azure.management.storage.StorageAccount;
import com.microsoft.azure.management.storage.StorageAccounts;
import com.sequenceiq.cloudbreak.api.model.ArmAttachedStorageOption;
import com.sequenceiq.cloudbreak.cloud.azure.client.AzureClient;
import com.sequenceiq.cloudbreak.cloud.context.AuthenticatedContext;
import com.sequenceiq.cloudbreak.cloud.context.CloudContext;
import com.sequenceiq.cloudbreak.cloud.azure.view.AzureCredentialView;
//import com.sequenceiq.cloudbreak.cloud.scheduler.SyncPollingScheduler;
@Service
public class AzureStorage {
public static final String IMAGES = "images";
public static final String STORAGE_BLOB_PATTERN = "https://%s.blob.core.windows.net/";
private static final Logger LOGGER = LoggerFactory.getLogger(AzureStorage.class);
private static final int RADIX = 32;
private static final int MAX_LENGTH_OF_NAME_SLICE = 8;
private static final int MAX_LENGTH_OF_RESOURCE_NAME = 24;
@Inject
private AzureUtils armUtils;
public ArmAttachedStorageOption getArmAttachedStorageOption(Map<String, String> parameters) {
String attachedStorageOption = parameters.get("attachedStorageOption");
if (Strings.isNullOrEmpty(attachedStorageOption)) {
return ArmAttachedStorageOption.SINGLE;
}
return ArmAttachedStorageOption.valueOf(attachedStorageOption);
}
public String getImageStorageName(AzureCredentialView acv, CloudContext cloudContext, String persistentStorageName,
ArmAttachedStorageOption armAttachedStorageOption) {
String storageName;
if (isPersistentStorage(persistentStorageName)) {
storageName = getPersistentStorageName(persistentStorageName, acv, cloudContext.getLocation().getRegion().value());
} else {
storageName = buildStorageName(armAttachedStorageOption, acv, null, cloudContext, AzureDiskType.LOCALLY_REDUNDANT);
}
return storageName;
}
public String getAttachedDiskStorageName(ArmAttachedStorageOption armAttachedStorageOption, AzureCredentialView acv, Long vmId, CloudContext cloudContext,
AzureDiskType storageType) {
return buildStorageName(armAttachedStorageOption, acv, vmId, cloudContext, storageType);
}
public void createStorage(AuthenticatedContext ac, AzureClient client, String osStorageName, AzureDiskType storageType, String storageGroup, String region)
throws Exception {
if (!storageAccountExist(client, osStorageName)) {
client.createStorageAccount(storageGroup, osStorageName, region, SkuName.fromString(storageType.value()));
}
}
public void deleteStorage(AuthenticatedContext authenticatedContext, AzureClient client, String osStorageName, String storageGroup)
throws Exception {
if (storageAccountExist(client, osStorageName)) {
client.deleteStorageAccount(storageGroup, osStorageName);
}
}
private String buildStorageName(ArmAttachedStorageOption armAttachedStorageOption, AzureCredentialView acv, Long vmId, CloudContext cloudContext,
AzureDiskType storageType) {
String result;
String name = cloudContext.getName().toLowerCase().replaceAll("\\s+|-", "");
name = name.length() > MAX_LENGTH_OF_NAME_SLICE ? name.substring(0, MAX_LENGTH_OF_NAME_SLICE) : name;
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
String storageAccountId = acv.getId().toString() + "#" + cloudContext.getId() + "#" + cloudContext.getOwner();
LOGGER.info("Storage account internal id: {}", storageAccountId);
byte[] digest = messageDigest.digest(storageAccountId.getBytes());
String paddedId = "";
if (armAttachedStorageOption == ArmAttachedStorageOption.PER_VM && vmId != null) {
paddedId = String.format("%3s", Long.toString(vmId, RADIX)).replace(' ', '0');
}
result = name + storageType.getAbbreviation() + paddedId + new BigInteger(1, digest).toString(RADIX);
} catch (NoSuchAlgorithmException e) {
result = name + acv.getId() + cloudContext.getId() + cloudContext.getOwner();
}
if (result.length() > MAX_LENGTH_OF_RESOURCE_NAME) {
result = result.substring(0, MAX_LENGTH_OF_RESOURCE_NAME);
}
LOGGER.info("Storage account name: {}", result);
return result;
}
private String getPersistentStorageName(String persistentStorageName, AzureCredentialView acv, String region) {
String subscriptionIdPart = acv.getSubscriptionId().replaceAll("-", "").toLowerCase();
String regionInitials = WordUtils.initials(region, ' ').toLowerCase();
String result = String.format("%s%s%s", persistentStorageName, regionInitials, subscriptionIdPart);
if (result.length() > MAX_LENGTH_OF_RESOURCE_NAME) {
result = result.substring(0, MAX_LENGTH_OF_RESOURCE_NAME);
}
LOGGER.info("Storage account name: {}", result);
return result;
}
public String getDiskContainerName(CloudContext cloudContext) {
return armUtils.getStackName(cloudContext);
}
public String getPersistentStorageName(Map<String, String> parameters) {
return parameters.get("persistentStorage");
}
public boolean isPersistentStorage(String persistentStorageName) {
return !Strings.isNullOrEmpty(persistentStorageName);
}
public String getImageResourceGroupName(CloudContext cloudContext, Map<String, String> parameters) {
if (isPersistentStorage(getPersistentStorageName(parameters))) {
return getPersistentStorageName(parameters);
}
return armUtils.getResourceGroupName(cloudContext);
}
private boolean storageAccountExist(AzureClient client, String storageName) {
try {
StorageAccounts storageAccounts = client.getStorageAccounts();
for (StorageAccount account : storageAccounts.list()) {
if (account.name().equals(storageName)) {
return true;
}
}
} catch (Exception e) {
return false;
}
return false;
}
}