See the License for the specific language governing permissions and
limitations under the License.
-Neither the name of the SONATA-NFV [, ANY ADDITIONAL AFFILIATION]
+Neither the name of the SONATA-NFV, Paderborn University
nor the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
acknowledge the contributions of their colleagues of the SONATA
partner consortium (www.sonata-nfv.eu).
"""
+
import logging
import threading
from flask import Flask
from flask_restful import Api
+from gevent.wsgi import WSGIServer
# need to import total module to set its global variable dcs
import compute
-from compute import dcs, ComputeList, Compute, DatacenterList, DatacenterStatus
+from compute import dcs, ComputeList, Compute, ComputeResources, DatacenterList, DatacenterStatus
# need to import total module to set its global variable net
import network
-from network import NetworkAction
+from network import NetworkAction, DrawD3jsgraph
import monitor
-from monitor import MonitorInterfaceAction, MonitorFlowAction, MonitorLinkAction
+from monitor import MonitorInterfaceAction, MonitorFlowAction, MonitorLinkAction, MonitorSkewAction, MonitorTerminal
+
+import pkg_resources
+from os import path
-logging.basicConfig(level=logging.INFO)
+logging.basicConfig()
class RestApiEndpoint(object):
default command line client.
"""
- def __init__(self, listenip, port):
+ def __init__(self, listenip, port, DCnetwork=None):
self.ip = listenip
self.port = port
+ # connect this DC network to the rest api endpoint (needed for the networking and monitoring api)
+ self.connectDCNetwork(DCnetwork)
+
# setup Flask
- self.app = Flask(__name__)
+ # find directory of dashboard files
+ dashboard_file = pkg_resources.resource_filename('emuvim.dashboard', "index.html")
+ dashboard_dir = path.dirname(dashboard_file)
+ logging.info("Started emu dashboard: {0}".format(dashboard_dir))
+
+ self.app = Flask(__name__, static_folder=dashboard_dir, static_url_path='/dashboard')
self.api = Api(self.app)
# setup endpoints
# compute related actions (start/stop VNFs, get info)
- self.api.add_resource(Compute,
- "/restapi/compute/<dc_label>/<compute_name>",
- "/restapi/compute/<dc_label>/<compute_name>/<resource>/<value>")
+ self.api.add_resource(Compute, "/restapi/compute/<dc_label>/<compute_name>")
self.api.add_resource(ComputeList,
"/restapi/compute",
"/restapi/compute/<dc_label>")
+ self.api.add_resource(ComputeResources, "/restapi/compute/resources/<dc_label>/<compute_name>")
self.api.add_resource(DatacenterStatus, "/restapi/datacenter/<dc_label>")
self.api.add_resource(DatacenterList, "/restapi/datacenter")
# network related actions (setup chaining between VNFs)
self.api.add_resource(NetworkAction,
- "/restapi/network/<vnf_src_name>/<vnf_dst_name>")
-
+ "/restapi/network")
+ self.api.add_resource(DrawD3jsgraph,
+ "/restapi/network/d3jsgraph")
# monitoring related actions
# export a network interface traffic rate counter
self.api.add_resource(MonitorInterfaceAction,
- "/restapi/monitor/interface/<vnf_name>/<metric>",
- "/restapi/monitor/interface/<vnf_name>/<vnf_interface>/<metric>",
- "/restapi/monitor/interface/<vnf_name>/<vnf_interface>/<metric>/<cookie>")
+ "/restapi/monitor/interface")
# export flow traffic counter, of a manually pre-installed flow entry, specified by its cookie
self.api.add_resource(MonitorFlowAction,
- "/restapi/monitor/flow/<vnf_name>/<metric>/<cookie>",
- "/restapi/monitor/flow/<vnf_name>/<vnf_interface>/<metric>/<cookie>")
+ "/restapi/monitor/flow")
# install monitoring of a specific flow on a pre-existing link in the service.
# the traffic counters of the newly installed monitor flow are exported
self.api.add_resource(MonitorLinkAction,
- "/restapi/monitor/link/<vnf_src_name>/<vnf_dst_name>")
+ "/restapi/monitor/link")
+ # install skewness monitor of resource usage disribution
+ # the skewness metric is exported
+ self.api.add_resource(MonitorSkewAction,
+ "/restapi/monitor/skewness")
+ # start a terminal window for the specified vnfs
+ self.api.add_resource(MonitorTerminal,
+ "/restapi/monitor/term")
+
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(
self.__class__.__name__, self.ip, self.port))
def start(self):
- thread = threading.Thread(target=self._start_flask, args=())
- thread.daemon = True
- thread.start()
+ self.thread = threading.Thread(target=self._start_flask, args=())
+ self.thread.daemon = True
+ self.thread.start()
logging.info("Started API endpoint @ http://%s:%d" % (self.ip, self.port))
+ def stop(self):
+ if self.http_server:
+ self.http_server.close()
+
def _start_flask(self):
- self.app.run(self.ip, self.port, debug=True, use_reloader=False)
+ #self.app.run(self.ip, self.port, debug=False, use_reloader=False)
+ #this should be a more production-fit http-server
+ #self.app.logger.setLevel(logging.ERROR)
+ self.http_server = WSGIServer((self.ip, self.port),
+ self.app,
+ log=open("/dev/null", "w") # This disables HTTP request logs to not mess up the CLI when e.g. the auto-updated dashboard is used
+ )
+ self.http_server.serve_forever()