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)"
79 regexUrl = r"([0-9]+)([a-zA-Z]+)\.(url)"
81 matches = re.finditer(regex,file)
82 match = next(matches, None)
83 matchesUrl = re.finditer(regexUrl,file)
84 matchUrl = next(matchesUrl, None)
86 print("installing {}".format(file))
87 index = int(match.group(1))
89 add_application(name,index,INIT_FOLDER+'/'+file)
90 elif matchUrl is not None:
91 print("installing {}".format(file))
92 index = int(match.group(1))
94 add_application(name,index,INIT_FOLDER+'/'+file)
96 print("no index naming format found. try to autodetect")
97 infos = autoDetectInfosFromJar(file)
99 print("unable to detect index and application name for {}".format(file))
101 add_application(infos['name'],infos['index'],INIT_FOLDER+'/'+file)
105 def containsBlueprintExpression(file) -> bool:
106 print("check if file {} is blueprint".format(file))
107 with open(file, 'r') as fp:
108 lines = fp.readlines()
110 if "<blueprint" in line:
115 def findBlueprintXml(dir):
116 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']
118 if containsBlueprintExpression(file):
122 def autoDetectInfosFromJar(file):
123 print("autodetect infos(appName and index) from jar {}".format(file))
124 tmpDir=getRandomTempDir()
125 regexBundleName = r"<property[\ ]+name=\"bundleName\"[\ ]+value=\"([^\"]+)\""
126 regexIndex = r"<property[\ ]+name=\"index\"[\ ]+value=\"([^\"]+)\""
129 with zipfile.ZipFile(file, 'r') as zip_ref:
130 zip_ref.extractall(tmpDir)
131 blueprint = findBlueprintXml(tmpDir)
132 if blueprint is None:
134 with open(blueprint) as fp:
135 lines = fp.readlines()
138 matches = re.finditer(regexBundleName, line)
139 match = next(matches,None)
140 if match is not None:
141 name = match.group(1)
143 matches = re.finditer(regexIndex, line)
144 match = next(matches,None)
145 if match is not None:
146 index = int(match.group(1))
149 print("found infos from jar: name={} index={}".format(name,index))
150 return dict(index=index,name=name)
152 def getRandomTempDir(create=False):
154 dir='/tmp/{}'.format(uuid.uuid4())
155 if not os.path.exists(dir):
156 # print("found random not-existing dir {}".format(dir))
160 # print("dir {} already exists. try new".format(dir))
163 def getRandomTempFile():
164 dir = getRandomTempDir(True)
169 file='{}/{}.dat'.format(dir,uuid.uuid4())
170 if not os.path.exists(file):
171 # print("found random not-existing file {}".format(file))
173 # print("file {} already exists. try new".format(file))
178 tmpDir=getRandomTempDir()
179 with zipfile.ZipFile(fn, 'r') as zip_ref:
180 zip_ref.extractall(tmpDir)
181 exec(" ".join(['cp','-r',tmpDir+'/odlux/*',ODLUX_BASE_FOLDER+'/']))
185 def load_applications():
187 if os.path.exists(APPLICATION_LISTFILE):
188 with open(APPLICATION_LISTFILE,'r') as fp:
189 lines= fp.readlines()
191 if len(line.rstrip())<=0:
195 apps.append(dict(index=int(hlp[0]),name=hlp[1].rstrip()))
197 print('problem reading line {}'.format(line))
201 for app in DEFAULT_APPLICATIONS:
202 apps.append(dict(index=index,name=app))
204 # print('applications loaded={}'.format(apps))
205 return sorted(apps, key=lambda d: d['index'])
207 def write_applications(apps):
208 # print('saving applications={}'.format(apps))
209 apps = sorted(apps, key=lambda d: d['index'])
210 os.remove(APPLICATION_LISTFILE)
211 with open(APPLICATION_LISTFILE,'w') as fp:
213 fp.write('{} {}\n'.format(app['index'], app['name']))
216 def update_index_html(apps=None):
218 # # Backup the index.html file
219 if not os.path.exists(INDEX_HTML_TEMPLATE):
220 execToStdOut(['cp',INDEX_HTML,INDEX_HTML_TEMPLATE])
222 execToStdOut(['cp',INDEX_HTML_TEMPLATE,INDEX_HTML])
225 apps=load_applications()
226 ODLUX_AUTH_METHOD="basic"
227 ENABLE_ODLUX_RBAC=getEnv('ENABLE_ODLUX_RBAC','false')
228 TRPCEGUIURL=getEnv('TRPCEGUIURL')
230 if getEnv('ENABLE_OAUTH') == "true":
231 ODLUX_AUTH_METHOD="oauth"
232 ODLUX_CONFIG=dict(authentication=ODLUX_AUTH_METHOD,enablePolicy=ENABLE_ODLUX_RBAC == 'true')
233 print("authentication is {}".format(ODLUX_AUTH_METHOD))
234 print("rbac access is enabled: {}".format(ENABLE_ODLUX_RBAC))
236 if TRPCEGUIURL is not None:
237 ODLUX_CONFIG['transportpceUrl']=TRPCEGUIURL
238 print("trpce gui url is: {}".format(TRPCEGUIURL))
240 # 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
245 requireArg+='"{}",'.format(app['name'])
246 fnArgs+='{},'.format(app['name'])
247 appCalls+='{}.register();\\n'.format(app['name'])
248 #replace require expression
249 execToStdOut(['sed', '-z', 's/require(\["run"\],\ function\ (run)/require\(\[{}\"run\"\], function \({}run\)/'.format(requireArg,fnArgs), '-i', INDEX_HTML])
250 #replace run.runApplication expression
251 execToStdOut(['sed','-z', 's/run.runApplication();/{}run.runApplication();/'.format(appCalls), '-i',INDEX_HTML])
252 #replace run.configure expression if exists
253 execToStdOut(['sed', '-z', 's|run.configureApplication([^)]\+)|run.configureApplication({});|'.format(json.dumps(ODLUX_CONFIG)), '-i', INDEX_HTML])
256 def check_for_rule_template():
257 if os.path.exists('/opt/bitnami/nginx/conf/server_blocks/location.rules.tmpl'):
258 print("using template for forwarding rules")
259 execToStdOut(['cp','/opt/bitnami/nginx/conf/server_blocks/location.rules.tmpl','/opt/bitnami/nginx/conf/server_blocks/location.rules'])
261 def update_nginx_site_conf():
263 if getEnv('WEBPROTOCOL') == "HTTPS":
264 FN='/opt/bitnami/nginx/conf/server_blocks/https_site.conf'
265 execToStdOut(['rm', '/opt/bitnami/nginx/conf/server_blocks/http_site.conf'])
266 SSL_CERT_DIR=getEnv('SSL_CERT_DIR')
267 SSL_CERTIFICATE=getEnv('SSL_CERTIFICATE')
268 SSL_CERTIFICATE_KEY=getEnv('SSL_CERTIFICATE_KEY')
269 sedInFile('SSL_CERTIFICATE_KEY',SSL_CERTIFICATE_KEY,FN)
270 sedInFile('SSL_CERT_DIR',SSL_CERT_DIR,FN)
271 sedInFile('SSL_CERTIFICATE',SSL_CERTIFICATE, FN)
273 elif getEnv('WEBPROTOCOL') == "HTTP":
274 FN='/opt/bitnami/nginx/conf/server_blocks/http_site.conf'
275 execToStdOut(['rm', '/opt/bitnami/nginx/conf/server_blocks/https_site.conf'])
277 WEBPROTOCOL=getEnv('WEBPROTOCOL')
278 WEBPORT=getEnv('WEBPORT')
279 SDNRPROTOCOL=getEnv('SDNRPROTOCOL')
280 SDNRHOST=getEnv('SDNRHOST')
281 SDNRPORT=getEnv('SDNRPORT')
282 SDNRWEBSOCKETPORT=getEnv('SDNRWEBSOCKETPORT',SDNRPORT)
283 DNS_RESOLVER=getEnv('DNS_RESOLVER')
284 DNS_INTERNAL_RESOLVER=getEnv('DNS_INTERNAL_RESOLVER')
286 print("unknown env WEBPROTOCOL: {}".format(WEBPROTOCOL))
289 # replace needed base parameters
290 sedInFile('WEBPORT',WEBPORT,FN)
292 FN='/opt/bitnami/nginx/conf/server_blocks/location.rules'
293 # replace needed parameters in forwarding rules
294 sedInFile('WEBPORT',WEBPORT,FN)
295 sedInFile('SDNRPROTOCOL',SDNRPROTOCOL,FN)
296 sedInFile('SDNRHOST',SDNRHOST ,FN)
297 sedInFile('SDNRPORT',SDNRPORT,FN)
298 sedInFile('SDNRWEBSOCKETPORT',SDNRWEBSOCKETPORT, FN)
299 sedInFile('DNS_RESOLVER',DNS_RESOLVER ,FN)
300 sedInFile('DNS_INTERNAL_RESOLVER',DNS_INTERNAL_RESOLVER ,FN)
302 TRPCEURL=getEnv('TRPCEURL')
303 TOPOURL=getEnv('TOPOURL')
304 SITEDOCURL=getEnv('SITEDOCURL')
305 TILEURL=getEnv('TILEURL')
306 DATAPROVIDERURL=getEnv('DATAPROVIDERURL')
307 TERRAINURL=getEnv('TERRAINURL')
308 # handle optional parameters
310 print("transportPCE forwarding disabled")
311 sedInFile('proxy_pass TRPCEURL/$1;','return 404;',FN)
313 sedInFile('TRPCEURL',TRPCEURL ,FN)
316 print("topology api forwarding disabled")
317 sedInFile('proxy_pass TOPOURL;','return 404;',FN)
319 sedInFile('TOPOURL',TOPOURL ,FN)
321 if SITEDOCURL is None:
322 print("sitedoc api forwarding disabled")
323 sedInFile('proxy_pass SITEDOCURL/topology/stadok/$1;','return 404;', FN)
325 sedInFile('SITEDOCURL',SITEDOCURL, FN)
328 print("tile server forwarding disabled")
329 sedInFile('proxy_pass TILEURL/$1;','return 404;',FN)
331 sedInFile('TILEURL',TILEURL ,FN)
333 if DATAPROVIDERURL is None:
334 print("data provider forwarding disabled")
335 sedInFile('proxy_pass DATAPROVIDERURL/$1;','return 404;',FN)
337 sedInFile('DATAPROVIDERURL',DATAPROVIDERURL ,FN)
339 if TERRAINURL is None:
340 print("terrain server forwarding disabled")
341 sedInFile('proxy_pass TERRAINURL/$1;','return 404;',FN)
343 sedInFile('TERRAINURL',TERRAINURL ,FN)