Skip to content

Instantly share code, notes, and snippets.

@nmcspadden
Last active April 22, 2016 23:57
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 nmcspadden/32585b218400b4f8c61c87a8fc4365c8 to your computer and use it in GitHub Desktop.
Save nmcspadden/32585b218400b4f8c61c87a8fc4365c8 to your computer and use it in GitHub Desktop.
Postinstall for Tableau Desktop 9.3.0.
#!/usr/bin/python
"""License Tableau."""
import os
import sys
import re
import subprocess
import pwd
import FoundationPlist
def run_subp(command, input=None):
"""
Run a subprocess.
Command must be an array of strings, allows optional input.
Returns results in a dictionary.
"""
# Validate that command is not a string
if isinstance(command, basestring):
# Not an array!
raise TypeError('Command must be an array')
proc = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
(out, err) = proc.communicate(input)
result_dict = {
"stdout": out,
"stderr": err,
"status": proc.returncode,
"success": True if proc.returncode == 0 else False
}
return result_dict
def getconsoleuser():
'''Uses Apple's SystemConfiguration framework to get the current
console user'''
from SystemConfiguration import SCDynamicStoreCopyConsoleUser
cfuser = SCDynamicStoreCopyConsoleUser(None, None, None)
return cfuser[0]
tableau_dir = '/Applications/Tableau9.3/Tableau.app/Contents'
tableau_binary = "%s/MacOS/Tableau" % tableau_dir
cust_binary = "%s/Frameworks/FlexNet/custactutil" % tableau_dir
current_license = 'XXXX-XXXX-XXXX-XXXX-XXXX'
# Add in the registration data
registration = dict()
# Get the system serial number. For simplicity, this is abstracted out.
# This could be easily done by using subprocess to run:
# `system_profiler SPHardwareDataType`
# and searching for 'Serial Number'
serial = get_serial()
username = getconsoleuser()
# For simplicity, these values are hardcoded.
# You will need to have some way of looking up this information
# from your own directory source.
registration['Data.email'] = "email@domain.com"
registration['Data.first_name'] = "Nick"
registration['Data.last_name'] = "McSpadden"
registration['Data.company'] = 'Facebook:%s:%s' % (serial, username)
registration['Data.city'] = "Menlo Park"
registration['Data.country'] = "US"
registration['Data.department'] = "Engineering/Development"
registration['Data.industry'] = "Software & Technology"
registration['Data.phone'] = "650-555-1234"
registration['Data.state'] = "CA"
registration['Data.title'] = "Engineer"
registration['Data.zip'] = "94025"
# For simplicity, assume home directory in /Users
home_dir = os.path.join('/Users', username)
FoundationPlist.writePlist(
registration,
'%s/Library/Preferences/com.tableau.Registration.plist' % home_dir
)
os.chmod(
'%s/Library/Preferences/com.tableau.Registration.plist' % home_dir,
0644
)
os.chown(
'%s/Library/Preferences/com.tableau.Registration.plist' % home_dir,
pwd.getpwnam(username).pw_uid,
-1
)
info_plist = os.path.join(tableau_dir, 'Info.plist')
version = FoundationPlist.readPlist(info_plist)['CFBundleShortVersionString']
# Install the licensing agent
# install_pkg() is a convenience function to call subprocess with
# /usr/sbin/installer
# Not provided in this post.
install_pkg(
"\"%s/Installers/Tableau\ FLEXNet.pkg\"" % tableau_dir, untrusted=True
)
# Execute the binary to get current licenses (if any)
cust_output = run_subp([cust_binary, '-view'])['stdout']
if current_license in cust_output:
print "Already licensed, exiting."
print (
'Tableau-Success',
(
'Machine is already licensed. Cusactutil Stdout:%s (Username: %s, '
'Serial: %s, Version: %s)' % (cust_output, username, serial, version)
)
)
sys.exit(0)
# Activate Tableau and log failures
apply_license_cmd = [tableau_binary, '-activate', current_license]
shell_out = run_subp(apply_license_cmd)
if not shell_out['success']:
print >> sys.stderr, (
'Tableau-Fail',
(
'Applying license failed with error code: %s (Username: %s, Serial: %s, '
'Version: %s)' % (shell_out['status'], username, serial, version)
)
)
else:
# Check for fulfillment id and log results
cusactutil_stdout = run_subp([cust_binary, '-view'])['stdout']
fulfillment_id = re.search(
'Fulfillment ID: (FID[a-z0-9_]*)',
cusactutil_stdout
)
if fulfillment_id:
print (
'Tableau-Success',
(
'License activated and fulfillment id applied. %s (Username: %s, '
'Serial: %s, Version: %s)' % (
fulfillment_id.group(0), username, serial, version
)
)
)
else:
print >> sys.stderr, (
'Tableau-Fail',
(
'License activated but no fulfillment id. Cusactutil Stdout: %s '
'(Username: %s, Serial: %s, Version: %s)' % (
cusactutil_stdout, username, serial, version
)
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment