Wired Intelligent Edge (Campus Switching and Routing)

Reply
Highlighted
Occasional Contributor I

Are concurrent REST API sessions possible on HP-2920

I have a need to run POE bounce on many ports on my HP 2920. I have a Python script to do this which iterates a list of ports and then uses REST API to send the appopriate requests via the CLI endpoint. This works but it is slow. I would like to speed things up by opening multiple concurrent REST API sessions.

Do I need each session to be a different user, or is it OK to use the same user for multiple sessions (and if so, how many sessions will I get)?

I'm finding it very hard to get information about REST API users, but I do know that during my experiments to make this work I've managed to periodically exhaust the available REST  sessions... but I have no idea how to change that number either!


Accepted Solutions
Highlighted
MVP Guru Elite

Re: Are concurrent REST API sessions possible on HP-2920

You need to download REST API JSON and Schema

 

https://h10145.www1.hpe.com/downloads/SoftwareReleases.aspx?ProductNumber=J9836A&lang=&cc=&prodSeriesId=

And after go on folder device-rest-api -> services and common or wired following what you need for PoE it is on wired and open HTML file

 



PowerArubaSW: Powershell Module to use Aruba Switch API for Vlan, VlanPorts, LACP, LLDP... More info

PowerArubaCP: Powershell Module to use ClearPass API (create NAD, Guest...) More info

PowerArubaCX: Powershell Module to use ArubaCX API (get interface/vlan/ports info)

PowerArubaIAP: Powershell Module to use Aruba Instant AP

PowerArubaMC: Powershell Module to use Mobility Controller / Master


ACMP 6.4 / ACMX #107 / ACCP 6.5 / ACSP

View solution in original post


All Replies
Highlighted
MVP Guru Elite

Re: Are concurrent REST API sessions possible on HP-2920

Hi Paul,

 

Do you are using HTTP Keepalive ?

Because i found this week a issue when use HTTP Keepalive and REST API...

It is very slow between each API call... (need to wait 5secs)



PowerArubaSW: Powershell Module to use Aruba Switch API for Vlan, VlanPorts, LACP, LLDP... More info

PowerArubaCP: Powershell Module to use ClearPass API (create NAD, Guest...) More info

PowerArubaCX: Powershell Module to use ArubaCX API (get interface/vlan/ports info)

PowerArubaIAP: Powershell Module to use Aruba Instant AP

PowerArubaMC: Powershell Module to use Mobility Controller / Master


ACMP 6.4 / ACMX #107 / ACCP 6.5 / ACSP
Highlighted
Occasional Contributor I

Re: Are concurrent REST API sessions possible on HP-2920

Yes I am definitely seeing a delay of about that time (5 seconds). It's very odd. Even with just two threads, I am able to see the logins happen almost simultaneously, and they have unique cookies, but the sessions are not executing the poe operation concurrently or anything close to concurrently. I'm quite disappointed in the behavior, although I've found nothing in Aruba documenation that even talks about REST API concurrency. 

Highlighted
MVP Guru Elite

Re: Are concurrent REST API sessions possible on HP-2920

What your code ? because if you disable Keep Alive, it will be very fast (need to recreate a TCP session for each HTTP command)

 



PowerArubaSW: Powershell Module to use Aruba Switch API for Vlan, VlanPorts, LACP, LLDP... More info

PowerArubaCP: Powershell Module to use ClearPass API (create NAD, Guest...) More info

PowerArubaCX: Powershell Module to use ArubaCX API (get interface/vlan/ports info)

PowerArubaIAP: Powershell Module to use Aruba Instant AP

PowerArubaMC: Powershell Module to use Mobility Controller / Master


ACMP 6.4 / ACMX #107 / ACCP 6.5 / ACSP
Highlighted
Occasional Contributor I

Re: Are concurrent REST API sessions possible on HP-2920

