Search in sources :

Example 1 with PackageDownloadException

use of com.aws.greengrass.componentmanager.exceptions.PackageDownloadException in project aws-greengrass-nucleus by aws-greengrass.

the class ComponentManager method preparePackage.

private void preparePackage(ComponentIdentifier componentIdentifier) throws PackageLoadingException, PackageDownloadException, InvalidArtifactUriException, InterruptedException {
    logger.atInfo().setEventType("prepare-package-start").kv(PACKAGE_IDENTIFIER, componentIdentifier).log();
    try {
        ComponentRecipe pkg = componentStore.getPackageRecipe(componentIdentifier);
        prepareArtifacts(componentIdentifier, pkg.getArtifacts());
        logger.atDebug("prepare-package-finished").kv(PACKAGE_IDENTIFIER, componentIdentifier).log();
    } catch (SizeLimitException e) {
        logger.atError().log("Size limit reached", e);
        throw e;
    } catch (PackageLoadingException | PackageDownloadException e) {
        logger.atError().log("Failed to prepare package {}", componentIdentifier, e);
        throw e;
    }
}
Also used : SizeLimitException(com.aws.greengrass.componentmanager.exceptions.SizeLimitException) PackageDownloadException(com.aws.greengrass.componentmanager.exceptions.PackageDownloadException) ComponentRecipe(com.aws.greengrass.componentmanager.models.ComponentRecipe) PackageLoadingException(com.aws.greengrass.componentmanager.exceptions.PackageLoadingException)

Example 2 with PackageDownloadException

use of com.aws.greengrass.componentmanager.exceptions.PackageDownloadException in project aws-greengrass-nucleus by aws-greengrass.

the class ArtifactDownloader method download.

/**
 * Download an artifact from remote. This call can take a long time if the network is intermittent.
 *
 * @return file handle of the downloaded file
 * @throws IOException              if I/O error occurred in network/disk
 * @throws InterruptedException     if interrupted in downloading
 * @throws PackageDownloadException if error occurred in download process
 */
@SuppressWarnings({ "PMD.AvoidCatchingGenericException", "PMD.AvoidRethrowingException" })
public File download() throws PackageDownloadException, IOException, InterruptedException {
    MessageDigest messageDigest;
    try {
        if (artifact.getAlgorithm() == null) {
            throw new ArtifactChecksumMismatchException(getErrorString("Algorithm missing from artifact."));
        }
        messageDigest = MessageDigest.getInstance(artifact.getAlgorithm());
    } catch (NoSuchAlgorithmException e) {
        throw new ArtifactChecksumMismatchException(getErrorString("Algorithm requested for artifact checksum is not supported"), e);
    }
    saveToPath = getArtifactFile().toPath();
    long artifactSize = getDownloadSize();
    final AtomicLong offset = new AtomicLong(0);
    // If there are partially downloaded artifact existing on device
    if (Files.exists(saveToPath)) {
        if (Files.size(saveToPath) > artifactSize) {
            // Existing file is corrupted, it's larger than defined in artifact.
            // Normally shouldn't happen, corrupted files are deleted every time.
            logger.atError().log("existing file corrupted. Expected size: {}, Actual size: {}." + " Removing and retrying download.", artifactSize, Files.size(saveToPath));
            Files.deleteIfExists(saveToPath);
        } else {
            offset.set(Files.size(saveToPath));
            updateDigestFromFile(saveToPath, messageDigest);
        }
    }
    try {
        // download for 10 times before giving up.
        return RetryUtils.runWithRetry(checksumMismatchRetryConfig, () -> {
            while (offset.get() < artifactSize) {
                long downloadedBytes = download(offset.get(), artifactSize - 1, messageDigest);
                offset.addAndGet(downloadedBytes);
            }
            String digest = Base64.getEncoder().encodeToString(messageDigest.digest());
            if (!digest.equals(artifact.getChecksum())) {
                // Handle failure in integrity check, delete bad file then throw
                Files.deleteIfExists(saveToPath);
                offset.set(0);
                messageDigest.reset();
                throw new ArtifactChecksumMismatchException("Integrity check for downloaded artifact failed. " + "Probably due to file corruption.");
            }
            logger.atDebug().setEventType("download-artifact").log("Passed integrity check");
            return saveToPath.toFile();
        }, "download-artifact", logger);
    } catch (InterruptedException e) {
        throw e;
    } catch (Exception e) {
        throw new PackageDownloadException(getErrorString("Failed to download the artifact"), e);
    }
}
Also used : AtomicLong(java.util.concurrent.atomic.AtomicLong) PackageDownloadException(com.aws.greengrass.componentmanager.exceptions.PackageDownloadException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) MessageDigest(java.security.MessageDigest) ArtifactChecksumMismatchException(com.aws.greengrass.componentmanager.exceptions.ArtifactChecksumMismatchException) ArtifactChecksumMismatchException(com.aws.greengrass.componentmanager.exceptions.ArtifactChecksumMismatchException) IOException(java.io.IOException) PackageDownloadException(com.aws.greengrass.componentmanager.exceptions.PackageDownloadException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException)

