Solving Problems With python-jss: Finding the Printers in the Policies
I wanted to start showing some short examples of easy and quick python scripts that I have used in my day-to-day admin job. Today I got around to working on a broken printer installation. One of our printers had a driver that was not working, and needed to be switched out.
Adding the package to the JSS and creating an update policy was no big deal, but I wanted to know exactly which policies distributed that printer. If you need to change a printer’s PPD file, you have to remove and then re-add a printer; and when you remove a printer from Casper Admin, that printer gets silently dropped from all policies as well. We have a large number of policies, and I don’t like to make mistakes, so I wanted to get this right the first time.
python-jss to the rescue!
I of course already have my python-jss preferences set up (see the Wiki!), so we can start with:
and we have a functioning JSS object.
Next, we are interested in looking at Policies, so let’s grab them:
Notice that I skip the intermediary step of assigning the results of j.Policy()
to a variable. This would just give us a list of policy ID’s and names, which isn’t enough information. We want the entire XML for the policies.
Speaking of which, we need to know a little bit about the structure of a policy to be able to find the data that we’re interested in (we can’t just “Find”) through the whole text, since this is XML, and structure is important! So, doing a little research, I pulled up one of my printer-installer policies and looked at the relevant data. Here’s how to do it, and what it looks like (I trimmed out all of the unimportant stuff):
So we can see that a policy has a “printers” section, with a list of “printer”s. Each “printer” has its user-facing name in a subelement named “name”. Also, the policy has an ID and a name which I’m interested in because I want to make sure I know how to identify them later. Fortunately, pretty much all JSSObject subclasses have a convenience accessor for .id and .name.
Now, we just loop through all of the policies looking for a printer with the name we’re looking for; in this case “LSCopier”. This is slightly challenging because it involves using the interface to ElementTree.Element
. Let’s look at the fully expanded version first:
Running this short (10 lines) gets me my results. Indeed, I could probably parameterize this and re-use it later… Which I’ll do next. Also, let’s trim it up into a list comprehension.
(There’s no way this will fit on a single line in this theme… Sorry!) This nets us a “results” array filled with tuples of policy names and ids that match our argument “search_name”. To pull this off we need to import sys, and make a few more changes.
Here is the entire finished script:
This would be easy to expand into a more general XML search utility for auditing your Policies. For example, you may want to search for policies that install a particular package (although jss_helper already does that). Or you might want to search for policies that Recon.