Working VMs without the GUI

Here I went on a mission I though would never happened to me. You set up fail-safe and prepare and make sure all is properly set and then when time comes it is all improvisation again!

After a file level migration of some VMs to a new set of hosts, a license check mechanism made me realized that the mac addresses of a particular VM had changed – in fact all mac addresses had changed thanks to the dynamic mac setting and Hyper-V mac addresses pool. The mission was to change the mac address of the “new” VMs by “new” addresses from the old VMs

So “I” decided that my Hyper-V hosts would well be hypervisor only aka Microsoft Hyper 2012 R2 Core (or something like this).

I had tested connectivity with Hyper-V Management.

I had even built up some powershell scripts to copy the mac addresses from the old VMs (on another host) to the new host.

$OLD get-vm -computername old -name LoadBalancer | select -expandproperty networkadapters
get-vm -computername new -name LoadBalancer | stop-vm
get-vm -computername new -name LoadBalancer | set-vmnetworkadapter -staticMacAddress $OLD.MacAddress
get-vm -computername new -name LoadBalancer | start-vm

And when came time to change the mac addresses or my VMs I had lost access to using Hyper-V Manager, to the host hosting the “better” mac addresses. So no quick easy 3 click change, and the script I wrote was now useless.

So I can up with this code to actually change them afterall

get-vm -Name "LoadMaster VLM" | start-vm

Get-VMNetworkAdapter -VMName "LoadMaster VLM" | Select

Name IsManagementOs VMName SwitchName MacAddress Status IP Addresses
---- -------------- ------ ---------- ---------- ------ --
Network Adapter False LoadMaster VLM Trusted 00155D01820C {}
Network Adapter False LoadMaster VLM Trusted 00155D01820D {}

Get-VMNetworkAdapter -VMName "LoadMaster VLM" | where {$_.MacAddress -eq "00155D01820C"} | Set-VMNetworkAdapter -StaticMacAddress "00155D030208"
Get-VMNetworkAdapter -VMName "LoadMaster VLM" | where {$_.MacAddress -eq "00155D01820D"} | Set-VMNetworkAdapter -StaticMacAddress "00155D030208"

Get-VMNetworkAdapter -VMName "LoadMaster VLM" | Select

Name IsManagementOs VMName SwitchName MacAddress Status IPAddresses
---- -------------- ------ ---------- ---------- ------ --
Network Adapter False LoadMaster VLM Trusted 00155D030208 {}
Network Adapter False LoadMaster VLM Trusted 00155D030208 {}

get-vm -Name "LoadMaster VLM" | start-vm
get-vm -Name "LoadMaster VLM"

Name State CPUUsage(%) MemoryAssigned(M) Uptime Status
---- ----- ----------- ----------------- ------ ------
LoadMaster VLM Running 1 1024 00:00:08 Operating norm...

Do you even use the GUI to manipulate your VMs?

Mapping DFS-R Replication groups

As you saw previously I have been investigating DFS-R mostly doing some troubleshooting. Having more than 50 Replication Groups (RGs) with lots of connection I was trying to find a way to report on the scheduling or bandwidth of those. I came up with the following…

If you are looking for a specific schedule, you would go to the DFS-R GUI and check the schedule and options. If you need to get that information for all of your RGs I wrote a short script that get the RGs list and then get the information of the connections which include the information we are looking for: if the connection is enabled, if Remote Differential Compression is enabled or the bandwidth allocated.

##Script to retrieve all information about connections details in order to perhaps build some diagram or usefull output
##for now I use it raw and import it to excel as a pivot table

##Variables
$DebugPreference = “SilentlyContinue” #[{Continue | Ignore | Inquire | SilentlyContinue | Stop |  Suspend }]
$RGs = $null
$RGitem = $null
$CurrentRGItem = $null
$ConnItem = $null

##Get the RG list
$RGs = DfsrAdmin.exe RG list /Attr:RgName

