# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Django database Router Django gets configured with three database connections in frontend/settings.py. - The default database - This database should be used for most things. - For the main, this is the global database. - For shards, this this is the shard-local database. - The global database - For the main, this is the same database as default, which is the global database. - For the shards, this is the global database (the same as for the main). - The readonly connection - This should be the same database as the global database, but it should use an account on the database that only has readonly permissions. - The server database - This is the database stores information about all servers in the Autotest instance. Each instance, main or shard should have its own server database is use_server_db is enabled in global config. The reason shards need two distinct databases for different objects is, that the tko parser should always write to the global database. Otherwise test results wouldn't be synced back to the main and would not be accessible in one place. Therefore this class will route all queries for tables starts with `server` prefix to server database, route all queries for tables that involve `tko_`-prefixed tables to the global database. For all others this router will not give a hint, which means the default database will be used. """ class Router(object): """ Decide if an object should be written to the default or to the global db. This is an implementaton of Django's multi-database router interface: https://docs.djangoproject.com/en/1.5/topics/db/multi-db/ """ def _should_be_in_server_db(self, model): """Return True if the model should be stored in the server db. @param model: Model to decide for. @return: True if querying the model requires server database. """ return model._meta.db_table.startswith('server') def _should_be_in_global(self, model): """Returns True if the model should be stored in the global db. @param model: Model to decide for. @return: True if querying the model requires global database. """ return model._meta.db_table.startswith('tko_') def db_for_read(self, model, **hints): """Return the database for a reading access. @param model: Model to decide for. @param hints: Optional arguments to determine which database for read. @returns: 'server' for all server models. 'global' for all tko models, None otherwise. None means the router doesn't have an opinion. """ if self._should_be_in_server_db(model): return 'server' if self._should_be_in_global(model): return 'global' return None def db_for_write(self, model, **hints): """Return the database for a writing access. @param model: Model to decide for. @param hints: Optional arguments to determine which database for write. @returns: 'server' for all server models. 'global' for all tko models, None otherwise. None means the router doesn't have an opinion. """ if self._should_be_in_server_db(model): return 'server' if self._should_be_in_global(model): return 'global' return None def allow_relation(self, obj1, obj2, **hints): """ Allow relations only if either both are in tko_ tables or none is. @param obj1: First object involved in the relation. @param obj2: Second object involved in the relation. @param hints: Optional arguments to determine if relation is allowed. @returns False, if the relation should be prohibited, None, if the router doesn't have an opinion. """ if (not self._should_be_in_server_db(type(obj1)) == self._should_be_in_server_db(type(obj2))): return False if (not self._should_be_in_global(type(obj1)) == self._should_be_in_global(type(obj2))): return False return None