| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- #!/usr/bin/env python
- # Licensed to Cloudera, Inc. under one
- # or more contributor license agreements. See the NOTICE file
- # distributed with this work for additional information
- # regarding copyright ownership. Cloudera, Inc. licenses this file
- # to you 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.
- import logging
- import os
- import socket
- import sys
- from django.utils.translation import ugettext_lazy as _t, ugettext as _
- from desktop.conf import default_ssl_cacerts, default_ssl_validate, AUTH_USERNAME as DEFAULT_AUTH_USERNAME, \
- AUTH_PASSWORD as DEFAULT_AUTH_PASSWORD, has_connectors
- from desktop.lib.conf import ConfigSection, Config, coerce_bool, coerce_csv, coerce_password_from_script
- from desktop.lib.exceptions import StructuredThriftTransportException
- from desktop.lib.paths import get_desktop_root
- from impala.impala_flags import get_max_result_cache_size, is_impersonation_enabled, is_kerberos_enabled, is_webserver_spnego_enabled
- from impala.settings import NICE_NAME
- LOG = logging.getLogger(__name__)
- SERVER_HOST = Config(
- key="server_host",
- help=_t("Host of the Impala Server."),
- default="localhost")
- SERVER_PORT = Config(
- key="server_port",
- help=_t("Port of the Impala Server."),
- default=21050,
- type=int)
- COORDINATOR_URL = Config(
- key="coordinator_url",
- help=_t("URL of the Impala Coordinator Server."),
- type=str,
- default="")
- IMPALA_PRINCIPAL=Config(
- key='impala_principal',
- help=_t("Kerberos principal name for Impala. Typically 'impala/hostname.foo.com'."),
- type=str,
- default="impala/%s" % socket.getfqdn())
- IMPERSONATION_ENABLED=Config(
- key='impersonation_enabled',
- help=_t("Turn on/off impersonation mechanism when talking to Impala."),
- type=coerce_bool,
- dynamic_default=is_impersonation_enabled)
- QUERYCACHE_ROWS=Config(
- key='querycache_rows',
- help=_t("Number of initial rows of a resultset to ask Impala to cache in order to"
- " support re-fetching them for downloading them."
- " Set to 0 for disabling the option and backward compatibility."),
- type=int,
- dynamic_default=get_max_result_cache_size)
- SERVER_CONN_TIMEOUT = Config(
- key='server_conn_timeout',
- default=120,
- type=int,
- help=_t('Timeout in seconds for Thrift calls.'))
- CLOSE_QUERIES = Config(
- key="close_queries",
- help=_t("Hue will try to close the Impala query when the user leaves the editor page. "
- "This will free all the query resources in Impala, but also make its results inaccessible."),
- type=coerce_bool,
- default=True
- )
- QUERY_TIMEOUT_S = Config(
- key="query_timeout_s",
- help=_t("If QUERY_TIMEOUT_S > 0, the query will be timed out (i.e. cancelled) if Impala does not do any work"
- " (compute or send back results) for that query within QUERY_TIMEOUT_S seconds."),
- type=int,
- default=300
- )
- SESSION_TIMEOUT_S = Config(
- key="session_timeout_s",
- help=_t("If SESSION_TIMEOUT_S > 0, the session will be timed out (i.e. cancelled) if Impala does not do any work"
- " (compute or send back results) for that session within SESSION_TIMEOUT_S seconds. Default: 15 min."),
- type=int,
- default=15 * 60
- )
- CONFIG_WHITELIST = Config(
- key='config_whitelist',
- default='debug_action,explain_level,mem_limit,optimize_partition_key_scans,query_timeout_s,request_pool',
- type=coerce_csv,
- help=_t('A comma-separated list of white-listed Impala configuration properties that users are authorized to set.')
- )
- IMPALA_CONF_DIR = Config(
- key='impala_conf_dir',
- help=_t('Impala configuration directory, where impala_flags is located.'),
- type=str,
- default=os.environ.get("HUE_CONF_DIR", get_desktop_root("conf")) + '/impala-conf'
- )
- SSL = ConfigSection(
- key='ssl',
- help=_t('SSL configuration for the server.'),
- members=dict(
- ENABLED = Config(
- key="enabled",
- help=_t("SSL communication enabled for this server."),
- type=coerce_bool,
- default=False
- ),
- CACERTS = Config(
- key="cacerts",
- help=_t("Path to Certificate Authority certificates."),
- type=str,
- dynamic_default=default_ssl_cacerts,
- ),
- KEY = Config(
- key="key",
- help=_t("Path to the private key file, e.g. /etc/hue/key.pem"),
- type=str,
- default=None
- ),
- CERT = Config(
- key="cert",
- help=_t("Path to the public certificate file, e.g. /etc/hue/cert.pem"),
- type=str,
- default=None
- ),
- VALIDATE = Config(
- key="validate",
- help=_t("Choose whether Hue should validate certificates received from the server."),
- type=coerce_bool,
- dynamic_default=default_ssl_validate,
- )
- )
- )
- def get_auth_username():
- """Get from top level default from desktop"""
- return DEFAULT_AUTH_USERNAME.get()
- AUTH_USERNAME = Config(
- key="auth_username",
- help=_t("Auth username of the hue user used for authentications."),
- private=True,
- dynamic_default=get_auth_username)
- def get_auth_password():
- """Get from script or backward compatibility"""
- password = AUTH_PASSWORD_SCRIPT.get()
- if password:
- return password
- return DEFAULT_AUTH_PASSWORD.get()
- AUTH_PASSWORD = Config(
- key="auth_password",
- help=_t("LDAP/PAM/.. password of the hue user used for authentications."),
- private=True,
- dynamic_default=get_auth_password
- )
- AUTH_PASSWORD_SCRIPT = Config(
- key="auth_password_script",
- help=_t("Execute this script to produce the auth password. This will be used when `auth_password` is not set."),
- private=True,
- type=coerce_password_from_script,
- default=None
- )
- def get_daemon_config(key):
- from metadata.conf import MANAGER
- from metadata.manager_client import ManagerApi
- if MANAGER.API_URL.get():
- return ManagerApi().get_impalad_config(key=key, impalad_host=SERVER_HOST.get())
- return None
- def get_daemon_api_username():
- """
- Try to get daemon_api_username from Cloudera Manager API
- """
- return get_daemon_config('webserver_htpassword_user')
- def get_daemon_api_password():
- """
- Try to get daemon_api_password from Cloudera Manager API
- """
- return get_daemon_config('webserver_htpassword_password')
- DAEMON_API_PASSWORD = Config(
- key="daemon_api_password",
- help=_t("Password for Impala Daemon when username/password authentication is enabled for the Impala Daemon UI."),
- private=True,
- dynamic_default=get_daemon_api_password
- )
- DAEMON_API_PASSWORD_SCRIPT = Config(
- key="daemon_api_password_script",
- help=_t("Execute this script to produce the Impala Daemon Password. This will be used when `daemon_api_password` is not set."),
- private=True,
- type=coerce_password_from_script,
- default=None
- )
- DAEMON_API_USERNAME = Config(
- key="daemon_api_username",
- help=_t("Username for Impala Daemon when username/password authentication is enabled for the Impala Daemon UI."),
- private=True,
- dynamic_default=get_daemon_api_username
- )
- def get_use_sasl_default():
- """kerberos enabled or password is specified"""
- return is_kerberos_enabled() or AUTH_PASSWORD.get() is not None # Maps closely to legacy behavior
- USE_SASL = Config(
- key="use_sasl",
- help=_t("Use SASL framework to establish connection to host."),
- private=False,
- type=coerce_bool,
- dynamic_default=get_use_sasl_default
- )
- def config_validator(user):
- # dbms is dependent on beeswax.conf, import in method to avoid circular dependency
- from beeswax.design import hql_query
- from beeswax.server import dbms
- from beeswax.server.dbms import get_query_server_config
- res = []
- if has_connectors():
- return res
- try:
- try:
- if not 'test' in sys.argv: # Avoid tests hanging
- query_server = get_query_server_config(name='impala')
- server = dbms.get(user, query_server)
- query = hql_query("SELECT 'Hello World!';")
- handle = server.execute_and_wait(query, timeout_sec=10.0)
- if handle:
- server.fetch(handle, rows=100)
- server.close(handle)
- except StructuredThriftTransportException as ex:
- if 'TSocket read 0 bytes' in str(ex): # this message appears when authentication fails
- msg = "Failed to authenticate to Impalad, check authentication configurations."
- LOG.exception(msg)
- res.append((NICE_NAME, _(msg)))
- else:
- raise ex
- except Exception as ex:
- msg = "No available Impalad to send queries to."
- LOG.exception(msg)
- res.append((NICE_NAME, _(msg)))
- return res
|