Office Servers and Services

"La connaissance ne vaut que si elle est partagée" / "An effective Knowledge is a shared one"

Archive for août 2011

Outlook : Blocage de l’expéditeur qui ne fonctionne pas

Posted by Teruin laurent sur août 31, 2011


ENVIRONNEMENT

Exchange 2007 / Outlook 2010

PROBLEME

Le blocage d’un expéditeur via le client Outlook ne fonctionne pas.


RAISON

Le fait que le blocage d’un expéditeur ne fonctionne pas peut être dû au fait que le flux SMTP entrant vers le serveur Exchange (Eventuellement d’un équipement tiers : Fortimail, Ironport etc..) est considéré comme étant de confiance. En fait ce cas se produit si vous avez paramétré vos « receive connector » (particulièrement ceux utilisé pour la réception de message provenant de votre relais de messagerie en DMZ par exemple) comme autorisant les adresses IP de vos boitiers de relais dans l’onglet Allowed Addresses.


Si vous faites cela, l’ensemble des flux de messagerie provenant de cette destination seront taggué avec un SCL ayant une valeur a -1 comme le montre les deux lignes suivantes.

X-MS-Exchange-Organization-Antispam-Report: IPOnAllowList
X-MS-Exchange-Organization-SCL: -1

Dans ce cas le client Outlook ne bloquera pas votre Expéditeur même si vous lui demandez. Nous avons effectuez pas mal de test, et le simple fait d’enlever l’adresse IP des boitiers relais de messagerie dans le « receive connector » Onglet AntiSpam / Allowed Addresses supprime le SCL a – 1 et le blocage du client via Outlook fonctionne à nouveau

Cordialement
Laurent Teruin

Publicités

Posted in EXCHANGE 2007, Exchange Server 2007, Problèmes 2007, Sécurité-2007 | Leave a Comment »

Délégations de Boîtes aux lettres Exchange Server 2010

Posted by David PEKMEZ sur août 29, 2011


Bonjour,

Je vous présente un script qui pourrait vous dépanner lors de demandes de délégations sur un environnement Exchange Server 2010, lors d’une migration ou simplement en administration de vos plateformes Exchange.

Merci au passage à Thomas ANDRES et Yohan BOULLIER pour leur précieuse participation à l’élaboration de ce script !

Ce script va vous permettre de placer des permissions de délégations sur les boîtes à distance, à l’aide d’un compte ayant ces droits spécifiques pour placer des droits dans les Boîtes Exchange de vos utilisateurs

Pour plus de renseignements sur les droits nécessaires, veuillez-vous rendre sur cette page http://msdn.microsoft.com/en-us/library/bb204095(v=exchg.140).aspx

New-ManagementRoleAssignment -Name:ExchangeImpersonation -Role:ApplicationImpersonation -User:ServiceAccount


Pour vous servir de ce script, vous pouvez au choix:

  • Utiliser les paramètres powershell en entrée
  • Utiliser un fichier CSV en entrée

Les différents paramètres du script sont les suivants

  • MbxtoDelegate : Boîte à déléguer (paramètre obligatoire)
  • DelegatetoAdd : Délégué à ajouter (paramètre obligatoire)
  • InboxAccessPermissions : Droits sur la boîte de réception

Choix disponible : None, Owner, PublishingEditor, Editor, PublishingAuthor, Author, NoneditingAuthor, Reviewer, Contributor, Custom

  • CalendarAccessPermissions : Droits sur le calendrier
    • Choix disponible : None, Owner, PublishingEditor, Editor, PublishingAuthor, Author, NoneditingAuthor, Reviewer, Contributor, Custom
  • ContactAccessPermissions : Droits sur les contacts
    • Choix disponible : None, Owner, PublishingEditor, Editor, PublishingAuthor, Author, NoneditingAuthor, Reviewer, Contributor, Custom
  • GrantSendAs : Droit « Envoyer en tant que »
    • Choix disponible : $True / $False

Exemple d’utilisation sans le fichier CSV en entrée

Commande powershell

.\AddDelegates.ps1 -MbxtoDelegate DPEKMEZEXT -DelegatetoAdd TANDRESEXT -InboxAccessPermissions Editor -CalendarAccessPermissions Editor -ContactAccessPermissions Editor -GrantSendAs $False



Exemple d’utilisation avec le fichier CSV en entrée

Format du fichier CSV

MbxtoDelegate,DelegatetoAdd,InboxAccessPermissions,CalendarAccessPermissions,ContactAccessPermissions,GrantSendAs

TANDRESEXT,DPEKMEZEXT,Editor,Editor,Editor,False


Commande powershell

.\AddDelegates.ps1 -csv .\AddDelegates.csv


Resultat


#=================================================================================
#	AddDelegates.ps1
#
#	THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
#	KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
#	IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
#	PARTICULAR PURPOSE.
#
#	Description:
#
#	# Script Written By: David Pekmez ( https://unifiedit.wordpress.com )
#
#	Version: 1
#	Last Updated: 19/08/2011
#=================================================================================
#=================================================================================
# Parameter definition
#=================================================================================

