Skip to main content

PowerShell Python Citrix Tricks.

Project description

PSytricks

PyPI PyPI - License pdoc Ruff

PowerShell Python Citrix Tricks - pun intended.

logo

This package provides an abstraction layer allowing Python code to interact with a Citrix Virtual Apps and Desktops (CVAD) stack, i.e. to fetch status information and trigger actions on machines and sessions. Since CVAD only provides a PowerShell Snap-In to do so, a core component written in Windows PowerShell (note: not PowerShell Core as snap-ins are not supported there) is required.

PSyTricks ships with two options for the PowerShell layer:

  • A wrapper script that is launched as a subprocess from the Python code. It doesn't require any further setup beyond the package installation but performance, well, slow.
  • A (zero-authentication) REST (see the note below on this) service providing several GET and POST endpoints to request status information or perform actions. Performance is much better compared to the wrapper script, but obviously this requires the code to be running as a service in an appropriate permission context.

NOTE: this RESTful claim isn't fully true. Or actually not at all, it would be better called an HTTP-JSON-RPC-API. For now, we'll still be using the term REST for it as the functionality of this package basically serves a very similar purpose to what people think of when they are coming across this label. Apologies, Roy T. Fielding.

🤯 Are you serious?

Calling PowerShell as a subprocess from within Python? 😳

To convert results to JSON and pass them back, just to parse it again in Python. Really? 🧐

Or, not sure if that's any better, implementing an HTTP REST API in plain PowerShell?!? 🫣

✅ Yes, we are

And the package name was chosen to reflect this.

To be very clear: performance of the wrapper script is abysmal, but this is not at all an issue for us. Abysmal, as in: for every wrapped call a full (new) PowerShell process needs to be instantiated, usually taking something like 1-2 seconds. ⏳

The REST / HTTP-RPC interface provides a much better performance, at the cost of some additional setup. If you're happy to take on this approach, the package offers a very smooth ride. 🎢🎡

🛠🚧 Installation

Prerequisites

