Forum Discussion

Chanan_Berler_3's avatar
Chanan_Berler_3
Icon for Nimbostratus rankNimbostratus
Jan 28, 2017

Create node fails

Hi All,

 

When running i get this error message - can anyone help? {'apiError': 1, 'code': 400, 'errorStack': [], 'message': 'Found invalid JSON body in the request.'}

 

Thanks Chanan

 

login and retrieve token

login_params = { 'f5_big_ip_public_ip': "myweb.com", 'f5_big_ip_pass': "mypass" } f5_token = _big_ip_login(login_params)

 

init request

request_url = "https://{0}/mgmt/tm/ltm/node".format( "myweb.com", ) headers = { 'X-F5-Auth-Token': f5_token, 'content-type': "application/json" } payload = {}

 

payload["name"] = "SSH-Jumpbox" payload["partition"] = "Common" payload["address"] = "any6" payload["connectionLimit"] = 0 payload["description"] = "SSH-Jumpbox" payload["dynamicRatio"] = 1 payload["ephemeral"] = "false" payload["fqdn"] = { 'addressFamily': 'ipv4', 'autopopulate': 'enabled', 'downInterval': 5, 'interval': '3600', 'tmName': 'myjumpboxjqnds.com' } payload["logging"] = "disabled" payload["monitor"] = "default" payload["rateLimit"] = "disabled" payload["ratio"] = 1 payload["session"] = "user-enabled" payload["state"] = "fqdn-up"

 

print(payload)

 

retrieve server pool

try: response = requests.request( "POST", request_url, data=payload, headers=headers, verify=False).json()

 

except requests.HTTPError as error: print("Failed to retrieve server pool list. Error: {0}".format(error)) exit(0)

 

pprint(response)

 

9 Replies

  • What are you trying to accomplish with the any6 as an address? That will likely fail.

     

    BTW, is there a reason you are doing this from scratch instead of using the f5-common-python sdk available on github?

     

  • The problem i have with the python SDK documentation: i am missing the function arguments. I tried to use the it but when trying to call create function the docs says **kywrds Where are the argument list? i did not find.

     

    Checking with F5 sales represenetive - he told me he never used the SDK :( But prefered to use REST directly Chanan

     

  • What i was told to try: create the node/or any F5 object call the GET request to retrieve the object properties and then reverse it as a Post request. Chanan

     

  • Oh did he now...off with his head! 🙂

     

    With the sdk:

     

    >>> fqdn['tmName'] = 'node.test.local'
    >>> node = b.tm.ltm.nodes.node.create(name='node.test.local', address='any6', partition='Common', fqdn=fqdn)
    

    The key for you is to not supply every argument that you see on a GET. Just setting the object name, the address, and the fqdn is sufficient, so if you clean up your code to reflect that it should work just fine. Supplying the autopopulate or addressFamily attributes in the fqdn dictionary will fail on POST.

     

    I contribute to the SDK as I have time, but the larger team working on it strive to make it easier on the end users. My $.02.

     

  • With the f5-common-python sdk:

    import requests
    from f5.bigip import ManagementRoot
    
     Ignore SSL Errors
    requests.packages.urllib3.disable_warnings()
    
     Instantiate the BIG-IP
    b = ManagementRoot('192.168.102.5', 'admin', 'admin', token=True)
    
     Create a node with IP address
    node1 = b.tm.ltm.nodes.node.create(name='node1', address='192.168.102.100', partition='Common')
    
     Create a node with FQDN
    node2 = b.tm.ltm.nodes.node.create(name='node2', address='any6', fqdn={'tmName': 'node2.test.local'}, partition='Common')
    

    Without the sdk:

    import requests, json
    
     Ignore SSL Errors
    requests.packages.urllib3.disable_warnings()
    
    
     Get Token Function
    def get_token(bigip, url, creds):
        payload = {}
        payload['username'] = creds[0]
        payload['password'] = creds[1]
        payload['loginProviderName'] = 'tmos'
    
        token = bigip.post(url, json.dumps(payload)).json()
    
        return token['token']['token']
    
    
     Set up request session
    b = requests.session()
    b.headers.update({'Content-Type': 'application/json'})
    b.auth = ('admin', 'admin')
    b.verify = False
     Call token function to get token
    token = get_token(b, 'https://192.168.102.5/mgmt/shared/authn/login',
                      ('admin', 'admin'))
     Update auth from basic to token
    b.auth = None
    b.headers.update({'X-F5-Auth-Token': token})
    
     Create a node with IP address
    payload = {}
    payload['name'] = 'node3'
    payload['partition'] = 'Common'
    payload['address'] = '192.168.102.101'
    node3 = b.post('https://192.168.102.5/mgmt/tm/ltm/node', data=json.dumps(payload))
    
     Create a node with FQDN
    payload = {}
    fqdn = {'tmName': 'node4.test.local'}
    payload['fqdn'] = fqdn
    payload['name'] = 'node4'
    payload['address'] = 'any6'
    payload['partition'] = 'Common'
    node4 = b.post('https://192.168.102.5/mgmt/tm/ltm/node', data=json.dumps(payload))
    
  • All..

    If you are dumbfounded with the error "", then you are not alone. I just spent the last couple of days yelling at my computer and the F5 API.

    If you are using "Requests: HTTP for Humans" (https://2.python-requests.org/en/master/) module/library within Python to perform http requests to the API, and you are sending JSON objects as part of the data, then they must use the syntax:

    json = { “key” : “value }

    NOT:

    data = { “key” : “value }

    Example:

    Perform a "Config-Sync" with the API, and using "data=postData" you will receive

    {u'errorStack': [], u'message': u'Found invalid JSON body in the request.', u'code': 400, u'apiError': 1}

    Changing that to "json=postData", removes the error as it properly encodes the json data into the request.

    cpURL = "https://"+aHost+"/mgmt/tm/cm"
    headers = { "content-type" : "application/json", 
                "X-F5-Auth-Token" : str(f5AuthToken)}
    postData = {"command": "run",
                "utilCmdArgs": "config-sync to-group "+syncHosts[aHost] }
    apiResponse = requests.post(cpURL, headers=headers, verify=False, json=postData)

    Hope this helps!