2 # ============LICENSE_START=======================================================
3 # ONAP : ccsdk distribution web
4 # ================================================================================
5 # Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
7 # ================================================================================
8 # Licensed under the Apache License, Version 2.0 (the "License");
9 # you may not use this file except in compliance with the License.
10 # You may obtain a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS,
16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 # See the License for the specific language governing permissions and
18 # limitations under the License.
19 # ============LICENSE_END=========================================================
31 urllib3.disable_warnings()
33 APPLICATION_LISTFILE="/app/odlux.application.list"
34 INIT_FOLDER="/app/init.d"
35 ODLUX_BASE_FOLDER='/app/odlux'
36 INDEX_HTML=ODLUX_BASE_FOLDER+'/index.html'
37 INDEX_HTML_TEMPLATE=INDEX_HTML+'.template'
38 DEFAULT_APPLICATIONS=["connectApp" "faultApp" "maintenanceApp" "configurationApp" "performanceHistoryApp" "inventoryApp" "eventLogApp" "mediatorApp" "helpApp"]
39 http = urllib3.PoolManager(cert_reqs=ssl.CERT_NONE)
42 output = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE).stdout.read()
44 def execToStdOut(commandArray):
45 process = subprocess.Popen(commandArray, shell=False)
48 def download(url, dst):
49 print("downloading from {}...".format(url),end="")
50 with open(dst, 'wb') as out_file:
51 resp= http.request('GET',url, preload_content=False)
52 shutil.copyfileobj(resp, out_file)
56 def getEnv(key, defaultValue=None):
58 return x if x is not None and len(x)>0 else defaultValue
60 def sedInFile(old, nu, fn):
61 execToStdOut(['sed', '-i', 's|{}|{}|g'.format(old,nu),fn])
63 def add_application(name, index, file=None):
64 apps = load_applications()
66 print("no index given. put it to last position")
67 index=apps[len(apps)-1]['index']+10
68 apps.append(dict(index=index,name=name))
69 if file is not None and os.path.exists(file):
72 print('unable to find file {}'.format(file))
73 write_applications(apps)
74 print("{} installed on index {}".format(name, index))
77 files = os.listdir(INIT_FOLDER)
78 regex = r"([0-9]+)([a-zA-Z]+)\.(jar|zip)"
80 matches = re.finditer(regex,file)
81 match = next(matches, None)
83 print("installing {}".format(file))
84 index = int(match.group(1))
86 add_application(name,index,INIT_FOLDER+'/'+file)
88 print("no index naming format found. try to autodetect")
89 infos = autoDetectInfosFromJar(file)
91 print("unable to detect index and application name for {}".format(file))
93 add_application(infos['name'],infos['index'],INIT_FOLDER+'/'+file)
97 def containsBlueprintExpression(file) -> bool:
98 print("check if file {} is blueprint".format(file))
99 with open(file, 'r') as fp:
100 lines = fp.readlines()
102 if "<blueprint" in line:
107 def findBlueprintXml(dir):
108 result = [os.path.join(dp, f) for dp, dn, filenames in os.walk(dir) for f in filenames if os.path.splitext(f)[1] == '.xml']
110 if containsBlueprintExpression(file):
114 def autoDetectInfosFromJar(file):
115 print("autodetect infos(appName and index) from jar {}".format(file))
116 tmpDir=getRandomTempDir()
117 regexBundleName = r"<property[\ ]+name=\"bundleName\"[\ ]+value=\"([^\"]+)\""
118 regexIndex = r"<property[\ ]+name=\"index\"[\ ]+value=\"([^\"]+)\""
121 with zipfile.ZipFile(file, 'r') as zip_ref:
122 zip_ref.extractall(tmpDir)
123 blueprint = findBlueprintXml(tmpDir)
124 if blueprint is None:
126 with open(blueprint) as fp:
127 lines = fp.readlines()
130 matches = re.finditer(regexBundleName, line)
131 match = next(matches,None)
132 if match is not None:
133 name = match.group(1)
135 matches = re.finditer(regexIndex, line)
136 match = next(matches,None)
137 if match is not None:
138 index = int(match.group(1))
141 print("found infos from jar: name={} index={}".format(name,index))
142 return dict(index=index,name=name)
144 def getRandomTempDir(create=False):
146 dir='/tmp/{}'.format(uuid.uuid4())
147 if not os.path.exists(dir):
148 # print("found random not-existing dir {}".format(dir))
152 # print("dir {} already exists. try new".format(dir))
155 def getRandomTempFile():
156 dir = getRandomTempDir(True)
161 file='{}/{}.dat'.format(dir,uuid.uuid4())
162 if not os.path.exists(file):
163 # print("found random not-existing file {}".format(file))
165 # print("file {} already exists. try new".format(file))
170 tmpDir=getRandomTempDir()
171 with zipfile.ZipFile(fn, 'r') as zip_ref:
172 zip_ref.extractall(tmpDir)
173 exec(" ".join(['cp','-r',tmpDir+'/odlux/*',ODLUX_BASE_FOLDER+'/']))
177 def load_applications():
179 if os.path.exists(APPLICATION_LISTFILE):
180 with open(APPLICATION_LISTFILE,'r') as fp:
181 lines= fp.readlines()
183 if len(line.rstrip())<=0:
187 apps.append(dict(index=int(hlp[0]),name=hlp[1].rstrip()))
189 print('problem reading line {}'.format(line))
193 for app in DEFAULT_APPLICATIONS:
194 apps.append(dict(index=index,name=app))
196 # print('applications loaded={}'.format(apps))
197 return sorted(apps, key=lambda d: d['index'])
199 def write_applications(apps):
200 # print('saving applications={}'.format(apps))
201 apps = sorted(apps, key=lambda d: d['index'])
202 os.remove(APPLICATION_LISTFILE)
203 with open(APPLICATION_LISTFILE,'w') as fp:
205 fp.write('{} {}\n'.format(app['index'], app['name']))
208 def update_index_html(apps=None):
210 # # Backup the index.html file
211 if not os.path.exists(INDEX_HTML_TEMPLATE):
212 execToStdOut(['cp',INDEX_HTML,INDEX_HTML_TEMPLATE])
214 execToStdOut(['cp',INDEX_HTML_TEMPLATE,INDEX_HTML])
217 apps=load_applications()
218 ODLUX_AUTH_METHOD="basic"
219 ENABLE_ODLUX_RBAC=getEnv('ENABLE_ODLUX_RBAC','false')
220 TRPCEGUIURL=getEnv('TRPCEGUIURL')
222 if getEnv('ENABLE_OAUTH') == "true":
223 ODLUX_AUTH_METHOD="oauth"
224 ODLUX_CONFIG=dict(authentication=ODLUX_AUTH_METHOD,enablePolicy=ENABLE_ODLUX_RBAC == 'true')
225 print("authentication is {}".format(ODLUX_AUTH_METHOD))
226 print("rbac access is enabled: {}".format(ENABLE_ODLUX_RBAC))
228 if TRPCEGUIURL is not None:
229 ODLUX_CONFIG['transportpceUrl']=TRPCEGUIURL
230 print("trpce gui url is: {}".format(TRPCEGUIURL))
232 # sed -z 's/<script>[^<]*<\/script>/<script>\n \/\/ run the application \n require\(\[\"connectApp\",\"faultApp\",\"maintenanceApp\",\"configurationApp\",\"performanceHistoryApp\",\"inventoryApp\",\"eventLogApp\",\"mediatorApp\",\"networkMapApp\",\"linkCalculationApp\",\"helpApp\",\"run\"\], function \(connectApp,faultApp,maintenanceApp,configurationApp,performanceHistoryApp,inventoryApp,eventLogApp,mediatorApp,networkMapApp,linkCalculationApp,helpApp,run\) \{ \n run.configure('$ODLUX_CONFIG'); \n connectApp.register\(\); \n faultApp.register\(\);\n maintenanceApp.register\(\); \n configurationApp.register\(\);\n performanceHistoryApp.register\(\); \n inventoryApp.register\(\);\n eventLogApp.register\(\);\n mediatorApp.register\(\);\n networkMapApp.register\(\);\n linkCalculationApp.register\(\);\n helpApp.register\(\);\n run.runApplication();\n \}\);\n <\/script>/' -i /opt/bitnami/nginx/html/odlux/index.html
237 requireArg+='"{}",'.format(app['name'])
238 fnArgs+='{},'.format(app['name'])
239 appCalls+='{}.register();\\n'.format(app['name'])
240 #replace require expression
241 execToStdOut(['sed', '-z', 's/require(\["run"\],\ function\ (run)/require\(\[{}\"run\"\], function \({}run\)/'.format(requireArg,fnArgs), '-i', INDEX_HTML])
242 #replace run.runApplication expression
243 execToStdOut(['sed','-z', 's/run.runApplication();/{}run.runApplication();/'.format(appCalls), '-i',INDEX_HTML])
244 #replace run.configure expression if exists
245 execToStdOut(['sed', '-z', 's|run.configureApplication([^)]\+)|run.configureApplication({});|'.format(json.dumps(ODLUX_CONFIG)), '-i', INDEX_HTML])
248 def check_for_rule_template():
249 if os.path.exists('/opt/bitnami/nginx/conf/server_blocks/location.rules.tmpl'):
250 print("using template for forwarding rules")
251 execToStdOut(['cp','/opt/bitnami/nginx/conf/server_blocks/location.rules.tmpl','/opt/bitnami/nginx/conf/server_blocks/location.rules'])
253 def update_nginx_site_conf():
255 if getEnv('WEBPROTOCOL') == "HTTPS":
256 FN='/opt/bitnami/nginx/conf/server_blocks/https_site.conf'
257 execToStdOut(['rm', '/opt/bitnami/nginx/conf/server_blocks/http_site.conf'])
258 SSL_CERT_DIR=getEnv('SSL_CERT_DIR')
259 SSL_CERTIFICATE=getEnv('SSL_CERTIFICATE')
260 SSL_CERTIFICATE_KEY=getEnv('SSL_CERTIFICATE_KEY')
261 sedInFile('SSL_CERTIFICATE_KEY',SSL_CERTIFICATE_KEY,FN)
262 sedInFile('SSL_CERT_DIR',SSL_CERT_DIR,FN)
263 sedInFile('SSL_CERTIFICATE',SSL_CERTIFICATE, FN)
265 elif getEnv('WEBPROTOCOL') == "HTTP":
266 FN='/opt/bitnami/nginx/conf/server_blocks/http_site.conf'
267 execToStdOut(['rm', '/opt/bitnami/nginx/conf/server_blocks/https_site.conf'])
269 WEBPROTOCOL=getEnv('WEBPROTOCOL')
270 WEBPORT=getEnv('WEBPORT')
271 SDNRPROTOCOL=getEnv('SDNRPROTOCOL')
272 SDNRHOST=getEnv('SDNRHOST')
273 SDNRPORT=getEnv('SDNRPORT')
274 DNS_RESOLVER=getEnv('DNS_RESOLVER')
275 DNS_INTERNAL_RESOLVER=getEnv('DNS_INTERNAL_RESOLVER')
277 print("unknown env WEBPROTOCOL: {}".format(WEBPROTOCOL))
280 # replace needed base parameters
281 sedInFile('WEBPORT',WEBPORT,FN)
283 FN='/opt/bitnami/nginx/conf/server_blocks/location.rules'
284 # replace needed parameters in forwarding rules
285 sedInFile('WEBPORT',WEBPORT,FN)
286 sedInFile('SDNRPROTOCOL',SDNRPROTOCOL,FN)
287 sedInFile('SDNRHOST',SDNRHOST ,FN)
288 sedInFile('SDNRPORT',SDNRPORT,FN)
289 sedInFile('DNS_RESOLVER',DNS_RESOLVER ,FN)
290 sedInFile('DNS_INTERNAL_RESOLVER',DNS_INTERNAL_RESOLVER ,FN)
292 TRPCEURL=getEnv('TRPCEURL')
293 TOPOURL=getEnv('TOPOURL')
294 SITEDOCURL=getEnv('SITEDOCURL')
295 TILEURL=getEnv('TILEURL')
296 DATAPROVIDERURL=getEnv('DATAPROVIDERURL')
297 TERRAINURL=getEnv('TERRAINURL')
298 # handle optional parameters
300 print("transportPCE forwarding disabled")
301 sedInFile('proxy_pass TRPCEURL/$1;','return 404;',FN)
303 sedInFile('TRPCEURL',TRPCEURL ,FN)
306 print("topology api forwarding disabled")
307 sedInFile('proxy_pass TOPOURL;','return 404;',FN)
309 sedInFile('TOPOURL',TOPOURL ,FN)
311 if SITEDOCURL is None:
312 print("sitedoc api forwarding disabled")
313 sedInFile('proxy_pass SITEDOCURL/topology/stadok/$1;','return 404;', FN)
315 sedInFile('SITEDOCURL',SITEDOCURL, FN)
318 print("tile server forwarding disabled")
319 sedInFile('proxy_pass TILEURL/$1;','return 404;',FN)
321 sedInFile('TILEURL',TILEURL ,FN)
323 if DATAPROVIDERURL is None:
324 print("data provider forwarding disabled")
325 sedInFile('proxy_pass DATAPROVIDERURL/$1;','return 404;',FN)
327 sedInFile('DATAPROVIDERURL',DATAPROVIDERURL ,FN)
329 if TERRAINURL is None:
330 print("terrain server forwarding disabled")
331 sedInFile('proxy_pass TERRAINURL/$1;','return 404;',FN)
333 sedInFile('TERRAINURL',TERRAINURL ,FN)