Prepare-Moverequest.ps1
Wenn Sie nicht mit Prepare-MoveRequest arbeiten wollen, dann ist auf Org2Org MoveRequest noch der Weg über eine CSV-Datei beschrieben.
Mit dem Wechsel von Exchange 2007 nach Exchange 2010 hat Microsoft eine aus meiner Sicht sinnvolle Änderung bezüglich einer Cross-Org-Migration durchgeführt. Das Exchange 2007 Commandlet "Move-Mailbox" hat nicht nur die Postfachinhalte von einer Organisation in die andere Organisation übertragen, sondern auch noch das Zielpostfach anhand ProxyAdresses, SIDHistory, ObjectSID LegacyExchangeDN "gesucht" und gematched. Bei Exchange 2010 wird nur noch das Feld "msExchMailboxGUID" zum Matchen genutzt.
Auf der einen Seite bedeutet dies, dass Sie die Zielumgebung nun entsprechend vorbereiten müssen. Andererseits können Sie dann aber auch sicher sein, dass die Übereinstimmung dann auch wirklich zuverlässig und Eindeutig sind. Das war vorher auch etwas von der Reihenfolge der Suche abhängig. für die Vorbereitung hat Microsoft die nun fehlende Logik in einem sehr leistungsfähigen PowerShell-Skript untergebracht. Prepare-MoveRequest.ps1 ist auf jedem Exchange 2010 Server im Verzeichnis "Scripts" enthalten und wird durch Servicepacks auch aktualisiert.
Ich begrüße diesen Wechsel, da Sie nun selbst im Skript die Funktionsweise nachvollziehen und sogar auf die eigenen Bedürfnisse anpassen können. Das ist besser als eine verkapselte EXE oder ein Commandlet, deren genauer Funktion verborgen bleibt.
Was macht Prepare-Moverequest.PS1?
Prepare-Moverequest.ps1 bereitet den Zielforest derart vor, dass es dort Active Directory Benutzer gibt, die in Exchange als "MailUser" erscheinen. Es sind also schon Benutzerobjekte im Active Directory aber in der Exchange-Sichtweise sind es erst einmal Kontakte. Diese Kontakte haben als Zieladresse (TargetAddress) eine SMTP-Adresse, die Mails an diesen Empfänger weiter an das Quellpostfach sendet. Aber Prepare-Moverequest macht kein "Provisioning", d.h. ein "Update-Recipient" o.ä. findet nicht statt. Damit ein MailUser fehlerfrei durchgeht, reicht der Inhalt in mailnickname, ProxyAddresses und TargetAddress. Prepare-MoveRequest kann auch eingesetzt werden, wenn es überhaupt keinen Verzeichnisabgleich gibt, weil es dann entsprechende „MailUser“ anlegt. Sollte es im Ziel aber bereits Benutzerobjekte oder Mailkontakte geben, dann werden diese anhand verschiedener Kriterien sogar gematched.
Einschränkungen
Auch wenn Prepare-MoveRequest ein sehr leistungsfähiges Skript ist, so gibt es ein paar Einschränkungen, die nicht verschwiegen werden sollen:
- DauerSync
Das Skript ist kein Ersatz oder Lösung für einen "Verzeichnisabgleich" zwischen zwei Organisationen sondern dient nur der Vorbereitung einer Migration. Es löscht z.B. keine Objekte im Ziel, so dass die Verzeichnisse auseinanderlaufen - Nur "Postfächer"
Mit dem Fokus auf eine Migration ist verständlich, dass Prepare-MoveRequest auch nur Postfächer in der Quelle sucht und auf Objekte im Ziel abbilden will. Verteiler und Kontakte sind außen vor. Das können Sie aber z.B. mit dem ADMT -Active Directory Migration Toolkit bewerkstelligen - Automapping
Leider übernimmt Prepare-Moverequest keine Einträge des Automappings. Diese Funktion ist gerade bei einer Shared Mailbox interessant, um diese automatisiert bei Benutzern einzubinden. Auch hier ist "Nacharbeit" erforderlich.
Neuanlage
Der einfachste Startpunkt ist die Neuanlage von Objekten über Prepare-Moverequest.
.\prepare-moverequest.ps1 ` -identity test@msxfaq.quelle ` -remoteforestdomaincontroller dcquelle.msxfaq.quelle` -remoteforestcredential $remote ` -LocalForestDomainController dcziel.msxfaq.ziel ` -localforestcredential $local ` -TargetMailUserOU "OU=Import,DC=msxfaq,DC=ziel" ` -mailboxdeliverydomain msxfaq.quelle ` -Disable -verbose
Auf der Konsole wird dann in etwas ausgegeben. Sie können schön sehen, was das Skript so tut.
VERBOSE: Setting displayName to Test TestSN VERBOSE: Setting Mail to User1@msxfaq.quelle VERBOSE: Setting mailNickName to User1 VERBOSE: Setting msExchMailboxGuid to fca24a96-5a54-4a2f-b9a7-f1aec452abe1 VERBOSE: Setting msExchUserCulture to de-DE VERBOSE: Setting proxyAddresses to SMTP:User1@msxfaq.quelle X400:C=DE;A= ;P=Erste Organisati;O=Exchange;S=TestSN;G=Test; FAX:User1@FAX VERBOSE: Setting UserAccountControl to 514 VERBOSE: Setting UserPrincipalName to User1@msxfaq.quelle VERBOSE: Setting samaccountname to User1 VERBOSE: Setting msExchVersion to 44220983382016 VERBOSE: Setting msExchRecipientDisplayType to -2147483642 VERBOSE: Setting msExchRecipientTypeDetails to 128 Appending x500:/o=Erste Organisation/ou=Erste administrative Gruppe/cn=Recipients/cn=User1 to proxyAddresses of New Object in Local forest. VERBOSE: Setting targetAddress to SMTP:User1@msxfaq.quelle VERBOSE: Setting countryCode to 0 VERBOSE: Setting Department to Abteilung VERBOSE: Setting facsimileTelephoneNumber to +495251304650 VERBOSE: Setting givenName to Test VERBOSE: Setting msExchHideFromAddressLists to False VERBOSE: Setting Sn to TestSN VERBOSE: Setting telephoneNumber to +495251304600 VERBOSE: Setting Title to Titel VERBOSE: Setting Description to TestUser VERBOSE: Setting msExchMDBRulesQuota to 64 VERBOSE: Setting msExchPoliciesExcluded to {26491cfc-9e50-4857-861b-0cb8df22b5d7} VERBOSE: Setting textEncodedORAddress to X400:C=DE;A= ;P=Erste Organisati;O=Exchange;S=TestSN;G=Test; WARNING: Cannot find corresponding object für CN=group1,DC=msxfaq,DC=quelle in current forest. 'member' not Updated. VERBOSE: Invoke Update-Recipient to Update LegacyExchangeDN. Appending x500:/o=MailOrg/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=Test to proxy Addresses of Object(CN=Test TestSN,DC=msxfaq,DC=quelle) in Source forest. Preparation für User1@msxfaq.quelle done. 1 mailbox(s) ready to move.
Sie können also recht genau sehen, was das Skript macht. Über den Parameter "Identity" können Sie einzelne (Test-)Benutzer durchproben, ehe Sie die komplette Liste abarbeiten.
Ich würde das Skript immer mit
"-verbose" starten
Zudem würde ich mit "Start-Transcript" auch die
Protokollierung der Konsole in eine Datei
aktivieren.
Matching und Merging
Wenn Prepare-Moverequest nicht zur Neuanlage von Objekten verwendet wird, sondern bestehenden Objekte verwenden muss, dann "kommen folgende "Match-Regeln" zum Einsatz:
- ProxyAddresses
Es wird geschaut, ob es eine Übereinstimmung einer "ProxyAdresses" der Quelle mit dem Ziel gibt. Dazu muss das Zielobjekt natürlich bereits "MailEnabled" sein (z.B. ein Kontakt) oder zumindest das Feld "ProxyAddresses" durch einen anderen Prozess gefüllt worden sein. - MasterAccountSid
Für spezielle Umgebungen mit einem Ressourceforst kann prepare-Moverequest auch das Feld msExchMasterAccountSID nutzen, um das Zielobjekt anhand der SID des Quellobjekts zu finden. Das ist aber ein eher seltener Fall. Prepare-Moverequest kann aber selbst die MasterAccountSID setzen. Siehe "Parameter -LinkedMailbox"
ADMT migriert per Default
nicht die Felder "mail", "msExchMailboxGuid" und
"proxyAddresses, wenn der Zielforest bereits
Exchange installiert ist. Sollte der Zielforest
aber noch kein Exchange enthalten, dann werden
diese Werte übertragen, was zu korrupten
Elementen führt.
937537 You find that several custom attributes
are missing when you use ADMT to migrate Users
between two forests
Die folgende Tabelle soll aufzeigen, was aus einem Zielobjekt durch Prepare-Moverequest gemacht wird, wenn mit "-UseLocalObjekt" ein Merge angefordert wird.
Feld\Quellobjekt |
MailContact |
MailUser |
User ohne Mail |
---|---|---|---|
Aktion |
Wird zu MailUser |
Wird erweitert |
Skip |
msExchMailboxGUID |
Aus Quelle |
Aus Quelle bei „-OverwriteLocalObject“ oder "-UseLocalObject" |
Skip |
msExchArchiveGUID |
Aus Quelle |
Aus Quelle bei „-OverwriteLocalObject“ oder "-UseLocalObject" |
Skip |
msExchArchiveName |
Aus Quelle |
Aus Quelle bei „-$OverwriteLocalObject“ oder "-UseLocalObject" |
Skip |
sAMAccountName |
Aus Quelle |
Nein |
Skip |
objectSid |
In
MasterAccountSID, |
In
MasterAccountSID, |
Skip |
masterAccountSid |
Wenn „LinkedMailUser“ gesetzt |
Leider nein |
Skip |
UserAccountControl |
514 (Disabled) |
Keine Änderung |
Skip |
UserPrincipalName |
Aus Quelle |
Keine Änderung |
Skip |
LegacyExchangeDN |
Wird neu
generiert |
Wird erweitert |
Skip |
|
Nicht geändert ! |
Aus Quelle
bei „-OverwriteLocalObject“ |
Skip |
ProxyAddresses |
Nicht geändert ! |
Aus Quelle
bei „-OverwriteLocalObject“ |
Skip |
Ist das Ziel angelegt oder gefunden worden, dann überträgt Prepare-MoveRequest jede Menge Felder vom Quellobjekt in das Zielobjekt. Die genaue Liste ist abhängig davon, ob das Ziel neu angelegt oder ein bestehendes Objekt "recycled" wurde.
Parameter "UseLocalObject"
Normalerweise legt Prepare-MoveRequest neue Mailenabled User im Ziel an. Wenn allerdings schon Objekte mit einer entsprechenden Target-Address vorhanden sind, dann stoppt das Skript mit einem Fehler, dass es den Benutzer schon vorhanden ist. Mit der Option "Use-LocalObject" wird das Skript angewiesen, den bestehenden Benutzer zu nutzen oder zu aktualisieren.
Findet Prepare-Moverequest keinen passenden Benutzer, wird der Eintrag mit einem Error übersprungen!
Prepare-Moverequest kann keine "Konsolidierung" über Domänen hinweg durchführen. Wenn der Kontakt also in einer anderen Domäne vorhanden ist, dann wird die Zusammenführung nicht funktionieren.
Zudem werden nur drei Properties kopiert.
- msExchMailboxGUID
- msExchArchiveGUID
- msExchArchiveName
Das kann man auch auf der Bildschirmausgabe ("-verbose") sehen':
VERBOSE: Local ad account with dupplicate proxy addresses found: CN=Test,OU=Import,DC=msxfaq,DC=test2 VERBOSE: Merging Mailbox properties to local MailUser VERBOSE: Setting msExchMailboxGUID to fca24a96-5a54-4a2f-b9a7-f1aec452abe1 Preparation für test@msxfaq.test2 done. Local recipient info Merged.
Die Quelle hat kein Archiv, so dass hier nur ein Property übrig bleibt. Diese drei Properties sind für die spätere Migration relevant. Alle anderen Felder sollten durch den Prozess bereits kopiert worden sein, der vorab die MailKontakte oder MailUser angelegt hat. In Verbindung mit ADMT kommt diesem Switch eine besondere Funktion zu.
When a User is created via
ADMT, the PrepareMoveRequest script doesn't work
since there are no proxyAddresses für the script
to match the source forest User with the target
forest User. The recommended approach is to copy
at least 1 proxy address using ADMT.
However, if you use the -UseLocalObject
parameter, the script will only copy the 3
mandatory parameters (msExchMailboxGUID,
msExchArchiveGUID, msExchArchiveName).
Quelle: Exchange 2010 Cross-Forest Mailbox Moves
(http://blogs.technet.com/b/exchange/archive/2010/08/10/3410619.aspx)
Parameter "-OverwriteLocalObject"
Dieser Parameter ist erst seit Exchange 2010 SP1 verfügbar und entspannt ein Problem der früheren Versionen in Verbindung mit ADMT. Wurde Prepare-Moverequest mit der Option "-UserExistingObjekt" aufgerufen, dann wurden nur die drei elementaren Felder übertragen, da davon ausgegangen wurde, dass alle anderen Felder durch einen anderen Prozess bereits beschrieben wurden. Das ist der Fall, wenn z.B. ADMT vorab eingesetzt wurde.
Mit "-OverwriteLocalObject" wird prepare-Moverequest.ps1 explizit angewiesen, bei dem bestehenden Objekte auch die anderen Felder (z.B. Ort, Straße etc.) aus der Quelle auf das Zielobjekt zu schreiben. Es kann damit nicht mit "-UseLocalObject" parallel verwendet werden.
Parameter "-MailDeliveryDomain"
Wenn Prepare-Moverequest die Mailenabled User anlegt, muss er eine "TargetAddress" mit angeben. Damit er die "richtige Adresse" verwendet, müssen Sie über den Parameter "MailDeliveryDomain" die SMTP-Domäne der Quelle angeben, in der das Postfach noch vorhanden ist. Prepare-Moverequest sucht sich dann eine der ProxyAddresses, um daraus die TargetAddress zu bilden.
Bitte fassen Sie den
Parameter mit "-Zeichen ein, damit es wirklich
nur der String ist.
Im Code ist ein "Compare" des Domainanteils mit
dieser Variable und der Wert sollte keine
Leerzeichen oder CRLF am Anfang oder Ende haben.
Parameter "-LinkedMailbox"
Achtung: Linked Mailbox
Warum auch immer setzt das Skript den Wert für "msExchMasterAccoundSID"
nur, wenn das Quellkonto deaktiviert ist.
Leider kopiert Prepare-Moverequest nur dann mit der Option „LinkedMailUser“ die msExchmasterAccountSID, wenn es einen MailContact konvertiert, einen MailUser anlegt oder das Quellkonto deaktiviert ist. Der temporäre Betrieb als Ressourceforest mit TargetAddress ist gerade während Migrationen eine interessante Option. Das Anmeldekonto verbleibt noch in der Quelle, wenn zuerst die Postfächer verschiedener Firmen in eine Organisation konsolidiert werden.
Wurden aber die Benutzer schon vorher per ADMT schon mal im Ziel angelegt, dann matched prepare-Moverequest das Objekt aber kopiert in diesem Fall den msExchMasterAccountSID nur, wenn die Quelle deaktiviert ist. Das passt natürlich nur, wenn das Postfach schon in der Quelle eine LinkedMailbox war.
Aber da Prepare-Moverequest ein
PowerShell-Skript ist, können Sie diese
Verhalten ja leicht so anpassen, dass das Feld
auch kopiert wird, wenn des Zielkonto
deaktiviert ist. Relevant ist bei der Version
aus Exchange 2010 SP1 die Zeile 870, die einfach
derart abgeändert wird, dass der
Status des Zielkontos überprüft wird. Wenn das
Zielkonto deaktiviert ist, dann wird die msExchMasterAccountSID kopiert
Parameter "-DisableEmailAddressPolicy"
Normalerweise würde der Exchange Server im Ziel das Objekt direkt den Empfängerrichtlinien unterwerfen. Wenn das nicht gewollt ist, kann es auch deaktiviert werden. Den Erfolg können Sie im Log sehen:
VERBOSE: Disable EmailAddressPolicy.
Auch wenn ein DisableEmailAddressPolicy als schnelle Lösung funktioniert, so ist langfristig die Verwaltung von Empfängern ohne Richtlinien ein aufwändiges Geschäft (Ausnahme: Provisioningtools). Daher würde ich eher eine passende Empfängerrichtlinie anlegen, die zuerst die neu migrierten Objekte korrekt konfiguriert und nach der Migration auch neue Postfächer gleich korrekt einrichtet
Übergabe per Pipeline oder "-Identity"
Wenn nur ein Postfach "vorbereitet" werden soll, dann gebe ich die Mailbox über den Parameter "Identity" an. Sollen mehrere Postfächer umgestellt werden, dann bietet es sich an, die Adressen der Mailboxen über die Pipeline zu übergeben. Alternative kann das Skript natürlich auch über eine For-Schleife aufgerufen werden und als "-identity" die Adresse übergeben werden.
Bei der Übergabe aus der Pipeline ist darauf zu achten, dass nur die Mailadresse (ohne Leerzeichen) übergeben wird. Gerade wenn man mit "Get-Content" eine Textdatei einliest, kann dies passieren und Prepare-Moverequest findet das Postfach dann nicht. Es macht keinen "TRIM"
DirSync mit Prepare-Moverequest.ps1
Ehe Sie nun frohlocken und Prepare-Moverequest als kostenfreie Alternative zu MISS, FIM und und anderen Tools ansehen, sei hier eine Warnung ausgesprochen.
Prepare-Moverequest kann keinen DirSync ersetzen!
Ein Verzeichnisabgleich (Siehe auch Verzeichnisabgleich) beinhaltet weitere Funktionen. Prepare-Moverequest.ps1 hat folgende Einschränkungen:
- Keine Verteiler, Kontakte und Public Folder
Diese Objekte werden durch das Skript einfach ignoriert. Das ist natürlich für eine produktive Migration nicht tolerierbar. Gerade Verteiler (Gruppen) können zwar per ADMT übertragen werden und Prepare-MoveRequest kann sogar die Member aktualisieren, aber weder ADMT noch Prepare-MoveRequest kopieren die Exchange Properties. - Änderungen im Ziel werden
überschrieben
Prepare-MoveRequest überschreibt immer wieder die Zieldaten mit den Quelldaten. Nur wenn das Zielobjekt schon ein Postfach geworden ist, wird dies blockiert. - keine Löschaktionen umsetzen.
Wird ein Objekt in der Quelle gelöscht, dann wird das Ziel nicht entfernt. - Keine Kennwort oder
SIDHistory
Hierzu sind ADMT und andere Skripte erforderlich.
Wer also nicht in einer kurzen Zeit die Migration durchführen kann, sollte sich Gedanken über einen echten Verzeichnisabgleich machen.
Automapping
Bei den Einschränkungen weiter oben habe ich schon beschrieben dass Prepare-Moverequest keine "Automapping"-Einträge kopiert. Beim Automapping wird an dem AD-Objekte der SharedMailbox im Feld "msExchDelegateListLink" hinterlegt, welche andere Postfächer "berechtigt" sind. Nach dem Umzug der Postfächer in das Ziel ist das Feld aber leer aber die Berechtigungen sind schon noch da. Damit haben wir nun zwei Optionen:
- Automapping anhand der Rechte neu
aufbauen
Mittels "Get-MailboxPermission" kann ich ermitteln, welche Postfächer welche berechtigten Benutzer haben und damit das Automapping nachführen. Das ist allerdings nicht ganz sicher, da dann alle berechtigten Benutzer ein Automapping bekommen. - Automapping kopieren
Der zweite und bessere Weg ist die Übernahme der Automapping-Einträge auf der Quelle. Dies kann durch einen Export aus der Quelle und einen passenden Import im Ziel erfolgen. Natürlich sind die Strings mit den DistinguishedNames angepasst werden.
Für den Export und späteren Import von Automapping-Einträgen habe ich ein eigenes Skript gebaut:
Prepare-Moverequest mit Office 365
Bei der Migration mit Office 365 kommt eine leicht abgewandelte Version zum Einsatz. Das mit Office 365 auch ein "DirSync" enthalten ist (Siehe DirSync) ist hier ein Modul für den genutzten FIM erforderlich und eine angepasste Version des Skripts.
Prepare für Online
Mailbox Move
http://www.microsoft.com/en-us/download/details.aspx?id=17741
Ich gehe auf dieser Seite nicht weiter auf diese besondere Version ein.
Weitere Links
- Migration Org2Org
- Org2Org Tools
- Org2Org MoveRequest
- TargetAddress
- Cross Org
- Export-Automapping
- Understanding Move Requests
http://technet.microsoft.com/en-us/library/dd298174.aspx - PrepareMoveMailbox-Script
http://technet.microsoft.com/en-us/library/ee861103.aspx - Prepare Mailboxes für Cross-Forest Move Requests
http://msdn.microsoft.com/en-us/library/ee633491.aspx - Create a Remote
Legacy Move Request Where One of the Forests Doesn't Have Exchange 2010
http://msdn.microsoft.com/en-us/library/dd876952.aspx - Create a Remote Move Request That has Exchange 2010 in Both Forests
http://msdn.microsoft.com/en-us/library/dd351280.aspx - New-MoveRequest
http://msdn.microsoft.com/en-us/library/dd351123.aspx - Prepare Mailboxes für Cross-Forest Moves using the
PrepareMoveRequest.ps1 script in the Shell
http://technet.microsoft.com/de-de/library/ee861103%28EXCHG.140%29.aspx - Prepare Mailboxes für Cross-Forest Moves using
Sample Code
http://technet.microsoft.com/en-us/library/ee861124%28EXCHG.140%29.aspx - Prepare für Online Mailbox Move
http://www.microsoft.com/downloads/details.aspx?FamilyID=16a91d42-5ca4-4b58-aaa6-b2689b99ba51&displaylang=en#filelist -
Exchange 2010 Cross-Forest
Mailbox Moves
http://blogs.technet.com/b/schadinio/archive/2010/08/11/exchange-2010-cross-forest-mailbox-moves.aspx -
Accessing Exchange 2010 mailbox
move history data
http://thoughtsofanidlemind.wordpress.com/2010/09/13/exchange2010-move-history/ -
Exchange Server 2010 Cross-Forest migration
http://blog.PowerShell.no/2010/04/23/exchange-server-2010-cross-forest-migration/
Alternatives PowerShell Script, welches ähnliche Vorarbeiten leistet. -
Prepare-MoveRequest creates the MEU locally
and appends the leDN of the MEU as an X500 proxy
to the MBX in the remote domain. When you kick
off the move request that will do the
conversions on both ends
http://blogs.technet.com/b/exchange/archive/2010/08/10/455779.aspx
http://blog.PowerShell.no/2010/04/23/exchange-server-2010-cross-forest-migration/ -
Felder die in das Ziel übertragen werden sollten
http://www.shudnow.net/2009/06/09/cross-forest-mailbox-move-changes-in-exchange-2010/ - Exchange 2010 Cross-Forest Mailbox Moves
http://blogs.technet.com/b/exchange/archive/2010/08/10/3410619.aspx - Exchange 2010 Cross-Forest Migration Step by Step
Guide
Part 1: http://blogs.technet.com/b/meamcs/archive/2011/06/10/exchange-2010-cross-forest-migration-step-by-step-guide-part-i.aspx
Part 2: http://blogs.technet.com/b/meamcs/archive/2011/10/25/exchange-2010-cross-forest-migration-step-by-step-guide-part-ii.aspx
Part 3: http://blogs.technet.com/b/meamcs/archive/2011/10/25/exchange-2010-cross-forest-migration-step-by-step-guide-part-iii.aspx - Exchange Server 2010 Cross-Forest migration
http://blog.PowerShell.no/2010/04/23/exchange-server-2010-cross-forest-migration/ - Vorbereiten von Postfächern für eine
standortübergreifende Verschiebung mit dem Skript
"Prepare-MoveRequest.ps1" in der Shell
http://technet.microsoft.com/de-de/library/ee861103(v=exchg.141).aspx - PrepareMoveRequest.ps1 in a multi domain scenario
http://blogs.technet.com/b/cloud_no_10/archive/2012/05/15/preparemoverequest-ps1-in-a-multi-domain-scenario.aspx -
GUI Interface für Exchange
2003 to Exchange 2010 Cross
Forest Move Mailbox using
PowerShell
http://www.itbigbang.com/gui-interface-for-exchange-2003-to-exchange-2010-cross-forest-move-mailbox-using-PowerShell/
http://gallery.technet.microsoft.com/ScriptCenter/c1a9e5b1-4e48-4659-8d9c-2ab8f7a01e60/ -
Exchange inter-forest migration
tips
https://www.hayesjupe.com/exchange-interforest-migration-tips/