diff --git a/Modules/ContentLibrary/ContentLibrary.psm1 b/Modules/ContentLibrary/ContentLibrary.psm1 index 318b999..9a8574b 100644 --- a/Modules/ContentLibrary/ContentLibrary.psm1 +++ b/Modules/ContentLibrary/ContentLibrary.psm1 @@ -20,12 +20,12 @@ [Parameter(Mandatory=$false)][String]$LibraryName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $results = @() - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryID) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryID) # Use vCenter REST API to retrieve name of Datastore that is backing the Content Library $datastoreService = Get-CisService com.vmware.vcenter.datastore @@ -108,18 +108,18 @@ Function Get-ContentLibraryItems { [Parameter(Mandatory=$false)][String]$LibraryItemName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $results = @() - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { - $contentLibaryItemService = Get-CisService com.vmware.content.library.item - $itemIds = $contentLibaryItemService.list($libraryID) + $contentLibraryItemService = Get-CisService com.vmware.content.library.item + $itemIds = $contentLibraryItemService.list($libraryID) foreach($itemId in $itemIds) { - $item = $contentLibaryItemService.get($itemId) + $item = $contentLibraryItemService.get($itemId) if(!$LibraryItemName) { $itemResult = [pscustomobject] @{ @@ -179,28 +179,40 @@ Function Get-ContentLibraryItemFiles { [Parameter(Mandatory=$false)][String]$LibraryItemName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $libraryIDs = $contentLibraryService.list() $results = @() - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $libraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { - $contentLibaryItemService = Get-CisService com.vmware.content.library.item - $itemIds = $contentLibaryItemService.list($libraryID) - + $contentLibraryItemService = Get-CisService com.vmware.content.library.item + $itemIds = $contentLibraryItemService.list($libraryID) + $DatastoreID = $library.storage_backings.datastore_id.Value + $Datastore = get-datastore -id "Datastore-$DatastoreID" + foreach($itemId in $itemIds) { - $itemName = ($contentLibaryItemService.get($itemId)).name - $contenLibraryItemFileSerice = Get-CisService com.vmware.content.library.item.file - $files = $contenLibraryItemFileSerice.list($itemId) + $itemName = ($contentLibraryItemService.get($itemId)).name + $contentLibraryItemFileSerice = Get-CisService com.vmware.content.library.item.file + $files = $contentLibraryItemFileSerice.list($itemId) + $contentLibraryItemStorageService = Get-CisService com.vmware.content.library.item.storage foreach($file in $files) { + if($contentLibraryItemStorageService.get($itemId, $($file.name)).storage_backing.type -eq "DATASTORE"){ + $filepath = $contentLibraryItemStorageService.get($itemId, $($file.name)).storage_uris.AbsolutePath.split("/")[5..7] -join "/" + $fullfilepath = "[$($datastore.name)] $filepath" + } + else{ + $fullfilepath = "UNKNOWN" + } + if(!$LibraryItemName) { $fileResult = [pscustomobject] @{ Name = $file.name; Version = $file.version; Size = $file.size; Stored = $file.cached; + Path = $fullfilepath; } $results+=$fileResult } else { @@ -210,6 +222,7 @@ Function Get-ContentLibraryItemFiles { Version = $file.version; Size = $file.size; Stored = $file.cached; + Path = $fullfilepath; } $results+=$fileResult } @@ -245,12 +258,12 @@ Function Set-ContentLibrary { [Parameter(Mandatory=$false)][Switch]$JSONPersistenceDisabled ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $found = $false - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { $found = $true break @@ -361,12 +374,12 @@ Function Remove-SubscribedContentLibrary { [Parameter(Mandatory=$true)][String]$LibraryName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $found = $false - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { $found = $true break @@ -460,12 +473,12 @@ Function Remove-LocalContentLibrary { [Parameter(Mandatory=$true)][String]$LibraryName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $found = $false - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { $found = $true break @@ -493,49 +506,49 @@ Function Copy-ContentLibrary { =========================================================================== .DESCRIPTION This function copies all library items from one Content Library to another - .PARAMETER SourceLibaryName + .PARAMETER SourceLibraryName The name of the source Content Library to copy from - .PARAMETER DestinationLibaryName + .PARAMETER DestinationLibraryName The name of the desintation Content Library to copy to .PARAMETER DeleteSourceFile Whther or not to delete library item from the source Content Library after copy .EXAMPLE - Copy-ContentLibrary -SourceLibaryName Foo -DestinationLibaryName Bar + Copy-ContentLibrary -SourceLibraryName Foo -DestinationLibraryName Bar .EXAMPLE - Copy-ContentLibrary -SourceLibaryName Foo -DestinationLibaryName Bar -DeleteSourceFile $true + Copy-ContentLibrary -SourceLibraryName Foo -DestinationLibraryName Bar -DeleteSourceFile $true #> param( - [Parameter(Mandatory=$true)][String]$SourceLibaryName, - [Parameter(Mandatory=$true)][String]$DestinationLibaryName, + [Parameter(Mandatory=$true)][String]$SourceLibraryName, + [Parameter(Mandatory=$true)][String]$DestinationLibraryName, [Parameter(Mandatory=$false)][Boolean]$DeleteSourceFile=$false ) - $sourceLibraryId = (Get-ContentLibrary -LibraryName $SourceLibaryName).Id + $sourceLibraryId = (Get-ContentLibrary -LibraryName $SourceLibraryName).Id if($sourceLibraryId -eq $null) { - Write-Host -ForegroundColor red "Unable to find Source Content Library named $SourceLibaryName" + Write-Host -ForegroundColor red "Unable to find Source Content Library named $SourceLibraryName" exit } - $destinationLibraryId = (Get-ContentLibrary -LibraryName $DestinationLibaryName).Id + $destinationLibraryId = (Get-ContentLibrary -LibraryName $DestinationLibraryName).Id if($destinationLibraryId -eq $null) { - Write-Host -ForegroundColor Red "Unable to find Destination Content Library named $DestinationLibaryName" + Write-Host -ForegroundColor Red "Unable to find Destination Content Library named $DestinationLibraryName" break } - $sourceItemFiles = Get-ContentLibraryItems -LibraryName $SourceLibaryName + $sourceItemFiles = Get-ContentLibraryItems -LibraryName $SourceLibraryName if($sourceItemFiles -eq $null) { - Write-Host -ForegroundColor red "Unable to retrieve Content Library Items from $SourceLibaryName" + Write-Host -ForegroundColor red "Unable to retrieve Content Library Items from $SourceLibraryName" break } - $contentLibaryItemService = Get-CisService com.vmware.content.library.item + $contentLibraryItemService = Get-CisService com.vmware.content.library.item foreach ($sourceItemFile in $sourceItemFiles) { # Check to see if file already exists in destination Content Library - $result = Get-ContentLibraryItems -LibraryName $DestinationLibaryName -LibraryItemName $sourceItemFile.Name + $result = Get-ContentLibraryItems -LibraryName $DestinationLibraryName -LibraryItemName $sourceItemFile.Name if($result -eq $null) { # Create CopySpec - $copySpec = $contentLibaryItemService.Help.copy.destination_create_spec.Create() + $copySpec = $contentLibraryItemService.Help.copy.destination_create_spec.Create() $copySpec.library_id = $destinationLibraryId $copySpec.name = $sourceItemFile.Name $copySpec.description = $sourceItemFile.Description @@ -545,7 +558,7 @@ Function Copy-ContentLibrary { # Perform Copy try { Write-Host -ForegroundColor Cyan "Copying" $sourceItemFile.Name "..." - $copyResult = $contentLibaryItemService.copy($UniqueChangeId, $sourceItemFile.Id, $copySpec) + $copyResult = $contentLibraryItemService.copy($UniqueChangeId, $sourceItemFile.Id, $copySpec) } catch { Write-Host -ForegroundColor Red "Failed to copy" $sourceItemFile.Name $Error[0] @@ -556,7 +569,7 @@ Function Copy-ContentLibrary { if($DeleteSourceFile) { try { Write-Host -ForegroundColor Magenta "Deleteing" $sourceItemFile.Name "..." - $deleteResult = $contentLibaryItemService.delete($sourceItemFile.Id) + $deleteResult = $contentLibraryItemService.delete($sourceItemFile.Id) } catch { Write-Host -ForegroundColor Red "Failed to delete" $sourceItemFile.Name $Error[0] @@ -570,7 +583,7 @@ Function Copy-ContentLibrary { if($DeleteSourceFile) { try { Write-Host -ForegroundColor Magenta "Deleteing" $sourceItemFile.Name "..." - $deleteResult = $contentLibaryItemService.delete($sourceItemFile.Id) + $deleteResult = $contentLibraryItemService.delete($sourceItemFile.Id) } catch { Write-Host -ForegroundColor Red "Failed to delete" $sourceItemFile.Name break @@ -597,7 +610,7 @@ Function New-VMTX { The name of the VM Template in Content Library .PARAMETER Description Description of the VM template - .PARAMETER LibaryName + .PARAMETER LibraryName The name of the Content Library to clone to .PARAMETER FolderName The name of vSphere Folder (Defaults to Workloads for VMC) @@ -696,4 +709,4 @@ Function New-VMFromVMTX { Write-Host "`nDeploying new VM $NewVMName from VMTX Template $VMTXName ..." $results = $vmtxService.deploy($vmtxId,$vmtxDeploySpec) -} \ No newline at end of file +} diff --git a/Modules/NSXT/NSXT.psd1 b/Modules/NSXT/NSXT.psd1 index c3371b3..3cee460 100644 --- a/Modules/NSXT/NSXT.psd1 +++ b/Modules/NSXT/NSXT.psd1 @@ -7,7 +7,35 @@ Copyright = '(c) 2017. All rights reserved.' Description = 'Powershell Module for NSX-T REST API Functions' PowerShellVersion = '5.0' - FunctionsToExport = 'Get-NSXTComputeManager','Get-NSXTFabricNode','Get-NSXTFirewallRule','Get-NSXTIPPool','Get-NSXTLogicalSwitch','Get-NSXTManager','Get-NSXTTransportZone','Get-NSXTController' + FunctionsToExport = 'Get-NSXTBGPNeighbors', + 'Get-NSXTComputeManager', + 'Get-NSXTController', + 'Get-NSXTEdgeCluster', + 'Get-NSXTFabricNode', + 'Get-NSXTFabricVM', + 'Get-NSXTFirewallRule', + 'Get-NSXTForwardingTable', + 'Get-NSXTIPPool', + 'Get-NSXTLogicalRouter', + 'Get-NSXTLogicalRouterPorts', + 'Get-NSXTLogicalSwitch', + 'Get-NSXTManager', + 'Get-NSXTNetworkRoutes', + 'Get-NSXTRoutingTable', + 'Get-NSXTTraceFlow', + 'Get-NSXTTraceFlowObservations', + 'Get-NSXTTransportNode', + 'Get-NSXTTransportZone', + 'Get-NSXTClusterNode', + 'Set-NSXTIPPool', + 'Set-NSXTLogicalRouter', + 'Set-NSXTLogicalSwitch', + 'Set-NSXTTraceFlow', + 'Get-NSXTIPAMIPBlock', + 'Set-NSXTIPAMIPBlock', + 'Remove-NSXTIPAMIPBlock' + + PrivateData = @{ PSData = @{ Tags = @('NSX-T','REST') diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index f8dcb49..4e135e8 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -71,63 +71,6 @@ Function Get-NSXTFabricNode { $results } -Function Get-NSXTIPPool { - Param ( - [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id - ) - - $ipPoolService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_pools" - - if($Id) { - $ipPools = $ipPoolService.get($Id) - } else { - $ipPools = $ipPoolService.list().results - } - - $results = @() - foreach ($ipPool in $ipPools) { - $tmp = [pscustomobject] @{ - Id = $ipPool.Id; - Name = $ipPool.Display_Name; - Total = $ipPool.pool_usage.total_ids; - Free = $ipPool.pool_usage.free_ids; - Network = $ipPool.subnets.cidr; - Gateway = $ipPool.subnets.gateway_ip; - DNS = $ipPool.subnets.dns_nameservers; - RangeStart = $ipPool.subnets.allocation_ranges.start; - RangeEnd = $ipPool.subnets.allocation_ranges.end - } - $results+=$tmp - } - $results -} - -Function Get-NSXTTransportZone { - Param ( - [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id - ) - - $transportZoneService = Get-NsxtService -Name "com.vmware.nsx.transport_zones" - - if($Id) { - $transportZones = $transportZoneService.get($Id) - } else { - $transportZones = $transportZoneService.list().results - } - - $results = @() - foreach ($transportZone in $transportZones) { - $tmp = [pscustomobject] @{ - Id = $transportZone.Id; - Name = $transportZone.display_name; - Type = $transportZone.transport_type; - HostSwitchName = $transportZone.host_switch_name; - } - $results+=$tmp - } - $results -} - Function Get-NSXTComputeManager { Param ( [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id @@ -160,38 +103,6 @@ Function Get-NSXTComputeManager { $results } -Function Get-NSXTLogicalSwitch { - Param ( - [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id - ) - - $logicalSwitchService = Get-NsxtService -Name "com.vmware.nsx.logical_switches" - $logicalSwitchSummaryService = Get-NsxtService -Name "com.vmware.nsx.logical_switches.summary" - - if($Id) { - $logicalSwitches = $logicalSwitchService.get($Id) - } else { - $logicalSwitches = $logicalSwitchService.list().results - } - - $results = @() - foreach ($logicalSwitch in $logicalSwitches) { - $transportZone = (Get-NSXTTransportZone -Id $logicalSwitch.transport_zone_id | Select Name | ft -HideTableHeaders | Out-String).trim() - $ports = $logicalSwitchSummaryService.get($logicalSwitch.id).num_logical_ports - - $tmp = [pscustomobject] @{ - Id = $logicalSwitch.Id; - Name = $logicalSwitch.display_name; - VLAN = $logicalSwitch.vlan; - AdminStatus = $logicalSwitch.admin_state; - Ports = $ports; - TransportZone = $transportZone; - } - $results+=$tmp - } - $results -} - Function Get-NSXTFirewallRule { Param ( [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id @@ -257,4 +168,1937 @@ Function Get-NSXTManager { } } $results -} \ No newline at end of file +} + +# Updated Function style below + +Function Get-NSXTTransportNode { + <# + .Synopsis + Retrieves the transport_node information + .DESCRIPTION + Retrieves transport_node information for a single or multiple IDs. Execute with no parameters to get all ports, specify a transport_node if known. + .EXAMPLE + Get-NSXTTransportNode + .EXAMPLE + Get-NSXTThingTemplate -Tranport_node_id "TN ID" +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id","Tranportnode_id")] + [string]$transport_node_id + ) + + begin + { + $NSXTransportNodesService = Get-NsxtService -Name "com.vmware.nsx.transport_nodes" + + class NSXTransportNode { + [string]$Name + [string]$Transport_node_id + [string]$maintenance_mode + hidden $tags = [System.Collections.Generic.List[string]]::new() + hidden $host_switches = [System.Collections.Generic.List[string]]::new() + hidden [string]$host_switch_spec + hidden $transport_zone_endpoints = [System.Collections.Generic.List[string]]::new() + } + } + + Process + { + if($transport_node_id) { + $NSXTransportNodes = $NSXTransportNodesService.get($transport_node_id) + } else { + $NSXTransportNodes = $NSXTransportNodesService.list().results + } + + foreach ($NSXTransportNode in $NSXTransportNodes) { + + $results = [NSXTransportNode]::new() + $results.Name = $NSXTransportNode.display_name; + $results.Transport_node_id = $NSXTransportNode.Id; + $results.maintenance_mode = $NSXTransportNode.maintenance_mode; + $results.Tags = $NSXTransportNode.tags; + $results.host_switches = $NSXTransportNode.host_switches; + $results.host_switch_spec = $NSXTransportNode.host_switch_spec; + $results.transport_zone_endpoints = $NSXTransportNode.transport_zone_endpoints; + $results.host_switches = $NSXTransportNode.host_switches + $results + } + } +} + +Function Get-NSXTTraceFlow { + <# + .Synopsis + Retrieves traceflow information + .DESCRIPTION + Retrieves traceflow information for a single or multiple traceflows. Execute with no parameters to get all traceflows, specify a traceflow_id if known. + .EXAMPLE + Get-NSXTTraceFlow + .EXAMPLE + Get-NSXTTraceFlow -traceflow_id "TF ID +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipeline=$true)] + [Alias("Id")] + [string]$traceflow_id + ) + + $NSXTraceFlowsService = Get-NsxtService -Name "com.vmware.nsx.traceflows" + + if($traceflow_id) { + $NSXTraceFlows = $NSXTraceFlowsService.get($traceflow_id) + } else { + $NSXTraceFlows = $NSXTraceFlowsService.list().results + } + + class NSXTraceFlow { + [string]$traceflow_id + hidden [string]$lport_id + [string]$Operation_State + [int]$Forwarded + [int]$Delivered + [int]$Received + [int]$Dropped + [string]$Analysis + } + + foreach ($NSXTraceFlow in $NSXTraceFlows) { + + $results = [NSXTraceFlow]::new() + $results.traceflow_id = $NSXTraceFlow.Id; + $results.Operation_State = $NSXTraceFlow.operation_state; + $results.forwarded = $NSXTraceFlow.Counters.forwarded_count; + $results.delivered = $NSXTraceFlow.Counters.delivered_count; + $results.received = $NSXTraceFlow.Counters.received_count; + $results.dropped = $NSXTraceFlow.Counters.dropped_count; + $results.analysis = $NSXTraceFlow.analysis + $results + } +} + +Function Get-NSXTTraceFlowObservations { + <# + .Synopsis + Retrieves traceflow observations information + .DESCRIPTION + Retrieves traceflow observations information for a single traceflow. Must specify a current traceflow_id + .EXAMPLE + Get-NSXTTraceFlowObservations -traceflow_id "TF ID" + .EXAMPLE + Get-NSXTTraceFlow | Get-NSXTTraceFlowObservations +#> + + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$traceflow_id + ) + + begin + { + $NSXTraceFlowsObservService = Get-NsxtService -Name "com.vmware.nsx.traceflows.observations" + } + + Process + { + if($traceflow_id) { + $NSXTraceFlowsObserv = $NSXTraceFlowsObservService.list($traceflow_id) + } else { + throw "TraceFlow ID required" + } + + $NSXTraceFlowsObserv.results | select transport_node_name,component_name,@{N='PacketEvent';E={($_.resource_type).TrimStart("TraceflowObservation")}} + } +} + +Function Get-NSXTEdgeCluster { + <# + .Synopsis + Retrieves the Edge cluster information + .DESCRIPTION + Retrieves Edge cluster information for a single or multiple clusterss. Execute with no parameters to get all ports, specify a edge_cluster_id if known. + .EXAMPLE + Get-NSXTEdgeCluster + .EXAMPLE + Get-NSXTEdgeCluster -edge_cluster_id "Edge Cluster ID" + .EXAMPLE + Get-NSXTThingTemplate | where name -eq "My Edge Cluster Name" +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$edge_cluster_id + ) + + Begin + { + $NSXTEdgeClustersService = Get-NsxtService -Name "com.vmware.nsx.edge_clusters" + + class NSXEdgeCluster { + [string]$Name + hidden [string]$Protection + hidden [string]$Tags + [string]$edge_cluster_id + [string]$resource_type + [string]$deployment_type + [string]$member_node_type + $members = [System.Collections.Generic.List[string]]::new() + $cluster_profile_bindings = [System.Collections.Generic.List[string]]::new() + } + } + + Process + { + if ($edge_cluster_id) { + $NSXEdgeClusters = $NSXTEdgeClustersService.get($edge_cluster_id) + } + else { + $NSXEdgeClusters = $NSXTEdgeClustersService.list().results + } + + foreach ($NSXEdgeCluster in $NSXEdgeClusters) { + + $results = [NSXEdgeCluster]::new() + $results.Name = $NSXEdgeCluster.display_name; + $results.Protection = $NSXEdgeCluster.Protection; + $results.edge_cluster_id = $NSXEdgeCluster.Id; + $results.resource_type = $NSXEdgeCluster.resource_type; + $results.Tags = $NSXEdgeCluster.tags; + $results.deployment_type = $NSXEdgeCluster.deployment_type; + $results.member_node_type = $NSXEdgeCluster.member_node_type; + $results.members = $NSXEdgeCluster.members; + $results.cluster_profile_bindings = $NSXEdgeCluster.cluster_profile_bindings + $results + } + } +} + +Function Get-NSXTLogicalRouter { + <# + .Synopsis + Retrieves the Logical Router information + .DESCRIPTION + Retrieves Logical Router information for a single or multiple LR's. This includes corresponding SR's and transport_node_id. Execute with no parameters to get all ports, specify a Logical_router_id if known. + .EXAMPLE + Get-NSXTLogicalRouter + .EXAMPLE + Get-NSXTLogicalRouter -Logical_router_id "LR ID" + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" + .EXAMPLE + (Get-NSXTLogicalRouter -Logical_router_id "LR ID").per_node_status +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$Logical_router_id + ) + + begin + { + $NSXTLogicalRoutersService = Get-NsxtService -Name "com.vmware.nsx.logical_routers" + $NSXTLogicalRoutersStatusService = Get-NsxtService -Name "com.vmware.nsx.logical_routers.status" + + class per_node_status { + $service_router_id + [ValidateSet("ACTIVE","STANDBY","DOWN","SYNC","UNKNOWN")] + $high_availability_status + $transport_node_id + + per_node_status(){} + + per_node_status( + $service_router_id, + $high_availability_status, + $transport_node_id + ) { + $this.service_router_id = $service_router_id + $this.high_availability_status = $high_availability_status + $this.transport_node_id = $transport_node_id + } + } + + class NSXTLogicalRouter { + [string]$Name + [string]$Logical_router_id + [string]$protection + hidden [string]$Tags + [string]$edge_cluster_id + [ValidateSet("TIER0","TIER1")] + [string]$router_type + [ValidateSet("ACTIVE_ACTIVE","ACTIVE_STANDBY","")] + [string]$high_availability_mode + [ValidateSet("PREEMPTIVE","NON_PREEMPTIVE","")] + [string]$failover_mode + [string]$external_transit + [string]$internal_transit + hidden [string]$advanced_config = [System.Collections.Generic.List[string]]::new() + hidden [string]$firewall_sections = [System.Collections.Generic.List[string]]::new() + $per_node_status = [System.Collections.Generic.List[string]]::new() + } + } + + Process + { + if($Logical_router_id) { + $NSXLogicalRouters = $NSXTLogicalRoutersService.get($Logical_router_id) + } else { + $NSXLogicalRouters = $NSXTLogicalRoutersService.list().results + } + + foreach ($NSXLogicalRouter in $NSXLogicalRouters) { + + $NSXTLogicalRoutersStatus = $NSXTLogicalRoutersStatusService.get($NSXLogicalRouter.id) + $results = [NSXTLogicalRouter]::new() + + foreach ($NSXTLogicalRouterStatus in $NSXTLogicalRoutersStatus.per_node_status) { + $results.per_node_status += [per_node_status]::new($NSXTLogicalRouterStatus.service_router_id,$NSXTLogicalRouterStatus.high_availability_status,$NSXTLogicalRouterStatus.transport_node_id) + } + + $results.Name = $NSXLogicalRouter.display_name; + $results.Logical_router_id = $NSXLogicalRouter.Id; + $results.protection = $NSXLogicalRouter.protection; + $results.Tags = $NSXLogicalRouter.tags; + $results.edge_cluster_id = $NSXLogicalRouter.edge_cluster_id; + $results.router_type = $NSXLogicalRouter.router_type; + $results.high_availability_mode = $NSXLogicalRouter.high_availability_mode; + $results.failover_mode =$NSXLogicalRouter.failover_mode; + $results.external_transit = $NSXLogicalRouter.advanced_config.external_transit_networks; + $results.internal_transit = $NSXLogicalRouter.advanced_config.internal_transit_network; + $results.advanced_config =$NSXLogicalRouter.advanced_config; + $results.firewall_sections =$NSXLogicalRouter.firewall_sections + $results + } + } +} + +Function Get-NSXTRoutingTable { + <# + .Synopsis + Retrieves the routing table information + .DESCRIPTION + Retrieves routing table for a single LR including LR type (SR/DR) and next_hop. Must specify Logical_router_id & transport_node_id. Pipeline input supported. + .EXAMPLE + Get-NSXTRoutingTable -Logical_router_id "LR ID" -transport_node_id "TN ID" | format-table -autosize + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" | Get-NSXTRoutingTable -transport_node_id "TN ID" + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq INT-T1 | Get-NSXTRoutingTable -transport_node_id ((Get-NSXTTransportNode | where name -match "INT")[0].transport_node_id) + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq INT-T1 | Get-NSXTRoutingTable -transport_node_id (((Get-NSXTLogicalRouter | where name -eq INT-T1).per_node_status | where high_availability_status -eq ACTIVE).transport_node_id) +#> + + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [string]$Logical_router_id, + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [string]$transport_node_id + ) + + Begin + { + $NSXTRoutingTableService = Get-NsxtService -Name "com.vmware.nsx.logical_routers.routing.route_table" + + class NSXTRoutingTable { + hidden [string]$Logical_router_id + [string]$lr_component_id + [string]$lr_component_type + [string]$network + [string]$next_hop + [string]$route_type + hidden [string]$logical_router_port_id + [long]$admin_distance + } + } + + Process + { + $NSXTRoutingTable = $NSXTRoutingTableService.list($Logical_router_id,$transport_node_id,$null,$null,$null,$null,$null,'realtime') + + foreach ($NSXTRoute in $NSXTRoutingTable.results) { + + $results = [NSXTRoutingTable]::new() + $results.Logical_router_id = $Logical_router_id; + $results.lr_component_type = $NSXTRoute.lr_component_type; + $results.lr_component_id = $NSXTRoute.lr_component_id; + $results.next_hop = $NSXTRoute.next_hop; + $results.route_type = $NSXTRoute.route_type; + $results.logical_router_port_id = $NSXTRoute.logical_router_port_id; + $results.admin_distance = $NSXTRoute.admin_distance; + $results.network = $NSXTRoute.network + $results + } + } +} + +Function Get-NSXTFabricVM { + <# + .Synopsis + Retrieves the VM's attached to the fabric. + .DESCRIPTION + Retrieves all VM's attached to the fabric. + .EXAMPLE + Get-NSXTFabricVM +#> + Begin + { + $NSXTVMService = Get-NsxtService -Name "com.vmware.nsx.fabric.virtual_machines" + + class NSXVM { + [string]$Name + $resource_type + hidden [string]$Tags + hidden $compute_ids + hidden [string]$external_id + [string]$host_id + [string]$power_state + [string]$type + hidden $source + } + } + + Process + { + + $NSXTVMs = $NSXTVMService.list().results + + foreach ($NSXTVM in $NSXTVMs) { + + $results = [NSXVM]::new() + $results.Name = $NSXTVM.display_name; + $results.resource_type = $NSXTVM.resource_type; + $results.compute_ids = $NSXTVM.compute_ids; + $results.resource_type = $NSXTVM.resource_type; + $results.Tags = $NSXTVM.tags; + $results.external_id = $NSXTVM.external_id; + $results.host_id = $NSXTVM.host_id; + $results.power_state = $NSXTVM.power_state; + $results.type = $NSXTVM.type; + $results.source = $NSXTVM.source + $results + } + } +} + +Function Get-NSXTBGPNeighbors { + <# + .Synopsis + Retrieves the BGP neighbor information + .DESCRIPTION + Retrieves BGP neighbor information for a single logical router. Must specify logical_router_id parameter. Pipeline input supported + .EXAMPLE + Get-NSXTBGPNeighbors -logical_router_id "LR ID" + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" | Get-NSXTBGPNeighbors +#> + + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$logical_router_id + ) + + begin + { + $NSXTThingsService = Get-NsxtService -Name "com.vmware.nsx.logical_routers.routing.bgp.neighbors" + + class NSXTBGPNeighbors { + [string]$Name + [string]$logical_router_id + hidden $tags = [System.Collections.Generic.List[string]]::new() + [string]$protection + [string]$resource_type + [string]$address_families = [System.Collections.Generic.List[string]]::new() + hidden $bfd_config + [bool]$enable_bfd + [bool]$enabled + hidden $filter_in_ipprefixlist_id + hidden $filter_in_routemap_id + hidden $filter_out_ipprefixlist_id + hidden $filter_out_routemap_id + hidden [long]$hold_down_timer + hidden [long]$keep_alive_timer + hidden [long]$maximum_hop_limit + [string]$neighbor_address + hidden [string]$password + [long]$remote_as + [string]$remote_as_num + [string]$source_address + [string]$source_addresses = [System.Collections.Generic.List[string]]::new() + } + } + + Process + { + $NSXTThings = $NSXTThingsService.list($logical_router_id).results + + foreach ($NSXTThing in $NSXTThings) { + + $results = [NSXTBGPNeighbors]::new() + $results.Name = $NSXTThing.display_name; + $results.logical_router_id = $NSXTThing.logical_router_id; + $results.tags = $NSXTThing.tags; + $results.protection = $NSXTThing.protection; + $results.resource_type = $NSXTThing.resource_type; + $results.address_families = $NSXTThing.address_families; + $results.bfd_config = $NSXTThing.bfd_config; + $results.enable_bfd = $NSXTThing.enable_bfd; + $results.enabled = $NSXTThing.enabled; + $results.filter_in_ipprefixlist_id = $NSXTThing.filter_in_ipprefixlist_id; + $results.filter_in_routemap_id = $NSXTThing.filter_in_routemap_id; + $results.filter_out_ipprefixlist_id = $NSXTThing.filter_out_ipprefixlist_id; + $results.filter_out_routemap_id = $NSXTThing.filter_out_routemap_id; + $results.hold_down_timer = $NSXTThing.hold_down_timer; + $results.keep_alive_timer = $NSXTThing.keep_alive_timer; + $results.maximum_hop_limit = $NSXTThing.maximum_hop_limit; + $results.neighbor_address = $NSXTThing.neighbor_address; + $results.password = $NSXTThing.password; + $results.remote_as = $NSXTThing.remote_as; + $results.remote_as_num = $NSXTThing.remote_as_num; + $results.source_address = $NSXTThing.source_address; + $results.source_addresses = $NSXTThing.source_addresses + $results + } + } +} + +Function Get-NSXTForwardingTable { + <# + .Synopsis + Retrieves the forwarding table information + .DESCRIPTION + Retrieves forwarding table for a single LR including LR type (SR/DR) and next_hop. Must specify Logical_router_id & transport_node_id. Pipeline input supported. + .EXAMPLE + Get-Get-NSXTForwardingTable -Logical_router_id "LR ID" -transport_node_id "TN ID" | format-table -autosize + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" | Get-NSXTForwardingTable -transport_node_id "TN ID" + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" | Get-NSXTForwardingTable -transport_node_id ((Get-NSXTTransportNode | where name -match "Edge Name")[0].transport_node_id) + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" | Get-NSXTForwardingTable -transport_node_id (((Get-NSXTLogicalRouter | where name -eq "Edge Name").per_node_status | where high_availability_status -eq ACTIVE).transport_node_id) +#> + + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [string]$Logical_router_id, + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [string]$transport_node_id + ) + + Begin + { + $NSXTForwardingTableService = Get-NsxtService -Name "com.vmware.nsx.logical_routers.routing.forwarding_table" + + class NSXTForwardingTable { + hidden [string]$Logical_router_id + [string]$lr_component_id + [string]$lr_component_type + [string]$network + [string]$next_hop + [string]$route_type + hidden [string]$logical_router_port_id + } + } + + Process + { + $NSXTForwardingTable = $NSXTForwardingTableService.list($Logical_router_id,$transport_node_id,$null,$null,$null,$null,$null,$null,'realtime') + + foreach ($NSXTForwarding in $NSXTForwardingTable.results) { + + $results = [NSXTForwardingTable]::new() + $results.Logical_router_id = $Logical_router_id; + $results.lr_component_type = $NSXTForwarding.lr_component_type; + $results.lr_component_id = $NSXTForwarding.lr_component_id; + $results.network = $NSXTForwarding.network; + $results.next_hop = $NSXTForwarding.next_hop; + $results.route_type = $NSXTForwarding.route_type; + $results.logical_router_port_id = $NSXTForwarding.logical_router_port_id + $results + } + } +} + +Function Get-NSXTNetworkRoutes { +<# + .Synopsis + Retrieves the network routes information + .DESCRIPTION + Retrieves the network routes information for a single or multiple routes. + .EXAMPLE + Get-NSXTNetworkRoutes + .EXAMPLE + Get-NSXTNetworkRoutes -route_id "Route ID" +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [string]$route_id + ) + + Begin + { + $NSXTNetworkRoutesService = Get-NsxtService -Name "com.vmware.nsx.node.network.routes" + + class NSXTNetworkRoutes { + [string]$route_id + $route_type + $interface_id + $gateway + $from_address + $destination + $netmask + $metric + $proto + $scope + $src + } + } + + Process + { + if ($route_id) { + $NSXTNetworkRoutes = $NSXTNetworkRoutesService.get($route_id) + } + else { + $NSXTNetworkRoutes = $NSXTNetworkRoutesService.list().results + } + + foreach ($NSXTRoute in $NSXTNetworkRoutes) { + + $results = [NSXTNetworkRoutes]::new() + $results.route_id = $NSXTRoute.route_id; + $results.route_type = $NSXTRoute.route_type; + $results.interface_id = $NSXTRoute.interface_id; + $results.gateway = $NSXTRoute.gateway; + $results.from_address = $NSXTRoute.from_address; + $results.destination = $NSXTRoute.destination; + $results.netmask = $NSXTRoute.netmask; + $results.metric = $NSXTRoute.metric; + $results.proto = $NSXTRoute.proto; + $results.scope = $NSXTRoute.scope; + $results.src = $NSXTRoute.src + $results + } + } +} + +Function Get-NSXTLogicalRouterPorts { +<# + .Synopsis + Retrieves the logical router port information + .DESCRIPTION + Retrieves logical router port information for a single or multiple ports. Execute with no parameters to get all ports, specify a single port if known, or feed a logical switch for filtered output. + .EXAMPLE + Get-NSXTLogicalRouterPorts + .EXAMPLE + Get-NSXTLogicalRouterPorts -logical_router_port_id "LR Port Name" + .EXAMPLE + Get-NSXTLogicalRouterPorts -logical_router_id "LR Name" + .EXAMPLE + Get-NSXTLogicalRouterPorts -logical_router_id (Get-NSXTLogicalRouter | where name -eq "LR Name") +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$logical_router_port_id, + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [string]$logical_router_id + ) + + begin + { + $NSXTLogicalRouterPortsService = Get-NsxtService -Name "com.vmware.nsx.logical_router_ports" + + class subnets { + $ip_addresses + $prefix_length + + subnets(){} + + subnets( + $ip_addresses, + $prefix_length + ) { + $this.ip_addresses = $ip_addresses + $this.prefix_length = $prefix_length + } + } + + class NSXTLogicalRouterPorts { + [string]$Name + $Id + [string]$logical_router_id + $resource_type + [string]$protection + $mac_address + $subnets = [System.Collections.Generic.List[string]]::new() + hidden [string]$Tags + hidden $linked_logical_switch_port_id + } + } + + Process + { + if($logical_router_port_id) { + $NSXTLogicalRouterPorts = $NSXTLogicalRouterPortsService.get($logical_router_port_id) + } else { + if ($logical_router_id) { + $NSXTLogicalRouterPorts = $NSXTLogicalRouterPortsService.list().results | where {$_.logical_router_id -eq $Logical_router_id} + } + else { + $NSXTLogicalRouterPorts = $NSXTLogicalRouterPortsService.list().results + } + } + + foreach ($NSXTLogicalRouterPort in $NSXTLogicalRouterPorts) { + + $results = [NSXTLogicalRouterPorts]::new() + + foreach ($subnet in $NSXTLogicalRouterPort.subnets) { + $results.subnets += [subnets]::new($subnet.ip_addresses,$subnet.prefix_length) + } + + $results.Name = $NSXTLogicalRouterPort.display_name + $results.Id = $NSXTLogicalRouterPort.Id + $results.Logical_router_id = $NSXTLogicalRouterPort.Logical_router_id + $results.resource_type = $NSXTLogicalRouterPort.resource_type + $results.protection = $NSXTLogicalRouterPort.protection + $results.Tags = $NSXTLogicalRouterPort.tags + $results.mac_address = $NSXTLogicalRouterPort.mac_address + $results.linked_logical_switch_port_id = $NSXTLogicalRouterPort.linked_logical_switch_port_id + $results + } + } +} + +Function Get-NSXTTransportZone { + <# + .Synopsis + Retrieves the Transport Zone information + .DESCRIPTION + Retrieves THING information for a single or multiple ports. Execute with no parameters to get all ports, specify a PARAM if known. + .EXAMPLE + Get-NSXTTransportZone + .EXAMPLE + Get-NSXTTransportZone -zone_id "Zone ID" + .EXAMPLE + Get-NSXTTransportZone -name "Zone1" +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$zone_id, + [parameter(Mandatory=$false)] + [string]$name + ) + + begin + { + $NSXTTransportZoneService = Get-NsxtService -Name "com.vmware.nsx.transport_zones" + + class NSXTTransportZone { + [string]$Name + [string]$ID + hidden [string]$description + hidden $tags + $resource_type + $host_switch_name + $transport_type + hidden $transport_zone_profile_ids + $host_switch_mode + $protection + hidden $uplink_teaming_policy_names + } + } + + Process + { + if($zone_id) { + $NSXTTransportZones = $NSXTTransportZoneService.get($zone_id) + } else { + if ($name) { + $NSXTTransportZones = $NSXTTransportZoneService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTTransportZones = $NSXTTransportZoneService.list().results + } + } + + foreach ($NSXTTransportZone in $NSXTTransportZones) { + + $results = [NSXTTransportZone]::new() + $results.Name = $NSXTTransportZone.display_name; + $results.ID = $NSXTTransportZone.Id; + $results.description = $NSXTTransportZone.description; + $results.tags = $NSXTTransportZone.tags; + $results.resource_type = $NSXTTransportZone.resource_type; + $results.host_switch_name = $NSXTTransportZone.host_switch_name; + $results.transport_type = $NSXTTransportZone.transport_type; + $results.transport_zone_profile_ids = $NSXTTransportZone.transport_zone_profile_ids; + $results.host_switch_mode = $NSXTTransportZone.host_switch_mode; + $results.protection = $NSXTTransportZone.protection; + $results.uplink_teaming_policy_names = $NSXTTransportZone.uplink_teaming_policy_names + $results + } + } +} + +Function Get-NSXTLogicalSwitch { + <# + .Synopsis + Retrieves the Logical Switch information + .DESCRIPTION + Retrieves Logical Switch information for a single or multiple switches. Execute with no parameters to get all ports, specify a name or lswitch_id if known. + .EXAMPLE + Get-NSXTLogicalSwitch + .EXAMPLE + Get-NSXTLogicalSwitch -lswitch_id "switch id" + .EXAMPLE + Get-NSXTLogicalSwitch -name "switch name" +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$lswitch_id, + [parameter(Mandatory=$false)] + [string]$name + ) + + begin + { + $NSXTLogicalSwitchService = Get-NsxtService -Name "com.vmware.nsx.logical_switches" + + class NSXTLogicalSwitch { + [string]$Name + [string]$ID + $tags + $resource_type + hidden $description + $vni + $transport_zone_id + $admin_state + $replication_mode + hidden $address_bindings + $protection + hidden $extra_configs + $ip_pool_id + hidden $mac_pool_id + hidden $uplink_teaming_policy_name + hidden $vlan + hidden $vlan_trunk_spec + } + } + + Process + { + if($lswitch_id) { + $NSXTLogicalSwitches = $NSXTLogicalSwitchService.get($lswitch_id) + } else { + if ($name) { + $NSXTLogicalSwitches = $NSXTLogicalSwitchService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTLogicalSwitches = $NSXTLogicalSwitchService.list().results + } + } + + foreach ($NSXTLogicalSwitch in $NSXTLogicalSwitches) { + + $results = [NSXTLogicalSwitch]::new() + $results.Name = $NSXTLogicalSwitch.display_name; + $results.Id = $NSXTLogicalSwitch.Id; + $results.Tags = $NSXTLogicalSwitch.tags; + $results.resource_type = $NSXTLogicalSwitch.resource_type; + $results.description = $NSXTLogicalSwitch.description; + $results.vni = $NSXTLogicalSwitch.vni; + $results.transport_zone_id = $NSXTLogicalSwitch.transport_zone_id; + $results.admin_state = $NSXTLogicalSwitch.admin_state; + $results.replication_mode = $NSXTLogicalSwitch.replication_mode; + $results.address_bindings = $NSXTLogicalSwitch.address_bindings; + $results.protection = $NSXTLogicalSwitch.protection; + $results.extra_configs = $NSXTLogicalSwitch.extra_configs; + $results.ip_pool_id = $NSXTLogicalSwitch.ip_pool_id; + $results.mac_pool_id = $NSXTLogicalSwitch.mac_pool_id; + $results.uplink_teaming_policy_name = $NSXTLogicalSwitch.uplink_teaming_policy_name; + $results.vlan = $NSXTLogicalSwitch.vlan; + $results.vlan_trunk_spec = $NSXTLogicalSwitch.vlan_trunk_spec + $results + } + } +} + +Function Get-NSXTIPPool { + <# + .Synopsis + Retrieves the THING information + .DESCRIPTION + Retrieves THING information for a single or multiple ports. Execute with no parameters to get all ports, specify a PARAM if known. + .EXAMPLE + Get-NSXTIPPool + .EXAMPLE + Get-NSXTThingTemplate -pool_id "Pool ID" +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$pool_id, + [parameter(Mandatory=$false)] + [string]$name + ) + + begin + { + $NSXTIPPoolService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_pools" + + class NSXTIPPool { + [string]$Name + [string]$id + $total_ids + $free_ids + $allocated_ids + $Network + $Gateway + $DNS + $RangeStart + $RangeEnd + } + } + + Process + { + if($pool_id) { + $NSXTIPPools = $NSXTIPPoolService.get($pool_id) + } else { + if ($name) { + $NSXTIPPools = $NSXTIPPoolService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTIPPools = $NSXTIPPoolService.list().results + } + } + + foreach ($NSXTIPPool in $NSXTIPPools) { + + $results = [NSXTIPPool]::new() + $results.Name = $NSXTIPPool.display_name; + $results.ID = $NSXTIPPool.id; + $results.total_ids = $NSXTIPPool.pool_usage.total_ids; + $results.free_ids = $NSXTIPPool.pool_usage.free_ids; + $results.allocated_ids = $NSXTIPPool.pool_usage.allocated_ids; + $results.Network = $NSXTIPPool.subnets.cidr; + $results.Gateway = $NSXTIPPool.subnets.gateway_ip; + $results.DNS = $NSXTIPPool.subnets.dns_nameservers; + $results.RangeStart = $NSXTIPPool.subnets.allocation_ranges.start; + $results.RangeEnd = $NSXTIPPool.subnets.allocation_ranges.end + $results + } + } +} + +Function Get-NSXTIPAMIPBlock { + <# + .Synopsis + Retrieves the IPAM IP Block information + .DESCRIPTION + Retrieves IPAM IP Block information for a single or multiple ports. Execute with no parameters to get all ports, specify a PARAM if known. + .EXAMPLE + Get-NSXTIPAMIPBlock + .EXAMPLE + Get-NSXTIPAMIPBlock -block_id "Block Id" + .EXAMPLE + Get-NSXTIPAMIPBlock -name "Block Name" + +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$block_id, + [parameter(Mandatory=$false)] + [string]$name + ) + + begin + { + $NSXTIPAMIPBlocksService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_blocks" + + class ip_block { + [string]$Name + [string]$block_id + hidden [string]$Tags = [System.Collections.Generic.List[string]]::new() + [string]$protection + #[ValidateSet("TIER0","TIER1")] + [string]$cidr + hidden [string]$resource_type + } + } + + Process + { + if($block_id) { + $NSXTIPAMIPBlocks = $NSXTIPAMIPBlocksService.get($block_id) + } else { + if ($name) { + $NSXTIPAMIPBlocks = $NSXTIPAMIPBlocksService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTIPAMIPBlocks = $NSXTIPAMIPBlocksService.list().results + } + } + + foreach ($NSXTIPAMIPBlock in $NSXTIPAMIPBlocks) { + + $results = [ip_block]::new() + $results.Name = $NSXTIPAMIPBlock.display_name; + $results.block_id = $NSXTIPAMIPBlock.id; + $results.Tags = $NSXTIPAMIPBlock.tags; + $results.protection = $NSXTIPAMIPBlock.protection; + $results.cidr = $NSXTIPAMIPBlock.cidr; + $results.resource_type = $NSXTIPAMIPBlock.resource_type + + $results + } + } +} + +Function Get-NSXTClusterNode { + <# + .Synopsis + Retrieves the cluster node information + .DESCRIPTION + Retrieves cluster node information including manager and controller nodes. + .EXAMPLE + Get-NSXTClusterNode + .EXAMPLE + Get-NSXTClusterNode -node_id "Node Id" + .EXAMPLE + Get-NSXTClusterNode -name "Name" +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$node_id, + [parameter(Mandatory=$false)] + [string]$name + ) + + begin + { + $NSXTClusterNodesService = Get-NsxtService -Name "com.vmware.nsx.cluster.nodes" + + class NSXTClusterNode { + [string]$Name + [string]$node_id + hidden [array]$Tags = [System.Collections.Generic.List[string]]::new() + hidden [string]$controller_role + hidden [array]$manager_role + [string]$protection + [string]$appliance_mgmt_listen_addr + hidden [string]$external_id + hidden [string]$description + [string]$role + } + } + + Process + { + if($node_id) { + $NSXTThings = $NSXTClusterNodesService.get($node_id) + } else { + if ($name) { + $NSXTClusterNodes = $NSXTClusterNodesService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTClusterNodes = $NSXTClusterNodesService.list().results + } + } + + foreach ($NSXTClusterNode in $NSXTClusterNodes) { + + $results = [NSXTClusterNode]::new() + $results.Name = $NSXTClusterNode.display_name; + $results.node_id = $NSXTClusterNode.Id; + $results.Tags = $NSXTClusterNode.tags; + $results.controller_role = $NSXTClusterNode.controller_role; + $results.manager_role = $NSXTClusterNode.manager_role; + $results.protection = $NSXTClusterNode.protection; + $results.appliance_mgmt_listen_addr = $NSXTClusterNode.appliance_mgmt_listen_addr; + $results.external_id = $NSXTClusterNode.external_id; + $results.description = $NSXTClusterNode.description + + if ($NSXTClusterNode.manager_role -ne $null) { + $results.role = "Manager" + } + elseif ($NSXTClusterNode.controller_role -ne $null) { + $results.role = "Controller" + } + + $results + } + } +} + +# Working Set Functions +Function Set-NSXTLogicalRouter { + <# + .Synopsis + Creates a Logical Router + .DESCRIPTION + Create a TIER0 or TIER1 logical router + .EXAMPLE + Set-NSXTLogicalRouter -display_name "Name" -high_availability_mode "ACTIVE_STANDBY" -router_type "TIER1" + .EXAMPLE + Set-NSXTLogicalRouter -display_name "Name" -high_availability_mode "ACTIVE_ACTIVE" -router_type "TIER0" -edge_cluster_id "Edge Cluster ID" + .EXAMPLE + Set-NSXTLogicalRouter -display_name "Name" -high_availability_mode "ACTIVE_STANDBY" -router_type "TIER1" -description "this is my new tier1 lr" +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='Medium')] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$false, + ParameterSetName='TIER0')] + [parameter(Mandatory=$false, + ParameterSetName='TIER1')] + [string]$description, + + [parameter(Mandatory=$true, + ParameterSetName='TIER0')] + [parameter(Mandatory=$true, + ParameterSetName='TIER1')] + [string]$display_name, + + [parameter(Mandatory=$true, + ParameterSetName='TIER0')] + [parameter(Mandatory=$true, + ParameterSetName='TIER1')] + [ValidateSet("ACTIVE_ACTIVE","ACTIVE_STANDBY")] + [string]$high_availability_mode, + + [parameter(Mandatory=$true, + ParameterSetName='TIER0')] + [parameter(Mandatory=$true, + ParameterSetName='TIER1')] + [ValidateSet("TIER0","TIER1")] + [string]$router_type, + + [parameter(Mandatory=$true, + ParameterSetName='TIER0')] + [string]$edge_cluster_id + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTLogicalRouterService = Get-NsxtService -Name "com.vmware.nsx.logical_routers" + } + + Process + { + $logical_router_request = $NSXTLogicalRouterService.help.create.logical_router.Create() + + $logical_router_request.display_name = $display_name + $logical_router_request.description = $description + $logical_router_request.router_type = $router_type + $logical_router_request.high_availability_mode = $high_availability_mode + $logical_router_request.resource_type = "LogicalRouter" + $logical_router_request.failover_mode = "NON_PREEMPTIVE" + + if ($edge_cluster_id) { + $logical_router_request.edge_cluster_id = $edge_cluster_id + } + + try + { + # Should process + if ($pscmdlet.ShouldProcess($logical_router_request.display_name, "Create logical router")) + { + $NSXTLogicalRouter = $NSXTLogicalRouterService.create($logical_router_request) + } + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + + $NSXTLogicalRouter + } +} + +Function Set-NSXTLogicalSwitch { + <# + .Synopsis + Creates a Logical Switch + .DESCRIPTION + Creates a Logical Switch with a number of required parameters. IP Pool is necessary even for an overlay logical switch + .EXAMPLE + Set-NSXTLogicalSwitch -display_name "Name" -transport_zone_id "TP Zone ID" + .EXAMPLE + Set-NSXTLogicalSwitch -display_name "Name" -transport_zone_id "TP Zone ID" -admin_state "UP" -replication_mode "MTEP" -ip_pool_id "IP Pool Name" +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='Medium')] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$false)] + [string]$description, + + [parameter(Mandatory=$true)] + [string]$display_name, + + [parameter(Mandatory=$true)] + [string]$transport_zone_id, + + [parameter(Mandatory=$true)] + [ValidateSet("UP","DOWN")] + [string]$admin_state, + + [parameter(Mandatory=$false)] + [ValidateSet("MTEP","SOURCE")] + [string]$replication_mode, + + [parameter(Mandatory=$true)] + [string]$ip_pool_id + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTLogicalSwitchService = Get-NsxtService -Name "com.vmware.nsx.logical_switches" + } + + Process + { + $logical_switch_request = $NSXTLogicalSwitchService.help.create.logical_switch.Create() + + $logical_switch_request.display_name = $display_name + $logical_switch_request.description = $description + $logical_switch_request.admin_state = $admin_state + $logical_switch_request.transport_zone_id = $transport_zone_id + $logical_switch_request.resource_type = "LogicalSwitch" + $logical_switch_request.replication_mode = $replication_mode + $logical_switch_request.ip_pool_id = $ip_pool_id + + try + { + # Should process + if ($pscmdlet.ShouldProcess($logical_switch_request.display_name, "Create logical switch")) + { + $NSXTLogicalSwitch = $NSXTLogicalSwitchService.create($logical_switch_request) + } + + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + + $NSXTLogicalSwitch + } +} + +Function Set-NSXTIPAMIPBlock { + <# + .Synopsis + Creates an IPAM IP Block + .DESCRIPTION + Creates a IPAM IP Block with a cidr parameter. + .EXAMPLE + Set-NSXTIPAMIPBlock -name "IPAM Block Name" -cidr "192.168.0.0/24" +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='Medium')] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$false)] + [string]$description, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$display_name, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$cidr + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTIPAMIPBlockService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_blocks" + } + + Process + { + $IPAMIPBlock_request = $NSXTIPAMIPBlockService.help.create.ip_block.Create() + + $IPAMIPBlock_request.display_name = $display_name + $IPAMIPBlock_request.description = $description + $IPAMIPBlock_request.resource_type = "IpBlock" + $IPAMIPBlock_request.cidr = $cidr + + + try + { + # Should process + if ($pscmdlet.ShouldProcess($ip_pool.display_name, "Create IP Pool")) + { + $NSXTIPAMIPBlock = $NSXTIPAMIPBlockService.create($IPAMIPBlock_request) + } + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + + $NSXTIPAMIPBlock + } +} + +Function Set-NSXTIPPool { + <# + .Synopsis + Creates an IP Pool + .DESCRIPTION + Creates a IP Pool with a number of required parameters. Supported IP formats include 192.168.1.1, 192.168.1.1-192.168.1.100, 192.168.0.0/24 + .EXAMPLE + Set-NSXTIPPool -display_name "Pool Name" -allocation_start "192.168.1.2" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" + .EXAMPLE + Set-NSXTIPPool -display_name "Test Pool Name" -allocation_start "192.168.1.2" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" -dns_nameservers "192.168.1.1" -gateway_ip "192.168.1.1" -dns_suffix "evil corp" +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='High')] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$display_name, + + [parameter(Mandatory=$false)] + [string]$description, + + [parameter(Mandatory=$false)] + [string]$dns_nameservers, + + [parameter(Mandatory=$false)] + [string]$dns_suffix, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$allocation_start, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$allocation_end, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$cidr, + + [parameter(Mandatory=$false)] + [string]$gateway_ip + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTIPPoolService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_pools" + + # Classes unused - part of early testing + class allocation_ranges { + [string]$start + [string]$end + #$self + } + + class subnets { + [array]$allocation_ranges = [allocation_ranges]::new() + [array]$dns_nameservers + [string]$dns_suffix + [string]$cidr + [string]$gateway_ip + #hidden $self + } + + class ip_pool { + [string]$display_name + [string]$description + [string]$resource_type = 'IpPool' + [long]$revision = '0' + [array]$subnets = [subnets]::new() + hidden $pool_usage + hidden [array]$tags + # hidden $self + hidden $links + } + } + + Process + { + $sample_ip_pool = $NSXTIPPoolService.help.create.ip_pool.Create() + $sample_ip_pool.subnets = @($NSXTIPPoolService.help.create.ip_pool.subnets.Create()) + $sample_ip_pool.subnets = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.Create()) + $sample_ip_pool.subnets[0].allocation_ranges = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.create()) + $sample_ip_pool.subnets[0].allocation_ranges = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.element.create()) + + #Remove buggy self object + $ip_pool = $sample_ip_pool | select -Property * -ExcludeProperty self + $ip_pool.subnets[0] = $sample_ip_pool.subnets[0] | select -Property * -ExcludeProperty self + $ip_pool.subnets[0].allocation_ranges[0] = $sample_ip_pool.subnets[0].allocation_ranges[0] | select -Property * -ExcludeProperty self + + # Assign objects + $ip_pool.display_name = $display_name + $ip_pool.description = $description + $ip_pool.resource_type = "IpPool" + $ip_pool.subnets[0].dns_nameservers = @($dns_nameservers) + $ip_pool.subnets[0].dns_suffix = $dns_suffix + $ip_pool.subnets[0].allocation_ranges[0].start = $allocation_start + $ip_pool.subnets[0].allocation_ranges[0].end = $allocation_end + $ip_pool.subnets[0].cidr = $cidr + $ip_pool.subnets[0].gateway_ip = $gateway_ip + $ip_pool.revision = 0 + $ip_pool.tags = @() + + try + { + # Should process + if ($pscmdlet.ShouldProcess($ip_pool.display_name, "Create IP Pool")) + { + $NSXTIPPoolService.create($ip_pool) + } + } + + catch + { + $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file; grep POOL-MGMT + throw + } + } +} + +# Remove functions +Function Remove-NSXTIPAMIPBlock { + <# + .Synopsis + Removes an IPAM IP Block + .DESCRIPTION + Removes a IPAM IP Block with a block_id parameter. + .EXAMPLE + Remove-NSXTIPAMIPBlock -block_id "id" + .EXAMPLE + Get-NSXTIPAMIPBlock | where name -eq "IPAM Test2" | Remove-NSXTIPAMIPBlock +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='High')] + + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [ValidateNotNullOrEmpty()] + [Alias("Id")] + [string]$block_id + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTIPAMIPBlockService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_blocks" + } + + Process + { + try + { + # Should process + if ($pscmdlet.ShouldProcess($block_id, "Delete IP Pool")) + { + $NSXTIPAMIPBlockService.delete($block_id) + } + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + } +} + +# Non-working Set Functions +Function Set-NSXTTraceFlow { + <# + .Synopsis + Creates a TraceFlow + .DESCRIPTION + Create a TraceFlow for later observation. + .EXAMPLE + Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" + .EXAMPLE + Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" | Get-NSXTTraceFlow + .EXAMPLE + Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" | Get-NSXTTraceFlow | Get-NSXTTraceFlowObservations +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='Medium')] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateSet("UNICAST")] + [string] + $transport_type = "UNICAST", + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + #[ValidateScript({Get-NSXTLogicalPort -Id $_}] + [string] + $lport_id, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$_ -match [IPAddress]$_})] + [string] + $src_ip, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$pattern = '^(([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2}))|(([0-9A-Fa-f]{2}[-]){5}([0-9A-Fa-f]{2}))$' + if ($_ -match ($pattern -join '|')) {$true} else { + throw "The argument '$_' does not match a valid MAC address format." + } + })] + [string] + $src_mac, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$_ -match [IPAddress]$_ })] + [string] + $dst_ip, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$pattern = '^(([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2}))|(([0-9A-Fa-f]{2}[-]){5}([0-9A-Fa-f]{2}))$' + if ($_ -match ($pattern -join '|')) {$true} else { + throw "The argument '$_' does not match a valid MAC address format." + } + })] + [string] + $dst_mac) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTraceFlowsService = Get-NsxtService -Name "com.vmware.nsx.traceflows" + + # Comment out custom classes + <# + class ip_header { + [string]$src_ip + [string]$dst_ip + } + + class eth_header { + [string]$src_mac + [string]$dst_mac + } + + class packet_data { + [boolean]$routed + [ValidateSet("UNICAST","BROADCAST","MULTICAST","UNKNOWN")] + [string]$transport_type + [ValidateSet("BINARYPACKETDATA","FIELDSPACKETDATA")] + [string]$resource_type + [long]$frame_size + [eth_header]$eth_header = [eth_header]::new() + [ip_header]$ip_header = [ip_header]::new() + + packet_data(){ + $this.routed = 'true' + $this.transport_type = 'UNICAST' + $this.resource_type = 'FieldsPacketData' + } + } + + class traceflow_request { + [string]$lport_id + [long]$timeout + [packet_data]$packet = [packet_data]::new() + + traceflow_request(){ + $this.timeout = '15000' + } + } +#> + } + + Process + { + $traceflow_request = $NSXTraceFlowsService.Help.create.traceflow_request.Create() + + $traceflow_request.lport_id = $lport_id + $traceflow_request.packet.transport_type = $transport_type + + $eth_header = [ordered]@{'src_mac' = $src_mac;'eth_type' = '2048';'dst_mac' = $dst_mac} + $ip_header = [ordered]@{src_ip = $src_ip;protocol = '1';ttl = '64';dst_ip = $dst_ip} + $traceflow_request.packet | Add-Member -NotePropertyMembers $eth_header -TypeName eth_header + $traceflow_request.packet | Add-Member -NotePropertyMembers $ip_header -TypeName ip_header + + try + { + # Should process + if ($pscmdlet.ShouldProcess($traceflow_request.lport_id, "Create traceflow")) + { + # This does not work, bug report submitted to PowerCLI team + $NSXTraceFlow = $NSXTraceFlowService.create($traceflow_request) + } + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. Filter by MONITORING. + } + + $NSXTraceFlow + } +} + + + +########################### +# # +# TEMPLATES!! # +# # +########################### + +# Get Template +Function Get-NSXTThingTemplate { + <# + .Synopsis + Retrieves the THING information + .DESCRIPTION + Retrieves THING information for a single or multiple ports. Execute with no parameters to get all ports, specify a PARAM if known. + .EXAMPLE + Get-NSXTThingTemplate + .EXAMPLE + Get-NSXTThingTemplate -param1 "LR Port Name" + .EXAMPLE + Get-NSXTThingTemplate -param2 "LR Name" + .EXAMPLE + Get-NSXTThingTemplate -param2 (Get-NSXTLogicalRouter | where name -eq "LR Name") +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$Thing_id, + [parameter(Mandatory=$false)] + [string]$name + ) + + begin + { + $NSXTThingsService = Get-NsxtService -Name "com.vmware.nsx.API.Thing" + + class NSXTThing { + [string]$Name + [string]$Thing1 + hidden [string]$Tags = [System.Collections.Generic.List[string]]::new() + [string]$Thing2 + #[ValidateSet("TIER0","TIER1")] + [string]$Thing3 + #[ValidateSet("ACTIVE_ACTIVE","ACTIVE_STANDBY","")] + [string]$Thing4 + #[ValidateSet("PREEMPTIVE","NON_PREEMPTIVE","")] + [string]$Thing5 + [string]$Thing6 + [string]$Thing7 + } + } + + Process + { + if($Thing_id) { + $NSXTThings = $NSXTThingsService.get($Thing_id) + } else { + if ($name) { + $NSXTThings = $NSXTThingsService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTThings = $NSXTThingsService.list().results + } + } + + foreach ($NSXTThing in $NSXTThings) { + + $results = [NSXTThing]::new() + $results.Name = $NSXTThing.display_name; + $results.Logical_router_id = $NSXTThing.Id; + $results.Tags = $NSXTThing.tags; + $results.thing1 = $NSXTThing.thing1; + $results.thing2 = $NSXTThing.thing2 + + $results + } + } +} + +# Set Template +Function Set-NSXTThingTemplate { + <# + .Synopsis + Creates a THING + .DESCRIPTION + Creates a THING with a number of required parameters. + .EXAMPLE + Set-NSXTThingTemplateh -param1 "Name" -param2 "TP Zone ID" + .EXAMPLE + Set-NSXTThingTemplateh -param1 "Name" -param2 "TP Zone ID" +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='Medium')] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$false)] + [string]$description, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$display_name, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$transport_zone_id, + + [parameter(Mandatory=$true)] + [ValidateSet("UP","DOWN")] + [string]$admin_state, + + [parameter(Mandatory=$false)] + [ValidateSet("MTEP","SOURCE")] + [string]$replication_mode, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$ip_pool_id + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTTHINGService = Get-NsxtService -Name "com.vmware.nsx.THING" + } + + Process + { + $logical_THING_request = $NSXTTHINGService.help.create.logical_switch.Create() + + $logical_THING_request.display_name = $display_name + $logical_THING_request.description = $description + $logical_THING_request.admin_state = $admin_state + $logical_THING_request.transport_zone_id = $transport_zone_id + $logical_THING_request.resource_type = "LogicalSwitch" + $logical_THING_request.replication_mode = $replication_mode + $logical_THING_request.ip_pool_id = $ip_pool_id + + try + { + # Should process + if ($pscmdlet.ShouldProcess($ip_pool.display_name, "Create IP Pool")) + { + $NSXTTHING = $NSXTTHINGService.create($logical_THING_request) + } + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + + $NSXTTHING + } +} + +# Remove Template +Function Remove-NSXTThingTemplate { + <# + .Synopsis + Removes an IPAM IP Block + .DESCRIPTION + Removes a IPAM IP Block with a block_id parameter. + .EXAMPLE + Remove-NSXTIPAMIPBlock -block_id "id" +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='High')] + + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [ValidateNotNullOrEmpty()] + [Alias("Id")] + [string]$thing_id + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTTHINGkService = Get-NsxtService -Name "com.vmware.nsx.THING" + } + + Process + { + try + { + # Should process + if ($pscmdlet.ShouldProcess($thing_id, "Delete IP Pool")) + { + $NSXTTHINGkService.delete($thing_id) + } + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + } +} + + + diff --git a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psd1 b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psd1 new file mode 100644 index 0000000..b20f2de --- /dev/null +++ b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psd1 @@ -0,0 +1,123 @@ +# +# Module manifest for module 'VMware.Community.CISTag' +# +# Generated by: Kyle Ruddy +# +# Generated on: 12/14/18 +# + +@{ + +# Script module or binary module file associated with this manifest. +RootModule = 'VMware.Community.CISTag.psm1' + +# Version number of this module. +ModuleVersion = '1.0.0' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = 'a0803efd-6017-4049-bfc9-5983a5a0c348' + +# Author of this module +Author = 'Kyle Ruddy' + +# Company or vendor of this module +CompanyName = 'VMware' + +# Copyright statement for this module +Copyright = '(c) VMware. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'Community sourced PowerShell Module for managing vSphere Tags via the CIS Endpoint' + +# Minimum version of the PowerShell engine required by this module +PowerShellVersion = '4.0' + +# 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 = @() + +# 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 = 'Get-CISTag', 'Get-CISTagCategory', 'Get-CISTagAssignment', 'New-CISTag', 'New-CISTagCategory', 'New-CISTagAssignment', 'Remove-CISTag', 'Remove-CISTagCategory', 'Remove-CISTagAssignment' + +# 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 = '' + + } # 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 = '' + +} + diff --git a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 new file mode 100644 index 0000000..05594e4 --- /dev/null +++ b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 @@ -0,0 +1,705 @@ +function Get-CISTag { +<# +.SYNOPSIS + Gathers tag information from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of tags +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag name which should be retreived +.PARAMETER Category + Tag category name which should be retreived +.PARAMETER Id + Tag ID which should be retreived +.EXAMPLE + Get-CISTag + Retreives all tag information +.EXAMPLE + Get-CISTag -Name tagName + Retreives the tag information based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1,ValueFromPipelineByPropertyName=$true)] + [String]$Category, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$Id + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + if ($PSBoundParameters.ContainsKey("Id")) { + $tagOutput = $tagSvc.get($Id) + } else { + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + [Boolean]$vCenterConn = $true + $vCTagList = Get-Tag + } else { + $tagArray = @() + $tagIdList = $tagSvc.list() | Select-Object -ExpandProperty Value + [integer]$counter = 1 + foreach ($t in $tagIdList) { + $tagArray += $tagSvc.get($t) + $counter++ + if ($counter -gt 200) {Start-Sleep -Milliseconds 1; $counter = 1} + } + } + if ($PSBoundParameters.ContainsKey("Name")) { + if ($vCenterConn){ + $tagOutput = $vCTagList | where {$_.Name -eq $Name} + } else {$tagOutput = $tagArray | Where {$_.Name -eq $Name}} + } elseif ($PSBoundParameters.ContainsKey("Category")) { + if ($vCenterConn){ + $tagOutput = $vCTagList | where {$_.Category -eq $Category} + } else { + $tagCatid = Get-CISTagCategory -Name $Category | Select-Object -ExpandProperty Id + $tagIdList = $tagSvc.list_tags_for_category($tagCatid) + $tagArray2 = @() + foreach ($t in $tagIdList) { + $tagArray2 += $tagSvc.get($t) + } + $tagOutput = $tagArray2 + } + } else { + if ($vCenterConn){$tagOutput = $vCTagList} + else {$tagOutput = $tagArray} + } + } + $tagOutput | Select-Object Id, Name, Description + } + +} + +function New-CISTag { +<# +.SYNOPSIS + Creates a new tag from the CIS REST API endpoint +.DESCRIPTION + Will create a new tag +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag name which should be created +.PARAMETER Category + Category name where the new tag should be associated +.PARAMETER Description + Description for the new tag +.PARAMETER CategoryID + Category ID where the new tag should be associated +.EXAMPLE + New-CISTag -Name tagName -Category categoryName -Description "Tag Descrition" + Creates a new tag based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory=$true,Position=0)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1)] + [String]$Category, + [Parameter(Mandatory=$false,Position=2)] + [String]$Description, + [Parameter(Mandatory=$false,Position=3)] + [String]$CategoryID + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + $tagCreateHelper = $tagSvc.Help.create.create_spec.Create() + $tagCreateHelper.name = $Name + if ($PSBoundParameters.ContainsKey("Category")) { + $tagCreateHelper.category_id = Get-CISTagCategory -Name $Category | Select-Object -ExpandProperty Id + } elseif ($PSBoundParameters.ContainsKey("CategoryId")) { + $tagCreateHelper.category_id = $CategoryID + } else {Write-Warning "No Category input found. Add a Category name or ID."; break} + if ($PSBoundParameters.ContainsKey("Description")) { + $tagCreateHelper.description = $Description + } else { + $tagCreateHelper.description = "" + } + $tagNewId = $tagSvc.create($tagCreateHelper) + Get-CISTag -Id $tagNewId + } + +} + +function Remove-CISTag { +<# +.SYNOPSIS + Removes a tag from the CIS REST API endpoint +.DESCRIPTION + Will delete a new tag +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag name which should be removed +.PARAMETER ID + Tag ID which should be removed +.EXAMPLE + Remove-CISTag -Name tagName + Removes a new tag based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1,ValueFromPipelineByPropertyName=$true)] + [String]$ID + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + if ($ID) { + $tagSvc.delete($ID) + } else { + $tagId = Get-CISTag -Name $Name | select -ExpandProperty Id + if ($tagId) {$tagSvc.delete($tagId)} + else {Write-Warning "No valid tag found."} + } + } +} + +function Get-CISTagCategory { +<# +.SYNOPSIS + Gathers tag category information from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of tag categories +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag category name which should be retreived +.PARAMETER Id + Tag category ID which should be retreived +.EXAMPLE + Get-CISTagCategory + Retreives all tag category information +.EXAMPLE + Get-CISTagCategory -Name tagCategoryName + Retreives the tag category information based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$Id + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagCatSvc = Get-CisService -Name com.vmware.cis.tagging.category + if ($PSBoundParameters.ContainsKey("Id")) { + $tagCatOutput = $tagCatSvc.get($Id) + } else { + $tagCatArray = @() + $tagCatIdList = $tagCatSvc.list() | Select-Object -ExpandProperty Value + foreach ($tc in $tagCatIdList) { + $tagCatArray += $tagCatSvc.get($tc) + } + if ($PSBoundParameters.ContainsKey("Name")) { + $tagCatOutput = $tagCatArray | Where {$_.Name -eq $Name} + } else { + $tagCatOutput = $tagCatArray + } + } + $tagCatOutput | Select-Object Id, Name, Description, Cardinality + } + +} + +function New-CISTagCategory { +<# +.SYNOPSIS + Creates a new tag category from the CIS REST API endpoint +.DESCRIPTION + Will create a new tag category +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag category name which should be created +.PARAMETER Description + Tag category ID which should be retreived +.PARAMETER Cardinality + Tag category ID which should be retreived +.PARAMETER AssociableTypes + Tag category ID which should be retreived +.EXAMPLE + New-CISTagCategory -Name NewTagCategoryName -Description "New Tag Category Description" -Cardinality "Single" -AssociableTypes + Creates a new tag category with the specified information +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory=$true,Position=0)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1)] + [String]$Description, + [Parameter(Mandatory=$false,Position=2)] + [ValidateSet("SINGLE","MULTIPLE")] + [String]$Cardinality = "SINGLE", + [Parameter(Mandatory=$false,Position=3)] + [ValidateSet("All", "Cluster", "Datacenter", "Datastore", "DatastoreCluster", "DistributedPortGroup", "DistributedSwitch", "Folder", "ResourcePool", "VApp", "VirtualPortGroup", "VirtualMachine", "VMHost")] + [String]$AssociableTypes = "All" + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagCatSvc = Get-CisService -Name com.vmware.cis.tagging.category + $tagCatCreateHelper = $tagCatSvc.Help.create.create_spec.Create() + $tagCatCreateHelper.name = $Name + if ($PSBoundParameters.ContainsKey("Description")) { + $tagCatCreateHelper.description = $Description + } else {$tagCatCreateHelper.description = ""} + $tagCatCreateHelper.cardinality = $Cardinality + $tagCatCreateAssocTypeHelper = $tagCatSvc.help.create.create_spec.associable_types.create() + $tagCatCreateAssocTypeHelper.Add($AssociableTypes) + $tagCatCreateHelper.associable_types = $tagCatCreateAssocTypeHelper + $tagCatNewId = $tagCatSvc.create($tagCatCreateHelper) + Get-CISTagCategory -Id $tagCatNewId + } + +} + +function Remove-CISTagCategory { +<# +.SYNOPSIS + Removes tag category information from the CIS REST API endpoint +.DESCRIPTION + Will remove a tag category +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag category name which should be removed +.PARAMETER Id + Tag category ID which should be removed +.EXAMPLE + Remove-CISTagCategory -Name tagCategoryName + Removes the tag category information based on the specified name + +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$Id + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagCatSvc = Get-CisService -Name com.vmware.cis.tagging.category + if ($PSBoundParameters.ContainsKey("Id")) { + $tagCatSvc.delete($Id) + } elseif ($PSBoundParameters.ContainsKey("Name")) { + $tagCatId = Get-CISTagCategory -Name $Name | Select-Object -ExpandProperty Id + $tagCatSvc.delete($tagCatId) + } else {Write-Warning "No tag category found."} + } +} + +function Get-CISTagAssignment { +<# +.SYNOPSIS + Displays a list of the tag assignments from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of the tag assignments +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Category + Tag category name which should be referenced +.PARAMETER Entity + Object name which should be retreived +.PARAMETER ObjectId + Object ID which should be retreived +.EXAMPLE + Get-CISTagAssignment + Retreives all tag assignment information +.EXAMPLE + Get-CISTagAssignment -Entity VMName + Retreives all tag assignments for the VM name +.EXAMPLE + Get-CISTagAssignment -ObjectId 'vm-11' + Retreives all tag assignments for the VM object +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')] + param( + [Parameter(Mandatory=$false,Position=0)] + [String]$Category, + [Parameter(Mandatory=$false,Position=1)] + [String]$Entity, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$ObjectId + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagOutput = @() + [Boolean]$vCenterConn = $false + $tagAssocSvc = Get-CisService -Name com.vmware.cis.tagging.tag_association + if ($PSBoundParameters.ContainsKey("ObjectId")) { + if ($ObjectId.split('-')[0] -eq 'vm') { + $objType = 'VirtualMachine' + } else {Write-Warning 'Only VirtualMachine types currently supported.'; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagIdOutput = $tagAssocSvc.list_attached_tags($objObject) + } elseif ($PSBoundParameters.ContainsKey("Entity")) { + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + [Boolean]$vCenterConn = $true + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagIdOutput = $tagAssocSvc.list_attached_tags($objObject) + } else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + $tagIdOutput = @() + $tagCategories = Get-CISTagCategory | Sort-Object -Property Name + if ($Category) { + $tagCatId = $tagCategories | where {$_.Name -eq $Category} | Select-Object -ExpandProperty Id + $tagIdOutput += $tagSvc.list_tags_for_category($tagCatId) + } else { + foreach ($tagCat in $tagCategories) { + $tagIdOutput += $tagSvc.list_tags_for_category($tagCat.id) + } + } + } + $tagReference = Get-CISTag + + if ($Entity -or $ObjectId) { + foreach ($tagId in $tagIdOutput) { + $tagAttObj = @() + if ($Entity) { + $tagAttObj += $tagAssocSvc.list_attached_objects($tagId) | where {$_.type -eq $viObject.type -and $_.id -eq $viObject.Value} + } else { + $tagAttObj += $tagAssocSvc.list_attached_objects($tagId) | where {$_.id -eq $ObjectId} + } + foreach ($obj in $tagAttObj) { + if ($obj.type -eq "VirtualMachine") { + if (-Not $vmSvc) {$vmSvc = Get-CisService -Name com.vmware.vcenter.vm} + $filterVmObj = $vmsvc.help.list.filter.create() + $filterVmObj.vms.add($obj.Id) | Out-Null + $objName = $vmSvc.list($filterVmObj) | Select-Object -ExpandProperty Name + } + else {$objName = 'Object Not Found'} + $tempObject = "" | Select-Object Tag, Entity + $tempObject.Tag = $tagReference | where {$_.id -eq $tagId} | Select-Object -ExpandProperty Name + $tempObject.Entity = $objName + $tagOutput += $tempObject + } + } + } else { + foreach ($tagId in $tagIdOutput) { + $tagAttObj = @() + $tagAttObj += $tagAssocSvc.list_attached_objects($tagId) + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + [Boolean]$vCenterConn = $true + } elseif ($tagAttObj.Type -contains 'VirtualMachine') { + if (-Not $vmSvc) {$vmSvc = Get-CisService -Name com.vmware.vcenter.vm} + } + foreach ($obj in $tagAttObj) { + if ($vCenterConn) { + $newViObj = New-Object -TypeName VMware.Vim.ManagedObjectReference + $newViObj.Type = $obj.type + $newViObj.Value = $obj.id + $objName = Get-View -Id $newViObj -Property Name | Select-Object -ExpandProperty Name + } elseif ($obj.type -eq "VirtualMachine") { + $filterVmObj = $vmsvc.help.list.filter.create() + $filterVmObj.vms.add($obj.Id) | Out-Null + $objName = $vmSvc.list($filterVmObj) | Select-Object -ExpandProperty Name + } else {$objName = 'Object Not Found'} + $tempObject = "" | Select-Object Tag, Entity + $tempObject.Tag = $tagReference | where {$_.id -eq $tagId} | Select-Object -ExpandProperty Name + $tempObject.Entity = $objName + $tagOutput += $tempObject + } + } + } + return $tagOutput + } +} + +function New-CISTagAssignment { +<# +.SYNOPSIS + Creates new tag assignments from the CIS REST API endpoint +.DESCRIPTION + Will create new tag assignments +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Tag + Tag name which should be referenced +.PARAMETER Entity + Object name which should be retreived +.PARAMETER TagId + Tag ID/s which should be referenced +.PARAMETER ObjectId + Object ID which/s should be retreived +.EXAMPLE + New-CISTagAssignment -Tag TagName -Entity VMName + Creates a tag assignment between the Tag name and the VM name +.EXAMPLE + New-CISTagAssignment -TagId $tagId -ObjectId 'vm-11' + Creates a tag assignment between the Tag ID and the Object ID +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory=$false,Position=0)] + $Tag, + [Parameter(Mandatory=$false,Position=1)] + $Entity, + [Parameter(Mandatory=$false,Position=2)] + $TagId, + [Parameter(Mandatory=$false,Position=3)] + $ObjectId + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagAssocSvc = Get-CisService -Name com.vmware.cis.tagging.tag_association + if ($PSBoundParameters.ContainsKey("Tag") -and $PSBoundParameters.ContainsKey("Entity")) { + if ($Tag -is [array] -and $Entity -isnot [array]) { + $tagIdList = $tagAssocSvc.help.attach_multiple_tags_to_object.tag_ids.create() + foreach ($t in $Tag) { + $tempId = Get-CISTag -Name $t | Select-Object -ExpandProperty Id + $tagIdList.add($tempId) | Out-Null + } + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.attach_multiple_tags_to_object($objObject,$tagIdList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -is [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + $objList = $tagAssocSvc.help.attach_tag_to_multiple_objects.object_ids.create() + foreach ($e in $Entity) { + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $e).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.attach_tag_to_multiple_objects($TagId,$objList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -isnot [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.attach($TagId,$objObject) | Out-Null + } + } elseif ($PSBoundParameters.ContainsKey("TagId") -and $PSBoundParameters.ContainsKey("ObjectId")) { + if ($ObjectId.split('-')[0] -eq 'vm') { + $objType = 'VirtualMachine' + } else {Write-Warning 'Only VirtualMachine types currently supported.'; break} + if ($TagId -is [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.attach_multiple_tags_to_object.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagIdList = $tagAssocSvc.help.attach_multiple_tags_to_object.tag_ids.create() + foreach ($tId in $TagId) { + $tagIdList.add($tId) | Out-Null + } + $tagAssocSvc.attach_multiple_tags_to_object($objObject,$tagIdList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -is [array]) { + $objList = $tagAssocSvc.help.attach_tag_to_multiple_objects.object_ids.create() + foreach ($obj in $ObjectId) { + $objObject = $tagAssocSvc.help.attach_tag_to_multiple_objects.object_ids.element.create() + $objObject.id = $obj + $objObject.type = $objType + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.attach_tag_to_multiple_objects($TagId,$objList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.attach.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagAssocSvc.attach($TagId,$objObject) | Out-Null + } + + } else {Write-Output "Multiple tags with multiple objects are not a supported call."} + + } +} + +function Remove-CISTagAssignment { +<# +.SYNOPSIS + Removes a tag assignment from the CIS REST API endpoint +.DESCRIPTION + Will remove provided tag assignments +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Tag + Tag name which should be removed +.PARAMETER Entity + Object name which should be removed +.PARAMETER TagId + Tag ID/s which should be removed +.PARAMETER ObjectId + Object ID which/s should be removed +.EXAMPLE + Remove-CISTagAssignment -TagId $tagId -ObjectId 'vm-11' + Removes the tag assignment between the Tag ID and the Object ID +.EXAMPLE + Remove-CISTagAssignment -Tag TagName -Entity VMName + Removes the tag assignment between the Tag name and the Entity name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + $Tag, + [Parameter(Mandatory=$false,Position=1,ValueFromPipelineByPropertyName=$true)] + $Entity, + [Parameter(Mandatory=$false,Position=2)] + $TagId, + [Parameter(Mandatory=$false,Position=3)] + $ObjectId + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagAssocSvc = Get-CisService -Name com.vmware.cis.tagging.tag_association + if ($PSBoundParameters.ContainsKey("Tag") -and $PSBoundParameters.ContainsKey("Entity")) { + if ($Tag -is [array] -and $Entity -isnot [array]) { + $tagIdList = $tagAssocSvc.help.detach_multiple_tags_from_object.tag_ids.create() + foreach ($t in $Tag) { + $tempId = Get-CISTag -Name $t | Select-Object -ExpandProperty Id + $tagIdList.add($tempId) | Out-Null + } + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.detach_multiple_tags_from_object.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.detach_multiple_tags_from_object.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.detach_multiple_tags_from_object($objObject,$tagIdList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -is [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + $objList = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.create() + foreach ($e in $Entity) { + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $e).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.element.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.element.create() + $objObject.id = $objId + $objObject.type = $objType + } + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.detach_tag_from_multiple_objects($TagId,$objList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -isnot [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.detach.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.detach.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.detach($TagId,$objObject) | Out-Null + } + } elseif ($PSBoundParameters.ContainsKey("TagId") -and $PSBoundParameters.ContainsKey("ObjectId")) { + if ($ObjectId.split('-')[0] -eq 'vm') { + $objType = 'VirtualMachine' + } else {Write-Warning 'Only VirtualMachine types currently supported.'; break} + if ($TagId -is [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.detach_multiple_tags_from_object.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagIdList = $tagAssocSvc.help.detach_multiple_tags_from_object.tag_ids.create() + foreach ($tId in $TagId) { + $tagIdList.add($tId) | Out-Null + } + $tagAssocSvc.detach_multiple_tags_from_object($objObject,$tagIdList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -is [array]) { + $objList = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.create() + foreach ($obj in $ObjectId) { + $objObject = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.element.create() + $objObject.id = $obj + $objObject.type = $objType + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.detach_tag_from_multiple_objects($TagId,$objList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.detach.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagAssocSvc.detach($TagId,$objObject) | Out-Null + } + } else {Write-Output "Multiple tags with multiple objects are not a supported call."} + + } +} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index fa5ed36..c150c5f 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -1761,8 +1761,8 @@ function Get-HVQueryResult { Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2, 7.1.0 - PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 + Horizon View Server Version : 7.0.2, 7.1.0,7.4 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1, PowerCLI 10.1.1 PowerShell Version : 5.0 #> @@ -1775,7 +1775,7 @@ function Get-HVQueryResult { 'FarmSummaryView','GlobalApplicationEntitlementInfo','GlobalEntitlementSummaryView', 'MachineNamesView','MachineSummaryView','PersistentDiskInfo','PodAssignmentInfo', 'RDSServerInfo','RDSServerSummaryView','RegisteredPhysicalMachineInfo','SampleInfo', - 'SessionLocalSummaryView','TaskInfo','URLRedirectionInfo','UserHomeSiteInfo')] + 'SessionLocalSummaryView','TaskInfo','URLRedirectionInfo','UserHomeSiteInfo','EventSummaryView','GlobalApplicationEntitlementInfo')] [string]$EntityType, [Parameter(Position = 1,Mandatory = $false)] @@ -3568,30 +3568,35 @@ function New-HVPool { [string[]] $ConnectionServerRestrictions, - #desktopSpec.desktopSettings.logoffSettings.powerPloicy + #desktopSpec.desktopSettings.logoffSettings.powerPolicy [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('TAKE_NO_POWER_ACTION', 'ALWAYS_POWERED_ON', 'SUSPEND', 'POWER_OFF')] [string]$PowerPolicy = 'TAKE_NO_POWER_ACTION', - #desktopSpec.desktopSettings.logoffSettings.powerPloicy + #desktopSpec.desktopSettings.logoffSettings.powerPolicy + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('IMMEDIATELY', 'NEVER', 'AFTER')] [string]$AutomaticLogoffPolicy = 'NEVER', #desktopSpec.desktopSettings.logoffSettings.automaticLogoffMinutes + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateRange(1,[int]::MaxValue)] [int]$AutomaticLogoffMinutes = 120, #desktopSpec.desktopSettings.logoffSettings.allowUsersToResetMachines + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [boolean]$allowUsersToResetMachines = $false, #desktopSpec.desktopSettings.logoffSettings.allowMultipleSessionsPerUser + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [boolean]$allowMultipleSessionsPerUser = $false, #desktopSpec.desktopSettings.logoffSettings.deleteOrRefreshMachineAfterLogoff + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('NEVER', 'DELETE', 'REFRESH')] [string]$deleteOrRefreshMachineAfterLogoff = 'NEVER', @@ -3612,25 +3617,30 @@ function New-HVPool { #DesktopDisplayProtocolSettings #desktopSpec.desktopSettings.logoffSettings.supportedDisplayProtocols + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('RDP', 'PCOIP', 'BLAST')] [string[]]$supportedDisplayProtocols = @('RDP', 'PCOIP', 'BLAST'), #desktopSpec.desktopSettings.logoffSettings.defaultDisplayProtocol + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('RDP', 'PCOIP', 'BLAST')] [string]$defaultDisplayProtocol = 'PCOIP', #desktopSpec.desktopSettings.logoffSettings.allowUsersToChooseProtocol + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [int]$allowUsersToChooseProtocol = $true, #desktopSpec.desktopSettings.logoffSettings.enableHTMLAccess + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [boolean]$enableHTMLAccess = $false, # DesktopPCoIPDisplaySettings #desktopSpec.desktopSettings.logoffSettings.pcoipDisplaySettings.renderer3D + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('MANAGE_BY_VSPHERE_CLIENT', 'AUTOMATIC', 'SOFTWARE', 'HARDWARE', 'DISABLED')] [string]$renderer3D = 'DISABLED', @@ -3725,7 +3735,7 @@ function New-HVPool { [string] $ResourcePool, - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.datacenter if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.datacenter if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] @@ -3739,7 +3749,7 @@ function New-HVPool { [string[]] $Datastores, - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastores.storageOvercommit if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastores.storageOvercommit if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] @@ -3980,7 +3990,8 @@ function New-HVPool { [string] $CustType, - #desktopSpec.automatedDesktopSpec.customizationSettings.reusePreExistingAccounts if LINKED_CLONE + #desktopSpec.automatedDesktopSpec.customizationSettings.reusePreExistingAccounts if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] [Boolean] $ReusePreExistingAccounts = $false, @@ -4259,20 +4270,20 @@ function New-HVPool { $redirectWindowsProfile = $false } } - if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings) { - $useViewStorageAccelerator = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.UseViewStorageAccelerator + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings) { + $useViewStorageAccelerator = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings.UseViewStorageAccelerator if ($useViewStorageAccelerator -and $LinkedClone) { - $viewComposerDiskTypes = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.ViewComposerDiskTypes + $viewComposerDiskTypes = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings.ViewComposerDiskTypes } if (! $InstantClone -and $useViewStorageAccelerator) { - $regenerateViewStorageAcceleratorDays = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.RegenerateViewStorageAcceleratorDays - if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.blackoutTimes) { - $blackoutTimesList =$jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.blackoutTimes + $regenerateViewStorageAcceleratorDays = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings.RegenerateViewStorageAcceleratorDays + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings.blackoutTimes) { + $blackoutTimesList =$jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings.blackoutTimes foreach ($blackout in $blackoutTimesList) { $blackoutObj = New-Object VMware.Hv.DesktopBlackoutTime $blackoutObj.Days = $blackout.Days $blackoutObj.StartTime = $blackout.StartTime - $blackoutObj.EndTime = $blackoutObj.EndTime + $blackoutObj.EndTime = $blackout.EndTime $blackoutTimes += $blackoutObj } } @@ -5211,6 +5222,7 @@ function Get-HVPoolCustomizationSetting { throw "No Instant Clone Engine Domain Administrator found with netBiosName: [$netBiosName]" } $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings = Get-CustomizationObject + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.ReusePreExistingAccounts = $reusePreExistingAccounts $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.InstantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.powerOffScriptName = $powerOffScriptName $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.powerOffScriptParameters = $powerOffScriptParameters @@ -7161,7 +7173,6 @@ function Get-HVMachine { $machineList = Find-HVMachine -Param $PSBoundParameters if (!$machineList) { Write-Host "Get-HVMachine: No Virtual Machine(s) Found with given search parameters" - break } $queryResults = @() $desktop_helper = New-Object VMware.Hv.MachineService @@ -8119,8 +8130,7 @@ function Get-HVEntitlement { } if (! $results) { Write-Host "Get-HVEntitlement: No entitlements found with given search parameters" - break - } + } return $results } end { @@ -9309,6 +9319,16 @@ function Set-HVApplicationIcon { } process { + if (!(Test-Path $IconPath)) { + Write-Error "File:[$IconPath] does not exist." + break + } + + if ([IO.Path]::GetExtension($IconPath) -ne '.png') { + Write-Error "Unsupported file format:[$IconPath]. Only PNG image files are supported." + break + } + try { $appInfo = Get-HVQueryResult -EntityType ApplicationInfo -Filter (Get-HVQueryFilter data.name -Eq $ApplicationName) -HvServer $HvServer } catch { @@ -9322,11 +9342,6 @@ function Set-HVApplicationIcon { break } - if (!(Test-Path $IconPath)) { - Write-Error "File:[$IconPath] does not exists" - break - } - $spec = New-Object VMware.Hv.ApplicationIconSpec $base = New-Object VMware.Hv.ApplicationIconBase @@ -9989,63 +10004,75 @@ function Reset-HVMachine { $services.machine.Machine_ResetMachines($machine.id) } } -function Remove-HVMachine(){ +function Remove-HVMachine { <# .Synopsis - Remove a Horizon View desktop or desktops. - + Remove a Horizon View desktop or desktops. + .DESCRIPTION - Deletes a VM or an array of VM's from Horizon. Utilizes an Or query filter to match machine names. + Deletes a VM or an array of VM's from Horizon. Utilizes an Or query filter to match machine names. .PARAMETER HVServer - The Horizon server where the machine to be deleted resides.Parameter is not mandatory, - but if you do not specify the server, than make sure you are connected to a Horizon server + The Horizon server where the machine to be deleted resides. Parameter is not mandatory, + but if you do not specify the server, than make sure you are connected to a Horizon server first with connect-hvserver. .PARAMETER MachineNames - The name or names of the machine(s) to be deleted. Accepts a single VM or an array of VM names.This is a mandatory parameter. + The name or names of the machine(s) to be deleted. Accepts a single VM or an array of VM names.This is a mandatory parameter. + + .PARAMETER DeleteFromDisk + Determines whether the Machine VM should be deleted from vCenter Server. This is only applicable for managed machines. + This must always be true for machines in linked and instant clone desktops. + This defaults to true for linked and instant clone machines and false for all other types. .EXAMPLE - remove-HVMachine -HVServer 'horizonserver123' -MachineNames 'LAX-WIN10-002' - Deletes VM 'LAX-WIN10-002' from HV Server 'horizonserver123' + Remove-HVMachine -HVServer 'horizonserver123' -MachineNames 'LAX-WIN10-002' + Deletes VM 'LAX-WIN10-002' from HV Server 'horizonserver123' .EXAMPLE - remove-HVMachine -HVServer 'horizonserver123' -MachineNames $machines - Deletes VM's contained within an array of machine names from HV Server 'horizonserver123' - + Remove-HVMachine -HVServer 'horizonserver123' -MachineNames $machines + Deletes VM's contained within an array of machine names from HV Server 'horizonserver123' + + .EXAMPLE + Remove-HVMachine -HVServer 'horizonserver123' -MachineNames 'ManualVM01' -DeleteFromDisk:$false + Deletes VM 'ManualVM01' from Horizon inventory, but not from vSphere. Note this only works for Full Clone VMs. + .NOTES Author : Jose Rodriguez Author email : jrodsguitar@gmail.com Version : 1.0 - + ===Tested Against Environment==== Horizon View Server Version : 7.1.1 PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> - - [CmdletBinding( + + [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High' )] - - param( - + + param( + [Parameter(Mandatory = $true)] [array] - $MachineNames, - + $MachineNames, + + [Parameter(Mandatory = $false)] + [switch]$DeleteFromDisk = $true, + [Parameter(Mandatory = $false)] $HVServer = $null - ) + ) #Connect to HV Server $services = Get-ViewAPIService -HVServer $HVServer - - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" + +if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" break - } + } #Connect to Query Service $queryService = New-Object 'Vmware.Hv.QueryServiceService' @@ -10097,9 +10124,9 @@ $trys = 0 foreach($session in $deleteMachine.base.session){ $sessions = $null - [VMware.Hv.SessionId[]]$sessions += $session - - } + [VMware.Hv.SessionId[]]$sessions += $session + + } try{ @@ -10111,8 +10138,8 @@ $trys = 0 #Wait more for Sessions to end - Start-Sleep -Seconds 5 - + Start-Sleep -Seconds 5 + } catch{ @@ -10122,39 +10149,39 @@ $trys = 0 write-host ($deleteMachine.base.Name -join "`n") start-sleep -seconds 5 - + } - - if(($trys -le 10)){ - + + if(($trys -le 10)){ + write-host "`n" write-host "Retrying Logoffs: $trys times" #Recheck existing sessions $deleteMachine = $machineService.Machine_GetInfos($services,$deleteThisMachine.Id) - + } - - $trys++ + + $trys++ } until((!$deleteMachine.base.session.id) -or ($trys -gt 10)) - + } #Create delete spec for the DeleteMachines method $deleteSpec = [VMware.Hv.MachineDeleteSpec]::new() -$deleteSpec.DeleteFromDisk = $true +$deleteSpec.DeleteFromDisk = $DeleteFromDisk $deleteSpec.ArchivePersistentDisk = $false - + #Delete the machines -write-host "Attempting to Delete:" +if($DeleteFromDisk){write-host "Attempting to Delete:"}else{write-host "Attempting to remove from inventory:"} Write-Output ($deleteMachine.base.Name -join "`n") $bye = $machineService.Machine_DeleteMachines($services,$deleteMachine.id,$deleteSpec) [System.gc]::collect() - -} + +} function get-hvhealth { <# @@ -10886,4 +10913,671 @@ function remove-hvsite { [System.gc]::collect() } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-hvlocalsession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, new-hvpodfederation, remove-hvpodfederation, get-hvpodfederation, register-hvpod, unregister-hvpod, set-hvpodfederation,get-hvsite,new-hvsite,set-hvsite,remove-hvsite +function Get-HVHomeSite { + <# + .Synopsis + Gets the configured Horizon View Homesites + + .DESCRIPTION + Gets the configured Horizon View Homesites + + .PARAMETER Group + User principal name of a group + + .PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + + .EXAMPLE + Get-HVHomeSite + + .EXAMPLE + Get-HVHomeSite -group group@domain + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $false, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $false)] + [ValidatePattern("^.+?[@\\].+?$")] + [String] + $Group, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin{ + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process{ + $hsresults = Get-HVQueryResult -EntityType UserHomeSiteInfo -HvServer $HvServer + $resultsoverview=@() + + foreach ($hsresult in $hsresults){ + if ($hsresult.Globalentitlement){ + $Globalentitlement = ($services.GlobalEntitlement.GlobalEntitlement_Get($hsresult.base.GlobalEntitlement)).base.displayname + } + else{ + $Globalentitlement="" + } + + if (($hsresult.globalapplicationEntitlement)){ + $GlobalApplicationEntitlement = ($services.GlobalApplicationEntitlement.GlobalApplicationEntitlement_Get($hsresult.base.GlobalApplicationEntitlement)).base.displayname + } + else{ + $GlobalApplicationEntitlement="" + } + + $resultsoverview+=New-Object PSObject -Property @{"id" = ($hsresult).id; + "Group" = ($services.ADUserOrGroup.ADUserOrGroup_Get(($hsresult.base).userorgroup)).base.displayname; + "Site" = ($services.site.site_Get($hsresult.base.site)).base.displayname; + "Globalentitlement" =$Globalentitlement; + "Globalapplicationentitlement" =$GlobalApplicationEntitlement; + } + } + if ($group){ + $results=$resultsoverview | where-object {$_.Group -eq $group} | select-object id,Group,Site,Globalentitlement,GlobalApplicationEntitlement + } + else{ + $results=$resultsoverview | select-object id,Group,Site,Globalentitlement,GlobalApplicationEntitlement + } + return $results + [System.gc]::collect() + } + +} + +function New-HVHomeSite { + <# + .Synopsis + Defines a homesite within a Horizon View Cloud Pod architecture + + .DESCRIPTION + Creates a new homesite within a Cloud Pod Archtitecture. By default it will be applied to everything + but the choice can be made to only apply for a single global entitlement or singel global application entitlement + + .PARAMETER Group + User principal name of a group + + .PARAMETER Site + Name of the Horizon View Site + + .PARAMETER globalEntitlement + Name of the global entitlement + + .PARAMETER globalApplicationEntitlement + Name of the global application entitlement + + .PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + + .EXAMPLE + New-HVHomeSite -group group@domain -site SITE + + .EXAMPLE + New-HVHomeSite -group group@domain -site SITE -globalapplicationentitlement ge-ap01 + + .EXAMPLE + New-HVHomeSite -group group@domain -site SITE -globalentitlement GE_Production + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4 + PowerCLI Version : PowerCLI 10.1.1 + PowerShell Version : 5.0 + #> + + + [CmdletBinding(DefaultParameterSetName="Default")] + param( + [Parameter(Mandatory = $true,ParameterSetName="Default")] + [Parameter(ParameterSetName = "globalEntitlement")] + [Parameter(ParameterSetName = "globalApplicationEntitlement")] + [ValidatePattern("^.+?[@\\].+?$")] + [String] + $Group, + + [Parameter(Mandatory = $true,ParameterSetName="Default")] + [Parameter(ParameterSetName = "globalEntitlement")] + [Parameter(ParameterSetName = "globalApplicationEntitlement")] + [String] + $Site, + + [Parameter(Mandatory = $false,ParameterSetName="globalEntitlement")] + [String] + $globalEntitlement , + + [Parameter(Mandatory = $false,ParameterSetName="globalApplicationEntitlement")] + [String] + $globalApplicationEntitlement , + + [Parameter(Mandatory = $false,ParameterSetName="Default")] + [Parameter(ParameterSetName = "globalEntitlement")] + [Parameter(ParameterSetName = "globalApplicationEntitlement")] + $HvServer = $null + ) + + begin{ + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys + $groupinfo = Get-UserInfo -UserName $Group + $UserOrGroupName = $groupinfo.Name + $Domain = $groupinfo.Domain + $filter1 = Get-HVQueryFilter 'base.name' -Eq $UserOrGroupName + $filter2 = Get-HVQueryFilter 'base.domain' -Eq $Domain + $filter3 = Get-HVQueryFilter 'base.group' -Eq $true + $andFilter = Get-HVQueryFilter -And -Filters @($filter1, $filter2, $filter3) + $adresults = Get-HVQueryResult -EntityType ADUserOrGroupSummaryView -Filter $andFilter -HvServer $HvServer + + if ($adresults.length -ne 1) { + Write-host "Unable to find specific group with given search parameters" + break + } + $userhomesitebase=new-object VMware.Hv.UserHomeSiteBase + $userhomesitebase.UserOrGroup=$adresults.id + $userhomesitebase.site=($services.site.site_list() | where-object {$_.base.displayname -eq $site}).id + if ($globalEntitlement){ + $geresults = Get-HVQueryResult -EntityType GlobalEntitlementSummaryView -HvServer $HvServer + $geid=$geresults | where-object {$_.base.displayname -eq $globalEntitlement} + $userhomesitebase.globalEntitlement=$geid.id + } + elseif($globalApplicationEntitlement){ + $gaefilter1 = Get-HVQueryFilter 'data.name' -Eq $globalApplicationEntitlement + $gaeresults = Get-HVQueryResult -EntityType ApplicationInfo -Filter $gaefilter1 -HvServer $HvServer + $userhomesitebase.GlobalApplicationEntitlement=$gaeresults.id + } + $services.UserHomeSite.UserHomeSite_Create($userhomesitebase) + } +} + +function Set-HVEventDatabase { + <# + .Synopsis + Registers or changes a Horizon View Event database. + + .DESCRIPTION + Registers or changes a Horizon View Event database + + .PARAMETER ServerName + Name of the database server (Required) + + .PARAMETER Databasetype + Database type, possible options: MYSQL,SQLSERVER,ORACLE. Defaults to SQLSERVER + + .PARAMETER DatabasePort + Port number on the database server to which View will send events. Defaults to 1433. + + .PARAMETER Databasename + Name of the Database (required) + + .PARAMETER TablePrefix + Prefix to use for the Event Databse. Allowed characters are letters, numbers, and the characters @, $, #, _, and may not be longer than 6 characters. + + .PARAMETER UserName + UserName to connect to the database (required) + + .PARAMETER Password + Password of the user connecting to the database in Securestring format. + Can be created with: $password = Read-Host 'Domain Password' -AsSecureString + + .PARAMETER eventtime + Time to show the events for. Possible options are ONE_WEEK, TWO_WEEKS, THREE_WEEKS, ONE_MONTH,TWO_MONTHS, THREE_MONTHS, SIX_MONTHS + + .PARAMETER EventNewTime + Time in days to classify events for new. Range 1-3 + + .PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + + .EXAMPLE + register-hveventdatabase -server SERVER@domain -database DATABASENAME -username USER@domain -password $password + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $false, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $true)] + [string] + $ServerName, + + [Parameter(Mandatory = $false)] + [string] + $DatabaseType = "SQLSERVER", + + [Parameter(Mandatory = $false)] + [int] + $DatabasePort = 1433, + + [Parameter(Mandatory = $true)] + [string] + $DatabaseName, + + [Parameter(Mandatory = $false)] + [string][ValidateLength(1,6)] + $TablePrefix, + + [Parameter(Mandatory = $true)] + + [String] + $UserName, + + [Parameter(Mandatory = $true)] + [securestring] + $password, + + [Parameter(Mandatory = $false)] + [ValidateSet('ONE_WEEK','TWO_WEEKS','THREE_WEEKS','ONE_MONTH','TWO_MONTHS','THREE_MONTHS','SIX_MONTHS')] + [string] + $eventtime="TWO_WEEKS", + + [Parameter(Mandatory = $false)] + [ValidateRange(1,3)] + [int] + $eventnewtime = 2, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + $temppw = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password) + $PlainevdbPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($temppw) + $dbupassword = New-Object VMware.Hv.SecureString + $enc = [system.Text.Encoding]::UTF8 + $dbupassword.Utf8String = $enc.GetBytes($PlainevdbPassword) + + $eventservice=new-object vmware.hv.eventdatabaseservice + $eventservicehelper=$eventservice.getEventDatabaseInfoHelper() + $eventsettings=new-object VMware.Hv.EventDatabaseEventSettings + $eventdatabase=new-object VMware.Hv.EventDatabaseSettings + $eventsettings.ShowEventsForTime=$eventtime + $eventsettings.ClassifyEventsAsNewForDays=$eventnewtime + $eventdatabase.Server=$ServerName + $eventdatabase.type=$DatabaseType + $eventdatabase.port=$DatabasePort + $eventdatabase.name=$DatabaseName + $eventdatabase.username=$UserName + if($TablePrefix){ + $eventdatabase.tablePrefix=$tableprefix + } + + $eventdatabase.password=$dbupassword + $eventservicehelper.setDatabase($eventdatabase) + $eventservicehelper.setsettings($eventsettings) + $eventservice.update($services, $eventservicehelper) + + [System.gc]::collect() +} + +function Get-HVEventDatabase { + <# + .Synopsis + Retreives information about the configured Event Database + + .DESCRIPTION + Collects information about the configured event database for aHorizon View pod + + .PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + + .EXAMPLE + Get-HVEventDatabase + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $false, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + $eventdatabase=$services.EventDatabase.EventDatabase_Get() + if ($eventdatabase.eventdatabaseset -eq $False){ + write-output "No Event Database configuration found" + } + elseif ($eventdatabase.eventdatabaseset -eq $true){ + $Eventdatabaseoverview=@() + $Eventdatabaseoverview+=New-Object PSObject -Property @{"Servername" = $eventdatabase.Database.Server; + "Type" = $eventdatabase.Database.Type; + "DatabaseName" = $eventdatabase.Database.Name; + "UserName" = $eventdatabase.Database.UserName; + "TablePrefix" = $eventdatabase.Database.TablePrefix; + "ShowEventsForTime" = $eventdatabase.settings.ShowEventsForTime; + "ClassifyEventsAsNewForDays" = $eventdatabase.settings.ClassifyEventsAsNewForDays; + } | select-object Servername,Type,DatabaseName,UserName,TablePrefix,ShowEventsForTime,ClassifyEventsAsNewForDays + } + return $Eventdatabaseoverview + [System.gc]::collect() +} + +function Clear-HVEventDatabase { + <# + .Synopsis + Clears configurationof the configured Event Database + + .DESCRIPTION + Clears configurationof the configured Event Database + + .PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + + .EXAMPLE + Clear-HVEventDatabase + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High')] + + param( + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + PROCESS { + + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + if ($pscmdlet.ShouldProcess($($msg))) { + $services.EventDatabase.EventDatabase_Clear() + } + [System.gc]::collect() + } +} + +function Set-HVlicense { + <# + .Synopsis + Sets or changes the license for Horizon View + + .DESCRIPTION + Sets or changes the license for Horizon View + + .PARAMETER license + License key (string) + + .PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + + .EXAMPLE + set-hvlicense -license "LICENSE-KEY" + Returns information about the sites within a Horizon View Pod Federation. + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4,7.5 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $false, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $true)] + [string] + $license, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + try { + $services.license.license_set($license) + } + catch { + write-error $_.exception message + break + } + $licenseresult=$services.license.license_get() + return $licenseresult + [System.gc]::collect() +} + + +function Get-HVlicense { + <# + .Synopsis + Gets the license for Horizon View + + .DESCRIPTION + Gets the license for Horizon View + + + .PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + + .EXAMPLE + get-hvlicense + + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4,7.5 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $false, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + $license=$services.license.license_get() + return $license + [System.gc]::collect() +} + +function Set-HVInstantCloneMaintenance { + <# + .Synopsis + Enable or disable instant clone maintanence mode + + .DESCRIPTION + Toggles a host in instant clone maintanence mode. Specify the VMHost name and enable or disable to toggle. + + .PARAMETER VMHost + ESXi Host name to modify the InstantClone.Maintenance attribute + + .PARAMETER Enable + Enable Instant Clone maintenance mode. + + .PARAMETER Disable + Disable Instant Clone maintenance mode + + .EXAMPLE + Set-HvInstantCloneMaintenance -VMHost -Enable $true + Set-HvInstantCloneMaintenance -VMHost -Disable $true + + .NOTES + Author : Jack McMichael + Author email : @jackwmc4 / jackwmc4@gmail.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.6 + PowerCLI Version : PowerCLI 11 + PowerShell Version : 5.1 + #> + + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High')] + + param( + [Parameter(Mandatory=$true, Position=0)] + [string] + $VMHost, + + [Parameter(Mandatory = $false)] + [switch] + $Enable, + + [Parameter(Mandatory = $false)] + [switch] + $Disable, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + if ($Enable) { + if ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -eq ""){ + Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "1" | Out-Null + Write-Host "Instant Clone Maintenance Mode: Enabling for $VMHost...(This could take some time)" + } + while ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -ne "2") { + Start-Sleep -Seconds 10 + } + } elseif ($Disable) { + if (-not (Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -eq "") { + Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "" | Out-Null + Write-Host "Instant Clone Maintenance Mode: Disabling for $VMHost" + } + Set-VMhost $VMHost -State Connected | Out-Null + } + [System.gc]::collect() + } +} +# Object related +Export-ModuleMember -Function Get-HVMachine, Get-HVMachineSummary, Get-HVQueryResult, Get-HVQueryFilter, Get-HVInternalName +# RDS Farm related +Export-ModuleMember -Function Get-HVFarmSummary, Start-HVFarm, Start-HVPool, New-HVFarm, Remove-HVFarm, Get-HVFarm, Set-HVFarm, Add-HVRDSServer +# Desktop Pool related +Export-ModuleMember -Function Get-HVPoolSummary, New-HVPool, Remove-HVPool, Get-HVPool, Set-HVPool, Get-HVPoolSpec, Add-HVDesktop +# Entitlement related +Export-ModuleMember -Function New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement +Export-ModuleMember -Function Set-HVMachine, Reset-HVMachine, Remove-HVMachine +# Cloud Pod Architecture related +Export-ModuleMember -Function New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVGlobalEntitlement, New-HVPodFederation, Remove-HVPodFederation, Get-HVPodFederation, Set-HVPodFederation +Export-ModuleMember -Function Get-HVSite, New-HVSite, New-HVHomeSite, Remove-HVSite, Get-HVHomeSite, Set-HVSite, Register-HVPod, Unregister-HVPod +# Published App related +Export-ModuleMember -Function Get-HVGlobalSettings, Set-HVApplicationIcon, Remove-HVApplicationIcon, Set-HVGlobalSettings +Export-ModuleMember -Function Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession +# Event Database related +Export-ModuleMember -Function Get-HVEventDatabase, Set-HVEventDatabase, Clear-HVEventDatabase, Get-HVEvent, Connect-HVEvent, Disconnect-HVEvent +# Misc/other related +Export-ModuleMember -Function Get-HVlicense, Set-HVlicense, Get-HVHealth, Set-HVInstantCloneMaintenance \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/Export-VCGReport.ps1 b/Modules/VMware.VCGChecker/Export-VCGReport.ps1 new file mode 100644 index 0000000..3774915 --- /dev/null +++ b/Modules/VMware.VCGChecker/Export-VCGReport.ps1 @@ -0,0 +1,1057 @@ +# +# Generate the html report and save it to the report folder +# TODO: change to the class +Function Export-VCGReport { + Param( + [Parameter(Mandatory=$true)] $Data, + [Parameter(Mandatory=$true)] $Dir + ) + if (!(Test-Path $Dir)) { + New-Item -Type directory -Confirm:$false -Path $Dir -Force |Out-Null + } + + $Data,$flag = refactorData $Data + + $null=Generate_CsvReport $Data $Dir + $null=Generate_HtmlReport $Data $Dir + $null=Generate_SummaryReport $Data $Dir +} +Function Generate_HtmlReport($Data, $Dir) { + info ("Generating compatibility detail report...") + $content = $generalHead + $content += '

