Tuesday, October 18, 2011

DeployStudio rc129 and new MacBook Airs

The new Air shipped with a custom built 10.7.1, but now 10.7.2 supports these systems.
DeployStudio rc129 (latest stable) isn't capable of doing NetBoot sets from a 10.7.2 system, but the latest nightly is (111010). So how would you do to be able to NetBoot Airs with a DeployStudio NetBoot set and still use the latest stable release on the server?

Simple. Create a NetBoot set with the latest nightly on a 10.7.2 install (preferably in Fusion or Parallels). Take a copy of DeployStudio Admin (rc129) and copy into the NetBoot set and replace the one installed (111010).

Done! Now enable the NetBoot set on the server, and NetBoot the Air. Of course you have to have an 10.7.2 image to apply. Just download Lion from Mac App Store and extract the InstallESD.dmg and run InstaDMG or similar.

Thursday, October 6, 2011

Apple Warranty Info script

Made a quick bash-script to check warranty information for a specific serial number.

Usage: warrantyinfo.sh OR warrantyinfo.sh

If you do not specify a serial number as an argument, the script will use the serial number from the machine that it is run on.

UPDATE: Made it compatible with iPhones. I do not own an iPad and therefor no iPad serial number, so I haven't tested it with iPads.


# Check warranty
# Usage: $0 serialnumber OR just $0


if [ -z "$1" ]; then
 echo "No serial number specified, assuming it's the local machine's serial"
 SN=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F': ' '{print $2}')

if [ -z "$SN" ]; then
 printf "No serial number specified and no serial number automatically found\n"
 printf "Exiting\n\n"
 exit 1

# Get raw info
printf "Getting warranty info from Apple"
curl --silent https://selfsolve.apple.com/warrantyChecker.do?sn=$SN -o "$INFOF"

# Checking if it's an iPhone
IPHONESTAT=$(cat "$INFOF" | awk -F'IS_IPHONE' '{print $2}' | awk -F'"' '{print $3}')

if [ "$IPHONESTAT" = "Y" ]; then
 # This is an iPhone, check iPhone-specific data
 PRODUCT=$(cat "$INFOF" | awk -F'PROD_DESCR' '{print $2}' | awk -F'"' '{print $3}')
 PARTDESCR=$(cat "$INFOF" | awk -F'PART_DESCR' '{print $2}' | awk -F'"' '{print $3}')
 ICCID=$(cat "$INFOF" | awk -F'ICCID' '{print $2}' | awk -F'"' '{print $3}')
 REGISTERED=$(cat "$INFOF" | awk -F'IS_REGISTERED' '{print $2}' | awk -F'"' '{print $3}')
 ACTIVATED=$(cat "$INFOF" | awk -F'ACTIVATION_STATUS' '{print $2}' | awk -F'"' '{print $3}')
 IMEI=$(cat "$INFOF" | awk -F'AP_IMEI_NUM' '{print $2}' | awk -F'"' '{print $3}')
 WARRANTY=$(cat "$INFOF" | awk -F'HW_COVERAGE_DESC' '{print $2}' | awk -F'"' '{print $3}')
 CARRIER=$(cat "$INFOF" | awk -F'CARRIER' '{print $2}' | awk -F'"' '{print $3}')
 PURCHDATE=$(cat "$INFOF" | awk -F'PURCHASE_DATE' '{print $2}' | awk -F'"' '{print $3}')
 # Make it nicer
 if [ "$REGISTERED" = "Y" ]; then
 if [ "$ACTIVATED" = "Y" ]; then
 # Display data
 printf "\033[1mWarranty Information\033[m\n\n"
 printf "Product:\t\033[1m$PRODUCT\033[m\n"
 printf "Description:\t\033[1m$PARTDESCR\033[m\n"
 printf "Serial Number:\t\033[1m$SN\033[m\n"
 printf "ICCID:\t\t\033[1m$ICCID\033[m\n"
 printf "IMEI:\t\t\033[1m$IMEI\033[m\n"
 printf "Purchase Date:\t\033[1m$PURCHDATE\033[m\n"
 printf "Warranty:\t\033[1m$WARRANTY\033[m\n"
 printf "Registered:\t\033[1m$REGISTERED\033[m\n"
 printf "Activated:\t\033[1m$ACTIVATED\033[m\n"
 printf "Carrier:\t\033[1m$CARRIER\033[m\n\n\n"
 # This is a Mac, check Mac data
 # Get product description first as it may contain comma (,) 
 PRODUCT=$(cat "$INFOF" | awk -F'PROD_DESCR' '{print $2}' | awk -F'"' '{print $3}')
 DAYSREM=$(cat "$INFOF" | awk -F'DAYS_REM_IN_COV' '{print $2}' | awk -F'"' '{print $3}')
 PURCHDATE=$(cat "$INFOF" | awk -F'PURCHASE_DATE' '{print $2}' | awk -F'"' '{print $3}')
 ENDDATE=$(cat "$INFOF" | awk -F'COV_END_DATE' '{print $2}' | awk -F'"' '{print $3}')

 # Display data
 printf "\033[1mWarranty Information\033[m\n\n"
 printf "Product:\t\033[1m$PRODUCT\033[m\n"
 printf "Serial Number:\t\033[1m$SN\033[m\n"
 printf "Purchase Date:\t\033[1m$PURCHDATE\033[m\n"
 printf "End Date:\t\033[1m$ENDDATE\033[m\n"
 printf "Days remaining:\t\033[1m$DAYSREM\033[m\n"

 printf "\n\n"

