Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
param
(
[Parameter(Mandatory=$true)][string]$discoveryServiceUrl,
[Parameter(Mandatory=$true)][string]$csvSiteFile
)
#
# .\UpgradeSitesToWeb8.ps1 -discoveryServiceUrl "http://someserver:8882/discovery.svc" -csvSiteFile D:\SiteTest.csv -verbose
#Upgrade each site
# CSV File has format, "Site, Path"
# Example, MyWebsite.com, C:\InetPub\wwwroot\mywebsite.com
Function StartApplicationPool([string]$appPoolName)
{
if((Get-WebAppPoolState $appPoolName).Value -ne 'Started')
{
Start-WebAppPool -Name $appPoolName
}
}
Function StopApplicationPool([string]$appPoolName)
{
if((Get-WebAppPoolState $appPoolName).Value -ne 'Stopped')
{
Stop-WebAppPool -Name $appPoolName
}
}
#LOGGING STUFF
#Create Folder for logs
if (!(Test-Path -path "$PSScriptRoot\Web8MigrationLogs"))
{
New-Item -ItemType directory -Force -Path "$PSScriptRoot\Web8MigrationLogs"
}
$logfile = "$PSScriptRoot\Web8MigrationLogs\Web8MigrateDetailed.log"
Write-Host "Logging: $logfile"
$logfileSkippedSites = "$PSScriptRoot\Web8MigrationLogs\Web8MigrateSKIPPED.log"
function log($message)
{
$now = Get-Date -Format "MM-dd-yyyy_HH-mm-ss"
write-host $message
$message = "$now $message"
Add-content $logfile -value $message
}
function logInvalidSite($message)
{
$now = Get-Date -Format "MM-dd-yyyy_HH-mm-ss"
write-host $message
$message = "$now $message"
Add-content $logfileSkippedSites -value $message
}
$logfileWebConfigModules = "$PSScriptRoot\Web8MigrationLogs\WebConfigModulesCommented.log"
function logConfigModuleUpdates($message)
{
$now = Get-Date -Format "MM-dd-yyyy_HH-mm-ss"
Add-content $logfileWebConfigModules -value $message
}
$logfileSitesMigrated = "$PSScriptRoot\Web8MigrationLogs\SitesMigrated.log"
function logSitesMigrated($message)
{
$now = Get-Date -Format "MM-dd-yyyy_HH-mm-ss"
Add-content $logfileSitesMigrated -value $message
}
$logfileSitesNotMigrated = "$PSScriptRoot\Web8MigrationLogs\SitesNotMigrated.log"
function logSitesNotMigrated($message)
{
$now = Get-Date -Format "MM-dd-yyyy_HH-mm-ss"
Add-content $logfileSitesNotMigrated -value $message
}
#END LOGGING
log("`r`n====================== Input from $csvSiteFile ======================")
Function UpgradeSite()
{
<#
.SYNOPSIS
Upgrades a Tridion 2013 Website to Web 8 by removing the 2013 DLLS
.DESCRIPTION
Removes the lib folder, DLLs, and config files (zipped as a backup). Adds the Web 8 DLLs and config files.
Stops and Starts the AppPool for the site.
.PARAMETER productPath
tdp, tcw, or tpw
.PARAMETER websiteFilePath
The path to the Sites folder. Full Path is websiteFilePath + productPath. This is an optional parameter; if it is notincluded, no log file will be generated.
.PARAMERTER discoveryServiceUrl
URL to the Discovery service app config key that is added to web.config
.PARAMETER appPoolName
URL or Name of the Application Pool. Used to Stop / Start the app pool
.EXAMPLE
UpgradeSite -websiteFilePath $site.path -appPoolName $site.site -productPath $productPath -discoveryServiceUrl $discoveryServiceUrl
.NOTES
#>
Param
(
[Parameter(Mandatory=$true)][ValidateSet('tdp','tcw','tpw')][string]$productPath,
[string]$websiteFilePath,
[Parameter(Mandatory=$true)][string]$discoveryServiceUrl,
[Parameter(Mandatory=$true)][string]$appPoolName
)
$oAuthClientSecret = "CDUserP@ssw0rd"
$logfileWebsitesPath = "e:\LogFiles"
$ErrorActionPreference = "Stop"
$ConfirmPreference = "None" # don't ask in ISE mode for permissions when deleting files
$websiteUrlForLog = $appPoolName.Replace(".", "_")
#Create Folder for Site config backup
if (!(Test-Path -path "$PSScriptRoot\$websiteUrlForLog"))
{
$folderSiteLog = New-Item -ItemType directory -Force -Path "$PSScriptRoot\$websiteUrlForLog"
}
else
{
$folderSiteLog = Get-Item -Path "$PSScriptRoot\$websiteUrlForLog"
}
log("`r`n====================== Migrating Sites to Web 8 ======================")
log("`r`n====================== $appPoolName - $websiteFilePath ======================")
Import-Module WebAdministration
#VALIDATE APP POOL
if(-Not (Test-Path IIS:\AppPools\$appPoolName))
{
log "Cannot find AppPool for $appPoolName. Skipping"
Break
}
# Web 8 Source Files to Copy From
$web8Files = "E:\install\Web8WebsiteDLLs\"
$web8ConfigFiles = "E:\install\Web8WebsiteDLLs\config"
if(!$web8Files)
{
log "EXITING, NO Web 8 Files Found for $productPath"
Break
exit
}
if (!$websiteFilePath)
{
$websiteFilePath = "E:\Sites\websites"
}
$WebsitePath = $websiteFilePath
$binPath = Join-Path $WebsitePath bin
$confPath = Join-Path $binPath config
$libPath = Join-Path $binPath lib
$webConfigPath = Join-Path $WebsitePath "Web.config"
# Validate LIB folder and Web.config exist
if ( -Not (Test-Path $libPath.trim() ))
{
logInvalidSite "$appPoolName - Cannot find LIB Folder at path $libPath"
Return
}
if ( -Not (Test-Path $webConfigPath.trim() ))
{
logInvalidSite "$appPoolName no Web.Config at path $webConfigPath"
Return
}
#End Validations
#info to screen
log("`r`n====================== Disco: $discoveryServiceUrl ====================== " )
log("`r`n====================== Bin: $binPath ====================== " )
log("`r`n====================== Conf: $confPath ====================== " )
log("`r`n====================== Lib: $libPath ====================== " )
#Change web.config appSettings node from configSource to file in web.config
$webconfigFilesystem = Join-Path $WebsitePath "web.config"
log "Web.config file is $webconfigFilesystem"
[xml] $webConfigFile = Get-Content($webconfigFilesystem)
#comment out preview node
$previewContentModuleNode = $webConfigFile.SelectSingleNode("//system.webServer/modules/add[@name='PreviewContentModule']")
if($previewContentModuleNode)
{
$comment = $webConfigFile.CreateComment($previewContentModuleNode.OuterXml);
$previewContentModuleNode.ParentNode.ReplaceChild($comment, $previewContentModuleNode);
log "Web.config PreviewContentModule Commented out for $webConfigPath"
$webConfigFile.Save($webconfigFilesystem)
logConfigModuleUpdates $webconfigFilesystem
}
else
{
log 'No PreviewContentModule in Web.config'
}
#comment out ADF module
$adfModuleNode = $webConfigFile.SelectSingleNode("//system.webServer/modules/add[@name='Tridion.ContentDelivery.AmbientData.HttpModule']")
if($adfModuleNode)
{
$comment = $webConfigFile.CreateComment($adfModuleNode.OuterXml);
$adfModuleNode.ParentNode.ReplaceChild($comment, $adfModuleNode);
log "Web.config AmbientData.HttpModule module Commented out"
$webConfigFile.Save($webconfigFilesystem)
}
else
{
log 'No AmbientData.HttpModule in Web.config'
}
$appSettingsNode = $webConfigFile.configuration.appsettings
if($appSettingsNode.GetAttribute("configSource"))
{
log "Change web.config appSettings node from configSource to file in web.config"
$appSettingsNode.SetAttribute("file", $appSettingsNode.GetAttribute("configSource"))
$appSettingsNode.RemoveAttribute("configSource")
$webConfigFile.Save($webconfigFilesystem)
log "web.config file saved"
}
#End AppConfig
# Backup config files
try
{
$zipSource = $confPath
$zipFileName = "ConfBackup_$(get-date -format `"yyyyMMdd_hhmmsstt`").zip"
$zipDestination = "$PSScriptRoot\$websiteUrlForLog\$zipFileName"
log "Zipping config files"
If(Test-path $zipDestination) {Remove-item $zipDestination}
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($zipSource, $zipDestination)
log "Zipped"
}
Catch [Exception]
{
log("Error zipping files " + $_.Exception.Message)
logSitesNotMigrated $appPoolName
Return
}
# StopAppPool
log "Stopping App Pool $appPoolName"
StopApplicationPool($appPoolName)
log "App Pool Stopped for $appPoolName"
#remove Lib jars
try
{
log "*** Deleting Lib folder at $libPath ***"
remove-item $libPath -whatif # LOG
remove-item $libPath -Recurse -Force
#Remove-Item -Recurse -Force $libPath
log "*** Lib folder deleted ***"
}
Catch [Exception]
{
Write-Error ("Error deleting lib folder: " + $_.Exception.Message)
log("Error deleting lib folder: " + $_.Exception.Message)
logSitesNotMigrated $appPoolName
return
}
#remove config files from /bin/config
log "*** Removing Tridion 2013 config files ***"
try
{
Get-ChildItem $confPath -Recurse | Remove-Item -Force
log "*** Removed Tridion 2013 config files ***"
}
Catch [Exception]
{
Write-Error ("Error Removing Tridion 2013 config files: " + $_.Exception.Message)
log("Error Removing Tridion 2013 config files: " + $_.Exception.Message)
logSitesNotMigrated $appPoolName
return
}
#Copy Web 8 config files
log("*** Copying Web8 config files... ***")
try
{
Copy-Item -Recurse -Filter * -path $web8ConfigFiles\* -dest $confPath
log "*** Web8 config files copied ***"
}
Catch [Exception]
{
Write-Error ("Error Copying Web8 config files: " + $_.Exception.Message)
log "Error Copying Web8 config files: " + $_.Exception.Message
logSitesNotMigrated $appPoolName
return
}
#remove Tridion 2013 DLLs
log "*** Removing Tridion 2013sp1 Files from bin ***"
try
{
get-childitem $binPath -include Tridion*.dll -recurse | foreach ($_) {remove-item $_.fullname -whatif} # LOG
get-childitem $binPath -include Tridion*.dll -recurse | foreach ($_) {remove-item $_.fullname}
remove-item "$binPath\netrtsn.dll"
remove-item "$binPath\xmogrt.dll"
log "*** Tridion 2013sp1 bin files deleted ***"
}
Catch [Exception]
{
Write-Error ("Error Removing Tridion 2013sp1 Files : " + $_.Exception.Message)
log "Error Removing Tridion 2013sp1 Files : " + $_.Exception.Message
logSitesNotMigrated $appPoolName
Return
}
#Copy Web 8 DLLs
log "*** Copying Web8 files ***"
try
{
Copy-Item -Recurse -Filter *.dll -path $web8Files\* -dest $binPath
log "*** Web8 files copied ***"
}
Catch [Exception]
{
logSitesNotMigrated $appPoolName
Write-Error ("Error Copying Web8 Files: " + $_.Exception.Message)
log "Error Copying Web8 files: " + $_.Exception.Message
return
}
#Update web.config
log "Updating Web.config..."
try
{
$Path = Join-Path $WebsitePath "web.config"
[xml] $webConfigFile = Get-Content($Path)
$binding_WithAdf_WithAssemblyNode = '
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Tridion.ContentDelivery.AmbientData" publicKeyToken="ddfc895746e5ee6b" culture="neutral" preCondition="managedHandler" />
<bindingRedirect oldVersion="0.0.0.0-7.2.0.0" newVersion="8.1.0.1239" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Tridion.ContentDelivery" publicKeyToken="ddfc895746e5ee6b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.2.0.0" newVersion="8.1.0.1239" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Tridion.OutboundEmail.ContentDelivery" publicKeyToken="ddfc895746e5ee6b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.2.0.0" newVersion="8.1.0.244" />
</dependentAssembly>
</assemblyBinding>'
$binding_NoAdf_AssemblyNode = '
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Tridion.ContentDelivery" publicKeyToken="ddfc895746e5ee6b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.2.0.0" newVersion="8.1.0.1239" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Tridion.OutboundEmail.ContentDelivery" publicKeyToken="ddfc895746e5ee6b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.2.0.0" newVersion="8.1.0.244" />
</dependentAssembly>
</assemblyBinding>'
$binding_With_Adf = '
<dependentAssembly>
<assemblyIdentity name="Tridion.ContentDelivery.AmbientData" publicKeyToken="ddfc895746e5ee6b" culture="neutral" preCondition="managedHandler" />
<bindingRedirect oldVersion="0.0.0.0-7.2.0.0" newVersion="8.1.0.1239" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Tridion.ContentDelivery" publicKeyToken="ddfc895746e5ee6b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.2.0.0" newVersion="8.1.0.1239" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Tridion.OutboundEmail.ContentDelivery" publicKeyToken="ddfc895746e5ee6b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.2.0.0" newVersion="8.1.0.244" />
</dependentAssembly>
'
$binding_No_Adf = '
<dependentAssembly>
<assemblyIdentity name="Tridion.ContentDelivery" publicKeyToken="ddfc895746e5ee6b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.2.0.0" newVersion="8.1.0.1239" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Tridion.OutboundEmail.ContentDelivery" publicKeyToken="ddfc895746e5ee6b" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.2.0.0" newVersion="8.1.0.244" />
</dependentAssembly>
'
$runtimeNode = $webConfigFile.SelectSingleNode("//runtime")
if($runtimeNode -eq $null)
{
log "Updating web.config - Creating Runtime node with bindings"
# NO Runtime Node and no assembly node
log "NO Runtime Node"
$runtimeNode = $webConfigFile.CreateElement("runtime")
if($isTorkSite)
{
$runtimeNode.InnerXml = $binding_WithAdf_WithAssemblyNode
log "Runtime node added with no ADF bindings"
}
else
{
$runtimeNode.InnerXml = $binding_NoAdf_AssemblyNode
log "Runtime node added with ADF bindings"
}
# append runtime node
$configNode = $webConfigFile.SelectSingleNode("//configuration")
$configNode.AppendChild($runtimeNode)
}
else # Have Runtime node
{
log "Updating web.config - editing Runtime config"
if($runtimeNode.ChildNodes[0] -ne $null)
{
log "Runtime node before editing is..."
log $runtimeNode.ChildNodes[0].InnerXml
log "Adding SDL Web 8 Bindings within assemblyBindingXml"
$assemblyBindingInnerXml = $runtimeNode.ChildNodes[0].InnerXml
if($isTorkSite)
{
$assemblyBindingInnerXml = $assemblyBindingInnerXml + $binding_With_Adf
$runtimeNode.ChildNodes[0].InnerXml = $assemblyBindingInnerXml
log "Runtime node updated with ADF bindings"
}
else
{
$assemblyBindingInnerXml = $assemblyBindingInnerXml + $binding_No_Adf
$runtimeNode.ChildNodes[0].InnerXml = $assemblyBindingInnerXml
log "Runtime node updated with no ADF bindings"
}
}
}
log "Runtime config after editing is $runtimeNode"
log "Adding app setting keys to config..."
$appSettingsNode = $webConfigFile.SelectSingleNode("//appSettings")
#addConfigKey($webConfigFile, "discovery-service-uri", $DiscoveryServiceUrl)
$keyElement = $webConfigFile.CreateElement("add")
$keyElement.SetAttribute("key", "discovery-service-uri")
$keyElement.SetAttribute("value", $DiscoveryServiceUrl)
$appSettingsNode.AppendChild($keyElement)
log "discovery-service-uri-> $DiscoveryServiceUrl"
$keyElement = $webConfigFile.CreateElement("add")
$keyElement.SetAttribute("key", "oauth-enabled")
$keyElement.SetAttribute("value", "true")
$appSettingsNode.AppendChild($keyElement)
log "oauth-enabled"
$keyElement = $webConfigFile.CreateElement("add")
$keyElement.SetAttribute("key", "oauth-client-id")
$keyElement.SetAttribute("value", "cduser")
$appSettingsNode.AppendChild($keyElement)
log "oauth-client-id"
$keyElement = $webConfigFile.CreateElement("add")
$keyElement.SetAttribute("key", "oauth-client-secret")
$keyElement.SetAttribute("value", $oAuthClientSecret)
$appSettingsNode.AppendChild($keyElement)
$keyElement = $webConfigFile.CreateElement("add")
$keyElement.SetAttribute("key", "log-level")
$keyElement.SetAttribute("value", "Error")
$appSettingsNode.AppendChild($keyElement)
$keyElement = $webConfigFile.CreateElement("add")
$keyElement.SetAttribute("key", "log-rolling")
$keyElement.SetAttribute("value", "true")
$appSettingsNode.AppendChild($keyElement)
$keyElement = $webConfigFile.CreateElement("add")
$keyElement.SetAttribute("key", "log-max-log-size")
$keyElement.SetAttribute("value", "50000")
$appSettingsNode.AppendChild($keyElement)
$keyElement = $webConfigFile.CreateElement("add")
$keyElement.SetAttribute("key", "log-output")
$keyElement.SetAttribute("value", "$logfileWebsitesPath\\websites\\$appPoolName\\log_tridion_api_rest.log")
$appSettingsNode.AppendChild($keyElement)
$webConfigFile.Save($Path)
log "Saved WebConfig"
### Update AudienceManager Config Publication ID
$key = "PublicationID"
#TPW config/AppConfig.config
# <add key ="publicationId" value ="242"/>
if($productPath -eq 'tdp')
{
$Path = Join-Path $WebsitePath "/config/AppConfig.config"
[xml] $webConfigFile = Get-Content($Path)
$key = "publicationId"
$node = $webConfigFile.SelectSingleNode('/appSettings/add[@key="' + $key + '"]')
if($node)
{
$pubId = $node.Attributes['value'].Value
$amConfig = Join-Path $confPath "cd_audience_manager_conf.xml"
if($amConfig)
{
$amdoc = New-Object System.Xml.XmlDocument
$amdoc.Load($amConfig)
$amNode = $amdoc.SelectSingleNode('Configuration/DefaultPublicationId')
if($amNode)
{
log "========= AudienceManager Pub ID Update for $pubId =========="
$amNodeValue = $amNode.'#text'
log "AudieneManager PubId Before= $amNodeValue"
$amNode.'#text' = $pubId
$amdoc.Save($amConfig)
log "========= AudienceManager Updated To " + $amNode.InnerText + "=========="
}
}
else
{
log "No AudienceManager Config file found"
}
} # end TDP
}
#TPW config/AppConfig.config
# <add key ="publicationId" value ="242"/>
if($productPath -eq 'tpw')
{
$Path = Join-Path $WebsitePath "/config/AppConfig.config"
log "***** tpw config path is $Path"
[xml] $webConfigFile = Get-Content($Path)
$key = "publicationId"
$node = $webConfigFile.SelectSingleNode('/appSettings/add[@key="' + $key + '"]')
if($node)
{
log " *** TPW Config node found"
$pubId = $node.Attributes['value'].Value
$amConfig = Join-Path $confPath "cd_audience_manager_conf.xml"
if($amConfig)
{
$amdoc = New-Object System.Xml.XmlDocument
$amdoc.Load($amConfig)
$amNode = $amdoc.SelectSingleNode('Configuration/DefaultPublicationId')
if($amNode)
{
log "========= AudienceManager Pub ID Update for $pubId =========="
$amNodeValue = $amNode.'#text'
log "AudieneManager PubId Before= $amNodeValue"
$amNode.'#text' = $pubId
$amdoc.Save($amConfig)
log "========= AudienceManager Updated To " + $amNode.InnerText + "=========="
}
}
else
{
log "** No TPW AudienceManager Config file found"
}
}
else
{
log "** No TPW Config KEY file found"
}
}
#TCW config/AppConfig.config
# <add key="publicationId" value="tcm:0-28-1"/>
if($productPath -eq 'tcw')
{
$Path = Join-Path $WebsitePath "/config/AppConfig.config"
log " *** TCW Config path is $Path"
[xml] $webConfigFile = Get-Content($Path)
$node = $webConfigFile.SelectSingleNode('/appSettings/add[@key="' + $key + '"]')
if($node)
{
log "TCW config NODE FOUnd"
$pubId = $node.Attributes['value'].Value.Split('-')[1]
$amConfig = Join-Path $confPath "cd_audience_manager_conf.xml"
if($amConfig)
{
$amdoc = New-Object System.Xml.XmlDocument
$amdoc.Load($amConfig)
$amNode = $amdoc.SelectSingleNode('Configuration/DefaultPublicationId')
if($amNode)
{
log "========= AudienceManager Pub ID Update for $pubId =========="
$amNodeValue = $amNode.'#text'
log "AudieneManager PubId Before= $amNodeValue"
$amNode.'#text' = $pubId
$amdoc.Save($amConfig)
log "========= AudienceManager Updated To " + $amNode.InnerText + "=========="
}
}
else
{
log "No AudienceManager Config file found"
}
}
else
{
log "No TCW Config NODE found"
}
}
}
Catch [Exception]
{
logSitesNotMigrated $appPoolName
Write-Error ("Error updating web.config: " + $_.Exception.Message)
Return
}
Finally
{
#Start App Pool
StartApplicationPool($appPoolName)
log "App Pool Started for $appPoolName"
}
log("`r`n====================== DONE MIGRATING $appPoolName - $websiteFilePath ======================")
logSitesMigrated "$appPoolName, $websiteFilePath"
}
$sites = Import-Csv $csvSiteFile
#Upgrade each site
# CSV File has format, "Site, Path"
# Example, MyWebsite.com, C:\InetPub\wwwroot\mywebsite.com
ForEach ($site in $sites){
Try
{
UpgradeSite -websiteFilePath $site.path -appPoolName $site.site -discoveryServiceUrl $discoveryServiceUrl
} Catch [Exception]
{
logSitesNotMigrated $site
log $_.Exception.Message
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.