ESXi Hardware Compatibility Report for {0}

' -f $Data.hostname + $content += $generalBodyBase + if (-not(checkVersion($Data))) { + $content += 'Installed Release' + } + else { + $content += 'Checked Release' + } + $content += $generalBodyRest + foreach ($VCResource in $Data) { + $checkVersion = $VCResource.checkRelease + $Count1 = $VCResource.DCResource.HostResource.ComponentResource.Count + $Process = '' + if ($VCResource.hostname -ne 'null') { + $Process += '{1}' -f $Count1, [string]$VCResource.hostname + } + else { + $Process += '{1}' -f $Count1, '/' + } + foreach ($DCResource in $VCResource.DCResource) { + $Count2 = $DCResource.HostResource.ComponentResource.Count + if ($DCResource.dcname -ne 'null') { + $Process += '{1}' -f [string]$Count2, [string]$DCResource.dcname + } + else { + $Process += '{1}' -f [string]$Count2, '/' + } + foreach ($HostResourceOne in $DCResource.HostResource) { + $Count = $HostResourceOne.ComponentResource.count + $Process += '{1}' -f $Count, $HostResourceOne.HostName + foreach ($OneDevice in $HostResourceOne.ComponentResource) { + if ($OneDevice.type -eq 'Server') { + # $InfoServer = "" | Select HostName, Manufacturer, Model, CPU, Version, Bios, CpuFeature, Uuid, VcgLink, Status, FoundRelease, MatchResult, Warnings + $InfoServer = @{} + $InfoServer.HostName = $HostResourceOne.hostname + $InfoServer.Version = $HostResourceOne.version + $InfoServer.Manufacturer = $OneDevice.vendor + $InfoServer.Model = $OneDevice.model + $InfoServer.CPU = $OneDevice.cpumodel + $InfoServer.Bios = $OneDevice.biosversion + $InfoServer.CpuFeature = $OneDevice.cpufeatureid + $InfoServer.Uuid = $OneDevice.uuid + $InfoServer.VcgLink = $OneDevice.vcgLink + $InfoServer.Status = formatStatus($OneDevice.status) + $InfoServer.MatchResult = $OneDevice.matchResult + $InfoServer.Warnings = (([string]$OneDevice.warnings) -split "More information")[0] + # server info + $Process += 'Server' + $Process += '{0}' -f $InfoServer.Model + $Process += '{0}' -f $InfoServer.Manufacturer + if (-not $checkVersion) { + $Process += '{0}' -f $InfoServer.Version + } + else { + $Process += '{0}' -f $checkVersion + } + $Process += '{0}' -f $InfoServer.Status + $Process += '{0},
CpuFeature:{1},
Bios:{2}' -f $InfoServer.CPU, $InfoServer.CpuFeature, $InfoServer.Bios + if ($InfoServer.VcgLink.Count -gt 0) { + $Process += '{0}
' -f $InfoServer.Warnings + foreach ($link in $InfoServer.VcgLink) { + $Process += ' VCG link
' -f $link + } + $Process += '' + } + else + {$Process += '{0}
N/A' -f $InfoServer.Warnings} + $Process += '' + } + else { + # $InfoPci = "" | Select model, vendor, Vid, Did, Svid, Ssid, Driver, DriverVersion, Version, Pccid, VcgLink, Status, FoundRelease, MatchResult, Warnings + $InfoPci = @{} + $InfoPci.model = $OneDevice.model + $InfoPci.vendor = $OneDevice.vendor + $InfoPci.Vid = $OneDevice.vid + $InfoPci.Did = $OneDevice.did + $InfoPci.Svid = $OneDevice.svid + $InfoPci.Ssid = $OneDevice.ssid + $InfoPci.Driver = $OneDevice.driver + $InfoPci.DriverVersion = $OneDevice.driverversion + $InfoPci.Version = $HostResourceOne.version + $InfoPci.Pccid = $OneDevice.pciid + $InfoPci.VcgLink = $OneDevice.vcgLink + $InfoPci.Status = formatStatus($OneDevice.status) + $InfoPci.MatchResult = $OneDevice.matchResult + $InfoPci.Warnings = (([string]$OneDevice.warnings) -split "More information")[0] + # IO info + # TODO:Variable information coverage, need to be modified + $Process += '' + $Process += 'IO Device' + $Process += '{0}' -f $InfoPci.model + $Process += '{0}' -f $InfoPci.vendor + if (-not $checkVersion) { + $Process += '{0}' -f $InfoPci.Version + } + else { + $Process += '{0}' -f $checkVersion + } + $Process += '{0}' -f $InfoPci.Status + $Process += 'PCI ID:{0}
Driver:{1} Version:{2}' -f $InfoPci.Pccid, $InfoPci.Driver, $InfoPci.DriverVersion + if ($InfoPci.VcgLink.Count -gt 0) { + $Process += '{0}
' -f $InfoPci.Warnings + foreach ($link in $InfoPci.VcgLink) { + $Process += ' VCG link
' -f $link + } + $Process += '' + } + else + {$Process += '{0}
N/A' -f $InfoPci.Warnings} + $Process += '' + } + } + } + } + $content += $Process + } + $content += $generalFooter + #define filename and filepath + $dataTime = Get-Date -Format 'yyyy-M-d_h-m' + $vcName = vcName($Data) + $filename = 'compreport_' + $vcName + $dataTime + '.html' + $filePath = $Dir + '\' + $filename + #save report + $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null + info ("Report " + "'" + $filePath + "'" + " has been created!") +} + +Function Generate_SummaryReport($Data, $Dir) { + info ("Generating compatibility summary report...") + $content = $summaryHead + $vcCount = $Data.length + $barsWidth = 45 / ($vcCount+1) + $content += 'var barsWidth = {0};' -f $barsWidth + # get vCName arry and host count + $vcNameArray = @() + foreach ($DCResource in $Data) { + $vcNameArray += $DCResource.DCResource[0].vcname + } + + $content += "var vCname = [" + foreach ($vc in $vcNameArray) { + $content += '"{0}",' -f $vc + } + $content += "];" + # Count Compatible or unpgrade + $compatibleCountFormat = '[' + $mayNotCompatibleCountFormat = '[' + $UnabletoUpgradeCountFormat = '[' + foreach ($VCResource in $Data) { + $checkVersion = $VCResource.checkRelease + $compatibleCount = 0 + $notcompatibleCount = 0 + $UnabletoUpgradeCount = 0 + foreach ($DCResource in $VCResource.DCResource) { + foreach ($HostResourceOne in $DCResource.HostResource) { + foreach ($OneDevice in $HostResourceOne.ComponentResource) { + $flagcompatible = 0 + # if($checkVersion){ + # if(-not($OneDevice.upgrade)){ + # $flagcompatible = 'null' + # break + # } + # } + #whether compatible + if ($OneDevice.status -ne 'Compatible') { + $flagcompatible = 0 + break + } + else { + $flagcompatible = 1 + } + #whether upgrade + } + + if ($flagcompatible -eq 1) { + $compatibleCount += 1 + } + elseif($flagcompatible -eq 0){ + $notcompatibleCount += 1 + } + + elseif($flagcompatible -eq 'null') { + $UnabletoUpgradeCount += 1 + } + } + } + $compatibleCountFormat += $compatibleCount + $compatibleCountFormat += ',' + $mayNotCompatibleCountFormat += $notcompatibleCount + $mayNotCompatibleCountFormat += ',' + $UnabletoUpgradeCountFormat += $UnabletoUpgradeCount + $UnabletoUpgradeCountFormat += ',' + } + $compatibleCountFormat += ',]' + $mayNotCompatibleCountFormat += ',]' + $UnabletoUpgradeCountFormat += ']' + + $dataDict = [Ordered]@{} + + if (-not(checkVersion($Data))) { + $content += 'var lengendSeries = ["Compatible","May Not Compatible"];' + $content += $hostCountHead + + $dataDict.Insert(0, "Compatible", $compatibleCountFormat) + $dataDict.Insert(1, "May Not Compatible", $mayNotCompatibleCountFormat) + } + else { + $content += 'var lengendSeries = ["Compatible","May Not Compatible","Unable to upgrade"];' + $content += $hostCountHead + + $dataDict.Insert(0, "Compatible", $compatibleCountFormat) + $dataDict.Insert(1, "May Not Compatible", $mayNotCompatibleCountFormat) + $dataDict.Insert(2, "Unable to upgrade", $UnabletoUpgradeCountFormat) + } + [System.Collections.IEnumerator]$dataDict = $dataDict.Keys.GetEnumerator(); + $formatContent = formatHostCountGraphic $dataDict + + $content += $formatContent + $content += $hostCountRest + + + # Host Compatibility + $compatibleCount = 0 + $mayNotcompatibleCount = 0 + $unableUpgradeCount = 0 + foreach ($VCResource in $Data) { + foreach ($DCResource in $VCResource.DCResource) { + foreach ($HostResourceOne in $DCResource.HostResource) { + foreach ($OneDevice in $HostResourceOne.ComponentResource) { + #whether compatible + $flagcompatible = 0 + # if ($checkVersion){ + # if (-not($OneDevice.upgrade)){ + # $flagcompatible = 'null' + # break + # } + # } + if ($OneDevice.status -ne 'Compatible') { + $flagcompatible = 0 + break + } + else { + $flagcompatible = 1 + } + + } + if ($flagcompatible -eq 1) { + $compatibleCount += 1 + } + elseif ($flagcompatible -eq 0) { + $mayNotcompatibleCount += 1 + } + elseif ($flagcompatible -eq 'null') { + $unableUpgradeCount += 1 + } + } + } + } + + if (-not(checkVersion($Data))) { + $content += "var seriesCount = {'Compatible':$compatibleCount, 'May Not Compatible':$mayNotcompatibleCount,};" + $content += "var lengendSeries = ['Compatible','May Not Compatible'];" + $content += "var catalog = [ + {value:seriesCount['Compatible'], name:'Compatible'}, + {value:seriesCount['May Not Compatible'], name:'May Not Compatible'}, + ];" + $content += "var colors = [colorsC,colorsM];" + } + else { + $content += "var seriesCount = {'Compatible':$compatibleCount, 'May Not Compatible':$mayNotcompatibleCount,'Unable to Upgrade':$unableUpgradeCount};" + $content += "var lengendSeries = ['Compatible','May Not Compatible','Unable to Upgrade'];" + $content += "var catalog = [ + {value:seriesCount['Compatible'], name:'Compatible'}, + {value:seriesCount['May Not Compatible'], name:'May Not Compatible'}, + {value:seriesCount['Unable to Upgrade'], name:'Unable to Upgrade'}, + ];" + $content += "var colors = [colorsC,colorsM,colorsU];" + } + + $content += $hostCompatible + + + #Host Model Compatibility by vCenter + if (-not(checkVersion($Data))) { + $serverSource = "[['series', 'Compatible', 'May Not Compatible',]," + } + else { + $serverSource = "[['series', 'Compatible','May Not compatible','No Upgrade Path']," + } + + foreach ($VCResource in $Data) { + $compatibleCount = 0 + $mayNotCompatibleCount = 0 + $unableUpgradeCount = 0 + $checkVersion = $VCResource.checkRelease + foreach ($DCResourceOne in $VCResource.DCResource) { + foreach ($HostResourceOne in $DCResourceOne.HostResource) { + $flagcompatible = 0 + foreach ($ComoenentResourceOne in $HostResourceOne.ComponentResource) { + #whether compatible + if ($ComoenentResourceOne.type -eq 'Server') { + # if ($checkVersion) { + # if (-not($ComoenentResourceOne.upgrade)) { + # $flagcompatible = 'null' + # break + # } + # } + if ($ComoenentResourceOne.status -ne 'Compatible') { + $flagcompatible = 0 + } + else { + $flagcompatible = 1 + } + break + + } + } + if ($flagcompatible -eq 1) { + $compatibleCount += 1 + } + elseif ($flagcompatible -eq 0) { + $mayNotcompatibleCount += 1 + } + elseif ($flagcompatible -eq 'null') { + $unableUpgradeCount += 1 + } + } + } + if (-not $checkVersion) { + $serverSource += '["{0}",{1},{2}],' -f $DCResourceOne.vcname, $compatibleCount, $mayNotCompatibleCount + } + else { + $serverSource += '["{0}",{1},{2},{3}],' -f $DCResourceOne.vcname, $compatibleCount, $mayNotCompatibleCount, $unableUpgradeCount + } + } + $serverSource += '];' + $content += 'var serverSource = {0}' -f $serverSource + $content += $hostModelCompatibleHead + + if (-not $checkVersion) { + $colorsArray = 'colorsC', 'colorsM' + } + else { + $colorsArray = 'colorsC', 'colorsM', 'colorsU' + } + foreach ($colors in $colorsArray) { + $content += $hostModelCompatibleBody + $content += "color:$colors}," + } + $content += $hostModelCompatibleRest + + #count IO Device compatibility by vCenter + if (-not(checkVersion($Data))) { + $ioSource = "[['series', 'Compatible', 'May Not Compatible',]," + } + else { + $ioSource = "[['series', 'Compatible','May Not Compatible','No Upgrade Path',]," + } + + foreach ($VCResource in $Data) { + $compatibleCount = 0 + $mayNotCompatibleCount = 0 + $unableUpgradeCount = 0 + $checkVersion = $VCResource.checkRelease + foreach ($DCResourceOne in $VCResource.DCResource) { + foreach ($HostResourceOne in $DCResourceOne.HostResource) { + $flagcompatible = 0 + foreach ($ComoenentResourceOne in $HostResourceOne.ComponentResource) { + if ($ComoenentResourceOne.type -eq 'IO Device') { + # if ($checkVersion) { + # if (-not($ComoenentResourceOne.upgrade)) { + # $flagcompatible = 'null' + # } + # } + if ($ComoenentResourceOne.status -ne 'Compatible') { + $flagcompatible = 0 + } + else { + $flagcompatible = 1 + } + + if ($flagcompatible -eq 1) { + $compatibleCount += 1 + } + elseif ($flagcompatible -eq 0) { + $mayNotCompatibleCount += 1 + } + elseif ($flagcompatible -eq 'null') { + $unableUpgradeCount += 1 + } + } + } + + } + } + if (-not $checkVersion) { + $ioSource += '["{0}",{1},{2}],' -f $DCResourceOne.vcname, $compatibleCount, $mayNotCompatibleCount + } + else { + $ioSource += '["{0}",{1},{2},{3}],' -f $DCResourceOne.vcname, $compatibleCount, $mayNotCompatibleCount, $unableUpgradeCount + } + } + + $ioSource += '];' + $content += 'var ioSource = {0}' -f $ioSource + $content += $ioCompatibleHead + if (-not $checkVersion) { + $colorsArray = 'colorsC', 'colorsM' + } + else { + $colorsArray = 'colorsC', 'colorsM', 'colorsU' + } + foreach ($colors in $colorsArray) { + $content += $ioCompatibleBody + $content += "color:$colors}," + } + $content += $ioCompatibleRest + + $dataTime = Get-Date -Format 'yyyy-M-d_h-m' + $vcName = vcName($Data) + $filename = 'sumreport_' + $vcName + $dataTime + '.html' + $filePath = $Dir + '\' + $filename + # Out-put a html report + $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null + info ("Report " + "'" + $filePath + "'" + " has been created!") +} + +Function Generate_CsvReport($Data, $Dir) { + info("Generating compatibility csv report") + #define header + $content = '' + $content += "VC," + $content += "DataCenter," + $content += "Host," + $content += "Type," + $content += "Model Name," + $content += "Vendor," + if (-not(checkVersion($Data))) { + $content += "Installed Release," + } + else { + $content += "Checked Release," + } + $content += "Compatible Status," + $content += "Hardware Detail," + $content += "Comments," + $content += 'VCG Link,' + $content += "`n" + + #formate content + foreach ($VCResource in $Data) { + $checkVersion = $VCResource.checkRelease + foreach ($DCResourceOne in $VCResource.DCResource) { + foreach ($HostResourceOne in $DCResourceOne.HostResource) { + $installVersion = $HostResourceOne.version + foreach ($ComoenentResourceOne in $HostResourceOne.ComponentResource) { + if ($DCResourceOne.vcname -ne 'null') { + $content += "{0}," -f $DCResourceOne.vcname + } + else { + $content += "{0}," -f '/' + } + #DataCenterDetail + if ($DCResourceOne.dcname -ne 'null') { + $content += "{0}," -f $DCResourceOne.dcname + } + else { + $content += "{0}," -f '/' + } + #Host + $content += "{0}," -f $HostResourceOne.hostname + #Type + $content += "{0}," -f $ComoenentResourceOne.type + #Model Name + $content += '"{0}",' -f $ComoenentResourceOne.model + #Vendor + $content += '"{0}",' -f $ComoenentResourceOne.vendor + if (-not $checkVersion) { + #Installed Release + $content += '"{0}",' -f $installVersion + } + else { + $content += '"{0}",' -f $checkVersion + } + #Status + $content += '"{0}",' -f (formatStatus($ComoenentResourceOne.status)) + #CompatibleHardware + if ($ComoenentResourceOne.type -eq 'IO Device') { + $CompatibleHardware = "'PCI ID:{0}, Driver:{1} {2}" -f $ComoenentResourceOne.pciid, $ComoenentResourceOne.Driver, $ComoenentResourceOne.DriverVersion + } + else { + $CompatibleHardware = "'CPU: {0}(Feature:{1}) BIOS:{2}" -f $ComoenentResourceOne.cpumodel, $ComoenentResourceOne.cpufeatureid, $ComoenentResourceOne.biosversion + } + $content += '"{0}",' -f $CompatibleHardware + + #Comments + + if ($ComoenentResourceOne.Warnings.Count -gt 0) { + $Comments = $ComoenentResourceOne.Warnings + } + else { + $Comments ='N/A' + } + + $content += '"{0}",' -f $Comments + + #VCG Link + $VCGLink = '' + foreach ($link in $ComoenentResourceOne.VcgLink) { + $VCGLink += $link + $VCGLink += ' ' + } + $content += '"{0}",' -f $VCGLink + $content += "`n" + } + } + } + } + + #define filename and path + $dataTime = Get-Date -Format 'yyyy-M-d_h-m' + $vcName = vcName($Data) + $filename = 'compreport_' + $vcName + $dataTime + '.csv' + $filePath = $Dir + '\' + $filename + #save csv report + info ("Report " + "'" + $filePath + "'" + " has been created!") + $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null + return $content +} +Function refactorData ($data) { + $DCResource,$flag = refactorDC $data + $data,$flag = refactorVC $DCResource + return $data, $true +} + +Function refactorDC($data) { + $DCResource = @() + $HostResource = @() + $HR = @{} + $DC = @{} + + $ReData = $data + + $HR.__type__ = $ReData[0].__type__ + $HR.vcname = $ReData[0].vcname + $HR.dcname = $ReData[0].dcname + $HR.hostname = $ReData[0].hostname + $HR.apitype = $ReData[0].apitype + $HR.powerstatus = $ReData[0].powerstatus + $HR.version = $ReData[0].version + $HR.fullname = $ReData[0].fullname + $HR.connectionstatus = $ReData[0].connectionstatus + $HR.ComponentResource = $ReData[0].ComponentResource + $HostResource += $HR # HostResource = [{'hostname':'10.110.126.170'}] + $DC.dcname = $ReData[0].dcname #$DC={'dcname':'ha-datacenter'} + $DC.vcname = $ReData[0].vcname + $DC.HostResource = $HostResource #$DC={'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'}]} + $DC.checkRelease = $ReData[0].checkRelease + + $DCResource += $DC #$DCResource = [{'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'},]}] + $dcname = $ReData[0].dcname + $vcname = $ReData[0].vcname + $DcIndex = 0 + for ($i = 1; $i -lt $ReData.Count; $i++) { + $temp = $ReData[$i] + $HR = @{} + if ($temp.dcname -eq $dcname -and $temp.vcname -eq $vcname) { + $HR.__type__ = $temp.__type__ + $HR.vcname = $temp.vcname + $HR.dcname = $temp.dcname + $HR.hostname = $temp.hostname + $HR.apitype = $temp.apitype + $HR.powerstatus = $temp.powerstatus + $HR.version = $temp.version + $HR.fullname = $temp.fullname + $HR.connectionstatus = $temp.connectionstatus + $HR.ComponentResource = $temp.ComponentResource + $DCResource[$DcIndex].HostResource += $HR + } + else { + $DcIndex += 1 + $DCResource += @{} #$DCResource = [{'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'},{'hostname':'10.110.126.171'}]},{}] + $DCResource[$DcIndex].dcname = $temp.dcname # [{'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'},{'hostname':'10.110.126.171'}]},{'dcname':'hw-datacenter'}] + $DCResource[$DcIndex].vcname = $temp.vcname + $DCResource[$DcIndex].checkRelease = $temp.checkRelease + $DCResource[$DcIndex].HostResource = @() # [{'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'},{'hostname':'10.110.126.171'}]},{'dcname':'hw-datacenter','HostResource':[]}] + $HR = @{} + $HR.__type__ = $temp.__type__ + $HR.vcname = $temp.vcname + $HR.dcname = $temp.dcname + $HR.hostname = $temp.hostname + $HR.apitype = $temp.apitype + $HR.powerstatus = $temp.powerstatus + $HR.version = $temp.version + $HR.fullname = $temp.fullname + $HR.connectionstatus = $temp.connectionstatus + $HR.ComponentResource = $temp.ComponentResource + $DCResource[$DcIndex].HostResource += $HR # [{'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'},{'hostname':'10.110.126.171'}]},{'dcname':'hw-datacenter','HostResource':[{'hostname':'10.110.126.173'}]}] + $dcname = $temp.dcname + $vcname = $temp.vcname + } + } + return $DCResource,$true + # return $DCResource +} + +Function refactorVC ($data) { + $VCResource = @() + $DCResource = @() + $VC = @{} + $DCResource += $data[0] + $VC.DCResource = $DCResource + $VC.hostname = $data[0].vcName + $VC.checkRelease = $data[0].checkRelease + + $VCResource += $VC + $vcname = $data[0].vcname + $VcIndex = 0 + for ($i = 1 ; $i -lt $data.Count; $i++){ + $temp = $data[$i] + if ($vcname -eq $temp.vcname) { + $VCResource[$VcIndex].DCResource += $temp + } + else { + $VcIndex += 1 + $DCResource = @() + $VC = @{} + $DCResource += $temp + $VC.hostname = $temp.vcName + $VC.DCResource = $DCResource + $VC.checkRelease = $temp.checkRelease + $VCResource += $VC + $vcname = $temp.vcname + } + } + return $VCResource,$true +} + +Function vcName($Data) { + $vcName = '' + foreach ($VCResource in $Data) { + $vcName += $VCResource.hostname + $vcName += '_' + } + return $vcName +} + +Function checkVersion($Data) { + foreach ($VCResource in $Data) { + $checkVersion = $VCResource.checkRelease + return $checkVersion + } +} + +Function formatStatus($status) { + if ($status -eq 'MayNotBeCompatible') { + return 'May Not Be Compatible' + } + else { + return $status + } +} + +Function formatHostCountGraphic($dataDict) { + while ($dataDict.MoveNext()) { + $items = $dataDict.Key + + if ($items -eq 'Compatible') { + $colors = 'colorsC' + } + elseif ($items -eq 'May Not Compatible') { + $colors = 'colorsM' + } + elseif ($items -eq 'Unable to upgrade') { + $colors = 'colorsU' + } + + $content += $hostCountBody + $items = "'{0}'" -f $items + $content += 'name: {0},' -f $items + $content += 'data: {0},' -f $dataDict.Value + $content += 'color: {0},' -f $colors + $content += '},' + } + + return $content +} + + +#Detail report +$generalHead = @' + + + + + + + + + ESXi Compatible Report + + + +'@ + +$generalBodyBase = @' +

