LiveZilla Live Chat Software

0429 091 360

DFS Share Creation Script

Here is the first technical post. While on the whole I intend on putting snippets of tech stuff relevant to the everyday people I can’t help but go uber geek to begin with.

For those who work in a large environment (or even a small one) you may have come across Distributed File Systems (DFS). Let me give you a quick run down of the situation we have.

At the RAC we are currently using a domain level DFS to give us separation between share names and the servers they sit on. We currently have two primary servers one in HO and one in our DR Data Center. RAC also uses quota’s to do capacity management of disks and for charge back. We create a modify Rights group and a read only Rights group to manage permissions. We also modify the permissions on the share (I will blog on why we do that in the coming weeks). The sequence tasks we need to do goes like this.

  1. Create the Active Directory Groups
  2. Create the folders on both of the primary servers and assign the permissions to the folders
  3. Create the shares on both of the servers and adjust the permissions
  4. Create a quota template of the new share on each of the two servers then assign the quota’s to those two shares
  5. Create the DFS name space and add both nodes to the newly created DFS Share
  6. Create a replication group to make sure data is available at all times.

Estimated time to complete one share 30 to 45 mins including updating documentation and annotating the AD objects with relevant info in the notes field such as Service Ticket number, date of creation, who created the group and who requested the whole thing in the first place. And you are asked to create several of these it could turn out to be a full days work.

Here is what I came up with to resolve this issue. Power Shell script to the rescue!

[code language=”powershell”] #
#########################################
# New DFS Share Creation Script #
# Creator: Angelo Papiccio #
# Date: 10/03/2015 #
# Version 1.0 #
#########################################

#=== Description of Script Function ==
#This script uses input from a CSV file which defines some of the key variables that are required for the share.
#The CSV file must contain the following column headings

#GroupName BaseSharePath FilePath SC Requestor ShareName Quota

#GroupName – The AD Group Name that will be used to assign permissions (Using AD Naming Standards)
#BaseSharePath – This is the Share path that will present in DFS to the the top most name container
#FilePath – This is the file path from the top most folder.
#SC – This is the Service Call number in Service Now
#Requestor – The name of the person requesting the share
#ShareName – The Share name that will be used when adding nodes in DFS (N.B. This should always be a hidden share)
#Quota – The Quota that will be assigned this share.

#e.g.
#GroupName BaseSharePath FilePath SC # Requestor ShareName Quota
#MOTO.GM.Planning \\rac.com.au\files\MOTO\Motoring.Exec Motoring.Exec\GM.Planning RITM0042852 Fran Jones MOTO.GM.Planning$ 10

#This script will be used to make the selection of servers and disk easier when creating DFS shares.
#=======================================
#

# This Section sets the User Interface colours for the menu selection #
$Host.UI.RawUI.BackgroundColor = "DarkBlue"
$Host.UI.RawUI.ForegroundColor = "Green"
Clear-Host

# Import relevant modules #
Import-Module "c:\Windows\SysWOW64\WindowsPowerShell\v1.0\Modules\ActiveDirectory\ActiveDirectory.psd1" -DisableNameChecking
Import-Module "C:\Program Files\Quest Software\Management Shell for AD\Quest.ActiveRoles.ArsPowerShellSnapIn.dll" -DisableNameCheckin

# Get date values and logged in user details. Assign the Parent OU value.
# Also assign variables with Information for share permissions.
# Assign Log file variable
#
$Date = Get-Date
$ShortDate = $Date.ToShortDateString()
$CurrentUser = [Environment]::UserName
$RightParenteCont = "Enter your OU target DN here"
$RoleParenteCont = "Enter your OU Target DN here"
$LogDir = "\\DFSNamespace\files\SS\ICT\Ops\Logs\New.Share.Creation"
$DCA1 = "DCA-Server1"
$DCA2 = "DCA-Server2"
$DCB1 = "DCB-Server1"
$DCB2 = "DCB-Server2"

# Timer Function. Used to allow enough time for any Replication required #
function get-timer ($x)
{
$length = $x / 100
while($x -gt 0)
{
$min = [int](([string]($x/60)).split(‘.’)[0])
$text = " " + $min + " minutes " + ($x % 60) + " seconds left"
Write-Progress "Allowing Replication" -status $text -perc ($x/$length)
start-sleep -s 1
$x–
}
}

# This section creates a menu showing the different servers available.
# Once you select the server you want it will populate the variables that will be used latter
# to enumerate both nodes of the DFS replication groups.
#

