From 530271c247a4ce538e3aa69fd3893481fada44ab Mon Sep 17 00:00:00 2001 From: Sawyer Bergeron Date: Fri, 15 May 2020 14:58:37 -0400 Subject: Merge resource branch This pulls master up to date to include changes to models and surrounding infra that allow for multi-node templates and merging of pods Squashed commit of the following: commit abc8f27d9c6b05fb3afcb9b00dc35c0f2232d1a6 Author: Sawyer Bergeron Date: Thu Apr 2 14:05:26 2020 -0400 Start fixing workflow for model changes Change-Id: I79df975ef45abf2e6e69594d358bbd205938828f Signed-off-by: Sawyer Bergeron Signed-off-by: Sawyer Bergeron commit 7a7e2182acd0ea94e19aba4926c3a12771b30a6d Author: sms1097 Date: Tue Mar 31 15:13:06 2020 -0400 Working on workflow refactoring Change-Id: I4141b6aca98aff7bff9cb78a7d5594e25eb45e98 Signed-off-by: Sean Smith commit c09050ae2814f07af58557b40f9ed3559063d2c7 Merge: 71438d9 b5ccdc4 Author: Parker Berberian Date: Tue Mar 24 20:34:16 2020 +0000 Merge "Able to delete configurations and view lab details" into resource commit b5ccdc4ffbb883c20f2f6f69aeef5002aef5db53 Author: sms1097 Date: Thu Mar 19 17:08:12 2020 -0400 Able to delete configurations and view lab details Change-Id: Ib15c86d84f4cc7e7745551889ce91c89b5de46e2 Signed-off-by: Sean Smith Change-Id: Id6748c6bea67773a861921394d88579730246598 commit 71438d9a35cdb316cece865c9d410aeffb0053d8 Merge: 5460d0d a758223 Author: Parker Berberian Date: Thu Mar 19 18:51:09 2020 +0000 Merge "Add / Fix tests for refactor" into resource commit 5460d0d447b075433a763f9bfa33448b88ec8393 Merge: a9063a3 f55d839 Author: Parker Berberian Date: Wed Mar 18 15:59:37 2020 +0000 Merge "Fixed the quick booking form resource template filtering. Added some more models to the admin page." into resource commit f55d839a029ab1f5ab1273872e71a97fa1d5108b Author: Adam Hassick Date: Tue Mar 17 11:35:40 2020 -0400 Fixed the quick booking form resource template filtering. Added some more models to the admin page. Signed-off-by: Adam Hassick Change-Id: I2d2e7aeb96b10c231804a62f37a476039c954b7b commit a9063a347c4ebef0e53a17f198468bb135772810 Author: Parker Berberian Date: Wed Mar 18 10:29:51 2020 -0400 Fixes Some Issues with Quick Booking Seen in the Akraino lab Signed-off-by: Parker Berberian Change-Id: I2a1e843fbaa7984225f2f80742dad59dc348fbf2 commit a758223f44c6fec595b055d7c9b232b00e9174a0 Author: Parker Berberian Date: Tue Mar 17 11:07:32 2020 -0400 Add / Fix tests for refactor Change-Id: I0526d1942f87707082a4eb1c8c98910f84481c23 Signed-off-by: Parker Berberian Author: Parker Berberian Add "Pod" Column to booking list Signed-off-by: Parker Berberian Change-Id: I270913283bf1e5815cadf622ba2fd5f98bb61675 Author: Parker Berberian Fixes that make the Akraino dashboard work Signed-off-by: Parker Berberian Change-Id: I81746473a4511ef7d46445a7b16809a6e9da100f Signed-off-by: Sawyer Bergeron Change-Id: I4b428e7c8a8d401d7bae95cba01077feb0332a7f Signed-off-by: Sawyer Bergeron --- src/static/js/dashboard.js | 222 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 192 insertions(+), 30 deletions(-) (limited to 'src/static') diff --git a/src/static/js/dashboard.js b/src/static/js/dashboard.js index 6bff8d9..10c7d84 100644 --- a/src/static/js/dashboard.js +++ b/src/static/js/dashboard.js @@ -408,11 +408,8 @@ class MultipleSelectFilterWidget { this.dropdown_count++; const label = document.createElement("H5") label.appendChild(document.createTextNode(node['name'])) - label.classList.add("p-1", "m-1"); + label.classList.add("p-1", "m-1", "flex-grow-1"); div.appendChild(label); - let input = this.make_input(div, node, prepopulate); - input.classList.add("flex-grow-1", "p-1", "m-1"); - div.appendChild(input); let remove_btn = this.make_remove_button(div, node); remove_btn.classList.add("p-1", "m-1"); div.appendChild(remove_btn); @@ -425,10 +422,10 @@ class MultipleSelectFilterWidget { const node = this.filter_items[node_id] const parent = div.parentNode; div.parentNode.removeChild(div); - delete this.result[node.class][node.id]['values'][div.id]; + this.result[node.class][node.id]['count']--; //checks if we have removed last item in class - if(jQuery.isEmptyObject(this.result[node.class][node.id]['values'])){ + if(this.result[node.class][node.id]['count'] == 0){ delete this.result[node.class][node.id]; this.clear(node); } @@ -444,9 +441,9 @@ class MultipleSelectFilterWidget { updateObjectResult(node, childKey, childValue){ if(!this.result[node.class][node.id]) - this.result[node.class][node.id] = {selected: true, id: node.model_id, values: {}} + this.result[node.class][node.id] = {selected: true, id: node.model_id, count: 0} - this.result[node.class][node.id]['values'][childKey] = childValue; + this.result[node.class][node.id]['count']++; } finish(){ @@ -455,9 +452,41 @@ class MultipleSelectFilterWidget { } class NetworkStep { - constructor(debug, xml, hosts, added_hosts, removed_host_ids, graphContainer, overviewContainer, toolbarContainer){ - if(!this.check_support()) + // expects: + // + // debug: bool + // resources: { + // id: { + // id: int, + // value: { + // description: string, + // }, + // interfaces: [ + // id: int, + // name: str, + // description: str, + // connections: [ + // { + // network: int, [networks.id] + // tagged: bool + // } + // ], + // ], + // } + // } + // networks: { + // id: { + // id: int, + // name: str, + // public: bool, + // } + // } + // + constructor(debug, resources, networks, graphContainer, overviewContainer, toolbarContainer){ + if(!this.check_support()) { + console.log("Aborting, browser is not supported"); return; + } this.currentWindow = null; this.netCount = 0; @@ -470,9 +499,24 @@ class NetworkStep { this.editor = new mxEditor(); this.graph = this.editor.graph; + window.global_graph = this.graph; + window.network_rr_index = 5; + this.editor.setGraphContainer(graphContainer); this.doGlobalConfig(); - this.prefill(xml, hosts, added_hosts, removed_host_ids); + + let mx_networks = {} + + for(const network_id in networks) { + let network = networks[network_id]; + + mx_networks[network_id] = this.populateNetwork(network); + } + + this.prefillHosts(resources, mx_networks); + + //this.addToolbarButton(this.editor, toolbarContainer, 'zoomIn', '', "/static/img/mxgraph/zoom_in.png", true); + //this.addToolbarButton(this.editor, toolbarContainer, 'zoomOut', '', "/static/img/mxgraph/zoom_out.png", true); this.addToolbarButton(this.editor, toolbarContainer, 'zoomIn', 'fa-search-plus'); this.addToolbarButton(this.editor, toolbarContainer, 'zoomOut', 'fa-search-minus'); @@ -489,10 +533,6 @@ class NetworkStep { this.graph.addListener(mxEvent.CELL_CONNECTED, function(sender, event) {this.cellConnectionHandler(sender, event)}.bind(this)); //hooks up double click functionality this.graph.dblClick = function(evt, cell) {this.doubleClickHandler(evt, cell);}.bind(this); - - if(!this.has_public_net){ - this.addPublicNetwork(); - } } check_support(){ @@ -503,22 +543,84 @@ class NetworkStep { return true; } - prefill(xml, hosts, added_hosts, removed_host_ids){ - //populate existing data - if(xml){ - this.restoreFromXml(xml, this.editor); - } else if(hosts){ - for(const host of hosts) - this.makeHost(host); - } + /** + * Expects + * mx_interface: mxCell for the interface itself + * network: mxCell for the outer network + * tagged: bool + */ + connectNetwork(mx_interface, network, tagged) { + var cell = new mxCell( + "connection from " + network + " to " + mx_interface, + new mxGeometry(0, 0, 50, 50)); + cell.edge = true; + cell.geometry.relative = true; + cell.setValue(JSON.stringify({tagged: tagged})); + + let terminal = this.getClosestNetworkCell(mx_interface.geometry.y, network); + let edge = this.graph.addEdge(cell, null, mx_interface, terminal); + this.colorEdge(edge, terminal, true); + this.graph.refresh(edge); + } - //apply any changes - if(added_hosts){ - for(const host of added_hosts) - this.makeHost(host); - this.updateHosts([]); //TODO: why? + /** + * Expects: + * + * to: desired y axis position of the matching cell + * within: graph cell for a full network, with all child cells + * + * Returns: + * an mx cell, the one vertically closest to the desired value + * + * Side effect: + * modifies the on the parameter + */ + getClosestNetworkCell(to, within) { + if(window.network_rr_index === undefined) { + window.network_rr_index = 5; + } + + let child_keys = within.children.keys(); + let children = Array.from(within.children); + let index = (window.network_rr_index++) % children.length; + + let child = within.children[child_keys[index]]; + + return children[index]; + } + + /** Expects + * + * hosts: { + * id: { + * id: int, + * value: { + * description: string, + * }, + * interfaces: [ + * id: int, + * name: str, + * description: str, + * connections: [ + * { + * network: int, [networks.id] + * tagged: bool + * } + * ], + * ], + * } + * } + * + * network_mappings: { + * : + * } + * + * draws given hosts into the mxgraph + */ + prefillHosts(hosts, network_mappings){ + for(const host_id in hosts) { + this.makeHost(hosts[host_id], network_mappings); } - this.updateHosts(removed_host_ids); } cellConnectionHandler(sender, event){ @@ -625,7 +727,10 @@ class NetworkStep { color = kvp[1]; } } + edge.setStyle('strokeColor=' + color); + } else { + console.log("Failed to color " + edge + ", " + terminal + ", " + source); } } @@ -848,6 +953,7 @@ class NetworkStep { return true; } } + return false; }; @@ -926,6 +1032,27 @@ class NetworkStep { return ret_val; } + // expects: + // + // { + // id: int, + // name: str, + // public: bool, + // } + // + // returns: + // mxgraph id of network + populateNetwork(network) { + let mxNet = this.makeMxNetwork(network.name, network.public); + this.makeSidebarNetwork(network.name, mxNet.color, mxNet.element_id); + + if( network.public ) { + this.has_public_net = true; + } + + return mxNet.element_id; + } + addPublicNetwork() { const net = this.makeMxNetwork("public", true); this.makeSidebarNetwork("public", net['color'], net['element_id']); @@ -986,7 +1113,33 @@ class NetworkStep { document.getElementById("network_list").appendChild(newNet); } - makeHost(hostInfo) { + /** + * Expects format: + * { + * 'id': int, + * 'value': { + * 'description': string, + * }, + * 'interfaces': [ + * { + * id: int, + * name: str, + * description: str, + * connections: [ + * { + * network: int, , + * tagged: bool + * } + * ] + * } + * ] + * } + * + * network_mappings: { + * : + * } + */ + makeHost(hostInfo, network_mappings) { const value = JSON.stringify(hostInfo['value']); const interfaces = hostInfo['interfaces']; const width = 100; @@ -1022,6 +1175,15 @@ class NetworkStep { false ); port.getGeometry().offset = new mxPoint(-4*interfaces[i].name.length -2,0); + const iface = interfaces[i]; + for( const connection of iface.connections ) { + const network = this + .graph + .getModel() + .getCell(network_mappings[connection.network]); + + this.connectNetwork(port, network, connection.tagged); + } this.graph.refresh(port); } this.graph.refresh(host); -- cgit 1.2.3-korg