CSM API Python Bindings Guide¶
Tables of Contents:¶
About¶
The CSM API Python Bindings library works similar to other C Python binding libraries. CSM APIs can be accessed in Python because they are bound to C via Boost. More technical details can be found here: https://wiki.python.org/moin/boost.python/GettingStarted but understanding all of this is not required to use CSM APIs in Python. This guide provides a central location for users looking to utilize CSM APIs via Python. If you believe this guide to be incomplete, then please make a pull request with your additional content.
User Notes¶
Accessing CSM APIs in Python is very similar to accessing them in C. If you are familiar with the process, then you are already in a good position. If not, then the CSM API team suggest reading up on some CSM API documentation and guides.
Importing¶
Before writing your script and accessing CSM APIs, you must first import the CSM library into your script.
import sys
#add the python library to the path
sys.path.append('/opt/ibm/csm/lib')
import lib_csm_py as csm
import lib_csm_inv_py as inv
First you should say where the library is located. Which is what we did above in the first section.
import sys
#add the python library to the path
sys.path.append('/opt/ibm/csm/lib')
Second, you should import the main CSM library lib_csm_py
. We did this and then nicknamed it csm
for ease of use later in our script.
import lib_csm_py as csm
Then, you should import any appropriate sub libraries for the CSM APIs that you will be using. If you want workload manager APIs such as csm_allocation_query
then import the workload manager library lib_csm_wm_py
. If you want inventory APIs, such as csm_node_attributes_update
, then import the inventory library lib_csm_inv_py
. Look at CSM API documentation for a full list of all CSM API libraries.
For my example, I have imported the inventory library and nicknamed it inv
for ease of use later.
import lib_csm_inv_py as inv
Connection to CSM¶
At this point, a Python script can connect to CSM the same way a user would connect to CSM in the C language. You must connect to CSM by running the CSM init function before calling any CSM APIs. This init function is located in the main CSM library we imported earlier.
In Python, we do this below:
csm.init_lib()
Just like in C, this function takes care of connecting to CSM.
Accessing the CSM API¶
Below I have some code from an example script of setting a node to IN_SERVICE
via csm_node_attributes_update
input = inv.node_attributes_update_input_t()
nodes=["allie","node_01","bobby"]
input.set_node_names(nodes)
input.state = csm.csmi_node_state_t.CSM_NODE_IN_SERVICE
rc,handler,output = inv.node_attributes_update(input)
print rc
if rc == csm.csmi_cmd_err_t.CSMERR_UPDATE_MISMATCH:
print output.failure_count
for i in range(0, output.failure_count):
print output.get_failure_node_names(i)
Let’s break down some important lines here for first time users of the CSM Python library.
input = inv.node_attributes_update_input_t()
Here we are doing a few things. Just like in C, before we call the API we need to set up the input for the API. We do this on this line. Because this is an inventory API, we can find its input struct in the inventory library we imported earlier via inv
, and we create this as input
.
We now fill input
.
When using the CSM Python library arrays must be set
and get
.
nodes=["allie","node_01","bobby"]
input.set_node_names(nodes)
input.state = csm.csmi_node_state_t.CSM_NODE_IN_SERVICE
First we create an array in Python. nodes=["allie","node_01","bobby"]
Then we use the CSM Python library function set_ARRAYNAME(array)
to set the node_names
field of input
. We do not need to set node_names_count
like we do in C. the set_
function will take care of that for you. Finally, we call input.state = csm.csmi_node_state_t.CSM_NODE_IN_SERVICE
to set the state field of input to IN_SERVICE
. This will tell CSM to set these 3 nodes to IN_SERVICE
.
In the next line of code we call the csm API passing in the input we just populated.
rc,handler,output = inv.node_attributes_update(input)
Our CSM library returns 3 values.
- A return code - Here defined as
rc
. This is the same as the return code found in the C version of the API. - A handler - An identifier used in the
csm.api_object_destroy
function. - The API output - Here defined as output. This is the same as the output prarmeter found in the C version of the API. We will use this to access any output from the API. Similar to how you woul duse it in the C version.
If you noticed before I set nodes=["allie","node_01","bobby"]
. allie
and bobby
are not real nodes. So, the API will have some output data for us to check.
print rc
if rc == csm.csmi_cmd_err_t.CSMERR_UPDATE_MISMATCH:
print output.failure_count
for i in range(0, output.failure_count):
print output.get_failure_node_names(i)
The end of our sample script here first prints the return code, then if it matches the CSMERR_UPDATE_MISMATCH
prints additional information. Checking error codes and return codes from an API can be useful. The values are the same as the C APIs. Look at CSM API documentation for a full list of all CSM API return codes. Just like in the C version of APIs, error codes are found in the common API folder, which was included earlier as csm
.
Next we print out all the names of the nodes that could not be updated in the CSM database. To do this, we must access an array.
Arrays in the CSM Python library must be accessed using this get_
function. Following the pattern of get_ARRAYNAME
. The array names and fields of a CSM struct are the same as the C versions. Please look at CSM API documentation for a list of your struct and struct field names.
So in our example here, our struct has an array named failure_node_names
. To access it, we must call get_failure_node_names(i)
. i
here represents the element we want to access. Just like in the C version, output.failure_count
tells us how many elements are in our array.
This example keeps it simple and doesn’t do anything too crazy. We just loop through the array and print all the node names that did not update.
Cleaning Up and Closing Connection to CSM¶
Just like in C, when you are done communicating with CSM you must clean up and close connection. You call the same functions you would in C. api_object_destroy
and term_lib
. This will clean up memory and terminate connection to CSM.
csm.api_object_destroy(handler)
csm.term_lib()
Conclusion¶
This concludes the walkthrough of using the CSM Python library. If you have further question, then you can contact: https://github.com/NickyDaB . If you want more samples to analyze, then explore: CAST/csmi/python_samples
.
FAQ - Frequently Asked Questions¶
How do I access and set arrays in the CSM Python library.¶
When using the CSM Python library arrays must be set
and get
.
Get¶
Example:
if(result.dimms_count > 0):
print(" dimms:")
for j in range (0, result.dimms_count):
dimm = result.get_dimms(j)
print(" - serial_number: " + str(dimm.serial_number))
Here let’s assume that the dimms_count is > 0. Let’s say 3. The code will loop through each dimm, printing its serial number. The important line here is: dimm = result.get_dimms(j)
here we are accessing an array.
Arrays in the CSM Python library must be accessed using this get_
function. Following the pattern of get_ARRAYNAME
. The array names and fields of a CSM struct are the same as the C versions. Please look at CSM API documentation for a list of your struct and struct field names.
So in our example here, our struct has an array named dimms
. To access it, we must call get_dimms(j)
. j
here represents the element we want to access. dimm
represents how we will store this element.
Once stored, dimm
can be accessed like any other struct. print(" - serial_number: " + str(dimm.serial_number))
Set¶
Example:
input = inv.node_attributes_update_input_t()
nodes=["node_01","node_02","node_03"]
input.set_node_names(nodes)
input.state = csm.csmi_node_state_t.CSM_NODE_IN_SERVICE
Here we want to use csm_node_attributes_update
to set a few nodes to IN_SERVICE
. The API’s input takes in a list of nodes. So in Python we will need to set this array of node names. The important line here is: input.set_node_names(nodes)
here we are setting the array of the struct to an array we previously created.
Before we can call set_node_names(nodes)
we need to populate nodes
.
nodes=["node_01","node_02","node_03"]
Once nodes
has been defined, we can call: set_node_names(nodes)
.
Arrays in the CSM Python library must be set using this set_
function. Following the pattern of set_ARRAYNAME
. The set_
function requires a single parameter of a populated array. (Here that is nodes
.) The array names and fields of a CSM struct are the same as the C versions. Please look at CSM API documentation for a list of your struct and struct field names.
So in our example here, our struct has an array named node_names
. To set it, we must call input.set_node_names(nodes)
. nodes
here represents the Python array we already created in the previous line. input
represents the parent struct that contains this array.
Why am I getting an error when I use “set_ARRAY()” with my python list?¶
Common errors:
TypeError: No registered converter was able to produce a C++ rvalue of type std::string from this Python object of type unicode
Traceback (most recent call last):
File "node_attributes_query_with_xcat.py", line 95, in <module>
input.set_node_names(nodes_j)
Boost.Python.ArgumentError: Python argument types in
node_attributes_query_input_t.set_node_names(node_attributes_query_input_t, dict)
did not match C++ signature:
set_node_names(csm_node_attributes_query_input_t {lvalue}, boost::python::list {lvalue} e)
When using the set_
function to set a string
array for CSM. The python list should be encoded via utf8
. A list encoded via unicode
can not be properly set.
Example:
nodes_j1 = [x.encode('utf8') for x in nodes_j]