Configuring Cisco Virtual Switch System (VSS) on Cisco Catalyst 4500X Switches.

As part of a network infrastructure upgrade at a client site, I’ll be implementing Cisco VSS (Virtual Switching System). This technology will go a long way to meet some of the stated objectives of this infrastructure upgrade which include : Physical Hardware Redundancy, High Availability achieved by Switch Clustering, Self-healing, Increased bandwidth (10 GB trunk), to mention a few.

Quick Background on VSS:
A Virtual switching system (VSS) combines a pair of Catalyst 4500X series switches into a single network component, enabling them to function as one logical switch.Cisco Virtual Switching System is a clustering technology that pools two Cisco Catalyst 4500X Series Switches into a single virtual switch.

In a VSS, the data plane of both clustered switches is active at the same time in both chassis. In my VSS implementation, both VSS Switch members are connected by 2 virtual switch links (VSLs) using 10 Gigabit Ethernet connections between the VSS members. Virtual Switch Links carry regular user traffic in addition to control data between the VSS members.


I have outlined my VSS configuration steps for a pair of Cisco Catalyst 4500X switches below starting with Switch-1. The following diagram illustrates the physical topology:


Switch 1 Virtual Domain and Port Channel Configuration:

Switch-1(config)#switch virtual domain 100

Switch-1(config-vs-domain)#switch 1


Switch-1(config)#interface port-channel 10


Switch-1(config-if)#switch virtual link 1

Switch-1(config-if)#no shutdown


Configure Virtual Switch Link:

Switch-1(config)#interface range tenGigabitEthernet 1/1-2

Switch-1(config-if)#channel-group 10 mode on

Switch-1(config-if)#no shutdown

Switch-1(config-if)#channel-group 10 mode on
WARNING: Interface TenGigabitEthernet1/1,2 placed in restricted config mode. All extraneous configs removed!

Switch-1(config)#do wr mem (Save the current configuration)


Switch-1#switch convert mode virtual (Execute the command, but do not reload until VSS configuration is completed on Switch 2)

Switch 2 Virtual Domain and Port Channel Configuration:

Switch-2(config)#switch virtual domain 100

Switch-2(config-vs-domain)#switch 2


Switch-2(config)#interface port-channel 20


Switch-2(config-if)#switch virtual link 2

Switch-2(config-if)#no shutdown


Configure Virtual Switch Link:

Switch-2(config)#interface range tenGigabitEthernet 1/1-2

Switch-2(config-if)#channel-group 20 mode on

Switch-2(config-if)#no shutdown

Switch-2(config-if)#channel-group 20 mode on
WARNING: Interface TenGigabitEthernet1/1,2 placed in restricted config mode. All extraneous configs removed!

Switch-2(config)#do wr mem (Save the current configuration)


Switch-2#switch convert mode virtual

At this point, console into Switch-1 . You will be prompted to save the work and confirm the switch reboot. Do the same for Switch-2.

After the reboot, verify the VSS configuration:

Switch-1#sh switch virtual

Executing the command on VSS member switch role = VSS Active, id = 1

Switch mode : Virtual Switch
Virtual switch domain number : 100
Local switch number : 1
Local switch operational role: Virtual Switch Active
Peer switch number : 2
Peer switch operational role : Virtual Switch Standby

Executing the command on VSS member switch role = VSS Standby, id = 2

Switch mode : Virtual Switch
Virtual switch domain number : 100
Local switch number : 2
Local switch operational role: Virtual Switch Standby
Peer switch number : 1
Peer switch operational role : Virtual Switch Active

Verify Dual Active Detection:

Switch-1#sh switch virtual dual-active summary

Executing the command on VSS member switch role = VSS Active, id = 1

Pagp dual-active detection enabled: Yes
FastHello dual-active detection enabled: Yes
In dual-active recovery mode: No

Executing the command on VSS member switch role = VSS Standby, id = 2

Pagp dual-active detection enabled: Yes
FastHello dual-active detection enabled: Yes
In dual-active recovery mode: No

After the VSS configuration and restart, both switches start to function as one. One switch is designated as the Active and the other as the Standby switch. If I attempt to console into the Standby switch and run commands, I get the following prompt:

Switch-1-Standy#sh run
Standby console disabled.
Valid commands are: exit, logout

