Skip to content

Commit

Permalink
stats updates
Browse files Browse the repository at this point in the history
  • Loading branch information
waseembaig committed Oct 18, 2024
1 parent 0bc1b10 commit dec9136
Show file tree
Hide file tree
Showing 8 changed files with 491 additions and 91 deletions.
4 changes: 2 additions & 2 deletions snappi_ixload/Test_l47-loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@
http_2.high_perf_with_simulated_user = False #UDP configs can be mapped http.transport = udp_2.name

(http_server,) = http_2.servers.server()
http_server.name = "Http1Server1"
#http_server.name = "Http1Server1"
http_server.rst_timeout = 100
http_server.enable_http2 = False
http_server.port = 80
Expand Down Expand Up @@ -217,7 +217,7 @@
# (delete2,) = delete_b.delete.delete()
# delete2.destination = "Traffic2_Http1Server1:80"
# delete2.page = "./1b.html"

import pdb;pdb.set_trace()


tp = config.trafficprofile.trafficprofile()
Expand Down
32 changes: 15 additions & 17 deletions snappi_ixload/ixloadapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
#import ixrestutils as http_transport
from collections import namedtuple
import sys
#sys.path.append("C:\\Users\\waseebai\\Documents\\GitHub\\snappi\\artifacts\\snappi")

#sys.path.insert(0, "C:\\Users\\waseebai\\Documents\\project\\GitHub\\snappi\\artifacts\\snappi")
#sys.path.insert(0, "c:\\Users\\waseebai\\Documents\\project\\snappi_l47\\snappi\\artifacts\\snappi")

import snappi
import snappi_ixload.ixrestutils as http_transport
from snappi_ixload.interface import interfaces
Expand All @@ -23,7 +23,7 @@
#from protocols import protocols
#from snappi_ixload.chassis import chassis
#from stats import stats

from stats import stats_config

class Api(snappi.Api):
"""
Expand Down Expand Up @@ -65,6 +65,7 @@ def __init__(self,
self.port = port(self)
self.objective_con = objective_config(self)
self.trafficmap = trafficmap_config(self)
self.stats = stats_config(self)
self._log_level = (
logging.INFO
if kwargs.get("loglevel") is None
Expand Down Expand Up @@ -184,22 +185,19 @@ def set_control_state(self, config):
self.logger.info(f"error:{err}")
raise Snappil47Exception(err)
return self._request_detail()

def stats(self, config):
"""Set or update the configuration
"""

def get_metrics(self, req):
try:
if isinstance(config, (type(self._config_type),
str)) is False:
raise TypeError(
'The content must be of type Union[Config, str]')

if isinstance(config, str) is True:
config = self._config_type.deserialize(config)
self._config = config
metric_res = self.metrics_response()
if req.choice == "httpclient":
metric_res=self.stats.get_stats(name="HTTPClient", metric_obj = req, metric_res=metric_res)
if req.choice == "httpserver":
metric_res=self.stats.get_stats(name="HTTPServer", metric_obj = req, metric_res=metric_res)
except Exception as err:
print(err)

self.logger.info(f"error:{err}")
raise Snappil47Exception(err)
return metric_res

def _apply_config(self):
"""
Apply configs
Expand Down
22 changes: 16 additions & 6 deletions snappi_ixload/l47server.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
CONFIG = snappi.Config()
CS = snappi.ControlState()
GM = snappi.MetricsRequest()
MR = snappi.MetricsResponse()
#sys.path.append("C:\\Users\\waseebai\\Documents\\project\\GitHub\\snappi-ixload")
from snappi_ixload import ixloadapi
API = ixloadapi.Api(host="localhost", version="10.00.0.152")
Expand Down Expand Up @@ -88,15 +89,24 @@ def set_control_state():
@app.route('/monitor/metrics', methods=["POST"])
def get_metrics():
GM.deserialize(request.data.decode("utf-8"))

try:

