Satellite 6 - Listing of hosts with installed package(s)

Latest response


for now i must go to every single contenthost to see what package or version of packages are installed.
How can i get a list of hosts who has installed a specific package.


What version of Satellite are you running?

In Satellite 6.1, this was particularly difficult to do via the UI, and you had to resort to calling the API to get this data. An example is the script.

In Satellite 6.2, you can leverage the improved search capabilities to search for hosts by package, by going to Hosts -> Content Hosts and inputting installed_package = $NAME_VERSION_OF_PACKAGE -> Example:

Image of hosts page

Note: the search fields supports various operators such as > (greater than), < (less than), as well as boolean operators for AND (& or &&), OR (| , or ||), or NOT ( - or ! )

Hi Rich,

i'm still using Satellite 6.1.9.
Thanks for your great script, this helps me a lot.

Hi Guru, I have facing the below error while executing the script. displayMessage "You have not set a default organization on the user admin." errors
0 "You have not set a default organization on the user admin."

this probably won't help... you asked for contenthost... but if you can use a script,

For a match against a single rpm...

echo -n `hostname -s` ": " `rpm -qa | grep $package`

Push the above through the satellite server.

for a match against a number of packages...

packages=( apache httpd kernel )
for i in ${packages[@]}
  do echo -n `hostname -s` ": " `rpm -qa | grep $i`

The output will show the hostname with a full colon character and the list of package(s) matching following the hostname (the first one is a single rpm query, the bottom one is for multiple packages).

I often push scripts such as the above via spacecmd (I suspect hammer in satellite 6 will do the same in some fashion)

@Rich Jerrido, yes this is helpful. can you tell me how to get report with Machine type like physical or virtual ! Example : installed_package > kernel-2.6.18-416.el5.x86_64 and content_view = cv-rhel5 From above how do choose Virtual or physical? Thanks Ram

Virtual or Physical is a system fact, so adding

facts.is_virtual = true or facts.is_virtual = false

to your searches will allow you to include virtual or physical systems (respectively).


Here is an example of Python script that collects info for a specific package and sends an email with CSV attachment. It can me easily modified to do much more:


import json
import sys
import ConfigParser
import urllib2
import urllib
import base64
import warnings
import datetime
import smtplib
import glob, os
import time

  import requests
except ImportError:
  print "Please install the python-requests module."

defval1 = "" 
defval2 = "" 

mydate ="%d%b%Y")
myresults = 'Sat6-installed-packages-{0}.csv'.format(mydate)

# Save report in CSV file
tcfile = open(myresults, "w+")

# URL to Satellite 6 server.
URL = "https://sat6srv.domain.dom"

# URL for the API to deployed Satellite 6 server.
SAT_API = "%s/api/v2/" % URL
SAT_API2 = "%s/api/hosts/" % URL
SAT_API3 = "%s/api/v2/hosts/" % URL

# Katello-specific API
KATELLO_API = "%s/katello/api/" % URL
POST_HEADERS = {'content-type': 'application/json'}

# Default credentials to login to Satellite 6.
# Read Satellite API login and password and do not disclose it in the script itself.
mydir = "/home/myuser/.config-sat6"
config = ConfigParser.ConfigParser()
USERNAME = config.get("sat6", "username")
PASSWORD = config.get("sat6", "password")


def isNotEmpty(s):
  return bool(s and s.strip())