Param(
	[Parameter(Mandatory=$false, Position=0, HelpMessage="Please Enter Mailbox UserName Or SMTP Address of the mailbox you want to Delegate",ValueFromPipeline=$true)][string] $MbxtoDelegate,
	[Parameter(Mandatory=$false, Position=1, HelpMessage="Please Enter Mailbox UserName Or SMTP Address of the Delegate you want to Add",ValueFromPipeline=$true)][string] $DelegatetoAdd,
	[Parameter(Mandatory=$false, HelpMessage="Please Enter Inbox Folder permissions to add to the Delegate",ValueFromPipeline=$true)][string] $InboxAccessPermissions="None",
	[Parameter(Mandatory=$false, HelpMessage="Please Enter Calendar Folder permissions to add to the Delegate",ValueFromPipeline=$true)][string] $CalendarAccessPermissions="None",
	[Parameter(Mandatory=$false, HelpMessage="Please Enter Contact Folder permissions to add to the Delegate",ValueFromPipeline=$true)][string] $ContactAccessPermissions="None",
	[Parameter(Mandatory=$false, HelpMessage="Grant the 'SendAs permission to Delegate",ValueFromPipeline=$true)][boolean] $GrantSendAs=$false,
	[Parameter(Mandatory=$false, HelpMessage="CSV Input file",ValueFromPipeline=$true)][string]$csv="none"
)

#==========================================================================
# Function that returns true if the incoming argument is a help request
#==========================================================================
function IsHelpRequest
{
	param($argument)
	return ($argument -eq "-?" -or $argument -eq "-help");
}

#==========================================================================
# Function that returns true if the incoming argument is a help request
#==========================================================================
function Debug([string]$data)
{
$var = $null
$var = get-variable($data) -ea SilentlyContinue

	if ($var)
	{
	write-host "DEBUG: " -foregroundcolor cyan -nonewline
	write-host $var.name "  " -nonewline
	write-host "[$var.value]"
	}
	else
	{
	write-host "DEBUG: " -foregroundcolor cyan -nonewline
	write-host "[$data]"
	}

}

