public void UpdateSites(IEnumerable<WebSite> sites, List<string> sitesToIgnore = null)
{
_logger.DebugFormat("Sites list from table: {0}", string.Join(",", sites.Select(s => s.Name)));
using (var serverManager = new ServerManager())
{
var iisSites = serverManager.Sites;
_logger.DebugFormat("Sites list from IIS: {0}", string.Join(",", iisSites.Select(s => s.Name)));
// Find sites that need to be removed
foreach (var iisSite in iisSites.ToArray())
{
var name = iisSite.Name.ToLowerInvariant();
// Never delete "webRoleSiteName", which is the website for this web role
if (!name.Equals(AzureRoleEnvironment.RoleWebsiteName(), StringComparison.OrdinalIgnoreCase) &&
!sites.Select(s => s.Name.ToLowerInvariant()).Contains(name) &&
sitesToIgnore.All(s => name != s.ToLowerInvariant()))
{
// Remove site
_logger.InfoFormat("Removing site '{0}'", iisSite.Name);
serverManager.Sites.Remove(iisSite);
// Remove TEST and CDN applications
RemoveApplications(iisSites, name);
// Remove site path
try
{
var sitePath = Path.Combine(_localSitesPath, iisSite.Name);
var tempSitePath = Path.Combine(_tempSitesPath, iisSite.Name);
FilesHelper.RemoveFolder(sitePath, _logger);
FilesHelper.RemoveFolder(tempSitePath, _logger);
}
catch (Exception e)
{
_logger.Warn("Error removing site path", e);
}
// Remove appPool
var appPool = serverManager.ApplicationPools.SingleOrDefault(ap => ap.Name.Equals(iisSite.Name, StringComparison.OrdinalIgnoreCase));
if (appPool != null)
{
_logger.InfoFormat("Removing app pool '{0}'", appPool.Name);
serverManager.ApplicationPools.Remove(appPool);
}
}
}
try
{
serverManager.CommitChanges();
}
catch (Exception e)
{
_logger.Error("Error committing changes to IIS while updating sites", e);
}
}
foreach (var site in sites)
{
using (var serverManager = new ServerManager())
{
var siteName = site.Name.ToLowerInvariant().Replace(" ", string.Empty);
var iisSite = serverManager.Sites.SingleOrDefault(ap => ap.Name.Equals(siteName, StringComparison.OrdinalIgnoreCase));
var sitePath = Path.Combine(_localSitesPath, siteName);
// Add new sites
if (iisSite == null)
{
// Update Status
_syncStatusRepository.UpdateStatus(siteName, SyncInstanceStatus.NotCreated);
// Create physical path
if (!Directory.Exists(sitePath))
{
Directory.CreateDirectory(sitePath);
}
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("AzureWebFarm.Resources.index.html"))
{
var fileContent = new StreamReader(stream).ReadToEnd().Replace("{WebSiteName}", siteName);
File.WriteAllText(Path.Combine(sitePath, "index.html"), fileContent);
}
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("AzureWebFarm.Resources.site.css"))
{
var fileContent = new StreamReader(stream).ReadToEnd();
File.WriteAllText(Path.Combine(sitePath, "site.css"), fileContent);
}
// Add web site
_logger.InfoFormat("Adding site '{0}'", siteName);
var defaultBinding = site.Bindings.First();
X509Certificate2 cert = null;
if (!String.IsNullOrEmpty(defaultBinding.CertificateThumbprint))
{
cert = GetCertificate(defaultBinding.CertificateThumbprint);
}
if (cert != null)
{
_logger.InfoFormat("Adding website '{0}' with Binding Information '{1}' and Certificate '{2}'", site.Name, defaultBinding.BindingInformation, cert.Thumbprint);
iisSite = serverManager.Sites.Add(
siteName,
defaultBinding.BindingInformation,
sitePath,
cert.GetCertHash());
}
else
{
_logger.InfoFormat("Adding website '{0}' with Binding Information '{1}'", site.Name, defaultBinding.BindingInformation);
iisSite = serverManager.Sites.Add(
siteName,
defaultBinding.Protocol,
defaultBinding.BindingInformation,
sitePath);
}
// Create a new AppPool
var appPool = serverManager.ApplicationPools.SingleOrDefault(ap => ap.Name.Equals(siteName, StringComparison.OrdinalIgnoreCase));
if (appPool == null)
{
_logger.InfoFormat("Adding app pool '{0}' for site '{0}'", siteName);
appPool = serverManager.ApplicationPools.Add(siteName);
appPool.ManagedRuntimeVersion = "v4.0";
appPool.ProcessModel.IdentityType = ProcessModelIdentityType.NetworkService;
}
iisSite.ApplicationDefaults.ApplicationPoolName = appPool.Name;
// Update TEST and CDN applications
UpdateApplications(site, serverManager, siteName, sitePath, appPool);
// Update Sync Status
_syncStatusRepository.UpdateStatus(siteName, SyncInstanceStatus.Created);
}
else
{
// Update TEST and CDN applications
var appPool = serverManager.ApplicationPools.SingleOrDefault(ap => ap.Name.Equals(siteName, StringComparison.OrdinalIgnoreCase));
UpdateApplications(site, serverManager, siteName, sitePath, appPool);
}
// Find bindings that need to be removed
foreach (var binding in iisSite.Bindings.ToArray())
{
if (!site.Bindings.Any(b => AreEqualsBindings(binding, b)))
{
_logger.InfoFormat("Removing binding with protocol '{0}' from website '{1}'", binding.Protocol, site);
iisSite.Bindings.Remove(binding);
}
}
// Add new bindings
foreach (var binding in site.Bindings)
{
var iisBinding = iisSite.Bindings.SingleOrDefault(b => AreEqualsBindings(b, binding));
if (iisBinding == null)
{
X509Certificate2 cert = null;
if (!String.IsNullOrEmpty(binding.CertificateThumbprint))
{
cert = GetCertificate(binding.CertificateThumbprint);
}
if (cert != null)
{
_logger.InfoFormat("Adding Binding '{0}' for website '{1}' with Binding Information '{2}' and Certificate '{3}'", binding.Id, site.Name, binding.BindingInformation, cert.Thumbprint);
iisSite.Bindings.Add(binding.BindingInformation, cert.GetCertHash(), StoreName.My.ToString());
}
else
{
_logger.InfoFormat("Adding Binding '{0}' for WebSite '{1}' with Binding Information '{2}'", binding.Id, site.Name, binding.BindingInformation);
iisSite.Bindings.Add(binding.BindingInformation, binding.Protocol);
}
}
}
try
{
_logger.DebugFormat("Committing updates to IIS for site '{0}'", site.Name);
serverManager.CommitChanges();
}
catch (Exception e)
{
_syncStatusRepository.UpdateStatus(siteName, SyncInstanceStatus.Error, e);
_logger.ErrorFormat(e, "Error committing changes for site '{0}'", site.Name);
}
}
}
}