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;
}
}
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);
}
}
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);
}
}
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;
}
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));
}
Aggregations