public SiteExtensionInfo InstallExtension(string id, SiteExtensionInfo requestInfo)
        {
            if (requestInfo == null)
            {
                requestInfo = new SiteExtensionInfo();
            }

            SiteExtensionInfo extension;

            try
            {
                extension = _manager.InstallExtension(id, requestInfo.Version, requestInfo.FeedUrl);
            }
            catch (WebException e)
            {
                // This can happen for example if a bad feed URL is passed
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Site extension download failure", e));
            }
            catch (Exception e)
            {
                // This can happen for example if the exception package is corrupted
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Site extension install exception. The package might be invalid.", e));
            }

            if (extension == null)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, "Could not find " + id));
            }

            return extension;
        }
 public SiteExtensionInfo InstallExtension(SiteExtensionInfo info)
 {
     SiteExtensionInfo extension = _manager.InstallExtension(info);
     if (extension == null)
     {
         throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, info.ToString()));
     }
     return extension;
 }
        public async Task<HttpResponseMessage> InstallExtension(string id, SiteExtensionInfo requestInfo)
        {
            var startTime = DateTime.UtcNow;
            if (requestInfo == null)
            {
                requestInfo = new SiteExtensionInfo();
            }

            SiteExtensionInfo result;

            try
            {
                result = await _manager.InstallExtension(id, requestInfo.Version, requestInfo.FeedUrl);
            }
            catch (WebException e)
            {
                // This can happen for example if a bad feed URL is passed
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Site extension download failure", e));
            }
            catch (Exception e)
            {
                // This can happen for example if the exception package is corrupted
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Site extension install exception. The package might be invalid.", e));
            }

            if (result == null)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, "Could not find " + id));
            }

            // TODO: xiaowu, when update to real csm async, should return "Accepted" instead of "OK"
            var responseMessage = Request.CreateResponse(HttpStatusCode.OK, ArmUtils.AddEnvelopeOnArmRequest<SiteExtensionInfo>(result, Request));

            if (result != null  // result not null indicate instalation success, when move to async operation, will relying on provisionState instead
                && result.InstalledDateTime.HasValue
                && result.InstalledDateTime.Value > startTime
                && ArmUtils.IsArmRequest(Request))
            {
                // Populate this header if 
                //      Request is from ARM
                //      Installation action is performed
                responseMessage.Headers.Add("X-MS-SITE-OPERATION", Constants.SiteOperationRestart);
            }

            return responseMessage;
        }
 public SiteExtensionInfo(SiteExtensionInfo info)
 {
     Id = info.Id;
     Title = info.Title;
     Type = info.Type;
     Summary = info.Summary;
     Description = info.Description;
     Version = info.Version;
     ExtensionUrl = info.ExtensionUrl;
     ProjectUrl = info.ProjectUrl;
     IconUrl = info.IconUrl;
     LicenseUrl = info.LicenseUrl;
     Authors = info.Authors;
     PublishedDateTime = info.PublishedDateTime;
     IsLatestVersion = info.IsLatestVersion;
     DownloadCount = info.DownloadCount;
     LocalIsLatestVersion = info.LocalIsLatestVersion;
     LocalPath = info.LocalPath;
     InstalledDateTime = info.InstalledDateTime;
 }
