Ensure timely termination of all flask servers
1. The chain_api was never terminated. This was fixed by turning the
server into an pyWSGI instance.
2. no monkey patching was applied. The monkey patching of gevent is
required in order to be able to handle other events during a
time.sleep() call. Since multiple patching is detected, it was added to
all files which create WSGI servers.
All in all this change fixes a large leak of threads, open files and
performance.
This change updates Containernet in order to fix race conditions which
otherwise happen due to gevent's monkey patching.
Change-Id: Ia45ad07db1f85046bfcac85eaca20c930b931141
Signed-off-by: schillinge <ablu@mail.uni-paderborn.de>
diff --git a/src/emuvim/api/openstack/chain_api.py b/src/emuvim/api/openstack/chain_api.py
index 47af63c..fde3a42 100755
--- a/src/emuvim/api/openstack/chain_api.py
+++ b/src/emuvim/api/openstack/chain_api.py
@@ -27,12 +27,17 @@
import logging
import copy
+from gevent import monkey
+from gevent.pywsgi import WSGIServer
+
from mininet.node import OVSSwitch
from flask import Flask
from flask import Response, request
from flask_restful import Api, Resource
+monkey.patch_all()
+
class ChainApi(Resource):
"""
@@ -65,7 +70,6 @@
resource_class_kwargs={'api': self})
self.api.add_resource(QueryTopology, "/v1/topo",
resource_class_kwargs={'api': self})
- self.api.add_resource(Shutdown, "/shutdown")
@self.app.after_request
def add_access_control_header(response):
@@ -75,9 +79,18 @@
def _start_flask(self):
logging.info("Starting %s endpoint @ http://%s:%d" %
("ChainDummyApi", self.ip, self.port))
- if self.app is not None:
- self.app.before_request(self.dump_playbook)
- self.app.run(self.ip, self.port, debug=True, use_reloader=False)
+ self.http_server = WSGIServer(
+ (self.ip, self.port),
+ self.app,
+ log=open("/dev/null", "w") # don't show http logs
+ )
+ self.http_server.serve_forever(stop_timeout=1)
+ logging.info('Stopped %s' % self.__class__.__name__)
+
+ def stop(self):
+ if self.http_server:
+ logging.info('Stopping %s' % self.__class__.__name__)
+ self.http_server.stop(timeout=1)
def dump_playbook(self):
with self.manage.lock:
@@ -90,15 +103,6 @@
logfile.write(data + "\n")
-class Shutdown(Resource):
- def get(self):
- logging.debug(("%s is beeing shut down") % (__name__))
- func = request.environ.get('werkzeug.server.shutdown')
- if func is None:
- raise RuntimeError('Not running with the Werkzeug Server')
- func()
-
-
class ChainVersionsList(Resource):
'''
Entrypoint to find versions of the chain api.