def get_json(location):
  Performs a GET using the passed URL location
  r = requests.get(location, auth=(USERNAME, PASSWORD), verify=SSL_VERIFY)

  jsn = r.json()
  hosts = jsn['results']
  for host in hosts:
    base64string = base64.encodestring('%s:%s' % (USERNAME, PASSWORD)).strip()
    request = urllib2.Request(SAT_API3 + str(host['name']))
    request.add_header("Authorization", "Basic %s" % base64string)
    result = urllib2.urlopen(request)
    jsonresult = json.load(result)
    request2 = urllib2.Request(SAT_API2 + str(host['id']) + "/packages?per_page=3000")
    request2.add_header("Authorization", "Basic %s" % base64string)
    result2 = urllib2.urlopen(request2)
    jsonresult2 = json.load(result2)

    myinst = ''
    for dataform in jsonresult2['results']:
      if 'MyPackage' in dataform['nvra']:
        myinst = dataform['nvra']
    if isNotEmpty(jsonresult['subscription_facet_attributes']['registered_at']):
      defval1 = jsonresult['subscription_facet_attributes']['registered_at']

    if isNotEmpty(jsonresult['subscription_facet_attributes']['last_checkin']):
      defval2 = jsonresult['subscription_facet_attributes']['last_checkin']

    if isNotEmpty(myinst):
      print >> tcfile, "%s, %s, %s, %s, %s, %s, %s, %s" % (host['name'], jsonresult['operatingsystem_name'], jsonresult['facts']['kernelrelease'],
          jsonresult['facts']['cpu::cpu(s)'], defval1, jsonresult['facts']['uptime'], defval2, myinst )

print >> tcfile, "System,RHEL Release,Kernel,CPU Count,Registration Date,Uptime,Last Checkin to Satellite,Package Installations"

myhosts = get_json(SAT_API + "hosts/?per_page=3000")


# Email package modules we need
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.mime.base import MIMEBase
from email import encoders


# Create the container (outer) email message
msg = MIMEMultipart()
msg['Subject'] = 'SUMMARY: Package status
me = "root@domain.dom "
family = "myroup@domain.dom"
msg['From'] = "me@domain.dom"
msg['To'] = family
msg.preamble = 'Whatever'

# Open the CSV file in binary mode
fp = open(myresults, 'rb')
xls = MIMEBase('application','')
xls.add_header('Content-Disposition', 'attachment', filename=myresults)

# Send the email via our own SMTP server
s = smtplib.SMTP('smptsrv.domain.dom')
s.sendmail(me, family, msg.as_string())



Dusan Baljevic (amateur radio VK2COT)

What if you want to list content hosts that DON'T have a particular package installed? In Satellite 5, all you had to do was click on the package, then there was a tab that showed the name of the server that didn't have the package installed.

That's a simple search query in the UI. On the hosts page, you generally would use a search query similar to installed_package = $NAME_VERSION_OF_PACKAGE. To perform a negative query (thus show systems without a specific version of a package), use:

NOT installed_package = $NAME_VERSION_OF_PACKAGE

I was trying != and other variations for ages, cheers for that!

Scotty, that is not a proper tone of voice, please refrain from posting such comments in the future !


Hi Scotty,

Thank you for having changed the content of your post ... looks much better now. :)


Hi Know this is an old post but thought I would ask here. I want to search for firefox ona ll installed nodes. However doin as you susgest above does nto return any values. I am using satellite 6.4.

installed_package = firefox or installed_package = firefox*

It appears the search wants a specific release. No wildcards accepted?

Thank you in advance for responding. update i just tried installed_package_name = firefox

Seems that is a better search query for specific package.

Please correct me if i am wrong.

Could you try:

installed_package ~ firefox*

As far as I know, "=" is exact match (so you would have to provide NVR of the package), while "~" is similarity match.

Also, when you start to type the query, the auto-complete tool will offer you possible values as well.

To find all servers with any version of package firefox, the installed_package_name filter can be used. At least in Satellite 6.8.x.


Sometimes query from Satellite web page can be very slow!! You can do it directly from Postgres database.

[root@satellite ~]# su - postgres

-bash-4.2$ psql foreman

foreman=# select,, pkgs.nvra from katello_host_installed_packages host_pkg, katello_installed_packages pkgs, hosts srv where = 'tzdata' and pkgs.nvra like 'tzdata-2019b%' and host_pkg.host_id = and host_pkg.installed_package_id =;

Be careful, i don't that it is supported, but is safe...