Merge pull request #1 from vmware/master

sync
This commit is contained in:
Wouter Kursten
2018-02-04 13:59:58 +01:00
committed by GitHub
110 changed files with 18566 additions and 562 deletions

0
.gitattributes vendored Normal file
View File

51
.gitignore vendored Normal file
View File

@@ -0,0 +1,51 @@
# PowerShell Studio Files
*.temppoint.*
*.psproj.psbuild
*.psbuild
#VS Code Files
*.vscode
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

View File

@@ -32,13 +32,13 @@
If a -LocationType is not chosen, the function will default to FTP.
The destination location for a backup must be an empty folder (easiest to use the get-date cmdlet in the location)
-ShowProgress will give you a progressbar as well as updates in the console
-SeatBackup will only backup the config whereas -Fullbackup grabs the historical data as well
-CommonBackup will only backup the config whereas -Fullbackup grabs the historical data as well
#>
param (
[Parameter(ParameterSetName=FullBackup)]
[switch]$FullBackup,
[Parameter(ParameterSetName=SeatBackup)]
[switch]$SeatBackup,
[Parameter(ParameterSetName=CommonBackup)]
[switch]$CommonBackup,
[ValidateSet('FTPS', 'HTTP', 'SCP', 'HTTPS', 'FTP')]
$LocationType = "FTP",
$Location,
@@ -50,13 +50,14 @@
)
Begin {
if (!($global:DefaultCisServers)){
Add-Type -Assembly System.Windows.Forms
[System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null
$Connection = Connect-CisServer $global:DefaultVIServer
} else {
$Connection = $global:DefaultCisServers
}
if ($FullBackup) {$parts = @("common","seat")}
if ($SeatBackup) {$parts = @("seat")}
if ($CommonBackup) {$parts = @("common")}
}
Process{
$BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job
@@ -72,7 +73,7 @@
$BackupJob = $BackupAPI.create($CreateSpec)
}
catch {
Write-Error $Error[0].exception.Message
throw $_.Exception.Message
}
@@ -84,6 +85,7 @@
start-sleep -seconds 5
} until ($BackupAPI.get("$($BackupJob.ID)").progress -eq 100 -or $BackupAPI.get("$($BackupJob.ID)").state -ne "INPROGRESS")
Write-Progress -Activity "Backing up VCSA" -Completed
$BackupAPI.get("$($BackupJob.ID)") | select id, progress, state
}
Else {

View File

@@ -0,0 +1,581 @@
Function Get-ContentLibrary {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function lists all available vSphere Content Libaries
.PARAMETER LibraryName
The name of a vSphere Content Library
.EXAMPLE
Get-ContentLibrary
.EXAMPLE
Get-ContentLibrary -LibraryName Test
#>
param(
[Parameter(Mandatory=$false)][String]$LibraryName
)
$contentLibaryService = Get-CisService com.vmware.content.library
$libaryIDs = $contentLibaryService.list()
$results = @()
foreach($libraryID in $libaryIDs) {
$library = $contentLibaryService.get($libraryID)
# Use vCenter REST API to retrieve name of Datastore that is backing the Content Library
$datastoreService = Get-CisService com.vmware.vcenter.datastore
$datastore = $datastoreService.get($library.storage_backings.datastore_id)
if($library.publish_info.published) {
$published = $library.publish_info.published
$publishedURL = $library.publish_info.publish_url
$externalReplication = $library.publish_info.persist_json_enabled
} else {
$published = $library.publish_info.published
$publishedURL = "N/A"
$externalReplication = "N/A"
}
if($library.subscription_info) {
$subscribeURL = $library.subscription_info.subscription_url
$published = "N/A"
} else {
$subscribeURL = "N/A"
}
if(!$LibraryName) {
$libraryResult = [pscustomobject] @{
Id = $library.Id;
Name = $library.Name;
Type = $library.Type;
Description = $library.Description;
Datastore = $datastore.name;
Published = $published;
PublishedURL = $publishedURL;
JSONPersistence = $externalReplication;
SubscribedURL = $subscribeURL;
CreationTime = $library.Creation_Time;
}
$results+=$libraryResult
} else {
if($LibraryName -eq $library.name) {
$libraryResult = [pscustomobject] @{
Name = $library.Name;
Id = $library.Id;
Type = $library.Type;
Description = $library.Description;
Datastore = $datastore.name;
Published = $published;
PublishedURL = $publishedURL;
JSONPersistence = $externalReplication;
SubscribedURL = $subscribeURL;
CreationTime = $library.Creation_Time;
}
$results+=$libraryResult
}
}
}
$results
}
Function Get-ContentLibraryItems {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function lists all items within a given vSphere Content Library
.PARAMETER LibraryName
The name of a vSphere Content Library
.PARAMETER LibraryItemName
The name of a vSphere Content Library Item
.EXAMPLE
Get-ContentLibraryItems -LibraryName Test
.EXAMPLE
Get-ContentLibraryItems -LibraryName Test -LibraryItemName TinyPhotonVM
#>
param(
[Parameter(Mandatory=$true)][String]$LibraryName,
[Parameter(Mandatory=$false)][String]$LibraryItemName
)
$contentLibaryService = Get-CisService com.vmware.content.library
$libaryIDs = $contentLibaryService.list()
$results = @()
foreach($libraryID in $libaryIDs) {
$library = $contentLibaryService.get($libraryId)
if($library.name -eq $LibraryName) {
$contentLibaryItemService = Get-CisService com.vmware.content.library.item
$itemIds = $contentLibaryItemService.list($libraryID)
foreach($itemId in $itemIds) {
$item = $contentLibaryItemService.get($itemId)
if(!$LibraryItemName) {
$itemResult = [pscustomobject] @{
Name = $item.name;
Id = $item.id;
Description = $item.description;
Size = $item.size
Type = $item.type;
Version = $item.version;
MetadataVersion = $item.metadata_version;
ContentVersion = $item.content_version;
}
$results+=$itemResult
} else {
if($LibraryItemName -eq $item.name) {
$itemResult = [pscustomobject] @{
Name = $item.name;
Id = $item.id;
Description = $item.description;
Size = $item.size
Type = $item.type;
Version = $item.version;
MetadataVersion = $item.metadata_version;
ContentVersion = $item.content_version;
}
$results+=$itemResult
}
}
}
}
}
$results
}
Function Get-ContentLibraryItemFiles {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function lists all item files within a given vSphere Content Library
.PARAMETER LibraryName
The name of a vSphere Content Library
.PARAMETER LibraryItemName
The name of a vSphere Content Library Item
.EXAMPLE
Get-ContentLibraryItemFiles -LibraryName Test
.EXAMPLE
Get-ContentLibraryItemFiles -LibraryName Test -LibraryItemName TinyPhotonVM
#>
param(
[Parameter(Mandatory=$true)][String]$LibraryName,
[Parameter(Mandatory=$false)][String]$LibraryItemName
)
$contentLibaryService = Get-CisService com.vmware.content.library
$libaryIDs = $contentLibaryService.list()
$results = @()
foreach($libraryID in $libaryIDs) {
$library = $contentLibaryService.get($libraryId)
if($library.name -eq $LibraryName) {
$contentLibaryItemService = Get-CisService com.vmware.content.library.item
$itemIds = $contentLibaryItemService.list($libraryID)
foreach($itemId in $itemIds) {
$itemName = ($contentLibaryItemService.get($itemId)).name
$contenLibraryItemFileSerice = Get-CisService com.vmware.content.library.item.file
$files = $contenLibraryItemFileSerice.list($itemId)
foreach($file in $files) {
if(!$LibraryItemName) {
$fileResult = [pscustomobject] @{
Name = $file.name;
Version = $file.version;
Size = $file.size;
Stored = $file.cached;
}
$results+=$fileResult
} else {
if($itemName -eq $LibraryItemName) {
$fileResult = [pscustomobject] @{
Name = $file.name;
Version = $file.version;
Size = $file.size;
Stored = $file.cached;
}
$results+=$fileResult
}
}
}
}
}
}
$results
}
Function Set-ContentLibrary {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function updates the JSON Persistence property for a given Content Library
.PARAMETER LibraryName
The name of a vSphere Content Library
.EXAMPLE
Set-ContentLibraryItems -LibraryName Test -JSONPersistenceEnabled
.EXAMPLE
Set-ContentLibraryItems -LibraryName Test -JSONPersistenceDisabled
#>
param(
[Parameter(Mandatory=$true)][String]$LibraryName,
[Parameter(Mandatory=$false)][Switch]$JSONPersistenceEnabled,
[Parameter(Mandatory=$false)][Switch]$JSONPersistenceDisabled
)
$contentLibaryService = Get-CisService com.vmware.content.library
$libaryIDs = $contentLibaryService.list()
$found = $false
foreach($libraryID in $libaryIDs) {
$library = $contentLibaryService.get($libraryId)
if($library.name -eq $LibraryName) {
$found = $true
break
}
}
if($found) {
$localLibraryService = Get-CisService -Name "com.vmware.content.local_library"
if($JSONPersistenceEnabled) {
$jsonPersist = $true
} else {
$jsonPersist = $false
}
$updateSpec = $localLibraryService.Help.update.update_spec.Create()
$updateSpec.type = $library.type
$updateSpec.publish_info.authentication_method = $library.publish_info.authentication_method
$updateSpec.publish_info.persist_json_enabled = $jsonPersist
Write-Host "Updating JSON Persistence configuration setting for $LibraryName ..."
$localLibraryService.update($library.id,$updateSpec)
} else {
Write-Host "Unable to find Content Library $Libraryname"
}
}
Function New-ExtReplicatedContentLibrary {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function creates a new Subscriber Content Library from a JSON Persisted
Content Library that has been externally replicated
.PARAMETER LibraryName
The name of the new vSphere Content Library
.PARAMETER DatastoreName
The name of the vSphere Datastore which contains JSON Persisted configuration file
.PARAMETER SubscribeLibraryName
The name fo the root directroy of the externally replicated Content Library residing on vSphere Datastore
.PARAMETER AutoSync
Whether or not to Automatically sync content
.PARAMETER OnDemand
Only sync content when requested
.EXAMPLE
New-ExtReplicatedContentLibrary -LibraryName Bar -DatastoreName iSCSI-02 -SubscribeLibraryName myExtReplicatedLibrary
.EXAMPLE
New-ExtReplicatedContentLibrary -LibraryName Bar -DatastoreName iSCSI-02 -SubscribeLibraryName myExtReplicatedLibrary -AutoSync $false -OnDemand $true
#>
param(
[Parameter(Mandatory=$true)][String]$LibraryName,
[Parameter(Mandatory=$true)][String]$DatastoreName,
[Parameter(Mandatory=$true)][String]$SubscribeLibraryName,
[Parameter(Mandatory=$false)][Boolean]$AutoSync=$false,
[Parameter(Mandatory=$false)][Boolean]$OnDemand=$true
)
$datastore = Get-Datastore -Name $DatastoreName
if($datastore) {
$datastoreId = $datastore.ExtensionData.MoRef.Value
$datastoreUrl = $datastore.ExtensionData.Info.Url
$subscribeUrl = $datastoreUrl + $SubscribeLibraryName + "/lib.json"
$subscribeLibraryService = Get-CisService -Name "com.vmware.content.subscribed_library"
$StorageSpec = [pscustomobject] @{
datastore_id = $datastoreId;
type = "DATASTORE";
}
$UniqueChangeId = [guid]::NewGuid().tostring()
$createSpec = $subscribeLibraryService.Help.create.create_spec.Create()
$createSpec.name = $LibraryName
$addResults = $createSpec.storage_backings.Add($StorageSpec)
$createSpec.subscription_info.automatic_sync_enabled = $false
$createSpec.subscription_info.on_demand = $true
$createSpec.subscription_info.subscription_url = $subscribeUrl
$createSpec.subscription_info.authentication_method = "NONE"
$createSpec.type = "SUBSCRIBED"
Write-Host "Creating new Externally Replicated Content Library called $LibraryName ..."
$library = $subscribeLibraryService.create($UniqueChangeId,$createSpec)
}
}
Function Remove-SubscribedContentLibrary {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function deletes a Subscriber Content Library
.PARAMETER LibraryName
The name of the new vSphere Content Library to delete
.EXAMPLE
Remove-SubscribedContentLibrary -LibraryName Bar
#>
param(
[Parameter(Mandatory=$true)][String]$LibraryName
)
$contentLibaryService = Get-CisService com.vmware.content.library
$libaryIDs = $contentLibaryService.list()
$found = $false
foreach($libraryID in $libaryIDs) {
$library = $contentLibaryService.get($libraryId)
if($library.name -eq $LibraryName) {
$found = $true
break
}
}
if($found) {
$subscribeLibraryService = Get-CisService -Name "com.vmware.content.subscribed_library"
Write-Host "Deleting Subscribed Content Library $LibraryName ..."
$subscribeLibraryService.delete($library.id)
} else {
Write-Host "Unable to find Content Library $LibraryName"
}
}
Function New-LocalContentLibrary {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function creates a new Subscriber Content Library from a JSON Persisted
Content Library that has been externally replicated
.PARAMETER LibraryName
The name of the new vSphere Content Library
.PARAMETER DatastoreName
The name of the vSphere Datastore to store the Content Library
.PARAMETER Publish
Whther or not to publish the Content Library, this is required for JSON Peristence
.PARAMETER JSONPersistence
Whether or not to enable JSON Persistence which enables external replication of Content Library
.EXAMPLE
New-LocalContentLibrary -LibraryName Foo -DatastoreName iSCSI-01 -Publish $true
.EXAMPLE
New-LocalContentLibrary -LibraryName Foo -DatastoreName iSCSI-01 -Publish $true -JSONPersistence $true
#>
param(
[Parameter(Mandatory=$true)][String]$LibraryName,
[Parameter(Mandatory=$true)][String]$DatastoreName,
[Parameter(Mandatory=$false)][Boolean]$Publish=$true,
[Parameter(Mandatory=$false)][Boolean]$JSONPersistence=$false
)
$datastore = Get-Datastore -Name $DatastoreName
if($datastore) {
$datastoreId = $datastore.ExtensionData.MoRef.Value
$localLibraryService = Get-CisService -Name "com.vmware.content.local_library"
$StorageSpec = [pscustomobject] @{
datastore_id = $datastoreId;
type = "DATASTORE";
}
$UniqueChangeId = [guid]::NewGuid().tostring()
$createSpec = $localLibraryService.Help.create.create_spec.Create()
$createSpec.name = $LibraryName
$addResults = $createSpec.storage_backings.Add($StorageSpec)
$createSpec.publish_info.authentication_method = "NONE"
$createSpec.publish_info.persist_json_enabled = $JSONPersistence
$createSpec.publish_info.published = $Publish
$createSpec.type = "LOCAL"
Write-Host "Creating new Local Content Library called $LibraryName ..."
$library = $localLibraryService.create($UniqueChangeId,$createSpec)
}
}
Function Remove-LocalContentLibrary {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function deletes a Local Content Library
.PARAMETER LibraryName
The name of the new vSphere Content Library to delete
.EXAMPLE
Remove-LocalContentLibrary -LibraryName Bar
#>
param(
[Parameter(Mandatory=$true)][String]$LibraryName
)
$contentLibaryService = Get-CisService com.vmware.content.library
$libaryIDs = $contentLibaryService.list()
$found = $false
foreach($libraryID in $libaryIDs) {
$library = $contentLibaryService.get($libraryId)
if($library.name -eq $LibraryName) {
$found = $true
break
}
}
if($found) {
$localLibraryService = Get-CisService -Name "com.vmware.content.local_library"
Write-Host "Deleting Local Content Library $LibraryName ..."
$localLibraryService.delete($library.id)
} else {
Write-Host "Unable to find Content Library $LibraryName"
}
}
Function Copy-ContentLibrary {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function copies all library items from one Content Library to another
.PARAMETER SourceLibaryName
The name of the source Content Library to copy from
.PARAMETER DestinationLibaryName
The name of the desintation Content Library to copy to
.PARAMETER DeleteSourceFile
Whther or not to delete library item from the source Content Library after copy
.EXAMPLE
Copy-ContentLibrary -SourceLibaryName Foo -DestinationLibaryName Bar
.EXAMPLE
Copy-ContentLibrary -SourceLibaryName Foo -DestinationLibaryName Bar -DeleteSourceFile $true
#>
param(
[Parameter(Mandatory=$true)][String]$SourceLibaryName,
[Parameter(Mandatory=$true)][String]$DestinationLibaryName,
[Parameter(Mandatory=$false)][Boolean]$DeleteSourceFile=$false
)
$sourceLibraryId = (Get-ContentLibrary -LibraryName $SourceLibaryName).Id
if($sourceLibraryId -eq $null) {
Write-Host -ForegroundColor red "Unable to find Source Content Library named $SourceLibaryName"
exit
}
$destinationLibraryId = (Get-ContentLibrary -LibraryName $DestinationLibaryName).Id
if($destinationLibraryId -eq $null) {
Write-Host -ForegroundColor Red "Unable to find Destination Content Library named $DestinationLibaryName"
break
}
$sourceItemFiles = Get-ContentLibraryItems -LibraryName $SourceLibaryName
if($sourceItemFiles -eq $null) {
Write-Host -ForegroundColor red "Unable to retrieve Content Library Items from $SourceLibaryName"
break
}
$contentLibaryItemService = Get-CisService com.vmware.content.library.item
foreach ($sourceItemFile in $sourceItemFiles) {
# Check to see if file already exists in destination Content Library
$result = Get-ContentLibraryItems -LibraryName $DestinationLibaryName -LibraryItemName $sourceItemFile.Name
if($result -eq $null) {
# Create CopySpec
$copySpec = $contentLibaryItemService.Help.copy.destination_create_spec.Create()
$copySpec.library_id = $destinationLibraryId
$copySpec.name = $sourceItemFile.Name
$copySpec.description = $sourceItemFile.Description
# Create random Unique Copy Id
$UniqueChangeId = [guid]::NewGuid().tostring()
# Perform Copy
try {
Write-Host -ForegroundColor Cyan "Copying" $sourceItemFile.Name "..."
$copyResult = $contentLibaryItemService.copy($UniqueChangeId, $sourceItemFile.Id, $copySpec)
} catch {
Write-Host -ForegroundColor Red "Failed to copy" $sourceItemFile.Name
$Error[0]
break
}
# Delete source file if set to true
if($DeleteSourceFile) {
try {
Write-Host -ForegroundColor Magenta "Deleteing" $sourceItemFile.Name "..."
$deleteResult = $contentLibaryItemService.delete($sourceItemFile.Id)
} catch {
Write-Host -ForegroundColor Red "Failed to delete" $sourceItemFile.Name
$Error[0]
break
}
}
} else {
Write-Host -ForegroundColor Yellow "Skipping" $sourceItemFile.Name "already exists"
# Delete source file if set to true
if($DeleteSourceFile) {
try {
Write-Host -ForegroundColor Magenta "Deleteing" $sourceItemFile.Name "..."
$deleteResult = $contentLibaryItemService.delete($sourceItemFile.Id)
} catch {
Write-Host -ForegroundColor Red "Failed to delete" $sourceItemFile.Name
break
}
}
}
}
}

View File

@@ -0,0 +1,290 @@
Function Get-XVCMStatus {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function returns whether Cross vCenter Workload Migration Utility is running or not
.EXAMPLE
Get-XVCMStatus
#>
$Uri = "http://localhost:8080/api/ping"
$results = Invoke-WebRequest -Uri $Uri -Method GET -TimeoutSec 5
if($results.StatusCode -eq 200) {
Write-Host -ForegroundColor Green $results.Content
} else { Write-Host -ForegroundColor Red "Cross vCenter Workload Migration Utility is probably not running" }
}
Function Get-XVCMSite {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function returns all registered vCenter Servers
.EXAMPLE
Get-XVCMSite
#>
$Uri = "http://localhost:8080/api/sites"
$results = Invoke-WebRequest -Uri $Uri -Method GET
if($results.StatusCode -eq 200) {
($results.Content | ConvertFrom-Json)|select sitename,hostname,username
} else { Write-Host -ForegroundColor Red "Failed to retrieve VC Site Registration details" }
}
Function New-XVCMSite {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function registers a new vCenter Server endpoint
.PARAMETER SiteName
The display name for the particular vCenter Server to be registered
.PARAMETER VCHostname
The Hostname/IP Address of vCenter Server
.PARAMETER VCUsername
The VC Username of vCenter Server
.PARAMETER VCPassword
The VC Password of vCenter Server
.PARAMETER Insecure
Flag to disable SSL Verification checking, useful for lab environments
.EXAMPLE
New-XVCMSite -SiteName "SiteA" -VCHostname "vcenter65-1.primp-industries.com" -VCUsername "administrator@vsphere.local" -VCPassword "VMware1!" -Insecure
#>
param(
[Parameter(Mandatory=$true)][String]$SiteName,
[Parameter(Mandatory=$true)][String]$VCHostname,
[Parameter(Mandatory=$true)][String]$VCUsername,
[Parameter(Mandatory=$true)][String]$VCPassword,
[Parameter(Mandatory=$false)][Switch]$Insecure
)
$Uri = "http://localhost:8080/api/sites"
$insecureFlag = $false
if($Insecure) {
$insecureFlag = $true
}
$body = @{
"sitename"=$SiteName;
"hostname"=$VCHostname;
"username"=$VCUsername;
"password"=$VCPassword;
"insecure"=$insecureFlag;
}
$body = $body | ConvertTo-Json
Write-Host -ForegroundColor Cyan "Registering vCenter Server $VCHostname as $SiteName ..."
$results = Invoke-WebRequest -Uri $Uri -Method POST -Body $body -ContentType "application/json"
if($results.StatusCode -eq 200) {
Write-Host -ForegroundColor Green "Successfully registered $SiteName"
} else { Write-Host -ForegroundColor Red "Failed to register $SiteName" }
}
Function Remove-XVCMSite {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function removes vCenter Server endpoint
.PARAMETER SiteName
The name of the registered vCenter Server to remove
.EXAMPLE
Remove-XVCMSite -SiteName "SiteA"
#>
param(
[Parameter(Mandatory=$true)][String]$SiteName
)
$Uri = "http://localhost:8080/api/sites/$SiteName"
Write-Host -ForegroundColor Cyan "Deleting vCenter Server Site Registerion $SiteName ..."
$results = Invoke-WebRequest -Uri $Uri -Method DELETE
if($results.StatusCode -eq 200) {
Write-Host -ForegroundColor Green "Successfully deleted $SiteName"
} else { Write-Host -ForegroundColor Red "Failed to deleted $SiteName" }
}
Function New-XVCMRequest {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function initiates a migration request
.PARAMETER SrcSite
The name of the source vCenter Server
.PARAMETER DstSite
The name of the destination vCenter Server
.PARAMETER SrcDatacenter
The name of the source vSphere Datacenter
.PARAMETER DstDatacenter
The name of the destination vSphere Datacenter
.PARAMETER SrcCluster
The name of the source vSphere Cluster
.PARAMETER DstCluster
The name of the destination vSphere Cluster
.PARAMETER DstDatastore
The name of the destination Datastore
.PARAMETER srcVMs
List of VMs to migrate
.PARAMETER NetworkMapping
Hash table of the VM network mappings between your source and destination vCenter Server
.EXAMPLE
New-XVCMRequest -SrcSite SiteA -DstSite SiteB `
-SrcDatacenter Datacenter-SiteA -DstDatacenter Datacenter-SiteB `
-SrcCluster Palo-Alto -DstCluster Santa-Barbara `
-DstDatastore vsanDatastore `
-srcVMs @("PhotonOS-01","PhotonOS-02","PhotonOS-03","PhotonOS-04") `
-NetworkMapping @{"DVPG-VM Network 1"="DVPG-Internal Network";"DVPG-VM Network 2"="DVPG-External Network"}
#>
param(
[Parameter(Mandatory=$true)][String]$SrcSite,
[Parameter(Mandatory=$true)][String]$DstSite,
[Parameter(Mandatory=$true)][String]$SrcDatacenter,
[Parameter(Mandatory=$true)][String]$DstDatacenter,
[Parameter(Mandatory=$true)][String]$SrcCluster,
[Parameter(Mandatory=$true)][String]$DstCluster,
[Parameter(Mandatory=$true)][String]$DstDatastore,
[Parameter(Mandatory=$true)][String[]]$srcVMs,
[Parameter(Mandatory=$true)][Hashtable]$NetworkMapping
)
$Uri = "http://localhost:8080/api/tasks"
$body = @{
"sourceSite"=$SrcSite;
"targetSite"=$DstSite;
"sourceDatacenter"=$SrcDatacenter;
"targetDatacenter"=$dstDatacenter;
"sourceCluster"=$SrcCluster;
"targetCluster"=$DstCluster;
"targetDatastore"=$DstDatastore;
"networkMap"=$NetworkMapping;
"vmList"=$srcVMs;
}
$body = $body | ConvertTo-Json
Write-Host -ForegroundColor Cyan "Initiating migration request ..."
$results = Invoke-WebRequest -Uri $Uri -Method POST -Body $body -ContentType "application/json"
if($results.StatusCode -eq 200) {
$taskId = ($results.Content | ConvertFrom-Json).requestId
Write-Host -ForegroundColor Green "Successfully issued migration with TaskID: $taskId"
} else { Write-Host -ForegroundColor Red "Failed to initiate migration request" }
}
Function Get-XVCMTask {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function retrieves either all migration tasks and/or a specific migration task
.PARAMETER Id
The task ID returned from initiating a migration
.EXAMPLE
Get-XVCMTask -Id <Task ID>
#>
param(
[Parameter(Mandatory=$false)][String]$Id
)
$Uri = "http://localhost:8080/api/tasks"
if($Id) {
$body = @{"requestId"=$Id}
$results = Invoke-WebRequest -Uri $Uri -Method GET -Body $body -ContentType "application/json"
} else {
$results = Invoke-WebRequest -Uri $Uri -Method GET
}
if($results.StatusCode -eq 200) {
$results.Content | ConvertFrom-Json
} else { Write-Host -ForegroundColor Red "Failed to retrieve tasks" }
}
Function Get-VMNetwork {
<#
.NOTES
===========================================================================
Created by: William Lam
Organization: VMware
Blog: www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.DESCRIPTION
This function returns the list of all VM Networks attached to
given VMs to help with initiating migration
.PARAMETER srcVMs
List of VMs to query their current VM Networks
.EXAMPLE
Get-VMNetwork -srcVMs @("PhotonOS-01","PhotonOS-02","PhotonOS-03","PhotonOS-04")
#>
param(
[Parameter(Mandatory=$false)][String[]]$srcVMs
)
if (-not $global:DefaultVIServers) { Write-Host -ForegroundColor red "No vCenter Server Connection found, please connect to your source vCenter Server using Connect-VIServer"; break }
$results = @()
if($srcVMs) {
foreach ($srcVM in $srcVMs) {
$vm = Get-VM -Name $srcVM
$networkDetails = $vm | Get-NetworkAdapter
$tmp = [pscustomobject] @{
Name = $srcVM;
Adapter = $networkDetails.name;
Network = $networkDetails.NetworkName;
}
$results+=$tmp
}
} else {
foreach ($vm in Get-VM) {
$networkDetails = $vm | Get-NetworkAdapter
$tmp = [pscustomobject] @{
Name = $vm.Name;
Adapter = $networkDetails.name;
Network = $networkDetails.NetworkName;
}
$results+=$tmp
}
}
$results
}

View File

@@ -0,0 +1,245 @@
<#
.SYNOPSIS Datastore Functions
.DESCRIPTION A collection of functions to manipulate datastore Mount + Attach status
.EXAMPLE Get-Datastore | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize
.EXAMPLE Get-Datastore IX2ISCSI01 | Unmount-Datastore
.EXAMPLE Get-Datastore IX2ISCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize
.EXAMPLE Get-Datastore IX2iSCSI01 | Mount-Datastore
.EXAMPLE Get-Datastore IX2iSCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize
.EXAMPLE Get-Datastore IX2iSCSI01 | Detach-Datastore
.EXAMPLE Get-Datastore IX2iSCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize
.EXAMPLE Get-Datastore IX2iSCSI01 | Attach-datastore
.EXAMPLE Get-Datastore IX2iSCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize
.NOTES Written by Alan Renouf, originally published at https://blogs.vmware.com/vsphere/2012/01/automating-datastore-storage-device-detachment-in-vsphere-5.html
.NOTES May 2017: Modified by Jason Coleman (virtuallyjason.blogspot.com), to improve performance when dealing with a large number of hosts and datastores
#>
Function Get-HostViews {
[CmdletBinding()]
Param (
$Datastore
)
Begin{
$allDatastores = @()
}
Process {
$allDatastores += $Datastore
}
End {
#Build the array of Datastore Objects
if (-not $Datastore) {
$allDatastores = Get-Datastore
}
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
if (-not $allDatastores){
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
}
$allHosts = @()
$DShostsKeys = $allDatastores.extensiondata.host.key.value | sort | get-unique -asstring
$DShosts = foreach ($thisKey in $DShostsKeys) {($allDatastores.extensiondata.host | ? {$_.key.value -eq $thisKey})[0]}
$i = 1
foreach ($DSHost in $DSHosts){
write-progress -activity "Collecting ESXi Host Views" -status "Querying $($dshost.key)..." -percentComplete ($i++/$DSHosts.count*100)
$hostObj = "" | select keyValue,hostView,storageSys
$hostObj.hostView = get-view $DSHost.key
$hostObj.keyValue = $DSHost.key.value
$hostObj.storageSys = Get-View $hostObj.hostView.ConfigManager.StorageSystem
$allHosts += $hostObj
}
write-progress -activity "Collecting ESXi Host Views" -completed
$allHosts
}
}
Function Get-DatastoreMountInfo {
[CmdletBinding()]
Param (
[Parameter(ValueFromPipeline=$true)]
$Datastore
)
#Roll back up an unrolled array from a pipeline
Begin{
$allDatastores = @()
}
Process {
$allDatastores += $Datastore
}
End {
$AllInfo = @()
#Build the array of Datastore Objects
if (-not $Datastore) {
$allDatastores = Get-Datastore
}
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
if (-not $allDatastores){
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
}
$allDatastoreNAAs = foreach ($ds in $allDatastores) {$ds.ExtensionData.Info.vmfs.extent[0].diskname}
#Build the array of custom Host Objects
$allHosts = Get-HostViews -datastore $allDatastores
$output = @()
$i = 1
foreach ($dsHost in $allHosts){
write-progress -activity "Checking Datastore access" -status "Checking $($dshost.hostview.name)..." -percentComplete ($i++ / $allHosts.count * 100)
#Get all devices on the host that match the list of $allDatastoreNAAs
$devices = $dsHost.storagesys.StorageDeviceInfo.ScsiLun
foreach ($device in $devices){
if ($allDatastoreNAAs -contains $device.canonicalName){
#Record information about this device/host combo
$thisDatastore = $alldatastores | ? {$_.ExtensionData.Info.vmfs.extent[0].diskname -eq $device.canonicalName}
$hostviewDSAttachState = ""
if ($device.operationalState[0] -eq "ok") {
$hostviewDSAttachState = "Attached"
} elseif ($device.operationalState[0] -eq "off") {
$hostviewDSAttachState = "Detached"
} else {
$hostviewDSAttachState = $device.operationalstate[0]
}
$Info = "" | Select Datastore, VMHost, Lun, Mounted, State
$Info.VMHost = $dsHost.hostview.name
$Info.Datastore = $thisDatastore.name
$Info.Lun = $device.canonicalName
$Info.mounted = ($thisDatastore.extensiondata.host | ? {$_.key.value -eq $dshost.keyvalue}).mountinfo.mounted
$Info.state = $hostviewDSAttachState
$output += $info
}
}
}
write-progress -activity "Checking Datastore access" -completed
$output
}
}
Function Detach-Datastore {
[CmdletBinding()]
Param (
[Parameter(ValueFromPipeline=$true)]
$Datastore
)
Begin{
$allDatastores = @()
}
Process {
$allDatastores += $Datastore
}
End {
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
if (-not $allDatastores){
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
}
$allDatastoreNAAs = foreach ($ds in $allDatastores) {$ds.ExtensionData.Info.vmfs.extent[0].diskname}
$allHosts = Get-HostViews -datastore $allDatastores
$j = 1
foreach ($dsHost in $allHosts){
#Get all devices on the host that match the list of $allDatastoreNAAs
write-progress -id 1 -activity "Detaching Datastores" -status "Removing device(s) from $($dsHost.hostview.name)" -percentComplete ($j++ / $allHosts.count * 100)
$devices = $dsHost.storagesys.StorageDeviceInfo.ScsiLun | ? {$allDatastoreNAAs -contains $_.canonicalName}
$i = 1
foreach ($device in $devices){
write-progress -parentid 1 -activity "Detaching Datastores" -status "Removing device: $(($allDatastores | ? {$_.ExtensionData.Info.vmfs.extent[0].diskname -eq $device.canonicalName}).name)" -percentComplete ($i++ / $allDatastoreNAAs.count * 100)
$LunUUID = $Device.Uuid
$dsHost.storageSys.DetachScsiLun($LunUUID);
}
}
write-progress -activity "Detaching Datastores" -completed
}
}
Function Attach-Datastore {
[CmdletBinding()]
Param (
[Parameter(ValueFromPipeline=$true)]
$Datastore
)
Begin{
$allDatastores = @()
}
Process {
$allDatastores += $Datastore
}
End {
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
if (-not $allDatastores){
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
}
$allDatastoreNAAs = foreach ($ds in $allDatastores) {$ds.ExtensionData.Info.vmfs.extent[0].diskname}
$allHosts = Get-HostViews -datastore $allDatastores
$j = 1
foreach ($dsHost in $allHosts){
#Get all devices on the host that match the list of $allDatastoreNAAs
write-progress -id 1 -activity "Attaching Datastores" -status "Attaching devices to $($dsHost.hostview.name)" -percentComplete ($j++ / $allHosts.count * 100)
$devices = $dsHost.storagesys.StorageDeviceInfo.ScsiLun
$i = 1
foreach ($device in $devices){
write-progress -parentid 1 -activity "Attaching Datastores" -status "Attaching device: $($Device.Uuid)" -percentComplete ($i++ / $devices.count * 100)
if ($allDatastoreNAAs -contains $device.canonicalName){
$LunUUID = $Device.Uuid
$dsHost.storageSys.AttachScsiLun($LunUUID);
}
}
}
write-progress -activity "Attaching Datastores" -completed
}
}
Function Unmount-Datastore {
[CmdletBinding()]
Param (
[Parameter(ValueFromPipeline=$true)]
$Datastore
)
Begin{
$allDatastores = @()
}
Process {
$allDatastores += $Datastore
}
End {
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
if (-not $allDatastores){
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
}
$allHosts = Get-HostViews -datastore $allDatastores
$j = 1
foreach ($dsHost in $allHosts){
write-progress -id 1 -activity "Unmounting Datastores" -status "Unmounting devices from $($dsHost.hostview.name)" -percentComplete ($j++ / $allHosts.count * 100)
$i = 1
foreach ($ds in $allDatastores){
write-progress -parentid 1 -activity "Unmounting Datastores" -status "Unmounting device: $($ds.name)" -percentComplete ($i++ / $allDatastores.count * 100)
$dsHost.storageSys.UnmountVmfsVolume($DS.ExtensionData.Info.vmfs.uuid);
}
}
write-progress -activity "Unmounting Datastores" -completed
}
}
Function Mount-Datastore {
[CmdletBinding()]
Param (
[Parameter(ValueFromPipeline=$true)]
$Datastore
)
Begin{
$allDatastores = @()
}
Process {
$allDatastores += $Datastore
}
End {
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
if (-not $allDatastores){
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
}
$allHosts = Get-HostViews -datastore $allDatastores
$j = 0
foreach ($dsHost in $allHosts){
write-progress -activity "Mounting Datastores" -status "Mounting devices to $($dsHost.hostview.name)" -percentComplete ($j++ / $allHosts.count * 100)
$i = 1
foreach ($ds in $allDatastores){
write-progress -activity "Mounting Datastores" -status "Mounting device: $($DS.ExtensionData.Info.vmfs.uuid)" -percentComplete ($i++ / $allDatastores.count * 100)
$dsHost.storageSys.MountVmfsVolume($DS.ExtensionData.Info.vmfs.uuid);
}
}
write-progress -activity "Mounting Datastores" -completed
}
}

18
Modules/NSXT/NSXT.psd1 Normal file
View File

@@ -0,0 +1,18 @@
@{
ModuleToProcess = 'NSXT.psm1'
ModuleVersion = '1.0.0.0'
GUID = 'c72f4e3d-5d1d-498f-ba86-6fa03e4ae6dd'
Author = 'William Lam'
CompanyName = 'primp-industries.com'
Copyright = '(c) 2017. All rights reserved.'
Description = 'Powershell Module for NSX-T REST API Functions'
PowerShellVersion = '5.0'
FunctionsToExport = 'Get-NSXTComputeManager','Get-NSXTFabricNode','Get-NSXTFirewallRule','Get-NSXTIPPool','Get-NSXTLogicalSwitch','Get-NSXTManager','Get-NSXTTransportZone','Get-NSXTController'
PrivateData = @{
PSData = @{
Tags = @('NSX-T','REST')
LicenseUri = 'https://www.tldrlegal.com/l/mit'
ProjectUri = 'https://github.com/lamw/PowerCLI-Example-Scripts/tree/master/Modules/NSXT'
}
}
}

260
Modules/NSXT/NSXT.psm1 Normal file
View File

@@ -0,0 +1,260 @@
Function Get-NSXTController {
Param (
[parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id
)
$clusterNodeService = Get-NsxtService -Name "com.vmware.nsx.cluster.nodes"
$clusterNodeStatusService = Get-NsxtService -Name "com.vmware.nsx.cluster.nodes.status"
if($Id) {
$nodes = $clusterNodeService.get($Id)
} else {
$nodes = $clusterNodeService.list().results | where { $_.manager_role -eq $null }
}
$results = @()
foreach ($node in $nodes) {
$nodeId = $node.id
$nodeName = $node.controller_role.control_plane_listen_addr.ip_address
$nodeStatusResults = $clusterNodeStatusService.get($nodeId)
$tmp = [pscustomobject] @{
Id = $nodeId;
Name = $nodeName;
ClusterStatus = $nodeStatusResults.control_cluster_status.control_cluster_status;
Version = $nodeStatusResults.version;
}
$results+=$tmp
}
$results
}
Function Get-NSXTFabricNode {
Param (
[parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id,
[Switch]$ESXi,
[Switch]$Edge
)
$fabricNodeService = Get-NsxtService -Name "com.vmware.nsx.fabric.nodes"
$fabricNodeStatusService = Get-NsxtService -Name "com.vmware.nsx.fabric.nodes.status"
if($Id) {
$nodes = $fabricNodeService.get($Id)
} else {
if($ESXi) {
$nodes = $fabricNodeService.list().results | where { $_.resource_type -eq "HostNode" }
} elseif ($Edge) {
$nodes = $fabricNodeService.list().results | where { $_.resource_type -eq "EdgeNode" }
} else {
$nodes = $fabricNodeService.list().results
}
}
$results = @()
foreach ($node in $nodes) {
$nodeStatusResult = $fabricNodeStatusService.get($node.id)
$tmp = [pscustomobject] @{
Id = $node.id;
Name = $node.display_name;
Type = $node.resource_type;
Address = $node.ip_addresses;
NSXVersion = $nodeStatusResult.software_version
OS = $node.os_type;
Version = $node.os_version;
Status = $nodeStatusResult.host_node_deployment_status
ManagerStatus = $nodeStatusResult.mpa_connectivity_status
ControllerStatus = $nodeStatusResult.lcp_connectivity_status
}
$results+=$tmp
}
$results
}
Function Get-NSXTIPPool {
Param (
[parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id
)
$ipPoolService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_pools"
if($Id) {
$ipPools = $ipPoolService.get($Id)
} else {
$ipPools = $ipPoolService.list().results
}
$results = @()
foreach ($ipPool in $ipPools) {
$tmp = [pscustomobject] @{
Id = $ipPool.Id;
Name = $ipPool.Display_Name;
Total = $ipPool.pool_usage.total_ids;
Free = $ipPool.pool_usage.free_ids;
Network = $ipPool.subnets.cidr;
Gateway = $ipPool.subnets.gateway_ip;
DNS = $ipPool.subnets.dns_nameservers;
RangeStart = $ipPool.subnets.allocation_ranges.start;
RangeEnd = $ipPool.subnets.allocation_ranges.end
}
$results+=$tmp
}
$results
}
Function Get-NSXTTransportZone {
Param (
[parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id
)
$transportZoneService = Get-NsxtService -Name "com.vmware.nsx.transport_zones"
if($Id) {
$transportZones = $transportZoneService.get($Id)
} else {
$transportZones = $transportZoneService.list().results
}
$results = @()
foreach ($transportZone in $transportZones) {
$tmp = [pscustomobject] @{
Id = $transportZone.Id;
Name = $transportZone.display_name;
Type = $transportZone.transport_type;
HostSwitchName = $transportZone.host_switch_name;
}
$results+=$tmp
}
$results
}
Function Get-NSXTComputeManager {
Param (
[parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id
)
$computeManagerSerivce = Get-NsxtService -Name "com.vmware.nsx.fabric.compute_managers"
$computeManagerStatusService = Get-NsxtService -Name "com.vmware.nsx.fabric.compute_managers.status"
if($Id) {
$computeManagers = $computeManagerSerivce.get($id)
} else {
$computeManagers = $computeManagerSerivce.list().results
}
$results = @()
foreach ($computeManager in $computeManagers) {
$computeManagerStatus = $computeManagerStatusService.get($computeManager.Id)
$tmp = [pscustomobject] @{
Id = $computeManager.Id;
Name = $computeManager.display_name;
Server = $computeManager.server
Type = $computeManager.origin_type;
Version = $computeManagerStatus.Version;
Registration = $computeManagerStatus.registration_status;
Connection = $computeManagerStatus.connection_status;
}
$results+=$tmp
}
$results
}
Function Get-NSXTLogicalSwitch {
Param (
[parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id
)
$logicalSwitchService = Get-NsxtService -Name "com.vmware.nsx.logical_switches"
$logicalSwitchSummaryService = Get-NsxtService -Name "com.vmware.nsx.logical_switches.summary"
if($Id) {
$logicalSwitches = $logicalSwitchService.get($Id)
} else {
$logicalSwitches = $logicalSwitchService.list().results
}
$results = @()
foreach ($logicalSwitch in $logicalSwitches) {
$transportZone = (Get-NSXTTransportZone -Id $logicalSwitch.transport_zone_id | Select Name | ft -HideTableHeaders | Out-String).trim()
$ports = $logicalSwitchSummaryService.get($logicalSwitch.id).num_logical_ports
$tmp = [pscustomobject] @{
Id = $logicalSwitch.Id;
Name = $logicalSwitch.display_name;
VLAN = $logicalSwitch.vlan;
AdminStatus = $logicalSwitch.admin_state;
Ports = $ports;
TransportZone = $transportZone;
}
$results+=$tmp
}
$results
}
Function Get-NSXTFirewallRule {
Param (
[parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id
)
$firewallService = Get-NsxtService -Name "com.vmware.nsx.firewall.sections"
$firewallRuleService = Get-NsxtService -Name "com.vmware.nsx.firewall.sections.rules"
if($Id) {
$firewallRuleSections = $firewallService.get($Id)
} else {
$firewallRuleSections = $firewallService.list().results
}
$sectionResults = @()
foreach ($firewallRuleSection in $firewallRuleSections) {
$tmp = [pscustomobject] @{
Id = $firewallRuleSection.Id;
Name = $firewallRuleSection.display_name;
Type = $firewallRuleSection.section_type;
Stateful = $firewallRuleSection.stateful;
RuleCount = $firewallRuleSection.rule_count;
}
$sectionResults+=$tmp
}
$sectionResults
$firewallResults = @()
if($id) {
$firewallRules = $firewallRuleService.list($id).results
foreach ($firewallRule in $firewallRules) {
$tmp = [pscustomobject] @{
Id = $firewallRule.id;
Name = $firewallRule.display_name;
Sources = if($firewallRule.sources -eq $null) { "ANY" } else { $firewallRule.sources};
Destination = if($firewallRule.destinations -eq $null) { "ANY" } else { $firewallRule.destinations };
Services = if($firewallRule.services -eq $null) { "ANY" } else { $firewallRule.services } ;
Action = $firewallRule.action;
AppliedTo = if($firewallRule.applied_tos -eq $null) { "ANY" } else { $firewallRule.applied_tos };
Log = $firewallRule.logged;
}
$firewallResults+=$tmp
}
}
$firewallResults
}
Function Get-NSXTManager {
$clusterNodeService = Get-NsxtService -Name "com.vmware.nsx.cluster.nodes"
$nodes = $clusterNodeService.list().results
$results = @()
foreach ($node in $nodes) {
if($node.manager_role -ne $null) {
$tmp = [pscustomobject] @{
Id = $node.id;
Name = $node.display_name;
Address = $node.appliance_mgmt_listen_addr;
SHA256Thumbprint = $node.manager_role.api_listen_addr.certificate_sha256_thumbprint;
}
$results+=$tmp
}
}
$results
}

1
Modules/SRM/.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
*.psd1 diff

1
Modules/SRM/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.zip

View File

@@ -0,0 +1,167 @@
# Depends on SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
# It is assumed that the connection to VC and SRM Server have already been made
Function Get-SrmConfigReportSite {
Param(
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
Get-SrmServer $SrmServer |
Format-Table -Wrap -AutoSize @{Label="SRM Site Name"; Expression={$_.ExtensionData.GetSiteName()} },
@{Label="SRM Host"; Expression={$_.Name} },
@{Label="SRM Port"; Expression={$_.Port} },
@{Label="Version"; Expression={$_.Version} },
@{Label="Build"; Expression={$_.Build} },
@{Label="SRM Peer Site Name"; Expression={$_.ExtensionData.GetPairedSite().Name} }
}
Function Get-SrmConfigReportPlan {
Param(
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
Get-SrmRecoveryPlan -SrmServer $SrmServer | %{
$rp = $_
$rpinfo = $rp.GetInfo()
$peerState = $rp.GetPeer().State
$pgs = Get-SrmProtectionGroup -RecoveryPlan $rp
$pgnames = $pgs | %{ $_.GetInfo().Name }
$output = "" | select plan, state, peerState, groups
$output.plan = $rpinfo.Name
$output.state = $rpinfo.State
$output.peerState = $peerState
if ($pgnames) {
$output.groups = [string]::Join(",`r`n", $pgnames)
} else {
$output.groups = "NONE"
}
$output
} | Format-Table -Wrap -AutoSize @{Label="Recovery Plan Name"; Expression={$_.plan} },
@{Label="Recovery State"; Expression={$_.state} },
@{Label="Peer Recovery State"; Expression={$_.peerState} },
@{Label="Protection Groups"; Expression={$_.groups}}
}
Function Get-SrmConfigReportProtectionGroup {
Param(
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
Get-SrmProtectionGroup -SrmServer $SrmServer | %{
$pg = $_
$pginfo = $pg.GetInfo()
$pgstate = $pg.GetProtectionState()
$peerState = $pg.GetPeer().State
$rps = Get-SrmRecoveryPlan -ProtectionGroup $pg
$rpnames = $rps | %{ $_.GetInfo().Name }
$output = "" | select name, type, state, peerState, plans
$output.name = $pginfo.Name
$output.type = $pginfo.Type
$output.state = $pgstate
$output.peerState = $peerState
if ($rpnames) {
$output.plans = [string]::Join(",`r`n", $rpnames)
} else {
$output.plans = "NONE"
}
$output
} | Format-Table -Wrap -AutoSize @{Label="Protection Group Name"; Expression={$_.name} },
@{Label="Type"; Expression={$_.type} },
@{Label="Protection State"; Expression={$_.state} },
@{Label="Peer Protection State"; Expression={$_.peerState} },
@{Label="Recovery Plans"; Expression={$_.plans} }
}
Function Get-SrmConfigReportProtectedDatastore {
Param(
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
Get-SrmProtectionGroup -SrmServer $SrmServer -Type "san" | %{
$pg = $_
$pginfo = $pg.GetInfo()
$pds = Get-SrmProtectedDatastore -ProtectionGroup $pg
$pds | %{
$pd = $_
$output = "" | select datacenter, group, name, capacity, free
$output.datacenter = $pd.Datacenter.Name
$output.group = $pginfo.Name
$output.name = $pd.Name
$output.capacity = $pd.CapacityGB
$output.free = $pd.FreeSpaceGB
$output
}
} | Format-Table -Wrap -AutoSize -GroupBy "datacenter" @{Label="Datastore Name"; Expression={$_.name} },
@{Label="Capacity GB"; Expression={$_.capacity} },
@{Label="Free GB"; Expression={$_.free} },
@{Label="Protection Group"; Expression={$_.group} }
}
Function Get-SrmConfigReportProtectedVm {
Param(
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$srmversion = Get-SrmServerVersion -SrmServer $SrmServer
$srmMajorVersion, $srmMinorVersion = $srmversion -split "\."
Get-SrmProtectionGroup -SrmServer $SrmServer | %{
$pg = $_
$pginfo = $pg.GetInfo()
$pvms = Get-SrmProtectedVM -ProtectionGroup $pg
$rps = Get-SrmRecoveryPlan -ProtectionGroup $pg
$rpnames = $rps | %{ $_.GetInfo().Name }
$pvms | %{
$pvm = $_
if ($srmMajorVersion -ge 6 -or ($srmMajorVersion -eq 5 -and $srmMinorVersion -eq 8)) {
$rs = $rps | Select -First 1 | %{ $_.GetRecoverySettings($pvm.Vm.MoRef) }
}
$output = "" | select group, name, moRef, needsConfiguration, state, plans, priority, finalPowerState, preCallouts, postCallouts
$output.group = $pginfo.Name
$output.name = $pvm.Vm.Name
$output.moRef = $pvm.Vm.MoRef # this is necessary in case we can't retrieve the name when VC is unavailable
$output.needsConfiguration = $pvm.NeedsConfiguration
$output.state = $pvm.State
$output.plans = [string]::Join(",`r`n", $rpnames)
if ($rs) {
$output.priority = $rs.RecoveryPriority
$output.finalPowerState = $rs.FinalPowerState
$output.preCallouts = $rs.PrePowerOnCallouts.Count
$output.postCallouts = $rs.PostPowerOnCallouts.Count
}
$output
}
} | Format-Table -Wrap -AutoSize @{Label="VM Name"; Expression={$_.name} },
@{Label="VM MoRef"; Expression={$_.moRef} },
@{Label="Needs Config"; Expression={$_.needsConfiguration} },
@{Label="VM Protection State"; Expression={$_.state} },
@{Label="Protection Group"; Expression={$_.group} },
@{Label="Recovery Plans"; Expression={$_.plans} },
@{Label="Recovery Priority"; Expression={$_.priority} },
@{Label="Final Power State"; Expression={$_.finalPowerState} },
@{Label="Pre-PowerOn Callouts"; Expression={$_.preCallouts} },
@{Label="Post-PowerOn Callouts"; Expression={$_.postCallouts} }
}
Function Get-SrmConfigReport {
Param(
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
Get-SrmConfigReportSite -SrmServer $SrmServer
Get-SrmConfigReportPlan -SrmServer $SrmServer
Get-SrmConfigReportProtectionGroup -SrmServer $SrmServer
Get-SrmConfigReportProtectedDatastore -SrmServer $SrmServer
Get-SrmConfigReportProtectedVm -SrmServer $SrmServer
}

View File

@@ -0,0 +1,34 @@
# Depends on SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
# It is assumed that the connections to active VC and SRM Server have already been made
Import-Module Meadowcroft.SRM -Prefix Srm
$TagCategoryName = 'Meadowcroft.SRM.VM'
$TagCategoryDescription = 'Tag category for tagging VMs with SRM state'
# If the tag category doesn't exist, create it and the relevant tags
$TagCategory = Get-TagCategory -Name $TagCategoryName -ErrorAction SilentlyContinue
if (-Not $TagCategory) {
Write-Output "Creating Tag Category $TagCategoryName"
$TagCategory = New-TagCategory -Name $TagCategoryName -Description $TagCategoryDescription -EntityType 'VirtualMachine'
Write-Output "Creating Tag SrmProtectedVm"
New-Tag -Name 'SrmProtectedVm' -Category $TagCategory -Description "VM protected by VMware SRM"
Write-Output "Creating Tag SrmTestVm"
New-Tag -Name 'SrmTestVm' -Category $TagCategory -Description "Test VM instantiated by VMware SRM"
Write-Output "Creating Tag SrmPlaceholderVm"
New-Tag -Name 'SrmPlaceholderVm' -Category $TagCategory -Description "Placeholder VM used by VMware SRM"
}
$protectedVmTag = Get-Tag -Name 'SrmProtectedVm' -Category $TagCategory
$testVmTag = Get-Tag -Name 'SrmTestVm' -Category $TagCategory
$placeholderVmTag = Get-Tag -Name 'SrmPlaceholderVm' -Category $TagCategory
# Assign protected tag to a VM, use ready state to get "local" protected VMs
Get-SrmProtectedVM -State Ready | %{ New-TagAssignment -Tag $protectedVmTag -Entity $(Get-VIObjectByVIView $_.Vm) | Out-Null }
# Assign test tag to a VM
Get-SrmTestVM | %{ New-TagAssignment -Tag $testVmTag -Entity $_ | Out-Null }
# Assign placeholder tag to a VM
Get-SrmPlaceholderVM | %{ New-TagAssignment -Tag $placeholderVmTag -Entity $_ | Out-Null }

74
Modules/SRM/LICENSE.txt Normal file
View File

@@ -0,0 +1,74 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,422 @@
# SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
<#
.SYNOPSIS
Get the subset of protection groups matching the input criteria
.PARAMETER Name
Return protection groups matching the specified name
.PARAMETER Type
Return protection groups matching the specified protection group
type. For SRM 5.0-5.5 this is either 'san' for protection groups
consisting of a set of replicated datastores or 'vr' for vSphere
Replication based protection groups.
.PARAMETER RecoveryPlan
Return protection groups associated with a particular recovery
plan
.PARAMETER SrmServer
the SRM server to use for this operation.
#>
Function Get-ProtectionGroup {
[cmdletbinding()]
Param(
[Parameter(position=1)][string] $Name,
[string] $Type,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan[]] $RecoveryPlan,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
begin {
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
$pgs = @()
}
process {
if ($RecoveryPlan) {
foreach ($rp in $RecoveryPlan) {
$pgs += $RecoveryPlan.GetInfo().ProtectionGroups
}
$pgs = Select_UniqueByMoRef($pgs)
} else {
$pgs += $api.Protection.ListProtectionGroups()
}
}
end {
$pgs | ForEach-Object {
$pg = $_
$pgi = $pg.GetInfo()
$selected = (-not $Name -or ($Name -eq $pgi.Name)) -and (-not $Type -or ($Type -eq $pgi.Type))
if ($selected) {
Add-Member -InputObject $pg -MemberType NoteProperty -Name "Name" -Value $pgi.Name
$pg
}
}
}
}
<#
.SYNOPSIS
Get the subset of protected VMs matching the input criteria
.PARAMETER Name
Return protected VMs matching the specified name
.PARAMETER State
Return protected VMs matching the specified state. For protected
VMs on the protected site this is usually 'ready', for
placeholder VMs this is 'shadowing'
.PARAMETER ProtectionGroup
Return protected VMs associated with particular protection
groups
#>
Function Get-ProtectedVM {
[cmdletbinding()]
Param(
[Parameter(position=1)][string] $Name,
[VMware.VimAutomation.Srm.Views.SrmProtectionGroupProtectionState] $State,
[VMware.VimAutomation.Srm.Views.SrmProtectionGroupProtectionState] $PeerState,
[switch] $ConfiguredOnly,
[switch] $UnconfiguredOnly,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup[]] $ProtectionGroup,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan[]] $RecoveryPlan,
[string] $ProtectionGroupName,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
if ($null -eq $ProtectionGroup) {
$ProtectionGroup = Get-ProtectionGroup -Name $ProtectionGroupName -RecoveryPlan $RecoveryPlan -SrmServer $SrmServer
}
$ProtectionGroup | ForEach-Object {
$pg = $_
$pg.ListProtectedVms() | ForEach-Object {
# try and update the view data for the protected VM
try {
$_.Vm.UpdateViewData()
} catch {
Write-Error $_
} finally {
$_
}
} | Where-object { -not $Name -or ($Name -eq $_.Vm.Name) } |
where-object { -not $State -or ($State -eq $_.State) } |
where-object { -not $PeerState -or ($PeerState -eq $_.PeerState) } |
where-object { ($ConfiguredOnly -and $_.NeedsConfiguration -eq $false) -or ($UnconfiguredOnly -and $_.NeedsConfiguration -eq $true) -or (-not $ConfiguredOnly -and -not $UnconfiguredOnly) }
}
}
<#
.SYNOPSIS
Get the unprotected VMs that are associated with a protection group
.PARAMETER ProtectionGroup
Return unprotected VMs associated with particular protection
groups. For VR protection groups this is VMs that are associated
with the PG but not configured, For ABR protection groups this is
VMs on replicated datastores associated with the group that are not
configured.
#>
Function Get-UnProtectedVM {
[cmdletbinding()]
Param(
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup[]] $ProtectionGroup,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan[]] $RecoveryPlan,
[string] $ProtectionGroupName,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
if ($null -eq $ProtectionGroup) {
$ProtectionGroup = Get-ProtectionGroup -Name $ProtectionGroupName -RecoveryPlan $RecoveryPlan -SrmServer $SrmServer
}
$associatedVMs = @()
$protectedVmRefs = @()
$ProtectionGroup | ForEach-Object {
$pg = $_
# For VR listAssociatedVms to get list of VMs
if ($pg.GetInfo().Type -eq 'vr') {
$associatedVMs += @($pg.ListAssociatedVms() | Get-VIObjectByVIView)
}
# TODO test this: For ABR get VMs on GetProtectedDatastore
if ($pg.GetInfo().Type -eq 'san') {
$pds = @(Get-ProtectedDatastore -ProtectionGroup $pg)
$pds | ForEach-Object {
$ds = Get-Datastore -id $_.MoRef
$associatedVMs += @(Get-VM -Datastore $ds)
}
}
# get protected VMs
$protectedVmRefs += @(Get-ProtectedVM -ProtectionGroup $pg | ForEach-Object { $_.Vm.MoRef } | Select-Object -Unique)
}
# get associated but unprotected VMs
$associatedVMs | Where-Object { $protectedVmRefs -notcontains $_.ExtensionData.MoRef }
}
#Untested as I don't have ABR setup in my lab yet
<#
.SYNOPSIS
Get the subset of protected Datastores matching the input criteria
.PARAMETER ProtectionGroup
Return protected datastores associated with particular protection
groups
#>
Function Get-ProtectedDatastore {
[cmdletbinding()]
Param(
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup[]] $ProtectionGroup,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan[]] $RecoveryPlan,
[string] $ProtectionGroupName,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
if (-not $ProtectionGroup) {
$ProtectionGroup = Get-ProtectionGroup -Name $ProtectionGroupName -RecoveryPlan $RecoveryPlan -SrmServer $SrmServer
}
$ProtectionGroup | ForEach-Object {
$pg = $_
if ($pg.GetInfo().Type -eq 'san') { # only supported for array based replication datastores
$pg.ListProtectedDatastores()
}
}
}
#Untested as I don't have ABR setup in my lab yet
<#
.SYNOPSIS
Get the replicated datastores that aren't associated with a protection group.
#>
Function Get-ReplicatedDatastore {
[cmdletbinding()]
Param(
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
$api.Protection.ListUnassignedReplicatedDatastores()
}
<#
.SYNOPSIS
Protect a VM using SRM
.PARAMETER ProtectionGroup
The protection group that this VM will belong to
.PARAMETER Vm
The virtual machine to protect
#>
Function Protect-VM {
[cmdletbinding()]
Param(
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup] $ProtectionGroup,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine] $Vm,
[Parameter (ValueFromPipeline=$true)][VMware.Vim.VirtualMachine] $VmView
)
$moRef = Get_MoRefFromVmObj -Vm $Vm -VmView $VmView
$pgi = $ProtectionGroup.GetInfo()
#TODO query protection status first
if ($moRef) {
if ($pgi.Type -eq 'vr') {
$ProtectionGroup.AssociateVms(@($moRef))
}
$protectionSpec = New-Object VMware.VimAutomation.Srm.Views.SrmProtectionGroupVmProtectionSpec
$protectionSpec.Vm = $moRef
$protectTask = $ProtectionGroup.ProtectVms($protectionSpec)
while(-not $protectTask.IsComplete()) { Start-Sleep -Seconds 1 }
$protectTask.GetResult()
} else {
throw "Can't protect the VM, no MoRef found."
}
}
<#
.SYNOPSIS
Unprotect a VM using SRM
.PARAMETER ProtectionGroup
The protection group that this VM will be removed from
.PARAMETER Vm
The virtual machine to unprotect
#>
Function Unprotect-VM {
[cmdletbinding()]
Param(
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup] $ProtectionGroup,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine] $Vm,
[Parameter (ValueFromPipeline=$true)][VMware.Vim.VirtualMachine] $VmView,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroupProtectedVm] $ProtectedVm
)
$moRef = Get_MoRefFromVmObj -Vm $Vm -VmView $VmView -ProtectedVm $ProtectedVm
$pgi = $ProtectionGroup.GetInfo()
$protectTask = $ProtectionGroup.UnprotectVms($moRef)
while(-not $protectTask.IsComplete()) { Start-Sleep -Seconds 1 }
if ($pgi.Type -eq 'vr') {
$ProtectionGroup.UnassociateVms(@($moRef))
}
$protectTask.GetResult()
}
<#
.SYNOPSIS
Get a protection group folder
.PARAMETER SrmServer
The SRM Server to query for the protection group folder
#>
Function Get-ProtectionGroupFolder {
[cmdletbinding()]
Param(
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
$folder = $api.Protection.GetProtectionGroupRootFolder()
return $folder
}
<#
.SYNOPSIS
Create a new protection group
.PARAMETER Name
The name of the protection group
.PARAMETER Description
Description of the protection group
.PARAMETER Folder
The protection group folder in which to create the new protection group
.PARAMETER ArrayReplication
Set if protection group is for replicating VMs using Array based replication
.PARAMETER vSphereReplication
Set if protection group is for replicating VMs with vSphere Replication
.PARAMETER VMs
For vSphere Replication based protection, the VMs to add to the replication
group. These should already be replicated.
.PARAMETER VMViews
For vSphere Replication based protection, the VMs to add to the replication
group. These should already be replicated.
.PARAMETER SrmServer
The SRM Server to perform the operation against
#>
Function New-ProtectionGroup {
[cmdletbinding(DefaultParameterSetName="VR", SupportsShouldProcess=$True, ConfirmImpact="Medium")]
[OutputType([VMware.VimAutomation.Srm.Views.SrmProtectionGroup])]
Param(
[Parameter (Mandatory=$true)] $Name,
$Description,
[VMware.VimAutomation.Srm.Views.SrmProtectionGroupFolder] $Folder,
[Parameter (ParameterSetName="ABR", Mandatory=$true)][switch] $ArrayReplication,
[Parameter (ValueFromPipeline=$true, ParameterSetName="ABR")][VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore[]] $Datastores,
[Parameter (ValueFromPipeline=$true, ParameterSetName="ABR")][VMware.Vim.Datastore[]] $DatastoreViews,
[Parameter (ParameterSetName="VR", Mandatory=$true)][switch] $vSphereReplication,
[Parameter (ValueFromPipeline=$true, ParameterSetName="VR")][VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]] $VMs,
[Parameter (ValueFromPipeline=$true, ParameterSetName="VR")][VMware.Vim.VirtualMachine[]] $VMViews,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$api = Get-ServerApiEndpoint $SrmServer
[VMware.VimAutomation.Srm.Views.SrmCreateProtectionGroupTask] $task = $null
#get root folder if this wasn't specified as a parameter
if(-not $Folder) {
$Folder = Get-ProtectionGroupFolder -SrmServer $SrmServer
}
if ($vSphereReplication) {
#create list of managed object references from VM and/or VM view arrays
[VMware.Vim.ManagedObjectReference[]]$moRefs = @()
foreach ($vm in $VMs) {
$moRefs += Get_MoRefFromVmObj -Vm $Vm
}
foreach ($VmView in $VMViews) {
$moRefs += Get_MoRefFromVmObj -VmView $VmView
}
if ($pscmdlet.ShouldProcess($Name, "New")) {
$task = $api.Protection.CreateHbrProtectionGroup($Folder.MoRef, $Name, $Description, $moRefs)
}
} elseif ($ArrayReplication) {
#create list of managed object references from VM and/or VM view arrays
$moRefs = @()
foreach ($ds in $Datastores) {
$moRefs += $ds.ExtensionData.MoRef
}
foreach ($DsView in $DatastoreViews) {
$moRefs += $DsView.MoRef
}
if ($pscmdlet.ShouldProcess($Name, "New")) {
$task = $api.Protection.CreateAbrProtectionGroup($Folder.MoRef, $Name, $Description, $moRefs)
}
} else {
throw "Undetermined protection group type"
}
# Complete task
while(-not $task.IsCreateProtectionGroupComplete()) { Start-Sleep -Seconds 1 }
# Retrieve the protection group, and protect associated VMs
$pg = $task.GetNewProtectionGroup()
if ($pg) {
$unProtectedVMs = Get-UnProtectedVM -ProtectionGroup $pg
$unProtectedVMs | Protect-VM -ProtectionGroup $pg
}
return $pg
}
<#
.SYNOPSIS
Delete a protection group
.PARAMETER ProtectionGroup
The protection group to remove
.PARAMETER SrmServer
The SRM Server to perform the operation against
#>
Function Remove-ProtectionGroup {
[cmdletbinding(SupportsShouldProcess=$True, ConfirmImpact="High")]
[OutputType([VMware.VimAutomation.Srm.Views.RemoveProtectionGroupTask])]
Param(
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup] $ProtectionGroup,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$api = Get-ServerApiEndpoint $SrmServer
[VMware.VimAutomation.Srm.Views.RemoveProtectionGroupTask] $task = $null
$pginfo = $ProtectionGroup.GetInfo()
if ($pscmdlet.ShouldProcess($pginfo.Name, "Remove")) {
$task = $api.Protection.RemoveProtectionGroup($ProtectionGroup.MoRef)
}
return $task
}

View File

@@ -0,0 +1,556 @@
# SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
<#
.SYNOPSIS
Get the subset of recovery plans matching the input criteria
.PARAMETER Name
Return recovery plans matching the specified name
.PARAMETER ProtectionGroup
Return recovery plans associated with particular protection
groups
#>
Function Get-RecoveryPlan {
[cmdletbinding()]
Param(
[Parameter(position=1)][string] $Name,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup[]] $ProtectionGroup,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
begin {
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
$rps = @()
}
process {
if ($ProtectionGroup) {
foreach ($pg in $ProtectionGroup) {
$rps += $pg.ListRecoveryPlans()
}
$rps = Select_UniqueByMoRef($rps)
} else {
$rps += $api.Recovery.ListPlans()
}
}
end {
$rps | ForEach-Object {
$rp = $_
$rpi = $rp.GetInfo()
$selected = (-not $Name -or ($Name -eq $rpi.Name))
if ($selected) {
Add-Member -InputObject $rp -MemberType NoteProperty -Name "Name" -Value $rpi.Name
$rp
}
}
}
}
<#
.SYNOPSIS
Start a Recovery Plan action like test, recovery, cleanup, etc.
.PARAMETER RecoveryPlan
The recovery plan to start
.PARAMETER RecoveryMode
The recovery mode to invoke on the plan. May be one of "Test", "Cleanup", "Failover", "Migrate", "Reprotect"
#>
Function Start-RecoveryPlan {
[cmdletbinding(SupportsShouldProcess=$True, ConfirmImpact="High")]
Param(
[Parameter (Mandatory=$true, ValueFromPipeline=$true, Position=1)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
[VMware.VimAutomation.Srm.Views.SrmRecoveryPlanRecoveryMode] $RecoveryMode = [VMware.VimAutomation.Srm.Views.SrmRecoveryPlanRecoveryMode]::Test,
[bool] $SyncData = $True
)
# Validate with informative error messages
$rpinfo = $RecoveryPlan.GetInfo()
# Create recovery options
$rpOpt = New-Object VMware.VimAutomation.Srm.Views.SrmRecoveryOptions
$rpOpt.SyncData = $SyncData
# Prompt the user to confirm they want to execute the action
if ($pscmdlet.ShouldProcess($rpinfo.Name, $RecoveryMode)) {
if ($rpinfo.State -eq 'Protecting') {
throw "This recovery plan action needs to be initiated from the other SRM instance"
}
$RecoveryPlan.Start($RecoveryMode, $rpOpt)
}
}
<#
.SYNOPSIS
Stop a running Recovery Plan action.
.PARAMETER RecoveryPlan
The recovery plan to stop
#>
Function Stop-RecoveryPlan {
[cmdletbinding(SupportsShouldProcess=$True,ConfirmImpact="High")]
Param(
[Parameter (Mandatory=$true, ValueFromPipeline=$true, Position=1)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan
)
# Validate with informative error messages
$rpinfo = $RecoveryPlan.GetInfo()
# Prompt the user to confirm they want to cancel the running action
if ($pscmdlet.ShouldProcess($rpinfo.Name, 'Cancel')) {
$RecoveryPlan.Cancel()
}
}
<#
.SYNOPSIS
Retrieve the historical results of a recovery plan
.PARAMETER RecoveryPlan
The recovery plan to retrieve the history for
#>
Function Get-RecoveryPlanResult {
[cmdletbinding()]
Param(
[Parameter (Mandatory=$true, ValueFromPipeline=$true, Position=1)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
[VMware.VimAutomation.Srm.Views.SrmRecoveryPlanRecoveryMode] $RecoveryMode,
[VMware.VimAutomation.Srm.Views.SrmRecoveryResultResultState] $ResultState,
[DateTime] $StartedAfter,
[DateTime] $startedBefore,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
# Get the history objects
$history = $api.Recovery.GetHistory($RecoveryPlan.MoRef)
$resultCount = $history.GetResultCount()
if ($resultCount -gt 0) {
$results = $history.GetRecoveryResult($resultCount)
$results |
Where-Object { -not $RecoveryMode -or $_.RunMode -eq $RecoveryMode } |
Where-Object { -not $ResultState -or $_.ResultState -eq $ResultState } |
Where-Object { $null -eq $StartedAfter -or $_.StartTime -gt $StartedAfter } |
Where-Object { $null -eq $StartedBefore -or $_.StartTime -lt $StartedBefore }
}
}
<#
.SYNOPSIS
Exports a recovery plan result object to XML format
.PARAMETER RecoveryPlanResult
The recovery plan result to export
#>
Function Export-RecoveryPlanResultAsXml {
[cmdletbinding()]
[OutputType([xml])]
Param(
[Parameter (Mandatory=$true, ValueFromPipeline=$true, Position=1)][VMware.VimAutomation.Srm.Views.SrmRecoveryResult] $RecoveryPlanResult,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
$RecoveryPlan = $RecoveryPlanResult.Plan
$history = $api.Recovery.GetHistory($RecoveryPlan.MoRef)
$lines = $history.GetResultLength($RecoveryPlanResult.Key)
[xml] $history.RetrieveStatus($RecoveryPlanResult.Key, 0, $lines)
}
<#
.SYNOPSIS
Add a protection group to a recovery plan. This requires SRM 5.8 or later.
.PARAMETER RecoveryPlan
The recovery plan the protection group will be associated with
.PARAMETER ProtectionGroup
The protection group to associate with the recovery plan
#>
Function Add-ProtectionGroupToRecoveryPlan {
[cmdletbinding()]
Param(
[Parameter (Mandatory=$true, Position=1)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
[Parameter (Mandatory=$true, ValueFromPipeline=$true, Position=2)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup] $ProtectionGroup
)
if ($RecoveryPlan -and $ProtectionGroup) {
foreach ($pg in $ProtectionGroup) {
try {
$RecoveryPlan.AddProtectionGroup($pg.MoRef)
} catch {
Write-Error $_
}
}
}
}
<#
.SYNOPSIS
Remove a protection group to a recovery plan. This requires SRM 6.5 or later.
.PARAMETER RecoveryPlan
The recovery plan the protection group will be disassociated from
.PARAMETER ProtectionGroup
The protection group to disassociate from the recovery plan
#>
Function Remove-ProtectionGroupFromRecoveryPlan {
[cmdletbinding()]
Param(
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup] $ProtectionGroup
)
if ($RecoveryPlan -and $ProtectionGroup) {
foreach ($pg in $ProtectionGroup) {
try {
$RecoveryPlan.RemoveProtectionGroupFromRecoveryPlan($pg.MoRef)
} catch {
Write-Error $_
}
}
}
}
<#
.SYNOPSIS
Get the recovery settings of a protected VM. This requires SRM 5.8 or later.
.PARAMETER RecoveryPlan
The recovery plan the settings will be retrieved from.
.PARAMETER Vm
The virtual machine to retieve recovery settings for.
#>
Function Get-RecoverySetting {
[cmdletbinding()]
Param(
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine] $Vm,
[Parameter (ValueFromPipeline=$true)][VMware.Vim.VirtualMachine] $VmView,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroupProtectedVm] $ProtectedVm
)
$moRef = Get_MoRefFromVmObj -Vm $Vm -VmView $VmView -ProtectedVm $ProtectedVm
if ($RecoveryPlan -and $moRef) {
$RecoveryPlan.GetRecoverySettings($moRef)
}
}
<#
.SYNOPSIS
Get the recovery settings of a protected VM. This requires SRM 5.8 or later.
.PARAMETER RecoveryPlan
The recovery plan the settings will be retrieved from.
.PARAMETER Vm
The virtual machine to configure recovery settings on.
.PARAMETER RecoverySettings
The recovery settings to configure. These should have been retrieved via a
call to Get-RecoverySettings
#>
Function Set-RecoverySetting {
[cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="Medium")]
Param(
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine] $Vm,
[Parameter (ValueFromPipeline=$true)][VMware.Vim.VirtualMachine] $VmView,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroupProtectedVm] $ProtectedVm,
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings
)
$moRef = Get_MoRefFromVmObj -Vm $Vm -VmView $VmView -ProtectedVm $ProtectedVm
if ($RecoveryPlan -and $moRef -and $RecoverySettings) {
if ($PSCmdlet.ShouldProcess("$moRef", "Set")) {
$RecoveryPlan.SetRecoverySettings($moRef, $RecoverySettings)
}
}
}
<#
.SYNOPSIS
Create a new per-Vm command to add to the SRM Recovery Plan
.PARAMETER Command
The command script to execute.
.PARAMETER Description
The user friendly description of this script.
.PARAMETER Timeout
The number of seconds this command has to execute before it will be timedout.
.PARAMETER RunInRecoveredVm
For a post-power on command this flag determines whether it will run on the
recovered VM or on the SRM server.
#>
Function New-Command {
[cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="None")]
Param(
[Parameter (Mandatory=$true)][string] $Command,
[Parameter (Mandatory=$true)][string] $Description,
[int] $Timeout = 300,
[switch] $RunInRecoveredVm = $false
)
if($PSCmdlet.ShouldProcess("Description", "New")) {
$srmWsdlCmd = New-Object VMware.VimAutomation.Srm.WsdlTypes.SrmCommand
$srmCmd = New-Object VMware.VimAutomation.Srm.Views.SrmCommand -ArgumentList $srmWsdlCmd
$srmCmd.Command = $Command
$srmCmd.Description = $Description
$srmCmd.RunInRecoveredVm = $RunInRecoveredVm
$srmCmd.Timeout = $Timeout
$srmCmd.Uuid = [guid]::NewGuid()
return $srmCmd
}
}
<# Internal function #>
Function Add_Command {
[cmdletbinding()]
Param(
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings,
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmCommand] $SrmCommand,
[Parameter (Mandatory=$true)][bool] $PostRecovery
)
if ($PostRecovery) {
$commands = $RecoverySettings.PostPowerOnCallouts
} else {
$commands = $RecoverySettings.PrePowerOnCallouts
}
if (-not $commands) {
$commands = New-Object System.Collections.Generic.List[VMware.VimAutomation.Srm.Views.SrmCallout]
}
$commands.Add($SrmCommand)
if ($PostRecovery) {
$RecoverySettings.PostPowerOnCallouts = $commands
} else {
$RecoverySettings.PrePowerOnCallouts = $commands
}
}
<#
.SYNOPSIS
Add an SRM command to the set of pre recovery callouts for a VM.
.PARAMETER RecoverySettings
The recovery settings to update. These should have been retrieved via a
call to Get-RecoverySettings
.PARAMETER SrmCommand
The command to add to the list.
#>
Function Add-PreRecoveryCommand {
[cmdletbinding()]
[OutputType([VMware.VimAutomation.Srm.Views.SrmRecoverySettings])]
Param(
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings,
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmCommand] $SrmCommand
)
Add_Command -RecoverySettings $RecoverySettings -SrmCommand $SrmCommand -PostRecovery $false
return $RecoverySettings
}
<#
.SYNOPSIS
Remove an SRM command from the set of pre recovery callouts for a VM.
.PARAMETER RecoverySettings
The recovery settings to update. These should have been retrieved via a
call to Get-RecoverySettings
.PARAMETER SrmCommand
The command to remove from the list.
#>
Function Remove-PreRecoveryCommand {
[cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="Low")]
[OutputType([VMware.VimAutomation.Srm.Views.SrmRecoverySettings])]
Param(
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings,
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmCommand] $SrmCommand
)
if ($pscmdlet.ShouldProcess($SrmCommand.Description, "Remove")) {
$RecoverySettings.PrePowerOnCallouts.Remove($SrmCommand)
}
return $RecoverySettings
}
<#
.SYNOPSIS
Add an SRM command to the set of post recovery callouts for a VM.
.PARAMETER RecoverySettings
The recovery settings to update. These should have been retrieved via a
call to Get-RecoverySettings
.PARAMETER SrmCommand
The command to add to the list.
#>
Function Add-PostRecoveryCommand {
[cmdletbinding()]
[OutputType([VMware.VimAutomation.Srm.Views.SrmRecoverySettings])]
Param(
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings,
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmCommand] $SrmCommand
)
Add_Command -RecoverySettings $RecoverySettings -SrmCommand $SrmCommand -PostRecovery $true
return $RecoverySettings
}
<#
.SYNOPSIS
Remove an SRM command from the set of post recovery callouts for a VM.
.PARAMETER RecoverySettings
The recovery settings to update. These should have been retrieved via a
call to Get-RecoverySettings
.PARAMETER SrmCommand
The command to remove from the list.
#>
Function Remove-PostRecoveryCommand {
[cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="Low")]
[OutputType([VMware.VimAutomation.Srm.Views.SrmRecoverySettings])]
Param(
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings,
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmCommand] $SrmCommand
)
if ($pscmdlet.ShouldProcess($SrmCommand.Description, "Remove")) {
$RecoverySettings.PostPowerOnCallouts.Remove($SrmCommand)
}
return $RecoverySettings
}
<#
.SYNOPSIS
Create a new recovery plan
.PARAMETER Name
The name for this recovery plan
.PARAMETER Description
A description of the recovery plan
.PARAMETER Folder
The recovery plan folder in which to create this recovery plan. Will default to
the root recovery plan folder
.PARAMETER ProtectionGroups
The protection groups to associate with this recovery plan
.PARAMETER TestNetworkMappings
The test network mappings to configure as part of this recovery plan
.PARAMETER SrmServer
The SRM Server to operate against
#>
Function New-RecoveryPlan {
[cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="Medium")]
Param(
[Parameter (Mandatory=$true)][string] $Name,
[string] $Description,
[VMware.VimAutomation.Srm.Views.SrmRecoveryPlanFolder] $Folder,
[VMware.VimAutomation.Srm.Views.SrmProtectionGroup[]] $ProtectionGroups,
[VMware.VimAutomation.Srm.Views.SrmRecoveryTestNetworkMapping[]] $TestNetworkMappings,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
if (-not $Folder) {
$Folder = Get-RecoveryPlanFolder -SrmServer $SrmServer
}
$protectionGroupmRefs += @( $ProtectionGroups | ForEach-Object { $_.MoRef } | Select-Object -Unique)
[VMware.VimAutomation.Srm.Views.CreateRecoveryPlanTask] $task = $null
if ($PSCmdlet.ShouldProcess($Name, "New")) {
$task = $api.Recovery.CreateRecoveryPlan(
$Name,
$Folder.MoRef,
$protectionGroupmRefs,
$Description,
$TestNetworkMappings
)
}
while(-not $task.IsCreateRecoveryPlanComplete()) { Start-Sleep -Seconds 1 }
$task.GetNewRecoveryPlan()
}
<#
.SYNOPSIS
Remove a recovery plan permanently
.PARAMETER RecoveryPlan
The recovery plan to remove
.PARAMETER SrmServer
The SRM Server to operate against
#>
Function Remove-RecoveryPlan {
[cmdletbinding(SupportsShouldProcess=$True, ConfirmImpact="High")]
Param(
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
$rpinfo = $RecoveryPlan.GetInfo()
if ($pscmdlet.ShouldProcess($rpinfo.Name, "Remove")) {
$api.Recovery.DeleteRecoveryPlan($RecoveryPlan.MoRef)
}
}
<#
.SYNOPSIS
Get a recovery plan folder
.PARAMETER SrmServer
The SRM Server to query for the recovery plan folder
#>
Function Get-RecoveryPlanFolder {
[cmdletbinding()]
Param(
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
$folder = $api.Recovery.GetRecoveryPlanRootFolder()
return $folder
}

View File

@@ -0,0 +1,24 @@
# SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
<#
.SYNOPSIS
Trigger Discover Devices for Site Recovery Manager
.OUTPUTS
Returns discover devices task
#>
Function Start-DiscoverDevice {
[cmdletbinding(SupportsShouldProcess=$True, ConfirmImpact="Medium")]
[OutputType([VMware.VimAutomation.Srm.Views.DiscoverDevicesTask])]
Param(
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
$name = $SrmServer.Name
[VMware.VimAutomation.Srm.Views.DiscoverDevicesTask] $task = $null
if ($pscmdlet.ShouldProcess($name, "Rescan Storage Devices")) {
$task = $api.Storage.DiscoverDevices()
}
return $task
}

View File

@@ -0,0 +1,92 @@
#
# Module manifest for module 'Meadowcroft.Srm'
#
@{
# Script module or binary module file associated with this manifest.
RootModule = 'Meadowcroft.Srm.psm1'
# Version number of this module.
ModuleVersion = '0.2'
# ID used to uniquely identify this module
GUID = 'f9247009-9168-4a21-831b-819f82884ffe'
# Author of this module
Author = 'Ben Meadowcroft'
# Company or vendor of this module
CompanyName = 'VMware, Inc'
# Copyright statement for this module
Copyright = '(c) 2014 - 2017. All rights reserved.'
# Description of the functionality provided by this module
# Description = ''
# Minimum version of the Windows PowerShell engine required by this module
# PowerShellVersion = ''
# Name of the Windows PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of Microsoft .NET Framework required by this module
# DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module
# CLRVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @{ModuleName='VMware.VimAutomation.Srm'; ModuleVersion='6.5'}
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
NestedModules = 'Meadowcroft.Srm.Recovery.ps1','Meadowcroft.Srm.Protection.ps1','Meadowcroft.Srm.Storage.ps1'
# NestedModules = @()
# Functions to export from this module, note that internal functions use '_' not '-' as separator
FunctionsToExport = '*-*'
# Cmdlets to export from this module
CmdletsToExport = '*'
# Variables to export from this module
VariablesToExport = '*'
# Aliases to export from this module
AliasesToExport = '*'
# List of all modules packaged with this module
# ModuleList = @()
# List of all files packaged with this module
# FileList = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess
# PrivateData = ''
# HelpInfo URI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
DefaultCommandPrefix = 'Srm'
}

View File

@@ -0,0 +1,148 @@
# SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
<#
.SYNOPSIS
This is intended to be an "internal" function only. It filters a
pipelined input of objects and elimiates duplicates as identified
by the MoRef property on the object.
.LINK
https://github.com/benmeadowcroft/SRM-Cmdlets/
#>
Function Select_UniqueByMoRef {
Param(
[Parameter (ValueFromPipeline=$true)] $in
)
process {
$moref = New-Object System.Collections.ArrayList
$in | Sort-Object | Select-Object MoRef -Unique | ForEach-Object { $moref.Add($_.MoRef) } > $null
$in | ForEach-Object {
if ($_.MoRef -in $moref) {
$moref.Remove($_.MoRef)
$_ #output
}
}
}
}
<#
.SYNOPSIS
This is intended to be an "internal" function only. It gets the
MoRef property of a VM from either a VM object, a VM view, or the
protected VM object.
#>
Function Get_MoRefFromVmObj {
Param(
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine] $Vm,
[Parameter (ValueFromPipeline=$true)][VMware.Vim.VirtualMachine] $VmView,
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroupProtectedVm] $ProtectedVm
)
$moRef = $null
if ($Vm.ExtensionData.MoRef) { # VM object
$moRef = $Vm.ExtensionData.MoRef
} elseif ($VmView.MoRef) { # VM view
$moRef = $VmView.MoRef
} elseif ($protectedVm) {
$moRef = $ProtectedVm.Vm.MoRef
}
$moRef
}
<#
.SYNOPSIS
Lookup the srm instance for a specific server.
#>
Function Get-Server {
[cmdletbinding()]
Param(
[string] $SrmServerAddress,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$found = $null
if ($SrmServer) {
$found = $SrmServer
} elseif ($SrmServerAddress) {
# search for server address in default servers
$global:DefaultSrmServers | ForEach-Object {
if ($_.Name -ieq $SrmServerAddress) {
$found = $_
}
}
if (-not $found) {
throw "SRM server $SrmServerAddress not found. Connect-Server must be called first."
}
}
if (-not $found) {
#default result
$found = $global:DefaultSrmServers[0]
}
return $found;
}
<#
.SYNOPSIS
Retrieve the SRM Server Version
#>
Function Get-ServerVersion {
[cmdletbinding()]
Param(
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
$srm = Get-Server $SrmServer
$srm.Version
}
<#
.SYNOPSIS
Lookup the SRM API endpoint for a specific server.
#>
Function Get-ServerApiEndpoint {
[cmdletbinding()]
Param(
[string] $SrmServerAddress,
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
)
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $server = Get-Server -SrmServerAddress $SrmServerAddress -SrmServer $SrmServer
return $server.ExtensionData
}
<#
.SYNOPSIS
Get the placeholder VMs that are associated with SRM
#>
Function Get-PlaceholderVM {
[cmdletbinding()]
Param()
Get-VM @Args | Where-Object {$_.ExtensionData.Config.ManagedBy.extensionKey -like "com.vmware.vcDr*" -and $_.ExtensionData.Config.ManagedBy.Type -ieq 'placeholderVm'}
}
<#
.SYNOPSIS
Get the test VMs that are associated with SRM
#>
Function Get-TestVM {
[cmdletbinding()]
Param()
Get-VM @Args | Where-Object {$_.ExtensionData.Config.ManagedBy.extensionKey -like "com.vmware.vcDr*" -and $_.ExtensionData.Config.ManagedBy.Type -ieq 'testVm'}
}
<#
.SYNOPSIS
Get the VMs that are replicated using vSphere Replication. These may not be SRM
protected VMs.
#>
Function Get-ReplicatedVM {
[cmdletbinding()]
Param()
Get-VM @Args | Where-Object {($_.ExtensionData.Config.ExtraConfig | Where-Object { $_.Key -eq 'hbr_filter.destination' -and $_.Value } )}
}

7
Modules/SRM/NOTICE.txt Normal file
View File

@@ -0,0 +1,7 @@
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
This product is licensed to you under the Apache License version 2.0 (the "License"). You may not use this product except in compliance with the License.
This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file.

81
Modules/SRM/README.md Normal file
View File

@@ -0,0 +1,81 @@
# SRM PowerCLI Cmdlets
Helper functions for working with VMware SRM 6.5 with PowerCLI 6.5.1 or later. PowerShell 5.0 and above is required.
This module is provided for illustrative/educational purposes to explain how the PowerCLI access to the SRM public API can be used.
## Getting Started
### Getting the SRM cmdlets
The latest version of the software can be cloned from the git repository:
git clone https://github.com/benmeadowcroft/SRM-Cmdlets.git
Or downloaded as a [zip file](https://github.com/benmeadowcroft/SRM-Cmdlets/archive/master.zip).
Specific releases (compatible with earlier PowerCLI and SRM versions) can be downloaded via the [release page](https://github.com/benmeadowcroft/SRM-Cmdlets/releases).
### Deploy SRM-Cmdlets module
After cloning (or downloading and extracting) the PowerShell module, you can import the module into your current PowerShell session by by passing the path to `Meadowcroft.Srm.psd1` to the `Import-Module` cmdlet, e.g.:
Import-Module -Name .\SRM-Cmdlets\Meadowcroft.Srm.psd1
You can also install the module into the PowerShell path so it can be loaded implicitly. See [Microsoft's Installing Modules instructions](http://msdn.microsoft.com/en-us/library/dd878350) for more details on how to do this.
The module uses the default prefix of `Srm` for the custom functions it defines. This can be overridden when importing the module by setting the value of the `-Prefix` parameter when calling `Import-Module`.
### Connecting to SRM
After installing the module the next step is to connect to the SRM server. Details of how to do this are located in the [PowerCLI 6.5.1 User's Guide](http://pubs.vmware.com/vsphere-65/topic/com.vmware.powercli.ug.doc/GUID-A5F206CF-264D-4565-8CB9-4ED1C337053F.html)
$credential = Get-Credential
Connect-VIServer -Server vc-a.example.com -Credential $credential
Connect-SrmServer -Credential $credential -RemoteCredential $credential
At this point we've just been using the cmdlets provided by PowerCLI, the PowerCLI documentation also provides some examples of how to call the SRM API to perform various tasks. In the rest of this introduction we'll perform some of those tasks using the custom functions defined in this project.
### Report the Protected Virtual Machines and Their Protection Groups
Goal: Create a simple report listing the VMs protected by SRM and the protection group they belong to.
Get-SrmProtectionGroup | %{
$pg = $_
Get-SrmProtectedVM -ProtectionGroup $pg } | %{
$output = "" | select VmName, PgName
$output.VmName = $_.Vm.Name
$output.PgName = $pg.GetInfo().Name
$output
} | Format-Table @{Label="VM Name"; Expression={$_.VmName} },
@{Label="Protection group name"; Expression={$_.PgName}
}
### Report the Last Recovery Plan Test
Goal: Create a simple report listing the state of the last test of a recovery plan
Get-SrmRecoveryPlan | %{ $_ |
Get-SrmRecoveryPlanResult -RecoveryMode Test | select -First 1
} | Select Name, StartTime, RunMode, ResultState | Format-Table
### Execute a Recovery Plan Test
Goal: for a specific recovery plan, execute a test failover. Note the "local" SRM server we are connected to should be the recovery site in order for this to be successful.
Get-SrmRecoveryPlan -Name "Name of Plan" | Start-SrmRecoveryPlan -RecoveryMode Test
### Export the Detailed XML Report of the Last Recovery Plan Workflow
Goal: get the XML report of the last recovery plan execution for a specific recovery plan.
Get-SrmRecoveryPlan -Name "Name of Plan" | Get-SrmRecoveryPlanResult |
select -First 1 | Export-SrmRecoveryPlanResultAsXml
### Protect a Replicated VM
Goal: Take a VM replicated using vSphere Replication or Array Based Replication, add it to an appropriate protection group and configure it for protection
$pg = Get-SrmProtectionGroup "Name of Protection Group"
Get-VM vm-01a | Protect-SrmVM -ProtectionGroup $pg

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
VMware-vCD-Module PowerShell Module
===================================
![Invoke-MyOnBoarding](/media/Invoke-MyOnBoarding.png)
# About
## Project Owner:
Markus Kraus [@vMarkus_K](https://twitter.com/vMarkus_K)
MY CLOUD-(R)EVOLUTION [mycloudrevolution.com](http://mycloudrevolution.com/)
## Project WebSite:
[PowerCLI vCloud Director Customer Provisioning](https://mycloudrevolution.com/2017/06/13/powercli-vcloud-director-customer-provisioning/)
[PowerCLI Create vCloud Director Edge Gateway](https://mycloudrevolution.com/2017/06/27/powercli-create-vcloud-director-edge-gateway/)
## Project Documentation:
[Read the Docs - VMware-vCD-Module](http://vmware-vcd-module.readthedocs.io/)
## Project Description:
The 'VMware-vCD-Module' PowerShell Module is focused on the initial creation of VMware vCloud Director Objects like Org, Org User, Org VDC with External Networks or Edge Gateway.
All Functions in this Module can be used as standalone Cmdlet but also the ``Invoke-My OnBoarding`` Functions to process a JSON File and create all Objects at once.
### Fully tested Versions:
Powershell: v4, v5
PowerCLI: 6.5.1
VMware vCloud Director: 8.10.1

View File

@@ -0,0 +1,127 @@
#
# Modulmanifest für das Modul "PSGet_VMware-vCD-Module"
#
# Generiert von: Markus
#
# Generiert am: 6/11/2017
#
@{
# Die diesem Manifest zugeordnete Skript- oder Binärmoduldatei.
# RootModule = ''
# Die Versionsnummer dieses Moduls
ModuleVersion = '1.0.0'
# ID zur eindeutigen Kennzeichnung dieses Moduls
GUID = '1ef8a2de-ca22-4c88-8cdb-e00f35007d2a'
# Autor dieses Moduls
Author = 'Markus'
# Unternehmen oder Hersteller dieses Moduls
CompanyName = 'mycloudrevolution.com'
# Urheberrechtserklärung für dieses Modul
Copyright = '(c) 2017 Markus. Alle Rechte vorbehalten.'
# Beschreibung der von diesem Modul bereitgestellten Funktionen
# Description = ''
# Die für dieses Modul mindestens erforderliche Version des Windows PowerShell-Moduls
# PowerShellVersion = ''
# Der Name des für dieses Modul erforderlichen Windows PowerShell-Hosts
# PowerShellHostName = ''
# Die für dieses Modul mindestens erforderliche Version des Windows PowerShell-Hosts
# PowerShellHostVersion = ''
# Die für dieses Modul mindestens erforderliche Microsoft .NET Framework-Version
# DotNetFrameworkVersion = ''
# Die für dieses Modul mindestens erforderliche Version der CLR (Common Language Runtime)
# CLRVersion = ''
# Die für dieses Modul erforderliche Prozessorarchitektur ("Keine", "X86", "Amd64").
# ProcessorArchitecture = ''
# Die Module, die vor dem Importieren dieses Moduls in die globale Umgebung geladen werden müssen
# RequiredModules = @()
# Die Assemblys, die vor dem Importieren dieses Moduls geladen werden müssen
# RequiredAssemblies = @()
# Die Skriptdateien (PS1-Dateien), die vor dem Importieren dieses Moduls in der Umgebung des Aufrufers ausgeführt werden.
# ScriptsToProcess = @()
# Die Typdateien (.ps1xml), die beim Importieren dieses Moduls geladen werden sollen
# TypesToProcess = @()
# Die Formatdateien (.ps1xml), die beim Importieren dieses Moduls geladen werden sollen
# FormatsToProcess = @()
# Die Module, die als geschachtelte Module des in "RootModule/ModuleToProcess" angegebenen Moduls importiert werden sollen.
NestedModules = @('functions\Invoke-MyOnBoarding.psm1',
'functions\New-MyEdgeGateway.psm1',
'functions\New-MyOrg.psm1',
'functions\New-MyOrgAdmin.psm1',
'functions\New-MyOrgVdc.psm1')
# Aus diesem Modul zu exportierende Funktionen
FunctionsToExport = 'Invoke-MyOnBoarding', 'New-MyEdgeGateway', 'New-MyOrg', 'New-MyOrgAdmin', 'New-MyOrgVdc'
# Aus diesem Modul zu exportierende Cmdlets
CmdletsToExport = '*'
# Die aus diesem Modul zu exportierenden Variablen
VariablesToExport = '*'
# Aus diesem Modul zu exportierende Aliase
AliasesToExport = '*'
# Aus diesem Modul zu exportierende DSC-Ressourcen
# DscResourcesToExport = @()
# Liste aller Module in diesem Modulpaket
# ModuleList = @()
# Liste aller Dateien in diesem Modulpaket
# FileList = @()
# Die privaten Daten, die an das in "RootModule/ModuleToProcess" angegebene Modul übergeben werden sollen. Diese können auch eine PSData-Hashtabelle mit zusätzlichen von PowerShell verwendeten Modulmetadaten enthalten.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
# Tags = @()
# A URL to the license for this module.
# LicenseUri = ''
# A URL to the main website for this project.
# ProjectUri = ''
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
# ReleaseNotes = ''
# External dependent modules of this module
# ExternalModuleDependencies = ''
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfo-URI dieses Moduls
# HelpInfoURI = ''
# Standardpräfix für Befehle, die aus diesem Modul exportiert werden. Das Standardpräfix kann mit "Import-Module -Prefix" überschrieben werden.
# DefaultCommandPrefix = ''
}

View File

@@ -0,0 +1,30 @@
{
"Org": {
"Name":"TestOrg",
"FullName": "Test Org",
"Description":"Automation Test Org"
},
"OrgAdmin": {
"Name":"TestOrgAdmin",
"Pasword": "myPassword1!",
"FullName":"Test OrgAdmin",
"EmailAddress":"test@admin.org"
},
"OrgVdc": {
"Name":"TestOrgVdc",
"FixedSize": "M",
"CPULimit": "1000",
"MEMLimit":"1024",
"StorageLimit":"1024",
"StorageProfile":"Standard-DC01",
"ProviderVDC":"Provider-VDC-DC01",
"NetworkPool":"Provider-VDC-DC01-NetPool",
"ExternalNetwork": "External-OrgVdcNet",
"EdgeGateway": "Yes",
"IPAddress":"192.168.100.1",
"SubnetMask":"255.255.255.0",
"Gateway":"192.168.100.254",
"IPRangeStart":"192.168.100.2",
"IPRangeEnd":"192.168.100.3"
}
}

View File

@@ -0,0 +1,191 @@
#Requires -Version 4
#Requires -Modules VMware.VimAutomation.Cloud, @{ModuleName="VMware.VimAutomation.Cloud";ModuleVersion="6.3.0.0"}
Function Invoke-MyOnBoarding {
<#
.SYNOPSIS
Creates all vCD Objecst for a new IAAS Customer
.DESCRIPTION
Creates all vCD Objects for a new IAAS Customer
All Objects are:
* Org
* Default Org Admin
* Org VDC
** Private Catalog
** Optional Bridged Network
JSON Config Example:
{
"Org": {
"Name":"TestOrg",
"FullName": "Test Org",
"Description":"Automation Test Org"
},
"OrgAdmin": {
"Name":"TestOrgAdmin",
"Pasword": "myPassword1!",
"FullName":"Test OrgAdmin",
"EmailAddress":"test@admin.org"
},
"OrgVdc": {
"Name":"TestOrgVdc",
"FixedSize": "M",
"CPULimit": "1000",
"MEMLimit":"1000",
"StorageLimit":"1000",
"StorageProfile":"Standard-DC01",
"ProviderVDC":"Provider-VDC-DC01",
"NetworkPool":"Provider-VDC-DC01-NetPool",
"ExternalNetwork": "External_OrgVdcNet",
"EdgeGateway": "Yes",
"IPAddress":"192.168.100.1",
"SubnetMask":"255.255.255.0",
"Gateway":"192.168.100.254",
"IPRangeStart":"192.168.100.2",
"IPRangeEnd":"192.168.100.3"
}
}
.NOTES
File Name : Invoke-MyOnBoarding.ps1
Author : Markus Kraus
Version : 1.3
State : Ready
.LINK
https://mycloudrevolution.com/
.EXAMPLE
Invoke-MyOnBoarding -ConfigFile ".\OnBoarding.json" -Enabled:$true
.EXAMPLE
Invoke-MyOnBoarding -ConfigFile ".\OnBoarding.json" -Enabled:$false
.PARAMETER ConfigFile
Full Path to the JSON Config File
.PARAMETER Enabled
Should the Customer be enabled after creation
Default: $False
#>
Param (
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Full Path to the JSON Config File")]
[ValidateNotNullorEmpty()]
[String] $ConfigFile,
[Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Should the Customer be enabled after creation")]
[ValidateNotNullorEmpty()]
[Switch]$Enabled
)
Process {
$Valid = $true
Write-Verbose "## Import JSON Config"
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Importing JSON Config...`n"
$Configs = Get-Content -Raw -Path $ConfigFile -ErrorAction Continue | ConvertFrom-Json -ErrorAction Continue
if (!($Configs)) {
$Valid = $false
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Importing JSON Config Failed" -ForegroundColor Red
}
else {
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Importing JSON Config OK" -ForegroundColor Green
}
if ($Valid) {
try{
Write-Verbose "## Create Org"
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new Org...`n" -ForegroundColor Yellow
$Trash = New-MyOrg -Name $Configs.Org.Name -FullName $Configs.Org.Fullname -Description $Configs.Org.Description -Enabled:$Enabled
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new Org OK" -ForegroundColor Green
Get-Org -Name $Configs.Org.Name | Select-Object Name, FullName, Enabled | Format-Table -AutoSize
}
catch {
$Valid = $false
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new Org Failed" -ForegroundColor Red
}
}
if ($Valid) {
try{
Write-Verbose "## Create OrgAdmin"
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgAdmin...`n" -ForegroundColor Yellow
$Trash = New-MyOrgAdmin -Name $Configs.OrgAdmin.Name -Pasword $Configs.OrgAdmin.Pasword -FullName $Configs.OrgAdmin.FullName -EmailAddress $Configs.OrgAdmin.EmailAddress -Org $Configs.Org.Name -Enabled:$Enabled
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgAdmin OK" -ForegroundColor Green
Get-CIUser -Org $Configs.Org.Name -Name $Configs.OrgAdmin.Name | Select-Object Name, FullName, Email | Format-Table -AutoSize
}
catch {
$Valid = $false
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgAdmin Failed" -ForegroundColor Red
}
}
if ($Valid) {
try{
Write-Verbose "## Create OrgVdc"
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgVdc...`n" -ForegroundColor Yellow
if ($Configs.OrgVdc.FixedSize){
Write-Host "Fixed Size (T-Shirt Size) '$($Configs.OrgVdc.FixedSize)' Org VDC Requested!"
switch ($Configs.OrgVdc.FixedSize) {
M {
[String]$CPULimit = 36000
[String]$MEMLimit = 122880
[String]$StorageLimit = 1048576
}
L {
[String]$CPULimit = 36000
[String]$MEMLimit = 245760
[String]$StorageLimit = 1048576
}
default {throw "Invalid T-Shirt Size!"}
}
}
else{
Write-Host "Custom Org VDC Size Requested!"
$CPULimit = $Configs.OrgVdc.CPULimit
$MEMLimit = $Configs.OrgVdc.MEMLimit
$StorageLimit = $Configs.OrgVdc.StorageLimit
}
if ($Configs.OrgVdc.ExternalNetwork -and $Configs.OrgVdc.EdgeGateway -like "Yes"){
Write-Host "Edge Gateway for Org VDC '$($Configs.OrgVdc.Name)' Requested!"
$Trash = New-MyOrgVdc -Name $Configs.OrgVdc.Name -CPULimit $CPULimit -MEMLimit $MEMLimit -StorageLimit $StorageLimit -Networkpool $Configs.OrgVdc.NetworkPool `
-StorageProfile $Configs.OrgVdc.StorageProfile -ProviderVDC $Configs.OrgVdc.ProviderVDC -Org $Configs.Org.Name -Enabled:$Enabled
$EdgeName = $Configs.Org.Name + "-ESG01"
$Trash = New-MyEdgeGateway -Name $EdgeName -OrgVDCName $Configs.OrgVdc.Name -Orgname $Configs.Org.Name -ExternalNetwork $Configs.OrgVdc.ExternalNetwork `
-IPAddress $Configs.OrgVdc.IPAddress -SubnetMask $Configs.OrgVdc.SubnetMask -Gateway $Configs.OrgVdc.Gateway -IPRangeStart $Configs.OrgVdc.IPRangeStart -IPRangeEnd $Configs.OrgVdc.IPRangeEnd
}
elseif ($Configs.OrgVdc.ExternalNetwork -and $Configs.OrgVdc.EdgeGateway -like "No"){
Write-Host "External Network for Org VDC '$($Configs.OrgVdc.Name)' Requested!"
$Trash = New-MyOrgVdc -Name $Configs.OrgVdc.Name -CPULimit $CPULimit -MEMLimit $MEMLimit -StorageLimit $StorageLimit -Networkpool $Configs.OrgVdc.NetworkPool `
-StorageProfile $Configs.OrgVdc.StorageProfile -ProviderVDC $Configs.OrgVdc.ProviderVDC -ExternalNetwork $Configs.OrgVdc.ExternalNetwork -Org $Configs.Org.Name -Enabled:$Enabled
}
else {
Write-Host "No external Connection for Org VDC '$($Configs.OrgVdc.Name)' Requested!"
$Trash = New-PecOrgVdc -Name $Configs.OrgVdc.Name -CPULimit $CPULimit -MEMLimit $MEMLimit -StorageLimit $StorageLimit -Networkpool $ProVdcNetworkPool.Name `
-StorageProfile $Configs.OrgVdc.StorageProfile -ProviderVDC $Configs.OrgVdc.ProviderVDC -Org $Configs.Org.Name -Enabled:$Enabled
}
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgVdc OK" -ForegroundColor Green
Get-OrgVdc -Org $Configs.Org.Name -Name $Configs.OrgVdc.Name | Select-Object Name, Enabled, CpuAllocationGhz, MemoryLimitGB, StorageLimitGB, AllocationModel, ThinProvisioned, UseFastProvisioning, `
@{N="StorageProfile";E={$_.ExtensionData.VdcStorageProfiles.VdcStorageProfile.Name}}, `
@{N='VCpuInMhz';E={$_.ExtensionData.VCpuInMhz}} | Format-Table -AutoSize
if ($Configs.OrgVdc.EdgeGateway -like "Yes"){
Search-Cloud -QueryType EdgeGateway -Name $EdgeName | Select Name, IsBusy, GatewayStatus, HaStatus | ft -AutoSize
}
}
catch {
$Valid = $false
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgVdc Failed" -ForegroundColor Red
}
}

View File

@@ -0,0 +1,161 @@
#Requires -Version 4
#Requires -Modules VMware.VimAutomation.Cloud, @{ModuleName="VMware.VimAutomation.Cloud";ModuleVersion="6.3.0.0"}
Function New-MyEdgeGateway {
<#
.SYNOPSIS
Creates a new Edge Gateway with Default Parameters
.DESCRIPTION
Creates a new Edge Gateway with Default Parameters
Default Parameters are:
* Size
* HA State
* DNS Relay
.NOTES
File Name : New-MyEdgeGateway.ps1
Author : Markus Kraus
Version : 1.0
State : Ready
.LINK
https://mycloudrevolution.com/
.EXAMPLE
New-MyEdgeGateway -Name "TestEdge" -OrgVDCName "TestVDC" -OrgName "TestOrg" -ExternalNetwork "ExternalNetwork" -IPAddress "192.168.100.1" -SubnetMask "255.255.255.0" -Gateway "192.168.100.254" -IPRangeStart ""192.168.100.2" -IPRangeEnd ""192.168.100.3" -Verbose
.PARAMETER Name
Name of the New Edge Gateway as String
.PARAMETER OrgVDCName
OrgVDC where the new Edge Gateway should be created as string
.PARAMETER OrgName
Org where the new Edge Gateway should be created as string
.PARAMETER ExternalNetwork
External Network of the new Edge Gateway as String
.PARAMETER IPAddress
IP Address of the New Edge Gateway as IP Address
.PARAMETER SubnetMask
Subnet Mask of the New Edge Gateway as IP Address
.PARAMETER Gateway
Gateway of the New Edge Gateway as IP Address
.PARAMETER IPRangeStart
Sub Allocation IP Range Start of the New Edge Gateway as IP Address
.PARAMETER IPRangeEnd
Sub Allocation IP Range End of the New Edge Gateway as IP Address
.PARAMETER Timeout
Timeout for the Edge Gateway to get Ready
Default: 120s
#>
Param (
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Name of the New Edge Gateway as String")]
[ValidateNotNullorEmpty()]
[String] $Name,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="OrgVDC where the new Edge Gateway should be created as string")]
[ValidateNotNullorEmpty()]
[String] $OrgVdcName,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Org where the new Edge Gateway should be created as string")]
[ValidateNotNullorEmpty()]
[String] $OrgName,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="External Network of the New Edge Gateway as String")]
[ValidateNotNullorEmpty()]
[String] $ExternalNetwork,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="IP Address of the New Edge Gateway as IP Address")]
[ValidateNotNullorEmpty()]
[IPAddress] $IPAddress,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Subnet Mask of the New Edge Gateway as IP Address")]
[ValidateNotNullorEmpty()]
[IPAddress] $SubnetMask,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Gateway of the New Edge Gateway as IP Address")]
[ValidateNotNullorEmpty()]
[IPAddress] $Gateway,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Sub Allocation IP Range Start the New Edge Gateway as IP Address")]
[ValidateNotNullorEmpty()]
[IPAddress] $IPRangeStart,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Sub Allocation IP Range End the New Edge Gateway as IP Address")]
[ValidateNotNullorEmpty()]
[IPAddress] $IPRangeEnd,
[Parameter(Mandatory=$False, ValueFromPipeline=$False,HelpMessage="Timeout for the Edge Gateway to get Ready")]
[ValidateNotNullorEmpty()]
[int] $Timeout = 120
)
Process {
## Get Org vDC
Write-Verbose "Get Org vDC"
[Array] $orgVdc = Get-Org -Name $OrgName | Get-OrgVdc -Name $OrgVdcName
if ( $orgVdc.Count -gt 1) {
throw "Multiple OrgVdcs found!"
}
elseif ( $orgVdc.Count -lt 1) {
throw "No OrgVdc found!"
}
## Get External Network
Write-Verbose "Get External Network"
$extNetwork = Get-ExternalNetwork | Get-CIView -Verbose:$False | Where-Object {$_.name -eq $ExternalNetwork}
## Build EdgeGatway Configuration
Write-Verbose "Build EdgeGatway Configuration"
$EdgeGateway = New-Object VMware.VimAutomation.Cloud.Views.Gateway
$EdgeGateway.Name = $Name
$EdgeGateway.Configuration = New-Object VMware.VimAutomation.Cloud.Views.GatewayConfiguration
#$EdgeGateway.Configuration.BackwardCompatibilityMode = $false
$EdgeGateway.Configuration.GatewayBackingConfig = "compact"
$EdgeGateway.Configuration.UseDefaultRouteForDnsRelay = $false
$EdgeGateway.Configuration.HaEnabled = $false
$EdgeGateway.Configuration.EdgeGatewayServiceConfiguration = New-Object VMware.VimAutomation.Cloud.Views.GatewayFeatures
$EdgeGateway.Configuration.GatewayInterfaces = New-Object VMware.VimAutomation.Cloud.Views.GatewayInterfaces
$EdgeGateway.Configuration.GatewayInterfaces.GatewayInterface = New-Object VMware.VimAutomation.Cloud.Views.GatewayInterface
$EdgeGateway.Configuration.GatewayInterfaces.GatewayInterface[0].name = $extNetwork.Name
$EdgeGateway.Configuration.GatewayInterfaces.GatewayInterface[0].DisplayName = $extNetwork.Name
$EdgeGateway.Configuration.GatewayInterfaces.GatewayInterface[0].Network = $extNetwork.Href
$EdgeGateway.Configuration.GatewayInterfaces.GatewayInterface[0].InterfaceType = "uplink"
$EdgeGateway.Configuration.GatewayInterfaces.GatewayInterface[0].UseForDefaultRoute = $true
$EdgeGateway.Configuration.GatewayInterfaces.GatewayInterface[0].ApplyRateLimit = $false
$ExNetexternalSubnet = New-Object VMware.VimAutomation.Cloud.Views.SubnetParticipation
$ExNetexternalSubnet.Gateway = $Gateway.IPAddressToString
$ExNetexternalSubnet.Netmask = $SubnetMask.IPAddressToString
$ExNetexternalSubnet.IpAddress = $IPAddress.IPAddressToString
$ExNetexternalSubnet.IpRanges = New-Object VMware.VimAutomation.Cloud.Views.IpRanges
$ExNetexternalSubnet.IpRanges.IpRange = New-Object VMware.VimAutomation.Cloud.Views.IpRange
$ExNetexternalSubnet.IpRanges.IpRange[0].StartAddress = $IPRangeStart.IPAddressToString
$ExNetexternalSubnet.IpRanges.IpRange[0].EndAddress = $IPRangeEnd.IPAddressToString
$EdgeGateway.Configuration.GatewayInterfaces.GatewayInterface[0].SubnetParticipation = $ExNetexternalSubnet
## Create EdgeGatway
Write-Verbose "Create EdgeGatway"
$CreateEdgeGateway = $orgVdc.ExtensionData.CreateEdgeGateway($EdgeGateway)
## Wait for EdgeGatway to become Ready
Write-Verbose "Wait for EdgeGatway to become Ready"
while((Search-Cloud -QueryType EdgeGateway -Name $Name -Verbose:$False).IsBusy -eq $True){
$i++
Start-Sleep 5
if($i -gt $Timeout) { Write-Error "Creating Edge Gateway."; break}
Write-Progress -Activity "Creating Edge Gateway" -Status "Wait for Edge to become Ready..."
}
Write-Progress -Activity "Creating Edge Gateway" -Completed
Start-Sleep 1
Search-Cloud -QueryType EdgeGateway -Name $Name | Select-Object Name, IsBusy, GatewayStatus, HaStatus | Format-Table -AutoSize
}
}

View File

@@ -0,0 +1,107 @@
#Requires -Version 4
#Requires -Modules VMware.VimAutomation.Cloud, @{ModuleName="VMware.VimAutomation.Cloud";ModuleVersion="6.3.0.0"}
Function New-MyOrg {
<#
.SYNOPSIS
Creates a new vCD Org with Default Parameters
.DESCRIPTION
Creates a new vCD Org with Default Parameters.
Default Parameters are:
* Catalog Publishing
* Catalog Subscription
* VM Quota
* Stored VM Quota
* VM Lease Time
* Stored VM Lease Time
* Password Policy Settings
.NOTES
File Name : New-MyOrg.ps1
Author : Markus Kraus
Version : 1.1
State : Ready
.LINK
https://mycloudrevolution.com/
.EXAMPLE
New-MyOrg -Name "TestOrg" -FullName "Test Org" -Description "PowerCLI Test Org"
.PARAMETER Name
Name of the New Org as String
.PARAMETER FullName
Full Name of the New Org as String
.PARAMETER Description
Description of the New Org as String
.PARAMETER Enabled
Should the New Org be enabled after creation
Default:$false
#>
Param (
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Name of the New Org as string")]
[ValidateNotNullorEmpty()]
[String] $Name,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Full Name of the New Org as string")]
[ValidateNotNullorEmpty()]
[String] $FullName,
[Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Description of the New Org as string")]
[ValidateNotNullorEmpty()]
[String] $Description,
[Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Should the New Org be enabled after creation")]
[ValidateNotNullorEmpty()]
[Switch]$Enabled
)
Process {
$vcloud = $DefaultCIServers[0].ExtensionData
## Create Objects
$AdminOrg = New-Object VMware.VimAutomation.Cloud.Views.AdminOrg
$orgGeneralSettings = New-Object VMware.VimAutomation.Cloud.Views.OrgGeneralSettings
$orgOrgLeaseSettings = New-Object VMware.VimAutomation.Cloud.Views.OrgLeaseSettings
$orgOrgVAppTemplateLeaseSettings = New-Object VMware.VimAutomation.Cloud.Views.OrgVAppTemplateLeaseSettings
$orgOrgPasswordPolicySettings = New-Object VMware.VimAutomation.Cloud.Views.OrgPasswordPolicySettings
$orgSettings = New-Object VMware.VimAutomation.Cloud.Views.OrgSettings
## Admin Settings
$adminOrg.Name = $name
$adminOrg.FullName = $FullName
$adminOrg.Description = $description
$adminOrg.IsEnabled = $Enabled
## Org Setting
### General Org Settings
$orgGeneralSettings.CanPublishCatalogs = $False
$orgGeneralSettings.CanPublishExternally = $False
$orgGeneralSettings.CanSubscribe = $True
$orgGeneralSettings.DeployedVMQuota = 0
$orgGeneralSettings.StoredVmQuota = 0
$orgSettings.OrgGeneralSettings = $orgGeneralSettings
### vApp Org Setting
$orgOrgLeaseSettings.DeleteOnStorageLeaseExpiration = $false
$orgOrgLeaseSettings.DeploymentLeaseSeconds = 0
$orgOrgLeaseSettings.StorageLeaseSeconds = 0
$orgSettings.VAppLeaseSettings = $orgOrgLeaseSettings
### vApp Template Org Setting
$orgOrgVAppTemplateLeaseSettings.DeleteOnStorageLeaseExpiration = $false
$orgOrgVAppTemplateLeaseSettings.StorageLeaseSeconds = 0
$orgSettings.VAppTemplateLeaseSettings = $orgOrgVAppTemplateLeaseSettings
### PasswordPolicySettings Org Setting
$orgOrgPasswordPolicySettings.AccountLockoutEnabled = $True
$orgOrgPasswordPolicySettings.InvalidLoginsBeforeLockout = 5
$orgOrgPasswordPolicySettings.AccountLockoutIntervalMinutes = 30
$orgSettings.OrgPasswordPolicySettings = $orgOrgPasswordPolicySettings
$adminOrg.Settings = $orgSettings
$CreateOrg = $vcloud.CreateOrg($adminOrg)
Get-Org -Name $name | Format-Table -AutoSize
}
}

View File

@@ -0,0 +1,91 @@
#Requires -Version 4
#Requires -Modules VMware.VimAutomation.Cloud, @{ModuleName="VMware.VimAutomation.Cloud";ModuleVersion="6.3.0.0"}
Function New-MyOrgAdmin {
<#
.SYNOPSIS
Creates a new vCD Org Admin with Default Parameters
.DESCRIPTION
Creates a new vCD Org Admin with Default Parameters
Default Parameters are:
* User Role
.NOTES
File Name : New-MyOrgAdmin.ps1
Author : Markus Kraus
Version : 1.1
State : Ready
.LINK
https://mycloudrevolution.com/
.EXAMPLE
New-MyOrgAdmin -Name "OrgAdmin" -Pasword "Anfang!!" -FullName "Org Admin" -EmailAddress "OrgAdmin@TestOrg.local" -Org "TestOrg"
.PARAMETER Name
Name of the New Org Admin as String
.PARAMETER FullName
Full Name of the New Org Admin as String
.PARAMETER Password
Password of the New Org Admin as String
.PARAMETER EmailAddress
EmailAddress of the New Org Admin as String
.PARAMETER Enabled
Should the New Org be enabled after creation
Default:$false
.PARAMETER Org
Org where the new Org Admin should be created as string
#>
Param (
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Name of the New Org Admin as String")]
[ValidateNotNullorEmpty()]
[String] $Name,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Password of the New Org Admin as String")]
[ValidateNotNullorEmpty()]
[String] $Pasword,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Full Name of the New Org Admin as String")]
[ValidateNotNullorEmpty()]
[String] $FullName,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="EmailAddress of the New Org Admin as String")]
[ValidateNotNullorEmpty()]
[String] $EmailAddress,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Org where the new Org Admin should be created as string")]
[ValidateNotNullorEmpty()]
[String] $Org,
[Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Should the New Org be enabled after creation")]
[ValidateNotNullorEmpty()]
[Switch]$Enabled
)
Process {
## Create Objects
$OrgED = (Get-Org $Org).ExtensionData
$orgAdminUser = New-Object VMware.VimAutomation.Cloud.Views.User
## Settings
$orgAdminUser.Name = $Name
$orgAdminUser.FullName = $FullName
$orgAdminUser.EmailAddress = $EmailAddress
$orgAdminUser.Password = $Pasword
$orgAdminUser.IsEnabled = $Enabled
$vcloud = $DefaultCIServers[0].ExtensionData
## Find Role
$orgAdminRole = $vcloud.RoleReferences.RoleReference | Where-Object {$_.Name -eq "Organization Administrator"}
$orgAdminUser.Role = $orgAdminRole
## Create User
$user = $orgED.CreateUser($orgAdminUser)
Get-CIUser -Org $Org -Name $Name | Format-Table -AutoSize
}
}

View File

@@ -0,0 +1,252 @@
#Requires -Version 4
#Requires -Modules VMware.VimAutomation.Cloud, @{ModuleName="VMware.VimAutomation.Cloud";ModuleVersion="6.3.0.0"}
Function New-MyOrgVdc {
<#
.SYNOPSIS
Creates a new vCD Org VDC with Default Parameters
.DESCRIPTION
Creates a new vCD Org VDC with Default Parameters
Default Parameters are:
* Allocation Model
* Network Quota
* VM Quota
* 'vCpu In Mhz'
* Fast Provisioning
* Thin Provisioning
* private Catalog
.NOTES
File Name : New-MyOrgVdc.ps1
Author : Markus Kraus
Version : 1.2
State : Ready
.LINK
https://mycloudrevolution.com/
.EXAMPLE
New-MyOrgVdc -Name "TestVdc" -CPULimit 1000 -MEMLimit 1000 -StorageLimit 1000 -StorageProfile "Standard-DC01" -NetworkPool "NetworkPool-DC01" -ProviderVDC "Provider-VDC-DC01" -Org "TestOrg" -ExternalNetwork "External_OrgVdcNet"
.EXAMPLE
New-MyOrgVdc -Name "TestVdc" -CPULimit 1000 -MEMLimit 1000 -StorageLimit 1000 -StorageProfile "Standard-DC01" -NetworkPool "NetworkPool-DC01" -ProviderVDC "Provider-VDC-DC01" -Org "TestOrg"
.PARAMETER Name
Name of the New Org VDC as String
.PARAMETER CPULimit
CPU Limit (MHz) of the New Org VDC as String
.PARAMETER MEMLimit
Memory Limit (MB) of the New Org VDC as String
.PARAMETER StorageLimit
Storage Limit (MB) of the New Org VDC as String
.PARAMETER StorageProfile
Storage Profile of the New Org VDC as String
.PARAMETER NetworkPool
Network Pool of the New Org VDC as String
.PARAMETER ExternalNetwork
Optional External Network of the New Org VDC as String
.PARAMETER Enabled
Should the New Org VDC be enabled after creation
Default:$false
Note: If an External Network is requested the Org VDC will be enabled during External Network Configuration
.PARAMETER ProviderVDC
ProviderVDC where the new Org VDC should be created as string
.PARAMETER Org
Org where the new Org VDC should be created as string
.PARAMETER Timeout
Timeout for the Org VDC to get Ready
Default: 120s
#>
Param (
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Name of the New Org VDC as String")]
[ValidateNotNullorEmpty()]
[String] $Name,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="CPU Limit (MHz) of the New Org VDC as String")]
[ValidateNotNullorEmpty()]
[int] $CPULimit,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Memory Limit (MB) of the New Org VDC as String")]
[ValidateNotNullorEmpty()]
[int] $MEMLimit,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Storage Limit (MB) of the New Org VDC as String")]
[ValidateNotNullorEmpty()]
[int] $StorageLimit,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Storage Profile of the New Org VDC as String")]
[ValidateNotNullorEmpty()]
[String] $StorageProfile,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Network Pool of the New Org VDC as String")]
[ValidateNotNullorEmpty()]
[String] $NetworkPool,
[Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Optional External Network of the New Org VDC as String")]
[ValidateNotNullorEmpty()]
[String] $ExternalNetwork,
[Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Should the New Org VDC be enabled after creation")]
[ValidateNotNullorEmpty()]
[Switch]$Enabled,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="ProviderVDC where the new Org VDC should be created as string")]
[ValidateNotNullorEmpty()]
[String] $ProviderVDC,
[Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Org where the new Org VDC should be created as string")]
[ValidateNotNullorEmpty()]
[String] $Org,
[Parameter(Mandatory=$False, ValueFromPipeline=$False,HelpMessage="Timeout for the Org VDC to get Ready")]
[ValidateNotNullorEmpty()]
[int] $Timeout = 120
)
Process {
## Create Objects and all Settings
Write-Verbose "Create Objects and all Settings"
$adminVdc = New-Object VMware.VimAutomation.Cloud.Views.AdminVdc
$adminVdc.Name = $name
$adminVdc.IsEnabled = $Enabled
$OrgVdcproviderVdc = Get-ProviderVdc $ProviderVDC
$providerVdcRef = New-Object VMware.VimAutomation.Cloud.Views.Reference
$providerVdcRef.Href = $OrgVdcproviderVdc.Href
$adminVdc.ProviderVdcReference = $providerVdcRef
$adminVdc.AllocationModel = "AllocationPool"
$adminVdc.ComputeCapacity = New-Object VMware.VimAutomation.Cloud.Views.ComputeCapacity
$adminVdc.ComputeCapacity.Cpu = New-Object VMware.VimAutomation.Cloud.Views.CapacityWithUsage
$adminVdc.ComputeCapacity.Cpu.Units = "MHz"
$adminVdc.ComputeCapacity.Cpu.Limit = $CPULimit
$adminVdc.ComputeCapacity.Cpu.Allocated = $CPULimit
$adminVdc.ComputeCapacity.Memory = New-Object VMware.VimAutomation.Cloud.Views.CapacityWithUsage
$adminVdc.ComputeCapacity.Memory.Units = "MB"
$adminVdc.ComputeCapacity.Memory.Limit = $MEMLimit
$adminVdc.ComputeCapacity.Memory.Allocated = $MEMLimit
$adminVdc.StorageCapacity = New-Object VMware.VimAutomation.Cloud.Views.CapacityWithUsage
$adminVdc.StorageCapacity.Units = "MB"
$adminVdc.StorageCapacity.Limit = $StorageLimit
$adminVdc.NetworkQuota = 10
$adminVdc.VmQuota = 0
$adminVdc.VCpuInMhz = 1000
$adminVdc.VCpuInMhz2 = 1000
$adminVdc.UsesFastProvisioning = $false
$adminVdc.IsThinProvision = $true
## Create Org vDC
Write-Verbose "Create Org vDC"
$OrgED = (Get-Org $Org).ExtensionData
$orgVdc = $orgED.CreateVdc($adminVdc)
## Wait for getting Ready
Write-Verbose "Wait for getting Ready"
$i = 0
while(($orgVdc = Get-OrgVdc -Name $Name -Verbose:$false).Status -eq "NotReady"){
$i++
Start-Sleep 2
if($i -gt $Timeout) { Write-Error "Creating Org Failed."; break}
Write-Progress -Activity "Creating Org" -Status "Wait for Org to become Ready..."
}
Write-Progress -Activity "Creating Org" -Completed
Start-Sleep 2
## Search given Storage Profile
Write-Verbose "Search given Storage Profile"
$ProVdcStorageProfile = search-cloud -QueryType ProviderVdcStorageProfile -Name $StorageProfile | Get-CIView
## Create Storage Profile Object with Settings
Write-Verbose "Create Storage Profile Object with Settings"
$spParams = new-object VMware.VimAutomation.Cloud.Views.VdcStorageProfileParams
$spParams.Limit = $StorageLimit
$spParams.Units = "MB"
$spParams.ProviderVdcStorageProfile = $ProVdcStorageProfile.href
$spParams.Enabled = $true
$spParams.Default = $true
$UpdateParams = new-object VMware.VimAutomation.Cloud.Views.UpdateVdcStorageProfiles
$UpdateParams.AddStorageProfile = $spParams
## Update Org vDC
$orgVdc = Get-OrgVdc -Name $name
$orgVdc.ExtensionData.CreateVdcStorageProfile($UpdateParams)
## Wait for getting Ready
Write-Verbose "Wait for getting Ready"
while(($orgVdc = Get-OrgVdc -Name $name -Verbose:$false).Status -eq "NotReady"){
$i++
Start-Sleep 1
if($i -gt $Timeout) { Write-Error "Update Org Failed."; break}
Write-Progress -Activity "Updating Org" -Status "Wait for Org to become Ready..."
}
Write-Progress -Activity "Updating Org" -Completed
Start-Sleep 1
## Search Any-StorageProfile
Write-Verbose "Search Any-StorageProfile"
$orgvDCAnyProfile = search-cloud -querytype AdminOrgVdcStorageProfile | Where-Object {($_.Name -match '\*') -and ($_.VdcName -eq $orgVdc.Name)} | Get-CIView
## Disable Any-StorageProfile
Write-Verbose "Disable Any-StorageProfile"
$orgvDCAnyProfile.Enabled = $False
$return = $orgvDCAnyProfile.UpdateServerData()
## Remove Any-StorageProfile
Write-Verbose "Remove Any-StorageProfile"
$ProfileUpdateParams = new-object VMware.VimAutomation.Cloud.Views.UpdateVdcStorageProfiles
$ProfileUpdateParams.RemoveStorageProfile = $orgvDCAnyProfile.href
$remove = $orgvdc.extensiondata.CreatevDCStorageProfile($ProfileUpdateParams)
## Wait for getting Ready
Write-Verbose "Wait for getting Ready"
while(($orgVdc = Get-OrgVdc -Name $name -Verbose:$false).Status -eq "NotReady"){
$i++
Start-Sleep 1
if($i -gt $Timeout) { Write-Error "Update Org Failed."; break}
Write-Progress -Activity "Updating Org" -Status "Wait for Org to become Ready..."
}
Write-Progress -Activity "Updating Org" -Completed
Start-Sleep 1
## Set NetworkPool for correct location
Write-Verbose "Set NetworkPool for correct location"
$orgVdc = Get-OrgVdc -Name $name
$ProVdcNetworkPool = Get-NetworkPool -ProviderVdc $ProviderVDC -Name $NetworkPool
$set = Set-OrgVdc -OrgVdc $orgVdc -NetworkPool $ProVdcNetworkPool -NetworkMaxCount "10"
## Create private Catalog
Write-Verbose "Create private Catalog Object"
$OrgCatalog = New-Object VMware.VimAutomation.Cloud.Views.AdminCatalog
$OrgCatalog.name = "$Org Private Catalog"
if (!(Get-Org $org | Get-Catalog -Name $OrgCatalog.name -ErrorAction SilentlyContinue)) {
Write-Verbose "Create private Catalog"
$CreateCatalog = (Get-Org $org | Get-CIView).CreateCatalog($OrgCatalog)
$AccessControlRule = New-CIAccessControlRule -Entity $CreateCatalog.name -EveryoneInOrg -AccessLevel ReadWrite -Confirm:$False
}
else {
Write-Output "Catalog '$($OrgCatalog.name)' aleady exists!"
}
## Create a direct connect network
if ($ExternalNetwork) {
Write-Verbose "Create a direct connect network"
Write-Output "Org VDC '$Name' needs to be enabled to add an external Network!"
$EnableOrgVdc = Set-OrgVdc -OrgVdc $Name -Enabled:$True
$orgVdcView = Get-OrgVdc $Name | Get-CIView
$extNetwork = $_.externalnetwork
$extNetwork = Get-ExternalNetwork | Get-CIView -Verbose:$false | Where-Object {$_.name -eq $ExternalNetwork}
$orgNetwork = new-object vmware.vimautomation.cloud.views.orgvdcnetwork
$orgNetwork.name = $ExternalNetwork
$orgNetwork.Configuration = New-Object VMware.VimAutomation.Cloud.Views.NetworkConfiguration
$orgNetwork.Configuration.FenceMode = 'bridged'
$orgNetwork.configuration.ParentNetwork = New-Object vmware.vimautomation.cloud.views.reference
$orgNetwork.configuration.ParentNetwork.href = $extNetwork.href
$result = $orgVdcView.CreateNetwork($orgNetwork)
}
Get-OrgVdc -Name $name | Format-Table -AutoSize
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View File

@@ -0,0 +1,35 @@
$moduleRoot = Resolve-Path "$PSScriptRoot\.."
$moduleName = "VMware-vCD-Module"
$ConfigFile = "$moduleRoot\examples\OnBoarding.json"
Describe "General project validation: $moduleName" {
$scripts = Get-ChildItem $moduleRoot -Include *.ps1, *.psm1, *.psd1 -Recurse
# TestCases are splatted to the script so we need hashtables
$testCase = $scripts | Foreach-Object {@{file = $_}}
It "Script <file> should be valid powershell" -TestCases $testCase {
param($file)
$file.fullname | Should Exist
$contents = Get-Content -Path $file.fullname -ErrorAction Stop
$errors = $null
$null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors)
$errors.Count | Should Be 0
}
It "Module '$moduleName' prerequirements are met" {
{Import-Module VMware.VimAutomation.Cloud -Force} | Should Not Throw
}
It "Module '$moduleName' can import cleanly" {
{Import-Module (Join-Path $moduleRoot "$moduleName.psd1") -force } | Should Not Throw
}
It "Module '$moduleName' JSON example is valid" {
{Get-Content -Raw -Path $ConfigFile | ConvertFrom-Json} | Should Not Throw
}
}

View File

@@ -0,0 +1,30 @@
VMware-vCD-TenantReport PowerShell Module
=============
# About
## Project Owner:
Markus Kraus [@vMarkus_K](https://twitter.com/vMarkus_K)
MY CLOUD-(R)EVOLUTION [mycloudrevolution.com](http://mycloudrevolution.com/)
## Project WebSite:
[mycloudrevolution.com](http://mycloudrevolution.com/)
## Project Documentation:
[Read the Docs](http://readthedocs.io/)
## Project Description:
The 'VMware-vCD-TenantReport' PowerShell Module creates with the Fuction 'Get-VcdTenantReport' a HTML Report of your vCloud Director Objects.
![Get-VcdTenantReport](/media/Get-VcdTenantReport.png)
Big thanks to [Timothy Dewin](https://twitter.com/tdewin) for his great [PowerStartHTML](https://github.com/tdewin/randomsamples/tree/master/powerstarthtml) PowerShell Module which is used to generate the Report for this Module.

View File

@@ -0,0 +1,122 @@
#
# Modulmanifest für das Modul "VMware-vCD-TenantReport"
#
# Generiert von: Markus Kraus
#
# Generiert am: 8/22/2017
#
@{
# Die diesem Manifest zugeordnete Skript- oder Binärmoduldatei.
# RootModule = 'VMware-vCD-TenantReport.psm1'
# Die Versionsnummer dieses Moduls
ModuleVersion = '1.0.2'
# ID zur eindeutigen Kennzeichnung dieses Moduls
GUID = '21a71eaa-d259-48c5-8482-643ba152af76'
# Autor dieses Moduls
Author = 'Markus'
# Unternehmen oder Hersteller dieses Moduls
CompanyName = 'mycloudrevolution.com'
# Urheberrechtserklärung für dieses Modul
Copyright = '(c) 2017 Markus Kraus. Alle Rechte vorbehalten.'
# Beschreibung der von diesem Modul bereitgestellten Funktionen
# Description = ''
# Die für dieses Modul mindestens erforderliche Version des Windows PowerShell-Moduls
# PowerShellVersion = ''
# Der Name des für dieses Modul erforderlichen Windows PowerShell-Hosts
# PowerShellHostName = ''
# Die für dieses Modul mindestens erforderliche Version des Windows PowerShell-Hosts
# PowerShellHostVersion = ''
# Die für dieses Modul mindestens erforderliche Microsoft .NET Framework-Version
# DotNetFrameworkVersion = ''
# Die für dieses Modul mindestens erforderliche Version der CLR (Common Language Runtime)
# CLRVersion = ''
# Die für dieses Modul erforderliche Prozessorarchitektur ("Keine", "X86", "Amd64").
# ProcessorArchitecture = ''
# Die Module, die vor dem Importieren dieses Moduls in die globale Umgebung geladen werden müssen
# RequiredModules = @()
# Die Assemblys, die vor dem Importieren dieses Moduls geladen werden müssen
# RequiredAssemblies = @()
# Die Skriptdateien (PS1-Dateien), die vor dem Importieren dieses Moduls in der Umgebung des Aufrufers ausgeführt werden.
# ScriptsToProcess = @()
# Die Typdateien (.ps1xml), die beim Importieren dieses Moduls geladen werden sollen
# TypesToProcess = @()
# Die Formatdateien (.ps1xml), die beim Importieren dieses Moduls geladen werden sollen
# FormatsToProcess = @()
# Die Module, die als geschachtelte Module des in "RootModule/ModuleToProcess" angegebenen Moduls importiert werden sollen.
NestedModules = @( "modules/PowerStartHTML/PowerStartHTML.psd1",
"functions/Get-VcdTenantReport.psm1" )
# Aus diesem Modul zu exportierende Funktionen
FunctionsToExport = '*'
# Aus diesem Modul zu exportierende Cmdlets
CmdletsToExport = '*'
# Die aus diesem Modul zu exportierenden Variablen
VariablesToExport = '*'
# Aus diesem Modul zu exportierende Aliase
AliasesToExport = '*'
# Aus diesem Modul zu exportierende DSC-Ressourcen
# DscResourcesToExport = @()
# Liste aller Module in diesem Modulpaket
# ModuleList = @()
# Liste aller Dateien in diesem Modulpaket
# FileList = @()
# Die privaten Daten, die an das in "RootModule/ModuleToProcess" angegebene Modul übergeben werden sollen. Diese können auch eine PSData-Hashtabelle mit zusätzlichen von PowerShell verwendeten Modulmetadaten enthalten.
PrivateData = @{
PSData = @{
# 'Tags' wurde auf das Modul angewendet und unterstützt die Modulermittlung in Onlinekatalogen.
# Tags = @()
# Eine URL zur Lizenz für dieses Modul.
# LicenseUri = ''
# Eine URL zur Hauptwebsite für dieses Projekt.
# ProjectUri = ''
# Eine URL zu einem Symbol, das das Modul darstellt.
# IconUri = ''
# 'ReleaseNotes' des Moduls
# ReleaseNotes = ''
} # Ende der PSData-Hashtabelle
} # Ende der PrivateData-Hashtabelle
# HelpInfo-URI dieses Moduls
# HelpInfoURI = ''
# Standardpräfix für Befehle, die aus diesem Modul exportiert werden. Das Standardpräfix kann mit "Import-Module -Prefix" überschrieben werden.
# DefaultCommandPrefix = ''
}

View File

@@ -0,0 +1,251 @@
function Get-VcdTenantReport {
<#
.NOTES
===========================================================================
Created by: Markus Kraus
Twitter: @VMarkus_K
Private Blog: mycloudrevolution.com
===========================================================================
Changelog:
1.0.0 - Inital Release
1.0.1 - Removed "Test-IP" Module
1.0.2 - More Detailed Console Log
===========================================================================
External Code Sources:
Examle Usage of BOOTSTRAP with PowerShell
https://github.com/tdewin/randomsamples/tree/master/powershell-veeamallstat
BOOTSTRAP with PowerShell
https://github.com/tdewin/randomsamples/tree/master/powerstarthtml
===========================================================================
Tested Against Environment:
vCD Version: 8.20
PowerCLI Version: PowerCLI 6.5.1
PowerShell Version: 5.0
OS Version: Windows 8.1
Keyword: VMware, vCD, Report, HTML
===========================================================================
.DESCRIPTION
This Function creates a HTML Report for your vCloud Director Organization.
This Function is fully tested as Organization Administrator.
With lower permissions a unexpected behavior is possible.
.Example
Get-VcdTenantReport -Server $ServerFQDN -Org $OrgName -Credential $MyCedential
.Example
Get-VcdTenantReport -Server $ServerFQDN -Org $OrgName -Path "C:\Temp\Report.html"
.PARAMETER Server
The FQDN of your vCloud Director Endpoint.
.PARAMETER Org
The Organization Name.
.PARAMETER Credential
PowerShell Credentials to access the Eénvironment.
.PARAMETER Path
The Path of the exported HTML Report.
#>
#Requires -Version 5
#Requires -Modules VMware.VimAutomation.Cloud, @{ModuleName="VMware.VimAutomation.Cloud";ModuleVersion="6.5.1.0"}
[CmdletBinding()]
param(
[Parameter(Mandatory=$True, ValueFromPipeline=$False)]
[ValidateNotNullorEmpty()]
[String] $Server,
[Parameter(Mandatory=$True, ValueFromPipeline=$False)]
[ValidateNotNullorEmpty()]
[String] $Org,
[Parameter(Mandatory=$False, ValueFromPipeline=$False)]
[ValidateNotNullorEmpty()]
[PSCredential] $Credential,
[Parameter(Mandatory=$false, ValueFromPipeline=$False)]
[ValidateNotNullorEmpty()]
[String] $Path = ".\Report.html"
)
Process {
# Start Connection to vCD
if ($global:DefaultCIServers) {
"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - Disconnect existing vCD Server ..."
$Trash = Disconnect-CIServer -Server * -Force:$true -Confirm:$false -ErrorAction SilentlyContinue
}
"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - Connect vCD Server ..."
if ($Credential) {
$Trash = Connect-CIServer -Server $Server -Org $Org -Credential $Credential -ErrorAction Stop
}
else {
$Trash = Connect-CIServer -Server $Server -Org $Org -ErrorAction Stop
}
"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - Create HTML Report..."
# Init HTML Report
$ps = New-PowerStartHTML -title "vCD Tenant Report"
#Set CSS Style
$ps.cssStyles['.bgtitle'] = "background-color:grey"
$ps.cssStyles['.bgsubsection'] = "background-color:#eee;"
# Processing Data
## Get Main Objects
[Array] $OrgVdcs = Get-OrgVdc
[Array] $Catalogs = Get-Catalog
[Array] $Users = Get-CIUser
## Add Header to Report
$ps.Main().Add("div","jumbotron").N()
$ps.Append("h1","display-3",("vCD Tenant Report" -f $OrgVdcs.Count)).Append("p","lead","Organization User Count: {0}" -f $Users.Count).Append("p","lead","Organization Catalog Count: {0}" -f $Catalogs.Count).Append("p","lead","Organization VDC Count: {0}" -f $OrgVdcs.Count).Append("hr","my-4").Append("p","font-italic","This Report lists the most important objects in your vCD Environmet. For more details contact your Service Provider").N()
## add Org Users to Report
$ps.Main().Append("h2",$null,"Org Users").N()
$ps.Add('table','table').Add("tr","bgtitle text-white").Append("th",$null,"User Name").Append("th",$null,"Locked").Append("th",$null,"DeployedVMCount").Append("th",$null,"StoredVMCount").N()
$ps.Add("tr").N()
foreach ($User in $Users) {
$ps.Append("td",$null,$User.Name).N()
$ps.Append("td",$null,$User.Locked).N()
$ps.Append("td",$null,$User.DeployedVMCount).N()
$ps.Append("td",$null,$User.StoredVMCount).N()
$ps.Up().N()
}
$ps.Up().N()
## add Org Catalogs to Report
$ps.Main().Append("h2",$null,"Org Catalogs").N()
foreach ($Catalog in $Catalogs) {
$ps.Add('table','table').Add("tr","bgtitle text-white").Append("th",$null,"Catalog Name").N()
$ps.Add("tr").N()
$ps.Append("td",$null,$Catalog.Name).Up().N()
$ps.Add("td","bgsubsection").N()
$ps.Add("table","table bgcolorsub").N()
$ps.Add("tr").N()
$headers = @("Item")
foreach ($h in $headers) {
$ps.Append("th",$null,$h).N()
}
$ps.Up().N()
### add Itens of the Catalog to the Report
[Array] $Items = $Catalog.ExtensionData.CatalogItems.CatalogItem
foreach ($Item in $Items) {
$ps.Add("tr").N()
$ps.Append("td",$null,$Item.Name).N()
$ps.Up().N()
}
$ps.Up().Up().N()
}
$ps.Up().N()
## add Org VDC`s to the Report
$ps.Main().Append("h2",$null,"Org VDCs").N()
foreach ($OrgVdc in $OrgVdcs) {
$ps.Main().Add('table','table table-striped table-inverse').Add("tr").Append("th",$null,"VDC Name").Append("th",$null,"Enabled").Append("th",$null,"CpuUsedGHz").Append("th",$null,"MemoryUsedGB").Append("th",$null,"StorageUsedGB").Up().N()
$ps.Add("tr").N()
$ps.Append("td",$null,$OrgVdc.Name).Append("td",$null,$OrgVdc.Enabled).Append("td",$null,$OrgVdc.CpuUsedGHz).Append("td",$null,$OrgVdc.MemoryUsedGB).Append("td",$null,[Math]::Round($OrgVdc.StorageUsedGB,2)).Up().N()
### add Edge Gateways of this Org VDC to Report
$ps.Main().Append("h3",$null,"Org VDC Edge Gateways").N()
[Array] $Edges = Search-Cloud -QueryType EdgeGateway -Filter "Vdc==$($OrgVdc.Id)"
foreach ($Edge in $Edges) {
$ps.Add('table','table').Add("tr","bgtitle text-white").Append("th",$null,"Edge Name").N()
$ps.Add("tr").N()
$ps.Append("td",$null,$Edge.Name).Up().N()
$ps.Add("td","bgsubsection").N()
$ps.Add("table","table bgcolorsub").N()
$ps.Append("tr").Append("td","font-weight-bold","HaStatus").Append("td",$null,($Edge.HaStatus)).N()
$ps.Append("td","font-weight-bold","AdvancedNetworkingEnabled").Append("td",$null,$Edge.AdvancedNetworkingEnabled).N()
$ps.Append("tr").Append("td","font-weight-bold","NumberOfExtNetworks").Append("td",$null,($Edge.NumberOfExtNetworks)).N()
$ps.Append("td","font-weight-bold","NumberOfOrgNetworks").Append("td",$null,$Edge.NumberOfOrgNetworks).N()
$ps.Up().Up().N()
}
$ps.Up().N()
### add Org Networks of this Org VDC to Report
$ps.Main().Append("h3",$null,"Org VDC Networks").N()
[Array] $Networks = $OrgVdc | Get-OrgVdcNetwork
foreach ($Network in $Networks) {
$ps.Add('table','table').Add("tr","bgtitle text-white").Append("th",$null,"Network Name").N()
$ps.Add("tr").N()
$ps.Append("td",$null,$Network.Name).Up().N()
$ps.Add("td","bgsubsection").N()
$ps.Add("table","table bgcolorsub").N()
$ps.Append("tr").Append("td","font-weight-bold","DefaultGateway").Append("td",$null,($Network.DefaultGateway)).N()
$ps.Append("td","font-weight-bold","Netmask").Append("td",$null,$Network.Netmask).N()
$ps.Append("tr").Append("td","font-weight-bold","NetworkType").Append("td",$null,($Network.NetworkType)).N()
$ps.Append("td","font-weight-bold","StaticIPPool").Append("td",$null,$Network.StaticIPPool).N()
$ps.Up().Up().N()
}
$ps.Up().N()
### add vApps of this Org VDC to Report
$ps.Main().Append("h3",$null,"Org VDC vApps").N()
[Array] $Vapps = $OrgVdc | Get-CIVApp
foreach ($Vapp in $Vapps) {
$ps.Add('table','table').Add("tr","bgtitle text-white").Append("th",$null,"vApp Name").Append("th",$null,"Owner").Up().N()
$ps.Add("tr").N()
$ps.Append("td",$null,$Vapp.Name).Append("td",$null,$Vapp.Owner).Up().N()
#### add VMs of this vApp to Report
$ps.Add("td","bgsubsection").N()
$ps.Add("table","table bgcolorsub").N()
$ps.Add("tr").N()
$headers = @("Name","Status","GuestOSFullName","CpuCount","MemoryGB")
foreach ($h in $headers) {
$ps.Append("th",$null,$h).N()
}
$ps.Up().N()
[Array] $VMs = $Vapp | Get-CIVM
foreach ($VM in $VMs) {
$ps.Add("tr").N()
$ps.Append("td",$null,$VM.Name).N()
$ps.Append("td",$null,$VM.Status).N()
$ps.Append("td",$null,$VM.GuestOSFullName).N()
$ps.Append("td",$null,$VM.CpuCount).N()
$ps.Append("td",$null,$VM.MemoryGB).N()
$ps.Up().N()
}
$ps.Up().Up().N()
}
$ps.Up().N()
}
$ps.save($Path)
"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - Open HTML Report..."
Start-Process $Path
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -0,0 +1,237 @@
class PowerStartHTML {
[string]$PowerStartHtmlTemplate = "<html><head><meta charset=`"UTF-8`"/><title></title><style></style></head><body><div/></body></html>"
[xml]$xmlDocument = $null
$onLoadJS = $null
$cssStyles= @{}
$lastEl = $null
$newEl = $null
$indentedOutput = $false
$bootstrapAtCompile = $false
PowerStartHTML([string]$title) {
$this.xmlDocument = $this.PowerStartHtmlTemplate
$this.xmlDocument.html.head.title = $title
$this.lastEl = $this.xmlDocument.html.body.ChildNodes[0]
$this.onLoadJS = New-Object System.Collections.Generic.List[System.String]
}
[string] GetHtml() {
$xmlclone = $this.xmlDocument.Clone()
$csb = [System.Text.StringBuilder]::new()
foreach ($cssStyle in $this.cssStyles.GetEnumerator()) {
$null = $csb.AppendFormat("{0} {{ {1} }}",$cssStyle.Name,$cssStyle.Value)
}
$this.xmlDocument.html.head.style = $csb.toString()
$this.AddBootStrapAtCompile()
if($this.onLoadJS.Count -gt 0) {
$this.onLoadJs.Insert(0,"`r`n`$(document).ready(function() {")
$this.onLoadJs.Add("})`r`n")
$el = $this.xmlDocument.CreateElement("script")
$el.AppendChild($this.xmlDocument.CreateTextNode([System.String]::Join("`r`n",$this.onLoadJs)))
$this.xmlDocument.html.body.AppendChild($el)
}
$ms = [System.IO.MemoryStream]::new()
$xmlWriter = [System.Xml.XmlTextWriter]::new($ms,[System.Text.Encoding]::UTF8)
if($this.indentedOutput) {
$xmlWriter.Formatting = [System.Xml.Formatting]::Indented
}
$this.xmlDocument.WriteContentTo($xmlWriter)
$xmlWriter.Flush()
$ms.Flush()
#make sure that everytime we do gethtml we keep it clean
$this.xmlDocument = $xmlclone
$ms.Position = 0;
$sr = [System.IO.StreamReader]::new($ms);
return ("<!DOCTYPE html>{0}`r`n" -f $sr.ReadToEnd())
}
Save($path) {
$this.GetHtml() | Set-Content -path $path -Encoding UTF8
}
AddAttr($el,$name,$value) {
$attr = $this.xmlDocument.CreateAttribute($name)
$attr.Value = $value
$el.Attributes.Append($attr)
}
AddAttrs($el,$dict) {
foreach($a in $dict.GetEnumerator()) {
$this.AddAttr($el,$a.Name,$a.Value)
}
}
[PowerStartHTML] AddBootStrap() {
$this.bootstrapAtCompile = $true
return $this
}
AddJSScript($href,$integrity) {
$el = $this.xmlDocument.CreateElement("script")
$attrs = @{
"src"="$href";
"integrity"="$integrity";
"crossorigin"="anonymous"
}
$this.AddAttrs($el,$attrs)
$el.AppendChild($this.xmlDocument.CreateTextNode(""))
$this.xmlDocument.html.body.AppendChild($el)
}
AddBootStrapAtCompile() { #Bootstrap script needs to be added at the end
if($this.bootstrapAtCompile) {
$el = $this.xmlDocument.CreateElement("link")
$attrs = @{
"rel"="stylesheet";
"href"='https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css';
"integrity"="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M";
"crossorigin"="anonymous"
}
$this.AddAttrs($el,$attrs)
$el.AppendChild($this.xmlDocument.CreateTextNode(""))
$this.xmlDocument.html.head.AppendChild($el)
$this.AddJSScript('https://code.jquery.com/jquery-3.2.1.slim.min.js',"sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN")
$this.AddJSScript('https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js',"sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4")
$this.AddJSScript('https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js',"sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1")
}
}
[PowerStartHTML] AddContainerAttrToMain() {
$this.AddAttr($this.xmlDocument.html.body.ChildNodes[0],"class","container")
return $this
}
[PowerStartHTML] Append($elType = "table",$className=$null,[string]$text=$null) {
$el = $this.xmlDocument.CreateElement($elType)
if($text -ne $null) {
$el.AppendChild($this.xmlDocument.CreateTextNode($text))
}
if($className -ne $null) {
$this.AddAttr($el,"class",$className)
}
$this.lastEl.AppendChild($el)
$this.newEl = $el
return $this
}
[PowerStartHTML] Append($elType = "table",$className=$null) { return $this.Append($elType,$className,$null) }
[PowerStartHTML] Append($elType = "table") { return $this.Append($elType,$null,$null) }
[PowerStartHTML] Add($elType = "table",$className=$null,[string]$text=$null) {
$this.Append($elType,$className,$text)
$this.lastEl = $this.newEl
return $this
}
[PowerStartHTML] Add($elType = "table",$className=$null) { return $this.Add($elType,$className,$null) }
[PowerStartHTML] Add($elType = "table") { return $this.Add($elType,$null,$null) }
[PowerStartHTML] Main() {
$this.lastEl = $this.xmlDocument.html.body.ChildNodes[0];
return $this
}
[PowerStartHTML] Up() {
$this.lastEl = $this.lastEl.ParentNode;
return $this
}
N() {}
}
class PowerStartHTMLPassThroughLine {
$object;$cells
PowerStartHTMLPassThroughLine($object) {
$this.object = $object;
$this.cells = new-object System.Collections.HashTable;
}
}
class PowerStartHTMLPassThroughElement {
$name;$text;$element;$id
PowerStartHTMLPassThroughElement($name,$text,$element,$id) {
$this.name = $name; $this.text = $text; $this.element = $element;$this.id = $id
}
}
function New-PowerStartHTML {
param(
[Parameter(Mandatory=$true)][string]$title,
[switch]$nobootstrap=$false
)
$pshtml = (new-object PowerStartHTML($title))
if(-not $nobootstrap) {
$pshtml.AddBootStrap().AddContainerAttrToMain().N()
}
return $pshtml
}
function Add-PowerStartHTMLTable {
param(
[Parameter(Mandatory=$True,ValueFromPipeline=$True)]$object,
[PowerStartHTML]$psHtml,
[string]$tableTitle = $null,
[string]$tableClass = $null,
[string]$idOverride = $(if($tableTitle -ne $null) {($tableTitle.toLower() -replace "[^a-z0-9]","-") }),
[switch]$passthroughTable = $false,
[switch]$noheaders = $false
)
begin {
if($tableTitle -ne $null) {
$psHtml.Main().Append("h1",$null,$tableTitle).N()
if($idOverride -ne $null) {
$psHtml.AddAttr($psHtml.newEl,"id","header-$idOverride")
}
}
$psHtml.Main().Add("table").N()
[int]$r = 0
[int]$c = 0
if($idOverride -ne $null) {
$psHtml.AddAttr($psHtml.newEl,"id","table-$idOverride")
}
if($tableClass -ne $null) {
$psHtml.AddAttr($psHtml.newEl,"class",$tableClass)
}
[bool]$isFirst = $true
}
process {
$c = 0
$props = $object | Get-Member -Type Properties
if(-not $noheaders -and $isFirst) {
$psHtml.Add("tr").N()
if($idOverride -ne $null) {
$psHtml.AddAttr($psHtml.newEl,"id","table-$idOverride-trh")
}
$props | % {
$n = $_.Name;
$psHtml.Append("th",$null,$n).N()
if($idOverride -ne $null) {
$cellid = "table-$idOverride-td-$r-$c"
$psHtml.AddAttr($psHtml.newEl,"id",$cellid)
}
$c++
}
$c = 0
$psHtml.Up().N()
}
$psHtml.Add("tr").N()
if($idOverride -ne $null) {
$psHtml.AddAttr($psHtml.newEl,"id","table-$idOverride-tr-$r")
}
$pstableln = [PowerStartHTMLPassThroughLine]::new($object)
$props | % {
$n = $_.Name;
$psHtml.Append("td",$null,$object."$n").N()
$cellid = $null
if($idOverride -ne $null) {
$cellid = "table-$idOverride-td-$r-$c"
$psHtml.AddAttr($psHtml.newEl,"id",$cellid)
}
if($passthroughTable) {
$pstableln.cells.Add($n,[PowerStartHTMLPassThroughElement]::new($n,($object."$n"),$psHtml.newEl,$cellid))
}
$c++
}
if($passthroughTable) {
$pstableln
}
$psHtml.Up().N()
$isFirst = $false
$r++
}
end {
}
}
Export-ModuleMember -Function @('New-PowerStartHTML','Add-PowerStartHTMLTable')

View File

@@ -0,0 +1,24 @@
$moduleRoot = Resolve-Path "$PSScriptRoot\.."
$moduleName = "VMware-vCD-TenantReport"
Describe "General project validation: $moduleName" {
$scripts = Get-ChildItem $moduleRoot -Include *.ps1, *.psm1, *.psd1 -Recurse
# TestCases are splatted to the script so we need hashtables
$testCase = $scripts | Foreach-Object {@{file = $_}}
It "Script <file> should be valid powershell" -TestCases $testCase {
param($file)
$file.fullname | Should Exist
$contents = Get-Content -Path $file.fullname -ErrorAction Stop
$errors = $null
$null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors)
$errors.Count | Should Be 0
}
It "Module '$moduleName' can import cleanly" {
{Import-Module (Join-Path $moduleRoot "$moduleName.psd1") -force } | Should Not Throw
}
}

View File

@@ -0,0 +1,18 @@
@{
ModuleToProcess = 'VMware.Hosted.psm1'
ModuleVersion = '1.0.0.0'
GUID = '11393D09-D6B8-4E79-B9BC-247F1BE66683'
Author = 'William Lam'
CompanyName = 'primp-industries.com'
Copyright = '(c) 2017. All rights reserved.'
Description = 'Powershell Module for VMware Fusion 10 REST API'
PowerShellVersion = '5.0'
FunctionsToExport = 'Get-HostedCommand','Connect-HostedServer','Disconnect-HostedServer','Get-HostedVM','Start-HostedVM','Stop-HostedVM','Suspend-HostedVM','Resume-HostedVM','New-HostedVM','Remove-HostedVM','Get-HostedVMSharedFolder','New-HostedVMSharedFolder','Remove-HostedVMSharedFolder','Get-HostedVMNic','Get-HostedNetworks'
PrivateData = @{
PSData = @{
Tags = @('Fusion','REST','vmrest')
LicenseUri = 'https://www.tldrlegal.com/l/mit'
ProjectUri = 'https://github.com/lamw/PowerCLI-Example-Scripts/tree/master/Modules/VMware.Hosted'
}
}
}

View File

@@ -0,0 +1,501 @@
Function Get-Confirmation {
$choice = ""
while ($choice -notmatch "[y|n]"){
$choice = read-host "Do you want to continue? (Y/N)"
}
if($choice -ne 'y') {
break
}
}
Function Connect-HostedServer {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Server,
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Username,
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Password,
[parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Protocol = "http",
[parameter(Mandatory=$false,ValueFromPipeline=$true)][int]$Port = 8697
)
$pair = $Username+":"+$Password
$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64 = [System.Convert]::ToBase64String($bytes)
$basicAuthValue = "Basic $base64"
$headers = @{Authorization = $basicAuthValue}
$Global:DefaultHostedServer = [pscustomobject] @{
Server=$Protocol + "://" + $server + ":$Port/api";
Protcol=$Protocol
Headers=$headers
}
if($DefaultHostedServer.Protcol -eq "https") {
# PowerShell Core has a nice -SkipCertificateCheck but looks like Windows does NOT :(
if($PSVersionTable.PSEdition -eq "Core") {
$Global:fusionCommand = "Invoke-Webrequest -SkipCertificateCheck "
} else {
# Needed for Windows PowerShell to handle HTTPS scenario
# https://stackoverflow.com/a/15627483
$Provider = New-Object Microsoft.CSharp.CSharpCodeProvider
$Compiler = $Provider.CreateCompiler()
$Params = New-Object System.CodeDom.Compiler.CompilerParameters
$Params.GenerateExecutable = $false
$Params.GenerateInMemory = $true
$Params.IncludeDebugInformation = $false
$Params.ReferencedAssemblies.Add("System.DLL") > $null
$TASource=@'
namespace Local.ToolkitExtensions.Net.CertificatePolicy
{
public class TrustAll : System.Net.ICertificatePolicy
{
public bool CheckValidationResult(System.Net.ServicePoint sp,System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Net.WebRequest req, int problem)
{
return true;
}
}
}
'@
$TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
$TAAssembly=$TAResults.CompiledAssembly
## We create an instance of TrustAll and attach it to the ServicePointManager
$TrustAll = $TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
[System.Net.ServicePointManager]::CertificatePolicy = $TrustAll
$Global:fusionCommand = "Invoke-Webrequest "
}
} else {
$Global:fusionCommand = "Invoke-Webrequest "
}
$Global:DefaultHostedServer
}
Function Disconnect-HostedServer {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Server
)
$Global:DefaultHostedServer = $null
}
Function Get-HostedVM {
Param (
[parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id
)
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
if($Id) {
$vmUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id
try {
$params = "-Headers `$Global:DefaultHostedServer.Headers -Uri $vmUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
$vm = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Invalid VM Id $Id"
break
}
$vmIPUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/ip"
try {
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmIPUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
$vmIPResults = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
$vmIP = $vmIPResults.ip
} catch {
$vmIP = "N/A"
}
$vmPowerUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/power"
try {
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
$vmPower = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
$vmPower = "N/A"
}
$results = [pscustomobject] @{
Id = $vm.Id;
CPU = $vm.Cpu.processors;
Memory = $vm.Memory;
PowerState = $vmPower.power_state;
IPAddress = $vmIP;
}
$results
} else {
$uri = $Global:DefaultHostedServer.Server + "/vms"
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $uri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
try {
Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Failed to list VMs"
}
}
}
Function Start-HostedVM {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id
)
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
$vmPowerUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/power"
try {
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
$vmPower = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Invalid VM Id $Id"
break
}
if($vmPower.power_state -eq "poweredOff" -or $vmPower.power_state -eq "suspended") {
try {
Write-Host "Powering on VM $Id ..."
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method PUT -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `"on`""
$command = $Global:fusionCommand + $params
$vm = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Unable to Power On VM $Id"
break
}
} else {
Write-Host "VM $Id is already Powered On"
}
}
Function Stop-HostedVM {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id,
[parameter(Mandatory=$false,ValueFromPipeline=$true)][boolean]$Soft,
[parameter(Mandatory=$false,ValueFromPipeline=$true)][boolean]$Confirm = $true
)
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
if($Confirm) {
Get-Confirmation
}
$vmPowerUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/power"
try {
$params += "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
$vmPower = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Invalid VM Id $Id"
break
}
if($vmPower.power_state -eq "poweredOn") {
if($Soft) {
try {
Write-Host "Shutting down VM $Id ..."
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method PUT -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `"shutdown`""
$command = $Global:fusionCommand + $params
$vm = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Unable to Shutdown VM $Id"
break
}
} else {
try {
Write-Host "Powering off VM $Id ..."
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method PUT -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `"off`""
$command = $Global:fusionCommand + $params
$vm = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Unable to Power Off VM $Id"
break
}
}
} else {
Write-Host "VM $Id is already Powered Off"
}
}
Function Suspend-HostedVM {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id,
[parameter(Mandatory=$false,ValueFromPipeline=$true)][boolean]$Confirm
)
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
if($Confirm) {
Get-Confirmation
}
$vmPowerUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/power"
try {
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
$vmPower = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Invalid VM Id $Id"
break
}
if($vmPower.power_state -eq "poweredOn") {
try {
Write-Host "Suspending VM $Id ..."
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method PUT -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `"suspend`""
$command = $Global:fusionCommand + $params
$vm = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Unable to suspend VM $Id"
break
}
} else {
Write-Host "VM $Id can not be suspended because it is either Powered Off or Suspended"
}
}
Function Resume-HostedVM {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id
)
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
$vmPowerUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/power"
try {
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
$vmPower = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Invalid VM Id $Id"
break
}
if($vmPower.power_state -eq "suspended") {
try {
Start-HostedVM -Id $Id
} catch {
Write-host -ForegroundColor Red "Unable to Resume VM $Id"
break
}
} else {
Write-Host "VM $Id is not Suspended"
}
}
Function New-HostedVM {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$ParentId,
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Name
)
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
$vm = Get-HostedVM -Id $ParentId
if($vm -match "Invalid VM Id") {
Write-host -ForegroundColor Red "Unable to find existing VM Id $ParentId"
break
}
$vmUri = $Global:DefaultHostedServer.Server + "/vms"
$body = @{"ParentId"="$ParentId";"Name"=$Name}
$body = $body | ConvertTo-Json
try {
Write-Host "Cloning VM $ParentId to $Name ..."
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmUri -Method POST -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `$body"
$command = $Global:fusionCommand + $params
Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Failed to Clone VM Id $ParentId"
break
}
}
Function Remove-HostedVM {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id,
[parameter(Mandatory=$false,ValueFromPipeline=$true)][boolean]$Confirm = $true
)
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
$vm = Get-HostedVM -Id $Id
if($vm -match "Invalid VM Id") {
Write-host -ForegroundColor Red "Unable to find existing VM Id $Id"
break
}
if($Confirm) {
Get-Confirmation
}
$vmUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id
try {
Write-Host "Deleting VM Id $Id ..."
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmUri -Method DELETE -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Failed to Delete VM Id $Id"
break
}
}
Function Get-HostedVMSharedFolder {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id
)
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
$folderUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/sharedfolders"
try {
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $folderUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Invalid VM Id $Id"
break
}
}
Function New-HostedVMSharedFolder {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id,
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$FolderName,
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$HostPath
)
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
$body = @{"folder_id"="$FolderName";"host_path"=$HostPath;"flags"=4}
$body = $body | ConvertTo-Json
$folderUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/sharedfolders"
try {
Write-Host "Creating new Shared Folder $FolderName to $HostPath for VM Id $Id ..."
$params += "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $folderUri -Method POST -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `$body"
$command = $Global:fusionCommand + $params
Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Failed to create Shared Folder for VM Id $Id"
break
}
}
Function Remove-HostedVMSharedFolder {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id,
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$FolderName,
[parameter(Mandatory=$false,ValueFromPipeline=$true)][boolean]$Confirm = $true
)
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
if($Confirm) {
Get-Confirmation
}
$folderUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/sharedfolders/" + $FolderName
try {
Write-Host "Removing Shared Folder $FolderName for VM Id $Id ..."
$params += "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $folderUri -Method DELETE -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Failed to remove Shared Folder for VM Id $Id"
break
}
}
Function Get-HostedVMNic {
Param (
[parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id
)
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
$vmNicUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/nic"
try {
$params += "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmNicUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
$vmNics = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Invalid VM Id $Id"
break
}
$results = @()
foreach ($vmNic in $vmNics.nics) {
$tmp = [pscustomobject] @{
Index = $vmNic.index;
Type = $vmNic.Type;
VMnet = $vmNic.Vmnet;
}
$results+=$tmp
}
$results
}
Function Get-HostedNetworks {
if(!$Global:DefaultHostedServer) {
Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer"
exit
}
$networksUri = $Global:DefaultHostedServer.Server + "/vmnet"
try {
$params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $networksUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`""
$command = $Global:fusionCommand + $params
$networks = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-host -ForegroundColor Red "Unable to retrieve Networks"
break
}
$results = @()
foreach ($network in $networks.vmnets) {
$tmp = [pscustomobject] @{
Name = $network.Name;
Type = $network.Type;
DHCP = $network.Dhcp;
Network = $network.subnet;
Netmask = $network.mask;
}
$results+=$tmp
}
$results
}

View File

@@ -0,0 +1,98 @@
{
"Type": "AUTOMATED",
"Data": {
"Name": "ICFarmJson",
"DisplayName": "FarmJsonTest",
"AccessGroup": "Root",
"Description": "created IC Farm from PS via JSON",
"Enabled": null,
"Deleting": false,
"Settings": {
"DisconnectedSessionTimeoutPolicy" : "NEVER",
"DisconnectedSessionTimeoutMinutes" : 1,
"EmptySessionTimeoutPolicy" : "AFTER",
"EmptySessionTimeoutMinutes" : 1,
"LogoffAfterTimeout" : false
},
"Desktop": null,
"DisplayProtocolSettings": {
"DefaultDisplayProtocol" : "PCOIP",
"AllowDisplayProtocolOverride" : false,
"EnableHTMLAccess" : false
},
"ServerErrorThreshold": null,
"MirageConfigurationOverrides": {
"OverrideGlobalSetting" : false,
"Enabled" : false,
"Url" : null
}
},
"AutomatedFarmSpec": {
"ProvisioningType": "INSTANT_CLONE_ENGINE",
"VirtualCenter": null,
"RdsServerNamingSpec": {
"NamingMethod": "PATTERN",
"PatternNamingSettings": {
"NamingPattern": "ICFarmVMPS",
"MaxNumberOfRDSServers": 1
}
},
"VirtualCenterProvisioningSettings": {
"EnableProvisioning": true,
"StopProvisioningOnError": true,
"MinReadyVMsOnVComposerMaintenance": 0,
"VirtualCenterProvisioningData": {
"ParentVm": "vm-rdsh-ic",
"Snapshot": "snap_5",
"Datacenter": null,
"VmFolder": "Instant_Clone_VMs",
"HostOrCluster": "vimal-cluster",
"ResourcePool": "vimal-cluster"
},
"VirtualCenterStorageSettings": {
"Datastores": [
{
"Datastore": "Datastore1",
"StorageOvercommit": "UNBOUNDED"
}
],
"UseVSan": false,
"ViewComposerStorageSettings": {
"UseSeparateDatastoresReplicaAndOSDisks": false,
"ReplicaDiskDatastore": null,
"UseNativeSnapshots": false,
"SpaceReclamationSettings": {
"ReclaimVmDiskSpace": false,
"ReclamationThresholdGB": null,
"BlackoutTimes": null
}
}
},
"VirtualCenterNetworkingSettings": {
"Nics": null
}
},
"VirtualCenterManagedCommonSettings": {
"TransparentPageSharingScope": "VM"
},
"CustomizationSettings": {
"CustomizationType": "CLONE_PREP",
"DomainAdministrator": null,
"AdContainer": "CN=Computers",
"ReusePreExistingAccounts": false,
"ClonePrepCustomizationSettings": {
"InstantCloneEngineDomainAdministrator": null,
"PowerOffScriptName": null,
"PowerOffScriptParameters": null,
"PostSynchronizationScriptName": null,
"PostSynchronizationScriptParameters": null
}
},
"RdsServerMaxSessionsData": {
"MaxSessionsType": "UNLIMITED",
"MaxSessions": null
}
},
"ManualFarmSpec": null,
"NetBiosName" : "ad-vimalg"
}

View File

@@ -1,17 +1,31 @@
{
"Type": "AUTOMATED",
"Data": {
"Name": "LCFarmTest",
"DisplayName": "Ankit LC Farm Test",
"Name": "LCFarmJson",
"DisplayName": "FarmJsonTest",
"AccessGroup": "Root",
"Description": "created LC Farm from PS",
"Description": "created LC Farm from PS via JSON",
"Enabled": null,
"Deleting": false,
"Settings": null,
"Settings": {
"DisconnectedSessionTimeoutPolicy" : "NEVER",
"DisconnectedSessionTimeoutMinutes" : 1,
"EmptySessionTimeoutPolicy" : "AFTER",
"EmptySessionTimeoutMinutes" : 1,
"LogoffAfterTimeout" : false
},
"Desktop": null,
"DisplayProtocolSettings": null,
"DisplayProtocolSettings": {
"DefaultDisplayProtocol" : "PCOIP",
"AllowDisplayProtocolOverride" : false,
"EnableHTMLAccess" : false
},
"ServerErrorThreshold": null,
"MirageConfigurationOverrides": null
"MirageConfigurationOverrides": {
"OverrideGlobalSetting" : false,
"Enabled" : false,
"Url" : null
}
},
"AutomatedFarmSpec": {
"ProvisioningType": "VIEW_COMPOSER",
@@ -19,7 +33,7 @@
"RdsServerNamingSpec": {
"NamingMethod": "PATTERN",
"PatternNamingSettings": {
"NamingPattern": "LCFarmVM_PS",
"NamingPattern": "LCFarmVMPS",
"MaxNumberOfRDSServers": 1
}
},
@@ -28,17 +42,17 @@
"StopProvisioningOnError": true,
"MinReadyVMsOnVComposerMaintenance": 0,
"VirtualCenterProvisioningData": {
"ParentVm": "Win_Server_2012_R2",
"Snapshot": "Snap_RDS",
"ParentVm": "RDSServer",
"Snapshot": "RDS_SNAP1",
"Datacenter": null,
"VmFolder": "AnkitPoolVM",
"HostOrCluster": "cls",
"ResourcePool": "cls"
"VmFolder": "Praveen",
"HostOrCluster": "CS-1",
"ResourcePool": "CS-1"
},
"VirtualCenterStorageSettings": {
"Datastores": [
{
"Datastore": "datastore1 (5)",
"Datastore": "Datastore1",
"StorageOvercommit": "UNBOUNDED"
}
],
@@ -67,7 +81,7 @@
"AdContainer": "CN=Computers",
"ReusePreExistingAccounts": false,
"SysprepCustomizationSettings": {
"CustomizationSpec": "RDSH_Cust2"
"CustomizationSpec": "PraveenCust"
}
},
"RdsServerMaxSessionsData": {
@@ -76,5 +90,5 @@
}
},
"ManualFarmSpec": null,
"NetBiosName" : "adankit"
"NetBiosName" : "adviewdev"
}

View File

@@ -7,17 +7,31 @@
"Description": "Manual PS Test",
"Enabled": null,
"Deleting": false,
"Settings": null,
"Settings": {
"DisconnectedSessionTimeoutPolicy" : "NEVER",
"DisconnectedSessionTimeoutMinutes" : 1,
"EmptySessionTimeoutPolicy" : "AFTER",
"EmptySessionTimeoutMinutes" : 1,
"LogoffAfterTimeout" : false
},
"Desktop": null,
"DisplayProtocolSettings": null,
"DisplayProtocolSettings": {
"DefaultDisplayProtocol" : "PCOIP",
"AllowDisplayProtocolOverride" : false,
"EnableHTMLAccess" : false
},
"ServerErrorThreshold": null,
"MirageConfigurationOverrides": null
"MirageConfigurationOverrides": {
"OverrideGlobalSetting" : false,
"Enabled" : false,
"Url" : null
}
},
"AutomatedFarmSpec": null,
"ManualFarmSpec": {
"RdsServers": [
{
"rdsServer": "WIN-ORKA1Q8B0P7"
"rdsServer": "RDSServer.adviewdev.eng.vmware.com"
}
]
}

View File

@@ -5,7 +5,44 @@
"AccessGroup": "Root",
"Description": "create full clone via JSON"
},
"DesktopSettings": null,
"DesktopSettings": {
"enabled": true,
"deleting": false,
"connectionServerRestrictions": null,
"logoffSettings": {
"powerPolicy": "TAKE_NO_POWER_ACTION",
"automaticLogoffPolicy": "NEVER",
"automaticLogoffMinutes": 120,
"allowUsersToResetMachines": false,
"allowMultipleSessionsPerUser": false,
"deleteOrRefreshMachineAfterLogoff": "NEVER",
"refreshOsDiskAfterLogoff": "NEVER",
"refreshPeriodDaysForReplicaOsDisk": 5,
"refreshThresholdPercentageForReplicaOsDisk": 10
},
"displayProtocolSettings": {
"supportedDisplayProtocols": ["PCOIP", "BLAST" ],
"defaultDisplayProtocol": "BLAST",
"allowUsersToChooseProtocol": true,
"pcoipDisplaySettings": {
"renderer3D": "DISABLED",
"enableGRIDvGPUs": false,
"vRamSizeMB": 96,
"maxNumberOfMonitors": 3,
"maxResolutionOfAnyOneMonitor": "WSXGA_PLUS"
},
"enableHTMLAccess": true
},
"flashSettings": {
"quality": "NO_CONTROL",
"throttling": "DISABLED"
},
"mirageConfigurationOverrides": {
"overrideGlobalSetting": false,
"enabled": false,
"url": false
}
},
"Type": "AUTOMATED",
"AutomatedDesktopSpec": {
"ProvisioningType": "VIRTUAL_CENTER",
@@ -69,7 +106,7 @@
"NoCustomizationSettings": {
"DoNotPowerOnVMsAfterCreation": false
},
"SysprepCustomizationSettings": null,
"SysprepCustomizationSettings": {"customizationSpec" : "praveencust"},
"QuickprepCustomizationSettings": null,
"CloneprepCustomizationSettings": null
}
@@ -77,6 +114,5 @@
"ManualDesktopSpec": null,
"RdsDesktopSpec": null,
"GlobalEntitlementData": null,
"NetBiosName" : "adviewdev",
"SysPrepName" : "praveencust"
"NetBiosName" : "adviewdev"
}

View File

@@ -5,7 +5,44 @@
"AccessGroup": "ROOT",
"Description": "create instant pool"
},
"DesktopSettings": null,
"DesktopSettings": {
"enabled": true,
"deleting": false,
"connectionServerRestrictions": null,
"logoffSettings": {
"powerPolicy": "ALWAYS_POWERED_ON",
"automaticLogoffPolicy": "NEVER",
"automaticLogoffMinutes": 120,
"allowUsersToResetMachines": false,
"allowMultipleSessionsPerUser": false,
"deleteOrRefreshMachineAfterLogoff": "DELETE",
"refreshOsDiskAfterLogoff": "NEVER",
"refreshPeriodDaysForReplicaOsDisk": 5,
"refreshThresholdPercentageForReplicaOsDisk": 10
},
"displayProtocolSettings": {
"supportedDisplayProtocols": ["PCOIP", "BLAST" ],
"defaultDisplayProtocol": "BLAST",
"allowUsersToChooseProtocol": true,
"pcoipDisplaySettings": {
"renderer3D": "DISABLED",
"enableGRIDvGPUs": false,
"vRamSizeMB": 96,
"maxNumberOfMonitors": 3,
"maxResolutionOfAnyOneMonitor": "WSXGA_PLUS"
},
"enableHTMLAccess": true
},
"flashSettings": {
"quality": "NO_CONTROL",
"throttling": "DISABLED"
},
"mirageConfigurationOverrides": {
"overrideGlobalSetting": false,
"enabled": false,
"url": false
}
},
"Type": "AUTOMATED",
"AutomatedDesktopSpec": {
"ProvisioningType": "INSTANT_CLONE_ENGINE",

View File

@@ -5,7 +5,44 @@
"AccessGroup": "Root",
"Description": "created linkedclone pool from ps"
},
"DesktopSettings": null,
"DesktopSettings": {
"enabled": true,
"deleting": false,
"connectionServerRestrictions": null,
"logoffSettings": {
"powerPolicy": "TAKE_NO_POWER_ACTION",
"automaticLogoffPolicy": "NEVER",
"automaticLogoffMinutes": 120,
"allowUsersToResetMachines": false,
"allowMultipleSessionsPerUser": false,
"deleteOrRefreshMachineAfterLogoff": "NEVER",
"refreshOsDiskAfterLogoff": "NEVER",
"refreshPeriodDaysForReplicaOsDisk": 5,
"refreshThresholdPercentageForReplicaOsDisk": 10
},
"displayProtocolSettings": {
"supportedDisplayProtocols": ["RDP","PCOIP", "BLAST" ],
"defaultDisplayProtocol": "PCOIP",
"allowUsersToChooseProtocol": true,
"pcoipDisplaySettings": {
"renderer3D": "DISABLED",
"enableGRIDvGPUs": false,
"vRamSizeMB": 96,
"maxNumberOfMonitors": 3,
"maxResolutionOfAnyOneMonitor": "WSXGA_PLUS"
},
"enableHTMLAccess": true
},
"flashSettings": {
"quality": "NO_CONTROL",
"throttling": "DISABLED"
},
"mirageConfigurationOverrides": {
"overrideGlobalSetting": false,
"enabled": false,
"url": null
}
},
"Type": "AUTOMATED",
"AutomatedDesktopSpec": {
"ProvisioningType": "VIEW_COMPOSER",
@@ -33,7 +70,7 @@
"Template": null,
"ParentVm": "Agent_pra",
"Snapshot": "kb-hotfix",
"Datacenter": null,
"Datacenter": "Dev-Dc",
"VmFolder": "Praveen",
"HostOrCluster": "CS-1",
"ResourcePool": "CS-1"
@@ -52,7 +89,8 @@
"UseNativeSnapshots": false,
"SpaceReclamationSettings": {
"ReclaimVmDiskSpace": false,
"ReclamationThresholdGB": null
"ReclamationThresholdGB": null,
"BlackoutTimes" : null
},
"PersistentDiskSettings": {
"RedirectWindowsProfile": false,
@@ -75,19 +113,31 @@
}
},
"VirtualCenterNetworkingSettings": {
"Nics": null
"Nics": [
{
"Nic": "nicName",
"NetworkLabelAssignmentSpecs": [
{
"Enabled" : false,
"networkLabel" : null,
"maxLabelType" : null,
"maxLabel" : null
}
]
}
]
}
},
"VirtualCenterManagedCommonSettings": {
"TransparentPageSharingScope": "VM"
},
"CustomizationSettings": {
"CustomizationType": "QUICK_PREP",
"DomainAdministrator": null,
"CustomizationType": "SYS_PREP",
"DomainAdministrator": "administrator",
"AdContainer": "CN=Computers",
"ReusePreExistingAccounts": false,
"NoCustomizationSettings": null,
"SysprepCustomizationSettings": null,
"SysprepCustomizationSettings": {"customizationSpec" : "praveencust"},
"QuickprepCustomizationSettings": {
"PowerOffScriptName": null,
"PowerOffScriptParameters": null,
@@ -99,7 +149,6 @@
},
"ManualDesktopSpec": null,
"RdsDesktopSpec": null,
"GlobalEntitlementData": null,
"NetBiosName" : "adviewdev",
"SysPrepName" : "praveencust"
"GlobalEntitlementData": null,
"NetBiosName" : "adviewdev"
}

View File

@@ -5,7 +5,44 @@
"AccessGroup": "ROOT",
"Description": "Manual pool creation"
},
"DesktopSettings": null,
"DesktopSettings": {
"enabled": true,
"deleting": false,
"connectionServerRestrictions": null,
"logoffSettings": {
"powerPolicy": "TAKE_NO_POWER_ACTION",
"automaticLogoffPolicy": "NEVER",
"automaticLogoffMinutes": 120,
"allowUsersToResetMachines": false,
"allowMultipleSessionsPerUser": false,
"deleteOrRefreshMachineAfterLogoff": "NEVER",
"refreshOsDiskAfterLogoff": "NEVER",
"refreshPeriodDaysForReplicaOsDisk": 5,
"refreshThresholdPercentageForReplicaOsDisk": 10
},
"displayProtocolSettings": {
"supportedDisplayProtocols": ["PCOIP", "BLAST" ],
"defaultDisplayProtocol": "BLAST",
"allowUsersToChooseProtocol": true,
"pcoipDisplaySettings": {
"renderer3D": "DISABLED",
"enableGRIDvGPUs": false,
"vRamSizeMB": 96,
"maxNumberOfMonitors": 3,
"maxResolutionOfAnyOneMonitor": "WSXGA_PLUS"
},
"enableHTMLAccess": true
},
"flashSettings": {
"quality": "NO_CONTROL",
"throttling": "DISABLED"
},
"mirageConfigurationOverrides": {
"overrideGlobalSetting": false,
"enabled": false,
"url": false
}
},
"Type": "MANUAL",
"AutomatedDesktopSpec": null,
"ManualDesktopSpec": {
@@ -16,7 +53,7 @@
"Source": "VIRTUAL_CENTER",
"Machines": [
{
"Machine" : "PowerCLI-VM"
"Machine" : "Praveen_Agent"
}
],
"VirtualCenter": null,
@@ -32,4 +69,5 @@
},
"RdsDesktopSpec": null,
"GlobalEntitlementData": null
}

View File

@@ -0,0 +1,27 @@
{
"Base": {
"Name" : "RdsJson",
"DisplayName": "TestRDSPS",
"AccessGroup": "Root",
"Description": "Testing PS"
},
"DesktopSettings": {
"enabled": true,
"deleting": false,
"connectionServerRestrictions": null,
"logoffSettings": null,
"displayProtocolSettings": null,
"flashSettings": {
"quality": "NO_CONTROL",
"throttling": "DISABLED"
},
"mirageConfigurationOverrides": null
},
"Type": "RDS",
"AutomatedDesktopSpec": null,
"ManualDesktopSpec": null,
"RdsDesktopSpec": {
"Farm": "test1"
},
"GlobalEntitlementData": null
}

View File

@@ -1,16 +0,0 @@
{
"Base": {
"Name" : "RdsJson",
"DisplayName": "TestRDSPS",
"AccessGroup": "Root",
"Description": "Testing PS"
},
"DesktopSettings": null,
"Type": "RDS",
"AutomatedDesktopSpec": null,
"ManualDesktopSpec": null,
"RdsDesktopSpec": {
"Farm": "Farm2"
},
"GlobalEntitlementData": null
}

View File

@@ -0,0 +1,20 @@
Prerequisites/Steps to use this module:
1. This module only works for Horizon product E.g. Horizon 7.0.2 and later.
2. Install the latest version of Powershell, PowerCLI(6.5) or (later version via psgallery).
3. Import HorizonView module by running: Import-Module VMware.VimAutomation.HorizonView.
4. Import "VMware.Hv.Helper" module by running: Import-Module -Name "location of this module" or Get-Module -ListAvailable 'VMware.Hv.Helper' | Import-Module.
5. Get-Command -Module "This module Name" to list all available functions or Get-Command -Module 'VMware.Hv.Helper'.
# Example script to connect view API service of Connection Server:
Import-Module VMware.VimAutomation.HorizonView
# Connection to view API service
$hvServer = Connect-HVServer -server <connection server IP/FQDN>
$hvServices = $hvserver.ExtensionData
$csList = $hvServices.ConnectionServer.ConnectionServer_List()
# Load this module
Get-Module -ListAvailable 'VMware.Hv.Helper' | Import-Module
Get-Command -Module 'VMware.Hv.Helper'
# Use advanced functions of this module
New-HVPool -spec 'path to InstantClone.json file'

View File

@@ -0,0 +1,22 @@
{
"generalData.clientMaxSessionTimePolicy": "TIMEOUT_AFTER",
"generalData.clientMaxSessionTimeMinutes": 600,
"generalData.clientIdleSessionTimeoutPolicy": "NEVER",
"generalData.clientIdleSessionTimeoutMinutes": null,
"generalData.clientSessionTimeoutMinutes": 1200,
"generalData.desktopSSOTimeoutPolicy": "DISABLE_AFTER",
"generalData.desktopSSOTimeoutMinutes": 15,
"generalData.applicationSSOTimeoutPolicy": "ALWAYS_ENABLED",
"generalData.applicationSSOTimeoutMinutes": null,
"generalData.viewAPISessionTimeoutMinutes": 10,
"generalData.preLoginMessage": null,
"generalData.displayWarningBeforeForcedLogoff": true,
"generalData.forcedLogoffTimeoutMinutes": 5,
"generalData.forcedLogoffMessage": "Your desktop is scheduled for an important update and will shut down in 5 minutes. Please save any unsaved work now",
"generalData.enableServerInSingleUserMode": false,
"generalData.storeCALOnBroker": false,
"generalData.storeCALOnClient": false,
"securityData.reauthSecureTunnelAfterInterruption": true,
"securityData.messageSecurityMode": "ENHANCED",
"securityData.enableIPSecForSecurityServerPairing": true
}

View File

@@ -27,6 +27,10 @@
<TableColumnHeader>
<Width>16</Width>
<Label>User Assignment</Label>
</TableColumnHeader>
<TableColumnHeader>
<Width>8</Width>
<Label>Entitled</Label>
</TableColumnHeader>
<TableColumnHeader>
<Width>7</Width>
@@ -56,10 +60,23 @@
<TableColumnItem>
<ScriptBlock>$_.desktopSummaryData.userAssignment</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<TableColumnItem>
<ScriptBlock>
$filterContains = Get-HVQueryFilter localData.desktops -contains ([VMware.Hv.DesktopId[]]$_.id)
$GlobalfilterContains = Get-HVQueryFilter localData.desktops -contains ([VMware.Hv.DesktopId[]]$_.id)
Try {
$results += Get-HVQueryResult -EntityType EntitledUserOrGroupLocalSummaryView -Filter $filterContains
$results += Get-HVQueryResult -EntityType EntitledUserOrGroupGlobalSummaryView -Filter $GlobalfilterContains
} Catch {
#Do nothing
}
$results.length
</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>$_.desktopSummaryData.enabled</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<TableColumnItem>
<ScriptBlock>$_.desktopSummaryData.numSessions</ScriptBlock>
</TableColumnItem>
</TableColumnItems>
@@ -97,6 +114,20 @@
<ScriptBlock>$_.desktopSummaryData.userAssignment</ScriptBlock>
</ListItem>
<ListItem>
<Label>Entitled</Label>
<ScriptBlock>
$filterContains = Get-HVQueryFilter localData.desktops -contains ([VMware.Hv.DesktopId[]]$_.id)
$GlobalfilterContains = Get-HVQueryFilter localData.desktops -contains ([VMware.Hv.DesktopId[]]$_.id)
Try {
$results += Get-HVQueryResult -EntityType EntitledUserOrGroupLocalSummaryView -Filter $filterContains
$results += Get-HVQueryResult -EntityType EntitledUserOrGroupGlobalSummaryView -Filter $GlobalfilterContains
} Catch {
#Do nothing
}
$results.length
</ScriptBlock>
</ListItem>
<ListItem>
<Label>Enabled</Label>
<ScriptBlock>$_.desktopSummaryData.enabled</ScriptBlock>
</ListItem>

View File

@@ -12,7 +12,7 @@
# RootModule = ''
# Version number of this module.
ModuleVersion = '1.0'
ModuleVersion = '1.1'
# ID used to uniquely identify this module
GUID = '6d3f7fb5-4e52-43d8-91e1-f65f72532a1d'

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,692 @@
Function Get-VMCCommand {
<#
.NOTES
===========================================================================
Created by: VMware
Date: 11/17/2017
Organization: VMware
Blog: http://vmware.com/go/powercli
Twitter: @powercli
===========================================================================
.SYNOPSIS
Returns all cmdlets for VMware Cloud on AWS
.DESCRIPTION
This cmdlet will allow you to return all cmdlets included in the VMC module
.EXAMPLE
Get-VMCCommand
.EXAMPLE
Get-Command -Module VMware.VMC
.NOTES
You can either use this cmdlet or the Get-Command cmdlet as seen in Example 2
#>
Get-command -Module VMware.VimAutomation.Vmc
Get-Command -Module VMware.VMC
}
Function Connect-VMCVIServer {
<#
.NOTES
===========================================================================
Created by: VMware
Date: 11/17/2017
Organization: VMware
Blog: http://vmware.com/go/powercli
Twitter: @powercli
===========================================================================
.SYNOPSIS
Cmdlet to connect to your VMC vCenter Server
.DESCRIPTION
This will connect you to both the VMC ViServer as well as the CiSServer at the same time.
.EXAMPLE
Connect-VMCVIServer -Server <VMC vCenter address> -User <Username> -Password <Password>
.NOTES
Easiest way is to pipe through your credentials from Get-VMCSDDCDefaultCredential
#>
Param (
[Parameter(Mandatory=$true)]$Org,
[Parameter(Mandatory=$true)]$Sddc,
[switch]$Autologin
)
If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else {
$creds = Get-VMCSDDCDefaultCredential -Org $Org -Sddc $Sddc
Write-Host "Connecting to VMC vCenter Server" $creds.vc_public_ip
Connect-VIServer -Server $creds.vc_public_ip -User $creds.cloud_username -Password $creds.cloud_password | Add-Member -MemberType Noteproperty -Name Location -Value "VMC"
Write-Host "Connecting to VMC CIS Endpoint" $creds.vc_public_ip
Connect-CisServer -Server $creds.vc_public_ip -User $creds.cloud_username -Password $creds.cloud_password | Add-Member -MemberType Noteproperty -Name Location -Value "VMC"
}
}
Function Get-VMCOrg {
<#
.NOTES
===========================================================================
Created by: VMware
Date: 11/17/2017
Organization: VMware
Blog: http://vmware.com/go/powercli
Twitter: @powercli
===========================================================================
.SYNOPSIS
Return the Orgs that you are a part of
.DESCRIPTION
Depending on what you've purchased, you may be a part of one or more VMC Orgs. This will return your orgs
.EXAMPLE
Get-VMCOrg
.EXAMPLE
Get-VMCOrg -Name <Org Name>
.NOTES
Return all the info about the orgs you are a part of
#>
Param (
[Parameter(Mandatory=$false)]$Name
)
If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use Connect-VMC to connect" } Else {
$orgService = Get-VMCService com.vmware.vmc.orgs
if ($PSBoundParameters.ContainsKey("Name")){
$orgs = $orgService.list() | Where {$_.display_name -match $Name}
} Else {
$orgs = $orgService.list()
}
$Orgs | Select display_name, name, user_name, created, id
}
}
Function Get-VMCSDDC {
<#
.NOTES
===========================================================================
Created by: VMware
Date: 11/17/2017
Organization: VMware
Blog: http://vmware.com/go/powercli
Twitter: @powercli
===========================================================================
.SYNOPSIS
Returns all of the SDDCs you are associated to
.DESCRIPTION
Returns all of the SDDCs ayou are associated to
.EXAMPLE
Get-VMCSDDC -Org <Org Name>
.EXAMPLE
Get-VMCSDDC -Name <SDDC Name> -Org <Org Name>
#>
Param (
[Parameter(Mandatory=$True)]$Org,
[Parameter(Mandatory=$false)]$Name
)
If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else {
if ($PSBoundParameters.ContainsKey("Org")){
$orgs = Get-VMCOrg -Name $Org
} else {
$orgs = Get-VMCOrg
}
foreach ($org in $orgs) {
$orgID = $org.ID
$sddcService = Get-VMCService com.vmware.vmc.orgs.sddcs
if ($PSBoundParameters.ContainsKey("Name")){
$sddcService.list($OrgID) | Where {$_.name -match $Name}
} Else {
$sddcService.list($OrgID)
}
}
}
}
Function Get-VMCTask {
<#
.NOTES
===========================================================================
Created by: VMware
Date: 11/17/2017
Organization: VMware
Blog: http://vmware.com/go/powercli
Twitter: @powercli
===========================================================================
.SYNOPSIS
Returns all of the VMC Tasks
.DESCRIPTION
Returns all of the VMC Tasks that have either occurred or are in process
.EXAMPLE
Get-VMCTask
#>
Param (
[Parameter(Mandatory=$True)]$Org
)
If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else {
if ($PSBoundParameters.ContainsKey("Org")){
$orgs = Get-VMCOrg -Name $Org
} else {
$orgs = Get-VMCOrg
}
foreach ($org in $orgs) {
$orgID = $org.ID
$taskService = Get-VMCService com.vmware.vmc.orgs.tasks
$taskService.list($OrgID) | Select * -ExcludeProperty Help
}
}
}
Function Get-VMCSDDCDefaultCredential {
<#
.NOTES
===========================================================================
Created by: VMware
Date: 11/17/2017
Organization: VMware
Blog: http://vmware.com/go/powercli
Twitter: @powercli
===========================================================================
.SYNOPSIS
Returns the default credential for the SDDC
.DESCRIPTION
Returns the default credential for the sddc
.EXAMPLE
Get-VMCSDDCDefaultCredential -Org <Org Name>
.EXAMPLE
Get-VMCSDDCDefaultCredential -Sddc <SDDC Name> -Org <Org Name>
#>
Param (
[Parameter(Mandatory=$true)]$Org,
[Parameter(Mandatory=$false)]$Sddc
)
If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else {
if ($PSBoundParameters.ContainsKey("Sddc")){
$sddcs = Get-VMCSDDC -Name $Sddc -Org $Org
} else {
$sddcs = Get-VMCSDDC -Org $Org
}
foreach ($sddc in $sddcs) {
$sddc.resource_config | Select-object vc_url, vc_management_ip, vc_public_ip, cloud_username, cloud_password
}
}
}
Function Get-VMCSDDCPublicIP {
<#
.NOTES
===========================================================================
Created by: VMware
Date: 11/17/2017
Organization: VMware
Blog: http://vmware.com/go/powercli
Twitter: @powercli
===========================================================================
.SYNOPSIS
Returns your Public IPs
.DESCRIPTION
Returns your Public IPs
.EXAMPLE
Get-VMCSDDCPublicIP -Org <Org Name>
.EXAMPLE
Get-VMCSDDCPublicIP -Sddc <SDDC Name> -Org <Org Name>
.NOTES
Return your Public IPs that you have assigned to your account
#>
Param (
[Parameter(Mandatory=$true)]$Org,
[Parameter(Mandatory=$false)]$Sddc
)
If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else {
if ($PSBoundParameters.ContainsKey("Sddc")){
$sddcs = Get-VMCSDDC -Name $Sddc -Org $Org
} else {
$sddcs = Get-VMCSDDC -Org $Org
}
foreach ($sddc in $sddcs) {
$sddc.resource_config.Public_ip_pool
}
}
}
Function Get-VMCVMHost {
Param (
[Parameter(Mandatory=$false)]$Sddc,
[Parameter(Mandatory=$true)]$Org
)
If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else {
if ($PSBoundParameters.ContainsKey("Sddc")){
$sddcs = Get-VMCSDDC -Name $Sddc -Org $Org
} else {
$sddcs = Get-VMCSDDC -Org $Org
}
$results = @()
foreach ($sddc in $sddcs) {
foreach ($vmhost in $sddc.resource_config.esx_hosts) {
$tmp = [pscustomobject] @{
esx_id = $vmhost.esx_id;
name = $vmhost.name;
hostname = $vmhost.hostname;
esx_state = $vmhost.esx_state;
sddc_id = $sddc.id;
org_id = $sddc.org_id;
}
$results += $tmp
}
$results
}
}
}
Function Get-VMCSDDCVersion {
<#
.NOTES
===========================================================================
Created by: VMware
Date: 11/17/2017
Organization: VMware
Blog: http://vmware.com/go/powercli
Twitter: @powercli
===========================================================================
.SYNOPSIS
Returns SDDC Version
.DESCRIPTION
Returns Version of the SDDC
.EXAMPLE
Get-VMCSDDCVersion -Name <SDDC Name> -Org <Org Name>
#>
Param (
[Parameter(Mandatory=$True)]$Org,
[Parameter(Mandatory=$false)]$Name
)
If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else {
if ($PSBoundParameters.ContainsKey("Org")){
$orgs = Get-VMCOrg -Name $Org
} else {
$orgs = Get-VMCOrg
}
foreach ($org in $orgs) {
$orgID = $org.ID
$sddcService = Get-VMCService com.vmware.vmc.orgs.sddcs
if ($PSBoundParameters.ContainsKey("Name")){
($sddcService.list($OrgID) | Where {$_.name -match $Name}).resource_config.sddc_manifest | Select *version
} Else {
($sddcService.list($OrgID)).resource_config.sddc_manifest | Select *version
}
}
}
}
Function Get-VMCFirewallRule {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/19/2017
Organization: VMware
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Retruns VMC Firewall Rules for a given Gateway (MGW or CGW)
.DESCRIPTION
Retruns VMC Firewall Rules for a given Gateway (MGW or CGW)
.EXAMPLE
Get-VMCFirewallRule -OrgName <Org Name> -SDDCName <SDDC Name> -GatewayType <MGW or CGW>
.EXAMPLE
Get-VMCFirewallRule -OrgName <Org Name> -SDDCName <SDDC Name> -GatewayType <MGW or CGW> -ShowAll
#>
param(
[Parameter(Mandatory=$false)][String]$SDDCName,
[Parameter(Mandatory=$false)][String]$OrgName,
[Parameter(Mandatory=$false)][Switch]$ShowAll,
[Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType
)
if($GatewayType -eq "MGW") {
$EdgeId = "edge-1"
} else {
$EdgeId = "edge-2"
}
$orgId = (Get-VMCOrg -Name $OrgName).Id
$sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id
$firewallConfigService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config
$firewallRules = ($firewallConfigService.get($orgId, $sddcId, $EdgeId)).firewall_rules.firewall_rules
if(-not $ShowAll) {
$firewallRules = $firewallRules | where { $_.rule_type -ne "default_policy" -and $_.rule_type -ne "internal_high" -and $_.name -ne "vSphere Cluster HA" -and $_.name -ne "Outbound Access" } | Sort-Object -Property rule_tag
} else {
$firewallRules = $firewallRules | Sort-Object -Property rule_tag
}
$results = @()
foreach ($firewallRule in $firewallRules) {
if($firewallRule.source.ip_address.Count -ne 0) {
$source = $firewallRule.source.ip_address
} else { $source = "ANY" }
if($firewallRule.application.service.protocol -ne $null) {
$protocol = $firewallRule.application.service.protocol
} else { $protocol = "ANY" }
if($firewallRule.application.service.port -ne $null) {
$port = $firewallRule.application.service.port
} else { $port = "ANY" }
$tmp = [pscustomobject] @{
ID = $firewallRule.rule_id;
Name = $firewallRule.name;
Type = $firewallRule.rule_type;
Action = $firewallRule.action;
Protocol = $protocol;
Port = $port;
SourceAddress = $source
DestinationAddress = $firewallRule.destination.ip_address;
}
$results+=$tmp
}
$results
}
Function Export-VMCFirewallRule {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/19/2017
Organization: VMware
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Exports all "customer" created VMC Firewall Rules to JSON file
.DESCRIPTION
Exports all "customer" created VMC Firewall Rules to JSON file
.EXAMPLE
Export-VMCFirewallRule -OrgName <Org Name> -SDDCName <SDDC Name> -GatewayType <MGW or CGW> -Path "C:\Users\lamw\Desktop\VMCFirewallRules.json"
#>
param(
[Parameter(Mandatory=$false)][String]$SDDCName,
[Parameter(Mandatory=$false)][String]$OrgName,
[Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType,
[Parameter(Mandatory=$false)][String]$Path
)
if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break }
if($GatewayType -eq "MGW") {
$EdgeId = "edge-1"
} else {
$EdgeId = "edge-2"
}
$orgId = (Get-VMCOrg -Name $OrgName).Id
$sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id
if(-not $orgId) {
Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input"
break
}
if(-not $sddcId) {
Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input"
break
}
$firewallConfigService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config
$firewallRules = ($firewallConfigService.get($orgId, $sddcId, $EdgeId)).firewall_rules.firewall_rules
if(-not $ShowAll) {
$firewallRules = $firewallRules | where { $_.rule_type -ne "default_policy" -and $_.rule_type -ne "internal_high" -and $_.name -ne "vSphere Cluster HA" -and $_.name -ne "Outbound Access" } | Sort-Object -Property rule_tag
} else {
$firewallRules = $firewallRules | Sort-Object -Property rule_tag
}
$results = @()
$count = 0
foreach ($firewallRule in $firewallRules) {
if($firewallRule.source.ip_address.Count -ne 0) {
$source = $firewallRule.source.ip_address
} else {
$source = "ANY"
}
$tmp = [pscustomobject] @{
Name = $firewallRule.name;
Action = $firewallRule.action;
Protocol = $firewallRule.application.service.protocol;
Port = $firewallRule.application.service.port;
SourcePort = $firewallRule.application.service.source_port;
ICMPType = $firewallRule.application.service.icmp_type;
SourceAddress = $firewallRule.source.ip_address;
DestinationAddress = $firewallRule.destination.ip_address;
Enabled = $firewallRule.enabled;
Logging = $firewallRule.logging_enabled;
}
$count+=1
$results+=$tmp
}
if($Path) {
Write-Host -ForegroundColor Green "Exporting $count VMC Firewall Rules to $Path ..."
$results | ConvertTo-Json | Out-File $Path
} else {
$results | ConvertTo-Json
}
}
Function Import-VMCFirewallRule {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/19/2017
Organization: VMware
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Imports VMC Firewall Rules from exported JSON configuration file
.DESCRIPTION
Imports VMC Firewall Rules from exported JSON configuration file
.EXAMPLE
Import-VMCFirewallRule -OrgName <Org Name> -SDDCName <SDDC Name> -GatewayType <MGW or CGW> -Path "C:\Users\lamw\Desktop\VMCFirewallRules.json"
#>
param(
[Parameter(Mandatory=$false)][String]$SDDCName,
[Parameter(Mandatory=$false)][String]$OrgName,
[Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType,
[Parameter(Mandatory=$false)][String]$Path
)
if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break }
if($GatewayType -eq "MGW") {
$EdgeId = "edge-1"
} else {
$EdgeId = "edge-2"
}
$orgId = (Get-VMCOrg -Name $OrgName).Id
$sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id
if(-not $orgId) {
Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input"
break
}
if(-not $sddcId) {
Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input"
break
}
$firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules
$vmcFirewallRulesJSON = Get-Content -Raw $Path | ConvertFrom-Json
# Create top level Firewall Rules Object
$firewallRules = $firewallService.Help.add.firewall_rules.Create()
# Create top top level Firewall Rule Spec which will be an array of individual Firewall rules as we process them in next section
$ruleSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Create()
foreach ($vmcFirewallRule in $vmcFirewallRulesJSON) {
# Create Individual Firewall Rule Element Spec
$ruleElementSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.Create()
# AppSpec
$appSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.application.Create()
# ServiceSpec
$serviceSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.application.service.Element.Create()
$protocol = $null
if($vmcFirewallRule.Protocol -ne $null) {
$protocol = $vmcFirewallRule.Protocol
}
$serviceSpec.protocol = $protocol
# Process ICMP Type from JSON
$icmpType = $null
if($vmcFirewallRule.ICMPType -ne $null) {
$icmpType = $vmcFirewallRule.ICMPType
}
$serviceSpec.icmp_type = $icmpType
# Process Source Ports from JSON
$sourcePorts = @()
if($vmcFirewallRule.SourcePort -eq "any" -or $vmcFirewallRule.SourcePort -ne $null) {
foreach ($port in $vmcFirewallRule.SourcePort) {
$sourcePorts+=$port
}
} else {
$sourcePorts = @("any")
}
$serviceSpec.source_port = $sourcePorts
# Process Ports from JSON
$ports = @()
if($vmcFirewallRule.Port -ne "null") {
foreach ($port in $vmcFirewallRule.Port) {
$ports+=$port
}
}
$serviceSpec.port = $ports
$addSpec = $appSpec.service.Add($serviceSpec)
# Create Source Spec
$srcSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.source.Create()
$srcSpec.exclude = $false
# Process Source Address from JSON
$sourceAddess = @()
if($vmcFirewallRule.SourceAddress -ne "null") {
foreach ($address in $vmcFirewallRule.SourceAddress) {
$sourceAddess+=$address
}
}
$srcSpec.ip_address = $sourceAddess;
# Create Destination Spec
$destSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.destination.Create()
$destSpec.exclude = $false
# Process Destination Address from JSON
$destinationAddess = @()
if($vmcFirewallRule.DestinationAddress -ne "null") {
foreach ($address in $vmcFirewallRule.DestinationAddress) {
$destinationAddess+=$address
}
}
$destSpec.ip_address = $destinationAddess
# Add various specs
if($vmcFirewallRule.Protocol -ne $null -and $vmcFirewallRule.port -ne $null) {
$ruleElementSpec.application = $appSpec
}
$ruleElementSpec.source = $srcSpec
$ruleElementSpec.destination = $destSpec
$ruleElementSpec.rule_type = "user"
# Process Enabled from JSON
$fwEnabled = $false
if($vmcFirewallRule.Enabled -eq "true") {
$fwEnabled = $true
}
$ruleElementSpec.enabled = $fwEnabled
# Process Logging from JSON
$loggingEnabled = $false
if($vmcFirewallRule.Logging -eq "true") {
$loggingEnabled = $true
}
$ruleElementSpec.logging_enabled = $loggingEnabled
$ruleElementSpec.action = $vmcFirewallRule.Action
$ruleElementSpec.name = $vmcFirewallRule.Name
# Add the individual FW rule spec into our overall firewall rules array
Write-host "Creating VMC Firewall Rule Spec:" $vmcFirewallRule.Name "..."
$ruleSpecAdd = $ruleSpec.Add($ruleElementSpec)
}
$firewallRules.firewall_rules = $ruleSpec
Write-host "Adding VMC Firewall Rules ..."
$firewallRuleAdd = $firewallService.add($orgId,$sddcId,$EdgeId,$firewallRules)
}
Function Remove-VMCFirewallRule {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/19/2017
Organization: VMware
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Removes VMC Firewall Rule given Rule Id
.DESCRIPTION
Removes VMC Firewall Rule given Rule Id
.EXAMPLE
Import-VMCFirewallRule -OrgName <Org Name> -SDDCName <SDDC Name> -GatewayType <MGW or CGW> -RuleId <Rule Id>
#>
param(
[Parameter(Mandatory=$false)][String]$SDDCName,
[Parameter(Mandatory=$false)][String]$OrgName,
[Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType,
[Parameter(Mandatory=$false)][String]$RuleId
)
if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break }
if($GatewayType -eq "MGW") {
$EdgeId = "edge-1"
} else {
$EdgeId = "edge-2"
}
$orgId = (Get-VMCOrg -Name $OrgName).Id
$sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id
if(-not $orgId) {
Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input"
break
}
if(-not $sddcId) {
Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input"
break
}
$firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules
Write-Host "Removing VMC Firewall Rule Id $RuleId ..."
$firewallService.delete($orgId,$sddcId,$EdgeId,$RuleId)
}
Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', 'Get-VMCSDDCVersion', 'Get-VMCFirewallRule', 'Export-VMCFirewallRule', 'Import-VMCFirewallRule', 'Remove-VMCFirewallRule'

View File

@@ -83,6 +83,13 @@ New-VIProperty -Name EncryptionKeyId -ObjectType HardDisk -Value {
}
} -BasedOnExtensionProperty 'Backing.KeyId' -Force | Out-Null
New-VIProperty -Name KMSserver -ObjectType VMHost -Value {
Param ($VMHost)
if ($VMHost.CryptoSafe) {
$VMHost.ExtensionData.Runtime.CryptoKeyId.ProviderId.Id
}
} -BasedOnExtensionProperty 'Runtime.CryptoKeyId.ProviderId.Id' -Force | Out-Null
Function Enable-VMHostCryptoSafe {
<#
.SYNOPSIS
@@ -875,7 +882,7 @@ Function Set-VMEncryptionKey {
C:\PS>$VM|Set-VMEncryptionKey -KMSClusterId $KMSCluster.Id -Deep
Deep rekeys the VM Home and all its disks using a new key.
The key is generted from the KMS whose clusterId is $KMSCluster.Id.
The key is generated from the KMS whose clusterId is $KMSCluster.Id.
.NOTES
This cmdlet assumes there is already a KMS in vCenter Server. If VM is not encrypted, the cmdlet quits.
@@ -1027,10 +1034,10 @@ Function Set-VMDiskEncryptionKey {
C:\PS>$KMSCluster = Get-KMSCluster | select -last 1
C:\PS>$VM = Get-VM -Name win2012
C:\PS>$HardDisk = get-vm $vm|Get-HardDisk
C:\PS>$HardDisk|$Set-VMEncryptionKey -VM $VM -KMSClusterId $KMSCluster.Id -Deep
C:\PS>$HardDisk| Set-VMDiskEncryptionKey -VM $VM -KMSClusterId $KMSCluster.Id -Deep
Deep rekeys all the disks of the $VM using a new key.
The key is generted from the KMS whose clusterId is $KMSCluster.Id.
The key is generated from the KMS whose clusterId is $KMSCluster.Id.
.NOTES
This cmdlet assumes there is already a KMS in vCenter Server.

View File

@@ -0,0 +1,17 @@
# Fetch Cis Server hostname and credentials
.\CisConfig.ps1
Connect-rCisServer -Server $cisServer -User $cisUser -Password $cisPswd
# Get Tag information
Get-rCisTag
# Get Tag Category information
Get-rCisTagCategory
# Get Tag Assignment information
Get-rCisTagAssignment
Disconnect-rCisServer -Server $cisServer -Confirm:$false

View File

@@ -0,0 +1,14 @@
# Fetch Cis Server hostname and credentials
.\CisConfig.ps1
Connect-rCisServer -Server $cisServer -User $cisUser -Password $cisPswd
New-rCisTagCategory -Name MyCat1 -Cardinality Single -Description 'Test Tag Category' -EntityType 'VirtualMachine'
New-rCisTag -Name MyTag1 -Category MyCat1 -Description 'Test Tag'
$vm = Get-VM | Get-Random
New-rCisTagAssignment -Entity $vm -Tag MyTag1
Get-rCisTagAssignment -Tag MyTag1
Disconnect-rCisServer -Server $cisServer -Confirm:$false

View File

@@ -0,0 +1,11 @@
# Fetch Cis Server hostname and credentials
.\CisConfig.ps1
Connect-rCisServer -Server $cisServer -User $cisUser -Password $cisPswd
Get-rCisTag -Name MyTag1 | Set-rCisTag -Name MyNewTag1 -Description 'Name changed'
Get-rCisTagCategory -Name MyCat1 | Set-rCisTagCategory -Cardinality Multiple -Name MyNewCat1 -Description 'Name changed'
Disconnect-rCisServer -Server $cisServer -Confirm:$false

View File

@@ -0,0 +1,13 @@
# Fetch Cis Server hostname and credentials
.\CisConfig.ps1
Connect-rCisServer -Server $cisServer -User $cisUser -Password $cisPswd
Get-rCisTagAssignment -Tag MyNewTag1 | Remove-rCisTagAssignment -Confirm:$false
Get-rCisTag -Name MyNewTag1 | Remove-rCisTag -Confirm:$false
Get-rCisTagCategory -Name MyNewCat1 | Remove-rCisTagCategory -Confirm:$false
Disconnect-rCisServer -Server $cisServer -Confirm:$false

View File

@@ -0,0 +1,20 @@
# Fetch Cis Server hostname and credentials
.\CisConfig.ps1
Connect-rCisServer -Server $cisServer -User $cisUser -Password $cisPswd
$catName = 'Homelab'
# Clean up
Get-rCisTagCategory -Name $catName | Remove-rCisTagCategory -Confirm:$false
# Tag all datastores with their type
New-rCisTagCategory -Name HomeLab -Description 'Homelab datastores' -Cardinality Single -EntityType 'Datastore' |
New-rCisTag -Name 'VMFS','NFS' -Description 'Datastore type'
Get-Cluster -Name Cluster1 | Get-Datastore | %{
New-rCisTagAssignment -Entity $_ -Tag "$($_.Type)"
}
Disconnect-rCisServer -Server $cisServer -Confirm:$false

View File

@@ -0,0 +1,3 @@
$cisServer = 'vcsa.my.domain'
$cisUser = 'administrator@vsphere.local'
$cisPswd = 'VMware1!'

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) since 2015 Luc Dekens, Matt Boren
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

15
Modules/rCisTag/README.md Normal file
View File

@@ -0,0 +1,15 @@
# rCisTag
A module with cmdlets to provide CRUD functions to
* Tags
* Tag Categories
* Tag Assignments
The cmdlets use the Cis REST API
## History
* Author : **Luc Dekens**
* Release :
* **0.9.0** First draft

View File

@@ -0,0 +1,26 @@
TOPIC
about_rCISTag
SHORT DESCRIPTION
The rCisTag module provides CRUD functions to work with vSphere Tags
LONG DESCRIPTION
The CisTag module provides CRUD functions to work with vSphere Tags.
The functions in the module are based on the REST API
NOTE
The module requires PowerShell 5.0
TROUBLESHOOTING NOTE
EXAMPLES
Get-rCisTag
KEYWORDS
SEE ALSO
Place related topics here.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,821 @@
function Disable-SSLValidation{
<#
.SYNOPSIS
Disables SSL certificate validation
.DESCRIPTION
Disable-SSLValidation disables SSL certificate validation by using reflection to implement the System.Net.ICertificatePolicy class.
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
.NOTES
Reflection is ideal in situations when a script executes in an environment in which you cannot call csc.ese to compile source code. If compiling code is an option, then implementing System.Net.ICertificatePolicy in C# and Add-Type is trivial.
.LINK
http://www.exploit-monday.com
#>
Set-StrictMode -Version 2
# You have already run this function
if ([System.Net.ServicePointManager]::CertificatePolicy.ToString() -eq 'IgnoreCerts') { Return }
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object System.Reflection.AssemblyName('IgnoreCerts')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('IgnoreCerts', $false)
$TypeBuilder = $ModuleBuilder.DefineType('IgnoreCerts', 'AutoLayout, AnsiClass, Class, Public, BeforeFieldInit', [System.Object], [System.Net.ICertificatePolicy])
$TypeBuilder.DefineDefaultConstructor('PrivateScope, Public, HideBySig, SpecialName, RTSpecialName') | Out-Null
$MethodInfo = [System.Net.ICertificatePolicy].GetMethod('CheckValidationResult')
$MethodBuilder = $TypeBuilder.DefineMethod($MethodInfo.Name, 'PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask', $MethodInfo.CallingConvention, $MethodInfo.ReturnType, ([Type[]] ($MethodInfo.GetParameters() | % {$_.ParameterType})))
$ILGen = $MethodBuilder.GetILGenerator()
$ILGen.Emit([Reflection.Emit.Opcodes]::Ldc_I4_1)
$ILGen.Emit([Reflection.Emit.Opcodes]::Ret)
$TypeBuilder.CreateType() | Out-Null
# Disable SSL certificate validation
[System.Net.ServicePointManager]::CertificatePolicy = New-Object IgnoreCerts
}
function Invoke-vCisRest{
param (
[String]$Method,
[String]$Request,
[PSObject]$Body
)
Process
{
Write-Verbose -Message "$($MyInvocation.MyCommand.Name)"
Write-Verbose -Message "`t$($PSCmdlet.ParameterSetName)"
Write-Verbose -Message "`tCalled from $($stack = Get-PSCallStack; $stack[1].Command) at $($stack[1].Location)"
Disable-SSLValidation
$sRest = @{
Uri = "https:/",$Script:CisServer.Server,'rest',$Request -join '/'
Method = $Method
# Body = &{if($Body){$Body}}
Body = &{if($Body){$Body | ConvertTo-Json -Depth 32}}
ContentType = 'application/json'
Headers = &{
if($Script:CisServer.ContainsKey('vmware-api-session-id')){
@{
'vmware-api-session-id' = "$($Script:CisServer.'vmware-api-session-id')"
}
}
else{
@{
Authorization = "$($Script:CisServer.AuthHeader)"
}
}
}
}
Try
{
# $result = Invoke-WebRequest @sRest
$result = Invoke-RestMethod @sRest
}
Catch
{
}
$result
}
}
function Connect-rCisServer{
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low')]
param (
[Parameter(Mandatory, Position = 1)]
[String]$Server,
[Parameter(Mandatory = $True,ValueFromPipeline = $True, Position = 2, ParameterSetName = 'Credential')]
[System.Management.Automation.PSCredential]$Credential,
[Parameter(Mandatory = $True, Position = 2, ParameterSetName = 'PlainText')]
[String]$User,
[Parameter(Mandatory = $True, Position = 3, ParameterSetName = 'PlainText')]
[String]$Password,
[string]$Proxy,
[Parameter(DontShow)]
[switch]$Fiddler = $false
)
Process
{
if ($Proxy)
{
if ($PSDefaultParameterValues.ContainsKey('*:Proxy'))
{
$PSDefaultParameterValues['*:Proxy'] = $Proxy
}
else
{
$PSDefaultParameterValues.Add('*:Proxy', $Proxy)
}
if ($PSDefaultParameterValues.ContainsKey('*:ProxyUseDefaultCredentials'))
{
$PSDefaultParameterValues['*:ProxyUseDefaultCredentials'] = $True
}
else
{
$PSDefaultParameterValues.Add('*:ProxyUseDefaultCredentials', $True)
}
}
if ($PSCmdlet.ParameterSetName -eq 'PlainText')
{
$sPswd = ConvertTo-SecureString -String $Password -AsPlainText -Force
$CisCredential = New-Object System.Management.Automation.PSCredential -ArgumentList ($User, $sPswd)
}
if ($PSCmdlet.ParameterSetName -eq 'Credential')
{
$CisCredential = $Credential
}
if ($Fiddler)
{
if (Get-Process -Name fiddler -ErrorAction SilentlyContinue)
{
if ($PSDefaultParameterValues.ContainsKey('Invoke-RestMethod:Proxy'))
{
$PSDefaultParameterValues['Invoke-RestMethod:Proxy'] = 'http://127.0.0.1:8888'
}
else
{
$PSDefaultParameterValues.Add('Invoke-RestMethod:Proxy', 'http://127.0.0.1:8888')
}
}
}
$Script:CisServer = @{
Server = $Server
AuthHeader = &{
$User = $CisCredential.UserName
$Password = $CisCredential.GetNetworkCredential().password
$Encoded = [System.Text.Encoding]::UTF8.GetBytes(($User, $Password -Join ':'))
$EncodedPassword = [System.Convert]::ToBase64String($Encoded)
"Basic $($EncodedPassword)"
}
}
$sRest = @{
Method = 'Post'
Request = 'com/vmware/cis/session'
}
If($PSCmdlet.ShouldProcess("CisServer $($Server)"))
{
$result = Invoke-vCisRest @sRest
$Script:CisServer.Add('vmware-api-session-id',$result.value)
$Script:CisServer.Remove('AuthHeader')
}
}
}
function Disconnect-rCisServer{
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')]
param (
[Parameter(Mandatory = $True, Position = 1)]
[String]$Server
)
Process
{
if($Server -ne $Script:CisServer.Server){
Write-Warning "You are not connected to server $($Server)"
}
$sRest = @{
Method = 'Delete'
Request = 'com/vmware/cis/session'
}
If($PSCmdlet.ShouldProcess("CisServer $($Server)"))
{
$result = Invoke-vCisRest @sRest
$Script:CisServer.Remove('vmware-api-session-id')
}
}
}
function Get-rCisTag{`
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low', DefaultParameterSetName='Name')]
param (
[Parameter(Position = 1, ParameterSetName='Name')]
[String[]]$Name,
[Parameter(Position = 2, ParameterSetName='Name',ValueFromPipeline = $true)]
[PSObject[]]$Category,
[Parameter(Mandatory = $True, Position = 1, ParameterSetName='Id')]
[String[]]$Id
)
Process
{
if($PSCmdlet.ParameterSetName -eq 'Name'){
if($Category){
$tagIds = $Category | %{
$categoryIds = &{if($_ -is [string]){
(Get-rCisTagCategory -Name $_).Id
}
else{
$_.Id
}}
$categoryIds | %{
# Get all tags in categories
$sRest = @{
Method = 'Post'
Request = "com/vmware/cis/tagging/tag/id:$([uri]::EscapeDataString($_))?~action=list-tags-for-category"
}
(Invoke-vCisRest @sRest).value
}
}
}
else{
$sRest = @{
Method = 'Get'
Request = 'com/vmware/cis/tagging/tag'
}
$tagIds = (Invoke-vCisRest @sRest).value
}
}
else{
$tagIds = $Id
}
# Get category details
$out = @()
$tagIds | where{($PSCmdlet.ParameterSetName -eq 'Id' -and $Id -contains $_) -or $PSCmdlet.ParameterSetName -eq 'Name'} | %{
$sRest = @{
Method = 'Get'
Request = "com/vmware/cis/tagging/tag/id:$([uri]::EscapeDataString($_))"
}
$result = Invoke-vCisRest @sRest
if($PSCmdlet.ParameterSetName -eq 'Id' -or ($PSCmdlet.ParameterSetName -eq 'Name' -and ($Name -eq $null -or $Name -contains $result.value.name))){
$out += New-Object PSObject -Property @{
Description = $result.value.description
Id = $result.value.id
Name = $result.value.name
Category = (Get-rCisTagCategory -Id $result.value.category_id).Name
Uid = "$($global:defaultviserver.Id)Tag=$($result.value.id)/"
Client = $global:defaultviserver.Client
}
}
}
$out | Select-Object Category,Description,Id,Name,Uid,Client
}
}
function Get-rCisTagCategory{
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low', DefaultParameterSetName='Name')]
param (
[Parameter(Position = 1, ParameterSetName='Name')]
[String[]]$Name,
[Parameter(Mandatory = $True, Position = 1, ParameterSetName='Id')]
[String[]]$Id
)
Begin
{
$txtInfo = (Get-Culture).TextInfo
$entityTab = @{
'ClusterComputeResource' = 'Cluster'
'DistributedVirtualSwitch' = 'DistributedSwitch'
'VmwareDistributedVirtualSwitch' = 'DistributedSwitch'
'HostSystem' = 'VMHost'
'DistributedVirtualPortGroup' = 'DistributedPortGroup'
'VirtualApp' = 'VApp'
'StoragePod' = 'DatastoreCluster'
'Network' = 'VirtualPortGroup'
}
}
Process
{
if($PSCmdlet.ParameterSetName -eq 'Name'){
# Get all categories
$sRest = @{
Method = 'Get'
Request = 'com/vmware/cis/tagging/category'
}
$tagCategoryIds = (Invoke-vCisRest @sRest).value
}
else{
$tagCategoryIds = $Id
}
# Get category details
$out = @()
$tagCategoryids | where{($PSCmdlet.ParameterSetName -eq 'Id' -and $Id -contains $_) -or $PSCmdlet.ParameterSetName -eq 'Name'} | %{
$sRest = @{
Method = 'Get'
Request = "com/vmware/cis/tagging/category/id:$([uri]::EscapeDataString($_))"
}
$result = Invoke-vCisRest @sRest
if($PSCmdlet.ParameterSetName -eq 'Id' -or ($PSCmdlet.ParameterSetName -eq 'Name' -and ($Name -eq $null -or $Name -contains $result.value.name))){
$out += New-Object PSObject -Property @{
Description = $result.value.description
Cardinality = $txtInfo.ToTitleCase($result.value.cardinality.ToLower())
EntityType = @(&{
if($result.value.associable_types.Count -eq 0){'All'}
else{
$result.value.associable_types | %{
if($entityTab.ContainsKey($_)){
$entityTab.Item($_)
}
else{$_}
}
}} | Sort-Object -Unique)
Id = $result.value.id
Name = $result.value.name
Uid = "$($global:defaultviserver.Id)TagCategory=$($result.value.id)/"
Client = $global:defaultviserver.Client
}
}
}
$out | Select-Object Description,Cardinality,EntityType,Id,Name,Uid,Client
}
}
function Get-rCisTagAssignment{
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')]
param (
[parameter(Position = 1, ValueFromPipeline = $true)]
[PSObject[]]$Entity,
[parameter(Position = 2)]
[PSObject[]]$Tag,
[parameter(Position = 3)]
[PSObject[]]$Category
)
Begin
{
if($Category.Count -ne 0 -or $Tag.Count -ne 0){
$tagIds = @((Get-rCisTag -Name $Tag -Category $Category).Id)
}
else{
$tagIds = @((Get-rCisTag).Id)
}
$out = @()
}
Process
{
foreach($ent in $Entity){
if($ent -is [string]){
$ent = Get-Inventory -Name $ent -ErrorAction SilentlyContinue
}
$entMoRef = New-Object PSObject -Property @{
type = $ent.ExtensionData.MoRef.Type
id = $ent.ExtensionData.MoRef.Value
}
$sRest = @{
Method = 'Post'
Request = 'com/vmware/cis/tagging/tag-association?~action=list-attached-tags-on-objects'
Body = @{
object_ids = @($entMoRef)
}
}
$tagObj = (Invoke-vCisRest @sRest).value
foreach($obj in @($tagObj)){
foreach($tag in ($obj.tag_ids | where{$tagIds -contains $_})){
$sMoRef = "$($obj.object_id.type)-$($obj.object_id.id)"
$out += New-Object PSObject -Property @{
Entity = (Get-View -id $sMoRef -Property Name).Name
Tag = (Get-rCisTag -Id $tag).Name
Id = 'com.vmware.cis.tagging.TagAssociationModel'
Name = 'com.vmware.cis.tagging.TagAssociationModel'
Uid = "$($global:defaultviserver.Id)VirtualMachine=$($sMoRef)/TagAssignment=/Tag=$($tag.tag_id)/"
Client = $global:defaultviserver.Client
}
}
}
}
}
End
{
if($out.Count -eq 0)
{
$sRest = @{
Method = 'Post'
Request = 'com/vmware/cis/tagging/tag-association?~action=list-attached-objects-on-tags'
Body = @{
tag_ids = $tagIds
}
}
$tagObj = (Invoke-vCisRest @sRest).value
$out = foreach($tag in @(($tagObj | where{$tagIds -contains $_.tag_id}))){
foreach($obj in $tag.object_ids){
$sMoRef = "$($obj.type)-$($obj.id)"
New-Object PSObject -Property @{
Entity = (Get-View -id $sMoRef -Property Name).Name
Tag = (Get-rCisTag -Id $tag.tag_id).Name
Id = 'com.vmware.cis.tagging.TagAssociationModel'
Name = 'com.vmware.cis.tagging.TagAssociationModel'
Uid = "$($global:defaultviserver.Id)VirtualMachine=$($sMoRef)/TagAssignment=/Tag=$($tag.tag_id)/"
Client = $global:defaultviserver.Client
}
}
}
}
$out | Select-Object Uid,Tag,Entity,Id,Name,Client
}
}
function New-rCisTag{
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')]
param (
[Parameter(Mandatory=$true, Position = 1)]
[String[]]$Name,
[Parameter(Mandatory=$true, Position = 2,ValueFromPipeline = $true)]
[PSObject]$Category,
[Parameter(Position = 3)]
[string]$Description
)
Process
{
$out = @()
if($Category -is [String]){
$Category = Get-rCisTagCategory -Name $Category
}
$Name | %{
$sRest = @{
Method = 'Post'
Request = 'com/vmware/cis/tagging/tag'
Body = @{
create_spec = @{
category_id = $Category.Id
name = $_
description = $Description
}
}
}
$tagId = (Invoke-vCisRest @sRest).value
$out += New-Object PSObject -Property @{
Category = $Category.Name
Description = $Description
Id = $tagId
Name = $_
Uid = "$($global:defaultviserver.Id)Tag=$($tagId)/"
Client = $global:defaultviserver.Client
}
}
$out | Select-Object Category,Description,Id,Name,Uid,Client
}
}
function New-rCisTagCategory{
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')]
param (
[Parameter(Mandatory=$true, Position = 1)]
[String[]]$Name,
[Parameter(Position = 2)]
[ValidateSet('Single','Multiple')]
[string]$Cardinality = 'Single',
[Parameter(Position = 3)]
[string]$Description,
[Parameter(Position = 4)]
[string[]]$EntityType
)
Process
{
$out = @()
$Name | %{
$sRest = @{
Method = 'Post'
Request = 'com/vmware/cis/tagging/category'
Body = @{
create_spec = @{
cardinality = $Cardinality.ToUpper()
associable_types = @($EntityType)
name = $_
description = $Description
}
}
}
$categoryId = (Invoke-vCisRest @sRest).value
$out += New-Object PSObject -Property @{
Description = $Description
Cardinality = $Cardinality
EntityType = @($EntityType)
Id = $categoryId
Name = $_
Uid = "$($global:defaultviserver.Id)TagCategory=$($categoryId)/"
Client = $global:defaultviserver.Client
}
}
$out | Select-Object Description,Cardinality,EntityType,Id,Name,Uid,Client
}
}
function New-rCisTagAssignment{
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')]
param (
[Parameter(Mandatory=$true, Position = 1)]
[String[]]$Tag,
[Parameter(Mandatory=$true,ValueFromPipeline = $true, Position = 2)]
[PSObject[]]$Entity
)
Process
{
$tagIds = @((Get-rCisTag -Name $Tag).Id)
$Entity = foreach($ent in $Entity){
if($ent -is [string]){
$ent = Get-Inventory -Name $ent -ErrorAction SilentlyContinue
}
$entMoRef = New-Object PSObject -Property @{
type = $ent.ExtensionData.MoRef.Type
id = $ent.ExtensionData.MoRef.Value
}
foreach($tagId in $tagIds){
$sRest = @{
Method = 'Post'
Request = "com/vmware/cis/tagging/tag-association/id:$($tagId)?~action=attach"
Body = @{
object_id = $entMoRef
}
}
Invoke-vCisRest @sRest
}
}
}
# foreach($ent in
# if($Tag.Count -eq 1)
# {
# $tagId = (Get-rCisTag -Name $Tag).Id
# }
# elseif($Tag.Count -gt 1)
# {
# $tagIds = (Get-rCisTag -Name $Tag).Id
# }
# $Entity = foreach($ent in $Entity){
# if($ent -is [string]){
# Get-Inventory -Name $ent -ErrorAction SilentlyContinue
# }
# else{$ent}
# }
#
# if($Entity.Count -eq 1)
# {
# $entMoRef = New-Object PSObject -Property @{
# type = $Entity[0].ExtensionData.MoRef.Type
# id = $Entity[0].ExtensionData.MoRef.Value
# }
# if($tag.Count -eq 1){
# $sRest = @{
# Method = 'Post'
# Request = "com/vmware/cis/tagging/tag-association/id:$($tagId)?~action=attach"
# Body = @{
# object_id = $entMoRef
# }
# }
# Invoke-vCisRest @sRest
# }
# elseif($Tag.Count -gt 1){
# $sRest = @{
# Method = 'Post'
# Request = 'com/vmware/cis/tagging/tagassociation?~action=attach-multiple-tags-to-object'
# Body = @{
# object_id = $entMoRef
# tag_ids = @($tagIds)
# }
# }
# Invoke-vCisRest @sRest
# }
# }
# elseif($Entity.Count -gt 1)
# {
# $entMorefs = $Entity | %{
# New-Object PSObject -Property @{
# type = $_.ExtensionData.MoRef.Type
# id = $_.ExtensionData.MoRef.Value
# }
# }
# if($tag.Count -eq 1){
# $sRest = @{
# Method = 'Post'
# Request = 'com/vmware/cis/tagging/tagassociation/id:$($tagId)?~action=attach-tag-to-multiple-objects'
# Body = @{
# objects_ids = @($entMoRefs)
# tag_id = $tagId
# }
# }
# Invoke-vCisRest @sRest
# }
# elseif($Tag.Count -gt 1){
# $tagIds | %{
# $sRest = @{
# Method = 'Post'
# Request = 'com/vmware/cis/tagging/tagassociation/id:$($tagId)?~action=attach-tag-to-multiple-objects'
# Body = @{
# objects_ids = @($entMoRefs)
# tag_id = $_
# }
# }
# Invoke-vCisRest @sRest
# }
# }
# }
# }
}
function Remove-rCisTag{
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High', DefaultParameterSetName='Name')]
param (
[Parameter(Mandatory=$true, Position = 1, ValueFromPipeline = $true,ParameterSetName='Name')]
[PSObject[]]$Tag,
[Parameter(Mandatory=$true, Position = 1, ValueFromPipelineByPropertyName = $true,ParameterSetName='Id')]
[String[]]$Id
)
Process
{
if($PSCmdlet.ParameterSetName -eq 'Name'){
foreach($tagObj in $Tag){
if($tagObj -is [string]){
$tagObj = Get-rCisTag -Name $tagObj
}
$sRest = @{
Method = 'Delete'
Request = "com/vmware/cis/tagging/tag/id:$($tagObj.Id)"
}
Invoke-vCisRest @sRest
}
}
else{
foreach($tagId in $Id){
$sRest = @{
Method = 'Delete'
Request = "com/vmware/cis/tagging/tag/id:$($tagId)"
}
Invoke-vCisRest @sRest
}
}
}
}
function Remove-rCisTagCategory{
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High', DefaultParameterSetName='Name')]
param (
[Parameter(Mandatory=$true,Position = 1, ValueFromPipeline = $true,ParameterSetName='Name')]
[PSObject[]]$Category,
[Parameter(Mandatory=$true,Position = 1, ValueFromPipelineByPropertyName = $true,ParameterSetName='Id')]
[String[]]$Id
)
Process
{
if($PSCmdlet.ParameterSetName -eq 'Name'){
foreach($catObj in $Category){
if($catObj -is [string]){
$catObj = Get-rCisTagCategory -Name $catObj
}
$sRest = @{
Method = 'Delete'
Request = "com/vmware/cis/tagging/category/id:$($catObj.Id)"
}
Invoke-vCisRest @sRest
}
}
else{
foreach($catId in $Id){
$sRest = @{
Method = 'Delete'
Request = "com/vmware/cis/tagging/category/id:$($catId)"
}
Invoke-vCisRest @sRest
}
}
}
}
function Remove-rCisTagAssignment{
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High',DefaultParameterSetName='Assignment')]
param (
[Parameter(Mandatory=$true, Position = 1, ValueFromPipeline = $true,ParameterSetName='Assignment')]
[PSObject[]]$TagAssignment,
[Parameter(Mandatory=$true,Position = 1, ValueFromPipeline = $true,ParameterSetName='Name')]
[string[]]$Tag,
[Parameter(Position = 2, ParameterSetName='Name')]
[string[]]$Category,
[Parameter(Mandatory=$true, ValueFromPipelineByPropertyName = $true,ParameterSetName='Id')]
[string[]]$TagId,
[Parameter(ParameterSetName='Name')]
[Parameter(ParameterSetName='Id')]
[PSObject[]]$Entity
)
Process
{
switch ($PSCmdlet.ParameterSetName){
'Name' {
$TagAssignment = Get-rCisTagAssignment -Entity $Entity -Tag $Tag -Category $Category
}
'Id' {
$tags = Get-rCisTag -Id $TagId
$TagAssignment = Get-rCisTagAssignment -Tag $tags.Name -Entity $Entity
}
}
if($TagAssignment){
$entMoRefs = @(Get-Inventory -Name $TagAssignment.Entity -ErrorAction SilentlyContinue | %{
New-Object PSObject -Property @{
type = $_.ExtensionData.MoRef.Type
id = $_.ExtensionData.MoRef.Value
}
})
$tagIds = @((Get-rCisTag -Name $TagAssignment.Tag).Id)
}
foreach($entMoRef in $entMoRefs){
foreach($tId in $tagIds){
$sRest = @{
Method = 'Post'
Request = "com/vmware/cis/tagging/tag-association/id:$($tId)?~action=detach"
Body = @{
object_id = $entMoRef
}
}
Invoke-vCisRest @sRest
}
}
}
}
function Set-rCisTag{
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')]
param (
[Parameter(Mandatory=$true, Position = 1, ValueFromPipeline = $true)]
[PSObject[]]$Tag,
[Parameter(Position = 2)]
[string]$Name,
[Parameter(Position = 3)]
[string]$Description
)
Process
{
foreach($tagObj in $Tag){
if($tagObj -is [string]){
$tagObj = Get-rCisTag -Name $tagObj
}
$sRest = @{
Method = 'Patch'
Request = "com/vmware/cis/tagging/tag/id:$($tagObj.Id)"
Body = @{
update_spec = @{
name = $Name
description = $Description
}
}
}
Invoke-vCisRest @sRest
}
}
}
function Set-rCisTagCategory{
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')]
param (
[Parameter(Mandatory=$true, Position = 1, ValueFromPipeline = $true)]
[PSObject[]]$Category,
[Parameter(Position = 2)]
[string]$Name,
[Parameter(Position = 3)]
[ValidateSet('Single','Multiple')]
[string]$Cardinality, # Only SINGLE to MULTIPLE
# [string[]]$AddEntityType, # Does not work
[string]$Description
)
Process
{
foreach($catObj in $Category){
if($catObj -is [string]){
$catObj = Get-rCisTagCategory -Name $catObj
}
$sRest = @{
Method = 'Patch'
Request = "com/vmware/cis/tagging/category/id:$($catObj.Id)"
Body = @{
update_spec = @{
}
}
}
if($Name){
$sRest.Body.update_spec.Add('name',$Name)
}
if($Description){
$sRest.Body.update_spec.Add('description',$Description)
}
if($Cardinality -and $catObj.Cardinality -eq 'SINGLE'){
$sRest.Body.update_spec.Add('cardinality',$Cardinality.ToUpper())
}
if($Name -or $Description -or $Cardinality){
Invoke-vCisRest @sRest
}
}
}
}

View File

@@ -0,0 +1,79 @@
<#
===========================================================================
Created by: Jason Robinson
Created on: 05/2017
Twitter: @jrob24
Filename: New-vCenterAlarms.ps1
===========================================================================
.DESCRIPTION
Examples of creating alarms using vCenter.Alarm module
#>
Import-Module -Name vCenter.Alarms
Write-Verbose -Message "Example 1 : Creating new Host CPU Usage alarm (Metric based alarm)"
Write-Verbose -Message "Finding the metric id for 'cpu.usage.average'"
$MetricId = (Get-MetricId -MetricGroup CPU | Where-Object -FilterScript { $_.Name -eq 'cpu.usage.average' }).Key
Write-Verbose -Message "Creating an alarm trigger for cpu.usage.average of 90% for 15mins (Warning) & 95% for 10mins (Alert) on the HostSystem object type"
$Trigger = New-AlarmTrigger -MetricId $MetricId -MetricOperator isAbove -ObjectType HostSystem -Yellow 90 -YellowInterval 15 -Red 95 -RedInterval 10
Write-Verbose -Message "Creates a new alarm called 'Host CPU Usage' at the root level of vCenter"
New-AlarmDefinition -Name "Host CPU Usage" -Description "Alarm on 95%" -Entity Datacenters -Trigger $Trigger -ActionRepeatMinutes 10
Write-Verbose -Message "Configures the alarm to send snmp traps"
Get-AlarmDefinition -Name "Host CPU Usage" | vSphere.Alarms\New-AlarmAction -Snmp -GreenToYellow Once -YellowToRed Repeat
Write-Verbose -Message "Example 2 : Creating new HA Disabled alarm (Event based alarm)"
Write-Verbose -Message "Finding the event type for 'HA disabled for cluster'"
$EventType = (Get-EventId | Where-Object -FilterScript { $_.Description -match 'HA disabled for cluster' }).EventType
Write-Verbose -Message "Creating an alarm trigger for 'DasDisabledEvent' on the ClusterComputeResource object type"
$Trigger = New-AlarmTrigger -EventType $EventType -Status Red -ObjectType ClusterComputeResource
Write-Verbose -Message "Creates a new alarm called 'HA Disabled' at the root level of vCenter"
New-AlarmDefinition -Name "HA Disabled" -Description "Alarm on HA" -Entity Datacenters -Trigger $Trigger -ActionRepeatMinutes 30
Write-Verbose -Message "Configures the alarm to send an email every 30mins"
$EmailParams = @{
Email = $true
To = 'helpdesk@company.com'
Subject = 'HA Disabled'
}
Get-AlarmDefinition -Name "HA Disabled" | vCenter.Alarms\New-AlarmAction @EmailParams -YellowToRed Repeat
Write-Verbose -Message "Example 3 : Creating new Host Connection State alarm (State based alarm)"
Write-Verbose -Message "Creating an alarm trigger for StateType of 'runtime.connectionState' on the HostSystem object type"
$Trigger = New-AlarmTrigger -StateType runtime.connectionState -StateOperator isEqual -YellowStateCondition disconnected -RedStateCondition notResponding -ObjectType HostSystem
Write-Verbose -Message "Creates a new alarm called 'Host Connection State' at the root level of vCenter"
New-AlarmDefinition -Name "Host Connection State" -Description "Connection State" -Entity Datacenters -Trigger $Trigger
Write-Verbose -Message "Configures the alarm to send an email once"
$EmailParams = @{
Email = $true
To = 'helpdesk@company.com'
Subject = 'Host Connection Lost'
}
Get-AlarmDefinition -Name "Host Connection State" | vCenter.Alarms\New-AlarmAction @EmailParams -YellowToRed Once
Write-Verbose -Message "Example 4 : Creating new Lost Storage Connectivity (Event based alarm)"
Write-Verbose -Message "Find the event type for 'Lost Storage Connectivity'"
Get-EventId | Where-Object -FilterScript { $_.Description -match 'Lost Storage Connectivity' }
Write-Verbose -Message "Two results returned, we want esx not vprob"
<#
EventType : EventEx
EventTypeId : esx.problem.storage.connectivity.lost
Category : error
Description : Lost Storage Connectivity
FullFormat : Lost connectivity to storage device { 1 }. Path { 2 } is down. Affected datastores: { 3 }.
vCenter : vCenter01
EventType : EventEx
EventTypeId : vprob.storage.connectivity.lost
Category : error
Description : Lost Storage Connectivity
FullFormat : Lost connectivity to storage device { 1 }. Path { 2 } is down. Affected datastores: { 3 }.
vCenter : vCenter01
#>
Write-Verbose -Message "Since the event type is EventEx, we need both the EventType & EventTypeId to create the trigger"
$EventType = Get-EventId | Where-Object -FilterScript { $_.EventTypeId -eq 'esx.problem.storage.connectivity.lost' }
Write-Verbose -Message "Creating an alarm trigger for 'DasDisabledEvent' on the ClusterComputeResource object type"
$Trigger = New-AlarmTrigger -EventType $EventType.EventType -EventTypeId $EventType.EventTypeId -Status Red -ObjectType HostSystem
Write-Verbose -Message "Creates a new alarm called 'Lost Storage Connectivity' at the root level of vCenter"
New-AlarmDefinition -Name "Lost Storage Connectivity" -Description "Lost Storage" -Entity Datacenters -Trigger $Trigger -ActionRepeatMinutes 5
Write-Verbose -Message "Configures the alarm to send an snmp every 5mins"
Get-AlarmDefinition -Name "Lost Storage Connectivity" | vCenter.Alarms\New-AlarmAction -Snmp -YellowToRed Repeat

View File

@@ -0,0 +1,736 @@
<#
===========================================================================
Created by: Jason Robinson
Created on: 05/2017
Twitter: @jrob24
===========================================================================
.DESCRIPTION
PowerShell Module to help with creation of vCenter Alarms
.NOTES
See New-vCenterAlarms.ps1 for examples of alarm creation
* Tested against PowerShell 5.0
* Tested against PowerCLI 6.5.1 build 5377412
* Tested against vCenter 6.0
* Tested against ESXi 5.5/6.0
#>
function New-AlarmDefinition {
<#
.SYNOPSIS
This cmdlet creates a new alarm defintion on the specified entity in vCenter.
.DESCRIPTION
This cmdlet creates a new alarm defintion on the specified entity in vCenter.
An alarm trigger is required in order to create a new alarm definition.
They can be created by using the New-AlarmTrigger cmdlet.
After the alarm definition is created, if alarm actions are required use
the cmdlet New-AlarmAction to create actions for the alarm.
.PARAMETER Name
Specifies the name of the alarm you want to create.
.PARAMETER Description
Specifies the description for the alarm.
.PARAMETER Entity
Specifies where to create the alarm. To create the alarm at the root
level of vCenter use the entity 'Datacenters', otherwise specify any
object name.
.PARAMETER Trigger
Specifies the alarm event, state, or metric trigger(s). The alarm
trigger(s) are created with the New-AlarmTrigger cmdlet. For more
information about triggers, run Get-Help New-AlarmTrigger.
.PARAMETER Enabled
Specifies if the alarm is enabled when it is created. If unset, the
default value is true.
.PARAMETER ActionRepeatMinutes
Specifies the frequency how often the actions should repeat when an alarm
does not change state.
.PARAMETER ReportingFrequency
Specifies how often the alarm is triggered, measured in minutes. A zero
value means the alarm is allowed to trigger as often as possible. A
nonzero value means that any subsequent triggers are suppressed for a
period of minutes following a reported trigger.
If unset, the default value is 0. Allowed range is 0 - 60.
.PARAMETER ToleranceRange
Specifies the tolerance range for the metric triggers, measure in
percentage. A zero value means that the alarm triggers whenever the metric
value is above or below the specified value. A nonzero means that the
alarm triggers only after reaching a certain percentage above or below
the nominal trigger value.
If unset, the default value is 0. Allowed range is 0 - 100.
.PARAMETER Server
Specifies the vCenter Server system on which you want to run the cmdlet.
If no value is passed to this parameter, the command runs on the default
server, $DefaultVIServer. For more information about default servers,
see the description of Connect-VIServer.
.OUTPUTS
VMware.Vim.ManagedObjectReference
.NOTES
This cmdlet requires a connection to vCenter to create the alarm action.
.LINKS
http://pubs.vmware.com/vsphere-6-0/topic/com.vmware.wssdk.apiref.doc/vim.alarm.AlarmSpec.html
.EXAMPLE
PS C:\> $trigger = New-AlarmTrigger -StateType runtime.connectionState -StateOperator isEqual -YellowStateCondition disconnected -RedStateCondition notResponding -ObjectType HostSystem
PS C:\> New-AlarmDefinition -Name 'Host Connection' -Description 'Host Connection State Alarm -Entity Datacenters -Trigger $trigger -ActionRepeatMinutes 10
Type Value
---- -----
Alarm alarm-1801
This will create a host connection state alarm trigger and store it in
the variable $trigger. Then it will create a new alarm 'Host Connection'
on the root level of vCenter and set the action to repeat every 10 mins.
#>
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[Alias('AlarmName')]
[string]$Name,
[string]$Description,
[Parameter(Mandatory = $true)]
[string]$Entity,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[VMware.Vim.AlarmExpression[]]$Trigger,
[boolean]$Enabled = $true,
[ValidateRange(0, 60)]
[int32]$ActionRepeatMinutes,
[ValidateRange(0, 60)]
[int32]$ReportingFrequency = 0,
[ValidateRange(0, 100)]
[int32]$ToleranceRange = 0,
[string]$Server
)
BEGIN {
Write-Verbose -Message "Adding parameters with default values to PSBoundParameters"
foreach ($Key in $MyInvocation.MyCommand.Parameters.Keys) {
$Value = Get-Variable $Key -ValueOnly -ErrorAction SilentlyContinue
if ($Value -and !$PSBoundParameters.ContainsKey($Key)) {
$PSBoundParameters[$Key] = $Value
}
}
}
PROCESS {
try {
if ($PSBoundParameters.ContainsKey('Server')) {
$Object = Get-Inventory -Name $PSBoundParameters['Entity'] -ErrorAction Stop -Server $PSBoundParameters['Server']
$AlarmMgr = Get-View AlarmManager -ErrorAction Stop -Server $PSBoundParameters['Server']
} else {
$Object = Get-Inventory -Name $PSBoundParameters['Entity'] -ErrorAction Stop -Server $global:DefaultVIServer
$AlarmMgr = Get-View AlarmManager -ErrorAction Stop -Server $global:DefaultVIServer
}
if ($PSCmdlet.ShouldProcess($global:DefaultVIServer, "Create alarm $($PSBoundParameters['Name'])")) {
$Alarm = New-Object -TypeName VMware.Vim.AlarmSpec
$Alarm.Name = $PSBoundParameters['Name']
$Alarm.Description = $PSBoundParameters['Description']
$Alarm.Enabled = $PSBoundParameters['Enabled']
$Alarm.Expression = New-Object -TypeName VMware.Vim.OrAlarmExpression
$Alarm.Expression.Expression += $PSBoundParameters['Trigger']
$Alarm.Setting = New-Object -TypeName VMware.Vim.AlarmSetting
$Alarm.Setting.ReportingFrequency = $PSBoundParameters['ReportingFrequency'] * 60
$Alarm.Setting.ToleranceRange = $PSBoundParameters['ToleranceRange'] * 100
$Alarm.ActionFrequency = $PSBoundParameters['ActionRepeatMinutes'] * 60
$AlarmMgr.CreateAlarm($Object.Id, $Alarm)
}
} catch {
$PSCmdlet.ThrowTerminatingError($_)
}
}
} #End of New-AlarmDefinition function
function New-AlarmAction {
<#
.SYNOPSIS
This cmdlet creates an alarm action on the specified alarm definition.
.DESCRIPTION
This cmdlet creates an alarm action on the specified alarm definition.
This cmdlet differs from the VMware PowerCLI New-AlarmAction cmdlet as it
will create the transitions of the alarm state. It requires an alarm
action and at least one transition to be specified.
The transition indicates when the action executes and if it repeats.
There are only four acceptable transitions: green to yellow, yellow to
red, red to yellow, and yellow to green. At least one pair must be
specified or the results will be an invalid.
If an alarm action already exists on the alarm definition, it will be
overwritten if the same alarm action is specified. For example if the
alarm definition already has an alarm action of Snmp on the transition
of green to yellow and the cmdlet is used to create a new action of
Snmp on the transition of yellow to red, it will overwrite the existing
action and transition. The end result will be one Snmp action on the
transition of yellow to red. If you want the old to transition to remain
both should be specified during the usage of the cmdlet.
.PARAMETER AlarmDefinition
Specifies the alarm definition for which you want to configure actions.
The alarm definition can be retreived by using the Get-AlarmDefinition
cmdlet.
.PARAMETER Snmp
Indicates that a SNMP message is sent when the alarm is activated.
.PARAMETER Email
Indicates that when the alarm is activated, the system sends an email
message to the specified address. Use the Subject, To, CC, and Body
parameters to customize the alarm message.
.PARAMETER To
Specifies the email address to which you want to send a message.
.PARAMETER Cc
Specifies the email address you want to add to the CC field of the email
message.
.PARAMETER Subject
Specifies a subject for the email address message you want to send.
.PARAMETER Body
Specifies the text of the email message.
.PARAMETER GreenToYellow
Specifies the alarm action for the green to yellow transition. Allowed
values are 'Once' and 'Repeat'. If parameter is not set transition will
remain unset.
.PARAMETER YellowToRed
Specifies the alarm action for the yellow to red transition. Allowed
values are 'Once' and 'Repeat'. If parameter is not set transition will
remain unset.
.PARAMETER RedToYellow
Specifies the alarm action for the red to yellow transition. Allowed
values are 'Once' and 'Repeat'. If parameter is not set transition will
remain unset.
.PARAMETER YellowToGreen
Specifies the alarm action for the yellow to green transition. Allowed
values are 'Once' and 'Repeat'. If parameter is not set transition will
remain unset.
.NOTES
This cmdlet requires a connection to vCenter to create the alarm action.
When using this cmdlet specify the Module-Qualified cmdlet name to avoid
using the New-AlarmAction cmdlet with VMware PowerCLI.
.EXAMPLE
PS C:\> vCenter.Alarms\New-AlarmAction -AlarmDefinition (Get-AlarmDefintion "Host CPU Usage") -Snmp -YellowToRed Repeat
This will create an Snmp alarm action on the "Host CPU Usage" alarm
transition of yellow to red. The alarm action will also repeat, as per
the action frequency defined on the alarm.
.EXAMPLE
PS C:\> Get-AlarmDefintion "Cluster HA Status" | vCenter.Alarms\New-AlarmAction -Email -To helpdesk@company.com -GreenToYellow Once -YellowToRed Once
This will create an Email alarm action on the "Cluster HA Status" alarm
transition of green to yellow and yellow to red. The alarm action will
send an email to helpdesk@company.com one time per transition.
#>
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[VMware.VimAutomation.ViCore.Types.V1.Alarm.AlarmDefinition]$AlarmDefinition,
[Parameter(Mandatory = $true, ParameterSetName = 'Snmp')]
[switch]$Snmp,
[Parameter(Mandatory = $true, ParameterSetName = 'Email')]
[switch]$Email,
[Parameter(Mandatory = $true, ParameterSetName = 'Email')]
[string[]]$To,
[Parameter(ParameterSetName = 'Email')]
[string[]]$Cc,
[Parameter(ParameterSetName = 'Email')]
[string]$Subject,
[Parameter(ParameterSetName = 'Email')]
[string]$Body,
[ValidateSet('Once', 'Repeat')]
[string]$GreenToYellow,
[ValidateSet('Once', 'Repeat')]
[string]$YellowToRed,
[ValidateSet('Once', 'Repeat')]
[string]$RedToYellow,
[ValidateSet('Once', 'Repeat')]
[string]$YellowToGreen
)
BEGIN {
}
PROCESS {
try {
$AlarmView = Get-View -Id $PSBoundParameters['AlarmDefinition'].Id -Server ($PSBoundParameters['AlarmDefinition'].Uid.Split('@:')[1])
$Alarm = New-Object -TypeName VMware.Vim.AlarmSpec
$Alarm.Name = $AlarmView.Info.Name
$Alarm.Description = $AlarmView.Info.Description
$Alarm.Enabled = $AlarmView.Info.Enabled
$Alarm.ActionFrequency = $AlarmView.Info.ActionFrequency
$Alarm.Action = New-Object VMware.Vim.GroupAlarmAction
$Trigger = New-Object VMware.Vim.AlarmTriggeringAction
Write-Verbose -Message "Defining alarm actions"
if ($PSCmdlet.ParameterSetName -eq 'Snmp') {
$Trigger.Action = New-Object -TypeName VMware.Vim.SendSNMPAction
} elseif ($PSCmdlet.ParameterSetName -eq 'Email') {
$Trigger.Action = New-Object -TypeName VMware.Vim.SendEmailAction
$Trigger.Action.ToList = $PSBoundParameters['To'].GetEnumerator() | ForEach-Object -Process {
"$_;"
}
if ($PSBoundParameters.ContainsKey('Cc')) {
$Trigger.Action.CcList = $PSBoundParameters['Cc'].GetEnumerator() | ForEach-Object -Process {
"$_;"
}
} else {
$Trigger.Action.CcList = $null
}
$Trigger.Action.Subject = $PSBoundParameters['Subject']
$Trigger.Action.Body = $PSBoundParameters['Body']
}
Write-Verbose -Message "Defining alarm transitions"
if ($PSBoundParameters.ContainsKey('GreenToYellow')) {
$Trans1 = New-Object -TypeName VMware.Vim.AlarmTriggeringActionTransitionSpec
$Trans1.StartState = 'green'
$Trans1.FinalState = 'yellow'
if ($PSBoundParameters['GreenToYellow'] -eq 'Repeat') {
$Trans1.Repeats = $true
}
$Trigger.TransitionSpecs += $Trans1
}
if ($PSBoundParameters.ContainsKey('YellowToRed')) {
$Trans2 = New-Object -TypeName VMware.Vim.AlarmTriggeringActionTransitionSpec
$Trans2.StartState = 'yellow'
$Trans2.FinalState = 'red'
if ($PSBoundParameters['YellowToRed'] -eq 'Repeat') {
$Trans2.Repeats = $true
} else {
$Trans2.Repeats = $false
}
$Trigger.TransitionSpecs += $Trans2
}
if ($PSBoundParameters.ContainsKey('RedToYellow')) {
$Trans3 = New-Object -TypeName VMware.Vim.AlarmTriggeringActionTransitionSpec
$Trans3.StartState = 'red'
$Trans3.FinalState = 'yellow'
if ($PSBoundParameters['RedToYellow'] -eq 'Repeat') {
$Trans3.Repeats = $true
} else {
$Trans3.Repeats = $false
}
$Trigger.TransitionSpecs += $Trans3
}
if ($PSBoundParameters.ContainsKey('YellowToGreen')) {
$Trans4 = New-Object -TypeName VMware.Vim.AlarmTriggeringActionTransitionSpec
$Trans4.StartState = 'yellow'
$Trans4.FinalState = 'green'
if ($PSBoundParameters['YellowToGreen'] -eq 'Repeat') {
$Trans4.Repeats = $true
} else {
$Trans4.Repeats = $false
}
$Trigger.TransitionSpecs += $Trans4
}
$Alarm.Action.Action += $Trigger
$Alarm.Expression = New-Object -TypeName VMware.Vim.OrAlarmExpression
$Alarm.Expression.Expression += $AlarmView.Info.Expression.Expression
$Alarm.Setting += $AlarmView.Info.Setting
$AlarmView.ReconfigureAlarm($Alarm)
} catch {
$PSCmdlet.ThrowTerminatingError($_)
}
}
} #End of New-AlarmAction function
function New-AlarmTrigger {
<#
.SYNOPSIS
This cmdlet creates a vCenter event, state, or metric alarm trigger.
.DESCRIPTION
This cmdlet creates a vCenter event, state, or metric alarm trigger.
The trigger is used with the New-AlarmDefinition cmdlet to create a new
alarm in vCenter. This cmdlet will only create one alarm trigger. If more
triggers are required store the triggers in an array.
.PARAMETER EventType
Specifies the type of the event to trigger on. The event types can be
discovered by using the Get-EventId cmdlet. If the the event type is
'EventEx' or 'ExtendedEvent' the EventTypeId parameter is required.
.PARAMETER EventTypeId
Specifies the id of the event type. Only used when the event type is an
'EventEx' or 'ExtendedEvent'.
.PARAMETER Status
Specifies the status of the event. Allowed values are green, yellow, or
red.
.PARAMETER StateType
Specifies the state type to trigger on. Allowed values are
runtime.powerstate (HostSystem), summary.quickStats.guestHeartbeatStatus
(VirtualMachine), or runtime.connectionState (VirtualMachine).
.PARAMETER StateOperator
Specifies the operator condition on the target state. Allowed values are
'isEqual' or 'isUnequal'.
.PARAMETER YellowStateCondition
Specifies the yellow state condition. When creating a state alarm
trigger at least one condition must be specified for a valid trigger to
be created. If the parameter is not set, the yellow condition is unset.
.PARAMETER RedStateCondition
Specifies the red state condition. When creating a state alarm trigger
at least one condition must be specified for a valid trigger to be
created. If the parameter is not set, the red condition is unset.
.PARAMETER MetricId
Specifies the id of the metric to trigger on. The metric ids can be
discovered by using the Get-MetricId cmdlet.
.PARAMETER MetricOperator
Specifies the operator condition on the target metric. Allowed values
are 'isAbove' or 'isBelow'.
.PARAMETER Yellow
Specifies the threshold value that triggers a yellow status. Allowed
range is 1% - 100%.
.PARAMETER YellowInterval
Specifies the time interval in minutes for which the yellow condition
must be true before the yellow status is triggered. If unset, the yellow
status is triggered immediately when the yellow condition becomes true.
.PARAMETER Red
Specifies the threshold value that triggers a red status. Allowed range
is 1% - 100%.
.PARAMETER RedInterval
Specifies the time interval in minutes for which the red condition must
be true before the red status is triggered. If unset, the red status is
triggered immediately when the red condition becomes true.
.PARAMETER ObjectType
Specifies the type of object on which the event is logged, the object
type containing the state condition or the type of object containing the
metric.
When creating a state alarm trigger the only acceptable values are
'HostSystem' or 'VirtualMachine'. The supported state types for each object
are as follows:
VirtualMachine type: runtime.powerState or summary.quickStats.guestHeartbeatStatus
HostSystem type: runtime.connectionState
.OUTPUTS
(Event|State|Metric)AlarmExpression
.NOTES
This cmdlet requires the PowerCLI module to be imported.
.LINK
Event Alarm Trigger
http://pubs.vmware.com/vsphere-6-0/topic/com.vmware.wssdk.apiref.doc/vim.alarm.EventAlarmExpression.html
State Alarm Trigger
http://pubs.vmware.com/vsphere-6-0/topic/com.vmware.wssdk.apiref.doc/vim.alarm.StateAlarmExpression.html
Metric Alarm Trigger
http://pubs.vmware.com/vsphere-6-0/topic/com.vmware.wssdk.apiref.doc/vim.alarm.MetricAlarmExpression.html
.EXAMPLE
PS C:\> New-AlarmTrigger -EventType "DasDisabledEvent" -Status Red -ObjectType ClusterComputeResource
Comparisons :
EventType : DasDisabledEvent
ObjectType : ClusterComputeResource
Status : red
Creates an event trigger on 'DasDisabledEvent' (HA Disabled) with a
status on 'Red'. The object type is a ClusterComputerResource because
this event occurs at a cluster level.
.EXAMPLE
PS C:\> New-AlarmTrigger -MetricId (Get-MetricId | Where Name -EQ 'cpu.usage.average').Key -Operator isAbove -Yellow 90 -YellowInterval 30 -Red 98 -RedInterval 15 -ObjectType HostSytem
Operator : isAbove
Type : HostSytem
Metric : VMware.Vim.PerfMetricId
Yellow : 9000
YellowInterval : 30
Red : 9800
RedInterval : 15
Creates a trigger on the 'cpu.usage.average' metric where the warning
condition must be above 90% for 30mins and the alert condition must be
above 98% for 15mins. The object type is a HostSystem.
.EXAMPLE
PS C:\temp> New-AlarmTrigger -StateType runtime.connectionState -StateOperator isEqual -YellowStateCondition Disconnected -RedStateCondition notResponding -ObjectType HostSystem
Operator : isEqual
Type : HostSystem
StatePath : runtime.connectionState
Yellow : Disconnected
Red : notResponding
Creates a trigger on the 'runtime.connectionState' condition where the
warning condition is 'disconnected' and the alert condition is
'notResponding'. The object type is a HostSystem.
#>
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')]
param (
[Parameter(Mandatory = $true, ParameterSetName = 'Event')]
[string]$EventType,
[Parameter(ParameterSetName = 'Event')]
[string]$EventTypeId,
[Parameter(Mandatory = $true, ParameterSetName = 'Event')]
[ValidateSet('Green', 'Yellow', 'Red')]
[string]$Status,
[Parameter(Mandatory = $true, ParameterSetName = 'State')]
[ValidateSet('runtime.powerState', 'summary.quickStats.guestHeartbeatStatus', 'runtime.connectionState')]
[string]$StateType,
[Parameter(Mandatory = $true, ParameterSetName = 'State')]
[VMware.Vim.StateAlarmOperator]$StateOperator,
[Parameter(ParameterSetName = 'State')]
[ValidateSet('disconnected', 'notResponding', 'connected', 'noHeartbeat', 'intermittentHeartbeat', 'poweredOn', 'poweredOff', 'suspended')]
[string]$YellowStateCondition,
[Parameter(ParameterSetName = 'State')]
[ValidateSet('disconnected', 'notResponding', 'connected', 'noHeartbeat', 'intermittentHeartbeat', 'poweredOn', 'poweredOff', 'suspended')]
[string]$RedStateCondition,
[Parameter(Mandatory = $true, ParameterSetName = 'Metric')]
[string]$MetricId,
[Parameter(Mandatory = $true, ParameterSetName = 'Metric')]
[VMware.Vim.MetricAlarmOperator]$MetricOperator,
[Parameter(ParameterSetName = 'Metric')]
[ValidateRange(1, 100)]
[int32]$Yellow,
[Parameter(ParameterSetName = 'Metric')]
[ValidateRange(1, 90)]
[int32]$YellowInterval,
[Parameter(ParameterSetName = 'Metric')]
[ValidateRange(1, 100)]
[int32]$Red,
[Parameter(ParameterSetName = 'Metric')]
[ValidateRange(1, 90)]
[int32]$RedInterval,
[Parameter(Mandatory = $true)]
[ValidateSet('ClusterComputeResource', 'Datacenter', 'Datastore', 'DistributedVirtualSwitch', 'HostSystem', 'Network', 'ResourcePool', 'VirtualMachine')]
[string]$ObjectType
)
try {
if ($PSCmdlet.ShouldProcess("vCenter alarm", "Create $($PSCmdlet.ParameterSetName) trigger")) {
if ($PSCmdlet.ParameterSetName -eq 'Event') {
$Expression = New-Object -TypeName VMware.Vim.EventAlarmExpression
$Expression.EventType = $PSBoundParameters['EventType']
if ($PSBoundParameters.ContainsKey('EventTypeId')) {
$Expression.EventTypeId = $PSBoundParameters['EventTypeId']
}
$Expression.ObjectType = $PSBoundParameters['ObjectType']
$Expression.Status = $PSBoundParameters['Status']
$Expression
} elseif ($PSCmdlet.ParameterSetName -eq 'Metric') {
$Expression = New-Object -TypeName VMware.Vim.MetricAlarmExpression
$Expression.Metric = New-Object -TypeName VMware.Vim.PerfMetricId
$Expression.Metric.CounterId = $PSBoundParameters['MetricId']
$Expression.Metric.Instance = ""
$Expression.Operator = $PSBoundParameters['MetricOperator']
$Expression.Red = ($PSBoundParameters['Red'] * 100)
$Expression.RedInterval = ($PSBoundParameters['RedInterval'] * 60)
$Expression.Yellow = ($PSBoundParameters['Yellow'] * 100)
$Expression.YellowInterval = ($PSBoundParameters['YellowInterval'] * 60)
$Expression.Type = $PSBoundParameters['ObjectType']
$Expression
} elseif ($PSCmdlet.ParameterSetName -eq 'State') {
$Expression = New-Object -TypeName VMware.Vim.StateAlarmExpression
$Expression.Operator = $PSBoundParameters['StateOperator']
$Expression.Type = $PSBoundParameters['ObjectType']
$Expression.StatePath = $PSBoundParameters['StateType']
if ($PSBoundParameters.ContainsKey('RedStateCondition')) {
if ($PSBoundParameters['RedStateCondition'] -eq 'intermittentHeartbeat') {
$Expression.Red = 'yellow'
} elseif ($PSBoundParameters['RedStateCondition'] -eq 'noHeartbeat') {
$Expression.Red = 'red'
} else {
$Expression.Red = $PSBoundParameters['RedStateCondition']
}
}
if ($PSBoundParameters.ContainsKey('YellowStateCondition')) {
if ($PSBoundParameters['YellowStateCondition'] -eq 'intermittentHeartbeat') {
$Expression.Yellow = 'yellow'
} elseif ($PSBoundParameters['YellowStateCondition'] -eq 'noHeartbeat') {
$Expression.Yellow = 'red'
} else {
$Expression.Yellow = $PSBoundParameters['YellowStateCondition']
}
}
$Expression
}
}
} catch {
$PSCmdlet.ThrowTerminatingError($_)
}
} #End of New-AlarmTrigger function
function Get-MetricId {
<#
.SYNOPSIS
This cmdlet collects all of the available metrics from vCenter.
.DESCRIPTION
This cmdlet collects all of the available metrics from vCenter. It will
provide the metric name, key, stats level, and summary of the metric.
The information can be used to identify the available metrics on vCenter
as well as gathering the metric key needed for configuring an alarm.
The metric keys are unique across vCenters. If you are connected to
more than one vCenter metrics from each vCenter will be generated. A
vCenter property is available to help determine the correct metric key
on a given vCenter. This is extrememly useful when trying to create
a metric based vCenter alarm.
.PARAMETER MetricGroup
Specifies the name of the metric group you would like to see. Allowed
values are 'CPU', 'Mem', 'Disk', 'Net', and 'Datastore'.
.OUTPUTS
System.Management.Automation.PSCustomObject
.NOTES
This cmdlet requires a connection to vCenter to collect metric data.
.EXAMPLE
PS C:\> Get-MetricId -MetricGroup Mem
Name : mem.usage.none
Key : 23
Level : 4
Summary : Memory usage as percentage of total configured or available memory
vCenter : vCenter01
Name : mem.usage.average
Key : 24
Level : 1
Summary : Memory usage as percentage of total configured or available memory
vCenter : vCenter01
Name : mem.usage.minimum
Key : 25
Level : 4
Summary : Memory usage as percentage of total configured or available memory
vCenter : vCenter01
.....
Collects all of the available memory metrics on the connected vCenter.
#>
[CmdletBinding()]
param (
[ValidateSet('CPU', 'Mem', 'Disk', 'Net', 'Datastore')]
[string]$MetricGroup
)
foreach ($Mgr in (Get-View PerformanceManager-PerfMgr)) {
$vCenter = $Mgr.Client.ServiceUrl.Split('/')[2]
if ($PSBoundParameters.ContainsKey('MetricGroup')) {
$Metrics += $Mgr.PerfCounter | Where-Object -FilterScript {
$_.GroupInfo.Key -eq $PSBoundParameters['MetricGroup']
}
} else {
$Metrics += $Mgr.PerfCounter
}
$Metrics | ForEach-Object -Process {
[pscustomobject] @{
Name = $_.GroupInfo.Key + "." + $_.NameInfo.key + "." + $_.RollupType
Key = $_.Key
Level = $_.Level
Summary = $_.NameInfo.Summary
vCenter = $vCenter
}
}
}
} #End of Get-MetricId function
function Get-EventId {
<#
.SYNOPSIS
This cmdlet collects all of the available events from vCenter.
.DESCRIPTION
This cmdlet collects all of the available events from vCenter. It will
provide the event type, event type id (if applicable), category,
description, and summary of the event. The information can be used to
identify the available events on vCenter as well as gathering the event
type and event type id (if applicable) required for configuring an alarm.
If the event type is 'EventEx' or 'ExtendedEvent' both the event type
and event type id will be required to create a new event based vCenter
alarm.
The event types can be unique across vCenters. If you are connected to
more than one vCenter events from each vCenter will be generated. A
vCenter property is available to help determine the correct event type
on a given vCenter. This is extrememly useful when trying to create
a event based vCenter alarm.
.PARAMETER Category
Specifies the name of the event category you would like to see. Allowed
values are 'info', 'warning', 'error', and 'user'.
.OUTPUTS
System.Management.Automation.PSCustomObject
.NOTES
This cmdlet requires a connection to vCenter to collect event data.
.EXAMPLE
PS C:\> Get-EventId -Category Error
EventType : ExtendedEvent
EventTypeId : ad.event.ImportCertFailedEvent
Category : error
Description : Import certificate failure
FullFormat : Import certificate failed.
vCenter : vCenter01
EventType : ExtendedEvent
EventTypeId : ad.event.JoinDomainFailedEvent
Category : error
Description : Join domain failure
FullFormat : Join domain failed.
vCenter : vCenter01
EventType : ExtendedEvent
EventTypeId : ad.event.LeaveDomainFailedEvent
Category : error
Description : Leave domain failure
FullFormat : Leave domain failed.
vCenter : vCenter01
.....
#>
[CmdletBinding()]
param (
[VMware.Vim.EventCategory]$Category
)
foreach ($Mgr in (Get-View EventManager)) {
$vCenter = $Mgr.Client.ServiceUrl.Split('/')[2]
if ($PSBoundParameters.ContainsKey('Category')) {
$Events += $Mgr.Description.EventInfo | Where-Object -FilterScript {
$_.Category -eq $PSBoundParameters['Category']
}
} else {
$Events += $Mgr.Description.EventInfo
}
$Events | ForEach-Object -Process {
$Hash = [ordered]@{}
$Hash.Add('EventType', $_.Key)
if ($_.Key -eq 'ExtendedEvent' -or $_.Key -eq 'EventEx') {
$Hash.Add('EventTypeId', $_.FullFormat.Split('|')[0])
}
$Hash.Add('Category', $_.Category)
$Hash.Add('Description', $_.Description)
if ($Hash['EventType'] -eq 'ExtendedEvent' -or $Hash['EventType'] -eq 'EventEx') {
$Hash.Add('FullFormat', $_.FullFormat.Split('|')[1])
} else {
$Hash.Add('FullFormat', $_.FullFormat)
}
$Hash.Add('vCenter', $vCenter)
New-Object -TypeName System.Management.Automation.PSObject -Property $Hash
}
}
} #End of Get-EventId function

View File

@@ -0,0 +1,475 @@
Function Export-DRSRules {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/21/2017
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Export DRS Rules to JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.DESCRIPTION
Export DRS Rules to JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.EXAMPLE
Export-DRSRules -Path C:\Users\primp\Desktop\VMworld2017 -Cluster Windows-Cluster
#>
param(
[Parameter(Mandatory=$false)][String]$Path,
[Parameter(Mandatory=$true)][String]$Cluster
)
$rules = Get-Cluster -Name $Cluster | Get-DrsRule
$results = @()
foreach ($rule in $rules) {
$vmNames = @()
$vmIds = $rule.VMIds
# Reconstruct MoRef ID to VM Object to get Name
foreach ($vmId in $vmIds) {
$vm = New-Object VMware.Vim.ManagedObjectReference
$vm.Type = "VirtualMachine"
$vm.Value = ($vmId -replace "VirtualMachine-","")
$vmView = Get-View $vm
$vmNames += $vmView.name
}
$rulesObject = [pscustomobject] @{
Name = $rule.ExtensionData.Name;
Type = $rule.Type; #VMAffinity = 1, VMAntiAffinity = 0
Enabled = $rule.Enabled;
Mandatory = $rule.ExtensionData.Mandatory
VM = $vmNames
}
$results+=$rulesObject
}
if($Path) {
$fullPath = $Path + "\DRSRules.json"
Write-Host -ForegroundColor Green "Exporting DRS Rules to $fullpath ..."
$results | ConvertTo-Json | Out-File $fullPath
} else {
$results | ConvertTo-Json
}
}
Function Import-DRSRules {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/21/2017
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Import DRS Rules from JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.DESCRIPTION
Import DRS Rules from JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.EXAMPLE
Import-DRSRules -Path C:\Users\primp\Desktop\VMworld2017 -Cluster Windows-Cluster
#>
param(
[Parameter(Mandatory=$true)][String]$Path,
[Parameter(Mandatory=$true)][String]$Cluster
)
Get-DrsRule -Cluster $cluster | Remove-DrsRule -Confirm:$false | Out-Null
$DRSRulesFilename = "/DRSRules.json"
$fullPath = $Path + $DRSRulesFilename
$json = Get-Content -Raw $fullPath | ConvertFrom-Json
foreach ($line in $json) {
$vmArr = @()
$vmNames = $line.vm
foreach ($vmName in $vmNames) {
$vmView = Get-VM -Name $vmName
$vmArr+=$vmView
}
New-DrsRule -Name $line.name -Enabled $line.Enabled -Cluster (Get-Cluster -Name $Cluster) -KeepTogether $line.Type -VM $vmArr
}
}
Function Export-DRSClusterGroup {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/21/2017
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Export DRS Cluster Group Rules to JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.DESCRIPTION
Export DRS Cluster Group Rules to JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.EXAMPLE
Export-DRSClusterGroup -Path C:\Users\primp\Desktop\VMworld2017 -Cluster Windows-Cluster
#>
param(
[Parameter(Mandatory=$false)][String]$Path,
[Parameter(Mandatory=$true)][String]$Cluster
)
$rules = Get-Cluster -Name $Cluster | Get-DrsClusterGroup
$results = @()
foreach ($rule in $rules) {
$rulesObject = [pscustomobject] @{
Name = $rule.ExtensionData.Name;
Type = $rule.GroupType; #VMType = 1, HostType = 0
Member = $rule.Member
}
$results+=$rulesObject
}
if($Path) {
$fullPath = $Path + "\DRSClusterGroupRules.json"
Write-Host -ForegroundColor Green "Exporting DRS Cluster Group Rules to $fullpath ..."
$results | ConvertTo-Json | Out-File $fullPath
} else {
$results | ConvertTo-Json
}
}
Function Import-DRSClusterClusterGroup {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/21/2017
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Import DRS Cluster Group Rules from JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.DESCRIPTION
Import DRS Cluster Group Rules from JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.EXAMPLE
Import-DRSClusterClusterGroup -Path C:\Users\primp\Desktop\VMworld2017 -Cluster Windows-Cluster
#>
param(
[Parameter(Mandatory=$true)][String]$Path,
[Parameter(Mandatory=$true)][String]$Cluster
)
$DRSClusterGroupRulesFilename = "\DRSClusterGroupRules.json"
$fullPath = $Path + $DRSClusterGroupRulesFilename
$json = Get-Content -Raw $fullPath | ConvertFrom-Json
foreach ($line in $json) {
$memberArr = @()
$members = $line.member
# VMHost Group
if($line.Type -eq 0) {
foreach ($member in $members) {
$memberView = Get-VMhost -Name $member
$memberArr+=$memberView
}
New-DrsClusterGroup -Name $line.name -Cluster (Get-Cluster -Name $Cluster) -VMhost $memberArr
# VM Group
} else {
foreach ($member in $members) {
$memberView = Get-VM -Name $member
$memberArr+=$memberView
}
New-DrsClusterGroup -Name $line.name -Cluster (Get-Cluster -Name $Cluster) -VM $memberArr
}
}
}
Function Export-Tag {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/21/2017
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Export vSphere Tags and VM Assocations to JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.DESCRIPTION
Export vSphere Tags and VM Assocations to JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.EXAMPLE
Export-Tag -Path C:\Users\primp\Desktop\VMworld2017
#>
param(
[Parameter(Mandatory=$false)][String]$Path
)
# Export Tag Categories
$tagCatagorys = Get-TagCategory
$tagCatresults = @()
foreach ($tagCategory in $tagCatagorys) {
$tagCatObj = [pscustomobject] @{
Name = $tagCategory.Name;
Cardinality = $tagCategory.Cardinality;
Description = $tagCategory.Description;
Type = $tagCategory.EntityType
}
$tagCatresults+=$tagCatObj
}
if($Path) {
$fullPath = $Path + "\AllTagCategory.json"
Write-Host -ForegroundColor Green "Exporting vSphere Tag Category to $fullpath ..."
$tagCatresults | ConvertTo-Json | Out-File $fullPath
} else {
$tagCatresults | ConvertTo-Json
}
# Export Tags
$tags = Get-Tag
$tagResults = @()
foreach ($tag in $tags) {
$tagObj = [pscustomobject] @{
Name = $tag.Name;
Description = $tag.Description;
Category = $tag.Category.Name
}
$tagResults+=$tagObj
}
if($Path) {
$fullPath = $Path + "\AllTag.json"
Write-Host -ForegroundColor Green "Exporting vSphere Tag to $fullpath ..."
$tagResults | ConvertTo-Json | Out-File $fullPath
} else {
$tagResults | ConvertTo-Json
}
# Export VM to Tag Mappings
$vms = Get-VM
$vmResults = @()
foreach ($vm in $vms) {
$tagAssignments = $vm | Get-TagAssignment
$tags = @()
foreach ($tagAssignment in $tagAssignments) {
$tag = $tagAssignment.Tag
$tagName = $tag -split "/"
$tags+=$tagName
}
$vmObj = [pscustomobject] @{
Name = $vm.name;
Tag = $tags
}
$vmResults+=$vmObj
}
if($Path) {
$fullPath = $Path + "\AllTagAssocations.json"
Write-Host -ForegroundColor Green "Exporting VM to vSphere Tag Assignment to $fullpath ..."
$vmResults | ConvertTo-Json | Out-File $fullPath
} else {
$vmResults | ConvertTo-Json
}
}
Function Import-Tag {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/21/2017
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Import vSphere Tags and VM Assocations from JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.DESCRIPTION
Import vSphere Tags and VM Assocations from JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.EXAMPLE
Import-Tag -Path C:\Users\primp\Desktop\VMworld2017
#>
param(
[Parameter(Mandatory=$true)][String]$Path
)
$tagCatFilename = "\AllTagCategory.json"
$fullPath = $Path + $tagCatFilename
$tagCategoryJson = Get-Content -Raw $fullPath | ConvertFrom-Json
$tagFilename = "\AllTag.json"
$fullPath = $Path + $tagFilename
$tagJson = Get-Content -Raw $fullPath | ConvertFrom-Json
$vmTagFilename = "\AllTagAssocations.json"
$fullPath = $Path + $vmTagFilename
$vmTagJson = Get-Content -Raw $fullPath | ConvertFrom-Json
# Re-Create Tag Category
foreach ($category in $tagCategoryJson) {
if($category.Cardinality -eq 0) {
$cardinality = "Single"
} else {
$cardinality = "Multiple"
}
New-TagCategory -Name $category.Name -Cardinality $cardinality -Description $category.Description -EntityType $category.Type
}
# Re-Create Tags
foreach ($tag in $tagJson) {
New-Tag -Name $tag.Name -Description $tag.Description -Category (Get-TagCategory -Name $tag.Category)
}
# Re-Create VM to Tag Mappings
foreach ($vmTag in $vmTagJson) {
$vm = Get-VM -Name $vmTag.name
$tags = $vmTag.Tag
foreach ($tag in $tags) {
New-TagAssignment -Entity $vm -Tag (Get-Tag -Name $tag)
}
}
}
Function Export-VMFolder {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/21/2017
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Export vSphere Folder to JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.DESCRIPTION
Export vSphere Folder to JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.EXAMPLE
Export-VMFolder -Path C:\Users\primp\Desktop\VMworld2017
#>
param(
[Parameter(Mandatory=$false)][String]$Path
)
$vms = Get-VM
$vmFolderResults = @()
foreach ($vm in $vms) {
$vmFolderObj = [pscustomobject] @{
Name = $vm.name;
Folder = $vm.Folder.Name;
}
$vmFolderResults+=$vmFolderObj
}
if($Path) {
$fullPath = $Path + "\AllVMFolder.json"
Write-Host -ForegroundColor Green "Exporting VM Folders to $fullpath ..."
$vmFolderResults | ConvertTo-Json | Out-File $fullPath
} else {
$vmFolderResults | ConvertTo-Json
}
}
Function Import-VMFolder {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/21/2017
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Import vSphere Folder from JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.DESCRIPTION
Import vSphere Folder from JSON file based on VMworld Demo https://youtu.be/MagjfbIL4kg
.EXAMPLE
Import-VMFolder -Path C:\Users\primp\Desktop\VMworld2017
#>
param(
[Parameter(Mandatory=$true)][String]$Path
)
$vmFolderFilename = "\AllVMFolder.json"
$fullPath = $Path + $vmFolderFilename
$vmFolderJson = Get-Content -Raw $fullPath | ConvertFrom-Json
# Root vm Folder
$rootVMFolder = Get-Folder -Type VM -Name vm
$folders = $vmFolderJson | Select Folder | Sort-Object -Property Folder -Unique
foreach ($folder in $folders) {
$rootVMFolder | New-Folder -Name $folder.folder
}
foreach ($vmFolder in $vmFolderJson) {
$vm = Get-VM -Name $vmFolder.Name
$folder = Get-Folder -Name $vmFolder.Folder
Move-VM -VM $vm -Destination $folder
}
}
Function Export-VMStoragePolicy {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/21/2017
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Export VM Storage Policies to JSON file
.DESCRIPTION
Export VM Storage Policies to JSON file
.EXAMPLE
Export-VMStoragePolicy -Path C:\Users\primp\Desktop\VMworld2017
#>
param(
[Parameter(Mandatory=$false)][String]$Path
)
foreach ($policy in Get-SpbmStoragePolicy) {
$policyName = $policy.Name
if($Path) {
Write-Host -ForegroundColor Green "Exporting Policy $policyName to $Path\$policyName.xml ..."
$policy | Export-SpbmStoragePolicy -FilePath $Path\$policyName.xml -Force | Out-Null
} else {
$policy
}
}
}
Function Import-VMStoragePolicy {
<#
.NOTES
===========================================================================
Created by: William Lam
Date: 11/21/2017
Blog: https://www.virtuallyghetto.com
Twitter: @lamw
===========================================================================
.SYNOPSIS
Import VM Storage Policies from JSON file
.DESCRIPTION
Import VM Storage Policies from JSON file
.EXAMPLE
Import-VMStoragePolicy -Path C:\Users\primp\Desktop\VMworld2017
#>
param(
[Parameter(Mandatory=$false)][String]$Path
)
foreach ($file in Get-ChildItem -Path $Path -Filter *.xml) {
$policyName = $file.name
$policyName = $policyName.replace(".xml","")
if(Get-SpbmStoragePolicy -Name $policyName -ErrorAction SilentlyContinue) {
Continue
} else {
Write-Host "Importing Policy $policyname ..."
Import-SpbmStoragePolicy -FilePath $Path\$file -Name $policyName
}
}
}

View File

@@ -59,15 +59,15 @@ The repository has been provided to allow the community to share resources that
1. Browse to the appropriate section (example: Scripts)
2. Select the “Create new file” button
3. On the new page, enter a file name, enter the resources information
4. Within the “Commit new file” area, enter the title and description, then select “Create a new branch for this commit…” and enter a sensical branch name
4. Within the “Commit new file” area, enter the title and description, then select “Create a new branch for this commit…” and enter a sensible branch name
5. Click “Propose new file”
6. On the “Open a pull request” page, click “Create pull request”
#### GitHub - Upload files Option
1. Browse to the appropriate section (example: Modules)
2. Select the “Upload files” button
3. On the new page, drag or choose the files to add
4. Within the “Commit changes” area, enter the title and description, then select “Create a new branch for this commit…” and enter a sensical branch name
3. On the new page, drag or choose the files to add
4. Within the “Commit changes” area, enter the title and description, then select “Create a new branch for this commit…” and enter a sensible branch name
5. Click “Propose new file”
6. On the “Open a pull request” page, click “Create pull request”
@@ -88,7 +88,7 @@ The following information must be included with each submitted scripting resourc
#### Note Placement Examples:
Script: Top few lines
Module: Module manifest
#### Required Script Note Example:
`<#`
`Script name: script_name.ps1`
@@ -126,7 +126,7 @@ The following information should be included when possible. Inclusion of informa
This section describes guidelines put in place to maintain a standard of quality while also promoting broader contribution.
### General Best Practices
### Resource Naming
* Give the resource a name that is indicitive of the actions and/or results of its running
* Give the resource a name that is indicative of the actions and/or results of its running
### Fault Handling
* Read and apply the following basic fault handling where applicable: Microsofts Hey, Scripting Guy! Blog: https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/09/handling-errors-the-powershell-way/
@@ -138,7 +138,7 @@ This section describes guidelines put in place to maintain a standard of quality
* Avoid changing any global variables
### Help Information
* All resources should have inline documentation.
* All resources should have inline documentation.
### Scripts
* The script should be easy to read and understand
@@ -149,27 +149,27 @@ This section describes guidelines put in place to maintain a standard of quality
* Use only standard verbs
### Security
* Usage of PowerShells strict mode is preferred, but not required.
* Usage of PowerShells strict mode is preferred, but not required.
* Remove any information related to ones own environment (examples: Passwords, DNS/IP Addresses, custom user credentials, etc)
## Resource Maintenance
### Maintenance Ownership
Ownership of any and all submitted resources are maintained by the submitter. This ownership also includes maintenance of any and all submitted resources.
Ownership of any and all submitted resources are maintained by the submitter. This ownership also includes maintenance of any and all submitted resources.
### Filing Issues
Any bugs or other issues should be filed within GitHub by way of the repositorys Issue Tracker.
### Resolving Issues
Any community member can resolve issues within the repository, however only the owner or a board member can approve the update. Once approved, assuming the resolution involves a pull request, only a board member will be able to merge and close the request.
Any bugs or other issues should be filed within GitHub by way of the repositorys Issue Tracker.
### Resolving Issues
Any community member can resolve issues within the repository, however only the owner or a board member can approve the update. Once approved, assuming the resolution involves a pull request, only a board member will be able to merge and close the request.
## Additional Resources
### Discussions
Join in on the discussion within the VMware Code Slack team's PowerCLI channel: <https://code.vmware.com/slack/>
### VMware Sample Exchange
It is highly recommened to add any and all submitted resources to the VMware Sample Exchange: <https://developercenter.vmware.com/samples>
It is highly recommended to add any and all submitted resources to the VMware Sample Exchange: <https://developercenter.vmware.com/samples>
Sample Exchange can be allowed to access your GitHub resources, by way of a linking process, where they can be indexed and searched by the community. There are VMware social media accounts which will advertise resources posted to the site and there's no additional accounts needed, as the VMware Sample Exchange uses MyVMware credentials.
## VMWARE TECHNOLOGY PREVIEW LICENSE AGREEMENT
The VMware Technnology Preview License Agreement: <https://github.com/vmware/PowerCLI-Example-Scripts/blob/master/LICENSE.md>
The VMware Technology Preview License Agreement: <https://github.com/vmware/PowerCLI-Example-Scripts/blob/master/LICENSE.md>
# Repository Administrator Resources
## Table of Contents
@@ -180,7 +180,7 @@ The VMware Technnology Preview License Agreement: <https://github.com/vmware/Pow
Board members are volunteers from the PowerCLI community and VMware staff members, board members are not held responsible for any issues which may occur from running of scripts inside this repository.
Members:
Members:
* Josh Atwell (Community Member)
* Luc Dekens (Community Member)
* Jonathan Medd (Community Member)
@@ -189,4 +189,4 @@ Members:
* Rynardt Spies (Community Member)
## Approval of Additions
Items added to the repository, including items from the Board members, require a review and approval from at least one board member before being added to the repository. The approving member/s will have verified for a lack of malicious code. Once an “Approved for Merge” comment has been added from a board member, the pull can then be committed to the repository.
Items added to the repository, including items from the Board members, require a review and approval from at least one board member before being added to the repository. The approving member/s will have verified for a lack of malicious code. Once an “Approved for Merge” comment has been added from a board member, the pull can then be committed to the repository.

View File

@@ -0,0 +1,19 @@
<#
Script name: CreateVLANonStandardSwitch.ps1
Created on: 10/26/2017
Author: Alan Comstock, @Mr_Uptime
Description: Adds VLANs to an existing standard switch
Dependencies: None known
PowerCLI Version: VMware PowerCLI 6.5 Release 1 build 4624819
PowerShell Version: 5.1.14393.1532
OS Version: Windows 10
#>
$esxhost="HOSTNAME"
$vswitch="vSwitch0"
$vlanlist=10,20,30,40,50
Foreach ($vlan in $vlanlist) {
$portgroupname="VLAN " + $vlan
Get-VMHost $esxhost | Get-VirtualSwitch -name $vswitch | New-VirtualPortGroup -Name $portgroupname -VLanId $vlan
}
#The End

View File

@@ -0,0 +1,30 @@
$myCol = @()
$start = (Get-Date).AddDays(-30)
$finish = Get-Date
$cluster= "Demo"
$objServers = Get-Cluster $cluster | Get-VM
foreach ($server in $objServers) {
if ($server.guest.osfullname -ne $NULL){
if ($server.guest.osfullname.contains("Windows")){
$stats = get-stat -Entity $server -Stat "cpu.usage.average","mem.usage.average" -Start $start -Finish $finish
$ServerInfo = "" | Select-Object vName, OS, Mem, AvgMem, MaxMem, CPU, AvgCPU, MaxCPU, pDisk, Host
$ServerInfo.vName = $server.name
$ServerInfo.OS = $server.guest.osfullname
$ServerInfo.Host = $server.vmhost.name
$ServerInfo.Mem = $server.memoryGB
$ServerInfo.AvgMem = $("{0:N2}" -f ($stats | Where-Object {$_.MetricId -eq "mem.usage.average"} | Measure-Object -Property Value -Average).Average)
$ServerInfo.MaxMem = $("{0:N2}" -f ($stats | Where-Object {$_.MetricId -eq "mem.usage.average"} | Measure-Object -Property Value -Maximum).Maximum)
$ServerInfo.CPU = $server.numcpu
$ServerInfo.AvgCPU = $("{0:N2}" -f ($stats | Where-Object {$_.MetricId -eq "cpu.usage.average"} | Measure-Object -Property Value -Average).Average)
$ServerInfo.MaxCPU = $("{0:N2}" -f ($stats | Where-Object {$_.MetricId -eq "cpu.usage.average"} | Measure-Object -Property Value -Maximum).Maximum)
$ServerInfo.pDisk = [Math]::Round($server.ProvisionedSpaceGB,2)
$mycol += $ServerInfo
}
}
}
$myCol | Sort-Object vName | Export-Csv "VM_report.csv" -NoTypeInformation

235
Scripts/Get-CIVMData.ps1 Normal file
View File

@@ -0,0 +1,235 @@
Function Get-CIVMData
{
<#
.SYNOPSIS
Gathers information about a target CIVM
.DESCRIPTION
This function gathers CIVM Name, Parent vApp (obj), Parent vApp Name, All network adapters
(including IP, NIC index, and network), and vCenter VMX path details returning the resulting
ordered list.
.PARAMETER CIVM
The target vCloud VM from which information will be gathered
.NOTES
Author: Brian Marsh
Version: 1.0
#>
[CmdletBinding()]
Param (
[Parameter(
Position=0,
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[VMware.VimAutomation.Cloud.Types.V1.CIVM] $CIVM
)
BEGIN
{
}
PROCESS
{
$NewObj = [Ordered]@{}
$NewObj.GetCIVMData = @{}
$NewObj.GetCIVMData.Successful = $true
# Get the vCenter VM from the vCloud VM object
$vm = $civm | Get-VM -Debug:$False -Verbose:$False
Write-Verbose "Storing CIVM Name: $($CIVM.Name)/ Status: $($CIVM.Status)"
$NewObj.Name = $CIVM.Name
$NewObj.Status = $CIVM.Status
Write-Verbose "Recording Reservations"
$NewObj.Reservations = @{}
$NewObj.Reservations.CPU = @{}
$NewObj.Reservations.Memory = @{}
$NewObj.Reservations.CPU.Reservation = $vm.ExtensionData.ResourceConfig.CpuAllocation.Reservation
$NewObj.Reservations.CPU.Limit = $vm.ExtensionData.ResourceConfig.CpuAllocation.Limit
$NewObj.Reservations.Memory.Reservation = $vm.ExtensionData.ResourceConfig.MemoryAllocation.Reservation
$NewObj.Reservations.Memory.Limit = $vm.ExtensionData.ResourceConfig.MemoryAllocation.Limit
# Get the UUid from the Id, split out the UUID and pass it along
# Sample Id: urn:vcloud:vm:d9ca710d-cdf2-44eb-a274-26e1dcfd01bb
Write-Verbose "Storing CIVM UUID: $(($CIVM.Id).Split(':')[3])"
$NewObj.Uuid = ($CIVM.Id).Split(':')[3]
Write-Verbose "Gathering Network details"
$vAppNetworkAdapters = @()
$NetworkAdapters = Get-CINetworkAdapter -VM $civm -Debug:$False -Verbose:$False
foreach ($networkAdapter in $networkAdapters)
{
# Remove any existing VMNIC variables
Remove-Variable -Name VMNic -ErrorAction SilentlyContinue
$vAppNicInfo = [Ordered]@{}
$vAppNicInfo.NIC = ("NIC" + $networkAdapter.Index)
$vAppNicInfo.Index = $networkAdapter.Index
$vAppNicInfo.Connected = $networkAdapter.Connected
$vAppNicInfo.ExternalIP = $networkAdapter.IpAddress
$vAppNicInfo.InternalIP = $networkAdapter.ExternalIpAddress
$vAppNicInfo.MacAddress = $networkAdapter.MACAddress
$vAppNicInfo.vAppNetwork = [Ordered]@{}
$vAppNicInfo.vAppNetwork.Name = $networkAdapter.VAppNetwork.Name
<#
There is a chance that the vApp Network Name may not match a PortGroup which causes issues upon importing the VM after migration.
To fix this issue, we'll try to find get the PortGroup in this data gathering stage. If it is not found, we'll move on to attempted
remediation:
1) Get the vCenter VM network adapter that corresponds to this vCloud Director VM network adapter (where MAC Addresses match)
2) If the vCenter VM network adapter's network name doesn't match 'none' (indicating the VM is powered off) and the vCenter Network
name does not match the vCloud Director network name, set this target object's vAppNetwork Name to the vCenter PortGroup
3) If the vCenter VM network adapter's network name is 'none' then this VM is probably powered off and the network information is
not defined in vCenter. In this case, we mark the get-data as unsuccessful, set an error message and return.
#>
try
{
$vm | Get-VMHost -Debug:$false -Verbose:$false | Get-VDSwitch -Debug:$false -Verbose:$false -ErrorAction Stop | `
Get-VDPortgroup -name $networkAdapter.vAppNetwork.Name -Debug:$false -Verbose:$false -ErrorAction Stop | Out-Null
}
catch
{
Write-Debug "Portgroup not found by name $($networkAdapter.vAppNetwork.Name), Debug?"
Write-Verbose "Portgroup not found by name $($networkAdapter.vAppNetwork.Name), attempting fall back."
# Get VIVM network adapter where adapter mac matches vappnicinfo MacAddress
$VMNic = $vm | Get-NetworkAdapter -Debug:$false -Verbose:$false | Where-Object { $_.MacAddress -eq $vAppNicInfo.MacAddress }
# If VMNic Network Name doesn't match 'none' and doesn't match the vAppNetworkName, set vAppNetwork name to VMNic Network name
If ( ($VMNic.NetworkName -notlike 'none') -and ($VMNic.NetworkName -ne $vAppNicInfo.vAppNetwork.Name))
{
$vAppNicInfo.vAppNetwork.Name = $VMNic.NetworkName
}
else
{
Write-Debug "Tried to recover from missing network port group. Failed. Debug?"
$ErrorMessage = "VM [ $($CIVM.Name) ] has vAppNetwork connection that doesn't exist in vCenter [ $($vAppNicInfo.vAppNetwork.Name) ]"
$NewObj.GetCIVMData.Successful = $False
$NewObj.GetCIVMData.Error = $ErrorMessage
Write-Error $ErrorMessage
#Return whatever object we have at this point
$NewObj
Return
}
}
$vAppNetworkAdapters += $vAppNicInfo
}
Write-Verbose "Checking for Duplicate name upon Import"
Try
{
$DupeVM = Get-VM -Name $NewObj.NewName -Debug:$false -Verbose:$false -ErrorAction Stop -ErrorVariable DupeVM
If ($DupeVM)
{
$NewObj.GetCIVMData.Successful = $False
$NewObj.GetCIVMData.Error = "VM with name $($NewObj.NewName) already exists in vCenter"
Write-Error "VM with name $($NewObj.NewName) already exists in vCenter"
#Return whatever object we have at this point
$NewObj
return
}
}
Catch
{
Write-Verbose "No Duplicate Name Found!"
}
$NewObj.vAppNetworkAdapters = $vAppNetworkAdapters
Write-Verbose "Setting VIVIM object, parent vApp details, and CIVM object"
try
{
$NewObj.VIVM = $vm
$NewObj.ToolsStatus = $vm.ExtensionData.Guest.ToolsStatus
$NewObj.ToolsRunningStatus = $vm.ExtensionData.Guest.ToolsRunningStatus
$NewObj.HasSnapshots = ($vm | Get-Snapshot -Debug:$false -Verbose:$false -ErrorAction Stop | Select-Object Name, Description,VMId)
$NewObj.NeedsConsolidation = $vm.ExtensionData.Runtime.ConsolidationNeeded
$NewObj.OldMoref = $vm.Id
$NewObj.VmPathName = $vm.ExtensionData.Config.Files.VmPathName
$NewObj.ParentVApp = $CIVM.VApp.Name
$NewObj.StorageReservation = ($vm |Get-DatastoreCluster -Debug:$false -Verbose:$false -ErrorAction Stop | Select-Object -ExpandProperty Name)
$NewObj.CIVMId = $CIVM.Id
}
catch
{
$NewObj.GetCIVMData.Successful = $False
$NewObj.GetCIVMData.Error = "VM [ $($CIVM.Name) ] something went wrong while gathering details: $_"
Write-Debug "VM [ $($CIVM.Name) ] something went wrong while gathering details: $_, Debug"
Write-Error "VM [ $($CIVM.Name) ] something went wrong while gathering details: $_. "
#Return whatever object we have at this point
$NewObj
Return
}
# If ToolsStatus is not 'toolsOk' and status is not "PoweredOn", bomb out. We won't be able to power this VM off later.
If ($NewObj.ToolsRunningStatus -ne 'guestToolsRunning' -and $NewObj.status -eq "PoweredOn")
{
$NewObj.GetCIVMData.Successful = $False
$NewObj.GetCIVMData.Error = "VM [ $($CIVM.Name) ] tools are not running but the VM is powered On. Fix and try again."
Write-Debug "VM [ $($CIVM.Name) ] tools are not running but the VM is powered On, Debug"
Write-Error "VM [ $($CIVM.Name) ] tools are not running but the VM is powered On. "
#Return whatever object we have at this point
$NewObj
Return
}
If ($NewObj.HasSnapshots)
{
$NewObj.GetCIVMData.Successful = $False
$NewObj.GetCIVMData.Error = "VM [ $($CIVM.Name) ] has snapshots. Remove before trying again."
Write-Debug "VM [ $($CIVM.Name) ] has snapshots. Remove before trying again, Debug"
Write-Error "VM [ $($CIVM.Name) ] has snapshots. Remove before trying again."
#Return whatever object we have at this point
$NewObj
Return
}
Write-Verbose "Determining the VMX Path for this VM"
# Get this VM's path on disk
$vmPathName = $vm.ExtensionData.Config.Files.VmPathName
# Determine in which Datacenter this VM resides
$datacenter = $vm | get-Datacenter -Debug:$False -Verbose:$False | Select-Object -expand name
# Split out the datastore from the path name
$datastore = $vmPathName.Split("]")[0].split("[")[1]
# Split out the folder from the path name
$vmFolderPath = $vmPathName.Split("/")[0].split("]")[1].trim()
# Re-combine into a valid folder path
$vmxPath = "vmstore:\$($datacenter)\$($datastore)\$vmFolderPath"
Write-Verbose "VMXPath $vmxPath"
$NewObj.vmxPath = $vmxPath
$NewObj
}
END
{
Write-Debug "About to exit Get-CIVMData, anything else?"
Write-Verbose "Exited Get-CIVMData"
}
}

View File

@@ -0,0 +1,4 @@
#Script returns total disk usage by all Powered On VMs in the environment in Gigabytes
#Author: Chris Bradshaw via https://isjw.uk/using-powercli-to-measure-vm-disk-space-usage/
[math]::Round(((get-vm | Where-object{$_.PowerState -eq "PoweredOn" }).UsedSpaceGB | measure-Object -Sum).Sum)

View File

@@ -0,0 +1,6 @@
#Script gets total memory allocation in GB of all powered on VMs in the environment
#Author: Chris Bradshaw via https://isjw.uk/powercli-snippet-total-memory-allocation/
[System.Math]::Round(((get-vm |
where-object{$_.PowerState -eq "PoweredOn" }).MemoryGB |
Measure-Object -Sum).Sum ,0)

View File

@@ -0,0 +1,17 @@
function Get-VMHostWWPN {
<#
Script name: Get-VMHostWWPN.ps1
Created on: 08/31/2017
Author: Robin Haberstroh, @strohland
Description: This script returns the WWPN of the hosts FiberChannel HBA in a readable format that corresponds to what storage team expects
Dependencies: None known
#>
param(
[string]$cluster
)
Get-Cluster $cluster | get-vmhost | get-vmhosthba -type FibreChannel |
format-table VMHost, Device, @{
n='WorldWidePortName';e={[convert]::ToString($_.PortWorldWideName, 16)}
}
}

View File

@@ -0,0 +1,56 @@
<#
.SYNOPSIS
Finds the local ESXi network Port-ID where a VM is assigned
.DESCRIPTION
Reports back a VM's Port-ID according to the local ESXi host. This correlates to the Port-ID which is displayed via ESXTop
.NOTES
Author: Kyle Ruddy, @kmruddy, thatcouldbeaproblem.com
.PARAMETER vm
The name of the desired VM
.EXAMPLE
PS> .\Get-VMNetworkPortId.ps1 -vm vmname
.EXAMPLE
PS> Get-VM -Name vmname | .\Get-VMNetworkPortId.ps1
#>
[CmdletBinding(SupportsShouldProcess=$True)]
param(
[Parameter(Mandatory=$true,Position=0,ValueFromPipelineByPropertyName=$true)]
[Alias('Name')]
[String[]]$vm
)
Begin {
#Create an array to store output prior to return
$output = @()
}
Process {
#Loop through each of the input values
foreach ($v in $vm) {
#Validate the input is a valid VM
$vmobj = Get-VM -Name $v -erroraction silentlycontinue
if (!$vmobj) {Write-Verbose "No VM found by the name $v."}
else {
#Create a temporary object to store individual ouput
$tempout = "" | select VM,PortId
#Start an ESXCLI session with the host where the VM resides
$esxcli = Get-EsxCli -VMHost $vmobj.VMHost -v2
#ESXCLI call to obtain information about the VM, specifically its WorldID
$vmNetInfo = $esxcli.network.vm.list.Invoke() | ?{$_.Name -eq $vmobj.Name}
#Create spec to poll the host for the network information of the VM
$portArgs = $esxcli.network.vm.port.list.CreateArgs()
$portArgs.worldid = $vmNetInfo.WorldID
#Output the values to the temporary object
$tempout.VM = $vmobj.Name
$tempout.PortId = $esxcli.network.vm.port.list.Invoke($portArgs).PortId
$output += $tempout
}
}
}
End {
return $output
}

View File

@@ -0,0 +1,11 @@
$vms = Get-VM | where {$_.PowerState -eq "PoweredOn" -and $_.GuestId -match "Windows"}
ForEach ($vm in $vms){
Write-Host $vm
$namespace = "root\CIMV2"
$componentPattern = "hcmon|vmci|vmdebug|vmhgfs|VMMEMCTL|vmmouse|vmrawdsk|vmxnet|vmx_svga"
(Get-WmiObject -class Win32_SystemDriver -computername $vm -namespace $namespace |
where-object { $_.Name -match $componentPattern } |
Format-Table -Auto Name,State,StartMode,DisplayName
)
}

View File

@@ -0,0 +1,96 @@
<#
Script name: PowerCLI_FixNestedFolders.ps1
Created on: 01/11/2018
Author: Kyle Ruddy, @kmruddy, thatcouldbeaproblem.com
Description: The purpose of the script is to remove the nested Version based folders when using Powercli on systems using older versions of PowerShell
Dependencies: None known
===Tested Against Environment====
PowerCLI Version: PowerCLI 6.5.4
PowerShell Version: 5.1, 4.0
OS Version: Server 2016, Server 2012 R2
#>
# Variable used to store where the PowerCLI module folders exist
$pcliFolder = @()
# Variable used to store the current PSModulePath locations
$downloadDir = $env:PSModulePath.Split(';')
# Loop to detect PowerCLI module folders in any of the PSModulePath locations
foreach ($possPath in $downloadDir) {
# Verifying the PSModulePath location exists
if ((Test-Path -Path $possPath) -eq $true) {
# Searching for folders with the name of 'VMware.*'
$tempFolder = Get-ChildItem -Path $possPath -Name "VMware.*"
# If a VMware.* module folder is found, the full path is added to the pcliFolder variable
if ($tempFolder) {
foreach ($moduleName in $tempFolder) {
$pcliFolder += $possPath + "\" + $moduleName
}
}
}
}
# Verifying that there were PowerCLI module folders found
if ($pcliFolder) {
# Looping through each of the found PowerCLI module folders
foreach ($dir in $pcliFolder) {
# Variable to be used if there are several PowerCLI module versions available
$historicDir = $null
# Varibale used to store the PowerCLI module version folder
$tempDir = Get-ChildItem -Path $dir
# Verifying whether or not there are several PowerCLI module versions available by checking for a type of 'array'
if ($tempDir -is [array]) {
# Variable used to store the current folder structure
$historicDir = $tempDir
# Updating the tempDir variable to only contain the newest PowerCLI module version folder
$tempDir = $tempDir | Sort-Object Name -Descending | select-Object -First 1
}
# Verifying the child item is indeed a folder
if ($tempDir.GetType().Name -eq "DirectoryInfo") {
# Obtaining the child objects of the PowerCLI module version folder and copying them to the parent folder
$tempDir | Get-ChildItem | Copy-Item -Destination $dir -ErrorAction Stop
# Checking for any nested folders within the PowerCLI module version folder
if ($tempDir | Get-ChildItem -Directory) {
# Obtaining and storing the child items to a variable, then copying the items to the parent folder's nested folder
$nestFolder = $tempDir | Get-ChildItem -Directory
foreach ($nestDir in $nestFolder) {
$nestDir | Get-ChildItem | Copy-Item -Destination ($dir + "\" + $nestDir.Name) -ErrorAction Stop
}
}
# Detecting whether the historicDir variable was used
if ($historicDir) {
# Removing any of the former, no longer needed, directory structure
$historicDir | Remove-Item -Recurse -Force
}
else {
# Removing any of the former, no longer needed, directory structure
$tempDir | Remove-Item -Recurse -Force
}
}
}
}
else {Write-Host 'No PowerCLI module folders founds in the $PSModulePath directories.'}

View File

@@ -0,0 +1,20 @@
$MyRefreshToken = "XXXX-XXXX-XXXX-XXXX"
Connect-VMC -RefreshToken $MyRefreshToken
#List the user firewall Rules for MGW
Get-VMCFirewallRule -SDDCName "vGhetto" -OrgName "BashFest - Red Team" -GatewayType MGW
#List the firewall rules including system firewall rules for MGW
Get-VMCFirewallRule -SDDCName "vGhetto" -OrgName "BashFest - Red Team" -GatewayType MGW -ShowAll
#Export Firewall Rules from original SDDC
Export-VMCFirewallRule -SDDCName "vGhetto" -OrgName "BashFest - Red Team" -GatewayType MGW -Path ~/Desktop/VMCFirewallRules.json
#Import Firewall Rules to new SDDC
Import-VMCFirewallRule -SDDCName Single-Host-SDDC -OrgName "BashFest - Red Team" -GatewayType MGW -Path ~/Desktop/VMCFirewallRules.json
#Remove the firewall Rules we just created for the SDDC
$Rules = Get-VMCFirewallRule -SDDCName "Single-Host-SDDC" -OrgName "BashFest - Red Team" -GatewayType MGW
Foreach ($rule in $rules){
Remove-VMCFirewallRule -SDDCName Single-Host-SDDC -OrgName "BashFest - Red Team" -GatewayType MGW -RuleId $rule.id
}

View File

@@ -0,0 +1,23 @@
<#
Script name: SetClusterMultiPathToRoundRobin.ps1
Created on: 09/14/2017
Author: Alan Comstock, @Mr_Uptime
Description: Set the MultiPath policy for FC devices to RoundRobin and IOPS to 1 for all hosts in a cluster based upon the vendor tag.
Dependencies: None known
PowerCLI Version: VMware PowerCLI 6.5 Release 1 build 4624819
PowerShell Version: 5.1.14393.1532
OS Version: Windows 10
#>
$pathpolicy="RoundRobin"
$iops="1"
$vendor="3PARdata"
$AllESXHosts = Get-VMHost -Location CLUSTERNAME | Sort Name
Foreach ($esxhost in $AllESXHosts) {
Write-Host "Working on" $esxhost
$scsilun = Get-VMhost $esxhost | Get-VMHostHba -Type "FibreChannel" | Get-ScsiLun -LunType disk | Where-Object {$_.Vendor -like $vendor -and ($_.MultipathPolicy -notlike $pathpolicy -or $_.CommandsToSwitchPath -ne $iops)}
if ($scsilun -ne $null){
Set-ScsiLun -ScsiLun $scsilun -MultipathPolicy $pathpolicy -CommandsToSwitchPath $iops
}
}
#The End

198
Scripts/SetDatastoreTag.ps1 Executable file
View File

@@ -0,0 +1,198 @@
<#
.SYNOPSIS
A brief description of the file.
.DESCRIPTION
Given a list of Datastore Names, this script will assign a Tag to them
.PARAMETER csvFile
String representing the full path of the file
The file must be structured like this:
-----------------------------
Tag1,Tag2,Tag3,Tag4
IPv4-iSCSI-SiteA,Tag1,Tag3
IPv4-NFS-SiteA,Tag2,Tag4
...
-----------------------------
.NOTES
===========================================================================
Created on: 31/03/2017 11:16
Created by: Alessio Rocchi <arocchi@vmware.com>
Organization: VMware
Filename: SetDatastoreTag.ps1
===========================================================================
#>
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true,
ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[System.String]$csvFile,
[Parameter(Mandatory = $true,
ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[String]$vCenter,
[Parameter(ValueFromPipeline = $true,
Position = 2)]
[AllowNull()]
[String]$Username,
[Parameter(Position = 3)]
[AllowNull()]
[String]$Password
)
Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue | Out-Null
class vcConnector : System.IDisposable
{
[String]$Username
[String]$Password
[String]$vCenter
[PSObject]$server
static [vcConnector]$instance
vcConnector($Username, $Password, $vCenter)
{
Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue | Out-Null
$this.Username = $Username
$this.Password = $Password
$this.vCenter = $vCenter
$this.connect()
}
vcConnector($vcCredential, $vCenter)
{
Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue | Out-Null
$this.vcCredential = $vcCredential
$this.vCenter = $vCenter
$this.connect()
}
[void] hidden connect()
{
try
{
if ([String]::IsNullOrEmpty($this.Username) -or [String]::IsNullOrEmpty($this.Password))
{
$vcCredential = Get-Credential
Connect-VIServer -Server $this.vCenter -Credential $this.vcCredential -WarningAction SilentlyContinue -ErrorAction Stop | Out-Null
}
else
{
Connect-VIServer -Server $this.vCenter -User $this.Username -Password $this.Password -WarningAction SilentlyContinue -ErrorAction Stop
}
Write-Debug("Connected to vCenter: {0}" -f $this.vCenter)
}
catch
{
Write-Error($Error[0].Exception.Message)
exit
}
}
[void] Dispose()
{
Write-Debug("Called Dispose Method of Instance: {0}" -f ($this))
Disconnect-VIServer -WarningAction SilentlyContinue -Server $this.vCenter -Force -Confirm:$false | Out-Null
}
static [vcConnector] GetInstance()
{
if ([vcConnector]::instance -eq $null)
{
[vcConnector]::instance = [vcConnector]::new()
}
return [vcConnector]::instance
}
}
class Content{
[System.Collections.Generic.List[System.String]]$availableTags
[System.Collections.Generic.List[System.String]]$elements
Content()
{
}
Content([String]$filePath)
{
if ((Test-Path -Path $filePath) -eq $false)
{
throw ("Cannot find file: {0}" -f ($filePath))
}
try
{
# Cast the Get-Content return type to Generic List of Strings in order to avoid fixed-size array
$this.elements = [System.Collections.Generic.List[System.String]](Get-Content -Path $filePath -ea SilentlyContinue -wa SilentlyContinue)
$this.availableTags = $this.elements[0].split(',')
# Delete the first element aka availableTags
$this.elements.RemoveAt(0)
}
catch
{
throw ("Error reading the file: {0}" -f ($filePath))
}
}
}
try
{
$vc = [vcConnector]::new($Username, $Password, $vCenter)
$csvContent = [Content]::new($csvFile)
Write-Host("Available Tags: {0}" -f ($csvContent.availableTags))
foreach ($element in $csvContent.elements)
{
[System.Collections.Generic.List[System.String]]$splittedList = $element.split(',')
# Get the Datastore Name
[System.String]$datastoreName = $splittedList[0]
# Removing Datastore Name
$splittedList.RemoveAt(0)
# Create a List of Tags which will be assigned to the Datastore
[System.Collections.Generic.List[PSObject]]$tagsToAssign = $splittedList | ForEach-Object { Get-Tag -Name $_ }
Write-Host("Tags to assign to Datastore: {0} are: {1}" -f ($datastoreName, $tagsToAssign))
# Get Datastore object by the given Datastore Name, first field of the the line
$datastore = Get-Datastore -Name $datastoreName -ea Stop
# Iterate the assigned Datastore Tags
foreach ($tag in ($datastore | Get-TagAssignment))
{
# Check if the current tag is one of the available ones.
if ($tag.Tag.Name -in $csvContent.availableTags)
{
# Remove the current assigned Tag
Write-Host("Removing Tag: {0}" -f ($tag))
Remove-TagAssignment -TagAssignment $tag -Confirm:$false
}
}
# Finally add the new set of tags to the Datastore
foreach ($tag in $tagsToAssign)
{
Write-Host("Trying to assign Tag: {0} to Datastore: {1}" -f ($tag.Name, $datastoreName))
# Assign the Tag
New-TagAssignment -Entity $datastore -Tag $tag
}
}
}
catch [VMware.VimAutomation.Sdk.Types.V1.ErrorHandling.VimException.VimException]
{
Write-Error("VIException: {0}" -f ($Error[0].Exception.Message))
exit
}
catch
{
Write-Error $Error[0].Exception.Message
exit
}
finally
{
# Let be assured that the vc connection will be disposed.
$vc.Dispose()
}

Some files were not shown because too many files have changed in this diff Show More