Wednesday 1 April 2015

Migration of Site Collections


Good Morning Friends! :)

Today, I am going to discuss about couple of Migration Strategies that can be used to migrate whole site collections from one web application to another and on the same SharePoint version. We tried these strategies on SharePoint 2010 and I think It can very well be used on SharePoint 2013 as well.

Typical scenario for migration of site collections can arise when Customer wants to move some of their site collections from Intranet to Extranet. 


First strategy is using Backup & Restore approach:

You can automate migration by executing all below steps from one single powershell(.ps1) file.


Step 1) To avoid any updates and loss of data during migration on the site collection to be migrated, first set the site collection as Read-Only using command Set-SPSite (for e.g. on Intranet application)

Step 2) Start backing up the site collection using Backup-SPSite command. It can take some time and please make sure you have sufficient space on the physical disk.

Step 3) After backup is succeeded, Start Restoring the site collection on another web application using command Restore-SPSite (for e.g. on Extranet)

Step 4) Remove read-only status of site collection from Extranet application using Set-SPSite command

Step 5) Delete the site collection from Intranet using  Remove-SPSite command

This strategy is useful when you are not allowed to access SQL Server and want to keep the backup of migrated site collection on your physical drive. 

But this has few drawbacks like you will need lots of empty space on the physical drive and second it takes lot of time to do backup and restore. So if you are OK with these issues then you can go ahead with this strategy.


Second strategy is using Content DB and Move Site collections:

You can automate migration by executing all below steps from one single powershell (.ps1) file.

Step 1) Create new content DB to Intranet application using New-SPContentDatabase command

Step 2) Use Move-SPSite command to move site collection to this new content DB. Repeat this step for all site collections.

Step 3) Detach this new content DB from Intranet web application using command Dismount-SPContentDatabase

Step 4) Attach the content DB to Extranet web application using Mount-SPContentDatabase 


It will require that you have an access to SQL server for performing operations on DB.

This strategy has an advantage that it doesn't require any space on actual physical disk and is very much faster as compared to the first approach. It may require only 3 mins to move site collections of sizes 50-100 GB. Whereas with approach 1 you may require 30-45 mins to restore sites back.


You can decide on any strategy from above based on the situation. 

Following are the scripts made available for both strategies.



Script for First Strategy (Backup and Restore):

Script requires SitesToMigrate.xml as an input file.

File 1) SitesToMigrate.xml

<?xml version="1.0"?>
-<Root><SiteCollection Url="http://test/sites/testsite1" ManagedPath="sites" Name="testsite1"/><SiteCollection Url="http://test/workspaces/testsite2" ManagedPath="workspaces" Name="testsite2"/></Root>


File 2) MigrateSites.ps1

<#
.SYNOPSIS
This script performs following steps to migrate workspace site collection from Intranet to Extranet web application.

1. Read sites to migrate from "SitesToMigrate.xml" and for each site perform following steps
2. Set site collection to read-only mode
3. Get a backup of the site collection from Intranet
4. Restore the site collection to extranet web application
5. Set the site collection in extranet web application to normal mode
6. Delete the original site collection from Intranet

.PARAMETER $ExtraNetWebApplicationURL
Extranet web application Url
#>

param
(
[parameter(Mandatory=$true)][string]$ExtraNetWebApplicationURL = $(throw '- Need parameter for Extranet web application Url')
)

$ErrorActionPreference = "Stop"

[xml]$sites = Get-Content SitesToMigrate.xml


