PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/silversupport/service/postgresql.py

https://bitbucket.org/ianb/silverlining/
Python | 125 lines | 113 code | 11 blank | 1 comment | 10 complexity | 6f5c06f1e4f04628bfd3c74e3ed16895 MD5 | raw file
Possible License(s): GPL-2.0
  1. import os
  2. from silversupport.shell import run, overwrite_file
  3. from silversupport.abstractservice import AbstractService
  4. class Service(AbstractService):
  5. packages = [
  6. 'postgresql-8.4',
  7. 'postgresql-client',
  8. 'postgresql-client-8.4',
  9. 'postgresql-client-common',
  10. 'postgresql-common',
  11. ]
  12. platform_packages = dict(
  13. python=[
  14. 'python-psycopg2',
  15. 'python-egenix-mxdatetime',
  16. 'python-egenix-mxtools',
  17. ],
  18. php=[
  19. 'php5-pgsql',
  20. ])
  21. def install(self):
  22. if not os.path.exists('/usr/bin/psql'):
  23. self.install_packages()
  24. overwrite_file('/etc/postgresql/8.4/main/pg_hba.conf',
  25. source_file=os.path.join(os.path.dirname(__file__),
  26. 'postgresql-pg_hba.conf'))
  27. run(['chown', 'postgres:postgres',
  28. '/etc/postgresql/8.4/main/pg_hba.conf'])
  29. run(['/etc/init.d/postgresql-8.4', 'restart'])
  30. stdout, stderr, returncode = run(
  31. ['psql', '-U', 'postgres', '--tuples-only'],
  32. capture_stdout=True, capture_stderr=True,
  33. stdin="select r.rolname from pg_catalog.pg_roles as r;")
  34. if 'www-mgr' not in stdout:
  35. run(['createuser', '-U', 'postgres',
  36. '--no-superuser', '--no-createdb',
  37. '--no-createrole', 'www-mgr'])
  38. app_name = self.app_config.app_name
  39. stdout, stderr, returncode = run(
  40. ['/usr/bin/psql', '-U', 'postgres', '-l', '-t', '-A'],
  41. capture_stdout=True)
  42. databases = [line.split('|')[0] for line in stdout.splitlines()]
  43. if app_name in databases:
  44. self.output('Database %s already exists' % app_name)
  45. else:
  46. self.output('Database %s does not exist; creating.' % app_name)
  47. run(['createdb', '-U', 'postgres', '-O', 'www-mgr',
  48. app_name])
  49. def env_setup(self):
  50. environ = {}
  51. app_name = self.app_config.app_name
  52. if not self.devel:
  53. environ['CONFIG_PG_DBNAME'] = app_name
  54. environ['CONFIG_PG_USER'] = 'www-mgr'
  55. environ['CONFIG_PG_PASSWORD'] = ''
  56. environ['CONFIG_PG_HOST'] = ''
  57. environ['CONFIG_PG_PORT'] = ''
  58. environ['CONFIG_PG_SQLALCHEMY'] = 'postgres://postgres@/%s' % app_name
  59. else:
  60. import getpass
  61. environ['CONFIG_PG_DBNAME'] = app_name
  62. environ['CONFIG_PG_USER'] = getpass.getuser()
  63. environ['CONFIG_PG_PASSWORD'] = ''
  64. environ['CONFIG_PG_HOST'] = ''
  65. environ['CONFIG_PG_PORT'] = ''
  66. for name, value in self.devel_config.items():
  67. if name.startswith('postgis.'):
  68. name = name[len('postgis.'):]
  69. environ['CONFIG_PG_%s' % name.upper()] = value
  70. sa = 'postgres://'
  71. if environ.get('CONFIG_PG_USER'):
  72. sa += environ['CONFIG_PG_USER']
  73. if environ.get('CONFIG_PG_PASSWORD'):
  74. sa += ':' + environ['CONFIG_PG_PASSWORD']
  75. sa += '@'
  76. if environ.get('CONFIG_PG_HOST'):
  77. ## FIXME: should this check for 'localhost', which SA actually doesn't like?
  78. sa += environ['CONFIG_PG_HOST']
  79. if environ.get('CONFIG_PG_PORT'):
  80. sa += ':' + environ['CONFIG_PG_PORT']
  81. sa += '/' + environ['CONFIG_PG_DBNAME']
  82. environ['CONFIG_PG_SQLALCHEMY'] = sa
  83. return environ
  84. def cli_options(self, force_user=None):
  85. if not force_user:
  86. force_user = self.env['CONFIG_PG_USER']
  87. options = ['-U', force_user]
  88. if self.env.get('CONFIG_PG_HOST'):
  89. options.extend(['--host', self.env['CONFIG_PG_HOST']])
  90. if self.env.get('CONFIG_PG_PORT'):
  91. options.extend(['--port', self.env['CONFIG_PG_PORT']])
  92. return options
  93. def backup(self, output_dir):
  94. ## FIXME: this includes a bunch of nonsense
  95. run(['pg_dump', '--format=custom', '--no-owner', '--no-acl', '--no-privileges']
  96. + self.cli_options('postgres')
  97. + [self.env['CONFIG_PG_DBNAME'], '--file', os.path.join(output_dir, 'postgis.pgdump')])
  98. fp = open(os.path.join(output_dir, 'postgis.README.txt'), 'w')
  99. fp.write(self.BACKUP_README)
  100. fp.close()
  101. BACKUP_README = """\
  102. The backup is created by pg_dump -Fc. To restore it use pg_restore.
  103. """
  104. def restore(self, input_dir):
  105. path = os.path.join(input_dir, 'postgis.pgdump')
  106. dbname = self.env['CONFIG_PG_DBNAME']
  107. run(['pg_restore'] + self.cli_options('postgres') + ['--dbname', dbname, path])
  108. def clear(self):
  109. dbname = self.env['CONFIG_PG_DBNAME']
  110. ## FIXME: -U etc?
  111. run(['dropdb'] + self.cli_options('postgres') + [dbname])
  112. self.install()