Thursday, 23 April 2020

Useful Active Directory Command-Line Operations


The commands below are a subset of the complete command list that perform queries, diagnostics or modifications to objects in an Active Directory. These commands can be useful for once-off or repeated tasks, and defining a source for bulk imports/modifications to objects.

Each command-line can be copied and pasted at the command prompt, if you use a batch file you'll need to reference variables with double-percent (%%).


Query a user from AD using WMI
wmic /node:"%DC%" /namespace:\\root\directory\LDAP path ds_user where "ds_cn='%username%'" GET ds_displayName,DS_UserPrincipalName,ds_cn,ds_name,ds_whenCreated

Show all replicated attributes in the AD Schema
dsquery * cn=schema,cn=configuration,DC=forestRootDomain -filter "(&(objectClass=attributeSchema)(objectCategory=attributeSchema)(!systemFlags:1.2.840.113556.1.4.803:=1))" -limit 0

Show an AD schema attribute
dsquery * cn=pwd-last-set,cn=schema,cn=configuration,DC=forestRootDomain

Given a list of user CNs, find them in the directory and report homeDirectory
for /f %i in (Users.txt) do @for /f "tokens=*" %m in ('"dsquery user -name %i"') do @for /f %p in ('"dsquery * %m -attr homeDirectory -l | find /i "\\" & if errorlevel 1 Echo NoHomeDirectory"') do @echo %i,%m,%p

Identify the DN of an Active Directory group
dsquery group -name %GroupName%

Find the current group scope of a security group
dsget group %GroupDN% -scope -secgrp

Change a group's scope to universal, a stepping stone for conversion
dsmod group %GroupDN% -scope u

Change a universal group's scope to global or local
dsmod group %GroupDN% -scope l | g

Modify the UPN for a user
dsmod user "%userdN%" -upn user@domain

After identifying one or more accounts without a UPN, set the UPN for each
for /f "skip=1 tokens=1,2-3" %i in (NoUPN.txt) do dsmod user "%j %k" -upn %i@%upnsuffix%

Find all user accounts with a UPN, and count the DNs returned
dsquery * domainroot -filter "&(objectclass=user)(objectcategory=person)(userprincipalname=*)" -s %server% | find /i /c "user"

Find all user accounts without a UPN, and count the DNs returned
dsquery * domainroot -filter "&(objectclass=user)(objectcategory=person)(!(userprincipalname=*))" -s %server% | find /i /c "user"

Identify user accounts without a UPN to be corrected
dsquery * %OU% -filter "&(objectclass=user)(objectcategory=person)(!(userprincipalname=*))" -s %server% -scope onelevel -attr name distinguishedname > NoUPN.txt

Determine whether an attribute is replicated in AD through bitwise AND
dsquery * cn=%AttributeName%,cn=schema,cn=configuration,dc=forestRootDomain -filter "!(&(systemFlags:1.2.840.113556.1.4.803:=1))"

Find customised Service Connection Points of type RISServerdsquery * -filter "&((objectClass=ConnectionPoint)(objectCategory=ServiceConnectionPoint)(keywords=RISServer))" -attr serviceDNSName

Find intellimirror SCPs fpr RIS servers
dsquery * -filter "&((objectClass=ConnectionPoint)(objectCategory=IntellimirrorSCP)(netbootServer=*))" -attr netbootServer

Query for the display specifiers in the AD user classdsquery * "CN=user-Display,CN=409,CN=DisplaySpecifiers,CN=Configuration,%forestrootDomain%" -attr *

Find computers and their description from the ADdsquery * -filter "(&(objectClass=Computer)(objectCategory=Computer))" "%rootDN%" -attr cn description

Use LDP to search for tombstoned objects in ADBase DN: CN=Deleted Objects,%domainRoot%, Filter: (isDeleted=*), Extended Search, Add control: 1.2.840.113556.1.4.417

Bulk modify of mailbox permissions
admodcmd -dn "%DN%" -f "(&(objectclass=user)(CN=%userFilter%*))" -addtomailboxrights %Domain%\%Group% ACE_MB_FULL_ACCESS

Check user attributes from AD (division, department, home drive, email)for /f "tokens=1-3" %i in (%users.txt%) do @for /f "tokens=*" %m in ('"@dsquery user -name %i"') do @for /f "tokens=1-10" %q in ('"@dsquery * %m -attr CN department division mail homeDirectory homedrive find /i /v "homeDirectory""') do @echo %q,%r,%s,%t,%u,%v,%w,%x,%y >> UserInformation.csv

Set a Service Principal Name for an alias against the host computer accountsetspn -A HOST/%alias%.domain.com %server%

Find the computer object advertising a specific SPN
dsquery * -filter "(&(objectClass=Computer)(objectCategory=Computer)(servicePrincipalName=*SPN*))" -attr cn servicePrincipalName distinguishedName

Export group objects from AD to a CSV fileadfind -b "domainRoot" -f "objectclass=group" cn samaccountname -csv

Servers in the directory and their descriptiondsquery * dc=common,dc=local -filter "(&(objectCategory=Computer)(objectClass=Computer)(operatingSystem=*server*))" -limit 0 -attr cn description

