четверг, 7 июля 2022 г.

Deleting Entry in vCloud PostgreSQL

If you're familiar with vCloud Director, you know that occasionally there can be stubborn, outdated entries. This happens when a VM, vApp, or template won't respond to the standard GUI methods. When this happens, many people turn to the VMware helpdesk for assistance. However, did you know that you can tackle this issue yourself, even if you're not a DBA? All you need is to take a backup or snapshot of the vCloud VM and make a backup of the Postgre DB with SSH/CLI. So, let's dive in!

1. First go in the GUI to the VM and take IDs of vApp and VM.

VM
e8b68b96-8c8a-4e2c-bf35-17ddc534e451
vApp
a893f027-6bee-4e54-8125-b09c04319c72

2. First enter to the vCloud PhotonOS with SSH (putty, MobaXterm).


4. Then enter to vCloud PostgreSQL with this command:
sudo -i -u postgres psql vcloud
(where postgres is a user, and vcloud is a DB)


5. =Deleting VM=
VM id: e8b68b96-8c8a-4e2c-bf35-17ddc534e451

delete from vapp_vm where id = ' 'e8b68b96-8c8a-4e2c-bf35-17ddc534e451'';
XXX
ERROR:  update or delete on table "vapp_vm" violates foreign key constraint "fk_vap_vm_scl_me2vapp_vm" on table "vapp_vm_sclass_metrics"
DETAIL:  Key (id)=(ac706161-1b79-4a41-a2d8-abfff0754758) is still referenced from table "vapp_vm_sclass_metrics".

We need to delete the VM from the referenced table vapp_vm_sclass_metrics, 
instead of id we will use vapp_vm_id.
select * from vapp_vm_sclass_metrics where vapp_vm_id = 'e8b68b96-8c8a-4e2c-bf35-17ddc534e451';
delete from vapp_vm_sclass_metrics where vapp_vm_id = 'e8b68b96-8c8a-4e2c-bf35-17ddc534e451';

delete from vapp_vm where id = 'e8b68b96-8c8a-4e2c-bf35-17ddc534e451';

Again we have referenced table

select * from guest_personalization_info where vapp_vm_id = 'e8b68b96-8c8a-4e2c-bf35-17ddc534e451';

delete from guest_personalization_info where vapp_vm_id = 'e8b68b96-8c8a-4e2c-bf35-17ddc534e451';


delete from vapp_vm where id = 'e8b68b96-8c8a-4e2c-bf35-17ddc534e451';

In GUI

We see that there is no VM, but again we cannot to delete the vApp.
Success for VM, but still not for vApp.

6. =VAPP=

We are taking vApp id: 'a893f027-6bee-4e54-8125-b09c04319c72'

https://vcloud.algotec.co.il/tenant/support/vdcs/7f306f1b-a035-4015-81d8-d3783b5a3128/vapp/vapp-a893f027-6bee-4e54-8125-b09c04319c72/vcd-vapp-vms

Now we can work with sg_id, which is more relaible than a name.

select * from vm_container where sg_id='a893f027-6bee-4e54-8125-b09c04319c72';
We see the vApp still exists:


Now we will try to delete the vApp.
delete from vm_container where sg_id = 'a893f027-6bee-4e54-8125-b09c04319c72';


We cannot delete the vApp because of another table that contains vApp id - "vapp_logical_resource".
Let's go there.
select * from vapp_logical_resource where vapp_id='a893f027-6bee-4e54-8125-b09c04319c72';


Now deleting.
delete from vapp_logical_resource where vapp_id='a893f027-6bee-4e54-8125-b09c04319c72';


Good, let's check in DB.
select * from vapp_logical_resource where vapp_id='a893f027-6bee-4e54-8125-b09c04319c72';


Now we return back to the original place in trial to delete the vApp.
First, little check:
select * from vm_container where sg_id='a893f027-6bee-4e54-8125-b09c04319c72';
Now the actual deleing:
delete from vm_container where sg_id='a893f027-6bee-4e54-8125-b09c04319c72';


Seems we have deleted the vApp!..., but let's check that it is a real thing:
select * from vm_container where sg_id='a893f027-6bee-4e54-8125-b09c04319c72';

Now we sure it is deleted, but let's check in GUI too:


