Model Numbers Incorrect

seamus
New Contributor

Hey All, I'm having some issues with model numbers appearing incorrectly (i.e., an early 2014 Macbook Air appears as a Late 2013 Macbook Air in our inventory). On Apple's How to identify your MacBook Air page (http://support.apple.com/kb/HT3255), they have the same Model Identifier, Model Number, and Configuration, but the Model is different.

I'm curious as to how the model information is gathered by Casper, if this is a bug or expected behavior, or if I should be tracking models using a different method (such as model identifier or number, rather than the model name [admittedly, Apple's model identification scheme is a bit confusing to me]).

Thanks to all in advance for helping me with this question!

14 REPLIES 14

mm2270
Legendary Contributor III

Casper, to my knowledge, uses a table in the JSS to translate the model # reported by the system into the Human Readable name you see in the JSS. Because Apple is re-using model identifiers (which makes me smh at them) as you guessed, that's why they are showing up wrong. We see this too, and I'm sure so does anyone else with those models.

Usually when models show up wrong, they just show up with the regular model identifier, which gets corrected in a future update to the JSS. but in this case, I'm not really sure how JAMF plans to address it.

In the meantime, here's an EA I put together that gets the actual model name from Apple's site. It uses the same mechanism that System Information.app uses to get the model name. You could try using this for the time being.

#!/bin/sh

