Display sc node config as tree view
display shared attribute in sc specs and node details page
Change-Id: I57b1cec1f697fb6c5295411d350d4d0f5225d71a
Closes-Bug: 1466912
(cherry picked from commit 4c0f73226b
)
@ -138,19 +138,19 @@ def update_policyaction_attributes(request, paction):
|
||||
|
||||
|
||||
def update_sc_spec_attributes(request, scspec):
|
||||
img_path = "/static/dashboard/images/"
|
||||
img_path = "/static/dashboard/img/"
|
||||
provider = "default"
|
||||
nodes = scspec.nodes
|
||||
nodes = [client.get_servicechain_node(request, item) for item in nodes]
|
||||
t = "<table class='table table-condensed' \
|
||||
style='margin-bottom:0px'><tr><td>"
|
||||
val = [t + "<span class='glyphicon glyphicon-remove-circle'></span></td>"]
|
||||
ds_path = "/opt/stack/horizon/static/dashboard/images/"
|
||||
ds_path = "/opt/stack/horizon/static/dashboard/img/"
|
||||
if os.path.exists(ds_path):
|
||||
local_img_path = ds_path
|
||||
else:
|
||||
local_img_path = "/usr/share/openstack-dashboard/openstack_dashboard/" \
|
||||
+ "static/dashboard/images/"
|
||||
+ "static/dashboard/img/"
|
||||
if os.path.exists(local_img_path):
|
||||
providers = os.listdir(local_img_path)
|
||||
for p in providers:
|
||||
|
@ -138,18 +138,79 @@ class ServiceChainNodeDetailsTab(tabs.Tab):
|
||||
config = scnode.config
|
||||
config = config.strip()
|
||||
if config.startswith('{'):
|
||||
config = json.loads(config)
|
||||
scnode.config = json.dumps(config, sort_keys=False, indent=4)
|
||||
config = yaml.load(config)
|
||||
if 'heat_template_version' in config:
|
||||
scnode.config = yaml.dump(
|
||||
config, default_flow_style=False, indent=4)
|
||||
else:
|
||||
scnode.config = json.dumps(
|
||||
config, sort_keys=False, indent=4)
|
||||
else:
|
||||
config = yaml.load(config)
|
||||
scnode.config = yaml.dump(
|
||||
config, default_flow_style=False, indent=4)
|
||||
scnode.tree = self.prepare_config_as_tree(config)
|
||||
except Exception:
|
||||
exceptions.handle(request, _(
|
||||
'Unable to retrieve service node details.'),
|
||||
redirect=self.failure_url)
|
||||
return {'scnode': scnode}
|
||||
|
||||
def prepare_config_as_tree(self, config):
|
||||
tree = []
|
||||
for key, value in config.iteritems():
|
||||
node = {}
|
||||
if isinstance(value, dict):
|
||||
node = self.prepare_root_node(value)
|
||||
node["text"] = key
|
||||
else:
|
||||
node["text"] = key + " : " + str(value)
|
||||
node["icon"] = "/static/dashboard/img/text.png"
|
||||
|
||||
tree.append(node)
|
||||
return json.dumps(tree)
|
||||
|
||||
def prepare_root_node(self, obj):
|
||||
node = {}
|
||||
if obj:
|
||||
children = self.prepare_children(obj)
|
||||
node["children"] = children
|
||||
state = {}
|
||||
state["opened"] = True
|
||||
node["state"] = state
|
||||
return node
|
||||
|
||||
def prepare_children(self, obj):
|
||||
children = []
|
||||
for key, value in obj.iteritems():
|
||||
node = {}
|
||||
child = self.json2array(value)
|
||||
node["text"] = key
|
||||
node["children"] = child
|
||||
children.append(node)
|
||||
|
||||
return children
|
||||
|
||||
def json2array(self, obj):
|
||||
arr = []
|
||||
for key, value in obj.iteritems():
|
||||
node = {}
|
||||
if isinstance(value, dict):
|
||||
children = self.json2array(value)
|
||||
node["text"] = key
|
||||
node["children"] = children
|
||||
elif isinstance(value, list):
|
||||
items = []
|
||||
for item in value:
|
||||
items.append(json.dumps(item))
|
||||
node["children"] = items
|
||||
node["text"] = key
|
||||
else:
|
||||
node["text"] = key + " : " + str(value)
|
||||
node["icon"] = "/static/dashboard/img/text.png"
|
||||
arr.append(node)
|
||||
return arr
|
||||
|
||||
|
||||
class SCNodeDetailsTabGroup(tabs.TabGroup):
|
||||
slug = 'scnode_details'
|
||||
@ -170,7 +231,20 @@ class ServiceChainSpecDetailsTab(tabs.Tab):
|
||||
gn = lambda x, y: client.get_servicechain_node(x, y)
|
||||
for node in scspec.nodes:
|
||||
n = gn(self.request, node)
|
||||
setattr(n, 'config', json.loads(n.config))
|
||||
config = n.config
|
||||
config = config.strip()
|
||||
if config.startswith('{'):
|
||||
config = yaml.load(config)
|
||||
if 'heat_template_version' in config:
|
||||
config = yaml.dump(
|
||||
config, default_flow_style=False, indent=4)
|
||||
else:
|
||||
config = json.dumps(config, sort_keys=False, indent=4)
|
||||
else:
|
||||
config = yaml.load(config)
|
||||
config = yaml.dump(
|
||||
config, default_flow_style=False, indent=4)
|
||||
setattr(n, 'config', config)
|
||||
nodes.append(n)
|
||||
setattr(scspec, 'nodes', nodes)
|
||||
except Exception:
|
||||
|
@ -1,9 +1,12 @@
|
||||
{% load i18n sizeformat parse_date %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block css %}
|
||||
<link href="/static/dashboard/css/jstree.css" rel='stylesheet' type='text/css'>
|
||||
{% endblock %}
|
||||
<div class="info row detail">
|
||||
<hr class="header_rule">
|
||||
<dl>
|
||||
<dl style="font-size:14px">
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd>{{ scnode.name|default:_("-") }}</dd>
|
||||
|
||||
@ -16,9 +19,42 @@
|
||||
<dt>{% trans "Service Profile" %}</dt>
|
||||
<dd><a href="{% url 'horizon:project:network_services:service_profile_details' sp_id=scnode.service_profile_id %}">{{ scnode.service_profile_id }}</a></dd>
|
||||
|
||||
<dt>{% trans "Config" %}</dt>
|
||||
<dd>
|
||||
<div style ="white-space:pre">{{ scnode.config }}</div>
|
||||
</dd>
|
||||
</dl>
|
||||
<dt>{% trans "Shared" %}</dt>
|
||||
<dd>{{ scnode.shared }}</dd>
|
||||
|
||||
<dt>
|
||||
<img src="/static/dashboard/img/config_as_text.png"
|
||||
data-swap="/static/dashboard/img/config_as_tree.png"
|
||||
id="display_format" alt="" > {% trans "Config" %}</dt>
|
||||
<dd >
|
||||
<div style="white-space:pre;display:none" id="config_text" >{{ scnode.config }} </div>
|
||||
<div id="config_tree"></div>
|
||||
</dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
{% block custom_js %}
|
||||
<script src='/static/dashboard/js/jstree.min.js' type='text/javascript'></script>
|
||||
<script type="text/javascript">
|
||||
function display_config_as_tree(){
|
||||
var data = JSON.stringify({{scnode.tree|safe}});
|
||||
$('#config_tree').jstree({ 'core' : {
|
||||
'data' : $.parseJSON(data),
|
||||
} });
|
||||
}
|
||||
function swap_image(_this){
|
||||
var current = _this.attr("src");
|
||||
var swap = _this.attr("data-swap");
|
||||
_this.attr('src', swap).attr("data-swap",current);
|
||||
}
|
||||
$(function(){
|
||||
display_config_as_tree();
|
||||
$("#display_format").click(function(){
|
||||
$("#config_text").toggle();
|
||||
$("#config_tree").toggle();
|
||||
swap_image($(this));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -12,6 +12,9 @@
|
||||
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ scspec.id }} </dd>
|
||||
|
||||
<dt>{% trans "Shared" %}</dt>
|
||||
<dd>{{ scspec.shared }}</dd>
|
||||
</dl>
|
||||
{% if scspec.nodes %}
|
||||
<div class="panel panel-default">
|
||||
@ -29,14 +32,14 @@
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url 'horizon:project:network_services:sc_node_details' scnode_id=node.id %}">
|
||||
{{node.name}}:{{node.id}}</a>
|
||||
{{node.name}}</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="{% url 'horizon:project:network_services:service_profile_details' sp_id=node.service_profile_id %}">
|
||||
{{ node.service_profile_id }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{node.config}}
|
||||
<div style ="white-space:pre;overflow-y: scroll;height:300px;background-color:#EEEEEE">{{node.config}}</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
1031
gbpui/static/dashboard/css/jstree.css
Normal file
BIN
gbpui/static/dashboard/img/32px.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
gbpui/static/dashboard/img/40px.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
gbpui/static/dashboard/img/config_as_text.png
Normal file
After Width: | Height: | Size: 1011 B |
BIN
gbpui/static/dashboard/img/config_as_tree.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 579 B After Width: | Height: | Size: 579 B |
Before Width: | Height: | Size: 717 B After Width: | Height: | Size: 717 B |
Before Width: | Height: | Size: 527 B After Width: | Height: | Size: 527 B |
BIN
gbpui/static/dashboard/img/text.png
Normal file
After Width: | Height: | Size: 477 B |
BIN
gbpui/static/dashboard/img/throbber.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
@ -56,7 +56,7 @@ horizon.Node = {
|
||||
var active_nodes = $("#selected_node > li").map(function(){
|
||||
return $(this).attr("name");
|
||||
});
|
||||
$("#nodeListId input:checkbox").removeAttr('checked');
|
||||
$("#nodeListId .multiple-checkbox input:checkbox").removeAttr('checked');
|
||||
active_nodes.each(function(index, value){
|
||||
$("#nodeListId input:checkbox[value=" + value + "]")
|
||||
.prop('checked', true)
|
||||
|