|
@@ -14,34 +14,27 @@
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
# See the License for the specific language governing permissions and
|
|
# See the License for the specific language governing permissions and
|
|
|
# limitations under the License.
|
|
# limitations under the License.
|
|
|
-
|
|
|
|
|
from __future__ import unicode_literals
|
|
from __future__ import unicode_literals
|
|
|
-
|
|
|
|
|
-from OpenSSL import crypto
|
|
|
|
|
-
|
|
|
|
|
import atexit
|
|
import atexit
|
|
|
|
|
+import desktop.log
|
|
|
|
|
+import gunicorn.app.base
|
|
|
|
|
+import logging
|
|
|
|
|
+import logging.config
|
|
|
import os
|
|
import os
|
|
|
-import sys
|
|
|
|
|
|
|
+import pkg_resources
|
|
|
import ssl
|
|
import ssl
|
|
|
-import multiprocessing
|
|
|
|
|
|
|
+import sys
|
|
|
import tempfile
|
|
import tempfile
|
|
|
|
|
|
|
|
-import gunicorn.app.base
|
|
|
|
|
-
|
|
|
|
|
|
|
+from OpenSSL import crypto
|
|
|
|
|
+from multiprocessing.util import _exit_function
|
|
|
from desktop import conf
|
|
from desktop import conf
|
|
|
-from desktop import supervisor, metrics
|
|
|
|
|
from django.core.management.base import BaseCommand
|
|
from django.core.management.base import BaseCommand
|
|
|
from django.core.wsgi import get_wsgi_application
|
|
from django.core.wsgi import get_wsgi_application
|
|
|
|
|
+from django.utils.translation import gettext as _
|
|
|
from gunicorn import util
|
|
from gunicorn import util
|
|
|
-from multiprocessing.util import _exit_function
|
|
|
|
|
from six import iteritems
|
|
from six import iteritems
|
|
|
|
|
|
|
|
-if sys.version_info[0] > 2:
|
|
|
|
|
- from django.utils.translation import gettext as _
|
|
|
|
|
-else:
|
|
|
|
|
- from django.utils.translation import ugettext as _
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
GUNICORN_SERVER_HELP = r"""
|
|
GUNICORN_SERVER_HELP = r"""
|
|
|
Run Hue using the Gunicorn WSGI server in asynchronous mode.
|
|
Run Hue using the Gunicorn WSGI server in asynchronous mode.
|
|
|
"""
|
|
"""
|
|
@@ -49,26 +42,47 @@ GUNICORN_SERVER_HELP = r"""
|
|
|
class Command(BaseCommand):
|
|
class Command(BaseCommand):
|
|
|
help = _("Gunicorn Web server for Hue.")
|
|
help = _("Gunicorn Web server for Hue.")
|
|
|
|
|
|
|
|
|
|
+ def add_arguments(self, parser):
|
|
|
|
|
+ parser.add_argument('--bind', help=_("Bind Address"), action='store', default=None)
|
|
|
|
|
+
|
|
|
def handle(self, *args, **options):
|
|
def handle(self, *args, **options):
|
|
|
- rungunicornserver()
|
|
|
|
|
|
|
+ start_server(args, options)
|
|
|
|
|
|
|
|
def usage(self, subcommand):
|
|
def usage(self, subcommand):
|
|
|
return GUNICORN_SERVER_HELP
|
|
return GUNICORN_SERVER_HELP
|
|
|
|
|
|
|
|
|
|
+def activate_translation():
|
|
|
|
|
+ from django.conf import settings
|
|
|
|
|
+ from django.utils import translation
|
|
|
|
|
+
|
|
|
|
|
+ # Activate the current language, because it won't get activated later.
|
|
|
|
|
+ try:
|
|
|
|
|
+ translation.activate(settings.LANGUAGE_CODE)
|
|
|
|
|
+ except AttributeError:
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
def number_of_workers():
|
|
def number_of_workers():
|
|
|
return (multiprocessing.cpu_count() * 2) + 1
|
|
return (multiprocessing.cpu_count() * 2) + 1
|
|
|
|
|
|
|
|
-
|
|
|
|
|
def handler_app(environ, start_response):
|
|
def handler_app(environ, start_response):
|
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "desktop.settings")
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "desktop.settings")
|
|
|
return get_wsgi_application()
|
|
return get_wsgi_application()
|
|
|
|
|
|
|
|
-def post_worker_init(worker):
|
|
|
|
|
- atexit.unregister(_exit_function)
|
|
|
|
|
|
|
+def enable_logging(args, options):
|
|
|
|
|
+ HUE_DESKTOP_VERSION = pkg_resources.get_distribution("desktop").version or "Unknown"
|
|
|
|
|
+ # Start basic logging as soon as possible.
|
|
|
|
|
+ if "HUE_PROCESS_NAME" not in os.environ:
|
|
|
|
|
+ _proc = os.path.basename(len(sys.argv) > 1 and sys.argv[1] or sys.argv[0])
|
|
|
|
|
+ os.environ["HUE_PROCESS_NAME"] = _proc
|
|
|
|
|
|
|
|
|
|
+ desktop.log.basic_logging(os.environ["HUE_PROCESS_NAME"], log_dir=None, conf_file='log.conf')
|
|
|
|
|
+ logging.info("Welcome to Hue from Gunicorn server " + HUE_DESKTOP_VERSION)
|
|
|
|
|
|
|
|
-class StandaloneApplication(gunicorn.app.base.BaseApplication):
|
|
|
|
|
|
|
+def post_fork(server, worker):
|
|
|
|
|
+ with open("/tmp/gunicorn_workers.pid", "a") as f:
|
|
|
|
|
+ f.write("%s\n"%worker.pid)
|
|
|
|
|
|
|
|
|
|
+class StandaloneApplication(gunicorn.app.base.BaseApplication):
|
|
|
def __init__(self, app, options=None):
|
|
def __init__(self, app, options=None):
|
|
|
self.options = options or {}
|
|
self.options = options or {}
|
|
|
self.app_uri = 'desktop.wsgi:application'
|
|
self.app_uri = 'desktop.wsgi:application'
|
|
@@ -97,8 +111,12 @@ class StandaloneApplication(gunicorn.app.base.BaseApplication):
|
|
|
def load(self):
|
|
def load(self):
|
|
|
return self.load_wsgiapp()
|
|
return self.load_wsgiapp()
|
|
|
|
|
|
|
|
-def rungunicornserver():
|
|
|
|
|
- bind_addr = conf.HTTP_HOST.get() + ":" + str(conf.HTTP_PORT.get())
|
|
|
|
|
|
|
+def argprocessing(args=[], options={}):
|
|
|
|
|
+ if options['bind']:
|
|
|
|
|
+ bind_addr = options['bind']
|
|
|
|
|
+ else:
|
|
|
|
|
+ bind_addr = conf.HTTP_HOST.get() + ":" + str(conf.HTTP_PORT.get())
|
|
|
|
|
+ options['bind_addr'] = bind_addr
|
|
|
|
|
|
|
|
# Currently gunicorn does not support passphrase suppored SSL Keyfile
|
|
# Currently gunicorn does not support passphrase suppored SSL Keyfile
|
|
|
# https://github.com/benoitc/gunicorn/issues/2410
|
|
# https://github.com/benoitc/gunicorn/issues/2410
|
|
@@ -115,11 +133,13 @@ def rungunicornserver():
|
|
|
ssl_keyfile = tf.name
|
|
ssl_keyfile = tf.name
|
|
|
else:
|
|
else:
|
|
|
ssl_keyfile = conf.SSL_PRIVATE_KEY.get()
|
|
ssl_keyfile = conf.SSL_PRIVATE_KEY.get()
|
|
|
|
|
+ options['ssl_keyfile'] = ssl_keyfile
|
|
|
|
|
|
|
|
- options = {
|
|
|
|
|
|
|
+def rungunicornserver(args=[], options={}):
|
|
|
|
|
+ gunicorn_options = {
|
|
|
'accesslog': "-",
|
|
'accesslog': "-",
|
|
|
'backlog': 2048,
|
|
'backlog': 2048,
|
|
|
- 'bind': [bind_addr],
|
|
|
|
|
|
|
+ 'bind': [options['bind_addr']],
|
|
|
'ca_certs': conf.SSL_CACERTS.get(), # CA certificates file
|
|
'ca_certs': conf.SSL_CACERTS.get(), # CA certificates file
|
|
|
'capture_output': True,
|
|
'capture_output': True,
|
|
|
'cert_reqs': None, # Whether client certificate is required (see stdlib ssl module)
|
|
'cert_reqs': None, # Whether client certificate is required (see stdlib ssl module)
|
|
@@ -137,11 +157,11 @@ def rungunicornserver():
|
|
|
'group': conf.SERVER_GROUP.get(),
|
|
'group': conf.SERVER_GROUP.get(),
|
|
|
'initgroups': None,
|
|
'initgroups': None,
|
|
|
'keepalive': 120, # seconds to wait for requests on a keep-alive connection.
|
|
'keepalive': 120, # seconds to wait for requests on a keep-alive connection.
|
|
|
- 'keyfile': ssl_keyfile, # SSL key file
|
|
|
|
|
|
|
+ 'keyfile': options['ssl_keyfile'], # SSL key file
|
|
|
'limit_request_field_size': conf.LIMIT_REQUEST_FIELD_SIZE.get(),
|
|
'limit_request_field_size': conf.LIMIT_REQUEST_FIELD_SIZE.get(),
|
|
|
'limit_request_fields': conf.LIMIT_REQUEST_FIELDS.get(),
|
|
'limit_request_fields': conf.LIMIT_REQUEST_FIELDS.get(),
|
|
|
'limit_request_line': conf.LIMIT_REQUEST_LINE.get(),
|
|
'limit_request_line': conf.LIMIT_REQUEST_LINE.get(),
|
|
|
- 'logconfig': None,
|
|
|
|
|
|
|
+ 'logconfig': '/etc/hue/conf/log.conf',
|
|
|
'loglevel': 'info',
|
|
'loglevel': 'info',
|
|
|
'max_requests': 1200, # The maximum number of requests a worker will process before restarting.
|
|
'max_requests': 1200, # The maximum number of requests a worker will process before restarting.
|
|
|
'max_requests_jitter': 0,
|
|
'max_requests_jitter': 0,
|
|
@@ -156,7 +176,7 @@ def rungunicornserver():
|
|
|
'raw_paste_global_conf': None,
|
|
'raw_paste_global_conf': None,
|
|
|
'reload': None,
|
|
'reload': None,
|
|
|
'reload_engine': None,
|
|
'reload_engine': None,
|
|
|
- 'sendfile': None,
|
|
|
|
|
|
|
+ 'sendfile': True,
|
|
|
'spew': None,
|
|
'spew': None,
|
|
|
'ssl_version': ssl.PROTOCOL_TLSv1_2, # SSL version to use
|
|
'ssl_version': ssl.PROTOCOL_TLSv1_2, # SSL version to use
|
|
|
'statsd_host': None,
|
|
'statsd_host': None,
|
|
@@ -173,10 +193,25 @@ def rungunicornserver():
|
|
|
'worker_class': conf.GUNICORN_WORKER_CLASS.get(),
|
|
'worker_class': conf.GUNICORN_WORKER_CLASS.get(),
|
|
|
'worker_connections': 1000,
|
|
'worker_connections': 1000,
|
|
|
'worker_tmp_dir': None,
|
|
'worker_tmp_dir': None,
|
|
|
- 'workers': conf.GUNICORN_NUMBER_OF_WORKERS.get() if conf.GUNICORN_NUMBER_OF_WORKERS.get() is not None else number_of_workers(),
|
|
|
|
|
- 'post_worker_init': post_worker_init
|
|
|
|
|
|
|
+ 'workers': conf.GUNICORN_NUMBER_OF_WORKERS.get() if conf.GUNICORN_NUMBER_OF_WORKERS.get() is not None else 5,
|
|
|
|
|
+ 'post_fork': post_fork
|
|
|
}
|
|
}
|
|
|
- StandaloneApplication(handler_app, options).run()
|
|
|
|
|
|
|
+ StandaloneApplication(handler_app, gunicorn_options).run()
|
|
|
|
|
+
|
|
|
|
|
+def start_server(args, options):
|
|
|
|
|
+ argprocessing(args, options)
|
|
|
|
|
+
|
|
|
|
|
+ # Hide the Server software version in the response body
|
|
|
|
|
+ gunicorn.SERVER_SOFTWARE = "apache"
|
|
|
|
|
+ os.environ["SERVER_SOFTWARE"] = gunicorn.SERVER_SOFTWARE
|
|
|
|
|
+
|
|
|
|
|
+ # Activate django translation
|
|
|
|
|
+ activate_translation()
|
|
|
|
|
+ enable_logging(args, options)
|
|
|
|
|
+ with open("/tmp/gunicorn_workers.pid", "w") as f:
|
|
|
|
|
+ f.write("%s\n"%os.getpid())
|
|
|
|
|
+ atexit.unregister(_exit_function)
|
|
|
|
|
+ rungunicornserver(args, options)
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
if __name__ == '__main__':
|
|
|
- rungunicornserver()
|
|
|
|
|
|
|
+ start_server(args=sys.argv[1:], options={})
|