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 }