Clear-Host
[int]$MenuChoice1 = 0
while ($MenuChoice1 -lt 1 -or $MenuChoice1 -gt 2)
{
Clear-Host
Write-Host "ntSelect which server in the farm you wish to create the shares on" -ForegroundColor Magenta
Write-Host "nt"
Write-Host "t1. DCA-Server1 (RACI, ADV.MEM, ORG, MOTO,DIST, Corporate.Groups)" -ForegroundColor Yellow
Write-Host "
t2. DCA-Server2 (ICT, PS, People.Development)" -ForegroundColor Yellow
[int]$MenuChoice1 = Read-Host "ntPlease enter an option 1 to 2…"
}
switch($MenuChoice1)
{
1{$ServerName = "DCA-Server1"}
2{$ServerName = "DCA-Server2"}
}
If ($ServerName -ilike "DCA-Server1")
{
$DCAServer = $DCA1
$DCBServer = $DCB1
}
Else
{
$DCAServer = $DCA2
$DCBServer = $DCB2
}

#
# Once the server you want is selected this next section will then use WMI to query the disk information which
# is then passed through a loop to create another menu.
# Define $DiskMenu as an array so that it can be dynamically updated by the for loop below
#
$DiskMenu =@()
$DiskInfo = Get-WmiObject win32_logicaldisk -ComputerName $ServerName
foreach ($Disk in $DiskInfo)
{
$drive = $Disk.DeviceID
$volume = $Disk.VolumeName
$DiskMenu += "$drive – $volume"
}

# Select The disk to create the share. Use the split function to strip away everything but the drive letter#
Clear-host
Write-Host "ntSelect the disk on which the share is to be created on" -ForegroundColor Magenta
Write-Host "nt"
$Host.UI.RawUI.ForegroundColor = "Yellow"
for ($i=0;$i-le $DiskMenu.Length-1;$i++){"tt[{0}]={1}" -f $i,$DiskMenu[$i]}
$Host.UI.RawUI.ForegroundColor = "Green"
[int]$z = Read-Host -Prompt "tChoose the disk to create the share on"
$chosen = $DiskMenu[$z] $Split = $chosen.split(":")
$DriveLetter = $Split[0]

