Välkommen till Cristie Nordic Sverige, genom lång erfarenhet och specialisering gör vi ditt data tillgängligt.


Cristie Nordic AB är den del av PEDAB Group sedan 2019 och är etablerade i alla nordiska länderna, Baltikum, DACH, Frankrike och Polen med en omsättning på c:a 2 miljarder kronor.

Cristie Studio är kontor dit vi bjuder in våra kunder för att tillsammans skapa lösningar anpassade efter behovet.

För mer information, besök vår internationella hemsida.

  • LinkedIn - White Circle
  • Twitter - White Circle

© 2018 Cristie Nordic AB

  • Magnus Thunberg

How to work with the new REST-API for Operation Center 7.1.3

After request from our readers, we are republishing John great post regarding REST-API for IBM Operations Center. Enjoy!

First, we need to enable the REST service, we can do this by clicking settings in OC.

The new version of operation center comes with a REST-API, this makes it easier to script queries and actions. We won’t cover the basics of REST-APIs, just fill the big gaps in the IBM documentation. I will use Python3.4 with requests and base64 modules to demonstrate how to do some basic tasks. The modules might need to be installed, for example via pip.

>>> import requests >>> import base64

I will authenticate to OC via the HTTP header, the header is a python dictionary. Why we set the Content-type to text/plain will be seen later. >>> credentials = base64.b64encode(b'username:password').decode('ascii') >>> print(credentials) dXNlcm5hbWU6cGFzc3dvcmQ= >>> header = {"Authorization": "Basic "+credentials, "Content-type": "text/plain", "Accept": "application/json"} >>> print(header) {'Accept': 'application/json', 'Authorization': 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=', 'Content-type': 'text/plain'}

The API support GET, PUT and POST. The limited documentation tells us to consult the https://:11090/oc/api/help for documentation (feel free to try this at home), and sure enough, here are the available endpoints. We see that we have a GET-endpoint called client, can use it to list the clients maybe?


(Note: We have to pass verify=False in the request because of the default untrusted certificate for OC, this will print a warning which I have omitted to make it look nicer)

>>> clients = requests.get('https://tsm1.cristie.se:11090/oc/api/clients', headers=header, verify=False) >>> >>> print(clients.status_code) 200 >>> print(clients.json()) {'list': [{'TYPE': 1, 'GUID': 'd4.b8.f3.a0.12.72.11.e4.b6.', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLATFORM': 'WINNT', 'VERSI ON': 7, 'SERVER': 'TSM1', 'NAME': 'DLNT420', 'VM_TYPE': None}, {'TYPE': 1, 'GUID ': 'd2.d8.e3.b0.77.1a.11.e1.a6.', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLATFORM': 'WINNT', 'VERSION': 7, 'SERVER': 'TSM1', ' NAME': 'TSM1', 'VM_TYPE': None}, {'TYPE': 1, 'GUID': 'd5.01.d1.51.ee.1b.11.e2.97 .ee.e4.1f.13.60.00.b2', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLA TFORM': 'WINNT', 'VERSION': 7, 'SERVER': 'TSM1', 'NAME': 'TSM2', 'VM_TYPE': None }, {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'DLNT420REST', 'VM_TYPE ': None}, {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKE D': 0, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'MOFO', 'VM_TYPE ': None}, {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKE D': 0, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'DANIEL', 'VM_TY PE': None}, {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOC KED': 0, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'DANIELREST', 'VM_TYPE': None}, {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD' , 'LOCKED': 0, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'JOHN-X1 ', 'VM_TYPE': None}, {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDA RD', 'LOCKED': 1, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'JOHN -X2', 'VM_TYPE': None}], 'list_count': 9}

Which datatype is the result?

>>> print(type(clients)) class 'requests.models.Response'>

Can we make that a dictionary maybe? Yes!

>>> clients = clients.json() >>> print(type(clients)) class 'dict'>

The dict has two keys, where list_count is the number of registered clients. We are interested in the values of the list-key.

>>> clients.keys() dict_keys(['list', 'list_count']) >>> >>> for client in clients['list']: ... print(client) ... {'TYPE': 1, 'GUID': 'd4.b8.f3.a0.12.72.11.e4.b6.', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLATFORM': 'WINNT', 'VERSION': 7, 'SERVER': 'TSM1', 'NAME': 'DLNT420', 'VM_TYPE': None} {'TYPE': 1, 'GUID': 'd2.d8.e3.b0.77.1a.11.e1.a6.', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLATFORM': 'WINNT', 'VERSION': 7, 'SERVER': 'TSM1', 'NAME': 'TSM1', 'VM_TYPE': None} {'TYPE': 1, 'GUID': 'd5.01.d1.51.ee.1b.11.e2.97.ee.e4.1f.13.60.00.b2', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLATFORM': 'WINNT', 'VERSION': 7, 'SERVER': 'TSM1', 'NAME': 'TSM2', 'VM_TYPE': None} {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'DLNT420REST', 'VM_TYPE':None} {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'MOFO', 'VM_TYPE': None} {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'DANIEL', 'VM_TYPE': None} {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'DANIELREST', 'VM_TYPE': None} {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 0, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'JOHN-X1', 'VM_TYPE': None} {'TYPE': 1, 'GUID': '?', 'VM_OWNER': ' ', 'DOMAIN': 'STANDARD', 'LOCKED': 1, 'PLATFORM': ' ', 'VERSION': 0, 'SERVER': 'TSM1', 'NAME': 'JOHN-X2', 'VM_TYPE': None}

Sweet, let’s just pick the values for the name and domain keys.



So how about POST? The documentation is still very bad, and it requires some trial and horror to understand it. I will only show working examples to minimize the length of this post. I will link to the documentation below instead of quote it because it keeps changing (for the better), so any quotes might be outdated soon. Let’ do some practical examples with registernode POST-endpoint: (Note how we have to enclose the dictionary in quotes… remember how we had to put Content-type to text/plain in the header?)

>>>Regnode = '''{"name":"newNode", ..."authentication":"LOCAL", ..."password":"supersecret", ..."domain":"STANDARD", ..."contact":"CannotContainWhitespaces", ..."email":"johns@cristie.se", ..."schedule":"", ..."optionset":"", ..."deduplication":"", ..."sslrequired":"", ..."sessioninitiation":"" ...}''' >>> >>> print(type(regnode)) class 'str'>


( What could have been a nice json is now a string…)

>>> r = requests.post('https://tsm1.cristie.se:11090/oc/api/server/TSM1/client', data=regnode, headers=header, verify=False) >>> >>> print(r.status_code) 201

Yay, 201 is good, let’s do a new GET-request to see if the new node is registered?

>>> clients = requests.get('https://tsm1.cristie.se:11090/oc/api/clients', headers=header, verify=False) >>> >>> for client in clients.json()['list']: ... print(client['NAME']) ... DLNT420 TSM1 TSM2 DLNT420REST MOFO DANIEL DANIELREST JOHN-X1 JOHN-X2 NEWNODE

It sure is, and in activity log we can see the following

2015-09-20, 11:30:10 ANR2017I Administrator JOHN issued command: REGISTER NODE newNode ?***? CONTACT=CannotContainWhitespaces DOMAIN=STANDARD EMAILADDRESS=johns@cristie.se AUTHENTICATION=LOCAL (SESSION: 4086) 2015-09-20, 11:30:10 ANR2060I Node NEWNODE registered in policy domain STANDARD. (SESSION: 4086) 2015-09-20, 11:30:10 ANR9961W Node entry NEWNODE has not been added to this server's definition in Active Directory. (SESSION: 4086) 2015-09-20, 11:30:10 ANR2099I Administrative userid NEWNODE defined for OWNER access to node NEWNODE. (SESSION: 4086)


Thank you John Skjonsberg at Cristie tech-team for writing this appreciated post. Looking forward for your next one!