Configure VSS Cluster Uplink to Distribution Stack Switches as Multichassis EtherChannel (MEC):

VSS enables the creation of Multi-Chassis EtherChannel (MEC), which is an Etherchannel whose member ports are distributed across the member switches in a VSS. The fact that ports from both chassis of the Virtual Switching System are included in this etherchannel makes it a Multichassis EtherChannel (MEC). My MEC configuration steps are below.

Console into the VSS switch cluster. Doesn’t matter if it’s the Switch master or slave, and configure the etherchannel switchport as it would on any other switch(In this scenario, I’m consoled into the standby/slave switch):

Switch-1(config)#interface port-channel 30
Switch-1(config)# no shut

Add ports from both chassis of the VSS Cluster to the Port Channel:

Switch-1(config)#interface range tenGigabitEthernet 1/1/3, tenGigabitEthernet 2/1/3
Switch-1(config-if)#switchport channel-group 30 mode on
Switch-1(config-if)#no shut

Configure the port channel and the physical ports in the Upstream Distribution Stack Switch:

DataCenterStack(config)#interface port-channel 30
DataCenterStack(config-if)#switchport trunk encapsulation dot1q
DataCenterStack(config-if)#switchport mode trunk
DataCenterStack(config-if)#no shut

Add the Stack switches physical ports to the Channel group. This would be the ports fitted with the X2-10GB-SR fiber converters on the Distribution Layer 3750E-48PD switches as indicated in the diagram above:

DataCenterStack(config)#interface range TenGigabitEthernet1/0/1-2
DataCenterStack(config-if)#switchport trunk encapsulation dot1q
DataCenterStack(config-if)#switchport mode trunk
DataCenterStack(config-if)#channel-group 30 mode on

Verify Ether Channel configuration :

DataCenterStack#sh etherchannel summary
Flags: D - down P - bundled in port-channel
I - stand-alone s - suspended
H - Hot-standby (LACP only)
R - Layer3 S - Layer2
U - in use f - failed to allocate aggregator

M - not in use, minimum links not met
u - unsuitable for bundling
w - waiting to be aggregated
d - default port

Number of channel-groups in use: 1
Number of aggregators: 1

Group Port-channel Protocol Ports
30 Po30(SU) - Te1/0/1(P) Te1/0/2(P)

I configured an SVI (Switch Virtual Interface) for telnet or ssh(preferably) management. I would add that it’s important to verify that the version of Cisco IOS-XE software on both VSS switches is the same.

Posted in Cisco, Virtual Switch System, VSS | Tagged , , , , , , , , , , , , , | Leave a comment

Configuring an Azure VM From a Sysprepped Source Image using ARM PowerShell.

While working on an Azure IaaS deployment, I was required to configure an Azure VM using a generalized image in a different resourcegroup.In this post, I want to document my experience using Azure Resource Manager Powershell cmdlets to achieve the related tasks.

The Sysprep tool in the C:\Windows\System32 directory of the windows Azure virtual machine shuts down the vm after the process.

Use the Set-AzureRmVM -Name APPVM0 -Generalized cmdlet with the Generalized parameter to mark the virtual machine as generalized.

The Generalized source image was captured using the Save-AzureRmVMImage cmdlet. Following the cmdlet run, the image was saved to an auto created “system” container/folder in the Storage account.In the following section, the set of ARM (Azure Resource Manager) PowerShell scripts perform the operations on the source Storage account that create the objects and variables required to copy the source vhd blob between containers in storage accounts residing in different Azure Resource Groups.

#Creating an Azure Virtual Machine from a Captured Image .
#Charles Chukwudozie

#Login to the ARM Portal.

#Retrieve and save the source ResourceGroupName in a variable.
$srcresourcegroupname = (Get-AzureRmResourceGroup -Name rgJsonTest -Location centralus).ResourceGroupName

#Get a list of the Resource group resources and note the storage account name.
Get-AzureRmResource  |?{$_.ResourceGroupName -eq "$srcresourcegroupname"} | ft Name

#Get the storage account name and save it in a variable.
$srcstorageaccountname = (Get-AzureRmStorageAccount -ResourceGroupName $srcresourcegroupname -Name rgjsonstorage).StorageAccountName

#Get the storage account access key pair, extract one of the keys and save it to a variable.
$srckeys = Get-AzureRmStorageAccountKey -ResourceGroupName $srcresourcegroupname -Name $srcstorageaccountname
$srckey = $srckeys.Value[0]

