Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
## [Current nightly]

### Added
- Added `Start-PnPTenantRename` cmdlet to schedule SharePoint Online tenant domain rename jobs. [#5304](https://github.com/pnp/powershell/pull/5304)
- Added `Get-PnPListVersionPolicy` and `Set-PnPListVersionPolicy` cmdlets to inspect and manage SharePoint Online document library version policies. [#5300](https://github.com/pnp/powershell/pull/5300)
- Added `New-PnPSiteManageVersionPolicyJob` cmdlet to queue site-level list version policy trim and sync jobs. [#5300](https://github.com/pnp/powershell/pull/5300)
- Added site version policy parameters to `Set-PnPSite` and `Set-PnPTenantSite`, including support for inheriting tenant defaults, targeting new or existing document libraries, managing file type overrides, and bypassing confirmation with `-Force`. [#5300](https://github.com/pnp/powershell/pull/5300)
Expand Down
123 changes: 123 additions & 0 deletions documentation/Start-PnPTenantRename.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
Module Name: PnP.PowerShell
title: Start-PnPTenantRename
schema: 2.0.0
applicable: SharePoint Online
external help file: PnP.PowerShell.dll-Help.xml
online version: https://pnp.github.io/powershell/cmdlets/Start-PnPTenantRename.html
---

# Start-PnPTenantRename

## SYNOPSIS
Schedules a rename of the SharePoint Online tenant domain name.

## SYNTAX

```powershell
Start-PnPTenantRename -DomainName <String> -ScheduledDateTime <DateTime> [-Connection <PnPConnection>] [-WhatIf] [-Confirm]
```

## DESCRIPTION
Schedules a tenant rename job to change the SharePoint Online domain name for the organization. For example, this can change `contoso.sharepoint.com` to `fabrikam.sharepoint.com`.

The new domain name must already have been added successfully to Microsoft Entra ID. Specify only the domain prefix, without `.sharepoint.com` or `.onmicrosoft.com`.

The scheduled date and time must be at least 24 hours in the future and no more than 30 days in the future. Tenant rename can take several hours to days depending on the number of SharePoint sites and OneDrive accounts in the tenant.

## EXAMPLES

### EXAMPLE 1
```powershell
Start-PnPTenantRename -DomainName "fabrikam" -ScheduledDateTime "2026-05-30T22:00:00"
```

Schedules the SharePoint Online tenant domain rename to `fabrikam.sharepoint.com` for May 30, 2026 at 22:00.

### EXAMPLE 2
```powershell
Start-PnPTenantRename -DomainName "fabrikam" -ScheduledDateTime (Get-Date).AddDays(7) -WhatIf
```

Shows what would happen if the tenant rename were scheduled one week from now.

## PARAMETERS

### -Connection
Optional connection to be used by the cmdlet. Retrieve the value for this parameter by specifying `-ReturnConnection` on `Connect-PnPOnline` or by executing `Get-PnPConnection`.

```yaml
Type: PnPConnection
Parameter Sets: (All)

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### -Confirm
Prompts you for confirmation before running the cmdlet.

```yaml
Type: SwitchParameter
Parameter Sets: (All)

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### -DomainName
Specifies the new SharePoint Online domain prefix. Do not include `.sharepoint.com` or `.onmicrosoft.com`.

```yaml
Type: String
Parameter Sets: (All)

Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### -ScheduledDateTime
Specifies the date and time at which the tenant rename job should start. SharePoint Online requires this to be at least 24 hours in the future and no more than 30 days in the future.

```yaml
Type: DateTime
Parameter Sets: (All)

Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### -WhatIf
Shows what would happen if the cmdlet runs. The cmdlet is not run.

```yaml
Type: SwitchParameter
Parameter Sets: (All)

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

## OUTPUTS

### System.String
Returns tenant rename warning and scheduling messages from SharePoint Online.

## RELATED LINKS

[Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp)
91 changes: 91 additions & 0 deletions src/Commands/Admin/StartTenantRename.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using PnP.PowerShell.Commands.Base;
using PnP.PowerShell.Commands.Model;
using PnP.PowerShell.Commands.Utilities.MultiGeo;
using PnP.PowerShell.Commands.Attributes;
using System;
using System.Collections.Generic;
using System.Management.Automation;

namespace PnP.PowerShell.Commands.Admin
{
[Cmdlet(VerbsLifecycle.Start, "PnPTenantRename", DefaultParameterSetName = ParameterSetFullRename, SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.High)]
[RequiredApiApplicationPermissions("sharepoint/Sites.FullControl.All")]
[RequiredApiDelegatedPermissions("sharepoint/AllSites.FullControl")]
[OutputType(typeof(string))]
public class StartTenantRename : PnPSharePointOnlineAdminCmdlet
{
Comment thread
gautamdsheth marked this conversation as resolved.
private const string ParameterSetFullRename = "FullRename";

[Parameter(Mandatory = true, ParameterSetName = ParameterSetFullRename)]
[ValidateNotNullOrEmpty]
public string DomainName { get; set; }

[Parameter(Mandatory = true, ParameterSetName = ParameterSetFullRename)]
[ValidateNotNullOrEmpty]
public DateTime ScheduledDateTime { get; set; }

protected override void ExecuteCmdlet()
{
var targetDomainPrefix = DomainName.Trim();
var scheduledDateTimeInUtc = GetValidatedScheduledDateTimeInUtc(ScheduledDateTime);
var multiGeoRestApiClient = new MultiGeoRestApiClient(AdminContext);

WriteResponse(multiGeoRestApiClient.GetTenantRenameWarningMessages());

if (!ShouldProcess(targetDomainPrefix, $"Schedule SharePoint tenant rename for {scheduledDateTimeInUtc:u}"))
{
return;
}

var tenantRenameJob = new TenantRenameJobEntityData
{
TargetDomainPrefix = targetDomainPrefix,
ScheduledDateTimeInUtc = scheduledDateTimeInUtc
};

var tenantRenameJobResponse = multiGeoRestApiClient.CreateTenantRenameJob(tenantRenameJob);
if (tenantRenameJobResponse?.ResponseMessages == null)
{
throw new PSInvalidOperationException("The tenant rename job could not be created. SharePoint Online did not return a response message.");
}

WriteResponse(tenantRenameJobResponse.ResponseMessages);
}

private static DateTime GetValidatedScheduledDateTimeInUtc(DateTime scheduledDateTime)
{
var scheduledDateTimeInUtc = scheduledDateTime.ToUniversalTime();
var utcNow = DateTime.UtcNow;
var minimumScheduledDateTimeInUtc = utcNow.AddHours(24);
var maximumScheduledDateTimeInUtc = utcNow.AddDays(30);

if (scheduledDateTimeInUtc < minimumScheduledDateTimeInUtc)
{
throw new PSArgumentException("ScheduledDateTime must be at least 24 hours in the future.", nameof(ScheduledDateTime));
}

if (scheduledDateTimeInUtc > maximumScheduledDateTimeInUtc)
{
throw new PSArgumentException("ScheduledDateTime must be no more than 30 days in the future.", nameof(ScheduledDateTime));
}

Comment thread
gautamdsheth marked this conversation as resolved.
return scheduledDateTimeInUtc;
}

private void WriteResponse(IEnumerable<string> messages)
{
if (messages == null)
{
return;
}

foreach (var message in messages)
{
if (!string.IsNullOrWhiteSpace(message))
{
WriteObject(message);
}
}
}
}
}
76 changes: 76 additions & 0 deletions src/Commands/Model/TenantRenameJob.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;

namespace PnP.PowerShell.Commands.Model
{
/// <summary>
/// Contains information about a SharePoint Online tenant rename job.
/// </summary>
public class TenantRenameJob
{
/// <summary>
/// Current state of the tenant rename job.
/// </summary>
public string JobState { get; set; }

/// <summary>
/// User or process that initiated the tenant rename job.
/// </summary>
public string TriggeredBy { get; set; }

/// <summary>
/// Number of site rename jobs queued for the tenant rename.
/// </summary>
public int QueuedSitesCount { get; set; }

/// <summary>
/// Number of site rename jobs currently in progress for the tenant rename.
/// </summary>
public int InprogressSitesCount { get; set; }

/// <summary>
/// Number of suspended site rename jobs for the tenant rename.
/// </summary>
public int SuspendedSitesCount { get; set; }

/// <summary>
/// Number of successfully completed site rename jobs for the tenant rename.
/// </summary>
public int SuccessSitesCount { get; set; }

/// <summary>
/// Number of failed site rename jobs for the tenant rename.
/// </summary>
public int FailedSitesCount { get; set; }

/// <summary>
/// Total number of site rename jobs for the tenant rename.
/// </summary>
public int TotalSitesCount { get; set; }

/// <summary>
/// Indicates whether the V2 tenant rename status endpoint should be used.
/// </summary>
public bool UseGetSpoTenantRenameStatusV2 { get; set; }

/// <summary>
/// Scheduled start time for the tenant rename in UTC.
/// </summary>
public DateTime ScheduledDateTimeInUtc { get; set; }

/// <summary>
/// Time at which the tenant rename was requested.
/// </summary>
public DateTime RequestedAt { get; set; }

/// <summary>
/// Messages returned by the tenant rename service.
/// </summary>
public List<string> ResponseMessages { get; set; }

/// <summary>
/// Date and time format used by the tenant rename service messages.
/// </summary>
public string DateTimeFormat { get; set; }
}
}
11 changes: 11 additions & 0 deletions src/Commands/Model/TenantRenameJobEntityData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace PnP.PowerShell.Commands.Model
{
internal class TenantRenameJobEntityData
{
public string TargetDomainPrefix { get; set; }

public DateTime ScheduledDateTimeInUtc { get; set; }
}
}
Loading
Loading