aboutsummaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorahothan <ahothan@cisco.com>2017-07-28 17:08:46 -0700
committerahothan <ahothan@cisco.com>2017-07-31 12:34:00 -0700
commit04a7de082bd221eae3c7004f4e0b99dfa4f8be91 (patch)
treec9fb7beaedc80479772ba24c3b47c85d49c22f76 /client
parentb8f02ed4e72399840a93aceb02b8c53831bbe68a (diff)
Initial code drop from Cisco1.0.0
Change-Id: Ie2993886dc8e95c5f73ccdb871add8b96ffcc849 Signed-off-by: ahothan <ahothan@cisco.com>
Diffstat (limited to 'client')
-rw-r--r--client/__init__.py0
-rw-r--r--client/client.py150
-rw-r--r--client/nfvbench_client.py88
-rw-r--r--client/requirements.txt7
4 files changed, 245 insertions, 0 deletions
diff --git a/client/__init__.py b/client/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/client/__init__.py
diff --git a/client/client.py b/client/client.py
new file mode 100644
index 0000000..5cbc733
--- /dev/null
+++ b/client/client.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python
+# Copyright 2017 Cisco Systems, Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+import requests
+import time
+
+from socketIO_client import SocketIO
+
+
+class TimeOutException(Exception):
+ pass
+
+
+class NfvbenchException(Exception):
+ pass
+
+
+class NfvbenchClient(object):
+ """Python client class to control a nfvbench server
+
+ The nfvbench server must run in background using the --server option.
+ Since HTML pages are not required, the path to pass to --server can be
+ any directory on the host.
+ """
+ def __init__(self, nfvbench_url, use_socketio):
+ """Client class to send requests to the nfvbench server
+
+ Args:
+ nfvbench_url: the URL of the nfvbench server (e.g. 'http://127.0.0.1:7555')
+ """
+ self.url = nfvbench_url
+ self.use_socketio = use_socketio
+
+ def socketio_send(self, send_event, receive_event, config, timeout):
+ class Exec(object):
+ socketIO = None
+ socketio_result = None
+
+ def close_socketio(result):
+ Exec.socketio_result = result
+ Exec.socketIO.disconnect()
+
+ def on_response(*args):
+ close_socketio(args[0])
+
+ def on_error(*args):
+ raise NfvbenchException(args[0])
+
+ Exec.socketIO = SocketIO(self.url)
+ Exec.socketIO.on(receive_event, on_response)
+ Exec.socketIO.on('error', on_error)
+ Exec.socketIO.emit(send_event, config)
+ Exec.socketIO.wait(seconds=timeout)
+
+ if timeout and not Exec.socketio_result:
+ raise TimeOutException()
+ return Exec.socketio_result
+
+ def http_get(self, command, config):
+ url = self.url + '/' + command
+ res = requests.get(url, json=config)
+ if res.ok:
+ return res.json()
+ res.raise_for_status()
+
+ def http_post(self, command, config):
+ url = self.url + '/' + command
+ res = requests.post(url, json=config)
+ if res.ok:
+ return res.json()
+ res.raise_for_status()
+
+ def echo_config(self, config, timeout=100):
+ """Send an echo event to the nfvbench server with some dummy config and expect the
+ config to be sent back right away.
+
+ Args:
+ config: some dummy configuration - must be a valid dict
+ timeout: how long to wait in seconds or 0 to return immediately,
+ defaults to 100 seconds
+
+ Returns:
+ The config as passed as a dict or None if timeout passed is 0
+
+ Raises:
+ NfvbenchException: the execution of the passed configuration failed,
+ the body of the exception
+ containes the description of the failure.
+ TimeOutException: the request timed out (and might still being executed
+ by the server)
+ """
+ if self.use_socketio:
+ return self.socketio_send('echo', 'echo', config, timeout)
+ return self.http_get('echo', config)
+
+ def run_config(self, config, timeout=300, poll_interval=5):
+ """Request an nfvbench configuration to be executed by the nfvbench server.
+
+ This function will block the caller until the request completes or the request times out.
+ It can return immediately if timeout is set to 0.
+ Note that running a configuration may take a while depending on the amount of work
+ requested - so set the timeout value to an appropriate value.
+
+ Args:
+ config: the nfvbench configuration to execute - must be a valid dict with
+ valid nfvbench attributes
+ timeout: how long to wait in seconds or 0 to return immediately,
+ defaults to 300 seconds
+ poll_interval: seconds between polling (http only) - defaults to every 5 seconds
+
+ Returns:
+ The result of the nfvbench execution
+ or None if timeout passed is 0
+ The function will return as soon as the request is completed or when the
+ timeout occurs (whichever is first).
+
+ Raises:
+ NfvbenchException: the execution of the passed configuration failed, the body of
+ the exception contains the description of the failure.
+ TimeOutException: the request timed out but will still be executed by the server.
+ """
+ if self.use_socketio:
+ return self.socketio_send('start_run', 'run_end', config, timeout)
+ res = self.http_post('start_run', config)
+ if res['status'] != 'PENDING':
+ raise NfvbenchException(res['error_message'])
+
+ # poll until request completes
+ elapsed = 0
+ while True:
+ time.sleep(poll_interval)
+ result = self.http_get('status', config)
+ if result['status'] != 'PENDING':
+ return result
+ elapsed += poll_interval
+ if elapsed >= timeout:
+ raise TimeOutException()
diff --git a/client/nfvbench_client.py b/client/nfvbench_client.py
new file mode 100644
index 0000000..3973b9c
--- /dev/null
+++ b/client/nfvbench_client.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+# Copyright 2017 Cisco Systems, Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+#
+# This is an example of python application controling a nfvbench server
+# using the nfvbench client API.
+# The nfvbench server must run in background using the --server option.
+# Since HTML pages are not required, the path to pass to --server can be any directory on the host.
+#
+import argparse
+import json
+import sys
+
+from client import NfvbenchClient
+
+
+#
+# At the CLI, the user can either:
+# - pass an nfvbench configuration as a string (-c <config>)
+# - pass an nfvbench configuration as a file name containing the
+# configuration (-f <config_file_path>)
+# - or pass a test config (-e <config>) that will be echoed back by the server as is
+#
+def main():
+ parser = argparse.ArgumentParser()
+
+ parser.add_argument('-f', '--file', dest='file',
+ action='store',
+ help='NFVbench config file to execute (json format)',
+ metavar='<config_file_path>')
+ parser.add_argument('-c', '--config', dest='config',
+ action='store',
+ help='NFVbench config to execute (json format)',
+ metavar='<config>')
+ parser.add_argument('-e', '--echo', dest='echo',
+ action='store',
+ help='NFVbench config to echo (json format)',
+ metavar='<config>')
+ parser.add_argument('-t', '--timeout', dest='timeout',
+ default=900,
+ action='store',
+ help='time (seconds) to wait for NFVbench result',
+ metavar='<config>')
+ parser.add_argument('--use-socketio', dest='use_socketio',
+ action='store_true',
+ help='NFVbench config to echo (json format)')
+ parser.add_argument('url', help='nfvbench server url (e.g. http://10.0.0.1:5000)')
+ opts = parser.parse_args()
+
+ if not opts.file and not opts.config and not opts.echo:
+ print('at least one of -f or -c or -e required')
+ sys.exit(-1)
+
+ nfvbench = NfvbenchClient(opts.url, opts.use_socketio)
+ # convert JSON into a dict
+ try:
+ timeout = int(opts.timeout)
+ if opts.file:
+ with open(opts.file) as fd:
+ config = json.loads(fd.read())
+ result = nfvbench.run_config(config, timeout=timeout)
+ elif opts.config:
+ config = json.loads(opts.config)
+ result = nfvbench.run_config(config, timeout=timeout)
+ elif opts.echo:
+ config = json.loads(opts.echo)
+ result = nfvbench.echo_config(config, timeout=timeout)
+ print('Result:', result)
+ except ValueError as ex:
+ print('Input configuration is invalid: ' + str(ex))
+ print()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/client/requirements.txt b/client/requirements.txt
new file mode 100644
index 0000000..80fc402
--- /dev/null
+++ b/client/requirements.txt
@@ -0,0 +1,7 @@
+#
+#
+backports.ssl-match-hostname==3.5.0.1 # via websocket-client
+requests==2.13.0 # via socketio-client
+six==1.10.0 # via socketio-client, websocket-client
+socketIO-client==0.7.2
+websocket-client==0.40.0 # via socketio-client