From 677d0c211d0006751b407e233d2f4dac34c6c2a2 Mon Sep 17 00:00:00 2001 From: William Lam Date: Wed, 4 Oct 2017 14:26:05 -0700 Subject: [PATCH] Adding VMware Fusion Module --- Modules/VMware.Hosted/VMware.Hosted.psd1 | 18 + Modules/VMware.Hosted/VMware.Hosted.psm1 | 501 +++++++++++++++++++++++ 2 files changed, 519 insertions(+) create mode 100644 Modules/VMware.Hosted/VMware.Hosted.psd1 create mode 100644 Modules/VMware.Hosted/VMware.Hosted.psm1 diff --git a/Modules/VMware.Hosted/VMware.Hosted.psd1 b/Modules/VMware.Hosted/VMware.Hosted.psd1 new file mode 100644 index 0000000..59d5b53 --- /dev/null +++ b/Modules/VMware.Hosted/VMware.Hosted.psd1 @@ -0,0 +1,18 @@ +@{ + ModuleToProcess = 'VMware.Hosted.psm1' + ModuleVersion = '1.0.0.0' + GUID = '11393D09-D6B8-4E79-B9BC-247F1BE66683' + Author = 'William Lam' + CompanyName = 'primp-industries.com' + Copyright = '(c) 2017. All rights reserved.' + Description = 'Powershell Module for VMware Fusion 10 REST API' + PowerShellVersion = '5.0' + FunctionsToExport = 'Get-HostedCommand','Connect-HostedServer','Disconnect-HostedServer','Get-HostedVM','Start-HostedVM','Stop-HostedVM','Suspend-HostedVM','Resume-HostedVM','New-HostedVM','Remove-HostedVM','Get-HostedVMSharedFolder','New-HostedVMSharedFolder','Remove-HostedVMSharedFolder','Get-HostedVMNic','Get-HostedNetworks' + PrivateData = @{ + PSData = @{ + Tags = @('Fusion','REST','vmrest') + LicenseUri = 'https://www.tldrlegal.com/l/mit' + ProjectUri = 'https://github.com/lamw/PowerCLI-Example-Scripts/tree/master/Modules/VMware.Hosted' + } + } +} \ No newline at end of file diff --git a/Modules/VMware.Hosted/VMware.Hosted.psm1 b/Modules/VMware.Hosted/VMware.Hosted.psm1 new file mode 100644 index 0000000..4997dee --- /dev/null +++ b/Modules/VMware.Hosted/VMware.Hosted.psm1 @@ -0,0 +1,501 @@ +Function Get-Confirmation { + $choice = "" + while ($choice -notmatch "[y|n]"){ + $choice = read-host "Do you want to continue? (Y/N)" + } + if($choice -ne 'y') { + break + } +} + +Function Connect-HostedServer { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Server, + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Username, + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Password, + [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Protocol = "http", + [parameter(Mandatory=$false,ValueFromPipeline=$true)][int]$Port = 8697 + ) + $pair = $Username+":"+$Password + $bytes = [System.Text.Encoding]::ASCII.GetBytes($pair) + $base64 = [System.Convert]::ToBase64String($bytes) + $basicAuthValue = "Basic $base64" + $headers = @{Authorization = $basicAuthValue} + + $Global:DefaultHostedServer = [pscustomobject] @{ + Server=$Protocol + "://" + $server + ":$Port/api"; + Protcol=$Protocol + Headers=$headers + } + + if($DefaultHostedServer.Protcol -eq "https") { + # PowerShell Core has a nice -SkipCertificateCheck but looks like Windows does NOT :( + if($PSVersionTable.PSEdition -eq "Core") { + $Global:fusionCommand = "Invoke-Webrequest -SkipCertificateCheck " + } else { + # Needed for Windows PowerShell to handle HTTPS scenario + # https://stackoverflow.com/a/15627483 + $Provider = New-Object Microsoft.CSharp.CSharpCodeProvider + $Compiler = $Provider.CreateCompiler() + $Params = New-Object System.CodeDom.Compiler.CompilerParameters + $Params.GenerateExecutable = $false + $Params.GenerateInMemory = $true + $Params.IncludeDebugInformation = $false + $Params.ReferencedAssemblies.Add("System.DLL") > $null + $TASource=@' + namespace Local.ToolkitExtensions.Net.CertificatePolicy + { + public class TrustAll : System.Net.ICertificatePolicy + { + public bool CheckValidationResult(System.Net.ServicePoint sp,System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Net.WebRequest req, int problem) + { + return true; + } + } + } +'@ + $TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource) + $TAAssembly=$TAResults.CompiledAssembly + ## We create an instance of TrustAll and attach it to the ServicePointManager + $TrustAll = $TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll") + [System.Net.ServicePointManager]::CertificatePolicy = $TrustAll + $Global:fusionCommand = "Invoke-Webrequest " + } + } else { + $Global:fusionCommand = "Invoke-Webrequest " + } + $Global:DefaultHostedServer +} + +Function Disconnect-HostedServer { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Server + ) + + $Global:DefaultHostedServer = $null +} + +Function Get-HostedVM { + Param ( + [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id + ) + + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + if($Id) { + $vmUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + try { + $params = "-Headers `$Global:DefaultHostedServer.Headers -Uri $vmUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + $vm = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Invalid VM Id $Id" + break + } + + $vmIPUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/ip" + try { + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmIPUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + $vmIPResults = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + $vmIP = $vmIPResults.ip + } catch { + $vmIP = "N/A" + } + + $vmPowerUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/power" + try { + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + $vmPower = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + $vmPower = "N/A" + } + + $results = [pscustomobject] @{ + Id = $vm.Id; + CPU = $vm.Cpu.processors; + Memory = $vm.Memory; + PowerState = $vmPower.power_state; + IPAddress = $vmIP; + } + $results + } else { + $uri = $Global:DefaultHostedServer.Server + "/vms" + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $uri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + try { + Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Failed to list VMs" + } + } +} + +Function Start-HostedVM { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id + ) + + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + $vmPowerUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/power" + try { + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + $vmPower = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Invalid VM Id $Id" + break + } + + if($vmPower.power_state -eq "poweredOff" -or $vmPower.power_state -eq "suspended") { + try { + Write-Host "Powering on VM $Id ..." + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method PUT -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `"on`"" + $command = $Global:fusionCommand + $params + $vm = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Unable to Power On VM $Id" + break + } + } else { + Write-Host "VM $Id is already Powered On" + } +} + +Function Stop-HostedVM { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id, + [parameter(Mandatory=$false,ValueFromPipeline=$true)][boolean]$Soft, + [parameter(Mandatory=$false,ValueFromPipeline=$true)][boolean]$Confirm = $true + ) + + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + if($Confirm) { + Get-Confirmation + } + + $vmPowerUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/power" + try { + $params += "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + $vmPower = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Invalid VM Id $Id" + break + } + + if($vmPower.power_state -eq "poweredOn") { + if($Soft) { + try { + Write-Host "Shutting down VM $Id ..." + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method PUT -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `"shutdown`"" + $command = $Global:fusionCommand + $params + $vm = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Unable to Shutdown VM $Id" + break + } + } else { + try { + Write-Host "Powering off VM $Id ..." + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method PUT -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `"off`"" + $command = $Global:fusionCommand + $params + $vm = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Unable to Power Off VM $Id" + break + } + } + } else { + Write-Host "VM $Id is already Powered Off" + } +} + +Function Suspend-HostedVM { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id, + [parameter(Mandatory=$false,ValueFromPipeline=$true)][boolean]$Confirm + ) + + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + if($Confirm) { + Get-Confirmation + } + + $vmPowerUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/power" + try { + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + $vmPower = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Invalid VM Id $Id" + break + } + + if($vmPower.power_state -eq "poweredOn") { + try { + Write-Host "Suspending VM $Id ..." + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method PUT -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `"suspend`"" + $command = $Global:fusionCommand + $params + $vm = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Unable to suspend VM $Id" + break + } + } else { + Write-Host "VM $Id can not be suspended because it is either Powered Off or Suspended" + } +} + +Function Resume-HostedVM { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id + ) + + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + $vmPowerUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/power" + try { + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmPowerUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + $vmPower = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Invalid VM Id $Id" + break + } + + if($vmPower.power_state -eq "suspended") { + try { + Start-HostedVM -Id $Id + } catch { + Write-host -ForegroundColor Red "Unable to Resume VM $Id" + break + } + } else { + Write-Host "VM $Id is not Suspended" + } +} + +Function New-HostedVM { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$ParentId, + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Name + ) + + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + $vm = Get-HostedVM -Id $ParentId + + if($vm -match "Invalid VM Id") { + Write-host -ForegroundColor Red "Unable to find existing VM Id $ParentId" + break + } + + $vmUri = $Global:DefaultHostedServer.Server + "/vms" + $body = @{"ParentId"="$ParentId";"Name"=$Name} + $body = $body | ConvertTo-Json + + try { + Write-Host "Cloning VM $ParentId to $Name ..." + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmUri -Method POST -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `$body" + $command = $Global:fusionCommand + $params + Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Failed to Clone VM Id $ParentId" + break + } +} + +Function Remove-HostedVM { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id, + [parameter(Mandatory=$false,ValueFromPipeline=$true)][boolean]$Confirm = $true + ) + + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + $vm = Get-HostedVM -Id $Id + + if($vm -match "Invalid VM Id") { + Write-host -ForegroundColor Red "Unable to find existing VM Id $Id" + break + } + + if($Confirm) { + Get-Confirmation + } + + $vmUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + try { + Write-Host "Deleting VM Id $Id ..." + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmUri -Method DELETE -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Failed to Delete VM Id $Id" + break + } +} + +Function Get-HostedVMSharedFolder { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id + ) + + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + $folderUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/sharedfolders" + try { + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $folderUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Invalid VM Id $Id" + break + } +} + +Function New-HostedVMSharedFolder { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id, + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$FolderName, + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$HostPath + ) + + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + $body = @{"folder_id"="$FolderName";"host_path"=$HostPath;"flags"=4} + $body = $body | ConvertTo-Json + + $folderUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/sharedfolders" + try { + Write-Host "Creating new Shared Folder $FolderName to $HostPath for VM Id $Id ..." + $params += "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $folderUri -Method POST -ContentType `"application/vnd.vmware.vmw.rest-v1+json`" -Body `$body" + $command = $Global:fusionCommand + $params + Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Failed to create Shared Folder for VM Id $Id" + break + } +} + +Function Remove-HostedVMSharedFolder { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id, + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$FolderName, + [parameter(Mandatory=$false,ValueFromPipeline=$true)][boolean]$Confirm = $true + ) + + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + if($Confirm) { + Get-Confirmation + } + + $folderUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/sharedfolders/" + $FolderName + try { + Write-Host "Removing Shared Folder $FolderName for VM Id $Id ..." + $params += "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $folderUri -Method DELETE -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Failed to remove Shared Folder for VM Id $Id" + break + } +} + +Function Get-HostedVMNic { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id + ) + + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + $vmNicUri = $Global:DefaultHostedServer.Server + "/vms/" + $Id + "/nic" + try { + $params += "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $vmNicUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + $vmNics = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Invalid VM Id $Id" + break + } + + $results = @() + foreach ($vmNic in $vmNics.nics) { + $tmp = [pscustomobject] @{ + Index = $vmNic.index; + Type = $vmNic.Type; + VMnet = $vmNic.Vmnet; + } + $results+=$tmp + } + $results +} + +Function Get-HostedNetworks { + if(!$Global:DefaultHostedServer) { + Write-Host -ForegroundColor Red "You are not connected to Hosted Server, please run Connect-HostedServer" + exit + } + + $networksUri = $Global:DefaultHostedServer.Server + "/vmnet" + try { + $params = "-UseBasicParsing -Headers `$Global:DefaultHostedServer.Headers -Uri $networksUri -Method GET -ContentType `"application/vnd.vmware.vmw.rest-v1+json`"" + $command = $Global:fusionCommand + $params + $networks = Invoke-Expression -Command $command | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-host -ForegroundColor Red "Unable to retrieve Networks" + break + } + + $results = @() + foreach ($network in $networks.vmnets) { + $tmp = [pscustomobject] @{ + Name = $network.Name; + Type = $network.Type; + DHCP = $network.Dhcp; + Network = $network.subnet; + Netmask = $network.mask; + } + $results+=$tmp + } + $results +} \ No newline at end of file