Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

274 lignes
8.2 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. # called from wnf.py
  4. # lib/wnf.py --install [rootpassword] [dbname] [source]
  5. from __future__ import unicode_literals
  6. import os, json, sys
  7. import frappe
  8. import frappe.database
  9. import getpass
  10. import importlib
  11. from frappe.model.db_schema import DbManager
  12. from frappe.model.sync import sync_for
  13. from frappe.utils.fixtures import sync_fixtures
  14. from frappe.website import render, statics
  15. def install_db(root_login="root", root_password=None, db_name=None, source_sql=None,
  16. admin_password=None, verbose=True, force=0, site_config=None, reinstall=False):
  17. make_conf(db_name, site_config=site_config)
  18. frappe.flags.in_install_db = True
  19. if reinstall:
  20. frappe.connect(db_name=db_name)
  21. dbman = DbManager(frappe.local.db)
  22. dbman.create_database(db_name)
  23. else:
  24. frappe.local.db = make_connection(root_login, root_password)
  25. frappe.local.session = frappe._dict({'user':'Administrator'})
  26. create_database_and_user(force, verbose)
  27. frappe.conf.admin_password = frappe.conf.admin_password or admin_password
  28. frappe.connect(db_name=db_name)
  29. check_if_ready_for_barracuda()
  30. import_db_from_sql(source_sql, verbose)
  31. remove_missing_apps()
  32. create_auth_table()
  33. frappe.flags.in_install_db = False
  34. def get_current_host():
  35. return frappe.db.sql("select user()")[0][0].split('@')[1]
  36. def create_database_and_user(force, verbose):
  37. db_name = frappe.local.conf.db_name
  38. dbman = DbManager(frappe.local.db)
  39. if force or (db_name not in dbman.get_database_list()):
  40. dbman.delete_user(db_name, get_current_host())
  41. dbman.drop_database(db_name)
  42. else:
  43. raise Exception("Database %s already exists" % (db_name,))
  44. dbman.create_user(db_name, frappe.conf.db_password, get_current_host())
  45. if verbose: print "Created user %s" % db_name
  46. dbman.create_database(db_name)
  47. if verbose: print "Created database %s" % db_name
  48. dbman.grant_all_privileges(db_name, db_name, get_current_host())
  49. dbman.flush_privileges()
  50. if verbose: print "Granted privileges to user %s and database %s" % (db_name, db_name)
  51. # close root connection
  52. frappe.db.close()
  53. def create_auth_table():
  54. frappe.db.sql_ddl("""create table if not exists __Auth (
  55. `user` VARCHAR(180) NOT NULL PRIMARY KEY,
  56. `password` VARCHAR(180) NOT NULL
  57. ) ENGINE=InnoDB DEFAULT CHARSET=utf8""")
  58. def import_db_from_sql(source_sql, verbose):
  59. if verbose: print "Starting database import..."
  60. db_name = frappe.conf.db_name
  61. if not source_sql:
  62. source_sql = os.path.join(os.path.dirname(frappe.__file__), 'data', 'Framework.sql')
  63. DbManager(frappe.local.db).restore_database(db_name, source_sql, db_name, frappe.conf.db_password)
  64. if verbose: print "Imported from database %s" % source_sql
  65. def make_connection(root_login, root_password):
  66. if root_login:
  67. if not root_password:
  68. root_password = frappe.conf.get("root_password") or None
  69. if not root_password:
  70. root_password = getpass.getpass("MySQL root password: ")
  71. return frappe.database.Database(user=root_login, password=root_password)
  72. def install_app(name, verbose=False, set_as_patched=True):
  73. frappe.clear_cache()
  74. app_hooks = frappe.get_hooks(app_name=name)
  75. installed_apps = frappe.get_installed_apps()
  76. # install pre-requisites
  77. if app_hooks.required_apps:
  78. for app in app_hooks.required_apps:
  79. install_app(app)
  80. print "Installing {0}...".format(name)
  81. frappe.flags.in_install = name
  82. frappe.clear_cache()
  83. if name not in frappe.get_all_apps(with_frappe=True):
  84. raise Exception("App not in apps.txt")
  85. if name in installed_apps:
  86. print "Already installed"
  87. frappe.msgprint("App {0} already installed".format(name))
  88. return
  89. if name != "frappe":
  90. frappe.only_for("System Manager")
  91. for before_install in app_hooks.before_install or []:
  92. frappe.get_attr(before_install)()
  93. if name != "frappe":
  94. add_module_defs(name)
  95. sync_for(name, force=True, sync_everything=True, verbose=verbose)
  96. add_to_installed_apps(name)
  97. if set_as_patched:
  98. set_all_patches_as_completed(name)
  99. for after_install in app_hooks.after_install or []:
  100. frappe.get_attr(after_install)()
  101. print "Installing fixtures..."
  102. sync_fixtures(name)
  103. frappe.flags.in_install = False
  104. def add_to_installed_apps(app_name, rebuild_website=True):
  105. installed_apps = frappe.get_installed_apps()
  106. if not app_name in installed_apps:
  107. installed_apps.append(app_name)
  108. frappe.db.set_global("installed_apps", json.dumps(installed_apps))
  109. frappe.db.commit()
  110. post_install(rebuild_website)
  111. def remove_from_installed_apps(app_name):
  112. installed_apps = frappe.get_installed_apps()
  113. if app_name in installed_apps:
  114. installed_apps.remove(app_name)
  115. frappe.db.set_global("installed_apps", json.dumps(installed_apps))
  116. frappe.db.commit()
  117. if frappe.flags.in_install:
  118. post_install()
  119. def post_install(rebuild_website=False):
  120. if rebuild_website:
  121. render.clear_cache()
  122. statics.sync().start()
  123. init_singles()
  124. frappe.db.commit()
  125. frappe.clear_cache()
  126. def set_all_patches_as_completed(app):
  127. patch_path = os.path.join(frappe.get_pymodule_path(app), "patches.txt")
  128. if os.path.exists(patch_path):
  129. for patch in frappe.get_file_items(patch_path):
  130. frappe.get_doc({
  131. "doctype": "Patch Log",
  132. "patch": patch
  133. }).insert()
  134. frappe.db.commit()
  135. def init_singles():
  136. singles = [single['name'] for single in frappe.get_all("DocType", filters={'issingle': True})]
  137. for single in singles:
  138. if not frappe.db.get_singles_dict(single):
  139. doc = frappe.new_doc(single)
  140. doc.flags.ignore_mandatory=True
  141. doc.flags.ignore_validate=True
  142. doc.save()
  143. def make_conf(db_name=None, db_password=None, site_config=None):
  144. site = frappe.local.site
  145. make_site_config(db_name, db_password, site_config)
  146. sites_path = frappe.local.sites_path
  147. frappe.destroy()
  148. frappe.init(site, sites_path=sites_path)
  149. def make_site_config(db_name=None, db_password=None, site_config=None):
  150. frappe.create_folder(os.path.join(frappe.local.site_path))
  151. site_file = os.path.join(frappe.local.site_path, "site_config.json")
  152. if not os.path.exists(site_file):
  153. if not (site_config and isinstance(site_config, dict)):
  154. site_config = get_conf_params(db_name, db_password)
  155. with open(site_file, "w") as f:
  156. f.write(json.dumps(site_config, indent=1, sort_keys=True))
  157. def get_conf_params(db_name=None, db_password=None):
  158. if not db_name:
  159. db_name = raw_input("Database Name: ")
  160. if not db_name:
  161. raise Exception("Database Name Required")
  162. if not db_password:
  163. from frappe.utils import random_string
  164. db_password = random_string(16)
  165. return {"db_name": db_name, "db_password": db_password}
  166. def make_site_dirs():
  167. site_public_path = os.path.join(frappe.local.site_path, 'public')
  168. site_private_path = os.path.join(frappe.local.site_path, 'private')
  169. for dir_path in (
  170. os.path.join(site_private_path, 'backups'),
  171. os.path.join(site_public_path, 'files')):
  172. if not os.path.exists(dir_path):
  173. os.makedirs(dir_path)
  174. locks_dir = frappe.get_site_path('locks')
  175. if not os.path.exists(locks_dir):
  176. os.makedirs(locks_dir)
  177. def add_module_defs(app):
  178. modules = frappe.get_module_list(app)
  179. for module in modules:
  180. d = frappe.new_doc("Module Def")
  181. d.app_name = app
  182. d.module_name = module
  183. d.save()
  184. def remove_missing_apps():
  185. apps = ('frappe_subscription', 'shopping_cart')
  186. installed_apps = json.loads(frappe.db.get_global("installed_apps") or "[]")
  187. for app in apps:
  188. if app in installed_apps:
  189. try:
  190. importlib.import_module(app)
  191. except ImportError:
  192. installed_apps.remove(app)
  193. frappe.db.set_global("installed_apps", json.dumps(installed_apps))
  194. def check_if_ready_for_barracuda():
  195. mariadb_variables = frappe._dict(frappe.db.sql("""show variables"""))
  196. for key, value in {
  197. "innodb_file_format": "Barracuda",
  198. "innodb_file_per_table": "ON",
  199. "innodb_large_prefix": "ON",
  200. "character_set_server": "utf8mb4",
  201. "collation_server": "utf8mb4_unicode_ci"
  202. }.items():
  203. if mariadb_variables.get(key) != value:
  204. print "="*80
  205. print "Please add this to MariaDB's my.cnf and restart MariaDB before proceeding"
  206. print
  207. print expected_config_for_barracuda
  208. print "="*80
  209. sys.exit(1)
  210. # raise Exception, "MariaDB needs to be configured!"
  211. expected_config_for_barracuda = """[mysqld]
  212. innodb-file-format=barracuda
  213. innodb-file-per-table=1
  214. innodb-large-prefix=1
  215. character-set-client-handshake = FALSE
  216. character-set-server = utf8mb4
  217. collation-server = utf8mb4_unicode_ci
  218. [mysql]
  219. default-character-set = utf8mb4
  220. """