Exemple #5
0
 public SiteExtensionInfo(SiteExtensionInfo info)
 {
     Id                   = info.Id;
     Title                = info.Title;
     Type                 = info.Type;
     Summary              = info.Summary;
     Description          = info.Description;
     Version              = info.Version;
     ExtensionUrl         = info.ExtensionUrl;
     ProjectUrl           = info.ProjectUrl;
     IconUrl              = info.IconUrl;
     LicenseUrl           = info.LicenseUrl;
     Authors              = info.Authors;
     PublishedDateTime    = info.PublishedDateTime;
     IsLatestVersion      = info.IsLatestVersion;
     DownloadCount        = info.DownloadCount;
     LocalIsLatestVersion = info.LocalIsLatestVersion;
     LocalPath            = info.LocalPath;
     InstalledDateTime    = info.InstalledDateTime;
 }
        /// <summary>
        /// <para>1. Download package</para>
        /// <para>2. Generate xdt file if not exist</para>
        /// <para>3. Deploy site extension job</para>
        /// <para>4. Execute install.cmd if exist</para>
        /// </summary>
        private async Task<UIPackageMetadata> InstallExtension(UIPackageMetadata package, string installationDirectory, string feedUrl, SiteExtensionInfo.SiteExtensionType type, ITracer tracer)
        {
            try
            {
                EnsureInstallationEnviroment(installationDirectory, tracer);

                string packageLocalFilePath = GetNuGetPackageFile(package.Identity.Id, package.Identity.Version.ToNormalizedString());
                bool packageExisted = FileSystemHelpers.DirectoryExists(installationDirectory);
                SourceRepository remoteRepo = GetRemoteRepository(feedUrl);

                using (tracer.Step("Download site extension: {0}", package.Identity))
                {
                    string extractPath = installationDirectory;
                    if (SiteExtensionInfo.SiteExtensionType.WebRoot == type)
                    {
                        extractPath = _environment.WebRootPath;
                        FileSystemHelpers.EnsureDirectory(extractPath);
                    }

                    // Copy/update content folder
                    // Copy/update nupkg file for package list/lookup
                    if (packageExisted)
                    {
                        await remoteRepo.UpdateLocalPackage(_localRepository, package.Identity, extractPath, packageLocalFilePath, tracer);
                    }
                    else
                    {
                        FileSystemHelpers.EnsureDirectory(installationDirectory);
                        await remoteRepo.DownloadPackageToFolder(package.Identity, extractPath, packageLocalFilePath);
                    }

                    if (SiteExtensionInfo.SiteExtensionType.WebRoot == type)
                    {
                        // if install to WebRoot, check if there is any xdt file come with package
                        // if there is one, move it to site extension folder
                        string xdtFile = Path.Combine(extractPath, Constants.ApplicationHostXdtFileName);
                        if (File.Exists(xdtFile))
                        {
                            tracer.Trace("Use xdt file from package.");
                            string newXdtFile = Path.Combine(installationDirectory, Constants.ApplicationHostXdtFileName);

                            tracer.Trace("Moving {0} to {1}", xdtFile, newXdtFile);
                            FileSystemHelpers.MoveFile(xdtFile, newXdtFile);
                        }
                        else
                        {
                            tracer.Trace("No xdt file come with package.");
                        }
                    }
                }

                // ignore below action if we install packge to wwwroot
                if (SiteExtensionInfo.SiteExtensionType.WebRoot != type)
                {
                    // If there is no xdt file, generate default.
                    using (tracer.Step("Check if applicationhost.xdt file existed."))
                    {
                        GenerateApplicationHostXdt(installationDirectory, '/' + package.Identity.Id, isPreInstalled: false, tracer: tracer);
                    }

                    using (tracer.Step("Trigger site extension job"))
                    {
                        OperationManager.Attempt(() => DeploySiteExtensionJobs(package.Identity.Id));
                    }

                    var externalCommandFactory = new ExternalCommandFactory(_environment, _settings, installationDirectory);
                    string installScript = Path.Combine(installationDirectory, _installScriptName);
                    if (FileSystemHelpers.FileExists(installScript))
                    {
                        using (tracer.Step("Execute install.cmd"))
                        {
                            OperationManager.Attempt(() =>
                            {
                                Executable exe = externalCommandFactory.BuildCommandExecutable(installScript,
                                    installationDirectory,
                                    _settings.GetCommandIdleTimeout(), NullLogger.Instance);
                                exe.ExecuteWithProgressWriter(NullLogger.Instance, _traceFactory.GetTracer(), String.Empty);
                            });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                tracer.TraceError(ex);
                FileSystemHelpers.DeleteDirectorySafe(installationDirectory);
                throw;
            }

            return await _localRepository.GetLatestPackageById(package.Identity.Id);
        }
        public SiteExtensionInfo ConvertRemotePackageToSiteExtensionInfo(IPackage package)
        {
            var info = new SiteExtensionInfo(package);

            IPackage localPackage = _localRepository.FindPackage(info.Id);
            if (localPackage != null)
            {
                UpdateLocalInfo(info);
                // Assume input package (from remote) is always the latest version.
                info.LocalIsLatestVersion = package.Version == localPackage.Version;
            }

            return info;
        }
Exemple #8
0
        private static void SetPreInstalledExtensionInfo(SiteExtensionInfo info)
        {
            string directory = GetPreInstalledDirectory(info.Id);

            if (FileSystemHelpers.DirectoryExists(directory))
            {
                if (info.Type == SiteExtensionInfo.SiteExtensionType.PreInstalledMonaco)
                {
                    info.Version = GetPreInstalledLatestVersion(directory);
                }
                else if (info.Type == SiteExtensionInfo.SiteExtensionType.PreInstalledEnabled)
                {
                    info.Version = typeof(SiteExtensionManager).Assembly.GetName().Version.ToString();
                }

                info.PublishedDateTime = FileSystemHelpers.GetLastWriteTimeUtc(directory);
            }
            else
            {
                info.Version = null;
                info.PublishedDateTime = null;
            }

            info.LocalIsLatestVersion = true;
        }
Exemple #9
0
        private SiteExtensionInfo ConvertLocalPackageToSiteExtensionInfo(IPackage package, bool checkLatest)
        {
            if (package == null)
            {
                return null;
            }

            var info = new SiteExtensionInfo(package);

            SetLocalInfo(info);

            if (checkLatest)
            {
                // FindPackage gets back the latest version.
                IPackage latestPackage = GetRemoteRepository(info.FeedUrl).FindPackage(info.Id);
                if (latestPackage != null)
                {
                    info.LocalIsLatestVersion = package.Version == latestPackage.Version;
                    info.DownloadCount = latestPackage.DownloadCount;
                    info.PublishedDateTime = latestPackage.Published;
                }
            }

            return info;
        }
Exemple #10
0
        private static string GetUrlFromApplicationHost(SiteExtensionInfo info)
        {
            try
            {
                var appHostDoc = new XmlDocument();
                appHostDoc.Load(Path.Combine(info.LocalPath, _applicationHostFile));

                // Get the 'path' property of the first 'application' element, which is the relative url.
                XmlNode pathPropertyNode = appHostDoc.SelectSingleNode("//application[@path]/@path");

                return pathPropertyNode.Value;
            }
            catch (SystemException)
            {
                return null;
            }
        }
Exemple #11
0
        private SiteExtensionInfo EnablePreInstalledExtension(SiteExtensionInfo info)
        {
            string id = info.Id;
            string installationDirectory = GetInstallationDirectory(id);

            try
            {
                if (FileSystemHelpers.DirectoryExists(installationDirectory))
                {
                    FileSystemHelpers.DeleteDirectorySafe(installationDirectory);
                }

                if (ExtensionRequiresApplicationHost(info))
                {
                    if (info.Type == SiteExtensionInfo.SiteExtensionType.PreInstalledMonaco)
                    {
                        GenerateApplicationHostXdt(installationDirectory,
                            _preInstalledExtensionDictionary[id].ExtensionUrl, isPreInstalled: true);
                    }
                }
                else
                {
                    FileSystemHelpers.CreateDirectory(installationDirectory);
                }
            }
            catch (Exception ex)
            {
                ITracer tracer = _traceFactory.GetTracer();
                tracer.TraceError(ex);
                FileSystemHelpers.DeleteDirectorySafe(installationDirectory);
                return null;
            }

            return GetPreInstalledExtension(id);
        }
 private async Task TryCheckLocalPackageLatestVersionFromRemote(SiteExtensionInfo info, bool checkLatest, ITracer tracer = null)
 {
     if (checkLatest)
     {
         try
         {
             // FindPackage gets back the latest version.
             SourceRepository remoteRepo = GetRemoteRepository(info.FeedUrl);
             UIPackageMetadata latestPackage = await remoteRepo.GetLatestPackageById(info.Id);
             if (latestPackage != null)
             {
                 NuGetVersion currentVersion = NuGetVersion.Parse(info.Version);
                 info.LocalIsLatestVersion = NuGetVersion.Parse(info.Version).Equals(latestPackage.Identity.Version);
                 info.DownloadCount = latestPackage.DownloadCount;
                 info.PublishedDateTime = latestPackage.Published;
             }
         }
         catch (Exception ex)
         {
             if (tracer != null)
             {
                 tracer.TraceError(ex);
             }
         }
     }
 }
 public async Task<SiteExtensionInfo> InstallExtension(SiteExtensionInfo info)
 {
     return await Client.PostJsonAsync<SiteExtensionInfo, SiteExtensionInfo>(String.Empty, info);
 }
 private static bool ExtensionRequiresApplicationHost(SiteExtensionInfo info)
 {
     string appSettingName = info.Id.ToUpper(CultureInfo.CurrentCulture) + "_EXTENSION_VERSION";
     return ConfigurationManager.AppSettings[appSettingName] != "beta";
 }
        private void SetLocalInfo(SiteExtensionInfo info)
        {
            string localPath = GetInstallationDirectory(info.Id);
            if (FileSystemHelpers.DirectoryExists(localPath))
            {
                info.LocalPath = localPath;
                info.InstalledDateTime = FileSystemHelpers.GetLastWriteTimeUtc(info.LocalPath);
            }

            if (ExtensionRequiresApplicationHost(info))
            {
                info.ExtensionUrl = FileSystemHelpers.FileExists(Path.Combine(localPath, Constants.ApplicationHostXdtFileName))
                    ? GetFullUrl(GetUrlFromApplicationHost(info)) : null;
            }
            else
            {
                info.ExtensionUrl = String.IsNullOrEmpty(info.LocalPath) ? null : GetFullUrl(info.ExtensionUrl);
            }

            foreach (var setting in GetSettingManager(info.Id).GetValues())
            {
                if (String.Equals(setting.Key, _feedUrlSetting, StringComparison.OrdinalIgnoreCase))
                {
                    info.FeedUrl = setting.Value.Value<string>();
                }
                else if (String.Equals(setting.Key, _installUtcTimestampSetting, StringComparison.OrdinalIgnoreCase))
                {
                    DateTime installedDateTime;
                    if (DateTime.TryParse(setting.Value.Value<string>(), out installedDateTime))
                    {
                        info.InstalledDateTime = installedDateTime.ToUniversalTime();
                    }
                }
            }
        }
 public SiteExtensionInfo InstallExtension(SiteExtensionInfo info)
 {
     return InstallExtension(info.Id);
 }
        public SiteExtensionInfo ConvertLocalPackageToSiteExtensionInfo(IPackage package, bool checkLatest = true)
        {
            var info = new SiteExtensionInfo(package);

            UpdateLocalInfo(info);
            if (checkLatest)
            {
                // FindPackage gets back the latest version.
                IPackage latestPackage = _remoteRepository.FindPackage(info.Id);
                info.LocalIsLatestVersion = package.Version == latestPackage.Version;
            }

            return info;
        }
        private async Task<SiteExtensionInfo> CheckRemotePackageLatestVersion(SiteExtensionInfo info, string feedUrl)
        {
            info.FeedUrl = feedUrl;
            UIPackageMetadata localPackage = await _localRepository.GetLatestPackageById(info.Id);

            if (localPackage != null)
            {
                SetLocalInfo(info);
                // Assume input package (from remote) is always the latest version.
                info.LocalIsLatestVersion = NuGetVersion.Parse(info.Version).Equals(localPackage.Identity.Version);
            }

            return info;
        }
 public void FillSiteExtensionInfo(SiteExtensionInfo info, string defaultProvisionState = null)
 {
     info.ProvisioningState = ProvisioningState ?? defaultProvisionState;
     info.Comment = Comment;
 }
        private async Task<SiteExtensionInfo> ConvertLocalPackageToSiteExtensionInfo(UIPackageMetadata package, bool checkLatest, ITracer tracer = null)
        {
            if (package == null)
            {
                return null;
            }

            var info = new SiteExtensionInfo(package);
            if (IsInstalledToWebRoot(info.Id))
            {
                info.Type = SiteExtensionInfo.SiteExtensionType.WebRoot;
            }

            SetLocalInfo(info);
            await TryCheckLocalPackageLatestVersionFromRemote(info, checkLatest, tracer);
            return info;
        }
 public void ReadSiteExtensionInfo(SiteExtensionInfo info)
 {
     ProvisioningState = info.ProvisioningState;
     Comment = info.Comment;
 }
Exemple #22
0
        private SiteExtensionInfo GetPreInstalledExtension(string id)
        {
            if (_preInstalledExtensionDictionary.ContainsKey(id))
            {
                var info = new SiteExtensionInfo(_preInstalledExtensionDictionary[id]);

                SetLocalInfo(info);

                SetPreInstalledExtensionInfo(info);

                return info;
            }
            else
            {
                return null;
            }
        }
Exemple #23
0
        private void SetLocalInfo(SiteExtensionInfo info)
        {
            string localPath = GetInstallationDirectory(info.Id);
            if (FileSystemHelpers.DirectoryExists(localPath))
            {
                info.LocalPath = localPath;
                info.InstalledDateTime = FileSystemHelpers.GetLastWriteTimeUtc(info.LocalPath);
            }

            if (ExtensionRequiresApplicationHost(info))
            {
                if (FileSystemHelpers.FileExists(Path.Combine(localPath, _applicationHostFile)))
                {
                    info.ExtensionUrl = GetFullUrl(GetUrlFromApplicationHost(info));
                }
                else
                {
                    info.ExtensionUrl = null;
                }
            }
            else
            {
                if (!String.IsNullOrEmpty(info.LocalPath))
                {
                    info.ExtensionUrl = GetFullUrl(info.ExtensionUrl);
                }
                else
                {
                    info.ExtensionUrl = null;
                }
            }
        }
Exemple #24
0
        private void SetLocalInfo(SiteExtensionInfo info)
        {
            string localPath = GetInstallationDirectory(info.Id);
            if (FileSystemHelpers.DirectoryExists(localPath))
            {
                info.LocalPath = localPath;
                info.InstalledDateTime = FileSystemHelpers.GetLastWriteTimeUtc(info.LocalPath);
            }

            if (ExtensionRequiresApplicationHost(info))
            {
                info.ExtensionUrl = FileSystemHelpers.FileExists(Path.Combine(localPath, _applicationHostFile))
                    ? GetFullUrl(GetUrlFromApplicationHost(info)) : null;
            }
            else if (String.Equals(info.Id, "Monaco", StringComparison.OrdinalIgnoreCase))
            {
                // Monaco does not need ApplicationHost only when it is enabled through app setting
                info.ExtensionUrl = GetFullUrl(info.ExtensionUrl);
            }
            else
            {
                info.ExtensionUrl = String.IsNullOrEmpty(info.LocalPath) ? null : GetFullUrl(info.ExtensionUrl);
            }

            info.FeedUrl = GetSettingManager(info.Id).GetValue(_feedUrlSetting);
        }
        private SiteExtensionInfo ConvertLocalPackageToSiteExtensionInfo(IPackage package, bool checkLatest = true)
        {
            var info = new SiteExtensionInfo(package);

            SetLocalInfo(info);

            if (checkLatest)
            {
                // FindPackage gets back the latest version.
                IPackage latestPackage = _remoteRepository.FindPackage(info.Id);
                if (latestPackage != null)
                {
                    info.LocalIsLatestVersion = package.Version == latestPackage.Version;
                    info.DownloadCount = package.DownloadCount;
                }
            }

            return info;
        }
Exemple #26
0
        private SiteExtensionInfo ConvertRemotePackageToSiteExtensionInfo(IPackage package, string feedUrl)
        {
            var info = new SiteExtensionInfo(package);

            info.FeedUrl = feedUrl;

            IPackage localPackage = _localRepository.FindPackage(info.Id);
            if (localPackage != null)
            {
                SetLocalInfo(info);
                // Assume input package (from remote) is always the latest version.
                info.LocalIsLatestVersion = package.Version == localPackage.Version;
            }

            return info;
        }
        // <inheritdoc />
        public async Task<SiteExtensionInfo> InstallExtension(string id, string version, string feedUrl, SiteExtensionInfo.SiteExtensionType type, ITracer tracer)
        {
            try
            {
                using (tracer.Step("Installing '{0}' version '{1}' from '{2}'", id, version, feedUrl))
                {
                    var installationLock = SiteExtensionInstallationLock.CreateLock(_environment.SiteExtensionSettingsPath, id, enableAsync: true);
                    // hold on to lock till action complete (success or fail)
                    return await installationLock.LockOperationAsync<SiteExtensionInfo>(async () =>
                    {
                        return await TryInstallExtension(id, version, feedUrl, type, tracer);
                    }, "Installing SiteExtension", TimeSpan.Zero);
                }
            }
            catch (Exception ex)
            {
                _analytics.UnexpectedException(
                        ex,
                        method: "PUT",
                        path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id),
                        result: Constants.SiteExtensionProvisioningStateFailed,
                        message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl),
                        trace: false);

                // handle unexpected exception
                tracer.TraceError(ex);

                var info = new SiteExtensionInfo();
                info.Id = id;

                SiteExtensionStatus armStatus = new SiteExtensionStatus(_environment.SiteExtensionSettingsPath, id, tracer);
                armStatus.Operation = Constants.SiteExtensionOperationInstall;
                armStatus.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed;
                armStatus.Status = HttpStatusCode.BadRequest;
                armStatus.FillSiteExtensionInfo(info);
                tracer.Trace("Update arm settings for {0} installation. Status: {1}", id, armStatus.Status);
                return info;
            }
        }
Exemple #28
0
 private static bool ExtensionRequiresApplicationHost(SiteExtensionInfo info)
 {
     string appSettingName = info.Id.ToUpper(CultureInfo.CurrentCulture) + "_EXTENSION_VERSION";
     bool enabledInSetting = ConfigurationManager.AppSettings[appSettingName] == "beta";
     return !(enabledInSetting || info.Type == SiteExtensionInfo.SiteExtensionType.PreInstalledEnabled);
 }
        private async Task<SiteExtensionInfo> TryInstallExtension(string id, string version, string feedUrl, SiteExtensionInfo.SiteExtensionType type, ITracer tracer)
        {
            SiteExtensionInfo info = null;
            HttpStatusCode status = HttpStatusCode.OK;  // final status when success
            bool alreadyInstalled = false;

            if (_preInstalledExtensionDictionary.ContainsKey(id))
            {
                tracer.Trace("Pre-installed site extension found: {0}, not going to perform new installation.", id);
                info = EnablePreInstalledExtension(_preInstalledExtensionDictionary[id], tracer);
                alreadyInstalled = true;
            }
            else
            {
                try
                {
                    // Check if site extension already installed (id, version, feedUrl), if already install return right away
                    if (await this.IsSiteExtensionInstalled(id, version, feedUrl))
                    {
                        // package already installed, return package from local repo.
                        tracer.Trace("Package {0} with version {1} from {2} already installed.", id, version, feedUrl);
                        info = await GetLocalExtension(id);
                        alreadyInstalled = true;
                    }
                    else
                    {
                        JsonSettings siteExtensionSettings = GetSettingManager(id);
                        feedUrl = (string.IsNullOrEmpty(feedUrl) ? siteExtensionSettings.GetValue(_feedUrlSetting) : feedUrl);
                        SourceRepository remoteRepo = GetRemoteRepository(feedUrl);
                        UIPackageMetadata localPackage = null;
                        UIPackageMetadata repoPackage = null;

                        if (this.IsInstalledToWebRoot(id))
                        {
                            // override WebRoot type from setting
                            // WebRoot is a special type that install package to wwwroot, when perform update we need to update new content to wwwroot even if type is not specified
                            type = SiteExtensionInfo.SiteExtensionType.WebRoot;
                        }

                        if (string.IsNullOrWhiteSpace(version))
                        {
                            using (tracer.Step("Version is null, search latest package by id: {0}, will not search for unlisted package.", id))
                            {
                                repoPackage = await remoteRepo.GetLatestPackageById(id);
                            }
                        }
                        else
                        {
                            using (tracer.Step("Search package by id: {0} and version: {1}, will also search for unlisted package.", id, version))
                            {
                                repoPackage = await remoteRepo.GetPackageByIdentity(id, version);
                            }
                        }

                        if (repoPackage != null)
                        {
                            using (tracer.Step("Install package: {0}.", id))
                            {
                                string installationDirectory = GetInstallationDirectory(id);
                                localPackage = await InstallExtension(repoPackage, installationDirectory, feedUrl, type, tracer);
                                siteExtensionSettings.SetValues(new KeyValuePair<string, JToken>[] {
                                    new KeyValuePair<string, JToken>(_versionSetting, localPackage.Identity.Version.ToNormalizedString()),
                                    new KeyValuePair<string, JToken>(_feedUrlSetting, feedUrl),
                                    new KeyValuePair<string, JToken>(_installUtcTimestampSetting, DateTime.UtcNow.ToString("u")),
                                    new KeyValuePair<string, JToken>(_packageType, Enum.GetName(typeof(SiteExtensionInfo.SiteExtensionType), type))
                                });
                            }
                        }

                        info = await ConvertLocalPackageToSiteExtensionInfo(localPackage, checkLatest: true, tracer: tracer);
                    }
                }
                catch (FileNotFoundException ex)
                {
                    _analytics.UnexpectedException(
                        ex,
                        method: "PUT",
                        path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id),
                        result: Constants.SiteExtensionProvisioningStateFailed,
                        message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl),
                        trace: false);

                    tracer.TraceError(ex);
                    info = new SiteExtensionInfo();
                    info.Id = id;
                    info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed;
                    info.Comment = ex.ToString();
                    status = HttpStatusCode.NotFound;
                }
                catch (WebException ex)
                {
                    _analytics.UnexpectedException(
                        ex,
                        method: "PUT",
                        path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id),
                        result: Constants.SiteExtensionProvisioningStateFailed,
                        message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl),
                        trace: false);

                    tracer.TraceError(ex);
                    info = new SiteExtensionInfo();
                    info.Id = id;
                    info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed;
                    info.Comment = ex.ToString();
                    status = HttpStatusCode.BadRequest;
                }
                catch (InvalidEndpointException ex)
                {
                    _analytics.UnexpectedException(ex, trace: false);

                    tracer.TraceError(ex);
                    info = new SiteExtensionInfo();
                    info.Id = id;
                    info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed;
                    info.Comment = ex.ToString();
                    status = HttpStatusCode.BadRequest;
                }
                catch (Exception ex)
                {
                    _analytics.UnexpectedException(
                        ex,
                        method: "PUT",
                        path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id),
                        result: Constants.SiteExtensionProvisioningStateFailed,
                        message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl),
                        trace: false);

                    tracer.TraceError(ex);
                    info = new SiteExtensionInfo();
                    info.Id = id;
                    info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed;
                    info.Comment = ex.ToString();
                    status = HttpStatusCode.BadRequest;
                }
            }

            if (info == null)
            {
                // treat this as an error case since no result return from repo
                _analytics.UnexpectedException(
                        new FileNotFoundException(id),
                        method: "PUT",
                        path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id),
                        result: Constants.SiteExtensionProvisioningStateFailed,
                        message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl),
                        trace: false);

                info = new SiteExtensionInfo();
                info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed;
                info.Comment = string.Format(Constants.SiteExtensionProvisioningStateNotFoundMessageFormat, id);
                status = HttpStatusCode.NotFound;
            }
            else if (!string.Equals(Constants.SiteExtensionProvisioningStateFailed, info.ProvisioningState, StringComparison.OrdinalIgnoreCase))
            {
                info.ProvisioningState = Constants.SiteExtensionProvisioningStateSucceeded;
                info.Comment = null;
            }

            using (tracer.Step("Update arm settings for {0} installation. Status: {1}", id, status))
            {
                SiteExtensionStatus armSettings = new SiteExtensionStatus(_environment.SiteExtensionSettingsPath, id, tracer);
                armSettings.ReadSiteExtensionInfo(info);
                armSettings.Status = status;
                armSettings.Operation = alreadyInstalled ? null : Constants.SiteExtensionOperationInstall;
            }

            return info;
        }
        public async Task<HttpResponseMessage> InstallExtension(string id, string version = null, string feedUrl = null, SiteExtensionInfo.SiteExtensionType? type = null)
        {
            var json = new JObject();
            json["version"] = version;
            json["feed_url"] = feedUrl;
            if (type.HasValue)
            {
                json["type"] = Enum.GetName(typeof(SiteExtensionInfo.SiteExtensionType), type.Value);
            }

            // if it is arm request, payload will be something like below
            /*
                {"properties":{
                    "version": "1.0.0",
                    "feed_url": "https://www.nuget.org/api/v2/"
                }}
             */
            if (Client.DefaultRequestHeaders.Contains(ArmUtils.GeoLocationHeaderKey))
            {
                JObject armProperties = json;
                json = new JObject();
                json["properties"] = armProperties;
            }

            return (await Client.PutAsJsonAsync("siteextensions/" + id, json)).EnsureSuccessful();
        }
 public void UpdateLocalInfo(SiteExtensionInfo info)
 {
     string localPath = GetInstallationDirectory(info.Id);
     if (FileSystemHelpers.DirectoryExists(localPath))
     {
         info.LocalPath = localPath;
         info.InstalledDateTime = FileSystemHelpers.GetLastWriteTimeUtc(info.LocalPath);
     }
 }