import logging
-import threading
-from flask import Flask, request
-from flask_restful import Resource,Api
+from flask_restful import Resource
+from flask import request
import json
-
-
logging.basicConfig(level=logging.INFO)
-
dcs = {}
-class RestApiEndpoint(object):
-
- """
- Simple API endpoint that offers a REST
- interface. This interface will be used by the
- default command line client.
- """
- global dcs
-
- def __init__(self, listenip, port):
- self.ip = listenip
- self.port = port
-
- # setup Flask
- self.app = Flask(__name__)
- self.api = Api(self.app)
-
- # setup endpoints
- self.api.add_resource(ComputeList, "/restapi/compute/<dc_label>")
- self.api.add_resource(ComputeStart, "/restapi/compute/<dc_label>/<compute_name>/start")
- self.api.add_resource(ComputeStop, "/restapi/compute/<dc_label>/<compute_name>/stop")
- self.api.add_resource(ComputeStatus, "/restapi/compute/<dc_label>/<compute_name>")
- self.api.add_resource(DatacenterList, "/restapi/datacenter")
- self.api.add_resource(DatacenterStatus, "/restapi/datacenter/<dc_label>")
-
- logging.debug("Created API endpoint %s(%s:%d)" % (self.__class__.__name__, self.ip, self.port))
-
-
- def connectDatacenter(self, dc):
- dcs[dc.label] = dc
- logging.info("Connected DC(%s) to API endpoint %s(%s:%d)" % (dc.label, self.__class__.__name__, self.ip, self.port))
-
- def start(self):
- thread = threading.Thread(target= self._start_flask, args=())
- thread.daemon = True
- thread.start()
- logging.info("Started API endpoint @ http://%s:%d" % (self.ip, self.port))
-
-
- def _start_flask(self):
- self.app.run(self.ip, self.port, debug=True, use_reloader=False)
-
-
class ComputeStart(Resource):
"""
Start a new compute instance: A docker container (note: zerorpc does not support keyword arguments)
:param image: image name
:param command: command to execute
:param network: list of all interface of the vnf, with their parameters (id=id1,ip=x.x.x.x/x),...
- :return: networks list({"id":"input","ip": "10.0.0.254/8"}, {"id":"output","ip": "11.0.0.254/24"})
+ example networks list({"id":"input","ip": "10.0.0.254/8"}, {"id":"output","ip": "11.0.0.254/24"})
+ :return: docker inspect dict of deployed docker
"""
global dcs
c = dcs.get(dc_label).startCompute(
compute_name, image= image, command= command, network= network)
# return docker inspect dict
- return c. getStatus(), 200
+ return c.getStatus(), 200
except Exception as ex:
logging.exception("API error.")
return ex.message, 500
--- /dev/null
+import logging
+from flask_restful import Resource
+from flask import request
+import json
+
+logging.basicConfig(level=logging.INFO)
+
+net = None
+
+
+
+class MonitorInterfaceAction(Resource):
+ """
+ Monitor the counters of a VNF interface
+ :param vnf_name: name of the VNF to be monitored
+ :param vnf_interface: name of the VNF interface to be monitored
+ :param metric: tx_bytes, rx_bytes, tx_packets, rx_packets
+ :return: message string indicating if the monitor action is succesful or not
+ """
+ global net
+
+ def put(self, vnf_name, vnf_interface, metric):
+ logging.debug("REST CALL: start monitor VNF interface")
+ try:
+ c = net.monitor_agent.setup_metric(vnf_name, vnf_interface, metric)
+ # return monitor message response
+ return str(c), 200
+ except Exception as ex:
+ logging.exception("API error.")
+ return ex.message, 500
+
+ def delete(self, vnf_name, vnf_interface, metric):
+ logging.debug("REST CALL: stop monitor VNF interface")
+ try:
+ c = net.monitor_agent.stop_metric(vnf_name, vnf_interface, metric)
+ # return monitor message response
+ return str(c), 200
+ except Exception as ex:
+ logging.exception("API error.")
+ return ex.message, 500
+
+
+class MonitorFlowAction(Resource):
+ """
+ Monitor the counters of a specific flow
+ :param vnf_name: name of the VNF to be monitored
+ :param vnf_interface: name of the VNF interface to be monitored
+ :param metric: tx_bytes, rx_bytes, tx_packets, rx_packets
+ :param cookie: specific identifier of flows to monitor
+ :return: message string indicating if the monitor action is succesful or not
+ """
+ global net
+
+ def put(self, vnf_name, vnf_interface, metric, cookie):
+ logging.debug("REST CALL: start monitor VNF interface")
+ try:
+ c = net.monitor_agent.setup_flow(vnf_name, vnf_interface, metric, cookie)
+ # return monitor message response
+ return str(c), 200
+ except Exception as ex:
+ logging.exception("API error.")
+ return ex.message, 500
+
+ def delete(self, vnf_name, vnf_interface, metric, cookie):
+ logging.debug("REST CALL: stop monitor VNF interface")
+ try:
+ c = net.monitor_agent.stop_flow(vnf_name, vnf_interface, metric, cookie)
+ # return monitor message response
+ return str(c), 200
+ except Exception as ex:
+ logging.exception("API error.")
+ return ex.message, 500
\ No newline at end of file
--- /dev/null
+import logging
+from flask_restful import Resource
+from flask import request
+import json
+
+logging.basicConfig(level=logging.INFO)
+
+net = None
+
+
+class NetworkAction(Resource):
+ """
+ Add or remove chains between VNFs. These chain links are implemented as flow entries in the networks' SDN switches.
+ :param vnf_src_name: VNF name of the source of the link
+ :param vnf_dst_name: VNF name of the destination of the link
+ :param vnf_src_interface: VNF interface name of the source of the link
+ :param vnf_dst_interface: VNF interface name of the destination of the link
+ :param weight: weight of the link (can be useful for routing calculations)
+ :param match: OpenFlow match format of the flow entry
+ :param bidirectional: boolean value if the link needs to be implemented from src to dst and back
+ :param cookie: cookie value, identifier of the flow entry to be installed.
+ :return: message string indicating if the chain action is succesful or not
+ """
+
+ global net
+
+ def put(self, vnf_src_name, vnf_dst_name):
+ logging.debug("REST CALL: network chain add")
+ command = 'add-flow'
+ return self._NetworkAction(vnf_src_name, vnf_dst_name, command=command)
+
+ def delete(self, vnf_src_name, vnf_dst_name):
+ logging.debug("REST CALL: network chain remove")
+ command = 'del-flows'
+ return self._NetworkAction(vnf_src_name, vnf_dst_name, command=command)
+
+ def _NetworkAction(self, vnf_src_name, vnf_dst_name, command=None):
+ # call DCNetwork method, not really datacenter specific API for now...
+ # no check if vnfs are really connected to this datacenter...
+ try:
+ vnf_src_interface = json.loads(request.json).get("vnf_src_interface")
+ vnf_dst_interface = json.loads(request.json).get("vnf_dst_interface")
+ weight = json.loads(request.json).get("weight")
+ match = json.loads(request.json).get("match")
+ bidirectional = json.loads(request.json).get("bidirectional")
+ cookie = json.loads(request.json).get("cookie")
+ c = net.setChain(
+ vnf_src_name, vnf_dst_name,
+ vnf_src_interface=vnf_src_interface,
+ vnf_dst_interface=vnf_dst_interface,
+ cmd=command,
+ weight=weight,
+ match=match,
+ bidirectional=bidirectional,
+ cookie=cookie)
+ # return setChain response
+ return str(c), 200
+ except Exception as ex:
+ logging.exception("API error.")
+ return ex.message, 500
\ No newline at end of file
--- /dev/null
+import logging
+import threading
+from flask import Flask
+from flask_restful import Api
+
+# need to import total module to set its global variable dcs
+import compute
+from compute import dcs, ComputeList, ComputeStart, ComputeStatus, ComputeStop, DatacenterList, DatacenterStatus
+
+# need to import total module to set its global variable net
+import network
+from network import NetworkAction
+
+import monitor
+from monitor import MonitorInterfaceAction, MonitorFlowAction
+
+logging.basicConfig(level=logging.INFO)
+
+
+
+class RestApiEndpoint(object):
+
+ """
+ Simple API endpoint that offers a REST
+ interface. This interface will be used by the
+ default command line client.
+ """
+
+ def __init__(self, listenip, port):
+ self.ip = listenip
+ self.port = port
+
+ # setup Flask
+ self.app = Flask(__name__)
+ self.api = Api(self.app)
+
+ # setup endpoints
+ self.api.add_resource(ComputeList, "/restapi/compute/<dc_label>")
+ self.api.add_resource(ComputeStart, "/restapi/compute/<dc_label>/<compute_name>/start")
+ self.api.add_resource(ComputeStop, "/restapi/compute/<dc_label>/<compute_name>/stop")
+ self.api.add_resource(ComputeStatus, "/restapi/compute/<dc_label>/<compute_name>")
+ self.api.add_resource(DatacenterList, "/restapi/datacenter")
+ self.api.add_resource(DatacenterStatus, "/restapi/datacenter/<dc_label>")
+
+ self.api.add_resource(NetworkAction, "/restapi/network/<vnf_src_name>/<vnf_dst_name>")
+
+ self.api.add_resource(MonitorInterfaceAction, "/restapi/monitor/<vnf_name>/<vnf_interface>/<metric>")
+ self.api.add_resource(MonitorFlowAction, "/restapi/monitor/<vnf_name>/<vnf_interface>/<metric>/<cookie>")
+
+ logging.debug("Created API endpoint %s(%s:%d)" % (self.__class__.__name__, self.ip, self.port))
+
+
+ def connectDatacenter(self, dc):
+ compute.dcs[dc.label] = dc
+ logging.info("Connected DC(%s) to API endpoint %s(%s:%d)" % (dc.label, self.__class__.__name__, self.ip, self.port))
+
+ def connectDCNetwork(self, DCnetwork):
+
+ network.net = DCnetwork
+ monitor.net = DCnetwork
+
+ logging.info("Connected DCNetwork to API endpoint %s(%s:%d)" % (
+ self.__class__.__name__, self.ip, self.port))
+
+ def start(self):
+ thread = threading.Thread(target= self._start_flask, args=())
+ thread.daemon = True
+ thread.start()
+ logging.info("Started API endpoint @ http://%s:%d" % (self.ip, self.port))
+
+
+ def _start_flask(self):
+ self.app.run(self.ip, self.port, debug=True, use_reloader=False)
\ No newline at end of file
# set this to localhost for now
# this is correct for son-emu started outside of a container or as a container with net=host
+#TODO prometheus sdk DB is started outside of emulator, place these globals in an external SDK config file?
prometheus_ip = '127.0.0.1'
prometheus_port = '9090'
prometheus_REST_api = 'http://{0}:{1}'.format(prometheus_ip, prometheus_port)
'command':args.get("docker_command"),
'network':nw_list}
- responce = put("%s/restapi/compute/%s/%s/start" %
+ response = put("%s/restapi/compute/%s/%s/start" %
(args.get("endpoint"),
args.get("datacenter"),
args.get("name")),
json = json.dumps(req))
- pp.pprint(responce.json())
+ pp.pprint(response.json())
+
def stop(self, args):
- responce = get("%s/restapi/compute/%s/%s/stop" %
+ response = get("%s/restapi/compute/%s/%s/stop" %
(args.get("endpoint"),
args.get("datacenter"),
args.get("name")))
- pp.pprint(responce.json())
+ pp.pprint(response.json())
def list(self,args):
--- /dev/null
+from requests import get, put, delete
+from tabulate import tabulate
+import pprint
+import argparse
+import json
+from emuvim.cli import prometheus
+
+pp = pprint.PrettyPrinter(indent=4)
+
+class RestApiClient():
+
+ def __init__(self):
+ self.cmds = {}
+
+ def execute_command(self, args):
+ if getattr(self, args["command"]) is not None:
+ # call the local method with the same name as the command arg
+ getattr(self, args["command"])(args)
+ else:
+ print("Command not implemented.")
+
+ def setup_metric(self, args):
+ vnf_name = self._parse_vnf_name(args.get("vnf_name"))
+ vnf_interface = self._parse_vnf_interface(args.get("vnf_name"))
+
+ response = put("%s/restapi/monitor/%s/%s/%s" %
+ (args.get("endpoint"),
+ vnf_name,
+ vnf_interface,
+ args.get("metric")))
+ pp.pprint(response.json())
+
+ def stop_metric(self, args):
+ vnf_name = self._parse_vnf_name(args.get("vnf_name"))
+ vnf_interface = self._parse_vnf_interface(args.get("vnf_name"))
+
+ response = delete("%s/restapi/monitor/%s/%s/%s" %
+ (args.get("endpoint"),
+ vnf_name,
+ vnf_interface,
+ args.get("metric")))
+ pp.pprint(response.json())
+
+ def setup_flow(self, args):
+ vnf_name = self._parse_vnf_name(args.get("vnf_name"))
+ vnf_interface = self._parse_vnf_interface(args.get("vnf_name"))
+
+ response = put("%s/restapi/monitor/%s/%s/%s/%s" %
+ (args.get("endpoint"),
+ vnf_name,
+ vnf_interface,
+ args.get("metric"),
+ args.get("cookie")))
+
+ pp.pprint(response.json())
+
+ def stop_flow(self, args):
+ vnf_name = self._parse_vnf_name(args.get("vnf_name"))
+ vnf_interface = self._parse_vnf_interface(args.get("vnf_name"))
+
+ response = delete("%s/restapi/monitor/%s/%s/%s/%s" %
+ (args.get("endpoint"),
+ vnf_name,
+ vnf_interface,
+ args.get("metric"),
+ args.get("cookie")))
+
+ pp.pprint(response.json())
+
+ def _parse_vnf_name(self, vnf_name_str):
+ vnf_name = vnf_name_str.split(':')[0]
+ return vnf_name
+
+ def _parse_vnf_interface(self, vnf_name_str):
+ try:
+ vnf_interface = vnf_name_str.split(':')[1]
+ except:
+ vnf_interface = None
+
+ return vnf_interface
+
+parser = argparse.ArgumentParser(description='son-emu monitor')
+parser.add_argument(
+ "command",
+ choices=['setup_metric', 'stop_metric', 'setup_flow', 'stop_flow','prometheus'],
+ help="setup/stop a metric/flow to be monitored or query Prometheus")
+parser.add_argument(
+ "--vnf_name", "-vnf", dest="vnf_name",
+ help="vnf name:interface to be monitored")
+parser.add_argument(
+ "--metric", "-m", dest="metric",
+ help="tx_bytes, rx_bytes, tx_packets, rx_packets")
+parser.add_argument(
+ "--cookie", "-c", dest="cookie",
+ help="flow cookie to monitor")
+parser.add_argument(
+ "--query", "-q", dest="query",
+ help="prometheus query")
+parser.add_argument(
+ "--datacenter", "-d", dest="datacenter",
+ help="Data center where the vnf is deployed")
+parser.add_argument(
+ "--endpoint", "-e", dest="endpoint",
+ default="http://127.0.0.1:5000",
+ help="UUID of the plugin to be manipulated.")
+
+def main(argv):
+ args = vars(parser.parse_args(argv))
+ c = RestApiClient()
+ c.execute_command(args)
\ No newline at end of file
--- /dev/null
+from requests import get,put, delete
+from tabulate import tabulate
+import pprint
+import argparse
+import json
+
+pp = pprint.PrettyPrinter(indent=4)
+
+class RestApiClient():
+
+ def __init__(self):
+ self.cmds = {}
+
+ def execute_command(self, args):
+ if getattr(self, args["command"]) is not None:
+ # call the local method with the same name as the command arg
+ getattr(self, args["command"])(args)
+ else:
+ print("Command not implemented.")
+
+ def add(self, args):
+ vnf_src_name = self._parse_vnf_name(args.get("source"))
+ vnf_dst_name = self._parse_vnf_name(args.get("destination"))
+
+ params = self._create_dict(
+ vnf_src_interface=self._parse_vnf_interface(args.get("source")),
+ vnf_dst_interface=self._parse_vnf_interface(args.get("destination")),
+ weight=args.get("weight"),
+ match=args.get("match"),
+ bidirectional=args.get("bidirectional"),
+ cookie=args.get("cookie"))
+
+ response = put("%s/restapi/network/%s/%s" %
+ (args.get("endpoint"),
+ vnf_src_name,
+ vnf_dst_name),
+ json=json.dumps(params))
+ pp.pprint(response.json())
+
+ def remove(self, args):
+ vnf_src_name = self._parse_vnf_name(args.get("source"))
+ vnf_dst_name = self._parse_vnf_name(args.get("destination"))
+
+ params = self._create_dict(
+ vnf_src_interface=self._parse_vnf_interface(args.get("source")),
+ vnf_dst_interface=self._parse_vnf_interface(args.get("destination")),
+ weight=args.get("weight"),
+ match=args.get("match"),
+ bidirectional=args.get("bidirectional"),
+ cookie=args.get("cookie"))
+
+ response = delete("%s/restapi/network/%s/%s" %
+ (args.get("endpoint"),
+ vnf_src_name,
+ vnf_dst_name),
+ json=json.dumps(params))
+ pp.pprint(response.json())
+
+ def _parse_vnf_name(self, vnf_name_str):
+ vnf_name = vnf_name_str.split(':')[0]
+ return vnf_name
+
+ def _parse_vnf_interface(self, vnf_name_str):
+ try:
+ vnf_interface = vnf_name_str.split(':')[1]
+ except:
+ vnf_interface = None
+
+ return vnf_interface
+
+ def _create_dict(self, **kwargs):
+ return kwargs
+
+parser = argparse.ArgumentParser(description='son-emu network')
+parser.add_argument(
+ "command",
+ choices=['add', 'remove'],
+ help="Action to be executed.")
+parser.add_argument(
+ "--datacenter", "-d", dest="datacenter",
+ help="Data center to in which the network action should be initiated")
+parser.add_argument(
+ "--source", "-src", dest="source",
+ help="vnf name of the source of the chain")
+parser.add_argument(
+ "--destination", "-dst", dest="destination",
+ help="vnf name of the destination of the chain")
+parser.add_argument(
+ "--weight", "-w", dest="weight",
+ help="weight metric to calculate the path")
+parser.add_argument(
+ "--match", "-m", dest="match",
+ help="string holding extra matches for the flow entries")
+parser.add_argument(
+ "--bidirectional", "-b", dest="bidirectional",
+ action='store_true',
+ help="add/remove the flow entries from src to dst and back")
+parser.add_argument(
+ "--cookie", "-c", dest="cookie",
+ help="cookie for this flow, as easy to use identifier (eg. per tenant/service)")
+parser.add_argument(
+ "--endpoint", "-e", dest="endpoint",
+ default="http://127.0.0.1:5000",
+ help="UUID of the plugin to be manipulated.")
+
+def main(argv):
+ args = vars(parser.parse_args(argv))
+ c = RestApiClient()
+ c.execute_command(args)
\ No newline at end of file
from emuvim.cli import network
from emuvim.cli.rest import compute as restcom
from emuvim.cli.rest import datacenter as restdc
-
+from emuvim.cli.rest import monitor as restmon
+from emuvim.cli.rest import network as restnetw
def main():
exit(0)
if sys.argv[1] == "compute-zapi":
compute.main(sys.argv[2:])
- elif sys.argv[1] == "network":
+ elif sys.argv[1] == "network-zapi":
network.main(sys.argv[2:])
elif sys.argv[1] == "datacenter-zapi":
datacenter.main(sys.argv[2:])
- elif sys.argv[1] == "monitor":
+ elif sys.argv[1] == "monitor-zapi":
monitor.main(sys.argv[2:])
+ elif sys.argv[1] == "monitor":
+ restmon.main(sys.argv[2:])
+ elif sys.argv[1] == "network":
+ restnetw.main(sys.argv[2:])
elif sys.argv[1] == "compute":
restcom.main(sys.argv[2:])
elif sys.argv[1] == "datacenter":
if learning_switch:
self.ryu_process = Popen([ryu_cmd, ryu_path, ryu_path2, ryu_option, ryu_of_port], stdout=FNULL, stderr=FNULL)
else:
- # no learning switch
+ # no learning switch, but with rest api
self.ryu_process = Popen([ryu_cmd, ryu_path2, ryu_option, ryu_of_port], stdout=FNULL, stderr=FNULL)
time.sleep(1)
import logging
from mininet.log import setLogLevel
from emuvim.dcemulator.net import DCNetwork
-from emuvim.api.rest.compute import RestApiEndpoint
-#from emuvim.api.zerorpc.compute import ZeroRpcApiEndpoint
+from emuvim.api.rest.rest_api_endpoint import RestApiEndpoint
+
+from emuvim.api.zerorpc.compute import ZeroRpcApiEndpoint
from emuvim.api.zerorpc.network import ZeroRpcApiEndpointDCNetwork
logging.basicConfig(level=logging.INFO)
"""
1. Create a data center network object (DCNetwork)
"""
- net = DCNetwork()
+ net = DCNetwork(monitor=True, enable_learning=False)
"""
1b. add a monitoring agent to the DCNetwork
"""
+ #keep old zeroRPC interface to test the prometheus metric query
mon_api = ZeroRpcApiEndpointDCNetwork("0.0.0.0", 5151)
mon_api.connectDCNetwork(net)
mon_api.start()
one or more data centers to it, which can then be controlled through
this API, e.g., start/stop/list compute instances.
"""
+ # keep the old zeroRPC interface for the prometheus metric query test
+ zapi1 = ZeroRpcApiEndpoint("0.0.0.0", 4242)
+ # connect data centers to this endpoint
+ zapi1.connectDatacenter(dc1)
+ zapi1.connectDatacenter(dc2)
+ # run API endpoint server (in another thread, don't block)
+ zapi1.start()
+
# create a new instance of a endpoint implementation
api1 = RestApiEndpoint("127.0.0.1", 5000)
# connect data centers to this endpoint
api1.connectDatacenter(dc2)
api1.connectDatacenter(dc3)
api1.connectDatacenter(dc4)
+ # connect total network also, needed to do the chaining and monitoring
+ api1.connectDCNetwork(net)
# run API endpoint server (in another thread, don't block)
api1.start()
import subprocess
import docker
from emuvim.dcemulator.net import DCNetwork
-from emuvim.api.rest.compute import RestApiEndpoint
+from emuvim.api.rest.rest_api_endpoint import RestApiEndpoint
from mininet.clean import cleanup
from mininet.node import Controller
from emuvim.test.api_base import SimpleTestTopology
import subprocess
-
class testRestApi( SimpleTestTopology ):
"""
Tests to check the REST API endpoints of the emulator.
print('compute list ->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
subprocess.call("son-emu-cli compute list", shell=True)
+
+ print('network add vnf1 vnf2->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
+ print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
+ subprocess.call("son-emu-cli network add -src vnf1 -dst vnf2 -b -c 10", shell=True)
+ print('network remove vnf1 vnf2->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
+ print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
+ subprocess.call("son-emu-cli network remove -src vnf1 -dst vnf2 -b", shell=True)
+
print('compute stop datacenter0, vnf2 ->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
subprocess.call("son-emu-cli compute stop -d datacenter0 -n vnf2", shell=True)
--- /dev/null
+vnf1_uuid=$(docker inspect --format="{{.Id}}" mn.vnf1)
+
+
sleep 1
#stop the vnf
-son-emu-cli compute-zapi stop -d datacenter1 -n vnf1
+son-emu-cli compute stop -d datacenter1 -n vnf1
#python src/emuvim/examples/monitoring_demo_topology.py &
# start a vnf
-son-emu-cli compute-zapi start -d datacenter1 -n vnf1 --net '(id=input,ip=10.0.10.3/24),(id=output,ip=10.0.10.4/24)'
+son-emu-cli compute start -d datacenter1 -n vnf1 --net '(id=input,ip=10.0.10.3/24),(id=output,ip=10.0.10.4/24)'
sleep 1
# monitor a metric
son-emu-cli monitor setup_metric -vnf vnf1:output --metric tx_packets
-sleep 5
+# allow some time to gather metrics
+sleep 20
# check if metric is monitored as expected (exported by son-emu, has vnf name as metric id)
-tx_rate=$(son-emu-cli monitor prometheus -d datacenter1 -vnf vnf1 -q 'rate(sonemu_tx_count_packets{vnf_name="vnf1"}[1m])')
+tx_rate=$(son-emu-cli monitor-zapi prometheus -d datacenter1 -vnf vnf1 -q 'rate(sonemu_tx_count_packets{vnf_name="vnf1"}[10s])')
+sleep 1
# test if prometheus query worked
echo $tx_rate
# check if cpu load can be monitored (exported by cAdvisor, needs uuid)
-cpu_load=$(son-emu-cli monitor prometheus -d datacenter1 -vnf vnf1 -q 'sum(rate(container_cpu_usage_seconds_total{id="/docker/<uuid>"}[10s]))')
+cpu_load=$(son-emu-cli monitor-zapi prometheus -d datacenter1 -vnf vnf1 -q 'sum(rate(container_cpu_usage_seconds_total{id="/docker/<uuid>"}[10s]))')
sleep 1