[WARNING] The compatible status may not be fully accurate, please validate it with the official VMware Compatibility Guide

+ + +
+ + + + + + + + + + +'@ + +$generalBodyRest = @' + + + + + + +'@ + +$generalFooter = @' + +
VCDataCenterHostTypeModel NameVendorCompatible StatusHardware DetailComments
+
+ + + +'@ + + +#Summary report +$summaryHead = @' + + + + + Summary Report + + + + + + + +
+
+
+
+
+ +
+ + +'@ + diff --git a/Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 b/Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 new file mode 100644 index 0000000..229608f --- /dev/null +++ b/Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 @@ -0,0 +1,310 @@ +<# +Copyright 2018 VMware, Inc. All rights reserved. +#> + +# Class to manage Host resources +Class HostResource { + [VMware.VimAutomation.Types.VMHost] $vmhost + [string] $vcname + [string] $clustername + [string] $dcname + [string] $hostname + [string] $apitype + [string] $powerstatus + [string] $productname + [string] $version + [string] $fullname + [string] $connectionstatus + [string] $checkRelease + [int] $port + [Array] $ComponentResource = @() + [Array] $JsonProperties = @('__type__', 'dcname', 'vcname','clustername','hostname', 'apitype', + 'powerstatus', 'productname', 'version', 'fullname', 'connectionstatus','checkRelease') + + HostResource( + [VMware.VimAutomation.Types.VMHost] $vmhost) { + $this.vmhost = $vmhost + $view =$vmhost|Get-View + $vCenter_IP = $view.Summary.ManagementServerIp + if($vCenter_IP){ + $this.vcname =$vCenter_IP + $this.dcname = (Get-Datacenter -VMHost $vmhost).Name + $this.clustername = (Get-Cluster -VMHost $vmhost).Name + }else{ + $this.vcname =$this.vmhost.Name + } + $this.hostname = $this.vmhost.Name + $summary = $this.vmhost.ExtensionData.Summary + $this.powerstatus = $summary.runtime.powerState + $this.connectionstatus = $summary.runtime.connectionState + $this.apitype = $summary.Config.Product.apiType + $this.fullname = $summary.Config.Product.FullName + $this.version = $summary.Config.Product.version + $this.productname = $summary.Config.Product.licenseProductName + $this.port = 443 + } + + [Array] query_components() { + if ($this.ComponentResource.Count -eq 0) { + # Get server info + for($count_retry=0;$count_retry -lt 3;$count_retry ++){ + try{ + $svrResoure = [ServerResource]::new() + $svrResoure.set_data($this.vmhost) + $this.ComponentResource += $svrResoure + break + }catch{ + error('query components server for '+$this.vmhost.Name +' error, retry it ' +($count_retry+1) +' times') + } + } + # Get PCI devices + for($count_retry=0;$count_retry -lt 3;$count_retry ++){ + try{ + $this.query_pcidevices() + break + }catch{ + error('query components pcidevice for '+$this.vmhost.Name +' error, retry it ' +($count_retry+1) +' times') + if($count_retry -eq 2){ + error('query components pcidevice for '+$this.vmhost.Name +' faild') + } + } + } + } + return $this.ComponentResource + } + + [void] query_pcidevices() { + $EsxCliV2 = Get-EsxCli -V2 -VMHost $this.vmhost + $AllPciDevice = $EsxCliV2.hardware.pci.list.invoke() + foreach ($Pci in $AllPciDevice) { + # Ignore USB controllers, iLO/iDRAC devices + if ($Pci.DeviceName -like "*USB*" -or $Pci.DeviceName -like "*iLO*" -or $Pci.DeviceName -like "*iDRAC*") { + continue + } + # Get the NICs and storage adapters. + # We found NIC and storage adapters usually have module ID other than 0 or 1 + $pciDevice = [IoDeviceResource]::new() + if ($Pci.ModuleID -ne 0 -and $Pci.ModuleID -ne -1) { + if (!$this.is_pcidevice_exist($Pci)) { + $pciDevice.set_data($Pci, $EsxCliV2) + $this.ComponentResource += $pciDevice + } + } + } + } + + [boolean] is_pcidevice_exist($device) { + foreach ($pci in $this.ComponentResource) { + if ($pci.psobject.TypeNames[0] -eq "IoDeviceResource") { + $vid = [String]::Format("{0:x4}", [int]$device.VendorID) + $did = [String]::Format("{0:x4}", [int]$device.DeviceID) + $svid = [String]::Format("{0:x4}", [int]$device.SubVendorID) + $ssid = [String]::Format("{0:x4}", [int]$device.SubDeviceID) + if ($pci.vid -eq $vid -and $pci.did -eq $did -and + $pci.svid -eq $svid -and $pci.ssid -eq $ssid) { + return $true + } + } + } + return $false + } + + [object] to_jsonobj() { + $Json = $this | Select-Object -Property $this.JsonProperties + $ComponentChildren = @() + $this.ComponentResource | ForEach-Object {$ComponentChildren += $_.to_jsonobj()} + $Json | Add-Member -Name "ComponentResource" -Value $ComponentChildren -MemberType NoteProperty + + return $Json + } + + [string] get_host_status() { + if ($this.powerstatus -and $this.powerstatus -ne 'unknown') { + return $this.powerstatus + } + if ($this.connectionstatus) { + return ("Server " + $this.connectionstatus) + } + else { + return "Server status is unknown" + } + } + + [string] get_prompt_name() { + if ($this.apitype) { + $start = $this.apitype + } + else { + $start = "Host" + } + return $start + " " + $this.hostname + } +} + + +# Class to manage server resources +Class ServerResource { + [string] $type + [string] $model + [string] $vendor + [string] $biosversion + [string] $cpumodel + [string] $cpufeatureid + [string] $uuid + [string] $status + [array] $matchResult + [array] $warnings + [string] $vcgLink + [array] $updateRelease + + [VMware.VimAutomation.Types.VMHost] $vmhost + [Array] $JsonProperties = @('__type__','type', 'model', 'vendor', 'biosversion', + 'cpumodel', 'cpufeatureid', 'uuid','status','matchResult','warnings','vcgLink','updateRelease') + + + [void] set_data( + [VMware.VimAutomation.Types.VMHost] $vmhost) { + $this.vmhost = $vmhost + $this.type = "Server" + $this.model = $this.vmhost.Model + $this.vendor = $this.vmhost.Manufacturer + $this.biosversion = $this.vmhost.ExtensionData.Hardware.BiosInfo.BiosVersion + $this.cpumodel = $this.vmhost.ProcessorType + $cpuFeature = $this.vmhost.ExtensionData.Hardware.CpuFeature + if ($cpuFeature -and $cpuFeature.Count -gt 2) { + $this.cpufeatureid = $this.vmhost.ExtensionData.Hardware.CpuFeature[1].Eax + } + $this.uuid = $this.vmhost.ExtensionData.Hardware.systeminfo.uuid + } + + [object] to_jsonobj() { + return $this | Select-Object -Property $this.JsonProperties + } + +} + +# Class to manage each IO device +Class IoDeviceResource { + + [string] $type + [string] $model + [string] $deviceid + [string] $device + [string] $comptype + [string] $vid + [string] $did + [string] $svid + [string] $ssid + [string] $pciid + [string] $vendor + [string] $driver + [string] $driverversion + [string] $firmware + [string] $status + [array] $matchResult + [array] $warnings + [string] $vcgLink + [array] $updateRelease + + [Array] $JsonProperties = @('__type__','type', 'model', 'deviceid', 'device', + 'comptype', 'vid', 'did', 'svid', 'ssid', 'pciid', + 'vendor', 'driver', 'driverversion', 'firmware','status','matchResult','warnings','vcgLink','updateRelease') + + [void] set_data( + [object] $pci, + [object] $EsxCli) { + $this.type = "IO Device" + $this.model = $Pci.DeviceName + $this.deviceid = $pci.Address + $this.device = $pci.VMKernelName + $this.vid = [String]::Format("{0:x4}", [int]$Pci.VendorID) + $this.did = [String]::Format("{0:x4}", [int]$Pci.DeviceID) + $this.svid = [String]::Format("{0:x4}", [int]$Pci.SubVendorID) + $this.ssid = [String]::Format("{0:x4}", [int]$Pci.SubDeviceID) + $this.pciid = $this.vid + ":" + $this.did + ":" + $this.svid + ":" + $this.ssid + $this.vendor = $pci.VendorName + $this.driver = $Pci.ModuleName + $this.driverversion = "N/A" + $this.firmware = "N/A" + + + # Set component type and driverversion, firmware + if ($this.device -match 'nic') { + $arg = @{} + $arg['nicname'] = $this.device + $nic = $EsxCli.network.nic.get.invoke($arg) + $this.comptype = "Physical NIC" + $this.driverversion = $nic.driverinfo.Version + $this.firmware = $nic.driverinfo.FirmwareVersion + } + elseif ($this.device -match 'hba') { + $arg = @{} + $arg['module'] = $this.driver + $module = $EsxCli.system.module.get.invoke($arg) + $this.comptype = "Storage Adapter" + $this.driverversion = $module.Version + } + } + + [object] to_jsonobj() { + return $this | Select-Object -Property $this.JsonProperties + } + + [string] get_id_detail() { + return $this.driver + " (PCIId:" + $this.pciid + ")" + } +} + +# Class to manage IO device group +Class IoDeviceResourceGroup { + [Array] $iodevices = @() + [Array] $nics = @() + [Array] $adapters = @() + + [void] append_nic([IODeviceResource] $nic) { + $this.iodevices += $nic + $this.nics += $nic + } + + [void] append_storage_adapter([IODeviceResource] $adapter) { + $this.iodevices += $adapter + $this.adapters += $adapter + } + + [boolean] has_nics() { + return $this.nics.Count > 0 + } + + [boolean] has_storage_adapters() { + return $this.adapters.Count > 0 + } + +} + + +# +# Collect hardware inventory data from all the hosts +# +Function Get-VCGHWInfo { + Param( + [Parameter(Mandatory=$true)] $vmHosts + ) + # Collect the hardware data + $Data = @() + foreach($vmHost in $vmHosts) { + $vm = [HostResource]::new($vmHost) + try { + info ("Collecting hardware data from " + $vm.hostname) + $null = $vm.query_components() + if($vm.powerstatus -eq 'poweredOn' -and $vm.connectionstatus -eq 'connected'){ + $Data += $vm + info ("Collecting hardware data from " + $vm.hostname +' success') + } + } + catch { + error ("Failed to collect hardware data from " + $vm.hostname) + } + } + + return $Data +} \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 b/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 new file mode 100644 index 0000000..426d6ce --- /dev/null +++ b/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 @@ -0,0 +1,168 @@ +$Uuid = [guid]::NewGuid() +$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" +$Headers.add("x-request-id", $Uuid) +$Headers.add("x-api-toolid", "180209100001") +$Headers.add("x-api-key", "SJyb8QjK2L") +$Url_Perfix = 'https://apigw.vmware.com/m4/compatibility/v1' +$Url = $Url_Perfix + "/compatible/servers/search?" +$UrlPci = $Url_Perfix + "/compatible/iodevices/search?" +$apiQurryDict=@{} + +# +# Ping remote api server. +# +Function PingApiServer(){ + $apiServerIp='apigw.vmware.com' + $results =Test-Connection $apiServerIp -Quiet + if($results -ne $true){ + error ("Failed to access VMware Compatibility API, + Unable to use comparison function, only view basic hardware information; + you can use 'Get-VCGHWInfo -g ' create hardware json, + then use 'Check-VCGStatus -f ' load hardware json file to comapre when connect an available network") + Exit(1) + } +} + +# +# Get the web request. +# +Function Get-WebRequest($VCGurl) { + try { + $req = Invoke-WebRequest -Headers $Headers -Uri $VCGUrl -ErrorVariable $err -UseBasicParsing + } + catch { + if ($err[0].errorrecord.exception.response) { + error ("WebReponse code:" + $err[0].errorrecord.exception.response.statuscode.value__) + error ($exitScript) + Exit(1) + } + else { + error ("Failed to check " + $type + " data for " + $HostResource.hostname) + error ("Failed to access VMware Compatibility API, please check your Internet connection or contact VMware Compatibility API administrator") + error ("Exit the script") + Exit(1) + } + } + return $req +} + +Function Get-RemoteApiTitleString([object]$device,$EsxiVersion){ + if ($device.type -eq 'Server') { + $Title = $device.model + $device.vendor + $device.cpufeatureid + $device.biosversion +$EsxiVersion + } + else{ + $Title = $device.vid + $device.did + $device.Svid + $device.Ssid + $EsxiVersion + } + return $Title +} + +Function Get-ResponseFromApi([object]$device,$EsxiVersion){ + if ($device.type -eq 'Server') { + $VCGUrl = $Url + "model=" + $device.model + "&releaseversion=" + $EsxiVersion ` + + "&vendor=" + $device.vendor + "&cpuFeatureId=" + $device.cpufeatureid ` + + "&bios=" + $device.biosversion + debug ("Model:" + $device.model) + debug ("VCG Url:" + $VCGUrl) + $Headers.GetEnumerator() | ForEach-Object {debug ("Req Header:" + $_.key + ":" + $_.value)} + $request = Get-WebRequest $VCGUrl + $Response = ConvertFrom-Json -InputObject $request -Erroraction 'silentlycontinue' + } + elseif ($device.type -eq 'IO Device') { + $VCGUrl = $UrlPci + "vid=0X" + $device.vid + "&did=0X" + $device.did + "&svid=0X" + $device.Svid ` + + "&ssid=0X" + $device.Ssid + "&releaseversion=" + $EsxiVersion ` + + "&driver=" + $device.Driver + "&driverversion=" + $device.driverversion + "&firmware=N/A" + debug ("Model:" + $device.model) + debug ("VCG Url:" + $VCGUrl) + $Headers.GetEnumerator() | ForEach-Object {debug ("Req Header:" + $_.key + ":" + $_.value)} + $request = Get-WebRequest $VCGUrl + $Response = ConvertFrom-Json -InputObject $request -Erroraction 'silentlycontinue' + } + return $Response +} +# +# Get the data from api +# +Function Get-VCGData($HostResource) { + foreach ($device in $HostResource.ComponentResource) { + if ($HostResource.checkRelease) { + $EsxiVersion = $HostResource.checkRelease + } + else { + $EsxiVersion = $HostResource.version + } + $temp=0 + $title=Get-RemoteApiTitleString $device $EsxiVersion + if($apiQurryDict.Count -eq 0){ + $Response= Get-ResponseFromApi $device $EsxiVersion + $apiQurryDict.Add($title,$Response) + }else{ + foreach($onetitle in $apiQurryDict.keys){ + if($onetitle -eq $title){ + $Response= $apiQurryDict[$onetitle] + $temp=1 + break + } + } + if($temp -eq 0){ + $Response= Get-ResponseFromApi $device $EsxiVersion + $apiQurryDict.Add($title,$Response) + } + } + + if ($Response.matches) { + foreach ($match in $Response.matches) { + $device.vcgLink += [string]$match.vcgLink + } + } + else { + foreach ($potentialMatche in $Response.potentialMatches) { + $device.vcgLink += [string]$potentialMatche.vcgLink + } + } + $device.status = [string]$Response.searchResult.status + $device.matchResult = [string]$Response.searchResult.matchResult + $device.warnings = $Response.searchResult.warnings + $device.updateRelease = [string]$Response.searchOption.foundRelease + } +} + +# +# Send the hardware data to VCG API and handle returned result +# +Function Get-DataFromRemoteApi([object]$servers) { + info ("Checking hardware compatibility result with VMware Compatibility Guide API...") + info ("This may take a few minutes depending on your network.") + for ($idx = 0; $idx -lt $servers.Count; $idx++) { + $server = $servers[$idx] + $i = $idx + 1 + info ([string]$i + "/" + [string]$servers.Count + " - Checking hardware compatibility results for " + $server.hostname) + if (!$server -or $server.ComponentResource.Count -eq 0) { + error('Failed to get the hardware info.') + Exit(1) + } + Get-VCGData $server + } + return $servers +} + +Function Get-VCGStatus{ + Param( + [Parameter(Mandatory=$true)] $Data, + [Parameter(Mandatory=$false)] $Version + ) + $checkRelease = $Version + PingApiServer + + foreach ($vmHost in $Data) { + # $vmHost|add-member -Name "checkRelease" -value $checkRelease -MemberType NoteProperty -Force + $vmHost.checkRelease=$checkRelease + } + + $results = Get-DataFromRemoteApi($Data) + if ($results.Count -eq 0) { + error ("Failed to get compatibility results. No report will be generated") + error ("Exit the script") + Exit(1) + } + return $results +} \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/README.md b/Modules/VMware.VCGChecker/README.md new file mode 100644 index 0000000..79007d4 --- /dev/null +++ b/Modules/VMware.VCGChecker/README.md @@ -0,0 +1,41 @@ +# About +This module is designed to ease the work of collecting hardware inventory data and compare it with VMware's official VCG data. Before deploying vSphere, it is required to validate your physical machines with VCG to make sure all the devices in your physical machines are compatible with the vSphere version you want to install. It is a time-consuming and painful experience to collect hardware/driver/firmware data from all of the machines, especially when you have a huge number of machines in your data center. + +# How It Works +By using this module, it will automate the data collection and comparison work. + +When running the module, it will connect to the target vCenter or ESXi to read the hardware data. It is a read-only operation and nothing on the target hosts will be changed. There is almost no impact on the machine's performance as the read operation takes just few seconds. + +The module will then send your hardware inventory data to VMware's offical website to conduct a compatibility check. The result will be 'Compatible', 'May not be compatible' or 'Not compatible'. +* Compatible: the hardware is compatible with the given vSphere release. Link to that VCG page will be provided. +* May not be compatible: manual check is required to confirm the compatibility status of this hardware. A few potential matching VCG records will be provided. +* Not compatible: the hardware is not compatible with the given vSphere release. + +After the checking is completed, the module will generate reports in different formats for your review and future use. A summary view in html will give you an overview of your machines compatibility status; an html file with device details to view each device/driver/firmware you have, their compatibility with vSphere version you specified and links to the corresponding VCG documents online; a csv file with device details to allow customization on report in Excel or by your own tool. + +# Usage +Considering many data center may have control on internet access, we create 3 cmdlets to meet various situations. +* Get-VCGHWInfo: cmdlet to collect hardware info +* Get-VCGStatus: cmdlet to check hardware compatibility by query VCG website +* Export-VCGReport: cmdlet to export the summary/html/csv reports + +1. You need to first import this module after you import PowerCLI module +PS> Import-Module <path_to_VMware.VCGChecker.psd1> + +2. Connect to the target vSphere hosts using Connect-VIServer and get VMHosts +PS> Connect-VIServer -Server <server> -User <username> -Password <password> +PS> $vmhosts = Get-VMHost + +3. Collect the hardware data +PS> $hwdata = Get-VCGHWInfo -vmHosts $vmhosts +Note: if you don't have internet access, you need to connect your client to internet before proceeding to the next step. + +4. Specify the target vSphere release you want to check and submit the hardware data to VMware website +PS> $vcgdata= Get-VCGStatus -Data $hwdata -Version '<release>' + +5. Save the compatibility reports +PS> Export-VCGReport -Data $vcgdata -Dir <dir> + +# Known Limitation +* The module is not able to get the firmware version for HBA devices. +* The module is not able to get the HDD/SSD data. diff --git a/Modules/VMware.VCGChecker/Save-VCGJsonFile.ps1 b/Modules/VMware.VCGChecker/Save-VCGJsonFile.ps1 new file mode 100644 index 0000000..785fc00 --- /dev/null +++ b/Modules/VMware.VCGChecker/Save-VCGJsonFile.ps1 @@ -0,0 +1,17 @@ +Function Save-VCGJsonFile{ + Param( + [Parameter(Mandatory=$true)] $FileName, + [Parameter(Mandatory=$true)] $Data, + [Parameter(Mandatory=$true)] $Dir + ) + $json = @() + $Data | ForEach-Object { $json += $_.to_jsonobj()} + + if (!(Test-Path $Dir)) { + New-Item -Type directory -Confirm:$false -Path $Dir -Force |Out-Null + } + + $Path= $Dir + '\' + $FileName + '.json' + info ("Saving data to " + $Path) + ConvertTo-Json -Depth 10 -Compress $json | Out-File -encoding 'UTF8' -FilePath $Path +} \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/VMware.VCGChecker.psd1 b/Modules/VMware.VCGChecker/VMware.VCGChecker.psd1 new file mode 100644 index 0000000..12493af --- /dev/null +++ b/Modules/VMware.VCGChecker/VMware.VCGChecker.psd1 @@ -0,0 +1,90 @@ +# +# Module manifest for module 'VMware.VCGChecker' +# +# Generated by: fdai@vmware.com, zhangta@vmware.com, linweij@vmware.com +# +# Generated on: 11/15/18 +# + +@{ + + # Script module or binary module file associated with this manifest. + # RootModule = 'VMware.VCGChecker.psm1' + + # Version number of this module. + ModuleVersion = '1.0.0' + + # Supported PSEditions + # CompatiblePSEditions = @() + + # ID used to uniquely identify this module + # GUID = '' + + # Author of this module + Author = 'Frank Dai, Tao Zhang, Linwei Jiang' + + # Company or vendor of this module + CompanyName = 'VMware' + + # Copyright statement for this module + Copyright = '(c) 2018 VMware. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'PowerShell Module for Checking Hardware Compatibility Status' + + RequiredModules = @('VMware.VimAutomation.Core') + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + NestedModules = 'Get-VCGHWInfo.ps1','Get-VCGStatus.ps1','Export-VCGReport.ps1', 'Save-VCGJsonFile.ps1', 'logger.ps1' + + # 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 = 'Get-VCGHWInfo', 'Get-VCGStatus', 'Export-VCGReport', 'Save-VCGJsonFile' + # 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 = '' + + } # 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 = '' + + } \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/logger.ps1 b/Modules/VMware.VCGChecker/logger.ps1 new file mode 100644 index 0000000..686611a --- /dev/null +++ b/Modules/VMware.VCGChecker/logger.ps1 @@ -0,0 +1,112 @@ +<# +Copyright 2018 VMware, Inc. All rights reserved. + +#> + +# Messages +$HEADER_OK = "[OK] " +$HEADER_INFO = "[INFO] " +$HEADER_WARNING = "[WARNING] " +$HEADER_ERR = "[ERROR] " + +Class DebugLog +{ + # Static variables of the logger class + static [string] $CAFILE_PATH = "./.certs/" + + [boolean] $debug + [string] $logfile + + DebugLog() + { + $this.debug = $false + $this.logfile = $null + if (!(Test-Path $this::CAFILE_PATH)) + { + New-Item -Type directory -Confirm:$false -Path $this::CAFILE_PATH + } + } + + [void] SetDebug( + [boolean] $debug, + [string] $hostname + ){ + if (!$hostname) {$hostname = ''} + $this.debug = $debug + if ($this.debug) + { + $this.logfile = $this::CAFILE_PATH + $hostname + [DateTime]::Now.ToString("_yyyy-MM-dd_HH-mm") + ".log" + }else{ + $this.logfile = $null + } + } + + [void] log_vars( + [string] $message, + [object] $var + ){ + $this.log($message + $var) + } + + [void] log( + [string] $message + ){ + if (!$this.debug -or !$this.logfile) {return} + try + { + $message | Out-File $this.logfile -Append + }catch { + Out-Host -InputObject ("[Exception] Failed to write to a logfile: " + $this.logfile) + Out-Host -InputObject $_ + } + } +} + +Function debug_vars( + [string] $message, + [object] $var) +{ + $logger.log_vars($message, $var) +} + +Function debug( + [string] $message) +{ + $logger.log($message) +} + +Function vcglog( + [string] $message, + [string] $header="") +{ + $msg = $header + $message + $logger.log($msg) + Out-Host -InputObject $msg +} + +Function ok( + [string] $message) +{ + vcglog $message $HEADER_OK +} + +Function warning( + [string] $message) +{ + vcglog $message $HEADER_WARNING +} + +Function info( + [string] $message) +{ + vcglog $message $HEADER_INFO +} + +Function error( + [string] $message) +{ + vcglog $message $HEADER_ERR +} + +$logger = [DebugLog]::new() +$logger.SetDebug($true, "vcc-debug") \ No newline at end of file diff --git a/Modules/VMware.VMC/VMware.VMC.psd1 b/Modules/VMware.VMC/VMware.VMC.psd1 index b33fca9..105fec0 100755 Binary files a/Modules/VMware.VMC/VMware.VMC.psd1 and b/Modules/VMware.VMC/VMware.VMC.psd1 differ diff --git a/Modules/VMware.VMC/VMware.VMC.psm1 b/Modules/VMware.VMC/VMware.VMC.psm1 index b6c8541..33f78a7 100644 --- a/Modules/VMware.VMC/VMware.VMC.psm1 +++ b/Modules/VMware.VMC/VMware.VMC.psm1 @@ -1,1048 +1,1427 @@ -Function Get-VMCCommand { -<# - .NOTES - =========================================================================== - Created by: VMware - Date: 11/17/2017 - Organization: VMware - Blog: http://vmware.com/go/powercli - Twitter: @powercli - =========================================================================== - - .SYNOPSIS - Returns all cmdlets for VMware Cloud on AWS - .DESCRIPTION - This cmdlet will allow you to return all cmdlets included in the VMC module - .EXAMPLE - Get-VMCCommand - .EXAMPLE - Get-Command -Module VMware.VMC - .NOTES - You can either use this cmdlet or the Get-Command cmdlet as seen in Example 2 -#> - Get-command -Module VMware.VimAutomation.Vmc - Get-Command -Module VMware.VMC - -} -Function Connect-VMCVIServer { -<# - .NOTES - =========================================================================== - Created by: VMware - Date: 11/17/2017 - Organization: VMware - Blog: http://vmware.com/go/powercli - Twitter: @powercli - =========================================================================== - - .SYNOPSIS - Cmdlet to connect to your VMC vCenter Server - .DESCRIPTION - This will connect you to both the VMC ViServer as well as the CiSServer at the same time. - .EXAMPLE - Connect-VMCVIServer -Server -User -Password - .NOTES - Easiest way is to pipe through your credentials from Get-VMCSDDCDefaultCredential -#> - Param ( - [Parameter(Mandatory=$true)]$Org, - [Parameter(Mandatory=$true)]$Sddc, - [switch]$Autologin - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - $creds = Get-VMCSDDCDefaultCredential -Org $Org -Sddc $Sddc - Write-Host "Connecting to VMC vCenter Server" $creds.vc_public_ip - Connect-VIServer -Server $creds.vc_public_ip -User $creds.cloud_username -Password $creds.cloud_password | Add-Member -MemberType Noteproperty -Name Location -Value "VMC" - Write-Host "Connecting to VMC CIS Endpoint" $creds.vc_public_ip - Connect-CisServer -Server $creds.vc_public_ip -User $creds.cloud_username -Password $creds.cloud_password | Add-Member -MemberType Noteproperty -Name Location -Value "VMC" - } -} -Function Get-VMCOrg { -<# - .NOTES - =========================================================================== - Created by: VMware - Date: 11/17/2017 - Organization: VMware - Blog: http://vmware.com/go/powercli - Twitter: @powercli - =========================================================================== - - .SYNOPSIS - Return the Orgs that you are a part of - .DESCRIPTION - Depending on what you've purchased, you may be a part of one or more VMC Orgs. This will return your orgs - .EXAMPLE - Get-VMCOrg - .EXAMPLE - Get-VMCOrg -Name - .NOTES - Return all the info about the orgs you are a part of -#> - Param ( - [Parameter(Mandatory=$false)]$Name - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use Connect-VMC to connect" } Else { - $orgService = Get-VMCService com.vmware.vmc.orgs - if ($PSBoundParameters.ContainsKey("Name")){ - $orgs = $orgService.list() | Where {$_.display_name -match $Name} - } Else { - $orgs = $orgService.list() - } - $Orgs | Select display_name, name, user_name, created, id - } -} -Function Get-VMCSDDC { -<# - .NOTES - =========================================================================== - Created by: VMware - Date: 11/17/2017 - Organization: VMware - Blog: http://vmware.com/go/powercli - Twitter: @powercli - =========================================================================== - - .SYNOPSIS - Returns all of the SDDCs you are associated to - .DESCRIPTION - Returns all of the SDDCs ayou are associated to - .EXAMPLE - Get-VMCSDDC -Org - .EXAMPLE - Get-VMCSDDC -Name -Org -#> - Param ( - [Parameter(Mandatory=$True)]$Org, - [Parameter(Mandatory=$false)]$Name - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - if ($PSBoundParameters.ContainsKey("Org")){ - $orgs = Get-VMCOrg -Name $Org - } else { - $orgs = Get-VMCOrg - } - - foreach ($org in $orgs) { - $orgID = $org.ID - $sddcService = Get-VMCService com.vmware.vmc.orgs.sddcs - if ($PSBoundParameters.ContainsKey("Name")){ - $sddcService.list($OrgID) | Where {$_.name -match $Name} - } Else { - $sddcService.list($OrgID) - } - } - } -} -Function Get-VMCTask { -<# - .NOTES - =========================================================================== - Created by: VMware - Date: 11/17/2017 - Organization: VMware - Blog: http://vmware.com/go/powercli - Twitter: @powercli - =========================================================================== - - .SYNOPSIS - Returns all of the VMC Tasks - .DESCRIPTION - Returns all of the VMC Tasks that have either occurred or are in process - .EXAMPLE - Get-VMCTask -#> - Param ( - [Parameter(Mandatory=$True)]$Org - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - if ($PSBoundParameters.ContainsKey("Org")){ - $orgs = Get-VMCOrg -Name $Org - } else { - $orgs = Get-VMCOrg - } - - foreach ($org in $orgs) { - $orgID = $org.ID - $taskService = Get-VMCService com.vmware.vmc.orgs.tasks - $taskService.list($OrgID) | Select * -ExcludeProperty Help - } - } -} -Function Get-VMCSDDCDefaultCredential { -<# - .NOTES - =========================================================================== - Created by: VMware - Date: 11/17/2017 - Organization: VMware - Blog: http://vmware.com/go/powercli - Twitter: @powercli - =========================================================================== - - .SYNOPSIS - Returns the default credential for the SDDC - .DESCRIPTION - Returns the default credential for the sddc - .EXAMPLE - Get-VMCSDDCDefaultCredential -Org - .EXAMPLE - Get-VMCSDDCDefaultCredential -Sddc -Org -#> - Param ( - [Parameter(Mandatory=$true)]$Org, - [Parameter(Mandatory=$false)]$Sddc - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - if ($PSBoundParameters.ContainsKey("Sddc")){ - $sddcs = Get-VMCSDDC -Name $Sddc -Org $Org - } else { - $sddcs = Get-VMCSDDC -Org $Org - } - - foreach ($sddc in $sddcs) { - $sddc.resource_config | Select-object vc_url, vc_management_ip, vc_public_ip, cloud_username, cloud_password - } - } -} -Function Get-VMCSDDCPublicIP { -<# - .NOTES - =========================================================================== - Created by: VMware - Date: 11/17/2017 - Organization: VMware - Blog: http://vmware.com/go/powercli - Twitter: @powercli - =========================================================================== - - .SYNOPSIS - Returns your Public IPs - .DESCRIPTION - Returns your Public IPs - .EXAMPLE - Get-VMCSDDCPublicIP -Org - .EXAMPLE - Get-VMCSDDCPublicIP -Sddc -Org - .NOTES - Return your Public IPs that you have assigned to your account -#> - Param ( - [Parameter(Mandatory=$true)]$Org, - [Parameter(Mandatory=$false)]$Sddc - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - if ($PSBoundParameters.ContainsKey("Sddc")){ - $sddcs = Get-VMCSDDC -Name $Sddc -Org $Org - } else { - $sddcs = Get-VMCSDDC -Org $Org - } - - foreach ($sddc in $sddcs) { - $sddc.resource_config.Public_ip_pool - } - } -} -Function Get-VMCVMHost { - Param ( - [Parameter(Mandatory=$false)]$Sddc, - [Parameter(Mandatory=$true)]$Org - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - if ($PSBoundParameters.ContainsKey("Sddc")){ - $sddcs = Get-VMCSDDC -Name $Sddc -Org $Org - } else { - $sddcs = Get-VMCSDDC -Org $Org - } - - $results = @() - foreach ($sddc in $sddcs) { - foreach ($vmhost in $sddc.resource_config.esx_hosts) { - $tmp = [pscustomobject] @{ - esx_id = $vmhost.esx_id; - name = $vmhost.name; - hostname = $vmhost.hostname; - esx_state = $vmhost.esx_state; - sddc_id = $sddc.id; - org_id = $sddc.org_id; - } - $results += $tmp - } - $results - } - } -} -Function Get-VMCSDDCVersion { -<# - .NOTES - =========================================================================== - Created by: VMware - Date: 11/17/2017 - Organization: VMware - Blog: http://vmware.com/go/powercli - Twitter: @powercli - =========================================================================== - - .SYNOPSIS - Returns SDDC Version - .DESCRIPTION - Returns Version of the SDDC - .EXAMPLE - Get-VMCSDDCVersion -Name -Org -#> - Param ( - [Parameter(Mandatory=$True)]$Org, - [Parameter(Mandatory=$false)]$Name - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - if ($PSBoundParameters.ContainsKey("Org")){ - $orgs = Get-VMCOrg -Name $Org - } else { - $orgs = Get-VMCOrg - } - - foreach ($org in $orgs) { - $orgID = $org.ID - $sddcService = Get-VMCService com.vmware.vmc.orgs.sddcs - if ($PSBoundParameters.ContainsKey("Name")){ - ($sddcService.list($OrgID) | Where {$_.name -match $Name}).resource_config.sddc_manifest | Select *version - } Else { - ($sddcService.list($OrgID)).resource_config.sddc_manifest | Select *version - } - } - } -} - -Function Get-VMCFirewallRule { - <# - .NOTES - =========================================================================== - Created by: William Lam - Date: 11/19/2017 - Organization: VMware - Blog: https://www.virtuallyghetto.com - Twitter: @lamw - =========================================================================== - - .SYNOPSIS - Retruns VMC Firewall Rules for a given Gateway (MGW or CGW) - .DESCRIPTION - Retruns VMC Firewall Rules for a given Gateway (MGW or CGW) - .EXAMPLE - Get-VMCFirewallRule -OrgName -SDDCName -GatewayType - .EXAMPLE - Get-VMCFirewallRule -OrgName -SDDCName -GatewayType -ShowAll - #> - param( - [Parameter(Mandatory=$false)][String]$SDDCName, - [Parameter(Mandatory=$false)][String]$OrgName, - [Parameter(Mandatory=$false)][Switch]$ShowAll, - [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType - ) - - if($GatewayType -eq "MGW") { - $EdgeId = "edge-1" - } else { - $EdgeId = "edge-2" - } - - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - - $firewallConfigService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config - - $firewallRules = ($firewallConfigService.get($orgId, $sddcId, $EdgeId)).firewall_rules.firewall_rules - if(-not $ShowAll) { - $firewallRules = $firewallRules | where { $_.rule_type -ne "default_policy" -and $_.rule_type -ne "internal_high" -and $_.name -ne "vSphere Cluster HA" -and $_.name -ne "Outbound Access" } | Sort-Object -Property rule_tag - } else { - $firewallRules = $firewallRules | Sort-Object -Property rule_tag - } - - $results = @() - foreach ($firewallRule in $firewallRules) { - if($firewallRule.source.ip_address.Count -ne 0) { - $source = $firewallRule.source.ip_address - } else { $source = "ANY" } - - if($firewallRule.application.service.protocol -ne $null) { - $protocol = $firewallRule.application.service.protocol - } else { $protocol = "ANY" } - - if($firewallRule.application.service.port -ne $null) { - $port = $firewallRule.application.service.port - } else { $port = "ANY" } - - $tmp = [pscustomobject] @{ - ID = $firewallRule.rule_id; - Name = $firewallRule.name; - Type = $firewallRule.rule_type; - Action = $firewallRule.action; - Protocol = $protocol; - Port = $port; - SourceAddress = $source - DestinationAddress = $firewallRule.destination.ip_address; - } - $results+=$tmp - } - $results - } - - Function Export-VMCFirewallRule { - <# - .NOTES - =========================================================================== - Created by: William Lam - Date: 11/19/2017 - Organization: VMware - Blog: https://www.virtuallyghetto.com - Twitter: @lamw - =========================================================================== - - .SYNOPSIS - Exports all "customer" created VMC Firewall Rules to JSON file - .DESCRIPTION - Exports all "customer" created VMC Firewall Rules to JSON file - .EXAMPLE - Export-VMCFirewallRule -OrgName -SDDCName -GatewayType -Path "C:\Users\lamw\Desktop\VMCFirewallRules.json" - #> - param( - [Parameter(Mandatory=$false)][String]$SDDCName, - [Parameter(Mandatory=$false)][String]$OrgName, - [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, - [Parameter(Mandatory=$false)][String]$Path - ) - - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - - if($GatewayType -eq "MGW") { - $EdgeId = "edge-1" - } else { - $EdgeId = "edge-2" - } - - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - - if(-not $orgId) { - Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" - break - } - if(-not $sddcId) { - Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" - break - } - - $firewallConfigService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config - - $firewallRules = ($firewallConfigService.get($orgId, $sddcId, $EdgeId)).firewall_rules.firewall_rules - if(-not $ShowAll) { - $firewallRules = $firewallRules | where { $_.rule_type -ne "default_policy" -and $_.rule_type -ne "internal_high" -and $_.name -ne "vSphere Cluster HA" -and $_.name -ne "Outbound Access" } | Sort-Object -Property rule_tag - } else { - $firewallRules = $firewallRules | Sort-Object -Property rule_tag - } - - $results = @() - $count = 0 - foreach ($firewallRule in $firewallRules) { - if($firewallRule.source.ip_address.Count -ne 0) { - $source = $firewallRule.source.ip_address - } else { - $source = "ANY" - } - - $tmp = [pscustomobject] @{ - Name = $firewallRule.name; - Action = $firewallRule.action; - Protocol = $firewallRule.application.service.protocol; - Port = $firewallRule.application.service.port; - SourcePort = $firewallRule.application.service.source_port; - ICMPType = $firewallRule.application.service.icmp_type; - SourceAddress = $firewallRule.source.ip_address; - DestinationAddress = $firewallRule.destination.ip_address; - Enabled = $firewallRule.enabled; - Logging = $firewallRule.logging_enabled; - } - $count+=1 - $results+=$tmp - } - if($Path) { - Write-Host -ForegroundColor Green "Exporting $count VMC Firewall Rules to $Path ..." - $results | ConvertTo-Json | Out-File $Path - } else { - $results | ConvertTo-Json - } - } - - Function Import-VMCFirewallRule { - <# - .NOTES - =========================================================================== - Created by: William Lam - Date: 11/19/2017 - Organization: VMware - Blog: https://www.virtuallyghetto.com - Twitter: @lamw - =========================================================================== - - .SYNOPSIS - Imports VMC Firewall Rules from exported JSON configuration file - .DESCRIPTION - Imports VMC Firewall Rules from exported JSON configuration file - .EXAMPLE - Import-VMCFirewallRule -OrgName -SDDCName -GatewayType -Path "C:\Users\lamw\Desktop\VMCFirewallRules.json" - #> - param( - [Parameter(Mandatory=$false)][String]$SDDCName, - [Parameter(Mandatory=$false)][String]$OrgName, - [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, - [Parameter(Mandatory=$false)][String]$Path - ) - - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - - if($GatewayType -eq "MGW") { - $EdgeId = "edge-1" - } else { - $EdgeId = "edge-2" - } - - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - - if(-not $orgId) { - Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" - break - } - if(-not $sddcId) { - Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" - break - } - - $firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules - - $vmcFirewallRulesJSON = Get-Content -Raw $Path | ConvertFrom-Json - - # Create top level Firewall Rules Object - $firewallRules = $firewallService.Help.add.firewall_rules.Create() - # Create top top level Firewall Rule Spec which will be an array of individual Firewall rules as we process them in next section - $ruleSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Create() - - foreach ($vmcFirewallRule in $vmcFirewallRulesJSON) { - # Create Individual Firewall Rule Element Spec - $ruleElementSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.Create() - - # AppSpec - $appSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.application.Create() - # ServiceSpec - $serviceSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.application.service.Element.Create() - - $protocol = $null - if($vmcFirewallRule.Protocol -ne $null) { - $protocol = $vmcFirewallRule.Protocol - } - $serviceSpec.protocol = $protocol - - # Process ICMP Type from JSON - $icmpType = $null - if($vmcFirewallRule.ICMPType -ne $null) { - $icmpType = $vmcFirewallRule.ICMPType - } - $serviceSpec.icmp_type = $icmpType - - # Process Source Ports from JSON - $sourcePorts = @() - if($vmcFirewallRule.SourcePort -eq "any" -or $vmcFirewallRule.SourcePort -ne $null) { - foreach ($port in $vmcFirewallRule.SourcePort) { - $sourcePorts+=$port - } - } else { - $sourcePorts = @("any") - } - $serviceSpec.source_port = $sourcePorts - - # Process Ports from JSON - $ports = @() - if($vmcFirewallRule.Port -ne "null") { - foreach ($port in $vmcFirewallRule.Port) { - $ports+=$port - } - } - $serviceSpec.port = $ports - $addSpec = $appSpec.service.Add($serviceSpec) - - # Create Source Spec - $srcSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.source.Create() - $srcSpec.exclude = $false - # Process Source Address from JSON - $sourceAddess = @() - if($vmcFirewallRule.SourceAddress -ne "null") { - foreach ($address in $vmcFirewallRule.SourceAddress) { - $sourceAddess+=$address - } - } - $srcSpec.ip_address = $sourceAddess; - - # Create Destination Spec - $destSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.destination.Create() - $destSpec.exclude = $false - # Process Destination Address from JSON - $destinationAddess = @() - if($vmcFirewallRule.DestinationAddress -ne "null") { - foreach ($address in $vmcFirewallRule.DestinationAddress) { - $destinationAddess+=$address - } - } - $destSpec.ip_address = $destinationAddess - - # Add various specs - if($vmcFirewallRule.Protocol -ne $null -and $vmcFirewallRule.port -ne $null) { - $ruleElementSpec.application = $appSpec - } - - $ruleElementSpec.source = $srcSpec - $ruleElementSpec.destination = $destSpec - $ruleElementSpec.rule_type = "user" - - # Process Enabled from JSON - $fwEnabled = $false - if($vmcFirewallRule.Enabled -eq "true") { - $fwEnabled = $true - } - $ruleElementSpec.enabled = $fwEnabled - - # Process Logging from JSON - $loggingEnabled = $false - if($vmcFirewallRule.Logging -eq "true") { - $loggingEnabled = $true - } - $ruleElementSpec.logging_enabled = $loggingEnabled - - $ruleElementSpec.action = $vmcFirewallRule.Action - $ruleElementSpec.name = $vmcFirewallRule.Name - - # Add the individual FW rule spec into our overall firewall rules array - Write-host "Creating VMC Firewall Rule Spec:" $vmcFirewallRule.Name "..." - $ruleSpecAdd = $ruleSpec.Add($ruleElementSpec) - } - $firewallRules.firewall_rules = $ruleSpec - - Write-host "Adding VMC Firewall Rules ..." - $firewallRuleAdd = $firewallService.add($orgId,$sddcId,$EdgeId,$firewallRules) - } - - Function Remove-VMCFirewallRule { - <# - .NOTES - =========================================================================== - Created by: William Lam - Date: 11/19/2017 - Organization: VMware - Blog: https://www.virtuallyghetto.com - Twitter: @lamw - =========================================================================== - - .SYNOPSIS - Removes VMC Firewall Rule given Rule Id - .DESCRIPTION - Removes VMC Firewall Rule given Rule Id - .EXAMPLE - Remove-VMCFirewallRule -OrgName -SDDCName -GatewayType -RuleId - #> - param( - [Parameter(Mandatory=$false)][String]$SDDCName, - [Parameter(Mandatory=$false)][String]$OrgName, - [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, - [Parameter(Mandatory=$false)][String]$RuleId - ) - - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - - if($GatewayType -eq "MGW") { - $EdgeId = "edge-1" - } else { - $EdgeId = "edge-2" - } - - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - - if(-not $orgId) { - Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" - break - } - if(-not $sddcId) { - Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" - break - } - - $firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules - Write-Host "Removing VMC Firewall Rule Id $RuleId ..." - $firewallService.delete($orgId,$sddcId,$EdgeId,$RuleId) - } - -Function Get-VMCLogicalNetwork { - <# - .NOTES - =========================================================================== - Created by: Kyle Ruddy - Date: 03/06/2018 - Organization: VMware - Blog: https://thatcouldbeaproblem.com - Twitter: @kmruddy - =========================================================================== - - .SYNOPSIS - Retruns VMC Logical Networks for a given SDDC - .DESCRIPTION - Retruns VMC Logical Networks for a given SDDC - .EXAMPLE - Get-VMCLogicalNetwork -OrgName -SDDCName - .EXAMPLE - Get-VMCLogicalNetwork -OrgName -SDDCName -LogicalNetworkName - #> - param( - [Parameter(Mandatory=$true)][String]$SDDCName, - [Parameter(Mandatory=$true)][String]$OrgName, - [Parameter(Mandatory=$false)][String]$LogicalNetworkName - - ) - - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - - if(-not $orgId) { - Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" - break - } - if(-not $sddcId) { - Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" - break - } - - $logicalNetworkService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.logical - - $logicalNetworks = ($logicalNetworkService.get_0($orgId, $sddcId)).data | Sort-Object -Property id - - if($LogicalNetworkName) { - $logicalNetworks = $logicalNetworks | Where-Object {$_.Name -eq $LogicalNetworkName} - } - - $results = @() - foreach ($logicalNetwork in $logicalNetworks) { - $tmp = [pscustomobject] @{ - ID = $logicalNetwork.id; - Name = $logicalNetwork.name; - SubnetMask = $logicalNetwork.subnets.address_groups.prefix_length; - Gateway = $logicalNetwork.subnets.address_groups.primary_address; - DHCPipRange = $logicalNetwork.dhcp_configs.ip_pools.ip_range; - DHCPdomain = $logicalNetwork.dhcp_configs.ip_pools.domain_name; - CGatewayID = $logicalNetwork.cgw_id; - CGateway = $logicalNetwork.cgw_name; - } - $results+=$tmp - } - $results -} - -Function Remove-VMCLogicalNetwork { - <# - .NOTES - =========================================================================== - Created by: Kyle Ruddy - Date: 03/06/2018 - Organization: VMware - Blog: https://thatcouldbeaproblem.com - Twitter: @kmruddy - =========================================================================== - - .SYNOPSIS - Removes Logical Network given ID - .DESCRIPTION - Removes Logical Network given ID - .EXAMPLE - Remove-VMCLogicalNetwork -OrgName -SDDCName -LogicalNetworkName - #> - [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] - param( - [Parameter(Mandatory=$true)][String]$SDDCName, - [Parameter(Mandatory=$true)][String]$OrgName, - [Parameter(Mandatory=$true)][String]$LogicalNetworkName - ) - - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - $lsId = (Get-VMCLogicalNetwork -OrgName $OrgName -SDDCName $SDDCName -LogicalNetworkName $LogicalNetworkName).Id - - if(-not $orgId) { - Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" - break - } - if(-not $sddcId) { - Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" - break - } - if(-not $lsId) { - Write-Host -ForegroundColor red "Unable to find SDDC $LogicalNetworkName, please verify input" - break - } - - $logicalNetworkService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.logical - $logicalNetworkService.delete($orgId,$sddcId,$lsId) -} - -Function New-VMCLogicalNetwork { - <# - .NOTES - =========================================================================== - Created by: Kyle Ruddy - Date: 03/06/2018 - Organization: VMware - Blog: https://thatcouldbeaproblem.com - Twitter: @kmruddy - =========================================================================== - - .SYNOPSIS - Creates a new Logical Network - .DESCRIPTION - Creates a new Logical Network - .EXAMPLE - New-VMCLogicalNetwork -OrgName -SDDCName -LogicalNetworkName -SubnetMask -Gateway - #> - [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] - param( - [Parameter(Mandatory=$true)][String]$SDDCName, - [Parameter(Mandatory=$true)][String]$OrgName, - [Parameter(Mandatory=$true)][String]$LogicalNetworkName, - [Parameter(Mandatory=$true)][String]$SubnetMask, - [Parameter(Mandatory=$true)][String]$Gateway - ) - - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - - if(-not $orgId) { - Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" - break - } - if(-not $sddcId) { - Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" - break - } - - $logicalNetworkService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.logical - $logicalNetworkSpec = $logicalNetworkService.Help.create.sddc_network.Create() - $logicalNetworkSpec.name = $LogicalNetworkName - $logicalNetworkSpec.cgw_id = "edge-2" - $logicalNetworkSpec.cgw_name = "SDDC-CGW-1" - $logicalNetworkAddressGroupSpec = $logicalNetworkService.Help.create.sddc_network.subnets.address_groups.Element.Create() - $logicalNetworkAddressGroupSpec.prefix_length = $SubnetMask - $logicalNetworkAddressGroupSpec.primary_address = $Gateway - - $logicalNetworkSpec.subnets.address_groups.Add($logicalNetworkAddressGroupSpec) | Out-Null - $logicalNetworkService.create($orgId, $sddcId, $logicalNetworkSpec) - Get-VMCLogicalNetwork -OrgName $OrgName -SDDCName $SDDCName -LogicalNetworkName $LogicalNetworkName -} - -Function Get-VMCSDDCSummary { - <# - .NOTES - =========================================================================== - Created by: VMware - Date: 09/04/18 - Organization: VMware - Blog: https://www.virtuallyghetto.com - Twitter: @lamw - =========================================================================== - - .SYNOPSIS - Returns a number of useful informational data about a given SDDC within VMC Org - .DESCRIPTION - Returns Version, Create/Expiration Date, Deployment Type, Region, AZ, Instance Type, VPC CIDR & NSX-T - .EXAMPLE - Get-VMCSDDCSummary -Name -Org - #> - Param ( - [Parameter(Mandatory=$True)]$OrgName, - [Parameter(Mandatory=$True)]$SDDCName - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - $orgId = (Get-VMCOrg -Name $Org).Id - $sddcId = (Get-VMCSDDC -Name $Name -Org $Org).Id - - $sddcService = Get-VmcService "com.vmware.vmc.orgs.sddcs" - $sddc = $sddcService.get($orgId,$sddcId) - - $results = [pscustomobject] @{ - Version = $sddc.resource_config.sddc_manifest.vmc_version; - CreateDate = $sddc.created; - ExpirationDate = $sddc.expiration_date; - DeploymentType = $sddc.resource_config.deployment_type; - Region = $sddc.resource_config.region; - AvailabilityZone = $sddc.resource_config.availability_zones; - InstanceType = $sddc.resource_config.sddc_manifest.esx_ami.instance_type; - VpcCIDR = $sddc.resource_config.vpc_info.vpc_cidr; - NSXT = $sddc.resource_config.nsxt; - } - $results - } -} - -Function Get-VMCPublicIP { - <# - .NOTES - =========================================================================== - Created by: William Lam - Date: 09/12/2018 - Organization: VMware - Blog: http://www.virtuallyghetto.com - Twitter: @lamw - =========================================================================== - - .SYNOPSIS - Retrieves all public IP Addresses for a given SDDC - .DESCRIPTION - This cmdlet retrieves all public IP Address for a given SDDC - .EXAMPLE - Get-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName - #> - Param ( - [Parameter(Mandatory=$True)]$OrgName, - [Parameter(Mandatory=$True)]$SDDCName - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - - $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" - $publicIPs = $publicIPService.list($orgId,$sddcId) - - $publicIPs | select public_ip, name, allocation_id - } -} - -Function New-VMCPublicIP { - <# - .NOTES - =========================================================================== - Created by: William Lam - Date: 09/12/2018 - Organization: VMware - Blog: http://www.virtuallyghetto.com - Twitter: @lamw - =========================================================================== - - .SYNOPSIS - Request a new public IP Address for a given SDDC - .DESCRIPTION - This cmdlet requests a new public IP Address for a given SDDC - .EXAMPLE - New-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -Description "Test for Randy" - #> - Param ( - [Parameter(Mandatory=$True)]$OrgName, - [Parameter(Mandatory=$True)]$SDDCName, - [Parameter(Mandatory=$False)]$Description - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - - $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" - - $publicIPSpec = $publicIPService.Help.create.spec.Create() - $publicIPSpec.count = 1 - $publicIPSpec.names = @($Description) - - Write-Host "Requesting a new public IP Address for your SDDC ..." - $results = $publicIPService.create($orgId,$sddcId,$publicIPSpec) - } -} - -Function Remove-VMCPublicIP { - <# - .NOTES - =========================================================================== - Created by: William Lam - Date: 09/12/2018 - Organization: VMware - Blog: http://www.virtuallyghetto.com - Twitter: @lamw - =========================================================================== - - .SYNOPSIS - Removes a specific public IP Addresses for a given SDDC - .DESCRIPTION - This cmdlet removes a specific public IP Address for a given SDDC - .EXAMPLE - Remove-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -AllocationId "eipalloc-0567acf34e436c01f" - #> - Param ( - [Parameter(Mandatory=$True)]$OrgName, - [Parameter(Mandatory=$True)]$SDDCName, - [Parameter(Mandatory=$True)]$AllocationId - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - - $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" - - Write-Host "Deleting public IP Address with ID $AllocationId ..." - $results = $publicIPService.delete($orgId,$sddcId,$AllocationId) - } -} - -Function Set-VMCSDDC { - <# - .NOTES - =========================================================================== - Created by: William Lam - Date: 01/12/2019 - Organization: VMware - Blog: http://www.virtuallyghetto.com - Twitter: @lamw - =========================================================================== - - .SYNOPSIS - Rename an SDDC - .DESCRIPTION - This cmdlet renames an SDDC - .EXAMPLE - Set-VMCSDDC -SDDC $SDDCName -OrgName $OrgName -Name $NewSDDCName - #> - Param ( - [Parameter(Mandatory=$True)]$SDDCName, - [Parameter(Mandatory=$True)]$OrgName, - [Parameter(Mandatory=$True)]$Name - ) - - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - $sddc = Get-VMCSDDC -Org $OrgName -Name $SDDCName - if($sddc) { - $sddcService = Get-VmcService com.vmware.vmc.orgs.sddcs - $renameSpec = $sddcService.help.patch.sddc_patch_request.Create() - $renameSpec.name = $Name - - Write-Host "`nRenaming SDDC `'$SDDCName`' to `'$Name`' ...`n" - $results = $sddcService.patch($sddc.org_id,$sddc.id,$renameSpec) - } - } -} - -Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', 'Get-VMCSDDCVersion', 'Get-VMCFirewallRule', 'Export-VMCFirewallRule', 'Import-VMCFirewallRule', 'Remove-VMCFirewallRule', 'Get-VMCLogicalNetwork', 'Remove-VMCLogicalNetwork', 'New-VMCLogicalNetwork', 'Get-VMCSDDCSummary', 'Get-VMCPublicIP', 'New-VMCPublicIP', 'Remove-VMCPublicIP', 'Set-VMCSDDC' +Function Get-VMCCommand { +<# + .NOTES + =========================================================================== + Created by: VMware + Date: 11/17/2017 + Organization: VMware + Blog: http://vmware.com/go/powercli + Twitter: @powercli + =========================================================================== + + .SYNOPSIS + Returns all cmdlets for VMware Cloud on AWS + .DESCRIPTION + This cmdlet will allow you to return all cmdlets included in the VMC module + .EXAMPLE + Get-VMCCommand + .EXAMPLE + Get-Command -Module VMware.VMC + .NOTES + You can either use this cmdlet or the Get-Command cmdlet as seen in Example 2 +#> + Get-command -Module VMware.VimAutomation.Vmc + Get-Command -Module VMware.VMC + +} +Function Connect-VMCVIServer { +<# + .NOTES + =========================================================================== + Created by: VMware + Date: 11/17/2017 + Organization: VMware + Blog: http://vmware.com/go/powercli + Twitter: @powercli + =========================================================================== + + .SYNOPSIS + Cmdlet to connect to your VMC vCenter Server + .DESCRIPTION + This will connect you to both the VMC ViServer as well as the CiSServer at the same time. + .EXAMPLE + Connect-VMCVIServer -Server -User -Password + .NOTES + Easiest way is to pipe through your credentials from Get-VMCSDDCDefaultCredential +#> + Param ( + [Parameter(Mandatory=$true)]$Org, + [Parameter(Mandatory=$true)]$Sddc, + [switch]$Autologin + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $creds = Get-VMCSDDCDefaultCredential -Org $Org -Sddc $Sddc + Write-Host "Connecting to VMC vCenter Server" $creds.vc_public_ip + Connect-VIServer -Server $creds.vc_public_ip -User $creds.cloud_username -Password $creds.cloud_password | Add-Member -MemberType Noteproperty -Name Location -Value "VMC" + Write-Host "Connecting to VMC CIS Endpoint" $creds.vc_public_ip + Connect-CisServer -Server $creds.vc_public_ip -User $creds.cloud_username -Password $creds.cloud_password | Add-Member -MemberType Noteproperty -Name Location -Value "VMC" + } +} +Function Get-VMCOrg { +<# + .NOTES + =========================================================================== + Created by: VMware + Date: 11/17/2017 + Organization: VMware + Blog: http://vmware.com/go/powercli + Twitter: @powercli + =========================================================================== + + .SYNOPSIS + Return the Orgs that you are a part of + .DESCRIPTION + Depending on what you've purchased, you may be a part of one or more VMC Orgs. This will return your orgs + .EXAMPLE + Get-VMCOrg + .EXAMPLE + Get-VMCOrg -Name + .NOTES + Return all the info about the orgs you are a part of +#> + Param ( + [Parameter(Mandatory=$false)]$Name + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use Connect-VMC to connect" } Else { + $orgService = Get-VMCService com.vmware.vmc.orgs + if ($PSBoundParameters.ContainsKey("Name")){ + $orgs = $orgService.list() | Where {$_.display_name -match $Name} + } Else { + $orgs = $orgService.list() + } + $Orgs | Select display_name, name, user_name, created, id + } +} +Function Get-VMCSDDC { +<# + .NOTES + =========================================================================== + Created by: VMware + Date: 11/17/2017 + Organization: VMware + Blog: http://vmware.com/go/powercli + Twitter: @powercli + =========================================================================== + + .SYNOPSIS + Returns all of the SDDCs you are associated to + .DESCRIPTION + Returns all of the SDDCs ayou are associated to + .EXAMPLE + Get-VMCSDDC -Org + .EXAMPLE + Get-VMCSDDC -Name -Org +#> + Param ( + [Parameter(Mandatory=$True)]$Org, + [Parameter(Mandatory=$false)]$Name + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + if ($PSBoundParameters.ContainsKey("Org")){ + $orgs = Get-VMCOrg -Name $Org + } else { + $orgs = Get-VMCOrg + } + + foreach ($org in $orgs) { + $orgID = $org.ID + $sddcService = Get-VMCService com.vmware.vmc.orgs.sddcs + if ($PSBoundParameters.ContainsKey("Name")){ + $sddcService.list($OrgID) | Where {$_.name -match $Name} + } Else { + $sddcService.list($OrgID) + } + } + } +} +Function Get-VMCTask { +<# + .NOTES + =========================================================================== + Created by: VMware + Date: 11/17/2017 + Organization: VMware + Blog: http://vmware.com/go/powercli + Twitter: @powercli + =========================================================================== + + .SYNOPSIS + Returns all of the VMC Tasks + .DESCRIPTION + Returns all of the VMC Tasks that have either occurred or are in process + .EXAMPLE + Get-VMCTask +#> + Param ( + [Parameter(Mandatory=$True)]$Org + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + if ($PSBoundParameters.ContainsKey("Org")){ + $orgs = Get-VMCOrg -Name $Org + } else { + $orgs = Get-VMCOrg + } + + foreach ($org in $orgs) { + $orgID = $org.ID + $taskService = Get-VMCService com.vmware.vmc.orgs.tasks + $taskService.list($OrgID) | Select * -ExcludeProperty Help + } + } +} +Function Get-VMCSDDCDefaultCredential { +<# + .NOTES + =========================================================================== + Created by: VMware + Date: 11/17/2017 + Organization: VMware + Blog: http://vmware.com/go/powercli + Twitter: @powercli + =========================================================================== + + .SYNOPSIS + Returns the default credential for the SDDC + .DESCRIPTION + Returns the default credential for the sddc + .EXAMPLE + Get-VMCSDDCDefaultCredential -Org + .EXAMPLE + Get-VMCSDDCDefaultCredential -Sddc -Org +#> + Param ( + [Parameter(Mandatory=$true)]$Org, + [Parameter(Mandatory=$false)]$Sddc + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + if ($PSBoundParameters.ContainsKey("Sddc")){ + $sddcs = Get-VMCSDDC -Name $Sddc -Org $Org + } else { + $sddcs = Get-VMCSDDC -Org $Org + } + + foreach ($sddc in $sddcs) { + $sddc.resource_config | Select-object vc_url, vc_management_ip, vc_public_ip, cloud_username, cloud_password + } + } +} +Function Get-VMCSDDCPublicIP { +<# + .NOTES + =========================================================================== + Created by: VMware + Date: 11/17/2017 + Organization: VMware + Blog: http://vmware.com/go/powercli + Twitter: @powercli + =========================================================================== + + .SYNOPSIS + Returns your Public IPs + .DESCRIPTION + Returns your Public IPs + .EXAMPLE + Get-VMCSDDCPublicIP -Org + .EXAMPLE + Get-VMCSDDCPublicIP -Sddc -Org + .NOTES + Return your Public IPs that you have assigned to your account +#> + Param ( + [Parameter(Mandatory=$true)]$Org, + [Parameter(Mandatory=$false)]$Sddc + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + if ($PSBoundParameters.ContainsKey("Sddc")){ + $sddcs = Get-VMCSDDC -Name $Sddc -Org $Org + } else { + $sddcs = Get-VMCSDDC -Org $Org + } + + foreach ($sddc in $sddcs) { + $sddc.resource_config.Public_ip_pool + } + } +} +Function Get-VMCVMHost { + Param ( + [Parameter(Mandatory=$false)]$Sddc, + [Parameter(Mandatory=$true)]$Org + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + if ($PSBoundParameters.ContainsKey("Sddc")){ + $sddcs = Get-VMCSDDC -Name $Sddc -Org $Org + } else { + $sddcs = Get-VMCSDDC -Org $Org + } + + $results = @() + foreach ($sddc in $sddcs) { + foreach ($vmhost in $sddc.resource_config.esx_hosts) { + $tmp = [pscustomobject] @{ + esx_id = $vmhost.esx_id; + name = $vmhost.name; + hostname = $vmhost.hostname; + esx_state = $vmhost.esx_state; + sddc_id = $sddc.id; + org_id = $sddc.org_id; + } + $results += $tmp + } + $results + } + } +} +Function Get-VMCSDDCVersion { +<# + .NOTES + =========================================================================== + Created by: VMware + Date: 11/17/2017 + Organization: VMware + Blog: http://vmware.com/go/powercli + Twitter: @powercli + =========================================================================== + + .SYNOPSIS + Returns SDDC Version + .DESCRIPTION + Returns Version of the SDDC + .EXAMPLE + Get-VMCSDDCVersion -Name -Org +#> + Param ( + [Parameter(Mandatory=$True)]$Org, + [Parameter(Mandatory=$false)]$Name + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + if ($PSBoundParameters.ContainsKey("Org")){ + $orgs = Get-VMCOrg -Name $Org + } else { + $orgs = Get-VMCOrg + } + + foreach ($org in $orgs) { + $orgID = $org.ID + $sddcService = Get-VMCService com.vmware.vmc.orgs.sddcs + if ($PSBoundParameters.ContainsKey("Name")){ + ($sddcService.list($OrgID) | Where {$_.name -match $Name}).resource_config.sddc_manifest | Select *version + } Else { + ($sddcService.list($OrgID)).resource_config.sddc_manifest | Select *version + } + } + } +} +Function Get-VMCFirewallRule { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 11/19/2017 + Organization: VMware + Blog: https://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Retruns VMC Firewall Rules for a given Gateway (MGW or CGW) + .DESCRIPTION + Retruns VMC Firewall Rules for a given Gateway (MGW or CGW) + .EXAMPLE + Get-VMCFirewallRule -OrgName -SDDCName -GatewayType + .EXAMPLE + Get-VMCFirewallRule -OrgName -SDDCName -GatewayType -ShowAll + #> + param( + [Parameter(Mandatory=$false)][String]$SDDCName, + [Parameter(Mandatory=$false)][String]$OrgName, + [Parameter(Mandatory=$false)][Switch]$ShowAll, + [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType + ) + + if($GatewayType -eq "MGW") { + $EdgeId = "edge-1" + } else { + $EdgeId = "edge-2" + } + + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + $firewallConfigService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config + + $firewallRules = ($firewallConfigService.get($orgId, $sddcId, $EdgeId)).firewall_rules.firewall_rules + if(-not $ShowAll) { + $firewallRules = $firewallRules | where { $_.rule_type -ne "default_policy" -and $_.rule_type -ne "internal_high" -and $_.name -ne "vSphere Cluster HA" -and $_.name -ne "Outbound Access" } | Sort-Object -Property rule_tag + } else { + $firewallRules = $firewallRules | Sort-Object -Property rule_tag + } + + $results = @() + foreach ($firewallRule in $firewallRules) { + if($firewallRule.source.ip_address.Count -ne 0) { + $source = $firewallRule.source.ip_address + } else { $source = "ANY" } + + if($firewallRule.application.service.protocol -ne $null) { + $protocol = $firewallRule.application.service.protocol + } else { $protocol = "ANY" } + + if($firewallRule.application.service.port -ne $null) { + $port = $firewallRule.application.service.port + } else { $port = "ANY" } + + $tmp = [pscustomobject] @{ + ID = $firewallRule.rule_id; + Name = $firewallRule.name; + Type = $firewallRule.rule_type; + Action = $firewallRule.action; + Protocol = $protocol; + Port = $port; + SourceAddress = $source + DestinationAddress = $firewallRule.destination.ip_address; + } + $results+=$tmp + } + $results + } +Function Export-VMCFirewallRule { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 11/19/2017 + Organization: VMware + Blog: https://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Exports all "customer" created VMC Firewall Rules to JSON file + .DESCRIPTION + Exports all "customer" created VMC Firewall Rules to JSON file + .EXAMPLE + Export-VMCFirewallRule -OrgName -SDDCName -GatewayType -Path "C:\Users\lamw\Desktop\VMCFirewallRules.json" + #> + param( + [Parameter(Mandatory=$false)][String]$SDDCName, + [Parameter(Mandatory=$false)][String]$OrgName, + [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, + [Parameter(Mandatory=$false)][String]$Path + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + if($GatewayType -eq "MGW") { + $EdgeId = "edge-1" + } else { + $EdgeId = "edge-2" + } + + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + + $firewallConfigService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config + + $firewallRules = ($firewallConfigService.get($orgId, $sddcId, $EdgeId)).firewall_rules.firewall_rules + if(-not $ShowAll) { + $firewallRules = $firewallRules | where { $_.rule_type -ne "default_policy" -and $_.rule_type -ne "internal_high" -and $_.name -ne "vSphere Cluster HA" -and $_.name -ne "Outbound Access" } | Sort-Object -Property rule_tag + } else { + $firewallRules = $firewallRules | Sort-Object -Property rule_tag + } + + $results = @() + $count = 0 + foreach ($firewallRule in $firewallRules) { + if($firewallRule.source.ip_address.Count -ne 0) { + $source = $firewallRule.source.ip_address + } else { + $source = "ANY" + } + + $tmp = [pscustomobject] @{ + Name = $firewallRule.name; + Action = $firewallRule.action; + Protocol = $firewallRule.application.service.protocol; + Port = $firewallRule.application.service.port; + SourcePort = $firewallRule.application.service.source_port; + ICMPType = $firewallRule.application.service.icmp_type; + SourceAddress = $firewallRule.source.ip_address; + DestinationAddress = $firewallRule.destination.ip_address; + Enabled = $firewallRule.enabled; + Logging = $firewallRule.logging_enabled; + } + $count+=1 + $results+=$tmp + } + if($Path) { + Write-Host -ForegroundColor Green "Exporting $count VMC Firewall Rules to $Path ..." + $results | ConvertTo-Json | Out-File $Path + } else { + $results | ConvertTo-Json + } +} +Function Import-VMCFirewallRule { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 11/19/2017 + Organization: VMware + Blog: https://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Imports VMC Firewall Rules from exported JSON configuration file + .DESCRIPTION + Imports VMC Firewall Rules from exported JSON configuration file + .EXAMPLE + Import-VMCFirewallRule -OrgName -SDDCName -GatewayType -Path "C:\Users\lamw\Desktop\VMCFirewallRules.json" + #> + param( + [Parameter(Mandatory=$false)][String]$SDDCName, + [Parameter(Mandatory=$false)][String]$OrgName, + [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, + [Parameter(Mandatory=$false)][String]$Path + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + if($GatewayType -eq "MGW") { + $EdgeId = "edge-1" + } else { + $EdgeId = "edge-2" + } + + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + + $firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules + + $vmcFirewallRulesJSON = Get-Content -Raw $Path | ConvertFrom-Json + + # Create top level Firewall Rules Object + $firewallRules = $firewallService.Help.add.firewall_rules.Create() + # Create top top level Firewall Rule Spec which will be an array of individual Firewall rules as we process them in next section + $ruleSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Create() + + foreach ($vmcFirewallRule in $vmcFirewallRulesJSON) { + # Create Individual Firewall Rule Element Spec + $ruleElementSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.Create() + + # AppSpec + $appSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.application.Create() + # ServiceSpec + $serviceSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.application.service.Element.Create() + + $protocol = $null + if($vmcFirewallRule.Protocol -ne $null) { + $protocol = $vmcFirewallRule.Protocol + } + $serviceSpec.protocol = $protocol + + # Process ICMP Type from JSON + $icmpType = $null + if($vmcFirewallRule.ICMPType -ne $null) { + $icmpType = $vmcFirewallRule.ICMPType + } + $serviceSpec.icmp_type = $icmpType + + # Process Source Ports from JSON + $sourcePorts = @() + if($vmcFirewallRule.SourcePort -eq "any" -or $vmcFirewallRule.SourcePort -ne $null) { + foreach ($port in $vmcFirewallRule.SourcePort) { + $sourcePorts+=$port + } + } else { + $sourcePorts = @("any") + } + $serviceSpec.source_port = $sourcePorts + + # Process Ports from JSON + $ports = @() + if($vmcFirewallRule.Port -ne "null") { + foreach ($port in $vmcFirewallRule.Port) { + $ports+=$port + } + } + $serviceSpec.port = $ports + $addSpec = $appSpec.service.Add($serviceSpec) + + # Create Source Spec + $srcSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.source.Create() + $srcSpec.exclude = $false + # Process Source Address from JSON + $sourceAddess = @() + if($vmcFirewallRule.SourceAddress -ne "null") { + foreach ($address in $vmcFirewallRule.SourceAddress) { + $sourceAddess+=$address + } + } + $srcSpec.ip_address = $sourceAddess; + + # Create Destination Spec + $destSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.destination.Create() + $destSpec.exclude = $false + # Process Destination Address from JSON + $destinationAddess = @() + if($vmcFirewallRule.DestinationAddress -ne "null") { + foreach ($address in $vmcFirewallRule.DestinationAddress) { + $destinationAddess+=$address + } + } + $destSpec.ip_address = $destinationAddess + + # Add various specs + if($vmcFirewallRule.Protocol -ne $null -and $vmcFirewallRule.port -ne $null) { + $ruleElementSpec.application = $appSpec + } + + $ruleElementSpec.source = $srcSpec + $ruleElementSpec.destination = $destSpec + $ruleElementSpec.rule_type = "user" + + # Process Enabled from JSON + $fwEnabled = $false + if($vmcFirewallRule.Enabled -eq "true") { + $fwEnabled = $true + } + $ruleElementSpec.enabled = $fwEnabled + + # Process Logging from JSON + $loggingEnabled = $false + if($vmcFirewallRule.Logging -eq "true") { + $loggingEnabled = $true + } + $ruleElementSpec.logging_enabled = $loggingEnabled + + $ruleElementSpec.action = $vmcFirewallRule.Action + $ruleElementSpec.name = $vmcFirewallRule.Name + + # Add the individual FW rule spec into our overall firewall rules array + Write-host "Creating VMC Firewall Rule Spec:" $vmcFirewallRule.Name "..." + $ruleSpecAdd = $ruleSpec.Add($ruleElementSpec) + } + $firewallRules.firewall_rules = $ruleSpec + + Write-host "Adding VMC Firewall Rules ..." + $firewallRuleAdd = $firewallService.add($orgId,$sddcId,$EdgeId,$firewallRules) +} +Function Remove-VMCFirewallRule { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 11/19/2017 + Organization: VMware + Blog: https://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Removes VMC Firewall Rule given Rule Id + .DESCRIPTION + Removes VMC Firewall Rule given Rule Id + .EXAMPLE + Remove-VMCFirewallRule -OrgName -SDDCName -GatewayType -RuleId + #> + param( + [Parameter(Mandatory=$false)][String]$SDDCName, + [Parameter(Mandatory=$false)][String]$OrgName, + [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, + [Parameter(Mandatory=$false)][String]$RuleId + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + if($GatewayType -eq "MGW") { + $EdgeId = "edge-1" + } else { + $EdgeId = "edge-2" + } + + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + + $firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules + Write-Host "Removing VMC Firewall Rule Id $RuleId ..." + $firewallService.delete($orgId,$sddcId,$EdgeId,$RuleId) +} +Function Get-VMCLogicalNetwork { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/06/2018 + Organization: VMware + Blog: https://thatcouldbeaproblem.com + Twitter: @kmruddy + =========================================================================== + + .SYNOPSIS + Retruns VMC Logical Networks for a given SDDC + .DESCRIPTION + Retruns VMC Logical Networks for a given SDDC + .EXAMPLE + Get-VMCLogicalNetwork -OrgName -SDDCName + .EXAMPLE + Get-VMCLogicalNetwork -OrgName -SDDCName -LogicalNetworkName + #> + param( + [Parameter(Mandatory=$true)][String]$SDDCName, + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$false)][String]$LogicalNetworkName + + ) + + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + + # @LucD22 - 21/10/18 - Fix for issue #176 VMware.VMC module only lists firts 20 Logical networks + # Loop until entries (total_count) are returned + + $index = [long]0 + + $logicalNetworks = do{ + $netData = $logicalNetworkService.get_0($orgId,$sddcId,$pagesize,$index) + $netData.data | Sort-Object -Property id + $index = $index + $netdata.paging_info.page_size + } + until($index -ge $netData.paging_info.total_count) + + if($LogicalNetworkName) { + $logicalNetworks = $logicalNetworks | Where-Object {$_.Name -eq $LogicalNetworkName} + } + + $results = @() + foreach ($logicalNetwork in $logicalNetworks) { + $tmp = [pscustomobject] @{ + ID = $logicalNetwork.id; + Name = $logicalNetwork.name; + SubnetMask = $logicalNetwork.subnets.address_groups.prefix_length; + Gateway = $logicalNetwork.subnets.address_groups.primary_address; + DHCPipRange = $logicalNetwork.dhcp_configs.ip_pools.ip_range; + DHCPdomain = $logicalNetwork.dhcp_configs.ip_pools.domain_name; + CGatewayID = $logicalNetwork.cgw_id; + CGateway = $logicalNetwork.cgw_name; + } + $results+=$tmp + } + $results +} +Function Remove-VMCLogicalNetwork { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/06/2018 + Organization: VMware + Blog: https://thatcouldbeaproblem.com + Twitter: @kmruddy + =========================================================================== + + .SYNOPSIS + Removes Logical Network given ID + .DESCRIPTION + Removes Logical Network given ID + .EXAMPLE + Remove-VMCLogicalNetwork -OrgName -SDDCName -LogicalNetworkName + #> + [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] + param( + [Parameter(Mandatory=$true)][String]$SDDCName, + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$true)][String]$LogicalNetworkName + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $lsId = (Get-VMCLogicalNetwork -OrgName $OrgName -SDDCName $SDDCName -LogicalNetworkName $LogicalNetworkName).Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + if(-not $lsId) { + Write-Host -ForegroundColor red "Unable to find SDDC $LogicalNetworkName, please verify input" + break + } + + $logicalNetworkService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.logical + $logicalNetworkService.delete($orgId,$sddcId,$lsId) +} +Function New-VMCLogicalNetwork { +<# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/06/2018 + Organization: VMware + Blog: https://thatcouldbeaproblem.com + Twitter: @kmruddy + =========================================================================== + + .SYNOPSIS + Creates a new Logical Network + .DESCRIPTION + Creates a new Logical Network + .EXAMPLE + New-VMCLogicalNetwork -OrgName -SDDCName -LogicalNetworkName -SubnetMask -Gateway +#> + [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] + param( + [Parameter(Mandatory=$true)][String]$SDDCName, + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$true)][String]$LogicalNetworkName, + [Parameter(Mandatory=$true)][String]$SubnetMask, + [Parameter(Mandatory=$true)][String]$Gateway + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + + $logicalNetworkService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.logical + $logicalNetworkSpec = $logicalNetworkService.Help.create.sddc_network.Create() + $logicalNetworkSpec.name = $LogicalNetworkName + $logicalNetworkSpec.cgw_id = "edge-2" + $logicalNetworkSpec.cgw_name = "SDDC-CGW-1" + $logicalNetworkAddressGroupSpec = $logicalNetworkService.Help.create.sddc_network.subnets.address_groups.Element.Create() + $logicalNetworkAddressGroupSpec.prefix_length = $SubnetMask + $logicalNetworkAddressGroupSpec.primary_address = $Gateway + + $logicalNetworkSpec.subnets.address_groups.Add($logicalNetworkAddressGroupSpec) | Out-Null + $logicalNetworkService.create($orgId, $sddcId, $logicalNetworkSpec) + Get-VMCLogicalNetwork -OrgName $OrgName -SDDCName $SDDCName -LogicalNetworkName $LogicalNetworkName +} +Function Get-VMCSDDCSummary { + <# + .NOTES + =========================================================================== + Created by: VMware + Date: 09/04/18 + Organization: VMware + Blog: https://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Returns a number of useful informational data about a given SDDC within VMC Org + .DESCRIPTION + Returns Version, Create/Expiration Date, Deployment Type, Region, AZ, Instance Type, VPC CIDR & NSX-T + .EXAMPLE + Get-VMCSDDCSummary -Name -Org + #> + Param ( + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$SDDCName + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $orgId = (Get-VMCOrg -Name $Org).Id + $sddcId = (Get-VMCSDDC -Name $Name -Org $Org).Id + + $sddcService = Get-VmcService "com.vmware.vmc.orgs.sddcs" + $sddc = $sddcService.get($orgId,$sddcId) + + $results = [pscustomobject] @{ + Version = $sddc.resource_config.sddc_manifest.vmc_version; + CreateDate = $sddc.created; + ExpirationDate = $sddc.expiration_date; + DeploymentType = $sddc.resource_config.deployment_type; + Region = $sddc.resource_config.region; + AvailabilityZone = $sddc.resource_config.availability_zones; + InstanceType = $sddc.resource_config.sddc_manifest.esx_ami.instance_type; + VpcCIDR = $sddc.resource_config.vpc_info.vpc_cidr; + NSXT = $sddc.resource_config.nsxt; + } + $results + } +} +Function Get-VMCPublicIP { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 09/12/2018 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Retrieves all public IP Addresses for a given SDDC + .DESCRIPTION + This cmdlet retrieves all public IP Address for a given SDDC + .EXAMPLE + Get-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName + #> + Param ( + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$SDDCName + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" + $publicIPs = $publicIPService.list($orgId,$sddcId) + + $publicIPs | select public_ip, name, allocation_id + } +} + +Function New-VMCPublicIP { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 09/12/2018 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Request a new public IP Address for a given SDDC + .DESCRIPTION + This cmdlet requests a new public IP Address for a given SDDC + .EXAMPLE + New-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -Description "Test for Randy" + #> + Param ( + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$SDDCName, + [Parameter(Mandatory=$False)]$Description + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" + + $publicIPSpec = $publicIPService.Help.create.spec.Create() + $publicIPSpec.count = 1 + $publicIPSpec.names = @($Description) + + Write-Host "Requesting a new public IP Address for your SDDC ..." + $results = $publicIPService.create($orgId,$sddcId,$publicIPSpec) + } +} + +Function Remove-VMCPublicIP { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 09/12/2018 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Removes a specific public IP Addresses for a given SDDC + .DESCRIPTION + This cmdlet removes a specific public IP Address for a given SDDC + .EXAMPLE + Remove-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -AllocationId "eipalloc-0567acf34e436c01f" + #> + Param ( + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$SDDCName, + [Parameter(Mandatory=$True)]$AllocationId + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" + + Write-Host "Deleting public IP Address with ID $AllocationId ..." + $results = $publicIPService.delete($orgId,$sddcId,$AllocationId) + } +} + +Function Set-VMCSDDC { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 01/12/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Rename an SDDC + .DESCRIPTION + This cmdlet renames an SDDC + .EXAMPLE + Set-VMCSDDC -SDDC $SDDCName -OrgName $OrgName -Name $NewSDDCName + #> + Param ( + [Parameter(Mandatory=$True)]$SDDCName, + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$Name + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $sddc = Get-VMCSDDC -Org $OrgName -Name $SDDCName + if($sddc) { + $sddcService = Get-VmcService com.vmware.vmc.orgs.sddcs + $renameSpec = $sddcService.help.patch.sddc_patch_request.Create() + $renameSpec.name = $Name + + Write-Host "`nRenaming SDDC `'$SDDCName`' to `'$Name`' ...`n" + $results = $sddcService.patch($sddc.org_id,$sddc.id,$renameSpec) + } + } +} + +Function New-VMCPublicIP { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 09/12/2018 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Request a new public IP Address for a given SDDC + .DESCRIPTION + This cmdlet requests a new public IP Address for a given SDDC + .EXAMPLE + New-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -Description "Test for Randy" +#> + Param ( + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$SDDCName, + [Parameter(Mandatory=$False)]$Description + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" + + $publicIPSpec = $publicIPService.Help.create.spec.Create() + $publicIPSpec.count = 1 + $publicIPSpec.names = @($Description) + + Write-Host "Requesting a new public IP Address for your SDDC ..." + $results = $publicIPService.create($orgId,$sddcId,$publicIPSpec) + } +} + +Function Remove-VMCPublicIP { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 09/12/2018 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Removes a specific public IP Addresses for a given SDDC + .DESCRIPTION + This cmdlet removes a specific public IP Address for a given SDDC + .EXAMPLE + Remove-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -AllocationId "eipalloc-0567acf34e436c01f" +#> + Param ( + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$SDDCName, + [Parameter(Mandatory=$True)]$AllocationId + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" + + Write-Host "Deleting public IP Address with ID $AllocationId ..." + $results = $publicIPService.delete($orgId,$sddcId,$AllocationId) + } +} + +Function Get-VMCEdge { +<# +.NOTES +=========================================================================== +Created by: Luc Dekens +Date: 23/10/2018 +Organization: Community +Blog: http://lucd.info +Twitter: @LucD22 +=========================================================================== + +.SYNOPSIS + Returns all the VMC Edges +.DESCRIPTION + Returns all the VMC Edges +.EXAMPLE + Get-VMCEdge -OrgName $orgName -SddcName $SDDCName -EdgeType gatewayServices +#> + Param ( + [Parameter(Mandatory=$True)] + [string]$OrgName, + [Parameter(Mandatory=$True)] + [string]$SDDCName, + [ValidateSet('gatewayServices','distributedRouter')] + [string]$EdgeType = '' + ) + + If (-Not $global:DefaultVMCServers) { + Write-error "No VMC Connection found, please use the Connect-VMC to connect" + } + Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + $edgeService = Get-VmcService -Name 'com.vmware.vmc.orgs.sddcs.networks.edges' + $index = [long]0 + $edges = do{ + $edgeData = $edgeService.get($orgId,$sddcId,$EdgeType,'',$index) + $edgeData.edge_page.data | Sort-Object -Property id + $index = $index + $edgeData.edge_page.paging_info.page_size + } + until($index -ge $edgeData.paging_info.total_count) + $edges | %{ + [pscustomobject]@{ + Name = $_.Name + Id = $_.id + Type = $_.edge_type + State = $_.state + Status = $_.edge_status + VNics = $_.number_of_connected_vnics + TenantId = $_.tenant_id + } + } + } +} + +Function Get-VMCEdgeStatus { +<# +.NOTES +=========================================================================== +Created by: Luc Dekens +Date: 23/10/2018 +Organization: Community +Blog: http://lucd.info +Twitter: @LucD22 +=========================================================================== + +.SYNOPSIS + Returns the status of the gateway +.DESCRIPTION + Retrieve the status of the specified management or compute gateway (NSX Edge). +.EXAMPLE + Get-VMCEdgeStatus -OrgName $orgName -SddcName $SDDCName -Edge $EdgeName +#> + Param ( + [Parameter(Mandatory=$True)] + [string]$OrgName, + [Parameter(Mandatory=$True)] + [string]$SDDCName, + [Parameter(Mandatory=$True)] + [string]$EdgeName + ) + + If (-Not $global:DefaultVMCServers) { + Write-error "No VMC Connection found, please use the Connect-VMC to connect" + } + Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $edgeId = Get-VMCEdge -SDDCName $SDDCName -Org $OrgName | where{$_.Name -eq $EdgeName} | select -ExpandProperty Id + + $statusService = Get-VmcService -Name 'com.vmware.vmc.orgs.sddcs.networks.edges.status' + $status = $statusService.get($orgId,$sddcId,$edgeId) + + $vmStatus = $status.edge_vm_status | %{ + [pscustomobject]@{ + Name = $_.name + State = $_.edge_VM_status + HAState = $_.ha_state + Index = $_.index + } + } + $featureStatus = $status.feature_statuses | %{ + [pscustomobject]@{ + Service = $_.service + Status = $_.status + } + } + [pscustomobject]@{ + Time = [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($status.timestamp/1000)) + Status = $status.edge_status + PublishStatus = $status.publish_status + SystemStatus = $_.system_status + NicInUse = $status.ha_vnic_in_use + } + } +} + +Function Get-VMCEdgeNic { +<# +.NOTES +=========================================================================== +Created by: Luc Dekens +Date: 23/10/2018 +Organization: Community +Blog: http://lucd.info +Twitter: @LucD22 +=========================================================================== + +.SYNOPSIS + Returns all interfaces for the gateway +.DESCRIPTION + Retrieve all interfaces for the specified management or compute gateway (NSX Edge). +.EXAMPLE + Get-VMCEdgeNic -OrgName $orgName -SddcName $SDDCName -Edge $EdgeName +#> + Param ( + [Parameter(Mandatory=$True)] + [string]$OrgName, + [Parameter(Mandatory=$True)] + [string]$SDDCName, + [Parameter(Mandatory=$True)] + [string]$EdgeName + ) + + If (-Not $global:DefaultVMCServers) { + Write-error "No VMC Connection found, please use the Connect-VMC to connect" + } + Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $edgeId = Get-VMCEdge -SDDCName $SDDCName -Org $OrgName | where{$_.Name -eq $EdgeName} | select -ExpandProperty Id + + $vnicService = Get-VmcService -Name 'com.vmware.vmc.orgs.sddcs.networks.edges.vnics' + $vnicService.get($orgId,$sddcId,$edgeId) | select -ExpandProperty vnics | %{ + [pscustomobject]@{ + Label = $_.label + Name = $_.Name + Type = $_.type + Index = $_.index + IsConnected = $_.is_connected + Portgroup = $_.portgroup_name + } + } + } +} + +Function Get-VMCEdgeNicStat { +<# +.NOTES +=========================================================================== +Created by: Luc Dekens +Date: 23/10/2018 +Organization: Community +Blog: http://lucd.info +Twitter: @LucD22 +=========================================================================== + +.SYNOPSIS + Returns statistics for the gateway interfaces +.DESCRIPTION + Retrieve interface statistics for a management or compute gateway (NSX Edge). +.EXAMPLE + Get-VMCEdgeNicStat -OrgName $orgName -SddcName $SDDCName -Edge $EdgeName +#> + [CmdletBinding(DefaultParameterSetName='Default')] + Param ( + [Parameter(Mandatory=$True)] + [string]$OrgName, + [Parameter(Mandatory=$True)] + [string]$SDDCName, + [Parameter(Mandatory=$True)] + [string]$EdgeName +# [DateTime]$Start, +# [DateTime]$Finish + ) + + If (-Not $global:DefaultVMCServers) { + Write-error "No VMC Connection found, please use the Connect-VMC to connect" + } + Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $edgeId = Get-VMCEdge -SDDCName $SDDCName -Org $OrgName | where{$_.Name -eq $EdgeName} | select -ExpandProperty Id + +# $epoch = Get-Date 01/01/1970 +# +# if($start){ +# $startEpoch = (New-TimeSpan -Start $epoch -End $Start.ToUniversalTime()).TotalMilliseconds +# } +# if($Finish){ +# $finishEpoch = (New-TimeSpan -Start $epoch -End $Finish.ToUniversalTime()).TotalMilliseconds +# } + + $vnicStatService = Get-VmcService -Name 'com.vmware.vmc.orgs.sddcs.networks.edges.statistics.interfaces' +# $stats = $vnicStatService.get($orgId,$sddcId,$edgeId,[long]$startEpoch,[long]$finishEpoch) + $stats = $vnicStatService.get($orgId,$sddcId,$edgeId) + + $stats.data_dto | Get-Member -MemberType NoteProperty | where{$_.Name -ne 'Help'} | %{$_.Name} | %{ + $stats.data_dto."$_" | %{ + [pscustomobject]@{ + vNIC = $_.vnic + Timestamp = [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($_.timestamp)) + In = $_.in + Out = $_.out + Unit = 'Kbps' + Interval = $stats.meta_dto.interval + } + } + } + } +} + +Function Get-VMCEdgeUplinkStat { +<# +.NOTES +=========================================================================== +Created by: Luc Dekens +Date: 23/10/2018 +Organization: Community +Blog: http://lucd.info +Twitter: @LucD22 +=========================================================================== + +.SYNOPSIS + Returns statistics for the uplink interfaces +.DESCRIPTION + Retrieve uplink interface statistics for a management or compute gateway (NSX Edge). +.EXAMPLE + Get-VMCEdgeUplinkStat -OrgName $orgName -SddcName $SDDCName -Edge $EdgeName +#> + Param ( + [Parameter(Mandatory=$True)] + [string]$OrgName, + [Parameter(Mandatory=$True)] + [string]$SDDCName, + [Parameter(Mandatory=$True)] + [string]$EdgeName +# [DateTime]$Start, +# [DateTime]$Finish + ) + + If (-Not $global:DefaultVMCServers) { + Write-error "No VMC Connection found, please use the Connect-VMC to connect" + } + Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $edgeId = Get-VMCEdge -SDDCName $SDDCName -Org $OrgName | where{$_.Name -eq $EdgeName} | select -ExpandProperty Id + +# $epoch = Get-Date 01/01/1970 +# +# if($start){ +# $startEpoch = (New-TimeSpan -Start $epoch -End $Start.ToUniversalTime()).TotalMilliseconds +# } +# if($Finish){ +# $finishEpoch = (New-TimeSpan -Start $epoch -End $Finish.ToUniversalTime()).TotalMilliseconds +# } + + $uplinkStatService = Get-VmcService -Name 'com.vmware.vmc.orgs.sddcs.networks.edges.statistics.interfaces.uplink' +# $stats = $uplinkStatService.get($orgId,$sddcId,$edgeId,[long]$startEpoch,[long]$finishEpoch) + $stats = $uplinkStatService.get($orgId,$sddcId,$edgeId) + + $stats.data_dto | Get-Member -MemberType NoteProperty | where{$_.Name -ne 'Help'} | %{$_.Name} | %{ + if($stats.data_dto."$_".Count -ne 0){ + $stats.data_dto."$_" | %{ + [pscustomobject]@{ + vNIC = $_.vnic + Timestamp = [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($_.timestamp)) + In = $_.in + Out = $_.out + Unit = 'Kbps' + Interval = $stats.meta_dto.interval + } + } + } + } + } +} + +Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', + 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', + 'Get-VMCSDDCVersion', 'Get-VMCFirewallRule', 'Export-VMCFirewallRule', 'Import-VMCFirewallRule', + 'Remove-VMCFirewallRule', 'Get-VMCLogicalNetwork', 'Remove-VMCLogicalNetwork', 'New-VMCLogicalNetwork', + 'Get-VMCSDDCSummary', 'Get-VMCPublicIP', 'New-VMCPublicIP', 'Remove-VMCPublicIP', 'Set-VMCSDDC', + 'Get-VMCEdge', 'Get-VMCEdgeNic', 'Get-VMCEdgeStatus', 'Get-VMCEdgeNicStat', 'Get-VMCEdgeUplinkStat' + diff --git a/Modules/VMware.VMEncryption/VMware.VMEncryption.psd1 b/Modules/VMware.VMEncryption/VMware.VMEncryption.psd1 index aa83854..8a93a97 100644 --- a/Modules/VMware.VMEncryption/VMware.VMEncryption.psd1 +++ b/Modules/VMware.VMEncryption/VMware.VMEncryption.psd1 @@ -49,7 +49,7 @@ Copyright = 'Copyright (c) 2016 VMware, Inc. All rights reserved.' # Modules that must be imported into the global environment prior to importing this module RequiredModules = @( -@{"ModuleName"="VMware.VimAutomation.Core";"ModuleVersion"="10.1.0.8346946"} +@{"ModuleName"="VMware.VimAutomation.Core";"ModuleVersion"="10.1.0.8344055"} ) # Assemblies that must be loaded prior to importing this module diff --git a/Modules/VMware.VsanEncryption/README.md b/Modules/VMware.VsanEncryption/README.md new file mode 100644 index 0000000..8037171 --- /dev/null +++ b/Modules/VMware.VsanEncryption/README.md @@ -0,0 +1,7 @@ +Prerequisites/Steps to use this module: + +1. This module only works for vSphere products that support vSAN Encryption. E.g. vSAN 6.6 and later with a vSAN Enterprise license +2. All the functions in this module only work for KMIP Servers. +3. Install the latest version of Powershell and PowerCLI(11). +4. Import this module by running: Import-Module -Name "location of this module" +5. Get-Command -Module "This module Name" to list all available functions. \ No newline at end of file diff --git a/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psd1 b/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psd1 new file mode 100644 index 0000000..47b0ca3 Binary files /dev/null and b/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psd1 differ diff --git a/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 b/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 new file mode 100644 index 0000000..870bd44 --- /dev/null +++ b/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 @@ -0,0 +1,341 @@ +# Script Module : VMware.VsanEncryption +# Version : 1.0 +# Author : Jase McCarty, VMware Storage & Availability Business Unit + +# Copyright © 2018 VMware, Inc. All Rights Reserved. + +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +Function Invoke-VsanEncryptionRekey { + <# + .SYNOPSIS + This function will initiate a ReKey of a vSAN Cluster. Shallow ReKeying (KEK Only) or Deep ReKeying (DEK Also) are supported, as well as Reduced Redundancy if necessary. + + .DESCRIPTION + This function will initiate a ReKey of a vSAN Cluster. Shallow ReKeying (KEK Only) or Deep ReKeying (DEK Also) are supported, as well as Reduced Redundancy if necessary. + + .PARAMETER Cluster + Specifies the Cluster to perform the rekey process on + + .PARAMETER DeepRekey + Use to invoke a Deep Rekey ($true) or a Shallow ($false or omit) + + .PARAMETER ReducedRedundancy + For clusters that have 4 or more hosts, this will allow for reduced redundancy. + For clusters that have 2 or 3 hosts, this does not need to be set (can be). + + .EXAMPLE + C:\PS>Invoke-VsanEncryptionRekey -Cluster "ClusterName" -DeepRekey $true/$false -ReducedRedundancy $true/$false + + #> + + # Set our Parameters + [CmdletBinding()]Param( + [Parameter(Mandatory = $True)][String]$Cluster, + [Parameter(Mandatory = $False)][Boolean]$DeepRekey, + [Parameter(Mandatory = $False)][Boolean]$ReducedRedundancy + ) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + # Get a count of hosts to guarantee reduced redundancy for 2 and 3 node clusters + $HostCount = $VsanCluster | Select @{n="count";e={($_ | Get-VMHost).Count}} + + # If reduced redundancy is specified, or there are less than 4 hosts, force reduced redundancy + If (($ReducedRedundancy -eq $true) -or ($HostCount.Value -lt 4)) { + + } + # Determine Rekey Type for messaging + Switch ($DeepRekey) { + $true { $ReKeyType = "deep"} + default { $ReKeyType = "shallow"} + } + + # Determine Reduced Redundancy for messaging + Switch ($ReducedRedundancy) { + $true { $RRMessage = "with reduced redundancy"} + default { $RRMessage = ""} + } + + # Echo task being performed + Write-Host "Executing $ReKeyType rekey of vSAN Cluster $VsanCluster $RRMessage" + + # Execute the rekeying task + $ReKeyTask = $VsanVcClusterConfig.VsanEncryptedClusterRekey_Task($VsanCluster.ExtensionData.MoRef,$DeepRekey,$ReducedRedundancy) + } +} + +Function Set-VsanEncryptionKms { + <# + .SYNOPSIS + This function will set the KMS to be used with vSAN Encryption + + .DESCRIPTION + This function will set the KMS to be used with vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster to set the KMS server for + + .PARAMETER KmsCluster + Use to set the KMS Cluster to be used with vSAN Encryption + + .EXAMPLE + C:\PS>Set-VsanEncryptionKms -Cluster "ClusterName" -KmsCluster "vCenter KMS Cluster Entry" + + #> + + # Set our Parameters + [CmdletBinding()]Param( + [Parameter(Mandatory = $True)][String]$Cluster, + [Parameter(Mandatory = $False)][String]$KmsCluster + ) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the list of KMS Servers that are included + $KmsClusterList = Get-KmsCluster + + # Was a KMS Cluster Specified? + # Specified: Is it in the list? + # Is it not in the list? + # Not Specified: Present a list + If ($KmsCluster) { + If ($KmsClusterList.Name.Contains($KmsCluster)) { + Write-Host "$KmsCluster In the list, proceeding" -ForegroundColor Green + $KmsClusterProfile = $KmsClusterList | Where-Object {$_.Name -eq $KmsCluster} + } else { + + $Count = 0 + Foreach ($KmsClusterItem in $KmsClusterList) { + Write-Host "$Count) $KmsClusterItem " + $Count = $Count + 1 + } + $KmsClusterEntry = Read-Host -Prompt "$KmsCluster is not valid, please select one of the existing KMS Clusters to use" + Write-Host $KmsClusterList[$KmsClusterEntry] + $KmsClusterProfile = $KmsClusterList[$KmsClusterEntry] + } + } else { + + $Count = 0 + Foreach ($KmsClusterItem in $KmsClusterList) { + Write-Host "$Count) $KmsClusterItem " + $Count = $Count + 1 + } + $KmsClusterEntry = Read-Host -Prompt "No KMS provided, please select one of the existing KMS Clusters to use" + Write-Host $KmsClusterList[$KmsClusterEntry] + $KmsClusterProfile = $KmsClusterList[$KmsClusterEntry] + } + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + If ($EncryptedVsan.KmsProviderId.Id -eq $KmsClusterProfile.Name) { + # If the Specified KMS Profile is the KMS Profile being used, then don't do anything + Write-Host $EncryptedVsan.KmsProviderId.Id "is already the assigned KMS Cluster Profile, exiting" + } else { + Write-Host "Changing the KMS Profile to $KmsClusterProfile on Cluster $VsanCluster" + + # Setup the KMS Provider Id Specification + $KmsProviderIdSpec = New-Object VMware.Vim.KeyProviderId + $KmsProviderIdSpec.Id = $KmsClusterProfile.Name + + # Setup the Data Encryption Configuration Specification + $DataEncryptionConfigSpec = New-Object VMware.Vsan.Views.VsanDataEncryptionConfig + $DataEncryptionConfigSpec.KmsProviderId = $KmsProviderIdSpec + $DataEncryptionConfigSpec.EncryptionEnabled = $true + + # Set the Reconfigure Specification to use the Data Encryption Configuration Spec + $vsanReconfigSpec = New-Object VMware.Vsan.Views.VimVsanReconfigSpec + $vsanReconfigSpec.DataEncryptionConfig = $DataEncryptionConfigSpec + + # Execute the task of changing the KMS Cluster Profile Being Used + $ChangeKmsTask = $VsanVcClusterConfig.VsanClusterReconfig($VsanCluster.ExtensionData.MoRef,$vsanReconfigSpec) + } + + } + } + + Function Get-VsanEncryptionKms { + <# + .SYNOPSIS + This function will set the KMS to be used with vSAN Encryption + + .DESCRIPTION + This function will set the KMS to be used with vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster to set the KMS server for + + .EXAMPLE + C:\PS>Get-VsanEncryptionKms -Cluster "ClusterName" + #> + + # Set our Parameters + [CmdletBinding()]Param([Parameter(Mandatory = $True)][String]$Cluster) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + $EncryptedVsan.KmsProviderId.Id + } +} + +Function Set-VsanEncryptionDiskWiping { + <# + .SYNOPSIS + This function will update the Disk Wiping option in vSAN Encryption + + .DESCRIPTION + This function will update the Disk Wiping option in vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster set the Disk Wiping Setting on + + .PARAMETER DiskWiping + Use to set the Disk Wiping setting for vSAN Encryption + + .EXAMPLE + C:\PS>Set-VsanEncryptionDiskWiping -Cluster "ClusterName" -DiskWiping $true + + .EXAMPLE + C:\PS>Set-VsanEncryptionDiskWiping -Cluster "ClusterName" -DiskWiping $false + + #> + + # Set our Parameters + [CmdletBinding()]Param( + [Parameter(Mandatory = $True)][String]$Cluster, + [Parameter(Mandatory = $True)][Boolean]$DiskWiping + ) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + # Determine Rekey Type for messaging + Switch ($DiskWiping) { + $true { $DiskWipingSetting = "enabled" } + default { $DiskWipingSetting = "disabled" } + } + + # Check to see the current Disk Wiping value + If ($DiskWiping -eq $EncryptedVsan.EraseDisksBeforeUse) { + Write-Host "Disk Wiping is already $DiskWipingSetting" -ForegroundColor "Green" + Write-Host "No action necessary" -ForegroundColor "Green" + + } else { + + Write-Host "Disk Wiping is not set to $DiskWipingSetting" -ForegroundColor "Yellow" + Write-Host "Changing Disk Wiping setting on Cluster $VsanCluster" -ForegroundColor "Blue" + + # Setup the Data Encryption Configuration Specification + $DataEncryptionConfigSpec = New-Object VMware.Vsan.Views.VsanDataEncryptionConfig + $DataEncryptionConfigSpec.EncryptionEnabled = $true + $DataEncryptionConfigSpec.EraseDisksBeforeUse = $DiskWiping + + # Set the Reconfigure Specification to use the Data Encryption Configuration Spec + $vsanReconfigSpec = New-Object VMware.Vsan.Views.VimVsanReconfigSpec + $vsanReconfigSpec.DataEncryptionConfig = $DataEncryptionConfigSpec + + # Execute the task of changing the KMS Cluster Profile Being Used + $VsanVcClusterConfig.VsanClusterReconfig($VsanCluster.ExtensionData.MoRef,$vsanReconfigSpec) + + } + } +} + +Function Get-VsanEncryptionDiskWiping { + <# + .SYNOPSIS + This function will retrieve the Disk Wiping option setting in vSAN Encryption + + .DESCRIPTION + This function will retrieve the Disk Wiping option setting in vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster set the Disk Wiping Setting on + + .EXAMPLE + C:\PS>Get-VsanEncryptionDiskWiping -Cluster "ClusterName" + + #> + + # Set our Parameters + [CmdletBinding()]Param([Parameter(Mandatory = $True)][String]$Cluster) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + # Change the setting + $EncryptedVsan.EraseDisksBeforeUse + } +} + + + +# Export Function for vSAN Rekeying +Export-ModuleMember -Function Invoke-VsanEncryptionRekey +Export-ModuleMember -Function Set-VsanEncryptionKms +Export-ModuleMember -Function Get-VsanEncryptionKms +Export-ModuleMember -Function Set-VsanEncryptionDiskWiping +Export-ModuleMember -Function Get-VsanEncryptionDiskWiping \ No newline at end of file diff --git a/Modules/Validate-ESXiPackages/Validate-ESXiPackages.psm1 b/Modules/Validate-ESXiPackages/Validate-ESXiPackages.psm1 new file mode 100644 index 0000000..ccf5d85 --- /dev/null +++ b/Modules/Validate-ESXiPackages/Validate-ESXiPackages.psm1 @@ -0,0 +1,82 @@ +function Validate-ESXiPackages { + <# + .DESCRIPTION + Compares all ESXi Host VIBs within a vSphere with a reference Hosts. + + .NOTES + File Name : Validate-ESXiPackages.ps1 + Author : Markus Kraus + Version : 1.0 + State : Ready + + Tested Against Environment: + + vSphere Version: 6.0 U2, 6.5 U1 + PowerCLI Version: PowerCLI 10.0.0 build 7895300 + PowerShell Version: 4.0 + OS Version: Windows Server 2012 R2 + + .LINK + https://mycloudrevolution.com/ + + .EXAMPLE + Validate-ESXiPackages -Cluster (Get-Cluster) -RefernceHost (Get-VMHost | Select-Object -First 1) + + .PARAMETER Cluster + vSphere Cluster to verify + + .PARAMETER RefernceHost + The VIB Reference ESXi Host + #> + + [CmdletBinding()] + param( + [Parameter(Mandatory=$True, ValueFromPipeline=$True, HelpMessage="vSphere Cluster to verify")] + [ValidateNotNullorEmpty()] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.ComputeResourceImpl] $Cluster, + [Parameter(Mandatory=$True, ValueFromPipeline=$false, HelpMessage="The VIB Reference ESXi Host")] + [ValidateNotNullorEmpty()] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl] $RefernceHost + ) + + Process { + + #region: Get reference VIBs + $EsxCli2 = Get-ESXCLI -VMHost $RefernceHost -V2 + $RefernceVibList = $esxcli2.software.vib.list.invoke() + #endregion + + #region: Compare reference VIBs + $MyView = @() + foreach ($VmHost in ($Cluster | Get-VMHost)) { + + $EsxCli2 = Get-ESXCLI -VMHost $VmHost -V2 + $VibList = $esxcli2.software.vib.list.invoke() + [Array]$VibDiff = Compare-Object -ReferenceObject $RefernceVibList.ID -DifferenceObject $VibList.ID + + if($VibDiff.Count -gt 0) { + $VibDiffSideIndicator = @() + foreach ($Item in $VibDiff) { + $VibDiffSideIndicator += $($Item.SideIndicator + " " + $Item.InputObject) + } + } + else { + $VibDiffSideIndicator = $null + } + + $Report = [PSCustomObject] @{ + Host = $VmHost.Name + Version = $VmHost.Version + Build = $VmHost.Build + VibDiffCount = $VibDiff.Count + VibDiff = $VibDiff.InputObject + VibDiffSideIndicator = $VibDiffSideIndicator + } + $MyView += $Report + + } + #region: Compare reference VIBs + + $MyView + } +} \ No newline at end of file diff --git a/README.md b/README.md index 86afe3e..a82900f 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,8 @@ * [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) - * [Resolving issues](https://github.com/vmware/PowerCLI-Example-Scripts#resolving-issues) + * [Filing Issues](https://github.com/vmware/PowerCLI-Example-Scripts#filing-isssues) + * [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) * [VMware Sample Exchange](https://github.com/vmware/PowerCLI-Example-Scripts#vmware-sample-exchange) diff --git a/Scripts/ReadVMSnapshotConfig.ps1 b/Scripts/ReadVMSnapshotConfig.ps1 new file mode 100644 index 0000000..fe274ee --- /dev/null +++ b/Scripts/ReadVMSnapshotConfig.ps1 @@ -0,0 +1,104 @@ +function Get-VMSnapshotConfigContent { +<# + .SYNOPSIS + Reads .vmsd file content + + .DESCRIPTION + Build the vmsd file http URI following https://code.vmware.com/apis/358/vsphere#/doc/vim.FileManager.html + and reads its content with the session established by Connect-VIServer + + .INPUTS + VirtualMachine + + .OUTPUTS + String - the content of the vmsd file + + .NOTES + Author: Dimitar Milov + Version: 1.0 + + .EXAMPLE + Get-VM | Get-VMSnapshotConfigContent +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory=$true, ValueFromPipeline=$true)] + [ValidateNotNull()] + [VMware.VimAutomation.Types.VirtualMachine] + $VM +) + +PROCESS { + # Create web client from current session + $sessionKey = $vm.GetClient().ConnectivityService.CurrentUserSession.SoapSessionKey + $certValidationHandler = $vm.GetClient().ConnectivityService.GetValidationHandlerForCurrentServer() + $webClient = [vmware.vimautomation.common.util10.httpclientUtil]::CreateHttpClientWithSessionReuse($certValidationHandler, $sessionKey, $null) + + # Build VMSD file http URI + # https://code.vmware.com/apis/358/vsphere#/doc/vim.FileManager.html + $vmName = $vm.Name + $datastoreName = ($vm | Get-Datastore).Name + $dcName = ($vm | Get-Datacenter).Name + $serverAddress = $vm.GetClient().ConnectivityService.ServerAddress + $vmsdUri = [uri]"https://$serverAddress/folder/$vmName/$vmName.vmsd?dcPath=$dcName&dsName=$datastoreName" + + # Get VMSD content as string + $task = $webClient.GetAsync($vmsdUri) + $task.Wait() + $vmsdContent = $task.Result.Content.ReadAsStringAsync().Result + + # Dispose web client + $webClient.Dispose() + + # Result + $vmsdContent +} + +} + +function Get-VMSnapshotConfigSetting { +<# + .SYNOPSIS + Gets the value of a specified key from the snapshot config file content + + .DESCRIPTION + Reads the VM's snapshot config file and searches for specified key. + If key is found its value is returned as an output + + .INPUTS + VirtualMachine and key + + .OUTPUTS + String - config value for the specified key + + .NOTES + Author: Dimitar Milov + Version: 1.0 + + .EXAMPLE + Get-VM | Get-VMSnapshotConfigSetting -Key "numSentinels" +#> +[CmdletBinding()] +param( + [Parameter(Mandatory=$true, ValueFromPipeline=$true)] + [ValidateNotNull()] + [VMware.VimAutomation.Types.VirtualMachine] + $VM, + + [Parameter(Mandatory=$true)] + [ValidateNotNull()] + [string] + $Key +) + +PROCESS { + $content = Get-VMSnapshotConfigContent -vm $vm + + $keyMatch = $content | Select-String ('{0} = "(?.*)"' -f $key) + + if ($keyMatch.Matches -ne $null) { + $keyMatch.Matches[0].Groups["value"].Value + } +} +} diff --git a/Scripts/Save-PowerCLI.ps1 b/Scripts/Save-PowerCLI.ps1 new file mode 100644 index 0000000..e9127bc --- /dev/null +++ b/Scripts/Save-PowerCLI.ps1 @@ -0,0 +1,147 @@ +function Save-PowerCLI { + <# + .SYNOPSIS + Advanced function which can be used to easily download specific versions of PowerCLI from an online gallery + .DESCRIPTION + Downloads a specific version of PowerCLI and all the dependencies at the appropriate version + .NOTES + Author: 1.0 - Dimitar Milov + Author: 2.0 - Kyle Ruddy, @kmruddy + .PARAMETER RequiredVersion + Dynamic parameter used to specify the PowerCLI version + .PARAMETER Path + Directory path where the modules should be downloaded + .PARAMETER Repository + Repository to access the PowerCLI modules + .PARAMETER Simple + Switch used to specify the nested version folders should be removed (therefore adding PowerShell 3/4 compatibility) + .EXAMPLE + Save-PowerCLI -RequiredVersion '10.0.0.7895300' -Path .\Downloads\ + Downloads PowerCLI 10.0.0 to the Downloads folder + .EXAMPLE + Save-PowerCLI -RequiredVersion '6.5.2.6268016' -Path .\Downloads\ -Simple + Downloads PowerCLI 6.5.2 to the Downloads folder and removes the nested version folders + #> + [CmdletBinding(SupportsShouldProcess = $True)] + param( + [Parameter(Mandatory = $true, Position = 1)] + [ValidateScript( { Test-Path $_} )] + $Path, + [Parameter(Mandatory = $false, Position = 2)] + [string]$Repository = 'PSGallery', + [Parameter(Mandatory = $false, Position = 3)] + [Switch]$Simple + ) + DynamicParam + { + # Set the dynamic parameters name + $ParameterName = 'RequiredVersion' + + # Create the dictionary + $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary + + # Create the collection of attributes + $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] + + # Create and set the parameters' attributes + $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute + $ParameterAttribute.ValueFromPipeline = $true + $ParameterAttribute.ValueFromPipelineByPropertyName = $true + $ParameterAttribute.Mandatory = $true + $ParameterAttribute.Position = 0 + + # Add the attributes to the attributes collection + $AttributeCollection.Add($ParameterAttribute) + + # Generate and set the ValidateSet + $pcliVersions = Find-Module -Name 'VMware.PowerCLI' -AllVersions + $arrSet = $pcliVersions | select-Object -ExpandProperty Version + $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet) + + # Add the ValidateSet to the attributes collection + $AttributeCollection.Add($ValidateSetAttribute) + + # Create and return the dynamic parameter + $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection) + $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter) + return $RuntimeParameterDictionary + } + + begin { + $powercliModuleName = 'VMware.PowerCLI' + $desiredPowerCLIModule = Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion -Repository $Repository + + $depsOrder = 'VMware.VimAutomation.Sdk', 'VMware.VimAutomation.Common', 'VMware.Vim', 'VMware.VimAutomation.Cis.Core', 'VMware.VimAutomation.Core', 'VMware.VimAutomation.Nsxt', 'VMware.VimAutomation.Vmc', 'VMware.VimAutomation.Vds', 'VMware.VimAutomation.Srm', 'VMware.ImageBuilder', 'VMware.VimAutomation.Storage', 'VMware.VimAutomation.StorageUtility', 'VMware.VimAutomation.License', 'VMware.VumAutomation', 'VMware.VimAutomation.HorizonView', 'VMware.DeployAutomation', 'VMware.VimAutomation.vROps', 'VMware.VimAutomation.PCloud' + $orderedDependencies = @() + foreach ($depModuleName in $depsOrder) { + $orderedDependencies += $desiredPowerCLIModule.Dependencies | Where-Object {$_.Name -eq $depModuleName} + } + + foreach ($remainingDep in $desiredPowerCLIModule.Dependencies) { + if ($orderedDependencies.Name -notcontains $remainingDep.Name) { + $orderedDependencies += $remainingDep + } + + } + } + + process { + # Save PowerCLI Module Version + $desiredPowerCLIModule | Save-Module -Path $Path + + # Working with the depenent modules + foreach ($dependency in $orderedDependencies) { + if (Get-ChildItem -Path (Join-Path $path $dependency.Name) | Where-Object {$_.Name -ne $dependency.MinimumVersion}) { + # Save dependencies with minimum version + Find-Module $dependency.Name -RequiredVersion $dependency.MinimumVersion | Save-Module -Path $Path + + # Remove newer dependencies version + Get-ChildItem -Path (Join-Path $path $dependency.Name) | Where-Object {$_.Name -ne $dependency.MinimumVersion} | Remove-Item -Confirm:$false -Force -Recurse + } + } + } + + end { + if ($Simple) { + + function FolderCleanup { + param( + [Parameter(Mandatory = $true, Position = 0)] + [ValidateScript( { Test-Path $_} )] + $ParentFolder, + [Parameter(Mandatory = $true, Position = 1)] + [String]$ModuleName, + [Parameter(Mandatory = $true, Position = 2)] + $Version + ) + + + $topFolder = Get-Item -Path (Join-Path $ParentFolder $ModuleName) + $versionFolder = $topFolder | Get-ChildItem -Directory | Where-Object {$_.Name -eq $Version} + $versionFolder | Get-ChildItem | Copy-Item -Destination $topFolder + + # Checking for any nested folders within the PowerCLI module version folder + if ($versionFolder| Get-ChildItem -Directory) { + + # Obtaining and storing the child items to a variable, then copying the items to the parent folder's nested folder + $nestFolder = $versionFolder| Get-ChildItem -Directory + foreach ($nestDir in $nestFolder) { + $nestDir | Get-ChildItem | Copy-Item -Destination (Join-Path $topFolder $nestDir.Name) + } + + } + + # Removing any of the former, no longer needed, directory structure + $versionFolder| Remove-Item -Recurse -Force + } + + FolderCleanup -ParentFolder $Path -ModuleName $desiredPowerCLIModule.Name -Version $desiredPowerCLIModule.Version + foreach ($cleanUp in $orderedDependencies) { + + FolderCleanup -ParentFolder $Path -ModuleName $cleanUp.Name -Version $cleanUp.MinimumVersion + } + + } + + } + } \ No newline at end of file diff --git a/Scripts/Set-CustomAttributesInGuestinfo.ps1 b/Scripts/Set-CustomAttributesInGuestinfo.ps1 new file mode 100644 index 0000000..d76d3ee --- /dev/null +++ b/Scripts/Set-CustomAttributesInGuestinfo.ps1 @@ -0,0 +1,84 @@ +<# +.NOTES + Script name: Set-CustomAttributesInGuestinfo.ps1 + Created on: 10/04/2018 + Author: Doug Taliaferro, @virtually_doug + Description: Gets Custom Attributes assigned to a VM and makes them available to the guest OS. + Dependencies: None known + + ===Tested Against Environment==== + vSphere Version: 6.5 + PowerCLI Version: 10.0.0.7893909 + PowerShell Version: 5.1.14409.1005 + OS Version: Windows 7, 10 + Keyword: VM, Attributes, Guestinfo + +.SYNOPSIS + Gets Custom Attributes assigned to a VM and makes them available to the guest OS. + +.DESCRIPTION + Gets the custom attributes assigned to one or more VMs and sets their values in the + VM's 'guestinfo' advanced settings. This makes the attributes available within the + guest OS using VM tools (vmtoolsd.exe) and allows the attributes to be used as metadata + for applications or management agents that run inside the guest. If the attribute name + contains spaces they are removed in naming the advanced setting. + + For example, if a VM has a custom attribute named 'Created On', the advanced setting + becomes: + 'guestinfo.CreatedOn' = '08/08/2018 14:24:17' + + This can be retrieved in the guest OS by running: + vmtoolsd.exe --cmd "info-get guestinfo.CreatedOn" + +.PARAMETER VMs + One or more VMs returned from the Get-VM cmdlet. + +.PARAMETER Attributes + The names of the Custom Attributes to get. If the names contain spaces they must be + enclosed in quotes. The spaces will be removed to name the advanced setting. + +.PARAMETER vCenter + The vCenter server to connect to. Optional if you are already connected. + +.EXAMPLE + .\Set-CustomAttributesInGuestInfo.ps1 -VM (get-vm testvm01) -Attributes 'Created On', 'Created By' + + Gets the custom attributes 'Created On' and 'Created By' for 'testvm01' and sets their + values in 'guestinfo.CreatedOn' and 'guestinfo.CreatedBy'. + +.EXAMPLE + .\Set-CustomAttributesInGuestInfo.ps1-VM (get-cluster Dev-01 | get-vm) -Attributes 'Created On' + + Gets the custom attribute 'Created On' for all VMs in the Dev-01 cluster and sets 'guestinfo.CreatedOn' + on each VM. +#> +#Requires -modules VMware.VimAutomation.Core +[CmdletBinding()] +param ( + [Parameter(Mandatory=$true,Position=0)] + $VMs, + [Parameter(Mandatory=$true,Position=1)] + [string[]]$Attributes, + [string]$vCenter +) +if ($vCenter) { + Connect-VIServer $vCenter +} + +ForEach ($vm in $VMs) { + ForEach ($attributeName in $Attributes) { + # Get the custom attribute with a matcing key name + $customField = $vm.CustomFields | Where-Object Key -eq $attributeName + if ($customField) { + # Remove white space from the attribute name because the advanced + # setting name cannot contain spaces + $attributeNameNoSpaces = $customField.Key -replace '\s','' + $guestinfoName = "guestinfo.$attributeNameNoSpaces" + $guestinfoValue = $customField.Value + Write-Host "$($vm): setting '$guestinfoName' = '$guestinfoValue'" + New-AdvancedSetting -Entity $vm -Name $guestinfoName -Value $guestinfoValue -Confirm:$false -Force | Out-Null + } else { + Write-Host "$($vm): custom attribute '$attributeName' not set on this VM" + } + } +} diff --git a/Scripts/Set-TagsInGuestinfo.ps1 b/Scripts/Set-TagsInGuestinfo.ps1 new file mode 100644 index 0000000..c245c05 --- /dev/null +++ b/Scripts/Set-TagsInGuestinfo.ps1 @@ -0,0 +1,98 @@ +<# +.NOTES + Script name: Set-TagsInGuestinfo.ps1 + Created on: 10/02/2018 + Author: Doug Taliaferro, @virtually_doug + Description: Gets the vSphere Tags assigned to a VM and makes them available to the guest OS. + Dependencies: None known + + ===Tested Against Environment==== + vSphere Version: 6.5 + PowerCLI Version: 10.0.0.7893909 + PowerShell Version: 5.1.14409.1005 + OS Version: Windows 7, 10 + Keyword: VM, Tags, Guestinfo + +.SYNOPSIS + Gets the vSphere Tags assigned to a VM and makes them available to the guest OS. + +.DESCRIPTION + Gets the tags assigned to one or more VMs from one or more categories and sets the tag values + in the VM's 'guestinfo' advanced settings. This makes the tags available within the guest OS + using VM tools (vmtoolsd.exe) and allows the tags to be used as metadata for applications or + management agents that run inside the guest. + + For example, if a VM has a tag named 'Accounting' from the + category 'Departments', the advanced setting becomes: + guestinfo.Departments = Accounting + + This can be retrieved in the guest OS by running: + vmtoolsd.exe --cmd "info-get guestinfo.Departments" + + If multiple tags are assigned from the same category, they are joined using the specified + delimter (a semicolon by default): + guestinfo.Departments = Accounting;Sales + +.PARAMETER VMs + One or more VMs returned from the Get-VM cmdlet. + +.PARAMETER Categories + The names of tag categories that should be set in the advanced settings. + + .PARAMETER Delimiter + The delimiting character used for multiple tags of the same category. Defaults to a + semicolon. + +.PARAMETER vCenter + The vCenter server to connect to. Optional if you are already connected. + +.EXAMPLE + .\Set-TagsInGuestInfo.ps1 -VM (get-vm testvm01) -Categories Departments, Environment + + Gets tags assigned to 'testvm01' in the Departments and Environment categories and + sets their values in 'guestinfo.Departments' and 'guestinfo.Environment'. + +.EXAMPLE + .\Set-TagsInGuestInfo.ps1 -VM (get-cluster Dev-01 | get-vm) -Categories Departments + + Gets tags assigned to all VMs in the Dev-01 cluster and sets 'guestinfo.Departments' + on each VM. +#> +#Requires -modules VMware.VimAutomation.Core +[CmdletBinding()] +param ( + [Parameter(Mandatory=$true,Position=0)] + $VMs, + [Parameter(Mandatory=$true,Position=1)] + [string[]]$Categories, + [string]$Delimiter = ';', + [string]$vCenter +) +if ($vCenter) { + Connect-VIServer $vCenter +} + +ForEach ($categoryName in $Categories) { + $category = Get-TagCategory -Name $categoryName + if ($category) { + $guestinfoName = "guestinfo.$category" + + # Get Tag assignments for the VMs + $tags = Get-TagAssignment -Entity $VMs -Category $category + + # Group the tags by VM (in this case the Entity property of Group-Object) + $groups = $tags | Group-Object -Property Entity + + # Get each VM and set the guestinfo + ForEach ($item in $groups) { + $vm = get-vm $item.Name + # Multiple tags of the same category are joined + $guestinfoValue = $item.Group.Tag.Name -join $Delimiter + + Write-Host "$($vm): setting '$guestinfoName' = '$guestinfoValue'" + New-AdvancedSetting -Entity $vm -Name $guestinfoName -Value $guestinfoValue -Confirm:$false -Force | Out-Null + } + } else { + Write-Host "Category '$categoryName' was not found." + } +} diff --git a/Scripts/VMware_Cloud_on_AWS/VMWonAWS_1nodeDeployment.ps1 b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_1nodeDeployment.ps1 index 8b17b16..2a41690 100644 --- a/Scripts/VMware_Cloud_on_AWS/VMWonAWS_1nodeDeployment.ps1 +++ b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_1nodeDeployment.ps1 @@ -7,9 +7,10 @@ # Set details for SDDC $oauthToken = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx" -$sddcName = "PowerCLI-1Node-SDDC" +$sddcName = "PowerCLI-1Host-SDDC" $hostCount = "1" $awsRegion = "US_WEST_2" +$useAwsAccount = $false # --- Deployment code --- # Connect to VMware Cloud Service @@ -18,19 +19,25 @@ Connect-Vmc -RefreshToken $oauthToken | Out-Null # Get ORG ID $orgSvc = Get-VmcService -Name com.vmware.vmc.orgs $org = $orgSvc.List() -Write-Host "Org:"$org.display_name" ID:"$org.id +Write-Output -InputObject "Org: $($org.display_name) ID: $($org.id)" -# Get Linked Account ID -$connAcctSvc = Get-VmcService -Name com.vmware.vmc.orgs.account_link.connected_accounts -$connAcctId = $connAcctSvc.get($org.id) | Select-Object -ExpandProperty id -Write-Host "Account ID: $connAcctId" +# Check to use the already existing AWS account connection +if ($useAwsAccount -eq $true) { + # Get Linked Account ID + $connAcctSvc = Get-VmcService -Name com.vmware.vmc.orgs.account_link.connected_accounts + $connAcctId = $connAcctSvc.get($org.id) | Select-Object -ExpandProperty id + Write-Output -InputObject "Account ID: $connAcctId" -# Get Subnet ID -$compSubnetSvc = Get-VmcService -Name com.vmware.vmc.orgs.account_link.compatible_subnets -$vpcMap = $compSubnetSvc.Get($org.id, $connAcctId, $region) | Select-Object -ExpandProperty vpc_map -$compSubnets = $vpcMap | Select-Object -ExpandProperty Values | Select-Object -ExpandProperty subnets -$compSubnet = $compSubnets | where {$_.name -ne $null} | Select-Object -first 1 -Write-Host "Subnet CIDR"$compSubnet.subnet_cidr_block"ID:"$compSubnet.subnet_id + # Get Subnet ID + $compSubnetSvc = Get-VmcService -Name com.vmware.vmc.orgs.account_link.compatible_subnets + $vpcMap = $compSubnetSvc.Get($org.id, $connAcctId, $region) | Select-Object -ExpandProperty vpc_map + $compSubnets = $vpcMap | Select-Object -ExpandProperty Values | Select-Object -ExpandProperty subnets + $compSubnet = $compSubnets | where {$_.name -ne $null} | Select-Object -first 1 + Write-Output -InputObject "Subnet CIDR $($compSubnet.subnet_cidr_block) ID: $($compSubnet.subnet_id)" +} +elseif ($useAwsAccount -eq $false) { + Write-Output -InputObject "AWS Account Not Configured - you must connect to an AWS account within 14 days of creating this SDDC" +} # Deploy the SDDC $sddcSvc = Get-VmcService com.vmware.vmc.orgs.sddcs @@ -40,12 +47,20 @@ $sddcCreateSpec.Name = $sddcName $sddcCreateSpec.num_hosts = $hostCount if ($org.properties.values.sddcTypes) {$sddcCreateSpec.sddc_type = "1NODE"} $sddcCreateSpec.Provider = "AWS" -$accountLinkSpec = $sddcSvc.Help.create.sddc_config.account_link_sddc_config.Element.Create() -$accountLinkSpec.connected_account_id = $connAcctId -$custSubId0 = $sddcSvc.Help.create.sddc_config.account_link_sddc_config.Element.customer_subnet_ids.Element.Create() -$custSubId0 = $compSubnet.subnet_id -$accountLinkSpec.customer_subnet_ids.Add($custSubId0) | Out-Null -$sddcCreateSpec.account_link_sddc_config.Add($accountLinkSpec) | Out-Null -$sddcCreateSpec + +if ($useAwsAccount -eq $true) { + $accountLinkSpec = $sddcSvc.Help.create.sddc_config.account_link_sddc_config.Element.Create() + $accountLinkSpec.connected_account_id = $connAcctId + $custSubId0 = $sddcSvc.Help.create.sddc_config.account_link_sddc_config.Element.customer_subnet_ids.Element.Create() + $custSubId0 = $compSubnet.subnet_id + $accountLinkSpec.customer_subnet_ids.Add($custSubId0) | Out-Null + $sddcCreateSpec.account_link_sddc_config.Add($accountLinkSpec) | Out-Null +} +elseif ($useAwsAccount -eq $false) { + $accountLinkDelaySpec = $sddcSvc.Help.create.sddc_config.account_link_config.delay_account_link.Create() + $accountLinkDelaySpec = $true + $sddcCreateSpec.account_link_config.delay_account_link = $accountLinkDelaySpec +} + $newSddc = $sddcSvc.create($org.Id, $sddcCreateSpec) -$newSddc \ No newline at end of file +$newSddc | Select-Object resource_id,status,task_type,start_time,task_id \ No newline at end of file diff --git a/Scripts/VMware_Cloud_on_AWS/VMWonAWS_FirewallRuleAccelerator.ps1 b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_FirewallRuleAccelerator.ps1 new file mode 100644 index 0000000..de5b870 --- /dev/null +++ b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_FirewallRuleAccelerator.ps1 @@ -0,0 +1,209 @@ +# Author: Kyle Ruddy +# Product: VMware Cloud on AWS +# Description: VMware Cloud on AWS Firewall Rule Accelerator for PowerCLI +# Requirements: +# - PowerShell 3.x or newer +# - PowerCLI 6.5.4 or newer +# - Use Default IP Addresses +# - Use NSX-V on VMware Cloud on AWS + +#---------- USER VARIABLES ---------------------------------------- + +$oauthToken = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx" +$orgId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx' +$sddcId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx' + +# ---------- DO NOT MODIFY BELOW THIS ------------------------------ + + +Connect-Vmc -RefreshToken $oauthToken | Out-Null + +$orgSvc = Get-VmcService -Name com.vmware.vmc.orgs + +if ($orgId) { + $org = $orgSvc.List() | where {$_.id -eq $orgId} +} +else {$org = $orgSvc.List()} + +if ($org -eq $null) {Write-Output "No Org Found. Exiting."; break} + +$sddcSvc = Get-VmcService -Name com.vmware.vmc.orgs.sddcs + +if ($sddcId) { + $sddc = $sddcSvc.Get($org.id, $sddcId) +} +else {$sddc = $sddcSvc.List($org.id)} + +if ($sddc -eq $null) {Write-Output "No SDDC Found. Exiting."; break} +elseif ($sddc -is [array]) {Write-Output "Multiple SDDCs Found. Please Specify an SDDC ID. Exiting."; break} + +$edgeSvc = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges +$mgwEdge = ($edgeSvc.Get($org.id,$sddcId,'gatewayServices') | Select-Object -ExpandProperty edge_page).data | where {$_.id -eq 'edge-1'} + +$ipsecSvc = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.ipsec.config +$ipsecVPN = $ipsecSvc.Get($org.id, $sddcId, $mgwEdge.id) + +$localSubnet = $ipsecVPN.sites.sites.local_subnets.subnets +$vpnSubnet = $ipsecVPN.sites.sites.peer_subnets.subnets +$vcMgmtIP = $sddc.resource_config.vc_management_ip +$vcPublicIP = $sddc.resource_config.vc_public_ip +$esxSubnet = $sddc.resource_config.esx_host_subnet +$ipsecVPNname = $ipsecVPN.sites.sites.name + +function Add-VMCFirewallRule { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 08/22/2018 + Organization: VMware + Blog: https://www.kmruddy.com + Twitter: @kmruddy + =========================================================================== + .SYNOPSIS + Creates a Firewall Rule for a given SDDC + .DESCRIPTION + Creates a Firewall Rule for a given SDDC + .EXAMPLE + Add-VMCFirewallRule -OrgId -sddcId -FwRuleName -SourceIpAddress -DestIpAddress -Service + + #> + param( + [Parameter(Mandatory=$true)] + [String]$OrgId, + [Parameter(Mandatory=$true)] + [String]$SddcId, + [Parameter(Mandatory=$false)] + [ValidateSet('Management Gateway','Compute Gateway')] + [String]$Edge = 'Management Gateway', + [Parameter(Mandatory=$true)] + [String]$FwRuleName, + [Parameter(Mandatory=$false)] + $SourceIpAddress, + [Parameter(Mandatory=$false)] + $DestIpAddress, + [Parameter(Mandatory=$true)] + [ValidateSet('HTTPS','ICMP','SSO','Provisioning','Any','Remote Console')] + [String]$Service, + [Parameter(Mandatory=$false)] + [ValidateSet('accept')] + $FwAction = 'accept' + + ) + + if ($edge -eq 'Management Gateway') {$EdgeId = 'edge-1'} + elseif ($edge -eq 'Compute Gateway') {$EdgeId = 'edge-2'} + else {Write-Output "No Valid Edge Input Found."} + + $fwRuleSvc = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules + + $ruleElementSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Element.Create() + $fwRules = $fwRuleSvc.Help.add.firewall_rules.Create() + $ruleSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Create() + + # AppSpec + $appSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Element.application.Create() + # ServiceSpec + $serviceSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Element.application.service.Element.Create() + + if ($Service -eq 'HTTPS') { + $protocol = 'TCP' + $port = @("443") + } + elseif ($Service -eq 'ICMP') { + $protocol = 'ICMP' + $icmpType = 'any' + + } + elseif ($Service -eq 'SSO') { + $protocol = 'TCP' + $port = @("7444") + } + elseif ($Service -eq 'Provisioning') { + $protocol = 'TCP' + $port = @("902") + } + elseif ($Service -eq 'Any') { + $protocol = 'Any' + $port = $null + } + elseif ($Service -eq 'Remote Console') { + $protocol = 'TCP' + $port = @("903") + } + else {Write-Output "No Protocol Found."; break} + + $serviceSpec.protocol = $protocol + + # Process ICMP Type from JSON + $icmpType = $null + if($protocol -eq 'ICMP') { + $icmpType = 'any' + } + + if ($icmpType) { + $serviceSpec.icmp_type = $icmpType} + if ($port) { + $serviceSpec.port = $port + $serviceSpec.source_port = @("any") + } + + $addSpec = $ruleElementSpec.application.service.Add($serviceSpec) + + + # Create Source Spec + if($SourceIpAddress) { + $srcSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Element.source.Create() + $srcSpec.exclude = $false + $srcSpec.ip_address = @($SourceIpAddress) + $ruleElementSpec.source = $srcSpec + } + + + # Create Destination Spec + if($DestIpAddress) { + $destSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Element.destination.Create() + $destSpec.exclude = $false + $destSpec.ip_address = @($DestIpAddress) + $ruleElementSpec.destination = $destSpec + + } + + + $ruleElementSpec.rule_type = "user" + $ruleElementSpec.enabled = $true + $ruleElementSpec.logging_enabled = $false + + $ruleElementSpec.action = $FwAction + $ruleElementSpec.name = $FwRuleName + + # Add the individual FW rule spec into our overall firewall rules array + Write-Output "Creating VMC Firewall Rule: $FwRuleName" + $ruleSpecAdd = $ruleSpec.Add($ruleElementSpec) + + $fwRules.firewall_rules = $ruleSpec + $fwRuleAdd = $fwRuleSvc.add($orgId,$sddcId,$EdgeId,$fwRules) + +} + + +# vCenter (ANY) to VPN +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "vCenter (ANY) to $ipsecVPNname" -SourceIpAddress $vcMgmtIP -DestIpAddress $vpnSubnet -Service 'Any' + +# ESXi (ANY) to VPN +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "ESXi (ANY) to $ipsecVPNname" -SourceIpAddress $esxSubnet,'10.2.16.0/20' -DestIpAddress $vpnSubnet -Service 'Any' + +# VPN to vCenter (HTTPS) +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "$ipsecVPNname to vCenter (HTTPS)" -SourceIpAddress $vpnSubnet -DestIpAddress $vcMgmtIP -Service 'HTTPS' + +# VPN to vCenter (ICMP) +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "$ipsecVPNname to vCenter (ICMP)" -SourceIpAddress $vpnSubnet -DestIpAddress $vcMgmtIP -Service 'ICMP' + +# VPN to ESXi (Provisioning) +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "$ipsecVPNname to ESXi (Provisioning)" -SourceIpAddress $vpnSubnet -DestIpAddress $esxSubnet,'10.2.16.0/20' -Service 'Provisioning' + +# VPN to ESXi (Remove Console) +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "$ipsecVPNname to ESXi (Remote Console)" -SourceIpAddress $vpnSubnet -DestIpAddress $esxSubnet,'10.2.16.0/20' -Service 'Remote Console' + +# VPN to ESXi (ICMP) +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "$ipsecVPNname to ESXi (ICMP)" -SourceIpAddress $vpnSubnet -DestIpAddress $esxSubnet,'10.2.16.0/20' -Service 'ICMP' \ No newline at end of file diff --git a/Scripts/VMware_Cloud_on_AWS/VMWonAWS_InviteUsers.ps1 b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_InviteUsers.ps1 new file mode 100644 index 0000000..59ddb7a --- /dev/null +++ b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_InviteUsers.ps1 @@ -0,0 +1,114 @@ +<# +.SYNOPSIS + Takes email address input in order to create VMware Cloud on AWS invites for the desired Organization +.DESCRIPTION + Script which can be used to automate the process of adding new users to a specified VMware Cloud on AWS Organization +.NOTES + Author: Kyle Ruddy, @kmruddy, kmruddy.com +.PARAMETER newUserEmail + Plain text email address or array of email addresses +.PARAMETER roleName + Desired role name of the new users, default is Organization Member +.EXAMPLE + PS > ./VMWonAWS_InviteUsers.ps1 -newUserEmail 'testuser@vmware.com' +.EXAMPLE + PS > ./VMWonAWS_InviteUsers.ps1 -newUserEmail $arrayOfEmailAddresses +#> +[CmdletBinding(SupportsShouldProcess=$True)] + param ( + + [Parameter (Mandatory = $True, Position=0)] + $newUserEmail, + [Parameter (Mandatory = $False, Position=1)] + [ValidateSet("Organization Member","Organization Owner","Support User")] + [string]$roleName = "Organization Member" + ) + + # Set Static Variables for your environment + $oauthToken = 'xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + $orgID = 'xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + + ### DO NOT MODIFY CODE BELOW THIS LINE ### + $inviteReport = @() + $userEmail = @() + + # Email Validation Testing + if ($newUserEmail -is [array]) { + foreach ($email in $newUserEmail) { + try { + $userEmail += [mailAddress]$email | select-object -ExpandProperty Address + } + catch { + Write-Warning "$email is not a valid email address" + } + } + } + else { + try { + $userEmail += [mailAddress]$newUserEmail | select-object -ExpandProperty Address + } + catch { + Write-Warning "$newUserEmail is not a valid email address" + } + } + + if ($userEmail.Count -eq 0) { + Write-Warning "No valid email addresses found." + Break + } + + # Validation and translation of the role name to the role ID + if ($roleName -eq 'Organization Member') { + $orgRoleNames = @("org_member") + } + elseif ($roleName -eq 'Organization Owner') { + $orgRoleNames = @("org_owner") + } + elseif ($roleName -eq 'Support User') { + $orgRoleNames = @("support_user") + } + + # Creating custom objects to start building out the body input + $bodyObj = new-object -TypeName System.Object + $SvcRoleNames = @("vmc-user:full") + $SvcDefinitionLink = '/csp/gateway/slc/api/definitions/external/ybUdoTC05kYFC9ZG560kpsn0I8M_' + $bodyObj | Add-Member -Name 'orgRoleNames' -MemberType Noteproperty -Value $orgRoleNames + $serviceRolesDtos = New-Object -TypeName System.Object + $serviceRolesDtos | Add-Member -Name 'serviceDefinitionLink' -MemberType Noteproperty -Value $SvcDefinitionLink + $serviceRolesDtos | Add-Member -Name 'serviceRoleNames' -MemberType Noteproperty -Value $SvcRoleNames + $bodyObj | Add-Member -Name 'serviceRolesDtos' -MemberType Noteproperty -Value @($serviceRolesDtos) + $bodyObj | Add-Member -Name 'usernames' -MemberType Noteproperty -Value $userEmail + $body = $bodyObj | ConvertTo-Json -Depth 100 + + # Connecting to the REST API service for authentication and then to perform the POST method + $connection = Invoke-WebRequest -Uri "https://console.cloud.vmware.com/csp/gateway/am/api/auth/api-tokens/authorize?refresh_token=$oauthToken" -Method Post + $accesskey = ($connection.content | Convertfrom-json).access_token + $inviteUsers = Invoke-WebRequest -Uri "https://console.cloud.vmware.com/csp/gateway/am/api/orgs/$orgID/invitations" -headers @{"csp-auth-token"="$accesskey"} -Method Post -Body $body -ContentType "application/json" + + # Outputting the successful invite which was just created + $orgInviteRefResponse = Invoke-WebRequest -Uri "https://console.cloud.vmware.com/csp/gateway/am/api/orgs/$orgid/invitations" -headers @{"csp-auth-token"="$accessKey"} -Method Get + if ($orgInviteRefResponse) { + $orgInviteRefObject = $orgInviteRefResponse | ConvertFrom-Json + + foreach ($inviteRef in $orgInviteRefObject) { + $link = $inviteRef.refLink + $orgInviteResponse = Invoke-WebRequest -Uri "https://console.cloud.vmware.com$link" -headers @{"csp-auth-token"="$accessKey"} -Method Get + + $orgInviteObject = $orgInviteResponse.content | ConvertFrom-Json + + foreach ($emailInput in $userEmail) { + + if ($orgInviteObject.username -eq $emailInput) { + $i = New-Object System.Object + $i | Add-Member -Type NoteProperty -Name InviteID -Value $orgInviteObject.refLink.Substring($orgInviteObject.refLink.Length - 36) + $i | Add-Member -Type NoteProperty -Name Username -Value $orgInviteObject.username + $i | Add-Member -Type NoteProperty -Name Status -Value $orgInviteObject.status + $i | Add-Member -Type NoteProperty -Name OrgRoles -Value ($orgInviteObject.OrgRoleNames -join ", ") + $i | Add-Member -Type NoteProperty -Name Requester -Value $orgInviteObject.generatedBy + $inviteReport += $i + } + } + } + } + + return $inviteReport \ No newline at end of file diff --git a/Scripts/VMware_Cloud_on_AWS/XRef-VMC-Services.ps1 b/Scripts/VMware_Cloud_on_AWS/XRef-VMC-Services.ps1 new file mode 100644 index 0000000..eb591bb --- /dev/null +++ b/Scripts/VMware_Cloud_on_AWS/XRef-VMC-Services.ps1 @@ -0,0 +1,37 @@ +$refreshToken = 'your-refresh-token' + +$reportPath = '.\VMC-services.xlsx' + +Connect-Vmc -RefreshToken $refreshToken > $null + +$columns = @{} +$services = Get-VmcService | Sort-Object -Property Name +$services | ForEach-Object -Process { + $_.Help | Get-Member -MemberType NoteProperty | where{'Constants','Documentation' -notcontains $_.Name} | + ForEach-Object -Process { + if(-not $columns.ContainsKey($_.Name)){ + $columns.Add($_.Name,'') + } + } +} +$columns = $columns.Keys | Sort-Object +$report = @() +foreach($service in $services){ + $obj = [ordered]@{ + Name = $service.Name + } + $columns | ForEach-Object -Process { + $obj.Add($_,'') + } + + $service.Help | Get-Member -MemberType NoteProperty | where{'Constants','Documentation' -notcontains $_.Name} | + ForEach-Object -Process { +# $obj.Item($_.Name) = "$($service.Help.$($_.Name).Documentation)" + $obj.Item($_.Name) = "X" + } + $report += New-Object PSObject -Property $obj +} +$report | Export-Excel -Path $reportPath -WorksheetName 'Services' -FreezeTopRow -BoldTopRow -AutoSize -Show + +Disconnect-Vmc -Confirm:$false + diff --git a/Scripts/backup-esxi-host-configuration.ps1 b/Scripts/backup-esxi-host-configuration.ps1 new file mode 100644 index 0000000..924ca06 --- /dev/null +++ b/Scripts/backup-esxi-host-configuration.ps1 @@ -0,0 +1,22 @@ +<# +Script name: backup-esxi-host-configuration.ps1 +Created on: 09/10/2018 +Author: Gerasimos Alexiou, @jerrak0s +Description: The purpose of the script is to backup esxi host configuration for restore purposes. +Dependencies: None known + +===Tested Against Environment==== +vSphere Version: 6.5 U2 +PowerCLI Version: PowerCLI 10.1.1 +PowerShell Version: 5.1 +OS Version: Windows 10 +Keyword: Backup Configuration ESXi Host +#> + + +$serverIp = Read-Host 'What is the server ip address:' +$path = Read-Host 'Give path where backup configuration will be stored:' +$serverPass = Read-Host 'What is the server root password:' -AsSecureString +Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false +Connect-VIServer serverip -user "root" -password $serverPass +Get-VMHostFirmware -vmhost serverip -BackupConfiguration -DestinationPath $path \ No newline at end of file