Bravo!





воскресенье, 19 июня 2022 г.

VMware vCenter HA Master with PowerCLI

If you manage vSphere, sometimes you can wonder - who is this master of crime, master/primary ESXi Host, which is responsible for HA cluster.

воскресенье, 29 мая 2022 г.

Discard VMs suspended state in vCloud with PowerCLI

If you have experienced difficulty in removing a VM from a suspended state within a vApp, then you will understand what I am referring to. However, if this is not something you have encountered, then you may skip this.


Unfortunately, we often encounter problematic states such as suspended states. However, this script can be very useful in completely discarding the suspended state.

==START==
cls
Write-Host "=Suspended VMs=" -BackgroundColor DarkRed -ForegroundColor Yellow
Write-Host "This script shows all suspended VMs on vCenter VCRD" -ForegroundColor Yellow
$host.UI.RawUI.WindowTitle = "=Suspended VMs to Stop="

Write-Host ""
$vCenter = ""
$User = ""
$Pass = ""
$RealPass = ""
$GetVM = ""
$Suspended = ""
$ToStop = ""
$ToStopCount = ""
$StopVM = ""

#=== Policy/Configuration ===#
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass -Force
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -confirm:$false | Out-Null
$ErrorActionPreference= 'SilentlyContinue'
$WarningActionPreference= 'SilentlyContinue'
Add-PsSnapin VMware.VimAutomation.Core

#=== My Login Credentials ===#
$vCenter = 'VCRD.algotec.co.il'
$User = $env:UserName
$SecurePass = Read-Host -AsSecureString "Please enter password for $UserName and wait..."
$Pass = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePass))
If(-not$Pass){Write-Host "You must enter a password!" -ForegroundColor Yellow -BackgroundColor Black; Write-Host; Break}

Write-Host "I am connecting you to vCenter..." -ForegroundColor Yellow
Disconnect-VIServer * -Confirm:$false 
If (!($global:defaultviserver.IsConnected)){$VIServerConnected = Connect-VIServer -Server $vCenter -User $User -Password $Pass}
If(!($VIServerConnected)){Write-Host "$vCenter is NOT Connected! Try another password." -BackgroundColor Black -ForegroundColor Yellow; Break}
Else{Write-Host "vCenter is Connected!" -ForegroundColor Green -BackgroundColor DarkRed}
Write-Host 

Write-Host "I am getting all Suspended VMs..." -ForegroundColor Yellow
$GetVM = Get-VM
$Suspended = $GetVM | Where-Object -Property PowerState -EQ 'Suspended'
If(!$Suspended){Write-Host "Okay. There is NO Suspended VMs!" -ForegroundColor Yellow -BackgroundColor DarkRed; Break}
$Suspended | Select Name, Powerstate, VApp, VMHost
$Count = $Suspended.count
Write-Host
Write-Host "The number of Suspended VMs is $Count" -ForegroundColor Green
$ToStop = $Suspended | Out-GridView -Title "Suspended VMs to Stop" -PassThru
Write-Host
$ToStopCount = $ToStop.count
Write-Host "The number of VMs selected to Stop $ToStopCount" -ForegroundColor Green
Write-Host

foreach($StopVM in $ToStop)
    {
    $StopVM | Stop-VM -Confirm:$false | Out-Null
    $StoppedName = $StopVM.name
    Write-Host "$StoppedName is stopped" -ForegroundColor White -BackgroundColor DarkRed
    }

Write-Host "$ToStopCount VMs are stopped" -ForegroundColor Black -BackgroundColor White
==FINISH==

If there are no suspended VMs in your environment, you are lucky.



Find Datastore Id/Uuid/MoRef in vCenter

Was it you searched to which Datastore the error is connected?
Maybe you couldn't create a VM because of lacking free space on a Datastore, and the system got you only some Id or Moref (if you are using vCloud Director) instead of a normal Datastore name. 

If you hated these moments, so do I.
Because of that I have made some script that can give us additional info and bound Datastore names to their Id/Moref, etc.

Here it is.

===BEGINNING===

cls

Write-Host "=Datastores IDs=" -BackgroundColor DarkRed -ForegroundColor Yellow

$host.UI.RawUI.WindowTitle = "=Datastores IDs="

