summaryrefslogtreecommitdiffstats
path: root/scripts/automation/trex_control_plane/stl/examples/rpc_proxy_server.py
blob: ad2697d8d36743b1abe23fcab6dab766c2816547 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/usr/bin/python

import argparse
import traceback
import logging
import sys
import os
import json
import socket
from functools import partial
logging.basicConfig(level = logging.FATAL) # keep quiet

import stl_path
from trex_stl_lib.api import *
from trex_stl_lib.trex_stl_hltapi import CTRexHltApi, HLT_OK, HLT_ERR

# ext libs
ext_libs = os.path.join(os.pardir, os.pardir, os.pardir, os.pardir, 'external_libs') # usual package path
if not os.path.exists(ext_libs):
    ext_libs = os.path.join(os.pardir, os.pardir, 'external_libs') # client package path
sys.path.append(os.path.join(ext_libs, 'jsonrpclib-pelix-0.2.5'))
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer
import yaml

# TODO: refactor this to class

native_client = None
hltapi_client = None

def OK(res = True):
    return[True, res]

def ERR(res = 'Unknown error'):
    return [False, res]

def deunicode_json(data):
    return yaml.safe_load(json.dumps(data))


### Server functions ###

def add(a, b): # for sanity checks
    try:
        return OK(a + b)
    except:
        return ERR(traceback.format_exc())

def check_connectivity():
    return OK()

def native_proxy_init(force = False, *args, **kwargs):
    global native_client
    if native_client and not force:
        return ERR('Native Client is already initiated')
    try:
        native_client = STLClient(*args, **kwargs)
        return OK('Native Client initiated')
    except:
        return ERR(traceback.format_exc())

def native_proxy_del():
    global native_client
    native_client = None
    return OK()

def hltapi_proxy_init(force = False, *args, **kwargs):
    global hltapi_client
    if hltapi_client and not force:
        return HLT_ERR('HLTAPI Client is already initiated')
    try:
        hltapi_client = CTRexHltApi(*args, **kwargs)
        return HLT_OK()
    except:
        return HLT_ERR(traceback.format_exc())

def hltapi_proxy_del():
    global hltapi_client
    hltapi_client = None
    return HLT_OK()

# any method not listed above can be called with passing its name here
def native_method(func_name, *args, **kwargs):
    try:
        func = getattr(native_client, func_name)
        return OK(func(*deunicode_json(args), **deunicode_json(kwargs)))
    except:
        return ERR(traceback.format_exc())

# any HLTAPI method can be called with passing its name here
def hltapi_method(func_name, *args, **kwargs):
    try:
        func = getattr(hltapi_client, func_name)
        return func(*deunicode_json(args), **deunicode_json(kwargs))
    except:
        return HLT_ERR(traceback.format_exc())

### /Server functions ###


def run_server(port = 8095):
    native_methods = [
                      'acquire',
                      'connect',
                      'disconnect',
                      'get_stats',
                      'get_warnings',
                      'push_remote',
                      'reset',
                      'wait_on_traffic',
                     ]
    hltapi_methods = [
                      'connect',
                      'cleanup_session',
                      'interface_config',
                      'traffic_config',
                      'traffic_control',
                      'traffic_stats',
                     ]

    try:
        register_socket('trex_stl_rpc_proxy')
        server = SimpleJSONRPCServer(('0.0.0.0', port))
        server.register_function(add)
        server.register_function(check_connectivity)
        server.register_function(native_proxy_init)
        server.register_function(native_proxy_del)
        server.register_function(hltapi_proxy_init)
        server.register_function(hltapi_proxy_del)
        server.register_function(native_method)
        server.register_function(hltapi_method)

        for method in native_methods:
            server.register_function(partial(native_method, method), method)
        for method in hltapi_methods:
            if method in native_methods: # collision in names
                method_hlt_name = 'hlt_%s' % method
            else:
                method_hlt_name = method
            server.register_function(partial(hltapi_method, method), method_hlt_name)
        server.register_function(server.funcs.keys, 'get_methods') # should be last
        print('Started Stateless RPC proxy at port %s' % port)
        server.serve_forever()
    except KeyboardInterrupt:
        print('Done')

# provides unique way to determine running process
def register_socket(tag):
    global foo_socket   # Without this our lock gets garbage collected
    foo_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    try:
        foo_socket.bind('\0%s' % tag)
        print('Got the socket lock for tag %s.' % tag)
    except socket.error:
        print('Error: process with tag %s is already running.' % tag)
        sys.exit(-1)

### Main ###



if __name__ == '__main__':
    parser = argparse.ArgumentParser(description = 'Runs TRex Stateless RPC proxy for usage with any language client.')
    parser.add_argument('-p', '--port', type=int, default = 8095, dest='port', action = 'store',
                        help = 'Select port on which the stl rpc proxy will run.\nDefault is 8095.')
    kwargs = vars(parser.parse_args())
    run_server(**kwargs)