Mobile Device Bulk Update/Import (csv?)

New Contributor


I am needing to update some fields of 200+ iPads. Tedious doing it manually when I am sure there is something I am missing.

How can I:

1) Update custom fields in bulk?

2) Update asset tag in bulk?

2) Set enforce mobile name in bulk?



You would have to write a script to do it but I believe you cannot set the enforce name by API but something like AutoIt would likely work. Setting the name and enforcing the name are contradictory, if the name is enforced you cannot set the name initially. I run a script each day to set ;the device name so it a student changes it, it gets changed back and the student does not know until they check. This reduces frustration and resultant damage. It also gives the kids more of a sense of ownership that is better for all concerned.

There are two ways to set the device name (3, if you include screen scraping), by posting an xml file or separate command, I found the xml had a bug so used the command.

To update extension attributes I post an xml file. If you go to https://your.mdm...:8443/api you can go to /mobiledevices then to "GET" to download an xml the will give you the id numbers and attribute information. There is also a .mobiledeviceextensionattributes command that I have not tried but plan too.

Updating anything this way will update the last inventory date and time so if you use this to find devices not checking in suddenly it wont work anymore. I now have extension attributes I populate (by script) of the last time the update inventory command was not acknowledged by the device.

Hope this helps, If you need more info about how I do it I can post it.


New Contributor

Hi @Graeme,
Would you be willing ot post the script that you use to update the names via the API? Are you able to pull JSS variables like $USERNAME into the script?


Hi mattlee06,
I have been using Python 3.4 and have pasted extracts of the code below. This should serve as good starting point. You can get the user name from the downloaded xml which you can use instead of %username%.

First import the required modules. I have removed the obvious ones from my code not used so this should be close to correct.

import urllib.parse import urllib.request import urllib.response import urllib import sys import codecs import xml.etree.cElementTree as etree from urllib.request import urlopen

Prepare environment to talk to JSS

# global set to not verify ssl certificate. Bad practice but works here. import ssl ssl._create_default_https_context = ssl._create_unverified_context userName = "Your_Username" passWord = "YourPassword" top_level_url = "https://Your_JSS_URL:8443/JSSResource" # create an authorization handler and add to all requests p = urllib.request.HTTPPasswordMgrWithDefaultRealm() p.add_password(None, top_level_url, userName, passWord); auth_handler = urllib.request.HTTPBasicAuthHandler(p) opener = urllib.request.build_opener(auth_handler) opener.addheaders.append(('Accept', 'application/xml')) urllib.request.install_opener(opener)

Python 3 is very fussy about the format text is in. I use the following to help with that

def unicodeToAscii(inStr): #Orginal thanks to try: return inStr.encode('ascii', 'ignore') #return str(inStr) except: pass outStr = "" for i in inStr: try: outStr = outStr str(i) except: if unicodeToAsciiMap.has_key(i): outStr = outStr unicodeToAsciiMap[i] else: try: #print ("unicodeToAscii: add to map:", i, repr(i), "(encoded as )") pass except: print ("unicodeToAscii: unknown code (encoded as )", repr(i)) outStr = outStr + "_" return outStr

Now we can download the device list from JSS, which includes the device id that we need and the username. The follow two routines work together to download the xml and convert the xml to an array containing the values I want.

def getDevices(): #Download from JSS an xml list of devices and basic attributes. response = sendXMLtoJSS(top_level_url + '/mobiledevices') responseBytes = responsetext = responseBytes.decode("utf-8", 'ignore') responsetext = unicodeToAscii(responsetext)#Remove special characters. #print(responsetext) xml = etree.fromstring(responsetext) #text_file = open("Output.xml", "wb") #text_file.write(responsetext) #text_file.close() return xml def getDeviceList(xmlOfDevices): for child in xmlOfDevices: #print(child.tag, child.text) deviceId = "" deviceSerial = "" deviceUsername = "" deviceName = "" deviceSupervised = "" try: temp = len(devices) except: devices = [] for group in child: #print(group.tag, group.text) if group.tag == "id": deviceId = group.text if group.tag == "serial_number": deviceSerial = group.text if group.tag == "username": deviceUsername = group.text if group.tag == "device_name": deviceName = group.text if group.tag == "supervised": deviceSupervised = group.text device = [deviceId, deviceSerial, deviceUsername, deviceName, deviceSupervised] devices.append(device) return devices

Now that we have an array of information about each iPad I can loop through it and generate (amongst other things) device names and only apply those names to supervised devices. The device id is the first field in each item in the array generated by the routine above.

def sendRenameCommandtoJSS(id, New_Name): # Will error out with a 500 error if a rename command is still outstanding. Devicename = urllib.parse.quote(New_Name) command = top_level_url "/mobiledevicecommands/command/DeviceName/" Devicename "/id/" str(id) req = urllib.request.Request(command) req.get_method = lambda: 'POST' #request = urllib.request.Request(resource) try: response = strResponse ='utf-8') logData(strResponse) print(New_Name " has been successfully renamed.") #logData('utf-8')) except urllib.error.HTTPError as e: if e.code == 400: print(New_Name " has an outstanding rename request. Rename failed.") else: print("Rename Error" + str(e), command)

Hope this helps.