cpee-model-management 1.0.16 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,98 +1,19 @@
1
- <description xmlns="http://riddl.org/ns/description/1.0" xmlns:ann="http://riddl.org/ns/annotation/1.0" xmlns:xi="http://www.w3.org/2001/XInclude" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
2
- <message name="item">
3
- <parameter name="stage" type="string">
4
- <xi:include href="stages"/>
5
- </parameter>
6
- <parameter name="new" type="string">
7
- <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+</param>
8
- </parameter>
9
- </message>
10
- <message name="name">
11
- <parameter name="new" type="string">
12
- <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+</param>
13
- </parameter>
14
- </message>
15
- <message name="dir">
16
- <parameter name="dir" type="string">
17
- <param name="pattern">([a-zA-Z0-9öäüÖÄÜ _-]+)|</param>
18
- </parameter>
19
- </message>
20
- <message name="dirname">
21
- <parameter name="dir" type="string">
22
- <param name="pattern">([a-zA-Z0-9öäüÖÄÜ _-]+)\.dir|</param>
23
- </parameter>
24
- </message>
25
- <message name="duplicate">
26
- <parameter name="new" type="string">
27
- <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+</param>
28
- </parameter>
29
- <parameter name="old" type="string">
30
- <param name="pattern">[a-zA-Z0-9öäüÖÄÜ _-]+\.xml</param>
31
- </parameter>
32
- </message>
33
- <message name="stages">
34
- <parameter name="stages" type="string"/>
35
- </message>
36
- <message name="newstage">
37
- <parameter name="stage" type="string">
38
- <xi:include href="stages"/>
39
- </parameter>
40
- </message>
41
- <message name="stage">
42
- <optional>
43
- <parameter name="stage" type="string">
44
- <xi:include href="stages"/>
45
- </parameter>
46
- </optional>
47
- </message>
48
- <message name="full">
49
- <parameter name="full" type="string"/>
50
- <optional>
51
- <parameter name="stage" type="string">
52
- <xi:include href="stages"/>
53
- </parameter>
54
- </optional>
55
- </message>
56
- <message name="list">
57
- <parameter name="list" mimetype="application/json"/>
58
- </message>
59
- <message name="content">
60
- <parameter name="content" mimetype="application/xml"/>
61
- </message>
62
- <resource>
63
- <post in="item"/>
64
- <post in="dir"/>
65
- <post in="duplicate"/>
66
- <get in="stage" out="list"/>
67
- <get in="full" out="list"/>
68
- <get in="stages" out="list"/>
69
- <sse/>
70
- <resource relative="[a-zA-Z0-9&#xF6;&#xE4;&#xFC;&#xD6;&#xC4;&#xDC; _-]+\.dir">
71
- <post in="item"/>
72
- <post in="duplicate"/>
73
- <get in="stage" out="list"/>
74
- <delete/>
75
- <put in="name"/> <!-- rename -->
76
- <resource relative="[a-zA-Z0-9&#xF6;&#xE4;&#xFC;&#xD6;&#xC4;&#xDC; _-]+\.xml">
77
- <get out='content'/>
78
- <delete/>
79
- <put in="content"/>
80
- <put in="name"/> <!-- rename -->
81
- <put in="dirname"/> <!-- move -->
82
- <put in="newstage"/> <!-- shift -->
83
- <resource relative="open"><get in="stage"/></resource>
84
- <resource relative="open-new"><get in="stage"/></resource>
85
- </resource>
86
- </resource>
87
- <resource relative="[a-zA-Z0-9&#xF6;&#xE4;&#xFC;&#xD6;&#xC4;&#xDC; _-]+\.xml">
88
- <get out='content'/>
89
- <delete/>
90
- <put in="content"/>
91
- <put in="name"/> <!-- rename -->
92
- <put in="dirname"/> <!-- move -->
93
- <put in="newstage"/> <!-- shift -->
94
- <resource relative="open"><get in="stage"/></resource>
95
- <resource relative="open-new"><get in="stage"/></resource>
96
- </resource>
97
- </resource>
98
- </description>
1
+ <declaration xmlns="http://riddl.org/ns/declaration/1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
2
+ <interface name="implementation">
3
+ <xi:include href="implementation.xml"/>
4
+ </interface>
5
+ <interface name="events">
6
+ <xi:include href="http://www.riddl.org/ns/common-patterns/notifications-consumer/2.0/consumer.xml"/>
7
+ </interface>
8
+
9
+ <facade>
10
+ <tile>
11
+ <layer name="implementation">
12
+ <apply-to>/</apply-to>
13
+ </layer>
14
+ <layer name="events">
15
+ <apply-to>/dash/events</apply-to>
16
+ </layer>
17
+ </tile>
18
+ </facade>
19
+ </declaration>
data/server/moma.conf CHANGED
@@ -2,6 +2,7 @@
2
2
  :models: models
3
3
  :location: https://cpee.org/design/server/
4
4
  :instantiate: https://cpee.org/flow/start/
5
+ :show: https://cpee.org/flow/index.html?monitor=
5
6
  :cockpit:
6
7
  draft: https://cpee.org/flow/model.html?monitor=
7
8
  development: https://cpee.org/flow/edit.html?monitor=
data/ui/css/design.css CHANGED
@@ -26,6 +26,11 @@ ui-behind {
26
26
  color: #d0d0d0;
27
27
  }
28
28
 
29
+ ui-area > *:first-child {
30
+ padding-top: 0;
31
+ margin-top: 0;
32
+ }
33
+
29
34
  ui-behind span {
30
35
  cursor: pointer;
31
36
  }
data/ui/css/stats.css ADDED
@@ -0,0 +1,55 @@
1
+ #resources h1 {
2
+ font-size: 1.2em;
3
+ border-bottom: 0.1em solid var(--x-ui-border-color);
4
+ }
5
+
6
+ #resources table {
7
+ margin-left: 1.3em;
8
+ }
9
+
10
+ #instances h1 {
11
+ font-size: 1.2em;
12
+ border-bottom: 0.1em solid var(--x-ui-border-color);
13
+ }
14
+
15
+ .instances .text {
16
+ white-space: nowrap;
17
+ }
18
+ .instances .text > td {
19
+ display: inline-block;
20
+ white-space: nowrap;
21
+ overflow: hidden;
22
+ text-overflow: ellipsis;
23
+ padding-right: 0.5em;
24
+ padding-left: 0.5em;
25
+ }
26
+
27
+ .instances .name {
28
+ width: 12em;
29
+ }
30
+ .instances .state {
31
+ width: 7em
32
+ }
33
+ .instances .state:not([data-state=ready]):not([data-state=stopped]) > span.abandon {
34
+ display: none;
35
+ }
36
+ .instances .author {
37
+ width: 12em
38
+ }
39
+
40
+ .instances tr.sub, .instances tr.sub > td {
41
+ margin:0;
42
+ padding:0;
43
+ }
44
+
45
+ .instances .sub table {
46
+ margin-left: 0.8em;
47
+ }
48
+ .instances .sub table > tr.text > td:first-child::before {
49
+ content: '⤷';
50
+ margin-right: 0.5em;
51
+ }
52
+
53
+ .instances tr.text.even td {
54
+ background-color: var(--x-ui-content-light-background);
55
+ }
@@ -0,0 +1,7 @@
1
+ [is="x-ui-"] {
2
+ padding: 1em;
3
+ }
4
+ [is="x-ui-"] *:first-child {
5
+ padding-top: 0;
6
+ margin-top: 0;
7
+ }
data/ui/index.html CHANGED
@@ -35,6 +35,7 @@
35
35
  <script type="text/javascript" src="/js_libs/underscore.min.js"></script>
36
36
  <script type="text/javascript" src="/js_libs/jquery.caret.min.js"></script>
37
37
  <script type="text/javascript" src="/js_libs/jquery.cookie.js"></script>
38
+ <script type="text/javascript" src="/js_libs/plotly.min.js"></script>
38
39
 
39
40
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
40
41
 
@@ -52,20 +53,22 @@
52
53
 
53
54
  <!-- custom stuff, play arround -->
54
55
  <link rel="stylesheet" href="css/design.css" type="text/css"/>
56
+ <link rel="stylesheet" href="css/stats.css" type="text/css"/>
55
57
  <script type="text/javascript" src="js/design.js"></script>
