private void deleteNetworkInterfaces(
      AuthenticatedContext authenticatedContext,
      AzureRMClient client,
      String stackName,
      List<String> networkInterfacesNames)
      throws CloudConnectorException {
    for (String networkInterfacesName : networkInterfacesNames) {
      try {
        client.deleteNetworkInterface(stackName, networkInterfacesName);
        PollTask<Boolean> task =
            armPollTaskFactory.newNetworkInterfaceDeleteStatusCheckerTask(
                authenticatedContext,
                armClient,
                new NetworkInterfaceCheckerContext(
                    new ArmCredentialView(authenticatedContext.getCloudCredential()),
                    stackName,
                    networkInterfacesName));

        syncPollingScheduler.schedule(task);

      } catch (HttpResponseException e) {
        if (e.getStatusCode() != NOT_FOUND) {
          throw new CloudConnectorException(e.getResponse().getData().toString(), e);
        }
      } catch (Exception e) {
        throw new CloudConnectorException(
            String.format("Could not delete network interface: %s", networkInterfacesName), e);
      }
    }
  }
  @Override
  public List<CloudResourceStatus> check(
      AuthenticatedContext authenticatedContext, List<CloudResource> resources) {
    List<CloudResourceStatus> result = new ArrayList<>();
    AzureRMClient access = armClient.createAccess(authenticatedContext.getCloudCredential());
    String stackName = armUtils.getStackName(authenticatedContext.getCloudContext());

    for (CloudResource resource : resources) {
      switch (resource.getType()) {
        case ARM_TEMPLATE:
          LOGGER.info("Checking Arm group stack status of: {}", stackName);
          try {
            Map<String, Object> resourceGroup = access.getTemplateDeployment(stackName, stackName);
            CloudResourceStatus templateResourceStatus =
                armUtils.templateStatus(resource, resourceGroup, access, stackName);
            result.add(templateResourceStatus);
          } catch (HttpResponseException e) {
            if (e.getStatusCode() == NOT_FOUND) {
              result.add(new CloudResourceStatus(resource, ResourceStatus.DELETED));
            } else {
              throw new CloudConnectorException(e.getResponse().getData().toString(), e);
            }
          } catch (Exception e) {
            throw new CloudConnectorException(
                String.format("Invalid resource exception: %s", e.getMessage()), e);
          }
          break;
        default:
          throw new CloudConnectorException(
              String.format("Invalid resource type: %s", resource.getType()));
      }
    }

    return result;
  }
 private void deallocateVirtualMachine(
     AuthenticatedContext authenticatedContext,
     AzureRMClient client,
     String stackName,
     String privateInstanceId)
     throws CloudConnectorException {
   try {
     client.deallocateVirtualMachine(stackName, privateInstanceId);
     PollTask<Boolean> task =
         armPollTaskFactory.newVirtualMachineStatusCheckerTask(
             authenticatedContext,
             armClient,
             new VirtualMachineCheckerContext(
                 new ArmCredentialView(authenticatedContext.getCloudCredential()),
                 stackName,
                 privateInstanceId,
                 "Succeeded"));
     syncPollingScheduler.schedule(task);
   } catch (HttpResponseException e) {
     if (e.getStatusCode() != NOT_FOUND) {
       throw new CloudConnectorException(e.getResponse().getData().toString(), e);
     }
   } catch (Exception e) {
     throw new CloudConnectorException(
         String.format("Could not deallocate machine: %s", privateInstanceId), e);
   }
 }
  @Override
  public List<CloudResourceStatus> upscale(
      AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources) {
    AzureRMClient azureRMClient = armClient.createAccess(authenticatedContext.getCloudCredential());

    String stackName = armUtils.getStackName(authenticatedContext.getCloudContext());
    String template =
        armTemplateBuilder.build(
            stackName,
            authenticatedContext.getCloudCredential(),
            authenticatedContext.getCloudContext(),
            stack);
    String parameters =
        armTemplateBuilder.buildParameters(
            authenticatedContext.getCloudCredential(), stack.getNetwork(), stack.getImage());

    try {
      azureRMClient.createTemplateDeployment(stackName, stackName, template, parameters);
      List<CloudResourceStatus> check = new ArrayList<>();
      check.add(new CloudResourceStatus(resources.get(0), ResourceStatus.IN_PROGRESS));
      return check;
    } catch (HttpResponseException e) {
      throw new CloudConnectorException(e.getResponse().getData().toString(), e);
    } catch (Exception e) {
      throw new CloudConnectorException(String.format("Could not upscale: %s", stackName), e);
    }
  }
 protected void httpResponseExceptionHandler(
     HttpResponseException ex, String resourceName, String user, Stack stack) {
   if (ex.getStatusCode() != NOT_FOUND && ex.getStatusCode() != NOT_EXIST) {
     throw new AzureResourceException(ex.getResponse().getData().toString());
   } else {
     LOGGER.error(
         String.format("Azure resource not found with %s name for %s user.", resourceName, user));
   }
 }
 private void deleteContainer(
     AzureRMClient azureRMClient, String resourceGroup, String storageName, String container) {
   try {
     azureRMClient.deleteContainerInStorage(resourceGroup, storageName, container);
   } catch (HttpResponseException e) {
     if (e.getStatusCode() != NOT_FOUND) {
       throw new CloudConnectorException(e.getResponse().getData().toString());
     }
   } catch (Exception e) {
     throw new CloudConnectorException(
         String.format("Could not delete container: %s", container), e);
   }
 }
  @Override
  public Map<String, String> createResources(WasbIntegratedFileSystemConfiguration fsConfig) {
    String resourceGroupName = fsConfig.getProperty(FileSystemConfiguration.RESOURCE_GROUP_NAME);
    if (!StringUtils.isEmpty(resourceGroupName)) {
      String tenantId = fsConfig.getTenantId();
      String subscriptionId = fsConfig.getSubscriptionId();
      String appId = fsConfig.getAppId();
      String appPassword = fsConfig.getAppPassword();
      String region = fsConfig.getRegion();
      String storageName = fsConfig.getStorageName();
      AzureRMClient azureClient = new AzureRMClient(tenantId, appId, appPassword, subscriptionId);

      try {
        azureClient.createStorageAccount(resourceGroupName, storageName, region, "Standard_LRS");

        storagePollingService.pollWithTimeout(
            storageAccountStatusCheckerTask,
            new StorageAccountCheckerContext(
                tenantId, subscriptionId, appId, appPassword, storageName, resourceGroupName),
            POLLING_INTERVAL,
            MAX_ATTEMPTS);

        Map<String, Object> keys =
            azureClient.getStorageAccountKeys(resourceGroupName, storageName);
        String key = (String) keys.get("key1");
        return Collections.singletonMap(STORAGE_ACCOUNT_KEY, key);
      } catch (Exception e) {
        if (e instanceof HttpResponseException) {
          HttpResponseException he = (HttpResponseException) e;
          throw new FileSystemConfigException(
              "Failed to create Azure storage resource: " + he.getResponse().getData().toString(),
              he);
        } else {
          throw new FileSystemConfigException("Failed to create Azure storage resource", e);
        }
      }
    } else {
      throw new FileSystemConfigException(
          String.format(
              "The WASB Integrated filesystem is only available on '%s' cloud platform and the '%s' parameter needs to be specified.",
              CloudPlatform.AZURE_RM, FileSystemConfiguration.RESOURCE_GROUP_NAME));
    }
  }
 private void deleteDisk(
     List<String> storageProfileDiskNames,
     AzureRMClient azureRMClient,
     String resourceGroup,
     String storageName,
     String container) {
   for (String storageProfileDiskName : storageProfileDiskNames) {
     try {
       azureRMClient.deleteBlobInStorageContainer(
           resourceGroup, storageName, container, storageProfileDiskName);
     } catch (HttpResponseException e) {
       if (e.getStatusCode() != NOT_FOUND) {
         throw new CloudConnectorException(e.getResponse().getData().toString());
       }
     } catch (Exception e) {
       throw new CloudConnectorException(
           String.format("Could not delete blob: %s", storageProfileDiskName), e);
     }
   }
 }
  @Override
  public List<CloudVmInstanceStatus> stop(
      AuthenticatedContext ac, List<CloudResource> resources, List<CloudInstance> vms) {
    AzureRMClient azureRMClient = armClient.getClient(ac.getCloudCredential());
    String stackName = armTemplateUtils.getStackName(ac.getCloudContext());
    List<CloudVmInstanceStatus> statuses = new ArrayList<>();

    for (CloudInstance vm : vms) {
      try {
        azureRMClient.stopVirtualMachine(stackName, vm.getInstanceId());
        statuses.add(new CloudVmInstanceStatus(vm, InstanceStatus.IN_PROGRESS));
      } catch (HttpResponseException e) {
        statuses.add(
            new CloudVmInstanceStatus(
                vm, InstanceStatus.FAILED, e.getResponse().getData().toString()));
      } catch (Exception e) {
        statuses.add(new CloudVmInstanceStatus(vm, InstanceStatus.FAILED, e.getMessage()));
      }
    }
    return statuses;
  }
 @Override
 public List<CloudResourceStatus> terminate(
     AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources) {
   AzureRMClient azureRMClient = armClient.createAccess(authenticatedContext.getCloudCredential());
   for (CloudResource resource : resources) {
     try {
       azureRMClient.deleteResourceGroup(resource.getName());
       PollTask<Boolean> task =
           armPollTaskFactory.newResourceGroupDeleteStatusCheckerTask(
               authenticatedContext,
               armClient,
               new ResourceGroupCheckerContext(
                   new ArmCredentialView(authenticatedContext.getCloudCredential()),
                   resource.getName()));
       Boolean statePollerResult = task.call();
       if (!task.completed(statePollerResult)) {
         syncPollingScheduler.schedule(task);
       }
       if (armUtils.isPersistentStorage()) {
         CloudContext cloudCtx = authenticatedContext.getCloudContext();
         String storageName =
             armUtils.getStorageName(
                 authenticatedContext.getCloudCredential(), cloudCtx, stack.getRegion());
         String imageStorageGroup = armUtils.getImageResourceGroupName(cloudCtx);
         String diskContainer = armUtils.getDiskContainerName(cloudCtx);
         deleteContainer(azureRMClient, imageStorageGroup, storageName, diskContainer);
       }
     } catch (HttpResponseException e) {
       if (e.getStatusCode() != NOT_FOUND) {
         throw new CloudConnectorException(e.getResponse().getData().toString(), e);
       } else {
         return check(authenticatedContext, new ArrayList<CloudResource>());
       }
     } catch (Exception e) {
       throw new CloudConnectorException(
           String.format("Could not delete resource group: %s", resource.getName()), e);
     }
   }
   return check(authenticatedContext, resources);
 }
  @Override
  public List<CloudResourceStatus> launch(
      AuthenticatedContext authenticatedContext,
      CloudStack stack,
      PersistenceNotifier notifier,
      AdjustmentType adjustmentType,
      Long threshold) {
    String stackName = armUtils.getStackName(authenticatedContext.getCloudContext());
    String resourceGroupName =
        armUtils.getResourceGroupName(authenticatedContext.getCloudContext());
    String template =
        armTemplateBuilder.build(
            stackName,
            authenticatedContext.getCloudCredential(),
            authenticatedContext.getCloudContext(),
            stack);
    String parameters =
        armTemplateBuilder.buildParameters(
            authenticatedContext.getCloudCredential(), stack.getNetwork(), stack.getImage());

    AzureRMClient access = armClient.createAccess(authenticatedContext.getCloudCredential());
    try {
      access.createTemplateDeployment(resourceGroupName, stackName, template, parameters);
    } catch (HttpResponseException e) {
      throw new CloudConnectorException(
          String.format(
              "Error occured when creating stack: %s", e.getResponse().getData().toString()));
    } catch (Exception e) {
      throw new CloudConnectorException(String.format("Invalid provisiong type: %s", stackName));
    }

    CloudResource cloudResource =
        new CloudResource.Builder().type(ResourceType.ARM_TEMPLATE).name(stackName).build();
    List<CloudResourceStatus> resources = check(authenticatedContext, Arrays.asList(cloudResource));
    LOGGER.debug("Launched resources: {}", resources);
    return resources;
  }
  @Override
  public List<CloudResourceStatus> downscale(
      AuthenticatedContext auth,
      CloudStack stack,
      List<CloudResource> resources,
      List<CloudInstance> vms) {
    AzureRMClient client = armClient.createAccess(auth.getCloudCredential());
    String stackName = armUtils.getStackName(auth.getCloudContext());
    String storageName =
        armUtils.getStorageName(
            auth.getCloudCredential(), auth.getCloudContext(), stack.getRegion());
    String imageStorageGroup = armUtils.getImageResourceGroupName(auth.getCloudContext());
    String diskContainer = armUtils.getDiskContainerName(auth.getCloudContext());

    for (CloudInstance instance : vms) {
      List<String> networkInterfacesNames = new ArrayList<>();
      List<String> storageProfileDiskNames = new ArrayList<>();
      String instanceId = instance.getInstanceId();

      try {
        Map<String, Object> virtualMachine = client.getVirtualMachine(stackName, instanceId);

        Map properties = (Map) virtualMachine.get("properties");

        Map networkProfile = (Map) properties.get("networkProfile");

        List<Map> networkInterfaces = (List<Map>) networkProfile.get("networkInterfaces");
        for (Map networkInterface : networkInterfaces) {
          networkInterfacesNames.add(
              getNameFromConnectionString(networkInterface.get("id").toString()));
        }

        Map storageProfile = (Map) properties.get("storageProfile");

        Map osDisk = (Map) storageProfile.get("osDisk");
        List<Map> dataDisks = (List<Map>) storageProfile.get("dataDisks");

        for (Map datadisk : dataDisks) {
          Map vhds = (Map) datadisk.get("vhd");
          storageProfileDiskNames.add(getNameFromConnectionString(vhds.get("uri").toString()));
        }
        Map vhds = (Map) osDisk.get("vhd");
        storageProfileDiskNames.add(getNameFromConnectionString(vhds.get("uri").toString()));
      } catch (HttpResponseException e) {
        if (e.getStatusCode() != NOT_FOUND) {
          throw new CloudConnectorException(e.getResponse().getData().toString(), e);
        }
      } catch (Exception e) {
        throw new CloudConnectorException(String.format("Could not downscale: %s", stackName), e);
      }
      try {
        deallocateVirtualMachine(auth, client, stackName, instanceId);
        deleteVirtualMachine(auth, client, stackName, instanceId);
        deleteNetworkInterfaces(auth, client, stackName, networkInterfacesNames);
        deleteDisk(storageProfileDiskNames, client, imageStorageGroup, storageName, diskContainer);
      } catch (CloudConnectorException e) {
        throw e;
      }
    }
    return check(auth, resources);
  }