- Reading Azure VM name, IP address, and hostname with PowerShell - Fri, Jul 28 2017
- Automating WSUS with PowerShell - Thu, Jul 13 2017
- Disable SSL and TLS 1.0/1.1 on IIS with PowerShell - Tue, Jun 27 2017
I wrote three scripts for the task: one to determine the LUN number that Windows used for the new drive, another one to create text files for diskpart.exe, and the last one to copy the files to the destination VMs and run them. Don’t worry; the scripts are pretty short and simple.
Let’s take a look at the first one:
rep = @() Import-Csv C:\temp\vms_increase.csv | % { $vmname = $_.NAme $Disks = Get-WmiObject -Class Win32_DiskDrive -ComputerName $vmname $info = "" | Select ComputerName, DiskSize, DiskNumber $dskmax = ($Disks.Deviceid.Substring(17) | Measure -Maximum).Maximum $dskid = "PHYSICALDRIVE" + $dskmax $dsk = $Disks | ?{$_.Deviceid -match $dskid} $info.ComputerName = $vmname $info.DiskSize = $dsk.size/1gb $info.DiskNumber = $dsk.Deviceid.Substring(17) $rep +=$info } $rep $rep | Export-Csv -Path C:\temp\vmdrives.csv
First, I get the server names one by one from the .csv file through the Import-Csv cmdlet and then use each name to get the disks' object data from the remote machine with the Get-WmiObject cmdlet. This data is stored in the $Disks variable. After that, I prepare the $info object for use in saving the disk data.
After all preparations are done, I get the highest disk number from the DeviceId field of the $Disks variable. This information is stored in the format "PHYSICALDRIVENN," where "NN" is the disk number. I get this number using the substring command that starts at the 17th symbol of the string. To find the highest number, I use the Measure –Maximum command.
Since Windows adds drives one after the other, the drive that was added last will have the largest number. In fact, I could stop here because I already have all the required information to proceed. However, to ensure that I get the right drive I also read the size. To do that, I first store the drive number in the $dskmax variable to use in getting the drive size from the $Disks variable.
Then I store all information for the current drive in the $info object. Since I’m in a loop, I use the $rep array I created in the first line of the script to save information I’ve obtained from all VMs in the .csv file. When the loop has completed, I export data to the .csv file.
This is what the script output looks like:
Now I need to prepare the text files I’m going to use to run diskpart.exe on the remote machines. There are going to be two files for each machine: one for disk initialization and another one for formatting the volume and assigning the drive letter.
Import-Csv C:\temp\vmdrives.csv | % { $vmname = $_.ComputerName $DiskN = $_.DiskNumber $dinit = New-Item -ItemType file -Path "c:\temp\$vmname-dinit.txt" -Force Add-Content -path $dinit -Value "select disk $DiskN" Add-Content -path $dinit -Value "ATTRIBUTES DISK CLEAR READONLY" Add-Content -path $dinit -Value "online disk" Add-Content -path $dinit -Value "CONVERT MBR" $dformat = New-Item -ItemType file -Path "c:\temp\$vmname-dformat.txt" -Force Add-Content -path $dformat -Value "select disk $DiskN" Add-Content -path $dformat -Value "create partition primary" Add-Content -path $dformat -Value "select partition 1" Add-Content -path $dformat -Value "format fs=ntfs label=Data quick" Add-Content -path $dformat -Value "assign letter=Z" }
Here I import the .csv file created by the previous script and loop though its contents to assign computer name and disk number values to the variables $vmname and $DiskN, respectively. Then I prepare the text file for disk initialization using the New-Item cmdlet.
Next, I use the Add-Content cmdlet to add the diskpart.exe commands to the file. I start by selecting disk, followed by the command that clears the read-only attribute, the command that gets the drive online, and finally the command that converts the drive into an MBR disk.
After the disk is initialized, I have to format it. To do that, I create a second file. The process is the same: select a disk, create a primary partition, select the partition, format it as NTFS using quick format, assign a label, and finally assign a drive letter.
After the script is done, I have two files for each VM. The first one initializes the disk:
select disk 3 ATTRIBUTES DISK CLEAR READONLY online disk CONVERT MBR
And the second formats the disk:
select disk 3 create partition primary select partition 1 format fs=ntfs label=Data quicj assign letter=Z
Finally, I have to run the two files on the remote machines. The script below does just that.
Import-Csv C:\temp\vms_increase.csv | %{ $vmname = $_.Name $Dest = "\\" + $_.Name + "\"+ "C$\Windows\temp" $Dinit = "$vmname-dinit.txt" $Dformat = "$vmname-dformat.txt" Copy-Item "C:\temp\$vmname-dinit.txt" -Destination $Dest -Force Copy-Item "C:\temp\$vmname-dformat.txt" -Destination $Dest -Force Invoke-Command -ComputerName $vmname -ScriptBlock{ $DinitExp = "C:\windows\system32\diskpart.exe /s c:\Windows\temp\$Using:Dinit" $DformatExp = "C:\windows\system32\diskpart.exe /s c:\Windows\temp\$Using:Dformat" Invoke-Expression $DinitExp sleep 15 Invoke-Expression $DformatExp } }
Note that I once again import the .csv file with the server names and loop though it. First I assign the VM name to the $vmname variable and then define the $Dest variable, which is nothing more than the path to which I’m going copy .txt files for diskpart.exe.
Then I assign file names to the $Dinit and $Dformat variables for the current VM and copy those files to the remote machine using Copy-Item. To run diskpart.exe on the remote machine, I apply the Invoke-Command cmdlet to the current VM name.
To format the diskpart.exe command line, I use two variables, $DinintExp and $DformatExp. I format the disks using the Invoke-Expression cmdlet with a 15-second interval between commands.
This is the script output:
Subscribe to 4sysops newsletter!
After this has been completed, my remote VMs have access to the newly-assigned drives, which have been initialized and formatted.
IT Administration News
- GitHub Actions – Deployment views across environments (GA) – The GitHub Blog
- Microsoft is reportedly making security improvements its current top priority at the company – Neowin
- Zuckerberg: It will take Meta years to make money from generative AI – The Verge
- Canonical Releases Ubuntu 24.04 LTS With Lifetime Support for .NET 8 – Thurrott.com
- IBM to Acquire HashiCorp, Inc. Creating a Comprehensive End-to-End Hybrid Cloud Platform