Last4Ser=$(ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformSerialNumber/{print $4}' | tail -c 5)
Last3Ser=$(ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformSerialNumber/{print $4}' | tail -c 4)

FullModelName=$(curl -s -o - "http://support-sp.apple.com/sp/product?cc=${Last4Ser}&lang=en_US"  xpath //root/configCode[1] 2>&1 | awk -F'<configCode>|</configCode>' '{print $2}' | sed '/^$/d')

if [[ "$FullModelName" == "" ]]; then
    FullModelName=$(curl -s -o - "http://support-sp.apple.com/sp/product?cc=${Last3Ser}&lang=en_US"  xpath //root/configCode[1] 2>&1 | awk -F'<configCode>|</configCode>' '{print $2}' | sed '/^$/d')
fi

echo "<result>$FullModelName</result>"

htse
Contributor III

@mm2270 that's a great solution! querying against last three-four digits of the serial number is much more accurate.

TomDay
Release Candidate Programs Tester

Definitely annoying piece that we discovered over the summer after we got 312 new early 2014 Airs. I was hoping this would be corrected in 9.5, sounds like that's not the case (currently running 9.32)?

sean
Valued Contributor

Does this help?

#!/bin/bash

# Author: Sean Holden
# Copyright Future Publishing. All rights reserved.

# Requires 10.8+

# ################################################## # 
#                  MY VARIABLES HERE
# ################################################## #

plistFile="/System/Library/PrivateFrameworks/ServerInformation.framework/Resources/English.lproj/SIMachineAttributes.plist"

# ################################################## # 
#                  SCRIPT STARTS HERE         
# ################################################## # 

sysModel=`sysctl -n hw.model`

FullModelName=`/usr/libexec/PlistBuddy -c "Print :${sysModel}:_LOCALIZABLE_:marketingModel" "$plistFile" 2> /dev/null`

if [ -z "$FullModelName" ]
then
        echo "<result>UNKNOWN</result>"
else
        echo "<result>$FullModelName</result>"
fi      

exit 0

sean
Valued Contributor

Answered my own question. Had a look at the file on a 10.9.5 Mac and there's no such machine in the file!

mm2270
Legendary Contributor III

Indeed. Was going to post before but my Mid 2014 MacBook Pro Retina gets reported as a Late 2013 Retina model with that script! Seems the plist doesn't stay current so it's not a reliable resource unfortunately.

On the other hand, the script I posted that queries Apple's site returns the correct model information.

sean
Valued Contributor

I imagine that it isn't so much that they don't update the file, but seeing as they have the same Model Identifier, they couldn't write two values against one key. Shame as it's potentially much quicker then scraping websites.

Unfortunately, the website isn't necessarily any better. For example, I'm seeing a reply to a 2013 MacBookAir6,2 coming back as:

<result>MacBook Air</result>

Also, there is no control over the external site. If it were down, then you'd have an empty value in Casper. For that reason, and to reduce overhead, may I suggest writing the result (if it isn't blank) to a file and then read that back. With the following, you will only run the various commands if you don't already have a saved value. Something like this will not only reduce overhead from your EAs, but maintain a result at the same time.

#!/bin/bash

# Replace [your.domain.filename] appropriately
fileName="[yourdomain.filename]"

FullModelName=`defaults read /Library/Preferences/"$fileName" MacModel 2>/dev/null`

if [[ "$FullModelName" == "" ]]
then
        function GetFullModelName
        {
                FullModelName=$(curl -s -o - "http://support-sp.apple.com/sp/product?cc=${1}&lang=en_US"  
                xpath //root/configCode[1] 2>&1 | awk -F'<configCode>|</configCode>' '{print $2}' | sed '/^$/d')
        }

        Last4Ser=$(ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformSerialNumber/{print $4}' | tail -c 5)

        GetFullModelName $Last4Ser

        if [[ "$FullModelName" == "" ]]
        then
                Last3Ser=${Last4Ser:1:3}
                GetFullModelName $Last3Ser
        fi

        /usr/libexec/PlistBuddy -c "Add :MacModel string $FullModelName" /Library/Preferences/${fileName}.plist &> /dev/null
fi

echo "<result>$FullModelName</result>"

exit 0

mm2270
Legendary Contributor III

@sean,

Yeah, I think I had mentioned something similar on some other thread where this was discussed. I agree relying on an external site for every recon isn't a super great idea, so dropping the results into a local file to be read back later was also something I had thought of doing. Its not like the Mac's model name will actually change through its life. It would only present an issue if a hard drive was swapped from one Mac to another and they were not the same model, but that's a mostly unlikely scenario, and would cause other issues with Casper anyway.

were_wulff
Valued Contributor II

@mm2270

It may have been the discussion in this Feature Request.

A couple of the EAs were mentioned there.

I'll also re-paste the local xml that can be edited to reflect changes as well:

Just to add to @mm2270 's comment, we can also change what/how the JSS displays there by editing the computerModels.xml file if you'd rather do it that way. Default locations for the computerModels.xml file: As always, we recommend making a backup of your original computerModels.xml file just as a safety precaution. MAC SERVER: usr/local/jss/tomcat/webapps/ROOT/WEB-INF/xml/computerModels.xml LINUX SERVER: /usr/local/JSS/Tomcat/webapps/ROOT/WEB-INF/xml/computerModels.xml WINDOWS SERVER: C:Program FilesJSS omcatwebappsROOTWEB-INFxmlcomputerModels.xml 1) Open up the computerModels.xml using TextWrangler (or similar script/text editor) 2) Scroll down or do a hot-key search for, as an example, "MacBookAir6,1" This is an example if what it might currently look like in the list: <model_name>MacBookAir6,1</model_name> <display_name>MacBookAir6,1</display_name> We will want to edit the display_name so that it looks like this when we are done: <model_name>MacBookAir6,1</model_name> <display_name>MacBook Air (11-inch, Mid 2013)</display_name> The key is that we are leaving the model_name as is, and just changing the display_name. The model_name is what the computer tells the JSS it is at inventory, and the display_name is what the JSS displays for you. We typically do NOT want to change the model_name. Further information can be found at this Apple Link: http://support.apple.com/kb/HT4132?viewlocale=en_US&locale=en_US "Model Identifier", from the Apple list linked above, is what populate both model_name and display_name in the XML. After making changes to the xml file, we'll need to restart Tomcat.

Hope that's some helpful additional information!

Amanda Wulff
JAMF Software Support

seamus
New Contributor

@mm2270 Ah, that's what I figured. If they didn't fragment their OS and have specific setregproptool versions for specific models, it wouldn't be such an issue, but they do so... Basically, I'm configuring EFI passwords, and wanted to create smart groups for different models so I'd have a clear list of which computers to deploy different versions of setregproptool to. Fortunately, I include the model in the name of the computer (E, M, and L followed by the two-digit year), so I can create a smart group based on that easily.

That's a great solution--I'm not savvy enough in scripting to have come up with it, but it should come in handy if I have any questions about a computer model. Thank you so much for providing that here!

mm2270
Legendary Contributor III

@seamus, if all you're looking to do is get the proper setregproptool on the Macs, there are actually better ways to do that.
I have a script somewhere here that gets at least part of the way there by silently mounting the Recovery HD partition (I assume your Macs all have Recovery HD?) and then silently mounting the BaseSystem.dmg inside it to locate the "Firmware Password Utility.app" located in the /Applications/Utilities/ directory. The setregproptool as you probably know comes from inside that app bundle. So basically, once you have the proper Recovery HD BaseSystem mounted, locate and copy the setregproptool into whatever location you want, like /Library/Application Support/JAMF/ or wherever. Then unmount everything as a cleanup phase.
Doing it that way ensures (hopefully) that the proper version of the binary is being used on the machine. The only way that wouldn't work is if something is wrong with your Recovery HD partition when you imaged the Macs.

If that sounds like something you'd like to do instead, post back and I'll dig up my script.

seamus
New Contributor

@mm2270 that sounds like a good way to get the proper setregproptool! I've taken the binary from the Recovery HD for each of our models manually thus far, which is fine as we don't make huge orders and typically have plenty of time to provision.

I was actually looking for a way to determine which hardware version requires which setregproptool version, and if there was a way to create a smart group based on the hardware version so I could deliver the proper setregproptool to the /Library/Application Support/JAMF/bin folder via a script and policy. I unfortunately didn't build it into the image I created for a number of our Macs, and would rather do as much via policy as possible to support out-of-box replacements in remote sites. Shouldn't be too difficult, but the fragmentation is a bit frustrating and I'm still wrapping my head around the many facets of the OS that are affected by it.

Thanks for everyone's answers--they've been insightful and helpful!

mm2270
Legendary Contributor III

Here's the script I was referring to. You could run this via policy right after a Mac gets imaged and goes through its final setup where it starts running any policies scoped to it.
Although there's a check in the script for the setregproptool up front, you could also build an Extension Attribute to make sure the tool is present (simple Yes/No) and make a Smart Group for Macs that don't have it. Then use this script in the policy and when it runs against any Mac in the Smart Group scoped to it. it should copy the setregproptool from the Mac's Recovery HD itself into the location you want. Just customize the paths where necessary if needed.

I'm sure this could be made a little more efficient, but in the usage here we've done, it works, and if it doesn't it exits with status 1, so Casper should report it as an error and you can look further into any that fail.

#!/bin/sh

setregprop="Applications/Utilities/Firmware Password Utility.app/Contents/Resources/setregproptool"

function copySetregprop ()
{

## Get Recovery HD's disk identifier
RecoveryID=$( diskutil list | awk '/Recovery HD/{print $NF}' )

## Create a mount point for Recovery HD in /tmp/
mkdir "/private/tmp/Recovery HD"
if [ "$?" == "0" ]; then
    RecoveryMntPoint="/private/tmp/Recovery HD"
else
    echo "Error: Could not create the necessary mount point in /tmp. Exiting..."
    exit 1
fi

## Mount Recovery HD into /tmp/
diskutil mount readOnly -mountPoint "/private/tmp/Recovery HD" ${RecoveryID}

## If Recovery HD shows up in a listing of the /tmp directory...
if [[ $(ls /private/tmp | grep "Recovery HD") ]]; then
    ## ...get the name of the BaseSystem disk image
    echo "Recovery HD was found in /tmp"
    BaseSystemName=$( ls "/private/tmp/Recovery HD/com.apple.recovery.boot/"  | grep .dmg )
else
    echo "Could not find the mounted Recovery HD partition. Exiting..."
    exit 1
fi

## Silently mount the BaseSystem DMG
BaseSystemPath=$( hdiutil attach "/private/tmp/Recovery HD/com.apple.recovery.boot/${BaseSystemName}" -nobrowse -noautoopen | awk -F'/' '/Volumes/{ print $NF }' )

## Copy the setregproptool into /Library/Application Support/JAMF/

cp "/Volumes/${BaseSystemPath}/${setregprop}" "/Library/Application Support/JAMF/"

if [ -e "/Library/Application Support/JAMF/setregproptool" ]; then
    echo "setregproptool successfully copied. Unmounting the BaseSystem.dmg - ${BaseSystemPath}..."
    hdiutil detach -force "/Volumes/${BaseSystemPath}"
    echo "Unmounting Recovery HD..."
    diskutil umountDisk force "${RecoveryID}"
    echo "Deleting the tmp mount point..."
    rm -Rf "/private/tmp/Recovery HD"
    exit 0
else
    echo "setregproptool copy failed. Unmounting the BaseSystem.dmg - ${BaseSystemPath}..."
    hdiutil detach -force "/Volumes/${BaseSystemPath}"
    echo "Unmounting Recovery HD..."
    diskutil umountDisk force "${RecoveryID}"
    echo "Deleting the tmp mount point..."
    rm -Rf "/private/tmp/Recovery HD"
    exit 1
fi

}

## Check to see if setregproptool is already there
if [ ! -e "/Library/Application Support/JAMF/setregproptool" ]; then
    copySetregprop
else
    echo "setregproptool already exists in JAMF directory."
    exit 0
fi

I assume later you could/would set up another policy with Macs that have the tool in place and set the Firmware password on them.

Hope that helps.

znilsson
Contributor II

Has there been any update on this? Is it going to be fixed in a future Casper release? I'm getting it too now, all these Macbook Pro Mid 2014 models are showing as Late 2013 models in Casper.