1 |
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
2 |
|
# you may not use this file except in compliance with the License. |
3 |
|
# You may obtain a copy of the License at |
4 |
|
# |
5 |
|
# http://www.apache.org/licenses/LICENSE-2.0 |
6 |
|
# |
7 |
|
# Unless required by applicable law or agreed to in writing, software |
8 |
|
# distributed under the License is distributed on an "AS IS" BASIS, |
9 |
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
10 |
|
# implied. |
11 |
|
# See the License for the specific language governing permissions and |
12 |
|
# limitations under the License. |
13 |
|
|
14 |
0 |
""" |
15 |
|
Contains html text in variables to make and html response |
16 |
|
""" |
17 |
|
|
18 |
0 |
import yaml |
19 |
0 |
from http import HTTPStatus |
20 |
0 |
from html import escape as html_escape |
21 |
|
|
22 |
0 |
__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>" |
23 |
|
|
24 |
0 |
html_start = """ |
25 |
|
<!DOCTYPE html> |
26 |
|
<html> |
27 |
|
<head> |
28 |
|
<link href="/osm/static/style.css" rel="stylesheet"> |
29 |
|
<title>Welcome to OSM</title> |
30 |
|
<link rel="shortcut icon" href="/osm/static/favicon.ico"> |
31 |
|
</head> |
32 |
|
<body> |
33 |
|
<div id="osm_topmenu"> |
34 |
|
<div> |
35 |
|
<a href="https://osm.etsi.org"> <img src="/osm/static/OSM-logo.png" height="42" width="100" |
36 |
|
style="vertical-align:middle"> </a> |
37 |
|
<a>( {} )</a> |
38 |
|
<a href="/osm/pdu/v1/pdu_descriptors">PDUs </a> |
39 |
|
<a href="/osm/vnfpkgm/v1/vnf_packages">VNFDs </a> |
40 |
|
<a href="/osm/nsd/v1/ns_descriptors">NSDs </a> |
41 |
|
<a href="/osm/nslcm/v1/ns_instances">NSs </a> |
42 |
|
<a href="/osm/nst/v1/netslice_templates">NSTDs </a> |
43 |
|
<a href="/osm/nsilcm/v1/netslice_instances">NSIs </a> |
44 |
|
<a href="/osm/admin/v1/users">USERs </a> |
45 |
|
<a href="/osm/admin/v1/projects">PROJECTs </a> |
46 |
|
<a href="/osm/admin/v1/tokens">TOKENs </a> |
47 |
|
<a href="/osm/admin/v1/vim_accounts">VIMs </a> |
48 |
|
<a href="/osm/admin/v1/wim_accounts">WIMs </a> |
49 |
|
<a href="/osm/admin/v1/sdns">SDNs </a> |
50 |
|
<a href="/osm/admin/v1/k8sclusters">K8s_clusters </a> |
51 |
|
<a href="/osm/admin/v1/k8srepos">K8s_repos </a> |
52 |
|
<a href="/osm/nslcm/v1/subscriptions">NS_Subs </a> |
53 |
|
<a href="/osm/admin/v1/tokens?METHOD=DELETE">logout </a> |
54 |
|
</div> |
55 |
|
</div> |
56 |
|
""" |
57 |
|
|
58 |
0 |
html_body = """ |
59 |
|
<h1>{item}</h1> |
60 |
|
""" |
61 |
|
|
62 |
0 |
html_end = """ |
63 |
|
</body> |
64 |
|
</html> |
65 |
|
""" |
66 |
|
|
67 |
0 |
html_body_error = "<h2> Error <pre>{}</pre> </h2>" |
68 |
|
|
69 |
|
|
70 |
0 |
html_auth2 = """ |
71 |
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> |
72 |
|
<html> |
73 |
|
<head><META http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
74 |
|
<link href="/osm/static/style.css" rel="stylesheet"> |
75 |
|
<title>OSM Login</title> |
76 |
|
<link rel="shortcut icon" href="/osm/static/favicon.ico"> |
77 |
|
</head> |
78 |
|
<body> |
79 |
|
<div id="osm_header"> |
80 |
|
<div> |
81 |
|
<a href="https://osm.etsi.org"> <h1><img src="/osm/static/OSM-logo.png" style="vertical-align:middle"></h1> </a> |
82 |
|
</div> |
83 |
|
</div> |
84 |
|
<div id="osm_error_message"> |
85 |
|
<h1>{error}</h1> |
86 |
|
</div> |
87 |
|
<div class="gerritBody" id="osm_body"> |
88 |
|
<h1>Sign in to OSM</h1> |
89 |
|
<form action="/osm/admin/v1/tokens" id="login_form" method="POST"> |
90 |
|
<table style="border: 0;"> |
91 |
|
<tr><th>Username</th><td><input id="f_user" name="username" size="25" tabindex="1" type="text"></td></tr> |
92 |
|
<tr><th>Password</th><td><input id="f_pass" name="password" size="25" tabindex="2" type="password"></td></tr> |
93 |
|
<tr><td><input tabindex="3" type="submit" value="Sign In"></td></tr> |
94 |
|
</table> |
95 |
|
</form> |
96 |
|
<div style="clear: both; margin-top: 15px; padding-top: 2px; margin-bottom: 15px;"> |
97 |
|
<div id="osm_footer"> |
98 |
|
<div></div> |
99 |
|
</div> |
100 |
|
</div> |
101 |
|
</div> |
102 |
|
<script src="/osm/static/login.js"> </script> |
103 |
|
</body> |
104 |
|
</html> |
105 |
|
""" |
106 |
|
|
107 |
0 |
html_upload_body = """ |
108 |
|
<form action="/osm{}" method="post" enctype="multipart/form-data"> |
109 |
|
<h3> <table style="border: 0;"> <tr> |
110 |
|
<td> Upload {} descriptor (tar.gz) file: <input type="file" name="descriptor_file"/> </td> |
111 |
|
<td> <input type="submit" value="Upload"/> </td> |
112 |
|
</tr> </table> </h3> |
113 |
|
</form> |
114 |
|
""" |
115 |
|
|
116 |
0 |
html_nslcmop_body = """ |
117 |
|
<a href="/osm/nslcm/v1/ns_lcm_op_occs?nsInstanceId={id}">nslcm operations </a> |
118 |
|
<a href="/osm/nslcm/v1/vnf_instances?nsr-id-ref={id}">VNFRS </a> |
119 |
|
<form action="/osm/nslcm/v1/ns_instances/{id}/terminate" method="post" enctype="multipart/form-data"> |
120 |
|
<h3> <table style="border: 0;"> <tr> |
121 |
|
<td> <input type="submit" value="Terminate"/> </td> |
122 |
|
</tr> </table> </h3> |
123 |
|
</form> |
124 |
|
""" |
125 |
|
|
126 |
0 |
html_nsilcmop_body = """ |
127 |
|
<a href="/osm/nsilcm/v1/nsi_lcm_op_occs?netsliceInstanceId={id}">nsilcm operations </a> |
128 |
|
<form action="/osm/nsilcm/v1/netslice_instances/{id}/terminate" method="post" enctype="multipart/form-data"> |
129 |
|
<h3> <table style="border: 0;"> <tr> |
130 |
|
<td> <input type="submit" value="Terminate"/> </td> |
131 |
|
</tr> </table> </h3> |
132 |
|
</form> |
133 |
|
""" |
134 |
|
|
135 |
0 |
html_vnfpackage_body = """<a href="/osm/vnfpkgm/v1/vnf_packages/{id}/artifacts">Artifacts </a>""" |
136 |
0 |
html_nspackage_body = """<a href="/osm/nsd/v1/ns_descriptors/{id}/artifacts">Artifacts </a>""" |
137 |
|
|
138 |
|
|
139 |
0 |
def format(data, request, response, toke_info): |
140 |
|
""" |
141 |
|
Format a nice html response, depending on the data |
142 |
|
:param data: |
143 |
|
:param request: cherrypy request |
144 |
|
:param response: cherrypy response |
145 |
|
:return: string with teh html response |
146 |
|
""" |
147 |
0 |
response.headers["Content-Type"] = 'text/html' |
148 |
0 |
if response.status == HTTPStatus.UNAUTHORIZED.value: |
149 |
0 |
if response.headers.get("WWW-Authenticate") and request.config.get("auth.allow_basic_authentication"): |
150 |
0 |
response.headers["WWW-Authenticate"] = "Basic" + response.headers["WWW-Authenticate"][6:] |
151 |
0 |
return |
152 |
|
else: |
153 |
0 |
return html_auth2.format(error=data) |
154 |
0 |
if request.path_info in ("/version", "/system"): |
155 |
0 |
return "<pre>" + yaml.safe_dump(data, explicit_start=False, indent=4, default_flow_style=False) + "</pre>" |
156 |
0 |
body = html_body.format(item=html_escape(request.path_info)) |
157 |
0 |
if response.status and response.status > 202: |
158 |
|
# input request.path_info (URL) can contain XSS that are translated into output error detail |
159 |
0 |
body += html_body_error.format(html_escape( |
160 |
|
yaml.safe_dump(data, explicit_start=True, indent=4, default_flow_style=False))) |
161 |
0 |
elif isinstance(data, (list, tuple)): |
162 |
0 |
if request.path_info == "/vnfpkgm/v1/vnf_packages": |
163 |
0 |
body += html_upload_body.format(request.path_info + "_content", "VNFD") |
164 |
0 |
elif request.path_info == "/nsd/v1/ns_descriptors": |
165 |
0 |
body += html_upload_body.format(request.path_info + "_content", "NSD") |
166 |
0 |
elif request.path_info == "/nst/v1/nst_templates": |
167 |
0 |
body += html_upload_body.format(request.path_info + "_content", "NSTD") |
168 |
0 |
for k in data: |
169 |
0 |
if isinstance(k, dict): |
170 |
0 |
data_id = k.pop("_id", None) |
171 |
0 |
elif isinstance(k, str): |
172 |
0 |
data_id = k |
173 |
0 |
body += '<p> <a href="/osm/{url}/{id}">{id}</a>: {t} </p>'.format(url=request.path_info, id=data_id, |
174 |
|
t=html_escape(str(k))) |
175 |
0 |
elif isinstance(data, dict): |
176 |
0 |
if "Location" in response.headers: |
177 |
0 |
body += '<a href="{}"> show </a>'.format(response.headers["Location"]) |
178 |
|
else: |
179 |
0 |
_id = request.path_info[request.path_info.rfind("/")+1:] |
180 |
0 |
body += '<a href="/osm/{}?METHOD=DELETE"> <img src="/osm/static/delete.png" height="25" width="25"> </a>'\ |
181 |
|
.format(request.path_info) |
182 |
0 |
if request.path_info.startswith("/nslcm/v1/ns_instances_content/") or \ |
183 |
|
request.path_info.startswith("/nslcm/v1/ns_instances/"): |
184 |
0 |
body += html_nslcmop_body.format(id=_id) |
185 |
0 |
elif request.path_info.startswith("/nsilcm/v1/netslice_instances_content/") or \ |
186 |
|
request.path_info.startswith("/nsilcm/v1/netslice_instances/"): |
187 |
0 |
body += html_nsilcmop_body.format(id=_id) |
188 |
0 |
elif request.path_info.startswith("/vnfpkgm/v1/vnf_packages/") or \ |
189 |
|
request.path_info.startswith("/vnfpkgm/v1/vnf_packages_content/"): |
190 |
0 |
body += html_vnfpackage_body.format(id=_id) |
191 |
0 |
elif request.path_info.startswith("/nsd/v1/ns_descriptors/") or \ |
192 |
|
request.path_info.startswith("/nsd/v1/ns_descriptors_content/"): |
193 |
0 |
body += html_nspackage_body.format(id=_id) |
194 |
0 |
body += "<pre>" + html_escape(yaml.safe_dump(data, explicit_start=True, indent=4, default_flow_style=False)) + \ |
195 |
|
"</pre>" |
196 |
0 |
elif data is None: |
197 |
0 |
if request.method == "DELETE" or "METHOD=DELETE" in request.query_string: |
198 |
0 |
body += "<pre> deleted </pre>" |
199 |
|
else: |
200 |
0 |
body = html_escape(str(data)) |
201 |
0 |
user_text = " " |
202 |
0 |
if toke_info: |
203 |
0 |
if toke_info.get("username"): |
204 |
0 |
user_text += "user: {}".format(toke_info.get("username")) |
205 |
0 |
if toke_info.get("project_id"): |
206 |
0 |
user_text += ", project: {}".format(toke_info.get("project_name")) |
207 |
0 |
return html_start.format(user_text) + body + html_end |
208 |
|
# yaml.safe_dump(data, explicit_start=True, indent=4, default_flow_style=False) |
209 |
|
# tags=False, |
210 |
|
# encoding='utf-8', allow_unicode=True) |