58
+ <script type="text/javascript" src="js/stats.js"></script>
56
59
  </head>
57
60
  <body is="x-ui-">
58
61
  <ui-rest id="main">
59
62
  <ui-tabbar>
60
- <ui-before ></ui-before>
61
- <ui-tab class="" data-tab="models" >Models</ui-tab>
62
- <ui-tab class="inactive" data-tab="newmodel">New Model</ui-tab>
63
- <ui-tab class="inactive" data-tab="newdir" >New Dir</ui-tab>
64
- <ui-space ></ui-space>
65
- <ui-tab class="inactive" data-tab="running" >Running</ui-tab>
66
- <ui-tab class="inactive" data-tab="stopped" >Stopped</ui-tab>
67
- <ui-behind ><span></span></ui-behind>
68
- <ui-last ><a class="logo" href=".."></a></ui-last>
63
+ <ui-before ></ui-before>
64
+ <ui-tab class="" data-tab="models" >Models</ui-tab>
65
+ <ui-tab class="inactive" data-tab="newmodel" >New Model</ui-tab>
66
+ <ui-tab class="inactive" data-tab="newdir" >New Dir</ui-tab>
67
+ <ui-space ></ui-space>
68
+ <ui-tab class="inactive" data-tab="instances">Instances</ui-tab>
69
+ <ui-tab class="inactive" data-tab="resources">Resources</ui-tab>
70
+ <ui-behind ><span></span></ui-behind>
71
+ <ui-last ><a class="logo" href=".."></a></ui-last>
69
72
  </ui-tabbar>
70
73
  <ui-content class="noselect">
71
74
  <ui-area data-belongs-to-tab="models">
@@ -160,7 +163,63 @@
160
163
  <p>
161
164
  <button>New Directory</button>
162
165
  </p>
163
- </id>
166
+ </form>
167
+ </ui-area>
168
+ <ui-area data-belongs-to-tab="instances" class="inactive">
169
+ <p>
170
+ Show ready, running and stopped instances.
171
+ </p>
172
+ <template id="stats_instances">
173
+ <h1 class="stats_title">Engine: </h1>
174
+ <table class='instances'></table>
175
+ </template>
176
+ <template id="stats_instance">
177
+ <tr class="text">
178
+ <td class="name"><a href='' target='_blank'><em>no name</em></a></td>
179
+ <td class="num">(<span></span>)</td>
180
+ <td class="state"><span class='value'></span> <span class='abandon'>[<a href='#' title='abandon'>a</a>]</span></td>
181
+ <td class="author"><em>unknown</em></td>
182
+ <td class="cpu"></td>
183
+ <td>/</td>
184
+ <td class="mem"></em></td>
185
+ </tr>
186
+ <tr class="sub">
187
+ <td colspan="6"><table></table></td>
188
+ </tr>
189
+ </template>
190
+ <div id='instances'></div>
191
+ </ui-area>
192
+ <ui-area data-belongs-to-tab="resources" class="inactive">
193
+ <p>
194
+ Show statistics about instances per server, and metrics about the health of the environment.
195
+ </p>
196
+ <template id="stats_engine">
197
+ <h1 class="stats_title">Engine: </h1>
198
+ <div class="stats_plot"></div>
199
+ <div class="stats_text">
200
+ <table>
201
+ <tbody>
202
+ <tr>
203
+ <td>Total Instances <strong>Created</strong> / <strong>Finished</strong> / <strong>Abandoned</strong>:</td>
204
+ <td class='total_created'></td>
205
+ <td>/</td>
206
+ <td class='total_finished'></td>
207
+ <td>/</td>
208
+ <td class='total_abandoned'></td>
209
+ </tr>
210
+ <tr>
211
+ <td>Instances Currently <strong>Ready</strong> / <strong>Running</strong> / <strong>Stopped</strong>:</td>
212
+ <td class='current_ready'></td>
213
+ <td>/</td>
214
+ <td class='current_running'></td>
215
+ <td>/</td>
216
+ <td class='current_stopped'></td>
217
+ </tr>
218
+ </tbody>
219
+ </table>
220
+ </div>
221
+ </template>
222
+ <div id='resources'></div>
164
223
  </ui-area>
