Jakob Juelich | 934f0dc | 2014-10-14 18:21:13 -0700 | [diff] [blame] | 1 | #pylint: disable-msg=C0111 |
| 2 | |
| 3 | # Copyright (c) 2014 The Chromium OS Authors. All rights reserved. |
| 4 | # Use of this source code is governed by a BSD-style license that can be |
| 5 | # found in the LICENSE file. |
| 6 | |
| 7 | """Helpers to load database settings. |
| 8 | |
Dan Shi | 9a535c9 | 2014-11-24 08:52:40 -0800 | [diff] [blame] | 9 | Four databases are used with django (a default and one for tko tables, |
| 10 | which always must be the global database, a readonly connection to the |
| 11 | global database, and a connection to server database). |
Jakob Juelich | 934f0dc | 2014-10-14 18:21:13 -0700 | [diff] [blame] | 12 | |
| 13 | In order to save configuration overhead, settings that aren't set for the |
| 14 | desired database type, should be obtained from the setting with the next lower |
| 15 | priority. The order is: |
| 16 | readonly -> global -> local. |
| 17 | I.e. this means if `readonly_host` is not set, `global_db_host` will be used. If |
| 18 | that is also not set, `host` (the local one) will be used. |
| 19 | |
Dan Shi | 9a535c9 | 2014-11-24 08:52:40 -0800 | [diff] [blame] | 20 | server database setting falls back to local database setting. That is, if |
| 21 | `server_db_host` is not set, `host`(the local one) will be used. |
| 22 | |
Jakob Juelich | 934f0dc | 2014-10-14 18:21:13 -0700 | [diff] [blame] | 23 | In case an instance is running on a shard, a global database must explicitly |
| 24 | be set. Instead of failing over from global to local, an exception will be |
| 25 | raised in that case. |
| 26 | |
| 27 | The complexity to do this, is combined in this file. |
| 28 | """ |
| 29 | |
| 30 | |
| 31 | # Don't import anything that needs django here: Django may not be configured |
| 32 | # on the builders, and this is also used by tko/db.py so failures like this |
| 33 | # may occur: http://crbug.com/421565 |
| 34 | import common |
| 35 | from autotest_lib.client.common_lib import global_config |
| 36 | |
| 37 | config = global_config.global_config |
| 38 | SHARD_HOSTNAME = config.get_config_value('SHARD', 'shard_hostname', |
| 39 | default=None) |
| 40 | |
| 41 | |
Dan Shi | 9a535c9 | 2014-11-24 08:52:40 -0800 | [diff] [blame] | 42 | def _get_config(config_key, section='AUTOTEST_WEB', **kwargs): |
Jakob Juelich | 934f0dc | 2014-10-14 18:21:13 -0700 | [diff] [blame] | 43 | """Retrieves a config value for the specified key. |
| 44 | |
| 45 | @param config_key: The string key associated with the desired config value. |
Dan Shi | 9a535c9 | 2014-11-24 08:52:40 -0800 | [diff] [blame] | 46 | @param section: Section of global config to read config. Default is set to |
| 47 | AUTOTEST_WEB. |
Jakob Juelich | 934f0dc | 2014-10-14 18:21:13 -0700 | [diff] [blame] | 48 | @param **kwargs: Additional arguments to be passed to |
| 49 | global_config.get_config_value. |
| 50 | |
| 51 | @return: The config value, as returned by |
| 52 | global_config.global_config.get_config_value(). |
| 53 | """ |
Dan Shi | 9a535c9 | 2014-11-24 08:52:40 -0800 | [diff] [blame] | 54 | return config.get_config_value(section, config_key, **kwargs) |
Jakob Juelich | 934f0dc | 2014-10-14 18:21:13 -0700 | [diff] [blame] | 55 | |
| 56 | |
Dan Shi | 9a535c9 | 2014-11-24 08:52:40 -0800 | [diff] [blame] | 57 | def _get_global_config(config_key, default=config._NO_DEFAULT_SPECIFIED, |
| 58 | **kwargs): |
Jakob Juelich | 934f0dc | 2014-10-14 18:21:13 -0700 | [diff] [blame] | 59 | """Retrieves a global config value for the specified key. |
| 60 | |
| 61 | If the value can't be found, this will happen: |
| 62 | - if no default value was specified, and this is run on a shard instance, |
| 63 | a ConfigError will be raised. |
| 64 | - if a default value is set or this is run on a non-shard instancee, the |
| 65 | non-global value is returned |
| 66 | |
| 67 | @param config_key: The string key associated with the desired config value. |
| 68 | @param default: The default value to return if the value couldn't be looked |
| 69 | up; neither with global_db_ nor no prefix. |
| 70 | @param **kwargs: Additional arguments to be passed to |
| 71 | global_config.get_config_value. |
| 72 | |
| 73 | @return: The config value, as returned by |
| 74 | global_config.global_config.get_config_value(). |
| 75 | """ |
| 76 | try: |
| 77 | return _get_config('global_db_' + config_key, **kwargs) |
| 78 | except global_config.ConfigError: |
| 79 | if SHARD_HOSTNAME and default == config._NO_DEFAULT_SPECIFIED: |
| 80 | # When running on a shard, fail loudly if the global_db_ prefixed |
| 81 | # settings aren't present. |
| 82 | raise |
| 83 | return _get_config(config_key, default=default, **kwargs) |
| 84 | |
| 85 | |
| 86 | def _get_readonly_config(config_key, default=config._NO_DEFAULT_SPECIFIED, |
| 87 | **kwargs): |
| 88 | """Retrieves a readonly config value for the specified key. |
| 89 | |
| 90 | If no value can be found, the value of non readonly but global value |
| 91 | is returned instead. |
| 92 | |
| 93 | @param config_key: The string key associated with the desired config value. |
| 94 | @param default: The default value to return if the value couldn't be looked |
| 95 | up; neither with readonly_, global_db_ nor no prefix. |
| 96 | @param **kwargs: Additional arguments to be passed to |
| 97 | global_config.get_config_value. |
| 98 | |
| 99 | @return: The config value, as returned by |
| 100 | global_config.global_config.get_config_value(). |
| 101 | """ |
| 102 | try: |
| 103 | return _get_config('readonly_' + config_key, **kwargs) |
| 104 | except global_config.ConfigError: |
| 105 | return _get_global_config(config_key, default=default, **kwargs) |
| 106 | |
| 107 | |
Dan Shi | 9a535c9 | 2014-11-24 08:52:40 -0800 | [diff] [blame] | 108 | def _get_server_db_config(config_key, default=config._NO_DEFAULT_SPECIFIED, |
| 109 | **kwargs): |
| 110 | """Retrieves a config value for the specified key for server database. |
| 111 | |
Prashanth Balasubramanian | 144e98d | 2014-11-28 18:36:09 -0800 | [diff] [blame] | 112 | The order of searching for the specified config_key is: |
| 113 | section: AUTOTEST_SERVER_DB |
| 114 | section: AUTOTEST_WEB |
| 115 | supplied default |
Dan Shi | 9a535c9 | 2014-11-24 08:52:40 -0800 | [diff] [blame] | 116 | |
| 117 | @param config_key: The string key associated with the desired config value. |
| 118 | @param default: The default value to return if the value couldn't be looked |
| 119 | up; neither with global_db_ nor no prefix. |
| 120 | @param **kwargs: Additional arguments to be passed to |
| 121 | global_config.get_config_value. |
| 122 | |
| 123 | @return: The config value, as returned by |
| 124 | global_config.global_config.get_config_value(). |
| 125 | """ |
| 126 | try: |
Prashanth Balasubramanian | 144e98d | 2014-11-28 18:36:09 -0800 | [diff] [blame] | 127 | return _get_config(config_key, section='AUTOTEST_SERVER_DB', **kwargs) |
Dan Shi | 9a535c9 | 2014-11-24 08:52:40 -0800 | [diff] [blame] | 128 | except global_config.ConfigError: |
| 129 | return _get_config(config_key, default=default, **kwargs) |
| 130 | |
| 131 | |
Jakob Juelich | 934f0dc | 2014-10-14 18:21:13 -0700 | [diff] [blame] | 132 | def _get_database_config(getter): |
| 133 | """Create a configuration dictionary that can be passed to Django. |
| 134 | |
Dan Shi | 9a535c9 | 2014-11-24 08:52:40 -0800 | [diff] [blame] | 135 | @param getter: A function to call to get configuration values. |
Jakob Juelich | 934f0dc | 2014-10-14 18:21:13 -0700 | [diff] [blame] | 136 | |
| 137 | @return A dictionary that can be used in the Django DATABASES setting. |
| 138 | """ |
| 139 | config = { |
| 140 | 'ENGINE': 'autotest_lib.frontend.db.backends.afe', |
Prashanth Balasubramanian | 6a4cf37 | 2014-11-24 19:11:01 -0800 | [diff] [blame] | 141 | 'PORT': getter('port', default=''), |
Allen Li | f1e3584 | 2018-09-13 22:55:23 +0000 | [diff] [blame] | 142 | 'HOST': getter('host'), |
Jakob Juelich | 934f0dc | 2014-10-14 18:21:13 -0700 | [diff] [blame] | 143 | 'NAME': getter('database'), |
| 144 | 'USER': getter('user'), |
| 145 | 'PASSWORD': getter('password', default=''), |
| 146 | 'READONLY_HOST': getter('readonly_host', default=getter('host')), |
| 147 | 'READONLY_USER': getter('readonly_user', default=getter('user')), |
| 148 | } |
| 149 | if config['READONLY_USER'] != config['USER']: |
| 150 | config['READONLY_PASSWORD'] = getter('readonly_password', default='') |
| 151 | else: |
| 152 | config['READONLY_PASSWORD'] = config['PASSWORD'] |
| 153 | return config |
| 154 | |
| 155 | |
| 156 | def get_global_db_config(): |
| 157 | """Returns settings for the global database as required by django. |
| 158 | |
| 159 | @return: A dictionary that can be used in the Django DATABASES setting. |
| 160 | """ |
| 161 | return _get_database_config(getter=_get_global_config) |
| 162 | |
| 163 | |
| 164 | def get_default_db_config(): |
| 165 | """Returns settings for the default/local database as required by django. |
| 166 | |
| 167 | @return: A dictionary that can be used in the Django DATABASES setting. |
| 168 | """ |
| 169 | return _get_database_config(getter=_get_config) |
| 170 | |
| 171 | |
| 172 | def get_readonly_db_config(): |
| 173 | """Returns settings for the readonly database as required by django. |
| 174 | |
| 175 | @return: A dictionary that can be used in the Django DATABASES setting. |
| 176 | """ |
| 177 | return _get_database_config(getter=_get_readonly_config) |
Dan Shi | 9a535c9 | 2014-11-24 08:52:40 -0800 | [diff] [blame] | 178 | |
| 179 | |
| 180 | def get_server_db_config(): |
| 181 | """Returns settings for the server database as required by django. |
| 182 | |
| 183 | @return: A dictionary that can be used in the Django DATABASES setting. |
| 184 | """ |
| 185 | return _get_database_config(getter=_get_server_db_config) |