Remove cloud-config from existing vRA 8 deployments
In vRA you have the possibility to enable cloud-config in your blueprints to automate certain tasks at creation time. This could be tasks like installing packages, changing root credentials, setting a hostname and much more.
vRA and cloud-config
When you enable cloud-config in a blueprint and perform a deployment, an ISO file will be created in the VM folder on the datastore. The ISO contains a file with these settings that eventually will be used upon creation time. The ISO file will automatically be connected to the VM by vRA.
Enabling this is straight forward and can be done through the vRA GUI. When cloud-config is enabled in a deployment, you will see the cloud-config parameters in the deployment as shown below.
But in this case the customer was experiencing some strange behavior with already deployed Ubuntu VMs through vRA. Somehow cloud-init got triggered within the VM what led to a password reset of one of the native users within Ubuntu.
This issue was fixed by removing the connected ISO from the VM. For some reason, vRA did not remove the ISO file after the creation and configuration of the machine.
But how can you remove this setting from an existing deployment? There is no way in the GUI to remove this settings and we had like 50+ deployments with this setting.
The only way to remove it is by leveraging the vRA REST API.
The Script: Remove-CloudConfigFromDeployments.ps1
Script can be downloaded from my github page on the following location.
The Remove-CloudConfigFromDeployments.ps1 powershell script does the following:
- Connect to the vRA REST API
- Query list of deployments with the cloud config setting
- If enabled: remove cloud-config from deployments
How to use it.
Set the $vraServer variable with the FQDN of the vRA server. By default, the script does not remove the cloud-config settings. It only output the deployments with these settings enabled. If you would like to perform the remove action, you should set the $removeCloudConfig variable to $true
Note:
Keep in mind that it could take a few minutes before the GUI is updated with these changes.
# Settings:
$vraServer = ""
$credential = Get-Credential
$username = $credential.UserName
$password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($credential.Password))
$removeCloudConfig = $false
$header = @{
"Accept" = "application/json"
"Content-Type" = "application/json"
}
$authBody = @{
"username" = $username
"password" = $password
} | ConvertTo-Json
# Get Refresh Token:
$uri = "https://" + $vraServer + "/csp/gateway/am/api/login?access_token"
$refreshToken = Invoke-RestMethod -uri $uri -Method POST -Headers $header -Body $authBody
$refreshToken = $refreshToken.refresh_token
$refreshTokenBody = @{
"refreshToken" = $refreshToken
} | ConvertTo-Json
# Get Access Token:
$uri = "https://" + $vraServer + "/iaas/api/login"
$accessToken = Invoke-RestMethod -Uri $uri -Method POST -Headers $header -body $refreshTokenBody
$accessToken = "Bearer " + $accessToken.token
$header.Add("Authorization",$accessToken)
# Get all vRA deployments
# INFO: API return size is limited to 200.
$count = 0
$uri = "https://" + $vraServer + "/iaas/api/deployments"
$totalResources = (Invoke-RestMethod -Uri $uri -Method GET -Headers $header).totalElements
$arrayDeployments = @()
Write-Host "Requesting all deployments from VMware vRA..."
do{
$uriNextPage = $uri + "?`$top=200&`$skip=$($count)"
$deployments = Invoke-RestMethod -Uri $uriNextPage -Method GET -Headers $header
$arrayDeployments += $deployments
$count = $count + 200
}while($count -lt $totalResources)
Write-Host "Total resources collected:" $arrayDeployments.content.count -ForegroundColor Green
# Searching for deployments with cloud-config settings.
# If some resources are failing, it is most likely caused of a machine error in the vRA deployment
$cloudConfigResources = @()
foreach($d in $arrayDeployments.content){
foreach($r in $d._links.resources.hrefs){
if($r -like "/iaas/api/machines/*"){
$uri = "https://" + $vraServer + $r
$resource = Invoke-RestMethod -Uri $uri -Method GET -Headers $header
$resourceName = $resource.hostname
Write-Host "Checking on resource: $resourceName" -ForegroundColor Yellow
if($resource.bootConfig){
$resourceID = $r.replace("/iaas/api/machines/",'')
$hashtable = @{Name = $resourceName; ResourceID = $resourceID; BootConfig = $resource.bootConfig.content}
$cloudConfigResources += $hashtable
Write-Host "Cloud-Config settings available!" -ForegroundColor Green
}else{
Write-Host "No cloud-config settings."
}
}
}
}
# Show all gathered resources with cloud-config.
if($cloudConfigResources){
Write-Host "List of cloud-config enabled deployments:"
$cloudConfigResources | %{[pscustomobject] $_} | Select-Object Name, ResourceID, Bootconfig
}else{
Write-Host "No cloud-config enabled deployments."
}
# Removing the cloud-config settings from the custom properties
if($removeCloudConfig -eq $true){
Write-Host "`$removeCloudConfig variable is enabled."
foreach($a in ($cloudConfigResources)){
$resourceName = $a.Name
$uri = "https://" + $vraServer + "/iaas/api/machines/" + $a.resourceID
$body = @{
"bootConfig" = @{}
"customProperties" = @{
"cloudConfig" = ""
}
} | ConvertTo-Json
Write-Host "Removing bootConfig and the cloud-config settings from the customProperties of resource:" $resourceName
$Patch = Invoke-RestMethod -Uri $uri -Method Patch -Body $body -Headers $header
}
}else{
Write-Host "`$removeCloudConfig variable not enabled."
}
Thanks for sharing.
For future deployments, wouldn’t you run a ABX (part of an subscription) removing or disconnecting the CD-ROM drive of the newly deployed VM – on a VM Post Deployment subscription? – using the build-in PowerCLI of the ABX.
You’re welcome. That is indeed an option to remove or disconnect a cd-drive. The customer doesn’t want to use cloud-config anymore instead they are using ansible for future configuration.