As mentioned above, the Citrix Broker PowerShell Snap-In is required to be installed on the machine that will run the wrapper script, since its commands are being used to communicate with the CVAD stack. This is also the reason why this package will work on Windows PowerShell only as snap-ins are not supported on other PowerShell editions. Please note this also implies that the latest usable PowerShell version is 5.1 as newer ones have dropped support for snap-ins (but that's a different problem that Citrix will have to solve at some point).

To install the snap-in, look for an MSI package like this in the Delivery Controller or XenDesktop installation media and install it as usual:

  • Broker_PowerShellSnapIn_x64.msi

Installing the 🐍 Python package

In case you're planning to use psytricks via the subprocess approach (discouraged but less components to set up), you will have to install the package itself on the Windows machine having the above mentioned Snap-In installed. For the REST approach (recommended) only the PowerShell service described in the section below has to run on that machine - the Python package can be installed on any computer that is able to talk to the REST service.

For installing psytricks please create and activate a venv, then run:

pip install psytricks

NOTE: this will also register the psytricks CLI tool although that one is mostly meant for testing and demonstration purposes, otherwise the *-Broker* commands provided by the PowerShell snap-in could be used directly.

Setting up the REST service

💡 When using the ResTricksService (recommended), only that service itself needs to run on a Windows machine having the Citrix Broker PowerShell Snap-In installed - the 🐍 Python package can then be used from any (Linux, ...) system that is able to connect to the service!

The currently recommended way for installing the ResTricksService is using WinSW (Windows Service Wrapper) but you may choose anything you like to launch the server process like NSSM, Scheduled Tasks 📅, homegrown dark magic 🪄🔮 or others.

🧪 A more recent approach could be Shawl - let us know if you've tried it and how it went!

To go with WinSW simply download the bundled version provided with each PSyTricks release. Just look for the .zip asset having REST and WinSW in its name, matching your .NET version.

🔧 Configuration

Unzip the downloaded file to the desired target location, e.g. %PROGRAMDATA%\PSyTricks, then copy / rename restricks-server.example.xml to restricks-server.xml and open it in an editor.

Adapt the entries in the <serviceaccount> section to match your requirements and make sure to update the hostname passed via the -AdminAddress parameter in the <startarguments> section. It needs to point to your Citrix Delivery Controller, just in case that's not obvious.

🛑⚠️🛑 Enable execution

Depending on the security policies in place on your system, the service components need to be explicitly unblocked before the service can be started. To do this, run the following commands:

cd C:\ProgramData\PSyTricks  # or wherever you're installing to
Unblock-File .\psytricks-lib.ps1
Unblock-File .\restricks-server.ps1
Unblock-File .\restricks-server.exe

💡 Those steps also need to be performed when upgrading the service, which is done by replacing exactly the files listed above. For a TL;DR summary on downloading, extracting and upgrading an installation, see the installation / upgrade instructions.

☑️ Register and 🏃🏼‍♀️‍➡️ run it

The final step is to install and start the service:

.\restricks-server.exe install
Start-Service RESTricksServer

In case the service doesn't start up, check the Windows Event Log and the .log files created by WinSW in the service directory.

Once the service has started, you can monitor its actions by live-watching the log file:

Get-Content -Wait C:\ProgramData\PSyTricks\restricks-server.log

Tada! That's it, the service is now ready to take HTTP requests (from localhost)! 🎉

Please be aware that the REST interface doesn't do any authentication on purpose, meaning everything / everyone that can access it will be able to run all requests!

We're using it in combination with an 🔐🌐 SSH tunnel but essentially anything that controls who / what can access the service will do the job.

🎪 What does it provide?

To interact with CVAD, a wrapper object needs to be instantiated and instructed how to communicate with the stack.

Using the REST service - recommended

After setting up the REST service as described above and making sure to be able to connect to it (firewall rules, ssh tunnel, ...), a psytricks.wrapper.ResTricksWrapper object can be used while passing the URL under which the REST service is reachable, e.g.

from psytricks.wrapper import ResTricksWrapper

wrapper = ResTricksWrapper(base_url="http://localhost:8080/")

Using the subprocess wrapper - use with caution

(This is only recommended for testing or if for some reason you don't want / can't set up the REST service.)

To create a wrapper object using the subprocess variant, a psytricks.wrapper.PSyTricksWrapper with the address of the Delivery Controller to connect to has to be instantiated, for example:

from psytricks.wrapper import PSyTricksWrapper

wrapper = PSyTricksWrapper(deliverycontroller="cdc01.vdi.example.xy")

Fetching status information

The wrapper object can then be used to e.g. retrieve information on the machines controlled ("brokered") by Citrix:

machines = wrapper.get_machine_status()

for machine in machines:
    print(f"[{machine["DNSName"]}] is in power state '{machine["PowerState"]}'")
print(f"Got status details on {len(machines)} machines.")

Performing actions

To restart a machine, use something like this:

wrapper.perform_poweraction(machine="vm23.vdi.example.xy", action="restart")

For placing a machine in Maintenance Mode use:

wrapper.set_maintenance(machine="vm42.vdi.example.xy", disable=False)

🏗️ ResTricks Service Installation / Upgrade TL;DR ⏩

The commands below can be used to upgrade an existing installation of the ResTricksService - for a fresh installation you'd also need to create the target location and adjust the configuration in restricks-server.xml.

# adjust the version and path variables to your preferences:
$PSyTricksTag = "v2.2.0.a21"
$PSyTricksVersion = "2.2.0a21"
$TargetDir = "C:\ProgramData\PSyTricks"

# this one usually doesn't require changes:
$WinSwVersion = "WinSW.NET461-2.12.0"

$PSyTricksPkg = "psytricks-REST-${PSyTricksVersion}_${WinSwVersion}"
$PSyTricksZip = "${PSyTricksPkg}.zip"
$PSyTricksBaseDl = "https://github.com/imcf/psytricks/releases/download"
$PSyTricksUri = "${PSyTricksBaseDl}/${PSyTricksTag}/${PSyTricksZip}"

Set-Location "C:\Temp\"

Invoke-WebRequest -Uri $PSyTricksUri -OutFile $PSyTricksZip
Expand-Archive $PSyTricksZip -DestinationPath .
Set-Location $PSyTricksPkg
# when upgrading, simply remove the example config - for an initial installation
# move it to the target location and rename it to "restricks-server.xml":
Remove-Item restricks-server.example.xml

Stop-Service RESTricksServer
Get-Service RESTricksServer

foreach ($File in Get-ChildItem -File) {
    Unblock-File -Path $File.FullName
    Move-Item -Path $File.FullName -Destination $TargetDir -Force
}

Start-Service RESTricksServer
Get-Service RESTricksServer
Get-Content -Tail 10 "${TargetDir}\restricks-server.wrapper.log"

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

psytricks-2.2.0.tar.gz (43.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

psytricks-2.2.0-py3-none-any.whl (43.7 kB view details)

Uploaded Python 3

File details

Details for the file psytricks-2.2.0.tar.gz.

File metadata

  • Download URL: psytricks-2.2.0.tar.gz
  • Upload date:
  • Size: 43.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for psytricks-2.2.0.tar.gz
Algorithm Hash digest
SHA256 39e0c2ffdc84ba0ee50d8e628720ca3937fa0773e80d6a26ab7398ee380d34fc
MD5 1ec9597d6b603e006c6cd7805414a512
BLAKE2b-256 70fe69c88fa52729de3dfb86b20762116d37cc5cf4e5ba4c5c9aa69fda8908ca

See more details on using hashes here.

Provenance

The following attestation bundles were made for psytricks-2.2.0.tar.gz:

Publisher: release.yml on imcf/psytricks

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file psytricks-2.2.0-py3-none-any.whl.

File metadata

  • Download URL: psytricks-2.2.0-py3-none-any.whl
  • Upload date:
  • Size: 43.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for psytricks-2.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e168639695eff549dfccb064e058f2e4a6b250fc25b0e79c0689146effee70c1
MD5 da3c0f456948240c0abe6ce4282df7b9
BLAKE2b-256 91555441a94c30285caebf6552b7a609390de2ef0c6f9c83f2be06eb8e895e82

See more details on using hashes here.

Provenance

The following attestation bundles were made for psytricks-2.2.0-py3-none-any.whl:

Publisher: release.yml on imcf/psytricks

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page