#Create a storage context for authorization to the storage account and it's containers/folders.
$srccontext = New-AzureStorageContext -StorageAccountName $srcstorageaccountname -StorageAccountKey $srckey

#Retrieve the current containers in the storage account and select the system container.
Get-AzureStorageContainer -Context $srccontext

#Retrieve the captured source vhd blob container absoluteuri from the system container and assign it to a variable.System container was autocreated during the Save-AzureRmVMImage task.
$absoluteuri = (((Get-AzureStorageContainer -Context $srccontext -Name system).CloudBlobContainer).Uri).AbsoluteUri

#Retrieve the captured source blobs' path from the name property in the system(captured image location) container. Assign it to a variable.
$srcblobspath = (Get-AzureStorageBlob -Container system -Context $srccontext).Name

#Retrieve the vhd blob path from the array.
$srcvhdblobpath = $srcblobspath[0]

#Use the Split() method with the forward slash as seperator,number of element count argument and array position to isolate the source vhd blob only.
$srcvhdblob = $srcvhdblobpath.Split('/',4)[3]

#Concatenate the $absoluteuri and $srcblob variables to build the $srcvhduri variable.
$srcvhduri = $absoluteuri + "/" + $srcvhdblobpath

In the next section, the PowerShell scripts create the destination Azure Resource Groups and performs the operations required to initiate the source vhd blob copy between the source and destination Azure storage accounts in different Resource resource groups.

#Create destination ResourceGroup.

#Save the ResourceGroupName to a variable.
New-AzureRmResourceGroup -Name rgNewImageVMs -Location centralus
$destresourcegroupname = (Get-AzureRmResourceGroup -Name rgNewImageVMs).ResourceGroupName

#Create destination storage account and save the storage account name to a variable. Retrieve the storage account key and create acontext for authorization.
New-AzureRmStorageAccount -ResourceGroupName $destresourcegroupname -Name capimgstorageaccount -SkuName Standard_LRS -Location centralus -Kind Storage
$deststorageacctname = (Get-AzureRmStorageAccount -ResourceGroupName $destresourcegroupname -Name capimgstorageaccount).StorageAccountName
$destkey = (Get-AzureRmStorageAccountKey -ResourceGroupName $destresourcegroupname -Name $deststorageacctname).Value[0]
$destcontext = New-AzureStorageContext -StorageAccountName $deststorageacctname -StorageAccountKey $destkey

#Create a storage container as a copy target for the source image from above.
New-AzureStorageContainer -Name vhds -Permission Blob -Context $destcontext
$destcontainer = (Get-AzureStorageContainer -Name vhds -Context $destcontext).Name

#Initiate the copy of the source image to the destination storage account.
Start-AzureStorageBlobCopy -AbsoluteUri $srcvhduri -DestContainer $destcontainer -DestBlob $srcvhdblob -Context $srccontext -DestContext $destcontext
Get-AzureStorageBlobCopyState -Blob $srcvhdblob -Container $destcontainer -Context $destcontext 

In the third and final section of the script, the Azure VM configuration object is created using the copied source image.

#Create an Azure VM from the captured sysprepped image.

#Set the parameters and variables required to configure the new Azure VMConfig.
$credential = Get-Credential -UserName "localuser"  -Message "Type the username and password of the VM local administrator account."
$timezone = "Central Standard Time"

#Create a storage container for the new VM os disk location.
New-AzureStorageContainer -Name osdisks -Permission Blob -Context $destcontext

#Get the new os disk container name and save to a variable.
$vmcontainer = (Get-AzureStorageContainer -Name osdisks -Context $destcontext).Name

#Get the absolute uri of the source image and save the object to a variable.
$srcimgpreuri = (((Get-AzureStorageContainer -Context $destcontext -Name $destcontainer).CloudBlobContainer).Uri).AbsoluteUri

#Get the source image vhd blob path and save to a variable.
$srcimgblob = (Get-AzureStorageBlob -Container $destcontainer -Context $destcontext).Name

#Concatenate the source image uri and source vhd blob variables to build the source image uri variable.
$srcimageuri = $srcimgpreuri + "/" + $srcimgblob