I am using python Requests module, and I do see that keep-alive is enabled by default :(https://requests.readthedocs.io/en/master/user/advanced/#keep-alive) so I will disable it and try again. I will update here with the results.

Highlighted
MVP Guru Elite

Re: Are concurrent REST API sessions possible on HP-2920

What code do you are using ?

 

because, yes on python with request KeepAlive is enable... but with this code, i don't reuse the TCP Session.....

 

url_login = "http://@ip/rest/v4/login-sessions"
payload_login = {"userName" : "admin", "password" : "enable"}

get_cookie = requests.post(url_login, data=json.dumps(payload_login), verify=False)


headers = {'cookie' : get_cookie.json()['cookie']}


try:
    url_lldp = "http://@ip/rest/v3/lldp/remote-device"
    lldp = requests.get(url_lldp, headers=headers, verify=False)
    print("Get lldp neighbor (v3) : ")
    for u in lldp.json()['lldp_remote_device_element']:
        pprint.pprint(u)
finally:
    delete_session = requests.delete(url_login, headers=headers, verify=False)
    print(delete_session.status_code)


PowerArubaSW: Powershell Module to use Aruba Switch API for Vlan, VlanPorts, LACP, LLDP... More info

PowerArubaCP: Powershell Module to use ClearPass API (create NAD, Guest...) More info

PowerArubaCX: Powershell Module to use ArubaCX API (get interface/vlan/ports info)

PowerArubaIAP: Powershell Module to use Aruba Instant AP

PowerArubaMC: Powershell Module to use Mobility Controller / Master


ACMP 6.4 / ACMX #107 / ACCP 6.5 / ACSP
Highlighted
Occasional Contributor I

Re: Are concurrent REST API sessions possible on HP-2920

Thanks for graciously sharing your code. I am not seeing concurrent operations. You do a login, save the cookie, use it in a single GET, then you logout. These are sequential operations. How would it behave if you iterated over 

lldp_remote_device_element 

and issued some other GET request concurrently on each of the elements, maybe using

with futures.ThreadPoolExecutor

to handle the concurrent Requests?

 

I will post some of my own code soon. Thx again for sharing you code.

Highlighted
Occasional Contributor I

Re: Are concurrent REST API sessions possible on HP-2920

Here is my code as a work in progress. The output (at the very bottom of this post) suggests that everything is working fine, but in fact only 1 of the 2 poe bounce operations actually does a bounce. I can tell this because the connected devices have power indicator lights, and only one of them goes off.

 

I apologize for the anount of code, this is still a work in progress and not tidy!

 

 

"""aruba_commands_v2.py"""
import argparse from concurrent import futures import contextlib import requests import sys import time import aruba_common_v2 available_projects = aruba_common_v2.cfg.get('cpus', {}) available_switches = aruba_common_v2.cfg.get('switches', {}) def valid_project(project): return True if project in available_projects else False @contextlib.contextmanager def switch_session(switch_name): """Use this context manager to ensure that we logout of the switch session""" session = None try: session = SwitchSession(switch_name) yield session except RuntimeError: raise finally: session and session.end_session() class SwitchSession: """ Encapsulates all operations a switch session can perform. Prefer to use the switch_session context manager as it will call end_session for you. Otherwise make sure to call end_session (essentially a __del__() but we shouldn't rely on Python to run it, as if it fails to, we'll leave sessions active. """ def __init__(self, switch_name): # Modify session for no keep-alive self.s = requests.Session()
# This should remove keep-alive, but I see no difference in behavior, so commenting it out for now
# del self.s.headers['Connection'] self.cookie = aruba_common_v2.login_os(self.s, switch_name) if self.cookie is None: raise RuntimeError('Switch login failed. Unable to get a cookie.') self.ip = aruba_common_v2.cfg['switches'][switch_name]['ip'] self.base_url = 'http://{}/rest/v{}/'.format(self.ip, aruba_common_v2.api_version) self.switch_name = switch_name print(self.cookie) def end_session(self): """Logout of the session.""" aruba_common_v2.logout_os(self.s, self.base_url, self.cookie) def poe_bounce(self, projects, sleep_time=0): """ Bounce power on specified project. :param str projects: projects to bounce :param int sleep_time: time (seconds) to wait before restoring power """ if not isinstance(projects, list): projects = [projects] for project in projects: if valid_project(project): self.poe_disable(project) if sleep_time > 0: print('Waiting for {} seconds before restoring power to project {}.'.format(sleep_time, project)) time.sleep(sleep_time) self.poe_enable(project) else: print('Invalid project {} cannot be bounced.'. format(project)) def poe_disable(self, projects): """ Disable power on specified project. :param str projects: projects to bounce """ if not isinstance(projects, list): projects = [projects] for project in projects: if valid_project(project): port_number = aruba_common_v2.cfg['cpus'][project]['switch_port_{}'.format(self.switch_name[-1:])] print('Performing poe disable for project {} on port {}.'.format(project, port_number)) commands = [ 'configure terminal', 'interface {}'.format(port_number), 'no power-over-ethernet' ] for cmd in commands: aruba_common_v2.execute_cli(self.s, self.base_url, cmd, self.cookie) else: print('Invalid project {} cannot be poe disabled.'. format(project)) def poe_enable(self, projects): """ Enable power on specified port. :param str projects: projects to bounce """ if not isinstance(projects, list): projects = [projects] for project in projects: if valid_project(project): port_number = aruba_common_v2.cfg['cpus'][project]['switch_port_{}'.format(self.switch_name[-1:])] print('Performing poe enable for project {} on port {}.'.format(project, port_number)) commands = [ 'configure terminal', 'interface {}'.format(port_number), 'power-over-ethernet' ] for cmd in commands: aruba_common_v2.execute_cli(self.s, self.base_url, cmd, self.cookie) else: print('Invalid project {} cannot be poe enabled.'. format(project)) def get_port_by_id(self, port_number): """ Get info on specified port :param str port_number: port number :return: JSON response """ port = '/ports/{}'.format(port_number) return aruba_common_v2.execute_api_get(self.base_url, port, self.cookie) def main(): parser = argparse.ArgumentParser(description='Bounce, enable or disable a project.') # All arguments are positional and required parser.add_argument( 'operation', default='bounce', choices=['bounce', 'enable', 'disable'], help='POE operation to perform' ) parser.add_argument( 'projects', default='fca', nargs='+', choices=available_projects, help='Project to operate on (default: %(default)s)' ) parser.add_argument( 'switch', choices=available_switches, help='Switch to operate on' ) parser.add_argument( '-sleep', '--sleep', type=int, default=0, help='For bounce only, the time (seconds) between disabling and enabling the port' ) args = parser.parse_args() if 'all' in args.projects: args.projects = available_projects def switch_operation(project): with switch_session(args.switch) as session: print(session) if 'bounce' in args.operation: session.poe_bounce(project, args.sleep) elif 'enable' in args.operation: session.poe_enable(project) else: session.poe_disable(project) with futures.ThreadPoolExecutor(2) as executor: executor.map(switch_operation, args.projects) sys.exit(0) if __name__ == '__main__': main()

And another file...

""aruba_common_v2.py.
You shouldn't need to import this module directly.
Instead, import aruba_commands and use its context manager function to issue poe commands.
"""
import json
import os
import sys

import requests
import yaml

YAML_CONFIG = 'Bench_Bird_s4_2p0.yaml'
user = ''user
password = 'password'

# Stacked switches should use version 3 or higher
api_version = '3'


try:
    cfg = yaml.load(
        open(
            os.path.join(
                os.path.dirname(__file__),
                YAML_CONFIG),
            'r'
        )
    )

except FileNotFoundError as error:
    print('Bench Bird YAML configuration file is required: {}'.format(error))
    sys.exit(1)


def login_os(s, switch_name):
    """
    Login to ArubaOS REST API
    :param string switch_name: name of the switch
    :return: cookie header for REST API access for current session
    :rtype: string
    :Example:

    >>>login_os('bbsa')
    """
    params = {'userName': user, 'password': password}
    proxies = {'http': None, 'https': None}
    ip = cfg['switches'][switch_name]['ip']
    url_login = 'http://{}/rest/v{}/login-sessions'.format(ip, api_version)
    response = s.post(url_login, verify=False, data=json.dumps(params), proxies=proxies, timeout=3)
    if response.status_code == 201:
        print('Login to switch {} is successful.'.format(switch_name))
        session = response.json()
        r_cookie = session['cookie']
        return r_cookie
    else:
        print('Login to switch {} returned HTTP {}.'.format(switch_name, response.status_code))


def logout_os(s, url, cookie):
    """
    Logout of ArubaOS REST API
    :param str url: base url of switch
    :param str cookie: cookie header for REST API access for current session
    :Example:

    >>>logout_os('http://10.2.8.3/rest/v3/', 'e3k...Tse')
    """
    url_login = url + "login-sessions"
    headers = {'cookie': cookie}
    proxies = {'http': None, 'https': None}
    response = s.delete(url_login, headers=headers, verify=False, proxies=proxies)
    if response.status_code == 204:
        print('Logout of switch is successful.')
    else:
        print('Logout of switch is not successful ({}).'.format(response.status_code))


def execute_cli(s, url, cmd, cookie):
    """
    Send CLI commands supported on ArubaOS switch via REST API.
    :param str url: base url of switch
    :param str cookie: cookie header for REST API access for current session
    :param str cmd: cli command to be executed
    :return JSON response
    :Example:

    >>>execute_cli('http://10.2.8.3/rest/v3/', 'show vlan', 'e3k...Tse')
    """
    url = url + 'cli'
    headers = {'cookie': cookie}
    command = {"cmd": cmd}
    response = s.post(url, verify=False, data=json.dumps(command), headers=headers)
    print(response.json()['status'])
    return response.json()

And finally here is output...

Login to switch bbsb is successful.
sessionId=6o2yHYGCxV7tjyfLkyQVBy8HRlRMqzgJV3quJgIT59grvhc9mGKFTvBUU6Z1tWx
<__main__.SwitchSession object at 0x108e55c18>
Performing poe disable for project mc on port 5.
Login to switch bbsb is successful.
sessionId=fyLQID4bzgrDhcvlFbhrgYrAsLAfH6QCtaWkDJVpzDJdqmGwis0YMxMos3gHo0a
<__main__.SwitchSession object at 0x108e55160>
Performing poe disable for project vns on port 4.
CCS_SUCCESS
CCS_SUCCESS
CCS_SUCCESS
CCS_SUCCESS
CCS_SUCCESS
Performing poe enable for project mc on port 5.
CCS_SUCCESS
Performing poe enable for project vns on port 4.
CCS_SUCCESS
CCS_SUCCESS
CCS_SUCCESS
CCS_SUCCESS
CCS_SUCCESS
CCS_SUCCESS
Logout of switch is successful.
Logout of switch is successful.

Process finished with exit code 0

 

 

Highlighted
MVP Guru Elite

Re: Are concurrent REST API sessions possible on HP-2920

Do you have a example of yaml file ? (for try your code...)

 

Yes, it is only a small example (but if make multiple get, i don't have issue with this code...)

 

and also why don' t use directly the poe API ?



PowerArubaSW: Powershell Module to use Aruba Switch API for Vlan, VlanPorts, LACP, LLDP... More info

PowerArubaCP: Powershell Module to use ClearPass API (create NAD, Guest...) More info

PowerArubaCX: Powershell Module to use ArubaCX API (get interface/vlan/ports info)

PowerArubaIAP: Powershell Module to use Aruba Instant AP

PowerArubaMC: Powershell Module to use Mobility Controller / Master


ACMP 6.4 / ACMX #107 / ACCP 6.5 / ACSP
Highlighted
Occasional Contributor I

Re: Are concurrent REST API sessions possible on HP-2920

 

By tomorrow I will attach a YAML file, and also a requirements.txt so you can use a virtual env. Meantime, would you be kind enough to send me a link to the poe API? I had read that the CLI service was suggested because API had insufficient functionality for poe. I would certainly much prefer to use direct poe API and any example code you have for that would be incredibly welcome! Thanks again for taking your time to assist me and follow-up each day on this issue.

Search Airheads
cancel
Showing results for 
Search instead for 
Did you mean: