Skip to content

Instantly share code, notes, and snippets.

@t-lark
Created July 13, 2020 01:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save t-lark/739aaddb3654056015e24087b00e43c0 to your computer and use it in GitHub Desktop.
Save t-lark/739aaddb3654056015e24087b00e43c0 to your computer and use it in GitHub Desktop.
search and detect OS platform and version for parallels VMs
#!/usr/bin/python
"""
this is a script to detect what VMs are on a sytsem and escrow what OS they are
You can run this daily or in another workflow
It will use Spotlight to find files with the .pvm extension to locate where the files are on the file system
then parse the PvInfo file for Parallels VMs
"""
# import modules
import xml.etree.ElementTree as et
from Foundation import NSMetadataQuery, NSPredicate, NSRunLoop, NSDate
# start functions
def get_vms():
"""use spotlight to find parallels VM files"""
file_list = []
query = NSMetadataQuery.alloc().init()
query.setPredicate_(
NSPredicate.predicateWithFormat_(
"(kMDItemContentType == 'com.parallels.vm.vmpackage')"
)
)
query.setSearchScopes_(["/Applications", "/Users"])
query.startQuery()
start_time = 0
max_time = 20
while query.isGathering() and start_time <= max_time:
start_time += 0.3
NSRunLoop.currentRunLoop().runUntilDate_(
NSDate.dateWithTimeIntervalSinceNow_(0.3)
)
query.stopQuery()
# get the results of the file names, and find their file path via spotlight attribute
for item in query.results():
pathname = item.valueForAttribute_("kMDItemPath")
if pathname:
file_list.append(pathname)
return file_list
def get_vm_os(vm_list):
"""feed this function a list of results from Spotlight to parse what VM is running what OS"""
# blank list to populate data in
os_list = []
# loop through return from spotlight and grab needed info
for vm in vm_list:
path = str(vm + "/VmInfo.pvi")
# load XML file into parser
tree = et.ElementTree(file=path)
root = tree.getroot()
# find the text of the tags we want
for element in root.iter():
if element.tag == "RealOsType" and element.text is not None:
# only want the data up until the first comma
os_type = element.text.split(",")[0]
if element.tag == "RealOsVersion" and element.text is not None:
os_ver = element.text
# combine the two pieces of data into single string for the list
cstring = os_type + " " + os_ver
os_list.append(cstring)
return os_list
def main():
"""main to rule them all"""
# get VM XML files
files = get_vms()
# parse XML files
results = get_vm_os(files)
# loop through and print out multi value EA for jamf inventory
for item in results:
print("<result>%s</result>" % item)
if __name__ == "__main__":
main()
@t-lark
Copy link
Author

t-lark commented Jul 13, 2020

Have to also give credit to the Munki Project for being one of the best examples of Python ObjC code, used Munki code in this

@t-lark
Copy link
Author

t-lark commented Jul 13, 2020

forgot with multi line EAs you need to separate it from the loop, change the main function to this

def main():
    """main to rule them all"""
    # get VM XML files
    files = get_vms()
    # parse XML files
    results = get_vm_os(files)
    # loop through and print out multi value EA for jamf inventory
    print("<result>")
    for item in results:
        print(item)
    print("</result>")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment