コード例 #1
0
        private async Task CreateContainerInnerAsync(ContainerConfig containerConfig, bool retryDownload)
        {
            var containerName  = this.activationArgs.ContainerDescription.ContainerName;
            var containerExist = false;

            try
            {
                var response = await Utility.ExecuteWithRetriesAsync(
                    (operationTimeout) =>
                {
                    return(this.activator.Client.ContainerOperation.CreateContainerAsync(
                               containerName,
                               containerConfig,
                               operationTimeout));
                },
                    $"CreateContainerInnerAsync_{containerName}",
                    TraceType,
                    HostingConfig.Config.DockerRequestTimeout,
                    this.timeoutHelper.RemainingTime);

                this.containerId = response.ID;

                HostingTrace.Source.WriteInfo(
                    TraceType,
                    "Creating Container={0} from Image={1} for AppId={2} succeeded.",
                    containerName,
                    containerConfig.Image,
                    this.activationArgs.ContainerDescription.ApplicationId);

                return;
            }
            catch (ContainerApiException ex)
            {
                if (ex.StatusCode == HttpStatusCode.NotFound && retryDownload == true)
                {
                    HostingTrace.Source.WriteInfo(
                        TraceType,
                        "Image not found while creating Container={0} from Image={1} for AppId={2}. StatusCode={3}, ResponseBody={4}.",
                        containerName,
                        containerConfig.Image,
                        activationArgs.ContainerDescription.ApplicationId,
                        ex.StatusCode,
                        ex.ResponseBody);
                }
                else if (ex.StatusCode == HttpStatusCode.Conflict)
                {
                    //
                    // This can happen in case of retries when docker request timeout.
                    // The client connection is close but docker might have just created
                    // the container.
                    //
                    containerExist = true;

                    HostingTrace.Source.WriteInfo(
                        TraceType,
                        "Container already exists while Creating Container={0} from Image={1} for AppId={2}. StatusCode={3}, ResponseBody={4}.",
                        containerName,
                        containerConfig.Image,
                        activationArgs.ContainerDescription.ApplicationId,
                        ex.StatusCode,
                        ex.ResponseBody);
                }
                else
                {
                    var errorMessage = string.Format(
                        "Creating Container from Image={0} failed for {1}.",
                        containerConfig.Image,
                        this.BuildErrorMessage(ex));

                    this.TraceAndThrow(errorMessage);
                }
            }
            catch (Exception ex)
            {
                var errorMessage = string.Format(
                    "Creating Container from Image={0} failed for {1}.",
                    containerConfig.Image,
                    this.BuildErrorMessage(ex));

                this.TraceAndThrow(errorMessage);
            }

            if (containerExist)
            {
                var success = await this.GetContainerIdAsync(containerName, containerConfig);

                if (!success)
                {
                    await this.CreateContainerInnerAsync(containerConfig, true);
                }

                return;
            }

            //
            // skipCacheCheck=true to handle the case where an image is
            // deleted outside knowledge of FabricCAS
            //

            var imageDescription = new ContainerImageDescription();

            imageDescription.ImageName = this.activationArgs.ProcessDescription.ExePath;
            imageDescription.UseDefaultRepositoryCredentials   = this.activationArgs.ContainerDescription.UseDefaultRepositoryCredentials;
            imageDescription.UseTokenAuthenticationCredentials = this.activationArgs.ContainerDescription.UseTokenAuthenticationCredentials;
            imageDescription.RepositoryCredential = this.activationArgs.ContainerDescription.RepositoryCredential;

            await this.activator.ImageDownloader.DownloadImageAsync(imageDescription, HostingConfig.Config.ContainerImageDownloadTimeout, true /*skipCacheCheck*/);

            await this.CreateContainerInnerAsync(containerConfig, false);
        }