#==========================================================================
# Wait until Key press
#==========================================================================
function Pause ($Message="Press any key to continue...")
{
Write-Host -NoNewLine $Message
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Write-Host ""
}
#===================================================================
# Function that displays the help related to this script following
# the same format provided by get-help or <cmdletcall> -?
#===================================================================
function Usage
{

@"
NAME: AddDelegates.ps1

SYNOPSIS:
AddDelegates to a Mailbox

SYNTAX:
AddDelegates.ps1

`t[-MbxtoDelegate <Mailbox UserName Or SMTP Address>]
`t[-DelegatetoAdd <Mailbox UserName Or SMTP Address>]
`t[-InboxAccessPermissions <Inbox Access Right>]
`t[-CalendarAccessPermissions <Calendar Access Right>]
`t[-ContactAccessPermissions <Contact Access Right>]
`t[-GrantSendAs <True/False>]
`t[-CSV <CSV file path>]

PARAMETERS:
-MbxtoDelegate (Requiered)
Mailbox UserName Or SMTP Address of the mailbox you want to Delegate

-DelegatetoAdd (Requiered)
Mailbox UserName Or SMTP Address of the Delegate you want to Add

-InboxAccessPermissions (Optionnal)
Inbox Folder permissions to add to the Delegate

-CalendarAccessPermissions (Optionnal)
Calendar Folder permissions to add to the Delegate

-ContactAccessPermissions (Optionnal)
Contact Folder permissions to add to the Delegate

-GrantSendAS (Optionnal)
Determine if the delegate must have the SendAs permission on the mailbox

-csv (Optionnal)
Specify a CSV file which contains one delegate per line

	CSV header file:
	MbxtoDelegate,DelegatetoAdd,InboxAccessPermissions,CalendarAccessPermissions,ContactAccessPermissions,GrantSendAs

-------------------------- EXAMPLE --------------------------

.\AddDelegates.ps1 -MbxtoDelegate dpekmez -DelegatetoAdd JohnDoe -InboxAccessPermissions Reviewer -CalendarAccessPermissions Editor -ContactAccessPermissions
.\AddDelegates.ps1 -csv input.csv
Mailbox folder and Calendar folder permission levels available : None, Owner, PublishingEditor, Editor, PublishingAuthor, Author, NoneditingAuthor, Reviewer, Contributor, Custom

For more information of permission level, you might want to have a look on the MDSN web Site
http://msdn.microsoft.com/en-us/library/bb856574(v=exchg.140).aspx

"@
}

#=======================================
# Check for Usage Statement Request
#=======================================
$args | foreach { if (IsHelpRequest $_) { Usage; exit; } }

#=================================================================================
# Exchange WebServices
#=================================================================================
$dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.1\Microsoft.Exchange.WebServices.dll"
[void][Reflection.Assembly]::LoadFile($dllpath)

$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010)

$windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$sidbind = "LDAP://<SID=" + $windowsIdentity.user.Value.ToString() + ">"
$aceuser = [ADSI]$sidbind

$service.AutodiscoverUrl($aceuser.mail.ToString())

#=================================================================================
# Get Current Domain
#=================================================================================

$domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()

#=================================================================================
# Main
#=================================================================================
function AddDelegate ([string] $MbxtoDelegate,[string] $DelegatetoAdd,[string] $InboxAccessPermissions,[string] $CalendarAccessPermissions,[string] $ContactAccessPermissions,[boolean] $GrantSendAs)
{
	#Connexion aux boites
	$Mailbox = $null;$Mailbox = get-mailbox $MbxtoDelegate -resultsize unlimited -ea stop
	$Delegate= $null;$Delegate = get-mailbox $DelegatetoAdd -resultsize unlimited -ea stop

	#initialisation des objets Web Services
	$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $Mailbox.primarySMTPAddress.tostring());
	$mbMailbox=$null ; $mbMailbox = new-object Microsoft.Exchange.WebServices.Data.Mailbox($Mailbox.primarySMTPAddress.tostring())
	$dgUser=$null ; $dgUser = new-object Microsoft.Exchange.WebServices.Data.DelegateUser($Delegate.primarySMTPAddress.tostring())
	$dgUser.ViewPrivateItems = $false
	$dgUser.ReceiveCopiesOfMeetingMessages = $false
	$dgUser.Permissions.InboxFolderPermissionLevel = [Microsoft.Exchange.WebServices.Data.DelegateFolderPermissionLevel]::$InboxAccessPermissions
	$dgUser.Permissions.CalendarFolderPermissionLevel = [Microsoft.Exchange.WebServices.Data.DelegateFolderPermissionLevel]::$CalendarAccessPermissions
	$dgUser.Permissions.ContactsFolderPermissionLevel = [Microsoft.Exchange.WebServices.Data.DelegateFolderPermissionLevel]::$ContactAccessPermissions
	$dgArray = new-object Microsoft.Exchange.WebServices.Data.DelegateUser[] 1
	$dgArray[0] = $dgUser
	$Delegate_list = $service.GetDelegates($mbMailbox, $true)
	write-host ""

	# Permissions

	$Permissions = (get-MailboxFolderPermission $MbxtoDelegate) | where-object {$_.User.tostring() -eq $Delegate.DisplayName}

	if($Permissions -eq $null){

	Write-host -ForegroundColor Green "Mailbox Folder Permissions not found ..."
	Write-host -ForegroundColor Green "Set permissions for: " -nonewline
	Write-host $Delegate.DisplayName -foregroundcolor  cyan
	Add-MailboxFolderPermission -Identity $MbxtoDelegate -User $DelegatetoAdd -AccessRights $InboxAccessPermissions
    }

	elseif ($Permissions.AccessRights -eq $InboxAccessPermissions )
	{
	Write-host -ForegroundColor Green "Mailbox Folder Permissions already set for: " -nonewline
	Write-host $Delegate.DisplayName -foregroundcolor  cyan
	Write-host -ForegroundColor Green "Access Permissions: " -nonewline
	Write-host $InboxAccessPermissions -foregroundcolor  cyan
	Write-host -ForegroundColor Green "Update sub folders permissions now ..."

	}

	else {

 	Write-host -ForegroundColor Green "Mailbox Folder Permissions Different from : " -nonewline
 	Write-host $InboxAccessPermissions -foregroundcolor  cyan
	Write-host -ForegroundColor Green "for User: " -nonewline
 	Write-host $Delegate.DisplayName -foregroundcolor  cyan
	Write-host -ForegroundColor Green "Updating to Permissions : " -nonewline
	Write-host $InboxAccessPermissions  -foregroundcolor  cyan
	Remove-MailboxFolderPermission -Identity $MbxtoDelegate -User $DelegatetoAdd -confirm:$False
 	Add-MailboxFolderPermission -Identity $MbxtoDelegate -User $DelegatetoAdd -AccessRights $InboxAccessPermissions
 	Write-host -ForegroundColor Green "Update sub folders permissions now ..."
}

	# Delegation

	[boolean]$IsAlreadyDelegate = $false
	ForEach($Response in $Delegate_list.DelegateUserResponses)
	{
	$userid = $response.DelegateUser.UserId
	if ($Delegate.primarySMTPAddress.tostring() -eq $userid.PrimarySMTPAddress.tostring()){$IsAlreadyDelegate = $true;break}
	}
	if (!($IsAlreadyDelegate))

	{$service.AddDelegates($mbMailbox, [Microsoft.Exchange.WebServices.Data.MeetingRequestsDeliveryScope]::DelegatesAndMe, $dgArray)
	$action = "set"
	}else{
	$service.updateDelegates($mbMailbox, [Microsoft.Exchange.WebServices.Data.MeetingRequestsDeliveryScope]::DelegatesAndMe, $dgArray)
	$action = "updated"
	}

	#Récap
	Write-Host ""
	Write-Host "Boite aux lettres  : " -nonewline
	Write-Host $Mailbox.DisplayName -foregroundcolor  cyan
	Write-Host "Utilisateur délégué: " -nonewline
	Write-Host $Delegate.DisplayName -foregroundcolor  cyan

	Write-host -ForegroundColor Green "Inbox Permissions $action to:" -NoNewLine
	Write-host -ForegroundColor Yellow " " $InboxAccessPermissions " " -NoNewLine
	Write-host -ForegroundColor Green "Calendar Permissions $action to" -NoNewLine
	Write-host -ForegroundColor Yellow " " $CalendarAccessPermissions " " -NoNewLine
	Write-host -ForegroundColor Green "Contact Permissions $action to" -NoNewLine
	Write-host -ForegroundColor Yellow " " $ContactAccessPermissions

	# 'Send-AS' Permissions

	$SendAs = $false
	$Mailbox_permissions = get-adpermission $mailbox.identity  -ea stop | where { $_.user.tostring() -eq ($domain.Name + "\" + $delegate.samaccountname.tolower())}
	foreach ($ADAcePresentationObject in $Mailbox_permissions){if ($ADAcePresentationObject.ExtendedRights -like "*Send*") {$SendAs = $true;break}}
	write-host  "Send-As permission: " -nonewline  -ForegroundColor Green

	if ($GrantSendAs -and !($SendAs)){
	write-host  " granted." -ForegroundColor Yellow
	Add-ADPermission $mailbox.identity -User $delegate.identity -Extendedrights "Send As"}

	if ($GrantSendAs -and $SendAs){write-host  " already set." -ForegroundColor Yellow}
	if (!($GrantSendAs) -and !($SendAs)){write-host  " not set." -ForegroundColor Yellow}

	if (!($GrantSendAs) -and $SendAs){
	write-host  " removed." -ForegroundColor Yellow
	remove-ADPermission $mailbox.identity -User $delegate.identity -Extendedrights "Send As" -confirm:$false}

}

#=================================================================================
#MAIN
#=================================================================================

if ($csv -eq "none"){AddDelegate $MbxtoDelegate $DelegatetoAdd $InboxAccessPermissions $CalendarAccessPermissions $ContactAccessPermissions $GrantSendAs}
else{
	$curdir =(get-location).path
	if (!(test-path $csv)){$csv=$curdir+"\"+$csv}
	if (!(test-path $csv)){write-host "Impossible de trouver le fichier CSV:" -backgroundcolor red -nonewline ;write-host "'$csv'" -foregroundcolor cyan;write-host "";exit}
	$csvdata = import-csv $csv
	$csvdata | %{
	[Boolean]$sa = $False;$sa = [System.Convert]::ToBoolean($_.GrantSendAs.tostring())
	AddDelegate $_.MbxtoDelegate $_.DelegatetoAdd $_.InboxAccessPermissions $_.CalendarAccessPermissions $_.ContactAccessPermissions $sa}
	}

#=================================================================================
#Gestion des erreurs
#=================================================================================
trap
{
write-host ""

	if ( $_.FullyQualifiedErrorID.tostring().contains("GetMailbox"))
	{
		if ($_.Exception.Message.tostring().contains("introuvable"))
		{
		write-host "Impossible de trouver la boite aux lettres:" -backgroundcolor red -nonewline
		[int]$io1 = $_.Exception.Message.tostring().indexof("'",43)
		[int]$io2 = $_.Exception.Message.tostring().indexof("'",$io1+1)
		$bal = $_.Exception.Message.tostring().substring($io1+1,$io2-$io1-1)
		write-host " " $bal -foregroundcolor cyan
		write-host ""
		exit
		}
	}

	if ($_.Exception.Message.tostring().contains("DelegateFolderPermissionLevel"))
	{
		write-host "Permission incorrecte pour le dossier:" -backgroundcolor red -nonewline
		[int]$io1= $_.Exception.Message.tostring().indexof("«")
		[int]$io2= $_.Exception.Message.tostring().indexof("»")
		$folder = $_.Exception.Message.tostring().substring($io1+1,$io2-$io1-1)
		$folder = $folder -replace("FolderPermissionLevel","")
		write-host " " $folder -foregroundcolor cyan
		write-host ""
		write-host "Permissions prises en charge:"
		write-host ""
		write-host " - None"
		write-host " - Editor"
		write-host " - Reviewer"
		write-host " - Author"
		write-host " - Custom"
		write-host ""
		exit
	}

	if ($_.Exception.Message.tostring().contains("ToBoolean"))
	{
		write-host "Valeur incorrecte dans le ficheir CSV pour la colonne :" -backgroundcolor red -nonewline
		write-host " 'GrantSendAs'" -foregroundcolor cyan
		write-host "Valeurs autorisées : 'true' ou 'false'"
		write-host ""
		exit
	}

	write-host ""
	write-host ""
	write-host "------------------------------------------------------"
	write-host "categoryInfo: " -backgroundcolor red -nonewline
	write-host $_.categoryInfo
	write-host "Exception.GetType: " -backgroundcolor red -nonewline
	write-host $_.Exception.GetType().fullname
	write-host "FullyQualifiedErrorID: " -backgroundcolor red -nonewline
	write-host $_.FullyQualifiedErrorID
	write-host "Message: " -backgroundcolor red -nonewline
	write-host $_.Exception.Message
	write-host "------------------------------------------------------"
	exit
}


Ce script est téléchargeable via le lien suivant

https://skydrive.live.com/?cid=deb7bf8a12d36694&sc=documents&id=DEB7BF8A12D36694%21410#

Voilà, j’espère que ce script vous sera utile !

Bonne lecture

David Pekmez

Posted in Exchange Server 2010, script | Leave a Comment »

Exchange et le Stockage – Partie 7

Posted by Anthony Costeseque sur août 28, 2011


Aujourd’hui nous allons voir un peu l’incidence de cette taille de block (taille de page) à 32KO sur la partie Backup.

Le backup ne peut se faire aujourd’hui qu’en mode VSS (Volume Shadow Copy Service) à l’aide d’un provider (l’un des 3 composants primaires de VSS (provider, requestor et writer)).

Pour plus d’informations sur VSS je vous renvoie vers un ancien billet que j’ai écrit : http://diskshadow.fr/microsoft/volume-shadow-copy-service-vss-details.html

Le but de tout cela est de lors du lancement d’un backup de bases de données Exchange, faire en sorte que le backup soit « Application Consistent » (qui correspond à un état de la base de données « Clean ») à l’inverse d’un backup de type « Crash Consistent » (qui correspond à un état de la base de données « Dirty »).

Comment fait-on pour avoir un backup Clean ?

Et bien l’outil de backup va grâce à son requestor discuter avec VSS qui a son tour va utiliser un writer (celui d’exchange) pour faire en sorte que la(es) base(s) de données soit dans un état consistant (« Clean ») et ainsi, créer un snapshot (un point dans le temps (une shadow copy)).

Le writer va utiliser un provider (celui de l’os natif ou un provider spécial fourni par une application de backup) pour maintenir le snapshot (shadow copy) tout au long du backup.

Une fois le backup terminée, en règle générale, tout est nettoyé (les snapshot sont supprimés).

Important : pour que la base de données soit en état « Clean » lors de l’appel du writer, une interruption de service à lieu (les IOs sont figés) et le snapshot est créée ! À partir de là les IOs reprennent.

Je vous rassure l’interruption ne dure que 10sec maximum avant qu’un time out n’intervienne pour mettre le backup en erreur.

Durant la vie du snapshot (généralement le temps du backup) COFW intervient (Copy On First Write) toutes modifications qui interviennent dans les bases de données sont enregistrées sur les disques mais les blocks originaux partent dans la réserve utilisée par VSS (par défaut le fameux répertoire « C:\System Volume Information » inaccessible au commun des mortels)

Le provider natif de Windows (dans Windows 2008 R2) qui s’appuie sur VOLSNAP.sys, utilise des blocks de 16KO.

Donc lorsqu’un snapshot est en court toutes écritures est interceptée par le provider, permettant au block original de se déplacer dans la snapshot reserve, mais même s’il n’y a que 1byte de modifié, ce sera 16KO qui seront déplacés !

De plus si une écriture à lieu sur plus de 16KO alors c’est tous les blocks modifiés qui sont déplacés.

 

Revenons à Exchange et ses tailles de page.

Exchange 2003 4KO

Exchange 2007 8KO

Exchange 2010 32KO

Prenons Exchange 2003, si une écriture de 4KO était contenue dans 1 block de 16KO alors c’était 16KO qui partaient vers la snapshot reserve ! De plus si ces 4KO touchaient 2 Blocks de 16KO alors c’était 32KO qui partaient dans la réserve !!

Donc 4KO de modif = soit +16KO ou au pire +32KO !! On commence à comprendre l’importance de laisser de la place sur les disques qui supportent les bases de données 🙂 pour peu que le backup tourne longtemps et qu’il y ait de l’activité ça peut vite grossir.

 

Donc pour Exchange 2010, une écriture de 32KO fera forcement 2 Blocks de 16KO au mieux et au pire 48KO !

Une modif de 32KO = soit +32KO ou au pire +48KO !

 

Maintenant attention ! Si votre solution de backup install son propre provider il est très important de vérifier quelle est la taille de block qu’elle utilise. Si par exemple elle utilise des blocks de 1024KO on imagine vite l’impact !

Une modif de 32KO = soit +1024KO ou au pire +2048KO !! (1Mo ou 2Mo)

 

Donc attention.

Pour toutes questions n’hésitez pas.

Anthony COSTESEQUE.

Posted in 1-EXCHANGE 2010, Exchange 2010 Service Pack 1, Sauvegarde-2010, Stockage-2010 | 1 Comment »

Exchange 2010 SP1 – RollUP 5

Posted by Anthony Costeseque sur août 24, 2011


Chose promise, chose due ! le RollUP 5 est maintenant disponible en téléchargement.

Bonne installation.

Anthony COSTESEQUE.

Posted in 1-EXCHANGE 2010, Exchange 2010 Service Pack 1 | Leave a Comment »

Exchange et le Stockage – Partie 6

Posted by Anthony Costeseque sur août 21, 2011


Aujourd’hui nous allons aller plus loin sur les I/Os dans Exchange 2010.

Nous avons dit qu’une application avait un profil de charge (workload) défini par :

I/O size (La taille des requêtes I/O)

Access pattern (Sequential ou Random ou encore entre les deux)

Footprint (La quantité totale de données disponible accédée dans le disque)

Command type (Read ou Write ou encore les deux)

 

Nous avons déjà vu la partie Command type (Read ou Write ou encore les deux)

Database : 60% Read / 40% Write

Logs : 50% Read / 50% Write

 

La partie Footprint depend de beaucoup de facteurs, ce n’est pas le but de ce billet.

 

La partie Access pattern (Sequential ou Random ou encore entre les deux) est intéressante :

Avec exchange 2010 les I/O séquentiels ont été augmenté grâce à de nouvelles fonctionnalités comme la défragmentation Online et les scans des databases Online.

Toutes les données sont stockées dans les bases de données qui sont constituées de B-trees, qui sont à leur tour composées de pages (la plus petite unité).

Ces pages sont défragmentées en ligne régulièrement, ce qui permet de réaliser des lectures séquentielles plus longues !

 

Et maintenant le plus intéressant, l’I/O size (La taille des requêtes I/O)

Nous avons définie dans la Partie 1, ce qu’est un I/O

Un I/O correspond à la plus petite quantité de données transférées depuis ou vers une application.

Sa taille peut être de 8/16/32/64/128/256KB

Et nous venons de voir plus haut que la plus petite unité dans une base de données est la « page ».

Nous pouvons donc en déduire la taille de nos I/O pour les bases de données Exchange 2010 :

1 I/O = 1 page = 32Ko

Cette taille a été augmentée dans la version 2010 pour améliorer les performances.

Pour historique :

En 2003 la taille d’un page été de 4Ko

En 2007 la taille est passée à 8Ko

 

Donc dans Exchange 2010 la lecture ou l’écriture de données dans une base de données se fait par morceau de 32Ko.

 

Pour toutes questions n’hésitez pas.

Anthony COSTESEQUE.

Posted in 1-EXCHANGE 2010, Exchange 2010 Service Pack 1, Performance-2010, Stockage-2010 | 1 Comment »

Powershell et les tâches planifiées

Posted by David PEKMEZ sur août 19, 2011


Suite à la lecture et au suivi régulier des mises à jour de l’excellent script de génération de rapports (de Steve Goodman ) exchange disponible sur cette page

http://www.stevieg.org/2011/06/exchange-environment-report/

J’ai voulu la faire tourner en tache planifiée

Il faut que vous lanciez Powershell en collant les informations ci-dessous

%systemroot%\system32\WindowsPowerShell\v1.0\powershell.exe


Puis dans les arguments vous pouvez ajouter vos paramètres, ici :

-noninteractive -Command « & D:\ScriptsExchange\Report\Get-ExchangeEnvironmentReport.ps1 -HTMLReport D:\ScriptsExchange\Report\Report.html

Si vous avez besoin de débuguer l’exécution de la tâche, ajoutez –noexit comme paramètre afin que la fenêtre d’exécution de script ne se referme pas automatiquement

N’hésitez pas l’utiliser, ces rapports sont très pratiques !

David Pekmez

Posted in Exchange Server 2010, Powershell-2010 | 1 Comment »

Exchange et le Stockage – Partie 5

Posted by Anthony Costeseque sur août 14, 2011


Voici le tableau recapitulatif des best practise (bonnes pratiques) qu’il faut suivre lors du design et installation d’Exchange 2010


Pour toutes questions n’hésitez pas.

Anthony COSTESEQUE

Posted in 1-EXCHANGE 2010, Exchange 2010 Service Pack 1, Exchange Server 2010, Stockage-2010 | 1 Comment »

Exchange et le Stockage – Partie 4

Posted by Anthony Costeseque sur août 7, 2011


Aujourd’hui nous allons voir ce que nous pouvons faire dans une configuration plus modeste (dans laquelle nous n’avons pas 4 MBX et donc pas la possibilité d’avoir 4 Copies de Database (1 Active + 3 passives) pour pouvoir utiliser du JBOD).

Nous pouvons avoir 2 types de configuration :

Sans HA avec par exemple 1 seul serveur et tous les rôles ensembles.

Avec HA et donc au moins 2 serveurs MBX (nous pourrons aussi avoir tous les rôles ensembles sur les 2 serveurs).

 

Tout d’abord la première limitation (best practise)

http://technet.microsoft.com/en-us/library/ee832792.aspx

Sans HA : taille maximale de la base de données -> 200Go

Avec HA : taille maximale de la base de données -> 2To

(Le maximum supporté (mais non recommandé) étant 16To)

 

Ensuite, n’étant pas en JBOD nous allons devoir utiliser du RAID et donc introduire le facteur pénalité au niveau des I/O.

En effet lorsque nous sommes en RAID, un I/O (de type écriture) qui arrive au niveau du contrôleur RAID, qui gère notre grappe de disques physiques sur lequel repose notre LUN, ne requière pas qu’une simple écriture ou lecture.

Prenons du RAID5 (le plus commun) nous avons une pénalité de 4 en écriture car :

Une fois que l’I/O arrive dans le contrôleur nous avons besoin de 2 opérations de lecture et 2 opérations d’écriture pour achever l’écriture de cet I/O dans notre stockage.

  1. Lecture de la donnée non modifiée (qui va être mise à jour)
  2. Lecture de la parité associée
  3. Calcule de nouvelle parité (nouvelle donnée avec la parité récupérée précédemment)
  4. Ecriture nouvelle donnée
  5. Ecriture nouvelle parité associée

 

Donc 1 I/O en écriture sur une LUN en RAID5 équivaut à 4 I/O en réalité, et c’est ce facteur que nous devons prendre en compte dans notre dimensionnement.

 

Tableau des pénalités :

Niveau RAID

Lecture

Ecriture

RAID 0

1

1

RAID 1 ou RAID 10

1

2

RAID 5

1

4

RAID 6

1

6

 

Pour minimiser l’impact de cette pénalité le stockage de type entreprise (EMC², Netapp, etc) utilise un cache et des algorithmes d’optimisation.

Mais tout cela marche très bien sur des I/O de type séquentiels et non aléatoire (random), encore une fois tout le travail de l’équipe d’exchange et d’optimiser la gestion de ses I/O pour les rendre au maximum séquentiels.

Nous sommes aujourd’hui avec Exchange 2010 sur 60% d’I/O séquentiels pour 40% d’I/O aléatoires.

 

Mais nous avons une configuration plus modeste et nous nous appuierons sur le contrôleur RAID de notre serveur donc il ne faudra pas trop s’attendre à des miracles.

Nous aurons à notre disposition un cache tout petit et des algorithmes basiques.

 

Alors maintenant voyons nos calculs :

 

  1. Sans HA

 

Pour minimiser les couts nous retrouverons souvent un serveur physique avec 5 disques.

2 disques en RAID 1 pour le système et les applications

2 disques en RAID 1 pour les bases de données et les logs

    Ou

3 disques en RAID 5 pour les bases de données et les logs

Si nous utilisons des disques standards nous aurons souvent des spindles à 7200 tours/min en 3,5 pouces SAS

 

Je vais répondre à une question que vous devez surement vous poser, à savoir pourquoi du RAID 1 pour les databases.

Et bien étant donné que nous sommes sur une petite configuration c’est moins gênant de perdre 50% de volumétrie (alors que l’on n’en perd que 1 disque sur du RAID 5).

Les bases feront 200 Go maximum pour héberger nos utilisateurs et rentrerons sur 2To (en RAID 1) nous utiliserons donc 2 disques.

Elles rentreraient aussi sur du RAID 5 même en comptant la pénalité supplémentaire mais par contre nous devrions utiliser 3 disques !

 

Nous allons utiliser le même type de profile que dans la partie 3 :

Profile I/O :

100 messages (80/20)

200Ko la taille moyenne d’un mail

14 jours de SIR

 

Partons sur une cible de 100 boîtes aux lettres à héberger

 

(Adapter en fonction de vos besoins avec les tableaux présents ici : http://technet.microsoft.com/en-us/library/ee712771(EXCHG.140).aspx)

C’est très important car si vous avez bien 100 mails par jour le profile est 0,12 alors qu’avec 150 on passe à 0,18)

 

Maintenant calculons :

La formule pour la charge en I/O est la même que vue en partie 3 :

Database Volume I/O = Number of Mailboxes x IOPS Profile x (1 + I/O Overhead Growth Factor)

100×0.12x(1+20%)=14,4 IOPS

Nous prendrons comme cible 15 IOPS

Ajoutons maintenant la pénalité :

Pour rappel une database représente 60% de lecture 40% d’écriture donc avec la formule (%Lecture + Pénalité(%Ecriture) nous obtenons :

RAID 1 de 2 : (0,6+(2×0,4))x15 = 21 IOPS

RAID 5 de 4 : (0,6+(4×0,4))x15 = 33 IOPS

 

Nous devons donc pouvoir soutenir 21 IOPS avec notre stockage.

 

Pour calculer le nombre de disques pour soutenir notre charge, voici la formule

nombre de disques = ((%Lecture + Pénalité(%Ecriture))(IOPS cible))/IOPS max par disque

 

En RAID 1 : ((0,6+(2×0,4))x15)/65=0,32 donc nous pouvons soutenir notre charge sur 2 disques en RAID 1

En RAID 5 : ((0,6+(4×0,4))x15)/65=0,50 donc nous pouvons aussi soutenir notre charge sur 3 disques en RAID 5

 

Maintenant essayons de définir nos building block, en partant du stockage je peux soutenir maximum 65 IOPS sur un disque de 2To SAS 7200 tours/min, donc :

Maximum IOPS database =

65 / (0,6+(2×0,4)) = 46,43 disons 46 IOPS pour du RAID 1

(65×2) / (0,6+(4×0,4)) = 59,09 disons 59 IOPS pour du RAID 5 (2+1)

 

Nous sommes presque arrivé au bout :

Nombre maximum d’utilisateurs =

(65 / (0,6+(2×0,4))) / (0,12x(1+20%)) = 322,42 disons 322 utilisateurs en RAID 1

((65×2) / (0,6+(4×0,4))) / (0,12x(1+20%)) = 410,35 disons 410 utilisateurs en RAID 5 (2+1)

 

Mais nous n’avons pas pris en compte les quotas car pour rappel nous sommes limités à une base de 200Go

Pour finir :

322 utilisateurs pourront avoir un quotas maximum de 210Mo pour tous les mettre dans 1 base de 200Go en RAID 1

410 utilisateurs pourront avoir un quotas maximum de 100Mo pour tous les mettre dans 1 base de 200Go en RAID 5

 

Donc nous voyons bien ici que nous sommes limités par la taille des boites aux lettres (Quota)

Si nous prenons des quotas à 1Go nous pouvons mettre 120 utilisateurs par base de 200Go

Si nous prenons des quotas à 2Go nous pouvons mettre 68 utilisateurs par base de 200Go

 

Récapitulatif

Type de disque

Niveau de RAID

Pénalité

Nombre d’IOPS supporté

Nombre d’utilisateurs

Quota

Nombre d’utilisateurs par base de 200Go

Nombre de bases nécessaire

Licence Exchange necessaire

SAS 2To 7200 trm

RAID 1 (1+1)

2

46

322

1Go

120

3

standard

SAS 2To 7200 trm

RAID 1 (1+1)

2

46

322

2Go

68

5

standard

SAS 2To 7200 trm

RAID 5 (2+1)

4

59

410

1Go

120

4

standard

SAS 2To 7200 trm

RAID 5 (2+1)

4

59

410

2Go

68

7

enterprise

 

  1. Avec HA

 

Ce qui va changer avec le HA c’est le nombre de serveurs MBX qui passe à 2 minimums ainsi que les licences Windows utilisées qui sont de type Entreprise (pour supporter le cluster MSCS utilisé par le DAG).

Mais surtout, nous passons de 200Go à 2To comme taille de Database en best practise!

Attention à ne pas oublier si vous installez tous les rôles Exchange sur vos 2 serveurs, le cluster MSCS étant obligatoire pour le rôle MBX en mode DAG, vous ne pourrez pas utiliser le cluster NLB pour vos rôles CAS, vous devrez recourir à un boitier externe de load balancing.

 

Coté calcul la seul chose qui change sera la taille limite à 2To (best practise) et le profile I/O qui passe de 0,12 à 0,1 et donc :

 

RAID 1 avec 2 disques de 2To = 2To de volumétrie exploitable

RAID 5 avec 3 disques de 2To = 4To de volumétrie exploitable

 

Je vous passe toutes les étapes qui sont les même que précédemment et vais directement à l’essentiel :

 

Nombre maximum d’utilisateurs =

(65 / (0,6+(2×0,4))) / (0,1x(1+20%)) = 386,90 disons 386 utilisateurs en RAID 1

((65×2) / (0,6+(4×0,4))) / (0,1x(1+20%)) = 492,42 disons 492 utilisateurs en RAID 5 (2+1)

 

Mais nous n’avons pas pris en compte les quotas car pour rappel nous sommes limités à une base de 2To

Donc la vrai taille de notre disque de 2To est : 2×0.931 = 1,862TB (To) = 1906,688Go (comme vu dans la partie 3)

En RAID 1 nous aurons donc 1906,688Go de disponible (1 LUN).

En RAID 5 nous aurons donc 2×1906,688Go soit 3813,376Go de disponible (2 LUNs).

 

Pour la donnée exchange nous avons toujours le garde-fou de 20% par LUN donc :

En RAID 1 nous avons 1906,688 – 20% = 1525,3504Go (pour mettre notre database + ses logs)

En RAID 5 nous avons 2×1525,3504Go = 3050,7008Go (pour mettre 2 databases + leurs logs)

 

Pour finir :

322 utilisateurs pourront avoir un quotas maximum de 2,5Go pour tous les mettre dans 1 LUN de 2To en RAID 1

492 utilisateurs pourront avoir un quotas maximum de 3Go pour tous les mettre dans 2 LUNs de 2To en RAID 5 (2+1)

 

Donc nous voyons bien ici que nous sommes limités par le nombre d’IO maximum que peut fournir notre grappe RAID !

Si nous baissons les quotas nous ne pourrons pas mettre plus d’utilisateurs !!

 

Récapitulatif

Type de disque

Niveau de RAID

Pénalité

Nombre d’IOPS supporté

Nombre d’utilisateurs

Quota maximum

Nombre de bases nécessaire

Licence Exchange necessaire

SAS 2To 7200 trm

RAID 1 (1+1)

2

46

386

2,5Go

1

standard

SAS 2To 7200 trm

RAID 5 (2+1)

4

59

492

3Go

2

standard

 

Nous sommes arrivés au bout de cette partie 🙂

Nous verrons dans la prochaine les best practise sur les volumes et le RAID à respecter pour être dans des conditions optimales.

 

Si vous avez des questions n’hésitez pas.

Anthony COSTESEQUE

Posted in 1-EXCHANGE 2010, Exchange 2010 Service Pack 1, Exchange Server 2010, Stockage-2010 | 1 Comment »

Microsoft Lync Server 2010 Capacity Calculator

Posted by David PEKMEZ sur août 4, 2011


Une nouvelle version du calculateur Lync est disponible sur le site Microsoft !

A vos téléchargements J

http://www.microsoft.com/download/en/details.aspx?id=12295


David Pekmez

Posted in Lync 2010, Outils-2010 | Leave a Comment »

Archivage et Fragmentation

Posted by David PEKMEZ sur août 3, 2011


Un petit post ce soir afin de vous donner un lien vers un article très intéressant concernant certains outils d’archivage et la Fragmentation des pages Exchange,

A prendre en compte lors de vos choix en termes de technologie d’archivage !

http://blogs.technet.com/b/jamec/archive/2011/08/01/exchange-2010-database-page-fragmentation-caused-by-archive-solutions.aspx

Bonne lecture

David Pekmez

Posted in 1-EXCHANGE 2010, Archivage-2010 | Leave a Comment »