# Import the CSV containing the details of the shares" #
Clear-Host
$Host.UI.RawUI.ForegroundColor = "Magenta"
$FileName = Read-Host -Prompt "Please enter the full path and file name to the import file "
$ShareList = Import-Csv $FileName
foreach ($share in $sharelist)
{
# Zero out all values
$GroupName, $SharePath, $SC, $Template, $BaseSharePath, $DCAFolderPath, $DCBFolderPath, $UNCPath, $Requestor, $Quota, $ModGroupName, $ReadGroupName, $path, $ShareName, $LogFile1, $Logfile2, $Remark = $null

# Assign values from $ShareList Array
$GroupName = $share.GroupName
$Template = $GroupName
$Path = $share.FilePath
$BaseSharePath = $share.BaseSharePath
$SharePath = "$BaseSharePath\$Path"
$SC = $share.SC
$Requestor = $share.Requestor
$ShareName = $share.ShareName
$DCAFolderPath = "\\$DCAServer\$DriveLetter$\Data\$Path"
$DCBFolderPath = "\\$DCBServer\$DriveLetter$\Data\$Path"
$UNCPath = "$DriveLetter"+":\Data\$Path"
[int]$Quota = $share.quota

# Create Groups in AD
$ModGroupName = ("Right-FS." + $GroupName + "-Modify")
$ReadGroupName = ("Right-FS." + $GroupName + "-Read")
$RoleGroupName = ("Role-"+ $GroupName + "-Moderator")
New-QADGroup -ParentContainer $RightParenteCont -Name $ModGroupName -SamAccountName $ModGroupName -GroupType Security -GroupScope DomainLocal -Description "Grant Users Modify Access to $SharePath" -Notes "SC#:$SC
rnRequested by:$RequestorrnCreated by:$CurrentUserrnDate:$ShortDate"
New-QADGroup -ParentContainer $RightParenteCont -Name $ReadGroupName -SamAccountName $ReadGroupName -GroupType Security -GroupScope DomainLocal -Description "Grant Users Read Access to $SharePath" -Notes "SC#:$SC
rnRequested by:$RequestorrnCreated by:$CurrentUserrnDate:$ShortDate"
New-QADGroup -ParentContainer $RoleParenteCont -Name $RoleGroupName -SamAccountName $RoleGroupName -GroupType Security -GroupScope DomainLocal -Description "Staff with modify access to $SharePath" -Notes "SC#:$SC
rnRequested by:$RequestorrnCreated by:$CurrentUserrnDate:$ShortDate"
Add-QADGroupMember -Identity $ModGroupName -Member $RoleGroupName

# Pause for replication
get-timer 60

# Create folder on Primary Member
New-Item $DCAFolderPath -ItemType directory
New-Item $DCBFolderPath -ItemType directory

# Assign Permissions on Primary Member
#---- Assign Modify Group----
$colRights = [System.Security.AccessControl.FileSystemRights]"Modify"
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None
$objType =[System.Security.AccessControl.AccessControlType]::Allow
$objACE = New-Object System.Security.AccessControl.FileSystemAccessRule ($ModGroupName, $colRights, $InheritanceFlag, $PropagationFlag, $objType)
$objACL = Get-Acl $DCAFolderPath
$objACL.AddAccessRule($objACE)
Set-Acl $DCAFolderPath $objACL
Set-Acl $DCBFolderPath $objACL

#---- Assign Read Group----
$colRights = [System.Security.AccessControl.FileSystemRights]"Read,ExecuteFile"
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None
$objType =[System.Security.AccessControl.AccessControlType]::Allow
$objACE = New-Object System.Security.AccessControl.FileSystemAccessRule ($ReadGroupName, $colRights, $InheritanceFlag, $PropagationFlag, $objType)
$objACL = Get-Acl $DCAFolderPath
$objACL.AddAccessRule($objACE)
Set-Acl $DCAFolderPath $objACL
Set-Acl $DCBFolderPath $objACL

#---- Write Folders to Log File----
$todaydate=$ShortDate.replace("/","_")
$txtSharePath1 = $DCAFolderPath.Replace("\","_")
$txtSharePath2 = $DCBFolderPath.Replace("\","_")
$LogFile1 = "$todaydate$txtSharePath1-NTFS.csv"
$LogFile2 = "$todaydate$txtSharePath2-NTFS.csv"
Get-Acl $DCAFolderPath | fl |Out-File $LogDir\$LogFile1
Get-Acl $DCBFolderPath | fl |Out-File $LogDir\$LogFile2

#---- Create the share and assign permissions----
$authuser = 'Everyone'
$domUser = 'Right-FS.Shares-FullAccess'
Invoke-Command -ComputerName $DCAServer -ScriptBlock {param($UNCPath, $ShareName, $domUser, $authuser, $SC)New-SmbShare -Path "$UNCPath" -Name "$ShareName" -FullAccess "$domUser" -ChangeAccess "$authuser" -Description "$SC"} -ArgumentList $UNCPath, $ShareName, $domUser, $authuser, $SC
Invoke-Command -ComputerName $DCBServer -ScriptBlock {param($UNCPath, $ShareName, $domUser, $authuser, $SC)New-SmbShare -Path "$UNCPath" -Name "$ShareName" -FullAccess "$domUser" -ChangeAccess "$authuser" -Description "$SC"} -ArgumentList $UNCPath, $ShareName, $domUser, $authuser, $SC

#---- Begin the Creation of the templates----
Clear-Host
Write-Host "
t#########################################" -ForegroundColor Magenta
Write-Host "t# 1. AD Groups Created Successfully #" -ForegroundColor Magenta
Write-Host "
t# 2. Folders Created Successfully #" -ForegroundColor Magenta
Write-Host "t# 3. Shares Created Successfully #" -ForegroundColor Magenta
Write-Host "
t#########################################" -ForegroundColor Magenta
Write-Host " "
Write-Host "tQuota templates and DFS Namespaces being created. Please wait...." -ForegroundColor Magenta

#This section creates the a new quota template, assocated quota actions then assign them to the folders just created
#It will also create the DFS Name Space for the share.
#N.B. Currently the servers hosting the DFS shares are only Windows 2012 not R2 therefore the PowerShell commands for creating the DFS Share will not work and have been remarked out.

#---- Create Quota Template----

Invoke-Command -ComputerName "$DCAServer" -ScriptBlock {
param($Template, $Quota, $SharePath)
$FSRMAction1 = New-FSRMAction Email -mailto "[Source Io Owner Email]" -Subject "[Quota Threshold]% quota threshold exceeded" -body "User [Source Io Owner] has exceeded the [Quota Threshold]% quota threshold for the quota on [Quota Path] on [Server]. The Quota limit is [Quota Limit GB] GB, and [Quota Used GB] GB currently is in use ([Quota used Percent]% of limit)"
$FSRMAction2 = New-FSRMAction Report -ReportTypes LargeFiles, DuplicateFiles, LeastRecentlyAccessed
$FSRMThreshold1 = New-FSRMQuotaThreshold -Percentage 85 -Action $FSRMAction1
$FSRMThreshold2 = New-FSRMQuotaThreshold -Percentage 100 -Action $FSRMAction1, $FSRMAction2
New-FSRMQuotaTemplate -Name "$Template" -Size ([Int64]($Quota) * [Int64]1GB) -Threshold $FSRMThreshold1, $FSRMThreshold2 -Description "$Quota GB Hard Quota for $SharePath"
} -ArgumentList $Template, $Quota, $SharePath
Invoke-Command -ComputerName "$DCBServer" -ScriptBlock {
param($Template, $Quota, $SharePath)
$FSRMAction1 = New-FSRMAction Email -mailto "[Source Io Owner Email]" -Subject "[Quota Threshold]% quota threshold exceeded" -body "User [Source Io Owner] has exceeded the [Quota Threshold]% quota threshold for the quota on [Quota Path] on [Server]. The Quota limit is [Quota Limit GB] GB, and [Quota Used GB] GB currently is in use ([Quota used Percent]% of limit)"
$FSRMAction2 = New-FSRMAction Report -ReportTypes LargeFiles, DuplicateFiles, LeastRecentlyAccessed
$FSRMThreshold1 = New-FSRMQuotaThreshold -Percentage 85 -Action $FSRMAction1
$FSRMThreshold2 = New-FSRMQuotaThreshold -Percentage 100 -Action $FSRMAction1, $FSRMAction2
New-FSRMQuotaTemplate -Name "$Template" -Size ([Int64]($Quota) * [Int64]1GB) -Threshold $FSRMThreshold1, $FSRMThreshold2 -Description "$Quota GB Hard Quota for $SharePath"
} -ArgumentList $Template, $Quota, $SharePath

#---- Assign the Quota to the folder----
Invoke-Command -ComputerName "$DCAServer" -ScriptBlock {
param($Quota, $SharePath,$UNCPath,$Template)
New-FSRMQuota -Path $UNCPath -Description "$Quota GB Hard Quota for $SharePath" -Template $Template
} -ArgumentList $Quota, $SharePath,$UNCPath,$Template
Invoke-Command -ComputerName "$DCBServer" -ScriptBlock {
param($Quota, $SharePath,$UNCPath,$Template)
New-FSRMQuota -Path $UNCPath -Description "$Quota GB Hard Quota for $SharePath" -Template $Template
} -ArgumentList $Quota, $SharePath,$UNCPath,$Template

Write-Host "t#########################################" -ForegroundColor Magenta
Write-Host "t# 1. Quota Template applied #" -ForegroundColor Magenta
Write-Host "
t#########################################" -ForegroundColor Magenta
Write-Host " "
Write-Host "tCreating DFS Namespace. Please wait ..."

# Script ending
Clear-Host
Write-Host "
t!!!!! SHARES AND QUOTAS CREATION COMPLETE !!!!!"
[/code]

So what does this bad boy do? Well lot’s actually.

It prompts you for the server you wish to use (we now are building a farm to spread the processing load). It Queries that server and returns you a list of drives using a WMI query.

It requires some input from a csv file which is explained in the text part up the very top. Once you have entered the information you require (e.g. group name, folder name, share name etc.) in the CSV this script will go out and create you the AD groups. It puts a 60 second pause to allow the replication between your Domain Controllers. Of course the more complex your AD structure is the longer you might want to put a pause or replace the pause with a replication command using Repadmin.

It then goes and and creates the folders, shares and quota templates. It assigns the permissions and then applies the quota’s. Becuase we are not running Windows 2012 R2 for the servers the Power Shell commands for creating the DFS namespaces is remarked out.

It turns a 45 min job to one that takes less than 10.

it’s probably not the most elegant of scripts but it works well and there are parts I am sure other scripters might find userful. Enjoy

Facebooktwittergoogle_plusby feather
Facebookby feather