-"""
-Copyright (c) 2015 SONATA-NFV and Paderborn University
-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.
-
-Neither the name of the SONATA-NFV [, ANY ADDITIONAL AFFILIATION]
-nor the names of its contributors may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-
-This work has been performed in the framework of the SONATA project,
-funded by the European Commission under Grant number 671517 through
-the Horizon 2020 and 5G-PPP programmes. The authors would like to
-acknowledge the contributions of their colleagues of the SONATA
-partner consortium (www.sonata-nfv.eu).
-"""
+# Copyright (c) 2015 SONATA-NFV and Paderborn University
+# 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.
+#
+# 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.
+#
+# This work has been performed in the framework of the SONATA project,
+# funded by the European Commission under Grant number 671517 through
+# the Horizon 2020 and 5G-PPP programmes. The authors would like to
+# 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
+from gevent.pywsgi import WSGIServer
# need to import total module to set its global variable dcs
import compute
-from compute import dcs, ComputeList, Compute, ComputeResources, DatacenterList, DatacenterStatus
+from compute import 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, MonitorSkewAction
+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
# find directory of dashboard files
- dashboard_file = pkg_resources.resource_filename('emuvim.dashboard', "index.html")
+ 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.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>")
+ 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>")
+ "/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(
+ 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")
-
+ 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")
- # export flow traffic counter, of a manually pre-installed flow entry, specified by its cookie
+ # export flow traffic counter, of a manually pre-installed flow entry,
+ # specified by its cookie
self.api.add_resource(MonitorFlowAction,
"/restapi/monitor/flow")
# install monitoring of a specific flow on a pre-existing link in the service.
# 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))
-
+ logging.debug("Created API endpoint %s(%s:%d)" %
+ (self.__class__.__name__, self.ip, self.port))
def connectDatacenter(self, dc):
compute.dcs[dc.label] = dc
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))
+ 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)
- #this should be a more production-fit http-server
- #http_server = WSGIServer((self.ip, self.port), self.app)
- #http_server.serve_forever()
+ # 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,
+ # This disables HTTP request logs to not
+ # mess up the CLI when e.g. the
+ # auto-updated dashboard is used
+ log=open("/dev/null", "w")
+ )
+ self.http_server.serve_forever()