Propagate liveness info.

This commit is contained in:
Ian Gulliver
2016-05-11 00:55:01 +00:00
parent 683252671f
commit da27533c68
3 changed files with 44 additions and 9 deletions

View File

@@ -69,6 +69,14 @@ class WebSockets(object):
for target in targets: for target in targets:
target.send(msgstr) target.send(msgstr)
def BroadcastTargets(self):
self.Broadcast(self.masters, {
'type': 'targets',
'data': {
'targets': list(self.targets.keys()),
},
})
class BaseWSHandler(websocket.WebSocket): class BaseWSHandler(websocket.WebSocket):
def opened(self, image_types): def opened(self, image_types):
@@ -92,6 +100,7 @@ def GetSlaveWSHandler(image_types, websockets):
websockets.slaves.remove(self) websockets.slaves.remove(self)
if self._hostname: if self._hostname:
del websockets.targets[self._hostname] del websockets.targets[self._hostname]
websockets.BroadcastTargets()
def received_message(self, msg): def received_message(self, msg):
parsed = json.loads(str(msg)) parsed = json.loads(str(msg))
@@ -108,6 +117,7 @@ def GetSlaveWSHandler(image_types, websockets):
if 'hostname' in parsed['data']: if 'hostname' in parsed['data']:
self._hostname = parsed['data']['hostname'] self._hostname = parsed['data']['hostname']
websockets.targets[self._hostname] = self websockets.targets[self._hostname] = self
websockets.BroadcastTargets()
return SlaveWSHandler return SlaveWSHandler
@@ -117,6 +127,12 @@ def GetMasterWSHandler(image_types, websockets):
def opened(self): def opened(self):
super().opened(image_types) super().opened(image_types)
websockets.masters.add(self) websockets.masters.add(self)
self.send(json.dumps({
'type': 'targets',
'data': {
'targets': list(websockets.targets.keys()),
},
}))
def closed(self, code, reason=None): def closed(self, code, reason=None):
websockets.masters.remove(self) websockets.masters.remove(self)

View File

@@ -35,13 +35,17 @@ header {
padding: 2px; padding: 2px;
} }
hostname, lastSeen, uptime, timestamp, volumeID, reboot { hostname, lastReport, uptime, timestamp, volumeID, reboot {
font-family: "droid-sans-mono"; font-family: "droid-sans-mono";
display: table-cell; display: table-cell;
padding: 2px; padding: 2px;
text-align: right; text-align: right;
} }
instanceSection.live hostname {
color: #3299bb;
}
volumeID { volumeID {
cursor: pointer; cursor: pointer;
} }

View File

@@ -25,6 +25,8 @@ ImageController.prototype.onMessage_ = function(msg) {
return this.onImageTypes_(msg['data']); return this.onImageTypes_(msg['data']);
case 'report': case 'report':
return this.onReport_(msg['data']); return this.onReport_(msg['data']);
case 'targets':
return this.onTargets_(msg['data']);
} }
}; };
@@ -50,7 +52,7 @@ ImageController.prototype.addImageType_ = function(type) {
this.insertSorted_(this.container_, value.section, type); this.insertSorted_(this.container_, value.section, type);
let headers = this.createNode_(value.section, 'headers'); let headers = this.createNode_(value.section, 'headers');
this.createNode_(headers, 'header', 'Hostname'); this.createNode_(headers, 'header', 'Hostname');
this.createNode_(headers, 'header', 'Last seen'); this.createNode_(headers, 'header', 'Last report');
this.createNode_(headers, 'header', 'Uptime'); this.createNode_(headers, 'header', 'Uptime');
this.createNode_(headers, 'header', 'Current image'); this.createNode_(headers, 'header', 'Current image');
this.createNode_(headers, 'header', 'Current volume ID'); this.createNode_(headers, 'header', 'Current volume ID');
@@ -70,8 +72,8 @@ ImageController.prototype.onReport_ = function(msg) {
this.addInstance_(type, msg['hostname']); this.addInstance_(type, msg['hostname']);
} }
let instance = type.instances.get(msg['hostname']); let instance = type.instances.get(msg['hostname']);
instance.last_report = Math.floor(Date.now() / 1000); instance.last_report_timestamp = Math.floor(Date.now() / 1000);
instance.last_seen.innerText = this.formatSeconds_(0); instance.last_report.innerText = this.formatSeconds_(0);
instance.uptime.innerText = this.formatSeconds_(msg['uptime_seconds']); instance.uptime.innerText = this.formatSeconds_(msg['uptime_seconds']);
instance.timestamp.innerText = msg['timestamp']; instance.timestamp.innerText = msg['timestamp'];
let volume_id_len = localStorage.getItem('volume_id_len') || Number.POSITIVE_INFINITY; let volume_id_len = localStorage.getItem('volume_id_len') || Number.POSITIVE_INFINITY;
@@ -86,7 +88,7 @@ ImageController.prototype.addInstance_ = function(type, hostname) {
}; };
this.insertSorted_(type.section, value.section, hostname); this.insertSorted_(type.section, value.section, hostname);
this.createNode_(value.section, 'hostname', hostname); this.createNode_(value.section, 'hostname', hostname);
value.last_seen = this.createNode_(value.section, 'lastSeen'); value.last_report = this.createNode_(value.section, 'lastReport');
value.uptime = this.createNode_(value.section, 'uptime'); value.uptime = this.createNode_(value.section, 'uptime');
value.timestamp = this.createNode_(value.section, 'timestamp'); value.timestamp = this.createNode_(value.section, 'timestamp');
value.volume_id = this.createNode_(value.section, 'volumeID'); value.volume_id = this.createNode_(value.section, 'volumeID');
@@ -104,12 +106,25 @@ ImageController.prototype.addInstance_ = function(type, hostname) {
type.instances.set(hostname, value); type.instances.set(hostname, value);
}; };
ImageController.prototype.onTargets_ = function(msg) {
let targets = new Set(msg['targets']);
for (let [type, type_value] of this.image_types_) {
for (let [instance, instance_value] of type_value.instances) {
if (targets.has(instance)) {
instance_value.section.classList.add('live');
} else {
instance_value.section.classList.remove('live');
}
}
}
};
ImageController.prototype.onTick_ = function() { ImageController.prototype.onTick_ = function() {
let now = Math.floor(Date.now() / 1000); let now = Math.floor(Date.now() / 1000);
for (let [type, type_section] of this.image_types_) { for (let [type, type_value] of this.image_types_) {
for (let [instance, instance_section] of type_section.instances) { for (let [instance, instance_value] of type_value.instances) {
instance_section.last_seen.innerText = instance_value.last_report.innerText =
this.formatSeconds_(now - instance_section.last_report); this.formatSeconds_(now - instance_value.last_report_timestamp);
} }
} }
}; };