exit 0

Thursday, August 25, 2011

rpcclient is gone from Lion

Just discovered that rpcclient is gone from Lion. I guess this is because Apple got rid of SAMBA. But does anyone know if there are any other tool that does the same thing as rpcclient?

Thursday, July 28, 2011

Lion PreCheck script for DeployStudio

Just wanted to share a small script that checks if the computer is 64 bit. Perfect to add to your workflow in DeployStudio as a first automated step. If the computer is 64 bit, it just continues with the workflow, if not, the workflow will get aborted.


ARCH=$(ioreg -l -p IODeviceTree | grep firmware-abi | awk -F'"' '{print $4}')

if [ "$ARCH" = "EFI64" ]; then
echo "LION PRECHECK - This computer can run Lion"
echo "LION PRECHECK - Architecture: $ARCH"
exit 0
echo "LION PRECHECK - This computer CANNOT run Lion"
echo "LION PRECHECK - Architecture: $ARCH"
exit 1

Windows printing via samba is broken in Lion [updated]

I just discovered that SMB-printing (Windows Printing via SAMBA) is broken in Lion. It seems like there are some kind of authentication bug between CUPS and SMB, but there is a workaround!

1. Add the printer as you always have done (DeviceURI: smb://server.company.com/printerqueue)
2. Connect to an available share on the print server
3. Print and type your credentials when asked

You must repeat step 2 each time you have logged out or restarted your computer.


Another solution seems to involve editing printers.conf.
1. Stop cupsd (sudo launchctl stop org.cups.cupsd)
2. Edit the entry "AuthInfoRequired" so it says "username,password" instead of "negotiate" in /etc/cups/printers.conf
3. Start cupsd (sudo launchctl start org.cups.cupsd)

If you add a printer via the Print settings pane - Advanced, it will set up the printer with "negotiate", but if you set up the printer via the cups web interface (http://localhost:631) it will add the printer with "username,password".

I have an open bugreport on this so Apple knows about it.

Update 2
Above did not work... My hopes are now on Apple and their engineers...

Thursday, July 21, 2011

Hidden accounts disappears in Lion

I have to investigate this further, but it seems like hidden user accounts is deleted/not migrated when you upgrade from 10.6 to 10.7.

I have now filed a bug report to Apple.

I will do some more testing to see if it's because the account is hidden or if it's the hidden home folder.

Update 2
Did a test and created some accounts with different settings...

Works: Hidden user account with home folder in /Users
Works: Standard user account but with home folder hidden (in my case /var/.home/)
Does NOT work: Hidden user account with hidden home folder

Update 3
Apple has now recognized this as a known issue, so hopefully this will get fixed in future installers of Lion.

Tuesday, March 1, 2011

Add-on to copy changed images for the previous script

Integrate this into my previous script or run it standalone (I run it standalone as a separate LaunchDaemon). This compares the auto generated image with an image with the same name in DeployStudios "Masters" directory, and if checksum is different, it renames the image in the Masters directory and copies the new one. Very simple, but wanted to share it more like an idea than a script itself.


IFS=$(echo -en "\n\b")

DSSDIR="/Shared Items/dsrepo/Masters/HFS"
INSTADIR="/Work area/InstaDMG/10.6/OutputFiles"
DATESTAMP=$(date "+%y%m%d")

# Loop that searches $INSTADIR for files ending with .dmg
for i in $(find "$INSTADIR" -type f -print | egrep -i '.dmg$')
echo -e "Working on image: $i" >> "$LOGF"
FILENAME=$(basename $i)
if [ -f "$DSSDIR/$FILENAME" ]
echo -e "Found the image \"$FILENAME\" in \"$DSSDIR\"\nwith the same name as in \"$INSTADIR\"" >> "$LOGF"
echo -e "Checksumming both files and comparing them" >> "$LOGF"
DSSSHA=$(shasum "$DSSDIR/$FILENAME" | awk '{print $1}')
INSTASHA=$(shasum "$i" | awk '{print $1}')
echo -e "The image \"$FILENAME\" is the same in \"$DSSDIR\"\nas in \"$INSTADIR\". Moving on." >> "$LOGF"
echo -e "The image \"$FILENAME\" in \"$DSSDIR\" has a different checksum.\nRenaming \"$FILENAME\" in \"$DSSDIR\"\nand copying \"$FILENAME\" from\n\"$INSTADIR\" to \"$DSSDIR\"" >> "$LOGF"
cp "$i" "$DSSDIR/"
echo -e "Did not find an image called \"$FILENAME\" in \"$DSSDIR\"\nCopying \"$FILENAME\" to \"$DSSDIR\"" >> "$LOGF"
cp "$i" "$DSSDIR/"


exit 0

Can also be downloaded here: http://db.tt/Gr0qYkI

Wednesday, February 23, 2011

Script for automatically update InstaDMG images

Just finished this script, which has room for improvements, but it works as is. This script uses InstaUp2Date. What this script does is that it searches a given folder for catalog files and if the checksum since last run is different, it launches instaUp2Date.

Set up a LaunchDaemon and let it run every night to check if you have done any changes to any instaUp2Date catalog files, and if so, it builds the new image.

Given as is...


# First of all, make sure this is run as root
if [[ "$(/usr/bin/whoami)" != "root" ]]; then
printf '\nMust be run as root!\n\n'
exit 1

cat << EOF ######################################## Put this script in /AddOns/InstaUp2Date
Usage: $0

#if [[ -z $1 ]]
# usage
# exit 1

IFS=$(echo -en "\n\b")

SCRIPTDIR=$(dirname $0)
OUTPUTDIR="$SCRIPTDIR/../../OutputFiles" # Path to default InstaDMG Output path
TIMESTAMP=$(date "+%y%m%d_%H.%M.%S")

if [ ! -d $SHADIR ];
mkdir "$SHADIR"

for i in $(find "$CATALOGDIR" -type f -print | egrep -i '.catalog$')
FILENAME=$(basename "$i" .catalog)
if [ ! -f "$SHADIR/$FILENAME.sha" ];
echo "Old shasum for \"$i\" does not exist. Assuming it's a new catalog file. Running InstaUp2Date for \"$i\""
/usr/bin/python "$SCRIPTDIR/instaUp2Date.py" --process $FILENAME
/usr/bin/shasum "$i" | awk '{print $1}' > "$SHADIR/$FILENAME.sha"
echo "Old shasum for \"$i\" exists"

NEWSHA=$(/usr/bin/shasum "$i" | awk '{print $1}')

if [ $NEWSHA = $OLDSHA ];
echo "No change done to the catalogfile: $i"
echo "Found changes in catalog file, renaming old image and running instaUp2Date for catalog file: $i"
OUTFILENAME=$(cat $i | grep "Output File Name" | awk -F" = " '{print $2}')
for image in $(find "$OUTPUTDIR" -name "$OUTFILENAME*");
mv $image $image-$TIMESTAMP
/usr/bin/python "$SCRIPTDIR/instaUp2Date.py" --process $FILENAME
echo "Checksumming: $i"
/usr/bin/shasum "$i" | awk '{print $1}' > "$SHADIR/$FILENAME.sha"



exit 0

Can also be downloaded here (with logging added): http://db.tt/95GzhdC

Thursday, January 27, 2011

Deploy Photoshop Elements 9 Trial with SCCM

Here is just a quick instruction on how to install Photoshop Elements 9 Trial silent with SCCM. Since it's Adobe, it wasn't as easy as you would hope.


First, deploy Adobe Application Manager 1.5:
"Setup.exe --mode=silent"
Second, deploy Adobe Photoshop Elements 9 and Elements Organizer with a Task Sequence.

msiexec /i "Elements 9 Organizer.msi" TRANSFORMS=1033.mst NOT_STANDALONE=1 /qn /norestart
Why not deploy AAM in the Task Sequence? It did not work (for me anyway...), the logs said it all went fine, but it didn't. So you have to deploy AAM as a regular program separately.

Thursday, January 20, 2011

Fully automated reinstall of computer lab

We have a computer room with 23 iMacs, all is dual boot Mac OS X 10.6/Windows 7 through BootCamp. Here is how I have automated the whole process.

Because there are so many applications in both OS's, we have created two master images which is deployed through DeployStudio (DSS).

DeployStudio does the following:

- Deploys the two master images
- Sets the computer name from the DSS database in both Mac OS and Windows
- Sets Mac OS as default startup disk
- Sets time server in Mac OS
- Joins Mac OS to our Active Directory
- Activates Software Update on first boot
- Activates a script on first boot that sets some energy savings settings
- Activates a script on first boot that sets the windows partition as default startup disk

So when DSS is done, rebooted and run Software Update, joined AD and run the scripts, it boots into a syspreped Windows 7 installation. The sysprep does a lot of things to the Windows installation, like: setting the computername, joining AD (through a powershell script on first automatic login), running winsat and so on...

One thing to think about is when you create the unattend.xml, you have to specify a ComputerName, otherwise, that key is not present in the xml file, and DSS does not set the ComputerName automatically.

And another thing to think about is the joining to AD. The component UnattendedJoin, did not work for us, then I discovered we were not alone. Setting the admin user to login automatically one time and setting a powershell script to run on first login did the trick.

So long fully automated, but you still have to go to every machine and netboot them, select workflow in DSS and trigger it. Here is where bless blesses us! But first we had to create a user and a group for DSS, which we named dsautodeploy and dsautodeployers. Add the group as a runtime group in DSS, create a NetBoot set in DSS with dsautodeploy enabled as autologin. Then edit the workflow in DSS so everything is automated and select a default workflow for the group of computers.
Now, all you have to do to reinstall the computers is to send this command with ARD (as root):

bless --netboot --server "bsdp://" --options "rp=nfs::/private/tftpboot/NetBoot/NetBootSP0:.nbi/DeployStudioRuntime.sparseimage"

And if the computers is booted in Windows 7, you can (as of BootCamp 3.0) run this command with psexec:
psexec \\COMPUTERNAME "C:\Program Files\Boot Camp\BootCamp.exe" -startupDisk

And then run the bless command above. The "BootCamp.exe -startupDisk" command may also be used in sysprep to boot into Mac OS after the windows setup is done when deploying. But we want windows to be the default OS on these machines...

The script I run in the workflow to make Windows the default startup disk is as simple as this:


#Find the Windows disk and it's mountpoint
WINDOWSDISK=$(mount | grep ntfs | awk -F" " '{print $3}')

#Set $WINDOWSDISK as default boot partition
bless --mount "$WINDOWSDISK" --setBoot --legacy --verbose

exit 0

Happy deploying!

PS. Don't you just love DSS? I know I do :)