Simon Hunt

GUI -- Continued work on supporting GUI failover. WIP

- Thomas to complete.

Change-Id: I4ed40a0d5b0b48cd1d9fac175a1f66e81df7dacf
...@@ -33,25 +33,25 @@ ...@@ -33,25 +33,25 @@
33 return secure ? protocol + 's' : protocol; 33 return secure ? protocol + 's' : protocol;
34 } 34 }
35 35
36 - function urlBase(protocol, port) { 36 + function urlBase(protocol, port, host) {
37 return matchSecure(protocol) + '://' + 37 return matchSecure(protocol) + '://' +
38 - $loc.host() + ':' + (port || $loc.port()); 38 + (host || $loc.host()) + ':' + (port || $loc.port());
39 } 39 }
40 40
41 function httpPrefix(suffix) { 41 function httpPrefix(suffix) {
42 return urlBase('http') + suffix; 42 return urlBase('http') + suffix;
43 } 43 }
44 44
45 - function wsPrefix(suffix, wsport) { 45 + function wsPrefix(suffix, wsport, host) {
46 - return urlBase('ws', wsport) + suffix; 46 + return urlBase('ws', wsport, host) + suffix;
47 } 47 }
48 48
49 function rsUrl(path) { 49 function rsUrl(path) {
50 return httpPrefix(rsSuffix) + path; 50 return httpPrefix(rsSuffix) + path;
51 } 51 }
52 52
53 - function wsUrl(path, wsport) { 53 + function wsUrl(path, wsport, host) {
54 - return wsPrefix(wsSuffix, wsport) + path; 54 + return wsPrefix(wsSuffix, wsport, host) + path;
55 } 55 }
56 56
57 return { 57 return {
......
...@@ -24,30 +24,45 @@ ...@@ -24,30 +24,45 @@
24 var $log, $loc, fs, ufs, wsock, vs; 24 var $log, $loc, fs, ufs, wsock, vs;
25 25
26 // internal state 26 // internal state
27 - var ws = null, // web socket reference 27 + var webSockOpts, // web socket options
28 + ws = null, // web socket reference
28 wsUp = false, // web socket is good to go 29 wsUp = false, // web socket is good to go
29 sid = 0, // event sequence identifier 30 sid = 0, // event sequence identifier
30 handlers = {}, // event handler bindings 31 handlers = {}, // event handler bindings
31 pendingEvents = [], // events TX'd while socket not up 32 pendingEvents = [], // events TX'd while socket not up
32 url, // web socket URL 33 url, // web socket URL
33 - instances = []; 34 + clusterNodes = [], // ONOS instances data for failover
35 + clusterIndex = -1, // the instance to which we are connected
36 + connectRetries = 0;
37 +
38 + // =======================
39 + // === Bootstrap Handler
34 40
35 var builtinHandlers = { 41 var builtinHandlers = {
36 - onosInstances: function (data) { 42 + bootstrap: function (data) {
37 - instances = data.instances; 43 + clusterNodes = data.instances;
44 + clusterNodes.forEach(function (d, i) {
45 + if (d.uiAttached) {
46 + clusterIndex = i;
38 } 47 }
48 + });
39 } 49 }
50 + };
40 51
41 // ========================== 52 // ==========================
42 // === Web socket callbacks 53 // === Web socket callbacks
43 54
44 function handleOpen() { 55 function handleOpen() {
45 $log.info('Web socket open'); 56 $log.info('Web socket open');
57 + vs.hide();
58 +
46 $log.debug('Sending ' + pendingEvents.length + ' pending event(s)...'); 59 $log.debug('Sending ' + pendingEvents.length + ' pending event(s)...');
47 pendingEvents.forEach(function (ev) { 60 pendingEvents.forEach(function (ev) {
48 _send(ev); 61 _send(ev);
49 }); 62 });
50 pendingEvents = []; 63 pendingEvents = [];
64 +
65 + connectRetries = 0;
51 wsUp = true; 66 wsUp = true;
52 } 67 }
53 68
...@@ -76,11 +91,14 @@ ...@@ -76,11 +91,14 @@
76 } 91 }
77 92
78 function handleClose() { 93 function handleClose() {
94 + var gsucc;
95 +
79 $log.info('Web socket closed'); 96 $log.info('Web socket closed');
80 wsUp = false; 97 wsUp = false;
81 98
82 - // FIXME: implement controller failover logic 99 + if (gsucc = findGuiSuccessor()) {
83 - 100 + createWebSocket(webSockOpts, gsucc);
101 + } else {
84 // If no controllers left to contact, show the Veil... 102 // If no controllers left to contact, show the Veil...
85 vs.show([ 103 vs.show([
86 'Oops!', 104 'Oops!',
...@@ -88,11 +106,27 @@ ...@@ -88,11 +106,27 @@
88 'Try refreshing the page.' 106 'Try refreshing the page.'
89 ]); 107 ]);
90 } 108 }
109 + }
91 110
92 111
93 // ============================== 112 // ==============================
94 // === Private Helper Functions 113 // === Private Helper Functions
95 114
115 + function findGuiSuccessor() {
116 + var ncn = clusterNodes.length,
117 + ip = undefined,
118 + node;
119 +
120 + while (connectRetries < ncn && !ip) {
121 + connectRetries++;
122 + clusterIndex = (clusterIndex + 1) % ncn;
123 + node = clusterNodes[clusterIndex];
124 + ip = node && node.ip;
125 + }
126 +
127 + return ip;
128 + }
129 +
96 function _send(ev) { 130 function _send(ev) {
97 $log.debug(' *Tx* >> ', ev.event, ev.payload); 131 $log.debug(' *Tx* >> ', ev.event, ev.payload);
98 ws.send(JSON.stringify(ev)); 132 ws.send(JSON.stringify(ev));
...@@ -109,10 +143,12 @@ ...@@ -109,10 +143,12 @@
109 143
110 // Currently supported opts: 144 // Currently supported opts:
111 // wsport: web socket port (other than default 8181) 145 // wsport: web socket port (other than default 8181)
112 - function createWebSocket(opts) { 146 + // server: if defined, is the server address to use
147 + function createWebSocket(opts, server) {
113 var wsport = (opts && opts.wsport) || null; 148 var wsport = (opts && opts.wsport) || null;
149 + webSockOpts = opts; // preserved for future calls
114 150
115 - url = ufs.wsUrl('core', wsport); 151 + url = ufs.wsUrl('core', wsport, server);
116 152
117 $log.debug('Attempting to open websocket to: ' + url); 153 $log.debug('Attempting to open websocket to: ' + url);
118 ws = wsock.newWebSocket(url); 154 ws = wsock.newWebSocket(url);
...@@ -192,10 +228,7 @@ ...@@ -192,10 +228,7 @@
192 wsock = _wsock_; 228 wsock = _wsock_;
193 vs = _vs_; 229 vs = _vs_;
194 230
195 - // Bind instance handlers 231 + bindHandlers(builtinHandlers);
196 - bindHandlers({
197 - onosInstances: builtinHandlers
198 - });
199 232
200 return { 233 return {
201 resetSid: resetSid, 234 resetSid: resetSid,
......
...@@ -81,4 +81,9 @@ describe('factory: fw/remote/urlfn.js', function () { ...@@ -81,4 +81,9 @@ describe('factory: fw/remote/urlfn.js', function () {
81 setLoc('http', 'foo', '123'); 81 setLoc('http', 'foo', '123');
82 expect(ufs.wsUrl('xyyzy', 456)).toEqual('ws://foo:456/onos/ui/websock/xyyzy'); 82 expect(ufs.wsUrl('xyyzy', 456)).toEqual('ws://foo:456/onos/ui/websock/xyyzy');
83 }); 83 });
84 +
85 + it('should allow us to define an alternate host', function () {
86 + setLoc('http', 'foo', '123');
87 + expect(ufs.wsUrl('core', 456, 'bar')).toEqual('ws://bar:456/onos/ui/websock/core');
88 + });
84 }); 89 });
......