Azure, PowerShell, Scripts

Rapid Virtual Machine Deployment using Azure Managed Disks

With the recent release of generally available Managed Disks, the ability to rapidly deploy virtual machines using these disks has been greatly improved.

Below is a simple script to create a snapshot of an ARM virtual machine, create a Managed Disk from that snapshot and deploy as a new virtual machine.

 


# Source VM Details START
        $resourceGroupName = 'resourcegroup01'
        $location = 'australiaeast' 
        $dataDiskName = 'vm01-osdisk' 
        $snapshotName = 'vm01_snapshot'
        $snapshotResourceGroupName = 'resourcegroup02'
# Source VM Details END

# New VM Details START
        $vmName = 'vm02'
        $location = "australiaeast"
        $vmresourceGroupName = "resourcegroup01"
        $vnetname = 'vnet1'
        $pipName = "$vmName-pip"
        $nicName = "$vmName-nic"
        $vmSize = 'Standard_A2'
# New VM Details END

###Create Snapshot of Source VM START

        $disk = Get-AzureRmDisk -ResourceGroupName $resourceGroupName -DiskName $dataDiskName

        $snapshot =  New-AzureRmSnapshotConfig -SourceUri $disk.Id -CreateOption Copy -Location $location

        New-AzureRmSnapshot -Snapshot $snapshot -SnapshotName $snapshotName -ResourceGroupName $snapshotResourceGroupName

###Create Snapshot of Source VM END

###Create New VM using Snapshot START

        # ResourceGroupName parameter has to be specified, without it. Cmdlet returns all snapshots it can find regardless their name.
        $snapshot = Get-AzureRmSnapshot -SnapshotName $snapshotName -ResourceGroupName $snapshotResourceGroupName

        #$subnet = New-AzureRmVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix $subnetPrefix
        $vnet = Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $resourceGroupName

        $pip = New-AzureRmPublicIpAddress -Name $pipName -ResourceGroupName $resourceGroupName `
            -Location $location -AllocationMethod Dynamic

        $nic = New-AzureRmNetworkInterface -Name $nicName -ResourceGroupName $resourceGroupName `
            -Location $location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id

        $managedDiskType = 'StandardLRS'
        $managedDiskCreateOption = 'Copy'
        $diskName = "$vmName-osdisk"
        $diskCreateOption = 'Attach'
        $vm = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize
        $vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $nic.Id
        $diskConfig = New-AzureRmDiskConfig -AccountType $managedDiskType -Location $location -CreateOption $managedDiskCreateOption -SourceResourceId $snapshot.Id
        $osDisk = New-AzureRmDisk -DiskName $diskName -Disk $diskConfig -ResourceGroupName $resourceGroupName
        $vm = Set-AzureRmVMOSDisk -VM $vm -Name $diskName -ManagedDiskId $osDisk.Id -CreateOption $diskCreateOption -Windows -Caching ReadWrite
        New-AzureRmVM -ResourceGroupName $resourceGroupName -Location $location -VM $vm

###Create New VM using Snapshot END

Advertisements
PowerShell, Scripts

PowerShell – Rename Computers Dynamically according to type

Below is a PowerShell script to dynamically change a computer name based of the model of computer. It first checks the model to determine if the computer is a desktop or laptop, and renames the computer accordingly by appending a “D” or “L”.


#Get Current PC Name
$hostname = hostname

#Serial Number can also be used using below code inreplace of hostname
###  $hostname = wmic bios get serialnumber

#Get Model of System
$model = wmic computersystem get model

#If model is like "Laptop Model" add "L" to computername
IF ($model -like "Portege*" -or "Tecra*" -or "ProBook*") {

Rename-Computer -ComputerName "L"+$hostname }

#If model is like "Desktop Model" add "L" to computername
IF ($model -like "Veriton*" -or "Optiplex")  {

Rename-Computer -ComputerName "D"+$hostname }

This script could be utilized in a startup script or deployed through a deployment solution, such as SCCM.

An alternate to using the model value, is to use the ChassisType under the systemenclosure query.

This leverages the pre determined computer chassis values found here -> https://technet.microsoft.com/en-us/library/ee156537.aspx


#Get Current PC Name
$hostname = hostname

#Serial Number can also be used using below code inreplace of hostname
###  $hostname = wmic bios get serialnumber

# Gets Chassis Type - Chassis type references - https://technet.microsoft.com/en-us/library/ee156537.aspx
$chassis = wmic systemenclosure get ChassisTypes