Example 3 with PackageDownloadException

use of com.aws.greengrass.componentmanager.exceptions.PackageDownloadException in project aws-greengrass-nucleus by aws-greengrass.

the class GreengrassRepositoryDownloader method download.

@SuppressWarnings({ "PMD.AvoidCatchingGenericException", "PMD.AvoidRethrowingException" })
@Override
protected long download(long rangeStart, long rangeEnd, MessageDigest messageDigest) throws PackageDownloadException, InterruptedException {
    String url = getArtifactDownloadURL(identifier, artifact.getArtifactUri().getSchemeSpecificPart());
    try {
        return RetryUtils.runWithRetry(clientExceptionRetryConfig, () -> {
            try (SdkHttpClient client = getSdkHttpClient()) {
                HttpExecuteRequest executeRequest = HttpExecuteRequest.builder().request(SdkHttpFullRequest.builder().uri(URI.create(url)).method(SdkHttpMethod.GET).putHeader(HTTP_RANGE_HEADER_KEY, String.format(HTTP_RANGE_HEADER_FORMAT, rangeStart, rangeEnd)).build()).build();
                HttpExecuteResponse executeResponse = client.prepareRequest(executeRequest).call();
                int responseCode = executeResponse.httpResponse().statusCode();
                // check response code
                if (responseCode == HttpURLConnection.HTTP_PARTIAL) {
                    try (InputStream inputStream = executeResponse.responseBody().get()) {
                        long downloaded = download(inputStream, messageDigest);
                        if (downloaded == 0) {
                            // Therefore throw IOException to trigger the retry logic.
                            throw new IOException(getErrorString("Failed to read any byte from the stream"));
                        } else {
                            return downloaded;
                        }
                    }
                } else if (responseCode == HttpURLConnection.HTTP_OK) {
                    long length = getContentLengthLong(executeResponse.httpResponse());
                    if (length < rangeEnd) {
                        String errMsg = String.format("Artifact size mismatch. Expected artifact size %d. HTTP contentLength %d", rangeEnd, length);
                        throw new PackageDownloadException(getErrorString(errMsg));
                    }
                    // try to discard the offset number of bytes.
                    try (InputStream inputStream = executeResponse.responseBody().get()) {
                        long byteSkipped = inputStream.skip(rangeStart);
                        // If number of bytes skipped is less than declared, throw error.
                        if (byteSkipped != rangeStart) {
                            throw new PackageDownloadException(getErrorString("Reach the end of the stream"));
                        }
                        long downloaded = download(inputStream, messageDigest);
                        if (downloaded == 0) {
                            // Therefore throw IOException to trigger the retry logic.
                            throw new IOException("Failed to read any byte from the inputStream");
                        } else {
                            return downloaded;
                        }
                    }
                } else {
                    throw new PackageDownloadException(getErrorString("Unable to download Greengrass artifact. HTTP Error: " + responseCode));
                }
            }
        }, "download-artifact", logger);
    } catch (InterruptedException e) {
        throw e;
    } catch (Exception e) {
        throw new PackageDownloadException(getErrorString("Failed to download the artifact"), e);
    }
}
Also used : HttpExecuteRequest(software.amazon.awssdk.http.HttpExecuteRequest) HttpExecuteResponse(software.amazon.awssdk.http.HttpExecuteResponse) InputStream(java.io.InputStream) SdkHttpClient(software.amazon.awssdk.http.SdkHttpClient) PackageDownloadException(com.aws.greengrass.componentmanager.exceptions.PackageDownloadException) IOException(java.io.IOException) PackageLoadingException(com.aws.greengrass.componentmanager.exceptions.PackageLoadingException) PackageDownloadException(com.aws.greengrass.componentmanager.exceptions.PackageDownloadException) IOException(java.io.IOException) SdkClientException(software.amazon.awssdk.core.exception.SdkClientException)

