Compare commits
31 Commits
adatanasov
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
062749868d | ||
|
|
9055bf72f3 | ||
|
|
e02efdec9e | ||
|
|
346141e69e | ||
|
|
3c0a12f72a | ||
|
|
50ac249ec1 | ||
|
|
3634649afc | ||
|
|
9e4f03aebe | ||
|
|
0b3e4c9ea2 | ||
|
|
ce06c5372b | ||
|
|
20871aeffa | ||
|
|
524b0aac2f | ||
|
|
f748f2591e | ||
|
|
cd502a516b | ||
|
|
d43b7ec88b | ||
|
|
d70d246e34 | ||
|
|
d41905e00f | ||
|
|
2be8d05707 | ||
|
|
356b3c4d68 | ||
|
|
52d38656ed | ||
|
|
1480fdec06 | ||
|
|
ddc96d276e | ||
|
|
ee6e800726 | ||
|
|
101b92e28d | ||
|
|
fdebb39901 | ||
|
|
74f450fb75 | ||
|
|
25700a9ac2 | ||
|
|
414b6ccb62 | ||
|
|
3c6190a2be | ||
|
|
b68077e4c3 | ||
|
|
c67b7d47a9 |
7
Modules/VISecret/README.md
Normal file
7
Modules/VISecret/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Example module for using SecretManagement and SecretStore to save PowerCLI credentials
|
||||
|
||||
|
||||
|
||||
This module demonstrates how users can use the the Microsoft.PowerShell.SecretManagement and Microsoft.PowerShell.SecretStore modules to save their PowerCLI credentials.
|
||||
|
||||
The module supports PowerShell 5.1 and PowerShell 7.0 and above.
|
||||
138
Modules/VISecret/VMware.VISecret.psd1
Normal file
138
Modules/VISecret/VMware.VISecret.psd1
Normal file
@@ -0,0 +1,138 @@
|
||||
#
|
||||
# Module manifest for module 'VMware.VISecret'
|
||||
#
|
||||
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
RootModule = 'VMware.VISecret.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.0.0.0'
|
||||
|
||||
# Supported PSEditions
|
||||
CompatiblePSEditions = @('Desktop', 'Core')
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '66124b00-4095-4a1f-9940-f91622009b15'
|
||||
|
||||
# Author of this module
|
||||
Author = 'VMware'
|
||||
|
||||
# Company or vendor of this module
|
||||
CompanyName = 'VMware'
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = 'Copyright (c) VMware, Inc. All rights reserved.'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'Module to enable easy use of Microsoft.PowerShell.SecretManagement module in VMware context'
|
||||
|
||||
# Minimum version of the PowerShell engine required by this module
|
||||
PowerShellVersion = '5.1'
|
||||
|
||||
# Name of the PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# 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.Core";"ModuleVersion"="1.0.0.0"}
|
||||
@{"ModuleName"="Microsoft.PowerShell.SecretManagement";"ModuleVersion"="1.1.2"}
|
||||
@{"ModuleName"="Microsoft.PowerShell.SecretStore";"ModuleVersion"="1.0.6"}
|
||||
)
|
||||
|
||||
# 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 = @()
|
||||
|
||||
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
|
||||
FunctionsToExport = @(
|
||||
'Initialize-VISecret',
|
||||
'New-VISecret',
|
||||
'Get-VISecret',
|
||||
'Remove-VISecret',
|
||||
'Connect-VIServerWithSecret'
|
||||
)
|
||||
|
||||
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
|
||||
CmdletsToExport = @()
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = @()
|
||||
|
||||
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
|
||||
AliasesToExport = @()
|
||||
|
||||
# DSC resources to export from this module
|
||||
# DscResourcesToExport = @()
|
||||
|
||||
# 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. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
|
||||
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 = ''
|
||||
|
||||
# Prerelease string of this module
|
||||
# Prerelease = ''
|
||||
|
||||
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
|
||||
# RequireLicenseAcceptance = $false
|
||||
|
||||
# External dependent modules of this module
|
||||
# ExternalModuleDependencies = @()
|
||||
|
||||
} # End of PSData hashtable
|
||||
|
||||
} # End of PrivateData hashtable
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
|
||||
}
|
||||
|
||||
314
Modules/VISecret/VMware.VISecret.psm1
Normal file
314
Modules/VISecret/VMware.VISecret.psm1
Normal file
@@ -0,0 +1,314 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This cmdlet downloads the dependencies and intializes the default settings of the VISecret module
|
||||
|
||||
.PARAMETER Vault
|
||||
The vault to save the credentials to. The default value is "VMwareSecretStore"
|
||||
|
||||
.DESCRIPTION
|
||||
This cmdlet downloads the dependecies and initializes the default settings of the VISecret module.
|
||||
It uses Microsoft.PowerShell.SecretStore as a default vault and sets it in no password mode, so that
|
||||
the credentials are encrypted, but the user is not prompted for a password. If you want to use a different
|
||||
vault or to use it with a password you should initialize those settings manually and not use this cmdlet.
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Initialize-VISecret
|
||||
|
||||
Initializes the default settings of the VISecret module
|
||||
#>
|
||||
function Initialize-VISecret {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$Vault = "VMwareSecretStore"
|
||||
)
|
||||
|
||||
process {
|
||||
Set-SecretStoreConfiguration -Scope CurrentUser -Authentication None -Interaction None -Confirm:$false
|
||||
|
||||
Register-SecretVault -Name $Vault -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This cmdlet saves new credential in the secret vault or updates it if it already exists.
|
||||
|
||||
.DESCRIPTION
|
||||
This cmdlet saves new credential in the secret vault or updates it if it already exists.
|
||||
|
||||
.PARAMETER Server
|
||||
The IP address or the hostname of the server to save the credential for
|
||||
|
||||
.PARAMETER Password
|
||||
The password to be saved in the secret vault
|
||||
|
||||
.PARAMETER SecureStringPassword
|
||||
The SecureString password to be saved in the secret vault
|
||||
|
||||
.PARAMETER User
|
||||
The username for which to save the credential
|
||||
|
||||
.PARAMETER Vault
|
||||
The vault to save the credential to. The default value is "VMwareSecretStore"
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> New-VISecret -Server 10.10.10.10 -User administrator@vsphere.local -password pass
|
||||
|
||||
Saves the password for the administrator@vsphere.local user on the 10.10.10.10 server in the secret vault
|
||||
|
||||
#>
|
||||
function New-VISecret {
|
||||
[CmdletBinding()]
|
||||
[Alias("Set-VISecret")]
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Server,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$User,
|
||||
[string]$Password,
|
||||
[securestring]$SecureStringPassword,
|
||||
[string]$Vault
|
||||
)
|
||||
|
||||
begin {
|
||||
if ([string]::IsNullOrWhiteSpace($password) -and (-not $secureStringPassword)) {
|
||||
Throw "Either Password or SecureStringPassword parameter needs to be specified"
|
||||
}
|
||||
|
||||
if (-not [string]::IsNullOrWhiteSpace($password) -and $secureStringPassword) {
|
||||
Throw "Password and SecureStringPassword parameters cannot be both specified at the same time"
|
||||
}
|
||||
}
|
||||
|
||||
process {
|
||||
$params = @{
|
||||
"Name" = "VISecret|"+$server+"|"+$User
|
||||
}
|
||||
if ($password) {
|
||||
$params += @{"Secret" = $password}
|
||||
} elseif ($secureStringPassword) {
|
||||
$params += @{"SecureStringSecret" = $secureStringPassword}
|
||||
} elseif ($Vault) {
|
||||
$params += @{"Vault" = $Vault}
|
||||
}
|
||||
Set-Secret @params
|
||||
}
|
||||
}
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieves a credential from the secret store vault.
|
||||
|
||||
.DESCRIPTION
|
||||
Retrieves a credential from the secret store vault.
|
||||
|
||||
.PARAMETER Server
|
||||
The IP address or the hostname of the server to retrieve the credential for
|
||||
|
||||
.PARAMETER User
|
||||
The username for which to retrieve the credential
|
||||
|
||||
.PARAMETER AsPlainText
|
||||
Specifies that a credential should be returned as a String (in plain text) instead of a SecureString.
|
||||
To ensure security, you should avoid using plaintext strings whenever possible.
|
||||
|
||||
.PARAMETER Vault
|
||||
The vault to retrieve the credential from. The default value is "VMwareSecretStore"
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> $securePassword = Get-VISecret -Server 10.10.10.10 -User administrator@vsphere.local
|
||||
|
||||
Retrieves the password for the administrator@vsphere.local user on the 10.10.10.10 server from the secret vault
|
||||
#>
|
||||
function Get-VISecret {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Server,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$User,
|
||||
[switch]$AsPlainText,
|
||||
[string]$Vault
|
||||
)
|
||||
|
||||
process {
|
||||
$params = @{
|
||||
"Name" = "VISecret|"+$server+"|"+$User
|
||||
}
|
||||
if ($AsPlainText.IsPresent) {
|
||||
$params += @{"AsPlainText" = $AsPlainText.ToBool()}
|
||||
} elseif ($Vault) {
|
||||
$params += @{"Vault" = $Vault}
|
||||
}
|
||||
Get-Secret @params
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Removes a credential from the vault.
|
||||
|
||||
.DESCRIPTION
|
||||
Removes a credential from the vault.
|
||||
|
||||
.PARAMETER Server
|
||||
The IP address or the hostname of the server to remove the credential for
|
||||
|
||||
.PARAMETER User
|
||||
The username for which to remove the credential
|
||||
|
||||
.PARAMETER Vault
|
||||
The vault to remove the credential from. The default value is "VMwareSecretStore"
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Remove-VISecret -Server 10.10.10.10 -User administrator@vsphere.local
|
||||
|
||||
Removes the password for the administrator@vsphere.local user on the 10.10.10.10 server from the vault
|
||||
#>
|
||||
function Remove-VISecret {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Server,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$User,
|
||||
[string]$Vault
|
||||
)
|
||||
|
||||
process {
|
||||
$params = @{
|
||||
"Name" = "VISecret|"+$server+"|"+$User
|
||||
}
|
||||
if ($Vault) {
|
||||
$params += @{"Vault" = $Vault}
|
||||
}
|
||||
Remove-Secret @params
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This cmdlet establishes a connection to a vCenter Server system.
|
||||
|
||||
.DESCRIPTION
|
||||
This cmdlet establishes a connection to a vCenter Server system.
|
||||
If a credential object or username and password the cmdlet uses them to connect and if the
|
||||
-SaveCredential parameter is specified saves them in the vault. If only username
|
||||
is specified the cmdlet uses the server name and the user name to search for the password in the
|
||||
vault.
|
||||
|
||||
.PARAMETER Server
|
||||
Specifies the IP address or the DNS name of the vSphere server to which you want to connect.
|
||||
|
||||
.PARAMETER User
|
||||
Specifies the user name you want to use for authenticating with the server.
|
||||
|
||||
.PARAMETER Password
|
||||
Specifies the password you want to use for authenticating with the server.
|
||||
|
||||
.PARAMETER Credential
|
||||
Specifies a PSCredential object that contains credentials for authenticating with the server.
|
||||
|
||||
.PARAMETER AllLinked
|
||||
Indicates whether you want to connect to vCenter Server in linked mode. If you specify $true
|
||||
for the -AllLinked parameter and the server to which you want to connect is a part of a federation
|
||||
vCenter Server, you'll be connected to all members of the linked vCenter Server. To use this
|
||||
option, PowerCLI must be configured to work in multiple servers connection mode. To configure
|
||||
PowerCLI to support multiple servers connection, specify Multiple for the DefaultVIServerMode
|
||||
parameter of the Set-PowerCLIConfiguration cmdlet.
|
||||
|
||||
.PARAMETER Force
|
||||
Suppresses all user interface prompts during the cmdlet execution.
|
||||
|
||||
.PARAMETER NotDefault
|
||||
Indicates that you do not want to include the server to which you connect into the $defaultVIServers variable.
|
||||
|
||||
.PARAMETER Port
|
||||
Specifies the port on the server you want to use for the connection.
|
||||
|
||||
.PARAMETER Protocol
|
||||
Specifies the Internet protocol you want to use for the connection. It can be either http or https.
|
||||
|
||||
.PARAMETER SaveCredentials
|
||||
Indicates that you want to save the specified credentials in the vault.
|
||||
|
||||
.PARAMETER Vault
|
||||
The vault to save the credential to. The default value is "VMwareSecretStore"
|
||||
|
||||
.EXAMPLE
|
||||
Connect-VIServer -Server 10.10.10.10 -User administrator@vsphere.local
|
||||
|
||||
Connects to a vSphere server using the saved credential for the specified user
|
||||
|
||||
.EXAMPLE
|
||||
Connect-VIServer -Server 10.10.10.10 -User administrator@vsphere.local -Password pass -SaveCredential
|
||||
|
||||
Connects to a vSphere server using the specified username and password and saves them in the vault
|
||||
#>
|
||||
function Connect-VIServerWithSecret {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Server,
|
||||
[string]$User,
|
||||
[string]$Password,
|
||||
[pscredential]$Credential,
|
||||
[switch]$AllLinked,
|
||||
[switch]$Force,
|
||||
[switch]$NotDefault,
|
||||
[int]$Port,
|
||||
[string]$Protocol,
|
||||
[switch]$SaveCredentials,
|
||||
[string]$Vault
|
||||
)
|
||||
|
||||
begin {
|
||||
if ([string]::IsNullOrWhiteSpace($User) -and (-not $Credential)) {
|
||||
if ($global:defaultUser) {
|
||||
$User = $global:defaultUser
|
||||
} else {
|
||||
Throw "Either User or Credential parameters needs to be specified"
|
||||
}
|
||||
}
|
||||
|
||||
if ((-not [string]::IsNullOrWhiteSpace($User) -or -not [string]::IsNullOrWhiteSpace($Password)) -and $Credential) {
|
||||
Throw "User/Password and Credential parameters cannot be both specified at the same time"
|
||||
}
|
||||
}
|
||||
|
||||
process {
|
||||
$params = @{
|
||||
"Server" = $Server
|
||||
"AllLinked" = $AllLinked
|
||||
"Force" = $Force
|
||||
"NotDefault" = $NotDefault
|
||||
}
|
||||
if ($Protocol) {
|
||||
$params += @{"Protocol" = $Protocol}
|
||||
}
|
||||
if ($Port) {
|
||||
$params += @{"Port" = $Port}
|
||||
}
|
||||
if ($User) {
|
||||
if (-not $Password) {
|
||||
if ($Vault) {
|
||||
$secret = Get-Secret -Name ("VISecret|"+$server+"|"+$User) -Vault $Vault -ErrorAction SilentlyContinue
|
||||
} else {
|
||||
$secret = Get-Secret -Name ("VISecret|"+$server+"|"+$User) -ErrorAction SilentlyContinue
|
||||
}
|
||||
if (-not $secret) {
|
||||
Throw "No password has been found for this server and user in the password vault"
|
||||
}
|
||||
$Credential = New-Object System.Management.Automation.PSCredential ($User, $secret)
|
||||
}
|
||||
else {
|
||||
$securePass = ConvertTo-SecureString -String $Password -AsPlainText
|
||||
$Credential = New-Object System.Management.Automation.PSCredential ($User, $securePass)
|
||||
}
|
||||
}
|
||||
$params += @{"Credential" = $Credential}
|
||||
Connect-VIServer @params
|
||||
if ($SaveCredentials) {
|
||||
New-VISecret -Server $Server -User $User -SecureStringPassword $Credential.Password -Vault $Vault
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2140,6 +2140,16 @@ function New-HVFarm {
|
||||
.PARAMETER Spec
|
||||
Path of the JSON specification file.
|
||||
|
||||
.PARAMETER NumCPU
|
||||
Number of CPU of the Vm Instances
|
||||
|
||||
.PARAMETER Ram
|
||||
Ram of the Vm Instances
|
||||
Units in MB for Ram parameter
|
||||
|
||||
.PARAMETER CoresPerSocket
|
||||
CoresPerSocket of the Vm Instances
|
||||
|
||||
.PARAMETER HvServer
|
||||
Reference to Horizon View Server to query the farms from. If the value is not passed or null then first element from global:DefaultHVServers would be considered in-place of hvServer.
|
||||
|
||||
@@ -2339,6 +2349,24 @@ function New-HVFarm {
|
||||
[int]
|
||||
$diskWriteLatencyThreshold = 0,
|
||||
|
||||
#farmSpec.automatedfarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ComputeProfile
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateRange(1,[Int]::MaxValue)]
|
||||
[int]
|
||||
$NumCPU = 4,
|
||||
|
||||
#farmSpec.automatedfarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ComputeProfile
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateRange(1,[Int]::MaxValue)]
|
||||
[int]
|
||||
$Ram = 16384,
|
||||
|
||||
#farmSpec.automatedfarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ComputeProfile
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateRange(1,[Int]::MaxValue)]
|
||||
[int]
|
||||
$CoresPerSocket = 1,
|
||||
|
||||
#farmSpec.automatedfarmSpec.virtualCenter if LINKED_CLONE, INSTANT_CLONE
|
||||
[Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")]
|
||||
[Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')]
|
||||
@@ -2499,6 +2527,7 @@ function New-HVFarm {
|
||||
|
||||
#farmSpec.automatedfarmSpec.customizationSettings.reusePreExistingAccounts
|
||||
[Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')]
|
||||
[Parameter(Mandatory = $false,ParameterSetName = "INSTANT_CLONE")]
|
||||
[Boolean]
|
||||
$ReusePreExistingAccounts = $false,
|
||||
|
||||
@@ -2639,6 +2668,7 @@ function New-HVFarm {
|
||||
$powerOffScriptParameters = $jsonObject.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.PowerOffScriptParameters
|
||||
$postSynchronizationScriptName = $jsonObject.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.PostSynchronizationScriptName
|
||||
$postSynchronizationScriptParameters = $jsonObject.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.PostSynchronizationScriptParameters
|
||||
$reusePreExistingAccounts = $jsonObject.AutomatedFarmSpec.CustomizationSettings.ReusePreExistingAccounts
|
||||
}
|
||||
} elseif ($jsonObject.AutomatedFarmSpec.ProvisioningType -eq "VIEW_COMPOSER") {
|
||||
$LinkedClone = $true
|
||||
@@ -2824,6 +2854,10 @@ function New-HVFarm {
|
||||
$farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec = $vmNamingSpec
|
||||
}
|
||||
|
||||
$farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ComputeProfile.NumCPU = $NumCPU
|
||||
$farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ComputeProfile.Ram = $Ram
|
||||
$farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ComputeProfile.CoresPerSocket = $CoresPerSocket
|
||||
|
||||
#
|
||||
# build the VM LIST
|
||||
#
|
||||
@@ -3238,6 +3272,7 @@ function Get-HVFarmCustomizationSetting {
|
||||
$farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.powerOffScriptParameters = $powerOffScriptParameters
|
||||
$farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.postSynchronizationScriptName = $postSynchronizationScriptName
|
||||
$farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.postSynchronizationScriptParameters = $postSynchronizationScriptParameters
|
||||
$farmSpecObj.AutomatedFarmSpec.CustomizationSettings.ReusePreExistingAccounts = $reusePreExistingAccounts
|
||||
$customObject = $farmSpecObj.AutomatedFarmSpec.CustomizationSettings
|
||||
} elseif ($LinkedClone) {
|
||||
$ViewComposerDomainAdministrator_service_helper = New-Object VMware.Hv.ViewComposerDomainAdministratorService
|
||||
@@ -3301,8 +3336,7 @@ function Get-FarmSpec {
|
||||
if ($farmType -eq 'AUTOMATED') {
|
||||
$farm_spec_helper.getDataObject().AutomatedFarmSpec.RdsServerNamingSpec.PatternNamingSettings = $farm_helper.getFarmPatternNamingSettingsHelper().getDataObject()
|
||||
$farm_spec_helper.getDataObject().AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings = $farm_helper.getFarmViewComposerStorageSettingsHelper().getDataObject()
|
||||
|
||||
|
||||
$farm_spec_helper.getDataObject().AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ComputeProfile = $farm_helper.getFarmComputeProfileSpecHelper().getDataObject()
|
||||
}
|
||||
$farm_spec_helper.getDataObject().Data.Settings = $farm_helper.getFarmSessionSettingsHelper().getDataObject()
|
||||
$farm_spec_helper.getDataObject().Data.LbSettings = $farm_helper.getRDSHLoadBalancingSettingsHelper().getDataObject()
|
||||
@@ -3891,18 +3925,26 @@ function New-HVPool {
|
||||
[boolean]$enableHTMLAccess = $false,
|
||||
|
||||
# DesktopPCoIPDisplaySettings
|
||||
#desktopSpec.desktopSettings.logoffSettings.pcoipDisplaySettings.renderer3D
|
||||
#desktopSpec.desktopSettings.DisplayProtocolSettings.pcoipDisplaySettings.renderer3D
|
||||
[Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')]
|
||||
[Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")]
|
||||
[Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')]
|
||||
[ValidateSet('MANAGE_BY_VSPHERE_CLIENT', 'AUTOMATIC', 'SOFTWARE', 'HARDWARE', 'DISABLED')]
|
||||
[string]$renderer3D = 'DISABLED',
|
||||
|
||||
#desktopSpec.desktopSettings.logoffSettings.pcoipDisplaySettings.enableGRIDvGPUs
|
||||
#desktopSpec.desktopSettings.DisplayProtocolSettings.pcoipDisplaySettings.enableGRIDvGPUs
|
||||
[Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")]
|
||||
[Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')]
|
||||
[Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')]
|
||||
[boolean]$enableGRIDvGPUs = $false,
|
||||
|
||||
#desktopSpec.desktopSettings.DisplayProtocolSettings.pcoipDisplaySettings.VGPUGridProfile
|
||||
[Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")]
|
||||
# [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')]
|
||||
[Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')]
|
||||
[ValidateSet('grid_m10-0b','grid_m10-1b','grid_m10-2b','grid_m10-0q','grid_m10-1q','grid_m10-2q','grid_m10-4q','grid_m10-8q')]
|
||||
[string]$VGPUGridProfile = $null,
|
||||
|
||||
#desktopSpec.desktopSettings.logoffSettings.pcoipDisplaySettings.vRamSizeMB
|
||||
[Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")]
|
||||
[ValidateRange(64,512)]
|
||||
@@ -3976,6 +4018,12 @@ function New-HVPool {
|
||||
[string]
|
||||
$SnapshotVM,
|
||||
|
||||
#desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.addVirtualTPM if INSTANT_CLONE, ???
|
||||
# [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")]
|
||||
[Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[boolean]$addVirtualTPM = $false,
|
||||
|
||||
#desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.vmFolder if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE
|
||||
[Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")]
|
||||
[Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')]
|
||||
@@ -4481,10 +4529,15 @@ function New-HVPool {
|
||||
if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot) {
|
||||
$snapshotVM = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot
|
||||
}
|
||||
if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.addVirtualTPM) {
|
||||
$addVirtualTPM = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.addVirtualTPM
|
||||
}
|
||||
$dataCenter = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.dataCenter
|
||||
$vmFolder = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.VmFolder
|
||||
$hostOrCluster = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.HostOrCluster
|
||||
$resourcePool = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ResourcePool
|
||||
|
||||
|
||||
$dataStoreList = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.Datastores
|
||||
foreach ($dtStore in $dataStoreList) {
|
||||
$datastores += $dtStore.Datastore
|
||||
@@ -4622,6 +4675,7 @@ function New-HVPool {
|
||||
if ($null -ne $jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings) {
|
||||
$renderer3D = $jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings.renderer3D
|
||||
$enableGRIDvGPUs = $jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings.enableGRIDvGPUs
|
||||
$VGPUGridProfile = $jsonObject.DesktopSettings.DisplayProtocolSettings.PcoipDisplaySettings.VGPUGridProfile
|
||||
if ($jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings.vRamSizeMB) {
|
||||
$vRamSizeMB = $jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings.vRamSizeMB
|
||||
}
|
||||
@@ -4871,6 +4925,7 @@ function New-HVPool {
|
||||
$desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $desktopVirtualCenterProvisioningData
|
||||
$desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $desktopVirtualCenterStorageSettings
|
||||
$desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $DesktopVirtualCenterNetworkingSettings
|
||||
$desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.AddVirtualTPM = $AddVirtualTPM
|
||||
$desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings = $desktopCustomizationSettings
|
||||
$desktopSpecObj.AutomatedDesktopSpec.ProvisioningType = $provisioningType
|
||||
$desktopSpecObj.AutomatedDesktopSpec.VirtualCenter = $virtualCenterID
|
||||
@@ -4879,6 +4934,7 @@ function New-HVPool {
|
||||
$DesktopVirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $desktopVirtualCenterProvisioningData
|
||||
$DesktopVirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $desktopVirtualCenterStorageSettings
|
||||
$DesktopVirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $DesktopVirtualCenterNetworkingSettings
|
||||
$DesktopVirtualCenterProvisioningSettings.AddVirtualTPM = $AddVirtualTPM
|
||||
|
||||
$DesktopAutomatedDesktopSpec = New-Object VMware.Hv.DesktopAutomatedDesktopSpec
|
||||
$DesktopAutomatedDesktopSpec.ProvisioningType = $provisioningType
|
||||
@@ -4945,6 +5001,16 @@ function New-HVPool {
|
||||
$desktopPCoIPDisplaySettings.setRenderer3D($renderer3D)
|
||||
#setEnableGRIDvGPUs is not exists, because this property cannot be updated.
|
||||
$desktopPCoIPDisplaySettings.getDataObject().EnableGRIDvGPUs = $enableGRIDvGPUs
|
||||
if ($enableGRIDvGPUs -eq $true -and $renderer3D -ne 'MANAGE_BY_VSPHERE_CLIENT' -and $InstantClone -eq $true) {
|
||||
Write-Error "Enabling GRID support requires that 3D rendering be managed by the vSphere client"
|
||||
break
|
||||
}
|
||||
if ($enableGRIDvGPUs -eq $true -and [string]::IsNullOrEmpty($VGPUGridProfile) -eq $true -and $InstantClone -ne $true) {
|
||||
Write-Error "Enabling GRID support for Instant clones, this requires a specified VGPUGridProfile"
|
||||
break
|
||||
} else {
|
||||
$desktopPCoIPDisplaySettings.getDataObject().VGPUGridProfile = $VGPUGridProfile
|
||||
}
|
||||
$desktopPCoIPDisplaySettings.setVRamSizeMB($vRamSizeMB)
|
||||
$desktopPCoIPDisplaySettings.setMaxNumberOfMonitors($maxNumberOfMonitors)
|
||||
$desktopPCoIPDisplaySettings.setMaxResolutionOfAnyOneMonitor($maxResolutionOfAnyOneMonitor)
|
||||
@@ -6533,6 +6599,16 @@ function Start-HVFarm {
|
||||
How frequently to repeat maintenance, expressed as a multiple of the maintenance period. e.g. Every 2 weeks.
|
||||
This property has a default value of 1. This property has values 1-100.
|
||||
|
||||
.PARAMETER NumCPU
|
||||
Number of CPU of the Vm Instances
|
||||
|
||||
.PARAMETER Ram
|
||||
Ram of the Vm Instances
|
||||
Units in MB for Ram parameter
|
||||
|
||||
.PARAMETER CoresPerSocket
|
||||
CoresPerSocket of the Vm Instances
|
||||
|
||||
.PARAMETER HvServer
|
||||
Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered in-place of hvServer.
|
||||
|
||||
@@ -6637,6 +6713,21 @@ function Start-HVFarm {
|
||||
[ValidateRange(1, 100)]
|
||||
[int]$EveryInt = 1,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateRange(1,[Int]::MaxValue)]
|
||||
[int]
|
||||
$NumCPU = 4,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateRange(1,[Int]::MaxValue)]
|
||||
[int]
|
||||
$Ram = 16384,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateRange(1,[Int]::MaxValue)]
|
||||
[int]
|
||||
$CoresPerSocket = 1,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
$HvServer = $null
|
||||
)
|
||||
@@ -6784,6 +6875,13 @@ function Start-HVFarm {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
#set ComputeProfile in a SCHEDULEMAINTENANCE
|
||||
$spec.ComputeProfile = New-Object VMware.Hv.FarmComputeProfileSpec
|
||||
$spec.ComputeProfile.NumCPU = $NumCPU
|
||||
$spec.ComputeProfile.Ram = $Ram
|
||||
$spec.ComputeProfile.CoresPerSocket = $CoresPerSocket
|
||||
|
||||
# call scheduleMaintenance service on farm
|
||||
if (!$confirmFlag -OR $pscmdlet.ShouldProcess($farmList.$item)) {
|
||||
$farm_service_helper.Farm_ScheduleMaintenance($services, $item, $spec)
|
||||
@@ -9902,12 +10000,11 @@ function Set-HVApplicationIcon {
|
||||
$applicationIconId = $_.Exception.InnerException.MethodFault.Id
|
||||
Write-Host "Some application(s) already have an association for the specified icon."
|
||||
$ApplicationIconHelper.ApplicationIcon_UpdateAssociations($services, $applicationIconId, @($appInfo.Id))
|
||||
Write-Host "Successfully updated customized icon association for Application:[$ApplicationName]."
|
||||
break
|
||||
}
|
||||
} else {
|
||||
Write-Host "Error in associating customized icon for Application:[$ApplicationName] $_"
|
||||
break
|
||||
}
|
||||
}
|
||||
Write-Host "Successfully associated customized icon for Application:[$ApplicationName]."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ SPDX-License-Identifier: BSD-2-Clause
|
||||
RootModule = 'VMware.Skyline.InsightsApi.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.0.0'
|
||||
ModuleVersion = '1.0.1'
|
||||
|
||||
# Supported PSEditions
|
||||
# CompatiblePSEditions = @()
|
||||
|
||||
@@ -237,10 +237,9 @@ Function Get-SkylineFinding {
|
||||
|
||||
# Try to get results the first time
|
||||
$results = @()
|
||||
$thisQueryBody = $queryBody -Replace 'filter: {}', "filter: { $filterString }"
|
||||
$thisIteration = 0
|
||||
do {
|
||||
$thisQueryBody = $thisQueryBody -Replace 'start: 0', "start: $thisIteration"
|
||||
$thisQueryBody = $queryBody -Replace 'filter: {}', "filter: { $filterString }" -Replace 'start: 0', "start: $thisIteration"
|
||||
Write-Debug $thisQueryBody
|
||||
$thisResult = Invoke-SkylineInsightsApi -queryBody (@{'query' = $thisQueryBody} | ConvertTo-Json -Compress)
|
||||
$totalRecords = $thisResult.data.activeFindings.totalRecords
|
||||
@@ -325,13 +324,11 @@ Function Get-SkylineAffectedObject {
|
||||
}
|
||||
|
||||
process {
|
||||
$thisQueryBody = $queryBody -Replace 'findingId: "",', "findingId: `"$findingId`","
|
||||
foreach ( $thisProduct in $products ) {
|
||||
$thisIteration = 0
|
||||
$results = @() # reset results variable between products
|
||||
do {
|
||||
$thisQueryBody = $thisQueryBody -Replace 'product: "",', "product: `"$thisProduct`","
|
||||
$thisQueryBody = $thisQueryBody -Replace 'start: 0', "start: $thisIteration"
|
||||
$thisQueryBody = $queryBody -Replace 'product: "",', "product: `"$thisProduct`"," -Replace 'start: 0', "start: $thisIteration" -Replace 'findingId: "",', "findingId: `"$findingId`","
|
||||
Write-Debug $thisQueryBody
|
||||
$thisResult = Invoke-SkylineInsightsApi -queryBody (@{'query' = $thisQueryBody} | ConvertTo-Json -Compress)
|
||||
$totalRecords = $thisResult.data.activeFindings.Findings.totalAffectedObjectsCount
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
RootModule = 'VMware.vSphere.SsoAdmin.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.3.8'
|
||||
ModuleVersion = '1.3.9'
|
||||
|
||||
# Supported PSEditions
|
||||
# CompatiblePSEditions = @()
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1305,7 +1305,7 @@ namespace VMware.vSphere.SsoAdminClient
|
||||
if (externalDomain.details?.certificates != null && externalDomain.details?.certificates.Length > 0) {
|
||||
var certificatesList = new List<X509Certificate2>();
|
||||
foreach (var cert in externalDomain.details?.certificates) {
|
||||
certificatesList.Add(new X509Certificate2(Encoding.ASCII.GetBytes(cert)));
|
||||
certificatesList.Add(new X509Certificate2(Convert.FromBase64String(cert)));
|
||||
}
|
||||
extIdentitySource.Certificates = certificatesList.ToArray();
|
||||
}
|
||||
|
||||
51
PowerActions/Example - ClusterSnapshotsReport.ps1
Normal file
51
PowerActions/Example - ClusterSnapshotsReport.ps1
Normal file
@@ -0,0 +1,51 @@
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster[]] $cluster,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $smtp,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $email)
|
||||
|
||||
$vms = Get-VM -Location $cluster
|
||||
$snapshots = @()
|
||||
foreach ($vm in $vms) {
|
||||
$snapshots += Get-Snapshot -VM $vm
|
||||
}
|
||||
|
||||
$header = @"
|
||||
<style>
|
||||
table {
|
||||
font-size: 12px;
|
||||
border: 0px;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 4px;
|
||||
margin: 0px;
|
||||
border: 0;
|
||||
}
|
||||
th {
|
||||
background: #395870;
|
||||
background: linear-gradient(#49708f, #293f50);
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
padding: 10px 15px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
tbody tr:nth-child(even) {
|
||||
background: #f0f0f2;
|
||||
}
|
||||
</style>
|
||||
"@
|
||||
|
||||
$snapshots | select Name,VM,Created,@{Name="Size";Expression={[math]::Round($_.SizeMB,3)}},IsCurrent | `
|
||||
ConvertTo-Html -head $header | Out-File "SnapshotReport.html"
|
||||
|
||||
Send-MailMessage -from "Snapshot Reports <noreply@vmware.com>" `
|
||||
-to $email `
|
||||
-subject "Snapshot Report" `
|
||||
-body "Cluster snapshot report" `
|
||||
-Attachment "SnapshotReport.html" `
|
||||
-smtpServer $smtp
|
||||
17
PowerActions/Example - RemoveOldClusterSnapshots.ps1
Normal file
17
PowerActions/Example - RemoveOldClusterSnapshots.ps1
Normal file
@@ -0,0 +1,17 @@
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster] $cluster,
|
||||
[DateTime] $date)
|
||||
|
||||
if ($null -eq $date) {
|
||||
$date = (Get-Date).AddDays(-7)
|
||||
}
|
||||
|
||||
$vms = Get-VM -Location $cluster
|
||||
foreach ($vm in $vms) {
|
||||
$snaphostsToBeRemoved = Get-Snapshot -VM $vm | where {$_.Created -lt $date}
|
||||
if ($null -ne $snaphostsToBeRemoved) {
|
||||
Write-Host "Removing snapshots: '$snaphostsToBeRemoved' of VM: '$vm'"
|
||||
Remove-Snapshot $snaphostsToBeRemoved -Confirm:$false
|
||||
}
|
||||
}
|
||||
44
PowerActions/Git Sync.ps1
Normal file
44
PowerActions/Git Sync.ps1
Normal file
@@ -0,0 +1,44 @@
|
||||
#Intall git
|
||||
tdnf install -y git
|
||||
|
||||
#Clone the repo
|
||||
git clone -n --depth=1 --filter=tree:0 https://github.com/vmware/PowerCLI-Example-Scripts.git
|
||||
cd PowerCLI-Example-Scripts
|
||||
git sparse-checkout set --no-cone PowerActions
|
||||
git checkout
|
||||
cd PowerActions
|
||||
|
||||
#Select the content library in which you want to store the scirpts from the repo
|
||||
$contentLibraryName = 'Power Actions'
|
||||
$contentLibrary = Get-ContentLibrary $contentLibraryName
|
||||
|
||||
#Get all the files that we have cloned from the repo
|
||||
$files = Get-ChildItem -Path . -File
|
||||
foreach ($file in $files) {
|
||||
$name = $file.BaseName
|
||||
|
||||
#Check if the item for this file already exists in the content library
|
||||
$item = Get-ContentLibraryItem -Name $name -ContentLibrary $contentLibrary -ErrorAction SilentlyContinue
|
||||
if ($item) {
|
||||
#If the item exists, check if it is up to date
|
||||
#Create a folder to store the current content library item
|
||||
if (-not (Test-Path -Path ./cl_versions -PathType Container))
|
||||
{
|
||||
New-Item -Path ./cl_versions -ItemType Directory
|
||||
}
|
||||
#Download the item from the content library
|
||||
$clFile = Export-ContentLibraryItem -ContentLibraryItem $item -Destination ((Get-Location).Path + "/cl_version") -Force
|
||||
#Compare if it's the same as the file we have downloaded from the repo
|
||||
$compResult = Compare-Object -ReferenceObject (Get-Content $file.FullName) -DifferenceObject (Get-Content ($clFile.FullName+"/"+$file.Name))
|
||||
if ($compResult) {
|
||||
#If the item is not up to date, update it
|
||||
Write-Host "Updating $name"
|
||||
Set-ContentLibraryItem -ContentLibraryItem $item -Files $file.FullName
|
||||
} else {
|
||||
Write-Host "$name is up to date"
|
||||
}
|
||||
} else {
|
||||
#If the item does not exist, create it
|
||||
New-ContentLibraryItem -Name $name -Files $file.FullName -ContentLibrary $contentLibrary
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
* [Security](https://github.com/vmware/PowerCLI-Example-Scripts#security)
|
||||
* [Resource Maintenance](https://github.com/vmware/PowerCLI-Example-Scripts#resource-maintenance)
|
||||
* [Maintenance Ownership](https://github.com/vmware/PowerCLI-Example-Scripts#maintenance-ownership)
|
||||
* [Filing Issues](https://github.com/vmware/PowerCLI-Example-Scripts#filing-isssues)
|
||||
* [Filing Issues](https://github.com/vmware/PowerCLI-Example-Scripts#filing-issues)
|
||||
* [Resolving Issues](https://github.com/vmware/PowerCLI-Example-Scripts#resolving-issues)
|
||||
* [Additional Resources](https://github.com/vmware/PowerCLI-Example-Scripts#additional-resources)
|
||||
* [Discussions](https://github.com/vmware/PowerCLI-Example-Scripts#discussions)
|
||||
|
||||
344
Scripts/PAIF-N/01-deploy-vcf-workload-domain.ps1
Normal file
344
Scripts/PAIF-N/01-deploy-vcf-workload-domain.ps1
Normal file
@@ -0,0 +1,344 @@
|
||||
<#
|
||||
# © 2024 Broadcom. All Rights Reserved. Broadcom. The term "Broadcom" refers to
|
||||
# Broadcom Inc. and/or its subsidiaries.
|
||||
#>
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
This script deploys a VI workload domain
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
This script creates a VI workload domain using the PowerCLI SDK module for VCF SDDC Manager.
|
||||
|
||||
The script can be broken into two main parts. First, the ESXi hosts are being commissioned.
|
||||
Then, the actual VI domain is created using the commissioned ESXi hosts.
|
||||
|
||||
Both steps - ESXi host commissioning and VI domain creations - are three-stage operations themselves.
|
||||
The commissioning/creation specs are constructed. The specs are validated. The actual operation is invoked.
|
||||
The validation and operation invocation are long-running tasks. This requires awaiting and status tracking
|
||||
until their completion. The waiting for validation and the actual operation is done using helper cmdlets -
|
||||
Wait-VcfValidation and Wait-VcfTask, located in utils sub-folder.
|
||||
|
||||
On completion a new VI workload domain reflecting the given parameters should be created.
|
||||
|
||||
.NOTES
|
||||
|
||||
Prerequisites:
|
||||
- A VCF Management Domain
|
||||
- A minimum of three free hosts marked with the appropriate storage and at least 4 NICs.
|
||||
Two of the NICs will be used for Frontend/Management and the other two for workloads.
|
||||
|
||||
"Global parameters", "Host commissioning parameters", "Workload domain creation parameters" should be updated to
|
||||
reflect the environment they are run in. This may require altering the spec creation script.
|
||||
|
||||
#>
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$SCRIPTROOT = ($PWD.ProviderPath, $PSScriptRoot)[!!$PSScriptRoot]
|
||||
. (Join-Path $SCRIPTROOT 'utils/Wait-VcfTask.ps1')
|
||||
. (Join-Path $SCRIPTROOT 'utils/Wait-VcfValidation.ps1')
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# Global parameters
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Organization name of the workload domain
|
||||
$OrgName = 'VMware'
|
||||
|
||||
# Name of the workload domain - used as a prefix for nested inventory items
|
||||
$domainName = 'sfo-w01'
|
||||
|
||||
$domain = 'vrack.vsphere.local'
|
||||
$gateway = '10.0.0.250'
|
||||
$sddcManager = @{
|
||||
Fqdn = "sddc-manager.$domain"
|
||||
User = 'administrator@vsphere.local'
|
||||
Password = 'VMware123!'
|
||||
}
|
||||
|
||||
############################################################################################################################
|
||||
# Host commissioning
|
||||
############################################################################################################################
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# Host commissioning parameters
|
||||
|
||||
$esxiHosts = @(
|
||||
@{
|
||||
Fqdn = "esxi-5.$domain"
|
||||
Username = 'root'
|
||||
Password = "ESXiSddc123!"
|
||||
StorageType = "VSAN"
|
||||
LicenseKey = 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'
|
||||
}
|
||||
@{
|
||||
Fqdn = "esxi-6.$domain"
|
||||
Username = 'root'
|
||||
Password = "ESXiSddc123!"
|
||||
StorageType = "VSAN"
|
||||
LicenseKey = 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'
|
||||
}
|
||||
@{
|
||||
Fqdn = "esxi-7.$domain"
|
||||
Username = 'root'
|
||||
Password = "ESXiSddc123!"
|
||||
StorageType = "VSAN"
|
||||
LicenseKey = 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'
|
||||
}
|
||||
@{
|
||||
Fqdn = "esxi-8.$domain"
|
||||
Username = 'root'
|
||||
Password = "ESXiSddc123!"
|
||||
StorageType = "VSAN"
|
||||
LicenseKey = 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'
|
||||
}
|
||||
)
|
||||
|
||||
# The network pool to associate the host with
|
||||
$networkPoolName = 'networkpool'
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Connect to SDDC manager
|
||||
$sddcConn = Connect-VcfSddcManagerServer `
|
||||
-Server $sddcManager.Fqdn `
|
||||
-User $sddcManager.User `
|
||||
-Password $sddcManager.Password
|
||||
|
||||
## Host commissioning spec construction
|
||||
$NetworkPool = Invoke-VcfGetNetworkPool | `
|
||||
Select-Object -ExpandProperty Elements | `
|
||||
Where-Object { $_.Name -eq $NetworkPoolName }
|
||||
|
||||
$hostCommissionSpecs = $esxiHosts | % {
|
||||
Initialize-VcfHostCommissionSpec -Fqdn $_.Fqdn `
|
||||
-NetworkPoolId $NetworkPool.Id `
|
||||
-Password $_.Password `
|
||||
-StorageType $_.StorageType `
|
||||
-Username $_.Username
|
||||
}
|
||||
|
||||
## Host commissioning validation
|
||||
$hostValidationResult = Invoke-VcfValidateHostCommissionSpec -HostCommissionSpecs $hostCommissionSpecs
|
||||
$hostValidationResult = Wait-VcfValidation `
|
||||
-Validation $hostValidationResult `
|
||||
-UpdateValidation { param($id) Invoke-VcfGetHostCommissionValidationByID -id $id } `
|
||||
-UpdateValidationArguments $hostValidationResult.Id `
|
||||
-ThrowOnError
|
||||
|
||||
## Host commissioning
|
||||
$commisionTask = Invoke-VcfCommissionHosts -hostCommissionSpecs $hostCommissionSpecs
|
||||
$commisionTask = Wait-VcfTask $commisionTask -ThrowOnError
|
||||
|
||||
|
||||
############################################################################################################################
|
||||
# Workload domain creation
|
||||
############################################################################################################################
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# Workload domain creation parameters
|
||||
|
||||
$domainSpec = @{
|
||||
DomainName = $DomainName
|
||||
OrgName = $OrgName
|
||||
VCenterSpec = @{
|
||||
Name = "$DomainName-vc01"
|
||||
DatacenterName = "$DomainName-dc01"
|
||||
RootPassword = "VMware123!"
|
||||
NetworkDetailsSpec = @{
|
||||
DnsName = "$DomainName-vc01.$domain"
|
||||
IpAddress = "10.0.0.40"
|
||||
SubnetMask = "255.255.255.0"
|
||||
Gateway = $gateway
|
||||
}
|
||||
}
|
||||
ComputeSpec = @{
|
||||
ClusterSpecs = @(
|
||||
@{
|
||||
DatastoreSpec = @{
|
||||
VSanDatastoreSpec = @{
|
||||
DatastoreName = "$DomainName-ds01"
|
||||
FailuresToTolerate = 1
|
||||
LicenseKey = "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"
|
||||
}
|
||||
}
|
||||
NetworkSpec = @{
|
||||
VdsSpecs = @(
|
||||
@{
|
||||
Name = "$DomainName-vds01"
|
||||
PortGroups = @(
|
||||
@{
|
||||
Name = 'vSAN'
|
||||
TransportType = 'VSAN'
|
||||
}
|
||||
@{
|
||||
Name = 'management'
|
||||
TransportType = 'MANAGEMENT'
|
||||
}
|
||||
@{
|
||||
Name = 'vmotion'
|
||||
TransportType = 'VMOTION'
|
||||
}
|
||||
)
|
||||
}
|
||||
@{
|
||||
Name = "$DomainName-vds02"
|
||||
IsUsedByNsxt = $true
|
||||
}
|
||||
)
|
||||
NsxClusterSpec = @{
|
||||
NsxTClusterSpec = @{
|
||||
GeneveVlanId = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
Name = "$DomainName-cl01"
|
||||
}
|
||||
)
|
||||
}
|
||||
NsxTSpec = @{
|
||||
NsxManagerSpecs = @(
|
||||
@{
|
||||
Name = "$domainName-nsx01a"
|
||||
NetworkDetailsSpec = @{
|
||||
DnsName = "$domainName-nsx01a.$domain"
|
||||
IpAddress = "10.0.0.41"
|
||||
SubnetMask = "255.255.255.0"
|
||||
Gateway = $gateway
|
||||
}
|
||||
}
|
||||
@{
|
||||
Name = "$domainName-nsx01b"
|
||||
NetworkDetailsSpec = @{
|
||||
DnsName = "$domainName-nsx01b.$domain"
|
||||
IpAddress = "10.0.0.42"
|
||||
SubnetMask = "255.255.255.0"
|
||||
Gateway = $gateway
|
||||
}
|
||||
}
|
||||
@{
|
||||
Name = "$domainName-nsx01c"
|
||||
NetworkDetailsSpec = @{
|
||||
DnsName = "$domainName-nsx01c.$domain"
|
||||
IpAddress = "10.0.0.43"
|
||||
SubnetMask = "255.255.255.0"
|
||||
Gateway = $gateway
|
||||
}
|
||||
}
|
||||
)
|
||||
FormFactor = 'large'
|
||||
LicenseKey = 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'
|
||||
NSXManagerAdminPassword = "VMware123!123"
|
||||
Vip = '10.0.0.44'
|
||||
VipFqdn = "$domainName-nsx01.$domain"
|
||||
}
|
||||
}
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
## Workload domain spec construction
|
||||
$esxiFqdns = $esxiHosts | Select-Object -ExpandProperty Fqdn
|
||||
$VcfHost = Invoke-VcfGetHosts -status "UNASSIGNED_USEABLE" | `
|
||||
Select-Object -ExpandProperty Elements | `
|
||||
Where-Object { $esxiFqdns -contains $_.Fqdn }
|
||||
|
||||
$ComputeSpec = Initialize-VcfComputeSpec -ClusterSpecs (
|
||||
$domainSpec.ComputeSpec.ClusterSpecs | ForEach-Object {
|
||||
$_clusterSpec = $_
|
||||
|
||||
Initialize-VcfClusterSpec `
|
||||
-DatastoreSpec (
|
||||
Initialize-VcfDatastoreSpec `
|
||||
-VsanDatastoreSpec (
|
||||
Initialize-VcfVsanDatastoreSpec `
|
||||
-DatastoreName $_.DatastoreSpec.VSanDatastoreSpec.DatastoreName `
|
||||
-FailuresToTolerate $_.DatastoreSpec.VSanDatastoreSpec.FailuresToTolerate `
|
||||
-LicenseKey $_.DatastoreSpec.VSanDatastoreSpec.LicenseKey
|
||||
)) `
|
||||
-HostSpecs (
|
||||
$VcfHost | ForEach-Object {
|
||||
$esxiHost = $esxiHosts | Where-Object { $_.Fqdn -eq $_.Fqdn } | Select-Object -First 1
|
||||
|
||||
Initialize-VcfHostSpec `
|
||||
-Id $_.Id `
|
||||
-LicenseKey $esxiHost.LicenseKey `
|
||||
-HostNetworkSpec (
|
||||
Initialize-VcfHostNetworkSpec -VmNics @(
|
||||
Initialize-VcfVmNic -Id 'vmnic0' -VdsName $_clusterSpec.NetworkSpec.VdsSpecs[0].Name
|
||||
Initialize-VcfVmNic -Id 'vmnic1' -VdsName $_clusterSpec.NetworkSpec.VdsSpecs[0].Name
|
||||
Initialize-VcfVmNic -Id 'vmnic2' -VdsName $_clusterSpec.NetworkSpec.VdsSpecs[1].Name
|
||||
Initialize-VcfVmNic -Id 'vmnic3' -VdsName $_clusterSpec.NetworkSpec.VdsSpecs[1].Name
|
||||
))
|
||||
}
|
||||
) `
|
||||
-Name $_.Name `
|
||||
-NetworkSpec (
|
||||
Initialize-VcfNetworkSpec `
|
||||
-NsxClusterSpec (
|
||||
Initialize-VcfNsxClusterSpec -NsxTClusterSpec (
|
||||
Initialize-VcfNsxTClusterSpec `
|
||||
-GeneveVlanId $_.NetworkSpec.NsxClusterSpec.NsxTClusterSpec.GeneveVlanId
|
||||
)
|
||||
) `
|
||||
-VdsSpecs @(
|
||||
Initialize-VcfVdsSpec -Name $_.NetworkSpec.VdsSpecs[0].Name `
|
||||
-PortGroupSpecs (
|
||||
$_.NetworkSpec.VdsSpecs[0].PortGroups | ForEach-Object {
|
||||
Initialize-VcfPortgroupSpec `
|
||||
-Name $_.Name `
|
||||
-TransportType $_.TransportType
|
||||
})
|
||||
Initialize-VcfVdsSpec -Name $_.NetworkSpec.VdsSpecs[1].Name `
|
||||
-IsUsedByNsxt $_.NetworkSpec.VdsSpecs[1].IsUsedByNsxt
|
||||
))
|
||||
})
|
||||
|
||||
|
||||
$DomainCreationSpec = Initialize-VcfDomainCreationSpec `
|
||||
-ComputeSpec $ComputeSpec `
|
||||
-DomainName $domainSpec.DomainName `
|
||||
-NsxTSpec (
|
||||
Initialize-VcfNsxTSpec `
|
||||
-FormFactor $domainSpec.NsxTSpec.FormFactor `
|
||||
-LicenseKey $domainSpec.NsxTSpec.LicenseKey `
|
||||
-NsxManagerAdminPassword $domainSpec.NsxTSpec.NSXManagerAdminPassword `
|
||||
-NsxManagerSpecs (
|
||||
$domainSpec.NsxTSpec.NsxManagerSpecs | ForEach-Object {
|
||||
Initialize-VcfNsxManagerSpec `
|
||||
-Name $_.Name `
|
||||
-NetworkDetailsSpec (
|
||||
Initialize-VcfNetworkDetailsSpec `
|
||||
-DnsName $_.NetworkDetailsSpec.DnsName `
|
||||
-IpAddress $_.NetworkDetailsSpec.IpAddress `
|
||||
-SubnetMask $_.NetworkDetailsSpec.SubnetMask `
|
||||
-Gateway $_.NetworkDetailsSpec.Gateway)
|
||||
}
|
||||
) `
|
||||
-Vip $domainSpec.NsxTSpec.Vip `
|
||||
-VipFqdn $domainSpec.NsxTSpec.VipFqdn) `
|
||||
-OrgName $domainSpec.OrgName `
|
||||
-VcenterSpec (
|
||||
Initialize-VcfVcenterSpec `
|
||||
-DatacenterName $domainSpec.VCenterSpec.DatacenterName `
|
||||
-Name $domainSpec.VCenterSpec.Name `
|
||||
-NetworkDetailsSpec (
|
||||
Initialize-VcfNetworkDetailsSpec `
|
||||
-DnsName $domainSpec.VCenterSpec.NetworkDetailsSpec.DnsName `
|
||||
-IpAddress $domainSpec.VCenterSpec.NetworkDetailsSpec.IpAddress `
|
||||
-SubnetMask $domainSpec.VCenterSpec.NetworkDetailsSpec.SubnetMask `
|
||||
-Gateway $domainSpec.VCenterSpec.NetworkDetailsSpec.Gateway
|
||||
) `
|
||||
-RootPassword $domainSpec.VCenterSpec.RootPassword)
|
||||
|
||||
# Workload domain spec validation
|
||||
$domainValidationResult = Invoke-VcfValidateDomainCreationSpec -domainCreationSpec $DomainCreationSpec
|
||||
$domainValidationResult = Wait-VcfValidation `
|
||||
-Validation $domainValidationResult `
|
||||
-ThrowOnError
|
||||
|
||||
# Workload domain creation
|
||||
$creationTask = Invoke-VcfCreateDomain -domainCreationSpec $DomainCreationSpec
|
||||
$creationTask = Wait-VcfTask $creationTask -ThrowOnError
|
||||
|
||||
Disconnect-VcfSddcManagerServer $sddcConn
|
||||
195
Scripts/PAIF-N/02-install-nvidia-driver-vlcm.ps1
Normal file
195
Scripts/PAIF-N/02-install-nvidia-driver-vlcm.ps1
Normal file
@@ -0,0 +1,195 @@
|
||||
<#
|
||||
# © 2024 Broadcom. All Rights Reserved. Broadcom. The term "Broadcom" refers to
|
||||
# Broadcom Inc. and/or its subsidiaries.
|
||||
#>
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
This script configures the ESXi host for AI workloads
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
This script configures the ESXi host for AI workloads which includes installing the
|
||||
NVIDIA AI Enterprise vGPU driver and NVIDIA GPU Management Daemon on the ESXi hosts.
|
||||
vLCM is used for that purpose.
|
||||
|
||||
The script changes the default graphics type of the GPU devices to Shared Direct. The Xorg
|
||||
service is then restarted. Finally, the vLCM is used to install the NVIDIA GPU driver and
|
||||
management daemon.
|
||||
|
||||
.NOTES
|
||||
|
||||
Prerequisites:
|
||||
- VI workload domain (vCenter server instance)
|
||||
- ESXi hosts with GPUs
|
||||
|
||||
"Global parameters", "Workload domain parameters", "GPU parameters" should be updated to
|
||||
reflect the environment they are run in. This may require altering the spec creation script.
|
||||
|
||||
#>
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# Global parameters
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Name of the workload domain - used as a prefix for nested inventory items
|
||||
$domainName = 'sfo-w01'
|
||||
|
||||
$domain = 'vrack.vsphere.local'
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# Workload domain parameters - stripped down version of $domainSpec from 01-deploy-vcf-workload-domain.ps1
|
||||
|
||||
$domainSpec = @{
|
||||
VCenterSpec = @{
|
||||
RootPassword = "VMware123!"
|
||||
NetworkDetailsSpec = @{
|
||||
DnsName = "$DomainName-vc01.$domain"
|
||||
}
|
||||
}
|
||||
ComputeSpec = @{
|
||||
ClusterSpecs = @(
|
||||
@{
|
||||
Name = "$DomainName-cl01"
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# GPU parameters
|
||||
|
||||
$nvidiaDriverLocation = "http://NVIDIA-VGPU-DRIVER-LOCATION/"
|
||||
$gpuParameters = @{
|
||||
EsxiImageName = "8.0 U2b - 23305546"
|
||||
NVIDIA = @(
|
||||
@{
|
||||
Location = "$nvidiaDriverLocation/NVD-AIE-800_550.54.16-1OEM.800.1.0.20613240_23471877.zip"
|
||||
Name = "NVIDIA AI Enterprise vGPU driver for VMWare ESX-8.0.0"
|
||||
Version = "550.54.16"
|
||||
Description = 'NVIDIA AI Enterprise vGPU driver for VMWare ESX-8.0.0'
|
||||
},
|
||||
@{
|
||||
Location = "$nvidiaDriverLocation/nvd-gpu-mgmt-daemon_550.54.16-0.0.0000_23475823.zip"
|
||||
Name = "NVIDIA GPU monitoring and management daemon"
|
||||
Version = "550.54.16 - Build 0000"
|
||||
Description = "NVIDIA GPU monitoring and management daemon"
|
||||
}
|
||||
)
|
||||
GraphicsType = 'sharedDirect'
|
||||
HostDefaultGraphicsType = 'sharedDirect'
|
||||
SharedPassthruAssignmentPolicy = 'performance'
|
||||
}
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Connect to the VC of the workload domain
|
||||
$vcConn = Connect-VIServer `
|
||||
-Server $domainSpec.VCenterSpec.NetworkDetailsSpec.DnsName `
|
||||
-User 'administrator@vsphere.local' `
|
||||
-Password $domainSpec.VCenterSpec.RootPassword
|
||||
|
||||
$esxHosts = $domainSpec.ComputeSpec.ClusterSpecs | ForEach-Object { Get-VMHost -Location $_.Name }
|
||||
|
||||
# Preparing the GPU Device for the vGPU Driver
|
||||
$esxHosts | ForEach-Object {
|
||||
$graphicsManager = Get-View -Id $_.ExtensionData.ConfigManager.GraphicsManager
|
||||
|
||||
# Preparing the GPU Device for the vGPU Driver
|
||||
# change the default graphics type to Shared Direct
|
||||
$_.ExtensionData.Config.GraphicsInfo | `
|
||||
Where-Object { $_.GraphicsType -ne $gpuParameters.GraphicsType } | `
|
||||
ForEach-Object {
|
||||
$config = New-Object VMware.Vim.HostGraphicsConfig
|
||||
$config.DeviceType = New-Object VMware.Vim.HostGraphicsConfigDeviceType[] (1)
|
||||
$config.DeviceType[0] = New-Object VMware.Vim.HostGraphicsConfigDeviceType
|
||||
$config.DeviceType[0].DeviceId = $_.PciId
|
||||
$config.DeviceType[0].GraphicsType = $gpuParameters.GraphicsType
|
||||
$config.HostDefaultGraphicsType = $gpuParameters.HostDefaultGraphicsType
|
||||
$config.SharedPassthruAssignmentPolicy = $gpuParameters.SharedPassthruAssignmentPolicy
|
||||
$graphicsManager.UpdateGraphicsConfig($config)
|
||||
}
|
||||
|
||||
# Restart xorg service
|
||||
$_this = Get-View -Id $_.ExtensionData.ConfigManager.ServiceSystem
|
||||
$_this.RestartService('xorg')
|
||||
}
|
||||
|
||||
$uploadTasksId = $gpuParameters.NVIDIA | ForEach-Object {
|
||||
# Upload the driver to vLCM
|
||||
$SettingsDepotsOfflineCreateSpec = Initialize-SettingsDepotsOfflineCreateSpec `
|
||||
-SourceType "PULL" `
|
||||
-Location $_.Location `
|
||||
-Description $_.Description
|
||||
|
||||
Invoke-CreateDepotsOfflineAsync -SettingsDepotsOfflineCreateSpec $SettingsDepotsOfflineCreateSpec
|
||||
}
|
||||
|
||||
$uploadTasks = $uploadTasksId | ForEach-Object { Invoke-GetTask -task $_ }
|
||||
|
||||
Write-Progress -Id 0 "Uploading NVIDIA vGPU driver into vLCM"
|
||||
$inProgress = $true
|
||||
while ($inProgress) {
|
||||
Write-Verbose "Waiting for NVIDIA driver upload into vLCM"
|
||||
$uploadTasks | ConvertTo-Json -Depth 5 | Write-Verbose
|
||||
|
||||
$subprocess = ''
|
||||
$completed = 0
|
||||
$total = 0
|
||||
|
||||
$inProgress = $false
|
||||
|
||||
foreach ($t in $uploadTasks) {
|
||||
if ($t -and $t.status -ne 'SUCCEEDED' -and $t.status -ne 'FAILED') {
|
||||
$inProgress = $true
|
||||
|
||||
if ($t.progress) {
|
||||
if ($t.progress.message -and `
|
||||
$t.progress.message.default_message) {
|
||||
if ($subprocess.Length -gt 0) {
|
||||
$subprocess += ','
|
||||
}
|
||||
$subprocess += $t.progress.message.default_message
|
||||
}
|
||||
$completed += $t.progress.completed
|
||||
$total += $t.progress.total
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($total -eq 0) { $total = 100 }
|
||||
|
||||
Write-Progress -Id 0 "Uploading NVIDIA vGPU driver into vLCM" -Status $subprocess -PercentComplete (($completed * 100) / $total)
|
||||
|
||||
Start-Sleep -Seconds 1
|
||||
$uploadTasks = $uploadTasksId | ForEach-Object { Invoke-GetTask -task $_ }
|
||||
}
|
||||
Write-Progress -Id 0 "Uploading NVIDIA vGPU driver into vLCM" -Completed
|
||||
|
||||
# 3 vSphere LifeCycle Management Configuration
|
||||
$esxiBaseImage = Get-LcmImage `
|
||||
-Type BaseImage `
|
||||
-Version $gpuParameters.EsxiImageName
|
||||
$allComponents = Get-LcmImage -Type Component
|
||||
$components = $gpuParameters.NVIDIA | ForEach-Object {
|
||||
$nvd = $_
|
||||
$allComponents | `
|
||||
Where-Object {
|
||||
$_.Name -eq $nvd.Name -and `
|
||||
$_.Version -eq $nvd.Version
|
||||
}
|
||||
}
|
||||
|
||||
if (($components -isnot [array]) -or ($components.Length -ne $gpuParameters.NVIDIA.Length)) {
|
||||
throw "Not all Nvidia components found"
|
||||
}
|
||||
|
||||
$domainSpec.ComputeSpec.ClusterSpecs | ForEach-Object {
|
||||
$cluster = Get-Cluster -Name $_.Name
|
||||
$cluster = $cluster | Set-Cluster -BaseImage $esxiBaseImage -Component $components -Confirm:$false
|
||||
$cluster = $cluster | Set-Cluster -AcceptEULA -Remediate -Confirm:$false
|
||||
}
|
||||
|
||||
|
||||
Disconnect-VIServer $vcConn
|
||||
226
Scripts/PAIF-N/03-deploy-edge-cluster.ps1
Normal file
226
Scripts/PAIF-N/03-deploy-edge-cluster.ps1
Normal file
@@ -0,0 +1,226 @@
|
||||
<#
|
||||
# © 2024 Broadcom. All Rights Reserved. Broadcom. The term "Broadcom" refers to
|
||||
# Broadcom Inc. and/or its subsidiaries.
|
||||
#>
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
This script creates a NSX edge cluster on a cluster in a VI workload domain
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
This script creates an NSX edge cluster on a cluster in a VI workload domain to provide connectivity
|
||||
from external networks to Supervisor Cluster objects.
|
||||
|
||||
To create NSX Edge Cluster on multiple VI workload domain clusters the script should be modified and
|
||||
executed multiple times.
|
||||
|
||||
.NOTES
|
||||
|
||||
Prerequisites:
|
||||
- VI workload domain (vCenter server instance)
|
||||
- VI workload domain cluster
|
||||
|
||||
"Global parameters", "Workload domain parameters", "Edge Cluster deployment parameters" should be updated to
|
||||
reflect the environment they are run in. This may require altering the spec creation script.
|
||||
|
||||
#>
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$SCRIPTROOT = ($PWD.ProviderPath, $PSScriptRoot)[!!$PSScriptRoot]
|
||||
. (Join-Path $SCRIPTROOT 'utils/Wait-VcfTask.ps1')
|
||||
. (Join-Path $SCRIPTROOT 'utils/Wait-VcfValidation.ps1')
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# Global parameters
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
$domainName = 'sfo-w01'
|
||||
|
||||
$domain = 'vrack.vsphere.local'
|
||||
$sddcManager = @{
|
||||
Fqdn = "sddc-manager.$domain"
|
||||
User = 'administrator@vsphere.local'
|
||||
Password = 'VMware123!'
|
||||
}
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# Workload domain parameters - stripped down version of $domainSpec from 01-deploy-vcf-workload-domain.ps1
|
||||
$domainSpec = @{
|
||||
VCenterSpec = @{
|
||||
RootPassword = "VMware123!"
|
||||
NetworkDetailsSpec = @{
|
||||
DnsName = "$DomainName-vc01.$domain"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Connect to SDDC manager
|
||||
$sddcConn = Connect-VcfSddcManagerServer `
|
||||
-Server $sddcManager.Fqdn `
|
||||
-User $sddcManager.User `
|
||||
-Password $sddcManager.Password
|
||||
|
||||
############################################################################################################################
|
||||
# Deploy Edge Cluster in the created workload domain
|
||||
############################################################################################################################
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# Edge Cluster deployment parameters
|
||||
|
||||
# The VI workload cluster on which the NSX Edge Cluster will be created
|
||||
$ClusterName = "$DomainName-cl01"
|
||||
|
||||
$edgeName = "$ClusterName-ec01"
|
||||
|
||||
$vcfCluster = Invoke-VcfGetClusters | `
|
||||
Select-Object -ExpandProperty Elements | `
|
||||
Where-Object { $_.Name -eq $ClusterName } | `
|
||||
Select-Object -First 1
|
||||
|
||||
$EdgeClusterParams = @{
|
||||
Asn = 65004
|
||||
EdgeAdminPassword = 'VMware123!VMware123!'
|
||||
EdgeAuditPassword = 'VMware123!VMware123!'
|
||||
EdgeClusterName = $edgeName
|
||||
EdgeClusterProfileType = "CUSTOM"
|
||||
EdgeClusterType = "NSX-T"
|
||||
EdgeFormFactor = "MEDIUM"
|
||||
EdgeNodeSpecs = @(
|
||||
@{
|
||||
ClusterId = $vcfCluster.Id
|
||||
EdgeNodeName = "$edgeName-en01.vrack.vsphere.local"
|
||||
EdgeTep1IP = "192.168.52.12/24"
|
||||
EdgeTep2IP = "192.168.52.13/24"
|
||||
EdgeTepGateway = "192.168.52.1"
|
||||
EdgeTepVlan = 1252
|
||||
InterRackCluster = $false
|
||||
ManagementGateway = "10.0.0.250"
|
||||
ManagementIP = "10.0.0.52/24"
|
||||
UplinkNetwork = @(
|
||||
@{
|
||||
UplinkInterfaceIP = "192.168.18.2/24"
|
||||
UplinkVlan = 2083
|
||||
AsnPeer = 65001
|
||||
PeerIP = "192.168.18.10/24"
|
||||
BgpPeerPassword = "VMware1!"
|
||||
}
|
||||
@{
|
||||
UplinkInterfaceIP = "192.168.19.2/24"
|
||||
UplinkVlan = 2084
|
||||
AsnPeer = 65001
|
||||
PeerIP = "192.168.19.10/24"
|
||||
BgpPeerPassword = "VMware1!"
|
||||
}
|
||||
)
|
||||
}
|
||||
@{
|
||||
ClusterId = $vcfCluster.Id
|
||||
EdgeNodeName = "$edgeName-en02.vrack.vsphere.local"
|
||||
EdgeTep1IP = "192.168.52.14/24"
|
||||
EdgeTep2IP = "192.168.52.15/24"
|
||||
EdgeTepGateway = "192.168.52.1"
|
||||
EdgeTepVlan = 1252
|
||||
InterRackCluster = $false
|
||||
ManagementGateway = "10.0.0.250"
|
||||
ManagementIP = "10.0.0.53/24"
|
||||
UplinkNetwork = @(
|
||||
@{
|
||||
UplinkInterfaceIP = "192.168.18.3/24"
|
||||
UplinkVlan = 2083
|
||||
AsnPeer = 65001
|
||||
PeerIP = "192.168.18.10/24"
|
||||
BgpPeerPassword = "VMware1!"
|
||||
}
|
||||
@{
|
||||
UplinkInterfaceIP = "192.168.19.3/24"
|
||||
UplinkVlan = 2084
|
||||
AsnPeer = 65001
|
||||
PeerIP = "192.168.19.10/24"
|
||||
BgpPeerPassword = "VMware1!"
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
EdgeRootPassword = 'VMware123!VMware123!'
|
||||
Mtu = 9000
|
||||
SkipTepRoutabilityCheck = $true
|
||||
Tier0Name = "$edgeName-t0"
|
||||
Tier0RoutingType = "EBGP"
|
||||
Tier0ServicesHighAvailability = "ACTIVE_ACTIVE"
|
||||
Tier1Name = "$edgeName-t1"
|
||||
EdgeClusterProfileSpec = @{
|
||||
BfdAllowedHop = 255
|
||||
BfdDeclareDeadMultiple = 3
|
||||
BfdProbeInterval = 1000
|
||||
EdgeClusterProfileName = "$ClusterName-ecp01"
|
||||
StandbyRelocationThreshold = 30
|
||||
}
|
||||
}
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Edge cluster deployment spec construction
|
||||
$edgeClusterCreationSpec = Initialize-VcfEdgeClusterCreationSpec `
|
||||
-Asn $EdgeClusterParams.Asn `
|
||||
-EdgeAdminPassword $EdgeClusterParams.EdgeAdminPassword `
|
||||
-EdgeAuditPassword $EdgeClusterParams.EdgeAuditPassword `
|
||||
-EdgeClusterName $EdgeClusterParams.EdgeClusterName `
|
||||
-EdgeClusterProfileType "CUSTOM" `
|
||||
-EdgeClusterType "NSX-T" `
|
||||
-EdgeFormFactor $EdgeClusterParams.EdgeFormFactor `
|
||||
-EdgeNodeSpecs (
|
||||
$EdgeClusterParams.EdgeNodeSpecs | ForEach-Object {
|
||||
Initialize-VcfNsxTEdgeNodeSpec `
|
||||
-ClusterId $_.ClusterId `
|
||||
-EdgeNodeName $_.EdgeNodeName `
|
||||
-EdgeTep1IP $_.EdgeTep1IP `
|
||||
-EdgeTep2IP $_.EdgeTep2IP `
|
||||
-EdgeTepGateway $_.EdgeTepGateway `
|
||||
-EdgeTepVlan $_.EdgeTepVlan `
|
||||
-InterRackCluster $_.InterRackCluster `
|
||||
-ManagementGateway $_.ManagementGateway `
|
||||
-ManagementIP $_.ManagementIP `
|
||||
-UplinkNetwork (
|
||||
$_.UplinkNetwork | ForEach-Object {
|
||||
Initialize-VcfNsxTEdgeUplinkNetwork `
|
||||
-UplinkInterfaceIP $_.UplinkInterfaceIP `
|
||||
-UplinkVlan $_.UplinkVlan `
|
||||
-AsnPeer $_.AsnPeer `
|
||||
-PeerIP $_.PeerIP `
|
||||
-BgpPeerPassword $_.BgpPeerPassword
|
||||
})
|
||||
}
|
||||
) `
|
||||
-EdgeRootPassword $EdgeClusterParams.EdgeRootPassword `
|
||||
-Mtu $EdgeClusterParams.Mtu `
|
||||
-SkipTepRoutabilityCheck $EdgeClusterParams.SkipTepRoutabilityCheck `
|
||||
-Tier0Name $EdgeClusterParams.Tier0Name `
|
||||
-Tier0RoutingType $EdgeClusterParams.Tier0RoutingType `
|
||||
-Tier0ServicesHighAvailability $EdgeClusterParams.Tier0ServicesHighAvailability `
|
||||
-Tier1Name $EdgeClusterParams.Tier1Name `
|
||||
-EdgeClusterProfileSpec (Initialize-VcfNsxTEdgeClusterProfileSpec `
|
||||
-BfdAllowedHop $EdgeClusterParams.EdgeClusterProfileSpec.BfdAllowedHop `
|
||||
-BfdDeclareDeadMultiple $EdgeClusterParams.EdgeClusterProfileSpec.BfdDeclareDeadMultiple `
|
||||
-BfdProbeInterval $EdgeClusterParams.EdgeClusterProfileSpec.BfdProbeInterval `
|
||||
-EdgeClusterProfileName $EdgeClusterParams.EdgeClusterProfileSpec.EdgeClusterProfileName `
|
||||
-StandbyRelocationThreshold $EdgeClusterParams.EdgeClusterProfileSpec.StandbyRelocationThreshold)
|
||||
|
||||
$edgeClusterCreationSpec.EdgeClusterProfileType = $EdgeClusterParams.EdgeClusterProfileType
|
||||
if ($EdgeClusterParams.EdgeClusterProfileType -eq "DEFAULT") {
|
||||
$edgeClusterCreationSpec.EdgeClusterProfileSpec = $null
|
||||
}
|
||||
|
||||
# Edge cluster deployment spec validation
|
||||
$edgeValidationResult = Invoke-VcfValidateEdgeClusterCreationSpec -edgeCreationSpec $edgeClusterCreationSpec
|
||||
$edgeValidationResult = Wait-VcfValidation `
|
||||
-Validation $edgeValidationResult `
|
||||
-UpdateValidation { param($id) Invoke-VcfGetEdgeClusterValidationByID -id $id } `
|
||||
-UpdateValidationArguments $edgeValidationResult.Id `
|
||||
-ThrowOnError
|
||||
|
||||
# Edge cluster deployment
|
||||
$taskResult = Invoke-VcfCreateEdgeCluster -edgeCreationSpec $edgeClusterCreationSpec
|
||||
$taskResult = Wait-VcfTask $taskResult -ThrowOnError
|
||||
|
||||
Disconnect-VcfSddcManagerServer $sddcConn
|
||||
283
Scripts/PAIF-N/04-enable-wcp.ps1
Normal file
283
Scripts/PAIF-N/04-enable-wcp.ps1
Normal file
@@ -0,0 +1,283 @@
|
||||
<#
|
||||
# © 2024 Broadcom. All Rights Reserved. Broadcom. The term "Broadcom" refers to
|
||||
# Broadcom Inc. and/or its subsidiaries.
|
||||
#>
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
This script enables Workload Management (Kubernetes)
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
This script enables Workload Management (Kubernetes) and sets it up for AI workloads.
|
||||
|
||||
The script:
|
||||
|
||||
1. Enables the Supervisor cluster
|
||||
2. Creates content library for the deep learning VM template
|
||||
3. Creates GPU-enabled VMClass
|
||||
4. Creates namespace(s) and assigns the created VMClass and assigns deep learning VM content library
|
||||
|
||||
.NOTES
|
||||
|
||||
Prerequisites:
|
||||
- VI workload domain (vCenter server instance)
|
||||
- NSX Edge Cluster
|
||||
|
||||
"Global parameters", "Workload domain parameters", "WCP enablement parameters" should be updated to
|
||||
reflect the environment they are run in. This may require altering the spec creation script.
|
||||
|
||||
#>
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$SCRIPTROOT = ($PWD.ProviderPath, $PSScriptRoot)[!!$PSScriptRoot]
|
||||
. (Join-Path $SCRIPTROOT 'utils/Wait-VcfTask.ps1')
|
||||
. (Join-Path $SCRIPTROOT 'utils/Wait-VcfValidation.ps1')
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# Global parameters
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
$domainName = 'sfo-w01'
|
||||
|
||||
$dnsServer = '10.0.0.250'
|
||||
$ntpServer = '10.0.0.250'
|
||||
|
||||
$domain = 'vrack.vsphere.local'
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# Workload domain parameters - stripped down version of $domainSpec from 01-deploy-vcf-workload-domain.ps1
|
||||
$domainSpec = @{
|
||||
VCenterSpec = @{
|
||||
RootPassword = "VMware123!"
|
||||
NetworkDetailsSpec = @{
|
||||
DnsName = "$DomainName-vc01.$domain"
|
||||
}
|
||||
}
|
||||
ComputeSpec = @{
|
||||
ClusterSpecs = @(
|
||||
@{
|
||||
DatastoreSpec = @{
|
||||
VSanDatastoreSpec = @{
|
||||
DatastoreName = "$DomainName-ds01"
|
||||
}
|
||||
}
|
||||
Name = "$DomainName-cl01"
|
||||
NetworkSpec = @{
|
||||
VdsSpecs = @(
|
||||
@{
|
||||
Name = "$DomainName-vds01"
|
||||
PortGroups = @(
|
||||
@{
|
||||
Name = 'management'
|
||||
TransportType = 'MANAGEMENT'
|
||||
}
|
||||
)
|
||||
}
|
||||
@{
|
||||
Name = "$DomainName-vds02"
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
NsxTSpec = @{
|
||||
NSXManagerAdminPassword = "VMware123!123"
|
||||
VipFqdn = "$domainName-nsx01.$domain"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$EdgeClusterParams = @{
|
||||
EdgeClusterName = "$($domainSpec.ComputeSpec.ClusterSpecs[0].Name)-ec01"
|
||||
}
|
||||
|
||||
############################################################################################################################
|
||||
# Enable WCP
|
||||
############################################################################################################################
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
# WCP enablement parameters
|
||||
$ContentLibraryParams = @{
|
||||
Name = "$DomainName-lib01"
|
||||
Url = 'https://wp-content.vmware.com/v2/latest/lib.json'
|
||||
SslThumbprint = 'AD:DA:3D:B9:99:75:1D:FF:2E:28:CA:92:83:64:38:20:5B:55:94:DC'
|
||||
DownloadOnDemand = $true
|
||||
Datastore = $domainSpec.ComputeSpec.ClusterSpecs[0].DatastoreSpec.VSanDatastoreSpec.DatastoreName
|
||||
}
|
||||
$DeepLearningVMContentLibraryParams = @{
|
||||
Name = "$DomainName-lib02"
|
||||
Url = 'https://packages.vmware.com/dl-vm/lib.json'
|
||||
SslThumbprint = 'AD:DA:3D:B9:99:75:1D:FF:2E:28:CA:92:83:64:38:20:5B:55:94:DC'
|
||||
DownloadOnDemand = $true
|
||||
Datastore = $domainSpec.ComputeSpec.ClusterSpecs[0].DatastoreSpec.VSanDatastoreSpec.DatastoreName
|
||||
}
|
||||
|
||||
$ClusterName = $domainSpec.ComputeSpec.ClusterSpecs[0].Name
|
||||
|
||||
$WcpClusterParams = @{
|
||||
SizeHint = 'Small'
|
||||
ManagementNetwork = @{
|
||||
Name = (
|
||||
$domainSpec.ComputeSpec.ClusterSpecs[0].
|
||||
NetworkSpec.VdsSpecs[0].
|
||||
PortGroups | Where-Object {$_.TransportType -eq 'MANAGEMENT'} | ForEach-Object { $_.Name } )
|
||||
Mode = 'StaticRange'
|
||||
StartIpAddress = "10.0.0.150"
|
||||
Gateway = "10.0.0.250"
|
||||
SubnetMask = '255.255.255.0'
|
||||
RangeSize = 5
|
||||
}
|
||||
MasterDnsNames = @(, "$ClusterName.$domain")
|
||||
MasterNtpServer = @(, $ntpServer)
|
||||
Cluster = $ClusterName
|
||||
EphemeralStoragePolicy = "$ClusterName vSAN Storage Policy"
|
||||
ImageStoragePolicy = "$ClusterName vSAN Storage Policy"
|
||||
MasterStoragePolicy = "$ClusterName vSAN Storage Policy"
|
||||
NcpClusterNetworkSpec = @{
|
||||
NsxEdgeClusterId = ''
|
||||
DistributedSwitch = $domainSpec.ComputeSpec.ClusterSpecs[0].NetworkSpec.VdsSpecs[1].Name
|
||||
PodCIDRs = @(, "10.244.10.0/23")
|
||||
ExternalIngressCIDRs = @(, "10.10.11.0/24")
|
||||
ExternalEgressCIDRs = @(, "10.10.10.0/24")
|
||||
}
|
||||
ServiceCIDR = "10.10.12.0/24"
|
||||
WorkerDnsServer = @(, $dnsServer)
|
||||
MasterDnsServerIpAddress = @(, $dnsServer)
|
||||
MasterDnsSearchDomain = @(, $domain)
|
||||
ContentLibrary = $null
|
||||
LicenseKey = "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"
|
||||
Namespace = @("$DomainName-wmn01", "$DomainName-tkc01")
|
||||
NamespaceStoragePolicy = "$ClusterName vSAN Storage Policy"
|
||||
NamespaceEditUserGroup = "gg-kub-admins"
|
||||
NamespaceViewUserGroup = "gg-kub-readonly"
|
||||
VmClassNamespace = @{
|
||||
"$DomainName-tkc01" = @(, "best-effort-small-vgpu")
|
||||
}
|
||||
ContentLibraryNamespace = @{
|
||||
"$DomainName-tkc01" = @()
|
||||
}
|
||||
VmClass = @(
|
||||
@{
|
||||
Id = "best-effort-small-vgpu"
|
||||
CpuCount = 2
|
||||
MemoryMB = 4096
|
||||
MemoryReservation = 100
|
||||
VGpuProfiles = @(
|
||||
'grid_a100-4c',
|
||||
'grid_a100-8c'
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Get Edge cluster Id from NSXt manager
|
||||
$nsxtConn = Connect-NsxtServer -Server $domainSpec.ComputeSpec.NsxTSpec.vipFqdn -User 'admin' -password $domainSpec.ComputeSpec.NsxTSpec.NSXManagerAdminPassword
|
||||
$svc = Get-NsxtService 'com.vmware.nsx.edge_clusters'
|
||||
$nsxEdgeCluster = $svc.list().results | Where-Object { $_.display_name -eq $EdgeClusterParams.EdgeClusterName }
|
||||
$WcpClusterParams.NcpClusterNetworkSpec.NsxEdgeClusterId = $nsxEdgeCluster.Id
|
||||
$nsxtConn | Disconnect-NsxtServer -Confirm:$false
|
||||
|
||||
# Connect to the VCF Workload domain VC
|
||||
$vcConn = Connect-ViServer -Server $domainSpec.VCenterSpec.NetworkDetailsSpec.DnsName `
|
||||
-User administrator@vsphere.local `
|
||||
-Password $domainSpec.VCenterSpec.RootPassword
|
||||
|
||||
# Create subscribed content library to https://wp-content.vmware.com/v2/latest/lib.json
|
||||
$contentLibrary = New-ContentLibrary `
|
||||
-Name $ContentLibraryParams.Name `
|
||||
-Datastore $ContentLibraryParams.Datastore `
|
||||
-SubscriptionUrl $ContentLibraryParams.Url `
|
||||
-DownloadContentOnDemand:($ContentLibraryParams.DownloadOnDemand) `
|
||||
-SslThumbprint $ContentLibraryParams.SslThumbprint
|
||||
|
||||
$WcpClusterParams.ContentLibrary = $contentLibrary
|
||||
|
||||
# Create subscribed content library to https://packages.vmware.com/dl-vm/lib.json
|
||||
$dlvmContentLibrary = New-ContentLibrary `
|
||||
-Name $DeepLearningVMContentLibraryParams.Name `
|
||||
-Datastore $DeepLearningVMContentLibraryParams.Datastore `
|
||||
-SubscriptionUrl $DeepLearningVMContentLibraryParams.Url `
|
||||
-DownloadContentOnDemand:($DeepLearningVMContentLibraryParams.DownloadOnDemand) `
|
||||
-SslThumbprint $DeepLearningVMContentLibraryParams.SslThumbprint
|
||||
|
||||
$WcpClusterParams.ContentLibraryNamespace["$DomainName-tkc01"] = @(, $dlvmContentLibrary.Id)
|
||||
|
||||
# Enable WCP in the VCF workload domain VC
|
||||
$wcpCluster = Enable-WMCluster `
|
||||
-SizeHint $WcpClusterParams.SizeHint `
|
||||
-ManagementVirtualNetwork (Get-VirtualNetwork -Name $WcpClusterParams.ManagementNetwork.Name) `
|
||||
-ManagementNetworkMode $WcpClusterParams.ManagementNetwork.Mode `
|
||||
-ManagementNetworkStartIpAddress $WcpClusterParams.ManagementNetwork.StartIpAddress `
|
||||
-ManagementNetworkAddressRangeSize $WcpClusterParams.ManagementNetwork.RangeSize `
|
||||
-ManagementNetworkGateway $WcpClusterParams.ManagementNetwork.Gateway `
|
||||
-ManagementNetworkSubnetMask $WcpClusterParams.ManagementNetwork.SubnetMask `
|
||||
-MasterDnsNames $WcpClusterParams.MasterDnsNames `
|
||||
-MasterNtpServer $WcpClusterParams.MasterNtpServer `
|
||||
-Cluster (Get-Cluster -Name $WcpClusterParams.Cluster) `
|
||||
-EphemeralStoragePolicy (Get-SpbmStoragePolicy -Name $WcpClusterParams.EphemeralStoragePolicy) `
|
||||
-ImageStoragePolicy (Get-SpbmStoragePolicy -Name $WcpClusterParams.ImageStoragePolicy) `
|
||||
-MasterStoragePolicy (Get-SpbmStoragePolicy -Name $WcpClusterParams.MasterStoragePolicy) `
|
||||
-NsxEdgeClusterId $WcpClusterParams.NcpClusterNetworkSpec.NsxEdgeClusterId `
|
||||
-DistributedSwitch (Get-VDSwitch -Name $WcpClusterParams.NcpClusterNetworkSpec.DistributedSwitch) `
|
||||
-PodCIDRs $WcpClusterParams.NcpClusterNetworkSpec.PodCIDRs `
|
||||
-ServiceCIDR $WcpClusterParams.ServiceCIDR `
|
||||
-ExternalIngressCIDRs $WcpClusterParams.NcpClusterNetworkSpec.ExternalIngressCIDRs `
|
||||
-ExternalEgressCIDRs $WcpClusterParams.NcpClusterNetworkSpec.ExternalEgressCIDRs `
|
||||
-WorkerDnsServer $WcpClusterParams.WorkerDnsServer `
|
||||
-MasterDnsServerIpAddress $WcpClusterParams.MasterDnsServerIpAddress `
|
||||
-MasterDnsSearchDomain $WcpClusterParams.MasterDnsSearchDomain `
|
||||
-ContentLibrary $contentLibrary
|
||||
|
||||
# Create VM classes
|
||||
$WcpClusterParams.VmClass | ForEach-Object {
|
||||
Invoke-CreateNamespaceManagementVirtualMachineClasses `
|
||||
-NamespaceManagementVirtualMachineClassesCreateSpec (
|
||||
Initialize-NamespaceManagementVirtualMachineClassesCreateSpec `
|
||||
-Id $_.Id `
|
||||
-CpuCount $_.CpuCount `
|
||||
-MemoryMB $_.MemoryMB `
|
||||
-MemoryReservation $_.MemoryReservation `
|
||||
-Devices (
|
||||
Initialize-NamespaceManagementVirtualMachineClassesVirtualDevices `
|
||||
-VgpuDevices (
|
||||
$_.VGpuProfiles | ForEach-Object {
|
||||
Initialize-NamespaceManagementVirtualMachineClassesVGPUDevice -ProfileName $_
|
||||
})))
|
||||
}
|
||||
|
||||
# Deploy Namespaces
|
||||
$WcpClusterParams.Namespace | ForEach-Object {
|
||||
$wmNamespace = New-WMNamespace `
|
||||
-Name $_ `
|
||||
-Cluster (Get-Cluster -Name $WcpClusterParams.Cluster)
|
||||
$wmNamespace | New-WMNamespaceStoragePolicy `
|
||||
-StoragePolicy (Get-SpbmStoragePolicy -Name $WcpClusterParams.NamespaceStoragePolicy) | Out-Null
|
||||
|
||||
# Assign the Supervisor Namespace Roles to Active Directory Groups
|
||||
$wmNamespace | New-WMNamespacePermission `
|
||||
-Role 'Edit' `
|
||||
-Domain $domain `
|
||||
-PrincipalType 'Group' `
|
||||
-PrincipalName $WcpClusterParams.NamespaceEditUserGroup `
|
||||
-ErrorAction SilentlyContinue | Out-Null
|
||||
|
||||
$wmNamespace | New-WMNamespacePermission `
|
||||
-Role 'View' `
|
||||
-Domain $domain `
|
||||
-PrincipalType 'Group' `
|
||||
-PrincipalName $WcpClusterParams.NamespaceViewUserGroup `
|
||||
-ErrorAction SilentlyContinue | Out-Null
|
||||
|
||||
if ($WcpClusterParams.VmClassNamespace.ContainsKey($_)) {
|
||||
Invoke-UpdateNamespaceInstances -Namespace $_ -NamespacesInstancesUpdateSpec (
|
||||
Initialize-NamespacesInstancesUpdateSpec -VmServiceSpec (
|
||||
Initialize-NamespacesInstancesVMServiceSpec -VmClasses $WcpClusterParams.VmClassNamespace[$_] -ContentLibraries $WcpClusterParams.ContentLibraryNamespace[$_]
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
$vcConn | Disconnect-VIServer -Confirm:$false
|
||||
38
Scripts/PAIF-N/README.md
Normal file
38
Scripts/PAIF-N/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# VMware Private AI Foundation with NVIDIA Guide
|
||||
|
||||
This example demonstrates how a VI admin would:
|
||||
|
||||
* instantiate a new VCF workload domain for data scientist teams
|
||||
* setup the following infrastructure configuration required for **PAIF-N** workload domain
|
||||
|
||||
## Deploying a VI workload domain
|
||||
|
||||
This script creates a VI workload domain using the **PowerCLI** SDK module for **VCF SDDC Manager**.
|
||||
|
||||
The script can be broken into two main parts. First, the ESXi hosts are being commissioned. Then, the actual VI domain is created using the commissioned ESXi hosts.
|
||||
|
||||
Both steps - ESXi host commissioning and VI domain creations - are three-stage operations themselves. The commissioning/creation specs are constructed. The specs are validated. The actual operation is invoked. The validation and operation invocation are long-running tasks. This requires awaiting and status tracking until their completion. The waiting for validation and the actual operation is done using helper cmdlets -
|
||||
Wait-VcfValidation and Wait-VcfTask, located in `utils` sub-folder.
|
||||
|
||||
On completion, a new VI workload domain reflecting the given parameters should be created.
|
||||
|
||||
## ESXi hosts configuration for AI workloads
|
||||
|
||||
This script configures the ESXi host for AI workloads which includes installing the Nvidia AI Enterprise vGPU driver and Nvidia GPU Management Daemon on the ESXi hosts. vLCM is used for that purpose.
|
||||
|
||||
The script changes the default graphics type of the GPU devices to Shared Direct. The Xorg service is then restarted. Finally, the vLCM is used to install the NVIDIA GPU driver and management daemon.
|
||||
|
||||
## NSX Edge Cluster creation
|
||||
|
||||
This script creates an NSX edge cluster to provide connectivity from external networks to Supervisor Cluster objects.
|
||||
|
||||
## Workload Management enablement and configuration
|
||||
|
||||
This script enables Workload Management (Kubernetes) and sets it up for AI workloads.
|
||||
|
||||
The script:
|
||||
|
||||
1. Enables the Supervisor cluster
|
||||
2. Creates content library for the deep learning VM template
|
||||
3. Creates GPU-enabled VMClass
|
||||
4. Creates namespace(s) and assigns the created VMClass and assigns deep learning VM content library
|
||||
109
Scripts/PAIF-N/utils/Wait-VcfTask.ps1
Normal file
109
Scripts/PAIF-N/utils/Wait-VcfTask.ps1
Normal file
@@ -0,0 +1,109 @@
|
||||
<#
|
||||
# © 2024 Broadcom. All Rights Reserved. Broadcom. The term "Broadcom" refers to
|
||||
# Broadcom Inc. and/or its subsidiaries.
|
||||
#>
|
||||
|
||||
using namespace VMware.Bindings.Vcf.SddcManager.Model
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
This cmdlet waits for VCF task to complete or fail.
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
This cmdlet waits for VCF task to complete or fail.
|
||||
|
||||
.PARAMETER Task
|
||||
Specifies the task to be waited for.
|
||||
|
||||
.PARAMETER ThrowOnError
|
||||
Specifies if an error will be thrown if the task fails.
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Wait-VcfTask -Task $task -ThrowOnError
|
||||
|
||||
Waits for the $task to complete or fails.
|
||||
|
||||
.OUTPUTS
|
||||
Zero or more VMware.Bindings.Vcf.SddcManager.Model.Task object
|
||||
|
||||
.LINK
|
||||
|
||||
#>
|
||||
|
||||
function Wait-VcfTask {
|
||||
[CmdletBinding(
|
||||
ConfirmImpact = "None",
|
||||
DefaultParameterSetName = "Default",
|
||||
SupportsPaging = $false,
|
||||
PositionalBinding = $false,
|
||||
RemotingCapability = "None",
|
||||
SupportsShouldProcess = $false,
|
||||
SupportsTransactions = $false)]
|
||||
[OutputType([VMware.Bindings.Vcf.SddcManager.Model.Task])]
|
||||
|
||||
Param (
|
||||
[Parameter(
|
||||
Mandatory = $true,
|
||||
Position = 0)]
|
||||
[VMware.Bindings.Vcf.SddcManager.Model.Task]
|
||||
$Task,
|
||||
|
||||
[Parameter()]
|
||||
[switch]
|
||||
$ThrowOnError
|
||||
)
|
||||
|
||||
$Task | ConvertTo-Json -Depth 10 | Write-Verbose
|
||||
|
||||
$taskName = $Task.Name
|
||||
|
||||
Write-Progress -Id 0 $taskName
|
||||
|
||||
while ($Task.Status -eq "In Progress" -or $Task.Status -eq 'IN_PROGRESS' -or $Task.Status -eq 'PENDING' -or $Task.Status -eq 'Pending') {
|
||||
|
||||
Write-Verbose "$taskName in progress"
|
||||
$Task | ConvertTo-Json -Depth 10 | Write-Verbose
|
||||
|
||||
if ($Task.SubTasks -and $Task.SubTasks.Count -gt 0) {
|
||||
$completedSubTask = $Task.SubTasks | Where-Object {
|
||||
$_.Status -eq 'SUCCESSFUL' -or $_.Status -eq 'Successful'
|
||||
} | Measure-Object | Select-Object -ExpandProperty Count
|
||||
|
||||
$currentSubTaskName = $Task.SubTasks | Where-Object {
|
||||
$_.Status -eq 'RUNNING' -or $_.Status -eq 'Running' -or $_.Status -eq "IN_PROGRESS" -or $_.Status -eq "In Progress"
|
||||
} | Select-Object -First 1 -ExpandProperty Name
|
||||
|
||||
if ($currentSubTaskName) {
|
||||
Write-Progress -Id 0 $taskName -Status $currentSubTaskName -PercentComplete (($completedSubTask * 100) / $Task.SubTasks.Count)
|
||||
} else {
|
||||
Write-Progress -Id 0 $taskName -PercentComplete (($completedSubTask * 100) / $Task.SubTasks.Count)
|
||||
}
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 1
|
||||
$Task = Invoke-VcfGetTask -id $Task.Id
|
||||
$taskName = $Task.Name
|
||||
}
|
||||
if ($Task.Status -ne "Successful" -and $Task.Status -ne 'SUCCESSFUL') {
|
||||
Write-Progress -Id 0 "$taskName failed" -Completed
|
||||
Write-Verbose "$taskName failed"
|
||||
$Task | ConvertTo-Json -Depth 10 | Write-Verbose
|
||||
|
||||
$Task.SubTasks | ForEach-Object {
|
||||
Write-Verbose "[$(if($_.Status -eq 'SUCCESSFUL' -or $_.Status -eq "Successful"){"+"}else{"-"})] $($_.Description)"
|
||||
}
|
||||
|
||||
if ($ThrowOnError) {
|
||||
throw $Task
|
||||
} else {
|
||||
Write-Output $Task
|
||||
}
|
||||
} else {
|
||||
Write-Progress -Id 0 "$taskName succeeded" -Completed
|
||||
Write-Verbose "$taskName succeeded"
|
||||
|
||||
Write-Output $Task
|
||||
}
|
||||
}
|
||||
123
Scripts/PAIF-N/utils/Wait-VcfValidation.ps1
Normal file
123
Scripts/PAIF-N/utils/Wait-VcfValidation.ps1
Normal file
@@ -0,0 +1,123 @@
|
||||
<#
|
||||
# © 2024 Broadcom. All Rights Reserved. Broadcom. The term "Broadcom" refers to
|
||||
# Broadcom Inc. and/or its subsidiaries.
|
||||
#>
|
||||
|
||||
using namespace VMware.Bindings.Vcf.SddcManager.Model
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
This cmdlet waits for VCF task to complete or fail.
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
This cmdlet waits for VCF task to complete or fail.
|
||||
|
||||
.PARAMETER Task
|
||||
Specifies the task to be waited for.
|
||||
|
||||
.PARAMETER ThrowOnError
|
||||
Specifies if an error will be thrown if the task fails.
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Wait-VcfTask -Task $task -ThrowOnError
|
||||
|
||||
Waits for the $task to complete or fails.
|
||||
|
||||
.OUTPUTS
|
||||
Zero or more VMware.Bindings.Vcf.SddcManager.Model.Task object
|
||||
|
||||
.LINK
|
||||
|
||||
#>
|
||||
|
||||
function Wait-VcfValidation {
|
||||
[CmdletBinding(
|
||||
ConfirmImpact = "None",
|
||||
DefaultParameterSetName = "Default",
|
||||
SupportsPaging = $false,
|
||||
PositionalBinding = $false,
|
||||
RemotingCapability = "None",
|
||||
SupportsShouldProcess = $false,
|
||||
SupportsTransactions = $false)]
|
||||
[OutputType([VMware.Bindings.Vcf.SddcManager.Model.Validation])]
|
||||
|
||||
Param (
|
||||
[Parameter(
|
||||
Mandatory = $true,
|
||||
ValueFromPipeline = $true,
|
||||
Position = 0)]
|
||||
[VMware.Bindings.Vcf.SddcManager.Model.Validation]
|
||||
$Validation,
|
||||
|
||||
[Parameter(
|
||||
Position = 1)]
|
||||
[scriptblock]
|
||||
$UpdateValidation,
|
||||
|
||||
[Parameter(
|
||||
Position = 2)]
|
||||
[object[]]
|
||||
$UpdateValidationArguments,
|
||||
|
||||
[Parameter()]
|
||||
[switch]
|
||||
$ThrowOnError
|
||||
)
|
||||
|
||||
$Validation | ConvertTo-Json -Depth 10 | Write-Verbose
|
||||
|
||||
$validationDescription = $Validation.Description
|
||||
|
||||
Write-Progress -Id 0 $validationDescription
|
||||
|
||||
while ($Validation.ExecutionStatus -eq 'IN_PROGRESS' -or $Validation.ExecutionStatus -eq 'CANCELLATION_IN_PROGRESS') {
|
||||
|
||||
Write-Verbose "$validationDescription in progress"
|
||||
$Validation | ConvertTo-Json -Depth 10 | Write-Verbose
|
||||
|
||||
if ($Validation.ValidationChecks -and $Validation.ValidationChecks.Count -gt 0) {
|
||||
$completedSubTask = $Validation.ValidationChecks | Where-Object {
|
||||
$_.ResultStatus -eq 'SUCCEEDED'
|
||||
} | Measure-Object | Select-Object -ExpandProperty Count
|
||||
|
||||
$currentSubTaskName = $Validation.ValidationChecks | Where-Object {
|
||||
$_.ResultStatus -eq 'IN_PROGRESS'
|
||||
} | Select-Object -First 1 -ExpandProperty Name
|
||||
|
||||
if ($currentSubTaskName) {
|
||||
Write-Progress -Id 0 $validationDescription -Status $currentSubTaskName -PercentComplete (($completedSubTask * 100) / $Validation.ValidationChecks.Count)
|
||||
} else {
|
||||
Write-Progress -Id 0 $validationDescription -PercentComplete (($completedSubTask * 100) / $Validation.ValidationChecks.Count)
|
||||
}
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 1
|
||||
if ($UpdateValidation) {
|
||||
$Validation = Invoke-Command -ScriptBlock $UpdateValidation -ArgumentList $UpdateValidationArguments
|
||||
}
|
||||
$validationDescription = $Validation.Description
|
||||
}
|
||||
|
||||
if ($Validation.ResultStatus -ne 'SUCCEEDED') {
|
||||
Write-Progress -Id 0 "$validationDescription failed" -Completed
|
||||
Write-Verbose "$validationDescription failed"
|
||||
$Validation | ConvertTo-Json -Depth 10 | Write-Verbose
|
||||
|
||||
$Validation.validationChecks | ForEach-Object {
|
||||
Write-Verbose "[$(if($_.ResultStatus -eq 'SUCCEEDED'){"+"}else{"-"})][$($_.Severity)] $($_.Description)"
|
||||
}
|
||||
|
||||
if ($ThrowOnError) {
|
||||
throw $Validation
|
||||
} else {
|
||||
Write-Output $Validation
|
||||
}
|
||||
} else {
|
||||
Write-Progress -Id 0 "$validationDescription succeeded" -Completed
|
||||
Write-Verbose "$validationDescription succeeded"
|
||||
|
||||
Write-Output $Validation
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user