#Get the new VM OS disk absolute uri.
$osuri = (((Get-AzureStorageContainer -Name osdisks -Context $destcontext).CloudBlobContainer).Uri).AbsoluteUri

#Concatenate the new VM OS disk absolute uri and it's corresponding vhd to build the new VM vhduri variable.
$vhduri = $osuri + "/" + "os.vhd"

#Create an Azure Public IP Address for the new VM.
$vmpip = New-AzureRmPublicIpAddress -Name vmpip -ResourceGroupName $destresourcegroupname -Location centralus -AllocationMethod Dynamic

#Create an Azure Subnet for the VM
New-AzureRmVirtualNetworkSubnetConfig -Name Subnet1 -AddressPrefix ""

#Create an Azure VNet for the VM.
New-AzureRmVirtualNetwork -Name VNET1 -ResourceGroupName $destresourcegroupname -Location centralus -AddressPrefix "" -Subnet $vmsubnetconfig
#Save the new vNet and subnet objects in variables for later use.
$vNet1 = Get-AzureRmVirtualNetwork -Name vNET1 -ResourceGroupName $destresourcegroupname
$subnet1 = Get-AzureRmVirtualNetworkSubnetConfig -Name Subnet1 -VirtualNetwork $vNet1

#Create the new VM network interface.
New-AzureRmNetworkInterface -Name vmNic1 -ResourceGroupName $destresourcegroupname -Location centralus -SubnetId $subnet1.Id -PublicIpAddressId $vmpip.Id
$vmNic1 = Get-AzureRmNetworkInterface -Name vmNic1 -ResourceGroupName $destresourcegroupname

#Create the new VM config object
$sysprepvm = New-AzureRmVMConfig -VMName "sysprepvm" -VMSize "Standard_A1_v2"
$sysprepvm = Set-AzureRmVMOSDisk -VM $sysprepvm -Name "os.vhd" -SourceImageUri $srcimageuri -VhdUri $vhduri -Windows -CreateOption FromImage
$sysprepvm = Set-AzureRmVMOperatingSystem -VM $sysprepvm -Windows -ComputerName $sysprepvm.Name -Credential $credential -EnableAutoUpdate -ProvisionVMAgent -TimeZone $timezone
$sysprepvm = Add-AzureRmVMNetworkInterface -VM $sysprepvm -Id $vmNic1.Id

#Instantiate the VM Object.
New-AzureRmVM -ResourceGroupName $destresourcegroupname -Location centralus -VM $sysprepvm

The following screen shot shows the final result of the Azure VM creation script.


Posted in Azure, Azure Resource Manager, Azure Windows PowerShell | Tagged , , , , , , , , | 1 Comment

Deploy WS2012R2 AD Domain Controller in Azure-OnPrem Hybrid Environment using Resource Manager (IaaS) Virtual Machine.

As part of the process of extending my on premise infrastructure environment to Microsoft Azure, I have configured the Azure S2S VPN, an Azure Virtual network and other Azure based components within an ARM resource group to facilitate the implementation of the hybrid infrastructure.

In a recent post, I wrote about the steps to design and configure the Azure virtual networks and services required to make this possible. The following steps describe the process of installing and configuring the Active Directory Domain Services on the Azure VM to enable DC resilience for the on premise environment.

1) Login to the Azure VM with the local admin account and join the machine to my on premise domain. After the restart, login with an user account with domain admin and enterprise admin group membership. Before installing Active Directory Domain Services, use the Get-WindowsFeature -Name *ad* cmdlet to verify the correct feature name.


2) Install the ADDS feature:

Install-WindowsFeature -Name AD-Domain-Services -IncludeAllSubFeature -IncludeManagementTools


3) Use the Test-ADDSDomainControllerInstallation cmdlet to determine the domain environment’s readiness to accept the new Windows Server 2012 R2 Domain Controller installation. The cmdlet accepts the SafeModeAdministratorPassword and DomainName as required parameters:

PS C:\Windows\system32> $password = ConvertTo-SecureString -String 'password' -AsPlainText -Force
PS C:\Windows\system32> Test-ADDSDomainControllerInstallation -DomainName -SafeModeAdministratorPass
word $password | fl


4) Based on the Test results, the VM needs to be assigned a static IP Address as a requirement of functioning as a Domain Controller with DNS installed. This VM sits on Microsoft Azure. Using the Azure Resource Manager, I’ll make the current dynamic IP Address configuration static on the Network Interfaces blade of the Azure virtual manager.