##Cycle through the RG list to connections information
foreach ($RGitem in $RGs) {
Write-Debug “RGItem= $RGitem”
if (($RGitem -notlike “*RgName*”) -and ($RGitem -notlike “*Command*”) -and ($RGitem -notlike “*domain*”)) {
Write-Debug “Looping on $RGItem”
##Getting the list of connexions for this item
$CurrentRGItem = DfsrAdmin.exe conn list /rgname:$RGItem /attr:”SendMem,ConnSendSite,RecvMem,ConnRecvSite,ConnEnabled,RepHrsWeek,ConnType,SchedType,MaxBW,ConnRdcEnabled”

##Cycle Through to remove header and build array
foreach ($ConnItem in $CurrentRGItem) {
if (($ConnItem -notlike “*SendMem*”) -and ($ConnItem -notlike “*Command*”) -and ($ConnItem -ne “”)){
Write-Debug “Looping on connection’t’t list”
$ConnItemLine = $RGitem+” “+$ConnItem
Write-Output $ConnItemLine
}
}
}
}

So now I end up with an output like this one, only longer:

> .\get-DFSRConnectionInfo.ps1
CA GAIA     Toronto       XANTHUS  Toronto       Yes          168         Intrasite  Default    FullBandwidth  Yes
CA XANTHUS  Toronto       GAIA     Toronto       Yes          168         Intrasite  Default    FullBandwidth  Yes
administration APOLLO   Toronto       ATHENS   Toronto       Yes          168         Intrasite  Default    Mbps2          No
administration APOLLO   Toronto       Patras   Montreal      Yes          168         Intersite  Default    Mbps2          No
administration APOLLO   Toronto       PONTUS   Toronto       Yes          168         Intrasite  Custom     FullBandwidth  Yes
administration ATHENS   Toronto       APOLLO   Toronto       Yes          168         Intrasite  Default    Mbps2          No
administration ATHENS   Toronto       Patras   Montreal      Yes          168         Intersite  Default    Mbps2          No
administration Patras   Montreal      APOLLO   Toronto       Yes          168         Intersite  Default    Mbps2          No
administration Patras   Montreal      ATHENS   Toronto       Yes          168         Intersite  Default    Mbps2          No
administration PONTUS   Toronto       APOLLO   Toronto       Yes          168         Intrasite  Custom     FullBandwidth  Yes

The columns are in order select from the attribute list I mention here: SendMem,ConnSendSite,RecvMem,ConnRecvSite,ConnEnabled,RepHrsWeek,ConnType,SchedType,MaxBW,ConnRdcEnabled.

Then I can import that as a csv in excel to then do some work! Perhaps I’ll script that later as part of the script, but with the new addition of PowerQuery for Excel it is quite easy.

As you noticed I have a line item for each connection, it is fine but not easy to read. I now want to create something like:

ServerA ServerB ServerC
ServerA        x          value    value
ServerB     value         x        value
ServerC     value      value       x

where you would read thing as follow: ServerA send replications to ServerB and ServerC (hence ServerB and C receiving stuff) or ServerC send replications to ServerA and B. Unfortunately pivot tables wont help because they cannot report the values in the columns and only do calculations (sum, count…). this is where Power Query comes to the rescue. If you don’t have it already, I recommend getting it from microsoft.

So in Excel, I do the following

1. import the csv

2. select the data and user power query to pivot the table into the above.

2.1 create a new colum with the values

2.2 remove the unwanted columns

2.3 use the powerquery pivottable function to create the dynamic columns with the name of the server.

let
Source = Excel.CurrentWorkbook(){[Name=”Table1″]}[Content],
InsertedCustom = Table.AddColumn(Source, “Attributes”, each Number.ToText([RepHrsDay])&”Hrs/d,”&[ConnType]&”,”&[MaxBW]&”,RDS?”&[RDS]),
#”Removed Columns” = Table.RemoveColumns(InsertedCustom,{“SendConnSite”, “RecvMemSite”, “ConnEnabled”, “RepHrsWeek”, “RepHrsDay”, “ConnType”, “SchedType”, “MaxBW”, “RDS”}),
InsertCustom1 = Table.Pivot(#”Removed Columns”, List.Distinct(Table.Column(Source, “RecvMem”)), “RecvMem”, “Attributes”)
in
InsertCustom1

3. wait, there is no 3.

And it would look like this:

DFS-R pivot with value table

I actually would nice I knew Visio a bit more and perhaps draw this out! may you can…

Update 2014/08/13: Instead of creating a new post, I am just listing a bunch of must read for dfs-r