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