1 # Copyright (c) 2015 SONATA-NFV and Paderborn University
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 # Neither the name of the SONATA-NFV, Paderborn University
17 # nor the names of its contributors may be used to endorse or promote
18 # products derived from this software without specific prior written
21 # This work has been performed in the framework of the SONATA project,
22 # funded by the European Commission under Grant number 671517 through
23 # the Horizon 2020 and 5G-PPP programmes. The authors would like to
24 # acknowledge the contributions of their colleagues of the SONATA
25 # partner consortium (www.sonata-nfv.eu).
29 from flask
import Flask
, send_from_directory
30 from flask_restful
import Api
31 from gevent
.pywsgi
import WSGIServer
33 # need to import total module to set its global variable dcs
35 from compute
import ComputeList
, Compute
, ComputeResources
, DatacenterList
, DatacenterStatus
37 # need to import total module to set its global variable net
39 from network
import NetworkAction
, DrawD3jsgraph
42 from monitor
import MonitorInterfaceAction
, MonitorFlowAction
, MonitorLinkAction
, MonitorSkewAction
, MonitorTerminal
51 class RestApiEndpoint(object):
53 Simple API endpoint that offers a REST
54 interface. This interface will be used by the
55 default command line client.
58 def __init__(self
, listenip
, port
, DCnetwork
=None):
62 # connect this DC network to the rest api endpoint (needed for the
63 # networking and monitoring api)
64 self
.connectDCNetwork(DCnetwork
)
67 self
.app
= Flask(__name__
)
68 self
.api
= Api(self
.app
)
70 # define dashboard endpoints
71 db_dir
, db_file
= self
.get_dashboard_path()
72 @self.app
.route('/dashboard/<path:path>')
74 logging
.info("[DB] Serving: {}".format(path
))
75 return send_from_directory(db_dir
, path
)
77 # define REST API endpoints
78 # compute related actions (start/stop VNFs, get info)
79 self
.api
.add_resource(
80 Compute
, "/restapi/compute/<dc_label>/<compute_name>")
81 self
.api
.add_resource(ComputeList
,
83 "/restapi/compute/<dc_label>")
84 self
.api
.add_resource(
85 ComputeResources
, "/restapi/compute/resources/<dc_label>/<compute_name>")
87 self
.api
.add_resource(
88 DatacenterStatus
, "/restapi/datacenter/<dc_label>")
89 self
.api
.add_resource(DatacenterList
, "/restapi/datacenter")
91 # network related actions (setup chaining between VNFs)
92 self
.api
.add_resource(NetworkAction
,
94 self
.api
.add_resource(DrawD3jsgraph
,
95 "/restapi/network/d3jsgraph")
97 # monitoring related actions
98 # export a network interface traffic rate counter
99 self
.api
.add_resource(MonitorInterfaceAction
,
100 "/restapi/monitor/interface")
101 # export flow traffic counter, of a manually pre-installed flow entry,
102 # specified by its cookie
103 self
.api
.add_resource(MonitorFlowAction
,
104 "/restapi/monitor/flow")
105 # install monitoring of a specific flow on a pre-existing link in the service.
106 # the traffic counters of the newly installed monitor flow are exported
107 self
.api
.add_resource(MonitorLinkAction
,
108 "/restapi/monitor/link")
109 # install skewness monitor of resource usage disribution
110 # the skewness metric is exported
111 self
.api
.add_resource(MonitorSkewAction
,
112 "/restapi/monitor/skewness")
113 # start a terminal window for the specified vnfs
114 self
.api
.add_resource(MonitorTerminal
,
115 "/restapi/monitor/term")
117 logging
.debug("Created API endpoint %s(%s:%d)" %
118 (self
.__class
__.__name
__, self
.ip
, self
.port
))
120 def get_dashboard_path(self
):
122 Return absolute path to dashboard files.
124 db_file
= pkg_resources
.resource_filename(
125 'emuvim.dashboard', "index.html")
126 db_dir
= path
.dirname(db_file
)
127 logging
.info("[DB] Serving emulator dashboard from: {} and {}"
128 .format(db_dir
, db_file
))
129 return db_dir
, db_file
131 def connectDatacenter(self
, dc
):
132 compute
.dcs
[dc
.label
] = dc
134 "Connected DC(%s) to API endpoint %s(%s:%d)" % (dc
.label
, self
.__class
__.__name
__, self
.ip
, self
.port
))
136 def connectDCNetwork(self
, DCnetwork
):
137 network
.net
= DCnetwork
138 monitor
.net
= DCnetwork
140 logging
.info("Connected DCNetwork to API endpoint %s(%s:%d)" % (
141 self
.__class
__.__name
__, self
.ip
, self
.port
))
144 self
.thread
= threading
.Thread(target
=self
._start
_flask
, args
=())
145 self
.thread
.daemon
= True
147 logging
.info("Started API endpoint @ http://%s:%d" %
148 (self
.ip
, self
.port
))
152 self
.http_server
.close()
154 def _start_flask(self
):
155 # self.app.run(self.ip, self.port, debug=False, use_reloader=False)
156 # this should be a more production-fit http-server
157 # self.app.logger.setLevel(logging.ERROR)
158 self
.http_server
= WSGIServer((self
.ip
, self
.port
),
160 # This disables HTTP request logs to not
161 # mess up the CLI when e.g. the
162 # auto-updated dashboard is used
163 log
=open("/dev/null", "w")
165 self
.http_server
.serve_forever()