Photo by Brian McGowan on Unsplash

Photo by Brian McGowan on Unsplash

Manage Windows Server storage with PowerShell

Robots in the Data Center

Article from ADMIN 71/2022
Numerous tools are available to manage the hard drive inventory of Windows servers, but they fall short when it comes to comprehensive automation, which is where PowerShell can help.

Experienced Windows administrators are familiar with numerous tools that help them manage hard drives, partitions, and filesystems. The portfolio extends from the Microsoft Management Console (MMC)-based Disk Management (diskmgmt.msc) and command-line tools to the Server Manager and Windows Admin Center. For more complex storage systems, you have tools such as iSCSICLI for configuring built-in Internet small computer systems interface (iSCSI) initiators or the multipath I/O control panel (MPIO CPL) graphical configuration applet for storage multipathing.

These tools are perfectly suitable for individual tasks, but when it comes to configuring a large number of servers or migrating complex storage landscapes, the tools quickly reach their limits. The syntax is not consistent, output depends on the operating system language set, and graphical interfaces do not support automation. In precisely such cases administrators turn their attention to PowerShell, which is also particularly important because it enables visual management of a Windows machine's local subsystems in Windows Admin Center.

This article references the current Server 2022 but should also apply to Server 2019 and 2016 without any changes. However, I look exclusively at provisioning storage capacity, which is served up by Server Message Block (SMB), Distributed File System (DFS), Network File System (NFS), or iSCSI supported by separate, sophisticated PowerShell features.

Physical and Logical Drives

Classical administration tasks with regard to the hard drives, their partitioning, and the storage volumes on them are traditionally the domain of the Disk Management MMC console or the diskpart command-line tool. The Get-Disk command in PowerShell is useful for an initial overview of the existing hard drives (Figure 1). The returned objects correspond to the view in Disk Management as long as all existing drives are of Basic Disk type. If you convert a disk to a Dynamic Disk , it disappears from the Get-Disk inventory, but remains visible in Disk Management.

Figure 1: Different tools let admins access different disk types.

In fact, PowerShell does not support operations that require dynamic disks (the Windows software RAID in various flavors). If you want to script dynamic disks, you will probably have to resort to diskpart, because neither PowerShell nor Windows Management Instrumentation (WMI) provide documented programming interfaces. However, dynamic disks are a little out of fashion: Microsoft explicitly recommends Storage Spaces [1] for mirrored startup volumes, and Storage Spaces is far better suited for more advanced configurations of local hard drives, with extensive PowerShell support, which I look at later.

To initialize a fresh hard drive for operation, use:

Get-Disk -Number <drive number> | Set-Disk -IsOffline $false
Initialize-Disk -Number <drive number> -PartitionStyle GPT

For the same initialization type for all uninitialized disks use:

Get-Disk | Where-Object {$_.IsOffline -and ($_.PartitionStyle -eq 'RAW')} | Initialize-Disk -PartitionStyle GPT

To continue processing the disk objects after initialization, you also need to add the -PassThru switch to the Initialize-Disk cmdlet.

To take an active hard drive offline again, use:

Get-Disk -Number <drive number> | Set-Disk -IsOffline $true

If you are working with real, not logical, disks physically connected to the computer, all of the tools I have mentioned so far will quickly reach their limits. The Get-Disk cmdlet does not display dynamic disks, and none of the three tools return disks that have been added to a Storage Spaces pool. Conventional Windows on-board tools let you see the connected disks in Device Management (devmgmt.msc), where you also have access to the multipath I/O information of the respective disk if configured for multiple paths.

PowerShell helps you achieve this functionality with the Get-PhysicalDisk command, but it does not show you any multipathing information. Moreover, the physical connection information relating to the adapter, target, and logical unit number (LUN) is only available as a string in the PhysicalLocation property. Unfortunately, this is exclusively for local drives and not for disks provided by a storage system by iSCSI or Fibre Channel (FC). The command

diskpart detail disk