Get-Date -Format "dd-MM-yyyy HH:mm"

Write-Host

Write-Host "Defining Configuration:" -BackgroundColor Green -ForegroundColor Blue

$ErrorActionPreference = 'SilentlyContinue'

$WarningActionPreference = 'SilentlyContinue'

$ErrorPreference = 'SilentlyContinue'

$WarningPreference = 'SilentlyContinue'

Import-Module VMware.PowerCLI | Out-Null

Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -confirm:$false | Out-Null

#$vCenter = "vCenter" ## Change as you need

#$User = "GeniousAdmin" ## Change as you need

#$Pass = "P@ssw0rd" ## Change as you need

Disconnect-VIServer * -Confirm:$false -ErrorAction SilentlyContinue | Out-Null

Connect-VIServer -Server $vCenter -User $User -Password $Pass@ | Out-Null

#####=====#####

$outputfile = "D:\Datastores_Uuid.csv"

$DStores = Get-Datastore | select * | Where-Object { $_.Name -like "Datastore_*" }

$TableArray = @()

foreach($DS in $DStores)

    {

    $DSName = $DS.Name

    $DSUuid = $DS.ExtensionData.Info.Vmfs.Uuid

    $DSId = $DS.Id

    $DSMoRef =- $DS.ExtensionData.MoRef

    $OneLineArray = New-Object "PSCustomObject"

    $OneLineArray | Add-Member -MemberType NoteProperty -Name "Datastore" -Value $DSName

    $OneLineArray | Add-Member -MemberType NoteProperty -Name "Datastore Uuid" -Value $DSUuid

    $OneLineArray | Add-Member -MemberType NoteProperty -Name "Datastore Id" -Value $DSId

    $OneLineArray | Add-Member -MemberType NoteProperty -Name "Datastore MoRef" -Value $DSMoRef

    $TableArray += $OneLineArray

    }

$TableArray | OGV -Title "=Datastores IDs="

$TableArray | Export-Csv -path $outputfile -NoTypeInformation

ii $outputfile

 ===FINISH===

This the end result:




понедельник, 14 марта 2022 г.

Removing Shadow VMs on vCloud

Removing Shadow VMs


##==  ==##

# Removing Shadow VMs on a specific Datastore

# ToDo - Choose Datastore with OGV !


$ErrorActionPreference = "SilentlyContinue" 

$WarningPreference = "SilentlyContinue" 


cls

$User = $env:UserName

$SecurePass = Read-Host -AsSecureString "Please enter password for '$User' and wait..."

$Pass = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePass))

If(-not($Pass)){Write-Host "You must enter a password!" -ForegroundColor Yellow -BackgroundColor DarkRed; Write-Host; Break}

$vCloud = "vCloud"

$vCenter = "VCRD"


##== Connecting to vCloud ==##

Disconnect-CIServer * -Confirm:$false 

$CIServerConnected = ""

$CIServerConnected = Connect-CIServer -Server $vCloud -User $User -Password $Pass # -Org $Org | Out-Null

If(-not($CIServerConnected)){Write-Host "$vCloud is NOT Connected! `nPlease check your password, locked user account or permissions!" -BackgroundColor DarkRed  -ForegroundColor Yellow; Write-Host; Break}

Else{Write-Host "$vCloud is Connected!" -ForegroundColor Yellow -BackgroundColor DarkRed}

Write-Host 


##== Connecting to vCenter ==##

Disconnect-VIServer * -Confirm:$false 

$VIServerConnected = ""

$VIServerConnected = Connect-VIServer -Server $vCenter -User $User -Password $Pass

If(-not($VIServerConnected)){Write-Host "$vCenter is NOT Connected!" -BackgroundColor DarkRed -ForegroundColor Yellow}

Else{Write-Host "vCenter is Connected!" -ForegroundColor Yellow -BackgroundColor DarkRed}

Write-Host 


##== Getting info for four NF400N Datastores from vCenter ==##

$AllDatastoreS = Get-Datastore

$ChosenDatastoreS = $AllDatastoreS | Where{$_.Name -like "Datastore_NF400N_*"} | sort -Property FreeSpaceGB | select -First 5

Write-Host "Five Datastores with the least free space" -BackgroundColor DarkGreen

$ChosenDatastoreS

