cancel
Showing results for 
Search instead for 
Did you mean: 
James_Preece
F5 Employee
F5 Employee

Problem this snippet solves:

BIG-IQ traditionally expects to be able to reach any BIG-IP devices it is going to license.

This code helps create a license file from the ELA SKU offerings which can be applied on an Unreachable BIG-IP.

How to use this snippet:

SSH into the BIG-IP device and run the following command to gain the MAC address of the management interface

tmsh show sys mac-address | grep -i interface


[root@bigip1:Active:Standalone] config # tmsh show sys mac-address | grep -i interface
ll:50:56:xx:xx:36 net interface         mgmt                              mac-address
xxxxxxxxxxxxxxxxx net interface         1.3                               mac-address
xxxxxxxxxxxxxxxxx net interface         1.1                               mac-address
xxxxxxxxxxxxxxxxx net interface         1.2                               mac-address

 

In the example above the MAC address we need is “ll:50:56:xx:xx:36”

Now SSH into the BIG-IQ

Move into the /shared directory (cd /shared)

Copy over the Create-license.PY python script and run it by typing

python Create-license.py

The script runs and will prompt you for the following information


[root@Preece-bigiq-cm1:Active:Standalone] shared # python Create-license.py
Enter BIG-IQ user ID: admin
Enter BIG-IQ Password:
Enter Management IP address of BIG-IQ: 44.131.176.101
Enter Management IP address of BIG-IP to be licensed: 44.131.176.22
Enter Management MAC address of BIG-IP to be licensed: ll:50:56:xx:kk:36
Enter the name of the License Pool from which to take BIG-IP license: Load-18
Enter the license name to be assigned to the BIG-IP: F5-BIG-MSP-BT-1GIPIF-LIC-DEV                                                                                                                                                                 
Enter hypervisor used, valid options are: aws, azure, gce, hyperv, kvm, vmware,                                                                                                                                                                             xen: vmware
Optional: Enter chargeback tag if required: Department-A
Optional: Enter tenant name if required: Customer-B



Once the details have been filled in the script authenticates to the BIG-IQ and generates the license (30 seconds)

If everything went well, you will be presented with a success message.

The license file is saved as IP-address_bigip.license in the same directory as you run the script

Using SCP copy the new license file from the BIG-IQ to your desktop.

Copy the license file into the /config directory of the BIG-IP device.

Rename the file, copy ip-address.bigip.license bigip.license

Reload the license by typing reloadlic

Observe the BIG-IP device restart its services and show as active.

You can review in the GUI (System—License) and provision modules as needed.

Code :

import getpass # used to hide the users password input
import json
import os
import requests
from time import sleep
"""
This script uses the BIG-IQ API to license an unreachable (dark site) BIG-IP.
The BIG-IQ licensing API needs certain details provided in order to license an appliance, these details can either be provided in a file call lic-data.json or
if that file does not exist you will be prompted to enter them.
The minimum contents of lic-data.json should be:
{
    "licensePoolName": " -- Enter License Pool Name here. License Pool name can be found in BIG-IQ GUI -- ",
    "command": "assign",
    "address": " -- Enter MGMT IP Address of BIG-IP here -- ",
    "assignmentType": "UNREACHABLE",
    "macAddress": " -- Enter MAC address of MGMT IP for the BIG-IP here -- ",
    "hypervisor": " -- Enter hypervisor value here options are; aws, azure, gce, hyperv, kvm, vmware, xen: --",
    "unitOfMeasure": "yearly",
    "skuKeyword1": "-- Enter License Name here. License Name (or Offering name) can be found in the BIG-IQ GUI  -- "
}  

Additional Optional key:value pairs can be added to the JSON file to afix useful tags to the license. The json file with optional key:value pairs looks like:
{
    "licensePoolName": " -- Enter License Pool Name here. License Pool name can be found in BIG-IQ GUI -- ",
    "command": "assign",
    "address": " -- Enter MGMT IP Address of BIG-IP here -- ",
    "assignmentType": "UNREACHABLE",
    "macAddress": " -- Enter MAC address of MGMT IP for the BIG-IP here -- ",
    "hypervisor": " -- Enter hypervisor value here options are; aws, azure, gce, hyperv, kvm, vmware, xen: --",
    "unitOfMeasure": "yearly",
    "skuKeyword1": "-- Enter License Name here. License Name (or Offering name) can be found in the BIG-IQ GUI  -- ",
    "chargebackTag": "OPTIONAL: Remove this line if you are not going to use it",
    "tenant": "OPTIONAL: Remove this line if you are not going to use it"
} 

A completed minimal lic-data.json file will look like this:
{
    "licensePoolName": "byol-pool-utility",
    "command": "assign",
    "address": "10.1.1.10",
    "assignmentType": "UNREACHABLE",
    "macAddress": "06:ce:c2:43:b3:05",
    "hypervisor": "kvm",
    "unitOfMeasure": "yearly",
    "skuKeyword1": "F5-BIG-MSP-BT-P3-3GF-LIC-DEV"
}

lic-data.json must reside in the directory from which you execute this python script.

"""