Forest/Domain Functional Levels
ldifde -d cn=partitions,cn=configuration,dc=%domain% -r "((systemFlags=3)(systemFlags=-2147483648))" -l msds-behavior-version,dnsroot,ntmixeddomain,NetBIOSName -p subtree -f con (see http://support.microsoft.com/kb/322692 and http://support.microsoft.com/kb/224386)

Forest/Domain Functional Levelsdsquery * cn=partitions,cn=configuration,dc=%domain% -filter "((systemFlags=3)(systemFlags=-2147483648))" -attr msDS-Behavior-Version Name dnsroot ntmixeddomain NetBIOSName (see http://support.microsoft.com/kb/322692 and http://support.microsoft.com/kb/224386)

Lookup SRV records from DNS
nslookup -type=srv _ldap._tcp.dc._msdcs.{domainRoot}

Find when the AD was installeddsquery * cn=configuration,DC=forestRootDomain -attr whencreated -scope base

Enumerate the trusts from the specified domaindsquery * "CN=System,DC=domainRoot" -filter "(objectClass=trustedDomain)" -attr trustPartner flatName

Modify ACLs using dsacls (account ACL, not mailbox rights)dsacls "%userDN%" /G "%Domain%\%Group%:CA;Send As"

Information on existing GPO’s
dsquery * "CN=Policies,CN=System,domainRoot" -filter "(objectCategory=groupPolicyContainer)" -attr displayName cn whenCreated gPCFileSysPath

FSMO Rolesntdsutil roles Connections "Connect to server %logonserver%" Quit "select Operation Target" "List roles for conn server" Quit Quit Quit

Domain ControllersNltest /dclist:%userdnsdomain%

Domain Controller IP Configurationfor /f %i in ('dsquery server -domain %userdnsdomain% -o rdn') do psexec \\%i ipconfig /all >> DC_IPConfig.txt

Stale computer accounts
dsquery computer domainroot -stalepwd 180 -limit 0 > ComputerAccounts+180.txt

Stale user accountsdsquery user domainroot -stalepwd 180 -limit 0 > UserAccounts+180.txt

Disabled user accountsdsquery user domainroot -disabled -limit 0 > UserAccountsDisabled.txt

AD Database disk usagefor /f %i in ('dsquery server -domain %userdnsdomain% -o rdn') do dir \\%i\d$\ntds >> NTDS_Size_%userdomain%.txt

Global Catalog Servers from DNSdnscmd %logonserver% /enumrecords %userdnsdomain% _tcp find /i "3268"

Global Catalog Servers from AD
dsquery * "CN=Configuration,DC=forestRootDomain" -filter "(&(objectCategory=nTDSDSA)(options:1.2.840.113556.1.4.803:=1))"

Users with no logon scriptdsquery * domainroot -filter "(&(objectCategory=Person)(objectClass=User)(!scriptPath=*))" -limit 0 -attr sAMAccountName sn givenName pwdLastSet distinguishedName

User accounts with no pwd requireddsquery * domainroot -filter "(&(objectCategory=Person)(objectClass=User)(userAccountControl:1.2.840.113556.1.4.803:=32))"

User accounts with no pwd expirydsquery * domainroot -filter "(&(objectCategory=Person)(objectClass=User)(userAccountControl:1.2.840.113556.1.4.803:=65536))"

User accounts that are disabled
dsquery * domainroot -filter "(&(objectCategory=Person)(objectClass=User)(userAccountControl:1.2.840.113556.1.4.803:=2))"

User accounts with no password expiry and not disableddsquery * domainroot -filter "(&(objectCategory=Person)(objectClass=User)(userAccountControl:1.2.840.113556.1.4.803:=65536)(!userAccountControl:1.2.840.113556.1.4.803:=2))"

Tombstoned AD objects
Adrestore.exe (sysinternals utility)

Garbage Collection and tombstonedsquery * "cn=Directory Service,cn=Windows NT,cn=Services,cn=Configuration,DC=forestRootDomain" -attr garbageCollPeriod tombstoneLifetime

DSQuery authorised DHCP Servers
Dsquery * "cn=NetServices,cn=Services,cn=Configuration, DC=forestRootDomain" -attr dhcpServers

Group Policy Verification Toolgpotool.exe /checkacl /verbose

AD OU membership
dsquery computer -limit 0

AD OU membershipdsquery user -limit 0

List Service Principal Namesfor /f %i in ('dsquery server -domain %userdnsdomain% -o rdn') do setspn -L %i

Compare DC Replica Object Countdsastat –s:DC1;DC2;... –b:Domain –gcattrs:objectclass –p:999

Check AD ACLs
acldiag dc=domainTree

NTFRS Replica Setsfor /f %i in ('dsquery server -domain %userdnsdomain% -o rdn') do ntfrsutl sets %i

NTFRS DS View
for /f %i in ('dsquery server -domain %userdnsdomain% -o rdn') do ntfrsutl ds %i

Domain Controllers per siteDsquery * "CN=Sites,CN=Configuration,DC=forestRootDomain" -filter (objectCategory=Server)

DNS Zones in AD
for /f %i in ('dsquery server -o rdn') do Dsquery * -s %i domainroot -filter (objectCategory=dnsZone)

Subnet information
Dsquery subnet –limit 0

List Organisational Units
Dsquery OU

ACL on all OUsFor /f “delims=” %i in ('dsquery OU') do acldiag %i >> ACLDiag.txt

Domain Trusts
nltest /domain_trusts /v

AD Subnet and Site Informationdsquery * "CN=Subnets,CN=Sites,CN=Configuration,DC=forestRootDomain" -attr cn siteObject description location

AD Site Information
dsquery * "CN=Sites,CN=Configuration,DC=forestRootDomain" -attr cn description location -filter (objectClass=site)

Printer Queue Objects in ADdsquery * domainroot -filter "(objectCategory=printQueue)" -limit 0

Group Membership with user detailsdsget group "groupDN" -members dsget user -samid -fn -mi -ln -display -empid -desc -office -tel -email -title -dept -mgr

Site Links and Cost
dsquery * "CN=Sites,CN=Configuration,DC=forestRootDomain" -attr cn cost description replInterval siteList -filter (objectClass=siteLink)

Time gpresulttimethis gpresult /v > GPResult_%ComputerName%.txt 2<&1 Check time against Domain w32tm /monitor /computers:ForestRootPDC > %temp%\Time.txt

Domain Controller Diagnosticsdcdiag /s:%logonserver% /v /e /c

Domain Replication Bridgeheads
repadmin /bridgeheads

Replication Failures from KCCrepadmin /failcache

Inter-site Topology servers per siteRepadmin /istg * /verbose

Replication latency
repadmin /latency /verbose

Queued replication requestsrepadmin /queue *

Show connections for a DC
repadmin /showconn *

Replication summaryRepadmin /replsummary

Show replication partnersrepadmin /showrepl * /all

All DCs in the forest
repadmin /viewlist *

ISTG from AD attributesdsquery * "CN=NTDS Site Settings,CN=siteName,CN=Sites,CN=Configuration,DC=forestRootDomain" -attr interSiteTopologyGenerator

Return the object if KCC Intra/Inter site is disabled for each siteDsquery site dsquery * -attr * -filter "((Options:1.2.840.113556.1.4.803:=1)(Options:1.2.840.113556.1.4.803:=16))"

Find all connection objects
dsquery * forestRoot -filter (objectCategory=nTDSConnection) –attr distinguishedName fromServer whenCreated displayName

Find all connection schedulesadfind -b "cn=Configuration,DC=forestRootDomain" -f "objectcategory=ntdsConnection" cn Schedule -csv

Copy all Group Policy .pol files
for /f "tokens=1-8 delims=\" %i in ('dir /b /s \\%dc%\sysvol\%userdnsdomain%\policies\*.pol') do @echo copy \\%i\%j\%k\%l\%m\%n\%o %m_%n.pol

Extract the registry entries from each Group Policy pol filefor %i in (*.pol) do regview %i > %i.txt

Find policy changes for each policy
for /f "tokens=1,2 delims=," %i in (Output from 'Extract policy registry entries') do for /f "tokens=2 delims=:" %k in ('"find /i /c "valuename" %~nj*.txt find /i "%~nj""') do @echo %i,%j,%k

Domain Controller Netlogon entriesfor /f %i in ('dsquery server /o rdn') do echo %i & reg query \\%i\hklm\system\currentcontrolset\services\netlogon\parameters

Find site links that contain two sites with Domain Controllersfor /f "tokens=1,2 delims=-" %i in (Sites.txt) do @find /i "%i" DCs.txt >nul & if errorlevel 0 if not errorlevel 1 @find /i "%j" DCs.txt find /i /v "----------"

Find policy display name given the GUID
dsquery * "CN=Policies,CN=System,DC=domainRoot" -filter (objectCategory=groupPolicyContainer) -attr Name displayName

Find empty groupsdsquery * -filter "&(objectCategory=group)(!member=*)" -limit 0 -attr whenCreated whenChanged groupType sAMAccountName distinguishedName memberOf

Find a DC for each trusted domain
for /f "skip=1" %i in ('"dsquery * CN=System,DC=domainRoot -filter (objectClass=trustedDomain) -attr trustPartner"') do nltest /dsgetdc:%i

Verify automatic external LDAP referrals are workingdsquery * dc=other,dc=domain -s %localDC%

Check winlogon notification packages on DCs
for /f %i in ('dsquery server /o rdn') do @for /f "tokens=4" %m in ('"reg query \\%i\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa /v "Notification Packages" find /i "Notification""') do @echo %i,%m

Find out if a user account is currently enabled or disableddsquery user DC=%userdnsdomain:.=,DC=% -name %username% dsget user -disabled -dn

Find 2003 servers in the domain
dsquery * domainroot -filter "(&(objectCategory=Computer)(objectClass=Computer)(operatingSystem=*Server*))" -limit 0

Open DS query windowrundll32 dsquery,OpenQueryWindow

Check for a schema attributedsquery * "CN=Schema,CN=Configuration,DC=forestRoot" -filter "(&((cn=%ObjectName*)((objectCategory=classSchema)(objectCategory=attributeSchema))))"

Find servers and the description recorded with the computer accountdsquery * %domainRoot% -filter "(&(objectCategory=Computer)(objectClass=Computer)(operatingSystem=*Server*))" -limit 0 -attr cn distinguishedName Description

Find DCs in the specified site from AD
dsquery * "CN=%SiteName%,CN=Sites,CN=Configuration,DC=root,DC=local" -filter "&(objectClass=server)(objectCategory=server)"

Dump account lockout eventlog entries from all DCs for the last five daysfor /f %i in ('dsquery server -domain %userdnsdomain% -o rdn') do echo dumpel.exe -e 644 -l Security -m Security -s %i -c -d 5

Query for universal groups
dsquery * dc=%forestRootDomain% -filter "(&(objectCategory=group)(groupType=-2147483640))"

Find the link speed when connecting to the domainlinkspeed /s %domain%

Determine users that aren’t in a group
for /f "tokens=1-3" %i in (%users.txt%) do @for /f "tokens=*" %m in ('"@dsquery user -name %i"') do @echo %m & @dsget user %m -memberof -expand @findstr /i /c:"%m" /c:"%GROUP%" & echo.

Query group membershipdsquery group -name %GROUP% dsget group -members -expand > %GROUP%.members

Check whether users are in a group (from 'Query group membership')for /f "skip=1 tokens=1-3" %i in (%users.txt%) do @find /i "%i" %GROUP%.members >NUL & @if errorlevel 1 echo %i

Check whether users are in a group or not (from 'Query group membership')
for /f "tokens=1-3" %i in (%users.txt%) do @find /i "%i" %GROUP%.members >NUL & @if errorlevel 0 if not errorlevel 1 (echo %i Member) else (echo %i NotMember)

Return the DN of a list of usersfor /f %i in (%users.txt%) do @dsquery user -name %i

Friday, 17 April 2020

USB tethering in Linux using android adb



On modern OS like Fedora 13, Ubuntu 10.04 etc. we do not have to do anything special for USB tethering to work. If we just connect mobile to PC/laptop and enable tethering then Internet will start working. But on older OS like CentOS 5.5 we can follow below mentioned steps to make tethering work on Linux with help of proxoid and adb:
  1. Download and install Proxoid from the Market on Android phone.
  2. Connect your Android device to your computer via USB.
  3. Launch Proxoid, and start the service.
  4. On phone, from home screen: Menu > Settings > Applications > Development > USB debugging (make sure it is checked, if it isn't)
  5. On Linux laptop/PC from a terminal window type:
    sudo gedit /etc/udev/rules.d/90-android.rules
    and write following contents to it 
             'SUBSYSTEM=="usb", ATTRS{idVendor}=="0bb4", MODE="0666"'
  6. Install i686 versions of libstdc++ and libncurses using 'yum -y install libncurses-devel.i686 libstdc++-devel.i686'
  7. Download and decompress the latest Android SDK. You can unpack it in any directory of your choice, for example /opt.
  8. Go to tools directory
  9. Run ./android and install 'Android SDK Platform-tools'
  10. Now go to newly create 'platform-tools' directory in parent directory of 'tools' directory. Once in the platform-tools directory, issue the following command in your terminal window as root:
    ./adb forward tcp:8080 tcp:8080
  11. Open Firefox.
  12. From Firefox: Edit > Preferences > Advanced > Network > Settings
  13. Select Manual Proxy Settings and set the HTTP Proxy field to localhost and the Port field to 8080. Click OK.
  14. Start surfing.

Monday, 13 April 2020

VMware PowerCLI Commands - Part 2

The VMware PowerCLI PowerShell interface provided for managing vSphere systems is a fantastic tool that should be useful for all VMware admins.

I've gathered these commands while implementing and managing ESXi clusters, use with caution on any production system.


Join a cluster by moving an ESX host from one location to the cluster
Move-Inventory -Item (Get-VMHost -Name esxHost) -Destination (Get-Cluster -Name clusterName)

Get the VMware.Vim.ClusterComputeResource MO from the PowerCLI cluster object
$clusterview = get-view $cluster.Id

Reconfigure a host for VMware HA (high availability)
$vmhost = get-vmhost -name esxHost; $hostMO = Get-View -ID $vmhost.ID; $hostMO.ReconfigureHostForDAS()

Find migration events for the last day
$events = Get-VIEvent -Start (Get-Date).AddDays(-1) | where {$_.fullFormattedMessage -match "Migrating.*"}

Find events other than CPU Alarms or user login/logout for the last day
$events = Get-VIEvent -Start (Get-Date).AddDays(-1) | where {$_.fullFormattedMessage -notmatch "Alarm.*CPU.*|User.*logged.*"}

Find events for degraded MPIO path redundancy 
$events = Get-VIEvent -Start (Get-Date).AddDays(-1) | where {$_.fullFormattedMessage -match "Path redundancy to storage.*degraded"}

Report the date, host and description for MPIO path redundancy errors
foreach ($event in $events) {write-output ($event.createdTime.ToString() + "," + $event.host.get_name() + "," + $event.fullFormattedMessage)}

List a table of VI events with only the date and message
$events | format-table -wrap -autosize -property createdTime,fullFormattedMessage

List the physical networks adapters and the current link speed (ESX 4.0)
$hostSystem = get-view -ViewType HostSystem; $hostConfigManager = $hostSystem.get_ConfigManager(); $hostNetworkSystem = $hostConfigManager.get_NetworkSystem(); $netSystem = Get-View $hostNetworkSystem; $netSystem.NetworkConfig.pnic; foreach ($pnic in  $netSystem.NetworkConfig.pnic) {Write-Output ($pnic.Device + "," + $pnic.spec.linkspeed.SpeedMB)}

List the vSwitches and the uplinks currently attached
$hostSystem = get-view -ViewType HostSystem; $hostConfigManager = $hostSystem.get_ConfigManager(); $hostNetworkSystem = $hostConfigManager.get_NetworkSystem(); $netSystem = Get-View $hostNetworkSystem; foreach ($vswitch in  $netSystem.NetworkConfig.vSwitch) {Write-Output ($vSwitch.Name + "," + $vswitch.spec.policy.NicTeaming.NicOrder.ActiveNic)}

Remove snapshots from a group of machines
$VMs = Get-VM -Location (get-folder -name "vmFolder"); foreach ($vm in $vms) {remove-snapshot -snapshot (Get-Snapshot -vm $vm) -confirm:$false}

Take snapshots of a group of machines
$VMs = Get-VM -Location (get-folder -name "vmFolder"); foreach ($vm in $VMs) {New-Snapshot -Name "snapshot 01" -description "Snapshot description" -vm $vm -Quiesce:$false}

Find VM name, description and primary disk datastore
$VMs = get-vm; foreach ($vm in $VMs) {write-output ($vm.Name + ",""" + $vm.Description + """," + $vm.harddisks[0].FileName.Replace(" ", ",")) | out-file -append -filepath c:\temp\VM_Datastores.txt}

Bring a host out of maintenance most
Set-VMHost -VMHost esxHost -State Connected

Generate diagnostic support bundles for all hosts
get-log -vmhost (get-vmhost) -bundle -destinationpath c:\temp\bundles

Find the network adapter type for each VM
$vms = get-vm ; foreach ($vm in $vms) {write-host $vm.Name "-"  $vm.networkadapters[0].type}

Find physical NICs and whether they're set to autonegotiate or hardcoded
foreach ($pnic in $hostNetwork.pnic) {if($pnic.linkSpeed -eq $null) {$ls = "Auto"} else {$ls= $pnic.linkSpeed.speedMB.toString() + ":" + $pnic.linkSpeed.duplex} ;write-output ($pnic.Device + "," + $ls)}

Find host sytem build information
$hostSystems = get-view -ViewType HostSystem; foreach ($hostSystem in $hostSystems) {Write-Output ($hostSystem.Name + "," + $hostSystem.config.product.Fullname)}

Find VMs and whether the VMtools is configured to synchronising time 
$vmSet = Get-VM ; foreach ($vm in $vmSet) { $view = get-view $vm.ID ;$config = $view.config; $tools = $config.tools; Write-Output ($vm.Name + "," + $tools.SyncTimeWithHost) }

Revert to a snapshot
set-vm -vm vmName -snapshot (get-snapshot -vm vmName) -confirm:$false

Remove a virtual machine from inventory and delete from disk
remove-vm -DeleteFromDisk:$true -RunAsync:$true -vm vmName

Shutdown one or more Virtual Machine guests
shutdown-vmguest -vm $vms -confirm:$false

Start one or more Virtual Machine guests
start-vm -vm $vms -confirm:$false

Forcefully power off one or more Virtual Machines
stop-vm $vms -confirm:$false

Get a virtual switch from the specified ESX host
get-virtualswitch -name vSwitch1 -vmhost esxHost

Create a new port group on the specified vSwitch
New-VirtualPortGroup -Name "pgName" -VirtualSwitch $vs

Find ESX memory balloon averages for the last five days
get-stat -entity $hosts -start (Get-Date).AddDays(-5) -finish (Get-Date) -stat mem.vmmemctl.average

Export a list of VMs
$vms | select-object -prop Name | out-file -filepath c:\temp\vms.txt

Export a list of VM guest hostnames 
$vms = get-vm; foreach ($vm in $vms) { write-output $vm.guest.get_HostName()}

Friday, 3 April 2020

VMware PowerCLI commands


The commands below are PowerCLI commands used to automate VMware ESX and VirtualCenter at the command prompt. Most of these commands were built on ESX with vSphere PowerCLI, and the majority have been tested against ESXi and vCenter Infrastructure.

Each command-line can be copied and pasted at a PowerCLI command prompt, and most commands assume you already have a connection to the target, be it vCenter or ESX.

Note that most of these commands use OBN - Object By Name - instead of using the get* command to get the object. This is supported with all but a few of the commands I've come across.

List the vSphere PowerCLI commands
Get-VICommand

Connect to a ESX or VirtualCenter instance
connect-viserver -server %server%

List the currently available datastores
Get-Datastore | sort

List the currently available datastores filtered and sorted
Get-Datastore | where {$_.Name -like '*pr*'} | sort

Find the VMs attached to one or more datastores
foreach ($prodDatastore in $prodDatastores) { write-output $prodDatastore.Name; get-vm -datastore $proddatastore; write-output ''}

Get a Virtual Machine
$vm = get-vm -name '%vm%'

Get the virtual harddisk for the specified VMs
Get-HardDisk -vm $vm

Move a virtual machine to another container
Move-VM -Destination $prodApps -VM $vm

Update the VM description for a list of CSV entries
foreach ($virtualServer in $virtualservers) {$arr = $virtualServer.split(","); $desc = $arr[1]; $vmName = $arr[0]; write-output $vmName; $desc; $vm = get-vm -name $vmName; Set-VM -VM $vm -description $desc}

Query for a list of VMs and output in ANSI format
get-vm | sort-object | format-table -property Name | out-file -encoding ASCII -filepath c:\temp\vms_20090625.txt

Find VMware machine performance statistics
 get-stat -entity $vm -disk -start 01/01/2009 -finish ([DateTime]::Now.ToString("dd/MM/yyyy"))

For a group of VMs, report performance statistics and save to file
foreach ($vm in $devVMs) {get-stat -entity $vm -disk -start 01/01/2009 -finish ([DateTime]::Now.ToString("dd/MM/yyyy")) | out-file -filepath ("c:\temp\" + $vm.Name + "DiskPerformance.txt")}

Find VM datastore disk usage
$devVMs = get-vm -name '*dv*'; foreach ($vm in $devvms) {$vm.harddisks}

Find VM datastore disk usage
$testVMs = Get-VM -Location (get-folder -name "Test") ;foreach ($vm in $testVMs) {$vm.harddisks | format-table -hideTableHeaders -wrap -autosize | findstr /i /c:per}

Find SCSI devices attached to an ESX server
get-scsilun -vmhost (Get-VMHost -Location "cluster")[0]

Rescan HBAs on an ESX server
get-VMHostStorage -VMHost (Get-VMHost -Location "cluster")[0] -RescanAllHba

Storage vMotion a virtual machine to a new datastore
Move-VM -vm "vmName" -datastore "NewDatastore"

Storage vMotion a group of machines from a CSV input file
$servers = get-content -path inputfile.txt; foreach ($server in $servers) {move-vm -vm $server.split(",")[0] -datastore $server.split(",")[1]}

Remove a snapshot and child snapshots, reporting how long the operation took
measure-command -expression {remove-snapshot -snapshot $snapshots[0] -removechildren}

Find datastore space, usage and number of VMs per datastore
$datastores = get-datastore | sort-object; write-output "Name,Size,Used,Free,% Used,#VMs"; foreach ($datastore in $datastores) { write-output ($datastore.Name + "," + [math]::round($datastore.CapacityMB/1024) + "," + [math]::round(($datastore.CapacityMB/1024)-($datastore.FreeSpaceMB/1024)) + "," + [math]::round($datastore.FreeSpaceMB/1024) + "," + [math]::round(((($datastore.CapacityMB/1024) - ($datastore.FreeSpaceMB/1024)) / ($datastore.CapacityMB/1024)) * 100) + "," + (get-vm -datastore $datastore).count)}

From a set of VMs, find which have snapshots
foreach ($testvm in $testvms) {if (get-snapshot -vm $testvm){write-output $testvm.Name}}

Find the size of the first hard disk in each VM
foreach ($vm in $vms) {$vm.harddisks[0] | format-table -hideTableHeaders -wrap -autosize | findstr /i /c:per }

Find disk information for VMs in the specified datastore
 $VMs = Get-VM ;foreach ($vm in $VMs) {$vm.harddisks | where {$_.FileName -like '*clusterpr*'} | format-table -hideTableHeaders -wrap -autosize | findstr /i /c:per}

Find VMs in the specified datastore
$VMs = Get-VM | where {$_.harddisks[0].FileName -like '*clusterpr*'}

Get VM guest information, including virtual OS
get-vm | get-vmguest | format-table -wrap -autosize

Find virtual machines and their description/notes
$vms = get-vm ; $vms | format-table -wrap -autosize -property Name,Description

Create an associative array containing VM names and descriptions
$vmdesc = @{}; foreach ($vm in $vms) {$vmdesc.add($vm.Name, $vm.Description)}

Migrate a virtual machine to another host in a VMware ESX cluster
move-vm -vm %vmName% -destination %hostname%

Find the host a VM is currently located on
get-vmhost -vm %vnName%

Add a new harddisk to a virtual machine
New-HardDisk -vm %vmName% -CapacityKB 20971520

Retrieve details on the resource pools from the currently connected datacenter
Get-ResourcePool | format-table -wrap -autosize -property Name,Id,CpuExpandableReservation,CpuLimitMHz,CpuReservationMHz,CpuSharesLevel,CustomFields,MemExpandableReservation,MemLimitMB,MemReservationMB,MemSharesLevel,Name,NumCpuShares,NumMemShares

Find virtual machines and if they have a CD-ROM
get-vm | format-table -wrap -autosize -property Name,CDDrives

Find the last 100 events that aren't alarm related
$events = Get-VIEvent -MaxSamples 100 | where {$_.fullFormattedMessage -notmatch "Alarm*"}

Find all events for machine deployments from templates
$events = Get-VIEvent | where {$_.fullFormattedMessage -match "Deploying (.*) on host (.*) in (.*) from template (.*)"}

Create a resource pool with high CPU and memory shares
New-ResourcePool -location (get-cluster -name 'cluster') -Name ResPool1 -CpuSharesLevel [VMware.VimAutomation.Types.SharesLevel]::High -MemSharesLevel [VMware.VimAutomation.Types.SharesLevel]::High

Create a folder from the root of the tree
New-Folder -Name Workstations -location (get-folder -name 'vm')

Move one or more VMs to a resource pool (or other destination)
$vms = get-vm -name vmNames*; move-vm -vm $vms -destination (Get-ResourcePool -name 'ResPool1')

Get an OS customization specification, and list the properties in wide format
Get-OSCustomizationSpec -name "SpecName" | format-list

Take a snapshot of a virtual machine
New-Snapshot -Name "Snapshot 01" -description "Snapshot description" -vm vmName -Quiesce:$true

Convert a virtual machine to a template
$vmView = get-vm -name vm01 | Get-View; $vmView.MarkAsTemplate()

Find Datastore usage (custom written function)
get-datastoreusage

Get an ESX log bundle using PowerCLI
Get-Log -VMHost esxhostname -Bundle -DestinationPath c:\temp

Query for snapshots
Get-VM | Get-Snapshot | export-csv -path c:\temp\VMsnapshots.csv

Query for snapshot information
Get-VM | Get-Snapshot | foreach-object {$out=  $_.VM.Name + "," + $_.Name + "," + $_.Description + "," + $_.PowerState; $out}

Wednesday, 25 March 2020

Finding Duplicate DNS records

Internal DNS in many organisations is usually a little messy and if tasked with cleaning it, my first step would be to identify duplicate records in DNS - either an IP address that is recorded against multiple host names or a host name with multiple host (A) records. Assuming you have a file containing one record per line, this is fairly simple to report on.

The following examples use dnscmd.exe, which assumes Windows 2000/2003 DNS, but you could use any input, as long as it contains a name and an IP.

The two commands:

  1. dnscmd %dnsServer% /enumrecords test.local @ /additional /continue | find /i /v "Aging:" | find /i "192.168" > DNSRecords.txt
  2. echo. > DuplicateIPs.txt & (for /f "tokens=1,4" %i in (DNSRecords.txt) do @if "%j" NEQ "" @find /i "%j" DuplicateIPs.txt >nul & if errorlevel 1 for /f "tokens=1" %m in ('"findstr /i "%j$" DNSRecords.txt | find /i /c "%j""') do @if %m GTR 1 (@echo %j,%m: & findstr /i "%j$" DNSRecords.txt & echo.) >> DuplicateIPs.txt) & type DuplicateIPs.txt
The first command uses dnscmd to enumerate the records from the root of the test.local zone and exclude aging (dynamic DNS) records. The last find command further filters the output by IP, which can be useful when targeting specific subnets/sites. You might also want to check aging dynamic records instead of static to see how well scavenging is working – if you do, just change the tokens to 1,5 instead of 1,4 (as the aging data is another token separating the name and IP).

The second command:

  1. Creates a new file called DuplicateIPs.txt in the current working directory
  2. Iterates through each line in the DNS record dump, extracting the first and fourth token (Name and IP)
  3. The commands in the first FOR loop check there is a value, then check the value hasn't already been processed in the duplicate list (otherwise you'd have duplicates of each duplicate) and then counts the duplicates and appends them to the file.
  4. The final command types the duplicate IP file created by the for loop iteration.
For example, supposing your DNS export contained the following records:


printer1 3600 A 192.168.10.100
printer2 3600 A 192.168.10.101
printer3 3600 A 192.168.10.100
printer4 3600 A 192.168.10.102
printer5 3600 A 192.168.10.103
printer6 3600 A 192.168.10.100
printer7 3600 A 192.168.10.102

After running the second command above, a file called DuplicateIPs.txt would be created and then typed to the prompt:


192.168.10.100,3:
printer1 3600 A 192.168.10.100
printer3 3600 A 192.168.10.100
printer6 3600 A 192.168.10.100

192.168.10.102,2:
printer4 3600 A 192.168.10.102
printer7 3600 A 192.168.10.102

The command below is modified to report duplicate names instead of IP addresses. This was done by using the first token (%i) instead of the second (%j), and modifying the findstr command to use a literal string search ending with a space rather than the regular expression EOL:

echo. > DuplicateIPs.txt & (for /f "tokens=1,4" %i in (DNSRecords.txt) do @if "%i" NEQ "" @find /i "%i" DuplicateIPs.txt >nul & if errorlevel 1 for /f "tokens=1" %m in ('"findstr /i /c:"%i " DNSRecords.txt | find /i /c "%i""') do @if %m GTR 1 (@echo %i,%m: & findstr /i /c:"%i " DNSRecords.txt & echo.) >> DuplicateIPs.txt) & type DuplicateIPs.txt


If you wanted a summary rather than the detail of each duplicate, you could also run the following command:
echo. > DuplicateIPSummary.txt & (for /f "tokens=1,4" %i in (DNSRecords.txt) do @if "%j" NEQ "" @find /i "%j" DuplicateIPSummary.txt >nul & if errorlevel 1 for /f "tokens=1" %m in ('"findstr /i "%j$" DNSRecords.txt | find /i /c "%j""') do @if %m GTR 1 (@echo %j,%m) >> DuplicateIPSummary.txt) & type DuplicateIPSummary.txt


In the example above, this would produce the following report: 
192.168.10.100,3
192.168.10.102,2

I use this sort of command to generate reports on duplicates, in this case from DNS, but it could also be useful in DHCP, WINS, or any number of Active Directory objects/attributes. People (myself included) are often wary of automated processes that make changes, but this is an excellent example of how powerful read-only automated commands can be – you can take thousands of objects and produce a report in seconds to quickly identify inconsistencies in an environment.

Dnscmd Overview
http://technet.microsoft.com/en-us/library/cc778513.aspx

Tuesday, 17 March 2020

High Availability – A Storage Architecture


Hello all, so I’ve been doing a lot of work around availability in the cloud and how to build applications that are architected for resiliency. And one of the common elements that comes up, is how do I architecture for resiliency around storage.

So the scenario is this, and its a common one, I need to be able to write new files to blob storage, and read from my storage accounts, and need it to be as resilient as possible.

So let’s start with the SLA, so currently if you are running LRS storage, then your SLA is 99.9%, which from a resiliency perspective isn’t ideal for a lot of applications. But if I use RA-GRS, my SLA goes up to 99.99%.

Now, I want to be clear about storage SLAs, this SLA says that I will be able to read data from blob storage, and that it will be available 99.99% of the time using RA-GRS.

For those who are new to blob storage, let’s talk about the different types of storage available:

  •     Locally Redundant Storage (LRS) : This mean that the 3 copies of the data you put in blob storage, are stored within the same zone.
  •     Zone Redundant Storage (ZRS): This means that the 3 copies of the data you put in blob storage, and stored across availability zones.
  •     Geo Redundant Storage (GRS) : This means that the 3 copies of the data you put in blob storage, are stored across multiple regions, following azure region pairings.
  •     Read Access Geo Redundant Storage (RA-GRS): This means that the 3 copies of the data you put in blob storage, are stored across multiple regions, following azure region pairings. But in this case you get a read access endpoint you can control.

So based on the above, the recommendation is that for the best availability you would use RA-GRS, which is a feature that is unique to Azure. RA-GRS enables you to have a secondary endpoint where you can get read-only access to the back up copies that are saved in the secondary region.

For more details, look here.

So based on that, you gain the fact that if your storage account is called : storagexyz.blob.core.windows.netYour secondary read-access endpoint would be : storagexyz-secondary.blob.core.windows.net
So the next question is, “That’s great AV Tech, but I need to be able to write and read”, and I have an architecture pattern I recommend for that and it is this:

So the above architecture, is oversimplified but focuses on the storage account configuration for higher availability. In the above architecture, we have a web application that is deployed behind traffic manager, with an instance in a primary region, and an instance in a secondary region.
Additionally we have an Azure SQL database that is ego-replicated into a backup region.
Let’s say for the sake of argument, with the above:
  • Region A => East US
  • Region B => West US
But for storage, we do the following, Storage Account A, will be in East US, which means that it will automatically replicate to West US.
For Storage Account B, will be in West US, which means it replicates to East US.
So let’s look at the Region A side:
  • New Blobs are written to Storage Account A
  • Blobs are read based on database entries.
  • Application tries to read from database identified blob storage, if it fails it uses the “-secondary” endpoint.
So for Region B side:
  • New Blobs are written to Storage Account B
  • Blobs are read based on database entries
  • Application tries to read from database identified blob storage, if it fails it uses the “-secondary” endpoint.
So in our databases I would recommend the following fields for every blob saved:
  • Storage Account Name
  • Container Name
  • Blob Name
This allows for me to easily implement the “-secondary” when it is required.
So based on the above, let’s play out a series of events:
  • We are writing blobs to Storage Account A. (1,2,3)
  • There is a failure, we fail over to Region B.
  • We start writing new blobs to Storage Account B. (4,5,6)
  • If we want to read Blob 1, we do so through the “-secondary” endpoint from Storage Account A.
  • The issue resolves
  • We read Blob 1-3 from Storage Account A (primary endpoint)
  • If we read Blob 4-6 it would be from the “-secondary” endpoint of Storage Account B
Now some would ask the question, “when do we migrate the blobs from B to A?” I would make the argument you don’t, at the end of the day, storage accounts cost nothing, and you would need to incur additional charges to move the data to the other account for no benefit. As long as you store each piece of data you can always find the blobs so I don’t see a benefit from merging.

Featured post

Top 10 Rare Windows Shortcuts to Supercharge Productivity

  Windows Key + X, U, U: This sequence quickly shuts down your computer. It's a great way to initiate a safe and swift shutdown without...