Example 4 with PackageDownloadException

use of com.aws.greengrass.componentmanager.exceptions.PackageDownloadException in project aws-greengrass-nucleus by aws-greengrass.

the class DockerImageDownloader method performDownloadSteps.

private File performDownloadSteps(Image image) throws PackageDownloadException, InterruptedException {
    AtomicBoolean credentialRefreshNeeded = new AtomicBoolean(false);
    do {
        // Attempt getting credentials and login only for private registries, .
        if (image.getRegistry().isPrivateRegistry()) {
            // Get credentials for the registry
            try {
                RetryUtils.runWithRetry(infiniteAttemptsRetryConfig, () -> {
                    // credentials for them on case by case basis
                    if (image.getRegistry().isEcrRegistry()) {
                        // Get auth token for ECR, which represents ECR registry credentials
                        Registry.Credentials credentials = ecrAccessor.getCredentials(image.getRegistry().getRegistryId());
                        image.getRegistry().setCredentials(credentials);
                        credentialRefreshNeeded.set(false);
                    }
                    return null;
                }, "get-ecr-auth-token", logger);
            } catch (InterruptedException e) {
                throw e;
            } catch (Exception e) {
                throw new PackageDownloadException(getErrorString("Failed to get auth token for docker login"), e);
            }
            // Login to registry
            // TODO: [P44950158]: Avoid logging into registries which might already have been logged in previously
            // with the same and valid credentials by maintaining a cache across artifacts and deployments
            run(() -> {
                if (credentialsUsable(image)) {
                    dockerClient.login(image.getRegistry());
                } else {
                    // Credentials have expired, re-fetch and login again
                    logger.atInfo().kv("registry-endpoint", image.getRegistry().getEndpoint()).log("Registry credentials have expired," + "fetching fresh credentials and logging in again");
                    credentialRefreshNeeded.set(true);
                }
                return null;
            }, "docker-login", "Failed to login to docker registry");
        }
        // Don't even attempt to pull images if credentials are expired, first try to refresh credentials
        if (credentialRefreshNeeded.get()) {
            continue;
        }
        // Docker pull
        run(() -> {
            if (credentialsUsable(image)) {
                dockerClient.pullImage(image);
            } else {
                // Credentials have expired, re-fetch and login again
                logger.atInfo().kv("registry-endpoint", image.getRegistry().getEndpoint()).log("Registry credentials have expired, fetching fresh credentials and logging in again");
                credentialRefreshNeeded.set(true);
            }
            return null;
        }, "docker-pull-image", "Failed to download docker image");
    } while (credentialRefreshNeeded.get());
    // No file resources available since image artifacts are stored in docker's image store
    return null;
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) PackageDownloadException(com.aws.greengrass.componentmanager.exceptions.PackageDownloadException) IOException(java.io.IOException) DockerServiceUnavailableException(com.aws.greengrass.componentmanager.plugins.docker.exceptions.DockerServiceUnavailableException) InvalidArtifactUriException(com.aws.greengrass.componentmanager.exceptions.InvalidArtifactUriException) SdkClientException(software.amazon.awssdk.core.exception.SdkClientException) ServerException(software.amazon.awssdk.services.ecr.model.ServerException) DockerLoginException(com.aws.greengrass.componentmanager.plugins.docker.exceptions.DockerLoginException) PackageDownloadException(com.aws.greengrass.componentmanager.exceptions.PackageDownloadException) ConnectionException(com.aws.greengrass.componentmanager.plugins.docker.exceptions.ConnectionException)

