blob: c5866dc67a6f400cdf73da36f600c999e1a1abef [file] [log] [blame]
Jakob Juelich8a764d12014-10-14 19:24:21 -07001# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Django database Router
6
7Django gets configured with three database connections in frontend/settings.py.
8- The default database
9 - This database should be used for most things.
10 - For the master, this is the global database.
11 - For shards, this this is the shard-local database.
12- The global database
13 - For the master, this is the same database as default, which is the global
14 database.
15 - For the shards, this is the global database (the same as for the master).
16- The readonly connection
17 - This should be the same database as the global database, but it should
18 use an account on the database that only has readonly permissions.
Dan Shi9a535c92014-11-24 08:52:40 -080019- The server database
20 - This is the database stores information about all servers in the Autotest
21 instance. Each instance, master or shard should have its own server
22 database is use_server_db is enabled in global config.
Jakob Juelich8a764d12014-10-14 19:24:21 -070023
24The reason shards need two distinct databases for different objects is, that
25the tko parser should always write to the global database. Otherwise test
26results wouldn't be synced back to the master and would not be accessible in one
27place.
28
Dan Shi9a535c92014-11-24 08:52:40 -080029Therefore this class will route all queries for tables starts with `server`
30prefix to server database, route all queries for tables that involve
31`tko_`-prefixed tables to the global database. For all others this router will
32not give a hint, which means the default database will be used.
Jakob Juelich8a764d12014-10-14 19:24:21 -070033"""
34
35class Router(object):
36 """
37 Decide if an object should be written to the default or to the global db.
38
39 This is an implementaton of Django's multi-database router interface:
40 https://docs.djangoproject.com/en/1.5/topics/db/multi-db/
41 """
42
Dan Shi9a535c92014-11-24 08:52:40 -080043 def _should_be_in_server_db(self, model):
44 """Return True if the model should be stored in the server db.
45
46 @param model: Model to decide for.
47
48 @return: True if querying the model requires server database.
49 """
50 return model._meta.db_table.startswith('server')
51
52
Jakob Juelich8a764d12014-10-14 19:24:21 -070053 def _should_be_in_global(self, model):
54 """Returns True if the model should be stored in the global db.
55
56 @param model: Model to decide for.
57
58 @return: True if querying the model requires global database.
59 """
60 return model._meta.db_table.startswith('tko_')
61
62
63 def db_for_read(self, model, **hints):
Dan Shi9a535c92014-11-24 08:52:40 -080064 """Return the database for a reading access.
Jakob Juelich8a764d12014-10-14 19:24:21 -070065
66 @param model: Model to decide for.
67 @param hints: Optional arguments to determine which database for read.
68
Dan Shi9a535c92014-11-24 08:52:40 -080069 @returns: 'server' for all server models. 'global' for all tko models,
70 None otherwise. None means the router doesn't have an opinion.
Jakob Juelich8a764d12014-10-14 19:24:21 -070071 """
Dan Shi9a535c92014-11-24 08:52:40 -080072 if self._should_be_in_server_db(model):
73 return 'server'
Jakob Juelich8a764d12014-10-14 19:24:21 -070074 if self._should_be_in_global(model):
75 return 'global'
76 return None
77
78
79 def db_for_write(self, model, **hints):
Dan Shi9a535c92014-11-24 08:52:40 -080080 """Return the database for a writing access.
Jakob Juelich8a764d12014-10-14 19:24:21 -070081
82 @param model: Model to decide for.
83 @param hints: Optional arguments to determine which database for write.
84
Dan Shi9a535c92014-11-24 08:52:40 -080085 @returns: 'server' for all server models. 'global' for all tko models,
86 None otherwise. None means the router doesn't have an opinion.
Jakob Juelich8a764d12014-10-14 19:24:21 -070087 """
Dan Shi9a535c92014-11-24 08:52:40 -080088 if self._should_be_in_server_db(model):
89 return 'server'
Jakob Juelich8a764d12014-10-14 19:24:21 -070090 if self._should_be_in_global(model):
91 return 'global'
92 return None
93
94
95 def allow_relation(self, obj1, obj2, **hints):
96 """
97 Allow relations only if either both are in tko_ tables or none is.
98
99 @param obj1: First object involved in the relation.
100 @param obj2: Second object involved in the relation.
101 @param hints: Optional arguments to determine if relation is allowed.
102
103 @returns False, if the relation should be prohibited,
104 None, if the router doesn't have an opinion.
105 """
Dan Shi9a535c92014-11-24 08:52:40 -0800106 if (not self._should_be_in_server_db(type(obj1)) ==
107 self._should_be_in_server_db(type(obj2))):
108 return False
Jakob Juelich8a764d12014-10-14 19:24:21 -0700109 if (not self._should_be_in_global(type(obj1)) ==
110 self._should_be_in_global(type(obj2))):
111 return False
112 return None