PDA

View Full Version : reporting on patches using salt



jgosney
23-Jan-2017, 20:59
We have recently switched our Susemanager from spacewalk to salt. With spacewalk, I could run spacewalk-channel and grep out patches with a critical status. However, with salt, I can not find a command-line equivalent. I am trying to create a script that will email me a list of any criticals received during the previous night's upgrade.

Anybody know how to accomplish this with salt?

j_renner
24-Jan-2017, 15:57
We have recently switched our Susemanager from spacewalk to salt. With spacewalk, I could run spacewalk-channel and grep out patches with a critical status. However, with salt, I can not find a command-line equivalent. I am trying to create a script that will email me a list of any criticals received during the previous night's upgrade.

How exactly do you do that? Isn't spacewalk-channel rather used to subscribe/unsubscribe to/from channels from within the client? How do you call it to extract the information about patches that you are looking for?


Anybody know how to accomplish this with salt?

Why not simply use zypper lp? You can grep the output for severity as needed. The zypper module of Salt (https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.zypper.html) could be used as well, but it cannot list available patches yet, only package updates via the list_upgrades call. If this is suitable for you though you could call it locally on a minion via salt-call pkg.list_upgrades.

jgosney
24-Jan-2017, 16:12
We thought about that but zypper lp only shows "Repository", "Name", "Version", "Category", and "Status". It doesn't show the severity. I thought maybe "Category" would do it but it is only security/optional/recommend. We're looking for something to display the "low", "important", "moderate", "critical", and then be able to grep or filter on just the "critical". But can't find a CL-switch for zypper to show that.

malcolmlewis
24-Jan-2017, 16:24
On Tue 24 Jan 2017 03:14:02 PM CST, jgosney wrote:

We thought about that but zypper lp only shows "Repository", "Name",
"Version", "Category", and "Status". It doesn't show the severity. I
thought maybe "Category" would do it but it is only
security/optional/recommend. We're looking for something to display the
"low", "important", "moderate", "critical", and then be able to grep or
filter on just the "critical". But can't find a CL-switch for zypper to
show that.




Hi
What about zypper if, for example;


zypper if -t patch SUSE-SLE-RPI-12-SP2-2017-135 SUSE-SLE-RPI-12-SP2-2017-138 |grep Summary
Summary : Recommended update for grub2
Summary : moderate: Security update for openssh