def bigiqAuth(_bigiqAuthUrl, _bigiqCredentials):
    """
    This function authenticates with BIG-IQ and collects the authentication token provided.
    Theo token will be used for subsequent calls to BIG-IQ
    """
    _errFlag=0
    try:
        _bigiqAuthInfo=_bigiq_session.post(_bigiqAuthUrl, data=json.dumps(_bigiqCredentials), verify=False)
        print(_bigiqAuthUrl)
        _bigiqAuthInfo.raise_for_status()
        print("Response code: %s" %_bigiqAuthInfo.status_code)
    except requests.exceptions.HTTPError as err:
        print(err)
        _errFlag=1
    #end try
    if _errFlag==0:
        _bigiqResponse=_bigiqAuthInfo.json()
        _bigiqToken=_bigiqResponse['token']
        for _token in _bigiqToken:
            if (_token == 'token'):
                _bigiqAuthToken=(_bigiqToken[_token])
            # End if
        # Next
        _authHeaders={
            "X-F5-Auth-Token": "{_authToken}".format(_authToken=_bigiqAuthToken)
            }
    else:
        _authHeaders=0
    #end if
    print("** Completed Authentication ***")
    return(_authHeaders);
#End Def

def extractLicense(_rawLicenseJSON):
    """
    This function pulls the generated license from BIG-IQ
    """
    for _license in _rawLicenseJSON:
        if (_license=='licenseText'):
            _extractedLicense=_rawLicenseJSON[_license]
        #end if
        if (_license=='status'):
            if (_rawLicenseJSON[_license]=="FINISHED"):
                print("***** License has been assigned *****")
            else:
                _extractedLicense="FAILED"
            #end if
        #end if
     #next
    return(_extractedLicense);
#End def

def licenseData():
    """
    This function read the lic-data.json file. If it does not exist you will be prompted to enter the necessary values.
    """
    if os.path.exists('lic-data.json'):
        with open('./lic-data.json') as licfile:
            _licdata = json.load(licfile)
    else:
        _bigipAddress=raw_input("Enter Management IP address of BIG-IP to be licensed: ")
        _bigipMACaddress=raw_input("Enter Management MAC address of BIG-IP to be licensed: ")
        _licensePoolName=raw_input("Enter the name of the License Pool from which to take BIG-IP license: ")
        _licenseSKU=raw_input("Enter the license name to be assigned to the BIG-IP: ")
        _hypervisorType=raw_input("Enter hypervisor used, valid options are: aws, azure, gce, hyperv, kvm, vmware, xen: ")
        _chargebackTag=raw_input("Optional: Enter chargeback tag if required: ")
        _tenantTag=raw_input("Optional: Enter tenant name if required: ")
        _licdata={
            "licensePoolName": "{_licensePool}".format(_licensePool=_licensePoolName),
            "command": "assign",
            "address": "{_bigipIP}".format(_bigipIP=_bigipAddress),
            "assignmentType": "UNREACHABLE",
            "macAddress": "{_bigipMAC}".format(_bigipMAC=_bigipMACaddress),
            "hypervisor": "{_hypervisor}".format(_hypervisor=_hypervisorType),
            "unitOfMeasure": "yearly",
            "skuKeyword1": "{_license}".format(_license=_licenseSKU),
            "chargebackTag": "{_chargeback}".format(_chargeback=_chargebackTag),
            "tenant": "{_tenant}".format(_tenant=_tenantTag)
        }
    # End if
    return(_licdata);