コード例 #2
0
        public async Task DownloadImageAsync(ContainerImageDescription imageDescription, TimeSpan timeout, bool skipCacheCheck = false)
        {
            var timeoutHelper = new TimeoutHelper(timeout);

            var  imageTags = imageDescription.ImageName.Split(':');
            bool isLatest  = false;

            if (imageTags.Length < 2 || String.IsNullOrEmpty(imageTags[1]))
            {
                imageDescription.ImageName = String.Concat(imageDescription.ImageName, ":latest");
                isLatest = true;
            }

            if (!skipCacheCheck && !isLatest)
            {
                if (this.IsImageCached(imageDescription.ImageName))
                {
                    HostingTrace.Source.WriteInfo(
                        TraceType,
                        "Container image download skipped as it is cached: ImageName={0}, Time={1}ms .", imageDescription.ImageName, 0);
                    return;
                }

                if (await this.IsImagePresentLocallyAsync(imageDescription.ImageName, timeoutHelper.RemainingTime))
                {
                    HostingTrace.Source.WriteInfo(
                        TraceType,
                        "Container image download skipped as it is present locally: ImageName={0}, Time={1}ms .", imageDescription.ImageName, 0);
                    this.AddImageToCache(imageDescription.ImageName);

                    return;
                }
            }

            CredentialType currentCredentialAttempt;

            if (imageDescription.UseTokenAuthenticationCredentials)
            {
                currentCredentialAttempt = CredentialType.TokenCredentials;
            }
            else if (imageDescription.UseDefaultRepositoryCredentials)
            {
                currentCredentialAttempt = CredentialType.ClusterManifestDefaultCredentials;
            }
            else
            {
                currentCredentialAttempt = CredentialType.AppManifestCredentials;
            }

            try
            {
                AuthConfig authConfig = this.GetAuthConfig(imageDescription.RepositoryCredential, imageDescription.ImageName, currentCredentialAttempt);

                var downloadProgressStream = await Utility.ExecuteWithRetriesAsync(
                    (operationTimeout) =>
                {
                    return(this.ImageOperation.CreateImageAsync(
                               imageDescription.ImageName,
                               authConfig,
                               operationTimeout));
                },
                    $"CreateImageAsync_{imageDescription.ImageName}",
                    TraceType,
                    HostingConfig.Config.DockerRequestTimeout,
                    timeoutHelper.RemainingTime);

                await this.TrackDownloadProgressAsync(
                    imageDescription.ImageName, downloadProgressStream, timeoutHelper.RemainingTime);

                if (!await this.IsImagePresentLocallyAsync(imageDescription.ImageName, timeoutHelper.RemainingTime))
                {
                    throw new Exception(
                              $"Container image download failed - ImageName={imageDescription.ImageName}. " +
                              $"Please check if container image OS is compatible with host OS or if you have sufficient disk space on the machine. " +
                              $"Try to pull the image manually on the machine using docker CLI for further error details. ");
                }

                this.AddImageToCache(imageDescription.ImageName);
            }
            catch (ContainerApiException dex)
            {
                var errMsgBuilder = new StringBuilder();

                errMsgBuilder.AppendFormat(
                    "Container image download failed with authorization attempt type {0} for ImageName={1}. DockerRequest returned StatusCode={2} with ResponseBody={3}.",
                    currentCredentialAttempt.ToString(),
                    imageDescription.ImageName,
                    dex.StatusCode,
                    dex.ResponseBody);

                if (dex.StatusCode == HttpStatusCode.NotFound)
                {
                    errMsgBuilder.Append(
                        "Please check if image is present in repository or repository credentials provided are correct.");
                }

                HostingTrace.Source.WriteWarning(TraceType, errMsgBuilder.ToString());
                throw new FabricException(errMsgBuilder.ToString(), FabricErrorCode.InvalidOperation);
            }
            catch (Exception ex)
            {
                var errMsgBuilder = new StringBuilder();

                errMsgBuilder.AppendFormat(
                    "Container image download failed with authorization attempt type {0} for ImageName={1} with unexpected error. Exception={2}.",
                    currentCredentialAttempt.ToString(),
                    imageDescription.ImageName,
                    ex.ToString());

                HostingTrace.Source.WriteWarning(TraceType, errMsgBuilder.ToString());
                throw new FabricException(errMsgBuilder.ToString(), FabricErrorCode.InvalidOperation);
            }
        }