shows this information – unless the disks are part of a Storage Spaces pool. With the same preconditions, you can retrieve this information in PowerShell with WMI:

Get-CIMInstance Win32_DiskDrive | Select Index, Model, SCSI*

The Index corresponds to the disk number in Get-Disk.

If the storage configuration changes outside of your PowerShell session, the PowerShell cmdlets don't always notice it right away. You are probably also familiar with this phenomenon from Disk Management and would select the Action | Rescan Disks menu item to fix it. In PowerShell, the equivalent command is Update-HostStorageCache.

Managing Partitions and Volumes

Managing partitions, and the filesystem volumes on them, is fraught with the same limitations as hard drive management. Dynamic volumes are invisible to PowerShell; however, you can use the Get-Partition cmdlet to list all partitions on all visible disks (i.e., Basic Disks and Storage Spaces VirtualDisks) without having to commit to a specific disk beforehand. What's even better is how you can manage volumes: Everything is visible and manageable regardless of the underlying storage technology. You can list them with Get-Volume, repair them with Repair-Volume, analyze and defragment them with Optimize-Volume, and reformat them with the Format-Volume command. The default setting is Quick Format, but you can force full formatting with the -Full switch. When creating a new volume, you can either use the entire disk:

Get-Disk -Number <number> | New-Volume -FileSystem NTFS -DriveLetter Z -FriendlyName <DiskLabel>

or create partitions:

Get-Disk -Number <number> | New-Partition -Size <size in bytes> -Offset <offset in bytes>

When done, create and format the filesystem volume with:

$part = Get-Partition -DiskNumber <number> -PartitionNumber <number>
$part | Set-Partition -NewDriveLetter <letter>
Format-Volume -Partition $part -FileSystem NTFS

You can clearly see the connections between volumes and partitions in Windows in the last example. The partition determines the physical location of the object on the disk subsystem and its deployment, and the volume defines the filesystem therein.

Multipath Mounting of iSCSI LUNs

As early as in Windows 2000 Server, the Microsoft operating system introduced its own iSCSI initiator that let you mount storage LUNs on your Windows instances with on-board tools – provided the LUNs were provisioned by the storage system with the iSCSI protocol. MPIO is another valuable feature that is available not only for iSCSI but for all block-based storage protocols, such as serial attached SCSI (SAS), FC, or Fibre Channel over Ethernet (FCoE). MPIO lets the initiator manage multiple connections to the same storage target in line with a defined policy.

On a freshly installed Windows system, the iSCSI initiator service (MSiSCSI) is disabled by default. Before configuring the initiator, you first need to configure and start the service for automatic startup with two PowerShell commands:

Set-Service MSiSCSI -StartupType Automatic
Start-Service MSiSCSI

Now you can configure the iSCSI initiator on your Windows server. One of the most important global settings is the iSCSI qualified name (IQN) of the initiator. To adjust this, use:

Set-InitiatorPort -NodeAddress <IQN> -NewNodeAddress <New IQN>

To find the existing initiator name, enter:

Get-InitiatorPort -ConnectionType iSCSI

Changes to the initiator name are often caused by the storage team's naming conventions. However, compelling technical reasons might also be in play. The IQN of a Windows computer assigned by default is a 26-character prefix followed by the computer name. However, older storage systems internally limit the IQN to 32 characters and therefore only evaluate the first six characters of the computer name. For example, if your cluster nodes are named SERVER01, SERVER02, and so on, this kind of storage system will see them all as SERVER, and LUN reservations within the cluster will fail.

Sometimes iSCSI connections take too long to establish when the server boots, and shares that reside on iSCSI LUNs are not provisioned. In this case, you need to make the server service (LanmanServer) dependent on the iSCSI initiator service (MSiSCSI). Creating this dependency is not possible with PowerShell tools; instead, you need to turn to the tried and trusted sc config depend. Make sure you add the iSCSI service and do not set it as the only dependency.