def urlConstruction(_bigiqUrl, _bigiqIP):
    """
    This function rewrites the selflink URL returned by BIG-IQ to reflect BIG-IQ management IP address rather than localhost
    """
    count=0
    _urlDeConstruct=_bigiqUrl.split("/")
    _urlReConstruct=""
    for _urlElement in _urlDeConstruct:
        #print("%d %s" %(count,_urlElement))
        if (_urlElement=="https:"):
                _urlReConstruct=_urlReConstruct+_urlElement+"//"
        elif (_urlElement=="localhost"):
                _urlReConstruct=_urlReConstruct+_bigiqIP
        else:
               if (_urlElement!=""):
                    _urlReConstruct=_urlReConstruct+"/"+_urlElement
               #end if
        #end if
        count+=1
    #Next
    return(_urlReConstruct);
#End Def

_userID=raw_input("Enter BIG-IQ user ID: ")
_password=getpass.getpass(prompt="Enter BIG-IQ Password: ")
_bigiqAddress=raw_input("Enter Management IP address of BIG-IQ: ")

_credPostBody={
        "username": "{_uname}".format(_uname=_userID),
        "password": "{_pword}".format(_pword=_password),
        "loginProvideriName": "RadiusServer"
}

_deviceToBeLicensed=licenseData()
_bigipAddress=_deviceToBeLicensed['address']
print("BIG-IP Address is:  %s" %_bigipAddress)
_bigiq_session=requests.session()

_bigiq_auth_url="https://{_bigiqIP}/mgmt/shared/authn/login".format(_bigiqIP=_bigiqAddress)
# Authenticates with BIG-IQ
_bigiqAuthHeader=bigiqAuth(_bigiq_auth_url, _credPostBody)
#
if _bigiqAuthHeader==0:
    print("Unable to authenticate with BIG-IQ. Check BIG-IQ reachability and credentials")
else:
    _bigiq_url1="https://{_bigiqIP}/mgmt/cm/device/tasks/licensing/pool/member-management".format(_bigiqIP=_bigiqAddress)
    #
    # --- This section requests the license from BIG-IQ. Posting the criteria as laid out in the _deviceToBeLicensed JSON blob
    #
    _errFlag=0
    try:
        _bigiqLicenseDevice=_bigiq_session.post(_bigiq_url1, headers=_bigiqAuthHeader, data=json.dumps(_deviceToBeLicensed), verify=False)
        _bigiqLicenseDevice.raise_for_status()
        print("Response code: %s" %_bigiqLicenseDevice.status_code)
    except requests.exceptions.HTTPError as err:
        print("Issue received, check rquest and or check connectivity %s" %err)
        _errFlag=1
    #end try
    if _errFlag==0:
        #print(_bigiqLicenseDevice.status_code)
        _bigiqResponse=_bigiqLicenseDevice.json()
        print(_bigiqResponse)
        print(_bigiqResponse['selfLink'])
        _bigiqLicenseStatus_url=_bigiqResponse['selfLink']
        _bigiqLicenseStatus_url=urlConstruction(_bigiqLicenseStatus_url, _bigiqAddress)
        print(_bigiqLicenseStatus_url)
        print("--- Standby for 30 seconds whilst BIG-IQ generates license ---")
        sleep(30)
        _errFlag1=0
        try:
            _licenseStatus=_bigiq_session.get(_bigiqLicenseStatus_url, headers=_bigiqAuthHeader, verify=False)
            _licenseStatus.raise_for_status()
            print("Response code: %s" %_licenseStatus.status_code)
        except requests.exceptions.HTTPError as err:
            print("Issue received, check rquest and or check connectivity %s" %err)
            _errFlag=1
        #end try
        if _errFlag==0:
            print(_licenseStatus.content)
            _licenseStatusDetail=_licenseStatus.json()
            _licenseOutput=extractLicense(_licenseStatusDetail)
            if (_licenseOutput=="FAILED"):
                print("***** License Assignment Failed. Most likely a valid license already exists for device, revoke it before applying a new license *****")
            else:
                _licenseFname=(_bigipAddress+"_bigip.license")
                _licensefile=open(_licenseFname, "w")
                _licensefile.write("%s" %_licenseOutput)
                _licensefile.close()
                print(_licenseOutput)
                print("***** SUCCESS, the license is stored here %s *****" %_licenseFname)
            #end if
        #end if
    #end if
#end if

Tested this on version:

13.0
Version history
Last update:
‎16-Oct-2020 10:43
Updated by:
Contributors