165
224
  </ui-content>
166
225
  </ui-rest>
data/ui/instances.html ADDED
@@ -0,0 +1,84 @@
1
+ <!--
2
+ This file is part of CPEE-MODEL-MANAGEMENT.
3
+
4
+ CPEE-MODEL-MANAGEMENT is free software: you can redistribute it and/or
5
+ modify it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or (at your
7
+ option) any later version.
8
+
9
+ CPEE-MODEL-MANAGEMENT is distributed in the hope that it will be useful, but
10
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
+ more details.
13
+
14
+ You should have received a copy of the GNU General Public License along with
15
+ CPEE-MODEL-MANAGEMENT (file LICENSE in the main directory). If not, see
16
+ <http://www.gnu.org/licenses/>.
17
+ -->
18
+
19
+ <!DOCTYPE html>
20
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
21
+ <head>
22
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
23
+ <title>Instances</title>
24
+
25
+ <!-- libs, do not modify. When local than load local libs. -->
26
+ <script type="text/javascript" src="/js_libs/jquery.min.js"></script>
27
+ <script type="text/javascript" src="/js_libs/jquery.browser.js"></script>
28
+ <script type="text/javascript" src="/js_libs/jquery.svg.min.js"></script>
29
+ <script type="text/javascript" src="/js_libs/jquery.svgdom.min.js"></script>
30
+ <script type="text/javascript" src="/js_libs/vkbeautify.js"></script>
31
+ <script type="text/javascript" src="/js_libs/util.js"></script>
32
+ <script type="text/javascript" src="/js_libs/printf.js"></script>
33
+ <script type="text/javascript" src="/js_libs/strftime.min.js"></script>
34
+ <script type="text/javascript" src="/js_libs/parsequery.js"></script>
35
+ <script type="text/javascript" src="/js_libs/underscore.min.js"></script>
36
+ <script type="text/javascript" src="/js_libs/jquery.caret.min.js"></script>
37
+ <script type="text/javascript" src="/js_libs/jquery.cookie.js"></script>
38
+ <script type="text/javascript" src="/js_libs/plotly.min.js"></script>
39
+
40
+ <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
41
+
42
+ <script type="text/javascript" src="/js_libs/relaxngui.js"></script>
43
+
44
+ <script type="text/javascript" src="/js_libs/uidash.js"></script>
45
+ <script type="text/javascript" src="/js_libs/custommenu.js"></script>
46
+
47
+ <link rel="stylesheet" href="/js_libs/custommenu.css" type="text/css"/>
48
+ <link rel="stylesheet" href="/js_libs/uidash.css" type="text/css"/>
49
+
50
+ <link rel="stylesheet" href="/global_ui/ui.css" type="text/css"/>
51
+
52
+ <link rel="stylesheet" href="/js_libs/relaxngui.css" type="text/css"/>
53
+
54
+ <!-- custom stuff, play arround -->
55
+ <link rel="stylesheet" href="css/design.css" type="text/css"/>
56
+ <link rel="stylesheet" href="css/stats.css" type="text/css"/>
57
+ <link rel="stylesheet" href="css/stats_standalone.css" type="text/css"/>
58
+ <script type="text/javascript" src="js/stats.js"></script>
59
+ </head>
60
+ <body is="x-ui-">
61
+ <p>
62
+ Show ready, running and stopped instances.
63
+ </p>
64
+ <template id="stats_instances">
65
+ <h1 class="stats_title">Engine: </h1>
66
+ <table class='instances'></table>
67
+ </template>
68
+ <template id="stats_instance">
69
+ <tr class="text">
70
+ <td class="name"><a href='' target='_blank'><em>no name</em></a></td>
71
+ <td class="num">(<span></span>)</td>
72
+ <td class="state"><span class='value'></span> <span class='abandon'>[<a href='#' title='abandon'>a</a>]</span></td>
73
+ <td class="author"><em>unknown</em></td>
74
+ <td class="cpu"></td>
75
+ <td>/</td>
76
+ <td class="mem"></em></td>
77
+ </tr>
78
+ <tr class="sub">
79
+ <td colspan="6"><table></table></td>
80
+ </tr>
81
+ </template>
82
+ <div id='instances'></div>
83
+ </body>
84
+ </html>
data/ui/js/design.js CHANGED
@@ -44,17 +44,17 @@ function delete_it(name) {
44
44
  }
