1
0

update_synapse_database 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #!/usr/bin/env python
  2. # Copyright 2019 The Matrix.org Foundation C.I.C.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import argparse
  16. import logging
  17. import sys
  18. import yaml
  19. from twisted.internet import defer, reactor
  20. import synapse
  21. from synapse.config.homeserver import HomeServerConfig
  22. from synapse.metrics.background_process_metrics import run_as_background_process
  23. from synapse.server import HomeServer
  24. from synapse.storage import DataStore
  25. from synapse.util.versionstring import get_version_string
  26. logger = logging.getLogger("update_database")
  27. class MockHomeserver(HomeServer):
  28. DATASTORE_CLASS = DataStore
  29. def __init__(self, config, **kwargs):
  30. super(MockHomeserver, self).__init__(
  31. config.server.server_name, reactor=reactor, config=config, **kwargs
  32. )
  33. self.version_string = "Synapse/" + get_version_string(synapse)
  34. def run_background_updates(hs):
  35. store = hs.get_datastore()
  36. async def run_background_updates():
  37. await store.db_pool.updates.run_background_updates(sleep=False)
  38. # Stop the reactor to exit the script once every background update is run.
  39. reactor.stop()
  40. def run():
  41. # Apply all background updates on the database.
  42. defer.ensureDeferred(
  43. run_as_background_process("background_updates", run_background_updates)
  44. )
  45. reactor.callWhenRunning(run)
  46. reactor.run()
  47. def main():
  48. parser = argparse.ArgumentParser(
  49. description=(
  50. "Updates a synapse database to the latest schema and optionally runs background updates"
  51. " on it."
  52. )
  53. )
  54. parser.add_argument("-v", action="store_true")
  55. parser.add_argument(
  56. "--database-config",
  57. type=argparse.FileType("r"),
  58. required=True,
  59. help="Synapse configuration file, giving the details of the database to be updated",
  60. )
  61. parser.add_argument(
  62. "--run-background-updates",
  63. action="store_true",
  64. required=False,
  65. help="run background updates after upgrading the database schema",
  66. )
  67. args = parser.parse_args()
  68. logging_config = {
  69. "level": logging.DEBUG if args.v else logging.INFO,
  70. "format": "%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s",
  71. }
  72. logging.basicConfig(**logging_config)
  73. # Load, process and sanity-check the config.
  74. hs_config = yaml.safe_load(args.database_config)
  75. if "database" not in hs_config:
  76. sys.stderr.write("The configuration file must have a 'database' section.\n")
  77. sys.exit(4)
  78. config = HomeServerConfig()
  79. config.parse_config_dict(hs_config, "", "")
  80. # Instantiate and initialise the homeserver object.
  81. hs = MockHomeserver(config)
  82. # Setup instantiates the store within the homeserver object and updates the
  83. # DB.
  84. hs.setup()
  85. if args.run_background_updates:
  86. run_background_updates(hs)
  87. if __name__ == "__main__":
  88. main()