No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

fs_utils.py 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. ##@brief This module contains usefull functions to handle lodelsites on FS
  2. import os
  3. import os.path
  4. import shutil
  5. from lodel.context import LodelContext
  6. from lodel import buildconf #No need to protect it in Contexts
  7. LodelContext.expose_modules(globals(), {
  8. 'lodel.logger' : 'logger',
  9. 'lodel.plugin.datasource_plugin': ['AbstractDatasource', 'DatasourcePlugin'],
  10. 'lodel.exceptions': ['LodelFatalError'],
  11. 'lodel.settings': ['Settings']})
  12. from .exceptions import *
  13. LODELSITE_DATA_PATH, LODELSITE_CONTEXTS_PATH = LodelContext.lodelsites_paths()
  14. ##@brief Define directories architecture
  15. #
  16. #@note useless because a lot of those stuff would be hardcoded
  17. LODELSITE_INSTALL_MODEL = {
  18. 'datas' : ['uploads', 'conf.d'], #For datadir
  19. 'ctx': ['leapi_dyncode'] #for context dir
  20. }
  21. CONF_MODELS = os.path.join(os.path.dirname(__file__),'model_conf.d/')
  22. CONF_AUTOCONF_FILENAME = 'lodelsites_autoconfig.ini'
  23. ##@brief Util function that returns both datadir and contextdir paths
  24. #@param name str : the site shortname
  25. #@return a tuple (datadir, contextdir)
  26. def name2path(name):
  27. return (os.path.join(LODELSITE_DATA_PATH, name),
  28. os.path.join(LODELSITE_CONTEXTS_PATH, name))
  29. ##@brief Util function that indicates if a site exists or not
  30. #
  31. #This function only checks that both paths returned by name2path are
  32. #existing directories
  33. #@param name str : site shortname
  34. #@return a bool
  35. #@throws LodelSiteDatasourceInconsistency if inconsistency detected on FS
  36. def site_exists(name):
  37. paths = name2paths(name)
  38. if name == Settings.sitename:
  39. msg = 'Site shortname "%s" is conflicting with the Lodelsites instance name' % name
  40. raise LodelSiteDatasourceError(msg)
  41. for path in paths:
  42. if os.path.isfile(path):
  43. msg = 'Will trying to determine if a lodesite "%s" exists we \
  44. found that "%s" is a file, but a directory was expected' % (name, path)
  45. raise LodelSiteDatasourceInconsistency(msg)
  46. res = [False, False]
  47. res = [os.path.isdir(paths[0]),
  48. os.path.isdir(paths[1])]
  49. if res[0] != res[1]:
  50. msg = 'Inconsistency detected on filesystem will trying to determine \
  51. wether a lodelsite exists or not : '
  52. if res[0]:
  53. msg += 'datadir was found but no contextdir'
  54. else:
  55. msg += 'contextdir found but no datadir'
  56. raise LodelSiteDatasourceInconsistency(msg)
  57. return res[0]
  58. ##@brief Create sites directory on filesystem
  59. #@param name str : site shortname
  60. #@return None
  61. #@throws LodelSiteDatasourceError if something fails
  62. #@throws LodelSiteDatasourceError if the site already exists
  63. #@todo make uploads directory name configurable
  64. def site_directories_creation(name):
  65. if site_exists(name):
  66. raise LodelSiteDatasourceError('This site identified by "%s" \
  67. already exists' % name)
  68. data_path, ctx_path = name2paths(name)
  69. #Starting by creating both directories
  70. #Datadir
  71. try:
  72. os.mkdir(data_path)
  73. except FileExistsError:
  74. logger.critical('This should never happen ! We just checked that this \
  75. directory does not exist. BAILOUT !')
  76. raise LodelFatalError('Unable to create data directory for lodelsite \
  77. "%s", file exists')
  78. except Exception as e:
  79. raise LodelFatalError('Unable to create data directory for lodelsite \
  80. "%s" : %s' % (name,e))
  81. #Context dir
  82. try:
  83. os.mkdir(ctx_path)
  84. except FileExistsError:
  85. logger.critical('This should never happen ! We just checked that this \
  86. directory does not exist. BAILOUT !')
  87. raise LodelFatalError('Unable to create context directory for \
  88. lodelsite "%s", file exists' % name)
  89. except Exception as e:
  90. raise LodelFatalError('Unable to create context directory for \
  91. lodelsite "%s" : %s' % (name, e))
  92. #Creates lodel site data subdirectories
  93. for data_subdirectory in LODELSITE_INSTALL_MODEL['datas']:
  94. to_create = os.path.join(data_path, data_subdirectory)
  95. try:
  96. os.mkdir(to_create)
  97. except FileExistsError:
  98. logger.critical('This should never happen ! We just checked that this \
  99. directory does not exist. BAILOUT !')
  100. except Exception as e:
  101. raise LodelFatalError('Unable to create %s directory for \
  102. lodelsite "%s" : %s' % (d,name, e))
  103. def site_lodelpkg_link_creation(name):
  104. dst_path = os.path.join(name2path(name)[1], lodel)
  105. src_path = LODEL_PKG_PATH
  106. try:
  107. os.symlink(src_path, dst_path)
  108. except FileExistsError:
  109. logger.critical('This should never happen ! We just checked that this \
  110. directory does not exist. BAILOUT !')
  111. raise LodelFatalError('Unable to create lodel package symlink for \
  112. lodelsite "%s", link exists in dir %s' % (name, directory))
  113. except Exception as e:
  114. raise LodelFatalError('Unable to create lodel package symlink for \
  115. lodelsite "%s" : %s' % (name, e))
  116. def site_context_init_creation(name):
  117. directory = name2path(name)[1]
  118. try:
  119. open('x', os.path.join(directory, '__init__.py')).close()
  120. except FileExistsError:
  121. logger.critical('This should never happen ! We just checked that this \
  122. directory does not exist. BAILOUT !')
  123. raise LodelFatalError('Unable to create python __init__ file for \
  124. lodelsite context "%s", file exists in dir %s' % (name, directory))
  125. except Exception as e:
  126. raise LodelFatalError('Unable to create python _init__ file for \
  127. lodelsite "%s" : %s' % (name, e))
  128. ##@brief Generate conffile containing informations set by lodelsites EM
  129. #
  130. #@param sitename str : site shortname
  131. #@param em_groups list : list of str -> selected em_groups
  132. #@param extensions list : list of str -> activated extensions
  133. #@return config file content
  134. def generate_conf(sitename, groups, extensions):
  135. tpl = """
  136. [lodel2]
  137. sitename = {sitename}
  138. extensions = {extensions}
  139. [lodel2.editorialmodel]
  140. groups = {em_groups}
  141. """
  142. return tpl.format(
  143. sitename = sitename,
  144. extensions = ', '.join(extensions),
  145. em_groups = ', '.join(groups))
  146. ##@brief Delete generated conf and generate a new one
  147. #@param sitename str : site shortname
  148. #@param em_groups list : list of str -> selected em_groups
  149. #@param extensions list : list of str -> activated extensions
  150. #@return None
  151. def update_conf(sitename, groups, extensions):
  152. data_path, _ = name2path(sitename)
  153. conf_dir = os.path.join(data_path, 'conf.d') #Booo hardcoded
  154. autoconf = os.path.join(conf_dir, CONF_AUTOCONF_FILENAME)
  155. try:
  156. os.unlink(autoconf)
  157. except Exception as e:
  158. #Dropping error on deletion
  159. logger.warning('Unable to delete generated conf %s when trying to \
  160. update it %s' % (autoconf, e))
  161. with open(autoconf, 'w+') as cfp:
  162. cfp.write(generate_conf(sitename, groups, extensions))
  163. logger.info('Generated configuration file update for %s' % sitename)
  164. ##@brief Copies conffile from model and generates a conffile from given info
  165. #@param sitename str : site shortname
  166. #@param em_groups list : list of str -> selected em_groups
  167. #@param extensions list : list of str -> activated extensions
  168. #@return None
  169. def make_confs(sitename, groups, extensions):
  170. data_path, _ = name2path(sitename)
  171. conf_dir = os.path.join(data_path, 'conf.d') #Booo hardcoded
  172. #Config copy & forge
  173. for conffile in os.listdir(CONF_MODELS):
  174. if conffile.endswith('.ini'):
  175. conffile = os.path.join(CONF_MODELS, conffile)
  176. target_conffile = os.path.join(conf_dir, conffile)
  177. logger.info(
  178. "Copying conffile %s -> %s" % (conffile, target_conffile))
  179. shutil.copyfile(conffile, target_conffile)
  180. #Creating generated conf
  181. autoconf = os.path.join(conf_dir, CONF_AUTOCONF_FILENAME)
  182. with open(autoconf, 'w+') as cfp:
  183. cfp.write(generate_conf(sitename, groups, extensions))
  184. logger.info("Configuration file %s generated" % (autoconf))
  185. ##@brief Deletes all files related to a site
  186. #@warning can lead to dirty bugs if the site is running...
  187. def purge(sitename):
  188. for todel in name2paths(sitename):
  189. try:
  190. shutil.rmtree(todel)
  191. except Exception as e:
  192. logger.error('Unable to delete "%s" folder' % todel)
  193. logger.info('"%s" files are deleted' % sitename)