45
45
  }
46
46
 
47
- function es_init(gdir,gstage) {
47
+ function design_init(gdir,gstage) {
48
48
  var es = new EventSource('server/');
49
49
  es.onopen = function() {
50
- console.log('es open');
50
+ console.log('design open');
51
51
  };
52
52
  es.onmessage = function(e) {
53
53
  paint(gdir,gstage);
54
54
  };
55
55
  es.onerror = function() {
56
- console.log('es error');
57
- // es_init();
56
+ console.log('design error');
57
+ // design_init();
58
58
  };
59
59
  }
60
60
 
@@ -88,6 +88,12 @@ function paint(gdir,gstage) {
88
88
  $('[data-class=guarded] abbr',clone).attr('title',data['guarded'] || '');
89
89
  $('[data-class=guarded] abbr',clone).text((data['guarded'] || '').match(/none/i) ? '' : (data['guarded'] || '').charAt(0).toUpperCase());
90
90
  $('[data-class=resource]',clone).text(data['guarded_id'] || '');
91
+
92
+ if (data['guarded']) {
93
+ $('[data-class=guarded] abbr',clone).attr('title',data['guarded']);
94
+ $('[data-class=guarded] abbr',clone).text(data['guarded'].match(/none/i) ? '' : data['guarded'].charAt(0).toUpperCase());
95
+ $('[data-class=resource]',clone).text(data['guarded_what']);
96
+ }
91
97
  }
92
98
  $('[data-class=author]',clone).text(data['author']);
93
99
  $('[data-class=date]',clone).text(new Date(data['date']).strftime('%Y-%m-%d, %H:%M:%S'));
@@ -108,7 +114,7 @@ $(document).ready(function() {
108
114
  gstage = urlParams.get('stage') || 'draft';
109
115
  gdir = urlParams.get('dir') ? (urlParams.get('dir') + '/').replace(/\/+/,'/') : '';
110
116
 
111
- es_init(gdir,gstage);
117
+ design_init(gdir,gstage);
112
118
 
113
119
  var shifts = []
114
120
  $.ajax({
data/ui/js/stats.js ADDED
@@ -0,0 +1,223 @@
1
+ var value_count = 100
2
+
3
+ function resource_update(ename) {
4
+ var iname = ename.replace(/[^a-z0-9A-Z]/g,'-').replace(/-$/,'')
5
+ $.get('server/dash/stats/',{ engine: ename },function(data){
6
+ $('#resource_utilization_text_' + iname + ' .total_created').text(data.total_created)
7
+ $('#resource_utilization_text_' + iname + ' .total_finished').text(data.total_finished)
8
+ $('#resource_utilization_text_' + iname + ' .total_abandoned').text(data.total_abandoned)
9
+ $('#resource_utilization_text_' + iname + ' .current_ready').text(data.ready)
10
+ $('#resource_utilization_text_' + iname + ' .current_running').text(data.running)
11
+ $('#resource_utilization_text_' + iname + ' .current_stopped').text(data.stopped)
12
+ });
13
+ }
14
+
15
+ function resource_add(ename) {
16
+ let inode = document.importNode($("#stats_engine")[0].content,true);
17
+ var iname = ename.replace(/[^a-z0-9A-Z]/g,'-').replace(/-$/,'')
18
+ $('.stats_title',inode).text($('.stats_title',inode).text() + ename)
19
+ $('.stats_plot',inode).attr('id','resource_utilization_plot_'+iname)
20
+ $('.stats_text',inode).attr('id','resource_utilization_text_'+iname)
21
+
22
+ $('#resources').append(inode)
23
+
24
+ resource_update(ename);
25
+
26
+ var trace1 = {
27
+ y: Array(value_count).fill(0),
28
+ type: 'scatter',
29
+ name: '% CPU'
30
+ };
31
+
32
+ var trace2 = {
33
+ y: Array(value_count).fill(0),
34
+ type: 'scatter',
35
+ name: '% Mem Used'
36
+ };
37
+
38
+ var layout = {
39
+ margin: {t:0,r:0,b:0,l:20},
40
+ height: 200,
41
+ width: 700,
42
+ yaxis: {
43
+ range: [-5, 105]
44
+ },
45
+ xaxis: {
46
+ showticklabels: false,
47
+ fixedrange: true
48
+ }
49
+ };
50
+
51
+ var data = [trace1, trace2];
52
+
53
+ Plotly.newPlot('resource_utilization_plot_' + iname, data, layout, {displayModeBar: false});
54
+ }
55
+
56
+ function instance_change(d) {
57
+ const ename = d.engine
58
+ const iname = d.engine.replace(/[^a-z0-9A-Z]/g,'-').replace(/-$/,'')
59
+
60
+ if (d.state == "ready") {
61
+ if ($('[data-id=' + d.uuid + ']').length > 0) {
62
+ if ($('[data-id=' + d.uuid + ']').attr('data-parent') != parent) {
63
+ $('[data-id=' + d.uuid + ']').remove()
64
+ instance_add(iname,d.uuid,d.url,d.name,d.state,d.author,0,0,d.parent)
65
+ } else {
66
+ instance_upd(d.uuid,d.name,d.state,d.author,0,0,d.parent)
67
+ }
68
+ } else {
69
+ instance_add(iname,d.uuid,d.url,d.name,d.state,d.author,0,0,d.parent)
70
+ }
71
+ } else if (d.state == 'abandoned' || d.state == 'finished') {
72
+ if ($('tr.sub[data-id=' + d.uuid + '] > td > table > tr').length > 0) {
73
+ $('tr.text[data-id=' + d.uuid + ']').replaceWith($('tr.sub[data-id=' + d.uuid + '] > td > table > tr'))
74
+ }
75
+ $('[data-id=' + d.uuid + ']').remove()
76
+ instances_striping(iname)
77
+ } else {
78
+ if ($('tr.sub[data-id=' + d.uuid + ']').attr('data-parent') != d.parent) {
79
+ $('[data-id=' + d.uuid + ']').remove()
80
+ instance_add(iname,d.uuid,d.url,d.name,d.state,d.author,0,0,d.parent)
81
+ } else {
82
+ instance_upd(d.uuid,d.name,d.state,d.author,0,0,d.parent)
83
+ }
84
+ }
85
+ }
86
+
87
+ function instance_upd(uuid,name,state,author,cpu,mem,parent) {
88
+ if (name != "") {
89
+ $('[data-id=' + uuid + '] > .name a').text(name)
90
+ }
91
+ $('[data-id=' + uuid + '] > .state span.value').text(state)
92
+ $('[data-id=' + uuid + '] > .state').attr('data-state',state)
93
+ if (author != "") {
94
+ $('[data-id=' + uuid + '] > .author').text(author)
95
+ }
96
+ instance_res(uuid,cpu,mem)
97
+ }
98
+ function instance_res(uuid,cpu,mem) {
99
+ $('[data-id=' + uuid + '] > .cpu').text($.sprintf('%05.2f',cpu))
100
+ $('[data-id=' + uuid + '] > .mem').text($.sprintf('%05.2f',mem))
101
+ }
102
+ function instance_add(iname,uuid,url,name,state,author,cpu,mem,parent) {
103
+ let inode = document.importNode($("#stats_instance")[0].content,true);
104
+ $('.sub',inode).attr('id',uuid)
105
+ $('.sub',inode).attr('data-id',uuid)
106
+ $('.sub',inode).attr('data-parent',parent)
107
+ $('.text',inode).attr('data-id',uuid)
108
+ $('.text',inode).attr('data-url',url)
109
+ $('.name a',inode).attr('href','server/dash/show?url=' + url)
110
+ $('.num span',inode).text(url.split(/[\\/]/).pop())
111
+ if (name != "") {
112
+ $('.name a',inode).text(name)
113
+ }
114
+ $('.state span.value',inode).text(state)
115
+ $('.state',inode).attr('data-state',state)
116
+ if (author != "") {
117
+ $('.author',inode).text(author)
118
+ }
119
+ $('.cpu',inode).text($.sprintf('%05.2f',cpu))
120
+ $('.mem',inode).text($.sprintf('%05.2f',mem))
121
+ if (parent == "") {
122
+ $('#instances_' + iname).append(inode)
123
+ } else {
124
+ $('#' + parent + ' > td > table').append(inode)
125
+ }
126
+ instances_striping(iname)
127
+ }
128
+
129
+ function instances_striping(iname) {
130
+ let even = true
131
+ $('#instances_' + iname + ' tr.text').removeClass('even')
132
+ $('#instances_' + iname + ' tr.text').each((i,e)=>{
133
+ if (even) {
134
+ $(e).addClass('even')
135
+ }
136
+ even = (even == true ? false : true)
137
+ })
138
+ }
139
+
140
+ function instances_init(ename) {
141
+ const iname = ename.replace(/[^a-z0-9A-Z]/g,'-').replace(/-$/,'')
142
+ let inode = document.importNode($("#stats_instances")[0].content,true);
143
+ $('.stats_title',inode).text($('.stats_title',inode).text() + ename)
144
+ $('table',inode).attr('id','instances_'+iname)
145
+ $('#instances').append(inode)
146
+ $.ajax({
147
+ type: "GET",
148
+ url: 'server/dash/instances',
149
+ data: { engine: ename },
150
+ success: (result) => {
151
+ $('instance',result).each((i,ele)=>{
152
+ const e = $(ele);
153
+ instance_add(iname,e.attr('uuid'),e.attr('url'),e.attr('name'),e.attr('state'),e.attr('author'),e.attr('cpu'),e.attr('mem'),e.attr('parent'))
154
+ })
155
+ }
156
+ })
157
+ }
158
+
159
+ function resource_paint(iname,data,count) {
160
+ count[iname]++
161
+ Plotly.extendTraces('resource_utilization_plot_' + iname, {y: [[data.cpu_usage], [(data.mem_total-data.mem_available)/data.mem_total * 100]]}, [0,1])
162
+ Plotly.relayout('resource_utilization_plot_' + iname, {
163
+ xaxis: {
164
+ range: [count[iname]-value_count,count[iname]],
165
+ showticklabels: false,
166
+ fixedrange: true
167
+ }
168
+ });
169
+ }
170
+
171
+ function stats_init() {
172
+ let es = new EventSource('server/dash/events/');
173
+ let count = {};
174
+ es.onopen = function() {
175
+ console.log('stats open');
176
+ };
177
+ es.onmessage = function(e) {
178
+ let data = JSON.parse(e.data)
179
+ const iname = data.engine.replace(/[^a-z0-9A-Z]/g,'-').replace(/-$/,'')
180
+ if ($('#instances').length > 0) {
181
+ if ($('#instances_' + iname).length == 0) {
182
+ instances_init(data.engine);
183
+ }
184
+ }
185
+ if (data.topic == "node" && data.event == "resource_utilization") {
186
+ if ($('#resources').length > 0) {
187
+ if ($('#resource_utilization_plot_' + iname).length == 0) {
188
+ resource_add(data.engine);
189
+ count[iname] = value_count;
190
+ }
191
+ resource_paint(iname,data,count)
192
+ }
193
+ } else if (data.topic == "state" && data.event == "change") {
194
+ if ($('#resources').length > 0) {
195
+ resource_update(data.engine)
196
+ }
197
+ if ($('#instances').length > 0) {
198
+ instance_change(data)
199
+ }
200
+ } else if (data.topic == "status" && data.event == "resource_utilization") {
201
+ if ($('#instances').length > 0) {
202
+ instance_res(data.uuid,data.cpu,data.mem)
203
+ }
204
+ } else {
205
+ console.log(data);
206
+ }
207
+ };
208
+ es.onerror = function() {
209
+ console.log('stats error');
210
+ }
211
+ }
212
+
213
+ $(document).ready(function() {
214
+ stats_init();
215
+ $('#instances').on('click','.abandon',function(e){
216
+ const par = $(e.target).parents('[data-url]').first()
217
+ $.ajax({
218
+ type: "PUT",
219
+ url: 'server/dash/abandon',
220
+ data: { url: par.attr('data-url') }
221
+ })
222
+ })
223
+ });