Ich konnte letzte Woche endlich ein kleines Projekt fertigstellen, welches mich schon etwas länger verfolgte. Das vCloud Director Customer Provisioning mit VMware PowerCLI. Neue Kunden im VMware vCloud Director anzulegen ist wieder mal ein Paradebeispiel für eine Automation, denn es muss schnell, standardisiert und hoffentlich oft erledigt werden.
Die meisten Service Provider werden diese Aufgabe nicht unbedingt per PowerShell abbilden, sondern ehr direkt die API des VMware vCloud Director nutzen. Ich wollte jedoch mit meinem Projekt vCloud Director Customer Provisioning sehen, ob das Komplett mit VMware PowerCLI abbildbar ist. Eines schon vorweg, es ist nicht sehr komfortabel und auch nur eingeschränkt möglich.
Schritte beim vCloud Director Customer Provisioning
Die Anlage eines komplett neuen Kunden ist in mehrere Schritte gegliedert, welche teilweise in der richtigen Reihenfolge ausgeführt werden müssen.
Initial müssen allerdings erst noch die PowerShell Module geladen und der VMware vCloud Director verbunden werden:
# Import VMware PowerCLI vCD Module Import-Module VMware.VimAutomation.Cloud # Import My vCD Module Import-Module .\VMware-vCD-Module\ # Connect vCD Instance Connect-CIServer <Your vCD FQDN>
Create VMware vCloud Director Organization
Die Organisationen im VMware vCD kann man als Mandanten betrachten. Jeder Kunden hat im Normalfall seine eigene Organisation hinter der eine eigene URL und seine eigenen Benutzer sowie Ressourcen stehen.
Wie auch für die meisten weiteren Schritte gibt es in VMware PowerCLI ein natives Cmdlet für das Erstellen einer neuen Organisation: New-Org
Für meine Zwecke hat dieses Cmdlet allerdings zu wenig Möglichkeiten die Optionen der Organisation direkt beim Anlegen anzupassen.
Meine weiterführenden Optionen:
- Catalog Publishing
- Catalog Subscription
- VM Quota
- Stored VM Quota
- VM Lease Time
- Stored VM Lease Time
- Password Policy Settings
Daher habe ich für das vCloud Director Customer Provisioning folgende Funktion geschrieben um alle meine Anforderungen zu erfüllen:
#Requires -Version 4 #Requires -Modules VMware.VimAutomation.Cloud, @{ModuleName="VMware.VimAutomation.Cloud";ModuleVersion="6.3.0.0"} Function New-MyOrg { <# .SYNOPSIS Creates a new vCD Org with Default Parameters .DESCRIPTION Creates a new vCD Org with Default Parameters. Default Parameters are: * Catalog Publishing * Catalog Subscription * VM Quota * Stored VM Quota * VM Lease Time * Stored VM Lease Time * Password Policy Settings .NOTES File Name : New-MyOrg.ps1 Author : Markus Kraus Version : 1.1 State : Ready .LINK https://mycloudrevolution.com/ .EXAMPLE New-MyOrg -Name "TestOrg" -FullName "Test Org" -Description "PowerCLI Test Org" .PARAMETER Name Name of the New Org as String .PARAMETER FullName Full Name of the New Org as String .PARAMETER Description Description of the New Org as String .PARAMETER Enabled Should the New Org be enabled after creation Default:$false #> Param ( [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Name of the New Org as string")] [ValidateNotNullorEmpty()] [String] $Name, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Full Name of the New Org as string")] [ValidateNotNullorEmpty()] [String] $FullName, [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Description of the New Org as string")] [ValidateNotNullorEmpty()] [String] $Description, [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Should the New Org be enabled after creation")] [ValidateNotNullorEmpty()] [Switch]$Enabled ) Process { $vcloud = $DefaultCIServers[0].ExtensionData ## Create Objects $AdminOrg = New-Object VMware.VimAutomation.Cloud.Views.AdminOrg $orgGeneralSettings = New-Object VMware.VimAutomation.Cloud.Views.OrgGeneralSettings $orgOrgLeaseSettings = New-Object VMware.VimAutomation.Cloud.Views.OrgLeaseSettings $orgOrgVAppTemplateLeaseSettings = New-Object VMware.VimAutomation.Cloud.Views.OrgVAppTemplateLeaseSettings $orgOrgPasswordPolicySettings = New-Object VMware.VimAutomation.Cloud.Views.OrgPasswordPolicySettings $orgSettings = New-Object VMware.VimAutomation.Cloud.Views.OrgSettings ## Admin Settings $adminOrg.Name = $name $adminOrg.FullName = $FullName $adminOrg.Description = $description $adminOrg.IsEnabled = $Enabled ## Org Setting ### General Org Settings $orgGeneralSettings.CanPublishCatalogs = $False $orgGeneralSettings.CanPublishExternally = $False $orgGeneralSettings.CanSubscribe = $True $orgGeneralSettings.DeployedVMQuota = 0 $orgGeneralSettings.StoredVmQuota = 0 $orgSettings.OrgGeneralSettings = $orgGeneralSettings ### vApp Org Setting $orgOrgLeaseSettings.DeleteOnStorageLeaseExpiration = $false $orgOrgLeaseSettings.DeploymentLeaseSeconds = 0 $orgOrgLeaseSettings.StorageLeaseSeconds = 0 $orgSettings.VAppLeaseSettings = $orgOrgLeaseSettings ### vApp Template Org Setting $orgOrgVAppTemplateLeaseSettings.DeleteOnStorageLeaseExpiration = $false $orgOrgVAppTemplateLeaseSettings.StorageLeaseSeconds = 0 $orgSettings.VAppTemplateLeaseSettings = $orgOrgVAppTemplateLeaseSettings ### PasswordPolicySettings Org Setting $orgOrgPasswordPolicySettings.AccountLockoutEnabled = $True $orgOrgPasswordPolicySettings.InvalidLoginsBeforeLockout = 5 $orgOrgPasswordPolicySettings.AccountLockoutIntervalMinutes = 30 $orgSettings.OrgPasswordPolicySettings = $orgOrgPasswordPolicySettings $adminOrg.Settings = $orgSettings $CreateOrg = $vcloud.CreateOrg($adminOrg) Get-Org -Name $name | Format-Table -AutoSize } }
Create VMware vCloud Director Organization Administrator
Um dem neuen Kunden auch Zugriff auf seine Ressourcen zu gewähren muss mindestens ein User initial angelegt werden, Im optimalen Fall ist das ein Organisations Administrator. Mit diesem User kann der Kunden dann alle weiteren User selbst anlegen und einige Einstellungen anpassen (Siehe auch: Predefined Roles and Their Rights).
Für diesen Prozess gibt es leider kein natives Cmdlet in VMware PowerCLI.
Meine Funktion zur Useranlage sieht vor, dass der User für das vCloud Director Customer Provisioning fix als Organisations Administrator angelegt wird:
Function New-MyOrgAdmin { <# .SYNOPSIS Creates a new vCD Org Admin with Default Parameters .DESCRIPTION Creates a new vCD Org Admin with Default Parameters Default Parameters are: * User Role .NOTES File Name : New-MyOrgAdmin.ps1 Author : Markus Kraus Version : 1.2 State : Ready .LINK https://mycloudrevolution.com/ .EXAMPLE New-MyOrgAdmin -Name "OrgAdmin" -Pasword "Anfang!!" -FullName "Org Admin" -EmailAddress "[email protected]" -Org "TestOrg" .PARAMETER Name Name of the New Org Admin as String .PARAMETER FullName Full Name of the New Org Admin as String .PARAMETER Password Password of the New Org Admin as String .PARAMETER EmailAddress EmailAddress of the New Org Admin as String .PARAMETER Enabled Should the New Org be enabled after creation Default:$false .PARAMETER Org Org where the new Org Admin should be created as string #> Param ( [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Name of the New Org Admin as String")] [ValidateNotNullorEmpty()] [String] $Name, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Password of the New Org Admin as String")] [ValidateNotNullorEmpty()] [String] $Pasword, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Full Name of the New Org Admin as String")] [ValidateNotNullorEmpty()] [String] $FullName, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="EmailAddress of the New Org Admin as String")] [ValidateNotNullorEmpty()] [String] $EmailAddress, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Org where the new Org Admin should be created as string")] [ValidateNotNullorEmpty()] [String] $Org, [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Should the New Org be enabled after creation")] [ValidateNotNullorEmpty()] [Switch]$Enabled ) Process { ## Create Objects $OrgED = (Get-Org $Org).ExtensionData $orgAdminUser = New-Object VMware.VimAutomation.Cloud.Views.User ## Settings $orgAdminUser.Name = $Name $orgAdminUser.FullName = $FullName $orgAdminUser.EmailAddress = $EmailAddress $orgAdminUser.Password = $Pasword $orgAdminUser.IsEnabled = $Enabled $vcloud = $DefaultCIServers[0].ExtensionData ## Find Role if ((Get-Module -Name VMware.VimAutomation.Cloud).Version.Major -eq "6") { $vcloud = $global:DefaultCIServers[0].ExtensionData $orgAdminRole = $vcloud.RoleReferences.RoleReference | Where-Object {$_.Name -eq "Organization Administrator"} } elseif ((Get-Module -Name VMware.VimAutomation.Cloud).Version.Major -ge "11") { $orgAdminRole = $OrgED.RoleReferences.RoleReference | Where-Object {$_.Name -eq "Organization Administrator"} } $orgAdminUser.Role = $orgAdminRole ## Create User $user = $orgED.CreateUser($orgAdminUser) Get-CIUser -Org $Org -Name $Name | Format-Table -AutoSize } }
Create VMware vCloud Director Organization VDC
Als letzter und umfangreichster Schritt soll der Kunde noch ein Virtual Datacenter (VDC) bekommen. Das Organization VDC (OrgVDC) legt grob gesagt die Compute, Storage und Netzwerk Ressourcen für den Mandanten fest.
Speziell die Storage Ressourcen gestalten sich in der Anlage ziemlich komplex wenn man mit Storage Profiles arbeitet. Weder das native Cmdlet zur Anlage eins neuen OrgVDC (New-OrgVdc) noch das Cmdlet zum Anpassen dieser (Set-OrgVdc) kennen Storage Profiles. Mit dem korrekten Storage Profil kann dann auch ein Privater Katalog für Medien und vApp Templates in der Organisation erstellt werden. Diesen Schritt könnte der Kunde zwar auch selbst erledigen, aber wenn wir ja sowieso schon dabei sind…
Aber auch im bereich Netzwerk gibt es einige Hürden zu nehmen. VXLAN Network Pools und External Networks sind auch nicht gerade simpel bereitzustellen.
Da es sich ja um ein standardisiertes Bereitstellen handelt werden auch wieder einige Optionen fix gesetzt.
Fixe Optionen:
- Allocation Model
- Network Quota
- VM Quota
- ‚vCpu In Mhz‘
- Fast Provisioning
- Thin Provisioning
Meine Funktion zum Bereitstellen eines Org VDC für das vCloud Director Customer Provisioning sieht dann so aus:
#Requires -Version 4 #Requires -Modules VMware.VimAutomation.Cloud, @{ModuleName="VMware.VimAutomation.Cloud";ModuleVersion="6.3.0.0"} Function New-MyOrgVdc { <# .SYNOPSIS Creates a new vCD Org VDC with Default Parameters .DESCRIPTION Creates a new vCD Org VDC with Default Parameters Default Parameters are: * Allocation Model * Network Quota * VM Quota * 'vCpu In Mhz' * Fast Provisioning * Thin Provisioning * private Catalog .NOTES File Name : New-MyOrgVdc.ps1 Author : Markus Kraus Version : 1.2 State : Ready .LINK https://mycloudrevolution.com/ .EXAMPLE New-MyOrgVdc -Name "TestVdc" -CPULimit 1000 -MEMLimit 1000 -StorageLimit 1000 -StorageProfile "Standard-DC01" -NetworkPool "NetworkPool-DC01" -ProviderVDC "Provider-VDC-DC01" -Org "TestOrg" -ExternalNetwork "External_OrgVdcNet" .EXAMPLE New-MyOrgVdc -Name "TestVdc" -CPULimit 1000 -MEMLimit 1000 -StorageLimit 1000 -StorageProfile "Standard-DC01" -NetworkPool "NetworkPool-DC01" -ProviderVDC "Provider-VDC-DC01" -Org "TestOrg" .PARAMETER Name Name of the New Org VDC as String .PARAMETER CPULimit CPU Limit (MHz) of the New Org VDC as String .PARAMETER MEMLimit Memory Limit (MB) of the New Org VDC as String .PARAMETER StorageLimit Storage Limit (MB) of the New Org VDC as String .PARAMETER StorageProfile Storage Profile of the New Org VDC as String .PARAMETER NetworkPool Network Pool of the New Org VDC as String .PARAMETER ExternalNetwork Optional External Network of the New Org VDC as String .PARAMETER Enabled Should the New Org VDC be enabled after creation Default:$false Note: If an External Network is requested the Org VDC will be enabled during External Network Configuration .PARAMETER ProviderVDC ProviderVDC where the new Org VDC should be created as string .PARAMETER Org Org where the new Org VDC should be created as string .PARAMETER Timeout Timeout for teh Org VDC to get Ready Default: 120s #> Param ( [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Name of the New Org VDC as String")] [ValidateNotNullorEmpty()] [String] $Name, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="CPU Limit (MHz) of the New Org VDC as String")] [ValidateNotNullorEmpty()] [int] $CPULimit, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Memory Limit (MB) of the New Org VDC as String")] [ValidateNotNullorEmpty()] [int] $MEMLimit, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Storage Limit (MB) of the New Org VDC as String")] [ValidateNotNullorEmpty()] [int] $StorageLimit, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Storage Profile of the New Org VDC as String")] [ValidateNotNullorEmpty()] [String] $StorageProfile, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Network Pool of the New Org VDC as String")] [ValidateNotNullorEmpty()] [String] $NetworkPool, [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Optional External Network of the New Org VDC as String")] [ValidateNotNullorEmpty()] [String] $ExternalNetwork, [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Should the New Org VDC be enabled after creation")] [ValidateNotNullorEmpty()] [Switch]$Enabled, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="ProviderVDC where the new Org VDC should be created as string")] [ValidateNotNullorEmpty()] [String] $ProviderVDC, [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Org where the new Org VDC should be created as string")] [ValidateNotNullorEmpty()] [String] $Org, [Parameter(Mandatory=$False, ValueFromPipeline=$False,HelpMessage="Timeout for teh Org VDC to get Ready")] [ValidateNotNullorEmpty()] [int] $Timeout = 120 ) Process { ## Create Objects and all Settings Write-Verbose "Create Objects and all Settings" $adminVdc = New-Object VMware.VimAutomation.Cloud.Views.AdminVdc $adminVdc.Name = $name $adminVdc.IsEnabled = $Enabled $OrgVdcproviderVdc = Get-ProviderVdc $ProviderVDC $providerVdcRef = New-Object VMware.VimAutomation.Cloud.Views.Reference $providerVdcRef.Href = $OrgVdcproviderVdc.Href $adminVdc.ProviderVdcReference = $providerVdcRef $adminVdc.AllocationModel = "AllocationPool" $adminVdc.ComputeCapacity = New-Object VMware.VimAutomation.Cloud.Views.ComputeCapacity $adminVdc.ComputeCapacity.Cpu = New-Object VMware.VimAutomation.Cloud.Views.CapacityWithUsage $adminVdc.ComputeCapacity.Cpu.Units = "MHz" $adminVdc.ComputeCapacity.Cpu.Limit = $CPULimit $adminVdc.ComputeCapacity.Cpu.Allocated = $CPULimit $adminVdc.ComputeCapacity.Memory = New-Object VMware.VimAutomation.Cloud.Views.CapacityWithUsage $adminVdc.ComputeCapacity.Memory.Units = "MB" $adminVdc.ComputeCapacity.Memory.Limit = $MEMLimit $adminVdc.ComputeCapacity.Memory.Allocated = $MEMLimit $adminVdc.StorageCapacity = New-Object VMware.VimAutomation.Cloud.Views.CapacityWithUsage $adminVdc.StorageCapacity.Units = "MB" $adminVdc.StorageCapacity.Limit = $StorageLimit $adminVdc.NetworkQuota = 10 $adminVdc.VmQuota = 0 $adminVdc.VCpuInMhz = 1000 $adminVdc.VCpuInMhz2 = 1000 $adminVdc.UsesFastProvisioning = $false $adminVdc.IsThinProvision = $true ## Create Org vDC Write-Verbose "Create Org vDC" $OrgED = (Get-Org $Org).ExtensionData $orgVdc = $orgED.CreateVdc($adminVdc) ## Wait for getting Ready Write-Verbose "Wait for getting Ready" $i = 0 while(($orgVdc = Get-OrgVdc -Name $Name).Status -eq "NotReady"){ $i++ Start-Sleep 2 if($i -gt $Timeout) { Write-Error "Creating Org Failed."; break} Write-Progress -Activity "Creating Org" -Status "Wait for Org to become Ready..." } Write-Progress -Activity "Creating Org" -Completed Start-Sleep 2 ## Search given Storage Profile Write-Verbose "Search given Storage Profile" $ProVdcStorageProfile = search-cloud -QueryType ProviderVdcStorageProfile -Name $StorageProfile | Get-CIView ## Create Storage Profile Object with Settings Write-Verbose "Create Storage Profile Object with Settings" $spParams = new-object VMware.VimAutomation.Cloud.Views.VdcStorageProfileParams $spParams.Limit = $StorageLimit $spParams.Units = "MB" $spParams.ProviderVdcStorageProfile = $ProVdcStorageProfile.href $spParams.Enabled = $true $spParams.Default = $true $UpdateParams = new-object VMware.VimAutomation.Cloud.Views.UpdateVdcStorageProfiles $UpdateParams.AddStorageProfile = $spParams ## Update Org vDC $orgVdc = Get-OrgVdc -Name $name $orgVdc.ExtensionData.CreateVdcStorageProfile($UpdateParams) ## Wait for getting Ready Write-Verbose "Wait for getting Ready" while(($orgVdc = Get-OrgVdc -Name $name).Status -eq "NotReady"){ $i++ Start-Sleep 1 if($i -gt $Timeout) { Write-Error "Update Org Failed."; break} Write-Progress -Activity "Updating Org" -Status "Wait for Org to become Ready..." } Write-Progress -Activity "Updating Org" -Completed Start-Sleep 1 ## Search Any-StorageProfile Write-Verbose "Search Any-StorageProfile" $orgvDCAnyProfile = search-cloud -querytype AdminOrgVdcStorageProfile | Where-Object {($_.Name -match '\*') -and ($_.VdcName -eq $orgVdc.Name)} | Get-CIView ## Disable Any-StorageProfile Write-Verbose "Disable Any-StorageProfile" $orgvDCAnyProfile.Enabled = $False $return = $orgvDCAnyProfile.UpdateServerData() ## Remove Any-StorageProfile Write-Verbose "Remove Any-StorageProfile" $ProfileUpdateParams = new-object VMware.VimAutomation.Cloud.Views.UpdateVdcStorageProfiles $ProfileUpdateParams.RemoveStorageProfile = $orgvDCAnyProfile.href $remove = $orgvdc.extensiondata.CreatevDCStorageProfile($ProfileUpdateParams) ## Wait for getting Ready Write-Verbose "Wait for getting Ready" while(($orgVdc = Get-OrgVdc -Name $name).Status -eq "NotReady"){ $i++ Start-Sleep 1 if($i -gt $Timeout) { Write-Error "Update Org Failed."; break} Write-Progress -Activity "Updating Org" -Status "Wait for Org to become Ready..." } Write-Progress -Activity "Updating Org" -Completed Start-Sleep 1 ## Set NetworkPool for correct location Write-Verbose "Set NetworkPool for correct location" $orgVdc = Get-OrgVdc -Name $name $ProVdcNetworkPool = Get-NetworkPool -ProviderVdc $ProviderVDC -Name $NetworkPool $set = Set-OrgVdc -OrgVdc $orgVdc -NetworkPool $ProVdcNetworkPool -NetworkMaxCount "10" ## Create private Catalog Write-Verbose "Create private Catalog Object" $OrgCatalog = New-Object VMware.VimAutomation.Cloud.Views.AdminCatalog $OrgCatalog.name = "$Org Private Catalog" if (!(Get-Org $org | Get-Catalog -Name $OrgCatalog.name -ErrorAction SilentlyContinue)) { Write-Verbose "Create private Catalog" $CreateCatalog = (Get-Org $org | Get-CIView).CreateCatalog($OrgCatalog) $AccessControlRule = New-CIAccessControlRule -Entity $CreateCatalog.name -EveryoneInOrg -AccessLevel ReadWrite -Confirm:$False } else { Write-Output "Catalog '$($OrgCatalog.name)' aleady exists!" } ## Create a direct connect network if ($ExternalNetwork) { Write-Verbose "Create a direct connect network" Write-Output "Org VDC '$Name' needs to be enabled to add an external Network!" $EnableOrgVdc = Set-OrgVdc -OrgVdc $Name -Enabled:$True $orgVdcView = Get-OrgVdc $Name | Get-CIView $extNetwork = $_.externalnetwork $extNetwork = Get-ExternalNetwork | Get-CIView | Where-Object {$_.name -eq $ExternalNetwork} $orgNetwork = new-object vmware.vimautomation.cloud.views.orgvdcnetwork $orgNetwork.name = $ExternalNetwork $orgNetwork.Configuration = New-Object VMware.VimAutomation.Cloud.Views.NetworkConfiguration $orgNetwork.Configuration.FenceMode = 'bridged' $orgNetwork.configuration.ParentNetwork = New-Object vmware.vimautomation.cloud.views.reference $orgNetwork.configuration.ParentNetwork.href = $extNetwork.href $result = $orgVdcView.CreateNetwork($orgNetwork) } Get-OrgVdc -Name $name | Format-Table -AutoSize } }
Starten des vCloud Director Customer Provisioning
Um nun die oben aufgeführten Schritte alle mögliches effizient in Kombination auszuführen habe ich mir eine übergeordnete Funktion erstellt. Diese PowerShell Funktion wird mit einem JSON Config File gefüttert und ruft dann die erforderlichen Funktionen mit den entsprechenden Parametern auf.
In dieser übergeordneten Funktion habe ich zusätzlich die Möglichkeit abgebildet mit OrgVDC T-Shirt Sizes zu arbeiten. Das bedeutet hinter der Größe M ist dann bereits ein gewisse Parametrisierung für CPU RAM und Storage hinterlegt. Wenn in dem JSON File das Feld ‚FixedSize‘ leer ist („FixedSize“: „“,) werden die darauffolgenden, manuellen Werte verwendet.
Ähnliches gilt für das Feld ‚ExternalNetwork‘. Ist dieses leer wir das neue OrgVDC ohne ein Externes Netzwerk angelegt.
Das JSON Config File
{ "Org": { "Name":"TestOrg", "FullName": "Test Org", "Description":"Automation Test Org" }, "OrgAdmin": { "Name":"TestOrgAdmin", "Pasword": "myPassword1!", "FullName":"Test OrgAdmin", "EmailAddress":"[email protected]" }, "OrgVdc": { "Name":"TestOrgVdc", "FixedSize": "M", "CPULimit": "1000", "MEMLimit":"1024", "StorageLimit":"1024", "StorageProfile":"Standard-DC01", "ProviderVDC":"Provider-VDC-DC01", "NetworkPool":"Provider-VDC-DC01-NetPool", "ExternalNetwork": "External-OrgVdcNet" } }
Die PowerShell Funktion
#Requires -Version 4 #Requires -Modules VMware.VimAutomation.Cloud, @{ModuleName="VMware.VimAutomation.Cloud";ModuleVersion="6.3.0.0"} Function Invoke-MyOnBoarding { <# .SYNOPSIS Creates all vCD Objecst for a new IAAS Customer .DESCRIPTION Creates all vCD Objects for a new IAAS Customer All Objects are: * Org * Default Org Admin * Org VDC ** Private Catalog ** Optional Bridged Network JSON Config Example: { "Org": { "Name":"TestOrg", "FullName": "Test Org", "Description":"Automation Test Org" }, "OrgAdmin": { "Name":"TestOrgAdmin", "Pasword": "myPassword1!", "FullName":"Test OrgAdmin", "EmailAddress":"[email protected]" }, "OrgVdc": { "Name":"TestOrgVdc", "FixedSize": "M", "CPULimit": "1000", "MEMLimit":"1000", "StorageLimit":"1000", "StorageProfile":"Standard-DC01", "ProviderVDC":"Provider-VDC-DC01", "NetworkPool":"Provider-VDC-DC01-NetPool", "ExternalNetwork": "External_OrgVdcNet" } } .NOTES File Name : Invoke-MyOnBoarding.ps1 Author : Markus Kraus Version : 1.2 State : Ready .LINK https://mycloudrevolution.com/ .EXAMPLE Invoke-MyOnBoarding -ConfigFile ".\OnBoarding.json" -Enabled:$true .EXAMPLE Invoke-MyOnBoarding -ConfigFile ".\OnBoarding.json" -Enabled:$false .PARAMETER ConfigFile Full Path to the JSON Config File .PARAMETER Enabled Should the Customer be enabled after creation Default: $False #> Param ( [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Full Path to the JSON Config File")] [ValidateNotNullorEmpty()] [String] $ConfigFile, [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Should the Customer be enabled after creation")] [ValidateNotNullorEmpty()] [Switch]$Enabled ) Process { $Valid = $true Write-Verbose "## Import JSON Config" Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Importing JSON Config...`n" $Configs = Get-Content -Raw -Path $ConfigFile -ErrorAction Continue | ConvertFrom-Json -ErrorAction Continue if (!($Configs)) { $Valid = $false Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Importing JSON Config Failed" -ForegroundColor Red } else { Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Importing JSON Config OK" -ForegroundColor Green } if ($Valid) { try{ Write-Verbose "## Create Org" Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new Org...`n" -ForegroundColor Yellow $Trash = New-MyOrg -Name $Configs.Org.Name -FullName $Configs.Org.Fullname -Description $Configs.Org.Description -Enabled:$Enabled Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new Org OK" -ForegroundColor Green Get-Org -Name $Configs.Org.Name | Select-Object Name, FullName, Enabled | Format-Table -AutoSize } catch { $Valid = $false Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new Org Failed" -ForegroundColor Red } } if ($Valid) { try{ Write-Verbose "## Create OrgAdmin" Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgAdmin...`n" -ForegroundColor Yellow $Trash = New-MyOrgAdmin -Name $Configs.OrgAdmin.Name -Pasword $Configs.OrgAdmin.Pasword -FullName $Configs.OrgAdmin.FullName -EmailAddress $Configs.OrgAdmin.EmailAddress -Org $Configs.Org.Name -Enabled:$Enabled Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgAdmin OK" -ForegroundColor Green Get-CIUser -Org $Configs.Org.Name -Name $Configs.OrgAdmin.Name | Select-Object Name, FullName, Email | Format-Table -AutoSize } catch { $Valid = $false Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgAdmin Failed" -ForegroundColor Red } } if ($Valid) { try{ Write-Verbose "## Create OrgVdc" Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgVdc...`n" -ForegroundColor Yellow if ($Configs.OrgVdc.FixedSize){ Write-Host "Fixed Size (T-Shirt Size) '$($Configs.OrgVdc.FixedSize)' Org VDC Requested!" switch ($Configs.OrgVdc.FixedSize) { M { [String]$CPULimit = 36000 [String]$MEMLimit = 122880 [String]$StorageLimit = 1048576 } L { [String]$CPULimit = 36000 [String]$MEMLimit = 245760 [String]$StorageLimit = 1048576 } default {throw "Invalid T-Shirt Size!"} } } else{ Write-Host "Custom Org VDC Size Requested!" $CPULimit = $Configs.OrgVdc.CPULimit $MEMLimit = $Configs.OrgVdc.MEMLimit $StorageLimit = $Configs.OrgVdc.StorageLimit } if ($Configs.OrgVdc.ExternalNetwork){ $Trash = New-MyOrgVdc -Name $Configs.OrgVdc.Name -CPULimit $CPULimit -MEMLimit $MEMLimit -StorageLimit $StorageLimit -Networkpool $Configs.OrgVdc.NetworkPool -StorageProfile $Configs.OrgVdc.StorageProfile -ProviderVDC $Configs.OrgVdc.ProviderVDC -ExternalNetwork $Configs.OrgVdc.ExternalNetwork -Org $Configs.Org.Name -Enabled:$Enabled } else { $Trash = New-MyOrgVdc -Name $Configs.OrgVdc.Name -CPULimit $CPULimit -MEMLimit $MEMLimit -StorageLimit $StorageLimit -Networkpool $Configs.OrgVdc.NetworkPool -StorageProfile $Configs.OrgVdc.StorageProfile -ProviderVDC $Configs.OrgVdc.ProviderVDC -Org $Configs.Org.Name -Enabled:$Enabled } Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgVdc OK" -ForegroundColor Green Get-OrgVdc -Org $Configs.Org.Name -Name $Configs.OrgVdc.Name | Select-Object Name, Enabled, CpuAllocationGhz, MemoryLimitGB, StorageLimitGB, AllocationModel, ThinProvisioned, UseFastProvisioning, ` @{N="StorageProfile";E={$_.ExtensionData.VdcStorageProfiles.VdcStorageProfile.Name}}, ` @{N='VCpuInMhz';E={$_.ExtensionData.VCpuInMhz}} | Format-Table -AutoSize } catch { $Valid = $false Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Creating new OrgVdc Failed" -ForegroundColor Red } } Write-Output "Overall Execution was Valid: $Valid" } }
Offene Punkte vCloud Director Customer Provisioning
Wie dem aufmerksamen Leser vielleicht aufgefallen ist, kann die New-MyOrgVdc Funktion zwar auf Wunsch ein Externel Netzwerk im Bridged Modus dem OrgVDC hinzufügen aber ’noch‘ kein Edge Gatway.
Ich arbeite hier weiter an einer Möglichkeit. Wer da bereits etwas Vergleichbares in PowerShell abgebildet hat kann mir gerne eine Tipp geben. Auf meine VMware Community Frage gab es leider bisher keine Reaktionen.
Später soll das vCloud Director Customer Provisioning Modul dann über das blanke Anlegen hinaus erweitert werden. Also Erweitern der Ressourcen eines OrgVDC, hinzufügen weiterer Storage Profiles und weitere Dinge dieser Art.
Das vCloud Director Customer Provisioning Projekt
Pester Tests
Für mein Projekt habe ich auch ein paar grundlegende Pester Tests vorgesehen. Die Tests validieren die PowerShell Syntax, die Voranforderungen auf dem System und den erfolgreichen Import des Modules.
Read the Docs
Um den Einstieg in das vCloud Director Customer Provisioning etwas zu erleichtern habe ich, wie in meinem Plaster Artikel angekündigt, eine kleine Dokumentation der Funktionen bereitgestellt:
Welcome to my VMware-vCD-Module Module
GitHub Repository
Ein GitHub Repository durfte natürlich auch wieder nicht fehlen:
Weitere Quellen
- Automating creation of vCD Organizations, Users and Org vDCs from Alan Renouf
- Creating a vCloud Director Organization with PowerCLI from Unknown
#LongLiveVCD
Commented on your communities post with some code I use to provision what you need. Mine may be overly complex for your needs as I needed a way to allow for custom network provisioning with on-demand nested labs.
If you’d like to take a look at the entire script let me know, it’s lengthy but it allowed for nested-labs to be deployed in around 30 minutes from scratch and allowed for network and naming customization.
Thanks William.
I will check your comment tomorrow.
If I will take a look at the entire Script I will come back to you. What is the best way to contact you?
[Email address hidden] is my personal email, feel free to send me a message.