Sanity-check database before running upgrades (#6982)

Some of the database deltas rely on `config.server_name` being set correctly,
so we should check that it is before running the deltas.

Fixes #6870.
This commit is contained in:
Richard van der Hoff 2020-02-25 17:46:00 +00:00 committed by GitHub
parent bbf8886a05
commit e66f099ca9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 17 deletions

1
changelog.d/6982.feature Normal file
View file

@ -0,0 +1 @@
Check that server_name is correctly set before running database updates.

View file

@ -20,6 +20,7 @@ import logging
import time import time
from synapse.api.constants import PresenceState from synapse.api.constants import PresenceState
from synapse.config.homeserver import HomeServerConfig
from synapse.storage.database import Database from synapse.storage.database import Database
from synapse.storage.engines import PostgresEngine from synapse.storage.engines import PostgresEngine
from synapse.storage.util.id_generators import ( from synapse.storage.util.id_generators import (
@ -117,16 +118,6 @@ class DataStore(
self._clock = hs.get_clock() self._clock = hs.get_clock()
self.database_engine = database.engine self.database_engine = database.engine
all_users_native = are_all_users_on_domain(
db_conn.cursor(), database.engine, hs.hostname
)
if not all_users_native:
raise Exception(
"Found users in database not native to %s!\n"
"You cannot changed a synapse server_name after it's been configured"
% (hs.hostname,)
)
self._stream_id_gen = StreamIdGenerator( self._stream_id_gen = StreamIdGenerator(
db_conn, db_conn,
"events", "events",
@ -567,13 +558,26 @@ class DataStore(
) )
def are_all_users_on_domain(txn, database_engine, domain): def check_database_before_upgrade(cur, database_engine, config: HomeServerConfig):
"""Called before upgrading an existing database to check that it is broadly sane
compared with the configuration.
"""
domain = config.server_name
sql = database_engine.convert_param_style( sql = database_engine.convert_param_style(
"SELECT COUNT(*) FROM users WHERE name NOT LIKE ?" "SELECT COUNT(*) FROM users WHERE name NOT LIKE ?"
) )
pat = "%:" + domain pat = "%:" + domain
txn.execute(sql, (pat,)) cur.execute(sql, (pat,))
num_not_matching = txn.fetchall()[0][0] num_not_matching = cur.fetchall()[0][0]
if num_not_matching == 0: if num_not_matching == 0:
return True return
return False
raise Exception(
"Found users in database not native to %s!\n"
"You cannot changed a synapse server_name after it's been configured"
% (domain,)
)
__all__ = ["DataStore", "check_database_before_upgrade"]

View file

@ -278,13 +278,17 @@ def _upgrade_existing_database(
the current_version wasn't generated by applying those delta files. the current_version wasn't generated by applying those delta files.
database_engine (DatabaseEngine) database_engine (DatabaseEngine)
config (synapse.config.homeserver.HomeServerConfig|None): config (synapse.config.homeserver.HomeServerConfig|None):
application config, or None if we are connecting to an existing None if we are initialising a blank database, otherwise the application
database which we expect to be configured already config
data_stores (list[str]): The names of the data stores to instantiate data_stores (list[str]): The names of the data stores to instantiate
on the given database. on the given database.
is_empty (bool): Is this a blank database? I.e. do we need to run the is_empty (bool): Is this a blank database? I.e. do we need to run the
upgrade portions of the delta scripts. upgrade portions of the delta scripts.
""" """
if is_empty:
assert not applied_delta_files
else:
assert config
if current_version > SCHEMA_VERSION: if current_version > SCHEMA_VERSION:
raise ValueError( raise ValueError(
@ -292,6 +296,13 @@ def _upgrade_existing_database(
+ "new for the server to understand" + "new for the server to understand"
) )
# some of the deltas assume that config.server_name is set correctly, so now
# is a good time to run the sanity check.
if not is_empty and "main" in data_stores:
from synapse.storage.data_stores.main import check_database_before_upgrade
check_database_before_upgrade(cur, database_engine, config)
start_ver = current_version start_ver = current_version
if not upgraded: if not upgraded:
start_ver += 1 start_ver += 1