--
Cheers Malcolm °¿° SUSE Knowledge Partner (Linux Counter #276890)
openSUSE Leap 42.1|GNOME 3.16.2|4.1.36-44-default
If you find this post helpful and are logged into the web interface,
please show your appreciation and click on the star below... Thanks!

mal90
30-Jan-2017, 10:49
You could use the Susemanager API to accomplish that. It should work with traditional Spacewalk Clients and with Salt Clients.

I've created a small Example for you :D



#!/usr/bin/python
import xmlrpclib
from optparse import OptionParser, OptionGroup

MANAGER_URL = "http://manager.example.com/rpc/api"
MANAGER_LOGIN = "username"
MANAGER_PASSWORD = "password"


def main():
if options.server != '0':
sm = susemanager(options.user, options.passw, options.url)
sm.patchStatus(options.server)
else:
print "No Parameters specified! Use --help!"


class susemanager(object):
def __init__(self, user, password, url):
self.client = xmlrpclib.Server(url, verbose=0)
self.key = self.client.auth.login(user, password)

def __del__(self):
self.client.auth.logout(self.key)
self.client=""
self.key=""

#### SM - FUNCTIONS
### getSysId - Function
### - Parameter is Name of the System in Susemanager (STRING)
### - Returns the internal SystemID from Susemanager
### - SystemID is needed for other Functions
def getSysId (self, name):
system = self.client.system.getId(self.key, name)
systemid = system[0]['id']
return systemid

def listSystems(self):
systems = self.client.system.listSystems(self.key)
return systems


### getRelevantPatchesByType - Function
### - Parameter is Name of the System in Susemanager (STRING) and Patch - Type ('Security Advisory', 'Product Enhancement Advisory', 'Bug Fix Advisory')
### - Gets SystemId, Patch List and returns the Elements on the List
def getRelevantPatchesByType(self,name, type):
systemid = self.getSysId (name)
errata = self.client.system.getRelevantErrataByType(self.ke y, systemid, type)
return errata

### patchStatus - Function
### - Parameter is Name of the System in Susemanager (STRING)
### - Prints Current Patchstatus for the specified System as Output
def patchStatus (self, name):
security = self.getRelevantPatchesByType(name, 'Security Advisory')
crit = 0
crit_list = []
mod = 0
mod_list = []
imp = 0
imp_list = []
low = 0
low_list = []

for patch in security: ### Loop over the Result
if patch['advisory_synopsis'].find('critical') > -1:
crit += 1
crit_list.append(patch)
elif patch['advisory_synopsis'].find('important') > -1:
imp += 1
imp_list.append(patch)
elif patch['advisory_synopsis'].find('moderate') > -1:
mod += 1
mod_list.append(patch)
elif patch['advisory_synopsis'].find('low') > -1:
low += 1
low_list.append(patch)

enhancements = self.getRelevantPatchesByType(name, 'Product Enhancement Advisory')
bugfix = self.getRelevantPatchesByType(name, 'Bug Fix Advisory')

print "################################################## ##########################"
print "### System Summary - %s " % (name)
print "################################################## ##########################"
print "### Critical: %s Important: %s Moderate: %s Low: %s " % (crit, imp, mod, low)
print "### Bugfix: %s Enhancement: %s " % (len(bugfix), len(enhancements))
print "################################################## ##########################"
print ""
print "Critical Patches:"
print "################################################## ##########################"
for critcal in crit_list:
print critcal['advisory_name']+' - '+critcal['advisory_synopsis']
print ""
print "Important Patches:"
print "################################################## ##########################"
for important in imp_list:
print important['advisory_name']+' - '+important['advisory_synopsis']
print ""

print "Moderate Patches:"
print "################################################## ##########################"
for moderate in mod_list:
print moderate['advisory_name']+' - '+moderate['advisory_synopsis']
print ""
print "Low Patches:"
print "################################################## ##########################"
for lows in low_list:
print lows['advisory_name']+' - '+lows['advisory_synopsis']
print ""
print "Bugfix Patches:"
print "################################################## ##########################"
for sbugfix in bugfix:
print sbugfix['advisory_name']+' - '+sbugfix['advisory_synopsis']
print ""
print "Enhancement Patches:"
print "################################################## ##########################"
for enh in mod_list:
print enh['advisory_name']+' - '+enh['advisory_synopsis']


parser = OptionParser()
usage = "usage: %prog [options]"
parser.add_option("--server", dest="server", default='0',
help="Patchstatus for single Server", metavar="SERVER")
parser.add_option("--url", dest="url", default=MANAGER_URL,
help="Susemanager API URL", metavar="URL")
parser.add_option("--user", dest="user", default=MANAGER_LOGIN,
help="Susemanager API User", metavar="USER")
parser.add_option("--pass", dest="passw", default=MANAGER_PASSWORD,
help="Susemanager API Password", metavar="PASS")
(options, args) = parser.parse_args()
#### Default Call to main() Function
if __name__ == "__main__":
main()



Example:


USAGE: <scriptname>.py --server=<name>
XXXXXX:/tmp # ./patchStatus.py --server=XXXXXXXXXXX
################################################## ##########################
### System Summary - XXXXXXXXXXXXX
################################################## ##########################
### Critical: 0 Important: 0 Moderate: 1 Low: 0
### Bugfix: 2 Enhancement: 0
################################################## ##########################

Critical Patches:
################################################## ##########################

Important Patches:
################################################## ##########################

Moderate Patches:
################################################## ##########################
SUSE-12-SP1-2017-150 - moderate: Security update for pcsc-lite

Low Patches:
################################################## ##########################

Bugfix Patches:
################################################## ##########################
SUSE-12-SP1-2017-156 - Recommended update for yast2-ruby-bindings
SUSE-12-SP1-2017-151 - Recommended update for kernel-firmware

Enhancement Patches:
################################################## ##########################
SUSE-12-SP1-2017-150 - moderate: Security update for pcsc-lite