2013-12-23 04:22:54 +00:00
|
|
|
Promise = require 'bluebird'
|
2014-06-18 16:54:36 +00:00
|
|
|
_ = require 'lodash'
|
2013-12-23 04:22:54 +00:00
|
|
|
fs = Promise.promisifyAll require 'fs'
|
2014-06-18 16:54:36 +00:00
|
|
|
config = require './config'
|
|
|
|
mixpanel = require 'mixpanel'
|
2014-11-13 20:26:14 +00:00
|
|
|
request = require './request'
|
2014-04-28 10:56:17 +00:00
|
|
|
|
2014-12-10 18:38:37 +00:00
|
|
|
utils = exports
|
|
|
|
|
2014-10-14 09:21:19 +00:00
|
|
|
# Parses package.json and returns resin-supervisor's version
|
|
|
|
exports.supervisorVersion = require('../package.json').version
|
|
|
|
|
2014-06-18 19:10:33 +00:00
|
|
|
mixpanelClient = mixpanel.init(config.mixpanelToken)
|
2014-06-18 16:54:36 +00:00
|
|
|
|
|
|
|
exports.mixpanelProperties = mixpanelProperties =
|
|
|
|
username: require('/boot/config.json').username
|
|
|
|
|
2014-09-15 11:31:14 +00:00
|
|
|
exports.mixpanelTrack = (event, properties = {}) ->
|
2014-10-01 17:37:35 +00:00
|
|
|
# Allow passing in an error directly and having it assigned to the error property.
|
|
|
|
if properties instanceof Error
|
|
|
|
properties = error: properties
|
|
|
|
|
|
|
|
# If the properties has an error argument that is an Error object then it treats it nicely,
|
|
|
|
# rather than letting it become `{}`
|
|
|
|
if properties.error instanceof Error
|
|
|
|
properties.error =
|
|
|
|
message: properties.error.message
|
|
|
|
stack: properties.error.stack
|
|
|
|
|
2014-06-19 13:49:30 +00:00
|
|
|
console.log('Event:', event, JSON.stringify(properties))
|
2014-06-18 16:54:36 +00:00
|
|
|
# Mutation is bad, and it should feel bad
|
|
|
|
properties = _.assign(_.cloneDeep(properties), mixpanelProperties)
|
|
|
|
|
2014-06-18 19:10:33 +00:00
|
|
|
mixpanelClient.track(event, properties)
|
2014-07-11 14:57:49 +00:00
|
|
|
|
|
|
|
# Returns an array of the host's ip address(es) by parsing the host /proc/net/fib_trie
|
|
|
|
exports.findIpAddrs = ->
|
|
|
|
fs.readFileAsync('/mnt/fib_trie', 'utf8')
|
|
|
|
.then (fibtrie) ->
|
|
|
|
prevLine = ''
|
|
|
|
fibtrie.split('\n')
|
|
|
|
.map (line) ->
|
|
|
|
line = line.trim()
|
|
|
|
|
|
|
|
# We only care about LOCAL routes (not UNICAST or BROADCAST)
|
|
|
|
if line.match(/LOCAL$/)
|
2014-09-15 14:04:38 +00:00
|
|
|
# Then we make sure the previous line was an ending branch (and hence contains an IP - 127.0.0.0 has
|
|
|
|
# BROADCAST and LOCAL entries)
|
2014-07-11 14:57:49 +00:00
|
|
|
if prevLine.match(/^\|--/)
|
|
|
|
# Then we remove the ending branch bit
|
|
|
|
maybeAddr = prevLine.replace(/^\|--/, '').trim()
|
|
|
|
# And ignore loopback/docker interfaces.
|
|
|
|
# TODO: Docker interface can technically be on another address range if 172.17
|
|
|
|
if !maybeAddr.match(/^(127.0.0.1|172.17.)/)
|
|
|
|
ipAddr = maybeAddr
|
|
|
|
|
|
|
|
prevLine = line
|
|
|
|
return ipAddr
|
|
|
|
.filter(Boolean)
|
2014-08-14 21:32:03 +00:00
|
|
|
|
|
|
|
# Helps in blinking the LED from the given end point.
|
|
|
|
exports.blink = (ms = 200) ->
|
|
|
|
fs.writeFileAsync(config.ledFile, 1)
|
|
|
|
.delay(ms)
|
|
|
|
.then -> fs.writeFileAsync(config.ledFile, 0)
|
|
|
|
|
2014-09-30 17:53:21 +00:00
|
|
|
# Helps in checking connectivity by pseudo-pinging our endpoint.
|
|
|
|
exports.checkConnectivity = ->
|
|
|
|
# We avoid using ICMP as this traffic is sometimes restricted/dropped. Good
|
|
|
|
# ol' port 80 HTTP should always be available :-)
|
|
|
|
request
|
2014-12-10 20:49:54 +00:00
|
|
|
.getAsync
|
|
|
|
url: config.heartbeatEndpoint
|
|
|
|
timeout: 10000
|
2014-09-30 18:02:13 +00:00
|
|
|
.spread (response) ->
|
2014-09-30 17:53:21 +00:00
|
|
|
return response.statusCode in [ 200, 304 ]
|
|
|
|
.catch ->
|
|
|
|
return false
|
2014-12-10 18:38:37 +00:00
|
|
|
|
2014-12-10 20:32:45 +00:00
|
|
|
blinkPattern = do ->
|
|
|
|
started = false
|
|
|
|
interval = null
|
|
|
|
timeout = null
|
|
|
|
# This function lets us have sensible param orders,
|
|
|
|
# and always have a timeout we can cancel.
|
|
|
|
delay = (ms, fn) ->
|
|
|
|
timeout = setTimeout(fn, ms)
|
|
|
|
start = () ->
|
|
|
|
interval = setInterval(utils.blink, 400)
|
|
|
|
delay 2000, ->
|
|
|
|
# Clear the blinks after 2 second
|
|
|
|
clearInterval(interval)
|
|
|
|
delay 2000, ->
|
|
|
|
# And then repeat again after another 2 seconds
|
|
|
|
start()
|
|
|
|
return {
|
|
|
|
start: () ->
|
|
|
|
return false if started
|
|
|
|
started = true
|
|
|
|
start()
|
|
|
|
stop: ->
|
|
|
|
return false if not started
|
|
|
|
started = false
|
|
|
|
clearInterval(interval)
|
|
|
|
clearTimeout(timeout)
|
|
|
|
}
|
|
|
|
|
2014-12-10 18:38:37 +00:00
|
|
|
exports.connectivityCheck = do ->
|
|
|
|
connectivityState = true # Used to prevent multiple messages when disconnected
|
2014-12-10 19:44:32 +00:00
|
|
|
_check = ->
|
2014-12-10 18:38:37 +00:00
|
|
|
utils.checkConnectivity()
|
|
|
|
.then (connected) ->
|
|
|
|
if not connected
|
|
|
|
if connectivityState
|
|
|
|
console.log('Waiting for connectivity...')
|
|
|
|
connectivityState = false
|
2014-12-10 20:32:45 +00:00
|
|
|
blinkPattern.start()
|
2014-12-10 18:38:37 +00:00
|
|
|
else
|
|
|
|
if not connectivityState
|
|
|
|
console.log('Internet Connectivity: OK')
|
|
|
|
connectivityState = true
|
2014-12-10 20:32:45 +00:00
|
|
|
blinkPattern.stop()
|
|
|
|
setTimeout(_check, 10 * 1000) # Every 10 seconds perform this check.
|
2014-12-10 19:44:32 +00:00
|
|
|
return _.once(_check)
|