PageRenderTime 34ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 1ms

/silversupport/service/mysql.py

https://bitbucket.org/ianb/silverlining/
Python | 172 lines | 160 code | 10 blank | 2 comment | 8 complexity | 36ff1629cc9253f06823fa04ede6b260 MD5 | raw file
Possible License(s): GPL-2.0
  1. """MySQL support"""
  2. import os
  3. import sys
  4. from silversupport.shell import run
  5. from silversupport.abstractservice import AbstractService
  6. class Service(AbstractService):
  7. packages = [
  8. 'mysql-server-5.1',
  9. 'mysql-client-5.1',
  10. 'python-mysqldb',
  11. ]
  12. platform_packages = dict(
  13. python=['python-mysqldb'],
  14. php=['php5-mysql'],
  15. )
  16. def install(self):
  17. if not os.path.exists('/usr/bin/mysqld_multi'):
  18. self.install_packages()
  19. run(['/usr/bin/mysql', '-u', 'root',
  20. '-e', 'CREATE USER wwwmgr'])
  21. if self.app_config.platform == 'php':
  22. # We need to restart Apache after installing php5-mysql
  23. run(['/etc/init.d/apache2', 'restart'])
  24. app_name = self.app_config.app_name
  25. stdout, stderr, returncode = run(
  26. ['/usr/bin/mysql', '-u', 'root',
  27. '-e', 'SHOW DATABASES', '--batch', '-s'],
  28. capture_stdout=True)
  29. databases = [l.strip() for l in stdout.splitlines() if l.strip()]
  30. if app_name in databases:
  31. self.output('Database %s already exists' % app_name)
  32. else:
  33. self.output('Database %s does not exist; creating.' % app_name)
  34. run(['/usr/bin/mysql', '-u', 'root',
  35. '-e', 'CREATE DATABASE %s' % app_name])
  36. run(['/usr/bin/mysql', '-u', 'root',
  37. '-e', "GRANT ALL ON %s.* TO 'wwwmgr'@'localhost'" % app_name])
  38. def env_setup(self):
  39. environ = {}
  40. app_name = self.app_config.app_name
  41. platform = self.app_config.platform
  42. if not self.devel:
  43. environ['CONFIG_MYSQL_DBNAME'] = app_name
  44. environ['CONFIG_MYSQL_USER'] = 'wwwmgr'
  45. environ['CONFIG_MYSQL_PASSWORD'] = ''
  46. if platform == 'php':
  47. environ['CONFIG_MYSQL_HOST'] = 'localhost'
  48. else:
  49. environ['CONFIG_MYSQL_HOST'] = ''
  50. environ['CONFIG_MYSQL_PORT'] = ''
  51. if platform == 'python':
  52. environ['CONFIG_MYSQL_SQLALCHEMY'] = 'mysql://wwwmgr@/%s' % app_name
  53. else:
  54. environ['CONFIG_MYSQL_DBNAME'] = app_name
  55. environ['CONFIG_MYSQL_USER'] = 'root'
  56. environ['CONFIG_MYSQL_PASSWORD'] = ''
  57. environ['CONFIG_MYSQL_HOST'] = ''
  58. environ['CONFIG_MYSQL_PORT'] = ''
  59. for name, value in self.devel_config.items():
  60. if name.startswith('mysql.'):
  61. name = name[len('mysql.'):]
  62. environ['CONFIG_MYSQL_%s' % name.upper()] = value
  63. sa = 'mysql://'
  64. if environ.get('CONFIG_MYSQL_USER'):
  65. sa += environ['CONFIG_MYSQL_USER']
  66. if environ.get('CONFIG_MYSQL_PASSWORD'):
  67. sa += ':' + environ['CONFIG_MYSQL_PASSWORD']
  68. sa += '@'
  69. if environ.get('CONFIG_MYSQL_HOST'):
  70. ## FIXME: should this check for 'localhost', which SA actually doesn't like?
  71. sa += environ['CONFIG_MYSQL_HOST']
  72. if environ.get('CONFIG_MYSQL_PORT'):
  73. sa += ':' + environ['CONFIG_MYSQL_PORT']
  74. sa += '/' + environ['CONFIG_MYSQL_DBNAME']
  75. environ['CONFIG_MYSQL_SQLALCHEMY'] = sa
  76. return environ
  77. def backup(self, output_dir):
  78. outfile = os.path.join(output_dir, 'mysql.dump')
  79. run(["mysqldump"] + self.mysql_options() + ['--result-file', outfile])
  80. fp = open(os.path.join(output_dir, 'README.txt'), 'w')
  81. fp.write(self.BACKUP_README)
  82. fp.close()
  83. BACKUP_README = """\
  84. The file mysql.dump was created with mysqldump; you can pip it into
  85. mysql to restore.
  86. """
  87. def restore(self, input_dir):
  88. input_file = os.path.join(input_dir, 'mysql.dump')
  89. fp = open(input_file)
  90. content = fp.read()
  91. fp.close()
  92. run(['mysql'] + self.mysql_options() + ['--silent'],
  93. stdin=content)
  94. def mysql_options(self):
  95. environ = self.env
  96. options = []
  97. options.append('--user=%s' % environ['CONFIG_MYSQL_USER'])
  98. for option, key in [('password', 'PASSWORD'),
  99. ('user', 'USER'),
  100. ('host', 'HOST'),
  101. ('port', 'PORT')]:
  102. if environ.get('CONFIG_MYSQL_%s' % key):
  103. options.append('--%s=%s' % (option, environ['CONFIG_MYSQL_%s' % key]))
  104. options.append(environ['CONFIG_MYSQL_DBNAME'])
  105. return options
  106. def clear(self):
  107. run(["mysql"] + self.mysql_options(),
  108. stdin='DROP DATABASE %s' % self.env['CONFIG_MYSQL_DBNAME'])
  109. self.install()
  110. self.output('Cleared database %s' % self.env['CONFIG_MYSQL_DBNAME'])
  111. def check_setup(self):
  112. try:
  113. import MySQLdb
  114. except ImportError:
  115. return 'Cannot import MySQLdb (cannot check database)'
  116. kw = {}
  117. for envname, kwname in [
  118. ('CONFIG_MYSQL_HOST', 'host'),
  119. ('CONFIG_MYSQL_USER', 'user'),
  120. ('CONFIG_MYSQL_PASSWORD', 'passwd'),
  121. ('CONFIG_MYSQL_DBNAME', 'db'),
  122. ('CONFIG_MYSQL_PORT', 'port'),
  123. ]:
  124. if self.env.get(envname):
  125. kw[kwname] = self.env[envname]
  126. try:
  127. MySQLdb.connect(**kw)
  128. except MySQLdb.OperationalError, e:
  129. exc_info = sys.exc_info()
  130. try:
  131. code = int(e.args[0])
  132. except:
  133. raise exc_info[0], exc_info[1], exc_info[2]
  134. if code == 1049:
  135. dbname = self.env['CONFIG_MYSQL_DBNAME']
  136. result = ['No database by the name %s exists' % dbname]
  137. result.append(
  138. 'To fix this run:')
  139. result.append(
  140. ' echo "CREATE DATABASE %s; GRANT ALL ON %s.* TO %s@localhost" | mysql -u root -p '
  141. % (dbname, dbname, self.env['CONFIG_MYSQL_USER']))
  142. return '\n'.join(result)
  143. raise
  144. def mysql_connect(**kw):
  145. """Connect to the configured database, returning a DBAPI/MySQLdb
  146. connection object."""
  147. import MySQLdb
  148. for environ_name, kw_name in [('CONFIG_MYSQL_HOST', 'host'),
  149. ('CONFIG_MYSQL_USER', 'user'),
  150. ('CONFIG_MYSQL_DBNAME', 'db'),
  151. ('CONFIG_MYSQL_PASSWORD', 'passwd'),
  152. ]:
  153. if os.environ.get(environ_name):
  154. kw.setdefault(kw_name, os.environ[environ_name])
  155. db = MySQLdb.connect(**kw)
  156. return db