Example 5 with PackageDownloadException

use of com.aws.greengrass.componentmanager.exceptions.PackageDownloadException in project aws-greengrass-nucleus by aws-greengrass.

the class S3Downloader method getRegionClientForBucket.

@SuppressWarnings({ "PMD.AvoidCatchingGenericException", "PMD.AvoidRethrowingException" })
private S3Client getRegionClientForBucket(String bucket) throws InterruptedException, PackageDownloadException {
    GetBucketLocationRequest getBucketLocationRequest = GetBucketLocationRequest.builder().bucket(bucket).build();
    String region = null;
    try {
        region = RetryUtils.runWithRetry(s3ClientExceptionRetryConfig, () -> s3ClientFactory.getS3Client().getBucketLocation(getBucketLocationRequest).locationConstraintAsString(), "get-bucket-location", logger);
    } catch (InterruptedException e) {
        throw e;
    } catch (S3Exception e) {
        String message = e.getMessage();
        if (message.contains(REGION_EXPECTING_STRING)) {
            message = message.substring(message.indexOf(REGION_EXPECTING_STRING) + REGION_EXPECTING_STRING.length());
            region = message.substring(0, message.indexOf('\''));
        } else {
            throw new PackageDownloadException(getErrorString("Failed to determine S3 bucket location"), e);
        }
    } catch (Exception e) {
        throw new PackageDownloadException(getErrorString("Failed to determine S3 bucket location"), e);
    }
    // If the region is empty, it is us-east-1
    return s3ClientFactory.getClientForRegion(Utils.isEmpty(region) ? Region.US_EAST_1 : Region.of(region));
}
Also used : S3Exception(software.amazon.awssdk.services.s3.model.S3Exception) PackageDownloadException(com.aws.greengrass.componentmanager.exceptions.PackageDownloadException) GetBucketLocationRequest(software.amazon.awssdk.services.s3.model.GetBucketLocationRequest) S3Exception(software.amazon.awssdk.services.s3.model.S3Exception) InvalidArtifactUriException(com.aws.greengrass.componentmanager.exceptions.InvalidArtifactUriException) PackageDownloadException(com.aws.greengrass.componentmanager.exceptions.PackageDownloadException) IOException(java.io.IOException) SdkClientException(software.amazon.awssdk.core.exception.SdkClientException)

Aggregations

PackageDownloadException (com.aws.greengrass.componentmanager.exceptions.PackageDownloadException)15 IOException (java.io.IOException)10 SdkClientException (software.amazon.awssdk.core.exception.SdkClientException)7 InvalidArtifactUriException (com.aws.greengrass.componentmanager.exceptions.InvalidArtifactUriException)5 PackageLoadingException (com.aws.greengrass.componentmanager.exceptions.PackageLoadingException)3 Test (org.junit.jupiter.api.Test)3 GetComponentVersionArtifactRequest (software.amazon.awssdk.services.greengrassv2data.model.GetComponentVersionArtifactRequest)3 GetComponentVersionArtifactResponse (software.amazon.awssdk.services.greengrassv2data.model.GetComponentVersionArtifactResponse)3 S3Exception (software.amazon.awssdk.services.s3.model.S3Exception)3 SizeLimitException (com.aws.greengrass.componentmanager.exceptions.SizeLimitException)2 ComponentArtifact (com.aws.greengrass.componentmanager.models.ComponentArtifact)2 ComponentIdentifier (com.aws.greengrass.componentmanager.models.ComponentIdentifier)2 RecipeMetadata (com.aws.greengrass.componentmanager.models.RecipeMetadata)2 Semver (com.vdurmont.semver4j.Semver)2 InputStream (java.io.InputStream)2 URI (java.net.URI)2 HttpExecuteRequest (software.amazon.awssdk.http.HttpExecuteRequest)2 HttpExecuteResponse (software.amazon.awssdk.http.HttpExecuteResponse)2 SdkHttpClient (software.amazon.awssdk.http.SdkHttpClient)2 S3Client (software.amazon.awssdk.services.s3.S3Client)2