Browse Source

Begin to fix some boostraping problems

Moved some function from plugin specific code to the bootstrap module
+ some bugfixes
Yann Weber 7 years ago
parent
commit
ffd4ef21d5

+ 121
- 0
lodel/bootstrap.py View File

@@ -104,3 +104,124 @@ MONOSITE instance")
104 104
     LodelContext.expose_modules(globals(), {
105 105
         'lodel.settings': ['Settings']})
106 106
     
107
+##@brief Preload a site
108
+#
109
+#Apply a common (as MONOSITE) loading process to a site :
110
+#1. Conf preload
111
+#2. Plugins preload
112
+#3. Conf loading
113
+#
114
+#4. starting plugins & hooks
115
+#@warning At this point we need a uniq identifier for the site (using it
116
+#as key for contexts & FAST_APP_EXPOSAL_CACHE). To achieve this we use
117
+#the data_path basename. It should works for handled sites and for the 
118
+#lodelsites instance
119
+#@warning may only work for handled sites in a multisite context
120
+#@param data_path str : path to the datas directory (containing the confdir)
121
+#@param confdir_basename str : the basename of the site confdir
122
+#@param lodelsites_instance bool : if true we are loading the lodelsites
123
+#instance of the multisite (allow to load the good confspecs)
124
+#
125
+#@todo For now the interface plugin name for sites is hardcoded (set to
126
+#webui). It HAS TO be loaded from settings. But it is a bit complicated, 
127
+#we have to get the plugin's module name abstracted from context :
128
+#lodel.something but if we ask directly to Plugin class the module name
129
+#it will return something like : lodelsites.sitename.something...
130
+#
131
+#@todo there is a quick & dirty workarround with comments saying that it
132
+#avoid context escape via hooks. We have to understand why and how and then
133
+#replace the workarround by a real solution !
134
+#@todo check if it works with monosite context !
135
+#@todo change data_path argument to sitename and determine datapath from it
136
+def site_preload(data_path, confdir_basename = 'conf.d', lodelsites_instance = False):
137
+    #args check
138
+    if confdir_basename != os.path.basename(confdir_basename):
139
+        LodelFatalError('Bad argument given to site_load(). This really \
140
+sux !')
141
+    #Determining uniq sitename from data_path
142
+    data_path = data_path.rstrip('/') #else basename returns ''
143
+    ctx_name = os.path.basename(data_path)
144
+    if not os.path.exists(data_path) or not os.path.isdir(data_path):
145
+        LodelContext.expose_modules(globals(), {
146
+            'lodel.exceptions': ['LodelFatalError']})
147
+        raise LodelFatalError("A site named '%s' was found in the DB but not on the FS (expected to found it in '%s'!!!" % (os.path.basename(data_path), data_path))
148
+    #Immediately switching to the context
149
+    LodelContext.new(ctx_name)
150
+    LodelContext.set(ctx_name)
151
+    os.chdir(data_path) #Now the confdir is ./$condir_basename
152
+    #Loading settings for current site
153
+    LodelContext.expose_modules(globals(), {
154
+        'lodel.settings.settings': [('Settings', 'settings_preloader')]})
155
+    if settings_preloader.started():
156
+        msg = 'Settings seems to be allready started for "%s". \
157
+This should not append !' % ctx_name
158
+        #switch back to loader context in order to log & raise
159
+        LodelContext.set(None)
160
+        logger.critical(msg)
161
+        raise LodelFatalError(msg)
162
+    if lodelsites_instance:
163
+        settings_preloader(os.path.join('./', confdir_basename), )
164
+    else:
165
+        settings_preloader(os.path.join('./', confdir_basename))
166
+    LodelContext.set(None)
167
+    return
168
+
169
+##@brief End a site loading process (load plugins & hooks)
170
+#@param data_path str : site data path (used to extract the sitename !!)
171
+#@todo change data_path argument to sitename
172
+def site_load(data_path):
173
+    ctx_name = os.path.basename(data_path)
174
+    LodelContext.set(ctx_name)
175
+    #
176
+    #Loading hooks & plugins
177
+    #
178
+    LodelContext.expose_modules(globals(), {
179
+        'lodel.plugin': ['Plugin', 'LodelHook'],
180
+        'lodel.logger': 'logger',
181
+        'lodel.plugin.core_hooks': 'core_hooks',
182
+        'lodel.plugin.core_scripts': 'core_scripts'
183
+    })
184
+    Plugin.load_all() #Then all plugins & hooks are loaded
185
+    #triggering dyncode datasource instanciations
186
+    LodelHook.call_hook('lodel2_plugins_loaded', '__main__', None)
187
+    #triggering boostrapped hook
188
+    LodelHook.call_hook('lodel2_bootstraped', '__main__', None)
189
+    #Populating FAST_APP_EXPOSAL_CACHE
190
+    #
191
+    #WARNING !!!! Hardcoded interface name ! Here we have to find the 
192
+    #interface plugin name in order to populate the cache properly
193
+    FAST_APP_EXPOSAL_CACHE[ctx_name] = LodelContext.module(
194
+        'lodel.plugins.webui.run')
195
+    #a dirty & quick attempt to fix context unwanted exite via
196
+    #hooks
197
+    for name in ( 'LodelHook', 'core_hooks', 'core_scripts',
198
+            'Settings', 'settings', 'logger', 'Plugin'):
199
+        del(globals()[name])
200
+    #site fully loaded, switching back to loader context
201
+    LodelContext.set(None)
202
+
203
+##@brief Fetch handled sites name
204
+#@warning assert that a full __loader__ context is ready and that the
205
+#multisite context is preloaded too
206
+#@warning hardcoded Lodelsite leo name and shortname fieldname
207
+#@todo attempt to delete hardcoded leo name
208
+#@todo attempt to delete hardcoded fieldname
209
+def get_handled_sites_name():
210
+    LodelContext.expose_modules(globals(), {
211
+        'lodel.settings': ['Settings']})
212
+    lodelsites_name = Settings.sitename
213
+    LodelContext.set(lodelsites_name)
214
+    lodelsite_leo = leapi_dyncode.Lodelsite #hardcoded leo name
215
+    LodelContext.expose_modules(globals(), {
216
+        'lodel.leapi.query': ['LeGetQuery'],
217
+    })
218
+    handled_sites = LeGetQuery(lodelsite_leo, query_filters = [],
219
+        field_list = ['shortname']).execute()
220
+    if handled_sites is None:
221
+        return []
222
+    res = [ s['shortname'] for s in handled_sites]
223
+    del(globals()['LeGetQuery'])
224
+    del(globals()['Settings'])
225
+    LodelContext.set(None)
226
+    return res
227
+    

+ 58
- 3
lodel/plugin/core_scripts.py View File

@@ -3,6 +3,7 @@ import shutil
3 3
 import tempfile
4 4
 import os, os.path
5 5
 from lodel.context import LodelContext
6
+from lodel import buildconf
6 7
 LodelContext.expose_modules(globals(), {
7 8
     'lodel.plugin.scripts': ['LodelScript'],
8 9
     'lodel.logger': 'logger'})
@@ -302,6 +303,8 @@ class ListHooks(LodelScript):
302 303
             print("\n")
303 304
 
304 305
 
306
+##@brief Implements lodel_admin **dyncode** action
307
+#@ingroup lodel2_script
305 308
 class RefreshDyncode(LodelScript):
306 309
     _action = 'dyncode'
307 310
     _description = 'Update the dynamic code according to EM and conf'
@@ -314,10 +317,16 @@ class RefreshDyncode(LodelScript):
314 317
         parser.add_argument('-o', '--dyncode',
315 318
             help='Specify the filename where the dyncode should be written',
316 319
             type=str, default='')
320
+        if LodelContext.multisite():
321
+            parser.add_argument('-a', '--all', action='store_true',
322
+                help="ONLY VALID FOR MULtisites ! Refresh lodelsites dyncode \
323
++ all handled sites dyncode")
317 324
         return
318 325
 
319 326
     ##@todo think of a better method to determine if we are in mono or
320 327
     #multisite instance
328
+    #@todo code factorisation to fetch handled sites list
329
+    #@todo fetch & use correct em_translator for handled sites
321 330
     @classmethod
322 331
     def run(cls, args):
323 332
         LodelContext.expose_modules(globals(), {
@@ -329,15 +338,61 @@ class RefreshDyncode(LodelScript):
329 338
         if len(args.em.strip()) == 0:
330 339
             #using the default em_file
331 340
             model_file = Settings.editorialmodel.emfile
332
-        #Model loaded
333
-        model = EditorialModel.load(em_translator, filename = model_file)
341
+        elif LodelContext.multisite() and args.all:
342
+            raise 
334 343
         #Creating dyncode
335 344
         dyncode_file = args.dyncode
336 345
         if len(args.dyncode.strip()) == 0:
337 346
             #using dyncode filename from conf
338 347
             dyncode_file = Settings.editorialmodel.dyncode
348
+        elif LodelContext.multisite() and args.all:
349
+            raise 
350
+        if LodelContext.multisite() and args.all:
351
+            #NOTE the code bellow can be factorised with 
352
+            #plugins/multisite/loader_utils.py
353
+
354
+            #Get the lodelsites instance name and the emfile path
355
+            LodelContext.set(None)
356
+            LodelContext.expose_modules(globals(), {
357
+                'lodel.settings':['Settings']})
358
+            lodelsites_name = Settings.sitename
359
+            emfile_path = Settings.lodelsites.sites_emfile
360
+            del(globals()['Settings']) #should be useless
361
+            #Get the list of handled sites name
362
+            LodelContext.set(lodelsites_name)
363
+            LodelContext.expose_modules(globals(), {
364
+                'lodel.leapi.query': ['LeGetQuery'],
365
+            })
366
+            handled_sites = LeGetQuery(lodelsite_leo, query_filters = [],
367
+                field_list = ['shortname']).execute()
368
+            del(globals()['LeGetQuery']) #should be useless
369
+            lodlesites_path = os.path.join(buildconf.LODEL2VARDIR,
370
+                MULTISITE_CONTEXTDIR)
371
+            if handled_sites is not None:
372
+                for sitename in handled_sites:
373
+                    LodelContext.set(None)
374
+                    #construct dyncode filename
375
+                    dyncode_path = os.path.join(
376
+                        os.path.join(lodlesites_path, sitename),
377
+                        'leapi_dyncode') #BOO hardcoded dyncode file name
378
+                    cls.refresh_dyncode(emfile_path, dyncode_path,
379
+                        em_translator)
380
+        #Refresh only one dyncode
381
+        #if multisite it's the lodelsites dyncode
382
+        LodelContext.set(None)
383
+        cls.refresh_dyncode(model_file, dyncode_file, em_translator)
384
+
385
+    
386
+    ##@brief Refresh dyncode
387
+    #@param model_file str : EM filename
388
+    #@param dyncode_file str : dyncode output filename
389
+    #@param em_translator str : translator name
390
+    @classmethod
391
+    def refresh_dyncode(cls, model_file, dyncode_file, em_translator):
392
+        #Model loaded
393
+        model = EditorialModel.load(em_translator, filename = model_file)
339 394
         dyncode_content = lefactory.dyncode_from_em(model)
340 395
         with open(dyncode_file, 'w+') as dfp:
341 396
             dfp.write(dyncode_content)
342 397
         print("Dyncode written in %s from em %s" % (dyncode_file, model_file))
343
-
398
+        

+ 17
- 85
lodel/plugins/multisite/loader_utils.py View File

@@ -30,8 +30,10 @@ LODELSITES_CONFD = lodel.buildconf.LODELSITE_CONFDIR
30 30
 #@todo get rid of hardcoded stuff (like shortname fieldname)
31 31
 #@todo use the dyncode getter when it will be available (replaced by
32 32
 #the string SUPERDYNCODE_ACCESSOR.Lodelsite for the moment)
33
+#@todo remove hardcoded app name (need a better abstraction or a really
34
+#generic multiinstance runner)
33 35
 #@return lodelsites instance name
34
-def main():
36
+def main(handled_sites_may_not_load = False):
35 37
     #Set current context to reserved loader context
36 38
     from lodel import bootstrap
37 39
     bootstrap.bootstrap('__loader__')
@@ -79,20 +81,27 @@ def main():
79 81
     #loader context and clean it
80 82
     if handled_sites is not None:
81 83
         LodelContext.set(None)
84
+        LodelContext.expose_modules(globals(), {
85
+            'lodel.bootstrap': ['site_preload', 'site_load']})
82 86
         for mname in ['LeGetQuery', 'Settings', 'LodelHook', 'Plugin', 'logger']:
83 87
             del(globals()[mname])
84 88
         #Loading handled sites
85 89
         for handled_sitename in [s['shortname'] for s in handled_sites]:
86 90
             datapath = os.path.join(lodelsites_datapath, handled_sitename)
87 91
             try:
88
-                site_load(datapath) #using default conf.d configuration dirname
92
+                site_preload(datapath) #using default conf.d configuration dirname
93
+                site_load(datapath)
94
+                #
95
+                # HARDCODED APP NAME
96
+                #
97
+                populate_fast_app_cache(datapath, 'lodel.plugins.webui.run')
89 98
             except Exception as e:
90 99
                 LodelContext.set(None)
91 100
                 LodelContext.set(lodelsites_name)
92 101
                 LodelContext.expose_modules(globals(), {
93 102
                     'lodel.settings': ['Settings'],
94 103
                     'lodel.logger': 'logger'})
95
-                if Settings.debug:
104
+                if Settings.debug or handled_sites_may_not_load:
96 105
                     logger.critical("Unable to load site %s : %s" % (
97 106
                         e, handled_sitename))
98 107
                 else:
@@ -102,89 +111,12 @@ def main():
102 111
     LodelContext.set(None)
103 112
     return lodelsites_name
104 113
     
105
-
106
-##@brief Load a site
107
-#
108
-#Apply a common (as MONOSITE) loading process to a site :
109
-#1. Conf preload
110
-#2. Plugins preload
111
-#3. Conf loading
112
-#4. starting plugins & hooks
113
-#@warning At this point we need a uniq identifier for the site (using it
114
-#as key for contexts & FAST_APP_EXPOSAL_CACHE). To achieve this we use
115
-#the data_path basename. It should works for handled sites and for the 
116
-#lodelsites instance
117
-#@param data_path str : path to the datas directory (containing the confdir)
118
-#@param confdir_basename str : the basename of the site confdir
119
-#@param lodelsites_instance bool : if true we are loading the lodelsites
120
-#instance of the multisite (allow to load the good confspecs)
121
-#
122
-#@todo For now the interface plugin name for sites is hardcoded (set to
123
-#webui). It HAS TO be loaded from settings. But it is a bit complicated, 
124
-#we have to get the plugin's module name abstracted from context :
125
-#lodel.something but if we ask directly to Plugin class the module name
126
-#it will return something like : lodelsites.sitename.something...
127
-#
128
-#@todo there is a quick & dirty workarround with comments saying that it
129
-#avoid context escape via hooks. We have to understand why and how and then
130
-#replace the workarround by a real solution !
131
-def site_load(data_path, confdir_basename = 'conf.d', lodelsites_instance = False):
132
-    #args check
133
-    if confdir_basename != os.path.basename(confdir_basename):
134
-        LodelFatalError('Bad argument given to site_load(). This really \
135
-sux !')
136
-    #Determining uniq sitename from data_path
137
-    data_path = data_path.rstrip('/') #else basename returns ''
114
+##@brief Add an app to FAST_APP_EXPOSAL_CACHE
115
+#@param data_path str : instance data_path (used to extract the sitename !)
116
+#@param app_name str : application name (like lodel.plugins.webui.run)
117
+def populate_fast_app_cache(data_path, app_name):
138 118
     ctx_name = os.path.basename(data_path)
139
-    if not os.path.exists(data_path) or not os.path.isdir(data_path):
140
-        LodelContext.expose_modules(globals(), {
141
-            'lodel.exceptions': ['LodelFatalError']})
142
-        raise LodelFatalError("A site named '%s' was found in the DB but not on the FS (expected to found it in '%s'!!!" % (os.path.basename(data_path), data_path))
143
-    #Immediately switching to the context
144
-    LodelContext.new(ctx_name)
145 119
     LodelContext.set(ctx_name)
146
-    os.chdir(data_path) #Now the confdir is ./$condir_basename
147
-    #Loading settings for current site
148
-    LodelContext.expose_modules(globals(), {
149
-        'lodel.settings.settings': [('Settings', 'settings_preloader')]})
150
-    if settings_preloader.started():
151
-        msg = 'Settings seems to be allready started for "%s". \
152
-This should not append !' % ctx_name
153
-        #switch back to loader context in order to log & raise
154
-        LodelContext.set(None)
155
-        logger.critical(msg)
156
-        raise LodelFatalError(msg)
157
-    if lodelsites_instance:
158
-        settings_preloader(os.path.join('./', confdir_basename), )
159
-    else:
160
-        settings_preloader(os.path.join('./', confdir_basename))
161
-    #
162
-    #Loading hooks & plugins
163
-    #
164
-    LodelContext.expose_modules(globals(), {
165
-        'lodel.plugin': ['Plugin', 'LodelHook'],
166
-        'lodel.logger': 'logger',
167
-        'lodel.plugin.core_hooks': 'core_hooks',
168
-        'lodel.plugin.core_scripts': 'core_scripts'
169
-    })
170
-    Plugin.load_all() #Then all plugins & hooks are loaded
171
-    #triggering dyncode datasource instanciations
172
-    LodelHook.call_hook('lodel2_plugins_loaded', '__main__', None)
173
-    #triggering boostrapped hook
174
-    LodelHook.call_hook('lodel2_bootstraped', '__main__', None)
175
-    #Populating FAST_APP_EXPOSAL_CACHE
176
-    #
177
-    #WARNING !!!! Hardcoded interface name ! Here we have to find the 
178
-    #interface plugin name in order to populate the cache properly
179
-    FAST_APP_EXPOSAL_CACHE[ctx_name] = LodelContext.module(
180
-        'lodel.plugins.webui.run')
181
-    #a dirty & quick attempt to fix context unwanted exite via
182
-    #hooks
183
-    for name in ( 'LodelHook', 'core_hooks', 'core_scripts',
184
-            'Settings', 'settings', 'logger', 'Plugin'):
185
-        del(globals()[name])
186
-    #site fully loaded, switching back to loader context
120
+    FAST_APP_EXPOSAL_CACHE[ctx_name] = LodelContext.module(app_name)
187 121
     LodelContext.set(None)
188
-    #lodel2 multisite instances are loaded and ready to run
189
-
190 122
 

+ 22
- 1
progs/slim/install_model/lodel_admin.py View File

@@ -139,15 +139,36 @@ def update_plugin_discover_cache(path_list = None):
139 139
 
140 140
 if __name__ == '__main__':
141 141
     _simlink_hack()
142
+    import lodel.buildconf
142 143
     from lodel import bootstrap
144
+    from lodel.context import LodelContext
143 145
     #to deleted when we known wich action need what kind of MULTISITE API
144 146
     if not bootstrap._monosite_test():
145 147
         bootstrap.bootstrap('lodelsites')
148
+        LodelContext.set(None)
149
+        #lodelsites instance preloading
150
+        #THIS CODE SHOULD BE IN AN UTIL FUNCTION
151
+        LodelContext.expose_modules(globals(), {
152
+            'lodel.bootstrap': ['get_handled_sites_name', 'site_preload'],
153
+            'lodel.settings': ['Settings']})
154
+        lodelsites_name = Settings.sitename
155
+        lodelsites_datapath = os.path.join(
156
+            os.path.join(lodel.buildconf.LODEL2VARDIR, lodelsites_name),
157
+            lodel.buildconf.MULTISITE_DATADIR)
158
+        del(globals()['Settings'])
159
+        site_preload(lodelsites_datapath, 'lodelsites.conf.d', True)
160
+
161
+        #preloading all handled sites
162
+        for sitename in get_handled_sites_name():
163
+            datapath = os.path.join(
164
+                os.path.join(lodel.buildconf.LODEL2VARDIR, sitename),
165
+                lodel.buildconf.MULTISITE_DATADIR)
166
+            site_preload(datapath)
146 167
     else:
147 168
         bootstrap.bootstrap()
148
-    from lodel.context import LodelContext
149 169
     #from lodel.plugin.scripts import main_run
150 170
     LodelContext.expose_modules(globals(),
151 171
         {'lodel.plugin.scripts': ['main_run'],
152 172
          'lodel.plugin.core_scripts': 'core_scripts'})
153 173
     main_run()
174
+    exit()

Loading…
Cancel
Save