$backupPath = ((Get-Item -Path ".\" -Verbose).FullName + "\Backup\") 
$logFile = ((Get-Item -Path ".\" -Verbose).FullName + "\Log.txt")
$xmlOutFile = ((Get-Item -Path ".\" -Verbose).FullName + "\xmlOutFile.xml")

$outLog = Get-Date;
out-file -encoding unicode -filepath $logFile -InputObject $outLog -Append -NoClobber

$outXML = "<Root>"
out-file -encoding unicode -filepath $xmlOutFile -InputObject $outXML -Append -NoClobber

$siteElements = ""

foreach($siteColl in $sites.Root.SiteCollection)
{
try
{
$siteElements = ("<SiteCollection Url='" + $ExtraNetWebApplicationURL + "/" + $siteColl.ManagedPath + "/" + $siteColl.Name + "'")
$siteElements = ($siteElements + " Name='" + $siteColl.Name + "'")
$siteElements = ($siteElements + " ManagedPath='" + $siteColl.ManagedPath + "'")

# 1. Set site collection to read-only mode with Set-SPSite
Set-SPSite -Identity $siteColl.Url -LockState "ReadOnly"

$siteElements = ($siteElements + " IsLocked='True' ")

# 2. Get a backup of the site collection with Backup-SPSite
Backup-SPSite $siteColl.Url -Path ($backupPath + $siteColl.ManagedPath + "_" + $siteColl.Name)

$siteElements = ($siteElements + " IsBackedUp='True' ")

# 3. Restore the site collection to extranet web application with Restore-SPSite
Restore-SPSite ($ExtraNetWebApplicationURL + "/" + $siteColl.ManagedPath + "/" + $siteColl.Name) -Path ($backupPath + $siteColl.ManagedPath + "_" + $siteColl.Name) -Confirm:$False

$siteElements = ($siteElements + " IsRestored='True' ")

# 4. Set the site collection in extranet web application to normal mode with Set-SPSite
Set-SPSite -Identity ($ExtraNetWebApplicationURL + "/" + $siteColl.ManagedPath + "/" + $siteColl.Name) -LockState "Unlock"

$siteElements = ($siteElements + " IsUnlocked='True' ")

# 5. Delete the original site collection with Remove-SPSite
Remove-SPSite -Identity $siteColl.Url -GradualDelete -Confirm:$False

$siteElements = ($siteElements + " IsRemoved='True' ")
$siteElements = ($siteElements + "></SiteCollection>")
}
catch
{
$siteElements = ($siteElements + "></SiteCollection>")

        # Log Exception
        $date = Get-Date;
        $outException = "Unhandled Exception," + $siteColl.Url + "," + $_.Exception.Message + "," + $_.Exception.ItemName + "," + $date
        out-file -encoding unicode -filepath $logFile -InputObject $outException -Append -NoClobber

$outException = "---------------------------------------------------------------------------------------------"
        out-file -encoding unicode -filepath $logFile -InputObject $outException -Append -NoClobber
}
out-file -encoding unicode -filepath $xmlOutFile -InputObject $siteElements -Append -NoClobber
}


$outLog = Get-Date;
out-file -encoding unicode -filepath $logFile -InputObject $outLog -Append -NoClobber
$outXML = "</Root>"
out-file -encoding unicode -filepath $xmlOutFile -InputObject $outXML -Append -NoClobber
#End



Script for Second Strategy (Content DB and Move Site):

Script requires SitesToMigrate.xml as an input file.

File 1) SitesToMigrate.xml

<?xml version="1.0"?>
-<Root><SiteCollection Url="http://test/sites/testsite1" ManagedPath="sites" Name="testsite1"/><SiteCollection Url="http://test/workspaces/testsite2" ManagedPath="workspaces" Name="testsite2"/></Root>


File 2) MigrateSitesWithMoveSite.ps1

<#
.SYNOPSIS
This script performs following steps to migrate workspace site collection from Intranet to Extranet web application.

1. Create new content DB to Intranet web application server
2. Read sites to migrate from "SitesToMigrate.xml"
a. Use Move-SPSite to move each site collection to this new content DB
3. Detach this new content DB from Intranet web application
4. Attach the content DB to extranet web application

.PARAMETER $IntraNetWebApplicationURL
Intranet web application Url

.PARAMETER $ExtraNetWebApplicationURL
Extranet web application Url

.PARAMETER $NewDBName
New DB Name

.PARAMETER $SQLDBServer
SQL DB Server Name
#>


param
(
[parameter(Mandatory=$true)][string]$IntraNetWebApplicationURL = $(throw '- Need parameter for Intranet web application Url'),
[parameter(Mandatory=$true)][string]$ExtraNetWebApplicationURL = $(throw '- Need parameter for Extranet web application Url'),
[parameter(Mandatory=$true)][string]$NewDBName = $(throw '- Need parameter for New DB Name'),
[parameter(Mandatory=$true)][string]$SQLDBServer = $(throw '- Need parameter for SQL DB Server Name')
)

$ErrorActionPreference = "Stop"

[xml]$sites = Get-Content SitesToMigrate.xml

$logFile = ((Get-Item -Path ".\" -Verbose).FullName + "\Log.txt")
$xmlOutFile = ((Get-Item -Path ".\" -Verbose).FullName + "\xmlOutFile.xml")


$outLog = Get-Date;
out-file -encoding unicode -filepath $logFile -InputObject $outLog -Append -NoClobber

$outXML = "<Root>"
out-file -encoding unicode -filepath $xmlOutFile -InputObject $outXML -Append -NoClobber

$siteElements = ""
$dbElements = ""

try
{
#Create new content DB to Intranet web application server
New-SPContentDatabase $NewDBName -DatabaseServer $SQLDBServer -WebApplication $IntraNetWebApplicationURL -Confirm:$False

$dbElements = "<NewContentDBCreatedInIntra>True</NewContentDBCreatedInIntra>"
out-file -encoding unicode -filepath $xmlOutFile -InputObject $dbElements -Append -NoClobber

foreach($siteColl in $sites.Root.SiteCollection)
{

try
{
$siteElements = ("<SiteCollection Url='" + $ExtraNetWebApplicationURL + "/" + $siteColl.ManagedPath + "/" + $siteColl.Name + "'")
$siteElements = ($siteElements + " Name='" + $siteColl.Name + "'")
$siteElements = ($siteElements + " ManagedPath='" + $siteColl.ManagedPath + "'")

# should we lock site collection before moving? I think yes, as if someone changes anything in existing site before unmounting content db then?


# Use Move-SPSite to move site collection to this new content DB
Move-SPSite $siteColl.Url -DestinationDatabase $NewDBName -Confirm:$False

$siteElements = ($siteElements + " IsMoved='True' ")
$siteElements = ($siteElements + "></SiteCollection>")
}
catch
{
$siteElements = ($siteElements + "></SiteCollection>")

        # Log Exception
        $date = Get-Date;
        $outException = "Unhandled Exception," + $siteColl.Url + "," + $_.Exception.Message + "," + $_.Exception.ItemName + "," + $date
        out-file -encoding unicode -filepath $logFile -InputObject $outException -Append -NoClobber

$outException = "---------------------------------------------------------------------------------------------"
        out-file -encoding unicode -filepath $logFile -InputObject $outException -Append -NoClobber
}


out-file -encoding unicode -filepath $xmlOutFile -InputObject $siteElements -Append -NoClobber
}

# Detach this new content DB from Intrasite
Dismount-SPContentDatabase $NewDBName -Confirm:$False

$dbElements = "<NewContentDBDismountedFromIntra>True</NewContentDBDismountedFromIntra>"
out-file -encoding unicode -filepath $xmlOutFile -InputObject $dbElements -Append -NoClobber


# Attach the content DB to extranet web application
Mount-SPContentDatabase $NewDBName -DatabaseServer $SQLDBServer -WebApplication $ExtraNetWebApplicationURL -Confirm:$False

$dbElements = "<NewContentDBMountedOnExtranet>True</NewContentDBMountedOnExtranet>"
out-file -encoding unicode -filepath $xmlOutFile -InputObject $dbElements -Append -NoClobber

}
catch
{
        # Log Exception
        $date = Get-Date;
        $outException = "Unhandled Exception,," + $_.Exception.Message + "," + $_.Exception.ItemName + "," + $date
        out-file -encoding unicode -filepath $logFile -InputObject $outException -Append -NoClobber

$outException = "---------------------------------------------------------------------------------------------"
        out-file -encoding unicode -filepath $logFile -InputObject $outException -Append -NoClobber
}

$outLog = Get-Date;
out-file -encoding unicode -filepath $logFile -InputObject $outLog -Append -NoClobber

$outXML = "</Root>"
out-file -encoding unicode -filepath $xmlOutFile -InputObject $outXML -Append -NoClobber
#End


Happy Learning! :)


No comments:

Post a Comment