#If chassis type is equal to "9 (Laptop)" or "10 (Notebook)" add "L" to computername
IF ($chassis -eq "{9}" -or "{10}*") {

Rename-Computer -ComputerName "L"+$hostname }

#If chassis type is equal to "3 (Desktop)" or "10 (Low Profile Desktop)" or "6 (Mini Tower")  or "7 (Tower)" add "D" to computername
IF ($chassis -eq "{3}" -or "{10}*" -or "{6}" -or "{7}") {

Rename-Computer -ComputerName "D"+$hostname }

PowerShell, Scripts

PowerShell – Export Exchange Mailbox Name, Item Count and Size to CSV

Below is a PowerShell script I wrote to connect to Exchange through Remote PowerShell, import a list of users from a CSV file, grab the Display Name, Total Item Count and Total Size in GB for each user mailbox and export back to CSV.

You will need to modify the $conuri variable to connect to your Exchange server using the full FQDN, for example, (http://mailserver.scottellis.com/PowerShell).

You can download the full script here: Script


#Written by Scott Ellis
#April 2016

#Gets User Credential for Remote PowerShell Session and sets variable
$creds = Get-Credential

#Sets Variable for Mail Server Connection URI
$conuri = "http://FQDNMAILSERVER/PowerShell/"

#Sets Variable for CSV file listing users to be imported
$mailboxusers = "C:\Temp\list_of_users.csv"

#Sets Output file location
$outputfile = "C:\temp\list_of_users_mailbox details.csv"

#Starts a new Remote PowerShell session to Exchange Server
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $conuri -Credential $creds

#Waits for connection to Exchange Server to complete
Start-Sleep -s 10

#Opens Remote PowerShell session to Exchange Server
Import-PSSession $Session

#Waits for Remote PowerShell session to Exchange Server to open
Start-Sleep -s 30

#Imports list of users in CSV file, gets mailbox stats, including DisplayName, Total Item Count and Total Mailbox Size in GB, sorts by DisplayName and Exports to CSV file
Import-Csv $mailboxusers |foreach {Get-MailboxStatistics -Identity $_.alias} |select displayname,itemcount,totalitemsize | sort-object DisplayName | export-csv $outputfile

 

PowerShell, Scripts

PowerShell – vSphere PowerCLI – Export Datastore Capacity and Usage

Below is a PowerShell script I wrote within VMWare PowerCLI 5.5 which exports the current capacity and usage of datastores in a VMWare environment to a CSV file.

The exported details include;

  • the datastore name
  • the datastore capacity in GB
  • the freespace remaining on the datastore in GB
  • the state of the datastore

Again, please note this was created using PowerCLI version 5.5

You can also grab the full script here: Script


#PowerShell Script to Export Datastore Capacity and Current Datastore Usage to CSV file
#Script to be ran using vSphere PowerCLI
#Script created using vSphere PowerCLI 5.5
#April 2016

#vSphere ServerName
$VIServer = "VCS01"

#CSV File Export Location and File name
$exportcsv = "D:\datastore.csv"

add-pssnapin VMware.VimAutomation.Core
Connect-VIServer $VIServer
Start-Sleep -s 25
Get-Datastore | Sort-Object Name | Select Name,FreeSpaceGB,CapacityGB,State | Export-Csv $exportcsv -force

PowerShell, Scripts

PowerShell – vSphere PowerCLI – Export Current Snapshots

Below is a PowerShell script I wrote within VMWare PowerCLI 5.5 which finds and exports a list of snapshots in a VMWare environment to a CSV file.

The exported details include;

  • the associated VM name and state
  • the description of the snapshot
  • when the snapshot was created
  • size of the snapshot

Again, please note this was created using PowerCLI version 5.5

You can also grab the full script here: Script


#PowerShell Script to Export Current Snapshots to CSV file
#Script to be ran using vSphere PowerCLI
#Script created using vSphere PowerCLI 5.5
#April 2016

#vSphere ServerName
$VIServer = "VCS01"

#CSV File Export Location and File name
$exportcsv = "D:\Current_Snapshots.csv"

add-pssnapin VMware.VimAutomation.Core
Connect-VIServer $VIServer
Start-Sleep -s 25
Get-VM |Get-Snapshot | Sort-Object VM | Select Name,Description,Created,VM,SizeGb,PowerState | Export-Csv $exportcsv -force

PowerShell

PowerShell -Export RDP Logs to Email

The below is a PowerShell script I wrote to grab a list of servers in a TXT file, filter for Event IDs specific to RDP logons and export to email.

To run this Script, you may need to allow Remote Event Log Management through the local firewall on each server.

You will need to modify the following variables to suit your requirements;

$filename

$filedir

$oldfiledir

$OutputFile

You will also need to create a TXT file listing the servers you wish to run the script against, similar to the below;

server_list

You can also grab the full script here: PowerShell Script

 


#PowerShell Script to find and export RDP specific logs to email
#Created by Scott Ellis
#July 2016

#Please note you will require; a TXT file listing server names to be checked and set in the below variable $serverlist
                            #; modify $filename, $filedir, $oldfiledir, $OutputFile to suit your needs

#Log Name to Search For (RDP Logons in this case)
$LogName = 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational'
$Results = @()

#Set Variable for Date (Get Current date, minus 14 days)
$checkDate = (Get-Date).AddDays(-14).Date

#Sets Variable for Current Date
$WorkingDate = Get-Date

#Sets Variable for File name to be outputted with current date
$filename = "RDP Event Logs - " + $WorkingDate.ToString('dd-MM-yyyy')+'.csv'

#Specifies directory where file will be exported to
$filedir="C:\Reports\RDP"

#If script is scheduled, sets variable for location for previous exports to be moved to
$oldfiledir="C:\Reports\RDP\Aged Reports"

#Sets Output location and file name
$OutputFile = $filedir+'\'+$filename

#Sets variable for TXT file listing servers
$serverlist = "C:\Reports\RDP\SERVER_LIST.txt"

#Checks for existing file, and if found, moves to previous exports location as defined by 'oldfiledir' variable
$existingfile = Test-Path $OutputFile
If ($existingfile -eq $true) {
Move-Item $OutputFile $oldfiledir }

#Gets Text File listing servers from 'serverlist' variable and Gets Windows Events using Log Name, Start Time (defined above) and Specific Event IDs (below)
Get-Content $serverlist | ForEach-Object {
$Events = Get-WinEvent -ComputerName $_ -FilterHashTable @{ LogName = $LogName; StartTime = $checkDate; ID = 21,22,23,24,25 }

#Using Filtered Events above, gets RDP event details including; Username, Server, Time, Event ID and Source IP for each server listed in server list TXT file and adds output to ResultsHash
foreach ($Event in $Events) {
    $EventXml = [xml]$Event.ToXML()

    $ResultHash = @{
        Username    = $EventXml.Event.UserData.EventXML.User
        Server      = $Event.MachineName
        Time        = $Event.TimeCreated.ToString()
        'Event ID'  = $Event.ID
        'Source IP' = $EventXml.Event.UserData.EventXML.Address

    }
    #Creates new variable using PSObject with ResultsHash table as Property
    $Results += (New-Object PSObject -Property $ResultHash)
} }
#Exports Output to CSV file (defined above)
$Results | Select-Object Username,Server,Time,'Source IP','Event ID' | Export-Csv $OutputFile

#Creates Legend Table to be included in body of email to help idenitfy Event IDs

# Create a DataTable
$table = New-Object system.Data.DataTable "Event ID Legend"
$col1 = New-Object system.Data.DataColumn "Event ID",([string])
$col2 = New-Object system.Data.DataColumn "Description",([string])
$table.columns.add($col1)
$table.columns.add($col2)

# Add content to the DataTable
$row = $table.NewRow()
$row."Event ID" = "21"
$row.Description = "RDP Logon"
$table.Rows.Add($row)
$row = $table.NewRow()
$row."Event ID" = "23"
$row.Description = "RDP Logoff"
$table.Rows.Add($row)
$row = $table.NewRow()
$row."Event ID" = "24"
$row.Description = "RDP Session Disconnected"
$table.Rows.Add($row)
$row = $table.NewRow()
$row."Event ID" = "25"
$row.Description = "RDP Session Reconnected"
$table.Rows.Add($row)

# Create an HTML version of the DataTable
$html = "<table><tr><td>Event ID</td><td>Description</td></tr>"
foreach ($row in $table.Rows)
{
    $html += "<tr><td>" + $row[0] + "</td><td>" + $row[1] + "</td></tr>"
}
$html += "</table>"

#Sets Settings for Mail

$smtpserver = "smtp.server.com"
$from = "from.from@microsoft.com"
$to = "to.to@microsoft.com"
$subject = "RDP Logons < 14 Days"
$body = "Hi,<br />The below table is your reference in assinsting to identifying Event IDs and their description.<br /><br />" + $html

#Sends Email with Output attached to sender defined above
Send-MailMessage -smtpserver $smtpserver -from $from -to $to -subject $subject -Attachments $OutputFile  -body $body -bodyashtml