If multipathing with your current or future storage system is an option, it is best to configure the MPIO feature right away. In fact, for server clusters, it is mandatory at least to enable MPIO before creating the cluster. The MPIO feature has built-in support for the on-board iSCSI initiator. However, this is disabled by default. Enabling this support requires a reboot, so you will want to complete this configuration step as early as possible:

Add-WindowsFeature Multipath-IO
$vid = 'MSFT2005'
$pid = 'iSCSIBusType_0x9'
New-MSDSMSupportedHW -VendorId $vid -ProductId $pid
Set-MSDSMGlobalDefaultLoadBalance-Policy -Policy RR
Restart-Computer -Force

The last configuration command sets the path selection policy to round robin (RR) by default. Each subsequent request takes the next active path regardless of the workload. Other valid values for the MPIO policy are FOO for failover only, None for no multipathing, LB for least blocks, and LQD for least queue depth. Make sure you read the storage vendor's integration guide before choosing an MPIO policy because not every iSCSI storage system supports every policy equally well. In most cases you will only have the choice between round robin and failover. The Get-MPIOSetting and Set-MPIOSetting commands let you configure further global MPIO settings on the system.

Once the iSCSI initiator is enabled and MPIO is configured, you can attach your iSCSI storage to the system and read the LUNs presented to your initiator. (For the sake of brevity, I will not look at authenticating against the target storage system here.) The parameters required are provided by Connect-IscsiTarget [2]. Listing 1 shows how to connect an iSCSI target to two paths with PowerShell. Make sure that the IP addresses from the individual storage subnets appear in the same order in the arrays for the initiator and target addresses.

Listing 1

Connecting to an iSCSI Target

$iniAddr = @(
$tgtAddr = @(
(0..($iniAddr.Length - 1)) | For-Each-Object {
   New-IscsiTargetPortal `
   -TargetPortalAddress $tgtAddr[$_] `
   -TargetPortalPortNumber 3260 `
   -InitiatorPortalAddress $iniAddr[$_]
$targets = Get-IscsiTarget
(0..($iniAddr.Length - 1)) | For-Each-Object {
   $targets | Connect-IscsiTarget `
     -IsMultipathEnabled $true `
     -IsPersistent $true `
     -TargetPortalAddress $tgtAddr[$_] `
     -InitiatorPortalAddress $iniAddr[$_]

Now, to load the newly attached iSCSI targets in Disk Management, use


New disks will now show up in your storage inventory, assuming the storage system has served up LUNs to this initiator.

The supplied Windows PowerShell modules do not provide any commands for advanced management of the MPIO settings of the individual devices and paths. WMI support in this area is also poor and only gives you read access to the MPIO configuration of the individual devices; you cannot change the configuration. You can either turn to the mpclaim.exe tool on the command line, with its slightly cryptic syntax, or configure the settings manually in the Device Management GUI (Figure 2).

Figure 2: Advanced management of the MPIO settings from the Device Management GUI or the command line.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Highly available Hyper-V in Windows Server 2016
    Microsoft has extended the failover options for Hyper-V in Windows Server 2016 to include two new cluster modes, as well as the ability to define an Azure Cloud Witness server. We look at how to set up a Hyper-V failover cluster.
  • Clusters with Windows Server 2012 R2
    With Windows, you can create a highly available cluster at the click of a button. The cluster will even handle fully automated, non-disruptive software upgrades.
  • Storage pools and storage spaces in Windows
    Storage spaces and storage pools combine a variety of storage technologies into a single logical unit, ensuring high availability and a choice of resiliency capability.
  • Dealing with VHDX files
    VHDX files introduce some improvements over the legacy virtual hard disk format. In this article, we review some of the interesting features.
  • Hyper-V with the SMB 3 protocol
    Microsoft has introduced several improvements to Windows Server 2012 and Windows Server 2012 R2 with its Server Message Block 3. Hyper-V mainly benefits from faster and more stable access to network storage. In this article, we look at the innovations.
comments powered by Disqus
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs

Support Our Work

ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.