Write-Host 


##== Searching for Shadow VMs on NF400N Datastores ==##

$ShadowVMs400 = Search-Cloud AdminShadowVM -Filter DatastoreName==Datastore_NF400N_*

$ShadowVMs400Count = $ShadowVMs400.Count

Write-Host "There are $ShadowVMs400Count ShadowVMs in NF400N Cluster" -BackgroundColor DarkGreen


##== Counting Shadow VMs by Datastore ==##

foreach ($Datastore in $ChosenDatastoreS)

    {

    $ShadowVMsDatastore = $ShadowVMs400 | where{$_.DatastoreName -like $Datastore}

    $VMsCount = $ShadowVMsDatastore.Count

    If($VMsCount){Write-Host "$Datastore = $VMsCount VMs" -BackgroundColor Green}

    }

Write-Host 


##== Choosing specific Datastore and creating filter sentence for searching Shadow VMs on this Datastore ==##

$DatastoreNumber = ""

[Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') > $NULL

$DatastoreNumber = [Microsoft.VisualBasic.Interaction]::InputBox("Choose Datastore number for deleting ShadowVMs (or press Enter for exit): ", "Datastore Number")


###=CHOOSE DATASTORE OR EXIT FROM THE SCRIPT IF A NUMBER IS NOT CHOOSEN=###

Write-Host 

$ChosenDatastore = -join("Datastore_NF400N_"+$DatastoreNumber)

$FilterDatastore = "DatastoreName==$ChosenDatastore"

Write-Host 


##== Exit from script by Datastore ==##

If(!$DatastoreNumber){Write-Host "NO Datastore is choosen.`n`nSCRIPT IS FINISHED!" -ForegroundColor Yellow -BackgroundColor DarkCyan; break}

Else{Write-Host "You selected '$ChosenDatastore'" -BackgroundColor Green}


##== Searching Shadow VMs on the specific Datastore ==##

$ShadowVMsOnDatastore = Search-Cloud AdminShadowVM -Filter $FilterDatastore

### $ShadowVMsOnDatastoreCount = $ShadowVMsOnDatastore.name.Count

$ShadowVMsOnDatastoreCount = $ShadowVMsOnDatastore.Count

##== Exit from script if NO ShadowVMs is found/defined on the selected Datastore ==##

If(!$ShadowVMsOnDatastoreCount){Write-Host "Wrong choice, there are NO Shadow VMs on '$ChosenDatastore'. I am exiting!" -BackgroundColor DarkGreen; Break}

Write-Host "There are $ShadowVMsOnDatastoreCount Shadow VMs on '$ChosenDatastore'. Select some or all to kill..." -BackgroundColor DarkGreen

Write-Host 


$VMsNamesBefore = $ShadowVMsOnDatastore.Name

$ShadowVMsDelete = $ShadowVMsOnDatastore | OGV -Title "Shadow VMs On '$ChosenDatastore'" -PassThru

$ShadowVMsNames = ($ShadowVMsDelete).Name

If(!$ShadowVMsNames){Write-Host "Seems you are afraid to kill the Shadow VMs :) `nYou should know it is your choice. I am exiting!" -BackgroundColor DarkGreen; Break}

Write-Host "Shadow VMs selected for deleting:" -BackgroundColor Green

$ShadowVMsNames

Write-Host 


##== Deleting Shadow VMs on the selected Datastore ==##

foreach ($shadowVM in $ShadowVMsDelete)

    {

    $shadowVMName = $shadowVM.Name

    Write-Host "Deleting '$shadowVMName'" -BackgroundColor DarkBlue -ForegroundColor Magenta

    $ShadowDelete = $shadowVM | Get-CIView

    $ShadowDelete.delete()

    }


Write-Host 

$ShadowVMsOnDatastore = Search-Cloud -QueryType AdminShadowVM

$ShadowVMsOnDatastore = $ShadowVMsOnDatastore | where {$_.DatastoreName -like $ChosenDatastore}

$VMsCountAfter = $ShadowVMsOnDatastore.Count

$VMsDifference = $ShadowVMsOnDatastoreCount - $VMsCountAfter


Write-Host $ChosenDatastore -BackgroundColor Black

Write-Host "From $ShadowVMsOnDatastoreCount Shadow VMs you choosed $VMsDifference to delete." -BackgroundColor DarkRed

Write-Host "After deleting there are $VMsCountAfter Shadow VMs left." -BackgroundColor DarkRed

Write-Host 

Write-Host "GREAT JOB '$env:UserName' !" -ForegroundColor Yellow -BackgroundColor DarkRed

Write-Host 


# del $env:TEMP\ShadowDeletedLog.csv

# $VMsDifference | Export-Csv $env:TEMP\ShadowDeletedLog.csv -NoTypeInformation -UseCulture

# ii $env:TEMP\ShadowDeletedLog.csv

##==  ==##




пятница, 11 марта 2022 г.

Unlock AD user with PowerShell

First you need to be Domain Administrator.

To find all locked accounts in Active Directory you may use this simple command:

Search-ADAccount -LockedOut 

To unlock specific user use this command:

Unlock-ADAccount "Username"

To unlock all found accounts you can pipe results of the command to another command:

Search-ADAccount -LockedOut | Unlock-ADAccount

If you want to unlock several users (not only one and not all of them) you may use Out-GridView command which gives the possibility for some sort of GUI menu.

Search-ADAccount -LockedOut | OGV -Title "Choose the accounts for unlocking" -PassThru | Unlock-ADAccount

Put attention to -PassThru  - it gives the possibility to choose one or more objects and then piping them to the next command which is in our case unlocks the chosen users.

In the most of cases these simple commands could be enough, but if you want to be cool you may do some scripting.

##== START ==##

cls

$LockedAcc = ""

$LockedAccCount = ""

$User = $env:UserName


Write-Host "'$User', I am seeking for Locked Accounts....." -BackgroundColor Green

$LockedAcc = Search-ADAccount -LockedOut

$LockedAcc | Select Name, SamAccountName, LockedOut

$LockedAccCount = ($LockedAcc | measure).Count


Write-Host

If(!($LockedAcc)){Write-Host "Great! I cannot find any!" -ForegroundColor Yellow -BackgroundColor DarkRed; Write-Host; Break}

Else{Write-Host "Found $LockedAccCount Locked Account(s)" -BackgroundColor Red}

$LockedAcc | OGV -PassThru | Unlock-ADAccount


##== CHECK ==##

Write-Host "Post-check for Locked Accounts..."

Start-Sleep 5


$LockedAcc2 = ""

$LockedAcc2Count = ""


$LockedAcc2 = Search-ADAccount -LockedOut

$LockedAcc2Count = ($LockedAcc2 | measure).Count


If($LockedAcc2){Write-Host "Still $LockedAcc2Count Account(s) is/are Locked" -BackgroundColor Red}

Else{Write-Host "Great! You successfully unlocked accounts." -BackgroundColor Red}

$LockedAcc2 | Select Name, SamAccountName, LockedOut


##== END ==##




суббота, 5 марта 2022 г.

Useful Links

 How to Allow Multiple RDP Sessions in Windows 10 and 11?

http://woshub.com/how-to-allow-multiple-rdp-sessions-in-windows-10/

Install RSAT on Windows 10 with PowerShell

PowerShell

Get-WindowsCapability -Name RSAT* -Online | Add-WindowsCapability -Online

понедельник, 14 февраля 2022 г.

Fixing issues with RDP connection when using multiple monitors

If you have two monitors at home and want to connect to your workplace, you might encounter an error when attempting to connect to a server using both monitors.

Luckily, there's a quick and easy solution! First, enter with a single monitor definition on the RDP client. Then, enter with the two-monitor definition without exiting the first session. This will allow the second connection to take the session from the first, preventing the error from occurring.

If you experience this error frequently and want to automate the double-connection process, you can use a small batch script that will do the work for you.

==START OF BATCH==

SET IP=X.X.X.X

SET USERNAME=youruser

SET PASSWORD=yourpassword

SET DOMAIN=yourdodmain.com

start cmdkey /generic:"%IP%" /user:"%USERNAME%" /pass:"%PASSWORD%"

start mstsc /f /v:"%IP%"

TIMEOUT  3

start mstsc -multimon /f /v:"%IP%"

==END OF BATCH==

Using the name of your computer instead of its IP address to connect is possible, but it may result in slower connections and potential DNS issues.