GUI -- Continued work on supporting GUI failover. WIP
- Thomas to complete. Change-Id: I4ed40a0d5b0b48cd1d9fac175a1f66e81df7dacf
Showing
3 changed files
with
64 additions
and
26 deletions
... | @@ -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; |
38 | - } | 44 | + clusterNodes.forEach(function (d, i) { |
39 | - } | 45 | + if (d.uiAttached) { |
46 | + clusterIndex = i; | ||
47 | + } | ||
48 | + }); | ||
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,23 +91,42 @@ | ... | @@ -76,23 +91,42 @@ |
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); |
84 | - // If no controllers left to contact, show the Veil... | 101 | + } else { |
85 | - vs.show([ | 102 | + // If no controllers left to contact, show the Veil... |
86 | - 'Oops!', | 103 | + vs.show([ |
87 | - 'Web-socket connection to server closed...', | 104 | + 'Oops!', |
88 | - 'Try refreshing the page.' | 105 | + 'Web-socket connection to server closed...', |
89 | - ]); | 106 | + 'Try refreshing the page.' |
107 | + ]); | ||
108 | + } | ||
90 | } | 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 | }); | ... | ... |
-
Please register or login to post a comment