Remove Active Directory Domain Services (ADDS) from a WS2012 R2 with PowerShell.

I decided to tear down my Azure Lab IaaS and ASR infrastructure and rebuild it. The process involves removing the ASR configurations, Recovery Vaults, S2S VPNs, VNets and Azure VM running as a Azure based Domain controller for resilience with on-premise infrastructure and Azure deployed Apps. The next steps will include uninstalling the Domain Controller, delete and disable the VMs and Hyper-V Hosts configured for Azure site Recovery. Following these tasks, I’ll delete or remove the resource group. All resources were configured and created within one ARM Resource Group to make it easier to tear down. The following are steps to uninstall ADDS from the Azure VM using PowerShell:

1) Login to the WS2012 R2 Domain Controller.

2) Open a PowerShell console as Admin.

3) Use the Get-Command -Module ADDSDeployment cmdlet to review the necessary ADDSDeployment module commands.

4) psdemote

5) Create a Credential variable:


6) Create a Local Admin Password secure string: $adminPassword = ConvertTo-SecureString -String "pa55w04d123A" -AsPlainText -Force

7) Run the ADDS uninstallation cmdlet with the WhatIf parameter to confirm that the script will run successfully:

Uninstall-ADDSDomainController -LocalAdministratorPassword $adminPassword -Credential $cred -DnsDelegationRemovalCredential $cred -RemoveDnsDelegation -WhatIf


8) Run the actual script without the WhatIf parameter:


9) Remove the ADDS role : Remove-WindowsFeature -Name AD-Domain-Services -IncludeManagementTools -Remove -WhatIf

It might still be necessary to remove refereces to the old DC in DNS and AD Domain Sites.

After disabling protection on the VMs, I deleted the Hyper-V Hosts in the Recovery vault site and then used the following cmdlet to remove the Resource Group:

PS C:\Users\Chinny> Get-AzureRmResourceGroup -Name RGXavier | Remove-AzureRmResourceGroup -Force

Posted in Active Directory, Active Directory Domain Services, Azure, Azure Site Recovery, Azure VPN, DCPromo, Domain Controller, FSMO, Microsoft Hyper-v, PowerShell, Powershell 4.0, Windows Server 2012 R2 | Tagged , , , , , , , , | Leave a comment

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 , , , , , , , , | Leave a 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