mirror of
https://github.com/munki/munki.git
synced 2026-01-26 08:59:17 -06:00
Initial commit for conditional items framework extension
This commit is contained in:
53
code/client/conditions/getnetworkinfo.py
Executable file
53
code/client/conditions/getnetworkinfo.py
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/python
|
||||
'''This is a basic example of a conditional script which outputs 2 key/value pairs:
|
||||
Examples:
|
||||
if_name,en0
|
||||
ip_address,192.168.1.128
|
||||
|
||||
NOTE: Information gathered is ONLY for the primary interface'''
|
||||
|
||||
from SystemConfiguration import * # from pyObjC
|
||||
import socket
|
||||
import collections
|
||||
import os
|
||||
|
||||
NETWORK_INFO = {}
|
||||
|
||||
def getIPAddress(service_uuid):
|
||||
# print service_uuid
|
||||
ds = SCDynamicStoreCreate(None, 'GetIPv4Addresses', None, None)
|
||||
newpattern = SCDynamicStoreKeyCreateNetworkServiceEntity(None,
|
||||
kSCDynamicStoreDomainState,
|
||||
service_uuid,
|
||||
kSCEntNetIPv4)
|
||||
|
||||
newpatterns = CFArrayCreate(None, (newpattern, ), 1, kCFTypeArrayCallBacks)
|
||||
ipaddressDict = SCDynamicStoreCopyMultiple(ds, None, newpatterns)
|
||||
for ipaddress in ipaddressDict.values():
|
||||
ipaddy = ipaddress['Addresses'][0]
|
||||
return ipaddy
|
||||
|
||||
|
||||
def getNetworkInfo():
|
||||
ds = SCDynamicStoreCreate(None, 'GetIPv4Addresses', None, None)
|
||||
|
||||
pattern = SCDynamicStoreKeyCreateNetworkGlobalEntity(None,
|
||||
kSCDynamicStoreDomainState,
|
||||
kSCEntNetIPv4);
|
||||
patterns = CFArrayCreate(None, (pattern, ), 1, kCFTypeArrayCallBacks)
|
||||
valueDict = SCDynamicStoreCopyMultiple(ds, None, patterns)
|
||||
|
||||
ipv4info = collections.namedtuple('ipv4info', 'ifname ip router service')
|
||||
|
||||
|
||||
for serviceDict in valueDict.values():
|
||||
ifname = serviceDict[u'PrimaryInterface']
|
||||
NETWORK_INFO['interface'] = serviceDict[u'PrimaryInterface']
|
||||
NETWORK_INFO['service_uuid'] = serviceDict[u'PrimaryService']
|
||||
NETWORK_INFO['router'] = serviceDict[u'Router']
|
||||
NETWORK_INFO['ip_address'] = getIPAddress(serviceDict[u'PrimaryService'])
|
||||
print "if_name,%s" % ifname
|
||||
print "ip_address,%s" % NETWORK_INFO['ip_address']
|
||||
|
||||
|
||||
getNetworkInfo()
|
||||
@@ -43,7 +43,7 @@ from distutils import version
|
||||
from types import StringType
|
||||
from xml.dom import minidom
|
||||
|
||||
from Foundation import NSDate, NSMetadataQuery, NSPredicate, NSRunLoop
|
||||
from Foundation import NSArray, NSDate, NSMetadataQuery, NSPredicate, NSRunLoop
|
||||
from Foundation import CFPreferencesCopyAppValue
|
||||
from Foundation import CFPreferencesSetValue
|
||||
from Foundation import CFPreferencesAppSynchronize
|
||||
@@ -1941,6 +1941,59 @@ def getMachineFacts():
|
||||
return MACHINE
|
||||
|
||||
|
||||
CONDITIONS = {}
|
||||
def getConditions():
|
||||
"""Fetches key/value pairs from condition scripts
|
||||
which can be placed into /usr/local/munki/conditions"""
|
||||
if not CONDITIONS:
|
||||
# define path to conditions directory which would contain admin created scripts
|
||||
scriptdir = os.path.realpath(os.path.dirname(sys.argv[0]))
|
||||
conditionsdir = os.path.join(scriptdir, "conditions")
|
||||
if os.path.exists(conditionsdir):
|
||||
from munkilib import utils
|
||||
for condition_script in listdir(conditionsdir):
|
||||
# grab path to each condition script
|
||||
condition_script_path = os.path.join(conditionsdir, condition_script)
|
||||
try:
|
||||
# attempt to execute condition script
|
||||
result, stdout, stderr = utils.runExternalScript(condition_script_path)
|
||||
# condition scripts may contain multi-line output,
|
||||
# each representing a key/value pair
|
||||
condition_stdout = stdout.splitlines()
|
||||
for condition in condition_stdout:
|
||||
# format and prepare each line for inclusion into the CONDITIONS dict
|
||||
condition = str(condition)
|
||||
key_value_pair = filter(len,[x.strip() for x in condition.split(',')])
|
||||
key_value_length = len(key_value_pair)
|
||||
if key_value_length == 2:
|
||||
# traditional key/value pairing
|
||||
condition_key = key_value_pair[0]
|
||||
condition_value = key_value_pair[1]
|
||||
elif key_value_length > 2:
|
||||
# 'complex' key/value pairing - value is a list of multiple values
|
||||
# keys with multiple values are cast as an NSArray.
|
||||
# This allows for a slightly different predicate evaluation
|
||||
condition_key = key_value_pair[0]
|
||||
condition_value = key_value_pair[1:]
|
||||
condition_value = NSArray.arrayWithArray_(condition_value)
|
||||
else:
|
||||
# key/value pair is invalid
|
||||
pass
|
||||
try:
|
||||
# Build dict of condition key/value pairs
|
||||
CONDITIONS[condition_key] = condition_value
|
||||
except:
|
||||
display_warning('No valid key/value pairs: %s', condition_script)
|
||||
except utils.ScriptNotFoundError:
|
||||
pass # script is not required, so pass
|
||||
except utils.RunExternalScriptError, e:
|
||||
print >> sys.stderr, str(e)
|
||||
else:
|
||||
# /usr/local/munki/conditions does not exist
|
||||
pass
|
||||
return CONDITIONS
|
||||
|
||||
|
||||
def isAppRunning(appname):
|
||||
"""Tries to determine if the application in appname is currently
|
||||
running"""
|
||||
|
||||
@@ -1630,11 +1630,28 @@ def makePredicateInfoObject():
|
||||
INFO_OBJECT['machine_type'] = 'laptop'
|
||||
else:
|
||||
INFO_OBJECT['machine_type'] = 'desktop'
|
||||
for key in CONDITIONS.keys():
|
||||
INFO_OBJECT[key] = CONDITIONS[key]
|
||||
|
||||
|
||||
def predicateEvaluatesAsTrue(predicate_string):
|
||||
'''Evaluates predicate against our info object'''
|
||||
munkicommon.display_debug1('Evaluating predicate: %s' % predicate_string)
|
||||
|
||||
# Parse condition item key from the predicate string
|
||||
condition_key = predicate_string.split()[0]
|
||||
if not condition_key in INFO_OBJECT:
|
||||
# Stop processing a predicate if it's conditional item key has not been defined
|
||||
munkicommon.display_warning('Condition "%s" is undefined', condition_key)
|
||||
return False
|
||||
|
||||
valueIsArray = False
|
||||
if "array" in str(type(INFO_OBJECT[condition_key])).lower():
|
||||
# Test if the key's value is an array and prepare a new predicate string
|
||||
predicate_string_orig = predicate_string
|
||||
# Manipulate predicate_string in prep for different evaluation
|
||||
predicate_string = predicate_string.replace(condition_key,'SELF')
|
||||
valueIsArray = True
|
||||
try:
|
||||
p = NSPredicate.predicateWithFormat_(predicate_string)
|
||||
except Exception, e:
|
||||
@@ -1642,7 +1659,18 @@ def predicateEvaluatesAsTrue(predicate_string):
|
||||
# can't parse predicate, so return False
|
||||
return False
|
||||
|
||||
result = p.evaluateWithObject_(INFO_OBJECT)
|
||||
if not valueIsArray:
|
||||
# Traditional key/value pair evaluation
|
||||
result = p.evaluateWithObject_(INFO_OBJECT)
|
||||
else:
|
||||
# Complex key/value pair evaluation
|
||||
if INFO_OBJECT[condition_key].filteredArrayUsingPredicate_(p):
|
||||
result = True
|
||||
else:
|
||||
result = False
|
||||
# Set predicate string back to it's original form for easier comprehension
|
||||
predicate_string = predicate_string_orig
|
||||
|
||||
munkicommon.display_debug1(
|
||||
'Predicate %s is %s' % (predicate_string, result))
|
||||
return result
|
||||
@@ -2308,6 +2336,7 @@ def getDownloadCachePath(destinationpathprefix, url):
|
||||
destinationpathprefix, getInstallerItemBasename(url))
|
||||
|
||||
MACHINE = {}
|
||||
CONDITIONS = {}
|
||||
def check(client_id='', localmanifestpath=None):
|
||||
"""Checks for available new or updated managed software, downloading
|
||||
installer items if needed. Returns 1 if there are available updates,
|
||||
@@ -2318,6 +2347,10 @@ def check(client_id='', localmanifestpath=None):
|
||||
MACHINE = munkicommon.getMachineFacts()
|
||||
munkicommon.report['MachineInfo'] = MACHINE
|
||||
|
||||
global CONDITIONS
|
||||
munkicommon.getConditions()
|
||||
CONDITIONS = munkicommon.getConditions()
|
||||
|
||||
ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
|
||||
if munkicommon.munkistatusoutput:
|
||||
munkistatus.activate()
|
||||
|
||||
Reference in New Issue
Block a user