Package: psytricks
PSytricksPowerShell Python Citrix Tricks- pun intended.This package provides an abstraction layer allowing Python code to interact with
aCitrix Virtual Apps and Desktops (CVAD)stack, i.e. to fetch
status information and trigger actions on machines and sessions. Since CVAD only
provides aPowerShell Snap-Into do so, a core component written inWindows PowerShell(note:notPowerShell Coreas 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 suprocess 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
severalGETandPOSTendpoints to request status information or perform
actions. Performance ismuchbetter compared to the wrapper script, but
obviously this requires the code to be running as a service in an appropriate
permission context.NOTE: thisRESTfulclaim is actually not entirely true. Or basically not at
all, it would be better called anHTTP-JSON-RPC-API. We'll still be using the
termRESTfor it as this is basically what people nowadays think of when they
are coming across this label. Sorry,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. AreAnd the package name was chosen to reflect this.To be very clear: performance of the wrapper script is abysmal, but this isnot
at allan 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 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. 🎢🎡🛠🚧 InstallationPrerequisitesAs mentioned above, theCitrix Broker PowerShell Snap-Inis 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 onWindows PowerShell onlyas 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 theDelivery ControllerorXenDesktopinstallation media and install it as usual:Broker_PowerShellSnapIn_x64.msiInstalling the 🐍 packageIn case you're planning to usepsytricksvia 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 mentionedSnap-Ininstalled. For theRESTapproach (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 theRESTservice.For installingpsytricksplease create and activate avenv, then run:pipinstallpsytricksNOTE: this will also register thepsytricksCLI 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 serviceThe easiest way for installing the REST service is to useWinSW (Windows
Service Wrapper)but you may choose anything you like to launch the
server process like NSSM, Scheduled Tasks 📅, homegrown dark magic 🪄🔮 or
others.To go withWinSWsimply download the bundled version provided with eachPSyTricks release. Just look for the.zipasset havingRESTandWinSWin its name.Unzip the downloaded file to the desired target location, e.g.%PROGRAMDATA%\PSyTricks, then copy / renamerestricks-server.example.xmltorestricks-server.xmland 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-AdminAddressparameter in
the<startarguments>section. It needs to point to your Citrix Delivery
Controller, just in case that's not obvious.Next step is to install and start the service:cdC:\ProgramData\PSyTricksrestricks-server.exeisntallStart-ServiceRESTricksServerIn case the service doesn't start up, check the Windows Event Log and the.logfiles 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-WaitC:\ProgramData\PSyTricks\restricks-server.logTada! That's it, the service is now ready to take HTTP requests (fromlocalhost)! 🎉Please be aware that the REST interface doesn't doany authenticationon
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 -recommendedAfter setting up the REST service as described above and making sure to be able
to connect to it (firewall rules, ssh tunnel, ...), apsytricks.wrapper.ResTricksWrapperobject can be used while passing the URL
under which the REST service is reachable, e.g.frompsytricks.wrapperimportResTricksWrapperwrapper=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, apsytricks.wrapper.PSyTricksWrapperwith the address of theDelivery
Controllerto connect to has to be instantiated, for example:frompsytricks.wrapperimportPSyTricksWrapperwrapper=PSyTricksWrapper(deliverycontroller="cdc01.vdi.example.xy")Fetching status informationThe wrapper object can then be used to e.g. retrieve information on the machines
controlled ("brokered") by Citrix:machines=wrapper.get_machine_status()formachineinmachines:print(f"[{machine["DNSName"]}] is in power state '{machine["PowerState"]}'")print(f"Got status details on{len(machines)}machines.")Performing actionsTo restart a machine, use something like this:wrapper.perform_poweraction(machine="vm23.vdi.example.xy",action="restart")For placing a machine inMaintenance Modeuse:wrapper.set_maintenance(machine="vm42.vdi.example.xy",disable=False)