5) After successfully setting the Azure VM IP Address assignment to Static. I’ll login to the VM via internal rdp, configure the IPv4 address as static and run the Test-ADDSDomainControllerInstallation cmdlet again to confirm the error has been resolved.

6) Use the Install-ADDSDomainController -DomainName -SafeModeAdministratorPassword $password -InstallDns -Verbose cmdlet with the the specified parameters to promote the machine to a Domain Controller.


7) After the system restart, I set about configuring a new Azure-Lab Active Directory Site and Subnet using the Active Directory Sites and Services console to reflect the Azure virtual network subnet/location. I added the the new subnet to the Azure-Lab Site. This will enable the new Azure-Lab site handle any login and authentication originating from my Azure Virtual Network.


Posted in Active Directory Domain Services, AD Forest, Azure, Azure VPN | Leave a comment

Copying an Azure Cloud Blob (VHD) between different Storage Accounts and Resource Groups with ARM PowerShell.

While working with Azure, I came across a situation where I needed to quickly provision an Azure Virtual Machine from an existing sysprepped VHD in a different storage account and resource group using the Azure Resource Manager deployment model. This can be achieved using Azure Resource Manager PowerShell cmdlets. It is worth noting that an Azure storage account has two authentication keys: a primary and a secondary. Either of these can be used for any operation. There are two keys to allow occasional rollover of the keys to enhance security.The storage account context is used for authentication against the storage account.

The key Azure Resource Manager resources and components to consider for this operation are:

1) The URI of the source vhd or blob. This resource will be assigned a variable: $srcvhduri.
2) The source Storage Account name : $srcstoraccountname.
3) The Access key of the source Storage Account: $srckey1.
4) The security context of the source storage environment: $srccontext.
5) The destination Storage account name: $deststoraccountname.
6) The Access key of the destination storage account: $destkey1.
7) The security context of the destination Storage account: $destcontext.

We’ll start this operation by initiating a login to the Azure Cloud subscription using PowerShell:

1) Use the PS C:\Scripts> Login-AzureRmAccount cmdlet to login the Azure subscription:


2) Confirm and verify the resources in the source resource group using the following Azure PowerShell script:
PS C:\Scripts> Get-AzureRmResource | ?{$_.ResourceGroupName -eq 'rgXtine'} | ft Name


3) Verify the source storage account key using the following Azure Resource Manager PowerShell script:
PS C:\Scripts> Get-AzureRmStorageAccountKey -ResourceGroupName rgXtine -Name vhdstoragexfqygzi2vdtwo


The storage account access keys come in pairs and can be regenerated at anytime. I’m interested in using just one of the access keys.

4) In the next script, I’ll retrieve one of the keys and save it in a variable.

$srckey1 = (Get-AzureRmStorageAccountKey -ResourceGroupName rgXtine -Name vhdstoragexfqygzi2vdtwo).Value[0]


5) Next, I’ll copy the blob/vhd url from the Azure portal or Azure Storage Explorer and assign the string to a variable.


6) Get the source storage account and save it in a variable:
$srcstoraccount = Get-AzureRmStorageAccount -ResourceGroupName rgXtine . Retreive the source storage account name and save in a variable: $srcstoraccountname = $srcstoraccount.StorageAccountName

7) Get the source storage account context and assign to a variable:
$srccontext = New-AzureStorageContext -StorageAccountName $srcstoraccountname -StorageAccountKey $srckey1

8) Run the same steps as above for the destination/target storage account of the copy operation:

a) Destination Storage account:

$deststoraccount=Get-AzureRmStorageAccount -ResourceGroupName rgCapturedImage -Name newcapimgstoracct2016

b) Retrieve the destination storage account name:

$deststoraccountname = $deststoraccount.StorageAccountName

c) Retrieve the destination storage account access key and assign it to variable:

PS$destkey1 = (Get-AzureRmStorageAccountKey -ResourceGroupName rgcapturedimage -Name newcapimgstoracct2016)

d) Get the authentication context for the destination storage account:

$destcontext=New-AzureStorageContext -StorageAccountName $deststoraccountname -StorageAccountKey $destkey1

9) Create a destination storage container for the copied vhd/blob object:

PS C:\Scripts> New-AzureStorageContainer -Name images2 -Permission Blob -Context $destcontext


10) Confirm the name of the Azure blob or vhd file object to be copied.


11) Use the Start-AzureStorageBlobCopy cmdlet to copy the Azure blob to the target container.


I can check the copy status by using the Get-AzureStorageBlobCopyState cmdlet. This cmdlet displays the status of the copy task, source blob, completion time and total bytes.


I could also confirm the blob is in the target container using the Azure Storage Explorer:


Posted in Azure, Azure Windows PowerShell | Tagged , , , , , , , | Leave a comment

Enable Hyper-V Server 2012 R2 Core Virtual Machine Protection using existing Azure Site Replication Policy.

In this post, I’ll be writing about my steps for enabling on premise Virtual Machine protection to Azure Site Recovery using an existing Hyper-V Site Replication policy. In this deployment, I’ll be adding and registering a Hyper-V Core Server 2012 R2 to Azure Site Recovery. The process differs from the steps in registering a full Windows Server 2012 R2 host in Azure Site Recovery.

1) Login to Azure Resource Manager portal.

2) Under the default Dashboard, select All Resources and select the already existing Recovery Services Vault. My current vault is the LabVaultASR.


3) On the current vault page, navigate to Settings, Manage, Site Recovery Infrastructure and select the recovery infrastructure that works best for you. In my scenario for this post, I’m working with non SCVMM Hyper-V hosts. I’ll select Hyper-V Hosts under the Hyper-V sites section.


4) Use the +Server button to add another Hyper-V host.


5) On the Add Server page, ensure that Hyper-V is selected. Download and install the installer for Azure Site Recovery Provider. This will install both the Provider and Agent services on the on premise Hyper-V host. I’ll also download the vault registration key to register the host with my Hyper-V site.

I’m running the Hyper-V core 2012 R2 on my on premise Hyper-V host. I login to the server, start a PowerShell console as Administrator and run the Provider file from the PowerShell prompt. This starts the installation GUI. I selected to enable Microsoft Update, click next and finish the installation. Click next to Register the server with Azure.


I encountered an error trying to register the Hyper-V host with my Azure vault.


The error occurred because I can’t register the server with the GUI on a Hyper-V core server. I need the command line tool and switches to properly register a Hyper-V Server 2012 R2 core with Azure vault. After downloading the key, I made sure to unblock the vault key file by right clicking on the file, selecting properties and using the “Unblock” button on the General tab to unblock the file. Then I ran the following command to register the server:

C:\Program Files\Microsoft Azure Site Recovery Provider>DRConfigurator.exe /r /friendlyname /Credentials "c:\ASR\LabVaultASR_LabHyper-V-Site_Wed Sep 21 2016.VaultCredentials"


Confirm that the registration was successful in Azure.


6) To configure and enable protection for Virtual Machines, navigate to the Recovery Services Vault(LabVaultASR in my deployment), Settings, Protected Items and select Replicated Items.

7) On the Replicated Items page, select the +Replicate button to start the VM protection/replication process.


8) On the Enable Replication page, select the Source Hyper-V site and click Ok. On the Target page, select ensure that Azure is selected as the Target.Select the subscription. Select the Post-failover deployment model, in my deployment, I’ll be using the Azure Classic model. Select the Storage account. I want to Configure now for selected machines. And I also selected my already configure Azure Virtual Network.Click Ok.


9) Select a VM to enable for protection on the Select VM page. Click Ok.


10) Select the relevant values on the VM properties page.Click Ok.


11) On the Replication settings page, select the existing Replication Policy. Click Ok.


12) Click on the Enable Replication button to enable protection for the configured VM.

13) After successfully enabling protection of the VM, click the refresh button to display the newly protected VM on the Replicated Items page.


After completing the Replication and Protection steps, I can view and monitor the status and health of my replica virtual machines in Azure Site Recovery by clicking on my Recovery Services Vault name.

I can view and assess the status of the Site Recovery provider on my registered Hyper-V host/servers. I can check out the properties and health of my replicated items, recovery plans and Site Recovery jobs.


Posted in Azure, Azure Site Recovery, Failover Cluster, Failover Cluster Manager, Hyper-v, Hyper-v 2012 R2, Hyper-v Manager, Microsoft Hyper-v | Tagged , , , , , , , , , , , | Leave a comment