config = API.metrics_request(CS)
return Response(config.serialize(),
api = snappi.api()
metrics_request = api.metrics_request()
metrics_request.deserialize(request.data.decode('utf-8'))
result = API.get_metrics(metrics_request)
return Response(result.serialize(),
mimetype='application/json',
status=200)
except Exception as error:
print(error)
except Exception as err:
error = snappi.Error()
error.code = err._status_code
error.kind = "validation"
error.errors = [err._message]
return Response(
status=400,
response=error.serialize(),
headers={"Content-Type": "application/json"},
)

# main driver function
if __name__ == "__main__":
Expand Down
20 changes: 17 additions & 3 deletions snappi_ixload/ports.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,21 @@ def _create_chassis(self):
for device in self._config.devices:
ethernet = device.ethernets[0]
location = self._get_chasiss(ethernet.connection.port_name, self._config.ports)
self._add_chassis(location)
for ip in ethernet.ipv4_addresses:
self._assign_ports(location, ip.name)
if location :
if not self.is_chassis_connected(location):
self._add_chassis(location)
for ip in ethernet.ipv4_addresses:
self._assign_ports(location, ip.name)
else:
pass

def _get_chasiss(self, port_name, port_config):
'''
'''
for port in port_config:
if port.name == port_name:
return port.location
return False

def _add_chassis(self, location):
'''
Expand All @@ -50,6 +55,15 @@ def _add_chassis(self, location):
response = self._api._request('POST', refresh_connection_url, {})
self._api._perform_generic_operation(refresh_connection_url, {})

def is_chassis_connected(self, location):
chassis_list_url = "%s/ixload/chassisChain/chassisList" % (self._api._ixload)
chassis_name = location.split("/")[0]
chassis_list = self._api._request('GET', chassis_list_url)
for chassis in chassis_list:
if chassis['name'] == chassis_name and chassis['isConnected'] == True:
return True
return False

def _assign_ports(self, location, ip_name):
'''
Expand Down
109 changes: 76 additions & 33 deletions snappi_ixload/stats.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,84 @@
import json
import re
import time
from brisk_ixload.timer import Timer
from timer import Timer
from datetime import datetime, timedelta

class stats(object):
"""Transforms OpenAPI objects into IxNetwork objects
- Lag to /lag
Args
----
- ixnetworkapi (Api): instance of the Api class
class stats_config():
"""
"""

def __init__(self, ixloadapi):
self._api = ixloadapi

def config(self):
"""Transform config.ports into Ixnetwork.Vport
1) delete any vport that is not part of the config
2) create a vport for every config.ports[] that is not present in IxNetwork
3) set config.ports[].location to /vport -location using resourcemanager
4) set /vport/l1Config/... properties using the corrected /vport -type
5) connectPorts to use new l1Config settings and clearownership
"""
self._scenarios_config = self._api.brisk_config

self._api = ixloadapi

with Timer(self._api, "Scenario Configuration"):
self._create_scenarios()

def _create_scenarios(self):
"""Add any scenarios to the api server that do not already exist
def _get_stats_list(self, req, name, metric_res):
self.metric = metric_res
if req.choice == "httpclient":
self.stat_list = req.httpclient.stat_name
all_stats_flag = req.httpclient.all_stats
self.metric_http = self.metric.httpclient_metrics
else:
self.stat_list = req.httpserver.stat_name
all_stats_flag = req.httpserver.all_stats
self.metric_http = self.metric.httpserver_metrics
if all_stats_flag:
stats_url = "%s/ixload/stats/%s/availableStats" % (self._api._ixload, name)
stats_dict = self._api._request('GET', stats_url, option=1)
stats_source_list = [stat['statName'] for stat in stats_dict]
else:
if not self.stat_list:
raise Exception("Please provide stats name list")
stats_source_list = [stat for stat in self.stat_list]
return stats_source_list

def get_stats(self, name, metric_obj, metric_res):
"""
get_stats - collects the stats information for the test
"""
for scenario in self._scenarios_config:
url1, url2 = self._api._get_url(self._api._ixload , scenario.url)
payload = {}
response = self._api._request('POST', url1, payload)
new_url = url1 + response + url2
scenario.url = new_url
self._create_network(scenario, scenario.url)

wait_time = datetime.now()+timedelta(0,300)
state = self._api.get_current_state()
if state.lower() == 'running' or 'Starting Run':
getting_stats = True
stats_source_url = "%s/ixload/stats/%s/values" % (self._api._ixload, name)
stats_source_list = self._get_stats_list(metric_obj, name, metric_res)
collected_timestamps = {}
time_stamp_dict = {}
for stats in stats_source_list:
time_stamp_dict[stats] = {}
time_stamp_dict[stats]['time_stamp'] = {}
time_stamp_dict[stats]['values'] = []
values_dict = self._api._request('GET', stats_source_url, option=1)
while getting_stats:
if values_dict:
for stats in stats_source_list:
new_time_stamps = [int(timestamp) for timestamp in values_dict.keys() if timestamp not in collected_timestamps.get(stats, [])]
new_time_stamps.sort()
stat_list = []
for timestamp in new_time_stamps:
time_stamp_str = str(timestamp)
if stats in values_dict[time_stamp_str].keys():
for caption, value in values_dict[time_stamp_str].items():
if caption == stats:
stat_list.append(str(value))
key = 'timestamp'+str(new_time_stamps.index(timestamp)+1)
time_stamp_dict[stats]['time_stamp'].update({key: (timestamp, str(value))})
time_stamp_dict[stats]['values'] = stat_list
else:
raise Exception("Please enter the valid stats-%s is invalid" % stats)
stats_value = time_stamp_dict
getting_stats = False
else:
if wait_time < datetime.now():
raise Exception("Cannot Get Stats after 300 seconds.Check the test status")
values_dict = self._api._request('GET', stats_source_url, option=1)
else:
raise Exception(not "Cannot Get Stats when ActiveTest State - %s" % state)
# metric_response
for key, value in stats_value.items():
index = list(stats_value.keys()).index(key)
self.metric_http.metric(name=key)
metric_stat = self.metric_http[index].stat_value
metric_stat.stat_value(values=value['values'])
stat_timestamp = metric_stat[0].timestamp
for tmstamp, tmval in value['time_stamp'].items():
stat_timestamp.timestamp(timestamp_id=str(tmval[0]), value=str(tmval[1]))
return self.metric
Loading

0 comments on commit dec9136

Please sign in to comment.