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.

loader_utils.py 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import os
  2. import os.path
  3. ##@brief basename of multisite process conf folder
  4. #@todo find a better place to declare it
  5. SERVER_CONFD = 'server_conf.d' #Should be accessible elsewhere
  6. ##@brief basename of lodelsites site conf folder
  7. #@todo find a better place to declare it
  8. LODELSITES_CONFD = 'lodelsites.conf.d' #Should be accessible elsewhere
  9. ##@brief A cache allowing a fast application exposure
  10. #
  11. #This dict contains reference on interface module of each handled site in
  12. #order to quickly call the application (PEP 3333) function of concerned site
  13. FAST_APP_EXPOSAL_CACHE = dict()
  14. try:
  15. from lodel.context import LodelContext
  16. except ImportError:
  17. LODEL_BASE_DIR = os.path.dirname(
  18. os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
  19. from lodel.context import LodelContext, ContextError
  20. import lodel.buildconf
  21. ##@brief Stores the main function of a multisite loader
  22. ##@brief Function designed to bootstrap a multisite runner
  23. #
  24. #Handles lodelsites site loading, handled site list fecth & load
  25. #@note called at end of file
  26. #
  27. #@todo evaluate if it is safe to assume that lodelsites_datapath = os.getcwd()
  28. #@todo get rid of hardcoded stuff (like shortname fieldname)
  29. #@todo use the dyncode getter when it will be available (replaced by
  30. #the string SUPERDYNCODE_ACCESSOR.Lodelsite for the moment)
  31. #@return lodelsites instance name
  32. def main():
  33. #Set current context to reserved loader context
  34. from lodel import bootstrap
  35. bootstrap.bootstrap('__loader__')
  36. LodelContext.expose_modules(globals(), {
  37. 'lodel.settings': ['Settings']})
  38. lodelsites_name = Settings.sitename
  39. del(globals()['Settings'])
  40. #bootstraping the lodelsites instance
  41. LodelContext.new(lodelsites_name)
  42. LodelContext.set(lodelsites_name)
  43. #in lodelsites context
  44. LodelContext.expose_modules(globals(), {
  45. 'lodel.settings.settings': [('Settings', 'settings_loader')],
  46. 'lodel.plugins.multisite.confspecs': 'multisite_confspecs',
  47. 'lodel.plugins.multisite.confspecs': 'multisite_confspecs'})
  48. settings_loader(lodel.buildconf.LODELSITE_CONFDIR,
  49. multisite_confspecs.LODEL2_CONFSPECS, True)
  50. del(globals()['settings_loader'])
  51. LodelContext.expose_modules(globals(), {
  52. 'lodel.settings': ['Settings']})
  53. LodelContext.expose_dyncode(globals())
  54. LodelContext.expose_modules(globals(), {
  55. 'lodel.logger': 'logger',
  56. 'lodel.plugin.hooks': ['LodelHook'],
  57. 'lodel.plugin': ['Plugin']})
  58. Plugin.load_all()
  59. LodelHook.call_hook('lodel2_bootstraped', '__main__', None)
  60. lodelsite_leo = leapi_dyncode.Lodelsite #hardcoded leo name
  61. LodelContext.expose_modules(globals(), {
  62. 'lodel.leapi.query': ['LeGetQuery'],
  63. })
  64. #the line bellow you will find another harcoded thing : the shortname
  65. #fieldname for a lodelsite
  66. handled_sites = LeGetQuery(lodelsite_leo, query_filters = [],
  67. field_list = ['shortname']).execute()
  68. #Now that we have the handled sitenames list we can go back to
  69. #loader context and clean it
  70. if handled_sites is not None:
  71. LodelContext.set(None)
  72. for mname in ['LeGetQuery', 'Settings', 'LodelHook', 'Plugin', 'logger']:
  73. del(globals()[mname])
  74. #Loading handled sites
  75. for handled_sitename in [s['shortname'] for s in handled_sites]:
  76. datapath = os.path.join(lodelsites_datapath, handled_sitename)
  77. site_load(datapath) #using default conf.d configuration dirname
  78. else:
  79. logger.warning("No handled sites !")
  80. LodelContext.set(None)
  81. return lodelsites_name
  82. ##@brief Load a site
  83. #
  84. #Apply a common (as MONOSITE) loading process to a site :
  85. #1. Conf preload
  86. #2. Plugins preload
  87. #3. Conf loading
  88. #4. starting plugins & hooks
  89. #@warning At this point we need a uniq identifier for the site (using it
  90. #as key for contexts & FAST_APP_EXPOSAL_CACHE). To achieve this we use
  91. #the data_path basename. It should works for handled sites and for the
  92. #lodelsites instance
  93. #@param data_path str : path to the datas directory (containing the confdir)
  94. #@param confdir_basename str : the basename of the site confdir
  95. #@param lodelsites_instance bool : if true we are loading the lodelsites
  96. #instance of the multisite (allow to load the good confspecs)
  97. #
  98. #@todo For now the interface plugin name for sites is hardcoded (set to
  99. #webui). It HAS TO be loaded from settings. But it is a bit complicated,
  100. #we have to get the plugin's module name abstracted from context :
  101. #lodel.something but if we ask directly to Plugin class the module name
  102. #it will return something like : lodelsites.sitename.something...
  103. #
  104. #@todo there is a quick & dirty workarround with comments saying that it
  105. #avoid context escape via hooks. We have to understand why and how and then
  106. #replace the workarround by a real solution !
  107. def site_load(data_path, confdir_basename = 'conf.d', lodelsites_instance = False):
  108. #args check
  109. if confdir_basename != os.path.basename(confdir_basename):
  110. LodelFatalError('Bad argument given to site_load(). This really \
  111. sux !')
  112. #Determining uniq sitename from data_path
  113. data_path = data_path.rstrip('/') #else basename returns ''
  114. ctx_name = os.path.basename(data_path)
  115. #Immediately switching to the context
  116. LodelContext.new(ctx_name)
  117. LodelContext.set(ctx_name)
  118. os.chdir(data_path) #Now the confdir is ./$condir_basename
  119. #Loading settings for current site
  120. LodelContext.expose_modules(globals(), {
  121. 'lodel.settings.settings': [('Settings', 'settings_preloader')]})
  122. if settings_preloader.started():
  123. msg = 'Settings seems to be allready started for "%s". \
  124. This should not append !' % ctx_name
  125. #switch back to loader context in order to log & raise
  126. LodelContext.set(None)
  127. logger.critical(msg)
  128. raise LodelFatalError(msg)
  129. if lodelsites_instance:
  130. settings_preloader(os.path.join('./', confdir_basename), )
  131. else:
  132. settings_preloader(os.path.join('./', confdir_basename))
  133. #
  134. #Loading hooks & plugins
  135. #
  136. LodelContext.expose_modules(globals(), {
  137. 'lodel.plugin': ['Plugin', 'LodelHook'],
  138. 'lodel.logger': 'logger',
  139. 'lodel.plugin.core_hooks': 'core_hooks',
  140. 'lodel.plugin.core_scripts': 'core_scripts'
  141. })
  142. Plugin.load_all() #Then all plugins & hooks are loaded
  143. #triggering dyncode datasource instanciations
  144. LodelHook.call_hook('lodel2_plugins_loaded', '__main__', None)
  145. #triggering boostrapped hook
  146. LodelHook.call_hook('lodel2_bootstraped', '__main__', None)
  147. #Populating FAST_APP_EXPOSAL_CACHE
  148. #
  149. #WARNING !!!! Hardcoded interface name ! Here we have to find the
  150. #interface plugin name in order to populate the cache properly
  151. FAST_APP_EXPOSAL_CACHE[ctx_name] = LodelContext.module(
  152. 'lodel.plugins.webui.run')
  153. #a dirty & quick attempt to fix context unwanted exite via
  154. #hooks
  155. for name in ( 'LodelHook', 'core_hooks', 'core_scripts',
  156. 'Settings', 'settings', 'logger', 'Plugin'):
  157. del(globals()[name])
  158. #site fully loaded, switching back to loader context
  159. LodelContext.set(None)
  160. #lodel2 multisite instances are loaded and ready to run